blob: 44f18a8d1cbe7e13d3bfa34bc5fd81718de33ad6 [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
Petar Jovanovica5da5882014-02-04 18:41:57 +000010#include "MCTargetDesc/MipsMCExpr.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000011#include "MCTargetDesc/MipsMCTargetDesc.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000012#include "MipsRegisterInfo.h"
Rafael Espindolaa17151a2013-10-08 13:08:17 +000013#include "MipsTargetStreamer.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000014#include "llvm/ADT/APInt.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000015#include "llvm/ADT/StringSwitch.h"
16#include "llvm/MC/MCContext.h"
17#include "llvm/MC/MCExpr.h"
18#include "llvm/MC/MCInst.h"
Daniel Sandersa771fef2014-03-24 14:05:39 +000019#include "llvm/MC/MCInstBuilder.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000020#include "llvm/MC/MCParser/MCAsmLexer.h"
21#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000022#include "llvm/MC/MCStreamer.h"
23#include "llvm/MC/MCSubtargetInfo.h"
24#include "llvm/MC/MCSymbol.h"
Akira Hatanaka7605630c2012-08-17 20:16:42 +000025#include "llvm/MC/MCTargetAsmParser.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000026#include "llvm/Support/Debug.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000027#include "llvm/Support/MathExtras.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000028#include "llvm/Support/TargetRegistry.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000029
30using namespace llvm;
31
Chandler Carruthe96dd892014-04-21 22:55:11 +000032#define DEBUG_TYPE "mips-asm-parser"
33
Joey Gouly0e76fa72013-09-12 10:28:05 +000034namespace llvm {
35class MCInstrInfo;
36}
37
Rafael Espindola870c4e92012-01-11 03:56:41 +000038namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000039class MipsAssemblerOptions {
40public:
Daniel Sandersc7dbc632014-07-08 10:11:38 +000041 MipsAssemblerOptions() : aTReg(1), reorder(true), macro(true) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000042
Vladimir Medic4c299852013-11-06 11:27:05 +000043 unsigned getATRegNum() { return aTReg; }
Jack Carter0b744b32012-10-04 02:29:46 +000044 bool setATReg(unsigned Reg);
45
Vladimir Medic4c299852013-11-06 11:27:05 +000046 bool isReorder() { return reorder; }
47 void setReorder() { reorder = true; }
48 void setNoreorder() { reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000049
Vladimir Medic4c299852013-11-06 11:27:05 +000050 bool isMacro() { return macro; }
51 void setMacro() { macro = true; }
52 void setNomacro() { macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000053
54private:
55 unsigned aTReg;
56 bool reorder;
57 bool macro;
58};
59}
60
61namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +000062class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +000063 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola4a1a3602014-01-14 01:21:46 +000064 MCTargetStreamer &TS = *Parser.getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +000065 return static_cast<MipsTargetStreamer &>(TS);
66 }
67
Jack Carterb4dbc172012-09-05 23:34:03 +000068 MCSubtargetInfo &STI;
69 MCAsmParser &Parser;
Jack Carter99d2afe2012-10-05 23:55:28 +000070 MipsAssemblerOptions Options;
Jack Carter0b744b32012-10-04 02:29:46 +000071
Akira Hatanaka7605630c2012-08-17 20:16:42 +000072#define GET_ASSEMBLER_HEADER
73#include "MipsGenAsmMatcher.inc"
74
Matheus Almeida595fcab2014-06-11 15:05:56 +000075 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
76
Chad Rosier49963552012-10-13 00:26:04 +000077 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +000078 OperandVector &Operands, MCStreamer &Out,
79 unsigned &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +000080 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +000081
Daniel Sandersb50ccf82014-04-01 10:35:28 +000082 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +000083 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +000084
David Blaikie960ea3f2014-06-08 16:18:35 +000085 bool ParseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +000086
David Blaikie960ea3f2014-06-08 16:18:35 +000087 bool ParseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +000088
David Blaikie960ea3f2014-06-08 16:18:35 +000089 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
90 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +000091
Craig Topper56c590a2014-04-29 07:58:02 +000092 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +000093
David Blaikie960ea3f2014-06-08 16:18:35 +000094 MipsAsmParser::OperandMatchResultTy parseMemOperand(OperandVector &Operands);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +000095
96 MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +000097 MatchAnyRegisterNameWithoutDollar(OperandVector &Operands,
98 StringRef Identifier, SMLoc S);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +000099
Jack Carter873c7242013-01-12 01:03:14 +0000100 MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +0000101 MatchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S);
Jack Carter873c7242013-01-12 01:03:14 +0000102
David Blaikie960ea3f2014-06-08 16:18:35 +0000103 MipsAsmParser::OperandMatchResultTy ParseAnyRegister(OperandVector &Operands);
Jack Carter873c7242013-01-12 01:03:14 +0000104
David Blaikie960ea3f2014-06-08 16:18:35 +0000105 MipsAsmParser::OperandMatchResultTy ParseImm(OperandVector &Operands);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000106
David Blaikie960ea3f2014-06-08 16:18:35 +0000107 MipsAsmParser::OperandMatchResultTy ParseJumpTarget(OperandVector &Operands);
Vladimir Medic2b953d02013-10-01 09:48:56 +0000108
David Blaikie960ea3f2014-06-08 16:18:35 +0000109 MipsAsmParser::OperandMatchResultTy parseInvNum(OperandVector &Operands);
Matheus Almeida779c5932013-11-18 12:32:49 +0000110
David Blaikie960ea3f2014-06-08 16:18:35 +0000111 MipsAsmParser::OperandMatchResultTy ParseLSAImm(OperandVector &Operands);
Jack Carterd76b2372013-03-21 21:44:16 +0000112
David Blaikie960ea3f2014-06-08 16:18:35 +0000113 bool searchSymbolAlias(OperandVector &Operands);
114
115 bool ParseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000116
Jack Carter30a59822012-10-04 04:03:53 +0000117 bool needsExpansion(MCInst &Inst);
118
Matheus Almeida3813d572014-06-19 14:39:14 +0000119 // Expands assembly pseudo instructions.
120 // Returns false on success, true otherwise.
121 bool expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000122 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000123
124 bool expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000125 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000126
127 bool expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000128 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000129
130 bool expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000131 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000132
Jack Carter9e65aa32013-03-22 00:05:30 +0000133 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000134 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
135 bool isImmOpnd);
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000136 bool reportParseError(Twine ErrorMsg);
137 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000138
Jack Carterb5cf5902013-04-17 00:18:04 +0000139 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000140 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000141
Vladimir Medic4c299852013-11-06 11:27:05 +0000142 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000143
144 bool isEvaluated(const MCExpr *Expr);
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000145 bool parseSetFeature(uint64_t Feature);
Matheus Almeida525bc4f2014-04-30 11:28:42 +0000146 bool parseDirectiveCPLoad(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000147 bool parseDirectiveCPSetup();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000148 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000149 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000150 bool parseDirectiveOption();
Jack Carter0b744b32012-10-04 02:29:46 +0000151
152 bool parseSetAtDirective();
153 bool parseSetNoAtDirective();
154 bool parseSetMacroDirective();
155 bool parseSetNoMacroDirective();
156 bool parseSetReorderDirective();
157 bool parseSetNoReorderDirective();
Jack Carter39536722014-01-22 23:08:42 +0000158 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000159 bool parseSetFpDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000160
Jack Carterd76b2372013-03-21 21:44:16 +0000161 bool parseSetAssignment();
162
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000163 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000164 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000165 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000166 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000167 bool parseDirectiveModuleFP();
168 bool parseFpABIValue(Val_GNU_MIPS_ABI &FpABI, StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000169
Jack Carterdc1e35d2012-09-06 20:00:02 +0000170 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000171
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000172 bool eatComma(StringRef ErrorStr);
173
Jack Carter1ac53222013-02-20 23:11:17 +0000174 int matchCPURegisterName(StringRef Symbol);
175
Jack Carter873c7242013-01-12 01:03:14 +0000176 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000177
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000178 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000179
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000180 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000181
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000182 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000183
Jack Carter5dc8ac92013-09-25 23:50:44 +0000184 int matchMSA128RegisterName(StringRef Name);
185
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000186 int matchMSA128CtrlRegisterName(StringRef Name);
187
Jack Carterd0bd6422013-04-18 00:41:53 +0000188 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000189
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000190 unsigned getGPR(int RegNo);
191
Matheus Almeida7de68e72014-06-18 14:46:05 +0000192 int getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000193
194 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000195 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000196
197 // Helper function that checks if the value of a vector index is within the
198 // boundaries of accepted values for each RegisterKind
199 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
200 bool validateMSAIndex(int Val, int RegKind);
201
Vladimir Medic615b26e2014-03-04 09:54:09 +0000202 void setFeatureBits(unsigned Feature, StringRef FeatureString) {
203 if (!(STI.getFeatureBits() & Feature)) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000204 setAvailableFeatures(
205 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000206 }
207 }
208
209 void clearFeatureBits(unsigned Feature, StringRef FeatureString) {
210 if (STI.getFeatureBits() & Feature) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000211 setAvailableFeatures(
212 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000213 }
214 }
215
Rafael Espindola870c4e92012-01-11 03:56:41 +0000216public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000217 enum MipsMatchResultTy {
218 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
219#define GET_OPERAND_DIAGNOSTIC_TYPES
220#include "MipsGenAsmMatcher.inc"
221#undef GET_OPERAND_DIAGNOSTIC_TYPES
222
223 };
224
Joey Gouly0e76fa72013-09-12 10:28:05 +0000225 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000226 const MCInstrInfo &MII, const MCTargetOptions &Options)
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000227 : MCTargetAsmParser(), STI(sti), Parser(parser) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000228 // Initialize the set of available features.
229 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000230
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000231 getTargetStreamer().updateABIInfo(*this);
232
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000233 // Assert exactly one ABI was chosen.
234 assert((((STI.getFeatureBits() & Mips::FeatureO32) != 0) +
235 ((STI.getFeatureBits() & Mips::FeatureEABI) != 0) +
236 ((STI.getFeatureBits() & Mips::FeatureN32) != 0) +
237 ((STI.getFeatureBits() & Mips::FeatureN64) != 0)) == 1);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000238 }
239
Jack Carterb4dbc172012-09-05 23:34:03 +0000240 MCAsmParser &getParser() const { return Parser; }
241 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000242
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000243 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
244 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
245
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000246 bool isGP64bit() const { return STI.getFeatureBits() & Mips::FeatureGP64Bit; }
247 bool isFP64bit() const { return STI.getFeatureBits() & Mips::FeatureFP64Bit; }
248 bool isABI_N32() const { return STI.getFeatureBits() & Mips::FeatureN32; }
249 bool isABI_N64() const { return STI.getFeatureBits() & Mips::FeatureN64; }
250 bool isABI_O32() const { return STI.getFeatureBits() & Mips::FeatureO32; }
251 bool isABI_FPXX() const { return false; } // TODO: add check for FeatureXX
252
253 bool inMicroMipsMode() const {
254 return STI.getFeatureBits() & Mips::FeatureMicroMips;
255 }
256 bool hasMips1() const { return STI.getFeatureBits() & Mips::FeatureMips1; }
257 bool hasMips2() const { return STI.getFeatureBits() & Mips::FeatureMips2; }
258 bool hasMips3() const { return STI.getFeatureBits() & Mips::FeatureMips3; }
259 bool hasMips4() const { return STI.getFeatureBits() & Mips::FeatureMips4; }
260 bool hasMips5() const { return STI.getFeatureBits() & Mips::FeatureMips5; }
261 bool hasMips32() const {
262 return (STI.getFeatureBits() & Mips::FeatureMips32);
263 }
264 bool hasMips64() const {
265 return (STI.getFeatureBits() & Mips::FeatureMips64);
266 }
267 bool hasMips32r2() const {
268 return (STI.getFeatureBits() & Mips::FeatureMips32r2);
269 }
270 bool hasMips64r2() const {
271 return (STI.getFeatureBits() & Mips::FeatureMips64r2);
272 }
273 bool hasMips32r6() const {
274 return (STI.getFeatureBits() & Mips::FeatureMips32r6);
275 }
276 bool hasMips64r6() const {
277 return (STI.getFeatureBits() & Mips::FeatureMips64r6);
278 }
279 bool hasDSP() const { return (STI.getFeatureBits() & Mips::FeatureDSP); }
280 bool hasDSPR2() const { return (STI.getFeatureBits() & Mips::FeatureDSPR2); }
281 bool hasMSA() const { return (STI.getFeatureBits() & Mips::FeatureMSA); }
282
283 bool inMips16Mode() const {
284 return STI.getFeatureBits() & Mips::FeatureMips16;
285 }
286 // TODO: see how can we get this info.
287 bool mipsSEUsesSoftFloat() const { return false; }
288
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000289 /// Warn if RegNo is the current assembler temporary.
290 void WarnIfAssemblerTemporary(int RegNo, SMLoc Loc);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000291};
292}
293
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000294namespace {
295
296/// MipsOperand - Instances of this class represent a parsed Mips machine
297/// instruction.
298class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000299public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000300 /// Broad categories of register classes
301 /// The exact class is finalized by the render method.
302 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000303 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000304 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000305 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000306 RegKind_FCC = 4, /// FCC
307 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
308 RegKind_MSACtrl = 16, /// MSA control registers
309 RegKind_COP2 = 32, /// COP2
310 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
311 /// context).
312 RegKind_CCR = 128, /// CCR
313 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000314 RegKind_COP3 = 512, /// COP3
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000315
316 /// Potentially any (e.g. $1)
317 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
318 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000319 RegKind_CCR | RegKind_HWRegs | RegKind_COP3
Jack Carter873c7242013-01-12 01:03:14 +0000320 };
321
322private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000323 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000324 k_Immediate, /// An immediate (possibly involving symbol references)
325 k_Memory, /// Base + Offset Memory Address
326 k_PhysRegister, /// A physical register from the Mips namespace
327 k_RegisterIndex, /// A register index in one or more RegKind.
328 k_Token /// A simple token
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000329 } Kind;
330
David Blaikie960ea3f2014-06-08 16:18:35 +0000331public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000332 MipsOperand(KindTy K, MipsAsmParser &Parser)
333 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
334
David Blaikie960ea3f2014-06-08 16:18:35 +0000335private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000336 /// For diagnostics, and checking the assembler temporary
337 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000338
Eric Christopher8996c5d2013-03-15 00:42:55 +0000339 struct Token {
340 const char *Data;
341 unsigned Length;
342 };
343
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000344 struct PhysRegOp {
345 unsigned Num; /// Register Number
346 };
347
348 struct RegIdxOp {
349 unsigned Index; /// Index into the register class
350 RegKind Kind; /// Bitfield of the kinds it could possibly be
351 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000352 };
353
354 struct ImmOp {
355 const MCExpr *Val;
356 };
357
358 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000359 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000360 const MCExpr *Off;
361 };
362
Jack Carterb4dbc172012-09-05 23:34:03 +0000363 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000364 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000365 struct PhysRegOp PhysReg;
366 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000367 struct ImmOp Imm;
368 struct MemOp Mem;
Jack Carterb4dbc172012-09-05 23:34:03 +0000369 };
370
371 SMLoc StartLoc, EndLoc;
372
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000373 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000374 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
375 const MCRegisterInfo *RegInfo,
376 SMLoc S, SMLoc E,
377 MipsAsmParser &Parser) {
378 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000379 Op->RegIdx.Index = Index;
380 Op->RegIdx.RegInfo = RegInfo;
381 Op->RegIdx.Kind = RegKind;
382 Op->StartLoc = S;
383 Op->EndLoc = E;
384 return Op;
385 }
386
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000387public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000388 /// Coerce the register to GPR32 and return the real register for the current
389 /// target.
390 unsigned getGPR32Reg() const {
391 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
392 AsmParser.WarnIfAssemblerTemporary(RegIdx.Index, StartLoc);
393 unsigned ClassID = Mips::GPR32RegClassID;
394 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000395 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000396
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000397 /// Coerce the register to GPR64 and return the real register for the current
398 /// target.
399 unsigned getGPR64Reg() const {
400 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
401 unsigned ClassID = Mips::GPR64RegClassID;
402 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000403 }
404
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000405private:
406 /// Coerce the register to AFGR64 and return the real register for the current
407 /// target.
408 unsigned getAFGR64Reg() const {
409 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
410 if (RegIdx.Index % 2 != 0)
411 AsmParser.Warning(StartLoc, "Float register should be even.");
412 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
413 .getRegister(RegIdx.Index / 2);
414 }
415
416 /// Coerce the register to FGR64 and return the real register for the current
417 /// target.
418 unsigned getFGR64Reg() const {
419 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
420 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
421 .getRegister(RegIdx.Index);
422 }
423
424 /// Coerce the register to FGR32 and return the real register for the current
425 /// target.
426 unsigned getFGR32Reg() const {
427 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
428 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
429 .getRegister(RegIdx.Index);
430 }
431
432 /// Coerce the register to FGRH32 and return the real register for the current
433 /// target.
434 unsigned getFGRH32Reg() const {
435 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
436 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
437 .getRegister(RegIdx.Index);
438 }
439
440 /// Coerce the register to FCC and return the real register for the current
441 /// target.
442 unsigned getFCCReg() const {
443 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
444 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
445 .getRegister(RegIdx.Index);
446 }
447
448 /// Coerce the register to MSA128 and return the real register for the current
449 /// target.
450 unsigned getMSA128Reg() const {
451 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
452 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
453 // identical
454 unsigned ClassID = Mips::MSA128BRegClassID;
455 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
456 }
457
458 /// Coerce the register to MSACtrl and return the real register for the
459 /// current target.
460 unsigned getMSACtrlReg() const {
461 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
462 unsigned ClassID = Mips::MSACtrlRegClassID;
463 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
464 }
465
466 /// Coerce the register to COP2 and return the real register for the
467 /// current target.
468 unsigned getCOP2Reg() const {
469 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
470 unsigned ClassID = Mips::COP2RegClassID;
471 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
472 }
473
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000474 /// Coerce the register to COP3 and return the real register for the
475 /// current target.
476 unsigned getCOP3Reg() const {
477 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
478 unsigned ClassID = Mips::COP3RegClassID;
479 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
480 }
481
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000482 /// Coerce the register to ACC64DSP and return the real register for the
483 /// current target.
484 unsigned getACC64DSPReg() const {
485 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
486 unsigned ClassID = Mips::ACC64DSPRegClassID;
487 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
488 }
489
490 /// Coerce the register to HI32DSP and return the real register for the
491 /// current target.
492 unsigned getHI32DSPReg() const {
493 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
494 unsigned ClassID = Mips::HI32DSPRegClassID;
495 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
496 }
497
498 /// Coerce the register to LO32DSP and return the real register for the
499 /// current target.
500 unsigned getLO32DSPReg() const {
501 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
502 unsigned ClassID = Mips::LO32DSPRegClassID;
503 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
504 }
505
506 /// Coerce the register to CCR and return the real register for the
507 /// current target.
508 unsigned getCCRReg() const {
509 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
510 unsigned ClassID = Mips::CCRRegClassID;
511 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
512 }
513
514 /// Coerce the register to HWRegs and return the real register for the
515 /// current target.
516 unsigned getHWRegsReg() const {
517 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
518 unsigned ClassID = Mips::HWRegsRegClassID;
519 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
520 }
521
522public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000523 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000524 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000525 if (!Expr)
Jack Carterb4dbc172012-09-05 23:34:03 +0000526 Inst.addOperand(MCOperand::CreateImm(0));
527 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
528 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
529 else
530 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000531 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000532
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000533 void addRegOperands(MCInst &Inst, unsigned N) const {
534 llvm_unreachable("Use a custom parser instead");
535 }
536
Daniel Sanders21bce302014-04-01 12:35:23 +0000537 /// Render the operand to an MCInst as a GPR32
538 /// Asserts if the wrong number of operands are requested, or the operand
539 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000540 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
541 assert(N == 1 && "Invalid number of operands!");
542 Inst.addOperand(MCOperand::CreateReg(getGPR32Reg()));
543 }
544
Daniel Sanders21bce302014-04-01 12:35:23 +0000545 /// Render the operand to an MCInst as a GPR64
546 /// Asserts if the wrong number of operands are requested, or the operand
547 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000548 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
549 assert(N == 1 && "Invalid number of operands!");
550 Inst.addOperand(MCOperand::CreateReg(getGPR64Reg()));
551 }
552
553 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
554 assert(N == 1 && "Invalid number of operands!");
555 Inst.addOperand(MCOperand::CreateReg(getAFGR64Reg()));
556 }
557
558 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
559 assert(N == 1 && "Invalid number of operands!");
560 Inst.addOperand(MCOperand::CreateReg(getFGR64Reg()));
561 }
562
563 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
564 assert(N == 1 && "Invalid number of operands!");
565 Inst.addOperand(MCOperand::CreateReg(getFGR32Reg()));
566 }
567
568 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
569 assert(N == 1 && "Invalid number of operands!");
570 Inst.addOperand(MCOperand::CreateReg(getFGRH32Reg()));
571 }
572
573 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
574 assert(N == 1 && "Invalid number of operands!");
575 Inst.addOperand(MCOperand::CreateReg(getFCCReg()));
576 }
577
578 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
579 assert(N == 1 && "Invalid number of operands!");
580 Inst.addOperand(MCOperand::CreateReg(getMSA128Reg()));
581 }
582
583 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
584 assert(N == 1 && "Invalid number of operands!");
585 Inst.addOperand(MCOperand::CreateReg(getMSACtrlReg()));
586 }
587
588 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
589 assert(N == 1 && "Invalid number of operands!");
590 Inst.addOperand(MCOperand::CreateReg(getCOP2Reg()));
591 }
592
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000593 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
594 assert(N == 1 && "Invalid number of operands!");
595 Inst.addOperand(MCOperand::CreateReg(getCOP3Reg()));
596 }
597
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000598 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
599 assert(N == 1 && "Invalid number of operands!");
600 Inst.addOperand(MCOperand::CreateReg(getACC64DSPReg()));
601 }
602
603 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
604 assert(N == 1 && "Invalid number of operands!");
605 Inst.addOperand(MCOperand::CreateReg(getHI32DSPReg()));
606 }
607
608 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
609 assert(N == 1 && "Invalid number of operands!");
610 Inst.addOperand(MCOperand::CreateReg(getLO32DSPReg()));
611 }
612
613 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
614 assert(N == 1 && "Invalid number of operands!");
615 Inst.addOperand(MCOperand::CreateReg(getCCRReg()));
616 }
617
618 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
619 assert(N == 1 && "Invalid number of operands!");
620 Inst.addOperand(MCOperand::CreateReg(getHWRegsReg()));
621 }
622
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000623 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000624 assert(N == 1 && "Invalid number of operands!");
625 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000626 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000627 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000628
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000629 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000630 assert(N == 2 && "Invalid number of operands!");
631
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000632 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000633
634 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000635 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000636 }
637
Craig Topper56c590a2014-04-29 07:58:02 +0000638 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000639 // As a special case until we sort out the definition of div/divu, pretend
640 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
641 if (isGPRAsmReg() && RegIdx.Index == 0)
642 return true;
643
644 return Kind == k_PhysRegister;
645 }
646 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000647 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000648 bool isConstantImm() const {
649 return isImm() && dyn_cast<MCConstantExpr>(getImm());
650 }
Craig Topper56c590a2014-04-29 07:58:02 +0000651 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000652 // Note: It's not possible to pretend that other operand kinds are tokens.
653 // The matcher emitter checks tokens first.
654 return Kind == k_Token;
655 }
Craig Topper56c590a2014-04-29 07:58:02 +0000656 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000657 bool isConstantMemOff() const {
658 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
659 }
660 template <unsigned Bits> bool isMemWithSimmOffset() const {
661 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff());
662 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000663 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000664 bool isLSAImm() const {
665 if (!isConstantImm())
666 return false;
667 int64_t Val = getConstantImm();
668 return 1 <= Val && Val <= 4;
669 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000670
671 StringRef getToken() const {
672 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000673 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000674 }
675
Craig Topper56c590a2014-04-29 07:58:02 +0000676 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000677 // As a special case until we sort out the definition of div/divu, pretend
678 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
679 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
680 RegIdx.Kind & RegKind_GPR)
681 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000682
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000683 assert(Kind == k_PhysRegister && "Invalid access!");
684 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +0000685 }
686
Jack Carterb4dbc172012-09-05 23:34:03 +0000687 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000688 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000689 return Imm.Val;
690 }
691
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000692 int64_t getConstantImm() const {
693 const MCExpr *Val = getImm();
694 return static_cast<const MCConstantExpr *>(Val)->getValue();
695 }
696
697 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000698 assert((Kind == k_Memory) && "Invalid access!");
699 return Mem.Base;
700 }
701
702 const MCExpr *getMemOff() const {
703 assert((Kind == k_Memory) && "Invalid access!");
704 return Mem.Off;
705 }
706
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000707 int64_t getConstantMemOff() const {
708 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
709 }
710
David Blaikie960ea3f2014-06-08 16:18:35 +0000711 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
712 MipsAsmParser &Parser) {
713 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000714 Op->Tok.Data = Str.data();
715 Op->Tok.Length = Str.size();
716 Op->StartLoc = S;
717 Op->EndLoc = S;
718 return Op;
719 }
720
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000721 /// Create a numeric register (e.g. $1). The exact register remains
722 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +0000723 static std::unique_ptr<MipsOperand>
724 CreateNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
725 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000726 DEBUG(dbgs() << "CreateNumericReg(" << Index << ", ...)\n");
727 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000728 }
729
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000730 /// Create a register that is definitely a GPR.
731 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +0000732 static std::unique_ptr<MipsOperand>
733 CreateGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
734 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000735 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000736 }
737
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000738 /// Create a register that is definitely a FGR.
739 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000740 static std::unique_ptr<MipsOperand>
741 CreateFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
742 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000743 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
744 }
745
746 /// Create a register that is definitely an FCC.
747 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000748 static std::unique_ptr<MipsOperand>
749 CreateFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
750 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000751 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
752 }
753
754 /// Create a register that is definitely an ACC.
755 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000756 static std::unique_ptr<MipsOperand>
757 CreateACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
758 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000759 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
760 }
761
762 /// Create a register that is definitely an MSA128.
763 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000764 static std::unique_ptr<MipsOperand>
765 CreateMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
766 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000767 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
768 }
769
770 /// Create a register that is definitely an MSACtrl.
771 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +0000772 static std::unique_ptr<MipsOperand>
773 CreateMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
774 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000775 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
776 }
777
David Blaikie960ea3f2014-06-08 16:18:35 +0000778 static std::unique_ptr<MipsOperand>
779 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
780 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000781 Op->Imm.Val = Val;
782 Op->StartLoc = S;
783 Op->EndLoc = E;
784 return Op;
785 }
786
David Blaikie960ea3f2014-06-08 16:18:35 +0000787 static std::unique_ptr<MipsOperand>
788 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
789 SMLoc E, MipsAsmParser &Parser) {
790 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
791 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +0000792 Op->Mem.Off = Off;
793 Op->StartLoc = S;
794 Op->EndLoc = E;
795 return Op;
796 }
797
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000798 bool isGPRAsmReg() const {
799 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000800 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000801 bool isFGRAsmReg() const {
802 // AFGR64 is $0-$15 but we handle this in getAFGR64()
803 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000804 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000805 bool isHWRegsAsmReg() const {
806 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000807 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000808 bool isCCRAsmReg() const {
809 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000810 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000811 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000812 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
813 return false;
814 if (!AsmParser.hasEightFccRegisters())
815 return RegIdx.Index == 0;
816 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +0000817 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000818 bool isACCAsmReg() const {
819 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +0000820 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000821 bool isCOP2AsmReg() const {
822 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +0000823 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000824 bool isCOP3AsmReg() const {
825 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
826 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000827 bool isMSA128AsmReg() const {
828 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +0000829 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000830 bool isMSACtrlAsmReg() const {
831 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000832 }
833
Jack Carterb4dbc172012-09-05 23:34:03 +0000834 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +0000835 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +0000836 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +0000837 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +0000838
NAKAMURA Takumie1f35832014-04-15 14:13:21 +0000839 virtual ~MipsOperand() {
840 switch (Kind) {
841 case k_Immediate:
842 break;
843 case k_Memory:
844 delete Mem.Base;
845 break;
846 case k_PhysRegister:
847 case k_RegisterIndex:
848 case k_Token:
849 break;
850 }
851 }
852
Craig Topper56c590a2014-04-29 07:58:02 +0000853 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000854 switch (Kind) {
855 case k_Immediate:
856 OS << "Imm<";
857 Imm.Val->print(OS);
858 OS << ">";
859 break;
860 case k_Memory:
861 OS << "Mem<";
862 Mem.Base->print(OS);
863 OS << ", ";
864 Mem.Off->print(OS);
865 OS << ">";
866 break;
867 case k_PhysRegister:
868 OS << "PhysReg<" << PhysReg.Num << ">";
869 break;
870 case k_RegisterIndex:
871 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
872 break;
873 case k_Token:
874 OS << Tok.Data;
875 break;
876 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000877 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000878}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +0000879} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000880
Jack Carter9e65aa32013-03-22 00:05:30 +0000881namespace llvm {
882extern const MCInstrDesc MipsInsts[];
883}
884static const MCInstrDesc &getInstDesc(unsigned Opcode) {
885 return MipsInsts[Opcode];
886}
887
888bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +0000889 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000890 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +0000891
Jack Carter9e65aa32013-03-22 00:05:30 +0000892 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000893
894 if (MCID.isBranch() || MCID.isCall()) {
895 const unsigned Opcode = Inst.getOpcode();
896 MCOperand Offset;
897
898 switch (Opcode) {
899 default:
900 break;
901 case Mips::BEQ:
902 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000903 case Mips::BEQ_MM:
904 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +0000905 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000906 Offset = Inst.getOperand(2);
907 if (!Offset.isImm())
908 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000909 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000910 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000911 if (OffsetToAlignment(Offset.getImm(),
912 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000913 return Error(IDLoc, "branch to misaligned address");
914 break;
915 case Mips::BGEZ:
916 case Mips::BGTZ:
917 case Mips::BLEZ:
918 case Mips::BLTZ:
919 case Mips::BGEZAL:
920 case Mips::BLTZAL:
921 case Mips::BC1F:
922 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000923 case Mips::BGEZ_MM:
924 case Mips::BGTZ_MM:
925 case Mips::BLEZ_MM:
926 case Mips::BLTZ_MM:
927 case Mips::BGEZAL_MM:
928 case Mips::BLTZAL_MM:
929 case Mips::BC1F_MM:
930 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +0000931 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000932 Offset = Inst.getOperand(1);
933 if (!Offset.isImm())
934 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000935 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000936 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000937 if (OffsetToAlignment(Offset.getImm(),
938 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000939 return Error(IDLoc, "branch to misaligned address");
940 break;
941 }
942 }
943
Daniel Sandersa84989a2014-06-16 13:25:35 +0000944 // SSNOP is deprecated on MIPS32r6/MIPS64r6
945 // We still accept it but it is a normal nop.
946 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
947 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
948 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
949 "nop instruction");
950 }
951
Jack Carterc15c1d22013-04-25 23:31:35 +0000952 if (MCID.hasDelaySlot() && Options.isReorder()) {
953 // If this instruction has a delay slot and .set reorder is active,
954 // emit a NOP after it.
955 Instructions.push_back(Inst);
956 MCInst NopInst;
957 NopInst.setOpcode(Mips::SLL);
958 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
959 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
960 NopInst.addOperand(MCOperand::CreateImm(0));
961 Instructions.push_back(NopInst);
962 return false;
963 }
964
Jack Carter9e65aa32013-03-22 00:05:30 +0000965 if (MCID.mayLoad() || MCID.mayStore()) {
966 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +0000967 // reference or immediate we may have to expand instructions.
968 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000969 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +0000970 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
971 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000972 MCOperand &Op = Inst.getOperand(i);
973 if (Op.isImm()) {
974 int MemOffset = Op.getImm();
975 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000976 // Offset can't exceed 16bit value.
977 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +0000978 return false;
979 }
980 } else if (Op.isExpr()) {
981 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +0000982 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000983 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +0000984 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +0000985 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000986 // Expand symbol.
987 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +0000988 return false;
989 }
Jack Carterb5cf5902013-04-17 00:18:04 +0000990 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000991 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +0000992 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +0000993 }
994 }
995 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000996 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +0000997 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +0000998
999 if (needsExpansion(Inst))
Matheus Almeida3813d572014-06-19 14:39:14 +00001000 return expandInstruction(Inst, IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +00001001 else
1002 Instructions.push_back(Inst);
1003
1004 return false;
1005}
1006
Jack Carter30a59822012-10-04 04:03:53 +00001007bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1008
Jack Carterd0bd6422013-04-18 00:41:53 +00001009 switch (Inst.getOpcode()) {
1010 case Mips::LoadImm32Reg:
1011 case Mips::LoadAddr32Imm:
1012 case Mips::LoadAddr32Reg:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001013 case Mips::LoadImm64Reg:
Jack Carterd0bd6422013-04-18 00:41:53 +00001014 return true;
1015 default:
1016 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001017 }
1018}
Jack Carter92995f12012-10-06 00:53:28 +00001019
Matheus Almeida3813d572014-06-19 14:39:14 +00001020bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001021 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001022 switch (Inst.getOpcode()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001023 default:
1024 assert(0 && "unimplemented expansion");
Matheus Almeida3813d572014-06-19 14:39:14 +00001025 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001026 case Mips::LoadImm32Reg:
1027 return expandLoadImm(Inst, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001028 case Mips::LoadImm64Reg:
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001029 if (!isGP64bit()) {
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001030 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1031 return true;
1032 }
1033 return expandLoadImm(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001034 case Mips::LoadAddr32Imm:
1035 return expandLoadAddressImm(Inst, IDLoc, Instructions);
1036 case Mips::LoadAddr32Reg:
1037 return expandLoadAddressReg(Inst, IDLoc, Instructions);
1038 }
Jack Carter30a59822012-10-04 04:03:53 +00001039}
Jack Carter92995f12012-10-06 00:53:28 +00001040
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001041namespace {
1042template <int Shift, bool PerformShift>
1043void createShiftOr(int64_t Value, unsigned RegNo, SMLoc IDLoc,
1044 SmallVectorImpl<MCInst> &Instructions) {
1045 MCInst tmpInst;
1046 if (PerformShift) {
1047 tmpInst.setOpcode(Mips::DSLL);
1048 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1049 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1050 tmpInst.addOperand(MCOperand::CreateImm(16));
1051 tmpInst.setLoc(IDLoc);
1052 Instructions.push_back(tmpInst);
1053 tmpInst.clear();
1054 }
1055 tmpInst.setOpcode(Mips::ORi);
1056 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1057 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1058 tmpInst.addOperand(
1059 MCOperand::CreateImm(((Value & (0xffffLL << Shift)) >> Shift)));
1060 tmpInst.setLoc(IDLoc);
1061 Instructions.push_back(tmpInst);
1062}
1063}
1064
Matheus Almeida3813d572014-06-19 14:39:14 +00001065bool MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001066 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +00001067 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +00001068 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +00001069 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +00001070 const MCOperand &RegOp = Inst.getOperand(0);
1071 assert(RegOp.isReg() && "expected register operand kind");
1072
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001073 int64_t ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +00001074 tmpInst.setLoc(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001075 // FIXME: gas has a special case for values that are 000...1111, which
1076 // becomes a li -1 and then a dsrl
Jack Carterd0bd6422013-04-18 00:41:53 +00001077 if (0 <= ImmValue && ImmValue <= 65535) {
1078 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +00001079 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001080 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +00001081 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001082 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001083 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001084 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001085 } else if (ImmValue < 0 && ImmValue >= -32768) {
1086 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +00001087 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001088 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +00001089 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001090 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001091 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001092 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001093 } else if ((ImmValue & 0xffffffff) == ImmValue) {
1094 // For any value of j that is representable as a 32-bit integer, create
1095 // a sequence of:
Jack Carter30a59822012-10-04 04:03:53 +00001096 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001097 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001098 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001099 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1100 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +00001101 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001102 createShiftOr<0, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1103 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001104 if (!isGP64bit()) {
1105 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001106 return true;
1107 }
1108
1109 // <------- lo32 ------>
1110 // <------- hi32 ------>
1111 // <- hi16 -> <- lo16 ->
1112 // _________________________________
1113 // | | | |
1114 // | 16-bytes | 16-bytes | 16-bytes |
1115 // |__________|__________|__________|
1116 //
1117 // For any value of j that is representable as a 48-bit integer, create
1118 // a sequence of:
1119 // li d,j => lui d,hi16(j)
1120 // ori d,d,hi16(lo32(j))
1121 // dsll d,d,16
1122 // ori d,d,lo16(lo32(j))
1123 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001124 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001125 tmpInst.addOperand(
1126 MCOperand::CreateImm((ImmValue & (0xffffLL << 32)) >> 32));
Jack Carter30a59822012-10-04 04:03:53 +00001127 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001128 createShiftOr<16, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1129 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1130 } else {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001131 if (!isGP64bit()) {
1132 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001133 return true;
1134 }
1135
1136 // <------- hi32 ------> <------- lo32 ------>
1137 // <- hi16 -> <- lo16 ->
1138 // ___________________________________________
1139 // | | | | |
1140 // | 16-bytes | 16-bytes | 16-bytes | 16-bytes |
1141 // |__________|__________|__________|__________|
1142 //
1143 // For any value of j that isn't representable as a 48-bit integer.
1144 // li d,j => lui d,hi16(j)
1145 // ori d,d,lo16(hi32(j))
1146 // dsll d,d,16
1147 // ori d,d,hi16(lo32(j))
1148 // dsll d,d,16
1149 // ori d,d,lo16(lo32(j))
1150 tmpInst.setOpcode(Mips::LUi);
1151 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1152 tmpInst.addOperand(
1153 MCOperand::CreateImm((ImmValue & (0xffffLL << 48)) >> 48));
1154 Instructions.push_back(tmpInst);
1155 createShiftOr<32, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1156 createShiftOr<16, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1157 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
Jack Carter30a59822012-10-04 04:03:53 +00001158 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001159 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001160}
Jack Carter92995f12012-10-06 00:53:28 +00001161
Matheus Almeida3813d572014-06-19 14:39:14 +00001162bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001163MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
1164 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001165 MCInst tmpInst;
1166 const MCOperand &ImmOp = Inst.getOperand(2);
1167 assert(ImmOp.isImm() && "expected immediate operand kind");
1168 const MCOperand &SrcRegOp = Inst.getOperand(1);
1169 assert(SrcRegOp.isReg() && "expected register operand kind");
1170 const MCOperand &DstRegOp = Inst.getOperand(0);
1171 assert(DstRegOp.isReg() && "expected register operand kind");
1172 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001173 if (-32768 <= ImmValue && ImmValue <= 65535) {
1174 // For -32768 <= j <= 65535.
1175 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +00001176 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +00001177 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1178 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1179 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1180 Instructions.push_back(tmpInst);
1181 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001182 // For any other value of j that is representable as a 32-bit integer.
1183 // la d,j(s) => lui d,hi16(j)
1184 // ori d,d,lo16(j)
1185 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +00001186 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001187 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1188 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1189 Instructions.push_back(tmpInst);
1190 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001191 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001192 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1193 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1194 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1195 Instructions.push_back(tmpInst);
1196 tmpInst.clear();
1197 tmpInst.setOpcode(Mips::ADDu);
1198 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1199 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1200 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1201 Instructions.push_back(tmpInst);
1202 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001203 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001204}
1205
Matheus Almeida3813d572014-06-19 14:39:14 +00001206bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001207MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1208 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001209 MCInst tmpInst;
1210 const MCOperand &ImmOp = Inst.getOperand(1);
1211 assert(ImmOp.isImm() && "expected immediate operand kind");
1212 const MCOperand &RegOp = Inst.getOperand(0);
1213 assert(RegOp.isReg() && "expected register operand kind");
1214 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001215 if (-32768 <= ImmValue && ImmValue <= 65535) {
1216 // For -32768 <= j <= 65535.
1217 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +00001218 tmpInst.setOpcode(Mips::ADDiu);
1219 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001220 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +00001221 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1222 Instructions.push_back(tmpInst);
1223 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001224 // For any other value of j that is representable as a 32-bit integer.
1225 // la d,j => lui d,hi16(j)
1226 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001227 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001228 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1229 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1230 Instructions.push_back(tmpInst);
1231 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001232 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001233 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1234 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1235 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1236 Instructions.push_back(tmpInst);
1237 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001238 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001239}
1240
Jack Carter9e65aa32013-03-22 00:05:30 +00001241void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001242 SmallVectorImpl<MCInst> &Instructions,
1243 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001244 const MCSymbolRefExpr *SR;
1245 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00001246 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00001247 const MCExpr *ExprOffset;
1248 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00001249 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001250 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1251 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001252 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001253 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1254 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001255 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00001256 if (isImmOpnd) {
1257 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
1258 ImmOffset = Inst.getOperand(2).getImm();
1259 LoOffset = ImmOffset & 0x0000ffff;
1260 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00001261 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00001262 if (LoOffset & 0x8000)
1263 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00001264 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001265 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001266 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00001267 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00001268 // These are some of the types of expansions we perform here:
1269 // 1) lw $8, sym => lui $8, %hi(sym)
1270 // lw $8, %lo(sym)($8)
1271 // 2) lw $8, offset($9) => lui $8, %hi(offset)
1272 // add $8, $8, $9
1273 // lw $8, %lo(offset)($9)
1274 // 3) lw $8, offset($8) => lui $at, %hi(offset)
1275 // add $at, $at, $8
1276 // lw $8, %lo(offset)($at)
1277 // 4) sw $8, sym => lui $at, %hi(sym)
1278 // sw $8, %lo(sym)($at)
1279 // 5) sw $8, offset($8) => lui $at, %hi(offset)
1280 // add $at, $at, $8
1281 // sw $8, %lo(offset)($at)
1282 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
1283 // ldc1 $f0, %lo(sym)($at)
1284 //
1285 // For load instructions we can use the destination register as a temporary
1286 // if base and dst are different (examples 1 and 2) and if the base register
1287 // is general purpose otherwise we must use $at (example 6) and error if it's
1288 // not available. For stores we must use $at (examples 4 and 5) because we
1289 // must not clobber the source register setting up the offset.
1290 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
1291 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
1292 unsigned RegClassIDOp0 =
1293 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
1294 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
1295 (RegClassIDOp0 == Mips::GPR64RegClassID);
1296 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00001297 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00001298 else {
1299 int AT = getATReg(IDLoc);
1300 // At this point we need AT to perform the expansions and we exit if it is
1301 // not available.
1302 if (!AT)
1303 return;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001304 TmpRegNum = getReg(
1305 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, AT);
Matheus Almeida7de68e72014-06-18 14:46:05 +00001306 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00001307
Jack Carter9e65aa32013-03-22 00:05:30 +00001308 TempInst.setOpcode(Mips::LUi);
1309 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1310 if (isImmOpnd)
1311 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
1312 else {
1313 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001314 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00001315 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
1316 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
1317 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001318 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001319 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001320 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00001321 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001322 }
1323 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001324 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00001325 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001326 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00001327 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00001328 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001329 TempInst.setOpcode(Mips::ADDu);
1330 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1331 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1332 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
1333 Instructions.push_back(TempInst);
1334 TempInst.clear();
Alp Tokercb402912014-01-24 17:20:08 +00001335 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00001336 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001337 TempInst.setOpcode(Inst.getOpcode());
1338 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
1339 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1340 if (isImmOpnd)
1341 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
1342 else {
1343 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001344 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
1345 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
1346 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001347 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001348 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001349 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00001350 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001351 }
1352 }
1353 Instructions.push_back(TempInst);
1354 TempInst.clear();
1355}
1356
Matheus Almeida595fcab2014-06-11 15:05:56 +00001357unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1358 // As described by the Mips32r2 spec, the registers Rd and Rs for
1359 // jalr.hb must be different.
1360 unsigned Opcode = Inst.getOpcode();
1361
1362 if (Opcode == Mips::JALR_HB &&
1363 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
1364 return Match_RequiresDifferentSrcAndDst;
1365
1366 return Match_Success;
1367}
1368
David Blaikie960ea3f2014-06-08 16:18:35 +00001369bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1370 OperandVector &Operands,
1371 MCStreamer &Out,
1372 unsigned &ErrorInfo,
1373 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00001374
Jack Carterb4dbc172012-09-05 23:34:03 +00001375 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00001376 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00001377 unsigned MatchResult =
1378 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00001379
1380 switch (MatchResult) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001381 default:
1382 break;
Jack Carterb4dbc172012-09-05 23:34:03 +00001383 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001384 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00001385 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001386 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00001387 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00001388 return false;
1389 }
1390 case Match_MissingFeature:
1391 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1392 return true;
1393 case Match_InvalidOperand: {
1394 SMLoc ErrorLoc = IDLoc;
1395 if (ErrorInfo != ~0U) {
1396 if (ErrorInfo >= Operands.size())
1397 return Error(IDLoc, "too few operands for instruction");
1398
David Blaikie960ea3f2014-06-08 16:18:35 +00001399 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001400 if (ErrorLoc == SMLoc())
1401 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00001402 }
1403
1404 return Error(ErrorLoc, "invalid operand for instruction");
1405 }
1406 case Match_MnemonicFail:
1407 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00001408 case Match_RequiresDifferentSrcAndDst:
1409 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00001410 }
Rafael Espindola870c4e92012-01-11 03:56:41 +00001411 return true;
1412}
1413
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001414void MipsAsmParser::WarnIfAssemblerTemporary(int RegIndex, SMLoc Loc) {
1415 if ((RegIndex != 0) && ((int)Options.getATRegNum() == RegIndex)) {
1416 if (RegIndex == 1)
1417 Warning(Loc, "Used $at without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001418 else
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001419 Warning(Loc, Twine("Used $") + Twine(RegIndex) + " with \".set at=$" +
1420 Twine(RegIndex) + "\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001421 }
1422}
1423
Jack Carter1ac53222013-02-20 23:11:17 +00001424int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001425 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00001426
Vladimir Medic4c299852013-11-06 11:27:05 +00001427 CC = StringSwitch<unsigned>(Name)
1428 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001429 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00001430 .Case("a0", 4)
1431 .Case("a1", 5)
1432 .Case("a2", 6)
1433 .Case("a3", 7)
1434 .Case("v0", 2)
1435 .Case("v1", 3)
1436 .Case("s0", 16)
1437 .Case("s1", 17)
1438 .Case("s2", 18)
1439 .Case("s3", 19)
1440 .Case("s4", 20)
1441 .Case("s5", 21)
1442 .Case("s6", 22)
1443 .Case("s7", 23)
1444 .Case("k0", 26)
1445 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001446 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00001447 .Case("sp", 29)
1448 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001449 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00001450 .Case("ra", 31)
1451 .Case("t0", 8)
1452 .Case("t1", 9)
1453 .Case("t2", 10)
1454 .Case("t3", 11)
1455 .Case("t4", 12)
1456 .Case("t5", 13)
1457 .Case("t6", 14)
1458 .Case("t7", 15)
1459 .Case("t8", 24)
1460 .Case("t9", 25)
1461 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00001462
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001463 if (isABI_N32() || isABI_N64()) {
Daniel Sandersa4b0c742014-03-26 11:39:07 +00001464 // Although SGI documentation just cuts out t0-t3 for n32/n64,
1465 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
1466 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
1467 if (8 <= CC && CC <= 11)
1468 CC += 4;
Jack Carter1ac53222013-02-20 23:11:17 +00001469
Daniel Sandersa4b0c742014-03-26 11:39:07 +00001470 if (CC == -1)
1471 CC = StringSwitch<unsigned>(Name)
1472 .Case("a4", 8)
1473 .Case("a5", 9)
1474 .Case("a6", 10)
1475 .Case("a7", 11)
1476 .Case("kt0", 26)
1477 .Case("kt1", 27)
1478 .Default(-1);
1479 }
Jack Carter1ac53222013-02-20 23:11:17 +00001480
1481 return CC;
1482}
Jack Carterd0bd6422013-04-18 00:41:53 +00001483
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001484int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001485
Jack Cartera63b16a2012-09-07 00:23:42 +00001486 if (Name[0] == 'f') {
1487 StringRef NumString = Name.substr(1);
1488 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001489 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001490 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001491 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00001492 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001493 return IntVal;
1494 }
1495 return -1;
1496}
Jack Cartera63b16a2012-09-07 00:23:42 +00001497
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001498int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
1499
1500 if (Name.startswith("fcc")) {
1501 StringRef NumString = Name.substr(3);
1502 unsigned IntVal;
1503 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001504 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001505 if (IntVal > 7) // There are only 8 fcc registers.
1506 return -1;
1507 return IntVal;
1508 }
1509 return -1;
1510}
1511
1512int MipsAsmParser::matchACRegisterName(StringRef Name) {
1513
Akira Hatanaka274d24c2013-08-14 01:15:52 +00001514 if (Name.startswith("ac")) {
1515 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001516 unsigned IntVal;
1517 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001518 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001519 if (IntVal > 3) // There are only 3 acc registers.
1520 return -1;
1521 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00001522 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001523 return -1;
1524}
Jack Carterd0bd6422013-04-18 00:41:53 +00001525
Jack Carter5dc8ac92013-09-25 23:50:44 +00001526int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
1527 unsigned IntVal;
1528
1529 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
1530 return -1;
1531
1532 if (IntVal > 31)
1533 return -1;
1534
1535 return IntVal;
1536}
1537
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001538int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
1539 int CC;
1540
1541 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00001542 .Case("msair", 0)
1543 .Case("msacsr", 1)
1544 .Case("msaaccess", 2)
1545 .Case("msasave", 3)
1546 .Case("msamodify", 4)
1547 .Case("msarequest", 5)
1548 .Case("msamap", 6)
1549 .Case("msaunmap", 7)
1550 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001551
1552 return CC;
1553}
1554
Jack Carter0b744b32012-10-04 02:29:46 +00001555bool MipsAssemblerOptions::setATReg(unsigned Reg) {
1556 if (Reg > 31)
1557 return false;
1558
1559 aTReg = Reg;
1560 return true;
1561}
1562
Matheus Almeida7de68e72014-06-18 14:46:05 +00001563int MipsAsmParser::getATReg(SMLoc Loc) {
Daniel Sandersd89b1362014-03-24 16:48:01 +00001564 int AT = Options.getATRegNum();
1565 if (AT == 0)
Matheus Almeida7de68e72014-06-18 14:46:05 +00001566 reportParseError(Loc,
1567 "Pseudo instruction requires $at, which is not available");
Daniel Sandersd89b1362014-03-24 16:48:01 +00001568 return AT;
1569}
Jack Carter0b744b32012-10-04 02:29:46 +00001570
Jack Carterd0bd6422013-04-18 00:41:53 +00001571unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00001572 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00001573}
1574
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001575unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001576 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00001577 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001578}
1579
Jack Carter873c7242013-01-12 01:03:14 +00001580int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001581 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00001582 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00001583 return -1;
1584
Jack Carter873c7242013-01-12 01:03:14 +00001585 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00001586}
1587
David Blaikie960ea3f2014-06-08 16:18:35 +00001588bool MipsAsmParser::ParseOperand(OperandVector &Operands, StringRef Mnemonic) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001589 DEBUG(dbgs() << "ParseOperand\n");
1590
Jack Carter30a59822012-10-04 04:03:53 +00001591 // Check if the current operand has a custom associated parser, if so, try to
1592 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00001593 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
1594 if (ResTy == MatchOperand_Success)
1595 return false;
1596 // If there wasn't a custom match, try the generic matcher below. Otherwise,
1597 // there was a match, but an error occurred, in which case, just return that
1598 // the operand parsing failed.
1599 if (ResTy == MatchOperand_ParseFail)
1600 return true;
1601
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001602 DEBUG(dbgs() << ".. Generic Parser\n");
1603
Jack Carterb4dbc172012-09-05 23:34:03 +00001604 switch (getLexer().getKind()) {
1605 default:
1606 Error(Parser.getTok().getLoc(), "unexpected token in operand");
1607 return true;
1608 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001609 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00001610 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00001611
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001612 // Almost all registers have been parsed by custom parsers. There is only
1613 // one exception to this. $zero (and it's alias $0) will reach this point
1614 // for div, divu, and similar instructions because it is not an operand
1615 // to the instruction definition but an explicit register. Special case
1616 // this situation for now.
1617 if (ParseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00001618 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001619
Jack Carterd0bd6422013-04-18 00:41:53 +00001620 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00001621 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001622 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00001623 return true;
1624
Jack Carter873c7242013-01-12 01:03:14 +00001625 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00001626 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00001627 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00001628 const MCExpr *Res =
1629 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00001630
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001631 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00001632 return false;
1633 }
Vladimir Medic4c299852013-11-06 11:27:05 +00001634 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00001635 case AsmToken::LParen:
1636 case AsmToken::Minus:
1637 case AsmToken::Plus:
1638 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00001639 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00001640 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001641 DEBUG(dbgs() << ".. generic integer\n");
1642 OperandMatchResultTy ResTy = ParseImm(Operands);
1643 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00001644 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00001645 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001646 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001647 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001648 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00001649 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00001650 return true;
1651
Jack Carter873c7242013-01-12 01:03:14 +00001652 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1653
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001654 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001655 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001656 } // case AsmToken::Percent
1657 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00001658 return true;
1659}
1660
Vladimir Medic4c299852013-11-06 11:27:05 +00001661const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00001662 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00001663 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00001664 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001665 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00001666 // It's a constant, evaluate reloc value.
1667 int16_t Val;
1668 switch (getVariantKind(RelocStr)) {
1669 case MCSymbolRefExpr::VK_Mips_ABS_LO:
1670 // Get the 1st 16-bits.
1671 Val = MCE->getValue() & 0xffff;
1672 break;
1673 case MCSymbolRefExpr::VK_Mips_ABS_HI:
1674 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
1675 // 16 bits being negative.
1676 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
1677 break;
1678 case MCSymbolRefExpr::VK_Mips_HIGHER:
1679 // Get the 3rd 16-bits.
1680 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
1681 break;
1682 case MCSymbolRefExpr::VK_Mips_HIGHEST:
1683 // Get the 4th 16-bits.
1684 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
1685 break;
1686 default:
1687 report_fatal_error("Unsupported reloc value!");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001688 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00001689 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00001690 }
1691
Jack Carterb5cf5902013-04-17 00:18:04 +00001692 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001693 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00001694 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00001695 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00001696 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001697 return Res;
1698 }
1699
1700 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00001701 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
1702
Sasa Stankovic06c47802014-04-03 10:37:45 +00001703 // Try to create target expression.
1704 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
1705 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00001706
Jack Carterd0bd6422013-04-18 00:41:53 +00001707 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
1708 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00001709 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
1710 return Res;
1711 }
1712
1713 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001714 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
1715 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
1716 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00001717 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001718 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001719 return Expr;
1720}
1721
1722bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
1723
1724 switch (Expr->getKind()) {
1725 case MCExpr::Constant:
1726 return true;
1727 case MCExpr::SymbolRef:
1728 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
1729 case MCExpr::Binary:
1730 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
1731 if (!isEvaluated(BE->getLHS()))
1732 return false;
1733 return isEvaluated(BE->getRHS());
1734 }
1735 case MCExpr::Unary:
1736 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00001737 case MCExpr::Target:
1738 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001739 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001740 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00001741}
Jack Carterd0bd6422013-04-18 00:41:53 +00001742
Jack Carterb5cf5902013-04-17 00:18:04 +00001743bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001744 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00001745 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00001746 if (Tok.isNot(AsmToken::Identifier))
1747 return true;
1748
1749 std::string Str = Tok.getIdentifier().str();
1750
Jack Carterd0bd6422013-04-18 00:41:53 +00001751 Parser.Lex(); // Eat the identifier.
1752 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001753 const MCExpr *IdVal;
1754 SMLoc EndLoc;
1755
1756 if (getLexer().getKind() == AsmToken::LParen) {
1757 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001758 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001759 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001760 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001761 const AsmToken &nextTok = Parser.getTok();
1762 if (nextTok.isNot(AsmToken::Identifier))
1763 return true;
1764 Str += "(%";
1765 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00001766 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00001767 if (getLexer().getKind() != AsmToken::LParen)
1768 return true;
1769 } else
1770 break;
1771 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001772 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00001773 return true;
1774
1775 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00001776 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001777
1778 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00001779 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001780
Jack Carterd0bd6422013-04-18 00:41:53 +00001781 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00001782 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001783}
1784
Jack Carterb4dbc172012-09-05 23:34:03 +00001785bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1786 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001787 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001788 OperandMatchResultTy ResTy = ParseAnyRegister(Operands);
1789 if (ResTy == MatchOperand_Success) {
1790 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00001791 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001792 StartLoc = Operand.getStartLoc();
1793 EndLoc = Operand.getEndLoc();
1794
1795 // AFAIK, we only support numeric registers and named GPR's in CFI
1796 // directives.
1797 // Don't worry about eating tokens before failing. Using an unrecognised
1798 // register is a parse error.
1799 if (Operand.isGPRAsmReg()) {
1800 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001801 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001802 }
1803
1804 return (RegNo == (unsigned)-1);
1805 }
1806
1807 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00001808 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00001809}
1810
Jack Carterb5cf5902013-04-17 00:18:04 +00001811bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00001812 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001813 bool Result = true;
1814
1815 while (getLexer().getKind() == AsmToken::LParen)
1816 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00001817
Jack Carterd0bd6422013-04-18 00:41:53 +00001818 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001819 default:
1820 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00001821 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00001822 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00001823 case AsmToken::Integer:
1824 case AsmToken::Minus:
1825 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00001826 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00001827 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00001828 else
1829 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00001830 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00001831 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001832 break;
Jack Carter873c7242013-01-12 01:03:14 +00001833 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00001834 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00001835 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001836 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001837}
1838
David Blaikie960ea3f2014-06-08 16:18:35 +00001839MipsAsmParser::OperandMatchResultTy
1840MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001841 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00001842 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00001843 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001844 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001845 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00001846 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00001847 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001848
Jack Carterb5cf5902013-04-17 00:18:04 +00001849 if (getLexer().getKind() == AsmToken::LParen) {
1850 Parser.Lex();
1851 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001852 }
1853
Jack Carterb5cf5902013-04-17 00:18:04 +00001854 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001855 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00001856 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001857
Jack Carterd0bd6422013-04-18 00:41:53 +00001858 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001859 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001860 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
1861 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00001862 SMLoc E =
1863 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001864 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00001865 return MatchOperand_Success;
1866 }
1867 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001868 SMLoc E =
1869 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00001870
Jack Carterd0bd6422013-04-18 00:41:53 +00001871 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001872 // "Base" will be managed by k_Memory.
David Blaikie960ea3f2014-06-08 16:18:35 +00001873 auto Base = MipsOperand::CreateGPRReg(0, getContext().getRegisterInfo(),
1874 S, E, *this);
1875 Operands.push_back(
1876 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00001877 return MatchOperand_Success;
1878 }
1879 Error(Parser.getTok().getLoc(), "'(' expected");
1880 return MatchOperand_ParseFail;
1881 }
1882
Jack Carterd0bd6422013-04-18 00:41:53 +00001883 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001884 }
1885
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001886 Res = ParseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001887 if (Res != MatchOperand_Success)
1888 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001889
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001890 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001891 Error(Parser.getTok().getLoc(), "')' expected");
1892 return MatchOperand_ParseFail;
1893 }
1894
Jack Carter873c7242013-01-12 01:03:14 +00001895 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1896
Jack Carterd0bd6422013-04-18 00:41:53 +00001897 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001898
Craig Topper062a2ba2014-04-25 05:30:21 +00001899 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00001900 IdVal = MCConstantExpr::Create(0, getContext());
1901
Jack Carterd0bd6422013-04-18 00:41:53 +00001902 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00001903 std::unique_ptr<MipsOperand> op(
1904 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001905 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001906 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001907 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00001908 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001909 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
1910 int64_t Imm;
1911 if (IdVal->EvaluateAsAbsolute(Imm))
1912 IdVal = MCConstantExpr::Create(Imm, getContext());
1913 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
1914 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
1915 getContext());
1916 }
1917
David Blaikie960ea3f2014-06-08 16:18:35 +00001918 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00001919 return MatchOperand_Success;
1920}
1921
David Blaikie960ea3f2014-06-08 16:18:35 +00001922bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Daniel Sanderse34a1202014-03-31 18:51:43 +00001923
Jack Carterd76b2372013-03-21 21:44:16 +00001924 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
1925 if (Sym) {
1926 SMLoc S = Parser.getTok().getLoc();
1927 const MCExpr *Expr;
1928 if (Sym->isVariable())
1929 Expr = Sym->getVariableValue();
1930 else
1931 return false;
1932 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001933 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carterd76b2372013-03-21 21:44:16 +00001934 const StringRef DefSymbol = Ref->getSymbol().getName();
1935 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001936 OperandMatchResultTy ResTy =
1937 MatchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00001938 if (ResTy == MatchOperand_Success) {
1939 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00001940 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00001941 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001942 llvm_unreachable("Should never ParseFail");
1943 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00001944 }
1945 } else if (Expr->getKind() == MCExpr::Constant) {
1946 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00001947 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00001948 Operands.push_back(
1949 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00001950 return true;
1951 }
1952 }
1953 return false;
1954}
Jack Carterd0bd6422013-04-18 00:41:53 +00001955
Jack Carter873c7242013-01-12 01:03:14 +00001956MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00001957MipsAsmParser::MatchAnyRegisterNameWithoutDollar(OperandVector &Operands,
1958 StringRef Identifier,
1959 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001960 int Index = matchCPURegisterName(Identifier);
1961 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001962 Operands.push_back(MipsOperand::CreateGPRReg(
1963 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1964 return MatchOperand_Success;
1965 }
1966
1967 Index = matchFPURegisterName(Identifier);
1968 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001969 Operands.push_back(MipsOperand::CreateFGRReg(
1970 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1971 return MatchOperand_Success;
1972 }
1973
1974 Index = matchFCCRegisterName(Identifier);
1975 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001976 Operands.push_back(MipsOperand::CreateFCCReg(
1977 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1978 return MatchOperand_Success;
1979 }
1980
1981 Index = matchACRegisterName(Identifier);
1982 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001983 Operands.push_back(MipsOperand::CreateACCReg(
1984 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1985 return MatchOperand_Success;
1986 }
1987
1988 Index = matchMSA128RegisterName(Identifier);
1989 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001990 Operands.push_back(MipsOperand::CreateMSA128Reg(
1991 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1992 return MatchOperand_Success;
1993 }
1994
1995 Index = matchMSA128CtrlRegisterName(Identifier);
1996 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001997 Operands.push_back(MipsOperand::CreateMSACtrlReg(
1998 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1999 return MatchOperand_Success;
2000 }
2001
2002 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00002003}
2004
2005MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002006MipsAsmParser::MatchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Daniel Sanders315386c2014-04-01 10:40:14 +00002007 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002008
2009 if (Token.is(AsmToken::Identifier)) {
2010 DEBUG(dbgs() << ".. identifier\n");
2011 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00002012 OperandMatchResultTy ResTy =
2013 MatchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00002014 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002015 } else if (Token.is(AsmToken::Integer)) {
2016 DEBUG(dbgs() << ".. integer\n");
2017 Operands.push_back(MipsOperand::CreateNumericReg(
2018 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
2019 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002020 return MatchOperand_Success;
2021 }
2022
2023 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
2024
2025 return MatchOperand_NoMatch;
2026}
2027
David Blaikie960ea3f2014-06-08 16:18:35 +00002028MipsAsmParser::OperandMatchResultTy
2029MipsAsmParser::ParseAnyRegister(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002030 DEBUG(dbgs() << "ParseAnyRegister\n");
2031
2032 auto Token = Parser.getTok();
2033
2034 SMLoc S = Token.getLoc();
2035
2036 if (Token.isNot(AsmToken::Dollar)) {
2037 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
2038 if (Token.is(AsmToken::Identifier)) {
2039 if (searchSymbolAlias(Operands))
2040 return MatchOperand_Success;
2041 }
2042 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
2043 return MatchOperand_NoMatch;
2044 }
2045 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002046
Daniel Sanders21bce302014-04-01 12:35:23 +00002047 OperandMatchResultTy ResTy = MatchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00002048 if (ResTy == MatchOperand_Success) {
2049 Parser.Lex(); // $
2050 Parser.Lex(); // identifier
2051 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002052 return ResTy;
2053}
2054
2055MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002056MipsAsmParser::ParseImm(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002057 switch (getLexer().getKind()) {
2058 default:
2059 return MatchOperand_NoMatch;
2060 case AsmToken::LParen:
2061 case AsmToken::Minus:
2062 case AsmToken::Plus:
2063 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002064 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002065 case AsmToken::String:
2066 break;
2067 }
2068
2069 const MCExpr *IdVal;
2070 SMLoc S = Parser.getTok().getLoc();
2071 if (getParser().parseExpression(IdVal))
2072 return MatchOperand_ParseFail;
2073
2074 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2075 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
2076 return MatchOperand_Success;
2077}
2078
David Blaikie960ea3f2014-06-08 16:18:35 +00002079MipsAsmParser::OperandMatchResultTy
2080MipsAsmParser::ParseJumpTarget(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002081 DEBUG(dbgs() << "ParseJumpTarget\n");
2082
2083 SMLoc S = getLexer().getLoc();
2084
2085 // Integers and expressions are acceptable
2086 OperandMatchResultTy ResTy = ParseImm(Operands);
2087 if (ResTy != MatchOperand_NoMatch)
2088 return ResTy;
2089
Daniel Sanders315386c2014-04-01 10:40:14 +00002090 // Registers are a valid target and have priority over symbols.
2091 ResTy = ParseAnyRegister(Operands);
2092 if (ResTy != MatchOperand_NoMatch)
2093 return ResTy;
2094
Daniel Sandersffd84362014-04-01 10:41:48 +00002095 const MCExpr *Expr = nullptr;
2096 if (Parser.parseExpression(Expr)) {
2097 // We have no way of knowing if a symbol was consumed so we must ParseFail
2098 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002099 }
Daniel Sandersffd84362014-04-01 10:41:48 +00002100 Operands.push_back(
2101 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002102 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00002103}
2104
Vladimir Medic2b953d02013-10-01 09:48:56 +00002105MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002106MipsAsmParser::parseInvNum(OperandVector &Operands) {
Vladimir Medic2b953d02013-10-01 09:48:56 +00002107 const MCExpr *IdVal;
2108 // If the first token is '$' we may have register operand.
2109 if (Parser.getTok().is(AsmToken::Dollar))
2110 return MatchOperand_NoMatch;
2111 SMLoc S = Parser.getTok().getLoc();
2112 if (getParser().parseExpression(IdVal))
2113 return MatchOperand_ParseFail;
2114 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00002115 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00002116 int64_t Val = MCE->getValue();
2117 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2118 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002119 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00002120 return MatchOperand_Success;
2121}
2122
Matheus Almeida779c5932013-11-18 12:32:49 +00002123MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002124MipsAsmParser::ParseLSAImm(OperandVector &Operands) {
Matheus Almeida779c5932013-11-18 12:32:49 +00002125 switch (getLexer().getKind()) {
2126 default:
2127 return MatchOperand_NoMatch;
2128 case AsmToken::LParen:
2129 case AsmToken::Plus:
2130 case AsmToken::Minus:
2131 case AsmToken::Integer:
2132 break;
2133 }
2134
2135 const MCExpr *Expr;
2136 SMLoc S = Parser.getTok().getLoc();
2137
2138 if (getParser().parseExpression(Expr))
2139 return MatchOperand_ParseFail;
2140
2141 int64_t Val;
2142 if (!Expr->EvaluateAsAbsolute(Val)) {
2143 Error(S, "expected immediate value");
2144 return MatchOperand_ParseFail;
2145 }
2146
2147 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
2148 // and because the CPU always adds one to the immediate field, the allowed
2149 // range becomes 1..4. We'll only check the range here and will deal
2150 // with the addition/subtraction when actually decoding/encoding
2151 // the instruction.
2152 if (Val < 1 || Val > 4) {
2153 Error(S, "immediate not in range (1..4)");
2154 return MatchOperand_ParseFail;
2155 }
2156
Jack Carter3b2c96e2014-01-22 23:31:38 +00002157 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002158 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00002159 return MatchOperand_Success;
2160}
2161
Jack Carterdc1e35d2012-09-06 20:00:02 +00002162MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
2163
Vladimir Medic4c299852013-11-06 11:27:05 +00002164 MCSymbolRefExpr::VariantKind VK =
2165 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
2166 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
2167 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
2168 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
2169 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
2170 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
2171 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
2172 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
2173 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
2174 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
2175 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
2176 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
2177 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
2178 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
2179 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
2180 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
2181 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
2182 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00002183 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
2184 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
2185 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
2186 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
2187 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
2188 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00002189 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
2190 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00002191 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002192
Matheus Almeida2852af82014-04-22 10:15:54 +00002193 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00002194
Jack Carterdc1e35d2012-09-06 20:00:02 +00002195 return VK;
2196}
Jack Cartera63b16a2012-09-07 00:23:42 +00002197
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002198/// Sometimes (i.e. load/stores) the operand may be followed immediately by
2199/// either this.
2200/// ::= '(', register, ')'
2201/// handle it before we iterate so we don't get tripped up by the lack of
2202/// a comma.
David Blaikie960ea3f2014-06-08 16:18:35 +00002203bool MipsAsmParser::ParseParenSuffix(StringRef Name, OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002204 if (getLexer().is(AsmToken::LParen)) {
2205 Operands.push_back(
2206 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
2207 Parser.Lex();
2208 if (ParseOperand(Operands, Name)) {
2209 SMLoc Loc = getLexer().getLoc();
2210 Parser.eatToEndOfStatement();
2211 return Error(Loc, "unexpected token in argument list");
2212 }
2213 if (Parser.getTok().isNot(AsmToken::RParen)) {
2214 SMLoc Loc = getLexer().getLoc();
2215 Parser.eatToEndOfStatement();
2216 return Error(Loc, "unexpected token, expected ')'");
2217 }
2218 Operands.push_back(
2219 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
2220 Parser.Lex();
2221 }
2222 return false;
2223}
2224
2225/// Sometimes (i.e. in MSA) the operand may be followed immediately by
2226/// either one of these.
2227/// ::= '[', register, ']'
2228/// ::= '[', integer, ']'
2229/// handle it before we iterate so we don't get tripped up by the lack of
2230/// a comma.
David Blaikie960ea3f2014-06-08 16:18:35 +00002231bool MipsAsmParser::ParseBracketSuffix(StringRef Name,
2232 OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002233 if (getLexer().is(AsmToken::LBrac)) {
2234 Operands.push_back(
2235 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
2236 Parser.Lex();
2237 if (ParseOperand(Operands, Name)) {
2238 SMLoc Loc = getLexer().getLoc();
2239 Parser.eatToEndOfStatement();
2240 return Error(Loc, "unexpected token in argument list");
2241 }
2242 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2243 SMLoc Loc = getLexer().getLoc();
2244 Parser.eatToEndOfStatement();
2245 return Error(Loc, "unexpected token, expected ']'");
2246 }
2247 Operands.push_back(
2248 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
2249 Parser.Lex();
2250 }
2251 return false;
2252}
2253
David Blaikie960ea3f2014-06-08 16:18:35 +00002254bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
2255 SMLoc NameLoc, OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002256 DEBUG(dbgs() << "ParseInstruction\n");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002257 // We have reached first instruction, module directive after
2258 // this is forbidden.
2259 getTargetStreamer().setCanHaveModuleDir(false);
Vladimir Medic74593e62013-07-17 15:00:42 +00002260 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00002261 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00002262 Parser.eatToEndOfStatement();
2263 return Error(NameLoc, "Unknown instruction");
2264 }
Vladimir Medic64828a12013-07-16 10:07:14 +00002265 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002266 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002267
2268 // Read the remaining operands.
2269 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2270 // Read the first operand.
Vladimir Medic64828a12013-07-16 10:07:14 +00002271 if (ParseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002272 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002273 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002274 return Error(Loc, "unexpected token in argument list");
2275 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002276 if (getLexer().is(AsmToken::LBrac) && ParseBracketSuffix(Name, Operands))
2277 return true;
2278 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00002279
Jack Carterd0bd6422013-04-18 00:41:53 +00002280 while (getLexer().is(AsmToken::Comma)) {
2281 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00002282 // Parse and remember the operand.
2283 if (ParseOperand(Operands, Name)) {
2284 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002285 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002286 return Error(Loc, "unexpected token in argument list");
2287 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002288 // Parse bracket and parenthesis suffixes before we iterate
2289 if (getLexer().is(AsmToken::LBrac)) {
2290 if (ParseBracketSuffix(Name, Operands))
2291 return true;
2292 } else if (getLexer().is(AsmToken::LParen) &&
2293 ParseParenSuffix(Name, Operands))
2294 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00002295 }
2296 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002297 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2298 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002299 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002300 return Error(Loc, "unexpected token in argument list");
2301 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002302 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00002303 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00002304}
2305
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002306bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002307 SMLoc Loc = getLexer().getLoc();
2308 Parser.eatToEndOfStatement();
2309 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00002310}
2311
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002312bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002313 return Error(Loc, ErrorMsg);
2314}
2315
Jack Carter0b744b32012-10-04 02:29:46 +00002316bool MipsAsmParser::parseSetNoAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002317 // Line should look like: ".set noat".
2318 // set at reg to 0.
Jack Carter99d2afe2012-10-05 23:55:28 +00002319 Options.setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00002320 // eat noat
2321 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002322 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002323 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2324 reportParseError("unexpected token in statement");
2325 return false;
2326 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002327 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002328 return false;
2329}
Jack Carterd0bd6422013-04-18 00:41:53 +00002330
Jack Carter0b744b32012-10-04 02:29:46 +00002331bool MipsAsmParser::parseSetAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002332 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00002333 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00002334 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00002335 getParser().Lex();
2336 if (getLexer().is(AsmToken::EndOfStatement)) {
Jack Carter99d2afe2012-10-05 23:55:28 +00002337 Options.setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00002338 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002339 return false;
2340 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002341 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00002342 if (getLexer().isNot(AsmToken::Dollar)) {
2343 reportParseError("unexpected token in statement");
2344 return false;
2345 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002346 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00002347 const AsmToken &Reg = Parser.getTok();
2348 if (Reg.is(AsmToken::Identifier)) {
2349 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
2350 } else if (Reg.is(AsmToken::Integer)) {
2351 AtRegNo = Reg.getIntVal();
2352 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00002353 reportParseError("unexpected token in statement");
2354 return false;
2355 }
Jack Carter1ac53222013-02-20 23:11:17 +00002356
Daniel Sanders71a89d922014-03-25 13:01:06 +00002357 if (AtRegNo < 0 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00002358 reportParseError("unexpected token in statement");
2359 return false;
2360 }
2361
2362 if (!Options.setATReg(AtRegNo)) {
Jack Carter0b744b32012-10-04 02:29:46 +00002363 reportParseError("unexpected token in statement");
2364 return false;
2365 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002366 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00002367
2368 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2369 reportParseError("unexpected token in statement");
2370 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002371 }
2372 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002373 return false;
2374 } else {
2375 reportParseError("unexpected token in statement");
2376 return false;
2377 }
2378}
2379
2380bool MipsAsmParser::parseSetReorderDirective() {
2381 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002382 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002383 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2384 reportParseError("unexpected token in statement");
2385 return false;
2386 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002387 Options.setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00002388 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002389 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002390 return false;
2391}
2392
2393bool MipsAsmParser::parseSetNoReorderDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002394 Parser.Lex();
2395 // If this is not the end of the statement, report an error.
2396 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2397 reportParseError("unexpected token in statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002398 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002399 }
2400 Options.setNoreorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00002401 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002402 Parser.Lex(); // Consume the EndOfStatement.
2403 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002404}
2405
2406bool MipsAsmParser::parseSetMacroDirective() {
2407 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002408 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002409 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2410 reportParseError("unexpected token in statement");
2411 return false;
2412 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002413 Options.setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002414 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002415 return false;
2416}
2417
2418bool MipsAsmParser::parseSetNoMacroDirective() {
2419 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002420 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002421 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2422 reportParseError("`noreorder' must be set before `nomacro'");
2423 return false;
2424 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002425 if (Options.isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00002426 reportParseError("`noreorder' must be set before `nomacro'");
2427 return false;
2428 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002429 Options.setNomacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002430 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002431 return false;
2432}
Jack Carterd76b2372013-03-21 21:44:16 +00002433
Jack Carter39536722014-01-22 23:08:42 +00002434bool MipsAsmParser::parseSetNoMips16Directive() {
2435 Parser.Lex();
2436 // If this is not the end of the statement, report an error.
2437 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2438 reportParseError("unexpected token in statement");
2439 return false;
2440 }
2441 // For now do nothing.
2442 Parser.Lex(); // Consume the EndOfStatement.
2443 return false;
2444}
2445
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002446bool MipsAsmParser::parseSetFpDirective() {
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002447 Val_GNU_MIPS_ABI FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002448 // Line can be: .set fp=32
2449 // .set fp=xx
2450 // .set fp=64
2451 Parser.Lex(); // Eat fp token
2452 AsmToken Tok = Parser.getTok();
2453 if (Tok.isNot(AsmToken::Equal)) {
2454 reportParseError("unexpected token in statement");
2455 return false;
2456 }
2457 Parser.Lex(); // Eat '=' token.
2458 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002459
2460 if (!parseFpABIValue(FpAbiVal, ".set"))
2461 return false;
2462
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002463 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2464 reportParseError("unexpected token in statement");
2465 return false;
2466 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002467 getTargetStreamer().emitDirectiveSetFp(FpAbiVal, isABI_O32());
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002468 Parser.Lex(); // Consume the EndOfStatement.
2469 return false;
2470}
2471
Jack Carterd76b2372013-03-21 21:44:16 +00002472bool MipsAsmParser::parseSetAssignment() {
2473 StringRef Name;
2474 const MCExpr *Value;
2475
2476 if (Parser.parseIdentifier(Name))
2477 reportParseError("expected identifier after .set");
2478
2479 if (getLexer().isNot(AsmToken::Comma))
2480 return reportParseError("unexpected token in .set directive");
Jack Carterb5cf5902013-04-17 00:18:04 +00002481 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00002482
Jack Carter3b2c96e2014-01-22 23:31:38 +00002483 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00002484 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00002485
Jack Carterd0bd6422013-04-18 00:41:53 +00002486 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00002487 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00002488 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00002489 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00002490 Sym = getContext().GetOrCreateSymbol(Name);
2491 Sym->setVariableValue(Value);
2492
2493 return false;
2494}
Jack Carterd0bd6422013-04-18 00:41:53 +00002495
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002496bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
2497 Parser.Lex();
2498 if (getLexer().isNot(AsmToken::EndOfStatement))
2499 return reportParseError("unexpected token in .set directive");
2500
Matheus Almeida2852af82014-04-22 10:15:54 +00002501 switch (Feature) {
2502 default:
2503 llvm_unreachable("Unimplemented feature");
2504 case Mips::FeatureDSP:
2505 setFeatureBits(Mips::FeatureDSP, "dsp");
2506 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002507 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002508 case Mips::FeatureMicroMips:
2509 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002510 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002511 case Mips::FeatureMips16:
2512 getTargetStreamer().emitDirectiveSetMips16();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002513 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002514 case Mips::FeatureMips32r2:
2515 setFeatureBits(Mips::FeatureMips32r2, "mips32r2");
2516 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002517 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002518 case Mips::FeatureMips64:
2519 setFeatureBits(Mips::FeatureMips64, "mips64");
2520 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00002521 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002522 case Mips::FeatureMips64r2:
2523 setFeatureBits(Mips::FeatureMips64r2, "mips64r2");
2524 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00002525 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002526 }
2527 return false;
2528}
2529
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002530bool MipsAsmParser::eatComma(StringRef ErrorStr) {
2531 if (getLexer().isNot(AsmToken::Comma)) {
2532 SMLoc Loc = getLexer().getLoc();
2533 Parser.eatToEndOfStatement();
2534 return Error(Loc, ErrorStr);
2535 }
2536
Matheus Almeida2852af82014-04-22 10:15:54 +00002537 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002538 return true;
2539}
2540
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002541bool MipsAsmParser::parseDirectiveCPLoad(SMLoc Loc) {
2542 if (Options.isReorder())
2543 Warning(Loc, ".cpload in reorder section");
2544
2545 // FIXME: Warn if cpload is used in Mips16 mode.
2546
David Blaikie960ea3f2014-06-08 16:18:35 +00002547 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002548 OperandMatchResultTy ResTy = ParseAnyRegister(Reg);
2549 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
2550 reportParseError("expected register containing function address");
2551 return false;
2552 }
2553
David Blaikie960ea3f2014-06-08 16:18:35 +00002554 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
2555 if (!RegOpnd.isGPRAsmReg()) {
2556 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002557 return false;
2558 }
2559
David Blaikie960ea3f2014-06-08 16:18:35 +00002560 getTargetStreamer().emitDirectiveCpload(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002561 return false;
2562}
2563
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002564bool MipsAsmParser::parseDirectiveCPSetup() {
2565 unsigned FuncReg;
2566 unsigned Save;
2567 bool SaveIsReg = true;
2568
Matheus Almeida7e815762014-06-18 13:08:59 +00002569 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
2570 OperandMatchResultTy ResTy = ParseAnyRegister(TmpReg);
2571 if (ResTy == MatchOperand_NoMatch) {
2572 reportParseError("expected register containing function address");
2573 Parser.eatToEndOfStatement();
2574 return false;
2575 }
2576
2577 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
2578 if (!FuncRegOpnd.isGPRAsmReg()) {
2579 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
2580 Parser.eatToEndOfStatement();
2581 return false;
2582 }
2583
2584 FuncReg = FuncRegOpnd.getGPR32Reg();
2585 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002586
2587 if (!eatComma("expected comma parsing directive"))
2588 return true;
2589
Matheus Almeida7e815762014-06-18 13:08:59 +00002590 ResTy = ParseAnyRegister(TmpReg);
2591 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002592 const AsmToken &Tok = Parser.getTok();
2593 if (Tok.is(AsmToken::Integer)) {
2594 Save = Tok.getIntVal();
2595 SaveIsReg = false;
2596 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00002597 } else {
2598 reportParseError("expected save register or stack offset");
2599 Parser.eatToEndOfStatement();
2600 return false;
2601 }
2602 } else {
2603 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
2604 if (!SaveOpnd.isGPRAsmReg()) {
2605 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
2606 Parser.eatToEndOfStatement();
2607 return false;
2608 }
2609 Save = SaveOpnd.getGPR32Reg();
2610 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002611
2612 if (!eatComma("expected comma parsing directive"))
2613 return true;
2614
2615 StringRef Name;
2616 if (Parser.parseIdentifier(Name))
2617 reportParseError("expected identifier");
2618 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002619
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00002620 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, *Sym, SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002621 return false;
2622}
2623
Matheus Almeida0051f2d2014-04-16 15:48:55 +00002624bool MipsAsmParser::parseDirectiveNaN() {
2625 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2626 const AsmToken &Tok = Parser.getTok();
2627
2628 if (Tok.getString() == "2008") {
2629 Parser.Lex();
2630 getTargetStreamer().emitDirectiveNaN2008();
2631 return false;
2632 } else if (Tok.getString() == "legacy") {
2633 Parser.Lex();
2634 getTargetStreamer().emitDirectiveNaNLegacy();
2635 return false;
2636 }
2637 }
2638 // If we don't recognize the option passed to the .nan
2639 // directive (e.g. no option or unknown option), emit an error.
2640 reportParseError("invalid option in .nan directive");
2641 return false;
2642}
2643
Jack Carter0b744b32012-10-04 02:29:46 +00002644bool MipsAsmParser::parseDirectiveSet() {
2645
Jack Carterd0bd6422013-04-18 00:41:53 +00002646 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00002647 const AsmToken &Tok = Parser.getTok();
2648
2649 if (Tok.getString() == "noat") {
2650 return parseSetNoAtDirective();
2651 } else if (Tok.getString() == "at") {
2652 return parseSetAtDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002653 } else if (Tok.getString() == "fp") {
2654 return parseSetFpDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00002655 } else if (Tok.getString() == "reorder") {
2656 return parseSetReorderDirective();
2657 } else if (Tok.getString() == "noreorder") {
2658 return parseSetNoReorderDirective();
2659 } else if (Tok.getString() == "macro") {
2660 return parseSetMacroDirective();
2661 } else if (Tok.getString() == "nomacro") {
2662 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00002663 } else if (Tok.getString() == "mips16") {
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002664 return parseSetFeature(Mips::FeatureMips16);
Jack Carter0b744b32012-10-04 02:29:46 +00002665 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00002666 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00002667 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00002668 getTargetStreamer().emitDirectiveSetNoMicroMips();
2669 Parser.eatToEndOfStatement();
2670 return false;
2671 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002672 return parseSetFeature(Mips::FeatureMicroMips);
Vladimir Medic615b26e2014-03-04 09:54:09 +00002673 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002674 return parseSetFeature(Mips::FeatureMips32r2);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00002675 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002676 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00002677 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002678 return parseSetFeature(Mips::FeatureMips64r2);
Vladimir Medic27c398e2014-03-05 11:05:09 +00002679 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002680 return parseSetFeature(Mips::FeatureDSP);
Jack Carterd76b2372013-03-21 21:44:16 +00002681 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002682 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00002683 parseSetAssignment();
2684 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002685 }
Jack Carter07c818d2013-01-25 01:31:34 +00002686
Jack Carter0b744b32012-10-04 02:29:46 +00002687 return true;
2688}
2689
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002690/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00002691/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002692bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Jack Carter07c818d2013-01-25 01:31:34 +00002693 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2694 for (;;) {
2695 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002696 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00002697 return true;
2698
2699 getParser().getStreamer().EmitValue(Value, Size);
2700
2701 if (getLexer().is(AsmToken::EndOfStatement))
2702 break;
2703
2704 // FIXME: Improve diagnostic.
2705 if (getLexer().isNot(AsmToken::Comma))
2706 return Error(L, "unexpected token in directive");
2707 Parser.Lex();
2708 }
2709 }
2710
2711 Parser.Lex();
2712 return false;
2713}
2714
Vladimir Medic4c299852013-11-06 11:27:05 +00002715/// parseDirectiveGpWord
2716/// ::= .gpword local_sym
2717bool MipsAsmParser::parseDirectiveGpWord() {
2718 const MCExpr *Value;
2719 // EmitGPRel32Value requires an expression, so we are using base class
2720 // method to evaluate the expression.
2721 if (getParser().parseExpression(Value))
2722 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00002723 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00002724
Vladimir Medice10c1122013-11-13 13:18:04 +00002725 if (getLexer().isNot(AsmToken::EndOfStatement))
Vladimir Medic4c299852013-11-06 11:27:05 +00002726 return Error(getLexer().getLoc(), "unexpected token in directive");
Vladimir Medice10c1122013-11-13 13:18:04 +00002727 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00002728 return false;
2729}
2730
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002731/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00002732/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002733bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindolab59fb732014-03-28 18:50:26 +00002734 const MCExpr *Value;
2735 // EmitGPRel64Value requires an expression, so we are using base class
2736 // method to evaluate the expression.
2737 if (getParser().parseExpression(Value))
2738 return true;
2739 getParser().getStreamer().EmitGPRel64Value(Value);
2740
2741 if (getLexer().isNot(AsmToken::EndOfStatement))
2742 return Error(getLexer().getLoc(), "unexpected token in directive");
2743 Parser.Lex(); // Eat EndOfStatement token.
2744 return false;
2745}
2746
Jack Carter0cd3c192014-01-06 23:27:31 +00002747bool MipsAsmParser::parseDirectiveOption() {
2748 // Get the option token.
2749 AsmToken Tok = Parser.getTok();
2750 // At the moment only identifiers are supported.
2751 if (Tok.isNot(AsmToken::Identifier)) {
2752 Error(Parser.getTok().getLoc(), "unexpected token in .option directive");
2753 Parser.eatToEndOfStatement();
2754 return false;
2755 }
2756
2757 StringRef Option = Tok.getIdentifier();
2758
2759 if (Option == "pic0") {
2760 getTargetStreamer().emitDirectiveOptionPic0();
2761 Parser.Lex();
2762 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2763 Error(Parser.getTok().getLoc(),
2764 "unexpected token in .option pic0 directive");
2765 Parser.eatToEndOfStatement();
2766 }
2767 return false;
2768 }
2769
Matheus Almeidaf79b2812014-03-26 13:40:29 +00002770 if (Option == "pic2") {
2771 getTargetStreamer().emitDirectiveOptionPic2();
2772 Parser.Lex();
2773 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2774 Error(Parser.getTok().getLoc(),
2775 "unexpected token in .option pic2 directive");
2776 Parser.eatToEndOfStatement();
2777 }
2778 return false;
2779 }
2780
Jack Carter0cd3c192014-01-06 23:27:31 +00002781 // Unknown option.
2782 Warning(Parser.getTok().getLoc(), "unknown option in .option directive");
2783 Parser.eatToEndOfStatement();
2784 return false;
2785}
2786
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002787bool MipsAsmParser::parseDirectiveModule() {
2788 // Line can be: .module fp=32
2789 // .module fp=xx
2790 // .module fp=64
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002791 if (!getTargetStreamer().getCanHaveModuleDir()) {
2792 // TODO : get a better message.
2793 reportParseError(".module directive must appear before any code");
2794 return false;
2795 }
2796 AsmToken Tok = Parser.getTok();
2797 if (Tok.isNot(AsmToken::Identifier) && Tok.getString() != "fp") {
2798 reportParseError("unexpected token in .module directive, 'fp' expected");
2799 return false;
2800 }
2801 Parser.Lex(); // Eat fp token
2802 Tok = Parser.getTok();
2803 if (Tok.isNot(AsmToken::Equal)) {
2804 reportParseError("unexpected token in statement");
2805 return false;
2806 }
2807 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002808
2809 Val_GNU_MIPS_ABI FpABI;
2810 if (!parseFpABIValue(FpABI, ".module"))
2811 return false;
2812
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002813 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2814 reportParseError("unexpected token in statement");
2815 return false;
2816 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002817
Daniel Sanders7201a3e2014-07-08 10:35:52 +00002818 // Emit appropriate flags.
2819 getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
2820
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002821 return false;
2822}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002823
2824bool MipsAsmParser::parseFpABIValue(Val_GNU_MIPS_ABI &FpABI,
2825 StringRef Directive) {
2826 MCAsmLexer &Lexer = getLexer();
2827
2828 if (Lexer.is(AsmToken::Identifier)) {
2829 StringRef Value = Parser.getTok().getString();
2830 Parser.Lex();
2831
2832 if (Value != "xx") {
2833 reportParseError("unsupported value, expected 'xx', '32' or '64'");
2834 return false;
2835 }
2836
2837 if (!isABI_O32()) {
2838 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
2839 return false;
2840 }
2841
2842 FpABI = MipsABIFlagsSection::Val_GNU_MIPS_ABI_FP_XX;
2843 return true;
2844 }
2845
2846 if (Lexer.is(AsmToken::Integer)) {
2847 unsigned Value = Parser.getTok().getIntVal();
2848 Parser.Lex();
2849
2850 if (Value != 32 && Value != 64) {
2851 reportParseError("unsupported value, expected 'xx', '32' or '64'");
2852 return false;
2853 }
2854
2855 if (Value == 32) {
2856 if (!isABI_O32()) {
2857 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
2858 return false;
2859 }
2860
2861 FpABI = MipsABIFlagsSection::Val_GNU_MIPS_ABI_FP_DOUBLE;
2862 return true;
2863 } else {
2864 if (isABI_N32() || isABI_N64()) {
2865 FpABI = MipsABIFlagsSection::Val_GNU_MIPS_ABI_FP_DOUBLE;
2866 return true;
2867 }
2868
2869 if (isABI_O32()) {
2870 FpABI = MipsABIFlagsSection::Val_GNU_MIPS_ABI_FP_64;
2871 return true;
2872 }
2873
2874 llvm_unreachable("Unknown ABI");
2875 }
2876 }
2877
2878 return false;
2879}
2880
Jack Carter0b744b32012-10-04 02:29:46 +00002881bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carter07c818d2013-01-25 01:31:34 +00002882 StringRef IDVal = DirectiveID.getString();
2883
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002884 if (IDVal == ".cpload")
2885 return parseDirectiveCPLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00002886 if (IDVal == ".dword") {
2887 parseDataDirective(8, DirectiveID.getLoc());
2888 return false;
2889 }
2890
Jack Carterd0bd6422013-04-18 00:41:53 +00002891 if (IDVal == ".ent") {
2892 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00002893 Parser.Lex();
2894 return false;
2895 }
2896
Jack Carter07c818d2013-01-25 01:31:34 +00002897 if (IDVal == ".end") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002898 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00002899 Parser.Lex();
2900 return false;
2901 }
2902
Jack Carter07c818d2013-01-25 01:31:34 +00002903 if (IDVal == ".frame") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002904 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002905 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002906 return false;
2907 }
2908
Jack Carter07c818d2013-01-25 01:31:34 +00002909 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00002910 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00002911 }
2912
Jack Carter07c818d2013-01-25 01:31:34 +00002913 if (IDVal == ".fmask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002914 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002915 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002916 return false;
2917 }
2918
Jack Carter07c818d2013-01-25 01:31:34 +00002919 if (IDVal == ".mask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002920 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002921 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002922 return false;
2923 }
2924
Matheus Almeida0051f2d2014-04-16 15:48:55 +00002925 if (IDVal == ".nan")
2926 return parseDirectiveNaN();
2927
Jack Carter07c818d2013-01-25 01:31:34 +00002928 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002929 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00002930 return false;
2931 }
2932
Rafael Espindolab59fb732014-03-28 18:50:26 +00002933 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002934 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00002935 return false;
2936 }
2937
Jack Carter07c818d2013-01-25 01:31:34 +00002938 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002939 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00002940 return false;
2941 }
2942
Jack Carter0cd3c192014-01-06 23:27:31 +00002943 if (IDVal == ".option")
2944 return parseDirectiveOption();
2945
2946 if (IDVal == ".abicalls") {
2947 getTargetStreamer().emitDirectiveAbiCalls();
2948 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2949 Error(Parser.getTok().getLoc(), "unexpected token in directive");
2950 // Clear line
2951 Parser.eatToEndOfStatement();
2952 }
2953 return false;
2954 }
2955
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002956 if (IDVal == ".cpsetup")
2957 return parseDirectiveCPSetup();
2958
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002959 if (IDVal == ".module")
2960 return parseDirectiveModule();
2961
Rafael Espindola870c4e92012-01-11 03:56:41 +00002962 return true;
2963}
2964
Rafael Espindola870c4e92012-01-11 03:56:41 +00002965extern "C" void LLVMInitializeMipsAsmParser() {
2966 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
2967 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
2968 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
2969 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
2970}
Jack Carterb4dbc172012-09-05 23:34:03 +00002971
2972#define GET_REGISTER_MATCHER
2973#define GET_MATCHER_IMPLEMENTATION
2974#include "MipsGenAsmMatcher.inc"