blob: 1794ede93bb930f63d1f81b87aed19742436498f [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"
Jack Carterb4dbc172012-09-05 23:34:03 +000025#include "llvm/MC/MCStreamer.h"
26#include "llvm/MC/MCSubtargetInfo.h"
27#include "llvm/MC/MCSymbol.h"
Akira Hatanaka7605630c2012-08-17 20:16:42 +000028#include "llvm/MC/MCTargetAsmParser.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000029#include "llvm/Support/Debug.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000030#include "llvm/Support/MathExtras.h"
Daniel Sandersef638fe2014-10-03 15:37:37 +000031#include "llvm/Support/SourceMgr.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000032#include "llvm/Support/TargetRegistry.h"
Benjamin Kramer799003b2015-03-23 19:32:43 +000033#include "llvm/Support/raw_ostream.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000034#include <memory>
Rafael Espindola870c4e92012-01-11 03:56:41 +000035
36using namespace llvm;
37
Chandler Carruthe96dd892014-04-21 22:55:11 +000038#define DEBUG_TYPE "mips-asm-parser"
39
Joey Gouly0e76fa72013-09-12 10:28:05 +000040namespace llvm {
41class MCInstrInfo;
42}
43
Rafael Espindola870c4e92012-01-11 03:56:41 +000044namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000045class MipsAssemblerOptions {
46public:
Toma Tabacu465acfd2015-06-09 13:33:26 +000047 MipsAssemblerOptions(const FeatureBitset &Features_) :
Toma Tabacu9db22db2014-09-09 10:15:38 +000048 ATReg(1), Reorder(true), Macro(true), Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000049
Toma Tabacu9db22db2014-09-09 10:15:38 +000050 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
Toma Tabacub19cf202015-04-27 13:12:59 +000051 ATReg = Opts->getATRegIndex();
Toma Tabacu9db22db2014-09-09 10:15:38 +000052 Reorder = Opts->isReorder();
53 Macro = Opts->isMacro();
54 Features = Opts->getFeatures();
55 }
56
Toma Tabacub19cf202015-04-27 13:12:59 +000057 unsigned getATRegIndex() const { return ATReg; }
58 bool setATRegIndex(unsigned Reg) {
Toma Tabacu92dbbf12015-03-26 13:08:55 +000059 if (Reg > 31)
60 return false;
61
62 ATReg = Reg;
63 return true;
64 }
Jack Carter0b744b32012-10-04 02:29:46 +000065
Toma Tabacu9db22db2014-09-09 10:15:38 +000066 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000067 void setReorder() { Reorder = true; }
68 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000069
Toma Tabacu9db22db2014-09-09 10:15:38 +000070 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000071 void setMacro() { Macro = true; }
72 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000073
Toma Tabacu465acfd2015-06-09 13:33:26 +000074 const FeatureBitset &getFeatures() const { return Features; }
75 void setFeatures(const FeatureBitset &Features_) { Features = Features_; }
Toma Tabacu9db22db2014-09-09 10:15:38 +000076
Daniel Sandersf0df2212014-08-04 12:20:00 +000077 // Set of features that are either architecture features or referenced
78 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
79 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
80 // The reason we need this mask is explained in the selectArch function.
81 // FIXME: Ideally we would like TableGen to generate this information.
Michael Kupersteindb0712f2015-05-26 10:47:10 +000082 static const FeatureBitset AllArchRelatedMask;
Daniel Sandersf0df2212014-08-04 12:20:00 +000083
Jack Carter0b744b32012-10-04 02:29:46 +000084private:
Toma Tabacu3c24b042014-09-05 15:43:21 +000085 unsigned ATReg;
86 bool Reorder;
87 bool Macro;
Toma Tabacu465acfd2015-06-09 13:33:26 +000088 FeatureBitset Features;
Jack Carter0b744b32012-10-04 02:29:46 +000089};
90}
91
Michael Kupersteindb0712f2015-05-26 10:47:10 +000092const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = {
93 Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3,
94 Mips::FeatureMips3_32, Mips::FeatureMips3_32r2, Mips::FeatureMips4,
95 Mips::FeatureMips4_32, Mips::FeatureMips4_32r2, Mips::FeatureMips5,
96 Mips::FeatureMips5_32r2, Mips::FeatureMips32, Mips::FeatureMips32r2,
97 Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6,
98 Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3,
99 Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips,
100 Mips::FeatureFP64Bit, Mips::FeatureGP64Bit, Mips::FeatureNaN2008
101};
102
Jack Carter0b744b32012-10-04 02:29:46 +0000103namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +0000104class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000105 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +0000106 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000107 return static_cast<MipsTargetStreamer &>(TS);
108 }
109
Eric Christophera5762812015-01-26 17:33:46 +0000110 MipsABIInfo ABI;
Toma Tabacu9db22db2014-09-09 10:15:38 +0000111 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000112 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
113 // nullptr, which indicates that no function is currently
114 // selected. This usually happens after an '.end func'
115 // directive.
Toma Tabacud88d79c2015-06-23 14:39:42 +0000116 bool IsLittleEndian;
Daniel Sandersa6994442015-08-18 12:33:54 +0000117 bool IsPicEnabled;
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000118 bool IsCpRestoreSet;
119 int CpRestoreOffset;
Daniel Sandersf173dda2015-09-22 10:50:09 +0000120 unsigned CpSaveLocation;
121 /// If true, then CpSaveLocation is a register, otherwise it's an offset.
122 bool CpSaveLocationIsRegister;
Jack Carter0b744b32012-10-04 02:29:46 +0000123
Daniel Sandersef638fe2014-10-03 15:37:37 +0000124 // Print a warning along with its fix-it message at the given range.
125 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
126 SMRange Range, bool ShowColors = true);
127
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000128#define GET_ASSEMBLER_HEADER
129#include "MipsGenAsmMatcher.inc"
130
Matheus Almeida595fcab2014-06-11 15:05:56 +0000131 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
132
Chad Rosier49963552012-10-13 00:26:04 +0000133 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000134 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000135 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000136 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000137
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000138 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000139 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000140
Toma Tabacu13964452014-09-04 13:23:44 +0000141 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000142
Toma Tabacu13964452014-09-04 13:23:44 +0000143 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000144
David Blaikie960ea3f2014-06-08 16:18:35 +0000145 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
146 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000147
Craig Topper56c590a2014-04-29 07:58:02 +0000148 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000149
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000150 OperandMatchResultTy parseMemOperand(OperandVector &Operands);
151 OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000152 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000153 StringRef Identifier, SMLoc S);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000154 OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
155 SMLoc S);
156 OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
157 OperandMatchResultTy parseImm(OperandVector &Operands);
158 OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
159 OperandMatchResultTy parseInvNum(OperandVector &Operands);
160 OperandMatchResultTy parseLSAImm(OperandVector &Operands);
161 OperandMatchResultTy parseRegisterPair(OperandVector &Operands);
162 OperandMatchResultTy parseMovePRegPair(OperandVector &Operands);
163 OperandMatchResultTy parseRegisterList(OperandVector &Operands);
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000164
David Blaikie960ea3f2014-06-08 16:18:35 +0000165 bool searchSymbolAlias(OperandVector &Operands);
166
Toma Tabacu13964452014-09-04 13:23:44 +0000167 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000168
Daniel Sanders5bf6eab2015-10-26 23:50:00 +0000169 enum MacroExpanderResultTy {
170 MER_NotAMacro,
171 MER_Success,
172 MER_Fail,
173 };
Jack Carter30a59822012-10-04 04:03:53 +0000174
Matheus Almeida3813d572014-06-19 14:39:14 +0000175 // Expands assembly pseudo instructions.
Daniel Sanders5bf6eab2015-10-26 23:50:00 +0000176 MacroExpanderResultTy
177 tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
178 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000179
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000180 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
181 SmallVectorImpl<MCInst> &Instructions);
182
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000183 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000184 bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000185 SmallVectorImpl<MCInst> &Instructions);
186
Toma Tabacuf712ede2015-06-17 14:31:51 +0000187 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
188 unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
189 SmallVectorImpl<MCInst> &Instructions);
Toma Tabacu674825c2015-06-16 12:16:24 +0000190
Toma Tabacu00e98672015-05-01 12:19:27 +0000191 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000192 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000193
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000194 bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
195 const MCOperand &Offset, bool Is32BitAddress,
196 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000197
Jozef Kolek5cfebdd2015-01-21 12:39:30 +0000198 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
199 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000200
Jack Carter9e65aa32013-03-22 00:05:30 +0000201 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000202 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
203 bool isImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000204
205 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
206 SmallVectorImpl<MCInst> &Instructions);
207
Zoran Jovanoviccdb64562015-09-28 11:11:34 +0000208 bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
209 SmallVectorImpl<MCInst> &Instructions);
210
Toma Tabacue1e460d2015-06-11 10:36:10 +0000211 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc,
212 SmallVectorImpl<MCInst> &Instructions);
213
Toma Tabacu1a108322015-06-17 13:20:24 +0000214 bool expandCondBranches(MCInst &Inst, SMLoc IDLoc,
215 SmallVectorImpl<MCInst> &Instructions);
216
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000217 bool expandDiv(MCInst &Inst, SMLoc IDLoc,
218 SmallVectorImpl<MCInst> &Instructions, const bool IsMips64,
219 const bool Signed);
220
Daniel Sanders6394ee52015-10-15 14:52:58 +0000221 bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
222 SmallVectorImpl<MCInst> &Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000223
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +0000224 bool expandUlw(MCInst &Inst, SMLoc IDLoc,
225 SmallVectorImpl<MCInst> &Instructions);
226
Toma Tabacu234482a2015-03-16 12:03:39 +0000227 void createNop(bool hasShortDelaySlot, SMLoc IDLoc,
228 SmallVectorImpl<MCInst> &Instructions);
229
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000230 void createAddu(unsigned DstReg, unsigned SrcReg, unsigned TrgReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +0000231 bool Is64Bit, SmallVectorImpl<MCInst> &Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000232
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000233 void createCpRestoreMemOp(bool IsLoad, int StackOffset, SMLoc IDLoc,
234 SmallVectorImpl<MCInst> &Instructions);
235
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000236 bool reportParseError(Twine ErrorMsg);
237 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000238
Jack Carterb5cf5902013-04-17 00:18:04 +0000239 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000240 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000241
Vladimir Medic4c299852013-11-06 11:27:05 +0000242 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000243
244 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000245 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000246 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000247 bool parseSetFeature(uint64_t Feature);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000248 bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000249 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000250 bool parseDirectiveCpRestore(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000251 bool parseDirectiveCPSetup();
Daniel Sandersf173dda2015-09-22 10:50:09 +0000252 bool parseDirectiveCPReturn();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000253 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000254 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000255 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000256 bool parseInsnDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000257
258 bool parseSetAtDirective();
259 bool parseSetNoAtDirective();
260 bool parseSetMacroDirective();
261 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000262 bool parseSetMsaDirective();
263 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000264 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000265 bool parseSetReorderDirective();
266 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000267 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000268 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000269 bool parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000270 bool parseSetOddSPRegDirective();
271 bool parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000272 bool parseSetPopDirective();
273 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000274 bool parseSetSoftFloatDirective();
275 bool parseSetHardFloatDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000276
Jack Carterd76b2372013-03-21 21:44:16 +0000277 bool parseSetAssignment();
278
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000279 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000280 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000281 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000282 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000283 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000284 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
285 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000286
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000287 bool parseInternalDirectiveReallowModule();
288
Jack Carterdc1e35d2012-09-06 20:00:02 +0000289 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000290
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000291 bool eatComma(StringRef ErrorStr);
292
Jack Carter1ac53222013-02-20 23:11:17 +0000293 int matchCPURegisterName(StringRef Symbol);
294
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000295 int matchHWRegsRegisterName(StringRef Symbol);
296
Jack Carter873c7242013-01-12 01:03:14 +0000297 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000298
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000299 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000300
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000301 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000302
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000303 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000304
Jack Carter5dc8ac92013-09-25 23:50:44 +0000305 int matchMSA128RegisterName(StringRef Name);
306
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000307 int matchMSA128CtrlRegisterName(StringRef Name);
308
Jack Carterd0bd6422013-04-18 00:41:53 +0000309 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000310
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000311 unsigned getGPR(int RegNo);
312
Toma Tabacu89a712b2015-04-15 10:48:56 +0000313 /// Returns the internal register number for the current AT. Also checks if
314 /// the current AT is unavailable (set to $0) and gives an error if it is.
315 /// This should be used in pseudo-instruction expansions which need AT.
316 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000317
318 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000319 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000320
321 // Helper function that checks if the value of a vector index is within the
322 // boundaries of accepted values for each RegisterKind
323 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
324 bool validateMSAIndex(int Val, int RegKind);
325
Daniel Sandersf0df2212014-08-04 12:20:00 +0000326 // Selects a new architecture by updating the FeatureBits with the necessary
327 // info including implied dependencies.
328 // Internally, it clears all the feature bits related to *any* architecture
329 // and selects the new one using the ToggleFeature functionality of the
330 // MCSubtargetInfo object that handles implied dependencies. The reason we
331 // clear all the arch related bits manually is because ToggleFeature only
332 // clears the features that imply the feature being cleared and not the
333 // features implied by the feature being cleared. This is easier to see
334 // with an example:
335 // --------------------------------------------------
336 // | Feature | Implies |
337 // | -------------------------------------------------|
338 // | FeatureMips1 | None |
339 // | FeatureMips2 | FeatureMips1 |
340 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
341 // | FeatureMips4 | FeatureMips3 |
342 // | ... | |
343 // --------------------------------------------------
344 //
345 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
346 // FeatureMipsGP64 | FeatureMips1)
347 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
348 void selectArch(StringRef ArchFeature) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000349 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000350 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
351 STI.setFeatureBits(FeatureBits);
352 setAvailableFeatures(
353 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000354 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000355 }
356
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000357 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000358 if (!(getSTI().getFeatureBits()[Feature])) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000359 setAvailableFeatures(
360 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000361 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000362 }
363 }
364
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000365 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000366 if (getSTI().getFeatureBits()[Feature]) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000367 setAvailableFeatures(
368 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000369 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000370 }
371 }
372
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000373 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
374 setFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000375 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000376 }
377
378 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
379 clearFeatureBits(Feature, FeatureString);
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000380 AssemblerOptions.front()->setFeatures(getSTI().getFeatureBits());
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000381 }
382
Rafael Espindola870c4e92012-01-11 03:56:41 +0000383public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000384 enum MipsMatchResultTy {
Daniel Sanders52da7af2015-11-06 12:11:03 +0000385 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
Matheus Almeida595fcab2014-06-11 15:05:56 +0000386#define GET_OPERAND_DIAGNOSTIC_TYPES
387#include "MipsGenAsmMatcher.inc"
388#undef GET_OPERAND_DIAGNOSTIC_TYPES
Matheus Almeida595fcab2014-06-11 15:05:56 +0000389 };
390
Joey Gouly0e76fa72013-09-12 10:28:05 +0000391 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000392 const MCInstrInfo &MII, const MCTargetOptions &Options)
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000393 : MCTargetAsmParser(Options, sti),
Daniel Sanders50f17232015-09-15 16:17:27 +0000394 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
395 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000396 MCAsmParserExtension::Initialize(parser);
397
Toma Tabacu11e14a92015-04-21 11:50:52 +0000398 parser.addAliasForDirective(".asciiz", ".asciz");
399
Jack Carterb4dbc172012-09-05 23:34:03 +0000400 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000401 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000402
Toma Tabacu9db22db2014-09-09 10:15:38 +0000403 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000404 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000405 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000406
Toma Tabacu9db22db2014-09-09 10:15:38 +0000407 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000408 AssemblerOptions.push_back(
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000409 llvm::make_unique<MipsAssemblerOptions>(getSTI().getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000410
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000411 getTargetStreamer().updateABIInfo(*this);
412
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000413 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000414 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000415
416 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000417
Daniel Sandersa6994442015-08-18 12:33:54 +0000418 IsPicEnabled =
419 (getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_);
420
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000421 IsCpRestoreSet = false;
422 CpRestoreOffset = -1;
423
Daniel Sanders50f17232015-09-15 16:17:27 +0000424 Triple TheTriple(sti.getTargetTriple());
425 if ((TheTriple.getArch() == Triple::mips) ||
426 (TheTriple.getArch() == Triple::mips64))
Toma Tabacud88d79c2015-06-23 14:39:42 +0000427 IsLittleEndian = false;
428 else
429 IsLittleEndian = true;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000430 }
431
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000432 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
433 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
434
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000435 bool isGP64bit() const {
436 return getSTI().getFeatureBits()[Mips::FeatureGP64Bit];
437 }
438 bool isFP64bit() const {
439 return getSTI().getFeatureBits()[Mips::FeatureFP64Bit];
440 }
Eric Christophera5762812015-01-26 17:33:46 +0000441 const MipsABIInfo &getABI() const { return ABI; }
442 bool isABI_N32() const { return ABI.IsN32(); }
443 bool isABI_N64() const { return ABI.IsN64(); }
444 bool isABI_O32() const { return ABI.IsO32(); }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000445 bool isABI_FPXX() const {
446 return getSTI().getFeatureBits()[Mips::FeatureFPXX];
447 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000448
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000449 bool useOddSPReg() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000450 return !(getSTI().getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000451 }
452
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000453 bool inMicroMipsMode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000454 return getSTI().getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000455 }
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000456 bool hasMips1() const {
457 return getSTI().getFeatureBits()[Mips::FeatureMips1];
458 }
459 bool hasMips2() const {
460 return getSTI().getFeatureBits()[Mips::FeatureMips2];
461 }
462 bool hasMips3() const {
463 return getSTI().getFeatureBits()[Mips::FeatureMips3];
464 }
465 bool hasMips4() const {
466 return getSTI().getFeatureBits()[Mips::FeatureMips4];
467 }
468 bool hasMips5() const {
469 return getSTI().getFeatureBits()[Mips::FeatureMips5];
470 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000471 bool hasMips32() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000472 return getSTI().getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000473 }
474 bool hasMips64() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000475 return getSTI().getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000476 }
477 bool hasMips32r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000478 return getSTI().getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000479 }
480 bool hasMips64r2() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000481 return getSTI().getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000482 }
Daniel Sanders17793142015-02-18 16:24:50 +0000483 bool hasMips32r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000484 return (getSTI().getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000485 }
486 bool hasMips64r3() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000487 return (getSTI().getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000488 }
489 bool hasMips32r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000490 return (getSTI().getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000491 }
492 bool hasMips64r5() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000493 return (getSTI().getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000494 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000495 bool hasMips32r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000496 return getSTI().getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000497 }
498 bool hasMips64r6() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000499 return getSTI().getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000500 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000501
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000502 bool hasDSP() const {
503 return getSTI().getFeatureBits()[Mips::FeatureDSP];
504 }
505 bool hasDSPR2() const {
506 return getSTI().getFeatureBits()[Mips::FeatureDSPR2];
507 }
508 bool hasDSPR3() const {
509 return getSTI().getFeatureBits()[Mips::FeatureDSPR3];
510 }
511 bool hasMSA() const {
512 return getSTI().getFeatureBits()[Mips::FeatureMSA];
513 }
Kai Nackee0245392015-01-27 19:11:28 +0000514 bool hasCnMips() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000515 return (getSTI().getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000516 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000517
Daniel Sandersa6994442015-08-18 12:33:54 +0000518 bool inPicMode() {
519 return IsPicEnabled;
520 }
521
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000522 bool inMips16Mode() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000523 return getSTI().getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000524 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000525
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000526 bool useTraps() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000527 return getSTI().getFeatureBits()[Mips::FeatureUseTCCInDIV];
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000528 }
529
Eric Christophere8ae3e32015-05-07 23:10:21 +0000530 bool useSoftFloat() const {
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000531 return getSTI().getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000532 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000533
Toma Tabacud9d344b2015-04-27 14:05:04 +0000534 /// Warn if RegIndex is the same as the current AT.
535 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000536
537 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000538
539 bool isLittle() const { return IsLittleEndian; }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000540};
541}
542
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000543namespace {
544
545/// MipsOperand - Instances of this class represent a parsed Mips machine
546/// instruction.
547class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000548public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000549 /// Broad categories of register classes
550 /// The exact class is finalized by the render method.
551 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000552 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000553 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000554 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000555 RegKind_FCC = 4, /// FCC
556 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
557 RegKind_MSACtrl = 16, /// MSA control registers
558 RegKind_COP2 = 32, /// COP2
559 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
560 /// context).
561 RegKind_CCR = 128, /// CCR
562 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000563 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000564 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000565 /// Potentially any (e.g. $1)
566 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
567 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000568 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000569 };
570
571private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000572 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000573 k_Immediate, /// An immediate (possibly involving symbol references)
574 k_Memory, /// Base + Offset Memory Address
575 k_PhysRegister, /// A physical register from the Mips namespace
576 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000577 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000578 k_RegList, /// A physical register list
579 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000580 } Kind;
581
David Blaikie960ea3f2014-06-08 16:18:35 +0000582public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000583 MipsOperand(KindTy K, MipsAsmParser &Parser)
584 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
585
David Blaikie960ea3f2014-06-08 16:18:35 +0000586private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000587 /// For diagnostics, and checking the assembler temporary
588 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000589
Eric Christopher8996c5d2013-03-15 00:42:55 +0000590 struct Token {
591 const char *Data;
592 unsigned Length;
593 };
594
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000595 struct PhysRegOp {
596 unsigned Num; /// Register Number
597 };
598
599 struct RegIdxOp {
600 unsigned Index; /// Index into the register class
601 RegKind Kind; /// Bitfield of the kinds it could possibly be
602 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000603 };
604
605 struct ImmOp {
606 const MCExpr *Val;
607 };
608
609 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000610 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000611 const MCExpr *Off;
612 };
613
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000614 struct RegListOp {
615 SmallVector<unsigned, 10> *List;
616 };
617
Jack Carterb4dbc172012-09-05 23:34:03 +0000618 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000619 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000620 struct PhysRegOp PhysReg;
621 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000622 struct ImmOp Imm;
623 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000624 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000625 };
626
627 SMLoc StartLoc, EndLoc;
628
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000629 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000630 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
631 const MCRegisterInfo *RegInfo,
632 SMLoc S, SMLoc E,
633 MipsAsmParser &Parser) {
634 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000635 Op->RegIdx.Index = Index;
636 Op->RegIdx.RegInfo = RegInfo;
637 Op->RegIdx.Kind = RegKind;
638 Op->StartLoc = S;
639 Op->EndLoc = E;
640 return Op;
641 }
642
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000643public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000644 /// Coerce the register to GPR32 and return the real register for the current
645 /// target.
646 unsigned getGPR32Reg() const {
647 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000648 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000649 unsigned ClassID = Mips::GPR32RegClassID;
650 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000651 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000652
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000653 /// Coerce the register to GPR32 and return the real register for the current
654 /// target.
655 unsigned getGPRMM16Reg() const {
656 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
657 unsigned ClassID = Mips::GPR32RegClassID;
658 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
659 }
660
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000661 /// Coerce the register to GPR64 and return the real register for the current
662 /// target.
663 unsigned getGPR64Reg() const {
664 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
665 unsigned ClassID = Mips::GPR64RegClassID;
666 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000667 }
668
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000669private:
670 /// Coerce the register to AFGR64 and return the real register for the current
671 /// target.
672 unsigned getAFGR64Reg() const {
673 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
674 if (RegIdx.Index % 2 != 0)
675 AsmParser.Warning(StartLoc, "Float register should be even.");
676 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
677 .getRegister(RegIdx.Index / 2);
678 }
679
680 /// Coerce the register to FGR64 and return the real register for the current
681 /// target.
682 unsigned getFGR64Reg() const {
683 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
684 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
685 .getRegister(RegIdx.Index);
686 }
687
688 /// Coerce the register to FGR32 and return the real register for the current
689 /// target.
690 unsigned getFGR32Reg() const {
691 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
692 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
693 .getRegister(RegIdx.Index);
694 }
695
696 /// Coerce the register to FGRH32 and return the real register for the current
697 /// target.
698 unsigned getFGRH32Reg() const {
699 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
700 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
701 .getRegister(RegIdx.Index);
702 }
703
704 /// Coerce the register to FCC and return the real register for the current
705 /// target.
706 unsigned getFCCReg() const {
707 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
708 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
709 .getRegister(RegIdx.Index);
710 }
711
712 /// Coerce the register to MSA128 and return the real register for the current
713 /// target.
714 unsigned getMSA128Reg() const {
715 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
716 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
717 // identical
718 unsigned ClassID = Mips::MSA128BRegClassID;
719 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
720 }
721
722 /// Coerce the register to MSACtrl and return the real register for the
723 /// current target.
724 unsigned getMSACtrlReg() const {
725 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
726 unsigned ClassID = Mips::MSACtrlRegClassID;
727 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
728 }
729
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000730 /// Coerce the register to COP0 and return the real register for the
731 /// current target.
732 unsigned getCOP0Reg() const {
733 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
734 unsigned ClassID = Mips::COP0RegClassID;
735 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
736 }
737
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000738 /// Coerce the register to COP2 and return the real register for the
739 /// current target.
740 unsigned getCOP2Reg() const {
741 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
742 unsigned ClassID = Mips::COP2RegClassID;
743 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
744 }
745
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000746 /// Coerce the register to COP3 and return the real register for the
747 /// current target.
748 unsigned getCOP3Reg() const {
749 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
750 unsigned ClassID = Mips::COP3RegClassID;
751 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
752 }
753
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000754 /// Coerce the register to ACC64DSP and return the real register for the
755 /// current target.
756 unsigned getACC64DSPReg() const {
757 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
758 unsigned ClassID = Mips::ACC64DSPRegClassID;
759 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
760 }
761
762 /// Coerce the register to HI32DSP and return the real register for the
763 /// current target.
764 unsigned getHI32DSPReg() const {
765 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
766 unsigned ClassID = Mips::HI32DSPRegClassID;
767 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
768 }
769
770 /// Coerce the register to LO32DSP and return the real register for the
771 /// current target.
772 unsigned getLO32DSPReg() const {
773 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
774 unsigned ClassID = Mips::LO32DSPRegClassID;
775 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
776 }
777
778 /// Coerce the register to CCR and return the real register for the
779 /// current target.
780 unsigned getCCRReg() const {
781 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
782 unsigned ClassID = Mips::CCRRegClassID;
783 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
784 }
785
786 /// Coerce the register to HWRegs and return the real register for the
787 /// current target.
788 unsigned getHWRegsReg() const {
789 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
790 unsigned ClassID = Mips::HWRegsRegClassID;
791 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
792 }
793
794public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000795 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000796 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000797 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000798 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000799 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000800 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000801 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000802 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000803 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000804
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000805 void addRegOperands(MCInst &Inst, unsigned N) const {
806 llvm_unreachable("Use a custom parser instead");
807 }
808
Daniel Sanders21bce302014-04-01 12:35:23 +0000809 /// Render the operand to an MCInst as a GPR32
810 /// Asserts if the wrong number of operands are requested, or the operand
811 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000812 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
813 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000814 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000815 }
816
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000817 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
818 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000819 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000820 }
821
Jozef Kolek1904fa22014-11-24 14:25:53 +0000822 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
823 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000824 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +0000825 }
826
Zoran Jovanovic41688672015-02-10 16:36:20 +0000827 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
828 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000829 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000830 }
831
Daniel Sanders21bce302014-04-01 12:35:23 +0000832 /// Render the operand to an MCInst as a GPR64
833 /// Asserts if the wrong number of operands are requested, or the operand
834 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000835 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
836 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000837 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000838 }
839
840 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
841 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000842 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000843 }
844
845 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
846 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000847 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000848 }
849
850 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
851 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000852 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000853 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000854 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000855 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
856 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000857 }
858
859 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
860 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000861 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000862 }
863
864 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
865 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000866 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000867 }
868
869 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
870 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000871 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000872 }
873
874 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
875 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000876 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000877 }
878
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000879 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
880 assert(N == 1 && "Invalid number of operands!");
881 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
882 }
883
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000884 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
885 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000886 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000887 }
888
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000889 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
890 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000891 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000892 }
893
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000894 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
895 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000896 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000897 }
898
899 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
900 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000901 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000902 }
903
904 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
905 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000906 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000907 }
908
909 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
910 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000911 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000912 }
913
914 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
915 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000916 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000917 }
918
Daniel Sandersea4f6532015-11-06 12:22:31 +0000919 template <unsigned Bits, int Offset = 0>
Daniel Sanders52da7af2015-11-06 12:11:03 +0000920 void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
921 assert(N == 1 && "Invalid number of operands!");
Daniel Sandersea4f6532015-11-06 12:22:31 +0000922 uint64_t Imm = getConstantImm() - Offset;
923 Imm &= (1 << Bits) - 1;
924 Imm += Offset;
Daniel Sanders52da7af2015-11-06 12:11:03 +0000925 Inst.addOperand(MCOperand::createImm(Imm));
926 }
927
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000928 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000929 assert(N == 1 && "Invalid number of operands!");
930 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000931 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000932 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000933
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000934 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000935 assert(N == 2 && "Invalid number of operands!");
936
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000937 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
938 ? getMemBase()->getGPR64Reg()
939 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000940
941 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000942 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000943 }
944
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000945 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
946 assert(N == 2 && "Invalid number of operands!");
947
Jim Grosbache9119e42015-05-13 18:37:00 +0000948 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000949
950 const MCExpr *Expr = getMemOff();
951 addExpr(Inst, Expr);
952 }
953
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000954 void addRegListOperands(MCInst &Inst, unsigned N) const {
955 assert(N == 1 && "Invalid number of operands!");
956
957 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000958 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000959 }
960
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000961 void addRegPairOperands(MCInst &Inst, unsigned N) const {
962 assert(N == 2 && "Invalid number of operands!");
963 unsigned RegNo = getRegPair();
Jim Grosbache9119e42015-05-13 18:37:00 +0000964 Inst.addOperand(MCOperand::createReg(RegNo++));
965 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000966 }
967
Zoran Jovanovic41688672015-02-10 16:36:20 +0000968 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
969 assert(N == 2 && "Invalid number of operands!");
970 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000971 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000972 }
973
Craig Topper56c590a2014-04-29 07:58:02 +0000974 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000975 // As a special case until we sort out the definition of div/divu, pretend
976 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
977 if (isGPRAsmReg() && RegIdx.Index == 0)
978 return true;
979
980 return Kind == k_PhysRegister;
981 }
982 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000983 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000984 bool isConstantImm() const {
985 return isImm() && dyn_cast<MCConstantExpr>(getImm());
986 }
Daniel Sanders52da7af2015-11-06 12:11:03 +0000987 bool isConstantImmz() const {
988 return isConstantImm() && getConstantImm() == 0;
989 }
Daniel Sandersea4f6532015-11-06 12:22:31 +0000990 template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
991 return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
992 }
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +0000993 template <unsigned Bits> bool isUImm() const {
994 return isImm() && isConstantImm() && isUInt<Bits>(getConstantImm());
995 }
Craig Topper56c590a2014-04-29 07:58:02 +0000996 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000997 // Note: It's not possible to pretend that other operand kinds are tokens.
998 // The matcher emitter checks tokens first.
999 return Kind == k_Token;
1000 }
Craig Topper56c590a2014-04-29 07:58:02 +00001001 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001002 bool isConstantMemOff() const {
1003 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
1004 }
1005 template <unsigned Bits> bool isMemWithSimmOffset() const {
Zoran Jovanovica6593ff2015-08-18 12:53:08 +00001006 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
1007 && getMemBase()->isGPRAsmReg();
1008 }
Zoran Jovanovic6e6a2c92015-09-16 09:14:35 +00001009 template <unsigned Bits> bool isMemWithSimmOffsetGPR() const {
1010 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff()) &&
1011 getMemBase()->isGPRAsmReg();
1012 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001013 bool isMemWithGRPMM16Base() const {
1014 return isMem() && getMemBase()->isMM16AsmReg();
1015 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001016 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
1017 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1018 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
1019 }
Jozef Kolek12c69822014-12-23 16:16:33 +00001020 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
1021 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
1022 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
1023 && (getMemBase()->getGPR32Reg() == Mips::SP);
1024 }
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00001025 bool isUImm5Lsl2() const {
1026 return (isImm() && isConstantImm() && isShiftedUInt<5, 2>(getConstantImm()));
1027 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001028 bool isRegList16() const {
1029 if (!isRegList())
1030 return false;
1031
1032 int Size = RegList.List->size();
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001033 if (Size < 2 || Size > 5)
1034 return false;
1035
1036 unsigned R0 = RegList.List->front();
1037 unsigned R1 = RegList.List->back();
1038 if (!((R0 == Mips::S0 && R1 == Mips::RA) ||
1039 (R0 == Mips::S0_64 && R1 == Mips::RA_64)))
Zoran Jovanovicf9a02502014-11-27 18:28:59 +00001040 return false;
1041
1042 int PrevReg = *RegList.List->begin();
1043 for (int i = 1; i < Size - 1; i++) {
1044 int Reg = (*(RegList.List))[i];
1045 if ( Reg != PrevReg + 1)
1046 return false;
1047 PrevReg = Reg;
1048 }
1049
1050 return true;
1051 }
Vladimir Medic2b953d02013-10-01 09:48:56 +00001052 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001053 bool isLSAImm() const {
1054 if (!isConstantImm())
1055 return false;
1056 int64_t Val = getConstantImm();
1057 return 1 <= Val && Val <= 4;
1058 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001059 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001060 bool isMovePRegPair() const {
1061 if (Kind != k_RegList || RegList.List->size() != 2)
1062 return false;
1063
1064 unsigned R0 = RegList.List->front();
1065 unsigned R1 = RegList.List->back();
1066
1067 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1068 (R0 == Mips::A1 && R1 == Mips::A3) ||
1069 (R0 == Mips::A2 && R1 == Mips::A3) ||
1070 (R0 == Mips::A0 && R1 == Mips::S5) ||
1071 (R0 == Mips::A0 && R1 == Mips::S6) ||
1072 (R0 == Mips::A0 && R1 == Mips::A1) ||
1073 (R0 == Mips::A0 && R1 == Mips::A2) ||
1074 (R0 == Mips::A0 && R1 == Mips::A3))
1075 return true;
1076
1077 return false;
1078 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001079
1080 StringRef getToken() const {
1081 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001082 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001083 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001084 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001085
Craig Topper56c590a2014-04-29 07:58:02 +00001086 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001087 // As a special case until we sort out the definition of div/divu, pretend
1088 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
1089 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1090 RegIdx.Kind & RegKind_GPR)
1091 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001092
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001093 assert(Kind == k_PhysRegister && "Invalid access!");
1094 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +00001095 }
1096
Jack Carterb4dbc172012-09-05 23:34:03 +00001097 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001098 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001099 return Imm.Val;
1100 }
1101
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001102 int64_t getConstantImm() const {
1103 const MCExpr *Val = getImm();
1104 return static_cast<const MCConstantExpr *>(Val)->getValue();
1105 }
1106
1107 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001108 assert((Kind == k_Memory) && "Invalid access!");
1109 return Mem.Base;
1110 }
1111
1112 const MCExpr *getMemOff() const {
1113 assert((Kind == k_Memory) && "Invalid access!");
1114 return Mem.Off;
1115 }
1116
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001117 int64_t getConstantMemOff() const {
1118 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1119 }
1120
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001121 const SmallVectorImpl<unsigned> &getRegList() const {
1122 assert((Kind == k_RegList) && "Invalid access!");
1123 return *(RegList.List);
1124 }
1125
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001126 unsigned getRegPair() const {
1127 assert((Kind == k_RegPair) && "Invalid access!");
1128 return RegIdx.Index;
1129 }
1130
David Blaikie960ea3f2014-06-08 16:18:35 +00001131 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1132 MipsAsmParser &Parser) {
1133 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001134 Op->Tok.Data = Str.data();
1135 Op->Tok.Length = Str.size();
1136 Op->StartLoc = S;
1137 Op->EndLoc = S;
1138 return Op;
1139 }
1140
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001141 /// Create a numeric register (e.g. $1). The exact register remains
1142 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001143 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001144 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001145 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001146 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001147 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001148 }
1149
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001150 /// Create a register that is definitely a GPR.
1151 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001152 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001153 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001154 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001155 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001156 }
1157
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001158 /// Create a register that is definitely a FGR.
1159 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001160 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001161 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001162 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001163 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1164 }
1165
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001166 /// Create a register that is definitely a HWReg.
1167 /// This is typically only used for named registers such as $hwr_cpunum.
1168 static std::unique_ptr<MipsOperand>
1169 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1170 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1171 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1172 }
1173
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001174 /// Create a register that is definitely an FCC.
1175 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001176 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001177 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001178 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001179 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1180 }
1181
1182 /// Create a register that is definitely an ACC.
1183 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001184 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001185 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001186 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001187 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1188 }
1189
1190 /// Create a register that is definitely an MSA128.
1191 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001192 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001193 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001194 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001195 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1196 }
1197
1198 /// Create a register that is definitely an MSACtrl.
1199 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001200 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001201 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001202 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001203 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1204 }
1205
David Blaikie960ea3f2014-06-08 16:18:35 +00001206 static std::unique_ptr<MipsOperand>
1207 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1208 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001209 Op->Imm.Val = Val;
1210 Op->StartLoc = S;
1211 Op->EndLoc = E;
1212 return Op;
1213 }
1214
David Blaikie960ea3f2014-06-08 16:18:35 +00001215 static std::unique_ptr<MipsOperand>
1216 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1217 SMLoc E, MipsAsmParser &Parser) {
1218 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1219 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001220 Op->Mem.Off = Off;
1221 Op->StartLoc = S;
1222 Op->EndLoc = E;
1223 return Op;
1224 }
1225
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001226 static std::unique_ptr<MipsOperand>
1227 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1228 MipsAsmParser &Parser) {
1229 assert (Regs.size() > 0 && "Empty list not allowed");
1230
1231 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001232 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001233 Op->StartLoc = StartLoc;
1234 Op->EndLoc = EndLoc;
1235 return Op;
1236 }
1237
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001238 static std::unique_ptr<MipsOperand>
1239 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1240 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1241 Op->RegIdx.Index = RegNo;
1242 Op->StartLoc = S;
1243 Op->EndLoc = E;
1244 return Op;
1245 }
1246
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001247 bool isGPRAsmReg() const {
1248 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001249 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001250 bool isMM16AsmReg() const {
1251 if (!(isRegIdx() && RegIdx.Kind))
1252 return false;
1253 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1254 || RegIdx.Index == 16 || RegIdx.Index == 17);
1255 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001256 bool isMM16AsmRegZero() const {
1257 if (!(isRegIdx() && RegIdx.Kind))
1258 return false;
1259 return (RegIdx.Index == 0 ||
1260 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1261 RegIdx.Index == 17);
1262 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001263 bool isMM16AsmRegMoveP() const {
1264 if (!(isRegIdx() && RegIdx.Kind))
1265 return false;
1266 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1267 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1268 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001269 bool isFGRAsmReg() const {
1270 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1271 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001272 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001273 bool isHWRegsAsmReg() const {
1274 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001275 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001276 bool isCCRAsmReg() const {
1277 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001278 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001279 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001280 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1281 return false;
1282 if (!AsmParser.hasEightFccRegisters())
1283 return RegIdx.Index == 0;
1284 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001285 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001286 bool isACCAsmReg() const {
1287 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001288 }
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001289 bool isCOP0AsmReg() const {
1290 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1291 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001292 bool isCOP2AsmReg() const {
1293 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001294 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001295 bool isCOP3AsmReg() const {
1296 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1297 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001298 bool isMSA128AsmReg() const {
1299 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001300 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001301 bool isMSACtrlAsmReg() const {
1302 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001303 }
1304
Jack Carterb4dbc172012-09-05 23:34:03 +00001305 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001306 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001307 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001308 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001309
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001310 virtual ~MipsOperand() {
1311 switch (Kind) {
1312 case k_Immediate:
1313 break;
1314 case k_Memory:
1315 delete Mem.Base;
1316 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001317 case k_RegList:
1318 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001319 case k_PhysRegister:
1320 case k_RegisterIndex:
1321 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001322 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001323 break;
1324 }
1325 }
1326
Craig Topper56c590a2014-04-29 07:58:02 +00001327 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001328 switch (Kind) {
1329 case k_Immediate:
1330 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001331 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001332 OS << ">";
1333 break;
1334 case k_Memory:
1335 OS << "Mem<";
1336 Mem.Base->print(OS);
1337 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001338 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001339 OS << ">";
1340 break;
1341 case k_PhysRegister:
1342 OS << "PhysReg<" << PhysReg.Num << ">";
1343 break;
1344 case k_RegisterIndex:
1345 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1346 break;
1347 case k_Token:
1348 OS << Tok.Data;
1349 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001350 case k_RegList:
1351 OS << "RegList< ";
1352 for (auto Reg : (*RegList.List))
1353 OS << Reg << " ";
1354 OS << ">";
1355 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001356 case k_RegPair:
1357 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1358 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001359 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001360 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001361}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001362} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001363
Jack Carter9e65aa32013-03-22 00:05:30 +00001364namespace llvm {
1365extern const MCInstrDesc MipsInsts[];
1366}
1367static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1368 return MipsInsts[Opcode];
1369}
1370
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001371static bool hasShortDelaySlot(unsigned Opcode) {
1372 switch (Opcode) {
1373 case Mips::JALS_MM:
1374 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001375 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001376 case Mips::BGEZALS_MM:
1377 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001378 return true;
1379 default:
1380 return false;
1381 }
1382}
1383
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001384static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1385 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1386 return &SRExpr->getSymbol();
1387 }
1388
1389 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1390 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1391 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1392
1393 if (LHSSym)
1394 return LHSSym;
1395
1396 if (RHSSym)
1397 return RHSSym;
1398
1399 return nullptr;
1400 }
1401
1402 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1403 return getSingleMCSymbol(UExpr->getSubExpr());
1404
1405 return nullptr;
1406}
1407
1408static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1409 if (isa<MCSymbolRefExpr>(Expr))
1410 return 1;
1411
1412 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1413 return countMCSymbolRefExpr(BExpr->getLHS()) +
1414 countMCSymbolRefExpr(BExpr->getRHS());
1415
1416 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1417 return countMCSymbolRefExpr(UExpr->getSubExpr());
1418
1419 return 0;
1420}
1421
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001422namespace {
1423void emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1, SMLoc IDLoc,
1424 SmallVectorImpl<MCInst> &Instructions) {
1425 MCInst tmpInst;
1426 tmpInst.setOpcode(Opcode);
1427 tmpInst.addOperand(MCOperand::createReg(Reg0));
1428 tmpInst.addOperand(Op1);
1429 tmpInst.setLoc(IDLoc);
1430 Instructions.push_back(tmpInst);
1431}
1432
1433void emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm, SMLoc IDLoc,
1434 SmallVectorImpl<MCInst> &Instructions) {
1435 emitRX(Opcode, Reg0, MCOperand::createImm(Imm), IDLoc, Instructions);
1436}
1437
1438void emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, SMLoc IDLoc,
1439 SmallVectorImpl<MCInst> &Instructions) {
1440 emitRX(Opcode, Reg0, MCOperand::createReg(Reg1), IDLoc, Instructions);
1441}
1442
1443void emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2, SMLoc IDLoc,
1444 SmallVectorImpl<MCInst> &Instructions) {
1445 MCInst tmpInst;
1446 tmpInst.setOpcode(Opcode);
1447 tmpInst.addOperand(MCOperand::createImm(Imm1));
1448 tmpInst.addOperand(MCOperand::createImm(Imm2));
1449 tmpInst.setLoc(IDLoc);
1450 Instructions.push_back(tmpInst);
1451}
1452
1453void emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc,
1454 SmallVectorImpl<MCInst> &Instructions) {
1455 MCInst tmpInst;
1456 tmpInst.setOpcode(Opcode);
1457 tmpInst.addOperand(MCOperand::createReg(Reg0));
1458 tmpInst.setLoc(IDLoc);
1459 Instructions.push_back(tmpInst);
1460}
1461
1462void emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1, MCOperand Op2,
1463 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1464 MCInst tmpInst;
1465 tmpInst.setOpcode(Opcode);
1466 tmpInst.addOperand(MCOperand::createReg(Reg0));
1467 tmpInst.addOperand(MCOperand::createReg(Reg1));
1468 tmpInst.addOperand(Op2);
1469 tmpInst.setLoc(IDLoc);
1470 Instructions.push_back(tmpInst);
1471}
1472
1473void emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, unsigned Reg2,
1474 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1475 emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc,
1476 Instructions);
1477}
1478
1479void emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm,
1480 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1481 emitRRX(Opcode, Reg0, Reg1, MCOperand::createImm(Imm), IDLoc,
1482 Instructions);
1483}
1484
1485void emitAppropriateDSLL(unsigned DstReg, unsigned SrcReg, int16_t ShiftAmount,
1486 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
1487 if (ShiftAmount >= 32) {
1488 emitRRI(Mips::DSLL32, DstReg, SrcReg, ShiftAmount - 32, IDLoc,
1489 Instructions);
1490 return;
1491 }
1492
1493 emitRRI(Mips::DSLL, DstReg, SrcReg, ShiftAmount, IDLoc, Instructions);
1494}
1495} // end anonymous namespace.
1496
Jack Carter9e65aa32013-03-22 00:05:30 +00001497bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001498 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001499 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001500 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001501
Jack Carter9e65aa32013-03-22 00:05:30 +00001502 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001503
1504 if (MCID.isBranch() || MCID.isCall()) {
1505 const unsigned Opcode = Inst.getOpcode();
1506 MCOperand Offset;
1507
1508 switch (Opcode) {
1509 default:
1510 break;
Kai Nackee0245392015-01-27 19:11:28 +00001511 case Mips::BBIT0:
1512 case Mips::BBIT032:
1513 case Mips::BBIT1:
1514 case Mips::BBIT132:
1515 assert(hasCnMips() && "instruction only valid for octeon cpus");
1516 // Fall through
1517
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001518 case Mips::BEQ:
1519 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001520 case Mips::BEQ_MM:
1521 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001522 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001523 Offset = Inst.getOperand(2);
1524 if (!Offset.isImm())
1525 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001526 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001527 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001528 if (OffsetToAlignment(Offset.getImm(),
1529 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001530 return Error(IDLoc, "branch to misaligned address");
1531 break;
1532 case Mips::BGEZ:
1533 case Mips::BGTZ:
1534 case Mips::BLEZ:
1535 case Mips::BLTZ:
1536 case Mips::BGEZAL:
1537 case Mips::BLTZAL:
1538 case Mips::BC1F:
1539 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001540 case Mips::BGEZ_MM:
1541 case Mips::BGTZ_MM:
1542 case Mips::BLEZ_MM:
1543 case Mips::BLTZ_MM:
1544 case Mips::BGEZAL_MM:
1545 case Mips::BLTZAL_MM:
1546 case Mips::BC1F_MM:
1547 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001548 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001549 Offset = Inst.getOperand(1);
1550 if (!Offset.isImm())
1551 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001552 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001553 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001554 if (OffsetToAlignment(Offset.getImm(),
1555 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001556 return Error(IDLoc, "branch to misaligned address");
1557 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001558 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001559 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001560 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001561 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001562 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1563 Offset = Inst.getOperand(1);
1564 if (!Offset.isImm())
1565 break; // We'll deal with this situation later on when applying fixups.
Craig Topper55b1f292015-10-10 20:17:07 +00001566 if (!isInt<8>(Offset.getImm()))
Jozef Kolek9761e962015-01-12 12:03:34 +00001567 return Error(IDLoc, "branch target out of range");
1568 if (OffsetToAlignment(Offset.getImm(), 2LL))
1569 return Error(IDLoc, "branch to misaligned address");
1570 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001571 }
1572 }
1573
Daniel Sandersa84989a2014-06-16 13:25:35 +00001574 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1575 // We still accept it but it is a normal nop.
1576 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1577 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1578 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1579 "nop instruction");
1580 }
1581
Kai Nackee0245392015-01-27 19:11:28 +00001582 if (hasCnMips()) {
1583 const unsigned Opcode = Inst.getOpcode();
1584 MCOperand Opnd;
1585 int Imm;
1586
1587 switch (Opcode) {
1588 default:
1589 break;
1590
1591 case Mips::BBIT0:
1592 case Mips::BBIT032:
1593 case Mips::BBIT1:
1594 case Mips::BBIT132:
1595 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1596 // The offset is handled above
1597 Opnd = Inst.getOperand(1);
1598 if (!Opnd.isImm())
1599 return Error(IDLoc, "expected immediate operand kind");
1600 Imm = Opnd.getImm();
1601 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1602 Opcode == Mips::BBIT1 ? 63 : 31))
1603 return Error(IDLoc, "immediate operand value out of range");
1604 if (Imm > 31) {
1605 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1606 : Mips::BBIT132);
1607 Inst.getOperand(1).setImm(Imm - 32);
1608 }
1609 break;
1610
1611 case Mips::CINS:
1612 case Mips::CINS32:
1613 case Mips::EXTS:
1614 case Mips::EXTS32:
1615 assert(MCID.getNumOperands() == 4 && "unexpected number of operands");
1616 // Check length
1617 Opnd = Inst.getOperand(3);
1618 if (!Opnd.isImm())
1619 return Error(IDLoc, "expected immediate operand kind");
1620 Imm = Opnd.getImm();
1621 if (Imm < 0 || Imm > 31)
1622 return Error(IDLoc, "immediate operand value out of range");
1623 // Check position
1624 Opnd = Inst.getOperand(2);
1625 if (!Opnd.isImm())
1626 return Error(IDLoc, "expected immediate operand kind");
1627 Imm = Opnd.getImm();
1628 if (Imm < 0 || Imm > (Opcode == Mips::CINS ||
1629 Opcode == Mips::EXTS ? 63 : 31))
1630 return Error(IDLoc, "immediate operand value out of range");
1631 if (Imm > 31) {
1632 Inst.setOpcode(Opcode == Mips::CINS ? Mips::CINS32 : Mips::EXTS32);
1633 Inst.getOperand(2).setImm(Imm - 32);
1634 }
1635 break;
1636
1637 case Mips::SEQi:
1638 case Mips::SNEi:
1639 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1640 Opnd = Inst.getOperand(2);
1641 if (!Opnd.isImm())
1642 return Error(IDLoc, "expected immediate operand kind");
1643 Imm = Opnd.getImm();
1644 if (!isInt<10>(Imm))
1645 return Error(IDLoc, "immediate operand value out of range");
1646 break;
1647 }
1648 }
1649
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00001650 // This expansion is not in a function called by tryExpandInstruction()
1651 // because the pseudo-instruction doesn't have a distinct opcode.
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001652 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
1653 inPicMode()) {
1654 warnIfNoMacro(IDLoc);
1655
1656 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
1657
1658 // We can do this expansion if there's only 1 symbol in the argument
1659 // expression.
1660 if (countMCSymbolRefExpr(JalExpr) > 1)
1661 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
1662
1663 // FIXME: This is checking the expression can be handled by the later stages
1664 // of the assembler. We ought to leave it to those later stages but
1665 // we can't do that until we stop evaluateRelocExpr() rewriting the
1666 // expressions into non-equivalent forms.
1667 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
1668
1669 // FIXME: Add support for label+offset operands (currently causes an error).
1670 // FIXME: Add support for forward-declared local symbols.
1671 // FIXME: Add expansion for when the LargeGOT option is enabled.
1672 if (JalSym->isInSection() || JalSym->isTemporary()) {
1673 if (isABI_O32()) {
1674 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001675 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001676 // R_(MICRO)MIPS_GOT16 label
1677 // addiu $25, $25, 0
1678 // R_(MICRO)MIPS_LO16 label
1679 // jalr $25
1680 const MCExpr *Got16RelocExpr = evaluateRelocExpr(JalExpr, "got");
1681 const MCExpr *Lo16RelocExpr = evaluateRelocExpr(JalExpr, "lo");
1682
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001683 emitRRX(Mips::LW, Mips::T9, Mips::GP,
1684 MCOperand::createExpr(Got16RelocExpr), IDLoc, Instructions);
1685 emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
1686 MCOperand::createExpr(Lo16RelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001687 } else if (isABI_N32() || isABI_N64()) {
1688 // If it's a local symbol and the N32/N64 ABIs are being used,
1689 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001690 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001691 // R_(MICRO)MIPS_GOT_DISP label
1692 // jalr $25
1693 const MCExpr *GotDispRelocExpr = evaluateRelocExpr(JalExpr, "got_disp");
1694
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001695 emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1696 MCOperand::createExpr(GotDispRelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001697 }
1698 } else {
1699 // If it's an external/weak symbol, we expand to:
1700 // lw/ld $25, 0($gp)
1701 // R_(MICRO)MIPS_CALL16 label
1702 // jalr $25
1703 const MCExpr *Call16RelocExpr = evaluateRelocExpr(JalExpr, "call16");
1704
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001705 emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
1706 MCOperand::createExpr(Call16RelocExpr), IDLoc, Instructions);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001707 }
1708
1709 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001710 if (IsCpRestoreSet && inMicroMipsMode())
1711 JalrInst.setOpcode(Mips::JALRS_MM);
1712 else
1713 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001714 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
1715 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
1716
1717 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
1718 // This relocation is supposed to be an optimization hint for the linker
1719 // and is not necessary for correctness.
1720
1721 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001722 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001723 }
1724
Jack Carter9e65aa32013-03-22 00:05:30 +00001725 if (MCID.mayLoad() || MCID.mayStore()) {
1726 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001727 // reference or immediate we may have to expand instructions.
1728 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001729 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001730 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1731 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001732 MCOperand &Op = Inst.getOperand(i);
1733 if (Op.isImm()) {
1734 int MemOffset = Op.getImm();
1735 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001736 // Offset can't exceed 16bit value.
1737 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001738 return false;
1739 }
1740 } else if (Op.isExpr()) {
1741 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001742 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001743 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001744 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001745 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001746 // Expand symbol.
1747 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001748 return false;
1749 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001750 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001751 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001752 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001753 }
1754 }
1755 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001756 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001757 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001758
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001759 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001760 if (MCID.mayLoad()) {
1761 // Try to create 16-bit GP relative load instruction.
1762 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1763 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1764 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1765 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1766 MCOperand &Op = Inst.getOperand(i);
1767 if (Op.isImm()) {
1768 int MemOffset = Op.getImm();
1769 MCOperand &DstReg = Inst.getOperand(0);
1770 MCOperand &BaseReg = Inst.getOperand(1);
Craig Topper55b1f292015-10-10 20:17:07 +00001771 if (isInt<9>(MemOffset) && (MemOffset % 4 == 0) &&
Jozef Koleke10a02e2015-01-28 17:27:26 +00001772 getContext().getRegisterInfo()->getRegClass(
1773 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00001774 (BaseReg.getReg() == Mips::GP ||
1775 BaseReg.getReg() == Mips::GP_64)) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00001776
1777 emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
1778 IDLoc, Instructions);
Jozef Koleke10a02e2015-01-28 17:27:26 +00001779 return false;
1780 }
1781 }
1782 }
1783 } // for
1784 } // if load
1785
1786 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1787
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001788 MCOperand Opnd;
1789 int Imm;
1790
1791 switch (Inst.getOpcode()) {
1792 default:
1793 break;
1794 case Mips::ADDIUS5_MM:
1795 Opnd = Inst.getOperand(2);
1796 if (!Opnd.isImm())
1797 return Error(IDLoc, "expected immediate operand kind");
1798 Imm = Opnd.getImm();
1799 if (Imm < -8 || Imm > 7)
1800 return Error(IDLoc, "immediate operand value out of range");
1801 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001802 case Mips::ADDIUSP_MM:
1803 Opnd = Inst.getOperand(0);
1804 if (!Opnd.isImm())
1805 return Error(IDLoc, "expected immediate operand kind");
1806 Imm = Opnd.getImm();
1807 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1808 Imm % 4 != 0)
1809 return Error(IDLoc, "immediate operand value out of range");
1810 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001811 case Mips::SLL16_MM:
1812 case Mips::SRL16_MM:
1813 Opnd = Inst.getOperand(2);
1814 if (!Opnd.isImm())
1815 return Error(IDLoc, "expected immediate operand kind");
1816 Imm = Opnd.getImm();
1817 if (Imm < 1 || Imm > 8)
1818 return Error(IDLoc, "immediate operand value out of range");
1819 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001820 case Mips::LI16_MM:
1821 Opnd = Inst.getOperand(1);
1822 if (!Opnd.isImm())
1823 return Error(IDLoc, "expected immediate operand kind");
1824 Imm = Opnd.getImm();
1825 if (Imm < -1 || Imm > 126)
1826 return Error(IDLoc, "immediate operand value out of range");
1827 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001828 case Mips::ADDIUR2_MM:
1829 Opnd = Inst.getOperand(2);
1830 if (!Opnd.isImm())
1831 return Error(IDLoc, "expected immediate operand kind");
1832 Imm = Opnd.getImm();
1833 if (!(Imm == 1 || Imm == -1 ||
1834 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1835 return Error(IDLoc, "immediate operand value out of range");
1836 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001837 case Mips::ADDIUR1SP_MM:
1838 Opnd = Inst.getOperand(1);
1839 if (!Opnd.isImm())
1840 return Error(IDLoc, "expected immediate operand kind");
1841 Imm = Opnd.getImm();
1842 if (OffsetToAlignment(Imm, 4LL))
1843 return Error(IDLoc, "misaligned immediate operand value");
1844 if (Imm < 0 || Imm > 255)
1845 return Error(IDLoc, "immediate operand value out of range");
1846 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001847 case Mips::ANDI16_MM:
1848 Opnd = Inst.getOperand(2);
1849 if (!Opnd.isImm())
1850 return Error(IDLoc, "expected immediate operand kind");
1851 Imm = Opnd.getImm();
1852 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1853 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1854 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1855 return Error(IDLoc, "immediate operand value out of range");
1856 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001857 case Mips::LBU16_MM:
1858 Opnd = Inst.getOperand(2);
1859 if (!Opnd.isImm())
1860 return Error(IDLoc, "expected immediate operand kind");
1861 Imm = Opnd.getImm();
1862 if (Imm < -1 || Imm > 14)
1863 return Error(IDLoc, "immediate operand value out of range");
1864 break;
Zoran Jovanovic7ba636c2015-09-17 10:14:09 +00001865 case Mips::TEQ_MM:
1866 case Mips::TGE_MM:
1867 case Mips::TGEU_MM:
1868 case Mips::TLT_MM:
1869 case Mips::TLTU_MM:
1870 case Mips::TNE_MM:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001871 case Mips::SB16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001872 case Mips::SB16_MMR6:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001873 Opnd = Inst.getOperand(2);
1874 if (!Opnd.isImm())
1875 return Error(IDLoc, "expected immediate operand kind");
1876 Imm = Opnd.getImm();
1877 if (Imm < 0 || Imm > 15)
1878 return Error(IDLoc, "immediate operand value out of range");
1879 break;
1880 case Mips::LHU16_MM:
1881 case Mips::SH16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001882 case Mips::SH16_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 > 30 || (Imm % 2 != 0))
1888 return Error(IDLoc, "immediate operand value out of range");
1889 break;
1890 case Mips::LW16_MM:
1891 case Mips::SW16_MM:
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00001892 case Mips::SW16_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 > 60 || (Imm % 4 != 0))
1898 return Error(IDLoc, "immediate operand value out of range");
1899 break;
Zoran Jovanovic6e6a2c92015-09-16 09:14:35 +00001900 case Mips::PREFX_MM:
Jozef Kolekab6d1cc2014-12-23 19:55:34 +00001901 case Mips::CACHE:
1902 case Mips::PREF:
1903 Opnd = Inst.getOperand(2);
1904 if (!Opnd.isImm())
1905 return Error(IDLoc, "expected immediate operand kind");
1906 Imm = Opnd.getImm();
1907 if (!isUInt<5>(Imm))
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;
Daniel Sanders6394ee52015-10-15 14:52:58 +00002061 case Mips::Ulh:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002062 return expandUlh(Inst, true, IDLoc, Instructions) ? MER_Fail : MER_Success;
Toma Tabacud88d79c2015-06-23 14:39:42 +00002063 case Mips::Ulhu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002064 return expandUlh(Inst, false, IDLoc, Instructions) ? MER_Fail : MER_Success;
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00002065 case Mips::Ulw:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002066 return expandUlw(Inst, IDLoc, Instructions) ? MER_Fail : MER_Success;
2067 case Mips::NORImm:
2068 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2069 : MER_Success;
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002070 case Mips::ADDi:
2071 case Mips::ADDiu:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002072 case Mips::SLTi:
2073 case Mips::SLTiu:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002074 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2075 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2076 int64_t ImmValue = Inst.getOperand(2).getImm();
2077 if (isInt<16>(ImmValue))
2078 return MER_NotAMacro;
2079 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2080 : MER_Success;
2081 }
2082 return MER_NotAMacro;
2083 case Mips::ANDi:
2084 case Mips::ORi:
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00002085 case Mips::XORi:
Daniel Sanders5bf6eab2015-10-26 23:50:00 +00002086 if ((Inst.getNumOperands() == 3) && Inst.getOperand(0).isReg() &&
2087 Inst.getOperand(1).isReg() && Inst.getOperand(2).isImm()) {
2088 int64_t ImmValue = Inst.getOperand(2).getImm();
2089 if (isUInt<16>(ImmValue))
2090 return MER_NotAMacro;
2091 return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
2092 : MER_Success;
2093 }
2094 return MER_NotAMacro;
Jack Carterd0bd6422013-04-18 00:41:53 +00002095 }
Jack Carter30a59822012-10-04 04:03:53 +00002096}
Jack Carter92995f12012-10-06 00:53:28 +00002097
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002098bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
2099 SmallVectorImpl<MCInst> &Instructions) {
2100 // Create a JALR instruction which is going to replace the pseudo-JAL.
2101 MCInst JalrInst;
2102 JalrInst.setLoc(IDLoc);
2103 const MCOperand FirstRegOp = Inst.getOperand(0);
2104 const unsigned Opcode = Inst.getOpcode();
2105
2106 if (Opcode == Mips::JalOneReg) {
2107 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002108 if (IsCpRestoreSet && inMicroMipsMode()) {
2109 JalrInst.setOpcode(Mips::JALRS16_MM);
2110 JalrInst.addOperand(FirstRegOp);
2111 } else if (inMicroMipsMode()) {
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002112 JalrInst.setOpcode(hasMips32r6() ? Mips::JALRC16_MMR6 : Mips::JALR16_MM);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002113 JalrInst.addOperand(FirstRegOp);
2114 } else {
2115 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002116 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002117 JalrInst.addOperand(FirstRegOp);
2118 }
2119 } else if (Opcode == Mips::JalTwoReg) {
2120 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002121 if (IsCpRestoreSet && inMicroMipsMode())
2122 JalrInst.setOpcode(Mips::JALRS_MM);
2123 else
2124 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002125 JalrInst.addOperand(FirstRegOp);
2126 const MCOperand SecondRegOp = Inst.getOperand(1);
2127 JalrInst.addOperand(SecondRegOp);
2128 }
2129 Instructions.push_back(JalrInst);
2130
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002131 // If .set reorder is active and branch instruction has a delay slot,
2132 // emit a NOP after it.
2133 const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
2134 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002135 createNop(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc, Instructions);
Zoran Jovanovic5a8dffc2015-10-05 14:00:09 +00002136 }
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002137
2138 return false;
2139}
2140
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002141/// Can the value be represented by a unsigned N-bit value and a shift left?
Benjamin Kramer039b1042015-10-28 13:54:36 +00002142template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002143 unsigned BitNum = findFirstSet(x);
2144
2145 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2146}
2147
2148/// Load (or add) an immediate into a register.
2149///
2150/// @param ImmValue The immediate to load.
2151/// @param DstReg The register that will hold the immediate.
2152/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2153/// for a simple initialization.
2154/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2155/// @param IsAddress True if the immediate represents an address. False if it
2156/// is an integer.
2157/// @param IDLoc Location of the immediate in the source file.
2158/// @param Instructions The instructions emitted by this expansion.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002159bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002160 unsigned SrcReg, bool Is32BitImm,
2161 bool IsAddress, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00002162 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu00e98672015-05-01 12:19:27 +00002163 if (!Is32BitImm && !isGP64bit()) {
2164 Error(IDLoc, "instruction requires a 64-bit architecture");
2165 return true;
2166 }
2167
Daniel Sanders03f9c012015-07-14 12:24:22 +00002168 if (Is32BitImm) {
2169 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2170 // Sign extend up to 64-bit so that the predicates match the hardware
2171 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2172 // true.
2173 ImmValue = SignExtend64<32>(ImmValue);
2174 } else {
2175 Error(IDLoc, "instruction requires a 32-bit immediate");
2176 return true;
2177 }
2178 }
2179
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002180 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2181 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2182
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002183 bool UseSrcReg = false;
2184 if (SrcReg != Mips::NoRegister)
2185 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002186
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002187 unsigned TmpReg = DstReg;
2188 if (UseSrcReg && (DstReg == SrcReg)) {
2189 // At this point we need AT to perform the expansions and we exit if it is
2190 // not available.
2191 unsigned ATReg = getATReg(IDLoc);
2192 if (!ATReg)
2193 return true;
2194 TmpReg = ATReg;
2195 }
2196
Daniel Sanders03f9c012015-07-14 12:24:22 +00002197 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002198 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002199 SrcReg = ZeroReg;
2200
2201 // This doesn't quite follow the usual ABI expectations for N32 but matches
2202 // traditional assembler behaviour. N32 would normally use addiu for both
2203 // integers and addresses.
2204 if (IsAddress && !Is32BitImm) {
2205 emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2206 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002207 }
2208
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002209 emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2210 return false;
2211 }
2212
2213 if (isUInt<16>(ImmValue)) {
2214 unsigned TmpReg = DstReg;
2215 if (SrcReg == DstReg) {
2216 TmpReg = getATReg(IDLoc);
2217 if (!TmpReg)
2218 return true;
2219 }
2220
2221 emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002222 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002223 emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2224 return false;
2225 }
2226
2227 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002228 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002229
Toma Tabacu79588102015-04-29 10:19:56 +00002230 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2231 uint16_t Bits15To0 = ImmValue & 0xffff;
2232
Toma Tabacua3d056f2015-05-15 09:42:11 +00002233 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002234 // Traditional behaviour seems to special case this particular value. It's
2235 // not clear why other masks are handled differently.
2236 if (ImmValue == 0xffffffff) {
Daniel Sandersf1ae3672015-08-18 09:55:57 +00002237 emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002238 emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, Instructions);
2239 if (UseSrcReg)
2240 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2241 return false;
2242 }
2243
2244 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002245 // upper 32 bits.
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002246 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002247 emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002248 if (Bits15To0)
2249 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
2250 if (UseSrcReg)
2251 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2252 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002253 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002254
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002255 emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, Instructions);
2256 if (Bits15To0)
2257 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002258 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002259 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2260 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002261 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002262
2263 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2264 if (Is32BitImm) {
2265 Error(IDLoc, "instruction requires a 32-bit immediate");
2266 return true;
2267 }
2268
2269 // Traditionally, these immediates are shifted as little as possible and as
2270 // such we align the most significant bit to bit 15 of our temporary.
2271 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2272 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2273 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2274 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
2275 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, Instructions);
2276 emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, Instructions);
2277
2278 if (UseSrcReg)
2279 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2280
2281 return false;
2282 }
2283
2284 warnIfNoMacro(IDLoc);
2285
2286 // The remaining case is packed with a sequence of dsll and ori with zeros
2287 // being omitted and any neighbouring dsll's being coalesced.
2288 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2289
2290 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2291 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
2292 IDLoc, Instructions))
2293 return false;
2294
2295 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2296 // skip it and defer the shift to the next chunk.
2297 unsigned ShiftCarriedForwards = 16;
2298 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2299 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2300
2301 if (ImmChunk != 0) {
2302 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2303 Instructions);
2304 emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, Instructions);
2305 ShiftCarriedForwards = 0;
2306 }
2307
2308 ShiftCarriedForwards += 16;
2309 }
2310 ShiftCarriedForwards -= 16;
2311
2312 // Finish any remaining shifts left by trailing zeros.
2313 if (ShiftCarriedForwards)
2314 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2315 Instructions);
2316
2317 if (UseSrcReg)
2318 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2319
Matheus Almeida3813d572014-06-19 14:39:14 +00002320 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002321}
Jack Carter92995f12012-10-06 00:53:28 +00002322
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002323bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
2324 SmallVectorImpl<MCInst> &Instructions) {
2325 const MCOperand &ImmOp = Inst.getOperand(1);
2326 assert(ImmOp.isImm() && "expected immediate operand kind");
2327 const MCOperand &DstRegOp = Inst.getOperand(0);
2328 assert(DstRegOp.isReg() && "expected register operand kind");
2329
2330 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002331 Is32BitImm, false, IDLoc, Instructions))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002332 return true;
2333
2334 return false;
2335}
2336
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002337bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2338 const MCOperand &Offset,
2339 bool Is32BitAddress, SMLoc IDLoc,
2340 SmallVectorImpl<MCInst> &Instructions) {
2341 // la can't produce a usable address when addresses are 64-bit.
2342 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2343 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2344 // We currently can't do this because we depend on the equality
2345 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2346 Error(IDLoc, "la used to load 64-bit address");
2347 // Continue as if we had 'dla' instead.
2348 Is32BitAddress = false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002349 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002350
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002351 // dla requires 64-bit addresses.
2352 if (!Is32BitAddress && !ABI.ArePtrs64bit()) {
2353 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002354 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002355 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002356
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002357 if (!Offset.isImm())
2358 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
2359 Is32BitAddress, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002360
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002361 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
2362 IDLoc, Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +00002363}
2364
Toma Tabacuf712ede2015-06-17 14:31:51 +00002365bool MipsAsmParser::loadAndAddSymbolAddress(
2366 const MCExpr *SymExpr, unsigned DstReg, unsigned SrcReg, bool Is32BitSym,
2367 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002368 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002369
Daniel Sandersd5a89412015-10-05 13:19:29 +00002370 const MCExpr *Symbol = cast<MCExpr>(SymExpr);
2371 const MipsMCExpr *HiExpr = MipsMCExpr::create(
2372 MCSymbolRefExpr::VK_Mips_ABS_HI, Symbol, getContext());
2373 const MipsMCExpr *LoExpr = MipsMCExpr::create(
2374 MCSymbolRefExpr::VK_Mips_ABS_LO, Symbol, getContext());
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002375
Toma Tabacufb9d1252015-06-22 12:08:39 +00002376 bool UseSrcReg = SrcReg != Mips::NoRegister;
2377
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002378 // This is the 64-bit symbol address expansion.
2379 if (ABI.ArePtrs64bit() && isGP64bit()) {
2380 // We always need AT for the 64-bit expansion.
2381 // If it is not available we exit.
2382 unsigned ATReg = getATReg(IDLoc);
2383 if (!ATReg)
2384 return true;
2385
Daniel Sandersd5a89412015-10-05 13:19:29 +00002386 const MipsMCExpr *HighestExpr = MipsMCExpr::create(
2387 MCSymbolRefExpr::VK_Mips_HIGHEST, Symbol, getContext());
2388 const MipsMCExpr *HigherExpr = MipsMCExpr::create(
2389 MCSymbolRefExpr::VK_Mips_HIGHER, Symbol, getContext());
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002390
2391 if (UseSrcReg && (DstReg == SrcReg)) {
2392 // If $rs is the same as $rd:
2393 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2394 // daddiu $at, $at, %higher(sym)
2395 // dsll $at, $at, 16
2396 // daddiu $at, $at, %hi(sym)
2397 // dsll $at, $at, 16
2398 // daddiu $at, $at, %lo(sym)
2399 // daddu $rd, $at, $rd
2400 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2401 Instructions);
2402 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HigherExpr),
2403 IDLoc, Instructions);
2404 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2405 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2406 Instructions);
2407 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2408 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2409 Instructions);
2410 emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, Instructions);
2411
2412 return false;
2413 }
2414
2415 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2416 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2417 // lui $at, %hi(sym)
2418 // daddiu $rd, $rd, %higher(sym)
2419 // daddiu $at, $at, %lo(sym)
2420 // dsll32 $rd, $rd, 0
2421 // daddu $rd, $rd, $at
2422 // (daddu $rd, $rd, $rs)
2423 emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2424 Instructions);
2425 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2426 Instructions);
2427 emitRRX(Mips::DADDiu, DstReg, DstReg, MCOperand::createExpr(HigherExpr),
2428 IDLoc, Instructions);
2429 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2430 Instructions);
2431 emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, Instructions);
2432 emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, Instructions);
2433 if (UseSrcReg)
2434 emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, Instructions);
2435
2436 return false;
2437 }
2438
2439 // And now, the 32-bit symbol address expansion:
2440 // If $rs is the same as $rd:
2441 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
2442 // ori $at, $at, %lo(sym)
2443 // addu $rd, $at, $rd
2444 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2445 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
2446 // ori $rd, $rd, %lo(sym)
2447 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00002448 unsigned TmpReg = DstReg;
2449 if (UseSrcReg && (DstReg == SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002450 // If $rs is the same as $rd, we need to use AT.
2451 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00002452 unsigned ATReg = getATReg(IDLoc);
2453 if (!ATReg)
2454 return true;
2455 TmpReg = ATReg;
2456 }
2457
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002458 emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, Instructions);
2459 emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr), IDLoc,
2460 Instructions);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002461
Toma Tabacufb9d1252015-06-22 12:08:39 +00002462 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002463 emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2464 else
2465 assert(DstReg == TmpReg);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002466
Toma Tabacu674825c2015-06-16 12:16:24 +00002467 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002468}
2469
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00002470bool MipsAsmParser::expandUncondBranchMMPseudo(
2471 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002472 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2473 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002474
2475 MCOperand Offset = Inst.getOperand(0);
2476 if (Offset.isExpr()) {
2477 Inst.clear();
2478 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002479 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2480 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2481 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002482 } else {
2483 assert(Offset.isImm() && "expected immediate operand kind");
Craig Topper55b1f292015-10-10 20:17:07 +00002484 if (isInt<11>(Offset.getImm())) {
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002485 // If offset fits into 11 bits then this instruction becomes microMIPS
2486 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00002487 if (inMicroMipsMode())
2488 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002489 } else {
Craig Topper55b1f292015-10-10 20:17:07 +00002490 if (!isInt<17>(Offset.getImm()))
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002491 Error(IDLoc, "branch target out of range");
2492 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2493 Error(IDLoc, "branch to misaligned address");
2494 Inst.clear();
2495 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002496 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2497 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2498 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002499 }
2500 }
2501 Instructions.push_back(Inst);
2502
Zoran Jovanovicada70912015-09-07 11:56:37 +00002503 // If .set reorder is active and branch instruction has a delay slot,
2504 // emit a NOP after it.
2505 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
2506 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Toma Tabacu234482a2015-03-16 12:03:39 +00002507 createNop(true, IDLoc, Instructions);
2508
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002509 return false;
2510}
2511
Toma Tabacue1e460d2015-06-11 10:36:10 +00002512bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc,
2513 SmallVectorImpl<MCInst> &Instructions) {
2514 const MCOperand &DstRegOp = Inst.getOperand(0);
2515 assert(DstRegOp.isReg() && "expected register operand kind");
2516
2517 const MCOperand &ImmOp = Inst.getOperand(1);
2518 assert(ImmOp.isImm() && "expected immediate operand kind");
2519
2520 const MCOperand &MemOffsetOp = Inst.getOperand(2);
2521 assert(MemOffsetOp.isImm() && "expected immediate operand kind");
2522
2523 unsigned OpCode = 0;
2524 switch(Inst.getOpcode()) {
2525 case Mips::BneImm:
2526 OpCode = Mips::BNE;
2527 break;
2528 case Mips::BeqImm:
2529 OpCode = Mips::BEQ;
2530 break;
2531 default:
2532 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2533 break;
2534 }
2535
2536 int64_t ImmValue = ImmOp.getImm();
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002537 if (ImmValue == 0)
2538 emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
2539 Instructions);
2540 else {
Toma Tabacue1e460d2015-06-11 10:36:10 +00002541 warnIfNoMacro(IDLoc);
2542
2543 unsigned ATReg = getATReg(IDLoc);
2544 if (!ATReg)
2545 return true;
2546
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002547 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
2548 IDLoc, Instructions))
Toma Tabacue1e460d2015-06-11 10:36:10 +00002549 return true;
2550
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002551 emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, Instructions);
Toma Tabacue1e460d2015-06-11 10:36:10 +00002552 }
2553 return false;
2554}
2555
Jack Carter9e65aa32013-03-22 00:05:30 +00002556void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00002557 SmallVectorImpl<MCInst> &Instructions,
2558 bool isLoad, bool isImmOpnd) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002559 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00002560 const MCExpr *ExprOffset;
2561 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00002562 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002563 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2564 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002565 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002566 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2567 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002568 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002569 if (isImmOpnd) {
2570 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2571 ImmOffset = Inst.getOperand(2).getImm();
2572 LoOffset = ImmOffset & 0x0000ffff;
2573 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002574 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002575 if (LoOffset & 0x8000)
2576 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002577 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002578 ExprOffset = Inst.getOperand(2).getExpr();
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002579 // These are some of the types of expansions we perform here:
2580 // 1) lw $8, sym => lui $8, %hi(sym)
2581 // lw $8, %lo(sym)($8)
2582 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2583 // add $8, $8, $9
2584 // lw $8, %lo(offset)($9)
2585 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2586 // add $at, $at, $8
2587 // lw $8, %lo(offset)($at)
2588 // 4) sw $8, sym => lui $at, %hi(sym)
2589 // sw $8, %lo(sym)($at)
2590 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2591 // add $at, $at, $8
2592 // sw $8, %lo(offset)($at)
2593 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2594 // ldc1 $f0, %lo(sym)($at)
2595 //
2596 // For load instructions we can use the destination register as a temporary
2597 // if base and dst are different (examples 1 and 2) and if the base register
2598 // is general purpose otherwise we must use $at (example 6) and error if it's
2599 // not available. For stores we must use $at (examples 4 and 5) because we
2600 // must not clobber the source register setting up the offset.
2601 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2602 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2603 unsigned RegClassIDOp0 =
2604 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2605 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2606 (RegClassIDOp0 == Mips::GPR64RegClassID);
2607 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002608 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002609 else {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002610 // At this point we need AT to perform the expansions and we exit if it is
2611 // not available.
Toma Tabacu89a712b2015-04-15 10:48:56 +00002612 TmpRegNum = getATReg(IDLoc);
2613 if (!TmpRegNum)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002614 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002615 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002616
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002617 emitRX(Mips::LUi, TmpRegNum,
2618 isImmOpnd ? MCOperand::createImm(HiOffset)
2619 : MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "hi")),
2620 IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00002621 // Add temp register to base.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002622 if (BaseRegNum != Mips::ZERO)
2623 emitRRR(Mips::ADDu, TmpRegNum, TmpRegNum, BaseRegNum, IDLoc, Instructions);
Alp Tokercb402912014-01-24 17:20:08 +00002624 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002625 // of offset and new base.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002626 emitRRX(Inst.getOpcode(), RegOpNum, TmpRegNum,
2627 isImmOpnd
2628 ? MCOperand::createImm(LoOffset)
2629 : MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "lo")),
2630 IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +00002631}
2632
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002633bool
2634MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2635 SmallVectorImpl<MCInst> &Instructions) {
2636 unsigned OpNum = Inst.getNumOperands();
2637 unsigned Opcode = Inst.getOpcode();
2638 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2639
2640 assert (Inst.getOperand(OpNum - 1).isImm() &&
2641 Inst.getOperand(OpNum - 2).isReg() &&
2642 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2643
2644 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2645 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002646 (Inst.getOperand(OpNum - 2).getReg() == Mips::SP ||
2647 Inst.getOperand(OpNum - 2).getReg() == Mips::SP_64) &&
2648 (Inst.getOperand(OpNum - 3).getReg() == Mips::RA ||
2649 Inst.getOperand(OpNum - 3).getReg() == Mips::RA_64)) {
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002650 // It can be implemented as SWM16 or LWM16 instruction.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00002651 if (inMicroMipsMode() && hasMips32r6())
2652 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MMR6 : Mips::LWM16_MMR6;
2653 else
2654 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2655 }
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002656
2657 Inst.setOpcode(NewOpcode);
2658 Instructions.push_back(Inst);
2659 return false;
2660}
2661
Toma Tabacu1a108322015-06-17 13:20:24 +00002662bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
2663 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002664 bool EmittedNoMacroWarning = false;
Toma Tabacu1a108322015-06-17 13:20:24 +00002665 unsigned PseudoOpcode = Inst.getOpcode();
2666 unsigned SrcReg = Inst.getOperand(0).getReg();
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002667 const MCOperand &TrgOp = Inst.getOperand(1);
Toma Tabacu1a108322015-06-17 13:20:24 +00002668 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
2669
2670 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002671 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00002672
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002673 unsigned TrgReg;
2674 if (TrgOp.isReg())
2675 TrgReg = TrgOp.getReg();
2676 else if (TrgOp.isImm()) {
2677 warnIfNoMacro(IDLoc);
2678 EmittedNoMacroWarning = true;
2679
2680 TrgReg = getATReg(IDLoc);
2681 if (!TrgReg)
2682 return true;
2683
2684 switch(PseudoOpcode) {
2685 default:
2686 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2687 case Mips::BLTImmMacro:
2688 PseudoOpcode = Mips::BLT;
2689 break;
2690 case Mips::BLEImmMacro:
2691 PseudoOpcode = Mips::BLE;
2692 break;
2693 case Mips::BGEImmMacro:
2694 PseudoOpcode = Mips::BGE;
2695 break;
2696 case Mips::BGTImmMacro:
2697 PseudoOpcode = Mips::BGT;
2698 break;
2699 case Mips::BLTUImmMacro:
2700 PseudoOpcode = Mips::BLTU;
2701 break;
2702 case Mips::BLEUImmMacro:
2703 PseudoOpcode = Mips::BLEU;
2704 break;
2705 case Mips::BGEUImmMacro:
2706 PseudoOpcode = Mips::BGEU;
2707 break;
2708 case Mips::BGTUImmMacro:
2709 PseudoOpcode = Mips::BGTU;
2710 break;
2711 case Mips::BLTLImmMacro:
2712 PseudoOpcode = Mips::BLTL;
2713 break;
2714 case Mips::BLELImmMacro:
2715 PseudoOpcode = Mips::BLEL;
2716 break;
2717 case Mips::BGELImmMacro:
2718 PseudoOpcode = Mips::BGEL;
2719 break;
2720 case Mips::BGTLImmMacro:
2721 PseudoOpcode = Mips::BGTL;
2722 break;
2723 case Mips::BLTULImmMacro:
2724 PseudoOpcode = Mips::BLTUL;
2725 break;
2726 case Mips::BLEULImmMacro:
2727 PseudoOpcode = Mips::BLEUL;
2728 break;
2729 case Mips::BGEULImmMacro:
2730 PseudoOpcode = Mips::BGEUL;
2731 break;
2732 case Mips::BGTULImmMacro:
2733 PseudoOpcode = Mips::BGTUL;
2734 break;
2735 }
2736
2737 if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
2738 false, IDLoc, Instructions))
2739 return true;
2740 }
2741
Toma Tabacu1a108322015-06-17 13:20:24 +00002742 switch (PseudoOpcode) {
2743 case Mips::BLT:
2744 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002745 case Mips::BLTL:
2746 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002747 AcceptsEquality = false;
2748 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002749 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
2750 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002751 ZeroSrcOpcode = Mips::BGTZ;
2752 ZeroTrgOpcode = Mips::BLTZ;
2753 break;
2754 case Mips::BLE:
2755 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002756 case Mips::BLEL:
2757 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002758 AcceptsEquality = true;
2759 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002760 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
2761 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002762 ZeroSrcOpcode = Mips::BGEZ;
2763 ZeroTrgOpcode = Mips::BLEZ;
2764 break;
2765 case Mips::BGE:
2766 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002767 case Mips::BGEL:
2768 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002769 AcceptsEquality = true;
2770 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002771 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
2772 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002773 ZeroSrcOpcode = Mips::BLEZ;
2774 ZeroTrgOpcode = Mips::BGEZ;
2775 break;
2776 case Mips::BGT:
2777 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002778 case Mips::BGTL:
2779 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002780 AcceptsEquality = false;
2781 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002782 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
2783 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002784 ZeroSrcOpcode = Mips::BLTZ;
2785 ZeroTrgOpcode = Mips::BGTZ;
2786 break;
2787 default:
2788 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2789 }
2790
Toma Tabacu1a108322015-06-17 13:20:24 +00002791 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
2792 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
2793 if (IsSrcRegZero && IsTrgRegZero) {
2794 // FIXME: All of these Opcode-specific if's are needed for compatibility
2795 // with GAS' behaviour. However, they may not generate the most efficient
2796 // code in some circumstances.
2797 if (PseudoOpcode == Mips::BLT) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002798 emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2799 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002800 return false;
2801 }
2802 if (PseudoOpcode == Mips::BLE) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002803 emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2804 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002805 Warning(IDLoc, "branch is always taken");
2806 return false;
2807 }
2808 if (PseudoOpcode == Mips::BGE) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002809 emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2810 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002811 Warning(IDLoc, "branch is always taken");
2812 return false;
2813 }
2814 if (PseudoOpcode == Mips::BGT) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002815 emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2816 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002817 return false;
2818 }
2819 if (PseudoOpcode == Mips::BGTU) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002820 emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
2821 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002822 return false;
2823 }
2824 if (AcceptsEquality) {
2825 // If both registers are $0 and the pseudo-branch accepts equality, it
2826 // will always be taken, so we emit an unconditional branch.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002827 emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2828 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002829 Warning(IDLoc, "branch is always taken");
2830 return false;
2831 }
2832 // If both registers are $0 and the pseudo-branch does not accept
2833 // equality, it will never be taken, so we don't have to emit anything.
2834 return false;
2835 }
2836 if (IsSrcRegZero || IsTrgRegZero) {
2837 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
2838 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
2839 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
2840 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
2841 // the pseudo-branch will never be taken, so we don't emit anything.
2842 // This only applies to unsigned pseudo-branches.
2843 return false;
2844 }
2845 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
2846 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
2847 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
2848 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
2849 // the pseudo-branch will always be taken, so we emit an unconditional
2850 // branch.
2851 // This only applies to unsigned pseudo-branches.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002852 emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
2853 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002854 Warning(IDLoc, "branch is always taken");
2855 return false;
2856 }
2857 if (IsUnsigned) {
2858 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
2859 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
2860 // the pseudo-branch will be taken only when the non-zero register is
2861 // different from 0, so we emit a BNEZ.
2862 //
2863 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
2864 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
2865 // the pseudo-branch will be taken only when the non-zero register is
2866 // equal to 0, so we emit a BEQZ.
2867 //
2868 // Because only BLEU and BGEU branch on equality, we can use the
2869 // AcceptsEquality variable to decide when to emit the BEQZ.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002870 emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
2871 IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
2872 MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002873 return false;
2874 }
2875 // If we have a signed pseudo-branch and one of the registers is $0,
2876 // we can use an appropriate compare-to-zero branch. We select which one
2877 // to use in the switch statement above.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002878 emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
2879 IsSrcRegZero ? TrgReg : SrcReg, MCOperand::createExpr(OffsetExpr),
2880 IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002881 return false;
2882 }
2883
2884 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
2885 // expansions. If it is not available, we return.
2886 unsigned ATRegNum = getATReg(IDLoc);
2887 if (!ATRegNum)
2888 return true;
2889
Daniel Sandersb1ef88c2015-10-12 14:24:05 +00002890 if (!EmittedNoMacroWarning)
2891 warnIfNoMacro(IDLoc);
Toma Tabacu1a108322015-06-17 13:20:24 +00002892
2893 // SLT fits well with 2 of our 4 pseudo-branches:
2894 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
2895 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
2896 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
2897 // This is accomplished by using a BNEZ with the result of the SLT.
2898 //
2899 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
2900 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
2901 // Because only BGE and BLE branch on equality, we can use the
2902 // AcceptsEquality variable to decide when to emit the BEQZ.
2903 // Note that the order of the SLT arguments doesn't change between
2904 // opposites.
2905 //
2906 // The same applies to the unsigned variants, except that SLTu is used
2907 // instead of SLT.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002908 emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
2909 ReverseOrderSLT ? TrgReg : SrcReg, ReverseOrderSLT ? SrcReg : TrgReg,
2910 IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002911
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00002912 emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
2913 : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
2914 ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
2915 Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00002916 return false;
2917}
2918
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002919bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc,
2920 SmallVectorImpl<MCInst> &Instructions,
2921 const bool IsMips64, const bool Signed) {
2922 if (hasMips32r6()) {
2923 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2924 return false;
2925 }
2926
2927 warnIfNoMacro(IDLoc);
2928
2929 const MCOperand &RsRegOp = Inst.getOperand(0);
2930 assert(RsRegOp.isReg() && "expected register operand kind");
2931 unsigned RsReg = RsRegOp.getReg();
2932
2933 const MCOperand &RtRegOp = Inst.getOperand(1);
2934 assert(RtRegOp.isReg() && "expected register operand kind");
2935 unsigned RtReg = RtRegOp.getReg();
2936 unsigned DivOp;
2937 unsigned ZeroReg;
2938
2939 if (IsMips64) {
2940 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
2941 ZeroReg = Mips::ZERO_64;
2942 } else {
2943 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
2944 ZeroReg = Mips::ZERO;
2945 }
2946
2947 bool UseTraps = useTraps();
2948
2949 if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) {
2950 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)
2951 Warning(IDLoc, "dividing zero by zero");
2952 if (IsMips64) {
2953 if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
2954 if (UseTraps) {
2955 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2956 return false;
2957 }
2958
2959 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2960 return false;
2961 }
2962 } else {
2963 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
2964 return false;
2965 }
2966 }
2967
2968 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
2969 Warning(IDLoc, "division by zero");
2970 if (Signed) {
2971 if (UseTraps) {
2972 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2973 return false;
2974 }
2975
2976 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2977 return false;
2978 }
2979 }
2980
2981 // FIXME: The values for these two BranchTarget variables may be different in
2982 // micromips. These magic numbers need to be removed.
2983 unsigned BranchTargetNoTraps;
2984 unsigned BranchTarget;
2985
2986 if (UseTraps) {
2987 BranchTarget = IsMips64 ? 12 : 8;
2988 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2989 } else {
2990 BranchTarget = IsMips64 ? 20 : 16;
2991 BranchTargetNoTraps = 8;
2992 // Branch to the li instruction.
2993 emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc,
2994 Instructions);
2995 }
2996
2997 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
2998
2999 if (!UseTraps)
3000 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
3001
3002 if (!Signed) {
3003 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
3004 return false;
3005 }
3006
3007 unsigned ATReg = getATReg(IDLoc);
3008 if (!ATReg)
3009 return true;
3010
3011 emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, Instructions);
3012 if (IsMips64) {
3013 // Branch to the mflo instruction.
3014 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
3015 emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, Instructions);
3016 emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, Instructions);
3017 } else {
3018 // Branch to the mflo instruction.
3019 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
3020 emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, Instructions);
3021 }
3022
3023 if (UseTraps)
3024 emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, Instructions);
3025 else {
3026 // Branch to the mflo instruction.
3027 emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, Instructions);
3028 emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, Instructions);
3029 emitII(Mips::BREAK, 0x6, 0, IDLoc, Instructions);
3030 }
3031 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
3032 return false;
3033}
3034
Daniel Sanders6394ee52015-10-15 14:52:58 +00003035bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
3036 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacud88d79c2015-06-23 14:39:42 +00003037 if (hasMips32r6() || hasMips64r6()) {
3038 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3039 return false;
3040 }
3041
3042 warnIfNoMacro(IDLoc);
3043
3044 const MCOperand &DstRegOp = Inst.getOperand(0);
3045 assert(DstRegOp.isReg() && "expected register operand kind");
3046
3047 const MCOperand &SrcRegOp = Inst.getOperand(1);
3048 assert(SrcRegOp.isReg() && "expected register operand kind");
3049
3050 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3051 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3052
3053 unsigned DstReg = DstRegOp.getReg();
3054 unsigned SrcReg = SrcRegOp.getReg();
3055 int64_t OffsetValue = OffsetImmOp.getImm();
3056
3057 // NOTE: We always need AT for ULHU, as it is always used as the source
3058 // register for one of the LBu's.
3059 unsigned ATReg = getATReg(IDLoc);
3060 if (!ATReg)
3061 return true;
3062
3063 // When the value of offset+1 does not fit in 16 bits, we have to load the
3064 // offset in AT, (D)ADDu the original source register (if there was one), and
3065 // then use AT as the source register for the 2 generated LBu's.
3066 bool LoadedOffsetInAT = false;
3067 if (!isInt<16>(OffsetValue + 1) || !isInt<16>(OffsetValue)) {
3068 LoadedOffsetInAT = true;
3069
3070 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003071 true, IDLoc, Instructions))
Toma Tabacud88d79c2015-06-23 14:39:42 +00003072 return true;
3073
3074 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3075 // because it will make our output more similar to GAS'. For example,
3076 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3077 // instead of just an "ori $1, $9, 32768".
3078 // NOTE: If there is no source register specified in the ULHU, the parser
3079 // will interpret it as $0.
3080 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3081 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3082 }
3083
3084 unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg;
3085 unsigned SecondLbuDstReg = LoadedOffsetInAT ? ATReg : DstReg;
3086 unsigned LbuSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3087
3088 int64_t FirstLbuOffset = 0, SecondLbuOffset = 0;
3089 if (isLittle()) {
3090 FirstLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3091 SecondLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3092 } else {
3093 FirstLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3094 SecondLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3095 }
3096
3097 unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg;
3098
Daniel Sanders6394ee52015-10-15 14:52:58 +00003099 emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
3100 FirstLbuOffset, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003101
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003102 emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondLbuOffset, IDLoc,
3103 Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003104
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003105 emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003106
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003107 emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00003108
3109 return false;
3110}
3111
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003112bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc,
3113 SmallVectorImpl<MCInst> &Instructions) {
3114 if (hasMips32r6() || hasMips64r6()) {
3115 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3116 return false;
3117 }
3118
3119 const MCOperand &DstRegOp = Inst.getOperand(0);
3120 assert(DstRegOp.isReg() && "expected register operand kind");
3121
3122 const MCOperand &SrcRegOp = Inst.getOperand(1);
3123 assert(SrcRegOp.isReg() && "expected register operand kind");
3124
3125 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3126 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3127
3128 unsigned SrcReg = SrcRegOp.getReg();
3129 int64_t OffsetValue = OffsetImmOp.getImm();
3130 unsigned ATReg = 0;
3131
3132 // When the value of offset+3 does not fit in 16 bits, we have to load the
3133 // offset in AT, (D)ADDu the original source register (if there was one), and
3134 // then use AT as the source register for the generated LWL and LWR.
3135 bool LoadedOffsetInAT = false;
3136 if (!isInt<16>(OffsetValue + 3) || !isInt<16>(OffsetValue)) {
3137 ATReg = getATReg(IDLoc);
3138 if (!ATReg)
3139 return true;
3140 LoadedOffsetInAT = true;
3141
3142 warnIfNoMacro(IDLoc);
3143
3144 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003145 true, IDLoc, Instructions))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +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 ULW, 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 FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3159 int64_t LeftLoadOffset = 0, RightLoadOffset = 0;
3160 if (isLittle()) {
3161 LeftLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3162 RightLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3163 } else {
3164 LeftLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3165 RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3166 }
3167
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003168 emitRRI(Mips::LWL, DstRegOp.getReg(), FinalSrcReg, LeftLoadOffset, IDLoc,
3169 Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003170
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003171 emitRRI(Mips::LWR, DstRegOp.getReg(), FinalSrcReg, RightLoadOffset, IDLoc,
3172 Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003173
3174 return false;
3175}
3176
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003177bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
3178 SmallVectorImpl<MCInst> &Instructions) {
3179
3180 assert (Inst.getNumOperands() == 3 && "Invalid operand count");
3181 assert (Inst.getOperand(0).isReg() &&
3182 Inst.getOperand(1).isReg() &&
3183 Inst.getOperand(2).isImm() && "Invalid instruction operand.");
3184
3185 unsigned ATReg = Mips::NoRegister;
3186 unsigned FinalDstReg = Mips::NoRegister;
3187 unsigned DstReg = Inst.getOperand(0).getReg();
3188 unsigned SrcReg = Inst.getOperand(1).getReg();
3189 int64_t ImmValue = Inst.getOperand(2).getImm();
3190
3191 bool Is32Bit = isInt<32>(ImmValue) || isUInt<32>(ImmValue);
3192
3193 unsigned FinalOpcode = Inst.getOpcode();
3194
3195 if (DstReg == SrcReg) {
3196 ATReg = getATReg(Inst.getLoc());
3197 if (!ATReg)
3198 return true;
3199 FinalDstReg = DstReg;
3200 DstReg = ATReg;
3201 }
3202
3203 if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Instructions)) {
3204 switch (FinalOpcode) {
3205 default:
3206 llvm_unreachable("unimplemented expansion");
3207 case (Mips::ADDi):
3208 FinalOpcode = Mips::ADD;
3209 break;
3210 case (Mips::ADDiu):
3211 FinalOpcode = Mips::ADDu;
3212 break;
3213 case (Mips::ANDi):
3214 FinalOpcode = Mips::AND;
3215 break;
3216 case (Mips::NORImm):
3217 FinalOpcode = Mips::NOR;
3218 break;
3219 case (Mips::ORi):
3220 FinalOpcode = Mips::OR;
3221 break;
3222 case (Mips::SLTi):
3223 FinalOpcode = Mips::SLT;
3224 break;
3225 case (Mips::SLTiu):
3226 FinalOpcode = Mips::SLTu;
3227 break;
3228 case (Mips::XORi):
3229 FinalOpcode = Mips::XOR;
3230 break;
3231 }
3232
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003233 if (FinalDstReg == Mips::NoRegister)
3234 emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, Instructions);
3235 else
3236 emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc,
3237 Instructions);
Zoran Jovanoviccdb64562015-09-28 11:11:34 +00003238 return false;
3239 }
3240 return true;
3241}
3242
Toma Tabacu234482a2015-03-16 12:03:39 +00003243void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
3244 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003245 if (hasShortDelaySlot)
3246 emitRR(Mips::MOVE16_MM, Mips::ZERO, Mips::ZERO, IDLoc, Instructions);
3247 else
3248 emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, Instructions);
Toma Tabacu234482a2015-03-16 12:03:39 +00003249}
3250
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003251void MipsAsmParser::createAddu(unsigned DstReg, unsigned SrcReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +00003252 unsigned TrgReg, bool Is64Bit,
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003253 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanders03f9c012015-07-14 12:24:22 +00003254 emitRRR(Is64Bit ? Mips::DADDu : Mips::ADDu, DstReg, SrcReg, TrgReg, SMLoc(),
3255 Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003256}
3257
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003258void MipsAsmParser::createCpRestoreMemOp(
3259 bool IsLoad, int StackOffset, SMLoc IDLoc,
3260 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003261 // If the offset can not fit into 16 bits, we need to expand.
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003262 if (!isInt<16>(StackOffset)) {
3263 MCInst MemInst;
3264 MemInst.setOpcode(IsLoad ? Mips::LW : Mips::SW);
3265 MemInst.addOperand(MCOperand::createReg(Mips::GP));
3266 MemInst.addOperand(MCOperand::createReg(Mips::SP));
3267 MemInst.addOperand(MCOperand::createImm(StackOffset));
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003268 expandMemInst(MemInst, IDLoc, Instructions, IsLoad, true /*HasImmOpnd*/);
Daniel Sanders2a5ce1a2015-10-12 14:09:12 +00003269 return;
3270 }
3271
3272 emitRRI(IsLoad ? Mips::LW : Mips::SW, Mips::GP, Mips::SP, StackOffset, IDLoc,
3273 Instructions);
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003274}
3275
Matheus Almeida595fcab2014-06-11 15:05:56 +00003276unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
3277 // As described by the Mips32r2 spec, the registers Rd and Rs for
3278 // jalr.hb must be different.
3279 unsigned Opcode = Inst.getOpcode();
3280
3281 if (Opcode == Mips::JALR_HB &&
3282 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
3283 return Match_RequiresDifferentSrcAndDst;
3284
3285 return Match_Success;
3286}
3287
Daniel Sanders52da7af2015-11-06 12:11:03 +00003288static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
3289 uint64_t ErrorInfo) {
3290 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
3291 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
3292 if (ErrorLoc == SMLoc())
3293 return Loc;
3294 return ErrorLoc;
3295 }
3296 return Loc;
3297}
3298
David Blaikie960ea3f2014-06-08 16:18:35 +00003299bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3300 OperandVector &Operands,
3301 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003302 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00003303 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00003304
Jack Carterb4dbc172012-09-05 23:34:03 +00003305 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00003306 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00003307 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003308 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00003309
3310 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003311 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003312 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00003313 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00003314 for (unsigned i = 0; i < Instructions.size(); i++)
Akira Hatanakabd9fc282015-11-14 05:20:05 +00003315 Out.EmitInstruction(Instructions[i], getSTI());
Jack Carterb4dbc172012-09-05 23:34:03 +00003316 return false;
3317 }
3318 case Match_MissingFeature:
3319 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
3320 return true;
3321 case Match_InvalidOperand: {
3322 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00003323 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003324 if (ErrorInfo >= Operands.size())
3325 return Error(IDLoc, "too few operands for instruction");
3326
Daniel Sanders52da7af2015-11-06 12:11:03 +00003327 ErrorLoc = Operands[ErrorInfo]->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00003328 if (ErrorLoc == SMLoc())
3329 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00003330 }
3331
3332 return Error(ErrorLoc, "invalid operand for instruction");
3333 }
3334 case Match_MnemonicFail:
3335 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00003336 case Match_RequiresDifferentSrcAndDst:
3337 return Error(IDLoc, "source and destination must be different");
Daniel Sanders52da7af2015-11-06 12:11:03 +00003338 case Match_Immz:
3339 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00003340 case Match_UImm1_0:
3341 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3342 "expected 1-bit unsigned immediate");
Daniel Sandersea4f6532015-11-06 12:22:31 +00003343 case Match_UImm2_0:
3344 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3345 "expected 2-bit unsigned immediate");
3346 case Match_UImm2_1:
3347 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3348 "expected immediate in range 1 .. 4");
Daniel Sanders38ce0f62015-11-06 12:31:27 +00003349 case Match_UImm3_0:
3350 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3351 "expected 3-bit unsigned immediate");
Daniel Sanders5762a4f2015-11-06 12:41:43 +00003352 case Match_UImm4_0:
3353 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
3354 "expected 4-bit unsigned immediate");
Jack Carterb4dbc172012-09-05 23:34:03 +00003355 }
Craig Topper589ceee2015-01-03 08:16:34 +00003356
3357 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00003358}
3359
Toma Tabacud9d344b2015-04-27 14:05:04 +00003360void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
3361 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
3362 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
3363 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003364}
3365
Toma Tabacu81496c12015-05-20 08:54:45 +00003366void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
3367 if (!AssemblerOptions.back()->isMacro())
3368 Warning(Loc, "macro instruction expanded into multiple instructions");
3369}
3370
Daniel Sandersef638fe2014-10-03 15:37:37 +00003371void
3372MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
3373 SMRange Range, bool ShowColors) {
3374 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00003375 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00003376 ShowColors);
3377}
3378
Jack Carter1ac53222013-02-20 23:11:17 +00003379int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003380 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003381
Vladimir Medic4c299852013-11-06 11:27:05 +00003382 CC = StringSwitch<unsigned>(Name)
3383 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003384 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00003385 .Case("a0", 4)
3386 .Case("a1", 5)
3387 .Case("a2", 6)
3388 .Case("a3", 7)
3389 .Case("v0", 2)
3390 .Case("v1", 3)
3391 .Case("s0", 16)
3392 .Case("s1", 17)
3393 .Case("s2", 18)
3394 .Case("s3", 19)
3395 .Case("s4", 20)
3396 .Case("s5", 21)
3397 .Case("s6", 22)
3398 .Case("s7", 23)
3399 .Case("k0", 26)
3400 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003401 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00003402 .Case("sp", 29)
3403 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003404 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00003405 .Case("ra", 31)
3406 .Case("t0", 8)
3407 .Case("t1", 9)
3408 .Case("t2", 10)
3409 .Case("t3", 11)
3410 .Case("t4", 12)
3411 .Case("t5", 13)
3412 .Case("t6", 14)
3413 .Case("t7", 15)
3414 .Case("t8", 24)
3415 .Case("t9", 25)
3416 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003417
Toma Tabacufda445c2014-09-15 15:33:01 +00003418 if (!(isABI_N32() || isABI_N64()))
3419 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003420
Daniel Sandersef638fe2014-10-03 15:37:37 +00003421 if (12 <= CC && CC <= 15) {
3422 // Name is one of t4-t7
3423 AsmToken RegTok = getLexer().peekTok();
3424 SMRange RegRange = RegTok.getLocRange();
3425
3426 StringRef FixedName = StringSwitch<StringRef>(Name)
3427 .Case("t4", "t0")
3428 .Case("t5", "t1")
3429 .Case("t6", "t2")
3430 .Case("t7", "t3")
3431 .Default("");
3432 assert(FixedName != "" && "Register name is not one of t4-t7.");
3433
3434 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
3435 "Did you mean $" + FixedName + "?", RegRange);
3436 }
3437
Toma Tabacufda445c2014-09-15 15:33:01 +00003438 // Although SGI documentation just cuts out t0-t3 for n32/n64,
3439 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
3440 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
3441 if (8 <= CC && CC <= 11)
3442 CC += 4;
3443
3444 if (CC == -1)
3445 CC = StringSwitch<unsigned>(Name)
3446 .Case("a4", 8)
3447 .Case("a5", 9)
3448 .Case("a6", 10)
3449 .Case("a7", 11)
3450 .Case("kt0", 26)
3451 .Case("kt1", 27)
3452 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003453
3454 return CC;
3455}
Jack Carterd0bd6422013-04-18 00:41:53 +00003456
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003457int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
3458 int CC;
3459
3460 CC = StringSwitch<unsigned>(Name)
3461 .Case("hwr_cpunum", 0)
3462 .Case("hwr_synci_step", 1)
3463 .Case("hwr_cc", 2)
3464 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00003465 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003466 .Default(-1);
3467
3468 return CC;
3469}
3470
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003471int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003472
Jack Cartera63b16a2012-09-07 00:23:42 +00003473 if (Name[0] == 'f') {
3474 StringRef NumString = Name.substr(1);
3475 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003476 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003477 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003478 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00003479 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003480 return IntVal;
3481 }
3482 return -1;
3483}
Jack Cartera63b16a2012-09-07 00:23:42 +00003484
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003485int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
3486
3487 if (Name.startswith("fcc")) {
3488 StringRef NumString = Name.substr(3);
3489 unsigned IntVal;
3490 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003491 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003492 if (IntVal > 7) // There are only 8 fcc registers.
3493 return -1;
3494 return IntVal;
3495 }
3496 return -1;
3497}
3498
3499int MipsAsmParser::matchACRegisterName(StringRef Name) {
3500
Akira Hatanaka274d24c2013-08-14 01:15:52 +00003501 if (Name.startswith("ac")) {
3502 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003503 unsigned IntVal;
3504 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003505 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003506 if (IntVal > 3) // There are only 3 acc registers.
3507 return -1;
3508 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00003509 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003510 return -1;
3511}
Jack Carterd0bd6422013-04-18 00:41:53 +00003512
Jack Carter5dc8ac92013-09-25 23:50:44 +00003513int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
3514 unsigned IntVal;
3515
3516 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
3517 return -1;
3518
3519 if (IntVal > 31)
3520 return -1;
3521
3522 return IntVal;
3523}
3524
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003525int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
3526 int CC;
3527
3528 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00003529 .Case("msair", 0)
3530 .Case("msacsr", 1)
3531 .Case("msaaccess", 2)
3532 .Case("msasave", 3)
3533 .Case("msamodify", 4)
3534 .Case("msarequest", 5)
3535 .Case("msamap", 6)
3536 .Case("msaunmap", 7)
3537 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003538
3539 return CC;
3540}
3541
Toma Tabacu89a712b2015-04-15 10:48:56 +00003542unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00003543 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00003544 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00003545 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00003546 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00003547 return 0;
3548 }
3549 unsigned AT = getReg(
3550 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00003551 return AT;
3552}
Jack Carter0b744b32012-10-04 02:29:46 +00003553
Jack Carterd0bd6422013-04-18 00:41:53 +00003554unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00003555 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00003556}
3557
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003558unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003559 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00003560 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003561}
3562
Jack Carter873c7242013-01-12 01:03:14 +00003563int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003564 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00003565 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00003566 return -1;
3567
Jack Carter873c7242013-01-12 01:03:14 +00003568 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00003569}
3570
Toma Tabacu13964452014-09-04 13:23:44 +00003571bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003572 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003573 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003574
Jack Carter30a59822012-10-04 04:03:53 +00003575 // Check if the current operand has a custom associated parser, if so, try to
3576 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00003577 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3578 if (ResTy == MatchOperand_Success)
3579 return false;
3580 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3581 // there was a match, but an error occurred, in which case, just return that
3582 // the operand parsing failed.
3583 if (ResTy == MatchOperand_ParseFail)
3584 return true;
3585
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003586 DEBUG(dbgs() << ".. Generic Parser\n");
3587
Jack Carterb4dbc172012-09-05 23:34:03 +00003588 switch (getLexer().getKind()) {
3589 default:
3590 Error(Parser.getTok().getLoc(), "unexpected token in operand");
3591 return true;
3592 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003593 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00003594 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00003595
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003596 // Almost all registers have been parsed by custom parsers. There is only
3597 // one exception to this. $zero (and it's alias $0) will reach this point
3598 // for div, divu, and similar instructions because it is not an operand
3599 // to the instruction definition but an explicit register. Special case
3600 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00003601 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00003602 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003603
Jack Carterd0bd6422013-04-18 00:41:53 +00003604 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00003605 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003606 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00003607 return true;
3608
Jack Carter873c7242013-01-12 01:03:14 +00003609 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00003610 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00003611 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00003612 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003613 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00003614
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003615 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003616 return false;
3617 }
Vladimir Medic4c299852013-11-06 11:27:05 +00003618 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00003619 case AsmToken::LParen:
3620 case AsmToken::Minus:
3621 case AsmToken::Plus:
3622 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00003623 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00003624 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003625 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00003626 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003627 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00003628 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00003629 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003630 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003631 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003632 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00003633 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00003634 return true;
3635
Jack Carter873c7242013-01-12 01:03:14 +00003636 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3637
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003638 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00003639 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003640 } // case AsmToken::Percent
3641 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00003642 return true;
3643}
3644
Vladimir Medic4c299852013-11-06 11:27:05 +00003645const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00003646 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00003647 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00003648 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00003649 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00003650 // It's a constant, evaluate reloc value.
3651 int16_t Val;
3652 switch (getVariantKind(RelocStr)) {
3653 case MCSymbolRefExpr::VK_Mips_ABS_LO:
3654 // Get the 1st 16-bits.
3655 Val = MCE->getValue() & 0xffff;
3656 break;
3657 case MCSymbolRefExpr::VK_Mips_ABS_HI:
3658 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
3659 // 16 bits being negative.
3660 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
3661 break;
3662 case MCSymbolRefExpr::VK_Mips_HIGHER:
3663 // Get the 3rd 16-bits.
3664 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
3665 break;
3666 case MCSymbolRefExpr::VK_Mips_HIGHEST:
3667 // Get the 4th 16-bits.
3668 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
3669 break;
3670 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00003671 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00003672 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00003673 return MCConstantExpr::create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00003674 }
3675
Jack Carterb5cf5902013-04-17 00:18:04 +00003676 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003677 // It's a symbol, create a symbolic expression from the symbol.
Toma Tabacu07c97b32015-06-17 10:43:45 +00003678 const MCSymbol *Symbol = &MSRE->getSymbol();
Jack Carterb5cf5902013-04-17 00:18:04 +00003679 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003680 Res = MCSymbolRefExpr::create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003681 return Res;
3682 }
3683
3684 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00003685 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
3686
Sasa Stankovic06c47802014-04-03 10:37:45 +00003687 // Try to create target expression.
3688 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
Jim Grosbach13760bd2015-05-30 01:25:56 +00003689 return MipsMCExpr::create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00003690
Jack Carterd0bd6422013-04-18 00:41:53 +00003691 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
3692 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003693 Res = MCBinaryExpr::create(BE->getOpcode(), LExp, RExp, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003694 return Res;
3695 }
3696
3697 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003698 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003699 Res = MCUnaryExpr::create(UN->getOpcode(), UnExp, getContext());
Jack Carterd0bd6422013-04-18 00:41:53 +00003700 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00003701 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003702 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00003703 return Expr;
3704}
3705
3706bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
3707
3708 switch (Expr->getKind()) {
3709 case MCExpr::Constant:
3710 return true;
3711 case MCExpr::SymbolRef:
3712 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
3713 case MCExpr::Binary:
3714 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
3715 if (!isEvaluated(BE->getLHS()))
3716 return false;
3717 return isEvaluated(BE->getRHS());
3718 }
3719 case MCExpr::Unary:
3720 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00003721 case MCExpr::Target:
3722 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003723 }
Jack Carterb5cf5902013-04-17 00:18:04 +00003724 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00003725}
Jack Carterd0bd6422013-04-18 00:41:53 +00003726
Jack Carterb5cf5902013-04-17 00:18:04 +00003727bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003728 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00003729 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00003730 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00003731 if (Tok.isNot(AsmToken::Identifier))
3732 return true;
3733
Yaron Keren075759a2015-03-30 15:42:36 +00003734 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00003735
Jack Carterd0bd6422013-04-18 00:41:53 +00003736 Parser.Lex(); // Eat the identifier.
3737 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003738 const MCExpr *IdVal;
3739 SMLoc EndLoc;
3740
3741 if (getLexer().getKind() == AsmToken::LParen) {
3742 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003743 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003744 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003745 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003746 const AsmToken &nextTok = Parser.getTok();
3747 if (nextTok.isNot(AsmToken::Identifier))
3748 return true;
3749 Str += "(%";
3750 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00003751 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00003752 if (getLexer().getKind() != AsmToken::LParen)
3753 return true;
3754 } else
3755 break;
3756 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003757 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00003758 return true;
3759
3760 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00003761 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003762
3763 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00003764 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003765
Jack Carterd0bd6422013-04-18 00:41:53 +00003766 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00003767 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003768}
3769
Jack Carterb4dbc172012-09-05 23:34:03 +00003770bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
3771 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003772 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00003773 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003774 if (ResTy == MatchOperand_Success) {
3775 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00003776 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003777 StartLoc = Operand.getStartLoc();
3778 EndLoc = Operand.getEndLoc();
3779
3780 // AFAIK, we only support numeric registers and named GPR's in CFI
3781 // directives.
3782 // Don't worry about eating tokens before failing. Using an unrecognised
3783 // register is a parse error.
3784 if (Operand.isGPRAsmReg()) {
3785 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003786 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003787 }
3788
3789 return (RegNo == (unsigned)-1);
3790 }
3791
3792 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00003793 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00003794}
3795
Jack Carterb5cf5902013-04-17 00:18:04 +00003796bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003797 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00003798 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00003799 bool Result = true;
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003800 unsigned NumOfLParen = 0;
Jack Carterb5cf5902013-04-17 00:18:04 +00003801
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003802 while (getLexer().getKind() == AsmToken::LParen) {
Jack Carterb5cf5902013-04-17 00:18:04 +00003803 Parser.Lex();
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003804 ++NumOfLParen;
3805 }
Jack Carter873c7242013-01-12 01:03:14 +00003806
Jack Carterd0bd6422013-04-18 00:41:53 +00003807 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00003808 default:
3809 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00003810 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00003811 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00003812 case AsmToken::Integer:
3813 case AsmToken::Minus:
3814 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00003815 if (isParenExpr)
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003816 Result = getParser().parseParenExprOfDepth(NumOfLParen, Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00003817 else
3818 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00003819 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00003820 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003821 break;
Jack Carter873c7242013-01-12 01:03:14 +00003822 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00003823 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00003824 }
Jack Carterb5cf5902013-04-17 00:18:04 +00003825 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003826}
3827
David Blaikie960ea3f2014-06-08 16:18:35 +00003828MipsAsmParser::OperandMatchResultTy
3829MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003830 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003831 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00003832 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00003833 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00003834 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003835 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00003836 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00003837 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00003838
Jack Carterb5cf5902013-04-17 00:18:04 +00003839 if (getLexer().getKind() == AsmToken::LParen) {
3840 Parser.Lex();
3841 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003842 }
3843
Jack Carterb5cf5902013-04-17 00:18:04 +00003844 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003845 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00003846 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003847
Jack Carterd0bd6422013-04-18 00:41:53 +00003848 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003849 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003850 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003851 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00003852 SMLoc E =
3853 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003854 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00003855 return MatchOperand_Success;
3856 }
3857 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003858 SMLoc E =
3859 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00003860
Jack Carterd0bd6422013-04-18 00:41:53 +00003861 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00003862 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00003863 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00003864 S, E, *this);
3865 Operands.push_back(
3866 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00003867 return MatchOperand_Success;
3868 }
3869 Error(Parser.getTok().getLoc(), "'(' expected");
3870 return MatchOperand_ParseFail;
3871 }
3872
Jack Carterd0bd6422013-04-18 00:41:53 +00003873 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003874 }
3875
Toma Tabacu13964452014-09-04 13:23:44 +00003876 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003877 if (Res != MatchOperand_Success)
3878 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003879
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003880 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00003881 Error(Parser.getTok().getLoc(), "')' expected");
3882 return MatchOperand_ParseFail;
3883 }
3884
Jack Carter873c7242013-01-12 01:03:14 +00003885 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3886
Jack Carterd0bd6422013-04-18 00:41:53 +00003887 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003888
Craig Topper062a2ba2014-04-25 05:30:21 +00003889 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003890 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00003891
Jack Carterd0bd6422013-04-18 00:41:53 +00003892 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00003893 std::unique_ptr<MipsOperand> op(
3894 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00003895 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00003896 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003897 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00003898 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003899 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
3900 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00003901 if (IdVal->evaluateAsAbsolute(Imm))
3902 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003903 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003904 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00003905 getContext());
3906 }
3907
David Blaikie960ea3f2014-06-08 16:18:35 +00003908 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003909 return MatchOperand_Success;
3910}
3911
David Blaikie960ea3f2014-06-08 16:18:35 +00003912bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003913 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00003914 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00003915 if (Sym) {
3916 SMLoc S = Parser.getTok().getLoc();
3917 const MCExpr *Expr;
3918 if (Sym->isVariable())
3919 Expr = Sym->getVariableValue();
3920 else
3921 return false;
3922 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003923 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00003924 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00003925 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003926 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00003927 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00003928 if (ResTy == MatchOperand_Success) {
3929 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00003930 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00003931 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003932 llvm_unreachable("Should never ParseFail");
3933 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00003934 }
3935 } else if (Expr->getKind() == MCExpr::Constant) {
3936 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00003937 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00003938 Operands.push_back(
3939 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00003940 return true;
3941 }
3942 }
3943 return false;
3944}
Jack Carterd0bd6422013-04-18 00:41:53 +00003945
Jack Carter873c7242013-01-12 01:03:14 +00003946MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003947MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00003948 StringRef Identifier,
3949 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003950 int Index = matchCPURegisterName(Identifier);
3951 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003952 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003953 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3954 return MatchOperand_Success;
3955 }
3956
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003957 Index = matchHWRegsRegisterName(Identifier);
3958 if (Index != -1) {
3959 Operands.push_back(MipsOperand::createHWRegsReg(
3960 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3961 return MatchOperand_Success;
3962 }
3963
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003964 Index = matchFPURegisterName(Identifier);
3965 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003966 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003967 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3968 return MatchOperand_Success;
3969 }
3970
3971 Index = matchFCCRegisterName(Identifier);
3972 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003973 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003974 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3975 return MatchOperand_Success;
3976 }
3977
3978 Index = matchACRegisterName(Identifier);
3979 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003980 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003981 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3982 return MatchOperand_Success;
3983 }
3984
3985 Index = matchMSA128RegisterName(Identifier);
3986 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003987 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003988 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3989 return MatchOperand_Success;
3990 }
3991
3992 Index = matchMSA128CtrlRegisterName(Identifier);
3993 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003994 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003995 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3996 return MatchOperand_Success;
3997 }
3998
3999 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00004000}
4001
4002MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004003MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004004 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00004005 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004006
4007 if (Token.is(AsmToken::Identifier)) {
4008 DEBUG(dbgs() << ".. identifier\n");
4009 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00004010 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00004011 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00004012 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004013 } else if (Token.is(AsmToken::Integer)) {
4014 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00004015 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004016 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
4017 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004018 return MatchOperand_Success;
4019 }
4020
4021 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
4022
4023 return MatchOperand_NoMatch;
4024}
4025
David Blaikie960ea3f2014-06-08 16:18:35 +00004026MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004027MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004028 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004029 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004030
4031 auto Token = Parser.getTok();
4032
4033 SMLoc S = Token.getLoc();
4034
4035 if (Token.isNot(AsmToken::Dollar)) {
4036 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
4037 if (Token.is(AsmToken::Identifier)) {
4038 if (searchSymbolAlias(Operands))
4039 return MatchOperand_Success;
4040 }
4041 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
4042 return MatchOperand_NoMatch;
4043 }
4044 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004045
Toma Tabacu13964452014-09-04 13:23:44 +00004046 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00004047 if (ResTy == MatchOperand_Success) {
4048 Parser.Lex(); // $
4049 Parser.Lex(); // identifier
4050 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004051 return ResTy;
4052}
4053
4054MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004055MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004056 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004057 switch (getLexer().getKind()) {
4058 default:
4059 return MatchOperand_NoMatch;
4060 case AsmToken::LParen:
4061 case AsmToken::Minus:
4062 case AsmToken::Plus:
4063 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00004064 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004065 case AsmToken::String:
4066 break;
4067 }
4068
4069 const MCExpr *IdVal;
4070 SMLoc S = Parser.getTok().getLoc();
4071 if (getParser().parseExpression(IdVal))
4072 return MatchOperand_ParseFail;
4073
4074 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4075 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
4076 return MatchOperand_Success;
4077}
4078
David Blaikie960ea3f2014-06-08 16:18:35 +00004079MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004080MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004081 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00004082 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004083
4084 SMLoc S = getLexer().getLoc();
4085
4086 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00004087 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004088 if (ResTy != MatchOperand_NoMatch)
4089 return ResTy;
4090
Daniel Sanders315386c2014-04-01 10:40:14 +00004091 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00004092 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00004093 if (ResTy != MatchOperand_NoMatch)
4094 return ResTy;
4095
Daniel Sandersffd84362014-04-01 10:41:48 +00004096 const MCExpr *Expr = nullptr;
4097 if (Parser.parseExpression(Expr)) {
4098 // We have no way of knowing if a symbol was consumed so we must ParseFail
4099 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004100 }
Daniel Sandersffd84362014-04-01 10:41:48 +00004101 Operands.push_back(
4102 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004103 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00004104}
4105
Vladimir Medic2b953d02013-10-01 09:48:56 +00004106MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00004107MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004108 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00004109 const MCExpr *IdVal;
4110 // If the first token is '$' we may have register operand.
4111 if (Parser.getTok().is(AsmToken::Dollar))
4112 return MatchOperand_NoMatch;
4113 SMLoc S = Parser.getTok().getLoc();
4114 if (getParser().parseExpression(IdVal))
4115 return MatchOperand_ParseFail;
4116 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00004117 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00004118 int64_t Val = MCE->getValue();
4119 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4120 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00004121 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00004122 return MatchOperand_Success;
4123}
4124
Matheus Almeida779c5932013-11-18 12:32:49 +00004125MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00004126MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004127 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00004128 switch (getLexer().getKind()) {
4129 default:
4130 return MatchOperand_NoMatch;
4131 case AsmToken::LParen:
4132 case AsmToken::Plus:
4133 case AsmToken::Minus:
4134 case AsmToken::Integer:
4135 break;
4136 }
4137
4138 const MCExpr *Expr;
4139 SMLoc S = Parser.getTok().getLoc();
4140
4141 if (getParser().parseExpression(Expr))
4142 return MatchOperand_ParseFail;
4143
4144 int64_t Val;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004145 if (!Expr->evaluateAsAbsolute(Val)) {
Matheus Almeida779c5932013-11-18 12:32:49 +00004146 Error(S, "expected immediate value");
4147 return MatchOperand_ParseFail;
4148 }
4149
4150 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
4151 // and because the CPU always adds one to the immediate field, the allowed
4152 // range becomes 1..4. We'll only check the range here and will deal
4153 // with the addition/subtraction when actually decoding/encoding
4154 // the instruction.
4155 if (Val < 1 || Val > 4) {
4156 Error(S, "immediate not in range (1..4)");
4157 return MatchOperand_ParseFail;
4158 }
4159
Jack Carter3b2c96e2014-01-22 23:31:38 +00004160 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004161 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00004162 return MatchOperand_Success;
4163}
4164
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004165MipsAsmParser::OperandMatchResultTy
4166MipsAsmParser::parseRegisterList(OperandVector &Operands) {
4167 MCAsmParser &Parser = getParser();
4168 SmallVector<unsigned, 10> Regs;
4169 unsigned RegNo;
4170 unsigned PrevReg = Mips::NoRegister;
4171 bool RegRange = false;
4172 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4173
4174 if (Parser.getTok().isNot(AsmToken::Dollar))
4175 return MatchOperand_ParseFail;
4176
4177 SMLoc S = Parser.getTok().getLoc();
4178 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
4179 SMLoc E = getLexer().getLoc();
4180 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
4181 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
4182 if (RegRange) {
4183 // Remove last register operand because registers from register range
4184 // should be inserted first.
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004185 if ((isGP64bit() && RegNo == Mips::RA_64) ||
4186 (!isGP64bit() && RegNo == Mips::RA)) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004187 Regs.push_back(RegNo);
4188 } else {
4189 unsigned TmpReg = PrevReg + 1;
4190 while (TmpReg <= RegNo) {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004191 if ((((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) && !isGP64bit()) ||
4192 (((TmpReg < Mips::S0_64) || (TmpReg > Mips::S7_64)) &&
4193 isGP64bit())) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004194 Error(E, "invalid register operand");
4195 return MatchOperand_ParseFail;
4196 }
4197
4198 PrevReg = TmpReg;
4199 Regs.push_back(TmpReg++);
4200 }
4201 }
4202
4203 RegRange = false;
4204 } else {
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004205 if ((PrevReg == Mips::NoRegister) &&
4206 ((isGP64bit() && (RegNo != Mips::S0_64) && (RegNo != Mips::RA_64)) ||
4207 (!isGP64bit() && (RegNo != Mips::S0) && (RegNo != Mips::RA)))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004208 Error(E, "$16 or $31 expected");
4209 return MatchOperand_ParseFail;
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004210 } else if (!(((RegNo == Mips::FP || RegNo == Mips::RA ||
4211 (RegNo >= Mips::S0 && RegNo <= Mips::S7)) &&
4212 !isGP64bit()) ||
4213 ((RegNo == Mips::FP_64 || RegNo == Mips::RA_64 ||
4214 (RegNo >= Mips::S0_64 && RegNo <= Mips::S7_64)) &&
4215 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004216 Error(E, "invalid register operand");
4217 return MatchOperand_ParseFail;
4218 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
Zlatko Buljan797c2ae2015-11-12 13:21:33 +00004219 ((RegNo != Mips::FP && RegNo != Mips::RA && !isGP64bit()) ||
4220 (RegNo != Mips::FP_64 && RegNo != Mips::RA_64 &&
4221 isGP64bit()))) {
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004222 Error(E, "consecutive register numbers expected");
4223 return MatchOperand_ParseFail;
4224 }
4225
4226 Regs.push_back(RegNo);
4227 }
4228
4229 if (Parser.getTok().is(AsmToken::Minus))
4230 RegRange = true;
4231
4232 if (!Parser.getTok().isNot(AsmToken::Minus) &&
4233 !Parser.getTok().isNot(AsmToken::Comma)) {
4234 Error(E, "',' or '-' expected");
4235 return MatchOperand_ParseFail;
4236 }
4237
4238 Lex(); // Consume comma or minus
4239 if (Parser.getTok().isNot(AsmToken::Dollar))
4240 break;
4241
4242 PrevReg = RegNo;
4243 }
4244
4245 SMLoc E = Parser.getTok().getLoc();
4246 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4247 parseMemOperand(Operands);
4248 return MatchOperand_Success;
4249}
4250
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004251MipsAsmParser::OperandMatchResultTy
4252MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
4253 MCAsmParser &Parser = getParser();
4254
4255 SMLoc S = Parser.getTok().getLoc();
4256 if (parseAnyRegister(Operands) != MatchOperand_Success)
4257 return MatchOperand_ParseFail;
4258
4259 SMLoc E = Parser.getTok().getLoc();
4260 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
4261 unsigned Reg = Op.getGPR32Reg();
4262 Operands.pop_back();
4263 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
4264 return MatchOperand_Success;
4265}
4266
Zoran Jovanovic41688672015-02-10 16:36:20 +00004267MipsAsmParser::OperandMatchResultTy
4268MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
4269 MCAsmParser &Parser = getParser();
4270 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4271 SmallVector<unsigned, 10> Regs;
4272
4273 if (Parser.getTok().isNot(AsmToken::Dollar))
4274 return MatchOperand_ParseFail;
4275
4276 SMLoc S = Parser.getTok().getLoc();
4277
4278 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4279 return MatchOperand_ParseFail;
4280
4281 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4282 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4283 Regs.push_back(RegNo);
4284
4285 SMLoc E = Parser.getTok().getLoc();
4286 if (Parser.getTok().isNot(AsmToken::Comma)) {
4287 Error(E, "',' expected");
4288 return MatchOperand_ParseFail;
4289 }
4290
4291 // Remove comma.
4292 Parser.Lex();
4293
4294 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4295 return MatchOperand_ParseFail;
4296
4297 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4298 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4299 Regs.push_back(RegNo);
4300
4301 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4302
4303 return MatchOperand_Success;
4304}
4305
Jack Carterdc1e35d2012-09-06 20:00:02 +00004306MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
4307
Vladimir Medic4c299852013-11-06 11:27:05 +00004308 MCSymbolRefExpr::VariantKind VK =
4309 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
4310 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
4311 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
4312 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
4313 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
4314 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
4315 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
4316 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
4317 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
4318 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
4319 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
4320 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
4321 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
4322 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
4323 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
4324 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
4325 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
4326 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00004327 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
4328 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
4329 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
4330 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
4331 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
4332 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00004333 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
4334 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00004335 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004336
Matheus Almeida2852af82014-04-22 10:15:54 +00004337 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00004338
Jack Carterdc1e35d2012-09-06 20:00:02 +00004339 return VK;
4340}
Jack Cartera63b16a2012-09-07 00:23:42 +00004341
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004342/// Sometimes (i.e. load/stores) the operand may be followed immediately by
4343/// either this.
4344/// ::= '(', register, ')'
4345/// handle it before we iterate so we don't get tripped up by the lack of
4346/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004347bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004348 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004349 if (getLexer().is(AsmToken::LParen)) {
4350 Operands.push_back(
4351 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
4352 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004353 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004354 SMLoc Loc = getLexer().getLoc();
4355 Parser.eatToEndOfStatement();
4356 return Error(Loc, "unexpected token in argument list");
4357 }
4358 if (Parser.getTok().isNot(AsmToken::RParen)) {
4359 SMLoc Loc = getLexer().getLoc();
4360 Parser.eatToEndOfStatement();
4361 return Error(Loc, "unexpected token, expected ')'");
4362 }
4363 Operands.push_back(
4364 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
4365 Parser.Lex();
4366 }
4367 return false;
4368}
4369
4370/// Sometimes (i.e. in MSA) the operand may be followed immediately by
4371/// either one of these.
4372/// ::= '[', register, ']'
4373/// ::= '[', integer, ']'
4374/// handle it before we iterate so we don't get tripped up by the lack of
4375/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004376bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00004377 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004378 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004379 if (getLexer().is(AsmToken::LBrac)) {
4380 Operands.push_back(
4381 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
4382 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004383 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004384 SMLoc Loc = getLexer().getLoc();
4385 Parser.eatToEndOfStatement();
4386 return Error(Loc, "unexpected token in argument list");
4387 }
4388 if (Parser.getTok().isNot(AsmToken::RBrac)) {
4389 SMLoc Loc = getLexer().getLoc();
4390 Parser.eatToEndOfStatement();
4391 return Error(Loc, "unexpected token, expected ']'");
4392 }
4393 Operands.push_back(
4394 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
4395 Parser.Lex();
4396 }
4397 return false;
4398}
4399
David Blaikie960ea3f2014-06-08 16:18:35 +00004400bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
4401 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004402 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004403 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004404
4405 // We have reached first instruction, module directive are now forbidden.
4406 getTargetStreamer().forbidModuleDirective();
4407
Vladimir Medic74593e62013-07-17 15:00:42 +00004408 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00004409 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00004410 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00004411 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00004412 }
Vladimir Medic64828a12013-07-16 10:07:14 +00004413 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004414 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004415
4416 // Read the remaining operands.
4417 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4418 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004419 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004420 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004421 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004422 return Error(Loc, "unexpected token in argument list");
4423 }
Toma Tabacu13964452014-09-04 13:23:44 +00004424 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004425 return true;
4426 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00004427
Jack Carterd0bd6422013-04-18 00:41:53 +00004428 while (getLexer().is(AsmToken::Comma)) {
4429 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00004430 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004431 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004432 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004433 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004434 return Error(Loc, "unexpected token in argument list");
4435 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004436 // Parse bracket and parenthesis suffixes before we iterate
4437 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00004438 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004439 return true;
4440 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00004441 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004442 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00004443 }
4444 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004445 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4446 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004447 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004448 return Error(Loc, "unexpected token in argument list");
4449 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004450 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00004451 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00004452}
4453
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004454bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004455 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004456 SMLoc Loc = getLexer().getLoc();
4457 Parser.eatToEndOfStatement();
4458 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00004459}
4460
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004461bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004462 return Error(Loc, ErrorMsg);
4463}
4464
Jack Carter0b744b32012-10-04 02:29:46 +00004465bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004466 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004467 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00004468
4469 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00004470 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00004471
4472 Parser.Lex(); // Eat "noat".
4473
Jack Carterd0bd6422013-04-18 00:41:53 +00004474 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004475 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004476 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004477 return false;
4478 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004479
4480 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004481 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004482 return false;
4483}
Jack Carterd0bd6422013-04-18 00:41:53 +00004484
Jack Carter0b744b32012-10-04 02:29:46 +00004485bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00004486 // Line can be: ".set at", which sets $at to $1
4487 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00004488 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00004489 Parser.Lex(); // Eat "at".
4490
Jack Carter0b744b32012-10-04 02:29:46 +00004491 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004492 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00004493 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00004494
4495 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004496 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004497 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00004498 }
4499
4500 if (getLexer().isNot(AsmToken::Equal)) {
4501 reportParseError("unexpected token, expected equals sign");
4502 return false;
4503 }
4504 Parser.Lex(); // Eat "=".
4505
4506 if (getLexer().isNot(AsmToken::Dollar)) {
4507 if (getLexer().is(AsmToken::EndOfStatement)) {
4508 reportParseError("no register specified");
4509 return false;
4510 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00004511 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00004512 return false;
4513 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004514 }
4515 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00004516
Toma Tabacu16a74492015-02-13 10:30:57 +00004517 // Find out what "reg" is.
4518 unsigned AtRegNo;
4519 const AsmToken &Reg = Parser.getTok();
4520 if (Reg.is(AsmToken::Identifier)) {
4521 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
4522 } else if (Reg.is(AsmToken::Integer)) {
4523 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00004524 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00004525 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00004526 return false;
4527 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004528
4529 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00004530 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004531 reportParseError("invalid register");
4532 return false;
4533 }
4534 Parser.Lex(); // Eat "reg".
4535
4536 // If this is not the end of the statement, report an error.
4537 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4538 reportParseError("unexpected token, expected end of statement");
4539 return false;
4540 }
4541
4542 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
4543
4544 Parser.Lex(); // Consume the EndOfStatement.
4545 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004546}
4547
4548bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004549 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004550 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004551 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004552 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004553 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004554 return false;
4555 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004556 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00004557 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004558 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004559 return false;
4560}
4561
4562bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004563 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004564 Parser.Lex();
4565 // If this is not the end of the statement, report an error.
4566 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004567 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004568 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00004569 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004570 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00004571 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004572 Parser.Lex(); // Consume the EndOfStatement.
4573 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004574}
4575
4576bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004577 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004578 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004579 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004580 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004581 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004582 return false;
4583 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004584 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004585 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004586 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004587 return false;
4588}
4589
4590bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004591 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004592 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004593 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004594 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004595 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004596 return false;
4597 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004598 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00004599 reportParseError("`noreorder' must be set before `nomacro'");
4600 return false;
4601 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004602 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004603 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004604 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004605 return false;
4606}
Jack Carterd76b2372013-03-21 21:44:16 +00004607
Daniel Sanders44934432014-08-07 12:03:36 +00004608bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004609 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004610 Parser.Lex();
4611
4612 // If this is not the end of the statement, report an error.
4613 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004614 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004615
4616 setFeatureBits(Mips::FeatureMSA, "msa");
4617 getTargetStreamer().emitDirectiveSetMsa();
4618 return false;
4619}
4620
4621bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004622 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004623 Parser.Lex();
4624
4625 // If this is not the end of the statement, report an error.
4626 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004627 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004628
4629 clearFeatureBits(Mips::FeatureMSA, "msa");
4630 getTargetStreamer().emitDirectiveSetNoMsa();
4631 return false;
4632}
4633
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004634bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004635 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004636 Parser.Lex(); // Eat "nodsp".
4637
4638 // If this is not the end of the statement, report an error.
4639 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4640 reportParseError("unexpected token, expected end of statement");
4641 return false;
4642 }
4643
4644 clearFeatureBits(Mips::FeatureDSP, "dsp");
4645 getTargetStreamer().emitDirectiveSetNoDsp();
4646 return false;
4647}
4648
Toma Tabacucc2502d2014-11-04 17:18:07 +00004649bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004650 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00004651 Parser.Lex(); // Eat "mips16".
4652
Jack Carter39536722014-01-22 23:08:42 +00004653 // If this is not the end of the statement, report an error.
4654 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004655 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00004656 return false;
4657 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00004658
4659 setFeatureBits(Mips::FeatureMips16, "mips16");
4660 getTargetStreamer().emitDirectiveSetMips16();
4661 Parser.Lex(); // Consume the EndOfStatement.
4662 return false;
4663}
4664
4665bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004666 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00004667 Parser.Lex(); // Eat "nomips16".
4668
4669 // If this is not the end of the statement, report an error.
4670 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4671 reportParseError("unexpected token, expected end of statement");
4672 return false;
4673 }
4674
4675 clearFeatureBits(Mips::FeatureMips16, "mips16");
4676 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00004677 Parser.Lex(); // Consume the EndOfStatement.
4678 return false;
4679}
4680
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004681bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004682 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004683 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004684 // Line can be: .set fp=32
4685 // .set fp=xx
4686 // .set fp=64
4687 Parser.Lex(); // Eat fp token
4688 AsmToken Tok = Parser.getTok();
4689 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004690 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004691 return false;
4692 }
4693 Parser.Lex(); // Eat '=' token.
4694 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004695
4696 if (!parseFpABIValue(FpAbiVal, ".set"))
4697 return false;
4698
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004699 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004700 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004701 return false;
4702 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004703 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004704 Parser.Lex(); // Consume the EndOfStatement.
4705 return false;
4706}
4707
Toma Tabacu32c72aa2015-06-30 09:36:50 +00004708bool MipsAsmParser::parseSetOddSPRegDirective() {
4709 MCAsmParser &Parser = getParser();
4710
4711 Parser.Lex(); // Eat "oddspreg".
4712 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4713 reportParseError("unexpected token, expected end of statement");
4714 return false;
4715 }
4716
4717 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4718 getTargetStreamer().emitDirectiveSetOddSPReg();
4719 return false;
4720}
4721
4722bool MipsAsmParser::parseSetNoOddSPRegDirective() {
4723 MCAsmParser &Parser = getParser();
4724
4725 Parser.Lex(); // Eat "nooddspreg".
4726 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4727 reportParseError("unexpected token, expected end of statement");
4728 return false;
4729 }
4730
4731 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4732 getTargetStreamer().emitDirectiveSetNoOddSPReg();
4733 return false;
4734}
4735
Toma Tabacu9db22db2014-09-09 10:15:38 +00004736bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004737 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004738 SMLoc Loc = getLexer().getLoc();
4739
4740 Parser.Lex();
4741 if (getLexer().isNot(AsmToken::EndOfStatement))
4742 return reportParseError("unexpected token, expected end of statement");
4743
4744 // Always keep an element on the options "stack" to prevent the user
4745 // from changing the initial options. This is how we remember them.
4746 if (AssemblerOptions.size() == 2)
4747 return reportParseError(Loc, ".set pop with no .set push");
4748
4749 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00004750 setAvailableFeatures(
4751 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
4752 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00004753
4754 getTargetStreamer().emitDirectiveSetPop();
4755 return false;
4756}
4757
4758bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004759 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004760 Parser.Lex();
4761 if (getLexer().isNot(AsmToken::EndOfStatement))
4762 return reportParseError("unexpected token, expected end of statement");
4763
4764 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00004765 AssemblerOptions.push_back(
4766 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00004767
4768 getTargetStreamer().emitDirectiveSetPush();
4769 return false;
4770}
4771
Toma Tabacu29696502015-06-02 09:48:04 +00004772bool MipsAsmParser::parseSetSoftFloatDirective() {
4773 MCAsmParser &Parser = getParser();
4774 Parser.Lex();
4775 if (getLexer().isNot(AsmToken::EndOfStatement))
4776 return reportParseError("unexpected token, expected end of statement");
4777
4778 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
4779 getTargetStreamer().emitDirectiveSetSoftFloat();
4780 return false;
4781}
4782
4783bool MipsAsmParser::parseSetHardFloatDirective() {
4784 MCAsmParser &Parser = getParser();
4785 Parser.Lex();
4786 if (getLexer().isNot(AsmToken::EndOfStatement))
4787 return reportParseError("unexpected token, expected end of statement");
4788
4789 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
4790 getTargetStreamer().emitDirectiveSetHardFloat();
4791 return false;
4792}
4793
Jack Carterd76b2372013-03-21 21:44:16 +00004794bool MipsAsmParser::parseSetAssignment() {
4795 StringRef Name;
4796 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00004797 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00004798
4799 if (Parser.parseIdentifier(Name))
4800 reportParseError("expected identifier after .set");
4801
4802 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00004803 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00004804 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00004805
Jack Carter3b2c96e2014-01-22 23:31:38 +00004806 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00004807 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00004808
Jim Grosbach6f482002015-05-18 18:43:14 +00004809 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00004810 Sym->setVariableValue(Value);
4811
4812 return false;
4813}
Jack Carterd0bd6422013-04-18 00:41:53 +00004814
Toma Tabacu26647792014-09-09 12:52:14 +00004815bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004816 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00004817 Parser.Lex();
4818 if (getLexer().isNot(AsmToken::EndOfStatement))
4819 return reportParseError("unexpected token, expected end of statement");
4820
4821 // Reset assembler options to their initial values.
Toma Tabacu465acfd2015-06-09 13:33:26 +00004822 setAvailableFeatures(
4823 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
4824 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00004825 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
4826
4827 getTargetStreamer().emitDirectiveSetMips0();
4828 return false;
4829}
4830
Toma Tabacu85618b32014-08-19 14:22:52 +00004831bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004832 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00004833 Parser.Lex();
4834 if (getLexer().isNot(AsmToken::Equal))
4835 return reportParseError("unexpected token, expected equals sign");
4836
4837 Parser.Lex();
4838 StringRef Arch;
4839 if (Parser.parseIdentifier(Arch))
4840 return reportParseError("expected arch identifier");
4841
4842 StringRef ArchFeatureName =
4843 StringSwitch<StringRef>(Arch)
4844 .Case("mips1", "mips1")
4845 .Case("mips2", "mips2")
4846 .Case("mips3", "mips3")
4847 .Case("mips4", "mips4")
4848 .Case("mips5", "mips5")
4849 .Case("mips32", "mips32")
4850 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00004851 .Case("mips32r3", "mips32r3")
4852 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00004853 .Case("mips32r6", "mips32r6")
4854 .Case("mips64", "mips64")
4855 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00004856 .Case("mips64r3", "mips64r3")
4857 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00004858 .Case("mips64r6", "mips64r6")
4859 .Case("cnmips", "cnmips")
4860 .Case("r4000", "mips3") // This is an implementation of Mips3.
4861 .Default("");
4862
4863 if (ArchFeatureName.empty())
4864 return reportParseError("unsupported architecture");
4865
4866 selectArch(ArchFeatureName);
4867 getTargetStreamer().emitDirectiveSetArch(Arch);
4868 return false;
4869}
4870
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004871bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004872 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004873 Parser.Lex();
4874 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004875 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004876
Matheus Almeida2852af82014-04-22 10:15:54 +00004877 switch (Feature) {
4878 default:
4879 llvm_unreachable("Unimplemented feature");
4880 case Mips::FeatureDSP:
4881 setFeatureBits(Mips::FeatureDSP, "dsp");
4882 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004883 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004884 case Mips::FeatureMicroMips:
4885 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004886 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004887 case Mips::FeatureMips1:
4888 selectArch("mips1");
4889 getTargetStreamer().emitDirectiveSetMips1();
4890 break;
4891 case Mips::FeatureMips2:
4892 selectArch("mips2");
4893 getTargetStreamer().emitDirectiveSetMips2();
4894 break;
4895 case Mips::FeatureMips3:
4896 selectArch("mips3");
4897 getTargetStreamer().emitDirectiveSetMips3();
4898 break;
4899 case Mips::FeatureMips4:
4900 selectArch("mips4");
4901 getTargetStreamer().emitDirectiveSetMips4();
4902 break;
4903 case Mips::FeatureMips5:
4904 selectArch("mips5");
4905 getTargetStreamer().emitDirectiveSetMips5();
4906 break;
4907 case Mips::FeatureMips32:
4908 selectArch("mips32");
4909 getTargetStreamer().emitDirectiveSetMips32();
4910 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004911 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004912 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00004913 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004914 break;
Daniel Sanders17793142015-02-18 16:24:50 +00004915 case Mips::FeatureMips32r3:
4916 selectArch("mips32r3");
4917 getTargetStreamer().emitDirectiveSetMips32R3();
4918 break;
4919 case Mips::FeatureMips32r5:
4920 selectArch("mips32r5");
4921 getTargetStreamer().emitDirectiveSetMips32R5();
4922 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004923 case Mips::FeatureMips32r6:
4924 selectArch("mips32r6");
4925 getTargetStreamer().emitDirectiveSetMips32R6();
4926 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004927 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004928 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00004929 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00004930 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004931 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004932 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00004933 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00004934 break;
Daniel Sanders17793142015-02-18 16:24:50 +00004935 case Mips::FeatureMips64r3:
4936 selectArch("mips64r3");
4937 getTargetStreamer().emitDirectiveSetMips64R3();
4938 break;
4939 case Mips::FeatureMips64r5:
4940 selectArch("mips64r5");
4941 getTargetStreamer().emitDirectiveSetMips64R5();
4942 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004943 case Mips::FeatureMips64r6:
4944 selectArch("mips64r6");
4945 getTargetStreamer().emitDirectiveSetMips64R6();
4946 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004947 }
4948 return false;
4949}
4950
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004951bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004952 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004953 if (getLexer().isNot(AsmToken::Comma)) {
4954 SMLoc Loc = getLexer().getLoc();
4955 Parser.eatToEndOfStatement();
4956 return Error(Loc, ErrorStr);
4957 }
4958
Matheus Almeida2852af82014-04-22 10:15:54 +00004959 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004960 return true;
4961}
4962
Daniel Sanderse2982ad2015-09-17 16:08:39 +00004963// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
4964// In this class, it is only used for .cprestore.
4965// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
4966// MipsTargetELFStreamer and MipsAsmParser.
4967bool MipsAsmParser::isPicAndNotNxxAbi() {
4968 return inPicMode() && !(isABI_N32() || isABI_N64());
4969}
4970
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004971bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00004972 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00004973 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004974
Toma Tabacudde4c462014-11-06 10:02:45 +00004975 if (inMips16Mode()) {
4976 reportParseError(".cpload is not supported in Mips16 mode");
4977 return false;
4978 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004979
David Blaikie960ea3f2014-06-08 16:18:35 +00004980 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00004981 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004982 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4983 reportParseError("expected register containing function address");
4984 return false;
4985 }
4986
David Blaikie960ea3f2014-06-08 16:18:35 +00004987 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
4988 if (!RegOpnd.isGPRAsmReg()) {
4989 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004990 return false;
4991 }
4992
Toma Tabacudde4c462014-11-06 10:02:45 +00004993 // If this is not the end of the statement, report an error.
4994 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4995 reportParseError("unexpected token, expected end of statement");
4996 return false;
4997 }
4998
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004999 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005000 return false;
5001}
5002
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005003bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
5004 MCAsmParser &Parser = getParser();
5005
5006 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
5007 // is used in non-PIC mode.
5008
5009 if (inMips16Mode()) {
5010 reportParseError(".cprestore is not supported in Mips16 mode");
5011 return false;
5012 }
5013
5014 // Get the stack offset value.
5015 const MCExpr *StackOffset;
5016 int64_t StackOffsetVal;
5017 if (Parser.parseExpression(StackOffset)) {
5018 reportParseError("expected stack offset value");
5019 return false;
5020 }
5021
5022 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
5023 reportParseError("stack offset is not an absolute expression");
5024 return false;
5025 }
5026
5027 if (StackOffsetVal < 0) {
5028 Warning(Loc, ".cprestore with negative stack offset has no effect");
5029 IsCpRestoreSet = false;
5030 } else {
5031 IsCpRestoreSet = true;
5032 CpRestoreOffset = StackOffsetVal;
5033 }
5034
5035 // If this is not the end of the statement, report an error.
5036 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5037 reportParseError("unexpected token, expected end of statement");
5038 return false;
5039 }
5040
5041 // Store the $gp on the stack.
5042 SmallVector<MCInst, 3> StoreInsts;
5043 createCpRestoreMemOp(false /*IsLoad*/, CpRestoreOffset /*StackOffset*/, Loc,
5044 StoreInsts);
5045
5046 getTargetStreamer().emitDirectiveCpRestore(StoreInsts, CpRestoreOffset);
5047 Parser.Lex(); // Consume the EndOfStatement.
5048 return false;
5049}
5050
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005051bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005052 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005053 unsigned FuncReg;
5054 unsigned Save;
5055 bool SaveIsReg = true;
5056
Matheus Almeida7e815762014-06-18 13:08:59 +00005057 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005058 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005059 if (ResTy == MatchOperand_NoMatch) {
5060 reportParseError("expected register containing function address");
5061 Parser.eatToEndOfStatement();
5062 return false;
5063 }
5064
5065 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5066 if (!FuncRegOpnd.isGPRAsmReg()) {
5067 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
5068 Parser.eatToEndOfStatement();
5069 return false;
5070 }
5071
5072 FuncReg = FuncRegOpnd.getGPR32Reg();
5073 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005074
Toma Tabacu65f10572014-09-16 15:00:52 +00005075 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005076 return true;
5077
Toma Tabacu13964452014-09-04 13:23:44 +00005078 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00005079 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00005080 const MCExpr *OffsetExpr;
5081 int64_t OffsetVal;
5082 SMLoc ExprLoc = getLexer().getLoc();
5083
5084 if (Parser.parseExpression(OffsetExpr) ||
5085 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
5086 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00005087 Parser.eatToEndOfStatement();
5088 return false;
5089 }
Daniel Sanders5d796282015-09-21 09:26:55 +00005090
5091 Save = OffsetVal;
5092 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00005093 } else {
5094 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5095 if (!SaveOpnd.isGPRAsmReg()) {
5096 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
5097 Parser.eatToEndOfStatement();
5098 return false;
5099 }
5100 Save = SaveOpnd.getGPR32Reg();
5101 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005102
Toma Tabacu65f10572014-09-16 15:00:52 +00005103 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005104 return true;
5105
Toma Tabacu8874eac2015-02-18 13:46:53 +00005106 const MCExpr *Expr;
5107 if (Parser.parseExpression(Expr)) {
5108 reportParseError("expected expression");
5109 return false;
5110 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005111
Toma Tabacu8874eac2015-02-18 13:46:53 +00005112 if (Expr->getKind() != MCExpr::SymbolRef) {
5113 reportParseError("expected symbol");
5114 return false;
5115 }
5116 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
5117
Daniel Sandersf173dda2015-09-22 10:50:09 +00005118 CpSaveLocation = Save;
5119 CpSaveLocationIsRegister = SaveIsReg;
5120
Toma Tabacu8874eac2015-02-18 13:46:53 +00005121 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
5122 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005123 return false;
5124}
5125
Daniel Sandersf173dda2015-09-22 10:50:09 +00005126bool MipsAsmParser::parseDirectiveCPReturn() {
5127 getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation,
5128 CpSaveLocationIsRegister);
5129 return false;
5130}
5131
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005132bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005133 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005134 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5135 const AsmToken &Tok = Parser.getTok();
5136
5137 if (Tok.getString() == "2008") {
5138 Parser.Lex();
5139 getTargetStreamer().emitDirectiveNaN2008();
5140 return false;
5141 } else if (Tok.getString() == "legacy") {
5142 Parser.Lex();
5143 getTargetStreamer().emitDirectiveNaNLegacy();
5144 return false;
5145 }
5146 }
5147 // If we don't recognize the option passed to the .nan
5148 // directive (e.g. no option or unknown option), emit an error.
5149 reportParseError("invalid option in .nan directive");
5150 return false;
5151}
5152
Jack Carter0b744b32012-10-04 02:29:46 +00005153bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005154 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00005155 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00005156 const AsmToken &Tok = Parser.getTok();
5157
5158 if (Tok.getString() == "noat") {
5159 return parseSetNoAtDirective();
5160 } else if (Tok.getString() == "at") {
5161 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00005162 } else if (Tok.getString() == "arch") {
5163 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005164 } else if (Tok.getString() == "fp") {
5165 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005166 } else if (Tok.getString() == "oddspreg") {
5167 return parseSetOddSPRegDirective();
5168 } else if (Tok.getString() == "nooddspreg") {
5169 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005170 } else if (Tok.getString() == "pop") {
5171 return parseSetPopDirective();
5172 } else if (Tok.getString() == "push") {
5173 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00005174 } else if (Tok.getString() == "reorder") {
5175 return parseSetReorderDirective();
5176 } else if (Tok.getString() == "noreorder") {
5177 return parseSetNoReorderDirective();
5178 } else if (Tok.getString() == "macro") {
5179 return parseSetMacroDirective();
5180 } else if (Tok.getString() == "nomacro") {
5181 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00005182 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00005183 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005184 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00005185 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005186 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00005187 getTargetStreamer().emitDirectiveSetNoMicroMips();
5188 Parser.eatToEndOfStatement();
5189 return false;
5190 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005191 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00005192 } else if (Tok.getString() == "mips0") {
5193 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00005194 } else if (Tok.getString() == "mips1") {
5195 return parseSetFeature(Mips::FeatureMips1);
5196 } else if (Tok.getString() == "mips2") {
5197 return parseSetFeature(Mips::FeatureMips2);
5198 } else if (Tok.getString() == "mips3") {
5199 return parseSetFeature(Mips::FeatureMips3);
5200 } else if (Tok.getString() == "mips4") {
5201 return parseSetFeature(Mips::FeatureMips4);
5202 } else if (Tok.getString() == "mips5") {
5203 return parseSetFeature(Mips::FeatureMips5);
5204 } else if (Tok.getString() == "mips32") {
5205 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00005206 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005207 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005208 } else if (Tok.getString() == "mips32r3") {
5209 return parseSetFeature(Mips::FeatureMips32r3);
5210 } else if (Tok.getString() == "mips32r5") {
5211 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005212 } else if (Tok.getString() == "mips32r6") {
5213 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005214 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005215 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005216 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005217 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005218 } else if (Tok.getString() == "mips64r3") {
5219 return parseSetFeature(Mips::FeatureMips64r3);
5220 } else if (Tok.getString() == "mips64r5") {
5221 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005222 } else if (Tok.getString() == "mips64r6") {
5223 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00005224 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005225 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005226 } else if (Tok.getString() == "nodsp") {
5227 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00005228 } else if (Tok.getString() == "msa") {
5229 return parseSetMsaDirective();
5230 } else if (Tok.getString() == "nomsa") {
5231 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00005232 } else if (Tok.getString() == "softfloat") {
5233 return parseSetSoftFloatDirective();
5234 } else if (Tok.getString() == "hardfloat") {
5235 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00005236 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00005237 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00005238 parseSetAssignment();
5239 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005240 }
Jack Carter07c818d2013-01-25 01:31:34 +00005241
Jack Carter0b744b32012-10-04 02:29:46 +00005242 return true;
5243}
5244
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005245/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00005246/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005247bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005248 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005249 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5250 for (;;) {
5251 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005252 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00005253 return true;
5254
5255 getParser().getStreamer().EmitValue(Value, Size);
5256
5257 if (getLexer().is(AsmToken::EndOfStatement))
5258 break;
5259
Jack Carter07c818d2013-01-25 01:31:34 +00005260 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005261 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00005262 Parser.Lex();
5263 }
5264 }
5265
5266 Parser.Lex();
5267 return false;
5268}
5269
Vladimir Medic4c299852013-11-06 11:27:05 +00005270/// parseDirectiveGpWord
5271/// ::= .gpword local_sym
5272bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005273 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00005274 const MCExpr *Value;
5275 // EmitGPRel32Value requires an expression, so we are using base class
5276 // method to evaluate the expression.
5277 if (getParser().parseExpression(Value))
5278 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00005279 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00005280
Vladimir Medice10c1122013-11-13 13:18:04 +00005281 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005282 return Error(getLexer().getLoc(),
5283 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00005284 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00005285 return false;
5286}
5287
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005288/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00005289/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005290bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005291 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005292 const MCExpr *Value;
5293 // EmitGPRel64Value requires an expression, so we are using base class
5294 // method to evaluate the expression.
5295 if (getParser().parseExpression(Value))
5296 return true;
5297 getParser().getStreamer().EmitGPRel64Value(Value);
5298
5299 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005300 return Error(getLexer().getLoc(),
5301 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00005302 Parser.Lex(); // Eat EndOfStatement token.
5303 return false;
5304}
5305
Jack Carter0cd3c192014-01-06 23:27:31 +00005306bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005307 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00005308 // Get the option token.
5309 AsmToken Tok = Parser.getTok();
5310 // At the moment only identifiers are supported.
5311 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005312 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00005313 Parser.eatToEndOfStatement();
5314 return false;
5315 }
5316
5317 StringRef Option = Tok.getIdentifier();
5318
5319 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005320 // MipsAsmParser needs to know if the current PIC mode changes.
5321 IsPicEnabled = false;
5322
Jack Carter0cd3c192014-01-06 23:27:31 +00005323 getTargetStreamer().emitDirectiveOptionPic0();
5324 Parser.Lex();
5325 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5326 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005327 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005328 Parser.eatToEndOfStatement();
5329 }
5330 return false;
5331 }
5332
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005333 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005334 // MipsAsmParser needs to know if the current PIC mode changes.
5335 IsPicEnabled = true;
5336
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005337 getTargetStreamer().emitDirectiveOptionPic2();
5338 Parser.Lex();
5339 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5340 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005341 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005342 Parser.eatToEndOfStatement();
5343 }
5344 return false;
5345 }
5346
Jack Carter0cd3c192014-01-06 23:27:31 +00005347 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00005348 Warning(Parser.getTok().getLoc(),
5349 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00005350 Parser.eatToEndOfStatement();
5351 return false;
5352}
5353
Toma Tabacu9ca50962015-04-16 09:53:47 +00005354/// parseInsnDirective
5355/// ::= .insn
5356bool MipsAsmParser::parseInsnDirective() {
5357 // If this is not the end of the statement, report an error.
5358 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5359 reportParseError("unexpected token, expected end of statement");
5360 return false;
5361 }
5362
5363 // The actual label marking happens in
5364 // MipsELFStreamer::createPendingLabelRelocs().
5365 getTargetStreamer().emitDirectiveInsn();
5366
5367 getParser().Lex(); // Eat EndOfStatement token.
5368 return false;
5369}
5370
Daniel Sanders7e527422014-07-10 13:38:23 +00005371/// parseDirectiveModule
5372/// ::= .module oddspreg
5373/// ::= .module nooddspreg
5374/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00005375/// ::= .module softfloat
5376/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005377bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005378 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005379 MCAsmLexer &Lexer = getLexer();
5380 SMLoc L = Lexer.getLoc();
5381
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00005382 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005383 // TODO : get a better message.
5384 reportParseError(".module directive must appear before any code");
5385 return false;
5386 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005387
Toma Tabacuc405c822015-01-23 10:40:19 +00005388 StringRef Option;
5389 if (Parser.parseIdentifier(Option)) {
5390 reportParseError("expected .module option identifier");
5391 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005392 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005393
Toma Tabacuc405c822015-01-23 10:40:19 +00005394 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005395 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005396
Toma Tabacu3c499582015-06-25 10:56:57 +00005397 // Synchronize the abiflags information with the FeatureBits information we
5398 // changed above.
5399 getTargetStreamer().updateABIInfo(*this);
5400
5401 // If printing assembly, use the recently updated abiflags information.
5402 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5403 // emitted at the end).
5404 getTargetStreamer().emitDirectiveModuleOddSPReg();
5405
Toma Tabacuc405c822015-01-23 10:40:19 +00005406 // If this is not the end of the statement, report an error.
5407 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5408 reportParseError("unexpected token, expected end of statement");
5409 return false;
5410 }
5411
5412 return false; // parseDirectiveModule has finished successfully.
5413 } else if (Option == "nooddspreg") {
5414 if (!isABI_O32()) {
5415 Error(L, "'.module nooddspreg' requires the O32 ABI");
5416 return false;
5417 }
5418
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005419 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005420
Toma Tabacu3c499582015-06-25 10:56:57 +00005421 // Synchronize the abiflags information with the FeatureBits information we
5422 // changed above.
5423 getTargetStreamer().updateABIInfo(*this);
5424
5425 // If printing assembly, use the recently updated abiflags information.
5426 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5427 // emitted at the end).
5428 getTargetStreamer().emitDirectiveModuleOddSPReg();
5429
Toma Tabacuc405c822015-01-23 10:40:19 +00005430 // If this is not the end of the statement, report an error.
5431 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5432 reportParseError("unexpected token, expected end of statement");
5433 return false;
5434 }
5435
5436 return false; // parseDirectiveModule has finished successfully.
5437 } else if (Option == "fp") {
5438 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00005439 } else if (Option == "softfloat") {
5440 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5441
5442 // Synchronize the ABI Flags information with the FeatureBits information we
5443 // updated above.
5444 getTargetStreamer().updateABIInfo(*this);
5445
5446 // If printing assembly, use the recently updated ABI Flags information.
5447 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5448 // emitted later).
5449 getTargetStreamer().emitDirectiveModuleSoftFloat();
5450
5451 // If this is not the end of the statement, report an error.
5452 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5453 reportParseError("unexpected token, expected end of statement");
5454 return false;
5455 }
5456
5457 return false; // parseDirectiveModule has finished successfully.
5458 } else if (Option == "hardfloat") {
5459 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5460
5461 // Synchronize the ABI Flags information with the FeatureBits information we
5462 // updated above.
5463 getTargetStreamer().updateABIInfo(*this);
5464
5465 // If printing assembly, use the recently updated ABI Flags information.
5466 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5467 // emitted later).
5468 getTargetStreamer().emitDirectiveModuleHardFloat();
5469
5470 // If this is not the end of the statement, report an error.
5471 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5472 reportParseError("unexpected token, expected end of statement");
5473 return false;
5474 }
5475
5476 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00005477 } else {
5478 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
5479 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005480}
5481
5482/// parseDirectiveModuleFP
5483/// ::= =32
5484/// ::= =xx
5485/// ::= =64
5486bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005487 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005488 MCAsmLexer &Lexer = getLexer();
5489
5490 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005491 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005492 return false;
5493 }
5494 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005495
Daniel Sanders7e527422014-07-10 13:38:23 +00005496 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005497 if (!parseFpABIValue(FpABI, ".module"))
5498 return false;
5499
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005500 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005501 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005502 return false;
5503 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005504
Toma Tabacua64e5402015-06-25 12:44:38 +00005505 // Synchronize the abiflags information with the FeatureBits information we
5506 // changed above.
5507 getTargetStreamer().updateABIInfo(*this);
5508
5509 // If printing assembly, use the recently updated abiflags information.
5510 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5511 // emitted at the end).
5512 getTargetStreamer().emitDirectiveModuleFP();
5513
Daniel Sanders7e527422014-07-10 13:38:23 +00005514 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005515 return false;
5516}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005517
Daniel Sanders7e527422014-07-10 13:38:23 +00005518bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005519 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005520 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005521 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005522 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005523
5524 if (Lexer.is(AsmToken::Identifier)) {
5525 StringRef Value = Parser.getTok().getString();
5526 Parser.Lex();
5527
5528 if (Value != "xx") {
5529 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5530 return false;
5531 }
5532
5533 if (!isABI_O32()) {
5534 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
5535 return false;
5536 }
5537
Daniel Sanders7e527422014-07-10 13:38:23 +00005538 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005539 if (ModuleLevelOptions) {
5540 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5541 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5542 } else {
5543 setFeatureBits(Mips::FeatureFPXX, "fpxx");
5544 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5545 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005546 return true;
5547 }
5548
5549 if (Lexer.is(AsmToken::Integer)) {
5550 unsigned Value = Parser.getTok().getIntVal();
5551 Parser.Lex();
5552
5553 if (Value != 32 && Value != 64) {
5554 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5555 return false;
5556 }
5557
5558 if (Value == 32) {
5559 if (!isABI_O32()) {
5560 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
5561 return false;
5562 }
5563
Daniel Sanders7e527422014-07-10 13:38:23 +00005564 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005565 if (ModuleLevelOptions) {
5566 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5567 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5568 } else {
5569 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5570 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5571 }
Toma Tabacua64e5402015-06-25 12:44:38 +00005572 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00005573 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005574 if (ModuleLevelOptions) {
5575 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5576 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5577 } else {
5578 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5579 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
5580 }
Toma Tabacua64e5402015-06-25 12:44:38 +00005581 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005582
Daniel Sanders7e527422014-07-10 13:38:23 +00005583 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005584 }
5585
5586 return false;
5587}
5588
Jack Carter0b744b32012-10-04 02:29:46 +00005589bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005590 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005591 StringRef IDVal = DirectiveID.getString();
5592
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005593 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005594 return parseDirectiveCpLoad(DirectiveID.getLoc());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005595 if (IDVal == ".cprestore")
5596 return parseDirectiveCpRestore(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00005597 if (IDVal == ".dword") {
5598 parseDataDirective(8, DirectiveID.getLoc());
5599 return false;
5600 }
Jack Carterd0bd6422013-04-18 00:41:53 +00005601 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005602 StringRef SymbolName;
5603
5604 if (Parser.parseIdentifier(SymbolName)) {
5605 reportParseError("expected identifier after .ent");
5606 return false;
5607 }
5608
5609 // There's an undocumented extension that allows an integer to
5610 // follow the name of the procedure which AFAICS is ignored by GAS.
5611 // Example: .ent foo,2
5612 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5613 if (getLexer().isNot(AsmToken::Comma)) {
5614 // Even though we accept this undocumented extension for compatibility
5615 // reasons, the additional integer argument does not actually change
5616 // the behaviour of the '.ent' directive, so we would like to discourage
5617 // its use. We do this by not referring to the extended version in
5618 // error messages which are not directly related to its use.
5619 reportParseError("unexpected token, expected end of statement");
5620 return false;
5621 }
5622 Parser.Lex(); // Eat the comma.
5623 const MCExpr *DummyNumber;
5624 int64_t DummyNumberVal;
5625 // If the user was explicitly trying to use the extended version,
5626 // we still give helpful extension-related error messages.
5627 if (Parser.parseExpression(DummyNumber)) {
5628 reportParseError("expected number after comma");
5629 return false;
5630 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00005631 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005632 reportParseError("expected an absolute expression after comma");
5633 return false;
5634 }
5635 }
5636
5637 // If this is not the end of the statement, report an error.
5638 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5639 reportParseError("unexpected token, expected end of statement");
5640 return false;
5641 }
5642
Jim Grosbach6f482002015-05-18 18:43:14 +00005643 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005644
5645 getTargetStreamer().emitDirectiveEnt(*Sym);
5646 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005647 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00005648 return false;
5649 }
5650
Jack Carter07c818d2013-01-25 01:31:34 +00005651 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005652 StringRef SymbolName;
5653
5654 if (Parser.parseIdentifier(SymbolName)) {
5655 reportParseError("expected identifier after .end");
5656 return false;
5657 }
5658
5659 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5660 reportParseError("unexpected token, expected end of statement");
5661 return false;
5662 }
5663
5664 if (CurrentFn == nullptr) {
5665 reportParseError(".end used without .ent");
5666 return false;
5667 }
5668
5669 if ((SymbolName != CurrentFn->getName())) {
5670 reportParseError(".end symbol does not match .ent symbol");
5671 return false;
5672 }
5673
5674 getTargetStreamer().emitDirectiveEnd(SymbolName);
5675 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005676 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00005677 return false;
5678 }
5679
Jack Carter07c818d2013-01-25 01:31:34 +00005680 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005681 // .frame $stack_reg, frame_size_in_bytes, $return_reg
5682 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005683 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005684 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5685 reportParseError("expected stack register");
5686 return false;
5687 }
5688
5689 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5690 if (!StackRegOpnd.isGPRAsmReg()) {
5691 reportParseError(StackRegOpnd.getStartLoc(),
5692 "expected general purpose register");
5693 return false;
5694 }
5695 unsigned StackReg = StackRegOpnd.getGPR32Reg();
5696
5697 if (Parser.getTok().is(AsmToken::Comma))
5698 Parser.Lex();
5699 else {
5700 reportParseError("unexpected token, expected comma");
5701 return false;
5702 }
5703
5704 // Parse the frame size.
5705 const MCExpr *FrameSize;
5706 int64_t FrameSizeVal;
5707
5708 if (Parser.parseExpression(FrameSize)) {
5709 reportParseError("expected frame size value");
5710 return false;
5711 }
5712
Jim Grosbach13760bd2015-05-30 01:25:56 +00005713 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005714 reportParseError("frame size not an absolute expression");
5715 return false;
5716 }
5717
5718 if (Parser.getTok().is(AsmToken::Comma))
5719 Parser.Lex();
5720 else {
5721 reportParseError("unexpected token, expected comma");
5722 return false;
5723 }
5724
5725 // Parse the return register.
5726 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00005727 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005728 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5729 reportParseError("expected return register");
5730 return false;
5731 }
5732
5733 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5734 if (!ReturnRegOpnd.isGPRAsmReg()) {
5735 reportParseError(ReturnRegOpnd.getStartLoc(),
5736 "expected general purpose register");
5737 return false;
5738 }
5739
5740 // If this is not the end of the statement, report an error.
5741 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5742 reportParseError("unexpected token, expected end of statement");
5743 return false;
5744 }
5745
5746 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
5747 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005748 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00005749 return false;
5750 }
5751
Jack Carter07c818d2013-01-25 01:31:34 +00005752 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00005753 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00005754 }
5755
Daniel Sandersd97a6342014-08-13 10:07:34 +00005756 if (IDVal == ".mask" || IDVal == ".fmask") {
5757 // .mask bitmask, frame_offset
5758 // bitmask: One bit for each register used.
5759 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
5760 // first register is expected to be saved.
5761 // Examples:
5762 // .mask 0x80000000, -4
5763 // .fmask 0x80000000, -4
5764 //
Jack Carterbe332172012-09-07 00:48:02 +00005765
Daniel Sandersd97a6342014-08-13 10:07:34 +00005766 // Parse the bitmask
5767 const MCExpr *BitMask;
5768 int64_t BitMaskVal;
5769
5770 if (Parser.parseExpression(BitMask)) {
5771 reportParseError("expected bitmask value");
5772 return false;
5773 }
5774
Jim Grosbach13760bd2015-05-30 01:25:56 +00005775 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005776 reportParseError("bitmask not an absolute expression");
5777 return false;
5778 }
5779
5780 if (Parser.getTok().is(AsmToken::Comma))
5781 Parser.Lex();
5782 else {
5783 reportParseError("unexpected token, expected comma");
5784 return false;
5785 }
5786
5787 // Parse the frame_offset
5788 const MCExpr *FrameOffset;
5789 int64_t FrameOffsetVal;
5790
5791 if (Parser.parseExpression(FrameOffset)) {
5792 reportParseError("expected frame offset value");
5793 return false;
5794 }
5795
Jim Grosbach13760bd2015-05-30 01:25:56 +00005796 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005797 reportParseError("frame offset not an absolute expression");
5798 return false;
5799 }
5800
5801 // If this is not the end of the statement, report an error.
5802 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5803 reportParseError("unexpected token, expected end of statement");
5804 return false;
5805 }
5806
5807 if (IDVal == ".mask")
5808 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
5809 else
5810 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00005811 return false;
5812 }
5813
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005814 if (IDVal == ".nan")
5815 return parseDirectiveNaN();
5816
Jack Carter07c818d2013-01-25 01:31:34 +00005817 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00005818 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00005819 return false;
5820 }
5821
Rafael Espindolab59fb732014-03-28 18:50:26 +00005822 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005823 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005824 return false;
5825 }
5826
Jack Carter07c818d2013-01-25 01:31:34 +00005827 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005828 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00005829 return false;
5830 }
5831
Jack Carter0cd3c192014-01-06 23:27:31 +00005832 if (IDVal == ".option")
5833 return parseDirectiveOption();
5834
5835 if (IDVal == ".abicalls") {
5836 getTargetStreamer().emitDirectiveAbiCalls();
5837 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005838 Error(Parser.getTok().getLoc(),
5839 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005840 // Clear line
5841 Parser.eatToEndOfStatement();
5842 }
5843 return false;
5844 }
5845
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005846 if (IDVal == ".cpsetup")
5847 return parseDirectiveCPSetup();
5848
Daniel Sandersf173dda2015-09-22 10:50:09 +00005849 if (IDVal == ".cpreturn")
5850 return parseDirectiveCPReturn();
5851
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005852 if (IDVal == ".module")
5853 return parseDirectiveModule();
5854
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00005855 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
5856 return parseInternalDirectiveReallowModule();
5857
Toma Tabacu9ca50962015-04-16 09:53:47 +00005858 if (IDVal == ".insn")
5859 return parseInsnDirective();
5860
Rafael Espindola870c4e92012-01-11 03:56:41 +00005861 return true;
5862}
5863
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00005864bool MipsAsmParser::parseInternalDirectiveReallowModule() {
5865 // If this is not the end of the statement, report an error.
5866 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5867 reportParseError("unexpected token, expected end of statement");
5868 return false;
5869 }
5870
5871 getTargetStreamer().reallowModuleDirective();
5872
5873 getParser().Lex(); // Eat EndOfStatement token.
5874 return false;
5875}
5876
Rafael Espindola870c4e92012-01-11 03:56:41 +00005877extern "C" void LLVMInitializeMipsAsmParser() {
5878 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
5879 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
5880 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
5881 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
5882}
Jack Carterb4dbc172012-09-05 23:34:03 +00005883
5884#define GET_REGISTER_MATCHER
5885#define GET_MATCHER_IMPLEMENTATION
5886#include "MipsGenAsmMatcher.inc"