blob: f14156dbfa2b9c916b5041411ab4d95f7c0fb9bf [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"
Rafael Espindolaa17151a2013-10-08 13:08:17 +000014#include "MipsTargetStreamer.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000015#include "llvm/ADT/APInt.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000016#include "llvm/ADT/SmallVector.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000017#include "llvm/ADT/StringSwitch.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000018#include "llvm/MC/MCContext.h"
19#include "llvm/MC/MCExpr.h"
20#include "llvm/MC/MCInst.h"
Daniel Sandersa771fef2014-03-24 14:05:39 +000021#include "llvm/MC/MCInstBuilder.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000022#include "llvm/MC/MCParser/MCAsmLexer.h"
23#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000024#include "llvm/MC/MCStreamer.h"
25#include "llvm/MC/MCSubtargetInfo.h"
26#include "llvm/MC/MCSymbol.h"
Akira Hatanaka7605630c2012-08-17 20:16:42 +000027#include "llvm/MC/MCTargetAsmParser.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000028#include "llvm/Support/Debug.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000029#include "llvm/Support/MathExtras.h"
Daniel Sandersef638fe2014-10-03 15:37:37 +000030#include "llvm/Support/SourceMgr.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000031#include "llvm/Support/TargetRegistry.h"
Benjamin Kramer799003b2015-03-23 19:32:43 +000032#include "llvm/Support/raw_ostream.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000033#include <memory>
Rafael Espindola870c4e92012-01-11 03:56:41 +000034
35using namespace llvm;
36
Chandler Carruthe96dd892014-04-21 22:55:11 +000037#define DEBUG_TYPE "mips-asm-parser"
38
Joey Gouly0e76fa72013-09-12 10:28:05 +000039namespace llvm {
40class MCInstrInfo;
41}
42
Rafael Espindola870c4e92012-01-11 03:56:41 +000043namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000044class MipsAssemblerOptions {
45public:
Toma Tabacu465acfd2015-06-09 13:33:26 +000046 MipsAssemblerOptions(const FeatureBitset &Features_) :
Toma Tabacu9db22db2014-09-09 10:15:38 +000047 ATReg(1), Reorder(true), Macro(true), Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000048
Toma Tabacu9db22db2014-09-09 10:15:38 +000049 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
Toma Tabacub19cf202015-04-27 13:12:59 +000050 ATReg = Opts->getATRegIndex();
Toma Tabacu9db22db2014-09-09 10:15:38 +000051 Reorder = Opts->isReorder();
52 Macro = Opts->isMacro();
53 Features = Opts->getFeatures();
54 }
55
Toma Tabacub19cf202015-04-27 13:12:59 +000056 unsigned getATRegIndex() const { return ATReg; }
57 bool setATRegIndex(unsigned Reg) {
Toma Tabacu92dbbf12015-03-26 13:08:55 +000058 if (Reg > 31)
59 return false;
60
61 ATReg = Reg;
62 return true;
63 }
Jack Carter0b744b32012-10-04 02:29:46 +000064
Toma Tabacu9db22db2014-09-09 10:15:38 +000065 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000066 void setReorder() { Reorder = true; }
67 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000068
Toma Tabacu9db22db2014-09-09 10:15:38 +000069 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000070 void setMacro() { Macro = true; }
71 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000072
Toma Tabacu465acfd2015-06-09 13:33:26 +000073 const FeatureBitset &getFeatures() const { return Features; }
74 void setFeatures(const FeatureBitset &Features_) { Features = Features_; }
Toma Tabacu9db22db2014-09-09 10:15:38 +000075
Daniel Sandersf0df2212014-08-04 12:20:00 +000076 // Set of features that are either architecture features or referenced
77 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
78 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
79 // The reason we need this mask is explained in the selectArch function.
80 // FIXME: Ideally we would like TableGen to generate this information.
Michael Kupersteindb0712f2015-05-26 10:47:10 +000081 static const FeatureBitset AllArchRelatedMask;
Daniel Sandersf0df2212014-08-04 12:20:00 +000082
Jack Carter0b744b32012-10-04 02:29:46 +000083private:
Toma Tabacu3c24b042014-09-05 15:43:21 +000084 unsigned ATReg;
85 bool Reorder;
86 bool Macro;
Toma Tabacu465acfd2015-06-09 13:33:26 +000087 FeatureBitset Features;
Jack Carter0b744b32012-10-04 02:29:46 +000088};
89}
90
Michael Kupersteindb0712f2015-05-26 10:47:10 +000091const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = {
92 Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3,
93 Mips::FeatureMips3_32, Mips::FeatureMips3_32r2, Mips::FeatureMips4,
94 Mips::FeatureMips4_32, Mips::FeatureMips4_32r2, Mips::FeatureMips5,
95 Mips::FeatureMips5_32r2, Mips::FeatureMips32, Mips::FeatureMips32r2,
96 Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6,
97 Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3,
98 Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips,
99 Mips::FeatureFP64Bit, Mips::FeatureGP64Bit, Mips::FeatureNaN2008
100};
101
Jack Carter0b744b32012-10-04 02:29:46 +0000102namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +0000103class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000104 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola961d4692014-11-11 05:18:41 +0000105 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000106 return static_cast<MipsTargetStreamer &>(TS);
107 }
108
Jack Carterb4dbc172012-09-05 23:34:03 +0000109 MCSubtargetInfo &STI;
Eric Christophera5762812015-01-26 17:33:46 +0000110 MipsABIInfo ABI;
Toma Tabacu9db22db2014-09-09 10:15:38 +0000111 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000112 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
113 // nullptr, which indicates that no function is currently
114 // selected. This usually happens after an '.end func'
115 // directive.
Toma Tabacud88d79c2015-06-23 14:39:42 +0000116 bool IsLittleEndian;
Jack Carter0b744b32012-10-04 02:29:46 +0000117
Daniel Sandersef638fe2014-10-03 15:37:37 +0000118 // Print a warning along with its fix-it message at the given range.
119 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
120 SMRange Range, bool ShowColors = true);
121
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000122#define GET_ASSEMBLER_HEADER
123#include "MipsGenAsmMatcher.inc"
124
Matheus Almeida595fcab2014-06-11 15:05:56 +0000125 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
126
Chad Rosier49963552012-10-13 00:26:04 +0000127 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000128 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000129 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000130 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000131
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000132 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000133 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000134
Toma Tabacu13964452014-09-04 13:23:44 +0000135 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000136
Toma Tabacu13964452014-09-04 13:23:44 +0000137 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000138
David Blaikie960ea3f2014-06-08 16:18:35 +0000139 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
140 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000141
Craig Topper56c590a2014-04-29 07:58:02 +0000142 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000143
David Blaikie960ea3f2014-06-08 16:18:35 +0000144 MipsAsmParser::OperandMatchResultTy parseMemOperand(OperandVector &Operands);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000145
146 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000147 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000148 StringRef Identifier, SMLoc S);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000149
Jack Carter873c7242013-01-12 01:03:14 +0000150 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000151 matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S);
Jack Carter873c7242013-01-12 01:03:14 +0000152
Toma Tabacu13964452014-09-04 13:23:44 +0000153 MipsAsmParser::OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
Jack Carter873c7242013-01-12 01:03:14 +0000154
Toma Tabacu13964452014-09-04 13:23:44 +0000155 MipsAsmParser::OperandMatchResultTy parseImm(OperandVector &Operands);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000156
Toma Tabacu13964452014-09-04 13:23:44 +0000157 MipsAsmParser::OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
Vladimir Medic2b953d02013-10-01 09:48:56 +0000158
David Blaikie960ea3f2014-06-08 16:18:35 +0000159 MipsAsmParser::OperandMatchResultTy parseInvNum(OperandVector &Operands);
Matheus Almeida779c5932013-11-18 12:32:49 +0000160
Toma Tabacu13964452014-09-04 13:23:44 +0000161 MipsAsmParser::OperandMatchResultTy parseLSAImm(OperandVector &Operands);
Jack Carterd76b2372013-03-21 21:44:16 +0000162
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000163 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000164 parseRegisterPair (OperandVector &Operands);
165
166 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovic41688672015-02-10 16:36:20 +0000167 parseMovePRegPair(OperandVector &Operands);
168
169 MipsAsmParser::OperandMatchResultTy
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000170 parseRegisterList (OperandVector &Operands);
171
David Blaikie960ea3f2014-06-08 16:18:35 +0000172 bool searchSymbolAlias(OperandVector &Operands);
173
Toma Tabacu13964452014-09-04 13:23:44 +0000174 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000175
Jack Carter30a59822012-10-04 04:03:53 +0000176 bool needsExpansion(MCInst &Inst);
177
Matheus Almeida3813d572014-06-19 14:39:14 +0000178 // Expands assembly pseudo instructions.
179 // Returns false on success, true otherwise.
180 bool expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000181 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000182
Toma Tabacu8f6603a2015-01-30 11:18:50 +0000183 bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
184 SmallVectorImpl<MCInst> &Instructions);
185
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000186 bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
187 bool Is32BitImm, SMLoc IDLoc,
188 SmallVectorImpl<MCInst> &Instructions);
189
Toma Tabacuf712ede2015-06-17 14:31:51 +0000190 bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
191 unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
192 SmallVectorImpl<MCInst> &Instructions);
Toma Tabacu674825c2015-06-16 12:16:24 +0000193
Toma Tabacu00e98672015-05-01 12:19:27 +0000194 bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000195 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000196
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000197 bool expandLoadAddressImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000198 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000199
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000200 bool expandLoadAddressReg(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000201 SmallVectorImpl<MCInst> &Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +0000202 bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
203 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000204
Jack Carter9e65aa32013-03-22 00:05:30 +0000205 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000206 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
207 bool isImmOpnd);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +0000208
209 bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
210 SmallVectorImpl<MCInst> &Instructions);
211
Toma Tabacue1e460d2015-06-11 10:36:10 +0000212 bool expandBranchImm(MCInst &Inst, SMLoc IDLoc,
213 SmallVectorImpl<MCInst> &Instructions);
214
Toma Tabacu1a108322015-06-17 13:20:24 +0000215 bool expandCondBranches(MCInst &Inst, SMLoc IDLoc,
216 SmallVectorImpl<MCInst> &Instructions);
217
Toma Tabacud88d79c2015-06-23 14:39:42 +0000218 bool expandUlhu(MCInst &Inst, SMLoc IDLoc,
219 SmallVectorImpl<MCInst> &Instructions);
220
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +0000221 bool expandUlw(MCInst &Inst, SMLoc IDLoc,
222 SmallVectorImpl<MCInst> &Instructions);
223
Toma Tabacu234482a2015-03-16 12:03:39 +0000224 void createNop(bool hasShortDelaySlot, SMLoc IDLoc,
225 SmallVectorImpl<MCInst> &Instructions);
226
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000227 void createAddu(unsigned DstReg, unsigned SrcReg, unsigned TrgReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +0000228 bool Is64Bit, SmallVectorImpl<MCInst> &Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +0000229
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000230 bool reportParseError(Twine ErrorMsg);
231 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000232
Jack Carterb5cf5902013-04-17 00:18:04 +0000233 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000234 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000235
Vladimir Medic4c299852013-11-06 11:27:05 +0000236 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000237
238 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000239 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000240 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000241 bool parseSetFeature(uint64_t Feature);
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000242 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000243 bool parseDirectiveCPSetup();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000244 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000245 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000246 bool parseDirectiveOption();
Toma Tabacu9ca50962015-04-16 09:53:47 +0000247 bool parseInsnDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000248
249 bool parseSetAtDirective();
250 bool parseSetNoAtDirective();
251 bool parseSetMacroDirective();
252 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000253 bool parseSetMsaDirective();
254 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000255 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000256 bool parseSetReorderDirective();
257 bool parseSetNoReorderDirective();
Toma Tabacucc2502d2014-11-04 17:18:07 +0000258 bool parseSetMips16Directive();
Jack Carter39536722014-01-22 23:08:42 +0000259 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000260 bool parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +0000261 bool parseSetOddSPRegDirective();
262 bool parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000263 bool parseSetPopDirective();
264 bool parseSetPushDirective();
Toma Tabacu29696502015-06-02 09:48:04 +0000265 bool parseSetSoftFloatDirective();
266 bool parseSetHardFloatDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000267
Jack Carterd76b2372013-03-21 21:44:16 +0000268 bool parseSetAssignment();
269
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000270 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000271 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000272 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000273 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000274 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000275 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
276 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000277
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +0000278 bool parseInternalDirectiveReallowModule();
279
Jack Carterdc1e35d2012-09-06 20:00:02 +0000280 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000281
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000282 bool eatComma(StringRef ErrorStr);
283
Jack Carter1ac53222013-02-20 23:11:17 +0000284 int matchCPURegisterName(StringRef Symbol);
285
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +0000286 int matchHWRegsRegisterName(StringRef Symbol);
287
Jack Carter873c7242013-01-12 01:03:14 +0000288 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000289
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000290 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000291
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000292 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000293
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000294 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000295
Jack Carter5dc8ac92013-09-25 23:50:44 +0000296 int matchMSA128RegisterName(StringRef Name);
297
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000298 int matchMSA128CtrlRegisterName(StringRef Name);
299
Jack Carterd0bd6422013-04-18 00:41:53 +0000300 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000301
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000302 unsigned getGPR(int RegNo);
303
Toma Tabacu89a712b2015-04-15 10:48:56 +0000304 /// Returns the internal register number for the current AT. Also checks if
305 /// the current AT is unavailable (set to $0) and gives an error if it is.
306 /// This should be used in pseudo-instruction expansions which need AT.
307 unsigned getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000308
309 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000310 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000311
312 // Helper function that checks if the value of a vector index is within the
313 // boundaries of accepted values for each RegisterKind
314 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
315 bool validateMSAIndex(int Val, int RegKind);
316
Daniel Sandersf0df2212014-08-04 12:20:00 +0000317 // Selects a new architecture by updating the FeatureBits with the necessary
318 // info including implied dependencies.
319 // Internally, it clears all the feature bits related to *any* architecture
320 // and selects the new one using the ToggleFeature functionality of the
321 // MCSubtargetInfo object that handles implied dependencies. The reason we
322 // clear all the arch related bits manually is because ToggleFeature only
323 // clears the features that imply the feature being cleared and not the
324 // features implied by the feature being cleared. This is easier to see
325 // with an example:
326 // --------------------------------------------------
327 // | Feature | Implies |
328 // | -------------------------------------------------|
329 // | FeatureMips1 | None |
330 // | FeatureMips2 | FeatureMips1 |
331 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
332 // | FeatureMips4 | FeatureMips3 |
333 // | ... | |
334 // --------------------------------------------------
335 //
336 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
337 // FeatureMipsGP64 | FeatureMips1)
338 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
339 void selectArch(StringRef ArchFeature) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000340 FeatureBitset FeatureBits = STI.getFeatureBits();
Daniel Sandersf0df2212014-08-04 12:20:00 +0000341 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
342 STI.setFeatureBits(FeatureBits);
343 setAvailableFeatures(
344 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000345 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000346 }
347
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000348 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000349 if (!(STI.getFeatureBits()[Feature])) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000350 setAvailableFeatures(
351 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000352 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000353 }
354 }
355
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000356 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000357 if (STI.getFeatureBits()[Feature]) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000358 setAvailableFeatures(
359 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Toma Tabacu465acfd2015-06-09 13:33:26 +0000360 AssemblerOptions.back()->setFeatures(STI.getFeatureBits());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000361 }
362 }
363
Toma Tabacufc97d8a2015-06-30 12:41:33 +0000364 void setModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
365 setFeatureBits(Feature, FeatureString);
366 AssemblerOptions.front()->setFeatures(STI.getFeatureBits());
367 }
368
369 void clearModuleFeatureBits(uint64_t Feature, StringRef FeatureString) {
370 clearFeatureBits(Feature, FeatureString);
371 AssemblerOptions.front()->setFeatures(STI.getFeatureBits());
372 }
373
Rafael Espindola870c4e92012-01-11 03:56:41 +0000374public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000375 enum MipsMatchResultTy {
376 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
377#define GET_OPERAND_DIAGNOSTIC_TYPES
378#include "MipsGenAsmMatcher.inc"
379#undef GET_OPERAND_DIAGNOSTIC_TYPES
380
381 };
382
Joey Gouly0e76fa72013-09-12 10:28:05 +0000383 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000384 const MCInstrInfo &MII, const MCTargetOptions &Options)
Eric Christophera5762812015-01-26 17:33:46 +0000385 : MCTargetAsmParser(), STI(sti),
386 ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()),
387 sti.getCPU(), Options)) {
Rafael Espindola961d4692014-11-11 05:18:41 +0000388 MCAsmParserExtension::Initialize(parser);
389
Toma Tabacu11e14a92015-04-21 11:50:52 +0000390 parser.addAliasForDirective(".asciiz", ".asciz");
391
Jack Carterb4dbc172012-09-05 23:34:03 +0000392 // Initialize the set of available features.
393 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000394
395 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000396 AssemblerOptions.push_back(
Toma Tabacu465acfd2015-06-09 13:33:26 +0000397 llvm::make_unique<MipsAssemblerOptions>(STI.getFeatureBits()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000398
399 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000400 AssemblerOptions.push_back(
Toma Tabacu465acfd2015-06-09 13:33:26 +0000401 llvm::make_unique<MipsAssemblerOptions>(STI.getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000402
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000403 getTargetStreamer().updateABIInfo(*this);
404
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000405 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000406 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000407
408 CurrentFn = nullptr;
Toma Tabacud88d79c2015-06-23 14:39:42 +0000409
410 Triple TheTriple(sti.getTargetTriple());
411 if ((TheTriple.getArch() == Triple::mips) ||
412 (TheTriple.getArch() == Triple::mips64))
413 IsLittleEndian = false;
414 else
415 IsLittleEndian = true;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000416 }
417
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000418 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
419 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
420
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000421 bool isGP64bit() const { return STI.getFeatureBits()[Mips::FeatureGP64Bit]; }
422 bool isFP64bit() const { return STI.getFeatureBits()[Mips::FeatureFP64Bit]; }
Eric Christophera5762812015-01-26 17:33:46 +0000423 const MipsABIInfo &getABI() const { return ABI; }
424 bool isABI_N32() const { return ABI.IsN32(); }
425 bool isABI_N64() const { return ABI.IsN64(); }
426 bool isABI_O32() const { return ABI.IsO32(); }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000427 bool isABI_FPXX() const { return STI.getFeatureBits()[Mips::FeatureFPXX]; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000428
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000429 bool useOddSPReg() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000430 return !(STI.getFeatureBits()[Mips::FeatureNoOddSPReg]);
Daniel Sanders7e527422014-07-10 13:38:23 +0000431 }
432
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000433 bool inMicroMipsMode() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000434 return STI.getFeatureBits()[Mips::FeatureMicroMips];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000435 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000436 bool hasMips1() const { return STI.getFeatureBits()[Mips::FeatureMips1]; }
437 bool hasMips2() const { return STI.getFeatureBits()[Mips::FeatureMips2]; }
438 bool hasMips3() const { return STI.getFeatureBits()[Mips::FeatureMips3]; }
439 bool hasMips4() const { return STI.getFeatureBits()[Mips::FeatureMips4]; }
440 bool hasMips5() const { return STI.getFeatureBits()[Mips::FeatureMips5]; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000441 bool hasMips32() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000442 return STI.getFeatureBits()[Mips::FeatureMips32];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000443 }
444 bool hasMips64() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000445 return STI.getFeatureBits()[Mips::FeatureMips64];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000446 }
447 bool hasMips32r2() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000448 return STI.getFeatureBits()[Mips::FeatureMips32r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000449 }
450 bool hasMips64r2() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000451 return STI.getFeatureBits()[Mips::FeatureMips64r2];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000452 }
Daniel Sanders17793142015-02-18 16:24:50 +0000453 bool hasMips32r3() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000454 return (STI.getFeatureBits()[Mips::FeatureMips32r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000455 }
456 bool hasMips64r3() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000457 return (STI.getFeatureBits()[Mips::FeatureMips64r3]);
Daniel Sanders17793142015-02-18 16:24:50 +0000458 }
459 bool hasMips32r5() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000460 return (STI.getFeatureBits()[Mips::FeatureMips32r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000461 }
462 bool hasMips64r5() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000463 return (STI.getFeatureBits()[Mips::FeatureMips64r5]);
Daniel Sanders17793142015-02-18 16:24:50 +0000464 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000465 bool hasMips32r6() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000466 return STI.getFeatureBits()[Mips::FeatureMips32r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000467 }
468 bool hasMips64r6() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000469 return STI.getFeatureBits()[Mips::FeatureMips64r6];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000470 }
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000471
472 bool hasDSP() const { return STI.getFeatureBits()[Mips::FeatureDSP]; }
473 bool hasDSPR2() const { return STI.getFeatureBits()[Mips::FeatureDSPR2]; }
474 bool hasMSA() const { return STI.getFeatureBits()[Mips::FeatureMSA]; }
Kai Nackee0245392015-01-27 19:11:28 +0000475 bool hasCnMips() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000476 return (STI.getFeatureBits()[Mips::FeatureCnMips]);
Kai Nackee0245392015-01-27 19:11:28 +0000477 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000478
479 bool inMips16Mode() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000480 return STI.getFeatureBits()[Mips::FeatureMips16];
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000481 }
Toma Tabacu506cfd02015-05-07 10:29:52 +0000482
Eric Christophere8ae3e32015-05-07 23:10:21 +0000483 bool useSoftFloat() const {
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000484 return STI.getFeatureBits()[Mips::FeatureSoftFloat];
Toma Tabacu506cfd02015-05-07 10:29:52 +0000485 }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000486
Toma Tabacud9d344b2015-04-27 14:05:04 +0000487 /// Warn if RegIndex is the same as the current AT.
488 void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc);
Toma Tabacu81496c12015-05-20 08:54:45 +0000489
490 void warnIfNoMacro(SMLoc Loc);
Toma Tabacud88d79c2015-06-23 14:39:42 +0000491
492 bool isLittle() const { return IsLittleEndian; }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000493};
494}
495
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000496namespace {
497
498/// MipsOperand - Instances of this class represent a parsed Mips machine
499/// instruction.
500class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000501public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000502 /// Broad categories of register classes
503 /// The exact class is finalized by the render method.
504 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000505 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000506 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000507 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000508 RegKind_FCC = 4, /// FCC
509 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
510 RegKind_MSACtrl = 16, /// MSA control registers
511 RegKind_COP2 = 32, /// COP2
512 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
513 /// context).
514 RegKind_CCR = 128, /// CCR
515 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000516 RegKind_COP3 = 512, /// COP3
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000517 RegKind_COP0 = 1024, /// COP0
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000518 /// Potentially any (e.g. $1)
519 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
520 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000521 RegKind_CCR | RegKind_HWRegs | RegKind_COP3 | RegKind_COP0
Jack Carter873c7242013-01-12 01:03:14 +0000522 };
523
524private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000525 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000526 k_Immediate, /// An immediate (possibly involving symbol references)
527 k_Memory, /// Base + Offset Memory Address
528 k_PhysRegister, /// A physical register from the Mips namespace
529 k_RegisterIndex, /// A register index in one or more RegKind.
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000530 k_Token, /// A simple token
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000531 k_RegList, /// A physical register list
532 k_RegPair /// A pair of physical register
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000533 } Kind;
534
David Blaikie960ea3f2014-06-08 16:18:35 +0000535public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000536 MipsOperand(KindTy K, MipsAsmParser &Parser)
537 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
538
David Blaikie960ea3f2014-06-08 16:18:35 +0000539private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000540 /// For diagnostics, and checking the assembler temporary
541 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000542
Eric Christopher8996c5d2013-03-15 00:42:55 +0000543 struct Token {
544 const char *Data;
545 unsigned Length;
546 };
547
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000548 struct PhysRegOp {
549 unsigned Num; /// Register Number
550 };
551
552 struct RegIdxOp {
553 unsigned Index; /// Index into the register class
554 RegKind Kind; /// Bitfield of the kinds it could possibly be
555 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000556 };
557
558 struct ImmOp {
559 const MCExpr *Val;
560 };
561
562 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000563 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000564 const MCExpr *Off;
565 };
566
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000567 struct RegListOp {
568 SmallVector<unsigned, 10> *List;
569 };
570
Jack Carterb4dbc172012-09-05 23:34:03 +0000571 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000572 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000573 struct PhysRegOp PhysReg;
574 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000575 struct ImmOp Imm;
576 struct MemOp Mem;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000577 struct RegListOp RegList;
Jack Carterb4dbc172012-09-05 23:34:03 +0000578 };
579
580 SMLoc StartLoc, EndLoc;
581
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000582 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000583 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
584 const MCRegisterInfo *RegInfo,
585 SMLoc S, SMLoc E,
586 MipsAsmParser &Parser) {
587 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000588 Op->RegIdx.Index = Index;
589 Op->RegIdx.RegInfo = RegInfo;
590 Op->RegIdx.Kind = RegKind;
591 Op->StartLoc = S;
592 Op->EndLoc = E;
593 return Op;
594 }
595
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000596public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000597 /// Coerce the register to GPR32 and return the real register for the current
598 /// target.
599 unsigned getGPR32Reg() const {
600 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacud9d344b2015-04-27 14:05:04 +0000601 AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000602 unsigned ClassID = Mips::GPR32RegClassID;
603 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000604 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000605
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000606 /// Coerce the register to GPR32 and return the real register for the current
607 /// target.
608 unsigned getGPRMM16Reg() const {
609 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
610 unsigned ClassID = Mips::GPR32RegClassID;
611 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
612 }
613
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000614 /// Coerce the register to GPR64 and return the real register for the current
615 /// target.
616 unsigned getGPR64Reg() const {
617 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
618 unsigned ClassID = Mips::GPR64RegClassID;
619 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000620 }
621
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000622private:
623 /// Coerce the register to AFGR64 and return the real register for the current
624 /// target.
625 unsigned getAFGR64Reg() const {
626 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
627 if (RegIdx.Index % 2 != 0)
628 AsmParser.Warning(StartLoc, "Float register should be even.");
629 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
630 .getRegister(RegIdx.Index / 2);
631 }
632
633 /// Coerce the register to FGR64 and return the real register for the current
634 /// target.
635 unsigned getFGR64Reg() const {
636 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
637 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
638 .getRegister(RegIdx.Index);
639 }
640
641 /// Coerce the register to FGR32 and return the real register for the current
642 /// target.
643 unsigned getFGR32Reg() const {
644 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
645 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
646 .getRegister(RegIdx.Index);
647 }
648
649 /// Coerce the register to FGRH32 and return the real register for the current
650 /// target.
651 unsigned getFGRH32Reg() const {
652 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
653 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
654 .getRegister(RegIdx.Index);
655 }
656
657 /// Coerce the register to FCC and return the real register for the current
658 /// target.
659 unsigned getFCCReg() const {
660 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
661 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
662 .getRegister(RegIdx.Index);
663 }
664
665 /// Coerce the register to MSA128 and return the real register for the current
666 /// target.
667 unsigned getMSA128Reg() const {
668 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
669 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
670 // identical
671 unsigned ClassID = Mips::MSA128BRegClassID;
672 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
673 }
674
675 /// Coerce the register to MSACtrl and return the real register for the
676 /// current target.
677 unsigned getMSACtrlReg() const {
678 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
679 unsigned ClassID = Mips::MSACtrlRegClassID;
680 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
681 }
682
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000683 /// Coerce the register to COP0 and return the real register for the
684 /// current target.
685 unsigned getCOP0Reg() const {
686 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP0) && "Invalid access!");
687 unsigned ClassID = Mips::COP0RegClassID;
688 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
689 }
690
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000691 /// Coerce the register to COP2 and return the real register for the
692 /// current target.
693 unsigned getCOP2Reg() const {
694 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
695 unsigned ClassID = Mips::COP2RegClassID;
696 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
697 }
698
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000699 /// Coerce the register to COP3 and return the real register for the
700 /// current target.
701 unsigned getCOP3Reg() const {
702 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
703 unsigned ClassID = Mips::COP3RegClassID;
704 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
705 }
706
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000707 /// Coerce the register to ACC64DSP and return the real register for the
708 /// current target.
709 unsigned getACC64DSPReg() const {
710 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
711 unsigned ClassID = Mips::ACC64DSPRegClassID;
712 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
713 }
714
715 /// Coerce the register to HI32DSP and return the real register for the
716 /// current target.
717 unsigned getHI32DSPReg() const {
718 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
719 unsigned ClassID = Mips::HI32DSPRegClassID;
720 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
721 }
722
723 /// Coerce the register to LO32DSP and return the real register for the
724 /// current target.
725 unsigned getLO32DSPReg() const {
726 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
727 unsigned ClassID = Mips::LO32DSPRegClassID;
728 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
729 }
730
731 /// Coerce the register to CCR and return the real register for the
732 /// current target.
733 unsigned getCCRReg() const {
734 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
735 unsigned ClassID = Mips::CCRRegClassID;
736 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
737 }
738
739 /// Coerce the register to HWRegs and return the real register for the
740 /// current target.
741 unsigned getHWRegsReg() const {
742 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
743 unsigned ClassID = Mips::HWRegsRegClassID;
744 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
745 }
746
747public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000748 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000749 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000750 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +0000751 Inst.addOperand(MCOperand::createImm(0));
Jack Carterb4dbc172012-09-05 23:34:03 +0000752 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +0000753 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000754 else
Jim Grosbache9119e42015-05-13 18:37:00 +0000755 Inst.addOperand(MCOperand::createExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000756 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000757
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000758 void addRegOperands(MCInst &Inst, unsigned N) const {
759 llvm_unreachable("Use a custom parser instead");
760 }
761
Daniel Sanders21bce302014-04-01 12:35:23 +0000762 /// Render the operand to an MCInst as a GPR32
763 /// Asserts if the wrong number of operands are requested, or the operand
764 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000765 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
766 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000767 Inst.addOperand(MCOperand::createReg(getGPR32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000768 }
769
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000770 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
771 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000772 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000773 }
774
Jozef Kolek1904fa22014-11-24 14:25:53 +0000775 void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const {
776 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000777 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Jozef Kolek1904fa22014-11-24 14:25:53 +0000778 }
779
Zoran Jovanovic41688672015-02-10 16:36:20 +0000780 void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const {
781 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000782 Inst.addOperand(MCOperand::createReg(getGPRMM16Reg()));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000783 }
784
Daniel Sanders21bce302014-04-01 12:35:23 +0000785 /// Render the operand to an MCInst as a GPR64
786 /// Asserts if the wrong number of operands are requested, or the operand
787 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000788 void addGPR64AsmRegOperands(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(getGPR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000791 }
792
793 void addAFGR64AsmRegOperands(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(getAFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000796 }
797
798 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
799 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000800 Inst.addOperand(MCOperand::createReg(getFGR64Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000801 }
802
803 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
804 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000805 Inst.addOperand(MCOperand::createReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000806 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000807 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000808 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
809 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000810 }
811
812 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
813 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000814 Inst.addOperand(MCOperand::createReg(getFGRH32Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000815 }
816
817 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
818 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000819 Inst.addOperand(MCOperand::createReg(getFCCReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000820 }
821
822 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
823 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000824 Inst.addOperand(MCOperand::createReg(getMSA128Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000825 }
826
827 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
828 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000829 Inst.addOperand(MCOperand::createReg(getMSACtrlReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000830 }
831
Daniel Sandersa3134fa2015-06-27 15:39:19 +0000832 void addCOP0AsmRegOperands(MCInst &Inst, unsigned N) const {
833 assert(N == 1 && "Invalid number of operands!");
834 Inst.addOperand(MCOperand::createReg(getCOP0Reg()));
835 }
836
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000837 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
838 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000839 Inst.addOperand(MCOperand::createReg(getCOP2Reg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000840 }
841
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000842 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
843 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000844 Inst.addOperand(MCOperand::createReg(getCOP3Reg()));
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000845 }
846
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000847 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
848 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000849 Inst.addOperand(MCOperand::createReg(getACC64DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000850 }
851
852 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
853 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000854 Inst.addOperand(MCOperand::createReg(getHI32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000855 }
856
857 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
858 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000859 Inst.addOperand(MCOperand::createReg(getLO32DSPReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000860 }
861
862 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
863 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000864 Inst.addOperand(MCOperand::createReg(getCCRReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000865 }
866
867 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
868 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +0000869 Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000870 }
871
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000872 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000873 assert(N == 1 && "Invalid number of operands!");
874 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000875 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000876 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000877
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000878 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000879 assert(N == 2 && "Invalid number of operands!");
880
Jim Grosbache9119e42015-05-13 18:37:00 +0000881 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000882
883 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000884 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000885 }
886
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000887 void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const {
888 assert(N == 2 && "Invalid number of operands!");
889
Jim Grosbache9119e42015-05-13 18:37:00 +0000890 Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg()));
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000891
892 const MCExpr *Expr = getMemOff();
893 addExpr(Inst, Expr);
894 }
895
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000896 void addRegListOperands(MCInst &Inst, unsigned N) const {
897 assert(N == 1 && "Invalid number of operands!");
898
899 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000900 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000901 }
902
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000903 void addRegPairOperands(MCInst &Inst, unsigned N) const {
904 assert(N == 2 && "Invalid number of operands!");
905 unsigned RegNo = getRegPair();
Jim Grosbache9119e42015-05-13 18:37:00 +0000906 Inst.addOperand(MCOperand::createReg(RegNo++));
907 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic2deca342014-12-16 14:59:10 +0000908 }
909
Zoran Jovanovic41688672015-02-10 16:36:20 +0000910 void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
911 assert(N == 2 && "Invalid number of operands!");
912 for (auto RegNo : getRegList())
Jim Grosbache9119e42015-05-13 18:37:00 +0000913 Inst.addOperand(MCOperand::createReg(RegNo));
Zoran Jovanovic41688672015-02-10 16:36:20 +0000914 }
915
Craig Topper56c590a2014-04-29 07:58:02 +0000916 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000917 // As a special case until we sort out the definition of div/divu, pretend
918 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
919 if (isGPRAsmReg() && RegIdx.Index == 0)
920 return true;
921
922 return Kind == k_PhysRegister;
923 }
924 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000925 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000926 bool isConstantImm() const {
927 return isImm() && dyn_cast<MCConstantExpr>(getImm());
928 }
Zoran Jovanovic6b0dcd72015-06-11 09:51:58 +0000929 template <unsigned Bits> bool isUImm() const {
930 return isImm() && isConstantImm() && isUInt<Bits>(getConstantImm());
931 }
Craig Topper56c590a2014-04-29 07:58:02 +0000932 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000933 // Note: It's not possible to pretend that other operand kinds are tokens.
934 // The matcher emitter checks tokens first.
935 return Kind == k_Token;
936 }
Craig Topper56c590a2014-04-29 07:58:02 +0000937 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000938 bool isConstantMemOff() const {
939 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
940 }
941 template <unsigned Bits> bool isMemWithSimmOffset() const {
942 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff());
943 }
Jozef Koleke8c9d1e2014-11-24 14:39:13 +0000944 bool isMemWithGRPMM16Base() const {
945 return isMem() && getMemBase()->isMM16AsmReg();
946 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000947 template <unsigned Bits> bool isMemWithUimmOffsetSP() const {
948 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
949 && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP);
950 }
Jozef Kolek12c69822014-12-23 16:16:33 +0000951 template <unsigned Bits> bool isMemWithUimmWordAlignedOffsetSP() const {
952 return isMem() && isConstantMemOff() && isUInt<Bits>(getConstantMemOff())
953 && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
954 && (getMemBase()->getGPR32Reg() == Mips::SP);
955 }
Zoran Jovanovicf9a02502014-11-27 18:28:59 +0000956 bool isRegList16() const {
957 if (!isRegList())
958 return false;
959
960 int Size = RegList.List->size();
961 if (Size < 2 || Size > 5 || *RegList.List->begin() != Mips::S0 ||
962 RegList.List->back() != Mips::RA)
963 return false;
964
965 int PrevReg = *RegList.List->begin();
966 for (int i = 1; i < Size - 1; i++) {
967 int Reg = (*(RegList.List))[i];
968 if ( Reg != PrevReg + 1)
969 return false;
970 PrevReg = Reg;
971 }
972
973 return true;
974 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000975 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000976 bool isLSAImm() const {
977 if (!isConstantImm())
978 return false;
979 int64_t Val = getConstantImm();
980 return 1 <= Val && Val <= 4;
981 }
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +0000982 bool isRegList() const { return Kind == k_RegList; }
Zoran Jovanovic41688672015-02-10 16:36:20 +0000983 bool isMovePRegPair() const {
984 if (Kind != k_RegList || RegList.List->size() != 2)
985 return false;
986
987 unsigned R0 = RegList.List->front();
988 unsigned R1 = RegList.List->back();
989
990 if ((R0 == Mips::A1 && R1 == Mips::A2) ||
991 (R0 == Mips::A1 && R1 == Mips::A3) ||
992 (R0 == Mips::A2 && R1 == Mips::A3) ||
993 (R0 == Mips::A0 && R1 == Mips::S5) ||
994 (R0 == Mips::A0 && R1 == Mips::S6) ||
995 (R0 == Mips::A0 && R1 == Mips::A1) ||
996 (R0 == Mips::A0 && R1 == Mips::A2) ||
997 (R0 == Mips::A0 && R1 == Mips::A3))
998 return true;
999
1000 return false;
1001 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001002
1003 StringRef getToken() const {
1004 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001005 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001006 }
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001007 bool isRegPair() const { return Kind == k_RegPair; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001008
Craig Topper56c590a2014-04-29 07:58:02 +00001009 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001010 // As a special case until we sort out the definition of div/divu, pretend
1011 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
1012 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
1013 RegIdx.Kind & RegKind_GPR)
1014 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001015
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001016 assert(Kind == k_PhysRegister && "Invalid access!");
1017 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +00001018 }
1019
Jack Carterb4dbc172012-09-05 23:34:03 +00001020 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001021 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +00001022 return Imm.Val;
1023 }
1024
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001025 int64_t getConstantImm() const {
1026 const MCExpr *Val = getImm();
1027 return static_cast<const MCConstantExpr *>(Val)->getValue();
1028 }
1029
1030 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001031 assert((Kind == k_Memory) && "Invalid access!");
1032 return Mem.Base;
1033 }
1034
1035 const MCExpr *getMemOff() const {
1036 assert((Kind == k_Memory) && "Invalid access!");
1037 return Mem.Off;
1038 }
1039
Daniel Sanders5e6f54e2014-06-16 10:00:45 +00001040 int64_t getConstantMemOff() const {
1041 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
1042 }
1043
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001044 const SmallVectorImpl<unsigned> &getRegList() const {
1045 assert((Kind == k_RegList) && "Invalid access!");
1046 return *(RegList.List);
1047 }
1048
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001049 unsigned getRegPair() const {
1050 assert((Kind == k_RegPair) && "Invalid access!");
1051 return RegIdx.Index;
1052 }
1053
David Blaikie960ea3f2014-06-08 16:18:35 +00001054 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
1055 MipsAsmParser &Parser) {
1056 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001057 Op->Tok.Data = Str.data();
1058 Op->Tok.Length = Str.size();
1059 Op->StartLoc = S;
1060 Op->EndLoc = S;
1061 return Op;
1062 }
1063
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001064 /// Create a numeric register (e.g. $1). The exact register remains
1065 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +00001066 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001067 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001068 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +00001069 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001070 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001071 }
1072
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001073 /// Create a register that is definitely a GPR.
1074 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +00001075 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001076 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001077 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001078 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001079 }
1080
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001081 /// Create a register that is definitely a FGR.
1082 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001083 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001084 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001085 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001086 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
1087 }
1088
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00001089 /// Create a register that is definitely a HWReg.
1090 /// This is typically only used for named registers such as $hwr_cpunum.
1091 static std::unique_ptr<MipsOperand>
1092 createHWRegsReg(unsigned Index, const MCRegisterInfo *RegInfo,
1093 SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1094 return CreateReg(Index, RegKind_HWRegs, RegInfo, S, E, Parser);
1095 }
1096
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001097 /// Create a register that is definitely an FCC.
1098 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001099 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001100 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001101 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001102 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
1103 }
1104
1105 /// Create a register that is definitely an ACC.
1106 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001107 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001108 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +00001109 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001110 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
1111 }
1112
1113 /// Create a register that is definitely an MSA128.
1114 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +00001115 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001116 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001117 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001118 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
1119 }
1120
1121 /// Create a register that is definitely an MSACtrl.
1122 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +00001123 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +00001124 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001125 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001126 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
1127 }
1128
David Blaikie960ea3f2014-06-08 16:18:35 +00001129 static std::unique_ptr<MipsOperand>
1130 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1131 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +00001132 Op->Imm.Val = Val;
1133 Op->StartLoc = S;
1134 Op->EndLoc = E;
1135 return Op;
1136 }
1137
David Blaikie960ea3f2014-06-08 16:18:35 +00001138 static std::unique_ptr<MipsOperand>
1139 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
1140 SMLoc E, MipsAsmParser &Parser) {
1141 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
1142 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001143 Op->Mem.Off = Off;
1144 Op->StartLoc = S;
1145 Op->EndLoc = E;
1146 return Op;
1147 }
1148
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001149 static std::unique_ptr<MipsOperand>
1150 CreateRegList(SmallVectorImpl<unsigned> &Regs, SMLoc StartLoc, SMLoc EndLoc,
1151 MipsAsmParser &Parser) {
1152 assert (Regs.size() > 0 && "Empty list not allowed");
1153
1154 auto Op = make_unique<MipsOperand>(k_RegList, Parser);
Benjamin Kramer6cd780f2015-02-17 15:29:18 +00001155 Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end());
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001156 Op->StartLoc = StartLoc;
1157 Op->EndLoc = EndLoc;
1158 return Op;
1159 }
1160
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001161 static std::unique_ptr<MipsOperand>
1162 CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
1163 auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
1164 Op->RegIdx.Index = RegNo;
1165 Op->StartLoc = S;
1166 Op->EndLoc = E;
1167 return Op;
1168 }
1169
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001170 bool isGPRAsmReg() const {
1171 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001172 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +00001173 bool isMM16AsmReg() const {
1174 if (!(isRegIdx() && RegIdx.Kind))
1175 return false;
1176 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
1177 || RegIdx.Index == 16 || RegIdx.Index == 17);
1178 }
Jozef Kolek1904fa22014-11-24 14:25:53 +00001179 bool isMM16AsmRegZero() const {
1180 if (!(isRegIdx() && RegIdx.Kind))
1181 return false;
1182 return (RegIdx.Index == 0 ||
1183 (RegIdx.Index >= 2 && RegIdx.Index <= 7) ||
1184 RegIdx.Index == 17);
1185 }
Zoran Jovanovic41688672015-02-10 16:36:20 +00001186 bool isMM16AsmRegMoveP() const {
1187 if (!(isRegIdx() && RegIdx.Kind))
1188 return false;
1189 return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) ||
1190 (RegIdx.Index >= 16 && RegIdx.Index <= 20));
1191 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001192 bool isFGRAsmReg() const {
1193 // AFGR64 is $0-$15 but we handle this in getAFGR64()
1194 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001195 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001196 bool isHWRegsAsmReg() const {
1197 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001198 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001199 bool isCCRAsmReg() const {
1200 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +00001201 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001202 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +00001203 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
1204 return false;
1205 if (!AsmParser.hasEightFccRegisters())
1206 return RegIdx.Index == 0;
1207 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +00001208 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001209 bool isACCAsmReg() const {
1210 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +00001211 }
Daniel Sandersa3134fa2015-06-27 15:39:19 +00001212 bool isCOP0AsmReg() const {
1213 return isRegIdx() && RegIdx.Kind & RegKind_COP0 && RegIdx.Index <= 31;
1214 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001215 bool isCOP2AsmReg() const {
1216 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001217 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +00001218 bool isCOP3AsmReg() const {
1219 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
1220 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001221 bool isMSA128AsmReg() const {
1222 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +00001223 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001224 bool isMSACtrlAsmReg() const {
1225 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001226 }
1227
Jack Carterb4dbc172012-09-05 23:34:03 +00001228 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001229 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001230 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +00001231 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +00001232
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001233 virtual ~MipsOperand() {
1234 switch (Kind) {
1235 case k_Immediate:
1236 break;
1237 case k_Memory:
1238 delete Mem.Base;
1239 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001240 case k_RegList:
1241 delete RegList.List;
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001242 case k_PhysRegister:
1243 case k_RegisterIndex:
1244 case k_Token:
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001245 case k_RegPair:
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001246 break;
1247 }
1248 }
1249
Craig Topper56c590a2014-04-29 07:58:02 +00001250 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001251 switch (Kind) {
1252 case k_Immediate:
1253 OS << "Imm<";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001254 OS << *Imm.Val;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001255 OS << ">";
1256 break;
1257 case k_Memory:
1258 OS << "Mem<";
1259 Mem.Base->print(OS);
1260 OS << ", ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001261 OS << *Mem.Off;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001262 OS << ">";
1263 break;
1264 case k_PhysRegister:
1265 OS << "PhysReg<" << PhysReg.Num << ">";
1266 break;
1267 case k_RegisterIndex:
1268 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
1269 break;
1270 case k_Token:
1271 OS << Tok.Data;
1272 break;
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00001273 case k_RegList:
1274 OS << "RegList< ";
1275 for (auto Reg : (*RegList.List))
1276 OS << Reg << " ";
1277 OS << ">";
1278 break;
Zoran Jovanovic2deca342014-12-16 14:59:10 +00001279 case k_RegPair:
1280 OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">";
1281 break;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001282 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001283 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001284}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001285} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001286
Jack Carter9e65aa32013-03-22 00:05:30 +00001287namespace llvm {
1288extern const MCInstrDesc MipsInsts[];
1289}
1290static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1291 return MipsInsts[Opcode];
1292}
1293
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001294static bool hasShortDelaySlot(unsigned Opcode) {
1295 switch (Opcode) {
1296 case Mips::JALS_MM:
1297 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001298 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001299 case Mips::BGEZALS_MM:
1300 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001301 return true;
1302 default:
1303 return false;
1304 }
1305}
1306
Jack Carter9e65aa32013-03-22 00:05:30 +00001307bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001308 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001309 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +00001310
Jack Carter9e65aa32013-03-22 00:05:30 +00001311 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001312
1313 if (MCID.isBranch() || MCID.isCall()) {
1314 const unsigned Opcode = Inst.getOpcode();
1315 MCOperand Offset;
1316
1317 switch (Opcode) {
1318 default:
1319 break;
Kai Nackee0245392015-01-27 19:11:28 +00001320 case Mips::BBIT0:
1321 case Mips::BBIT032:
1322 case Mips::BBIT1:
1323 case Mips::BBIT132:
1324 assert(hasCnMips() && "instruction only valid for octeon cpus");
1325 // Fall through
1326
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001327 case Mips::BEQ:
1328 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001329 case Mips::BEQ_MM:
1330 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001331 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001332 Offset = Inst.getOperand(2);
1333 if (!Offset.isImm())
1334 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001335 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001336 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001337 if (OffsetToAlignment(Offset.getImm(),
1338 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001339 return Error(IDLoc, "branch to misaligned address");
1340 break;
1341 case Mips::BGEZ:
1342 case Mips::BGTZ:
1343 case Mips::BLEZ:
1344 case Mips::BLTZ:
1345 case Mips::BGEZAL:
1346 case Mips::BLTZAL:
1347 case Mips::BC1F:
1348 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001349 case Mips::BGEZ_MM:
1350 case Mips::BGTZ_MM:
1351 case Mips::BLEZ_MM:
1352 case Mips::BLTZ_MM:
1353 case Mips::BGEZAL_MM:
1354 case Mips::BLTZAL_MM:
1355 case Mips::BC1F_MM:
1356 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001357 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001358 Offset = Inst.getOperand(1);
1359 if (!Offset.isImm())
1360 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001361 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001362 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001363 if (OffsetToAlignment(Offset.getImm(),
1364 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001365 return Error(IDLoc, "branch to misaligned address");
1366 break;
Jozef Kolek9761e962015-01-12 12:03:34 +00001367 case Mips::BEQZ16_MM:
1368 case Mips::BNEZ16_MM:
1369 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
1370 Offset = Inst.getOperand(1);
1371 if (!Offset.isImm())
1372 break; // We'll deal with this situation later on when applying fixups.
1373 if (!isIntN(8, Offset.getImm()))
1374 return Error(IDLoc, "branch target out of range");
1375 if (OffsetToAlignment(Offset.getImm(), 2LL))
1376 return Error(IDLoc, "branch to misaligned address");
1377 break;
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001378 }
1379 }
1380
Daniel Sandersa84989a2014-06-16 13:25:35 +00001381 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1382 // We still accept it but it is a normal nop.
1383 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1384 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1385 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1386 "nop instruction");
1387 }
1388
Kai Nackee0245392015-01-27 19:11:28 +00001389 if (hasCnMips()) {
1390 const unsigned Opcode = Inst.getOpcode();
1391 MCOperand Opnd;
1392 int Imm;
1393
1394 switch (Opcode) {
1395 default:
1396 break;
1397
1398 case Mips::BBIT0:
1399 case Mips::BBIT032:
1400 case Mips::BBIT1:
1401 case Mips::BBIT132:
1402 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1403 // The offset is handled above
1404 Opnd = Inst.getOperand(1);
1405 if (!Opnd.isImm())
1406 return Error(IDLoc, "expected immediate operand kind");
1407 Imm = Opnd.getImm();
1408 if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
1409 Opcode == Mips::BBIT1 ? 63 : 31))
1410 return Error(IDLoc, "immediate operand value out of range");
1411 if (Imm > 31) {
1412 Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
1413 : Mips::BBIT132);
1414 Inst.getOperand(1).setImm(Imm - 32);
1415 }
1416 break;
1417
1418 case Mips::CINS:
1419 case Mips::CINS32:
1420 case Mips::EXTS:
1421 case Mips::EXTS32:
1422 assert(MCID.getNumOperands() == 4 && "unexpected number of operands");
1423 // Check length
1424 Opnd = Inst.getOperand(3);
1425 if (!Opnd.isImm())
1426 return Error(IDLoc, "expected immediate operand kind");
1427 Imm = Opnd.getImm();
1428 if (Imm < 0 || Imm > 31)
1429 return Error(IDLoc, "immediate operand value out of range");
1430 // Check position
1431 Opnd = Inst.getOperand(2);
1432 if (!Opnd.isImm())
1433 return Error(IDLoc, "expected immediate operand kind");
1434 Imm = Opnd.getImm();
1435 if (Imm < 0 || Imm > (Opcode == Mips::CINS ||
1436 Opcode == Mips::EXTS ? 63 : 31))
1437 return Error(IDLoc, "immediate operand value out of range");
1438 if (Imm > 31) {
1439 Inst.setOpcode(Opcode == Mips::CINS ? Mips::CINS32 : Mips::EXTS32);
1440 Inst.getOperand(2).setImm(Imm - 32);
1441 }
1442 break;
1443
1444 case Mips::SEQi:
1445 case Mips::SNEi:
1446 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
1447 Opnd = Inst.getOperand(2);
1448 if (!Opnd.isImm())
1449 return Error(IDLoc, "expected immediate operand kind");
1450 Imm = Opnd.getImm();
1451 if (!isInt<10>(Imm))
1452 return Error(IDLoc, "immediate operand value out of range");
1453 break;
1454 }
1455 }
1456
Jack Carter9e65aa32013-03-22 00:05:30 +00001457 if (MCID.mayLoad() || MCID.mayStore()) {
1458 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001459 // reference or immediate we may have to expand instructions.
1460 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001461 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001462 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1463 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001464 MCOperand &Op = Inst.getOperand(i);
1465 if (Op.isImm()) {
1466 int MemOffset = Op.getImm();
1467 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001468 // Offset can't exceed 16bit value.
1469 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001470 return false;
1471 }
1472 } else if (Op.isExpr()) {
1473 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001474 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001475 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001476 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001477 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001478 // Expand symbol.
1479 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001480 return false;
1481 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001482 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001483 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001484 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001485 }
1486 }
1487 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001488 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001489 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001490
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001491 if (inMicroMipsMode()) {
Jozef Koleke10a02e2015-01-28 17:27:26 +00001492 if (MCID.mayLoad()) {
1493 // Try to create 16-bit GP relative load instruction.
1494 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
1495 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
1496 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1497 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
1498 MCOperand &Op = Inst.getOperand(i);
1499 if (Op.isImm()) {
1500 int MemOffset = Op.getImm();
1501 MCOperand &DstReg = Inst.getOperand(0);
1502 MCOperand &BaseReg = Inst.getOperand(1);
1503 if (isIntN(9, MemOffset) && (MemOffset % 4 == 0) &&
1504 getContext().getRegisterInfo()->getRegClass(
1505 Mips::GPRMM16RegClassID).contains(DstReg.getReg()) &&
1506 BaseReg.getReg() == Mips::GP) {
1507 MCInst TmpInst;
1508 TmpInst.setLoc(IDLoc);
1509 TmpInst.setOpcode(Mips::LWGP_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00001510 TmpInst.addOperand(MCOperand::createReg(DstReg.getReg()));
1511 TmpInst.addOperand(MCOperand::createReg(Mips::GP));
1512 TmpInst.addOperand(MCOperand::createImm(MemOffset));
Jozef Koleke10a02e2015-01-28 17:27:26 +00001513 Instructions.push_back(TmpInst);
1514 return false;
1515 }
1516 }
1517 }
1518 } // for
1519 } // if load
1520
1521 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1522
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001523 MCOperand Opnd;
1524 int Imm;
1525
1526 switch (Inst.getOpcode()) {
1527 default:
1528 break;
1529 case Mips::ADDIUS5_MM:
1530 Opnd = Inst.getOperand(2);
1531 if (!Opnd.isImm())
1532 return Error(IDLoc, "expected immediate operand kind");
1533 Imm = Opnd.getImm();
1534 if (Imm < -8 || Imm > 7)
1535 return Error(IDLoc, "immediate operand value out of range");
1536 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001537 case Mips::ADDIUSP_MM:
1538 Opnd = Inst.getOperand(0);
1539 if (!Opnd.isImm())
1540 return Error(IDLoc, "expected immediate operand kind");
1541 Imm = Opnd.getImm();
1542 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1543 Imm % 4 != 0)
1544 return Error(IDLoc, "immediate operand value out of range");
1545 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001546 case Mips::SLL16_MM:
1547 case Mips::SRL16_MM:
1548 Opnd = Inst.getOperand(2);
1549 if (!Opnd.isImm())
1550 return Error(IDLoc, "expected immediate operand kind");
1551 Imm = Opnd.getImm();
1552 if (Imm < 1 || Imm > 8)
1553 return Error(IDLoc, "immediate operand value out of range");
1554 break;
Zoran Jovanovic9bda2f12014-10-23 10:59:24 +00001555 case Mips::LI16_MM:
1556 Opnd = Inst.getOperand(1);
1557 if (!Opnd.isImm())
1558 return Error(IDLoc, "expected immediate operand kind");
1559 Imm = Opnd.getImm();
1560 if (Imm < -1 || Imm > 126)
1561 return Error(IDLoc, "immediate operand value out of range");
1562 break;
Zoran Jovanovicbac36192014-10-23 11:06:34 +00001563 case Mips::ADDIUR2_MM:
1564 Opnd = Inst.getOperand(2);
1565 if (!Opnd.isImm())
1566 return Error(IDLoc, "expected immediate operand kind");
1567 Imm = Opnd.getImm();
1568 if (!(Imm == 1 || Imm == -1 ||
1569 ((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
1570 return Error(IDLoc, "immediate operand value out of range");
1571 break;
Zoran Jovanovic42b84442014-10-23 11:13:59 +00001572 case Mips::ADDIUR1SP_MM:
1573 Opnd = Inst.getOperand(1);
1574 if (!Opnd.isImm())
1575 return Error(IDLoc, "expected immediate operand kind");
1576 Imm = Opnd.getImm();
1577 if (OffsetToAlignment(Imm, 4LL))
1578 return Error(IDLoc, "misaligned immediate operand value");
1579 if (Imm < 0 || Imm > 255)
1580 return Error(IDLoc, "immediate operand value out of range");
1581 break;
Zoran Jovanovic88531712014-11-05 17:31:00 +00001582 case Mips::ANDI16_MM:
1583 Opnd = Inst.getOperand(2);
1584 if (!Opnd.isImm())
1585 return Error(IDLoc, "expected immediate operand kind");
1586 Imm = Opnd.getImm();
1587 if (!(Imm == 128 || (Imm >= 1 && Imm <= 4) || Imm == 7 || Imm == 8 ||
1588 Imm == 15 || Imm == 16 || Imm == 31 || Imm == 32 || Imm == 63 ||
1589 Imm == 64 || Imm == 255 || Imm == 32768 || Imm == 65535))
1590 return Error(IDLoc, "immediate operand value out of range");
1591 break;
Jozef Koleke8c9d1e2014-11-24 14:39:13 +00001592 case Mips::LBU16_MM:
1593 Opnd = Inst.getOperand(2);
1594 if (!Opnd.isImm())
1595 return Error(IDLoc, "expected immediate operand kind");
1596 Imm = Opnd.getImm();
1597 if (Imm < -1 || Imm > 14)
1598 return Error(IDLoc, "immediate operand value out of range");
1599 break;
1600 case Mips::SB16_MM:
1601 Opnd = Inst.getOperand(2);
1602 if (!Opnd.isImm())
1603 return Error(IDLoc, "expected immediate operand kind");
1604 Imm = Opnd.getImm();
1605 if (Imm < 0 || Imm > 15)
1606 return Error(IDLoc, "immediate operand value out of range");
1607 break;
1608 case Mips::LHU16_MM:
1609 case Mips::SH16_MM:
1610 Opnd = Inst.getOperand(2);
1611 if (!Opnd.isImm())
1612 return Error(IDLoc, "expected immediate operand kind");
1613 Imm = Opnd.getImm();
1614 if (Imm < 0 || Imm > 30 || (Imm % 2 != 0))
1615 return Error(IDLoc, "immediate operand value out of range");
1616 break;
1617 case Mips::LW16_MM:
1618 case Mips::SW16_MM:
1619 Opnd = Inst.getOperand(2);
1620 if (!Opnd.isImm())
1621 return Error(IDLoc, "expected immediate operand kind");
1622 Imm = Opnd.getImm();
1623 if (Imm < 0 || Imm > 60 || (Imm % 4 != 0))
1624 return Error(IDLoc, "immediate operand value out of range");
1625 break;
Jozef Kolekab6d1cc2014-12-23 19:55:34 +00001626 case Mips::CACHE:
1627 case Mips::PREF:
1628 Opnd = Inst.getOperand(2);
1629 if (!Opnd.isImm())
1630 return Error(IDLoc, "expected immediate operand kind");
1631 Imm = Opnd.getImm();
1632 if (!isUInt<5>(Imm))
1633 return Error(IDLoc, "immediate operand value out of range");
1634 break;
Jozef Kolek2c6d7322015-01-21 12:10:11 +00001635 case Mips::ADDIUPC_MM:
1636 MCOperand Opnd = Inst.getOperand(1);
1637 if (!Opnd.isImm())
1638 return Error(IDLoc, "expected immediate operand kind");
1639 int Imm = Opnd.getImm();
1640 if ((Imm % 4 != 0) || !isIntN(25, Imm))
1641 return Error(IDLoc, "immediate operand value out of range");
1642 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001643 }
1644 }
1645
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001646 if (needsExpansion(Inst)) {
1647 if (expandInstruction(Inst, IDLoc, Instructions))
1648 return true;
1649 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001650 Instructions.push_back(Inst);
1651
Toma Tabacu7fc89d22015-04-23 14:48:38 +00001652 // If this instruction has a delay slot and .set reorder is active,
1653 // emit a NOP after it.
1654 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
1655 createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
1656
Jack Carter9e65aa32013-03-22 00:05:30 +00001657 return false;
1658}
1659
Jack Carter30a59822012-10-04 04:03:53 +00001660bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1661
Jack Carterd0bd6422013-04-18 00:41:53 +00001662 switch (Inst.getOpcode()) {
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001663 case Mips::LoadImm32:
1664 case Mips::LoadImm64:
1665 case Mips::LoadAddrImm32:
1666 case Mips::LoadAddrReg32:
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001667 case Mips::B_MM_Pseudo:
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001668 case Mips::LWM_MM:
1669 case Mips::SWM_MM:
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001670 case Mips::JalOneReg:
1671 case Mips::JalTwoReg:
Toma Tabacue1e460d2015-06-11 10:36:10 +00001672 case Mips::BneImm:
1673 case Mips::BeqImm:
Toma Tabacu1a108322015-06-17 13:20:24 +00001674 case Mips::BLT:
1675 case Mips::BLE:
1676 case Mips::BGE:
1677 case Mips::BGT:
1678 case Mips::BLTU:
1679 case Mips::BLEU:
1680 case Mips::BGEU:
1681 case Mips::BGTU:
Toma Tabacud88d79c2015-06-23 14:39:42 +00001682 case Mips::Ulhu:
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00001683 case Mips::Ulw:
Jack Carterd0bd6422013-04-18 00:41:53 +00001684 return true;
1685 default:
1686 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001687 }
1688}
Jack Carter92995f12012-10-06 00:53:28 +00001689
Matheus Almeida3813d572014-06-19 14:39:14 +00001690bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001691 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001692 switch (Inst.getOpcode()) {
Craig Topperd3c02f12015-01-05 10:15:49 +00001693 default: llvm_unreachable("unimplemented expansion");
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001694 case Mips::LoadImm32:
Toma Tabacu00e98672015-05-01 12:19:27 +00001695 return expandLoadImm(Inst, true, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001696 case Mips::LoadImm64:
Toma Tabacu00e98672015-05-01 12:19:27 +00001697 return expandLoadImm(Inst, false, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001698 case Mips::LoadAddrImm32:
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001699 return expandLoadAddressImm(Inst, true, IDLoc, Instructions);
Toma Tabacue1e3ffe2015-03-04 13:01:14 +00001700 case Mips::LoadAddrReg32:
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001701 return expandLoadAddressReg(Inst, true, IDLoc, Instructions);
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00001702 case Mips::B_MM_Pseudo:
1703 return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions);
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00001704 case Mips::SWM_MM:
1705 case Mips::LWM_MM:
1706 return expandLoadStoreMultiple(Inst, IDLoc, Instructions);
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001707 case Mips::JalOneReg:
1708 case Mips::JalTwoReg:
1709 return expandJalWithRegs(Inst, IDLoc, Instructions);
Toma Tabacue1e460d2015-06-11 10:36:10 +00001710 case Mips::BneImm:
1711 case Mips::BeqImm:
1712 return expandBranchImm(Inst, IDLoc, Instructions);
Toma Tabacu1a108322015-06-17 13:20:24 +00001713 case Mips::BLT:
1714 case Mips::BLE:
1715 case Mips::BGE:
1716 case Mips::BGT:
1717 case Mips::BLTU:
1718 case Mips::BLEU:
1719 case Mips::BGEU:
1720 case Mips::BGTU:
1721 return expandCondBranches(Inst, IDLoc, Instructions);
Toma Tabacud88d79c2015-06-23 14:39:42 +00001722 case Mips::Ulhu:
1723 return expandUlhu(Inst, IDLoc, Instructions);
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00001724 case Mips::Ulw:
1725 return expandUlw(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001726 }
Jack Carter30a59822012-10-04 04:03:53 +00001727}
Jack Carter92995f12012-10-06 00:53:28 +00001728
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001729namespace {
Toma Tabacua2861db2015-05-01 10:26:47 +00001730template <unsigned ShiftAmount>
Toma Tabacu61145652015-04-28 13:16:06 +00001731void createLShiftOri(MCOperand Operand, unsigned RegNo, SMLoc IDLoc,
Toma Tabacua2861db2015-05-01 10:26:47 +00001732 SmallVectorImpl<MCInst> &Instructions) {
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001733 MCInst tmpInst;
Toma Tabacua2861db2015-05-01 10:26:47 +00001734 if (ShiftAmount >= 32) {
1735 tmpInst.setOpcode(Mips::DSLL32);
Jim Grosbache9119e42015-05-13 18:37:00 +00001736 tmpInst.addOperand(MCOperand::createReg(RegNo));
1737 tmpInst.addOperand(MCOperand::createReg(RegNo));
1738 tmpInst.addOperand(MCOperand::createImm(ShiftAmount - 32));
Toma Tabacua2861db2015-05-01 10:26:47 +00001739 tmpInst.setLoc(IDLoc);
1740 Instructions.push_back(tmpInst);
1741 tmpInst.clear();
1742 } else if (ShiftAmount > 0) {
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001743 tmpInst.setOpcode(Mips::DSLL);
Jim Grosbache9119e42015-05-13 18:37:00 +00001744 tmpInst.addOperand(MCOperand::createReg(RegNo));
1745 tmpInst.addOperand(MCOperand::createReg(RegNo));
1746 tmpInst.addOperand(MCOperand::createImm(ShiftAmount));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001747 tmpInst.setLoc(IDLoc);
1748 Instructions.push_back(tmpInst);
1749 tmpInst.clear();
1750 }
Toma Tabacu7dea2e32015-04-28 14:06:35 +00001751 // There's no need for an ORi if the immediate is 0.
1752 if (Operand.isImm() && Operand.getImm() == 0)
1753 return;
1754
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001755 tmpInst.setOpcode(Mips::ORi);
Jim Grosbache9119e42015-05-13 18:37:00 +00001756 tmpInst.addOperand(MCOperand::createReg(RegNo));
1757 tmpInst.addOperand(MCOperand::createReg(RegNo));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001758 tmpInst.addOperand(Operand);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001759 tmpInst.setLoc(IDLoc);
1760 Instructions.push_back(tmpInst);
1761}
Toma Tabacu0d64b202014-08-14 10:29:17 +00001762
Toma Tabacua2861db2015-05-01 10:26:47 +00001763template <unsigned ShiftAmount>
Toma Tabacu61145652015-04-28 13:16:06 +00001764void createLShiftOri(int64_t Value, unsigned RegNo, SMLoc IDLoc,
Toma Tabacua2861db2015-05-01 10:26:47 +00001765 SmallVectorImpl<MCInst> &Instructions) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001766 createLShiftOri<ShiftAmount>(MCOperand::createImm(Value), RegNo, IDLoc,
Toma Tabacua2861db2015-05-01 10:26:47 +00001767 Instructions);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001768}
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001769}
1770
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001771bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
1772 SmallVectorImpl<MCInst> &Instructions) {
1773 // Create a JALR instruction which is going to replace the pseudo-JAL.
1774 MCInst JalrInst;
1775 JalrInst.setLoc(IDLoc);
1776 const MCOperand FirstRegOp = Inst.getOperand(0);
1777 const unsigned Opcode = Inst.getOpcode();
1778
1779 if (Opcode == Mips::JalOneReg) {
1780 // jal $rs => jalr $rs
1781 if (inMicroMipsMode()) {
1782 JalrInst.setOpcode(Mips::JALR16_MM);
1783 JalrInst.addOperand(FirstRegOp);
1784 } else {
1785 JalrInst.setOpcode(Mips::JALR);
Jim Grosbache9119e42015-05-13 18:37:00 +00001786 JalrInst.addOperand(MCOperand::createReg(Mips::RA));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001787 JalrInst.addOperand(FirstRegOp);
1788 }
1789 } else if (Opcode == Mips::JalTwoReg) {
1790 // jal $rd, $rs => jalr $rd, $rs
1791 JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
1792 JalrInst.addOperand(FirstRegOp);
1793 const MCOperand SecondRegOp = Inst.getOperand(1);
1794 JalrInst.addOperand(SecondRegOp);
1795 }
1796 Instructions.push_back(JalrInst);
1797
1798 // If .set reorder is active, emit a NOP after it.
1799 if (AssemblerOptions.back()->isReorder()) {
1800 // This is a 32-bit NOP because these 2 pseudo-instructions
1801 // do not have a short delay slot.
1802 MCInst NopInst;
1803 NopInst.setOpcode(Mips::SLL);
Jim Grosbache9119e42015-05-13 18:37:00 +00001804 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
1805 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
1806 NopInst.addOperand(MCOperand::createImm(0));
Toma Tabacu8f6603a2015-01-30 11:18:50 +00001807 Instructions.push_back(NopInst);
1808 }
1809
1810 return false;
1811}
1812
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001813bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
1814 unsigned SrcReg, bool Is32BitImm, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001815 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu00e98672015-05-01 12:19:27 +00001816 if (!Is32BitImm && !isGP64bit()) {
1817 Error(IDLoc, "instruction requires a 64-bit architecture");
1818 return true;
1819 }
1820
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001821 bool UseSrcReg = false;
1822 if (SrcReg != Mips::NoRegister)
1823 UseSrcReg = true;
Jack Carter30a59822012-10-04 04:03:53 +00001824
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001825 MCInst tmpInst;
1826
Toma Tabacu8e0316d2015-06-22 13:10:23 +00001827 unsigned TmpReg = DstReg;
1828 if (UseSrcReg && (DstReg == SrcReg)) {
1829 // At this point we need AT to perform the expansions and we exit if it is
1830 // not available.
1831 unsigned ATReg = getATReg(IDLoc);
1832 if (!ATReg)
1833 return true;
1834 TmpReg = ATReg;
1835 }
1836
Jack Carter92995f12012-10-06 00:53:28 +00001837 tmpInst.setLoc(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001838 // FIXME: gas has a special case for values that are 000...1111, which
1839 // becomes a li -1 and then a dsrl
Jack Carterd0bd6422013-04-18 00:41:53 +00001840 if (0 <= ImmValue && ImmValue <= 65535) {
Toma Tabacuae47f932015-04-10 13:28:16 +00001841 // For unsigned and positive signed 16-bit values (0 <= j <= 65535):
Jack Carter30a59822012-10-04 04:03:53 +00001842 // li d,j => ori d,$zero,j
Toma Tabacudf7fd462015-05-13 16:02:41 +00001843 if (!UseSrcReg)
1844 SrcReg = isGP64bit() ? Mips::ZERO_64 : Mips::ZERO;
Jack Carter873c7242013-01-12 01:03:14 +00001845 tmpInst.setOpcode(Mips::ORi);
Jim Grosbache9119e42015-05-13 18:37:00 +00001846 tmpInst.addOperand(MCOperand::createReg(DstReg));
1847 tmpInst.addOperand(MCOperand::createReg(SrcReg));
1848 tmpInst.addOperand(MCOperand::createImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001849 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001850 } else if (ImmValue < 0 && ImmValue >= -32768) {
Toma Tabacuae47f932015-04-10 13:28:16 +00001851 // For negative signed 16-bit values (-32768 <= j < 0):
Jack Carter30a59822012-10-04 04:03:53 +00001852 // li d,j => addiu d,$zero,j
Toma Tabacudf7fd462015-05-13 16:02:41 +00001853 if (!UseSrcReg)
1854 SrcReg = Mips::ZERO;
Jack Carter873c7242013-01-12 01:03:14 +00001855 tmpInst.setOpcode(Mips::ADDiu);
Jim Grosbache9119e42015-05-13 18:37:00 +00001856 tmpInst.addOperand(MCOperand::createReg(DstReg));
1857 tmpInst.addOperand(MCOperand::createReg(SrcReg));
1858 tmpInst.addOperand(MCOperand::createImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001859 Instructions.push_back(tmpInst);
Toma Tabacua3d056f2015-05-15 09:42:11 +00001860 } else if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) {
Toma Tabacu81496c12015-05-20 08:54:45 +00001861 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00001862
Toma Tabacuae47f932015-04-10 13:28:16 +00001863 // For all other values which are representable as a 32-bit integer:
Jack Carter30a59822012-10-04 04:03:53 +00001864 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001865 // ori d,d,lo16(j)
Toma Tabacu79588102015-04-29 10:19:56 +00001866 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
1867 uint16_t Bits15To0 = ImmValue & 0xffff;
1868
Toma Tabacua3d056f2015-05-15 09:42:11 +00001869 if (!Is32BitImm && !isInt<32>(ImmValue)) {
1870 // For DLI, expand to an ORi instead of a LUi to avoid sign-extending the
1871 // upper 32 bits.
1872 tmpInst.setOpcode(Mips::ORi);
Toma Tabacu8e0316d2015-06-22 13:10:23 +00001873 tmpInst.addOperand(MCOperand::createReg(TmpReg));
Toma Tabacua3d056f2015-05-15 09:42:11 +00001874 tmpInst.addOperand(MCOperand::createReg(Mips::ZERO));
1875 tmpInst.addOperand(MCOperand::createImm(Bits31To16));
1876 tmpInst.setLoc(IDLoc);
1877 Instructions.push_back(tmpInst);
1878 // Move the value to the upper 16 bits by doing a 16-bit left shift.
Toma Tabacu8e0316d2015-06-22 13:10:23 +00001879 createLShiftOri<16>(0, TmpReg, IDLoc, Instructions);
Toma Tabacua3d056f2015-05-15 09:42:11 +00001880 } else {
1881 tmpInst.setOpcode(Mips::LUi);
Toma Tabacu8e0316d2015-06-22 13:10:23 +00001882 tmpInst.addOperand(MCOperand::createReg(TmpReg));
Toma Tabacua3d056f2015-05-15 09:42:11 +00001883 tmpInst.addOperand(MCOperand::createImm(Bits31To16));
1884 Instructions.push_back(tmpInst);
1885 }
Toma Tabacu8e0316d2015-06-22 13:10:23 +00001886 createLShiftOri<0>(Bits15To0, TmpReg, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001887
1888 if (UseSrcReg)
Toma Tabacu0b3e9782015-06-23 14:00:54 +00001889 createAddu(DstReg, TmpReg, SrcReg, !Is32BitImm, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001890
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001891 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
Toma Tabacu00e98672015-05-01 12:19:27 +00001892 if (Is32BitImm) {
1893 Error(IDLoc, "instruction requires a 32-bit immediate");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001894 return true;
1895 }
Toma Tabacu81496c12015-05-20 08:54:45 +00001896 warnIfNoMacro(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001897
1898 // <------- lo32 ------>
1899 // <------- hi32 ------>
1900 // <- hi16 -> <- lo16 ->
1901 // _________________________________
1902 // | | | |
Toma Tabacubda745f2015-04-27 15:21:38 +00001903 // | 16-bits | 16-bits | 16-bits |
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001904 // |__________|__________|__________|
1905 //
Toma Tabacuae47f932015-04-10 13:28:16 +00001906 // For any 64-bit value that is representable as a 48-bit integer:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001907 // li d,j => lui d,hi16(j)
1908 // ori d,d,hi16(lo32(j))
1909 // dsll d,d,16
1910 // ori d,d,lo16(lo32(j))
Toma Tabacu79588102015-04-29 10:19:56 +00001911 uint16_t Bits47To32 = (ImmValue >> 32) & 0xffff;
1912 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
1913 uint16_t Bits15To0 = ImmValue & 0xffff;
1914
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001915 tmpInst.setOpcode(Mips::LUi);
Toma Tabacu8e0316d2015-06-22 13:10:23 +00001916 tmpInst.addOperand(MCOperand::createReg(TmpReg));
Jim Grosbache9119e42015-05-13 18:37:00 +00001917 tmpInst.addOperand(MCOperand::createImm(Bits47To32));
Jack Carter30a59822012-10-04 04:03:53 +00001918 Instructions.push_back(tmpInst);
Toma Tabacu8e0316d2015-06-22 13:10:23 +00001919 createLShiftOri<0>(Bits31To16, TmpReg, IDLoc, Instructions);
1920 createLShiftOri<16>(Bits15To0, TmpReg, IDLoc, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001921
1922 if (UseSrcReg)
Toma Tabacu0b3e9782015-06-23 14:00:54 +00001923 createAddu(DstReg, TmpReg, SrcReg, !Is32BitImm, Instructions);
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001924
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001925 } else {
Toma Tabacu00e98672015-05-01 12:19:27 +00001926 if (Is32BitImm) {
1927 Error(IDLoc, "instruction requires a 32-bit immediate");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001928 return true;
1929 }
Toma Tabacu81496c12015-05-20 08:54:45 +00001930 warnIfNoMacro(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001931
1932 // <------- hi32 ------> <------- lo32 ------>
1933 // <- hi16 -> <- lo16 ->
1934 // ___________________________________________
1935 // | | | | |
Toma Tabacubda745f2015-04-27 15:21:38 +00001936 // | 16-bits | 16-bits | 16-bits | 16-bits |
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001937 // |__________|__________|__________|__________|
1938 //
Toma Tabacuae47f932015-04-10 13:28:16 +00001939 // For all other values which are representable as a 64-bit integer:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001940 // li d,j => lui d,hi16(j)
1941 // ori d,d,lo16(hi32(j))
1942 // dsll d,d,16
1943 // ori d,d,hi16(lo32(j))
1944 // dsll d,d,16
1945 // ori d,d,lo16(lo32(j))
Toma Tabacu79588102015-04-29 10:19:56 +00001946 uint16_t Bits63To48 = (ImmValue >> 48) & 0xffff;
1947 uint16_t Bits47To32 = (ImmValue >> 32) & 0xffff;
1948 uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff;
1949 uint16_t Bits15To0 = ImmValue & 0xffff;
1950
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001951 tmpInst.setOpcode(Mips::LUi);
Toma Tabacu8e0316d2015-06-22 13:10:23 +00001952 tmpInst.addOperand(MCOperand::createReg(TmpReg));
Jim Grosbache9119e42015-05-13 18:37:00 +00001953 tmpInst.addOperand(MCOperand::createImm(Bits63To48));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001954 Instructions.push_back(tmpInst);
Toma Tabacu8e0316d2015-06-22 13:10:23 +00001955 createLShiftOri<0>(Bits47To32, TmpReg, IDLoc, Instructions);
Toma Tabacua2861db2015-05-01 10:26:47 +00001956
1957 // When Bits31To16 is 0, do a left shift of 32 bits instead of doing
1958 // two left shifts of 16 bits.
1959 if (Bits31To16 == 0) {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00001960 createLShiftOri<32>(Bits15To0, TmpReg, IDLoc, Instructions);
Toma Tabacua2861db2015-05-01 10:26:47 +00001961 } else {
Toma Tabacu8e0316d2015-06-22 13:10:23 +00001962 createLShiftOri<16>(Bits31To16, TmpReg, IDLoc, Instructions);
1963 createLShiftOri<16>(Bits15To0, TmpReg, IDLoc, Instructions);
Toma Tabacua2861db2015-05-01 10:26:47 +00001964 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001965
1966 if (UseSrcReg)
Toma Tabacu0b3e9782015-06-23 14:00:54 +00001967 createAddu(DstReg, TmpReg, SrcReg, !Is32BitImm, Instructions);
Jack Carter30a59822012-10-04 04:03:53 +00001968 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001969 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001970}
Jack Carter92995f12012-10-06 00:53:28 +00001971
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001972bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
1973 SmallVectorImpl<MCInst> &Instructions) {
1974 const MCOperand &ImmOp = Inst.getOperand(1);
1975 assert(ImmOp.isImm() && "expected immediate operand kind");
1976 const MCOperand &DstRegOp = Inst.getOperand(0);
1977 assert(DstRegOp.isReg() && "expected register operand kind");
1978
1979 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
1980 Is32BitImm, IDLoc, Instructions))
1981 return true;
1982
1983 return false;
1984}
1985
Matheus Almeida3813d572014-06-19 14:39:14 +00001986bool
Toma Tabacud0a7ff22015-05-13 13:56:16 +00001987MipsAsmParser::expandLoadAddressReg(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001988 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacub5592ee2015-05-14 10:02:58 +00001989 const MCOperand &DstRegOp = Inst.getOperand(0);
1990 assert(DstRegOp.isReg() && "expected register operand kind");
1991
Toma Tabacuf712ede2015-06-17 14:31:51 +00001992 const MCOperand &SrcRegOp = Inst.getOperand(1);
1993 assert(SrcRegOp.isReg() && "expected register operand kind");
1994
Jack Carter543fdf82012-10-09 23:29:45 +00001995 const MCOperand &ImmOp = Inst.getOperand(2);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001996 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1997 "expected immediate operand kind");
1998 if (!ImmOp.isImm()) {
Toma Tabacuf712ede2015-06-17 14:31:51 +00001999 if (loadAndAddSymbolAddress(ImmOp.getExpr(), DstRegOp.getReg(),
2000 SrcRegOp.getReg(), Is32BitImm, IDLoc,
2001 Instructions))
Toma Tabacu674825c2015-06-16 12:16:24 +00002002 return true;
2003
Toma Tabacu0d64b202014-08-14 10:29:17 +00002004 return false;
2005 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002006
2007 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), SrcRegOp.getReg(),
2008 Is32BitImm, IDLoc, Instructions))
2009 return true;
2010
Matheus Almeida3813d572014-06-19 14:39:14 +00002011 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00002012}
2013
Matheus Almeida3813d572014-06-19 14:39:14 +00002014bool
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002015MipsAsmParser::expandLoadAddressImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00002016 SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacub5592ee2015-05-14 10:02:58 +00002017 const MCOperand &DstRegOp = Inst.getOperand(0);
2018 assert(DstRegOp.isReg() && "expected register operand kind");
2019
Jack Carter543fdf82012-10-09 23:29:45 +00002020 const MCOperand &ImmOp = Inst.getOperand(1);
Toma Tabacu0d64b202014-08-14 10:29:17 +00002021 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
2022 "expected immediate operand kind");
2023 if (!ImmOp.isImm()) {
Toma Tabacuf712ede2015-06-17 14:31:51 +00002024 if (loadAndAddSymbolAddress(ImmOp.getExpr(), DstRegOp.getReg(),
2025 Mips::NoRegister, Is32BitImm, IDLoc,
2026 Instructions))
Toma Tabacu674825c2015-06-16 12:16:24 +00002027 return true;
2028
Toma Tabacu0d64b202014-08-14 10:29:17 +00002029 return false;
2030 }
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002031
2032 if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
2033 Is32BitImm, IDLoc, Instructions))
2034 return true;
2035
Matheus Almeida3813d572014-06-19 14:39:14 +00002036 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00002037}
2038
Toma Tabacuf712ede2015-06-17 14:31:51 +00002039bool MipsAsmParser::loadAndAddSymbolAddress(
2040 const MCExpr *SymExpr, unsigned DstReg, unsigned SrcReg, bool Is32BitSym,
2041 SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
Toma Tabacu81496c12015-05-20 08:54:45 +00002042 warnIfNoMacro(IDLoc);
Toma Tabacue625b5f2015-05-14 14:51:32 +00002043
Toma Tabacuec1de822015-05-14 10:53:40 +00002044 if (Is32BitSym && isABI_N64())
2045 Warning(IDLoc, "instruction loads the 32-bit address of a 64-bit symbol");
2046
Toma Tabacu0d64b202014-08-14 10:29:17 +00002047 MCInst tmpInst;
Toma Tabacu674825c2015-06-16 12:16:24 +00002048 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymExpr);
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002049 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::create(
2050 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
2051 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::create(
2052 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
2053
Toma Tabacufb9d1252015-06-22 12:08:39 +00002054 bool UseSrcReg = SrcReg != Mips::NoRegister;
2055
2056 unsigned TmpReg = DstReg;
2057 if (UseSrcReg && (DstReg == SrcReg)) {
2058 // At this point we need AT to perform the expansions and we exit if it is
2059 // not available.
2060 unsigned ATReg = getATReg(IDLoc);
2061 if (!ATReg)
2062 return true;
2063 TmpReg = ATReg;
2064 }
2065
Toma Tabacuec1de822015-05-14 10:53:40 +00002066 if (!Is32BitSym) {
Toma Tabacu0d64b202014-08-14 10:29:17 +00002067 // If it's a 64-bit architecture, expand to:
2068 // la d,sym => lui d,highest(sym)
2069 // ori d,d,higher(sym)
2070 // dsll d,d,16
2071 // ori d,d,hi16(sym)
2072 // dsll d,d,16
2073 // ori d,d,lo16(sym)
Toma Tabacu9e7b90c2015-06-17 12:30:37 +00002074 const MCSymbolRefExpr *HighestExpr = MCSymbolRefExpr::create(
2075 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
2076 const MCSymbolRefExpr *HigherExpr = MCSymbolRefExpr::create(
2077 &Symbol->getSymbol(), MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
Toma Tabacu0d64b202014-08-14 10:29:17 +00002078
2079 tmpInst.setOpcode(Mips::LUi);
Toma Tabacufb9d1252015-06-22 12:08:39 +00002080 tmpInst.addOperand(MCOperand::createReg(TmpReg));
Jim Grosbache9119e42015-05-13 18:37:00 +00002081 tmpInst.addOperand(MCOperand::createExpr(HighestExpr));
Toma Tabacu0d64b202014-08-14 10:29:17 +00002082 Instructions.push_back(tmpInst);
2083
Toma Tabacufb9d1252015-06-22 12:08:39 +00002084 createLShiftOri<0>(MCOperand::createExpr(HigherExpr), TmpReg, SMLoc(),
Toma Tabacua2861db2015-05-01 10:26:47 +00002085 Instructions);
Toma Tabacufb9d1252015-06-22 12:08:39 +00002086 createLShiftOri<16>(MCOperand::createExpr(HiExpr), TmpReg, SMLoc(),
Toma Tabacu0d64b202014-08-14 10:29:17 +00002087 Instructions);
Toma Tabacufb9d1252015-06-22 12:08:39 +00002088 createLShiftOri<16>(MCOperand::createExpr(LoExpr), TmpReg, SMLoc(),
Toma Tabacu0d64b202014-08-14 10:29:17 +00002089 Instructions);
2090 } else {
2091 // Otherwise, expand to:
2092 // la d,sym => lui d,hi16(sym)
2093 // ori d,d,lo16(sym)
2094 tmpInst.setOpcode(Mips::LUi);
Toma Tabacufb9d1252015-06-22 12:08:39 +00002095 tmpInst.addOperand(MCOperand::createReg(TmpReg));
Jim Grosbache9119e42015-05-13 18:37:00 +00002096 tmpInst.addOperand(MCOperand::createExpr(HiExpr));
Toma Tabacu0d64b202014-08-14 10:29:17 +00002097 Instructions.push_back(tmpInst);
2098
Toma Tabacufb9d1252015-06-22 12:08:39 +00002099 createLShiftOri<0>(MCOperand::createExpr(LoExpr), TmpReg, SMLoc(),
Toma Tabacua2861db2015-05-01 10:26:47 +00002100 Instructions);
Toma Tabacu0d64b202014-08-14 10:29:17 +00002101 }
Toma Tabacuf712ede2015-06-17 14:31:51 +00002102
Toma Tabacufb9d1252015-06-22 12:08:39 +00002103 if (UseSrcReg)
Toma Tabacu0b3e9782015-06-23 14:00:54 +00002104 createAddu(DstReg, TmpReg, SrcReg, !Is32BitSym, Instructions);
Toma Tabacuf712ede2015-06-17 14:31:51 +00002105
Toma Tabacu674825c2015-06-16 12:16:24 +00002106 return false;
Toma Tabacu0d64b202014-08-14 10:29:17 +00002107}
2108
NAKAMURA Takumi2bbc90c2015-01-23 01:02:07 +00002109bool MipsAsmParser::expandUncondBranchMMPseudo(
2110 MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
NAKAMURA Takumif6eee4a2015-01-23 01:01:52 +00002111 assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
2112 "unexpected number of operands");
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002113
2114 MCOperand Offset = Inst.getOperand(0);
2115 if (Offset.isExpr()) {
2116 Inst.clear();
2117 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002118 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2119 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2120 Inst.addOperand(MCOperand::createExpr(Offset.getExpr()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002121 } else {
2122 assert(Offset.isImm() && "expected immediate operand kind");
2123 if (isIntN(11, Offset.getImm())) {
2124 // If offset fits into 11 bits then this instruction becomes microMIPS
2125 // 16-bit unconditional branch instruction.
2126 Inst.setOpcode(Mips::B16_MM);
2127 } else {
2128 if (!isIntN(17, Offset.getImm()))
2129 Error(IDLoc, "branch target out of range");
2130 if (OffsetToAlignment(Offset.getImm(), 1LL << 1))
2131 Error(IDLoc, "branch to misaligned address");
2132 Inst.clear();
2133 Inst.setOpcode(Mips::BEQ_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002134 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2135 Inst.addOperand(MCOperand::createReg(Mips::ZERO));
2136 Inst.addOperand(MCOperand::createImm(Offset.getImm()));
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002137 }
2138 }
2139 Instructions.push_back(Inst);
2140
Toma Tabacu234482a2015-03-16 12:03:39 +00002141 // If .set reorder is active, emit a NOP after the branch instruction.
2142 if (AssemblerOptions.back()->isReorder())
2143 createNop(true, IDLoc, Instructions);
2144
Jozef Kolek5cfebdd2015-01-21 12:39:30 +00002145 return false;
2146}
2147
Toma Tabacue1e460d2015-06-11 10:36:10 +00002148bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc,
2149 SmallVectorImpl<MCInst> &Instructions) {
2150 const MCOperand &DstRegOp = Inst.getOperand(0);
2151 assert(DstRegOp.isReg() && "expected register operand kind");
2152
2153 const MCOperand &ImmOp = Inst.getOperand(1);
2154 assert(ImmOp.isImm() && "expected immediate operand kind");
2155
2156 const MCOperand &MemOffsetOp = Inst.getOperand(2);
2157 assert(MemOffsetOp.isImm() && "expected immediate operand kind");
2158
2159 unsigned OpCode = 0;
2160 switch(Inst.getOpcode()) {
2161 case Mips::BneImm:
2162 OpCode = Mips::BNE;
2163 break;
2164 case Mips::BeqImm:
2165 OpCode = Mips::BEQ;
2166 break;
2167 default:
2168 llvm_unreachable("Unknown immediate branch pseudo-instruction.");
2169 break;
2170 }
2171
2172 int64_t ImmValue = ImmOp.getImm();
2173 if (ImmValue == 0) {
2174 MCInst BranchInst;
2175 BranchInst.setOpcode(OpCode);
2176 BranchInst.addOperand(DstRegOp);
2177 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2178 BranchInst.addOperand(MemOffsetOp);
2179 Instructions.push_back(BranchInst);
2180 } else {
2181 warnIfNoMacro(IDLoc);
2182
2183 unsigned ATReg = getATReg(IDLoc);
2184 if (!ATReg)
2185 return true;
2186
2187 if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), IDLoc,
2188 Instructions))
2189 return true;
2190
2191 MCInst BranchInst;
2192 BranchInst.setOpcode(OpCode);
2193 BranchInst.addOperand(DstRegOp);
2194 BranchInst.addOperand(MCOperand::createReg(ATReg));
2195 BranchInst.addOperand(MemOffsetOp);
2196 Instructions.push_back(BranchInst);
2197 }
2198 return false;
2199}
2200
Jack Carter9e65aa32013-03-22 00:05:30 +00002201void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00002202 SmallVectorImpl<MCInst> &Instructions,
2203 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00002204 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00002205 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00002206 const MCExpr *ExprOffset;
2207 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00002208 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002209 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
2210 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002211 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00002212 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
2213 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00002214 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00002215 if (isImmOpnd) {
2216 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
2217 ImmOffset = Inst.getOperand(2).getImm();
2218 LoOffset = ImmOffset & 0x0000ffff;
2219 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00002220 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00002221 if (LoOffset & 0x8000)
2222 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00002223 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00002224 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00002225 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00002226 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00002227 // These are some of the types of expansions we perform here:
2228 // 1) lw $8, sym => lui $8, %hi(sym)
2229 // lw $8, %lo(sym)($8)
2230 // 2) lw $8, offset($9) => lui $8, %hi(offset)
2231 // add $8, $8, $9
2232 // lw $8, %lo(offset)($9)
2233 // 3) lw $8, offset($8) => lui $at, %hi(offset)
2234 // add $at, $at, $8
2235 // lw $8, %lo(offset)($at)
2236 // 4) sw $8, sym => lui $at, %hi(sym)
2237 // sw $8, %lo(sym)($at)
2238 // 5) sw $8, offset($8) => lui $at, %hi(offset)
2239 // add $at, $at, $8
2240 // sw $8, %lo(offset)($at)
2241 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
2242 // ldc1 $f0, %lo(sym)($at)
2243 //
2244 // For load instructions we can use the destination register as a temporary
2245 // if base and dst are different (examples 1 and 2) and if the base register
2246 // is general purpose otherwise we must use $at (example 6) and error if it's
2247 // not available. For stores we must use $at (examples 4 and 5) because we
2248 // must not clobber the source register setting up the offset.
2249 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
2250 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
2251 unsigned RegClassIDOp0 =
2252 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
2253 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
2254 (RegClassIDOp0 == Mips::GPR64RegClassID);
2255 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00002256 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002257 else {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002258 // At this point we need AT to perform the expansions and we exit if it is
2259 // not available.
Toma Tabacu89a712b2015-04-15 10:48:56 +00002260 TmpRegNum = getATReg(IDLoc);
2261 if (!TmpRegNum)
Matheus Almeida7de68e72014-06-18 14:46:05 +00002262 return;
Matheus Almeida7de68e72014-06-18 14:46:05 +00002263 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00002264
Jack Carter9e65aa32013-03-22 00:05:30 +00002265 TempInst.setOpcode(Mips::LUi);
Jim Grosbache9119e42015-05-13 18:37:00 +00002266 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
Jack Carter9e65aa32013-03-22 00:05:30 +00002267 if (isImmOpnd)
Jim Grosbache9119e42015-05-13 18:37:00 +00002268 TempInst.addOperand(MCOperand::createImm(HiOffset));
Jack Carter9e65aa32013-03-22 00:05:30 +00002269 else {
Toma Tabacu07c97b32015-06-17 10:43:45 +00002270 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
2271 TempInst.addOperand(MCOperand::createExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002272 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002273 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00002274 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00002275 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00002276 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00002277 // Add temp register to base.
Toma Tabacuc6ce0742015-04-08 13:52:41 +00002278 if (BaseRegNum != Mips::ZERO) {
2279 TempInst.setOpcode(Mips::ADDu);
Jim Grosbache9119e42015-05-13 18:37:00 +00002280 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
2281 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
2282 TempInst.addOperand(MCOperand::createReg(BaseRegNum));
Toma Tabacuc6ce0742015-04-08 13:52:41 +00002283 Instructions.push_back(TempInst);
2284 TempInst.clear();
2285 }
Alp Tokercb402912014-01-24 17:20:08 +00002286 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00002287 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00002288 TempInst.setOpcode(Inst.getOpcode());
Jim Grosbache9119e42015-05-13 18:37:00 +00002289 TempInst.addOperand(MCOperand::createReg(RegOpNum));
2290 TempInst.addOperand(MCOperand::createReg(TmpRegNum));
Jack Carter9e65aa32013-03-22 00:05:30 +00002291 if (isImmOpnd)
Jim Grosbache9119e42015-05-13 18:37:00 +00002292 TempInst.addOperand(MCOperand::createImm(LoOffset));
Jack Carter9e65aa32013-03-22 00:05:30 +00002293 else {
Toma Tabacu07c97b32015-06-17 10:43:45 +00002294 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
2295 TempInst.addOperand(MCOperand::createExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00002296 }
2297 Instructions.push_back(TempInst);
2298 TempInst.clear();
2299}
2300
Zoran Jovanovic14c567b2015-01-28 21:52:27 +00002301bool
2302MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
2303 SmallVectorImpl<MCInst> &Instructions) {
2304 unsigned OpNum = Inst.getNumOperands();
2305 unsigned Opcode = Inst.getOpcode();
2306 unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
2307
2308 assert (Inst.getOperand(OpNum - 1).isImm() &&
2309 Inst.getOperand(OpNum - 2).isReg() &&
2310 Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand.");
2311
2312 if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 &&
2313 Inst.getOperand(OpNum - 1).getImm() >= 0 &&
2314 Inst.getOperand(OpNum - 2).getReg() == Mips::SP &&
2315 Inst.getOperand(OpNum - 3).getReg() == Mips::RA)
2316 // It can be implemented as SWM16 or LWM16 instruction.
2317 NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM;
2318
2319 Inst.setOpcode(NewOpcode);
2320 Instructions.push_back(Inst);
2321 return false;
2322}
2323
Toma Tabacu1a108322015-06-17 13:20:24 +00002324bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
2325 SmallVectorImpl<MCInst> &Instructions) {
2326 unsigned PseudoOpcode = Inst.getOpcode();
2327 unsigned SrcReg = Inst.getOperand(0).getReg();
2328 unsigned TrgReg = Inst.getOperand(1).getReg();
2329 const MCExpr *OffsetExpr = Inst.getOperand(2).getExpr();
2330
2331 unsigned ZeroSrcOpcode, ZeroTrgOpcode;
2332 bool ReverseOrderSLT, IsUnsigned, AcceptsEquality;
2333
2334 switch (PseudoOpcode) {
2335 case Mips::BLT:
2336 case Mips::BLTU:
2337 AcceptsEquality = false;
2338 ReverseOrderSLT = false;
2339 IsUnsigned = (PseudoOpcode == Mips::BLTU);
2340 ZeroSrcOpcode = Mips::BGTZ;
2341 ZeroTrgOpcode = Mips::BLTZ;
2342 break;
2343 case Mips::BLE:
2344 case Mips::BLEU:
2345 AcceptsEquality = true;
2346 ReverseOrderSLT = true;
2347 IsUnsigned = (PseudoOpcode == Mips::BLEU);
2348 ZeroSrcOpcode = Mips::BGEZ;
2349 ZeroTrgOpcode = Mips::BLEZ;
2350 break;
2351 case Mips::BGE:
2352 case Mips::BGEU:
2353 AcceptsEquality = true;
2354 ReverseOrderSLT = false;
2355 IsUnsigned = (PseudoOpcode == Mips::BGEU);
2356 ZeroSrcOpcode = Mips::BLEZ;
2357 ZeroTrgOpcode = Mips::BGEZ;
2358 break;
2359 case Mips::BGT:
2360 case Mips::BGTU:
2361 AcceptsEquality = false;
2362 ReverseOrderSLT = true;
2363 IsUnsigned = (PseudoOpcode == Mips::BGTU);
2364 ZeroSrcOpcode = Mips::BLTZ;
2365 ZeroTrgOpcode = Mips::BGTZ;
2366 break;
2367 default:
2368 llvm_unreachable("unknown opcode for branch pseudo-instruction");
2369 }
2370
2371 MCInst BranchInst;
2372 bool IsTrgRegZero = (TrgReg == Mips::ZERO);
2373 bool IsSrcRegZero = (SrcReg == Mips::ZERO);
2374 if (IsSrcRegZero && IsTrgRegZero) {
2375 // FIXME: All of these Opcode-specific if's are needed for compatibility
2376 // with GAS' behaviour. However, they may not generate the most efficient
2377 // code in some circumstances.
2378 if (PseudoOpcode == Mips::BLT) {
2379 BranchInst.setOpcode(Mips::BLTZ);
2380 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2381 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2382 Instructions.push_back(BranchInst);
2383 return false;
2384 }
2385 if (PseudoOpcode == Mips::BLE) {
2386 BranchInst.setOpcode(Mips::BLEZ);
2387 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2388 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2389 Instructions.push_back(BranchInst);
2390 Warning(IDLoc, "branch is always taken");
2391 return false;
2392 }
2393 if (PseudoOpcode == Mips::BGE) {
2394 BranchInst.setOpcode(Mips::BGEZ);
2395 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2396 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2397 Instructions.push_back(BranchInst);
2398 Warning(IDLoc, "branch is always taken");
2399 return false;
2400 }
2401 if (PseudoOpcode == Mips::BGT) {
2402 BranchInst.setOpcode(Mips::BGTZ);
2403 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2404 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2405 Instructions.push_back(BranchInst);
2406 return false;
2407 }
2408 if (PseudoOpcode == Mips::BGTU) {
2409 BranchInst.setOpcode(Mips::BNE);
2410 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2411 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2412 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2413 Instructions.push_back(BranchInst);
2414 return false;
2415 }
2416 if (AcceptsEquality) {
2417 // If both registers are $0 and the pseudo-branch accepts equality, it
2418 // will always be taken, so we emit an unconditional branch.
2419 BranchInst.setOpcode(Mips::BEQ);
2420 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2421 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2422 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2423 Instructions.push_back(BranchInst);
2424 Warning(IDLoc, "branch is always taken");
2425 return false;
2426 }
2427 // If both registers are $0 and the pseudo-branch does not accept
2428 // equality, it will never be taken, so we don't have to emit anything.
2429 return false;
2430 }
2431 if (IsSrcRegZero || IsTrgRegZero) {
2432 if ((IsSrcRegZero && PseudoOpcode == Mips::BGTU) ||
2433 (IsTrgRegZero && PseudoOpcode == Mips::BLTU)) {
2434 // If the $rs is $0 and the pseudo-branch is BGTU (0 > x) or
2435 // if the $rt is $0 and the pseudo-branch is BLTU (x < 0),
2436 // the pseudo-branch will never be taken, so we don't emit anything.
2437 // This only applies to unsigned pseudo-branches.
2438 return false;
2439 }
2440 if ((IsSrcRegZero && PseudoOpcode == Mips::BLEU) ||
2441 (IsTrgRegZero && PseudoOpcode == Mips::BGEU)) {
2442 // If the $rs is $0 and the pseudo-branch is BLEU (0 <= x) or
2443 // if the $rt is $0 and the pseudo-branch is BGEU (x >= 0),
2444 // the pseudo-branch will always be taken, so we emit an unconditional
2445 // branch.
2446 // This only applies to unsigned pseudo-branches.
2447 BranchInst.setOpcode(Mips::BEQ);
2448 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2449 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2450 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2451 Instructions.push_back(BranchInst);
2452 Warning(IDLoc, "branch is always taken");
2453 return false;
2454 }
2455 if (IsUnsigned) {
2456 // If the $rs is $0 and the pseudo-branch is BLTU (0 < x) or
2457 // if the $rt is $0 and the pseudo-branch is BGTU (x > 0),
2458 // the pseudo-branch will be taken only when the non-zero register is
2459 // different from 0, so we emit a BNEZ.
2460 //
2461 // If the $rs is $0 and the pseudo-branch is BGEU (0 >= x) or
2462 // if the $rt is $0 and the pseudo-branch is BLEU (x <= 0),
2463 // the pseudo-branch will be taken only when the non-zero register is
2464 // equal to 0, so we emit a BEQZ.
2465 //
2466 // Because only BLEU and BGEU branch on equality, we can use the
2467 // AcceptsEquality variable to decide when to emit the BEQZ.
2468 BranchInst.setOpcode(AcceptsEquality ? Mips::BEQ : Mips::BNE);
2469 BranchInst.addOperand(
2470 MCOperand::createReg(IsSrcRegZero ? TrgReg : SrcReg));
2471 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2472 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2473 Instructions.push_back(BranchInst);
2474 return false;
2475 }
2476 // If we have a signed pseudo-branch and one of the registers is $0,
2477 // we can use an appropriate compare-to-zero branch. We select which one
2478 // to use in the switch statement above.
2479 BranchInst.setOpcode(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode);
2480 BranchInst.addOperand(MCOperand::createReg(IsSrcRegZero ? TrgReg : SrcReg));
2481 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2482 Instructions.push_back(BranchInst);
2483 return false;
2484 }
2485
2486 // If neither the SrcReg nor the TrgReg are $0, we need AT to perform the
2487 // expansions. If it is not available, we return.
2488 unsigned ATRegNum = getATReg(IDLoc);
2489 if (!ATRegNum)
2490 return true;
2491
2492 warnIfNoMacro(IDLoc);
2493
2494 // SLT fits well with 2 of our 4 pseudo-branches:
2495 // BLT, where $rs < $rt, translates into "slt $at, $rs, $rt" and
2496 // BGT, where $rs > $rt, translates into "slt $at, $rt, $rs".
2497 // If the result of the SLT is 1, we branch, and if it's 0, we don't.
2498 // This is accomplished by using a BNEZ with the result of the SLT.
2499 //
2500 // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT
2501 // and BLE with BGT), so we change the BNEZ into a a BEQZ.
2502 // Because only BGE and BLE branch on equality, we can use the
2503 // AcceptsEquality variable to decide when to emit the BEQZ.
2504 // Note that the order of the SLT arguments doesn't change between
2505 // opposites.
2506 //
2507 // The same applies to the unsigned variants, except that SLTu is used
2508 // instead of SLT.
2509 MCInst SetInst;
2510 SetInst.setOpcode(IsUnsigned ? Mips::SLTu : Mips::SLT);
2511 SetInst.addOperand(MCOperand::createReg(ATRegNum));
2512 SetInst.addOperand(MCOperand::createReg(ReverseOrderSLT ? TrgReg : SrcReg));
2513 SetInst.addOperand(MCOperand::createReg(ReverseOrderSLT ? SrcReg : TrgReg));
2514 Instructions.push_back(SetInst);
2515
2516 BranchInst.setOpcode(AcceptsEquality ? Mips::BEQ : Mips::BNE);
2517 BranchInst.addOperand(MCOperand::createReg(ATRegNum));
2518 BranchInst.addOperand(MCOperand::createReg(Mips::ZERO));
2519 BranchInst.addOperand(MCOperand::createExpr(OffsetExpr));
2520 Instructions.push_back(BranchInst);
2521 return false;
2522}
2523
Toma Tabacud88d79c2015-06-23 14:39:42 +00002524bool MipsAsmParser::expandUlhu(MCInst &Inst, SMLoc IDLoc,
2525 SmallVectorImpl<MCInst> &Instructions) {
2526 if (hasMips32r6() || hasMips64r6()) {
2527 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2528 return false;
2529 }
2530
2531 warnIfNoMacro(IDLoc);
2532
2533 const MCOperand &DstRegOp = Inst.getOperand(0);
2534 assert(DstRegOp.isReg() && "expected register operand kind");
2535
2536 const MCOperand &SrcRegOp = Inst.getOperand(1);
2537 assert(SrcRegOp.isReg() && "expected register operand kind");
2538
2539 const MCOperand &OffsetImmOp = Inst.getOperand(2);
2540 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
2541
2542 unsigned DstReg = DstRegOp.getReg();
2543 unsigned SrcReg = SrcRegOp.getReg();
2544 int64_t OffsetValue = OffsetImmOp.getImm();
2545
2546 // NOTE: We always need AT for ULHU, as it is always used as the source
2547 // register for one of the LBu's.
2548 unsigned ATReg = getATReg(IDLoc);
2549 if (!ATReg)
2550 return true;
2551
2552 // When the value of offset+1 does not fit in 16 bits, we have to load the
2553 // offset in AT, (D)ADDu the original source register (if there was one), and
2554 // then use AT as the source register for the 2 generated LBu's.
2555 bool LoadedOffsetInAT = false;
2556 if (!isInt<16>(OffsetValue + 1) || !isInt<16>(OffsetValue)) {
2557 LoadedOffsetInAT = true;
2558
2559 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
2560 IDLoc, Instructions))
2561 return true;
2562
2563 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
2564 // because it will make our output more similar to GAS'. For example,
2565 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
2566 // instead of just an "ori $1, $9, 32768".
2567 // NOTE: If there is no source register specified in the ULHU, the parser
2568 // will interpret it as $0.
2569 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
2570 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
2571 }
2572
2573 unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg;
2574 unsigned SecondLbuDstReg = LoadedOffsetInAT ? ATReg : DstReg;
2575 unsigned LbuSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
2576
2577 int64_t FirstLbuOffset = 0, SecondLbuOffset = 0;
2578 if (isLittle()) {
2579 FirstLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
2580 SecondLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
2581 } else {
2582 FirstLbuOffset = LoadedOffsetInAT ? 0 : OffsetValue;
2583 SecondLbuOffset = LoadedOffsetInAT ? 1 : (OffsetValue + 1);
2584 }
2585
2586 unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg;
2587
2588 MCInst TmpInst;
2589 TmpInst.setOpcode(Mips::LBu);
2590 TmpInst.addOperand(MCOperand::createReg(FirstLbuDstReg));
2591 TmpInst.addOperand(MCOperand::createReg(LbuSrcReg));
2592 TmpInst.addOperand(MCOperand::createImm(FirstLbuOffset));
2593 Instructions.push_back(TmpInst);
2594
2595 TmpInst.clear();
2596 TmpInst.setOpcode(Mips::LBu);
2597 TmpInst.addOperand(MCOperand::createReg(SecondLbuDstReg));
2598 TmpInst.addOperand(MCOperand::createReg(LbuSrcReg));
2599 TmpInst.addOperand(MCOperand::createImm(SecondLbuOffset));
2600 Instructions.push_back(TmpInst);
2601
2602 TmpInst.clear();
2603 TmpInst.setOpcode(Mips::SLL);
2604 TmpInst.addOperand(MCOperand::createReg(SllReg));
2605 TmpInst.addOperand(MCOperand::createReg(SllReg));
2606 TmpInst.addOperand(MCOperand::createImm(8));
2607 Instructions.push_back(TmpInst);
2608
2609 TmpInst.clear();
2610 TmpInst.setOpcode(Mips::OR);
2611 TmpInst.addOperand(MCOperand::createReg(DstReg));
2612 TmpInst.addOperand(MCOperand::createReg(DstReg));
2613 TmpInst.addOperand(MCOperand::createReg(ATReg));
2614 Instructions.push_back(TmpInst);
2615
2616 return false;
2617}
2618
Toma Tabacu0a6fa59a2015-06-26 13:20:17 +00002619bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc,
2620 SmallVectorImpl<MCInst> &Instructions) {
2621 if (hasMips32r6() || hasMips64r6()) {
2622 Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
2623 return false;
2624 }
2625
2626 const MCOperand &DstRegOp = Inst.getOperand(0);
2627 assert(DstRegOp.isReg() && "expected register operand kind");
2628
2629 const MCOperand &SrcRegOp = Inst.getOperand(1);
2630 assert(SrcRegOp.isReg() && "expected register operand kind");
2631
2632 const MCOperand &OffsetImmOp = Inst.getOperand(2);
2633 assert(OffsetImmOp.isImm() && "expected immediate operand kind");
2634
2635 unsigned SrcReg = SrcRegOp.getReg();
2636 int64_t OffsetValue = OffsetImmOp.getImm();
2637 unsigned ATReg = 0;
2638
2639 // When the value of offset+3 does not fit in 16 bits, we have to load the
2640 // offset in AT, (D)ADDu the original source register (if there was one), and
2641 // then use AT as the source register for the generated LWL and LWR.
2642 bool LoadedOffsetInAT = false;
2643 if (!isInt<16>(OffsetValue + 3) || !isInt<16>(OffsetValue)) {
2644 ATReg = getATReg(IDLoc);
2645 if (!ATReg)
2646 return true;
2647 LoadedOffsetInAT = true;
2648
2649 warnIfNoMacro(IDLoc);
2650
2651 if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
2652 IDLoc, Instructions))
2653 return true;
2654
2655 // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
2656 // because it will make our output more similar to GAS'. For example,
2657 // generating an "ori $1, $zero, 32768" followed by an "addu $1, $1, $9",
2658 // instead of just an "ori $1, $9, 32768".
2659 // NOTE: If there is no source register specified in the ULW, the parser
2660 // will interpret it as $0.
2661 if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
2662 createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
2663 }
2664
2665 unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
2666 int64_t LeftLoadOffset = 0, RightLoadOffset = 0;
2667 if (isLittle()) {
2668 LeftLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
2669 RightLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
2670 } else {
2671 LeftLoadOffset = LoadedOffsetInAT ? 0 : OffsetValue;
2672 RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
2673 }
2674
2675 MCInst LeftLoadInst;
2676 LeftLoadInst.setOpcode(Mips::LWL);
2677 LeftLoadInst.addOperand(DstRegOp);
2678 LeftLoadInst.addOperand(MCOperand::createReg(FinalSrcReg));
2679 LeftLoadInst.addOperand(MCOperand::createImm(LeftLoadOffset));
2680 Instructions.push_back(LeftLoadInst);
2681
2682 MCInst RightLoadInst;
2683 RightLoadInst.setOpcode(Mips::LWR);
2684 RightLoadInst.addOperand(DstRegOp);
2685 RightLoadInst.addOperand(MCOperand::createReg(FinalSrcReg));
2686 RightLoadInst.addOperand(MCOperand::createImm(RightLoadOffset ));
2687 Instructions.push_back(RightLoadInst);
2688
2689 return false;
2690}
2691
Toma Tabacu234482a2015-03-16 12:03:39 +00002692void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
2693 SmallVectorImpl<MCInst> &Instructions) {
2694 MCInst NopInst;
2695 if (hasShortDelaySlot) {
2696 NopInst.setOpcode(Mips::MOVE16_MM);
Jim Grosbache9119e42015-05-13 18:37:00 +00002697 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
2698 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
Toma Tabacu234482a2015-03-16 12:03:39 +00002699 } else {
2700 NopInst.setOpcode(Mips::SLL);
Jim Grosbache9119e42015-05-13 18:37:00 +00002701 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
2702 NopInst.addOperand(MCOperand::createReg(Mips::ZERO));
2703 NopInst.addOperand(MCOperand::createImm(0));
Toma Tabacu234482a2015-03-16 12:03:39 +00002704 }
2705 Instructions.push_back(NopInst);
2706}
2707
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002708void MipsAsmParser::createAddu(unsigned DstReg, unsigned SrcReg,
Toma Tabacu0b3e9782015-06-23 14:00:54 +00002709 unsigned TrgReg, bool Is64Bit,
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002710 SmallVectorImpl<MCInst> &Instructions) {
2711 MCInst AdduInst;
Toma Tabacu0b3e9782015-06-23 14:00:54 +00002712 AdduInst.setOpcode(Is64Bit ? Mips::DADDu : Mips::ADDu);
Jim Grosbache9119e42015-05-13 18:37:00 +00002713 AdduInst.addOperand(MCOperand::createReg(DstReg));
2714 AdduInst.addOperand(MCOperand::createReg(SrcReg));
2715 AdduInst.addOperand(MCOperand::createReg(TrgReg));
Toma Tabacud0a7ff22015-05-13 13:56:16 +00002716 Instructions.push_back(AdduInst);
2717}
2718
Matheus Almeida595fcab2014-06-11 15:05:56 +00002719unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
2720 // As described by the Mips32r2 spec, the registers Rd and Rs for
2721 // jalr.hb must be different.
2722 unsigned Opcode = Inst.getOpcode();
2723
2724 if (Opcode == Mips::JALR_HB &&
2725 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
2726 return Match_RequiresDifferentSrcAndDst;
2727
2728 return Match_Success;
2729}
2730
David Blaikie960ea3f2014-06-08 16:18:35 +00002731bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
2732 OperandVector &Operands,
2733 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00002734 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00002735 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00002736
Jack Carterb4dbc172012-09-05 23:34:03 +00002737 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00002738 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00002739 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00002740 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00002741
2742 switch (MatchResult) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002743 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00002744 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00002745 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00002746 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00002747 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00002748 return false;
2749 }
2750 case Match_MissingFeature:
2751 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
2752 return true;
2753 case Match_InvalidOperand: {
2754 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00002755 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002756 if (ErrorInfo >= Operands.size())
2757 return Error(IDLoc, "too few operands for instruction");
2758
David Blaikie960ea3f2014-06-08 16:18:35 +00002759 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00002760 if (ErrorLoc == SMLoc())
2761 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00002762 }
2763
2764 return Error(ErrorLoc, "invalid operand for instruction");
2765 }
2766 case Match_MnemonicFail:
2767 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00002768 case Match_RequiresDifferentSrcAndDst:
2769 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00002770 }
Craig Topper589ceee2015-01-03 08:16:34 +00002771
2772 llvm_unreachable("Implement any new match types added!");
Rafael Espindola870c4e92012-01-11 03:56:41 +00002773}
2774
Toma Tabacud9d344b2015-04-27 14:05:04 +00002775void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) {
2776 if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex)
2777 Warning(Loc, "used $at (currently $" + Twine(RegIndex) +
2778 ") without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002779}
2780
Toma Tabacu81496c12015-05-20 08:54:45 +00002781void MipsAsmParser::warnIfNoMacro(SMLoc Loc) {
2782 if (!AssemblerOptions.back()->isMacro())
2783 Warning(Loc, "macro instruction expanded into multiple instructions");
2784}
2785
Daniel Sandersef638fe2014-10-03 15:37:37 +00002786void
2787MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
2788 SMRange Range, bool ShowColors) {
2789 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00002790 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00002791 ShowColors);
2792}
2793
Jack Carter1ac53222013-02-20 23:11:17 +00002794int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002795 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002796
Vladimir Medic4c299852013-11-06 11:27:05 +00002797 CC = StringSwitch<unsigned>(Name)
2798 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00002799 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00002800 .Case("a0", 4)
2801 .Case("a1", 5)
2802 .Case("a2", 6)
2803 .Case("a3", 7)
2804 .Case("v0", 2)
2805 .Case("v1", 3)
2806 .Case("s0", 16)
2807 .Case("s1", 17)
2808 .Case("s2", 18)
2809 .Case("s3", 19)
2810 .Case("s4", 20)
2811 .Case("s5", 21)
2812 .Case("s6", 22)
2813 .Case("s7", 23)
2814 .Case("k0", 26)
2815 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002816 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00002817 .Case("sp", 29)
2818 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00002819 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00002820 .Case("ra", 31)
2821 .Case("t0", 8)
2822 .Case("t1", 9)
2823 .Case("t2", 10)
2824 .Case("t3", 11)
2825 .Case("t4", 12)
2826 .Case("t5", 13)
2827 .Case("t6", 14)
2828 .Case("t7", 15)
2829 .Case("t8", 24)
2830 .Case("t9", 25)
2831 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002832
Toma Tabacufda445c2014-09-15 15:33:01 +00002833 if (!(isABI_N32() || isABI_N64()))
2834 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00002835
Daniel Sandersef638fe2014-10-03 15:37:37 +00002836 if (12 <= CC && CC <= 15) {
2837 // Name is one of t4-t7
2838 AsmToken RegTok = getLexer().peekTok();
2839 SMRange RegRange = RegTok.getLocRange();
2840
2841 StringRef FixedName = StringSwitch<StringRef>(Name)
2842 .Case("t4", "t0")
2843 .Case("t5", "t1")
2844 .Case("t6", "t2")
2845 .Case("t7", "t3")
2846 .Default("");
2847 assert(FixedName != "" && "Register name is not one of t4-t7.");
2848
2849 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
2850 "Did you mean $" + FixedName + "?", RegRange);
2851 }
2852
Toma Tabacufda445c2014-09-15 15:33:01 +00002853 // Although SGI documentation just cuts out t0-t3 for n32/n64,
2854 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
2855 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
2856 if (8 <= CC && CC <= 11)
2857 CC += 4;
2858
2859 if (CC == -1)
2860 CC = StringSwitch<unsigned>(Name)
2861 .Case("a4", 8)
2862 .Case("a5", 9)
2863 .Case("a6", 10)
2864 .Case("a7", 11)
2865 .Case("kt0", 26)
2866 .Case("kt1", 27)
2867 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00002868
2869 return CC;
2870}
Jack Carterd0bd6422013-04-18 00:41:53 +00002871
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002872int MipsAsmParser::matchHWRegsRegisterName(StringRef Name) {
2873 int CC;
2874
2875 CC = StringSwitch<unsigned>(Name)
2876 .Case("hwr_cpunum", 0)
2877 .Case("hwr_synci_step", 1)
2878 .Case("hwr_cc", 2)
2879 .Case("hwr_ccres", 3)
Vasileios Kalintiris8c1c95e2014-11-11 11:22:39 +00002880 .Case("hwr_ulr", 29)
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00002881 .Default(-1);
2882
2883 return CC;
2884}
2885
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002886int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002887
Jack Cartera63b16a2012-09-07 00:23:42 +00002888 if (Name[0] == 'f') {
2889 StringRef NumString = Name.substr(1);
2890 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00002891 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002892 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002893 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00002894 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002895 return IntVal;
2896 }
2897 return -1;
2898}
Jack Cartera63b16a2012-09-07 00:23:42 +00002899
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002900int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
2901
2902 if (Name.startswith("fcc")) {
2903 StringRef NumString = Name.substr(3);
2904 unsigned IntVal;
2905 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002906 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002907 if (IntVal > 7) // There are only 8 fcc registers.
2908 return -1;
2909 return IntVal;
2910 }
2911 return -1;
2912}
2913
2914int MipsAsmParser::matchACRegisterName(StringRef Name) {
2915
Akira Hatanaka274d24c2013-08-14 01:15:52 +00002916 if (Name.startswith("ac")) {
2917 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002918 unsigned IntVal;
2919 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00002920 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002921 if (IntVal > 3) // There are only 3 acc registers.
2922 return -1;
2923 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00002924 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002925 return -1;
2926}
Jack Carterd0bd6422013-04-18 00:41:53 +00002927
Jack Carter5dc8ac92013-09-25 23:50:44 +00002928int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
2929 unsigned IntVal;
2930
2931 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
2932 return -1;
2933
2934 if (IntVal > 31)
2935 return -1;
2936
2937 return IntVal;
2938}
2939
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002940int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
2941 int CC;
2942
2943 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00002944 .Case("msair", 0)
2945 .Case("msacsr", 1)
2946 .Case("msaaccess", 2)
2947 .Case("msasave", 3)
2948 .Case("msamodify", 4)
2949 .Case("msarequest", 5)
2950 .Case("msamap", 6)
2951 .Case("msaunmap", 7)
2952 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002953
2954 return CC;
2955}
2956
Toma Tabacu89a712b2015-04-15 10:48:56 +00002957unsigned MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacub19cf202015-04-27 13:12:59 +00002958 unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
Toma Tabacu89a712b2015-04-15 10:48:56 +00002959 if (ATIndex == 0) {
Matheus Almeida7de68e72014-06-18 14:46:05 +00002960 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00002961 "pseudo-instruction requires $at, which is not available");
Toma Tabacu89a712b2015-04-15 10:48:56 +00002962 return 0;
2963 }
2964 unsigned AT = getReg(
2965 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex);
Daniel Sandersd89b1362014-03-24 16:48:01 +00002966 return AT;
2967}
Jack Carter0b744b32012-10-04 02:29:46 +00002968
Jack Carterd0bd6422013-04-18 00:41:53 +00002969unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00002970 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00002971}
2972
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002973unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002974 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00002975 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002976}
2977
Jack Carter873c7242013-01-12 01:03:14 +00002978int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002979 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00002980 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00002981 return -1;
2982
Jack Carter873c7242013-01-12 01:03:14 +00002983 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00002984}
2985
Toma Tabacu13964452014-09-04 13:23:44 +00002986bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002987 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00002988 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002989
Jack Carter30a59822012-10-04 04:03:53 +00002990 // Check if the current operand has a custom associated parser, if so, try to
2991 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00002992 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2993 if (ResTy == MatchOperand_Success)
2994 return false;
2995 // If there wasn't a custom match, try the generic matcher below. Otherwise,
2996 // there was a match, but an error occurred, in which case, just return that
2997 // the operand parsing failed.
2998 if (ResTy == MatchOperand_ParseFail)
2999 return true;
3000
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003001 DEBUG(dbgs() << ".. Generic Parser\n");
3002
Jack Carterb4dbc172012-09-05 23:34:03 +00003003 switch (getLexer().getKind()) {
3004 default:
3005 Error(Parser.getTok().getLoc(), "unexpected token in operand");
3006 return true;
3007 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003008 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00003009 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00003010
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003011 // Almost all registers have been parsed by custom parsers. There is only
3012 // one exception to this. $zero (and it's alias $0) will reach this point
3013 // for div, divu, and similar instructions because it is not an operand
3014 // to the instruction definition but an explicit register. Special case
3015 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00003016 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00003017 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003018
Jack Carterd0bd6422013-04-18 00:41:53 +00003019 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00003020 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003021 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00003022 return true;
3023
Jack Carter873c7242013-01-12 01:03:14 +00003024 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jim Grosbach6f482002015-05-18 18:43:14 +00003025 MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00003026 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00003027 const MCExpr *Res =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003028 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00003029
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003030 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003031 return false;
3032 }
Vladimir Medic4c299852013-11-06 11:27:05 +00003033 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00003034 case AsmToken::LParen:
3035 case AsmToken::Minus:
3036 case AsmToken::Plus:
3037 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00003038 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00003039 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003040 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00003041 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003042 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00003043 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00003044 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00003045 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003046 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00003047 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00003048 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00003049 return true;
3050
Jack Carter873c7242013-01-12 01:03:14 +00003051 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3052
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003053 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00003054 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003055 } // case AsmToken::Percent
3056 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00003057 return true;
3058}
3059
Vladimir Medic4c299852013-11-06 11:27:05 +00003060const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00003061 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00003062 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00003063 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00003064 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00003065 // It's a constant, evaluate reloc value.
3066 int16_t Val;
3067 switch (getVariantKind(RelocStr)) {
3068 case MCSymbolRefExpr::VK_Mips_ABS_LO:
3069 // Get the 1st 16-bits.
3070 Val = MCE->getValue() & 0xffff;
3071 break;
3072 case MCSymbolRefExpr::VK_Mips_ABS_HI:
3073 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
3074 // 16 bits being negative.
3075 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
3076 break;
3077 case MCSymbolRefExpr::VK_Mips_HIGHER:
3078 // Get the 3rd 16-bits.
3079 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
3080 break;
3081 case MCSymbolRefExpr::VK_Mips_HIGHEST:
3082 // Get the 4th 16-bits.
3083 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
3084 break;
3085 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00003086 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00003087 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00003088 return MCConstantExpr::create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00003089 }
3090
Jack Carterb5cf5902013-04-17 00:18:04 +00003091 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003092 // It's a symbol, create a symbolic expression from the symbol.
Toma Tabacu07c97b32015-06-17 10:43:45 +00003093 const MCSymbol *Symbol = &MSRE->getSymbol();
Jack Carterb5cf5902013-04-17 00:18:04 +00003094 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003095 Res = MCSymbolRefExpr::create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003096 return Res;
3097 }
3098
3099 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00003100 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
3101
Sasa Stankovic06c47802014-04-03 10:37:45 +00003102 // Try to create target expression.
3103 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
Jim Grosbach13760bd2015-05-30 01:25:56 +00003104 return MipsMCExpr::create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00003105
Jack Carterd0bd6422013-04-18 00:41:53 +00003106 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
3107 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003108 Res = MCBinaryExpr::create(BE->getOpcode(), LExp, RExp, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003109 return Res;
3110 }
3111
3112 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003113 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
Jim Grosbach13760bd2015-05-30 01:25:56 +00003114 Res = MCUnaryExpr::create(UN->getOpcode(), UnExp, getContext());
Jack Carterd0bd6422013-04-18 00:41:53 +00003115 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00003116 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003117 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00003118 return Expr;
3119}
3120
3121bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
3122
3123 switch (Expr->getKind()) {
3124 case MCExpr::Constant:
3125 return true;
3126 case MCExpr::SymbolRef:
3127 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
3128 case MCExpr::Binary:
3129 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
3130 if (!isEvaluated(BE->getLHS()))
3131 return false;
3132 return isEvaluated(BE->getRHS());
3133 }
3134 case MCExpr::Unary:
3135 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00003136 case MCExpr::Target:
3137 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003138 }
Jack Carterb5cf5902013-04-17 00:18:04 +00003139 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00003140}
Jack Carterd0bd6422013-04-18 00:41:53 +00003141
Jack Carterb5cf5902013-04-17 00:18:04 +00003142bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003143 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00003144 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00003145 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00003146 if (Tok.isNot(AsmToken::Identifier))
3147 return true;
3148
Yaron Keren075759a2015-03-30 15:42:36 +00003149 std::string Str = Tok.getIdentifier();
Jack Carterb5cf5902013-04-17 00:18:04 +00003150
Jack Carterd0bd6422013-04-18 00:41:53 +00003151 Parser.Lex(); // Eat the identifier.
3152 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003153 const MCExpr *IdVal;
3154 SMLoc EndLoc;
3155
3156 if (getLexer().getKind() == AsmToken::LParen) {
3157 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003158 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003159 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003160 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003161 const AsmToken &nextTok = Parser.getTok();
3162 if (nextTok.isNot(AsmToken::Identifier))
3163 return true;
3164 Str += "(%";
3165 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00003166 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00003167 if (getLexer().getKind() != AsmToken::LParen)
3168 return true;
3169 } else
3170 break;
3171 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003172 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00003173 return true;
3174
3175 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00003176 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003177
3178 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00003179 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003180
Jack Carterd0bd6422013-04-18 00:41:53 +00003181 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00003182 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003183}
3184
Jack Carterb4dbc172012-09-05 23:34:03 +00003185bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
3186 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003187 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00003188 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003189 if (ResTy == MatchOperand_Success) {
3190 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00003191 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003192 StartLoc = Operand.getStartLoc();
3193 EndLoc = Operand.getEndLoc();
3194
3195 // AFAIK, we only support numeric registers and named GPR's in CFI
3196 // directives.
3197 // Don't worry about eating tokens before failing. Using an unrecognised
3198 // register is a parse error.
3199 if (Operand.isGPRAsmReg()) {
3200 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003201 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003202 }
3203
3204 return (RegNo == (unsigned)-1);
3205 }
3206
3207 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00003208 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00003209}
3210
Jack Carterb5cf5902013-04-17 00:18:04 +00003211bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003212 MCAsmParser &Parser = getParser();
Jack Carter873c7242013-01-12 01:03:14 +00003213 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00003214 bool Result = true;
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003215 unsigned NumOfLParen = 0;
Jack Carterb5cf5902013-04-17 00:18:04 +00003216
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003217 while (getLexer().getKind() == AsmToken::LParen) {
Jack Carterb5cf5902013-04-17 00:18:04 +00003218 Parser.Lex();
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003219 ++NumOfLParen;
3220 }
Jack Carter873c7242013-01-12 01:03:14 +00003221
Jack Carterd0bd6422013-04-18 00:41:53 +00003222 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00003223 default:
3224 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00003225 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00003226 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00003227 case AsmToken::Integer:
3228 case AsmToken::Minus:
3229 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00003230 if (isParenExpr)
Toma Tabacu7bc44dc2015-06-25 09:52:02 +00003231 Result = getParser().parseParenExprOfDepth(NumOfLParen, Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00003232 else
3233 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00003234 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00003235 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003236 break;
Jack Carter873c7242013-01-12 01:03:14 +00003237 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00003238 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00003239 }
Jack Carterb5cf5902013-04-17 00:18:04 +00003240 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003241}
3242
David Blaikie960ea3f2014-06-08 16:18:35 +00003243MipsAsmParser::OperandMatchResultTy
3244MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003245 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003246 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00003247 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00003248 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00003249 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003250 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00003251 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00003252 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00003253
Jack Carterb5cf5902013-04-17 00:18:04 +00003254 if (getLexer().getKind() == AsmToken::LParen) {
3255 Parser.Lex();
3256 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003257 }
3258
Jack Carterb5cf5902013-04-17 00:18:04 +00003259 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00003260 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00003261 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003262
Jack Carterd0bd6422013-04-18 00:41:53 +00003263 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003264 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003265 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
3266 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00003267 SMLoc E =
3268 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003269 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00003270 return MatchOperand_Success;
3271 }
3272 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003273 SMLoc E =
3274 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00003275
Jack Carterd0bd6422013-04-18 00:41:53 +00003276 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00003277 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00003278 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00003279 S, E, *this);
3280 Operands.push_back(
3281 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00003282 return MatchOperand_Success;
3283 }
3284 Error(Parser.getTok().getLoc(), "'(' expected");
3285 return MatchOperand_ParseFail;
3286 }
3287
Jack Carterd0bd6422013-04-18 00:41:53 +00003288 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00003289 }
3290
Toma Tabacu13964452014-09-04 13:23:44 +00003291 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003292 if (Res != MatchOperand_Success)
3293 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00003294
Vladimir Medic27c87ea2013-08-13 13:07:09 +00003295 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00003296 Error(Parser.getTok().getLoc(), "')' expected");
3297 return MatchOperand_ParseFail;
3298 }
3299
Jack Carter873c7242013-01-12 01:03:14 +00003300 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3301
Jack Carterd0bd6422013-04-18 00:41:53 +00003302 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003303
Craig Topper062a2ba2014-04-25 05:30:21 +00003304 if (!IdVal)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003305 IdVal = MCConstantExpr::create(0, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00003306
Jack Carterd0bd6422013-04-18 00:41:53 +00003307 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00003308 std::unique_ptr<MipsOperand> op(
3309 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00003310 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00003311 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00003312 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00003313 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00003314 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
3315 int64_t Imm;
Jim Grosbach13760bd2015-05-30 01:25:56 +00003316 if (IdVal->evaluateAsAbsolute(Imm))
3317 IdVal = MCConstantExpr::create(Imm, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00003318 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003319 IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
Jack Carterb5cf5902013-04-17 00:18:04 +00003320 getContext());
3321 }
3322
David Blaikie960ea3f2014-06-08 16:18:35 +00003323 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003324 return MatchOperand_Success;
3325}
3326
David Blaikie960ea3f2014-06-08 16:18:35 +00003327bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003328 MCAsmParser &Parser = getParser();
Jim Grosbach6f482002015-05-18 18:43:14 +00003329 MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier());
Jack Carterd76b2372013-03-21 21:44:16 +00003330 if (Sym) {
3331 SMLoc S = Parser.getTok().getLoc();
3332 const MCExpr *Expr;
3333 if (Sym->isVariable())
3334 Expr = Sym->getVariableValue();
3335 else
3336 return false;
3337 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00003338 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00003339 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00003340 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003341 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00003342 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00003343 if (ResTy == MatchOperand_Success) {
3344 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00003345 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00003346 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003347 llvm_unreachable("Should never ParseFail");
3348 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00003349 }
3350 } else if (Expr->getKind() == MCExpr::Constant) {
3351 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00003352 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00003353 Operands.push_back(
3354 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00003355 return true;
3356 }
3357 }
3358 return false;
3359}
Jack Carterd0bd6422013-04-18 00:41:53 +00003360
Jack Carter873c7242013-01-12 01:03:14 +00003361MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003362MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00003363 StringRef Identifier,
3364 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003365 int Index = matchCPURegisterName(Identifier);
3366 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003367 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003368 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3369 return MatchOperand_Success;
3370 }
3371
Vasileios Kalintiris10b5ba32014-11-11 10:31:31 +00003372 Index = matchHWRegsRegisterName(Identifier);
3373 if (Index != -1) {
3374 Operands.push_back(MipsOperand::createHWRegsReg(
3375 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3376 return MatchOperand_Success;
3377 }
3378
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003379 Index = matchFPURegisterName(Identifier);
3380 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003381 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003382 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3383 return MatchOperand_Success;
3384 }
3385
3386 Index = matchFCCRegisterName(Identifier);
3387 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003388 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003389 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3390 return MatchOperand_Success;
3391 }
3392
3393 Index = matchACRegisterName(Identifier);
3394 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003395 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003396 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3397 return MatchOperand_Success;
3398 }
3399
3400 Index = matchMSA128RegisterName(Identifier);
3401 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003402 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003403 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3404 return MatchOperand_Success;
3405 }
3406
3407 Index = matchMSA128CtrlRegisterName(Identifier);
3408 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00003409 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003410 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
3411 return MatchOperand_Success;
3412 }
3413
3414 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00003415}
3416
3417MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003418MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003419 MCAsmParser &Parser = getParser();
Daniel Sanders315386c2014-04-01 10:40:14 +00003420 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003421
3422 if (Token.is(AsmToken::Identifier)) {
3423 DEBUG(dbgs() << ".. identifier\n");
3424 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00003425 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00003426 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00003427 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003428 } else if (Token.is(AsmToken::Integer)) {
3429 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00003430 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003431 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
3432 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003433 return MatchOperand_Success;
3434 }
3435
3436 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
3437
3438 return MatchOperand_NoMatch;
3439}
3440
David Blaikie960ea3f2014-06-08 16:18:35 +00003441MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003442MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003443 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003444 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003445
3446 auto Token = Parser.getTok();
3447
3448 SMLoc S = Token.getLoc();
3449
3450 if (Token.isNot(AsmToken::Dollar)) {
3451 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
3452 if (Token.is(AsmToken::Identifier)) {
3453 if (searchSymbolAlias(Operands))
3454 return MatchOperand_Success;
3455 }
3456 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
3457 return MatchOperand_NoMatch;
3458 }
3459 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003460
Toma Tabacu13964452014-09-04 13:23:44 +00003461 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00003462 if (ResTy == MatchOperand_Success) {
3463 Parser.Lex(); // $
3464 Parser.Lex(); // identifier
3465 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003466 return ResTy;
3467}
3468
3469MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003470MipsAsmParser::parseImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003471 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003472 switch (getLexer().getKind()) {
3473 default:
3474 return MatchOperand_NoMatch;
3475 case AsmToken::LParen:
3476 case AsmToken::Minus:
3477 case AsmToken::Plus:
3478 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00003479 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003480 case AsmToken::String:
3481 break;
3482 }
3483
3484 const MCExpr *IdVal;
3485 SMLoc S = Parser.getTok().getLoc();
3486 if (getParser().parseExpression(IdVal))
3487 return MatchOperand_ParseFail;
3488
3489 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3490 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
3491 return MatchOperand_Success;
3492}
3493
David Blaikie960ea3f2014-06-08 16:18:35 +00003494MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003495MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003496 MCAsmParser &Parser = getParser();
Toma Tabacu13964452014-09-04 13:23:44 +00003497 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003498
3499 SMLoc S = getLexer().getLoc();
3500
3501 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00003502 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003503 if (ResTy != MatchOperand_NoMatch)
3504 return ResTy;
3505
Daniel Sanders315386c2014-04-01 10:40:14 +00003506 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00003507 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00003508 if (ResTy != MatchOperand_NoMatch)
3509 return ResTy;
3510
Daniel Sandersffd84362014-04-01 10:41:48 +00003511 const MCExpr *Expr = nullptr;
3512 if (Parser.parseExpression(Expr)) {
3513 // We have no way of knowing if a symbol was consumed so we must ParseFail
3514 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003515 }
Daniel Sandersffd84362014-04-01 10:41:48 +00003516 Operands.push_back(
3517 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003518 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00003519}
3520
Vladimir Medic2b953d02013-10-01 09:48:56 +00003521MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00003522MipsAsmParser::parseInvNum(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003523 MCAsmParser &Parser = getParser();
Vladimir Medic2b953d02013-10-01 09:48:56 +00003524 const MCExpr *IdVal;
3525 // If the first token is '$' we may have register operand.
3526 if (Parser.getTok().is(AsmToken::Dollar))
3527 return MatchOperand_NoMatch;
3528 SMLoc S = Parser.getTok().getLoc();
3529 if (getParser().parseExpression(IdVal))
3530 return MatchOperand_ParseFail;
3531 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00003532 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00003533 int64_t Val = MCE->getValue();
3534 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
3535 Operands.push_back(MipsOperand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003536 MCConstantExpr::create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00003537 return MatchOperand_Success;
3538}
3539
Matheus Almeida779c5932013-11-18 12:32:49 +00003540MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00003541MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003542 MCAsmParser &Parser = getParser();
Matheus Almeida779c5932013-11-18 12:32:49 +00003543 switch (getLexer().getKind()) {
3544 default:
3545 return MatchOperand_NoMatch;
3546 case AsmToken::LParen:
3547 case AsmToken::Plus:
3548 case AsmToken::Minus:
3549 case AsmToken::Integer:
3550 break;
3551 }
3552
3553 const MCExpr *Expr;
3554 SMLoc S = Parser.getTok().getLoc();
3555
3556 if (getParser().parseExpression(Expr))
3557 return MatchOperand_ParseFail;
3558
3559 int64_t Val;
Jim Grosbach13760bd2015-05-30 01:25:56 +00003560 if (!Expr->evaluateAsAbsolute(Val)) {
Matheus Almeida779c5932013-11-18 12:32:49 +00003561 Error(S, "expected immediate value");
3562 return MatchOperand_ParseFail;
3563 }
3564
3565 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
3566 // and because the CPU always adds one to the immediate field, the allowed
3567 // range becomes 1..4. We'll only check the range here and will deal
3568 // with the addition/subtraction when actually decoding/encoding
3569 // the instruction.
3570 if (Val < 1 || Val > 4) {
3571 Error(S, "immediate not in range (1..4)");
3572 return MatchOperand_ParseFail;
3573 }
3574
Jack Carter3b2c96e2014-01-22 23:31:38 +00003575 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003576 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00003577 return MatchOperand_Success;
3578}
3579
Zoran Jovanovica4c4b5f2014-11-19 16:44:02 +00003580MipsAsmParser::OperandMatchResultTy
3581MipsAsmParser::parseRegisterList(OperandVector &Operands) {
3582 MCAsmParser &Parser = getParser();
3583 SmallVector<unsigned, 10> Regs;
3584 unsigned RegNo;
3585 unsigned PrevReg = Mips::NoRegister;
3586 bool RegRange = false;
3587 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3588
3589 if (Parser.getTok().isNot(AsmToken::Dollar))
3590 return MatchOperand_ParseFail;
3591
3592 SMLoc S = Parser.getTok().getLoc();
3593 while (parseAnyRegister(TmpOperands) == MatchOperand_Success) {
3594 SMLoc E = getLexer().getLoc();
3595 MipsOperand &Reg = static_cast<MipsOperand &>(*TmpOperands.back());
3596 RegNo = isGP64bit() ? Reg.getGPR64Reg() : Reg.getGPR32Reg();
3597 if (RegRange) {
3598 // Remove last register operand because registers from register range
3599 // should be inserted first.
3600 if (RegNo == Mips::RA) {
3601 Regs.push_back(RegNo);
3602 } else {
3603 unsigned TmpReg = PrevReg + 1;
3604 while (TmpReg <= RegNo) {
3605 if ((TmpReg < Mips::S0) || (TmpReg > Mips::S7)) {
3606 Error(E, "invalid register operand");
3607 return MatchOperand_ParseFail;
3608 }
3609
3610 PrevReg = TmpReg;
3611 Regs.push_back(TmpReg++);
3612 }
3613 }
3614
3615 RegRange = false;
3616 } else {
3617 if ((PrevReg == Mips::NoRegister) && (RegNo != Mips::S0) &&
3618 (RegNo != Mips::RA)) {
3619 Error(E, "$16 or $31 expected");
3620 return MatchOperand_ParseFail;
3621 } else if (((RegNo < Mips::S0) || (RegNo > Mips::S7)) &&
3622 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3623 Error(E, "invalid register operand");
3624 return MatchOperand_ParseFail;
3625 } else if ((PrevReg != Mips::NoRegister) && (RegNo != PrevReg + 1) &&
3626 (RegNo != Mips::FP) && (RegNo != Mips::RA)) {
3627 Error(E, "consecutive register numbers expected");
3628 return MatchOperand_ParseFail;
3629 }
3630
3631 Regs.push_back(RegNo);
3632 }
3633
3634 if (Parser.getTok().is(AsmToken::Minus))
3635 RegRange = true;
3636
3637 if (!Parser.getTok().isNot(AsmToken::Minus) &&
3638 !Parser.getTok().isNot(AsmToken::Comma)) {
3639 Error(E, "',' or '-' expected");
3640 return MatchOperand_ParseFail;
3641 }
3642
3643 Lex(); // Consume comma or minus
3644 if (Parser.getTok().isNot(AsmToken::Dollar))
3645 break;
3646
3647 PrevReg = RegNo;
3648 }
3649
3650 SMLoc E = Parser.getTok().getLoc();
3651 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3652 parseMemOperand(Operands);
3653 return MatchOperand_Success;
3654}
3655
Zoran Jovanovic2deca342014-12-16 14:59:10 +00003656MipsAsmParser::OperandMatchResultTy
3657MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
3658 MCAsmParser &Parser = getParser();
3659
3660 SMLoc S = Parser.getTok().getLoc();
3661 if (parseAnyRegister(Operands) != MatchOperand_Success)
3662 return MatchOperand_ParseFail;
3663
3664 SMLoc E = Parser.getTok().getLoc();
3665 MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
3666 unsigned Reg = Op.getGPR32Reg();
3667 Operands.pop_back();
3668 Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
3669 return MatchOperand_Success;
3670}
3671
Zoran Jovanovic41688672015-02-10 16:36:20 +00003672MipsAsmParser::OperandMatchResultTy
3673MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
3674 MCAsmParser &Parser = getParser();
3675 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
3676 SmallVector<unsigned, 10> Regs;
3677
3678 if (Parser.getTok().isNot(AsmToken::Dollar))
3679 return MatchOperand_ParseFail;
3680
3681 SMLoc S = Parser.getTok().getLoc();
3682
3683 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3684 return MatchOperand_ParseFail;
3685
3686 MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3687 unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3688 Regs.push_back(RegNo);
3689
3690 SMLoc E = Parser.getTok().getLoc();
3691 if (Parser.getTok().isNot(AsmToken::Comma)) {
3692 Error(E, "',' expected");
3693 return MatchOperand_ParseFail;
3694 }
3695
3696 // Remove comma.
3697 Parser.Lex();
3698
3699 if (parseAnyRegister(TmpOperands) != MatchOperand_Success)
3700 return MatchOperand_ParseFail;
3701
3702 Reg = &static_cast<MipsOperand &>(*TmpOperands.back());
3703 RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg();
3704 Regs.push_back(RegNo);
3705
3706 Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this));
3707
3708 return MatchOperand_Success;
3709}
3710
Jack Carterdc1e35d2012-09-06 20:00:02 +00003711MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
3712
Vladimir Medic4c299852013-11-06 11:27:05 +00003713 MCSymbolRefExpr::VariantKind VK =
3714 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
3715 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
3716 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
3717 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
3718 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
3719 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
3720 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
3721 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
3722 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
3723 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
3724 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
3725 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
3726 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
3727 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
3728 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
3729 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
3730 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
3731 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00003732 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
3733 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
3734 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
3735 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
3736 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
3737 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00003738 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
3739 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00003740 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00003741
Matheus Almeida2852af82014-04-22 10:15:54 +00003742 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00003743
Jack Carterdc1e35d2012-09-06 20:00:02 +00003744 return VK;
3745}
Jack Cartera63b16a2012-09-07 00:23:42 +00003746
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003747/// Sometimes (i.e. load/stores) the operand may be followed immediately by
3748/// either this.
3749/// ::= '(', register, ')'
3750/// handle it before we iterate so we don't get tripped up by the lack of
3751/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003752bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003753 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003754 if (getLexer().is(AsmToken::LParen)) {
3755 Operands.push_back(
3756 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
3757 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003758 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003759 SMLoc Loc = getLexer().getLoc();
3760 Parser.eatToEndOfStatement();
3761 return Error(Loc, "unexpected token in argument list");
3762 }
3763 if (Parser.getTok().isNot(AsmToken::RParen)) {
3764 SMLoc Loc = getLexer().getLoc();
3765 Parser.eatToEndOfStatement();
3766 return Error(Loc, "unexpected token, expected ')'");
3767 }
3768 Operands.push_back(
3769 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
3770 Parser.Lex();
3771 }
3772 return false;
3773}
3774
3775/// Sometimes (i.e. in MSA) the operand may be followed immediately by
3776/// either one of these.
3777/// ::= '[', register, ']'
3778/// ::= '[', integer, ']'
3779/// handle it before we iterate so we don't get tripped up by the lack of
3780/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00003781bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00003782 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003783 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003784 if (getLexer().is(AsmToken::LBrac)) {
3785 Operands.push_back(
3786 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
3787 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00003788 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003789 SMLoc Loc = getLexer().getLoc();
3790 Parser.eatToEndOfStatement();
3791 return Error(Loc, "unexpected token in argument list");
3792 }
3793 if (Parser.getTok().isNot(AsmToken::RBrac)) {
3794 SMLoc Loc = getLexer().getLoc();
3795 Parser.eatToEndOfStatement();
3796 return Error(Loc, "unexpected token, expected ']'");
3797 }
3798 Operands.push_back(
3799 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
3800 Parser.Lex();
3801 }
3802 return false;
3803}
3804
David Blaikie960ea3f2014-06-08 16:18:35 +00003805bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
3806 SMLoc NameLoc, OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003807 MCAsmParser &Parser = getParser();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003808 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00003809
3810 // We have reached first instruction, module directive are now forbidden.
3811 getTargetStreamer().forbidModuleDirective();
3812
Vladimir Medic74593e62013-07-17 15:00:42 +00003813 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00003814 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00003815 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00003816 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00003817 }
Vladimir Medic64828a12013-07-16 10:07:14 +00003818 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003819 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00003820
3821 // Read the remaining operands.
3822 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3823 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003824 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003825 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003826 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003827 return Error(Loc, "unexpected token in argument list");
3828 }
Toma Tabacu13964452014-09-04 13:23:44 +00003829 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003830 return true;
3831 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00003832
Jack Carterd0bd6422013-04-18 00:41:53 +00003833 while (getLexer().is(AsmToken::Comma)) {
3834 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00003835 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00003836 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00003837 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003838 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003839 return Error(Loc, "unexpected token in argument list");
3840 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003841 // Parse bracket and parenthesis suffixes before we iterate
3842 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00003843 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003844 return true;
3845 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00003846 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00003847 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00003848 }
3849 }
Jack Carterb4dbc172012-09-05 23:34:03 +00003850 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3851 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003852 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00003853 return Error(Loc, "unexpected token in argument list");
3854 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003855 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00003856 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00003857}
3858
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003859bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003860 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003861 SMLoc Loc = getLexer().getLoc();
3862 Parser.eatToEndOfStatement();
3863 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00003864}
3865
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003866bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003867 return Error(Loc, ErrorMsg);
3868}
3869
Jack Carter0b744b32012-10-04 02:29:46 +00003870bool MipsAsmParser::parseSetNoAtDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003871 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003872 // Line should look like: ".set noat".
Toma Tabacu16a74492015-02-13 10:30:57 +00003873
3874 // Set the $at register to $0.
Toma Tabacub19cf202015-04-27 13:12:59 +00003875 AssemblerOptions.back()->setATRegIndex(0);
Toma Tabacu16a74492015-02-13 10:30:57 +00003876
3877 Parser.Lex(); // Eat "noat".
3878
Jack Carterd0bd6422013-04-18 00:41:53 +00003879 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003880 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003881 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003882 return false;
3883 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003884
3885 getTargetStreamer().emitDirectiveSetNoAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00003886 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003887 return false;
3888}
Jack Carterd0bd6422013-04-18 00:41:53 +00003889
Jack Carter0b744b32012-10-04 02:29:46 +00003890bool MipsAsmParser::parseSetAtDirective() {
Toma Tabacu16a74492015-02-13 10:30:57 +00003891 // Line can be: ".set at", which sets $at to $1
3892 // or ".set at=$reg", which sets $at to $reg.
Rafael Espindola961d4692014-11-11 05:18:41 +00003893 MCAsmParser &Parser = getParser();
Toma Tabacu16a74492015-02-13 10:30:57 +00003894 Parser.Lex(); // Eat "at".
3895
Jack Carter0b744b32012-10-04 02:29:46 +00003896 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00003897 // No register was specified, so we set $at to $1.
Toma Tabacub19cf202015-04-27 13:12:59 +00003898 AssemblerOptions.back()->setATRegIndex(1);
Toma Tabacu16a74492015-02-13 10:30:57 +00003899
3900 getTargetStreamer().emitDirectiveSetAt();
Jack Carterd0bd6422013-04-18 00:41:53 +00003901 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003902 return false;
Toma Tabacu16a74492015-02-13 10:30:57 +00003903 }
3904
3905 if (getLexer().isNot(AsmToken::Equal)) {
3906 reportParseError("unexpected token, expected equals sign");
3907 return false;
3908 }
3909 Parser.Lex(); // Eat "=".
3910
3911 if (getLexer().isNot(AsmToken::Dollar)) {
3912 if (getLexer().is(AsmToken::EndOfStatement)) {
3913 reportParseError("no register specified");
3914 return false;
3915 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00003916 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00003917 return false;
3918 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003919 }
3920 Parser.Lex(); // Eat "$".
Jack Carter1ac53222013-02-20 23:11:17 +00003921
Toma Tabacu16a74492015-02-13 10:30:57 +00003922 // Find out what "reg" is.
3923 unsigned AtRegNo;
3924 const AsmToken &Reg = Parser.getTok();
3925 if (Reg.is(AsmToken::Identifier)) {
3926 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
3927 } else if (Reg.is(AsmToken::Integer)) {
3928 AtRegNo = Reg.getIntVal();
Jack Carter0b744b32012-10-04 02:29:46 +00003929 } else {
Toma Tabacu16a74492015-02-13 10:30:57 +00003930 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00003931 return false;
3932 }
Toma Tabacu16a74492015-02-13 10:30:57 +00003933
3934 // Check if $reg is a valid register. If it is, set $at to $reg.
Toma Tabacub19cf202015-04-27 13:12:59 +00003935 if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) {
Toma Tabacu16a74492015-02-13 10:30:57 +00003936 reportParseError("invalid register");
3937 return false;
3938 }
3939 Parser.Lex(); // Eat "reg".
3940
3941 // If this is not the end of the statement, report an error.
3942 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3943 reportParseError("unexpected token, expected end of statement");
3944 return false;
3945 }
3946
3947 getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo);
3948
3949 Parser.Lex(); // Consume the EndOfStatement.
3950 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003951}
3952
3953bool MipsAsmParser::parseSetReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003954 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003955 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003956 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003957 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003958 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003959 return false;
3960 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003961 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00003962 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003963 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003964 return false;
3965}
3966
3967bool MipsAsmParser::parseSetNoReorderDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003968 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00003969 Parser.Lex();
3970 // If this is not the end of the statement, report an error.
3971 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003972 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003973 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00003974 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003975 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00003976 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00003977 Parser.Lex(); // Consume the EndOfStatement.
3978 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003979}
3980
3981bool MipsAsmParser::parseSetMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003982 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003983 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003984 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003985 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003986 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00003987 return false;
3988 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00003989 AssemblerOptions.back()->setMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00003990 getTargetStreamer().emitDirectiveSetMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00003991 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00003992 return false;
3993}
3994
3995bool MipsAsmParser::parseSetNoMacroDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00003996 MCAsmParser &Parser = getParser();
Jack Carter0b744b32012-10-04 02:29:46 +00003997 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00003998 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00003999 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004000 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00004001 return false;
4002 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004003 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00004004 reportParseError("`noreorder' must be set before `nomacro'");
4005 return false;
4006 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00004007 AssemblerOptions.back()->setNoMacro();
Toma Tabacu772155c2015-05-14 13:42:10 +00004008 getTargetStreamer().emitDirectiveSetNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00004009 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00004010 return false;
4011}
Jack Carterd76b2372013-03-21 21:44:16 +00004012
Daniel Sanders44934432014-08-07 12:03:36 +00004013bool MipsAsmParser::parseSetMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004014 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004015 Parser.Lex();
4016
4017 // If this is not the end of the statement, report an error.
4018 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004019 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004020
4021 setFeatureBits(Mips::FeatureMSA, "msa");
4022 getTargetStreamer().emitDirectiveSetMsa();
4023 return false;
4024}
4025
4026bool MipsAsmParser::parseSetNoMsaDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004027 MCAsmParser &Parser = getParser();
Daniel Sanders44934432014-08-07 12:03:36 +00004028 Parser.Lex();
4029
4030 // If this is not the end of the statement, report an error.
4031 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004032 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00004033
4034 clearFeatureBits(Mips::FeatureMSA, "msa");
4035 getTargetStreamer().emitDirectiveSetNoMsa();
4036 return false;
4037}
4038
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004039bool MipsAsmParser::parseSetNoDspDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004040 MCAsmParser &Parser = getParser();
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004041 Parser.Lex(); // Eat "nodsp".
4042
4043 // If this is not the end of the statement, report an error.
4044 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4045 reportParseError("unexpected token, expected end of statement");
4046 return false;
4047 }
4048
4049 clearFeatureBits(Mips::FeatureDSP, "dsp");
4050 getTargetStreamer().emitDirectiveSetNoDsp();
4051 return false;
4052}
4053
Toma Tabacucc2502d2014-11-04 17:18:07 +00004054bool MipsAsmParser::parseSetMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004055 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00004056 Parser.Lex(); // Eat "mips16".
4057
Jack Carter39536722014-01-22 23:08:42 +00004058 // If this is not the end of the statement, report an error.
4059 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004060 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00004061 return false;
4062 }
Toma Tabacucc2502d2014-11-04 17:18:07 +00004063
4064 setFeatureBits(Mips::FeatureMips16, "mips16");
4065 getTargetStreamer().emitDirectiveSetMips16();
4066 Parser.Lex(); // Consume the EndOfStatement.
4067 return false;
4068}
4069
4070bool MipsAsmParser::parseSetNoMips16Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004071 MCAsmParser &Parser = getParser();
Toma Tabacucc2502d2014-11-04 17:18:07 +00004072 Parser.Lex(); // Eat "nomips16".
4073
4074 // If this is not the end of the statement, report an error.
4075 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4076 reportParseError("unexpected token, expected end of statement");
4077 return false;
4078 }
4079
4080 clearFeatureBits(Mips::FeatureMips16, "mips16");
4081 getTargetStreamer().emitDirectiveSetNoMips16();
Jack Carter39536722014-01-22 23:08:42 +00004082 Parser.Lex(); // Consume the EndOfStatement.
4083 return false;
4084}
4085
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004086bool MipsAsmParser::parseSetFpDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004087 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004088 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004089 // Line can be: .set fp=32
4090 // .set fp=xx
4091 // .set fp=64
4092 Parser.Lex(); // Eat fp token
4093 AsmToken Tok = Parser.getTok();
4094 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004095 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004096 return false;
4097 }
4098 Parser.Lex(); // Eat '=' token.
4099 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004100
4101 if (!parseFpABIValue(FpAbiVal, ".set"))
4102 return false;
4103
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004104 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004105 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004106 return false;
4107 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004108 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004109 Parser.Lex(); // Consume the EndOfStatement.
4110 return false;
4111}
4112
Toma Tabacu32c72aa2015-06-30 09:36:50 +00004113bool MipsAsmParser::parseSetOddSPRegDirective() {
4114 MCAsmParser &Parser = getParser();
4115
4116 Parser.Lex(); // Eat "oddspreg".
4117 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4118 reportParseError("unexpected token, expected end of statement");
4119 return false;
4120 }
4121
4122 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4123 getTargetStreamer().emitDirectiveSetOddSPReg();
4124 return false;
4125}
4126
4127bool MipsAsmParser::parseSetNoOddSPRegDirective() {
4128 MCAsmParser &Parser = getParser();
4129
4130 Parser.Lex(); // Eat "nooddspreg".
4131 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4132 reportParseError("unexpected token, expected end of statement");
4133 return false;
4134 }
4135
4136 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
4137 getTargetStreamer().emitDirectiveSetNoOddSPReg();
4138 return false;
4139}
4140
Toma Tabacu9db22db2014-09-09 10:15:38 +00004141bool MipsAsmParser::parseSetPopDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004142 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004143 SMLoc Loc = getLexer().getLoc();
4144
4145 Parser.Lex();
4146 if (getLexer().isNot(AsmToken::EndOfStatement))
4147 return reportParseError("unexpected token, expected end of statement");
4148
4149 // Always keep an element on the options "stack" to prevent the user
4150 // from changing the initial options. This is how we remember them.
4151 if (AssemblerOptions.size() == 2)
4152 return reportParseError(Loc, ".set pop with no .set push");
4153
4154 AssemblerOptions.pop_back();
Toma Tabacu465acfd2015-06-09 13:33:26 +00004155 setAvailableFeatures(
4156 ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures()));
4157 STI.setFeatureBits(AssemblerOptions.back()->getFeatures());
Toma Tabacu9db22db2014-09-09 10:15:38 +00004158
4159 getTargetStreamer().emitDirectiveSetPop();
4160 return false;
4161}
4162
4163bool MipsAsmParser::parseSetPushDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004164 MCAsmParser &Parser = getParser();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004165 Parser.Lex();
4166 if (getLexer().isNot(AsmToken::EndOfStatement))
4167 return reportParseError("unexpected token, expected end of statement");
4168
4169 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00004170 AssemblerOptions.push_back(
4171 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00004172
4173 getTargetStreamer().emitDirectiveSetPush();
4174 return false;
4175}
4176
Toma Tabacu29696502015-06-02 09:48:04 +00004177bool MipsAsmParser::parseSetSoftFloatDirective() {
4178 MCAsmParser &Parser = getParser();
4179 Parser.Lex();
4180 if (getLexer().isNot(AsmToken::EndOfStatement))
4181 return reportParseError("unexpected token, expected end of statement");
4182
4183 setFeatureBits(Mips::FeatureSoftFloat, "soft-float");
4184 getTargetStreamer().emitDirectiveSetSoftFloat();
4185 return false;
4186}
4187
4188bool MipsAsmParser::parseSetHardFloatDirective() {
4189 MCAsmParser &Parser = getParser();
4190 Parser.Lex();
4191 if (getLexer().isNot(AsmToken::EndOfStatement))
4192 return reportParseError("unexpected token, expected end of statement");
4193
4194 clearFeatureBits(Mips::FeatureSoftFloat, "soft-float");
4195 getTargetStreamer().emitDirectiveSetHardFloat();
4196 return false;
4197}
4198
Jack Carterd76b2372013-03-21 21:44:16 +00004199bool MipsAsmParser::parseSetAssignment() {
4200 StringRef Name;
4201 const MCExpr *Value;
Rafael Espindola961d4692014-11-11 05:18:41 +00004202 MCAsmParser &Parser = getParser();
Jack Carterd76b2372013-03-21 21:44:16 +00004203
4204 if (Parser.parseIdentifier(Name))
4205 reportParseError("expected identifier after .set");
4206
4207 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00004208 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00004209 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00004210
Jack Carter3b2c96e2014-01-22 23:31:38 +00004211 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00004212 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00004213
Jim Grosbach6f482002015-05-18 18:43:14 +00004214 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jack Carterd76b2372013-03-21 21:44:16 +00004215 Sym->setVariableValue(Value);
4216
4217 return false;
4218}
Jack Carterd0bd6422013-04-18 00:41:53 +00004219
Toma Tabacu26647792014-09-09 12:52:14 +00004220bool MipsAsmParser::parseSetMips0Directive() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004221 MCAsmParser &Parser = getParser();
Toma Tabacu26647792014-09-09 12:52:14 +00004222 Parser.Lex();
4223 if (getLexer().isNot(AsmToken::EndOfStatement))
4224 return reportParseError("unexpected token, expected end of statement");
4225
4226 // Reset assembler options to their initial values.
Toma Tabacu465acfd2015-06-09 13:33:26 +00004227 setAvailableFeatures(
4228 ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures()));
4229 STI.setFeatureBits(AssemblerOptions.front()->getFeatures());
Toma Tabacu26647792014-09-09 12:52:14 +00004230 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
4231
4232 getTargetStreamer().emitDirectiveSetMips0();
4233 return false;
4234}
4235
Toma Tabacu85618b32014-08-19 14:22:52 +00004236bool MipsAsmParser::parseSetArchDirective() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004237 MCAsmParser &Parser = getParser();
Toma Tabacu85618b32014-08-19 14:22:52 +00004238 Parser.Lex();
4239 if (getLexer().isNot(AsmToken::Equal))
4240 return reportParseError("unexpected token, expected equals sign");
4241
4242 Parser.Lex();
4243 StringRef Arch;
4244 if (Parser.parseIdentifier(Arch))
4245 return reportParseError("expected arch identifier");
4246
4247 StringRef ArchFeatureName =
4248 StringSwitch<StringRef>(Arch)
4249 .Case("mips1", "mips1")
4250 .Case("mips2", "mips2")
4251 .Case("mips3", "mips3")
4252 .Case("mips4", "mips4")
4253 .Case("mips5", "mips5")
4254 .Case("mips32", "mips32")
4255 .Case("mips32r2", "mips32r2")
Daniel Sanders17793142015-02-18 16:24:50 +00004256 .Case("mips32r3", "mips32r3")
4257 .Case("mips32r5", "mips32r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00004258 .Case("mips32r6", "mips32r6")
4259 .Case("mips64", "mips64")
4260 .Case("mips64r2", "mips64r2")
Daniel Sanders17793142015-02-18 16:24:50 +00004261 .Case("mips64r3", "mips64r3")
4262 .Case("mips64r5", "mips64r5")
Toma Tabacu85618b32014-08-19 14:22:52 +00004263 .Case("mips64r6", "mips64r6")
4264 .Case("cnmips", "cnmips")
4265 .Case("r4000", "mips3") // This is an implementation of Mips3.
4266 .Default("");
4267
4268 if (ArchFeatureName.empty())
4269 return reportParseError("unsupported architecture");
4270
4271 selectArch(ArchFeatureName);
4272 getTargetStreamer().emitDirectiveSetArch(Arch);
4273 return false;
4274}
4275
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004276bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004277 MCAsmParser &Parser = getParser();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004278 Parser.Lex();
4279 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004280 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004281
Matheus Almeida2852af82014-04-22 10:15:54 +00004282 switch (Feature) {
4283 default:
4284 llvm_unreachable("Unimplemented feature");
4285 case Mips::FeatureDSP:
4286 setFeatureBits(Mips::FeatureDSP, "dsp");
4287 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004288 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004289 case Mips::FeatureMicroMips:
4290 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004291 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004292 case Mips::FeatureMips1:
4293 selectArch("mips1");
4294 getTargetStreamer().emitDirectiveSetMips1();
4295 break;
4296 case Mips::FeatureMips2:
4297 selectArch("mips2");
4298 getTargetStreamer().emitDirectiveSetMips2();
4299 break;
4300 case Mips::FeatureMips3:
4301 selectArch("mips3");
4302 getTargetStreamer().emitDirectiveSetMips3();
4303 break;
4304 case Mips::FeatureMips4:
4305 selectArch("mips4");
4306 getTargetStreamer().emitDirectiveSetMips4();
4307 break;
4308 case Mips::FeatureMips5:
4309 selectArch("mips5");
4310 getTargetStreamer().emitDirectiveSetMips5();
4311 break;
4312 case Mips::FeatureMips32:
4313 selectArch("mips32");
4314 getTargetStreamer().emitDirectiveSetMips32();
4315 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004316 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004317 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00004318 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004319 break;
Daniel Sanders17793142015-02-18 16:24:50 +00004320 case Mips::FeatureMips32r3:
4321 selectArch("mips32r3");
4322 getTargetStreamer().emitDirectiveSetMips32R3();
4323 break;
4324 case Mips::FeatureMips32r5:
4325 selectArch("mips32r5");
4326 getTargetStreamer().emitDirectiveSetMips32R5();
4327 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004328 case Mips::FeatureMips32r6:
4329 selectArch("mips32r6");
4330 getTargetStreamer().emitDirectiveSetMips32R6();
4331 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004332 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004333 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00004334 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00004335 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00004336 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00004337 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00004338 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00004339 break;
Daniel Sanders17793142015-02-18 16:24:50 +00004340 case Mips::FeatureMips64r3:
4341 selectArch("mips64r3");
4342 getTargetStreamer().emitDirectiveSetMips64R3();
4343 break;
4344 case Mips::FeatureMips64r5:
4345 selectArch("mips64r5");
4346 getTargetStreamer().emitDirectiveSetMips64R5();
4347 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00004348 case Mips::FeatureMips64r6:
4349 selectArch("mips64r6");
4350 getTargetStreamer().emitDirectiveSetMips64R6();
4351 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00004352 }
4353 return false;
4354}
4355
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004356bool MipsAsmParser::eatComma(StringRef ErrorStr) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004357 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004358 if (getLexer().isNot(AsmToken::Comma)) {
4359 SMLoc Loc = getLexer().getLoc();
4360 Parser.eatToEndOfStatement();
4361 return Error(Loc, ErrorStr);
4362 }
4363
Matheus Almeida2852af82014-04-22 10:15:54 +00004364 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004365 return true;
4366}
4367
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004368bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00004369 if (AssemblerOptions.back()->isReorder())
Toma Tabacudde4c462014-11-06 10:02:45 +00004370 Warning(Loc, ".cpload should be inside a noreorder section");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004371
Toma Tabacudde4c462014-11-06 10:02:45 +00004372 if (inMips16Mode()) {
4373 reportParseError(".cpload is not supported in Mips16 mode");
4374 return false;
4375 }
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004376
David Blaikie960ea3f2014-06-08 16:18:35 +00004377 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00004378 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004379 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
4380 reportParseError("expected register containing function address");
4381 return false;
4382 }
4383
David Blaikie960ea3f2014-06-08 16:18:35 +00004384 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
4385 if (!RegOpnd.isGPRAsmReg()) {
4386 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004387 return false;
4388 }
4389
Toma Tabacudde4c462014-11-06 10:02:45 +00004390 // If this is not the end of the statement, report an error.
4391 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4392 reportParseError("unexpected token, expected end of statement");
4393 return false;
4394 }
4395
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004396 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004397 return false;
4398}
4399
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004400bool MipsAsmParser::parseDirectiveCPSetup() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004401 MCAsmParser &Parser = getParser();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004402 unsigned FuncReg;
4403 unsigned Save;
4404 bool SaveIsReg = true;
4405
Matheus Almeida7e815762014-06-18 13:08:59 +00004406 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00004407 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00004408 if (ResTy == MatchOperand_NoMatch) {
4409 reportParseError("expected register containing function address");
4410 Parser.eatToEndOfStatement();
4411 return false;
4412 }
4413
4414 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4415 if (!FuncRegOpnd.isGPRAsmReg()) {
4416 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
4417 Parser.eatToEndOfStatement();
4418 return false;
4419 }
4420
4421 FuncReg = FuncRegOpnd.getGPR32Reg();
4422 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004423
Toma Tabacu65f10572014-09-16 15:00:52 +00004424 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004425 return true;
4426
Toma Tabacu13964452014-09-04 13:23:44 +00004427 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00004428 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004429 const AsmToken &Tok = Parser.getTok();
4430 if (Tok.is(AsmToken::Integer)) {
4431 Save = Tok.getIntVal();
4432 SaveIsReg = false;
4433 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00004434 } else {
4435 reportParseError("expected save register or stack offset");
4436 Parser.eatToEndOfStatement();
4437 return false;
4438 }
4439 } else {
4440 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
4441 if (!SaveOpnd.isGPRAsmReg()) {
4442 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
4443 Parser.eatToEndOfStatement();
4444 return false;
4445 }
4446 Save = SaveOpnd.getGPR32Reg();
4447 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004448
Toma Tabacu65f10572014-09-16 15:00:52 +00004449 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004450 return true;
4451
Toma Tabacu8874eac2015-02-18 13:46:53 +00004452 const MCExpr *Expr;
4453 if (Parser.parseExpression(Expr)) {
4454 reportParseError("expected expression");
4455 return false;
4456 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004457
Toma Tabacu8874eac2015-02-18 13:46:53 +00004458 if (Expr->getKind() != MCExpr::SymbolRef) {
4459 reportParseError("expected symbol");
4460 return false;
4461 }
4462 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
4463
4464 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(),
4465 SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00004466 return false;
4467}
4468
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004469bool MipsAsmParser::parseDirectiveNaN() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004470 MCAsmParser &Parser = getParser();
Matheus Almeida0051f2d2014-04-16 15:48:55 +00004471 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4472 const AsmToken &Tok = Parser.getTok();
4473
4474 if (Tok.getString() == "2008") {
4475 Parser.Lex();
4476 getTargetStreamer().emitDirectiveNaN2008();
4477 return false;
4478 } else if (Tok.getString() == "legacy") {
4479 Parser.Lex();
4480 getTargetStreamer().emitDirectiveNaNLegacy();
4481 return false;
4482 }
4483 }
4484 // If we don't recognize the option passed to the .nan
4485 // directive (e.g. no option or unknown option), emit an error.
4486 reportParseError("invalid option in .nan directive");
4487 return false;
4488}
4489
Jack Carter0b744b32012-10-04 02:29:46 +00004490bool MipsAsmParser::parseDirectiveSet() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004491 MCAsmParser &Parser = getParser();
Jack Carterd0bd6422013-04-18 00:41:53 +00004492 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00004493 const AsmToken &Tok = Parser.getTok();
4494
4495 if (Tok.getString() == "noat") {
4496 return parseSetNoAtDirective();
4497 } else if (Tok.getString() == "at") {
4498 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00004499 } else if (Tok.getString() == "arch") {
4500 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004501 } else if (Tok.getString() == "fp") {
4502 return parseSetFpDirective();
Toma Tabacu32c72aa2015-06-30 09:36:50 +00004503 } else if (Tok.getString() == "oddspreg") {
4504 return parseSetOddSPRegDirective();
4505 } else if (Tok.getString() == "nooddspreg") {
4506 return parseSetNoOddSPRegDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00004507 } else if (Tok.getString() == "pop") {
4508 return parseSetPopDirective();
4509 } else if (Tok.getString() == "push") {
4510 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00004511 } else if (Tok.getString() == "reorder") {
4512 return parseSetReorderDirective();
4513 } else if (Tok.getString() == "noreorder") {
4514 return parseSetNoReorderDirective();
4515 } else if (Tok.getString() == "macro") {
4516 return parseSetMacroDirective();
4517 } else if (Tok.getString() == "nomacro") {
4518 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00004519 } else if (Tok.getString() == "mips16") {
Toma Tabacucc2502d2014-11-04 17:18:07 +00004520 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00004521 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00004522 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00004523 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00004524 getTargetStreamer().emitDirectiveSetNoMicroMips();
4525 Parser.eatToEndOfStatement();
4526 return false;
4527 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004528 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00004529 } else if (Tok.getString() == "mips0") {
4530 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00004531 } else if (Tok.getString() == "mips1") {
4532 return parseSetFeature(Mips::FeatureMips1);
4533 } else if (Tok.getString() == "mips2") {
4534 return parseSetFeature(Mips::FeatureMips2);
4535 } else if (Tok.getString() == "mips3") {
4536 return parseSetFeature(Mips::FeatureMips3);
4537 } else if (Tok.getString() == "mips4") {
4538 return parseSetFeature(Mips::FeatureMips4);
4539 } else if (Tok.getString() == "mips5") {
4540 return parseSetFeature(Mips::FeatureMips5);
4541 } else if (Tok.getString() == "mips32") {
4542 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00004543 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004544 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sanders17793142015-02-18 16:24:50 +00004545 } else if (Tok.getString() == "mips32r3") {
4546 return parseSetFeature(Mips::FeatureMips32r3);
4547 } else if (Tok.getString() == "mips32r5") {
4548 return parseSetFeature(Mips::FeatureMips32r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00004549 } else if (Tok.getString() == "mips32r6") {
4550 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00004551 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004552 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00004553 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004554 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sanders17793142015-02-18 16:24:50 +00004555 } else if (Tok.getString() == "mips64r3") {
4556 return parseSetFeature(Mips::FeatureMips64r3);
4557 } else if (Tok.getString() == "mips64r5") {
4558 return parseSetFeature(Mips::FeatureMips64r5);
Daniel Sandersf0df2212014-08-04 12:20:00 +00004559 } else if (Tok.getString() == "mips64r6") {
4560 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00004561 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00004562 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00004563 } else if (Tok.getString() == "nodsp") {
4564 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00004565 } else if (Tok.getString() == "msa") {
4566 return parseSetMsaDirective();
4567 } else if (Tok.getString() == "nomsa") {
4568 return parseSetNoMsaDirective();
Toma Tabacu29696502015-06-02 09:48:04 +00004569 } else if (Tok.getString() == "softfloat") {
4570 return parseSetSoftFloatDirective();
4571 } else if (Tok.getString() == "hardfloat") {
4572 return parseSetHardFloatDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00004573 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00004574 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00004575 parseSetAssignment();
4576 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00004577 }
Jack Carter07c818d2013-01-25 01:31:34 +00004578
Jack Carter0b744b32012-10-04 02:29:46 +00004579 return true;
4580}
4581
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004582/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00004583/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00004584bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004585 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00004586 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4587 for (;;) {
4588 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004589 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00004590 return true;
4591
4592 getParser().getStreamer().EmitValue(Value, Size);
4593
4594 if (getLexer().is(AsmToken::EndOfStatement))
4595 break;
4596
Jack Carter07c818d2013-01-25 01:31:34 +00004597 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00004598 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00004599 Parser.Lex();
4600 }
4601 }
4602
4603 Parser.Lex();
4604 return false;
4605}
4606
Vladimir Medic4c299852013-11-06 11:27:05 +00004607/// parseDirectiveGpWord
4608/// ::= .gpword local_sym
4609bool MipsAsmParser::parseDirectiveGpWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004610 MCAsmParser &Parser = getParser();
Vladimir Medic4c299852013-11-06 11:27:05 +00004611 const MCExpr *Value;
4612 // EmitGPRel32Value requires an expression, so we are using base class
4613 // method to evaluate the expression.
4614 if (getParser().parseExpression(Value))
4615 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00004616 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00004617
Vladimir Medice10c1122013-11-13 13:18:04 +00004618 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004619 return Error(getLexer().getLoc(),
4620 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00004621 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00004622 return false;
4623}
4624
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004625/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00004626/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00004627bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004628 MCAsmParser &Parser = getParser();
Rafael Espindolab59fb732014-03-28 18:50:26 +00004629 const MCExpr *Value;
4630 // EmitGPRel64Value requires an expression, so we are using base class
4631 // method to evaluate the expression.
4632 if (getParser().parseExpression(Value))
4633 return true;
4634 getParser().getStreamer().EmitGPRel64Value(Value);
4635
4636 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00004637 return Error(getLexer().getLoc(),
4638 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00004639 Parser.Lex(); // Eat EndOfStatement token.
4640 return false;
4641}
4642
Jack Carter0cd3c192014-01-06 23:27:31 +00004643bool MipsAsmParser::parseDirectiveOption() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004644 MCAsmParser &Parser = getParser();
Jack Carter0cd3c192014-01-06 23:27:31 +00004645 // Get the option token.
4646 AsmToken Tok = Parser.getTok();
4647 // At the moment only identifiers are supported.
4648 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004649 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00004650 Parser.eatToEndOfStatement();
4651 return false;
4652 }
4653
4654 StringRef Option = Tok.getIdentifier();
4655
4656 if (Option == "pic0") {
4657 getTargetStreamer().emitDirectiveOptionPic0();
4658 Parser.Lex();
4659 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4660 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00004661 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00004662 Parser.eatToEndOfStatement();
4663 }
4664 return false;
4665 }
4666
Matheus Almeidaf79b2812014-03-26 13:40:29 +00004667 if (Option == "pic2") {
4668 getTargetStreamer().emitDirectiveOptionPic2();
4669 Parser.Lex();
4670 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
4671 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00004672 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00004673 Parser.eatToEndOfStatement();
4674 }
4675 return false;
4676 }
4677
Jack Carter0cd3c192014-01-06 23:27:31 +00004678 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00004679 Warning(Parser.getTok().getLoc(),
4680 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00004681 Parser.eatToEndOfStatement();
4682 return false;
4683}
4684
Toma Tabacu9ca50962015-04-16 09:53:47 +00004685/// parseInsnDirective
4686/// ::= .insn
4687bool MipsAsmParser::parseInsnDirective() {
4688 // If this is not the end of the statement, report an error.
4689 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4690 reportParseError("unexpected token, expected end of statement");
4691 return false;
4692 }
4693
4694 // The actual label marking happens in
4695 // MipsELFStreamer::createPendingLabelRelocs().
4696 getTargetStreamer().emitDirectiveInsn();
4697
4698 getParser().Lex(); // Eat EndOfStatement token.
4699 return false;
4700}
4701
Daniel Sanders7e527422014-07-10 13:38:23 +00004702/// parseDirectiveModule
4703/// ::= .module oddspreg
4704/// ::= .module nooddspreg
4705/// ::= .module fp=value
Toma Tabacu0f093132015-06-30 13:46:03 +00004706/// ::= .module softfloat
4707/// ::= .module hardfloat
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004708bool MipsAsmParser::parseDirectiveModule() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004709 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004710 MCAsmLexer &Lexer = getLexer();
4711 SMLoc L = Lexer.getLoc();
4712
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00004713 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004714 // TODO : get a better message.
4715 reportParseError(".module directive must appear before any code");
4716 return false;
4717 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004718
Toma Tabacuc405c822015-01-23 10:40:19 +00004719 StringRef Option;
4720 if (Parser.parseIdentifier(Option)) {
4721 reportParseError("expected .module option identifier");
4722 return false;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004723 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004724
Toma Tabacuc405c822015-01-23 10:40:19 +00004725 if (Option == "oddspreg") {
Toma Tabacufc97d8a2015-06-30 12:41:33 +00004726 clearModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00004727
Toma Tabacu3c499582015-06-25 10:56:57 +00004728 // Synchronize the abiflags information with the FeatureBits information we
4729 // changed above.
4730 getTargetStreamer().updateABIInfo(*this);
4731
4732 // If printing assembly, use the recently updated abiflags information.
4733 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
4734 // emitted at the end).
4735 getTargetStreamer().emitDirectiveModuleOddSPReg();
4736
Toma Tabacuc405c822015-01-23 10:40:19 +00004737 // If this is not the end of the statement, report an error.
4738 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4739 reportParseError("unexpected token, expected end of statement");
4740 return false;
4741 }
4742
4743 return false; // parseDirectiveModule has finished successfully.
4744 } else if (Option == "nooddspreg") {
4745 if (!isABI_O32()) {
4746 Error(L, "'.module nooddspreg' requires the O32 ABI");
4747 return false;
4748 }
4749
Toma Tabacufc97d8a2015-06-30 12:41:33 +00004750 setModuleFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
Toma Tabacuc405c822015-01-23 10:40:19 +00004751
Toma Tabacu3c499582015-06-25 10:56:57 +00004752 // Synchronize the abiflags information with the FeatureBits information we
4753 // changed above.
4754 getTargetStreamer().updateABIInfo(*this);
4755
4756 // If printing assembly, use the recently updated abiflags information.
4757 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
4758 // emitted at the end).
4759 getTargetStreamer().emitDirectiveModuleOddSPReg();
4760
Toma Tabacuc405c822015-01-23 10:40:19 +00004761 // If this is not the end of the statement, report an error.
4762 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4763 reportParseError("unexpected token, expected end of statement");
4764 return false;
4765 }
4766
4767 return false; // parseDirectiveModule has finished successfully.
4768 } else if (Option == "fp") {
4769 return parseDirectiveModuleFP();
Toma Tabacu0f093132015-06-30 13:46:03 +00004770 } else if (Option == "softfloat") {
4771 setModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
4772
4773 // Synchronize the ABI Flags information with the FeatureBits information we
4774 // updated above.
4775 getTargetStreamer().updateABIInfo(*this);
4776
4777 // If printing assembly, use the recently updated ABI Flags information.
4778 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
4779 // emitted later).
4780 getTargetStreamer().emitDirectiveModuleSoftFloat();
4781
4782 // If this is not the end of the statement, report an error.
4783 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4784 reportParseError("unexpected token, expected end of statement");
4785 return false;
4786 }
4787
4788 return false; // parseDirectiveModule has finished successfully.
4789 } else if (Option == "hardfloat") {
4790 clearModuleFeatureBits(Mips::FeatureSoftFloat, "soft-float");
4791
4792 // Synchronize the ABI Flags information with the FeatureBits information we
4793 // updated above.
4794 getTargetStreamer().updateABIInfo(*this);
4795
4796 // If printing assembly, use the recently updated ABI Flags information.
4797 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
4798 // emitted later).
4799 getTargetStreamer().emitDirectiveModuleHardFloat();
4800
4801 // If this is not the end of the statement, report an error.
4802 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4803 reportParseError("unexpected token, expected end of statement");
4804 return false;
4805 }
4806
4807 return false; // parseDirectiveModule has finished successfully.
Toma Tabacuc405c822015-01-23 10:40:19 +00004808 } else {
4809 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
4810 }
Daniel Sanders7e527422014-07-10 13:38:23 +00004811}
4812
4813/// parseDirectiveModuleFP
4814/// ::= =32
4815/// ::= =xx
4816/// ::= =64
4817bool MipsAsmParser::parseDirectiveModuleFP() {
Rafael Espindola961d4692014-11-11 05:18:41 +00004818 MCAsmParser &Parser = getParser();
Daniel Sanders7e527422014-07-10 13:38:23 +00004819 MCAsmLexer &Lexer = getLexer();
4820
4821 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004822 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004823 return false;
4824 }
4825 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004826
Daniel Sanders7e527422014-07-10 13:38:23 +00004827 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004828 if (!parseFpABIValue(FpABI, ".module"))
4829 return false;
4830
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004831 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00004832 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004833 return false;
4834 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004835
Toma Tabacua64e5402015-06-25 12:44:38 +00004836 // Synchronize the abiflags information with the FeatureBits information we
4837 // changed above.
4838 getTargetStreamer().updateABIInfo(*this);
4839
4840 // If printing assembly, use the recently updated abiflags information.
4841 // If generating ELF, don't do anything (the .MIPS.abiflags section gets
4842 // emitted at the end).
4843 getTargetStreamer().emitDirectiveModuleFP();
4844
Daniel Sanders7e527422014-07-10 13:38:23 +00004845 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00004846 return false;
4847}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004848
Daniel Sanders7e527422014-07-10 13:38:23 +00004849bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004850 StringRef Directive) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004851 MCAsmParser &Parser = getParser();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004852 MCAsmLexer &Lexer = getLexer();
Toma Tabacufc97d8a2015-06-30 12:41:33 +00004853 bool ModuleLevelOptions = Directive == ".module";
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004854
4855 if (Lexer.is(AsmToken::Identifier)) {
4856 StringRef Value = Parser.getTok().getString();
4857 Parser.Lex();
4858
4859 if (Value != "xx") {
4860 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4861 return false;
4862 }
4863
4864 if (!isABI_O32()) {
4865 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
4866 return false;
4867 }
4868
Daniel Sanders7e527422014-07-10 13:38:23 +00004869 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00004870 if (ModuleLevelOptions) {
4871 setModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
4872 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
4873 } else {
4874 setFeatureBits(Mips::FeatureFPXX, "fpxx");
4875 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
4876 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004877 return true;
4878 }
4879
4880 if (Lexer.is(AsmToken::Integer)) {
4881 unsigned Value = Parser.getTok().getIntVal();
4882 Parser.Lex();
4883
4884 if (Value != 32 && Value != 64) {
4885 reportParseError("unsupported value, expected 'xx', '32' or '64'");
4886 return false;
4887 }
4888
4889 if (Value == 32) {
4890 if (!isABI_O32()) {
4891 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
4892 return false;
4893 }
4894
Daniel Sanders7e527422014-07-10 13:38:23 +00004895 FpABI = MipsABIFlagsSection::FpABIKind::S32;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00004896 if (ModuleLevelOptions) {
4897 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
4898 clearModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
4899 } else {
4900 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
4901 clearFeatureBits(Mips::FeatureFP64Bit, "fp64");
4902 }
Toma Tabacua64e5402015-06-25 12:44:38 +00004903 } else {
Daniel Sanders7e527422014-07-10 13:38:23 +00004904 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Toma Tabacufc97d8a2015-06-30 12:41:33 +00004905 if (ModuleLevelOptions) {
4906 clearModuleFeatureBits(Mips::FeatureFPXX, "fpxx");
4907 setModuleFeatureBits(Mips::FeatureFP64Bit, "fp64");
4908 } else {
4909 clearFeatureBits(Mips::FeatureFPXX, "fpxx");
4910 setFeatureBits(Mips::FeatureFP64Bit, "fp64");
4911 }
Toma Tabacua64e5402015-06-25 12:44:38 +00004912 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004913
Daniel Sanders7e527422014-07-10 13:38:23 +00004914 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00004915 }
4916
4917 return false;
4918}
4919
Jack Carter0b744b32012-10-04 02:29:46 +00004920bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004921 MCAsmParser &Parser = getParser();
Jack Carter07c818d2013-01-25 01:31:34 +00004922 StringRef IDVal = DirectiveID.getString();
4923
Matheus Almeida525bc4f2014-04-30 11:28:42 +00004924 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00004925 return parseDirectiveCpLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00004926 if (IDVal == ".dword") {
4927 parseDataDirective(8, DirectiveID.getLoc());
4928 return false;
4929 }
Jack Carterd0bd6422013-04-18 00:41:53 +00004930 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004931 StringRef SymbolName;
4932
4933 if (Parser.parseIdentifier(SymbolName)) {
4934 reportParseError("expected identifier after .ent");
4935 return false;
4936 }
4937
4938 // There's an undocumented extension that allows an integer to
4939 // follow the name of the procedure which AFAICS is ignored by GAS.
4940 // Example: .ent foo,2
4941 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4942 if (getLexer().isNot(AsmToken::Comma)) {
4943 // Even though we accept this undocumented extension for compatibility
4944 // reasons, the additional integer argument does not actually change
4945 // the behaviour of the '.ent' directive, so we would like to discourage
4946 // its use. We do this by not referring to the extended version in
4947 // error messages which are not directly related to its use.
4948 reportParseError("unexpected token, expected end of statement");
4949 return false;
4950 }
4951 Parser.Lex(); // Eat the comma.
4952 const MCExpr *DummyNumber;
4953 int64_t DummyNumberVal;
4954 // If the user was explicitly trying to use the extended version,
4955 // we still give helpful extension-related error messages.
4956 if (Parser.parseExpression(DummyNumber)) {
4957 reportParseError("expected number after comma");
4958 return false;
4959 }
Jim Grosbach13760bd2015-05-30 01:25:56 +00004960 if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004961 reportParseError("expected an absolute expression after comma");
4962 return false;
4963 }
4964 }
4965
4966 // If this is not the end of the statement, report an error.
4967 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4968 reportParseError("unexpected token, expected end of statement");
4969 return false;
4970 }
4971
Jim Grosbach6f482002015-05-18 18:43:14 +00004972 MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
Daniel Sandersd97a6342014-08-13 10:07:34 +00004973
4974 getTargetStreamer().emitDirectiveEnt(*Sym);
4975 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00004976 return false;
4977 }
4978
Jack Carter07c818d2013-01-25 01:31:34 +00004979 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00004980 StringRef SymbolName;
4981
4982 if (Parser.parseIdentifier(SymbolName)) {
4983 reportParseError("expected identifier after .end");
4984 return false;
4985 }
4986
4987 if (getLexer().isNot(AsmToken::EndOfStatement)) {
4988 reportParseError("unexpected token, expected end of statement");
4989 return false;
4990 }
4991
4992 if (CurrentFn == nullptr) {
4993 reportParseError(".end used without .ent");
4994 return false;
4995 }
4996
4997 if ((SymbolName != CurrentFn->getName())) {
4998 reportParseError(".end symbol does not match .ent symbol");
4999 return false;
5000 }
5001
5002 getTargetStreamer().emitDirectiveEnd(SymbolName);
5003 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00005004 return false;
5005 }
5006
Jack Carter07c818d2013-01-25 01:31:34 +00005007 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005008 // .frame $stack_reg, frame_size_in_bytes, $return_reg
5009 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00005010 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005011 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5012 reportParseError("expected stack register");
5013 return false;
5014 }
5015
5016 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5017 if (!StackRegOpnd.isGPRAsmReg()) {
5018 reportParseError(StackRegOpnd.getStartLoc(),
5019 "expected general purpose register");
5020 return false;
5021 }
5022 unsigned StackReg = StackRegOpnd.getGPR32Reg();
5023
5024 if (Parser.getTok().is(AsmToken::Comma))
5025 Parser.Lex();
5026 else {
5027 reportParseError("unexpected token, expected comma");
5028 return false;
5029 }
5030
5031 // Parse the frame size.
5032 const MCExpr *FrameSize;
5033 int64_t FrameSizeVal;
5034
5035 if (Parser.parseExpression(FrameSize)) {
5036 reportParseError("expected frame size value");
5037 return false;
5038 }
5039
Jim Grosbach13760bd2015-05-30 01:25:56 +00005040 if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005041 reportParseError("frame size not an absolute expression");
5042 return false;
5043 }
5044
5045 if (Parser.getTok().is(AsmToken::Comma))
5046 Parser.Lex();
5047 else {
5048 reportParseError("unexpected token, expected comma");
5049 return false;
5050 }
5051
5052 // Parse the return register.
5053 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00005054 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00005055 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
5056 reportParseError("expected return register");
5057 return false;
5058 }
5059
5060 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
5061 if (!ReturnRegOpnd.isGPRAsmReg()) {
5062 reportParseError(ReturnRegOpnd.getStartLoc(),
5063 "expected general purpose register");
5064 return false;
5065 }
5066
5067 // If this is not the end of the statement, report an error.
5068 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5069 reportParseError("unexpected token, expected end of statement");
5070 return false;
5071 }
5072
5073 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
5074 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00005075 return false;
5076 }
5077
Jack Carter07c818d2013-01-25 01:31:34 +00005078 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00005079 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00005080 }
5081
Daniel Sandersd97a6342014-08-13 10:07:34 +00005082 if (IDVal == ".mask" || IDVal == ".fmask") {
5083 // .mask bitmask, frame_offset
5084 // bitmask: One bit for each register used.
5085 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
5086 // first register is expected to be saved.
5087 // Examples:
5088 // .mask 0x80000000, -4
5089 // .fmask 0x80000000, -4
5090 //
Jack Carterbe332172012-09-07 00:48:02 +00005091
Daniel Sandersd97a6342014-08-13 10:07:34 +00005092 // Parse the bitmask
5093 const MCExpr *BitMask;
5094 int64_t BitMaskVal;
5095
5096 if (Parser.parseExpression(BitMask)) {
5097 reportParseError("expected bitmask value");
5098 return false;
5099 }
5100
Jim Grosbach13760bd2015-05-30 01:25:56 +00005101 if (!BitMask->evaluateAsAbsolute(BitMaskVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005102 reportParseError("bitmask not an absolute expression");
5103 return false;
5104 }
5105
5106 if (Parser.getTok().is(AsmToken::Comma))
5107 Parser.Lex();
5108 else {
5109 reportParseError("unexpected token, expected comma");
5110 return false;
5111 }
5112
5113 // Parse the frame_offset
5114 const MCExpr *FrameOffset;
5115 int64_t FrameOffsetVal;
5116
5117 if (Parser.parseExpression(FrameOffset)) {
5118 reportParseError("expected frame offset value");
5119 return false;
5120 }
5121
Jim Grosbach13760bd2015-05-30 01:25:56 +00005122 if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) {
Daniel Sandersd97a6342014-08-13 10:07:34 +00005123 reportParseError("frame offset not an absolute expression");
5124 return false;
5125 }
5126
5127 // If this is not the end of the statement, report an error.
5128 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5129 reportParseError("unexpected token, expected end of statement");
5130 return false;
5131 }
5132
5133 if (IDVal == ".mask")
5134 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
5135 else
5136 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00005137 return false;
5138 }
5139
Matheus Almeida0051f2d2014-04-16 15:48:55 +00005140 if (IDVal == ".nan")
5141 return parseDirectiveNaN();
5142
Jack Carter07c818d2013-01-25 01:31:34 +00005143 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00005144 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00005145 return false;
5146 }
5147
Rafael Espindolab59fb732014-03-28 18:50:26 +00005148 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00005149 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00005150 return false;
5151 }
5152
Jack Carter07c818d2013-01-25 01:31:34 +00005153 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00005154 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00005155 return false;
5156 }
5157
Jack Carter0cd3c192014-01-06 23:27:31 +00005158 if (IDVal == ".option")
5159 return parseDirectiveOption();
5160
5161 if (IDVal == ".abicalls") {
5162 getTargetStreamer().emitDirectiveAbiCalls();
5163 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00005164 Error(Parser.getTok().getLoc(),
5165 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00005166 // Clear line
5167 Parser.eatToEndOfStatement();
5168 }
5169 return false;
5170 }
5171
Daniel Sanders5bce5f62014-03-27 13:52:53 +00005172 if (IDVal == ".cpsetup")
5173 return parseDirectiveCPSetup();
5174
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00005175 if (IDVal == ".module")
5176 return parseDirectiveModule();
5177
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00005178 if (IDVal == ".llvm_internal_mips_reallow_module_directive")
5179 return parseInternalDirectiveReallowModule();
5180
Toma Tabacu9ca50962015-04-16 09:53:47 +00005181 if (IDVal == ".insn")
5182 return parseInsnDirective();
5183
Rafael Espindola870c4e92012-01-11 03:56:41 +00005184 return true;
5185}
5186
Toma Tabacu4e0cf8e2015-03-06 12:15:12 +00005187bool MipsAsmParser::parseInternalDirectiveReallowModule() {
5188 // If this is not the end of the statement, report an error.
5189 if (getLexer().isNot(AsmToken::EndOfStatement)) {
5190 reportParseError("unexpected token, expected end of statement");
5191 return false;
5192 }
5193
5194 getTargetStreamer().reallowModuleDirective();
5195
5196 getParser().Lex(); // Eat EndOfStatement token.
5197 return false;
5198}
5199
Rafael Espindola870c4e92012-01-11 03:56:41 +00005200extern "C" void LLVMInitializeMipsAsmParser() {
5201 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
5202 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
5203 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
5204 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
5205}
Jack Carterb4dbc172012-09-05 23:34:03 +00005206
5207#define GET_REGISTER_MATCHER
5208#define GET_MATCHER_IMPLEMENTATION
5209#include "MipsGenAsmMatcher.inc"