blob: d6994c6b5dc41f4eb85db72419ceb53e3fdf33ef [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
Jack Carterb4dbc172012-09-05 23:34:03 +0000110 MCSubtargetInfo &STI;
Eric Christophera5762812015-01-26 17:33:46 +0000111 MipsABIInfo ABI;
Toma Tabacu9db22db2014-09-09 10:15:38 +0000112 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000113 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
114 // nullptr, which indicates that no function is currently
115 // selected. This usually happens after an '.end func'
116 // directive.
Toma Tabacud88d79c2015-06-23 14:39:42 +0000117 bool IsLittleEndian;
Daniel Sandersa6994442015-08-18 12:33:54 +0000118 bool IsPicEnabled;
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000119 bool IsCpRestoreSet;
120 int CpRestoreOffset;
Jack Carter0b744b32012-10-04 02:29:46 +0000121
Daniel Sandersef638fe2014-10-03 15:37:37 +0000122 // Print a warning along with its fix-it message at the given range.
123 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
124 SMRange Range, bool ShowColors = true);
125
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000126#define GET_ASSEMBLER_HEADER
127#include "MipsGenAsmMatcher.inc"
128
Matheus Almeida595fcab2014-06-11 15:05:56 +0000129 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
130
Chad Rosier49963552012-10-13 00:26:04 +0000131 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000132 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000133 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000134 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000135
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000136 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000137 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000138
Toma Tabacu13964452014-09-04 13:23:44 +0000139 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000140
Toma Tabacu13964452014-09-04 13:23:44 +0000141 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000142
David Blaikie960ea3f2014-06-08 16:18:35 +0000143 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
144 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000145
Craig Topper56c590a2014-04-29 07:58:02 +0000146 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000147
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000148 OperandMatchResultTy parseMemOperand(OperandVector &Operands);
149 OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000150 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000151 StringRef Identifier, SMLoc S);
Simon Atanasyan75e3b3c2015-09-14 11:18:22 +0000152 OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands,
153 SMLoc S);
154 OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
155 OperandMatchResultTy parseImm(OperandVector &Operands);
156 OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
157 OperandMatchResultTy parseInvNum(OperandVector &Operands);
158 OperandMatchResultTy parseLSAImm(OperandVector &Operands);
159 OperandMatchResultTy parseRegisterPair(OperandVector &Operands);
160 OperandMatchResultTy parseMovePRegPair(OperandVector &Operands);
161 OperandMatchResultTy parseRegisterList(OperandVector &Operands);
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000162
David Blaikie960ea3f2014-06-08 16:18:35 +0000163 bool searchSymbolAlias(OperandVector &Operands);
164
Toma Tabacu13964452014-09-04 13:23:44 +0000165 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000166
Jack Carter30a59822012-10-04 04:03:53 +0000167 bool needsExpansion(MCInst &Inst);
168
Matheus Almeida3813d572014-06-19 14:39:14 +0000169 // Expands assembly pseudo instructions.
170 // Returns false on success, true otherwise.
171 bool expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000172 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000173
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000174 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
175 SmallVectorImpl<MCInst> &Instructions);
176
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000177 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000178 bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000179 SmallVectorImpl<MCInst> &Instructions);
180
Toma Tabacuf712ede2015-06-17 14:31:51 +0000181 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
182 unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
183 SmallVectorImpl<MCInst> &Instructions);
Toma Tabacu674825c2015-06-16 12:16:24 +0000184
Toma Tabacu00e98672015-05-01 12:19:27 +0000185 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000186 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000187
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000188 bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
189 const MCOperand &Offset, bool Is32BitAddress,
190 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000191
Jozef Kolek5cfebdd2015-01-21 12:39:30 +0000192 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
193 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000194
Jack Carter9e65aa32013-03-22 00:05:30 +0000195 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000196 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
197 bool isImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000198
199 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
200 SmallVectorImpl<MCInst> &Instructions);
201
Toma Tabacue1e460d2015-06-11 10:36:10 +0000202 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc,
203 SmallVectorImpl<MCInst> &Instructions);
204
Toma Tabacu1a108322015-06-17 13:20:24 +0000205 bool expandCondBranches(MCInst &Inst, SMLoc IDLoc,
206 SmallVectorImpl<MCInst> &Instructions);
207
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000208 bool expandDiv(MCInst &Inst, SMLoc IDLoc,
209 SmallVectorImpl<MCInst> &Instructions, const bool IsMips64,
210 const bool Signed);
211
Toma Tabacud88d79c2015-06-23 14:39:42 +0000212 bool expandUlhu(MCInst &Inst, SMLoc IDLoc,
213 SmallVectorImpl<MCInst> &Instructions);
214
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +0000215 bool expandUlw(MCInst &Inst, SMLoc IDLoc,
216 SmallVectorImpl<MCInst> &Instructions);
217
Toma Tabacu234482a2015-03-16 12:03:39 +0000218 void createNop(bool hasShortDelaySlot, SMLoc IDLoc,
219 SmallVectorImpl<MCInst> &Instructions);
220
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000221 void createAddu(unsigned DstReg, unsigned SrcReg, unsigned TrgReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +0000222 bool Is64Bit, SmallVectorImpl<MCInst> &Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000223
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000224 void createCpRestoreMemOp(bool IsLoad, int StackOffset, SMLoc IDLoc,
225 SmallVectorImpl<MCInst> &Instructions);
226
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000227 bool reportParseError(Twine ErrorMsg);
228 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000229
Jack Carterb5cf5902013-04-17 00:18:04 +0000230 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000231 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000232
Vladimir Medic4c299852013-11-06 11:27:05 +0000233 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000234
235 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000236 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000237 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000238 bool parseSetFeature(uint64_t Feature);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000239 bool isPicAndNotNxxAbi(); // Used by .cpload, .cprestore, and .cpsetup.
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000240 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000241 bool parseDirectiveCpRestore(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000242 bool parseDirectiveCPSetup();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000243 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000244 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000245 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000246 bool parseInsnDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000247
248 bool parseSetAtDirective();
249 bool parseSetNoAtDirective();
250 bool parseSetMacroDirective();
251 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000252 bool parseSetMsaDirective();
253 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000254 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000255 bool parseSetReorderDirective();
256 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000257 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000258 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000259 bool parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000260 bool parseSetOddSPRegDirective();
261 bool parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000262 bool parseSetPopDirective();
263 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000264 bool parseSetSoftFloatDirective();
265 bool parseSetHardFloatDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000266
Jack Carterd76b2372013-03-21 21:44:16 +0000267 bool parseSetAssignment();
268
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000269 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000270 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000271 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000272 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000273 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000274 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
275 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000276
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000277 bool parseInternalDirectiveReallowModule();
278
Jack Carterdc1e35d2012-09-06 20:00:02 +0000279 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000280
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000281 bool eatComma(StringRef ErrorStr);
282
Jack Carter1ac53222013-02-20 23:11:17 +0000283 int matchCPURegisterName(StringRef Symbol);
284
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000285 int matchHWRegsRegisterName(StringRef Symbol);
286
Jack Carter873c7242013-01-12 01:03:14 +0000287 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000288
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000289 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000290
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000291 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000292
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000293 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000294
Jack Carter5dc8ac92013-09-25 23:50:44 +0000295 int matchMSA128RegisterName(StringRef Name);
296
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000297 int matchMSA128CtrlRegisterName(StringRef Name);
298
Jack Carterd0bd6422013-04-18 00:41:53 +0000299 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000300
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000301 unsigned getGPR(int RegNo);
302
Toma Tabacu89a712b2015-04-15 10:48:56 +0000303 /// Returns the internal register number for the current AT. Also checks if
304 /// the current AT is unavailable (set to $0) and gives an error if it is.
305 /// This should be used in pseudo-instruction expansions which need AT.
306 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000307
308 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000309 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000310
311 // Helper function that checks if the value of a vector index is within the
312 // boundaries of accepted values for each RegisterKind
313 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
314 bool validateMSAIndex(int Val, int RegKind);
315
Daniel Sandersf0df2212014-08-04 12:20:00 +0000316 // Selects a new architecture by updating the FeatureBits with the necessary
317 // info including implied dependencies.
318 // Internally, it clears all the feature bits related to *any* architecture
319 // and selects the new one using the ToggleFeature functionality of the
320 // MCSubtargetInfo object that handles implied dependencies. The reason we
321 // clear all the arch related bits manually is because ToggleFeature only
322 // clears the features that imply the feature being cleared and not the
323 // features implied by the feature being cleared. This is easier to see
324 // with an example:
325 // --------------------------------------------------
326 // | Feature | Implies |
327 // | -------------------------------------------------|
328 // | FeatureMips1 | None |
329 // | FeatureMips2 | FeatureMips1 |
330 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
331 // | FeatureMips4 | FeatureMips3 |
332 // | ... | |
333 // --------------------------------------------------
334 //
335 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
336 // FeatureMipsGP64 | FeatureMips1)
337 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
338 void selectArch(StringRef ArchFeature) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000339 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000340 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
341 STI.setFeatureBits(FeatureBits);
342 setAvailableFeatures(
343 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000344 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000345 }
346
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000347 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000348 if (!(STI.getFeatureBits()[Feature])) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000349 setAvailableFeatures(
350 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000351 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000352 }
353 }
354
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000355 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000356 if (STI.getFeatureBits()[Feature]) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000357 setAvailableFeatures(
358 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000359 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000360 }
361 }
362
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000363 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
364 setFeatureBits(Feature, FeatureString);
365 AssemblerOptions.front()->setFeatures(STI.getFeatureBits());
366 }
367
368 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
369 clearFeatureBits(Feature, FeatureString);
370 AssemblerOptions.front()->setFeatures(STI.getFeatureBits());
371 }
372
Rafael Espindola870c4e92012-01-11 03:56:41 +0000373public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000374 enum MipsMatchResultTy {
375 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
376#define GET_OPERAND_DIAGNOSTIC_TYPES
377#include "MipsGenAsmMatcher.inc"
378#undef GET_OPERAND_DIAGNOSTIC_TYPES
379
380 };
381
Joey Gouly0e76fa72013-09-12 10:28:05 +0000382 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000383 const MCInstrInfo &MII, const MCTargetOptions &Options)
Colin LeMahieufe2c8b82015-07-27 21:56:53 +0000384 : MCTargetAsmParser(Options), STI(sti),
Daniel Sanders50f17232015-09-15 16:17:27 +0000385 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
386 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000387 MCAsmParserExtension::Initialize(parser);
388
Toma Tabacu11e14a92015-04-21 11:50:52 +0000389 parser.addAliasForDirective(".asciiz", ".asciz");
390
Jack Carterb4dbc172012-09-05 23:34:03 +0000391 // Initialize the set of available features.
392 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000393
Toma Tabacu9db22db2014-09-09 10:15:38 +0000394 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000395 AssemblerOptions.push_back(
Toma Tabacu465acfd2015-06-09 13:33:26 +0000396 llvm::make_unique<MipsAssemblerOptions>(STI.getFeatureBits()));
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000397
Toma Tabacu9db22db2014-09-09 10:15:38 +0000398 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000399 AssemblerOptions.push_back(
Toma Tabacu465acfd2015-06-09 13:33:26 +0000400 llvm::make_unique<MipsAssemblerOptions>(STI.getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000401
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000402 getTargetStreamer().updateABIInfo(*this);
403
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000404 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000405 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000406
407 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000408
Daniel Sandersa6994442015-08-18 12:33:54 +0000409 IsPicEnabled =
410 (getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_);
411
Daniel Sanderse2982ad2015-09-17 16:08:39 +0000412 IsCpRestoreSet = false;
413 CpRestoreOffset = -1;
414
Daniel Sanders50f17232015-09-15 16:17:27 +0000415 Triple TheTriple(sti.getTargetTriple());
416 if ((TheTriple.getArch() == Triple::mips) ||
417 (TheTriple.getArch() == Triple::mips64))
Toma Tabacud88d79c2015-06-23 14:39:42 +0000418 IsLittleEndian = false;
419 else
420 IsLittleEndian = true;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000421 }
422
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000423 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
424 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
425
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000426 bool isGP64bit() const { return STI.getFeatureBits()[Mips::FeatureGP64Bit]; }
427 bool isFP64bit() const { return STI.getFeatureBits()[Mips::FeatureFP64Bit]; }
Eric Christophera5762812015-01-26 17:33:46 +0000428 const MipsABIInfo &getABI() const { return ABI; }
429 bool isABI_N32() const { return ABI.IsN32(); }
430 bool isABI_N64() const { return ABI.IsN64(); }
431 bool isABI_O32() const { return ABI.IsO32(); }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000432 bool isABI_FPXX() const { return STI.getFeatureBits()[Mips::FeatureFPXX]; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000433
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000434 bool useOddSPReg() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000435 return !(STI.getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000436 }
437
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000438 bool inMicroMipsMode() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000439 return STI.getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000440 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000441 bool hasMips1() const { return STI.getFeatureBits()[Mips::FeatureMips1]; }
442 bool hasMips2() const { return STI.getFeatureBits()[Mips::FeatureMips2]; }
443 bool hasMips3() const { return STI.getFeatureBits()[Mips::FeatureMips3]; }
444 bool hasMips4() const { return STI.getFeatureBits()[Mips::FeatureMips4]; }
445 bool hasMips5() const { return STI.getFeatureBits()[Mips::FeatureMips5]; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000446 bool hasMips32() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000447 return STI.getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000448 }
449 bool hasMips64() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000450 return STI.getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000451 }
452 bool hasMips32r2() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000453 return STI.getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000454 }
455 bool hasMips64r2() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000456 return STI.getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000457 }
Daniel Sanders17793142015-02-18 16:24:50 +0000458 bool hasMips32r3() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000459 return (STI.getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000460 }
461 bool hasMips64r3() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000462 return (STI.getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000463 }
464 bool hasMips32r5() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000465 return (STI.getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000466 }
467 bool hasMips64r5() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000468 return (STI.getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000469 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000470 bool hasMips32r6() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000471 return STI.getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000472 }
473 bool hasMips64r6() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000474 return STI.getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000475 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000476
477 bool hasDSP() const { return STI.getFeatureBits()[Mips::FeatureDSP]; }
478 bool hasDSPR2() const { return STI.getFeatureBits()[Mips::FeatureDSPR2]; }
479 bool hasMSA() const { return STI.getFeatureBits()[Mips::FeatureMSA]; }
Kai Nackee0245392015-01-27 19:11:28 +0000480 bool hasCnMips() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000481 return (STI.getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000482 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000483
Daniel Sandersa6994442015-08-18 12:33:54 +0000484 bool inPicMode() {
485 return IsPicEnabled;
486 }
487
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000488 bool inMips16Mode() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000489 return STI.getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000490 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000491
Daniel Sanders3ebcaf62015-09-03 12:31:22 +0000492 bool useTraps() const {
493 return STI.getFeatureBits()[Mips::FeatureUseTCCInDIV];
494 }
495
Eric Christophere8ae3e32015-05-07 23:10:21 +0000496 bool useSoftFloat() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000497 return STI.getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000498 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000499
Toma Tabacud9d344b2015-04-27 14:05:04 +0000500 /// Warn if RegIndex is the same as the current AT.
501 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000502
503 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000504
505 bool isLittle() const { return IsLittleEndian; }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000506};
507}
508
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000509namespace {
510
511/// MipsOperand - Instances of this class represent a parsed Mips machine
512/// instruction.
513class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000514public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000515 /// Broad categories of register classes
516 /// The exact class is finalized by the render method.
517 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000518 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000519 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000520 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000521 RegKind_FCC = 4, /// FCC
522 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
523 RegKind_MSACtrl = 16, /// MSA control registers
524 RegKind_COP2 = 32, /// COP2
525 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
526 /// context).
527 RegKind_CCR = 128, /// CCR
528 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000529 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000530 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000531 /// Potentially any (e.g. $1)
532 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
533 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000534 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000535 };
536
537private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000538 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000539 k_Immediate, /// An immediate (possibly involving symbol references)
540 k_Memory, /// Base + Offset Memory Address
541 k_PhysRegister, /// A physical register from the Mips namespace
542 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000543 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000544 k_RegList, /// A physical register list
545 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000546 } Kind;
547
David Blaikie960ea3f2014-06-08 16:18:35 +0000548public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000549 MipsOperand(KindTy K, MipsAsmParser &Parser)
550 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
551
David Blaikie960ea3f2014-06-08 16:18:35 +0000552private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000553 /// For diagnostics, and checking the assembler temporary
554 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000555
Eric Christopher8996c5d2013-03-15 00:42:55 +0000556 struct Token {
557 const char *Data;
558 unsigned Length;
559 };
560
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000561 struct PhysRegOp {
562 unsigned Num; /// Register Number
563 };
564
565 struct RegIdxOp {
566 unsigned Index; /// Index into the register class
567 RegKind Kind; /// Bitfield of the kinds it could possibly be
568 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000569 };
570
571 struct ImmOp {
572 const MCExpr *Val;
573 };
574
575 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000576 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000577 const MCExpr *Off;
578 };
579
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000580 struct RegListOp {
581 SmallVector<unsigned, 10> *List;
582 };
583
Jack Carterb4dbc172012-09-05 23:34:03 +0000584 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000585 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000586 struct PhysRegOp PhysReg;
587 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000588 struct ImmOp Imm;
589 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000590 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000591 };
592
593 SMLoc StartLoc, EndLoc;
594
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000595 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000596 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
597 const MCRegisterInfo *RegInfo,
598 SMLoc S, SMLoc E,
599 MipsAsmParser &Parser) {
600 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000601 Op->RegIdx.Index = Index;
602 Op->RegIdx.RegInfo = RegInfo;
603 Op->RegIdx.Kind = RegKind;
604 Op->StartLoc = S;
605 Op->EndLoc = E;
606 return Op;
607 }
608
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000609public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000610 /// Coerce the register to GPR32 and return the real register for the current
611 /// target.
612 unsigned getGPR32Reg() const {
613 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000614 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000615 unsigned ClassID = Mips::GPR32RegClassID;
616 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000617 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000618
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000619 /// Coerce the register to GPR32 and return the real register for the current
620 /// target.
621 unsigned getGPRMM16Reg() const {
622 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
623 unsigned ClassID = Mips::GPR32RegClassID;
624 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
625 }
626
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000627 /// Coerce the register to GPR64 and return the real register for the current
628 /// target.
629 unsigned getGPR64Reg() const {
630 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
631 unsigned ClassID = Mips::GPR64RegClassID;
632 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000633 }
634
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000635private:
636 /// Coerce the register to AFGR64 and return the real register for the current
637 /// target.
638 unsigned getAFGR64Reg() const {
639 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
640 if (RegIdx.Index % 2 != 0)
641 AsmParser.Warning(StartLoc, "Float register should be even.");
642 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
643 .getRegister(RegIdx.Index / 2);
644 }
645
646 /// Coerce the register to FGR64 and return the real register for the current
647 /// target.
648 unsigned getFGR64Reg() const {
649 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
650 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
651 .getRegister(RegIdx.Index);
652 }
653
654 /// Coerce the register to FGR32 and return the real register for the current
655 /// target.
656 unsigned getFGR32Reg() const {
657 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
658 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
659 .getRegister(RegIdx.Index);
660 }
661
662 /// Coerce the register to FGRH32 and return the real register for the current
663 /// target.
664 unsigned getFGRH32Reg() const {
665 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
666 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
667 .getRegister(RegIdx.Index);
668 }
669
670 /// Coerce the register to FCC and return the real register for the current
671 /// target.
672 unsigned getFCCReg() const {
673 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
674 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
675 .getRegister(RegIdx.Index);
676 }
677
678 /// Coerce the register to MSA128 and return the real register for the current
679 /// target.
680 unsigned getMSA128Reg() const {
681 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
682 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
683 // identical
684 unsigned ClassID = Mips::MSA128BRegClassID;
685 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
686 }
687
688 /// Coerce the register to MSACtrl and return the real register for the
689 /// current target.
690 unsigned getMSACtrlReg() const {
691 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
692 unsigned ClassID = Mips::MSACtrlRegClassID;
693 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
694 }
695
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000696 /// Coerce the register to COP0 and return the real register for the
697 /// current target.
698 unsigned getCOP0Reg() const {
699 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
700 unsigned ClassID = Mips::COP0RegClassID;
701 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
702 }
703
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000704 /// Coerce the register to COP2 and return the real register for the
705 /// current target.
706 unsigned getCOP2Reg() const {
707 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
708 unsigned ClassID = Mips::COP2RegClassID;
709 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
710 }
711
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000712 /// Coerce the register to COP3 and return the real register for the
713 /// current target.
714 unsigned getCOP3Reg() const {
715 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
716 unsigned ClassID = Mips::COP3RegClassID;
717 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
718 }
719
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000720 /// Coerce the register to ACC64DSP and return the real register for the
721 /// current target.
722 unsigned getACC64DSPReg() const {
723 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
724 unsigned ClassID = Mips::ACC64DSPRegClassID;
725 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
726 }
727
728 /// Coerce the register to HI32DSP and return the real register for the
729 /// current target.
730 unsigned getHI32DSPReg() const {
731 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
732 unsigned ClassID = Mips::HI32DSPRegClassID;
733 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
734 }
735
736 /// Coerce the register to LO32DSP and return the real register for the
737 /// current target.
738 unsigned getLO32DSPReg() const {
739 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
740 unsigned ClassID = Mips::LO32DSPRegClassID;
741 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
742 }
743
744 /// Coerce the register to CCR and return the real register for the
745 /// current target.
746 unsigned getCCRReg() const {
747 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
748 unsigned ClassID = Mips::CCRRegClassID;
749 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
750 }
751
752 /// Coerce the register to HWRegs and return the real register for the
753 /// current target.
754 unsigned getHWRegsReg() const {
755 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
756 unsigned ClassID = Mips::HWRegsRegClassID;
757 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
758 }
759
760public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000761 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000762 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000763 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000764 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000765 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000766 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000767 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000768 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000769 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000770
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000771 void addRegOperands(MCInst &Inst, unsigned N) const {
772 llvm_unreachable("Use a custom parser instead");
773 }
774
Daniel Sanders21bce302014-04-01 12:35:23 +0000775 /// Render the operand to an MCInst as a GPR32
776 /// Asserts if the wrong number of operands are requested, or the operand
777 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000778 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
779 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000780 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000781 }
782
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000783 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
784 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000785 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000786 }
787
Jozef Kolek1904fa22014-11-24 14:25:53 +0000788 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
789 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000790 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +0000791 }
792
Zoran Jovanovic41688672015-02-10 16:36:20 +0000793 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
794 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000795 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000796 }
797
Daniel Sanders21bce302014-04-01 12:35:23 +0000798 /// Render the operand to an MCInst as a GPR64
799 /// Asserts if the wrong number of operands are requested, or the operand
800 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000801 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
802 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000803 Inst.addOperand(MCOperand::createReg(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000804 }
805
806 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
807 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000808 Inst.addOperand(MCOperand::createReg(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000809 }
810
811 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
812 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000813 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000814 }
815
816 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
817 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000818 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000819 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000820 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000821 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
822 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000823 }
824
825 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
826 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000827 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000828 }
829
830 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
831 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000832 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000833 }
834
835 void addMSA128AsmRegOperands(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(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000838 }
839
840 void addMSACtrlAsmRegOperands(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(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000843 }
844
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000845 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
846 assert(N == 1 && "Invalid number of operands!");
847 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
848 }
849
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000850 void addCOP2AsmRegOperands(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(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000853 }
854
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000855 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
856 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000857 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000858 }
859
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000860 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
861 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000862 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000863 }
864
865 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
866 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000867 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000868 }
869
870 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
871 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000872 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000873 }
874
875 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
876 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000877 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000878 }
879
880 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
881 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000882 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000883 }
884
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000885 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000886 assert(N == 1 && "Invalid number of operands!");
887 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000888 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000889 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000890
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000891 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000892 assert(N == 2 && "Invalid number of operands!");
893
Daniel Sandersa39ef1c2015-08-17 10:11:55 +0000894 Inst.addOperand(MCOperand::createReg(AsmParser.getABI().ArePtrs64bit()
895 ? getMemBase()->getGPR64Reg()
896 : getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000897
898 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000899 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000900 }
901
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000902 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
903 assert(N == 2 && "Invalid number of operands!");
904
Jim Grosbache9119e42015-05-13 18:37:00 +0000905 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000906
907 const MCExpr *Expr = getMemOff();
908 addExpr(Inst, Expr);
909 }
910
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000911 void addRegListOperands(MCInst &Inst, unsigned N) const {
912 assert(N == 1 && "Invalid number of operands!");
913
914 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000915 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000916 }
917
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000918 void addRegPairOperands(MCInst &Inst, unsigned N) const {
919 assert(N == 2 && "Invalid number of operands!");
920 unsigned RegNo = getRegPair();
Jim Grosbache9119e42015-05-13 18:37:00 +0000921 Inst.addOperand(MCOperand::createReg(RegNo++));
922 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000923 }
924
Zoran Jovanovic41688672015-02-10 16:36:20 +0000925 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
926 assert(N == 2 && "Invalid number of operands!");
927 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000928 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000929 }
930
Craig Topper56c590a2014-04-29 07:58:02 +0000931 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000932 // As a special case until we sort out the definition of div/divu, pretend
933 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
934 if (isGPRAsmReg() && RegIdx.Index == 0)
935 return true;
936
937 return Kind == k_PhysRegister;
938 }
939 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000940 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000941 bool isConstantImm() const {
942 return isImm() && dyn_cast<MCConstantExpr>(getImm());
943 }
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +0000944 template <unsigned Bits> bool isUImm() const {
945 return isImm() && isConstantImm() && isUInt<Bits>(getConstantImm());
946 }
Craig Topper56c590a2014-04-29 07:58:02 +0000947 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000948 // Note: It's not possible to pretend that other operand kinds are tokens.
949 // The matcher emitter checks tokens first.
950 return Kind == k_Token;
951 }
Craig Topper56c590a2014-04-29 07:58:02 +0000952 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000953 bool isConstantMemOff() const {
954 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
955 }
956 template <unsigned Bits> bool isMemWithSimmOffset() const {
Zoran Jovanovica6593ff2015-08-18 12:53:08 +0000957 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
958 && getMemBase()->isGPRAsmReg();
959 }
Zoran Jovanovic6e6a2c92015-09-16 09:14:35 +0000960 template <unsigned Bits> bool isMemWithSimmOffsetGPR() const {
961 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff()) &&
962 getMemBase()->isGPRAsmReg();
963 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000964 bool isMemWithGRPMM16Base() const {
965 return isMem() && getMemBase()->isMM16AsmReg();
966 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000967 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
968 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
969 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
970 }
Jozef Kolek12c69822014-12-23 16:16:33 +0000971 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
972 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
973 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
974 && (getMemBase()->getGPR32Reg() == Mips::SP);
975 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000976 bool isRegList16() const {
977 if (!isRegList())
978 return false;
979
980 int Size = RegList.List->size();
981 if (Size < 2 || Size > 5 || *RegList.List->begin() != Mips::S0 ||
982 RegList.List->back() != Mips::RA)
983 return false;
984
985 int PrevReg = *RegList.List->begin();
986 for (int i = 1; i < Size - 1; i++) {
987 int Reg = (*(RegList.List))[i];
988 if ( Reg != PrevReg + 1)
989 return false;
990 PrevReg = Reg;
991 }
992
993 return true;
994 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000995 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000996 bool isLSAImm() const {
997 if (!isConstantImm())
998 return false;
999 int64_t Val = getConstantImm();
1000 return 1 <= Val && Val <= 4;
1001 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001002 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001003 bool isMovePRegPair() const {
1004 if (Kind != k_RegList || RegList.List->size() != 2)
1005 return false;
1006
1007 unsigned R0 = RegList.List->front();
1008 unsigned R1 = RegList.List->back();
1009
1010 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
1011 (R0 == Mips::A1 && R1 == Mips::A3) ||
1012 (R0 == Mips::A2 && R1 == Mips::A3) ||
1013 (R0 == Mips::A0 && R1 == Mips::S5) ||
1014 (R0 == Mips::A0 && R1 == Mips::S6) ||
1015 (R0 == Mips::A0 && R1 == Mips::A1) ||
1016 (R0 == Mips::A0 && R1 == Mips::A2) ||
1017 (R0 == Mips::A0 && R1 == Mips::A3))
1018 return true;
1019
1020 return false;
1021 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001022
1023 StringRef getToken() const {
1024 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001025 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001026 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001027 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001028
Craig Topper56c590a2014-04-29 07:58:02 +00001029 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001030 // As a special case until we sort out the definition of div/divu, pretend
1031 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
1032 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1033 RegIdx.Kind & RegKind_GPR)
1034 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001035
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001036 assert(Kind == k_PhysRegister && "Invalid access!");
1037 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +00001038 }
1039
Jack Carterb4dbc172012-09-05 23:34:03 +00001040 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001041 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001042 return Imm.Val;
1043 }
1044
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001045 int64_t getConstantImm() const {
1046 const MCExpr *Val = getImm();
1047 return static_cast<const MCConstantExpr *>(Val)->getValue();
1048 }
1049
1050 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001051 assert((Kind == k_Memory) && "Invalid access!");
1052 return Mem.Base;
1053 }
1054
1055 const MCExpr *getMemOff() const {
1056 assert((Kind == k_Memory) && "Invalid access!");
1057 return Mem.Off;
1058 }
1059
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001060 int64_t getConstantMemOff() const {
1061 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1062 }
1063
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001064 const SmallVectorImpl<unsigned> &getRegList() const {
1065 assert((Kind == k_RegList) && "Invalid access!");
1066 return *(RegList.List);
1067 }
1068
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001069 unsigned getRegPair() const {
1070 assert((Kind == k_RegPair) && "Invalid access!");
1071 return RegIdx.Index;
1072 }
1073
David Blaikie960ea3f2014-06-08 16:18:35 +00001074 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1075 MipsAsmParser &Parser) {
1076 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001077 Op->Tok.Data = Str.data();
1078 Op->Tok.Length = Str.size();
1079 Op->StartLoc = S;
1080 Op->EndLoc = S;
1081 return Op;
1082 }
1083
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001084 /// Create a numeric register (e.g. $1). The exact register remains
1085 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001086 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001087 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001088 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001089 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001090 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001091 }
1092
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001093 /// Create a register that is definitely a GPR.
1094 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001095 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001096 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001097 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001098 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001099 }
1100
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001101 /// Create a register that is definitely a FGR.
1102 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001103 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001104 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001105 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001106 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1107 }
1108
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001109 /// Create a register that is definitely a HWReg.
1110 /// This is typically only used for named registers such as $hwr_cpunum.
1111 static std::unique_ptr<MipsOperand>
1112 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1113 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1114 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1115 }
1116
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001117 /// Create a register that is definitely an FCC.
1118 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001119 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001120 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001121 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001122 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1123 }
1124
1125 /// Create a register that is definitely an ACC.
1126 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001127 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001128 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001129 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001130 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1131 }
1132
1133 /// Create a register that is definitely an MSA128.
1134 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001135 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001136 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001137 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001138 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1139 }
1140
1141 /// Create a register that is definitely an MSACtrl.
1142 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001143 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001144 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001145 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001146 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1147 }
1148
David Blaikie960ea3f2014-06-08 16:18:35 +00001149 static std::unique_ptr<MipsOperand>
1150 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1151 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001152 Op->Imm.Val = Val;
1153 Op->StartLoc = S;
1154 Op->EndLoc = E;
1155 return Op;
1156 }
1157
David Blaikie960ea3f2014-06-08 16:18:35 +00001158 static std::unique_ptr<MipsOperand>
1159 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1160 SMLoc E, MipsAsmParser &Parser) {
1161 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1162 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001163 Op->Mem.Off = Off;
1164 Op->StartLoc = S;
1165 Op->EndLoc = E;
1166 return Op;
1167 }
1168
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001169 static std::unique_ptr<MipsOperand>
1170 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1171 MipsAsmParser &Parser) {
1172 assert (Regs.size() > 0 && "Empty list not allowed");
1173
1174 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001175 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001176 Op->StartLoc = StartLoc;
1177 Op->EndLoc = EndLoc;
1178 return Op;
1179 }
1180
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001181 static std::unique_ptr<MipsOperand>
1182 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1183 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1184 Op->RegIdx.Index = RegNo;
1185 Op->StartLoc = S;
1186 Op->EndLoc = E;
1187 return Op;
1188 }
1189
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001190 bool isGPRAsmReg() const {
1191 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001192 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001193 bool isMM16AsmReg() const {
1194 if (!(isRegIdx() && RegIdx.Kind))
1195 return false;
1196 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1197 || RegIdx.Index == 16 || RegIdx.Index == 17);
1198 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001199 bool isMM16AsmRegZero() const {
1200 if (!(isRegIdx() && RegIdx.Kind))
1201 return false;
1202 return (RegIdx.Index == 0 ||
1203 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1204 RegIdx.Index == 17);
1205 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001206 bool isMM16AsmRegMoveP() const {
1207 if (!(isRegIdx() && RegIdx.Kind))
1208 return false;
1209 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1210 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1211 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001212 bool isFGRAsmReg() const {
1213 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1214 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001215 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001216 bool isHWRegsAsmReg() const {
1217 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001218 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001219 bool isCCRAsmReg() const {
1220 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001221 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001222 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001223 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1224 return false;
1225 if (!AsmParser.hasEightFccRegisters())
1226 return RegIdx.Index == 0;
1227 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001228 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001229 bool isACCAsmReg() const {
1230 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001231 }
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001232 bool isCOP0AsmReg() const {
1233 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1234 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001235 bool isCOP2AsmReg() const {
1236 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001237 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001238 bool isCOP3AsmReg() const {
1239 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1240 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001241 bool isMSA128AsmReg() const {
1242 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001243 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001244 bool isMSACtrlAsmReg() const {
1245 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001246 }
1247
Jack Carterb4dbc172012-09-05 23:34:03 +00001248 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001249 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001250 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001251 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001252
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001253 virtual ~MipsOperand() {
1254 switch (Kind) {
1255 case k_Immediate:
1256 break;
1257 case k_Memory:
1258 delete Mem.Base;
1259 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001260 case k_RegList:
1261 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001262 case k_PhysRegister:
1263 case k_RegisterIndex:
1264 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001265 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001266 break;
1267 }
1268 }
1269
Craig Topper56c590a2014-04-29 07:58:02 +00001270 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001271 switch (Kind) {
1272 case k_Immediate:
1273 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001274 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001275 OS << ">";
1276 break;
1277 case k_Memory:
1278 OS << "Mem<";
1279 Mem.Base->print(OS);
1280 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001281 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001282 OS << ">";
1283 break;
1284 case k_PhysRegister:
1285 OS << "PhysReg<" << PhysReg.Num << ">";
1286 break;
1287 case k_RegisterIndex:
1288 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1289 break;
1290 case k_Token:
1291 OS << Tok.Data;
1292 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001293 case k_RegList:
1294 OS << "RegList< ";
1295 for (auto Reg : (*RegList.List))
1296 OS << Reg << " ";
1297 OS << ">";
1298 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001299 case k_RegPair:
1300 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1301 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001302 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001303 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001304}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001305} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001306
Jack Carter9e65aa32013-03-22 00:05:30 +00001307namespace llvm {
1308extern const MCInstrDesc MipsInsts[];
1309}
1310static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1311 return MipsInsts[Opcode];
1312}
1313
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001314static bool hasShortDelaySlot(unsigned Opcode) {
1315 switch (Opcode) {
1316 case Mips::JALS_MM:
1317 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001318 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001319 case Mips::BGEZALS_MM:
1320 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001321 return true;
1322 default:
1323 return false;
1324 }
1325}
1326
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001327static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
1328 if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
1329 return &SRExpr->getSymbol();
1330 }
1331
1332 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
1333 const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
1334 const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
1335
1336 if (LHSSym)
1337 return LHSSym;
1338
1339 if (RHSSym)
1340 return RHSSym;
1341
1342 return nullptr;
1343 }
1344
1345 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1346 return getSingleMCSymbol(UExpr->getSubExpr());
1347
1348 return nullptr;
1349}
1350
1351static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
1352 if (isa<MCSymbolRefExpr>(Expr))
1353 return 1;
1354
1355 if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
1356 return countMCSymbolRefExpr(BExpr->getLHS()) +
1357 countMCSymbolRefExpr(BExpr->getRHS());
1358
1359 if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
1360 return countMCSymbolRefExpr(UExpr->getSubExpr());
1361
1362 return 0;
1363}
1364
Jack Carter9e65aa32013-03-22 00:05:30 +00001365bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001366 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001367 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001368 bool ExpandedJalSym = false;
Daniel Sandersa771fef2014-03-24 14:05:39 +00001369
Jack Carter9e65aa32013-03-22 00:05:30 +00001370 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001371
1372 if (MCID.isBranch() || MCID.isCall()) {
1373 const unsigned Opcode = Inst.getOpcode();
1374 MCOperand Offset;
1375
1376 switch (Opcode) {
1377 default:
1378 break;
Kai Nackee0245392015-01-27 19:11:28 +00001379 case Mips::BBIT0:
1380 case Mips::BBIT032:
1381 case Mips::BBIT1:
1382 case Mips::BBIT132:
1383 assert(hasCnMips() && "instruction only valid for octeon cpus");
1384 // Fall through
1385
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001386 case Mips::BEQ:
1387 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001388 case Mips::BEQ_MM:
1389 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001390 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001391 Offset = Inst.getOperand(2);
1392 if (!Offset.isImm())
1393 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001394 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001395 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001396 if (OffsetToAlignment(Offset.getImm(),
1397 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001398 return Error(IDLoc, "branch to misaligned address");
1399 break;
1400 case Mips::BGEZ:
1401 case Mips::BGTZ:
1402 case Mips::BLEZ:
1403 case Mips::BLTZ:
1404 case Mips::BGEZAL:
1405 case Mips::BLTZAL:
1406 case Mips::BC1F:
1407 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001408 case Mips::BGEZ_MM:
1409 case Mips::BGTZ_MM:
1410 case Mips::BLEZ_MM:
1411 case Mips::BLTZ_MM:
1412 case Mips::BGEZAL_MM:
1413 case Mips::BLTZAL_MM:
1414 case Mips::BC1F_MM:
1415 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001416 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001417 Offset = Inst.getOperand(1);
1418 if (!Offset.isImm())
1419 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001420 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001421 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001422 if (OffsetToAlignment(Offset.getImm(),
1423 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001424 return Error(IDLoc, "branch to misaligned address");
1425 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001426 case Mips::BEQZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001427 case Mips::BEQZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001428 case Mips::BNEZ16_MM:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001429 case Mips::BNEZC16_MMR6:
Jozef Kolek9761e962015-01-12 12:03:34 +00001430 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1431 Offset = Inst.getOperand(1);
1432 if (!Offset.isImm())
1433 break; // We'll deal with this situation later on when applying fixups.
1434 if (!isIntN(8, Offset.getImm()))
1435 return Error(IDLoc, "branch target out of range");
1436 if (OffsetToAlignment(Offset.getImm(), 2LL))
1437 return Error(IDLoc, "branch to misaligned address");
1438 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001439 }
1440 }
1441
Daniel Sandersa84989a2014-06-16 13:25:35 +00001442 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1443 // We still accept it but it is a normal nop.
1444 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1445 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1446 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1447 "nop instruction");
1448 }
1449
Kai Nackee0245392015-01-27 19:11:28 +00001450 if (hasCnMips()) {
1451 const unsigned Opcode = Inst.getOpcode();
1452 MCOperand Opnd;
1453 int Imm;
1454
1455 switch (Opcode) {
1456 default:
1457 break;
1458
1459 case Mips::BBIT0:
1460 case Mips::BBIT032:
1461 case Mips::BBIT1:
1462 case Mips::BBIT132:
1463 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1464 // The offset is handled above
1465 Opnd = Inst.getOperand(1);
1466 if (!Opnd.isImm())
1467 return Error(IDLoc, "expected immediate operand kind");
1468 Imm = Opnd.getImm();
1469 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1470 Opcode == Mips::BBIT1 ? 63 : 31))
1471 return Error(IDLoc, "immediate operand value out of range");
1472 if (Imm > 31) {
1473 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1474 : Mips::BBIT132);
1475 Inst.getOperand(1).setImm(Imm - 32);
1476 }
1477 break;
1478
1479 case Mips::CINS:
1480 case Mips::CINS32:
1481 case Mips::EXTS:
1482 case Mips::EXTS32:
1483 assert(MCID.getNumOperands() == 4 && "unexpected number of operands");
1484 // Check length
1485 Opnd = Inst.getOperand(3);
1486 if (!Opnd.isImm())
1487 return Error(IDLoc, "expected immediate operand kind");
1488 Imm = Opnd.getImm();
1489 if (Imm < 0 || Imm > 31)
1490 return Error(IDLoc, "immediate operand value out of range");
1491 // Check position
1492 Opnd = Inst.getOperand(2);
1493 if (!Opnd.isImm())
1494 return Error(IDLoc, "expected immediate operand kind");
1495 Imm = Opnd.getImm();
1496 if (Imm < 0 || Imm > (Opcode == Mips::CINS ||
1497 Opcode == Mips::EXTS ? 63 : 31))
1498 return Error(IDLoc, "immediate operand value out of range");
1499 if (Imm > 31) {
1500 Inst.setOpcode(Opcode == Mips::CINS ? Mips::CINS32 : Mips::EXTS32);
1501 Inst.getOperand(2).setImm(Imm - 32);
1502 }
1503 break;
1504
1505 case Mips::SEQi:
1506 case Mips::SNEi:
1507 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1508 Opnd = Inst.getOperand(2);
1509 if (!Opnd.isImm())
1510 return Error(IDLoc, "expected immediate operand kind");
1511 Imm = Opnd.getImm();
1512 if (!isInt<10>(Imm))
1513 return Error(IDLoc, "immediate operand value out of range");
1514 break;
1515 }
1516 }
1517
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001518 // This expansion is not in a function called by expandInstruction() because
1519 // the pseudo-instruction doesn't have a distinct opcode.
1520 if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
1521 inPicMode()) {
1522 warnIfNoMacro(IDLoc);
1523
1524 const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
1525
1526 // We can do this expansion if there's only 1 symbol in the argument
1527 // expression.
1528 if (countMCSymbolRefExpr(JalExpr) > 1)
1529 return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
1530
1531 // FIXME: This is checking the expression can be handled by the later stages
1532 // of the assembler. We ought to leave it to those later stages but
1533 // we can't do that until we stop evaluateRelocExpr() rewriting the
1534 // expressions into non-equivalent forms.
1535 const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
1536
1537 // FIXME: Add support for label+offset operands (currently causes an error).
1538 // FIXME: Add support for forward-declared local symbols.
1539 // FIXME: Add expansion for when the LargeGOT option is enabled.
1540 if (JalSym->isInSection() || JalSym->isTemporary()) {
1541 if (isABI_O32()) {
1542 // If it's a local symbol and the O32 ABI is being used, we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001543 // lw $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001544 // R_(MICRO)MIPS_GOT16 label
1545 // addiu $25, $25, 0
1546 // R_(MICRO)MIPS_LO16 label
1547 // jalr $25
1548 const MCExpr *Got16RelocExpr = evaluateRelocExpr(JalExpr, "got");
1549 const MCExpr *Lo16RelocExpr = evaluateRelocExpr(JalExpr, "lo");
1550
1551 MCInst LwInst;
1552 LwInst.setOpcode(Mips::LW);
1553 LwInst.addOperand(MCOperand::createReg(Mips::T9));
1554 LwInst.addOperand(MCOperand::createReg(Mips::GP));
1555 LwInst.addOperand(MCOperand::createExpr(Got16RelocExpr));
1556 Instructions.push_back(LwInst);
1557
1558 MCInst AddiuInst;
1559 AddiuInst.setOpcode(Mips::ADDiu);
1560 AddiuInst.addOperand(MCOperand::createReg(Mips::T9));
1561 AddiuInst.addOperand(MCOperand::createReg(Mips::T9));
1562 AddiuInst.addOperand(MCOperand::createExpr(Lo16RelocExpr));
1563 Instructions.push_back(AddiuInst);
1564 } else if (isABI_N32() || isABI_N64()) {
1565 // If it's a local symbol and the N32/N64 ABIs are being used,
1566 // we expand to:
NAKAMURA Takumi0d725392015-09-07 00:26:54 +00001567 // lw/ld $25, 0($gp)
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001568 // R_(MICRO)MIPS_GOT_DISP label
1569 // jalr $25
1570 const MCExpr *GotDispRelocExpr = evaluateRelocExpr(JalExpr, "got_disp");
1571
1572 MCInst LoadInst;
1573 LoadInst.setOpcode(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW);
1574 LoadInst.addOperand(MCOperand::createReg(Mips::T9));
1575 LoadInst.addOperand(MCOperand::createReg(Mips::GP));
1576 LoadInst.addOperand(MCOperand::createExpr(GotDispRelocExpr));
1577 Instructions.push_back(LoadInst);
1578 }
1579 } else {
1580 // If it's an external/weak symbol, we expand to:
1581 // lw/ld $25, 0($gp)
1582 // R_(MICRO)MIPS_CALL16 label
1583 // jalr $25
1584 const MCExpr *Call16RelocExpr = evaluateRelocExpr(JalExpr, "call16");
1585
1586 MCInst LoadInst;
1587 LoadInst.setOpcode(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW);
1588 LoadInst.addOperand(MCOperand::createReg(Mips::T9));
1589 LoadInst.addOperand(MCOperand::createReg(Mips::GP));
1590 LoadInst.addOperand(MCOperand::createExpr(Call16RelocExpr));
1591 Instructions.push_back(LoadInst);
1592 }
1593
1594 MCInst JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001595 if (IsCpRestoreSet && inMicroMipsMode())
1596 JalrInst.setOpcode(Mips::JALRS_MM);
1597 else
1598 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001599 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
1600 JalrInst.addOperand(MCOperand::createReg(Mips::T9));
1601
1602 // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
1603 // This relocation is supposed to be an optimization hint for the linker
1604 // and is not necessary for correctness.
1605
1606 Inst = JalrInst;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001607 ExpandedJalSym = true;
Daniel Sanders63f4a5d2015-08-18 16:18:09 +00001608 }
1609
Jack Carter9e65aa32013-03-22 00:05:30 +00001610 if (MCID.mayLoad() || MCID.mayStore()) {
1611 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001612 // reference or immediate we may have to expand instructions.
1613 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001614 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001615 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1616 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001617 MCOperand &Op = Inst.getOperand(i);
1618 if (Op.isImm()) {
1619 int MemOffset = Op.getImm();
1620 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001621 // Offset can't exceed 16bit value.
1622 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001623 return false;
1624 }
1625 } else if (Op.isExpr()) {
1626 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001627 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001628 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001629 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001630 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001631 // Expand symbol.
1632 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001633 return false;
1634 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001635 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001636 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001637 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001638 }
1639 }
1640 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001641 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001642 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001643
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001644 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001645 if (MCID.mayLoad()) {
1646 // Try to create 16-bit GP relative load instruction.
1647 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1648 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1649 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1650 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1651 MCOperand &Op = Inst.getOperand(i);
1652 if (Op.isImm()) {
1653 int MemOffset = Op.getImm();
1654 MCOperand &DstReg = Inst.getOperand(0);
1655 MCOperand &BaseReg = Inst.getOperand(1);
1656 if (isIntN(9, MemOffset) && (MemOffset % 4 == 0) &&
1657 getContext().getRegisterInfo()->getRegClass(
1658 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
Zoran Jovanovic68be5f22015-09-08 08:25:34 +00001659 (BaseReg.getReg() == Mips::GP ||
1660 BaseReg.getReg() == Mips::GP_64)) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001661 MCInst TmpInst;
1662 TmpInst.setLoc(IDLoc);
1663 TmpInst.setOpcode(Mips::LWGP_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00001664 TmpInst.addOperand(MCOperand::createReg(DstReg.getReg()));
1665 TmpInst.addOperand(MCOperand::createReg(Mips::GP));
1666 TmpInst.addOperand(MCOperand::createImm(MemOffset));
Jozef Koleke10a02e2015-01-28 17:27:26 +00001667 Instructions.push_back(TmpInst);
1668 return false;
1669 }
1670 }
1671 }
1672 } // for
1673 } // if load
1674
1675 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1676
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001677 MCOperand Opnd;
1678 int Imm;
1679
1680 switch (Inst.getOpcode()) {
1681 default:
1682 break;
1683 case Mips::ADDIUS5_MM:
1684 Opnd = Inst.getOperand(2);
1685 if (!Opnd.isImm())
1686 return Error(IDLoc, "expected immediate operand kind");
1687 Imm = Opnd.getImm();
1688 if (Imm < -8 || Imm > 7)
1689 return Error(IDLoc, "immediate operand value out of range");
1690 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001691 case Mips::ADDIUSP_MM:
1692 Opnd = Inst.getOperand(0);
1693 if (!Opnd.isImm())
1694 return Error(IDLoc, "expected immediate operand kind");
1695 Imm = Opnd.getImm();
1696 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1697 Imm % 4 != 0)
1698 return Error(IDLoc, "immediate operand value out of range");
1699 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001700 case Mips::SLL16_MM:
1701 case Mips::SRL16_MM:
1702 Opnd = Inst.getOperand(2);
1703 if (!Opnd.isImm())
1704 return Error(IDLoc, "expected immediate operand kind");
1705 Imm = Opnd.getImm();
1706 if (Imm < 1 || Imm > 8)
1707 return Error(IDLoc, "immediate operand value out of range");
1708 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001709 case Mips::LI16_MM:
1710 Opnd = Inst.getOperand(1);
1711 if (!Opnd.isImm())
1712 return Error(IDLoc, "expected immediate operand kind");
1713 Imm = Opnd.getImm();
1714 if (Imm < -1 || Imm > 126)
1715 return Error(IDLoc, "immediate operand value out of range");
1716 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001717 case Mips::ADDIUR2_MM:
1718 Opnd = Inst.getOperand(2);
1719 if (!Opnd.isImm())
1720 return Error(IDLoc, "expected immediate operand kind");
1721 Imm = Opnd.getImm();
1722 if (!(Imm == 1 || Imm == -1 ||
1723 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1724 return Error(IDLoc, "immediate operand value out of range");
1725 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001726 case Mips::ADDIUR1SP_MM:
1727 Opnd = Inst.getOperand(1);
1728 if (!Opnd.isImm())
1729 return Error(IDLoc, "expected immediate operand kind");
1730 Imm = Opnd.getImm();
1731 if (OffsetToAlignment(Imm, 4LL))
1732 return Error(IDLoc, "misaligned immediate operand value");
1733 if (Imm < 0 || Imm > 255)
1734 return Error(IDLoc, "immediate operand value out of range");
1735 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001736 case Mips::ANDI16_MM:
1737 Opnd = Inst.getOperand(2);
1738 if (!Opnd.isImm())
1739 return Error(IDLoc, "expected immediate operand kind");
1740 Imm = Opnd.getImm();
1741 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1742 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1743 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1744 return Error(IDLoc, "immediate operand value out of range");
1745 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001746 case Mips::LBU16_MM:
1747 Opnd = Inst.getOperand(2);
1748 if (!Opnd.isImm())
1749 return Error(IDLoc, "expected immediate operand kind");
1750 Imm = Opnd.getImm();
1751 if (Imm < -1 || Imm > 14)
1752 return Error(IDLoc, "immediate operand value out of range");
1753 break;
Zoran Jovanovic7ba636c2015-09-17 10:14:09 +00001754 case Mips::TEQ_MM:
1755 case Mips::TGE_MM:
1756 case Mips::TGEU_MM:
1757 case Mips::TLT_MM:
1758 case Mips::TLTU_MM:
1759 case Mips::TNE_MM:
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001760 case Mips::SB16_MM:
1761 Opnd = Inst.getOperand(2);
1762 if (!Opnd.isImm())
1763 return Error(IDLoc, "expected immediate operand kind");
1764 Imm = Opnd.getImm();
1765 if (Imm < 0 || Imm > 15)
1766 return Error(IDLoc, "immediate operand value out of range");
1767 break;
1768 case Mips::LHU16_MM:
1769 case Mips::SH16_MM:
1770 Opnd = Inst.getOperand(2);
1771 if (!Opnd.isImm())
1772 return Error(IDLoc, "expected immediate operand kind");
1773 Imm = Opnd.getImm();
1774 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1775 return Error(IDLoc, "immediate operand value out of range");
1776 break;
1777 case Mips::LW16_MM:
1778 case Mips::SW16_MM:
1779 Opnd = Inst.getOperand(2);
1780 if (!Opnd.isImm())
1781 return Error(IDLoc, "expected immediate operand kind");
1782 Imm = Opnd.getImm();
1783 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1784 return Error(IDLoc, "immediate operand value out of range");
1785 break;
Zoran Jovanovic6e6a2c92015-09-16 09:14:35 +00001786 case Mips::PREFX_MM:
Jozef Kolekab6d1cc2014-12-23 19:55:34 +00001787 case Mips::CACHE:
1788 case Mips::PREF:
1789 Opnd = Inst.getOperand(2);
1790 if (!Opnd.isImm())
1791 return Error(IDLoc, "expected immediate operand kind");
1792 Imm = Opnd.getImm();
1793 if (!isUInt<5>(Imm))
1794 return Error(IDLoc, "immediate operand value out of range");
1795 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001796 case Mips::ADDIUPC_MM:
1797 MCOperand Opnd = Inst.getOperand(1);
1798 if (!Opnd.isImm())
1799 return Error(IDLoc, "expected immediate operand kind");
1800 int Imm = Opnd.getImm();
1801 if ((Imm % 4 != 0) || !isIntN(25, Imm))
1802 return Error(IDLoc, "immediate operand value out of range");
1803 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001804 }
1805 }
1806
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001807 if (needsExpansion(Inst)) {
1808 if (expandInstruction(Inst, IDLoc, Instructions))
1809 return true;
1810 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001811 Instructions.push_back(Inst);
1812
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001813 // If this instruction has a delay slot and .set reorder is active,
1814 // emit a NOP after it.
1815 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
1816 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1817
Daniel Sanderse2982ad2015-09-17 16:08:39 +00001818 if ((Inst.getOpcode() == Mips::JalOneReg ||
1819 Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
1820 isPicAndNotNxxAbi()) {
1821 if (IsCpRestoreSet) {
1822 // We need a NOP between the JALR and the LW:
1823 // If .set reorder has been used, we've already emitted a NOP.
1824 // If .set noreorder has been used, we need to emit a NOP at this point.
1825 if (!AssemblerOptions.back()->isReorder())
1826 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1827
1828 // Load the $gp from the stack.
1829 SmallVector<MCInst, 3> LoadInsts;
1830 createCpRestoreMemOp(true /*IsLoad*/, CpRestoreOffset /*StackOffset*/,
1831 IDLoc, LoadInsts);
1832
1833 for (const MCInst &Inst : LoadInsts)
1834 Instructions.push_back(Inst);
1835
1836 } else
1837 Warning(IDLoc, "no .cprestore used in PIC mode");
1838 }
1839
Jack Carter9e65aa32013-03-22 00:05:30 +00001840 return false;
1841}
1842
Jack Carter30a59822012-10-04 04:03:53 +00001843bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1844
Jack Carterd0bd6422013-04-18 00:41:53 +00001845 switch (Inst.getOpcode()) {
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001846 case Mips::LoadImm32:
1847 case Mips::LoadImm64:
1848 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001849 case Mips::LoadAddrImm64:
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001850 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001851 case Mips::LoadAddrReg64:
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001852 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001853 case Mips::B_MMR6_Pseudo:
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001854 case Mips::LWM_MM:
1855 case Mips::SWM_MM:
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001856 case Mips::JalOneReg:
1857 case Mips::JalTwoReg:
Toma Tabacue1e460d2015-06-11 10:36:10 +00001858 case Mips::BneImm:
1859 case Mips::BeqImm:
Toma Tabacu1a108322015-06-17 13:20:24 +00001860 case Mips::BLT:
1861 case Mips::BLE:
1862 case Mips::BGE:
1863 case Mips::BGT:
1864 case Mips::BLTU:
1865 case Mips::BLEU:
1866 case Mips::BGEU:
1867 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00001868 case Mips::BLTL:
1869 case Mips::BLEL:
1870 case Mips::BGEL:
1871 case Mips::BGTL:
1872 case Mips::BLTUL:
1873 case Mips::BLEUL:
1874 case Mips::BGEUL:
1875 case Mips::BGTUL:
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00001876 case Mips::SDivMacro:
1877 case Mips::UDivMacro:
1878 case Mips::DSDivMacro:
1879 case Mips::DUDivMacro:
Toma Tabacud88d79c2015-06-23 14:39:42 +00001880 case Mips::Ulhu:
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00001881 case Mips::Ulw:
Jack Carterd0bd6422013-04-18 00:41:53 +00001882 return true;
1883 default:
1884 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001885 }
1886}
Jack Carter92995f12012-10-06 00:53:28 +00001887
Matheus Almeida3813d572014-06-19 14:39:14 +00001888bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001889 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001890 switch (Inst.getOpcode()) {
Craig Topperd3c02f12015-01-05 10:15:49 +00001891 default: llvm_unreachable("unimplemented expansion");
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001892 case Mips::LoadImm32:
Toma Tabacu00e98672015-05-01 12:19:27 +00001893 return expandLoadImm(Inst, true, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001894 case Mips::LoadImm64:
Toma Tabacu00e98672015-05-01 12:19:27 +00001895 return expandLoadImm(Inst, false, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001896 case Mips::LoadAddrImm32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001897 case Mips::LoadAddrImm64:
1898 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1899 assert((Inst.getOperand(1).isImm() || Inst.getOperand(1).isExpr()) &&
1900 "expected immediate operand kind");
1901
1902 return expandLoadAddress(
1903 Inst.getOperand(0).getReg(), Mips::NoRegister, Inst.getOperand(1),
1904 Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001905 case Mips::LoadAddrReg32:
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001906 case Mips::LoadAddrReg64:
1907 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1908 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1909 assert((Inst.getOperand(2).isImm() || Inst.getOperand(2).isExpr()) &&
1910 "expected immediate operand kind");
1911
1912 return expandLoadAddress(
1913 Inst.getOperand(0).getReg(), Inst.getOperand(1).getReg(), Inst.getOperand(2),
1914 Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc, Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001915 case Mips::B_MM_Pseudo:
Zoran Jovanovicada70912015-09-07 11:56:37 +00001916 case Mips::B_MMR6_Pseudo:
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001917 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001918 case Mips::SWM_MM:
1919 case Mips::LWM_MM:
1920 return expandLoadStoreMultiple(Inst, IDLoc, Instructions);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001921 case Mips::JalOneReg:
1922 case Mips::JalTwoReg:
1923 return expandJalWithRegs(Inst, IDLoc, Instructions);
Toma Tabacue1e460d2015-06-11 10:36:10 +00001924 case Mips::BneImm:
1925 case Mips::BeqImm:
1926 return expandBranchImm(Inst, IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00001927 case Mips::BLT:
1928 case Mips::BLE:
1929 case Mips::BGE:
1930 case Mips::BGT:
1931 case Mips::BLTU:
1932 case Mips::BLEU:
1933 case Mips::BGEU:
1934 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00001935 case Mips::BLTL:
1936 case Mips::BLEL:
1937 case Mips::BGEL:
1938 case Mips::BGTL:
1939 case Mips::BLTUL:
1940 case Mips::BLEUL:
1941 case Mips::BGEUL:
1942 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00001943 return expandCondBranches(Inst, IDLoc, Instructions);
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00001944 case Mips::SDivMacro:
1945 return expandDiv(Inst, IDLoc, Instructions, false, true);
1946 case Mips::DSDivMacro:
1947 return expandDiv(Inst, IDLoc, Instructions, true, true);
1948 case Mips::UDivMacro:
1949 return expandDiv(Inst, IDLoc, Instructions, false, false);
1950 case Mips::DUDivMacro:
1951 return expandDiv(Inst, IDLoc, Instructions, true, false);
Toma Tabacud88d79c2015-06-23 14:39:42 +00001952 case Mips::Ulhu:
1953 return expandUlhu(Inst, IDLoc, Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00001954 case Mips::Ulw:
1955 return expandUlw(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001956 }
Jack Carter30a59822012-10-04 04:03:53 +00001957}
Jack Carter92995f12012-10-06 00:53:28 +00001958
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001959namespace {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001960void emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1, SMLoc IDLoc,
Daniel Sanders03f9c012015-07-14 12:24:22 +00001961 SmallVectorImpl<MCInst> &Instructions) {
1962 MCInst tmpInst;
1963 tmpInst.setOpcode(Opcode);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001964 tmpInst.addOperand(MCOperand::createReg(Reg0));
1965 tmpInst.addOperand(Op1);
Daniel Sanders03f9c012015-07-14 12:24:22 +00001966 tmpInst.setLoc(IDLoc);
1967 Instructions.push_back(tmpInst);
1968}
1969
Daniel Sandersf1ae3672015-08-18 09:55:57 +00001970void emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm, SMLoc IDLoc,
Daniel Sanders03f9c012015-07-14 12:24:22 +00001971 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001972 emitRX(Opcode, Reg0, MCOperand::createImm(Imm), IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00001973}
1974
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00001975void emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, SMLoc IDLoc,
1976 SmallVectorImpl<MCInst> &Instructions) {
1977 emitRX(Opcode, Reg0, MCOperand::createReg(Reg1), IDLoc, Instructions);
1978}
1979
1980void emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2, SMLoc IDLoc,
1981 SmallVectorImpl<MCInst> &Instructions) {
1982 MCInst tmpInst;
1983 tmpInst.setOpcode(Opcode);
1984 tmpInst.addOperand(MCOperand::createImm(Imm1));
1985 tmpInst.addOperand(MCOperand::createImm(Imm2));
1986 tmpInst.setLoc(IDLoc);
1987 Instructions.push_back(tmpInst);
1988}
1989
1990void emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc,
1991 SmallVectorImpl<MCInst> &Instructions) {
1992 MCInst tmpInst;
1993 tmpInst.setOpcode(Opcode);
1994 tmpInst.addOperand(MCOperand::createReg(Reg0));
1995 tmpInst.setLoc(IDLoc);
1996 Instructions.push_back(tmpInst);
1997}
1998
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00001999void emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1, MCOperand Op2,
Daniel Sanders03f9c012015-07-14 12:24:22 +00002000 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
2001 MCInst tmpInst;
2002 tmpInst.setOpcode(Opcode);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002003 tmpInst.addOperand(MCOperand::createReg(Reg0));
2004 tmpInst.addOperand(MCOperand::createReg(Reg1));
2005 tmpInst.addOperand(Op2);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002006 tmpInst.setLoc(IDLoc);
2007 Instructions.push_back(tmpInst);
2008}
2009
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002010void emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, unsigned Reg2,
Daniel Sanders03f9c012015-07-14 12:24:22 +00002011 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002012 emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc,
Daniel Sanders03f9c012015-07-14 12:24:22 +00002013 Instructions);
2014}
2015
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002016void emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm,
2017 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
2018 emitRRX(Opcode, Reg0, Reg1, MCOperand::createImm(Imm), IDLoc,
2019 Instructions);
2020}
Daniel Sanders03f9c012015-07-14 12:24:22 +00002021
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002022void emitAppropriateDSLL(unsigned DstReg, unsigned SrcReg, int16_t ShiftAmount,
2023 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
2024 if (ShiftAmount >= 32) {
2025 emitRRI(Mips::DSLL32, DstReg, SrcReg, ShiftAmount - 32, IDLoc,
2026 Instructions);
Toma Tabacu7dea2e32015-04-28 14:06:35 +00002027 return;
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002028 }
Toma Tabacu7dea2e32015-04-28 14:06:35 +00002029
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002030 emitRRI(Mips::DSLL, DstReg, SrcReg, ShiftAmount, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00002031}
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002032} // end anonymous namespace.
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00002033
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002034bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
2035 SmallVectorImpl<MCInst> &Instructions) {
2036 // Create a JALR instruction which is going to replace the pseudo-JAL.
2037 MCInst JalrInst;
2038 JalrInst.setLoc(IDLoc);
2039 const MCOperand FirstRegOp = Inst.getOperand(0);
2040 const unsigned Opcode = Inst.getOpcode();
2041
2042 if (Opcode == Mips::JalOneReg) {
2043 // jal $rs => jalr $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002044 if (IsCpRestoreSet && inMicroMipsMode()) {
2045 JalrInst.setOpcode(Mips::JALRS16_MM);
2046 JalrInst.addOperand(FirstRegOp);
2047 } else if (inMicroMipsMode()) {
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002048 JalrInst.setOpcode(Mips::JALR16_MM);
2049 JalrInst.addOperand(FirstRegOp);
2050 } else {
2051 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00002052 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002053 JalrInst.addOperand(FirstRegOp);
2054 }
2055 } else if (Opcode == Mips::JalTwoReg) {
2056 // jal $rd, $rs => jalr $rd, $rs
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002057 if (IsCpRestoreSet && inMicroMipsMode())
2058 JalrInst.setOpcode(Mips::JALRS_MM);
2059 else
2060 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002061 JalrInst.addOperand(FirstRegOp);
2062 const MCOperand SecondRegOp = Inst.getOperand(1);
2063 JalrInst.addOperand(SecondRegOp);
2064 }
2065 Instructions.push_back(JalrInst);
2066
2067 // If .set reorder is active, emit a NOP after it.
Daniel Sanderse2982ad2015-09-17 16:08:39 +00002068 if (AssemblerOptions.back()->isReorder())
2069 createNop(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc, Instructions);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00002070
2071 return false;
2072}
2073
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002074/// Can the value be represented by a unsigned N-bit value and a shift left?
2075template<unsigned N>
2076bool isShiftedUIntAtAnyPosition(uint64_t x) {
2077 unsigned BitNum = findFirstSet(x);
2078
2079 return (x == x >> BitNum << BitNum) && isUInt<N>(x >> BitNum);
2080}
2081
2082/// Load (or add) an immediate into a register.
2083///
2084/// @param ImmValue The immediate to load.
2085/// @param DstReg The register that will hold the immediate.
2086/// @param SrcReg A register to add to the immediate or Mips::NoRegister
2087/// for a simple initialization.
2088/// @param Is32BitImm Is ImmValue 32-bit or 64-bit?
2089/// @param IsAddress True if the immediate represents an address. False if it
2090/// is an integer.
2091/// @param IDLoc Location of the immediate in the source file.
2092/// @param Instructions The instructions emitted by this expansion.
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002093bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002094 unsigned SrcReg, bool Is32BitImm,
2095 bool IsAddress, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00002096 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu00e98672015-05-01 12:19:27 +00002097 if (!Is32BitImm && !isGP64bit()) {
2098 Error(IDLoc, "instruction requires a 64-bit architecture");
2099 return true;
2100 }
2101
Daniel Sanders03f9c012015-07-14 12:24:22 +00002102 if (Is32BitImm) {
2103 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
2104 // Sign extend up to 64-bit so that the predicates match the hardware
2105 // behaviour. In particular, isInt<16>(0xffff8000) and similar should be
2106 // true.
2107 ImmValue = SignExtend64<32>(ImmValue);
2108 } else {
2109 Error(IDLoc, "instruction requires a 32-bit immediate");
2110 return true;
2111 }
2112 }
2113
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002114 unsigned ZeroReg = IsAddress ? ABI.GetNullPtr() : ABI.GetZeroReg();
2115 unsigned AdduOp = !Is32BitImm ? Mips::DADDu : Mips::ADDu;
2116
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002117 bool UseSrcReg = false;
2118 if (SrcReg != Mips::NoRegister)
2119 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00002120
Toma Tabacu8e0316d2015-06-22 13:10:23 +00002121 unsigned TmpReg = DstReg;
2122 if (UseSrcReg && (DstReg == SrcReg)) {
2123 // At this point we need AT to perform the expansions and we exit if it is
2124 // not available.
2125 unsigned ATReg = getATReg(IDLoc);
2126 if (!ATReg)
2127 return true;
2128 TmpReg = ATReg;
2129 }
2130
Daniel Sanders03f9c012015-07-14 12:24:22 +00002131 if (isInt<16>(ImmValue)) {
Toma Tabacudf7fd462015-05-13 16:02:41 +00002132 if (!UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002133 SrcReg = ZeroReg;
2134
2135 // This doesn't quite follow the usual ABI expectations for N32 but matches
2136 // traditional assembler behaviour. N32 would normally use addiu for both
2137 // integers and addresses.
2138 if (IsAddress && !Is32BitImm) {
2139 emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2140 return false;
Daniel Sanders03f9c012015-07-14 12:24:22 +00002141 }
2142
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002143 emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
2144 return false;
2145 }
2146
2147 if (isUInt<16>(ImmValue)) {
2148 unsigned TmpReg = DstReg;
2149 if (SrcReg == DstReg) {
2150 TmpReg = getATReg(IDLoc);
2151 if (!TmpReg)
2152 return true;
2153 }
2154
2155 emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002156 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002157 emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2158 return false;
2159 }
2160
2161 if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002162 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002163
Toma Tabacu79588102015-04-29 10:19:56 +00002164 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
2165 uint16_t Bits15To0 = ImmValue & 0xffff;
2166
Toma Tabacua3d056f2015-05-15 09:42:11 +00002167 if (!Is32BitImm && !isInt<32>(ImmValue)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002168 // Traditional behaviour seems to special case this particular value. It's
2169 // not clear why other masks are handled differently.
2170 if (ImmValue == 0xffffffff) {
Daniel Sandersf1ae3672015-08-18 09:55:57 +00002171 emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002172 emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, Instructions);
2173 if (UseSrcReg)
2174 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2175 return false;
2176 }
2177
2178 // Expand to an ORi instead of a LUi to avoid sign-extending into the
Toma Tabacua3d056f2015-05-15 09:42:11 +00002179 // upper 32 bits.
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002180 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, Instructions);
Daniel Sanders03f9c012015-07-14 12:24:22 +00002181 emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, Instructions);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002182 if (Bits15To0)
2183 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
2184 if (UseSrcReg)
2185 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2186 return false;
Toma Tabacua2861db2015-05-01 10:26:47 +00002187 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002188
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002189 emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, Instructions);
2190 if (Bits15To0)
2191 emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002192 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002193 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2194 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002195 }
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002196
2197 if (isShiftedUIntAtAnyPosition<16>(ImmValue)) {
2198 if (Is32BitImm) {
2199 Error(IDLoc, "instruction requires a 32-bit immediate");
2200 return true;
2201 }
2202
2203 // Traditionally, these immediates are shifted as little as possible and as
2204 // such we align the most significant bit to bit 15 of our temporary.
2205 unsigned FirstSet = findFirstSet((uint64_t)ImmValue);
2206 unsigned LastSet = findLastSet((uint64_t)ImmValue);
2207 unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
2208 uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
2209 emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, Instructions);
2210 emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, Instructions);
2211
2212 if (UseSrcReg)
2213 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2214
2215 return false;
2216 }
2217
2218 warnIfNoMacro(IDLoc);
2219
2220 // The remaining case is packed with a sequence of dsll and ori with zeros
2221 // being omitted and any neighbouring dsll's being coalesced.
2222 // The highest 32-bit's are equivalent to a 32-bit immediate load.
2223
2224 // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
2225 if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
2226 IDLoc, Instructions))
2227 return false;
2228
2229 // Shift and accumulate into the register. If a 16-bit chunk is zero, then
2230 // skip it and defer the shift to the next chunk.
2231 unsigned ShiftCarriedForwards = 16;
2232 for (int BitNum = 16; BitNum >= 0; BitNum -= 16) {
2233 uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
2234
2235 if (ImmChunk != 0) {
2236 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2237 Instructions);
2238 emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, Instructions);
2239 ShiftCarriedForwards = 0;
2240 }
2241
2242 ShiftCarriedForwards += 16;
2243 }
2244 ShiftCarriedForwards -= 16;
2245
2246 // Finish any remaining shifts left by trailing zeros.
2247 if (ShiftCarriedForwards)
2248 emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
2249 Instructions);
2250
2251 if (UseSrcReg)
2252 emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2253
Matheus Almeida3813d572014-06-19 14:39:14 +00002254 return false;
Jack Carter30a59822012-10-04 04:03:53 +00002255}
Jack Carter92995f12012-10-06 00:53:28 +00002256
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002257bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
2258 SmallVectorImpl<MCInst> &Instructions) {
2259 const MCOperand &ImmOp = Inst.getOperand(1);
2260 assert(ImmOp.isImm() && "expected immediate operand kind");
2261 const MCOperand &DstRegOp = Inst.getOperand(0);
2262 assert(DstRegOp.isReg() && "expected register operand kind");
2263
2264 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002265 Is32BitImm, false, IDLoc, Instructions))
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002266 return true;
2267
2268 return false;
2269}
2270
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002271bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
2272 const MCOperand &Offset,
2273 bool Is32BitAddress, SMLoc IDLoc,
2274 SmallVectorImpl<MCInst> &Instructions) {
2275 // la can't produce a usable address when addresses are 64-bit.
2276 if (Is32BitAddress && ABI.ArePtrs64bit()) {
2277 // FIXME: Demote this to a warning and continue as if we had 'dla' instead.
2278 // We currently can't do this because we depend on the equality
2279 // operator and N64 can end up with a GPR32/GPR64 mismatch.
2280 Error(IDLoc, "la used to load 64-bit address");
2281 // Continue as if we had 'dla' instead.
2282 Is32BitAddress = false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002283 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002284
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002285 // dla requires 64-bit addresses.
2286 if (!Is32BitAddress && !ABI.ArePtrs64bit()) {
2287 Error(IDLoc, "instruction requires a 64-bit architecture");
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002288 return true;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002289 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002290
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002291 if (!Offset.isImm())
2292 return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
2293 Is32BitAddress, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002294
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002295 return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
2296 IDLoc, Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +00002297}
2298
Toma Tabacuf712ede2015-06-17 14:31:51 +00002299bool MipsAsmParser::loadAndAddSymbolAddress(
2300 const MCExpr *SymExpr, unsigned DstReg, unsigned SrcReg, bool Is32BitSym,
2301 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002302 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002303
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002304 // FIXME: The way we're handling symbols right now prevents simple expressions
2305 // like foo+8. We'll be able to fix this once our unary operators (%hi
2306 // and similar) are treated as operators rather than as fixup types.
Toma Tabacu674825c2015-06-16 12:16:24 +00002307 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymExpr);
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002308 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::create(
2309 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
2310 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::create(
2311 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
2312
Toma Tabacufb9d1252015-06-22 12:08:39 +00002313 bool UseSrcReg = SrcReg != Mips::NoRegister;
2314
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002315 // This is the 64-bit symbol address expansion.
2316 if (ABI.ArePtrs64bit() && isGP64bit()) {
2317 // We always need AT for the 64-bit expansion.
2318 // If it is not available we exit.
2319 unsigned ATReg = getATReg(IDLoc);
2320 if (!ATReg)
2321 return true;
2322
2323 const MCSymbolRefExpr *HighestExpr = MCSymbolRefExpr::create(
2324 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
2325 const MCSymbolRefExpr *HigherExpr = MCSymbolRefExpr::create(
2326 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
2327
2328 if (UseSrcReg && (DstReg == SrcReg)) {
2329 // If $rs is the same as $rd:
2330 // (d)la $rd, sym($rd) => lui $at, %highest(sym)
2331 // daddiu $at, $at, %higher(sym)
2332 // dsll $at, $at, 16
2333 // daddiu $at, $at, %hi(sym)
2334 // dsll $at, $at, 16
2335 // daddiu $at, $at, %lo(sym)
2336 // daddu $rd, $at, $rd
2337 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
2338 Instructions);
2339 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HigherExpr),
2340 IDLoc, Instructions);
2341 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2342 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2343 Instructions);
2344 emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
2345 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2346 Instructions);
2347 emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, Instructions);
2348
2349 return false;
2350 }
2351
2352 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2353 // (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
2354 // lui $at, %hi(sym)
2355 // daddiu $rd, $rd, %higher(sym)
2356 // daddiu $at, $at, %lo(sym)
2357 // dsll32 $rd, $rd, 0
2358 // daddu $rd, $rd, $at
2359 // (daddu $rd, $rd, $rs)
2360 emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
2361 Instructions);
2362 emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
2363 Instructions);
2364 emitRRX(Mips::DADDiu, DstReg, DstReg, MCOperand::createExpr(HigherExpr),
2365 IDLoc, Instructions);
2366 emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
2367 Instructions);
2368 emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, Instructions);
2369 emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, Instructions);
2370 if (UseSrcReg)
2371 emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, Instructions);
2372
2373 return false;
2374 }
2375
2376 // And now, the 32-bit symbol address expansion:
2377 // If $rs is the same as $rd:
2378 // (d)la $rd, sym($rd) => lui $at, %hi(sym)
2379 // ori $at, $at, %lo(sym)
2380 // addu $rd, $at, $rd
2381 // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
2382 // (d)la $rd, sym/sym($rs) => lui $rd, %hi(sym)
2383 // ori $rd, $rd, %lo(sym)
2384 // (addu $rd, $rd, $rs)
Toma Tabacufb9d1252015-06-22 12:08:39 +00002385 unsigned TmpReg = DstReg;
2386 if (UseSrcReg && (DstReg == SrcReg)) {
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002387 // If $rs is the same as $rd, we need to use AT.
2388 // If it is not available we exit.
Toma Tabacufb9d1252015-06-22 12:08:39 +00002389 unsigned ATReg = getATReg(IDLoc);
2390 if (!ATReg)
2391 return true;
2392 TmpReg = ATReg;
2393 }
2394
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002395 emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, Instructions);
2396 emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr), IDLoc,
2397 Instructions);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002398
Toma Tabacufb9d1252015-06-22 12:08:39 +00002399 if (UseSrcReg)
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002400 emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
2401 else
2402 assert(DstReg == TmpReg);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002403
Toma Tabacu674825c2015-06-16 12:16:24 +00002404 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002405}
2406
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00002407bool MipsAsmParser::expandUncondBranchMMPseudo(
2408 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002409 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2410 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002411
2412 MCOperand Offset = Inst.getOperand(0);
2413 if (Offset.isExpr()) {
2414 Inst.clear();
2415 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002416 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2417 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2418 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002419 } else {
2420 assert(Offset.isImm() && "expected immediate operand kind");
2421 if (isIntN(11, Offset.getImm())) {
2422 // If offset fits into 11 bits then this instruction becomes microMIPS
2423 // 16-bit unconditional branch instruction.
Zoran Jovanovicada70912015-09-07 11:56:37 +00002424 if (inMicroMipsMode())
2425 Inst.setOpcode(hasMips32r6() ? Mips::BC16_MMR6 : Mips::B16_MM);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002426 } else {
2427 if (!isIntN(17, Offset.getImm()))
2428 Error(IDLoc, "branch target out of range");
2429 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2430 Error(IDLoc, "branch to misaligned address");
2431 Inst.clear();
2432 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002433 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2434 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2435 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002436 }
2437 }
2438 Instructions.push_back(Inst);
2439
Zoran Jovanovicada70912015-09-07 11:56:37 +00002440 // If .set reorder is active and branch instruction has a delay slot,
2441 // emit a NOP after it.
2442 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
2443 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
Toma Tabacu234482a2015-03-16 12:03:39 +00002444 createNop(true, IDLoc, Instructions);
2445
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002446 return false;
2447}
2448
Toma Tabacue1e460d2015-06-11 10:36:10 +00002449bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc,
2450 SmallVectorImpl<MCInst> &Instructions) {
2451 const MCOperand &DstRegOp = Inst.getOperand(0);
2452 assert(DstRegOp.isReg() && "expected register operand kind");
2453
2454 const MCOperand &ImmOp = Inst.getOperand(1);
2455 assert(ImmOp.isImm() && "expected immediate operand kind");
2456
2457 const MCOperand &MemOffsetOp = Inst.getOperand(2);
2458 assert(MemOffsetOp.isImm() && "expected immediate operand kind");
2459
2460 unsigned OpCode = 0;
2461 switch(Inst.getOpcode()) {
2462 case Mips::BneImm:
2463 OpCode = Mips::BNE;
2464 break;
2465 case Mips::BeqImm:
2466 OpCode = Mips::BEQ;
2467 break;
2468 default:
2469 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2470 break;
2471 }
2472
2473 int64_t ImmValue = ImmOp.getImm();
2474 if (ImmValue == 0) {
2475 MCInst BranchInst;
2476 BranchInst.setOpcode(OpCode);
2477 BranchInst.addOperand(DstRegOp);
2478 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2479 BranchInst.addOperand(MemOffsetOp);
2480 Instructions.push_back(BranchInst);
2481 } else {
2482 warnIfNoMacro(IDLoc);
2483
2484 unsigned ATReg = getATReg(IDLoc);
2485 if (!ATReg)
2486 return true;
2487
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002488 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
2489 IDLoc, Instructions))
Toma Tabacue1e460d2015-06-11 10:36:10 +00002490 return true;
2491
2492 MCInst BranchInst;
2493 BranchInst.setOpcode(OpCode);
2494 BranchInst.addOperand(DstRegOp);
2495 BranchInst.addOperand(MCOperand::createReg(ATReg));
2496 BranchInst.addOperand(MemOffsetOp);
2497 Instructions.push_back(BranchInst);
2498 }
2499 return false;
2500}
2501
Jack Carter9e65aa32013-03-22 00:05:30 +00002502void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00002503 SmallVectorImpl<MCInst> &Instructions,
2504 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002505 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00002506 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00002507 const MCExpr *ExprOffset;
2508 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00002509 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002510 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2511 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002512 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002513 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2514 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002515 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002516 if (isImmOpnd) {
2517 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2518 ImmOffset = Inst.getOperand(2).getImm();
2519 LoOffset = ImmOffset & 0x0000ffff;
2520 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002521 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002522 if (LoOffset & 0x8000)
2523 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002524 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002525 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002526 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00002527 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002528 // These are some of the types of expansions we perform here:
2529 // 1) lw $8, sym => lui $8, %hi(sym)
2530 // lw $8, %lo(sym)($8)
2531 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2532 // add $8, $8, $9
2533 // lw $8, %lo(offset)($9)
2534 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2535 // add $at, $at, $8
2536 // lw $8, %lo(offset)($at)
2537 // 4) sw $8, sym => lui $at, %hi(sym)
2538 // sw $8, %lo(sym)($at)
2539 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2540 // add $at, $at, $8
2541 // sw $8, %lo(offset)($at)
2542 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2543 // ldc1 $f0, %lo(sym)($at)
2544 //
2545 // For load instructions we can use the destination register as a temporary
2546 // if base and dst are different (examples 1 and 2) and if the base register
2547 // is general purpose otherwise we must use $at (example 6) and error if it's
2548 // not available. For stores we must use $at (examples 4 and 5) because we
2549 // must not clobber the source register setting up the offset.
2550 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2551 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2552 unsigned RegClassIDOp0 =
2553 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2554 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2555 (RegClassIDOp0 == Mips::GPR64RegClassID);
2556 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002557 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002558 else {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002559 // At this point we need AT to perform the expansions and we exit if it is
2560 // not available.
Toma Tabacu89a712b2015-04-15 10:48:56 +00002561 TmpRegNum = getATReg(IDLoc);
2562 if (!TmpRegNum)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002563 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002564 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002565
Jack Carter9e65aa32013-03-22 00:05:30 +00002566 TempInst.setOpcode(Mips::LUi);
Jim Grosbache9119e42015-05-13 18:37:00 +00002567 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
Jack Carter9e65aa32013-03-22 00:05:30 +00002568 if (isImmOpnd)
Jim Grosbache9119e42015-05-13 18:37:00 +00002569 TempInst.addOperand(MCOperand::createImm(HiOffset));
Jack Carter9e65aa32013-03-22 00:05:30 +00002570 else {
Toma Tabacu07c97b32015-06-17 10:43:45 +00002571 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
2572 TempInst.addOperand(MCOperand::createExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002573 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002574 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00002575 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00002576 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00002577 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00002578 // Add temp register to base.
Toma Tabacuc6ce0742015-04-08 13:52:41 +00002579 if (BaseRegNum != Mips::ZERO) {
2580 TempInst.setOpcode(Mips::ADDu);
Jim Grosbache9119e42015-05-13 18:37:00 +00002581 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
2582 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
2583 TempInst.addOperand(MCOperand::createReg(BaseRegNum));
Toma Tabacuc6ce0742015-04-08 13:52:41 +00002584 Instructions.push_back(TempInst);
2585 TempInst.clear();
2586 }
Alp Tokercb402912014-01-24 17:20:08 +00002587 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002588 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00002589 TempInst.setOpcode(Inst.getOpcode());
Jim Grosbache9119e42015-05-13 18:37:00 +00002590 TempInst.addOperand(MCOperand::createReg(RegOpNum));
2591 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
Jack Carter9e65aa32013-03-22 00:05:30 +00002592 if (isImmOpnd)
Jim Grosbache9119e42015-05-13 18:37:00 +00002593 TempInst.addOperand(MCOperand::createImm(LoOffset));
Jack Carter9e65aa32013-03-22 00:05:30 +00002594 else {
Toma Tabacu07c97b32015-06-17 10:43:45 +00002595 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
2596 TempInst.addOperand(MCOperand::createExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002597 }
2598 Instructions.push_back(TempInst);
2599 TempInst.clear();
2600}
2601
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002602bool
2603MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2604 SmallVectorImpl<MCInst> &Instructions) {
2605 unsigned OpNum = Inst.getNumOperands();
2606 unsigned Opcode = Inst.getOpcode();
2607 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2608
2609 assert (Inst.getOperand(OpNum - 1).isImm() &&
2610 Inst.getOperand(OpNum - 2).isReg() &&
2611 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2612
2613 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2614 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
2615 Inst.getOperand(OpNum - 2).getReg() == Mips::SP &&
2616 Inst.getOperand(OpNum - 3).getReg() == Mips::RA)
2617 // It can be implemented as SWM16 or LWM16 instruction.
2618 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2619
2620 Inst.setOpcode(NewOpcode);
2621 Instructions.push_back(Inst);
2622 return false;
2623}
2624
Toma Tabacu1a108322015-06-17 13:20:24 +00002625bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
2626 SmallVectorImpl<MCInst> &Instructions) {
2627 unsigned PseudoOpcode = Inst.getOpcode();
2628 unsigned SrcReg = Inst.getOperand(0).getReg();
2629 unsigned TrgReg = Inst.getOperand(1).getReg();
2630 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
2631
2632 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002633 bool ReverseOrderSLT, IsUnsigned, IsLikely, AcceptsEquality;
Toma Tabacu1a108322015-06-17 13:20:24 +00002634
2635 switch (PseudoOpcode) {
2636 case Mips::BLT:
2637 case Mips::BLTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002638 case Mips::BLTL:
2639 case Mips::BLTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002640 AcceptsEquality = false;
2641 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002642 IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL));
2643 IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002644 ZeroSrcOpcode = Mips::BGTZ;
2645 ZeroTrgOpcode = Mips::BLTZ;
2646 break;
2647 case Mips::BLE:
2648 case Mips::BLEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002649 case Mips::BLEL:
2650 case Mips::BLEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002651 AcceptsEquality = true;
2652 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002653 IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL));
2654 IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002655 ZeroSrcOpcode = Mips::BGEZ;
2656 ZeroTrgOpcode = Mips::BLEZ;
2657 break;
2658 case Mips::BGE:
2659 case Mips::BGEU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002660 case Mips::BGEL:
2661 case Mips::BGEUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002662 AcceptsEquality = true;
2663 ReverseOrderSLT = false;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002664 IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL));
2665 IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002666 ZeroSrcOpcode = Mips::BLEZ;
2667 ZeroTrgOpcode = Mips::BGEZ;
2668 break;
2669 case Mips::BGT:
2670 case Mips::BGTU:
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002671 case Mips::BGTL:
2672 case Mips::BGTUL:
Toma Tabacu1a108322015-06-17 13:20:24 +00002673 AcceptsEquality = false;
2674 ReverseOrderSLT = true;
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002675 IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL));
2676 IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL));
Toma Tabacu1a108322015-06-17 13:20:24 +00002677 ZeroSrcOpcode = Mips::BLTZ;
2678 ZeroTrgOpcode = Mips::BGTZ;
2679 break;
2680 default:
2681 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2682 }
2683
2684 MCInst BranchInst;
2685 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
2686 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
2687 if (IsSrcRegZero && IsTrgRegZero) {
2688 // FIXME: All of these Opcode-specific if's are needed for compatibility
2689 // with GAS' behaviour. However, they may not generate the most efficient
2690 // code in some circumstances.
2691 if (PseudoOpcode == Mips::BLT) {
2692 BranchInst.setOpcode(Mips::BLTZ);
2693 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2694 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2695 Instructions.push_back(BranchInst);
2696 return false;
2697 }
2698 if (PseudoOpcode == Mips::BLE) {
2699 BranchInst.setOpcode(Mips::BLEZ);
2700 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2701 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2702 Instructions.push_back(BranchInst);
2703 Warning(IDLoc, "branch is always taken");
2704 return false;
2705 }
2706 if (PseudoOpcode == Mips::BGE) {
2707 BranchInst.setOpcode(Mips::BGEZ);
2708 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2709 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2710 Instructions.push_back(BranchInst);
2711 Warning(IDLoc, "branch is always taken");
2712 return false;
2713 }
2714 if (PseudoOpcode == Mips::BGT) {
2715 BranchInst.setOpcode(Mips::BGTZ);
2716 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2717 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2718 Instructions.push_back(BranchInst);
2719 return false;
2720 }
2721 if (PseudoOpcode == Mips::BGTU) {
2722 BranchInst.setOpcode(Mips::BNE);
2723 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2724 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2725 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2726 Instructions.push_back(BranchInst);
2727 return false;
2728 }
2729 if (AcceptsEquality) {
2730 // If both registers are $0 and the pseudo-branch accepts equality, it
2731 // will always be taken, so we emit an unconditional branch.
2732 BranchInst.setOpcode(Mips::BEQ);
2733 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2734 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2735 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2736 Instructions.push_back(BranchInst);
2737 Warning(IDLoc, "branch is always taken");
2738 return false;
2739 }
2740 // If both registers are $0 and the pseudo-branch does not accept
2741 // equality, it will never be taken, so we don't have to emit anything.
2742 return false;
2743 }
2744 if (IsSrcRegZero || IsTrgRegZero) {
2745 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
2746 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
2747 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
2748 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
2749 // the pseudo-branch will never be taken, so we don't emit anything.
2750 // This only applies to unsigned pseudo-branches.
2751 return false;
2752 }
2753 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
2754 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
2755 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
2756 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
2757 // the pseudo-branch will always be taken, so we emit an unconditional
2758 // branch.
2759 // This only applies to unsigned pseudo-branches.
2760 BranchInst.setOpcode(Mips::BEQ);
2761 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2762 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2763 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2764 Instructions.push_back(BranchInst);
2765 Warning(IDLoc, "branch is always taken");
2766 return false;
2767 }
2768 if (IsUnsigned) {
2769 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
2770 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
2771 // the pseudo-branch will be taken only when the non-zero register is
2772 // different from 0, so we emit a BNEZ.
2773 //
2774 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
2775 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
2776 // the pseudo-branch will be taken only when the non-zero register is
2777 // equal to 0, so we emit a BEQZ.
2778 //
2779 // Because only BLEU and BGEU branch on equality, we can use the
2780 // AcceptsEquality variable to decide when to emit the BEQZ.
2781 BranchInst.setOpcode(AcceptsEquality ? Mips::BEQ : Mips::BNE);
2782 BranchInst.addOperand(
2783 MCOperand::createReg(IsSrcRegZero ? TrgReg : SrcReg));
2784 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2785 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2786 Instructions.push_back(BranchInst);
2787 return false;
2788 }
2789 // If we have a signed pseudo-branch and one of the registers is $0,
2790 // we can use an appropriate compare-to-zero branch. We select which one
2791 // to use in the switch statement above.
2792 BranchInst.setOpcode(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode);
2793 BranchInst.addOperand(MCOperand::createReg(IsSrcRegZero ? TrgReg : SrcReg));
2794 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2795 Instructions.push_back(BranchInst);
2796 return false;
2797 }
2798
2799 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
2800 // expansions. If it is not available, we return.
2801 unsigned ATRegNum = getATReg(IDLoc);
2802 if (!ATRegNum)
2803 return true;
2804
2805 warnIfNoMacro(IDLoc);
2806
2807 // SLT fits well with 2 of our 4 pseudo-branches:
2808 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
2809 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
2810 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
2811 // This is accomplished by using a BNEZ with the result of the SLT.
2812 //
2813 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
2814 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
2815 // Because only BGE and BLE branch on equality, we can use the
2816 // AcceptsEquality variable to decide when to emit the BEQZ.
2817 // Note that the order of the SLT arguments doesn't change between
2818 // opposites.
2819 //
2820 // The same applies to the unsigned variants, except that SLTu is used
2821 // instead of SLT.
2822 MCInst SetInst;
2823 SetInst.setOpcode(IsUnsigned ? Mips::SLTu : Mips::SLT);
2824 SetInst.addOperand(MCOperand::createReg(ATRegNum));
2825 SetInst.addOperand(MCOperand::createReg(ReverseOrderSLT ? TrgReg : SrcReg));
2826 SetInst.addOperand(MCOperand::createReg(ReverseOrderSLT ? SrcReg : TrgReg));
2827 Instructions.push_back(SetInst);
2828
Zoran Jovanovic8eb8c982015-09-15 15:06:26 +00002829 if (!IsLikely)
2830 BranchInst.setOpcode(AcceptsEquality ? Mips::BEQ : Mips::BNE);
2831 else
2832 BranchInst.setOpcode(AcceptsEquality ? Mips::BEQL : Mips::BNEL);
Toma Tabacu1a108322015-06-17 13:20:24 +00002833 BranchInst.addOperand(MCOperand::createReg(ATRegNum));
2834 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2835 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2836 Instructions.push_back(BranchInst);
2837 return false;
2838}
2839
Daniel Sanders3ebcaf62015-09-03 12:31:22 +00002840bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc,
2841 SmallVectorImpl<MCInst> &Instructions,
2842 const bool IsMips64, const bool Signed) {
2843 if (hasMips32r6()) {
2844 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2845 return false;
2846 }
2847
2848 warnIfNoMacro(IDLoc);
2849
2850 const MCOperand &RsRegOp = Inst.getOperand(0);
2851 assert(RsRegOp.isReg() && "expected register operand kind");
2852 unsigned RsReg = RsRegOp.getReg();
2853
2854 const MCOperand &RtRegOp = Inst.getOperand(1);
2855 assert(RtRegOp.isReg() && "expected register operand kind");
2856 unsigned RtReg = RtRegOp.getReg();
2857 unsigned DivOp;
2858 unsigned ZeroReg;
2859
2860 if (IsMips64) {
2861 DivOp = Signed ? Mips::DSDIV : Mips::DUDIV;
2862 ZeroReg = Mips::ZERO_64;
2863 } else {
2864 DivOp = Signed ? Mips::SDIV : Mips::UDIV;
2865 ZeroReg = Mips::ZERO;
2866 }
2867
2868 bool UseTraps = useTraps();
2869
2870 if (RsReg == Mips::ZERO || RsReg == Mips::ZERO_64) {
2871 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)
2872 Warning(IDLoc, "dividing zero by zero");
2873 if (IsMips64) {
2874 if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
2875 if (UseTraps) {
2876 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2877 return false;
2878 }
2879
2880 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2881 return false;
2882 }
2883 } else {
2884 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
2885 return false;
2886 }
2887 }
2888
2889 if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) {
2890 Warning(IDLoc, "division by zero");
2891 if (Signed) {
2892 if (UseTraps) {
2893 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2894 return false;
2895 }
2896
2897 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2898 return false;
2899 }
2900 }
2901
2902 // FIXME: The values for these two BranchTarget variables may be different in
2903 // micromips. These magic numbers need to be removed.
2904 unsigned BranchTargetNoTraps;
2905 unsigned BranchTarget;
2906
2907 if (UseTraps) {
2908 BranchTarget = IsMips64 ? 12 : 8;
2909 emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
2910 } else {
2911 BranchTarget = IsMips64 ? 20 : 16;
2912 BranchTargetNoTraps = 8;
2913 // Branch to the li instruction.
2914 emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc,
2915 Instructions);
2916 }
2917
2918 emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
2919
2920 if (!UseTraps)
2921 emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
2922
2923 if (!Signed) {
2924 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
2925 return false;
2926 }
2927
2928 unsigned ATReg = getATReg(IDLoc);
2929 if (!ATReg)
2930 return true;
2931
2932 emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, Instructions);
2933 if (IsMips64) {
2934 // Branch to the mflo instruction.
2935 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
2936 emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, Instructions);
2937 emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, Instructions);
2938 } else {
2939 // Branch to the mflo instruction.
2940 emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
2941 emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, Instructions);
2942 }
2943
2944 if (UseTraps)
2945 emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, Instructions);
2946 else {
2947 // Branch to the mflo instruction.
2948 emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, Instructions);
2949 emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, Instructions);
2950 emitII(Mips::BREAK, 0x6, 0, IDLoc, Instructions);
2951 }
2952 emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
2953 return false;
2954}
2955
Toma Tabacud88d79c2015-06-23 14:39:42 +00002956bool MipsAsmParser::expandUlhu(MCInst &Inst, SMLoc IDLoc,
2957 SmallVectorImpl<MCInst> &Instructions) {
2958 if (hasMips32r6() || hasMips64r6()) {
2959 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2960 return false;
2961 }
2962
2963 warnIfNoMacro(IDLoc);
2964
2965 const MCOperand &DstRegOp = Inst.getOperand(0);
2966 assert(DstRegOp.isReg() && "expected register operand kind");
2967
2968 const MCOperand &SrcRegOp = Inst.getOperand(1);
2969 assert(SrcRegOp.isReg() && "expected register operand kind");
2970
2971 const MCOperand &OffsetImmOp = Inst.getOperand(2);
2972 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
2973
2974 unsigned DstReg = DstRegOp.getReg();
2975 unsigned SrcReg = SrcRegOp.getReg();
2976 int64_t OffsetValue = OffsetImmOp.getImm();
2977
2978 // NOTE: We always need AT for ULHU, as it is always used as the source
2979 // register for one of the LBu's.
2980 unsigned ATReg = getATReg(IDLoc);
2981 if (!ATReg)
2982 return true;
2983
2984 // When the value of offset+1 does not fit in 16 bits, we have to load the
2985 // offset in AT, (D)ADDu the original source register (if there was one), and
2986 // then use AT as the source register for the 2 generated LBu's.
2987 bool LoadedOffsetInAT = false;
2988 if (!isInt<16>(OffsetValue + 1) || !isInt<16>(OffsetValue)) {
2989 LoadedOffsetInAT = true;
2990
2991 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00002992 true, IDLoc, Instructions))
Toma Tabacud88d79c2015-06-23 14:39:42 +00002993 return true;
2994
2995 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
2996 // because it will make our output more similar to GAS'. For example,
2997 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
2998 // instead of just an "ori $1, $9, 32768".
2999 // NOTE: If there is no source register specified in the ULHU, the parser
3000 // will interpret it as $0.
3001 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3002 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3003 }
3004
3005 unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg;
3006 unsigned SecondLbuDstReg = LoadedOffsetInAT ? ATReg : DstReg;
3007 unsigned LbuSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3008
3009 int64_t FirstLbuOffset = 0, SecondLbuOffset = 0;
3010 if (isLittle()) {
3011 FirstLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3012 SecondLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3013 } else {
3014 FirstLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3015 SecondLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
3016 }
3017
3018 unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg;
3019
3020 MCInst TmpInst;
3021 TmpInst.setOpcode(Mips::LBu);
3022 TmpInst.addOperand(MCOperand::createReg(FirstLbuDstReg));
3023 TmpInst.addOperand(MCOperand::createReg(LbuSrcReg));
3024 TmpInst.addOperand(MCOperand::createImm(FirstLbuOffset));
3025 Instructions.push_back(TmpInst);
3026
3027 TmpInst.clear();
3028 TmpInst.setOpcode(Mips::LBu);
3029 TmpInst.addOperand(MCOperand::createReg(SecondLbuDstReg));
3030 TmpInst.addOperand(MCOperand::createReg(LbuSrcReg));
3031 TmpInst.addOperand(MCOperand::createImm(SecondLbuOffset));
3032 Instructions.push_back(TmpInst);
3033
3034 TmpInst.clear();
3035 TmpInst.setOpcode(Mips::SLL);
3036 TmpInst.addOperand(MCOperand::createReg(SllReg));
3037 TmpInst.addOperand(MCOperand::createReg(SllReg));
3038 TmpInst.addOperand(MCOperand::createImm(8));
3039 Instructions.push_back(TmpInst);
3040
3041 TmpInst.clear();
3042 TmpInst.setOpcode(Mips::OR);
3043 TmpInst.addOperand(MCOperand::createReg(DstReg));
3044 TmpInst.addOperand(MCOperand::createReg(DstReg));
3045 TmpInst.addOperand(MCOperand::createReg(ATReg));
3046 Instructions.push_back(TmpInst);
3047
3048 return false;
3049}
3050
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003051bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc,
3052 SmallVectorImpl<MCInst> &Instructions) {
3053 if (hasMips32r6() || hasMips64r6()) {
3054 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
3055 return false;
3056 }
3057
3058 const MCOperand &DstRegOp = Inst.getOperand(0);
3059 assert(DstRegOp.isReg() && "expected register operand kind");
3060
3061 const MCOperand &SrcRegOp = Inst.getOperand(1);
3062 assert(SrcRegOp.isReg() && "expected register operand kind");
3063
3064 const MCOperand &OffsetImmOp = Inst.getOperand(2);
3065 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
3066
3067 unsigned SrcReg = SrcRegOp.getReg();
3068 int64_t OffsetValue = OffsetImmOp.getImm();
3069 unsigned ATReg = 0;
3070
3071 // When the value of offset+3 does not fit in 16 bits, we have to load the
3072 // offset in AT, (D)ADDu the original source register (if there was one), and
3073 // then use AT as the source register for the generated LWL and LWR.
3074 bool LoadedOffsetInAT = false;
3075 if (!isInt<16>(OffsetValue + 3) || !isInt<16>(OffsetValue)) {
3076 ATReg = getATReg(IDLoc);
3077 if (!ATReg)
3078 return true;
3079 LoadedOffsetInAT = true;
3080
3081 warnIfNoMacro(IDLoc);
3082
3083 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003084 true, IDLoc, Instructions))
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00003085 return true;
3086
3087 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
3088 // because it will make our output more similar to GAS'. For example,
3089 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
3090 // instead of just an "ori $1, $9, 32768".
3091 // NOTE: If there is no source register specified in the ULW, the parser
3092 // will interpret it as $0.
3093 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
3094 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
3095 }
3096
3097 unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
3098 int64_t LeftLoadOffset = 0, RightLoadOffset = 0;
3099 if (isLittle()) {
3100 LeftLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3101 RightLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3102 } else {
3103 LeftLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
3104 RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
3105 }
3106
3107 MCInst LeftLoadInst;
3108 LeftLoadInst.setOpcode(Mips::LWL);
3109 LeftLoadInst.addOperand(DstRegOp);
3110 LeftLoadInst.addOperand(MCOperand::createReg(FinalSrcReg));
3111 LeftLoadInst.addOperand(MCOperand::createImm(LeftLoadOffset));
3112 Instructions.push_back(LeftLoadInst);
3113
3114 MCInst RightLoadInst;
3115 RightLoadInst.setOpcode(Mips::LWR);
3116 RightLoadInst.addOperand(DstRegOp);
3117 RightLoadInst.addOperand(MCOperand::createReg(FinalSrcReg));
3118 RightLoadInst.addOperand(MCOperand::createImm(RightLoadOffset ));
3119 Instructions.push_back(RightLoadInst);
3120
3121 return false;
3122}
3123
Toma Tabacu234482a2015-03-16 12:03:39 +00003124void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
3125 SmallVectorImpl<MCInst> &Instructions) {
3126 MCInst NopInst;
3127 if (hasShortDelaySlot) {
3128 NopInst.setOpcode(Mips::MOVE16_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00003129 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
3130 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
Toma Tabacu234482a2015-03-16 12:03:39 +00003131 } else {
3132 NopInst.setOpcode(Mips::SLL);
Jim Grosbache9119e42015-05-13 18:37:00 +00003133 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
3134 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
3135 NopInst.addOperand(MCOperand::createImm(0));
Toma Tabacu234482a2015-03-16 12:03:39 +00003136 }
3137 Instructions.push_back(NopInst);
3138}
3139
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003140void MipsAsmParser::createAddu(unsigned DstReg, unsigned SrcReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +00003141 unsigned TrgReg, bool Is64Bit,
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003142 SmallVectorImpl<MCInst> &Instructions) {
Daniel Sanders03f9c012015-07-14 12:24:22 +00003143 emitRRR(Is64Bit ? Mips::DADDu : Mips::ADDu, DstReg, SrcReg, TrgReg, SMLoc(),
3144 Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00003145}
3146
Daniel Sanderse2982ad2015-09-17 16:08:39 +00003147void MipsAsmParser::createCpRestoreMemOp(
3148 bool IsLoad, int StackOffset, SMLoc IDLoc,
3149 SmallVectorImpl<MCInst> &Instructions) {
3150 MCInst MemInst;
3151 MemInst.setOpcode(IsLoad ? Mips::LW : Mips::SW);
3152 MemInst.addOperand(MCOperand::createReg(Mips::GP));
3153 MemInst.addOperand(MCOperand::createReg(Mips::SP));
3154 MemInst.addOperand(MCOperand::createImm(StackOffset));
3155
3156 // If the offset can not fit into 16 bits, we need to expand.
3157 if (!isInt<16>(StackOffset))
3158 expandMemInst(MemInst, IDLoc, Instructions, IsLoad, true /*HasImmOpnd*/);
3159 else
3160 Instructions.push_back(MemInst);
3161}
3162
Matheus Almeida595fcab2014-06-11 15:05:56 +00003163unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
3164 // As described by the Mips32r2 spec, the registers Rd and Rs for
3165 // jalr.hb must be different.
3166 unsigned Opcode = Inst.getOpcode();
3167
3168 if (Opcode == Mips::JALR_HB &&
3169 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
3170 return Match_RequiresDifferentSrcAndDst;
3171
3172 return Match_Success;
3173}
3174
David Blaikie960ea3f2014-06-08 16:18:35 +00003175bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3176 OperandVector &Operands,
3177 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003178 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00003179 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00003180
Jack Carterb4dbc172012-09-05 23:34:03 +00003181 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00003182 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00003183 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003184 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00003185
3186 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003187 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003188 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00003189 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00003190 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00003191 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00003192 return false;
3193 }
3194 case Match_MissingFeature:
3195 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
3196 return true;
3197 case Match_InvalidOperand: {
3198 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00003199 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003200 if (ErrorInfo >= Operands.size())
3201 return Error(IDLoc, "too few operands for instruction");
3202
David Blaikie960ea3f2014-06-08 16:18:35 +00003203 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00003204 if (ErrorLoc == SMLoc())
3205 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00003206 }
3207
3208 return Error(ErrorLoc, "invalid operand for instruction");
3209 }
3210 case Match_MnemonicFail:
3211 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00003212 case Match_RequiresDifferentSrcAndDst:
3213 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00003214 }
Craig Topper589ceee2015-01-03 08:16:34 +00003215
3216 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00003217}
3218
Toma Tabacud9d344b2015-04-27 14:05:04 +00003219void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
3220 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
3221 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
3222 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003223}
3224
Toma Tabacu81496c12015-05-20 08:54:45 +00003225void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
3226 if (!AssemblerOptions.back()->isMacro())
3227 Warning(Loc, "macro instruction expanded into multiple instructions");
3228}
3229
Daniel Sandersef638fe2014-10-03 15:37:37 +00003230void
3231MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
3232 SMRange Range, bool ShowColors) {
3233 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00003234 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00003235 ShowColors);
3236}
3237
Jack Carter1ac53222013-02-20 23:11:17 +00003238int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003239 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003240
Vladimir Medic4c299852013-11-06 11:27:05 +00003241 CC = StringSwitch<unsigned>(Name)
3242 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00003243 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00003244 .Case("a0", 4)
3245 .Case("a1", 5)
3246 .Case("a2", 6)
3247 .Case("a3", 7)
3248 .Case("v0", 2)
3249 .Case("v1", 3)
3250 .Case("s0", 16)
3251 .Case("s1", 17)
3252 .Case("s2", 18)
3253 .Case("s3", 19)
3254 .Case("s4", 20)
3255 .Case("s5", 21)
3256 .Case("s6", 22)
3257 .Case("s7", 23)
3258 .Case("k0", 26)
3259 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003260 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00003261 .Case("sp", 29)
3262 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00003263 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00003264 .Case("ra", 31)
3265 .Case("t0", 8)
3266 .Case("t1", 9)
3267 .Case("t2", 10)
3268 .Case("t3", 11)
3269 .Case("t4", 12)
3270 .Case("t5", 13)
3271 .Case("t6", 14)
3272 .Case("t7", 15)
3273 .Case("t8", 24)
3274 .Case("t9", 25)
3275 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003276
Toma Tabacufda445c2014-09-15 15:33:01 +00003277 if (!(isABI_N32() || isABI_N64()))
3278 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00003279
Daniel Sandersef638fe2014-10-03 15:37:37 +00003280 if (12 <= CC && CC <= 15) {
3281 // Name is one of t4-t7
3282 AsmToken RegTok = getLexer().peekTok();
3283 SMRange RegRange = RegTok.getLocRange();
3284
3285 StringRef FixedName = StringSwitch<StringRef>(Name)
3286 .Case("t4", "t0")
3287 .Case("t5", "t1")
3288 .Case("t6", "t2")
3289 .Case("t7", "t3")
3290 .Default("");
3291 assert(FixedName != "" && "Register name is not one of t4-t7.");
3292
3293 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
3294 "Did you mean $" + FixedName + "?", RegRange);
3295 }
3296
Toma Tabacufda445c2014-09-15 15:33:01 +00003297 // Although SGI documentation just cuts out t0-t3 for n32/n64,
3298 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
3299 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
3300 if (8 <= CC && CC <= 11)
3301 CC += 4;
3302
3303 if (CC == -1)
3304 CC = StringSwitch<unsigned>(Name)
3305 .Case("a4", 8)
3306 .Case("a5", 9)
3307 .Case("a6", 10)
3308 .Case("a7", 11)
3309 .Case("kt0", 26)
3310 .Case("kt1", 27)
3311 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00003312
3313 return CC;
3314}
Jack Carterd0bd6422013-04-18 00:41:53 +00003315
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003316int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
3317 int CC;
3318
3319 CC = StringSwitch<unsigned>(Name)
3320 .Case("hwr_cpunum", 0)
3321 .Case("hwr_synci_step", 1)
3322 .Case("hwr_cc", 2)
3323 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00003324 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003325 .Default(-1);
3326
3327 return CC;
3328}
3329
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003330int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003331
Jack Cartera63b16a2012-09-07 00:23:42 +00003332 if (Name[0] == 'f') {
3333 StringRef NumString = Name.substr(1);
3334 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003335 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003336 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003337 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00003338 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003339 return IntVal;
3340 }
3341 return -1;
3342}
Jack Cartera63b16a2012-09-07 00:23:42 +00003343
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003344int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
3345
3346 if (Name.startswith("fcc")) {
3347 StringRef NumString = Name.substr(3);
3348 unsigned IntVal;
3349 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003350 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003351 if (IntVal > 7) // There are only 8 fcc registers.
3352 return -1;
3353 return IntVal;
3354 }
3355 return -1;
3356}
3357
3358int MipsAsmParser::matchACRegisterName(StringRef Name) {
3359
Akira Hatanaka274d24c2013-08-14 01:15:52 +00003360 if (Name.startswith("ac")) {
3361 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003362 unsigned IntVal;
3363 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00003364 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003365 if (IntVal > 3) // There are only 3 acc registers.
3366 return -1;
3367 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00003368 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003369 return -1;
3370}
Jack Carterd0bd6422013-04-18 00:41:53 +00003371
Jack Carter5dc8ac92013-09-25 23:50:44 +00003372int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
3373 unsigned IntVal;
3374
3375 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
3376 return -1;
3377
3378 if (IntVal > 31)
3379 return -1;
3380
3381 return IntVal;
3382}
3383
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003384int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
3385 int CC;
3386
3387 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00003388 .Case("msair", 0)
3389 .Case("msacsr", 1)
3390 .Case("msaaccess", 2)
3391 .Case("msasave", 3)
3392 .Case("msamodify", 4)
3393 .Case("msarequest", 5)
3394 .Case("msamap", 6)
3395 .Case("msaunmap", 7)
3396 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00003397
3398 return CC;
3399}
3400
Toma Tabacu89a712b2015-04-15 10:48:56 +00003401unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00003402 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00003403 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00003404 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00003405 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00003406 return 0;
3407 }
3408 unsigned AT = getReg(
3409 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00003410 return AT;
3411}
Jack Carter0b744b32012-10-04 02:29:46 +00003412
Jack Carterd0bd6422013-04-18 00:41:53 +00003413unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00003414 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00003415}
3416
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003417unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003418 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00003419 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003420}
3421
Jack Carter873c7242013-01-12 01:03:14 +00003422int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003423 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00003424 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00003425 return -1;
3426
Jack Carter873c7242013-01-12 01:03:14 +00003427 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00003428}
3429
Toma Tabacu13964452014-09-04 13:23:44 +00003430bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003431 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003432 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003433
Jack Carter30a59822012-10-04 04:03:53 +00003434 // Check if the current operand has a custom associated parser, if so, try to
3435 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00003436 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
3437 if (ResTy == MatchOperand_Success)
3438 return false;
3439 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3440 // there was a match, but an error occurred, in which case, just return that
3441 // the operand parsing failed.
3442 if (ResTy == MatchOperand_ParseFail)
3443 return true;
3444
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003445 DEBUG(dbgs() << ".. Generic Parser\n");
3446
Jack Carterb4dbc172012-09-05 23:34:03 +00003447 switch (getLexer().getKind()) {
3448 default:
3449 Error(Parser.getTok().getLoc(), "unexpected token in operand");
3450 return true;
3451 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003452 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00003453 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00003454
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003455 // Almost all registers have been parsed by custom parsers. There is only
3456 // one exception to this. $zero (and it's alias $0) will reach this point
3457 // for div, divu, and similar instructions because it is not an operand
3458 // to the instruction definition but an explicit register. Special case
3459 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00003460 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00003461 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003462
Jack Carterd0bd6422013-04-18 00:41:53 +00003463 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00003464 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003465 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00003466 return true;
3467
Jack Carter873c7242013-01-12 01:03:14 +00003468 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00003469 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00003470 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00003471 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003472 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00003473
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003474 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003475 return false;
3476 }
Vladimir Medic4c299852013-11-06 11:27:05 +00003477 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00003478 case AsmToken::LParen:
3479 case AsmToken::Minus:
3480 case AsmToken::Plus:
3481 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00003482 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00003483 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003484 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00003485 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003486 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00003487 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00003488 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003489 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003490 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003491 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00003492 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00003493 return true;
3494
Jack Carter873c7242013-01-12 01:03:14 +00003495 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3496
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003497 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00003498 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003499 } // case AsmToken::Percent
3500 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00003501 return true;
3502}
3503
Vladimir Medic4c299852013-11-06 11:27:05 +00003504const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00003505 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00003506 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00003507 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00003508 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00003509 // It's a constant, evaluate reloc value.
3510 int16_t Val;
3511 switch (getVariantKind(RelocStr)) {
3512 case MCSymbolRefExpr::VK_Mips_ABS_LO:
3513 // Get the 1st 16-bits.
3514 Val = MCE->getValue() & 0xffff;
3515 break;
3516 case MCSymbolRefExpr::VK_Mips_ABS_HI:
3517 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
3518 // 16 bits being negative.
3519 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
3520 break;
3521 case MCSymbolRefExpr::VK_Mips_HIGHER:
3522 // Get the 3rd 16-bits.
3523 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
3524 break;
3525 case MCSymbolRefExpr::VK_Mips_HIGHEST:
3526 // Get the 4th 16-bits.
3527 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
3528 break;
3529 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00003530 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00003531 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00003532 return MCConstantExpr::create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00003533 }
3534
Jack Carterb5cf5902013-04-17 00:18:04 +00003535 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003536 // It's a symbol, create a symbolic expression from the symbol.
Toma Tabacu07c97b32015-06-17 10:43:45 +00003537 const MCSymbol *Symbol = &MSRE->getSymbol();
Jack Carterb5cf5902013-04-17 00:18:04 +00003538 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003539 Res = MCSymbolRefExpr::create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003540 return Res;
3541 }
3542
3543 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00003544 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
3545
Sasa Stankovic06c47802014-04-03 10:37:45 +00003546 // Try to create target expression.
3547 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
Jim Grosbach13760bd2015-05-30 01:25:56 +00003548 return MipsMCExpr::create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00003549
Jack Carterd0bd6422013-04-18 00:41:53 +00003550 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
3551 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003552 Res = MCBinaryExpr::create(BE->getOpcode(), LExp, RExp, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003553 return Res;
3554 }
3555
3556 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003557 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003558 Res = MCUnaryExpr::create(UN->getOpcode(), UnExp, getContext());
Jack Carterd0bd6422013-04-18 00:41:53 +00003559 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00003560 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003561 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00003562 return Expr;
3563}
3564
3565bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
3566
3567 switch (Expr->getKind()) {
3568 case MCExpr::Constant:
3569 return true;
3570 case MCExpr::SymbolRef:
3571 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
3572 case MCExpr::Binary:
3573 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
3574 if (!isEvaluated(BE->getLHS()))
3575 return false;
3576 return isEvaluated(BE->getRHS());
3577 }
3578 case MCExpr::Unary:
3579 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00003580 case MCExpr::Target:
3581 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003582 }
Jack Carterb5cf5902013-04-17 00:18:04 +00003583 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00003584}
Jack Carterd0bd6422013-04-18 00:41:53 +00003585
Jack Carterb5cf5902013-04-17 00:18:04 +00003586bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003587 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00003588 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00003589 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00003590 if (Tok.isNot(AsmToken::Identifier))
3591 return true;
3592
Yaron Keren075759a2015-03-30 15:42:36 +00003593 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00003594
Jack Carterd0bd6422013-04-18 00:41:53 +00003595 Parser.Lex(); // Eat the identifier.
3596 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003597 const MCExpr *IdVal;
3598 SMLoc EndLoc;
3599
3600 if (getLexer().getKind() == AsmToken::LParen) {
3601 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003602 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003603 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003604 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003605 const AsmToken &nextTok = Parser.getTok();
3606 if (nextTok.isNot(AsmToken::Identifier))
3607 return true;
3608 Str += "(%";
3609 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00003610 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00003611 if (getLexer().getKind() != AsmToken::LParen)
3612 return true;
3613 } else
3614 break;
3615 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003616 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00003617 return true;
3618
3619 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00003620 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003621
3622 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00003623 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003624
Jack Carterd0bd6422013-04-18 00:41:53 +00003625 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00003626 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003627}
3628
Jack Carterb4dbc172012-09-05 23:34:03 +00003629bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
3630 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003631 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00003632 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003633 if (ResTy == MatchOperand_Success) {
3634 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00003635 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003636 StartLoc = Operand.getStartLoc();
3637 EndLoc = Operand.getEndLoc();
3638
3639 // AFAIK, we only support numeric registers and named GPR's in CFI
3640 // directives.
3641 // Don't worry about eating tokens before failing. Using an unrecognised
3642 // register is a parse error.
3643 if (Operand.isGPRAsmReg()) {
3644 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003645 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003646 }
3647
3648 return (RegNo == (unsigned)-1);
3649 }
3650
3651 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00003652 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00003653}
3654
Jack Carterb5cf5902013-04-17 00:18:04 +00003655bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003656 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00003657 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00003658 bool Result = true;
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003659 unsigned NumOfLParen = 0;
Jack Carterb5cf5902013-04-17 00:18:04 +00003660
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003661 while (getLexer().getKind() == AsmToken::LParen) {
Jack Carterb5cf5902013-04-17 00:18:04 +00003662 Parser.Lex();
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003663 ++NumOfLParen;
3664 }
Jack Carter873c7242013-01-12 01:03:14 +00003665
Jack Carterd0bd6422013-04-18 00:41:53 +00003666 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00003667 default:
3668 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00003669 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00003670 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00003671 case AsmToken::Integer:
3672 case AsmToken::Minus:
3673 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00003674 if (isParenExpr)
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003675 Result = getParser().parseParenExprOfDepth(NumOfLParen, Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00003676 else
3677 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00003678 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00003679 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003680 break;
Jack Carter873c7242013-01-12 01:03:14 +00003681 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00003682 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00003683 }
Jack Carterb5cf5902013-04-17 00:18:04 +00003684 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003685}
3686
David Blaikie960ea3f2014-06-08 16:18:35 +00003687MipsAsmParser::OperandMatchResultTy
3688MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003689 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003690 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00003691 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00003692 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00003693 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003694 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00003695 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00003696 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00003697
Jack Carterb5cf5902013-04-17 00:18:04 +00003698 if (getLexer().getKind() == AsmToken::LParen) {
3699 Parser.Lex();
3700 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003701 }
3702
Jack Carterb5cf5902013-04-17 00:18:04 +00003703 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003704 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00003705 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003706
Jack Carterd0bd6422013-04-18 00:41:53 +00003707 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003708 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003709 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
Daniel Sandersa39ef1c2015-08-17 10:11:55 +00003710 if (Mnemonic.getToken() == "la" || Mnemonic.getToken() == "dla") {
Vladimir Medic4c299852013-11-06 11:27:05 +00003711 SMLoc E =
3712 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003713 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00003714 return MatchOperand_Success;
3715 }
3716 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003717 SMLoc E =
3718 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00003719
Jack Carterd0bd6422013-04-18 00:41:53 +00003720 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00003721 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00003722 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00003723 S, E, *this);
3724 Operands.push_back(
3725 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00003726 return MatchOperand_Success;
3727 }
3728 Error(Parser.getTok().getLoc(), "'(' expected");
3729 return MatchOperand_ParseFail;
3730 }
3731
Jack Carterd0bd6422013-04-18 00:41:53 +00003732 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003733 }
3734
Toma Tabacu13964452014-09-04 13:23:44 +00003735 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003736 if (Res != MatchOperand_Success)
3737 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003738
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003739 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00003740 Error(Parser.getTok().getLoc(), "')' expected");
3741 return MatchOperand_ParseFail;
3742 }
3743
Jack Carter873c7242013-01-12 01:03:14 +00003744 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3745
Jack Carterd0bd6422013-04-18 00:41:53 +00003746 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003747
Craig Topper062a2ba2014-04-25 05:30:21 +00003748 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003749 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00003750
Jack Carterd0bd6422013-04-18 00:41:53 +00003751 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00003752 std::unique_ptr<MipsOperand> op(
3753 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00003754 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00003755 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003756 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00003757 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003758 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
3759 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00003760 if (IdVal->evaluateAsAbsolute(Imm))
3761 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003762 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003763 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00003764 getContext());
3765 }
3766
David Blaikie960ea3f2014-06-08 16:18:35 +00003767 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003768 return MatchOperand_Success;
3769}
3770
David Blaikie960ea3f2014-06-08 16:18:35 +00003771bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003772 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00003773 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00003774 if (Sym) {
3775 SMLoc S = Parser.getTok().getLoc();
3776 const MCExpr *Expr;
3777 if (Sym->isVariable())
3778 Expr = Sym->getVariableValue();
3779 else
3780 return false;
3781 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003782 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00003783 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00003784 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003785 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00003786 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00003787 if (ResTy == MatchOperand_Success) {
3788 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00003789 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00003790 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003791 llvm_unreachable("Should never ParseFail");
3792 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00003793 }
3794 } else if (Expr->getKind() == MCExpr::Constant) {
3795 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00003796 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00003797 Operands.push_back(
3798 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00003799 return true;
3800 }
3801 }
3802 return false;
3803}
Jack Carterd0bd6422013-04-18 00:41:53 +00003804
Jack Carter873c7242013-01-12 01:03:14 +00003805MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003806MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00003807 StringRef Identifier,
3808 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003809 int Index = matchCPURegisterName(Identifier);
3810 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003811 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003812 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3813 return MatchOperand_Success;
3814 }
3815
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003816 Index = matchHWRegsRegisterName(Identifier);
3817 if (Index != -1) {
3818 Operands.push_back(MipsOperand::createHWRegsReg(
3819 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3820 return MatchOperand_Success;
3821 }
3822
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003823 Index = matchFPURegisterName(Identifier);
3824 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003825 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003826 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3827 return MatchOperand_Success;
3828 }
3829
3830 Index = matchFCCRegisterName(Identifier);
3831 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003832 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003833 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3834 return MatchOperand_Success;
3835 }
3836
3837 Index = matchACRegisterName(Identifier);
3838 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003839 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003840 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3841 return MatchOperand_Success;
3842 }
3843
3844 Index = matchMSA128RegisterName(Identifier);
3845 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003846 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003847 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3848 return MatchOperand_Success;
3849 }
3850
3851 Index = matchMSA128CtrlRegisterName(Identifier);
3852 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003853 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003854 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3855 return MatchOperand_Success;
3856 }
3857
3858 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00003859}
3860
3861MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003862MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003863 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00003864 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003865
3866 if (Token.is(AsmToken::Identifier)) {
3867 DEBUG(dbgs() << ".. identifier\n");
3868 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00003869 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00003870 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00003871 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003872 } else if (Token.is(AsmToken::Integer)) {
3873 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00003874 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003875 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
3876 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003877 return MatchOperand_Success;
3878 }
3879
3880 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
3881
3882 return MatchOperand_NoMatch;
3883}
3884
David Blaikie960ea3f2014-06-08 16:18:35 +00003885MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003886MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003887 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003888 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003889
3890 auto Token = Parser.getTok();
3891
3892 SMLoc S = Token.getLoc();
3893
3894 if (Token.isNot(AsmToken::Dollar)) {
3895 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
3896 if (Token.is(AsmToken::Identifier)) {
3897 if (searchSymbolAlias(Operands))
3898 return MatchOperand_Success;
3899 }
3900 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
3901 return MatchOperand_NoMatch;
3902 }
3903 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003904
Toma Tabacu13964452014-09-04 13:23:44 +00003905 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00003906 if (ResTy == MatchOperand_Success) {
3907 Parser.Lex(); // $
3908 Parser.Lex(); // identifier
3909 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003910 return ResTy;
3911}
3912
3913MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003914MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003915 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003916 switch (getLexer().getKind()) {
3917 default:
3918 return MatchOperand_NoMatch;
3919 case AsmToken::LParen:
3920 case AsmToken::Minus:
3921 case AsmToken::Plus:
3922 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00003923 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003924 case AsmToken::String:
3925 break;
3926 }
3927
3928 const MCExpr *IdVal;
3929 SMLoc S = Parser.getTok().getLoc();
3930 if (getParser().parseExpression(IdVal))
3931 return MatchOperand_ParseFail;
3932
3933 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3934 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
3935 return MatchOperand_Success;
3936}
3937
David Blaikie960ea3f2014-06-08 16:18:35 +00003938MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003939MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003940 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003941 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003942
3943 SMLoc S = getLexer().getLoc();
3944
3945 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00003946 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003947 if (ResTy != MatchOperand_NoMatch)
3948 return ResTy;
3949
Daniel Sanders315386c2014-04-01 10:40:14 +00003950 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00003951 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00003952 if (ResTy != MatchOperand_NoMatch)
3953 return ResTy;
3954
Daniel Sandersffd84362014-04-01 10:41:48 +00003955 const MCExpr *Expr = nullptr;
3956 if (Parser.parseExpression(Expr)) {
3957 // We have no way of knowing if a symbol was consumed so we must ParseFail
3958 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003959 }
Daniel Sandersffd84362014-04-01 10:41:48 +00003960 Operands.push_back(
3961 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003962 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00003963}
3964
Vladimir Medic2b953d02013-10-01 09:48:56 +00003965MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00003966MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003967 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00003968 const MCExpr *IdVal;
3969 // If the first token is '$' we may have register operand.
3970 if (Parser.getTok().is(AsmToken::Dollar))
3971 return MatchOperand_NoMatch;
3972 SMLoc S = Parser.getTok().getLoc();
3973 if (getParser().parseExpression(IdVal))
3974 return MatchOperand_ParseFail;
3975 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00003976 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00003977 int64_t Val = MCE->getValue();
3978 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3979 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003980 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00003981 return MatchOperand_Success;
3982}
3983
Matheus Almeida779c5932013-11-18 12:32:49 +00003984MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003985MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003986 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00003987 switch (getLexer().getKind()) {
3988 default:
3989 return MatchOperand_NoMatch;
3990 case AsmToken::LParen:
3991 case AsmToken::Plus:
3992 case AsmToken::Minus:
3993 case AsmToken::Integer:
3994 break;
3995 }
3996
3997 const MCExpr *Expr;
3998 SMLoc S = Parser.getTok().getLoc();
3999
4000 if (getParser().parseExpression(Expr))
4001 return MatchOperand_ParseFail;
4002
4003 int64_t Val;
Jim Grosbach13760bd2015-05-30 01:25:56 +00004004 if (!Expr->evaluateAsAbsolute(Val)) {
Matheus Almeida779c5932013-11-18 12:32:49 +00004005 Error(S, "expected immediate value");
4006 return MatchOperand_ParseFail;
4007 }
4008
4009 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
4010 // and because the CPU always adds one to the immediate field, the allowed
4011 // range becomes 1..4. We'll only check the range here and will deal
4012 // with the addition/subtraction when actually decoding/encoding
4013 // the instruction.
4014 if (Val < 1 || Val > 4) {
4015 Error(S, "immediate not in range (1..4)");
4016 return MatchOperand_ParseFail;
4017 }
4018
Jack Carter3b2c96e2014-01-22 23:31:38 +00004019 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004020 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00004021 return MatchOperand_Success;
4022}
4023
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00004024MipsAsmParser::OperandMatchResultTy
4025MipsAsmParser::parseRegisterList(OperandVector &Operands) {
4026 MCAsmParser &Parser = getParser();
4027 SmallVector<unsigned, 10> Regs;
4028 unsigned RegNo;
4029 unsigned PrevReg = Mips::NoRegister;
4030 bool RegRange = false;
4031 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4032
4033 if (Parser.getTok().isNot(AsmToken::Dollar))
4034 return MatchOperand_ParseFail;
4035
4036 SMLoc S = Parser.getTok().getLoc();
4037 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
4038 SMLoc E = getLexer().getLoc();
4039 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
4040 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
4041 if (RegRange) {
4042 // Remove last register operand because registers from register range
4043 // should be inserted first.
4044 if (RegNo == Mips::RA) {
4045 Regs.push_back(RegNo);
4046 } else {
4047 unsigned TmpReg = PrevReg + 1;
4048 while (TmpReg <= RegNo) {
4049 if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
4050 Error(E, "invalid register operand");
4051 return MatchOperand_ParseFail;
4052 }
4053
4054 PrevReg = TmpReg;
4055 Regs.push_back(TmpReg++);
4056 }
4057 }
4058
4059 RegRange = false;
4060 } else {
4061 if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
4062 (RegNo != Mips::RA)) {
4063 Error(E, "$16 or $31 expected");
4064 return MatchOperand_ParseFail;
4065 } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
4066 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
4067 Error(E, "invalid register operand");
4068 return MatchOperand_ParseFail;
4069 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
4070 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
4071 Error(E, "consecutive register numbers expected");
4072 return MatchOperand_ParseFail;
4073 }
4074
4075 Regs.push_back(RegNo);
4076 }
4077
4078 if (Parser.getTok().is(AsmToken::Minus))
4079 RegRange = true;
4080
4081 if (!Parser.getTok().isNot(AsmToken::Minus) &&
4082 !Parser.getTok().isNot(AsmToken::Comma)) {
4083 Error(E, "',' or '-' expected");
4084 return MatchOperand_ParseFail;
4085 }
4086
4087 Lex(); // Consume comma or minus
4088 if (Parser.getTok().isNot(AsmToken::Dollar))
4089 break;
4090
4091 PrevReg = RegNo;
4092 }
4093
4094 SMLoc E = Parser.getTok().getLoc();
4095 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4096 parseMemOperand(Operands);
4097 return MatchOperand_Success;
4098}
4099
Zoran Jovanovic2deca342014-12-16 14:59:10 +00004100MipsAsmParser::OperandMatchResultTy
4101MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
4102 MCAsmParser &Parser = getParser();
4103
4104 SMLoc S = Parser.getTok().getLoc();
4105 if (parseAnyRegister(Operands) != MatchOperand_Success)
4106 return MatchOperand_ParseFail;
4107
4108 SMLoc E = Parser.getTok().getLoc();
4109 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
4110 unsigned Reg = Op.getGPR32Reg();
4111 Operands.pop_back();
4112 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
4113 return MatchOperand_Success;
4114}
4115
Zoran Jovanovic41688672015-02-10 16:36:20 +00004116MipsAsmParser::OperandMatchResultTy
4117MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
4118 MCAsmParser &Parser = getParser();
4119 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
4120 SmallVector<unsigned, 10> Regs;
4121
4122 if (Parser.getTok().isNot(AsmToken::Dollar))
4123 return MatchOperand_ParseFail;
4124
4125 SMLoc S = Parser.getTok().getLoc();
4126
4127 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4128 return MatchOperand_ParseFail;
4129
4130 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4131 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4132 Regs.push_back(RegNo);
4133
4134 SMLoc E = Parser.getTok().getLoc();
4135 if (Parser.getTok().isNot(AsmToken::Comma)) {
4136 Error(E, "',' expected");
4137 return MatchOperand_ParseFail;
4138 }
4139
4140 // Remove comma.
4141 Parser.Lex();
4142
4143 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
4144 return MatchOperand_ParseFail;
4145
4146 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
4147 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
4148 Regs.push_back(RegNo);
4149
4150 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
4151
4152 return MatchOperand_Success;
4153}
4154
Jack Carterdc1e35d2012-09-06 20:00:02 +00004155MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
4156
Vladimir Medic4c299852013-11-06 11:27:05 +00004157 MCSymbolRefExpr::VariantKind VK =
4158 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
4159 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
4160 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
4161 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
4162 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
4163 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
4164 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
4165 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
4166 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
4167 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
4168 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
4169 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
4170 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
4171 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
4172 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
4173 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
4174 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
4175 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00004176 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
4177 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
4178 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
4179 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
4180 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
4181 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00004182 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
4183 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00004184 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00004185
Matheus Almeida2852af82014-04-22 10:15:54 +00004186 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00004187
Jack Carterdc1e35d2012-09-06 20:00:02 +00004188 return VK;
4189}
Jack Cartera63b16a2012-09-07 00:23:42 +00004190
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004191/// Sometimes (i.e. load/stores) the operand may be followed immediately by
4192/// either this.
4193/// ::= '(', register, ')'
4194/// handle it before we iterate so we don't get tripped up by the lack of
4195/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004196bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004197 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004198 if (getLexer().is(AsmToken::LParen)) {
4199 Operands.push_back(
4200 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
4201 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004202 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004203 SMLoc Loc = getLexer().getLoc();
4204 Parser.eatToEndOfStatement();
4205 return Error(Loc, "unexpected token in argument list");
4206 }
4207 if (Parser.getTok().isNot(AsmToken::RParen)) {
4208 SMLoc Loc = getLexer().getLoc();
4209 Parser.eatToEndOfStatement();
4210 return Error(Loc, "unexpected token, expected ')'");
4211 }
4212 Operands.push_back(
4213 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
4214 Parser.Lex();
4215 }
4216 return false;
4217}
4218
4219/// Sometimes (i.e. in MSA) the operand may be followed immediately by
4220/// either one of these.
4221/// ::= '[', register, ']'
4222/// ::= '[', integer, ']'
4223/// handle it before we iterate so we don't get tripped up by the lack of
4224/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00004225bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00004226 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004227 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004228 if (getLexer().is(AsmToken::LBrac)) {
4229 Operands.push_back(
4230 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
4231 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00004232 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004233 SMLoc Loc = getLexer().getLoc();
4234 Parser.eatToEndOfStatement();
4235 return Error(Loc, "unexpected token in argument list");
4236 }
4237 if (Parser.getTok().isNot(AsmToken::RBrac)) {
4238 SMLoc Loc = getLexer().getLoc();
4239 Parser.eatToEndOfStatement();
4240 return Error(Loc, "unexpected token, expected ']'");
4241 }
4242 Operands.push_back(
4243 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
4244 Parser.Lex();
4245 }
4246 return false;
4247}
4248
David Blaikie960ea3f2014-06-08 16:18:35 +00004249bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
4250 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004251 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004252 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004253
4254 // We have reached first instruction, module directive are now forbidden.
4255 getTargetStreamer().forbidModuleDirective();
4256
Vladimir Medic74593e62013-07-17 15:00:42 +00004257 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00004258 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00004259 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00004260 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00004261 }
Vladimir Medic64828a12013-07-16 10:07:14 +00004262 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004263 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00004264
4265 // Read the remaining operands.
4266 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4267 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004268 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004269 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004270 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004271 return Error(Loc, "unexpected token in argument list");
4272 }
Toma Tabacu13964452014-09-04 13:23:44 +00004273 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004274 return true;
4275 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00004276
Jack Carterd0bd6422013-04-18 00:41:53 +00004277 while (getLexer().is(AsmToken::Comma)) {
4278 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00004279 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00004280 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00004281 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004282 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004283 return Error(Loc, "unexpected token in argument list");
4284 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004285 // Parse bracket and parenthesis suffixes before we iterate
4286 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00004287 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004288 return true;
4289 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00004290 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00004291 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00004292 }
4293 }
Jack Carterb4dbc172012-09-05 23:34:03 +00004294 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4295 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004296 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00004297 return Error(Loc, "unexpected token in argument list");
4298 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004299 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00004300 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00004301}
4302
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004303bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004304 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004305 SMLoc Loc = getLexer().getLoc();
4306 Parser.eatToEndOfStatement();
4307 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00004308}
4309
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004310bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004311 return Error(Loc, ErrorMsg);
4312}
4313
Jack Carter0b744b32012-10-04 02:29:46 +00004314bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004315 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004316 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00004317
4318 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00004319 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00004320
4321 Parser.Lex(); // Eat "noat".
4322
Jack Carterd0bd6422013-04-18 00:41:53 +00004323 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004324 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004325 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004326 return false;
4327 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004328
4329 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004330 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004331 return false;
4332}
Jack Carterd0bd6422013-04-18 00:41:53 +00004333
Jack Carter0b744b32012-10-04 02:29:46 +00004334bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00004335 // Line can be: ".set at", which sets $at to $1
4336 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00004337 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00004338 Parser.Lex(); // Eat "at".
4339
Jack Carter0b744b32012-10-04 02:29:46 +00004340 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004341 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00004342 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00004343
4344 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00004345 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004346 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00004347 }
4348
4349 if (getLexer().isNot(AsmToken::Equal)) {
4350 reportParseError("unexpected token, expected equals sign");
4351 return false;
4352 }
4353 Parser.Lex(); // Eat "=".
4354
4355 if (getLexer().isNot(AsmToken::Dollar)) {
4356 if (getLexer().is(AsmToken::EndOfStatement)) {
4357 reportParseError("no register specified");
4358 return false;
4359 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00004360 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00004361 return false;
4362 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004363 }
4364 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00004365
Toma Tabacu16a74492015-02-13 10:30:57 +00004366 // Find out what "reg" is.
4367 unsigned AtRegNo;
4368 const AsmToken &Reg = Parser.getTok();
4369 if (Reg.is(AsmToken::Identifier)) {
4370 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
4371 } else if (Reg.is(AsmToken::Integer)) {
4372 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00004373 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00004374 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00004375 return false;
4376 }
Toma Tabacu16a74492015-02-13 10:30:57 +00004377
4378 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00004379 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00004380 reportParseError("invalid register");
4381 return false;
4382 }
4383 Parser.Lex(); // Eat "reg".
4384
4385 // If this is not the end of the statement, report an error.
4386 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4387 reportParseError("unexpected token, expected end of statement");
4388 return false;
4389 }
4390
4391 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
4392
4393 Parser.Lex(); // Consume the EndOfStatement.
4394 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004395}
4396
4397bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004398 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004399 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004400 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004401 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004402 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004403 return false;
4404 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004405 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00004406 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004407 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004408 return false;
4409}
4410
4411bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004412 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004413 Parser.Lex();
4414 // If this is not the end of the statement, report an error.
4415 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004416 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004417 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00004418 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004419 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00004420 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00004421 Parser.Lex(); // Consume the EndOfStatement.
4422 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004423}
4424
4425bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004426 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004427 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004428 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004429 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004430 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004431 return false;
4432 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004433 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004434 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004435 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004436 return false;
4437}
4438
4439bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004440 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00004441 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00004442 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00004443 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004444 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004445 return false;
4446 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004447 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00004448 reportParseError("`noreorder' must be set before `nomacro'");
4449 return false;
4450 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004451 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004452 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004453 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004454 return false;
4455}
Jack Carterd76b2372013-03-21 21:44:16 +00004456
Daniel Sanders44934432014-08-07 12:03:36 +00004457bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004458 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004459 Parser.Lex();
4460
4461 // If this is not the end of the statement, report an error.
4462 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004463 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004464
4465 setFeatureBits(Mips::FeatureMSA, "msa");
4466 getTargetStreamer().emitDirectiveSetMsa();
4467 return false;
4468}
4469
4470bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004471 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004472 Parser.Lex();
4473
4474 // If this is not the end of the statement, report an error.
4475 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004476 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004477
4478 clearFeatureBits(Mips::FeatureMSA, "msa");
4479 getTargetStreamer().emitDirectiveSetNoMsa();
4480 return false;
4481}
4482
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004483bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004484 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004485 Parser.Lex(); // Eat "nodsp".
4486
4487 // If this is not the end of the statement, report an error.
4488 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4489 reportParseError("unexpected token, expected end of statement");
4490 return false;
4491 }
4492
4493 clearFeatureBits(Mips::FeatureDSP, "dsp");
4494 getTargetStreamer().emitDirectiveSetNoDsp();
4495 return false;
4496}
4497
Toma Tabacucc2502d2014-11-04 17:18:07 +00004498bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004499 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00004500 Parser.Lex(); // Eat "mips16".
4501
Jack Carter39536722014-01-22 23:08:42 +00004502 // If this is not the end of the statement, report an error.
4503 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004504 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00004505 return false;
4506 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00004507
4508 setFeatureBits(Mips::FeatureMips16, "mips16");
4509 getTargetStreamer().emitDirectiveSetMips16();
4510 Parser.Lex(); // Consume the EndOfStatement.
4511 return false;
4512}
4513
4514bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004515 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00004516 Parser.Lex(); // Eat "nomips16".
4517
4518 // If this is not the end of the statement, report an error.
4519 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4520 reportParseError("unexpected token, expected end of statement");
4521 return false;
4522 }
4523
4524 clearFeatureBits(Mips::FeatureMips16, "mips16");
4525 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00004526 Parser.Lex(); // Consume the EndOfStatement.
4527 return false;
4528}
4529
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004530bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004531 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004532 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004533 // Line can be: .set fp=32
4534 // .set fp=xx
4535 // .set fp=64
4536 Parser.Lex(); // Eat fp token
4537 AsmToken Tok = Parser.getTok();
4538 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004539 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004540 return false;
4541 }
4542 Parser.Lex(); // Eat '=' token.
4543 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004544
4545 if (!parseFpABIValue(FpAbiVal, ".set"))
4546 return false;
4547
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004548 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004549 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004550 return false;
4551 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004552 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004553 Parser.Lex(); // Consume the EndOfStatement.
4554 return false;
4555}
4556
Toma Tabacu32c72aa2015-06-30 09:36:50 +00004557bool MipsAsmParser::parseSetOddSPRegDirective() {
4558 MCAsmParser &Parser = getParser();
4559
4560 Parser.Lex(); // Eat "oddspreg".
4561 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4562 reportParseError("unexpected token, expected end of statement");
4563 return false;
4564 }
4565
4566 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4567 getTargetStreamer().emitDirectiveSetOddSPReg();
4568 return false;
4569}
4570
4571bool MipsAsmParser::parseSetNoOddSPRegDirective() {
4572 MCAsmParser &Parser = getParser();
4573
4574 Parser.Lex(); // Eat "nooddspreg".
4575 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4576 reportParseError("unexpected token, expected end of statement");
4577 return false;
4578 }
4579
4580 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4581 getTargetStreamer().emitDirectiveSetNoOddSPReg();
4582 return false;
4583}
4584
Toma Tabacu9db22db2014-09-09 10:15:38 +00004585bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004586 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004587 SMLoc Loc = getLexer().getLoc();
4588
4589 Parser.Lex();
4590 if (getLexer().isNot(AsmToken::EndOfStatement))
4591 return reportParseError("unexpected token, expected end of statement");
4592
4593 // Always keep an element on the options "stack" to prevent the user
4594 // from changing the initial options. This is how we remember them.
4595 if (AssemblerOptions.size() == 2)
4596 return reportParseError(Loc, ".set pop with no .set push");
4597
4598 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00004599 setAvailableFeatures(
4600 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
4601 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00004602
4603 getTargetStreamer().emitDirectiveSetPop();
4604 return false;
4605}
4606
4607bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004608 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004609 Parser.Lex();
4610 if (getLexer().isNot(AsmToken::EndOfStatement))
4611 return reportParseError("unexpected token, expected end of statement");
4612
4613 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00004614 AssemblerOptions.push_back(
4615 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00004616
4617 getTargetStreamer().emitDirectiveSetPush();
4618 return false;
4619}
4620
Toma Tabacu29696502015-06-02 09:48:04 +00004621bool MipsAsmParser::parseSetSoftFloatDirective() {
4622 MCAsmParser &Parser = getParser();
4623 Parser.Lex();
4624 if (getLexer().isNot(AsmToken::EndOfStatement))
4625 return reportParseError("unexpected token, expected end of statement");
4626
4627 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
4628 getTargetStreamer().emitDirectiveSetSoftFloat();
4629 return false;
4630}
4631
4632bool MipsAsmParser::parseSetHardFloatDirective() {
4633 MCAsmParser &Parser = getParser();
4634 Parser.Lex();
4635 if (getLexer().isNot(AsmToken::EndOfStatement))
4636 return reportParseError("unexpected token, expected end of statement");
4637
4638 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
4639 getTargetStreamer().emitDirectiveSetHardFloat();
4640 return false;
4641}
4642
Jack Carterd76b2372013-03-21 21:44:16 +00004643bool MipsAsmParser::parseSetAssignment() {
4644 StringRef Name;
4645 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00004646 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00004647
4648 if (Parser.parseIdentifier(Name))
4649 reportParseError("expected identifier after .set");
4650
4651 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00004652 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00004653 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00004654
Jack Carter3b2c96e2014-01-22 23:31:38 +00004655 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00004656 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00004657
Jim Grosbach6f482002015-05-18 18:43:14 +00004658 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00004659 Sym->setVariableValue(Value);
4660
4661 return false;
4662}
Jack Carterd0bd6422013-04-18 00:41:53 +00004663
Toma Tabacu26647792014-09-09 12:52:14 +00004664bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004665 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00004666 Parser.Lex();
4667 if (getLexer().isNot(AsmToken::EndOfStatement))
4668 return reportParseError("unexpected token, expected end of statement");
4669
4670 // Reset assembler options to their initial values.
Toma Tabacu465acfd2015-06-09 13:33:26 +00004671 setAvailableFeatures(
4672 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
4673 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00004674 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
4675
4676 getTargetStreamer().emitDirectiveSetMips0();
4677 return false;
4678}
4679
Toma Tabacu85618b32014-08-19 14:22:52 +00004680bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004681 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00004682 Parser.Lex();
4683 if (getLexer().isNot(AsmToken::Equal))
4684 return reportParseError("unexpected token, expected equals sign");
4685
4686 Parser.Lex();
4687 StringRef Arch;
4688 if (Parser.parseIdentifier(Arch))
4689 return reportParseError("expected arch identifier");
4690
4691 StringRef ArchFeatureName =
4692 StringSwitch<StringRef>(Arch)
4693 .Case("mips1", "mips1")
4694 .Case("mips2", "mips2")
4695 .Case("mips3", "mips3")
4696 .Case("mips4", "mips4")
4697 .Case("mips5", "mips5")
4698 .Case("mips32", "mips32")
4699 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00004700 .Case("mips32r3", "mips32r3")
4701 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00004702 .Case("mips32r6", "mips32r6")
4703 .Case("mips64", "mips64")
4704 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00004705 .Case("mips64r3", "mips64r3")
4706 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00004707 .Case("mips64r6", "mips64r6")
4708 .Case("cnmips", "cnmips")
4709 .Case("r4000", "mips3") // This is an implementation of Mips3.
4710 .Default("");
4711
4712 if (ArchFeatureName.empty())
4713 return reportParseError("unsupported architecture");
4714
4715 selectArch(ArchFeatureName);
4716 getTargetStreamer().emitDirectiveSetArch(Arch);
4717 return false;
4718}
4719
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004720bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004721 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004722 Parser.Lex();
4723 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004724 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004725
Matheus Almeida2852af82014-04-22 10:15:54 +00004726 switch (Feature) {
4727 default:
4728 llvm_unreachable("Unimplemented feature");
4729 case Mips::FeatureDSP:
4730 setFeatureBits(Mips::FeatureDSP, "dsp");
4731 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004732 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004733 case Mips::FeatureMicroMips:
4734 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004735 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004736 case Mips::FeatureMips1:
4737 selectArch("mips1");
4738 getTargetStreamer().emitDirectiveSetMips1();
4739 break;
4740 case Mips::FeatureMips2:
4741 selectArch("mips2");
4742 getTargetStreamer().emitDirectiveSetMips2();
4743 break;
4744 case Mips::FeatureMips3:
4745 selectArch("mips3");
4746 getTargetStreamer().emitDirectiveSetMips3();
4747 break;
4748 case Mips::FeatureMips4:
4749 selectArch("mips4");
4750 getTargetStreamer().emitDirectiveSetMips4();
4751 break;
4752 case Mips::FeatureMips5:
4753 selectArch("mips5");
4754 getTargetStreamer().emitDirectiveSetMips5();
4755 break;
4756 case Mips::FeatureMips32:
4757 selectArch("mips32");
4758 getTargetStreamer().emitDirectiveSetMips32();
4759 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004760 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004761 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00004762 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004763 break;
Daniel Sanders17793142015-02-18 16:24:50 +00004764 case Mips::FeatureMips32r3:
4765 selectArch("mips32r3");
4766 getTargetStreamer().emitDirectiveSetMips32R3();
4767 break;
4768 case Mips::FeatureMips32r5:
4769 selectArch("mips32r5");
4770 getTargetStreamer().emitDirectiveSetMips32R5();
4771 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004772 case Mips::FeatureMips32r6:
4773 selectArch("mips32r6");
4774 getTargetStreamer().emitDirectiveSetMips32R6();
4775 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004776 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004777 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00004778 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00004779 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004780 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004781 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00004782 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00004783 break;
Daniel Sanders17793142015-02-18 16:24:50 +00004784 case Mips::FeatureMips64r3:
4785 selectArch("mips64r3");
4786 getTargetStreamer().emitDirectiveSetMips64R3();
4787 break;
4788 case Mips::FeatureMips64r5:
4789 selectArch("mips64r5");
4790 getTargetStreamer().emitDirectiveSetMips64R5();
4791 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004792 case Mips::FeatureMips64r6:
4793 selectArch("mips64r6");
4794 getTargetStreamer().emitDirectiveSetMips64R6();
4795 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004796 }
4797 return false;
4798}
4799
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004800bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004801 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004802 if (getLexer().isNot(AsmToken::Comma)) {
4803 SMLoc Loc = getLexer().getLoc();
4804 Parser.eatToEndOfStatement();
4805 return Error(Loc, ErrorStr);
4806 }
4807
Matheus Almeida2852af82014-04-22 10:15:54 +00004808 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004809 return true;
4810}
4811
Daniel Sanderse2982ad2015-09-17 16:08:39 +00004812// Used to determine if .cpload, .cprestore, and .cpsetup have any effect.
4813// In this class, it is only used for .cprestore.
4814// FIXME: Only keep track of IsPicEnabled in one place, instead of in both
4815// MipsTargetELFStreamer and MipsAsmParser.
4816bool MipsAsmParser::isPicAndNotNxxAbi() {
4817 return inPicMode() && !(isABI_N32() || isABI_N64());
4818}
4819
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004820bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00004821 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00004822 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004823
Toma Tabacudde4c462014-11-06 10:02:45 +00004824 if (inMips16Mode()) {
4825 reportParseError(".cpload is not supported in Mips16 mode");
4826 return false;
4827 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004828
David Blaikie960ea3f2014-06-08 16:18:35 +00004829 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00004830 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004831 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4832 reportParseError("expected register containing function address");
4833 return false;
4834 }
4835
David Blaikie960ea3f2014-06-08 16:18:35 +00004836 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
4837 if (!RegOpnd.isGPRAsmReg()) {
4838 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004839 return false;
4840 }
4841
Toma Tabacudde4c462014-11-06 10:02:45 +00004842 // If this is not the end of the statement, report an error.
4843 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4844 reportParseError("unexpected token, expected end of statement");
4845 return false;
4846 }
4847
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004848 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004849 return false;
4850}
4851
Daniel Sanderse2982ad2015-09-17 16:08:39 +00004852bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
4853 MCAsmParser &Parser = getParser();
4854
4855 // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
4856 // is used in non-PIC mode.
4857
4858 if (inMips16Mode()) {
4859 reportParseError(".cprestore is not supported in Mips16 mode");
4860 return false;
4861 }
4862
4863 // Get the stack offset value.
4864 const MCExpr *StackOffset;
4865 int64_t StackOffsetVal;
4866 if (Parser.parseExpression(StackOffset)) {
4867 reportParseError("expected stack offset value");
4868 return false;
4869 }
4870
4871 if (!StackOffset->evaluateAsAbsolute(StackOffsetVal)) {
4872 reportParseError("stack offset is not an absolute expression");
4873 return false;
4874 }
4875
4876 if (StackOffsetVal < 0) {
4877 Warning(Loc, ".cprestore with negative stack offset has no effect");
4878 IsCpRestoreSet = false;
4879 } else {
4880 IsCpRestoreSet = true;
4881 CpRestoreOffset = StackOffsetVal;
4882 }
4883
4884 // If this is not the end of the statement, report an error.
4885 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4886 reportParseError("unexpected token, expected end of statement");
4887 return false;
4888 }
4889
4890 // Store the $gp on the stack.
4891 SmallVector<MCInst, 3> StoreInsts;
4892 createCpRestoreMemOp(false /*IsLoad*/, CpRestoreOffset /*StackOffset*/, Loc,
4893 StoreInsts);
4894
4895 getTargetStreamer().emitDirectiveCpRestore(StoreInsts, CpRestoreOffset);
4896 Parser.Lex(); // Consume the EndOfStatement.
4897 return false;
4898}
4899
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004900bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004901 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004902 unsigned FuncReg;
4903 unsigned Save;
4904 bool SaveIsReg = true;
4905
Matheus Almeida7e815762014-06-18 13:08:59 +00004906 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00004907 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00004908 if (ResTy == MatchOperand_NoMatch) {
4909 reportParseError("expected register containing function address");
4910 Parser.eatToEndOfStatement();
4911 return false;
4912 }
4913
4914 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4915 if (!FuncRegOpnd.isGPRAsmReg()) {
4916 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
4917 Parser.eatToEndOfStatement();
4918 return false;
4919 }
4920
4921 FuncReg = FuncRegOpnd.getGPR32Reg();
4922 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004923
Toma Tabacu65f10572014-09-16 15:00:52 +00004924 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004925 return true;
4926
Toma Tabacu13964452014-09-04 13:23:44 +00004927 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00004928 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5d796282015-09-21 09:26:55 +00004929 const MCExpr *OffsetExpr;
4930 int64_t OffsetVal;
4931 SMLoc ExprLoc = getLexer().getLoc();
4932
4933 if (Parser.parseExpression(OffsetExpr) ||
4934 !OffsetExpr->evaluateAsAbsolute(OffsetVal)) {
4935 reportParseError(ExprLoc, "expected save register or stack offset");
Matheus Almeida7e815762014-06-18 13:08:59 +00004936 Parser.eatToEndOfStatement();
4937 return false;
4938 }
Daniel Sanders5d796282015-09-21 09:26:55 +00004939
4940 Save = OffsetVal;
4941 SaveIsReg = false;
Matheus Almeida7e815762014-06-18 13:08:59 +00004942 } else {
4943 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4944 if (!SaveOpnd.isGPRAsmReg()) {
4945 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
4946 Parser.eatToEndOfStatement();
4947 return false;
4948 }
4949 Save = SaveOpnd.getGPR32Reg();
4950 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004951
Toma Tabacu65f10572014-09-16 15:00:52 +00004952 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004953 return true;
4954
Toma Tabacu8874eac2015-02-18 13:46:53 +00004955 const MCExpr *Expr;
4956 if (Parser.parseExpression(Expr)) {
4957 reportParseError("expected expression");
4958 return false;
4959 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004960
Toma Tabacu8874eac2015-02-18 13:46:53 +00004961 if (Expr->getKind() != MCExpr::SymbolRef) {
4962 reportParseError("expected symbol");
4963 return false;
4964 }
4965 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
4966
4967 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
4968 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004969 return false;
4970}
4971
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004972bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004973 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004974 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4975 const AsmToken &Tok = Parser.getTok();
4976
4977 if (Tok.getString() == "2008") {
4978 Parser.Lex();
4979 getTargetStreamer().emitDirectiveNaN2008();
4980 return false;
4981 } else if (Tok.getString() == "legacy") {
4982 Parser.Lex();
4983 getTargetStreamer().emitDirectiveNaNLegacy();
4984 return false;
4985 }
4986 }
4987 // If we don't recognize the option passed to the .nan
4988 // directive (e.g. no option or unknown option), emit an error.
4989 reportParseError("invalid option in .nan directive");
4990 return false;
4991}
4992
Jack Carter0b744b32012-10-04 02:29:46 +00004993bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004994 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004995 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00004996 const AsmToken &Tok = Parser.getTok();
4997
4998 if (Tok.getString() == "noat") {
4999 return parseSetNoAtDirective();
5000 } else if (Tok.getString() == "at") {
5001 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00005002 } else if (Tok.getString() == "arch") {
5003 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005004 } else if (Tok.getString() == "fp") {
5005 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00005006 } else if (Tok.getString() == "oddspreg") {
5007 return parseSetOddSPRegDirective();
5008 } else if (Tok.getString() == "nooddspreg") {
5009 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00005010 } else if (Tok.getString() == "pop") {
5011 return parseSetPopDirective();
5012 } else if (Tok.getString() == "push") {
5013 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00005014 } else if (Tok.getString() == "reorder") {
5015 return parseSetReorderDirective();
5016 } else if (Tok.getString() == "noreorder") {
5017 return parseSetNoReorderDirective();
5018 } else if (Tok.getString() == "macro") {
5019 return parseSetMacroDirective();
5020 } else if (Tok.getString() == "nomacro") {
5021 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00005022 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00005023 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005024 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00005025 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00005026 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00005027 getTargetStreamer().emitDirectiveSetNoMicroMips();
5028 Parser.eatToEndOfStatement();
5029 return false;
5030 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005031 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00005032 } else if (Tok.getString() == "mips0") {
5033 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00005034 } else if (Tok.getString() == "mips1") {
5035 return parseSetFeature(Mips::FeatureMips1);
5036 } else if (Tok.getString() == "mips2") {
5037 return parseSetFeature(Mips::FeatureMips2);
5038 } else if (Tok.getString() == "mips3") {
5039 return parseSetFeature(Mips::FeatureMips3);
5040 } else if (Tok.getString() == "mips4") {
5041 return parseSetFeature(Mips::FeatureMips4);
5042 } else if (Tok.getString() == "mips5") {
5043 return parseSetFeature(Mips::FeatureMips5);
5044 } else if (Tok.getString() == "mips32") {
5045 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00005046 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005047 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005048 } else if (Tok.getString() == "mips32r3") {
5049 return parseSetFeature(Mips::FeatureMips32r3);
5050 } else if (Tok.getString() == "mips32r5") {
5051 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005052 } else if (Tok.getString() == "mips32r6") {
5053 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00005054 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005055 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00005056 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005057 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00005058 } else if (Tok.getString() == "mips64r3") {
5059 return parseSetFeature(Mips::FeatureMips64r3);
5060 } else if (Tok.getString() == "mips64r5") {
5061 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00005062 } else if (Tok.getString() == "mips64r6") {
5063 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00005064 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00005065 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00005066 } else if (Tok.getString() == "nodsp") {
5067 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00005068 } else if (Tok.getString() == "msa") {
5069 return parseSetMsaDirective();
5070 } else if (Tok.getString() == "nomsa") {
5071 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00005072 } else if (Tok.getString() == "softfloat") {
5073 return parseSetSoftFloatDirective();
5074 } else if (Tok.getString() == "hardfloat") {
5075 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00005076 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00005077 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00005078 parseSetAssignment();
5079 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00005080 }
Jack Carter07c818d2013-01-25 01:31:34 +00005081
Jack Carter0b744b32012-10-04 02:29:46 +00005082 return true;
5083}
5084
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005085/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00005086/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005087bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005088 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005089 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5090 for (;;) {
5091 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005092 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00005093 return true;
5094
5095 getParser().getStreamer().EmitValue(Value, Size);
5096
5097 if (getLexer().is(AsmToken::EndOfStatement))
5098 break;
5099
Jack Carter07c818d2013-01-25 01:31:34 +00005100 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00005101 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00005102 Parser.Lex();
5103 }
5104 }
5105
5106 Parser.Lex();
5107 return false;
5108}
5109
Vladimir Medic4c299852013-11-06 11:27:05 +00005110/// parseDirectiveGpWord
5111/// ::= .gpword local_sym
5112bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005113 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00005114 const MCExpr *Value;
5115 // EmitGPRel32Value requires an expression, so we are using base class
5116 // method to evaluate the expression.
5117 if (getParser().parseExpression(Value))
5118 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00005119 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00005120
Vladimir Medice10c1122013-11-13 13:18:04 +00005121 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005122 return Error(getLexer().getLoc(),
5123 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00005124 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00005125 return false;
5126}
5127
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005128/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00005129/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005130bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005131 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005132 const MCExpr *Value;
5133 // EmitGPRel64Value requires an expression, so we are using base class
5134 // method to evaluate the expression.
5135 if (getParser().parseExpression(Value))
5136 return true;
5137 getParser().getStreamer().EmitGPRel64Value(Value);
5138
5139 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00005140 return Error(getLexer().getLoc(),
5141 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00005142 Parser.Lex(); // Eat EndOfStatement token.
5143 return false;
5144}
5145
Jack Carter0cd3c192014-01-06 23:27:31 +00005146bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005147 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00005148 // Get the option token.
5149 AsmToken Tok = Parser.getTok();
5150 // At the moment only identifiers are supported.
5151 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005152 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00005153 Parser.eatToEndOfStatement();
5154 return false;
5155 }
5156
5157 StringRef Option = Tok.getIdentifier();
5158
5159 if (Option == "pic0") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005160 // MipsAsmParser needs to know if the current PIC mode changes.
5161 IsPicEnabled = false;
5162
Jack Carter0cd3c192014-01-06 23:27:31 +00005163 getTargetStreamer().emitDirectiveOptionPic0();
5164 Parser.Lex();
5165 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5166 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005167 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005168 Parser.eatToEndOfStatement();
5169 }
5170 return false;
5171 }
5172
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005173 if (Option == "pic2") {
Daniel Sandersa6994442015-08-18 12:33:54 +00005174 // MipsAsmParser needs to know if the current PIC mode changes.
5175 IsPicEnabled = true;
5176
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005177 getTargetStreamer().emitDirectiveOptionPic2();
5178 Parser.Lex();
5179 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
5180 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00005181 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00005182 Parser.eatToEndOfStatement();
5183 }
5184 return false;
5185 }
5186
Jack Carter0cd3c192014-01-06 23:27:31 +00005187 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00005188 Warning(Parser.getTok().getLoc(),
5189 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00005190 Parser.eatToEndOfStatement();
5191 return false;
5192}
5193
Toma Tabacu9ca50962015-04-16 09:53:47 +00005194/// parseInsnDirective
5195/// ::= .insn
5196bool MipsAsmParser::parseInsnDirective() {
5197 // If this is not the end of the statement, report an error.
5198 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5199 reportParseError("unexpected token, expected end of statement");
5200 return false;
5201 }
5202
5203 // The actual label marking happens in
5204 // MipsELFStreamer::createPendingLabelRelocs().
5205 getTargetStreamer().emitDirectiveInsn();
5206
5207 getParser().Lex(); // Eat EndOfStatement token.
5208 return false;
5209}
5210
Daniel Sanders7e527422014-07-10 13:38:23 +00005211/// parseDirectiveModule
5212/// ::= .module oddspreg
5213/// ::= .module nooddspreg
5214/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00005215/// ::= .module softfloat
5216/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005217bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005218 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005219 MCAsmLexer &Lexer = getLexer();
5220 SMLoc L = Lexer.getLoc();
5221
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00005222 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005223 // TODO : get a better message.
5224 reportParseError(".module directive must appear before any code");
5225 return false;
5226 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005227
Toma Tabacuc405c822015-01-23 10:40:19 +00005228 StringRef Option;
5229 if (Parser.parseIdentifier(Option)) {
5230 reportParseError("expected .module option identifier");
5231 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005232 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005233
Toma Tabacuc405c822015-01-23 10:40:19 +00005234 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005235 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005236
Toma Tabacu3c499582015-06-25 10:56:57 +00005237 // Synchronize the abiflags information with the FeatureBits information we
5238 // changed above.
5239 getTargetStreamer().updateABIInfo(*this);
5240
5241 // If printing assembly, use the recently updated abiflags information.
5242 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5243 // emitted at the end).
5244 getTargetStreamer().emitDirectiveModuleOddSPReg();
5245
Toma Tabacuc405c822015-01-23 10:40:19 +00005246 // If this is not the end of the statement, report an error.
5247 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5248 reportParseError("unexpected token, expected end of statement");
5249 return false;
5250 }
5251
5252 return false; // parseDirectiveModule has finished successfully.
5253 } else if (Option == "nooddspreg") {
5254 if (!isABI_O32()) {
5255 Error(L, "'.module nooddspreg' requires the O32 ABI");
5256 return false;
5257 }
5258
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005259 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00005260
Toma Tabacu3c499582015-06-25 10:56:57 +00005261 // Synchronize the abiflags information with the FeatureBits information we
5262 // changed above.
5263 getTargetStreamer().updateABIInfo(*this);
5264
5265 // If printing assembly, use the recently updated abiflags information.
5266 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5267 // emitted at the end).
5268 getTargetStreamer().emitDirectiveModuleOddSPReg();
5269
Toma Tabacuc405c822015-01-23 10:40:19 +00005270 // If this is not the end of the statement, report an error.
5271 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5272 reportParseError("unexpected token, expected end of statement");
5273 return false;
5274 }
5275
5276 return false; // parseDirectiveModule has finished successfully.
5277 } else if (Option == "fp") {
5278 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00005279 } else if (Option == "softfloat") {
5280 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5281
5282 // Synchronize the ABI Flags information with the FeatureBits information we
5283 // updated above.
5284 getTargetStreamer().updateABIInfo(*this);
5285
5286 // If printing assembly, use the recently updated ABI Flags information.
5287 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5288 // emitted later).
5289 getTargetStreamer().emitDirectiveModuleSoftFloat();
5290
5291 // If this is not the end of the statement, report an error.
5292 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5293 reportParseError("unexpected token, expected end of statement");
5294 return false;
5295 }
5296
5297 return false; // parseDirectiveModule has finished successfully.
5298 } else if (Option == "hardfloat") {
5299 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
5300
5301 // Synchronize the ABI Flags information with the FeatureBits information we
5302 // updated above.
5303 getTargetStreamer().updateABIInfo(*this);
5304
5305 // If printing assembly, use the recently updated ABI Flags information.
5306 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5307 // emitted later).
5308 getTargetStreamer().emitDirectiveModuleHardFloat();
5309
5310 // If this is not the end of the statement, report an error.
5311 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5312 reportParseError("unexpected token, expected end of statement");
5313 return false;
5314 }
5315
5316 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00005317 } else {
5318 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
5319 }
Daniel Sanders7e527422014-07-10 13:38:23 +00005320}
5321
5322/// parseDirectiveModuleFP
5323/// ::= =32
5324/// ::= =xx
5325/// ::= =64
5326bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00005327 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00005328 MCAsmLexer &Lexer = getLexer();
5329
5330 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005331 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005332 return false;
5333 }
5334 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005335
Daniel Sanders7e527422014-07-10 13:38:23 +00005336 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005337 if (!parseFpABIValue(FpABI, ".module"))
5338 return false;
5339
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005340 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005341 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005342 return false;
5343 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005344
Toma Tabacua64e5402015-06-25 12:44:38 +00005345 // Synchronize the abiflags information with the FeatureBits information we
5346 // changed above.
5347 getTargetStreamer().updateABIInfo(*this);
5348
5349 // If printing assembly, use the recently updated abiflags information.
5350 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
5351 // emitted at the end).
5352 getTargetStreamer().emitDirectiveModuleFP();
5353
Daniel Sanders7e527422014-07-10 13:38:23 +00005354 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005355 return false;
5356}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005357
Daniel Sanders7e527422014-07-10 13:38:23 +00005358bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005359 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005360 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005361 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005362 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005363
5364 if (Lexer.is(AsmToken::Identifier)) {
5365 StringRef Value = Parser.getTok().getString();
5366 Parser.Lex();
5367
5368 if (Value != "xx") {
5369 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5370 return false;
5371 }
5372
5373 if (!isABI_O32()) {
5374 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
5375 return false;
5376 }
5377
Daniel Sanders7e527422014-07-10 13:38:23 +00005378 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005379 if (ModuleLevelOptions) {
5380 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5381 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5382 } else {
5383 setFeatureBits(Mips::FeatureFPXX, "fpxx");
5384 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5385 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005386 return true;
5387 }
5388
5389 if (Lexer.is(AsmToken::Integer)) {
5390 unsigned Value = Parser.getTok().getIntVal();
5391 Parser.Lex();
5392
5393 if (Value != 32 && Value != 64) {
5394 reportParseError("unsupported value, expected 'xx', '32' or '64'");
5395 return false;
5396 }
5397
5398 if (Value == 32) {
5399 if (!isABI_O32()) {
5400 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
5401 return false;
5402 }
5403
Daniel Sanders7e527422014-07-10 13:38:23 +00005404 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005405 if (ModuleLevelOptions) {
5406 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5407 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5408 } else {
5409 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5410 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
5411 }
Toma Tabacua64e5402015-06-25 12:44:38 +00005412 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00005413 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00005414 if (ModuleLevelOptions) {
5415 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
5416 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
5417 } else {
5418 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
5419 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
5420 }
Toma Tabacua64e5402015-06-25 12:44:38 +00005421 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005422
Daniel Sanders7e527422014-07-10 13:38:23 +00005423 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00005424 }
5425
5426 return false;
5427}
5428
Jack Carter0b744b32012-10-04 02:29:46 +00005429bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005430 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00005431 StringRef IDVal = DirectiveID.getString();
5432
Matheus Almeida525bc4f2014-04-30 11:28:42 +00005433 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00005434 return parseDirectiveCpLoad(DirectiveID.getLoc());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005435 if (IDVal == ".cprestore")
5436 return parseDirectiveCpRestore(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00005437 if (IDVal == ".dword") {
5438 parseDataDirective(8, DirectiveID.getLoc());
5439 return false;
5440 }
Jack Carterd0bd6422013-04-18 00:41:53 +00005441 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005442 StringRef SymbolName;
5443
5444 if (Parser.parseIdentifier(SymbolName)) {
5445 reportParseError("expected identifier after .ent");
5446 return false;
5447 }
5448
5449 // There's an undocumented extension that allows an integer to
5450 // follow the name of the procedure which AFAICS is ignored by GAS.
5451 // Example: .ent foo,2
5452 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5453 if (getLexer().isNot(AsmToken::Comma)) {
5454 // Even though we accept this undocumented extension for compatibility
5455 // reasons, the additional integer argument does not actually change
5456 // the behaviour of the '.ent' directive, so we would like to discourage
5457 // its use. We do this by not referring to the extended version in
5458 // error messages which are not directly related to its use.
5459 reportParseError("unexpected token, expected end of statement");
5460 return false;
5461 }
5462 Parser.Lex(); // Eat the comma.
5463 const MCExpr *DummyNumber;
5464 int64_t DummyNumberVal;
5465 // If the user was explicitly trying to use the extended version,
5466 // we still give helpful extension-related error messages.
5467 if (Parser.parseExpression(DummyNumber)) {
5468 reportParseError("expected number after comma");
5469 return false;
5470 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00005471 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005472 reportParseError("expected an absolute expression after comma");
5473 return false;
5474 }
5475 }
5476
5477 // If this is not the end of the statement, report an error.
5478 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5479 reportParseError("unexpected token, expected end of statement");
5480 return false;
5481 }
5482
Jim Grosbach6f482002015-05-18 18:43:14 +00005483 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005484
5485 getTargetStreamer().emitDirectiveEnt(*Sym);
5486 CurrentFn = Sym;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005487 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00005488 return false;
5489 }
5490
Jack Carter07c818d2013-01-25 01:31:34 +00005491 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005492 StringRef SymbolName;
5493
5494 if (Parser.parseIdentifier(SymbolName)) {
5495 reportParseError("expected identifier after .end");
5496 return false;
5497 }
5498
5499 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5500 reportParseError("unexpected token, expected end of statement");
5501 return false;
5502 }
5503
5504 if (CurrentFn == nullptr) {
5505 reportParseError(".end used without .ent");
5506 return false;
5507 }
5508
5509 if ((SymbolName != CurrentFn->getName())) {
5510 reportParseError(".end symbol does not match .ent symbol");
5511 return false;
5512 }
5513
5514 getTargetStreamer().emitDirectiveEnd(SymbolName);
5515 CurrentFn = nullptr;
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005516 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00005517 return false;
5518 }
5519
Jack Carter07c818d2013-01-25 01:31:34 +00005520 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005521 // .frame $stack_reg, frame_size_in_bytes, $return_reg
5522 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005523 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005524 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5525 reportParseError("expected stack register");
5526 return false;
5527 }
5528
5529 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5530 if (!StackRegOpnd.isGPRAsmReg()) {
5531 reportParseError(StackRegOpnd.getStartLoc(),
5532 "expected general purpose register");
5533 return false;
5534 }
5535 unsigned StackReg = StackRegOpnd.getGPR32Reg();
5536
5537 if (Parser.getTok().is(AsmToken::Comma))
5538 Parser.Lex();
5539 else {
5540 reportParseError("unexpected token, expected comma");
5541 return false;
5542 }
5543
5544 // Parse the frame size.
5545 const MCExpr *FrameSize;
5546 int64_t FrameSizeVal;
5547
5548 if (Parser.parseExpression(FrameSize)) {
5549 reportParseError("expected frame size value");
5550 return false;
5551 }
5552
Jim Grosbach13760bd2015-05-30 01:25:56 +00005553 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005554 reportParseError("frame size not an absolute expression");
5555 return false;
5556 }
5557
5558 if (Parser.getTok().is(AsmToken::Comma))
5559 Parser.Lex();
5560 else {
5561 reportParseError("unexpected token, expected comma");
5562 return false;
5563 }
5564
5565 // Parse the return register.
5566 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00005567 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005568 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5569 reportParseError("expected return register");
5570 return false;
5571 }
5572
5573 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5574 if (!ReturnRegOpnd.isGPRAsmReg()) {
5575 reportParseError(ReturnRegOpnd.getStartLoc(),
5576 "expected general purpose register");
5577 return false;
5578 }
5579
5580 // If this is not the end of the statement, report an error.
5581 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5582 reportParseError("unexpected token, expected end of statement");
5583 return false;
5584 }
5585
5586 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
5587 ReturnRegOpnd.getGPR32Reg());
Daniel Sanderse2982ad2015-09-17 16:08:39 +00005588 IsCpRestoreSet = false;
Jack Carterbe332172012-09-07 00:48:02 +00005589 return false;
5590 }
5591
Jack Carter07c818d2013-01-25 01:31:34 +00005592 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00005593 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00005594 }
5595
Daniel Sandersd97a6342014-08-13 10:07:34 +00005596 if (IDVal == ".mask" || IDVal == ".fmask") {
5597 // .mask bitmask, frame_offset
5598 // bitmask: One bit for each register used.
5599 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
5600 // first register is expected to be saved.
5601 // Examples:
5602 // .mask 0x80000000, -4
5603 // .fmask 0x80000000, -4
5604 //
Jack Carterbe332172012-09-07 00:48:02 +00005605
Daniel Sandersd97a6342014-08-13 10:07:34 +00005606 // Parse the bitmask
5607 const MCExpr *BitMask;
5608 int64_t BitMaskVal;
5609
5610 if (Parser.parseExpression(BitMask)) {
5611 reportParseError("expected bitmask value");
5612 return false;
5613 }
5614
Jim Grosbach13760bd2015-05-30 01:25:56 +00005615 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005616 reportParseError("bitmask not an absolute expression");
5617 return false;
5618 }
5619
5620 if (Parser.getTok().is(AsmToken::Comma))
5621 Parser.Lex();
5622 else {
5623 reportParseError("unexpected token, expected comma");
5624 return false;
5625 }
5626
5627 // Parse the frame_offset
5628 const MCExpr *FrameOffset;
5629 int64_t FrameOffsetVal;
5630
5631 if (Parser.parseExpression(FrameOffset)) {
5632 reportParseError("expected frame offset value");
5633 return false;
5634 }
5635
Jim Grosbach13760bd2015-05-30 01:25:56 +00005636 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005637 reportParseError("frame offset not an absolute expression");
5638 return false;
5639 }
5640
5641 // If this is not the end of the statement, report an error.
5642 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5643 reportParseError("unexpected token, expected end of statement");
5644 return false;
5645 }
5646
5647 if (IDVal == ".mask")
5648 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
5649 else
5650 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00005651 return false;
5652 }
5653
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005654 if (IDVal == ".nan")
5655 return parseDirectiveNaN();
5656
Jack Carter07c818d2013-01-25 01:31:34 +00005657 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00005658 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00005659 return false;
5660 }
5661
Rafael Espindolab59fb732014-03-28 18:50:26 +00005662 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005663 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005664 return false;
5665 }
5666
Jack Carter07c818d2013-01-25 01:31:34 +00005667 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005668 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00005669 return false;
5670 }
5671
Jack Carter0cd3c192014-01-06 23:27:31 +00005672 if (IDVal == ".option")
5673 return parseDirectiveOption();
5674
5675 if (IDVal == ".abicalls") {
5676 getTargetStreamer().emitDirectiveAbiCalls();
5677 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005678 Error(Parser.getTok().getLoc(),
5679 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005680 // Clear line
5681 Parser.eatToEndOfStatement();
5682 }
5683 return false;
5684 }
5685
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005686 if (IDVal == ".cpsetup")
5687 return parseDirectiveCPSetup();
5688
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005689 if (IDVal == ".module")
5690 return parseDirectiveModule();
5691
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00005692 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
5693 return parseInternalDirectiveReallowModule();
5694
Toma Tabacu9ca50962015-04-16 09:53:47 +00005695 if (IDVal == ".insn")
5696 return parseInsnDirective();
5697
Rafael Espindola870c4e92012-01-11 03:56:41 +00005698 return true;
5699}
5700
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00005701bool MipsAsmParser::parseInternalDirectiveReallowModule() {
5702 // If this is not the end of the statement, report an error.
5703 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5704 reportParseError("unexpected token, expected end of statement");
5705 return false;
5706 }
5707
5708 getTargetStreamer().reallowModuleDirective();
5709
5710 getParser().Lex(); // Eat EndOfStatement token.
5711 return false;
5712}
5713
Rafael Espindola870c4e92012-01-11 03:56:41 +00005714extern "C" void LLVMInitializeMipsAsmParser() {
5715 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
5716 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
5717 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
5718 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
5719}
Jack Carterb4dbc172012-09-05 23:34:03 +00005720
5721#define GET_REGISTER_MATCHER
5722#define GET_MATCHER_IMPLEMENTATION
5723#include "MipsGenAsmMatcher.inc"