blob: 0c06be8c7d9981d74dc9a5291ab9cbefdf5b2036 [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();
Daniel Sanders7e527422014-07-10 13:38:23 +0000168 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
169 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000170
Jack Carterdc1e35d2012-09-06 20:00:02 +0000171 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000172
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000173 bool eatComma(StringRef ErrorStr);
174
Jack Carter1ac53222013-02-20 23:11:17 +0000175 int matchCPURegisterName(StringRef Symbol);
176
Jack Carter873c7242013-01-12 01:03:14 +0000177 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000178
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000179 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000180
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000181 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000182
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000183 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000184
Jack Carter5dc8ac92013-09-25 23:50:44 +0000185 int matchMSA128RegisterName(StringRef Name);
186
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000187 int matchMSA128CtrlRegisterName(StringRef Name);
188
Jack Carterd0bd6422013-04-18 00:41:53 +0000189 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000190
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000191 unsigned getGPR(int RegNo);
192
Matheus Almeida7de68e72014-06-18 14:46:05 +0000193 int getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000194
195 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000196 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000197
198 // Helper function that checks if the value of a vector index is within the
199 // boundaries of accepted values for each RegisterKind
200 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
201 bool validateMSAIndex(int Val, int RegKind);
202
Vladimir Medic615b26e2014-03-04 09:54:09 +0000203 void setFeatureBits(unsigned Feature, StringRef FeatureString) {
204 if (!(STI.getFeatureBits() & Feature)) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000205 setAvailableFeatures(
206 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000207 }
208 }
209
210 void clearFeatureBits(unsigned Feature, StringRef FeatureString) {
211 if (STI.getFeatureBits() & Feature) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000212 setAvailableFeatures(
213 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000214 }
215 }
216
Rafael Espindola870c4e92012-01-11 03:56:41 +0000217public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000218 enum MipsMatchResultTy {
219 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
220#define GET_OPERAND_DIAGNOSTIC_TYPES
221#include "MipsGenAsmMatcher.inc"
222#undef GET_OPERAND_DIAGNOSTIC_TYPES
223
224 };
225
Joey Gouly0e76fa72013-09-12 10:28:05 +0000226 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000227 const MCInstrInfo &MII, const MCTargetOptions &Options)
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000228 : MCTargetAsmParser(), STI(sti), Parser(parser) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000229 // Initialize the set of available features.
230 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000231
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000232 getTargetStreamer().updateABIInfo(*this);
233
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000234 // Assert exactly one ABI was chosen.
235 assert((((STI.getFeatureBits() & Mips::FeatureO32) != 0) +
236 ((STI.getFeatureBits() & Mips::FeatureEABI) != 0) +
237 ((STI.getFeatureBits() & Mips::FeatureN32) != 0) +
238 ((STI.getFeatureBits() & Mips::FeatureN64) != 0)) == 1);
Daniel Sanders7e527422014-07-10 13:38:23 +0000239
240 if (!isABI_O32() && !allowOddSPReg() != 0)
241 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Rafael Espindola870c4e92012-01-11 03:56:41 +0000242 }
243
Jack Carterb4dbc172012-09-05 23:34:03 +0000244 MCAsmParser &getParser() const { return Parser; }
245 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000246
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000247 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
248 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
249
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000250 bool isGP64bit() const { return STI.getFeatureBits() & Mips::FeatureGP64Bit; }
251 bool isFP64bit() const { return STI.getFeatureBits() & Mips::FeatureFP64Bit; }
252 bool isABI_N32() const { return STI.getFeatureBits() & Mips::FeatureN32; }
253 bool isABI_N64() const { return STI.getFeatureBits() & Mips::FeatureN64; }
254 bool isABI_O32() const { return STI.getFeatureBits() & Mips::FeatureO32; }
255 bool isABI_FPXX() const { return false; } // TODO: add check for FeatureXX
256
Daniel Sanders7e527422014-07-10 13:38:23 +0000257 bool allowOddSPReg() const {
258 return !(STI.getFeatureBits() & Mips::FeatureNoOddSPReg);
259 }
260
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000261 bool inMicroMipsMode() const {
262 return STI.getFeatureBits() & Mips::FeatureMicroMips;
263 }
264 bool hasMips1() const { return STI.getFeatureBits() & Mips::FeatureMips1; }
265 bool hasMips2() const { return STI.getFeatureBits() & Mips::FeatureMips2; }
266 bool hasMips3() const { return STI.getFeatureBits() & Mips::FeatureMips3; }
267 bool hasMips4() const { return STI.getFeatureBits() & Mips::FeatureMips4; }
268 bool hasMips5() const { return STI.getFeatureBits() & Mips::FeatureMips5; }
269 bool hasMips32() const {
270 return (STI.getFeatureBits() & Mips::FeatureMips32);
271 }
272 bool hasMips64() const {
273 return (STI.getFeatureBits() & Mips::FeatureMips64);
274 }
275 bool hasMips32r2() const {
276 return (STI.getFeatureBits() & Mips::FeatureMips32r2);
277 }
278 bool hasMips64r2() const {
279 return (STI.getFeatureBits() & Mips::FeatureMips64r2);
280 }
281 bool hasMips32r6() const {
282 return (STI.getFeatureBits() & Mips::FeatureMips32r6);
283 }
284 bool hasMips64r6() const {
285 return (STI.getFeatureBits() & Mips::FeatureMips64r6);
286 }
287 bool hasDSP() const { return (STI.getFeatureBits() & Mips::FeatureDSP); }
288 bool hasDSPR2() const { return (STI.getFeatureBits() & Mips::FeatureDSPR2); }
289 bool hasMSA() const { return (STI.getFeatureBits() & Mips::FeatureMSA); }
290
291 bool inMips16Mode() const {
292 return STI.getFeatureBits() & Mips::FeatureMips16;
293 }
294 // TODO: see how can we get this info.
295 bool mipsSEUsesSoftFloat() const { return false; }
296
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000297 /// Warn if RegNo is the current assembler temporary.
298 void WarnIfAssemblerTemporary(int RegNo, SMLoc Loc);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000299};
300}
301
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000302namespace {
303
304/// MipsOperand - Instances of this class represent a parsed Mips machine
305/// instruction.
306class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000307public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000308 /// Broad categories of register classes
309 /// The exact class is finalized by the render method.
310 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000311 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000312 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000313 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000314 RegKind_FCC = 4, /// FCC
315 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
316 RegKind_MSACtrl = 16, /// MSA control registers
317 RegKind_COP2 = 32, /// COP2
318 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
319 /// context).
320 RegKind_CCR = 128, /// CCR
321 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000322 RegKind_COP3 = 512, /// COP3
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000323
324 /// Potentially any (e.g. $1)
325 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
326 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000327 RegKind_CCR | RegKind_HWRegs | RegKind_COP3
Jack Carter873c7242013-01-12 01:03:14 +0000328 };
329
330private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000331 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000332 k_Immediate, /// An immediate (possibly involving symbol references)
333 k_Memory, /// Base + Offset Memory Address
334 k_PhysRegister, /// A physical register from the Mips namespace
335 k_RegisterIndex, /// A register index in one or more RegKind.
336 k_Token /// A simple token
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000337 } Kind;
338
David Blaikie960ea3f2014-06-08 16:18:35 +0000339public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000340 MipsOperand(KindTy K, MipsAsmParser &Parser)
341 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
342
David Blaikie960ea3f2014-06-08 16:18:35 +0000343private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000344 /// For diagnostics, and checking the assembler temporary
345 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000346
Eric Christopher8996c5d2013-03-15 00:42:55 +0000347 struct Token {
348 const char *Data;
349 unsigned Length;
350 };
351
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000352 struct PhysRegOp {
353 unsigned Num; /// Register Number
354 };
355
356 struct RegIdxOp {
357 unsigned Index; /// Index into the register class
358 RegKind Kind; /// Bitfield of the kinds it could possibly be
359 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000360 };
361
362 struct ImmOp {
363 const MCExpr *Val;
364 };
365
366 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000367 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000368 const MCExpr *Off;
369 };
370
Jack Carterb4dbc172012-09-05 23:34:03 +0000371 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000372 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000373 struct PhysRegOp PhysReg;
374 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000375 struct ImmOp Imm;
376 struct MemOp Mem;
Jack Carterb4dbc172012-09-05 23:34:03 +0000377 };
378
379 SMLoc StartLoc, EndLoc;
380
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000381 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000382 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
383 const MCRegisterInfo *RegInfo,
384 SMLoc S, SMLoc E,
385 MipsAsmParser &Parser) {
386 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000387 Op->RegIdx.Index = Index;
388 Op->RegIdx.RegInfo = RegInfo;
389 Op->RegIdx.Kind = RegKind;
390 Op->StartLoc = S;
391 Op->EndLoc = E;
392 return Op;
393 }
394
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000395public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000396 /// Coerce the register to GPR32 and return the real register for the current
397 /// target.
398 unsigned getGPR32Reg() const {
399 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
400 AsmParser.WarnIfAssemblerTemporary(RegIdx.Index, StartLoc);
401 unsigned ClassID = Mips::GPR32RegClassID;
402 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000403 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000404
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000405 /// Coerce the register to GPR64 and return the real register for the current
406 /// target.
407 unsigned getGPR64Reg() const {
408 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
409 unsigned ClassID = Mips::GPR64RegClassID;
410 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000411 }
412
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000413private:
414 /// Coerce the register to AFGR64 and return the real register for the current
415 /// target.
416 unsigned getAFGR64Reg() const {
417 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
418 if (RegIdx.Index % 2 != 0)
419 AsmParser.Warning(StartLoc, "Float register should be even.");
420 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
421 .getRegister(RegIdx.Index / 2);
422 }
423
424 /// Coerce the register to FGR64 and return the real register for the current
425 /// target.
426 unsigned getFGR64Reg() const {
427 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
428 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
429 .getRegister(RegIdx.Index);
430 }
431
432 /// Coerce the register to FGR32 and return the real register for the current
433 /// target.
434 unsigned getFGR32Reg() const {
435 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
436 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
437 .getRegister(RegIdx.Index);
438 }
439
440 /// Coerce the register to FGRH32 and return the real register for the current
441 /// target.
442 unsigned getFGRH32Reg() const {
443 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
444 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
445 .getRegister(RegIdx.Index);
446 }
447
448 /// Coerce the register to FCC and return the real register for the current
449 /// target.
450 unsigned getFCCReg() const {
451 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
452 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
453 .getRegister(RegIdx.Index);
454 }
455
456 /// Coerce the register to MSA128 and return the real register for the current
457 /// target.
458 unsigned getMSA128Reg() const {
459 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
460 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
461 // identical
462 unsigned ClassID = Mips::MSA128BRegClassID;
463 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
464 }
465
466 /// Coerce the register to MSACtrl and return the real register for the
467 /// current target.
468 unsigned getMSACtrlReg() const {
469 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
470 unsigned ClassID = Mips::MSACtrlRegClassID;
471 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
472 }
473
474 /// Coerce the register to COP2 and return the real register for the
475 /// current target.
476 unsigned getCOP2Reg() const {
477 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
478 unsigned ClassID = Mips::COP2RegClassID;
479 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
480 }
481
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000482 /// Coerce the register to COP3 and return the real register for the
483 /// current target.
484 unsigned getCOP3Reg() const {
485 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
486 unsigned ClassID = Mips::COP3RegClassID;
487 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
488 }
489
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000490 /// Coerce the register to ACC64DSP and return the real register for the
491 /// current target.
492 unsigned getACC64DSPReg() const {
493 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
494 unsigned ClassID = Mips::ACC64DSPRegClassID;
495 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
496 }
497
498 /// Coerce the register to HI32DSP and return the real register for the
499 /// current target.
500 unsigned getHI32DSPReg() const {
501 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
502 unsigned ClassID = Mips::HI32DSPRegClassID;
503 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
504 }
505
506 /// Coerce the register to LO32DSP and return the real register for the
507 /// current target.
508 unsigned getLO32DSPReg() const {
509 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
510 unsigned ClassID = Mips::LO32DSPRegClassID;
511 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
512 }
513
514 /// Coerce the register to CCR and return the real register for the
515 /// current target.
516 unsigned getCCRReg() const {
517 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
518 unsigned ClassID = Mips::CCRRegClassID;
519 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
520 }
521
522 /// Coerce the register to HWRegs and return the real register for the
523 /// current target.
524 unsigned getHWRegsReg() const {
525 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
526 unsigned ClassID = Mips::HWRegsRegClassID;
527 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
528 }
529
530public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000531 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000532 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000533 if (!Expr)
Jack Carterb4dbc172012-09-05 23:34:03 +0000534 Inst.addOperand(MCOperand::CreateImm(0));
535 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
536 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
537 else
538 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000539 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000540
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000541 void addRegOperands(MCInst &Inst, unsigned N) const {
542 llvm_unreachable("Use a custom parser instead");
543 }
544
Daniel Sanders21bce302014-04-01 12:35:23 +0000545 /// Render the operand to an MCInst as a GPR32
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 addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
549 assert(N == 1 && "Invalid number of operands!");
550 Inst.addOperand(MCOperand::CreateReg(getGPR32Reg()));
551 }
552
Daniel Sanders21bce302014-04-01 12:35:23 +0000553 /// Render the operand to an MCInst as a GPR64
554 /// Asserts if the wrong number of operands are requested, or the operand
555 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000556 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
557 assert(N == 1 && "Invalid number of operands!");
558 Inst.addOperand(MCOperand::CreateReg(getGPR64Reg()));
559 }
560
561 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
562 assert(N == 1 && "Invalid number of operands!");
563 Inst.addOperand(MCOperand::CreateReg(getAFGR64Reg()));
564 }
565
566 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
567 assert(N == 1 && "Invalid number of operands!");
568 Inst.addOperand(MCOperand::CreateReg(getFGR64Reg()));
569 }
570
571 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
572 assert(N == 1 && "Invalid number of operands!");
573 Inst.addOperand(MCOperand::CreateReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000574 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
575 if (!AsmParser.allowOddSPReg() && RegIdx.Index & 1)
576 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
577 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000578 }
579
580 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
581 assert(N == 1 && "Invalid number of operands!");
582 Inst.addOperand(MCOperand::CreateReg(getFGRH32Reg()));
583 }
584
585 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
586 assert(N == 1 && "Invalid number of operands!");
587 Inst.addOperand(MCOperand::CreateReg(getFCCReg()));
588 }
589
590 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
591 assert(N == 1 && "Invalid number of operands!");
592 Inst.addOperand(MCOperand::CreateReg(getMSA128Reg()));
593 }
594
595 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
596 assert(N == 1 && "Invalid number of operands!");
597 Inst.addOperand(MCOperand::CreateReg(getMSACtrlReg()));
598 }
599
600 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
601 assert(N == 1 && "Invalid number of operands!");
602 Inst.addOperand(MCOperand::CreateReg(getCOP2Reg()));
603 }
604
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000605 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
606 assert(N == 1 && "Invalid number of operands!");
607 Inst.addOperand(MCOperand::CreateReg(getCOP3Reg()));
608 }
609
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000610 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
611 assert(N == 1 && "Invalid number of operands!");
612 Inst.addOperand(MCOperand::CreateReg(getACC64DSPReg()));
613 }
614
615 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
616 assert(N == 1 && "Invalid number of operands!");
617 Inst.addOperand(MCOperand::CreateReg(getHI32DSPReg()));
618 }
619
620 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
621 assert(N == 1 && "Invalid number of operands!");
622 Inst.addOperand(MCOperand::CreateReg(getLO32DSPReg()));
623 }
624
625 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
626 assert(N == 1 && "Invalid number of operands!");
627 Inst.addOperand(MCOperand::CreateReg(getCCRReg()));
628 }
629
630 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
631 assert(N == 1 && "Invalid number of operands!");
632 Inst.addOperand(MCOperand::CreateReg(getHWRegsReg()));
633 }
634
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000635 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000636 assert(N == 1 && "Invalid number of operands!");
637 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000638 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000639 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000640
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000641 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000642 assert(N == 2 && "Invalid number of operands!");
643
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000644 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000645
646 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000647 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000648 }
649
Craig Topper56c590a2014-04-29 07:58:02 +0000650 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000651 // As a special case until we sort out the definition of div/divu, pretend
652 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
653 if (isGPRAsmReg() && RegIdx.Index == 0)
654 return true;
655
656 return Kind == k_PhysRegister;
657 }
658 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000659 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000660 bool isConstantImm() const {
661 return isImm() && dyn_cast<MCConstantExpr>(getImm());
662 }
Craig Topper56c590a2014-04-29 07:58:02 +0000663 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000664 // Note: It's not possible to pretend that other operand kinds are tokens.
665 // The matcher emitter checks tokens first.
666 return Kind == k_Token;
667 }
Craig Topper56c590a2014-04-29 07:58:02 +0000668 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000669 bool isConstantMemOff() const {
670 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
671 }
672 template <unsigned Bits> bool isMemWithSimmOffset() const {
673 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff());
674 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000675 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000676 bool isLSAImm() const {
677 if (!isConstantImm())
678 return false;
679 int64_t Val = getConstantImm();
680 return 1 <= Val && Val <= 4;
681 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000682
683 StringRef getToken() const {
684 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000685 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000686 }
687
Craig Topper56c590a2014-04-29 07:58:02 +0000688 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000689 // As a special case until we sort out the definition of div/divu, pretend
690 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
691 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
692 RegIdx.Kind & RegKind_GPR)
693 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000694
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000695 assert(Kind == k_PhysRegister && "Invalid access!");
696 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +0000697 }
698
Jack Carterb4dbc172012-09-05 23:34:03 +0000699 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000700 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000701 return Imm.Val;
702 }
703
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000704 int64_t getConstantImm() const {
705 const MCExpr *Val = getImm();
706 return static_cast<const MCConstantExpr *>(Val)->getValue();
707 }
708
709 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000710 assert((Kind == k_Memory) && "Invalid access!");
711 return Mem.Base;
712 }
713
714 const MCExpr *getMemOff() const {
715 assert((Kind == k_Memory) && "Invalid access!");
716 return Mem.Off;
717 }
718
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000719 int64_t getConstantMemOff() const {
720 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
721 }
722
David Blaikie960ea3f2014-06-08 16:18:35 +0000723 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
724 MipsAsmParser &Parser) {
725 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000726 Op->Tok.Data = Str.data();
727 Op->Tok.Length = Str.size();
728 Op->StartLoc = S;
729 Op->EndLoc = S;
730 return Op;
731 }
732
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000733 /// Create a numeric register (e.g. $1). The exact register remains
734 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +0000735 static std::unique_ptr<MipsOperand>
736 CreateNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
737 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000738 DEBUG(dbgs() << "CreateNumericReg(" << Index << ", ...)\n");
739 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000740 }
741
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000742 /// Create a register that is definitely a GPR.
743 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +0000744 static std::unique_ptr<MipsOperand>
745 CreateGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
746 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000747 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000748 }
749
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000750 /// Create a register that is definitely a FGR.
751 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000752 static std::unique_ptr<MipsOperand>
753 CreateFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
754 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000755 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
756 }
757
758 /// Create a register that is definitely an FCC.
759 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000760 static std::unique_ptr<MipsOperand>
761 CreateFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
762 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000763 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
764 }
765
766 /// Create a register that is definitely an ACC.
767 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000768 static std::unique_ptr<MipsOperand>
769 CreateACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
770 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000771 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
772 }
773
774 /// Create a register that is definitely an MSA128.
775 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000776 static std::unique_ptr<MipsOperand>
777 CreateMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
778 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000779 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
780 }
781
782 /// Create a register that is definitely an MSACtrl.
783 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +0000784 static std::unique_ptr<MipsOperand>
785 CreateMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
786 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000787 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
788 }
789
David Blaikie960ea3f2014-06-08 16:18:35 +0000790 static std::unique_ptr<MipsOperand>
791 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
792 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000793 Op->Imm.Val = Val;
794 Op->StartLoc = S;
795 Op->EndLoc = E;
796 return Op;
797 }
798
David Blaikie960ea3f2014-06-08 16:18:35 +0000799 static std::unique_ptr<MipsOperand>
800 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
801 SMLoc E, MipsAsmParser &Parser) {
802 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
803 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +0000804 Op->Mem.Off = Off;
805 Op->StartLoc = S;
806 Op->EndLoc = E;
807 return Op;
808 }
809
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000810 bool isGPRAsmReg() const {
811 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000812 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000813 bool isFGRAsmReg() const {
814 // AFGR64 is $0-$15 but we handle this in getAFGR64()
815 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000816 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000817 bool isHWRegsAsmReg() const {
818 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000819 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000820 bool isCCRAsmReg() const {
821 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000822 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000823 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000824 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
825 return false;
826 if (!AsmParser.hasEightFccRegisters())
827 return RegIdx.Index == 0;
828 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +0000829 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000830 bool isACCAsmReg() const {
831 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +0000832 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000833 bool isCOP2AsmReg() const {
834 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +0000835 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000836 bool isCOP3AsmReg() const {
837 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
838 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000839 bool isMSA128AsmReg() const {
840 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +0000841 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000842 bool isMSACtrlAsmReg() const {
843 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000844 }
845
Jack Carterb4dbc172012-09-05 23:34:03 +0000846 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +0000847 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +0000848 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +0000849 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +0000850
NAKAMURA Takumie1f35832014-04-15 14:13:21 +0000851 virtual ~MipsOperand() {
852 switch (Kind) {
853 case k_Immediate:
854 break;
855 case k_Memory:
856 delete Mem.Base;
857 break;
858 case k_PhysRegister:
859 case k_RegisterIndex:
860 case k_Token:
861 break;
862 }
863 }
864
Craig Topper56c590a2014-04-29 07:58:02 +0000865 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000866 switch (Kind) {
867 case k_Immediate:
868 OS << "Imm<";
869 Imm.Val->print(OS);
870 OS << ">";
871 break;
872 case k_Memory:
873 OS << "Mem<";
874 Mem.Base->print(OS);
875 OS << ", ";
876 Mem.Off->print(OS);
877 OS << ">";
878 break;
879 case k_PhysRegister:
880 OS << "PhysReg<" << PhysReg.Num << ">";
881 break;
882 case k_RegisterIndex:
883 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
884 break;
885 case k_Token:
886 OS << Tok.Data;
887 break;
888 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000889 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000890}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +0000891} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000892
Jack Carter9e65aa32013-03-22 00:05:30 +0000893namespace llvm {
894extern const MCInstrDesc MipsInsts[];
895}
896static const MCInstrDesc &getInstDesc(unsigned Opcode) {
897 return MipsInsts[Opcode];
898}
899
900bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +0000901 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000902 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +0000903
Jack Carter9e65aa32013-03-22 00:05:30 +0000904 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000905
906 if (MCID.isBranch() || MCID.isCall()) {
907 const unsigned Opcode = Inst.getOpcode();
908 MCOperand Offset;
909
910 switch (Opcode) {
911 default:
912 break;
913 case Mips::BEQ:
914 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000915 case Mips::BEQ_MM:
916 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +0000917 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000918 Offset = Inst.getOperand(2);
919 if (!Offset.isImm())
920 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000921 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000922 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000923 if (OffsetToAlignment(Offset.getImm(),
924 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000925 return Error(IDLoc, "branch to misaligned address");
926 break;
927 case Mips::BGEZ:
928 case Mips::BGTZ:
929 case Mips::BLEZ:
930 case Mips::BLTZ:
931 case Mips::BGEZAL:
932 case Mips::BLTZAL:
933 case Mips::BC1F:
934 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000935 case Mips::BGEZ_MM:
936 case Mips::BGTZ_MM:
937 case Mips::BLEZ_MM:
938 case Mips::BLTZ_MM:
939 case Mips::BGEZAL_MM:
940 case Mips::BLTZAL_MM:
941 case Mips::BC1F_MM:
942 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +0000943 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000944 Offset = Inst.getOperand(1);
945 if (!Offset.isImm())
946 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000947 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000948 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000949 if (OffsetToAlignment(Offset.getImm(),
950 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000951 return Error(IDLoc, "branch to misaligned address");
952 break;
953 }
954 }
955
Daniel Sandersa84989a2014-06-16 13:25:35 +0000956 // SSNOP is deprecated on MIPS32r6/MIPS64r6
957 // We still accept it but it is a normal nop.
958 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
959 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
960 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
961 "nop instruction");
962 }
963
Jack Carterc15c1d22013-04-25 23:31:35 +0000964 if (MCID.hasDelaySlot() && Options.isReorder()) {
965 // If this instruction has a delay slot and .set reorder is active,
966 // emit a NOP after it.
967 Instructions.push_back(Inst);
968 MCInst NopInst;
969 NopInst.setOpcode(Mips::SLL);
970 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
971 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
972 NopInst.addOperand(MCOperand::CreateImm(0));
973 Instructions.push_back(NopInst);
974 return false;
975 }
976
Jack Carter9e65aa32013-03-22 00:05:30 +0000977 if (MCID.mayLoad() || MCID.mayStore()) {
978 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +0000979 // reference or immediate we may have to expand instructions.
980 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000981 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +0000982 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
983 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000984 MCOperand &Op = Inst.getOperand(i);
985 if (Op.isImm()) {
986 int MemOffset = Op.getImm();
987 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000988 // Offset can't exceed 16bit value.
989 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +0000990 return false;
991 }
992 } else if (Op.isExpr()) {
993 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +0000994 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000995 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +0000996 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +0000997 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000998 // Expand symbol.
999 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001000 return false;
1001 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001002 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001003 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001004 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001005 }
1006 }
1007 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001008 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001009 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001010
1011 if (needsExpansion(Inst))
Matheus Almeida3813d572014-06-19 14:39:14 +00001012 return expandInstruction(Inst, IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +00001013 else
1014 Instructions.push_back(Inst);
1015
1016 return false;
1017}
1018
Jack Carter30a59822012-10-04 04:03:53 +00001019bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1020
Jack Carterd0bd6422013-04-18 00:41:53 +00001021 switch (Inst.getOpcode()) {
1022 case Mips::LoadImm32Reg:
1023 case Mips::LoadAddr32Imm:
1024 case Mips::LoadAddr32Reg:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001025 case Mips::LoadImm64Reg:
Jack Carterd0bd6422013-04-18 00:41:53 +00001026 return true;
1027 default:
1028 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001029 }
1030}
Jack Carter92995f12012-10-06 00:53:28 +00001031
Matheus Almeida3813d572014-06-19 14:39:14 +00001032bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001033 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001034 switch (Inst.getOpcode()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001035 default:
1036 assert(0 && "unimplemented expansion");
Matheus Almeida3813d572014-06-19 14:39:14 +00001037 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001038 case Mips::LoadImm32Reg:
1039 return expandLoadImm(Inst, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001040 case Mips::LoadImm64Reg:
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001041 if (!isGP64bit()) {
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001042 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1043 return true;
1044 }
1045 return expandLoadImm(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001046 case Mips::LoadAddr32Imm:
1047 return expandLoadAddressImm(Inst, IDLoc, Instructions);
1048 case Mips::LoadAddr32Reg:
1049 return expandLoadAddressReg(Inst, IDLoc, Instructions);
1050 }
Jack Carter30a59822012-10-04 04:03:53 +00001051}
Jack Carter92995f12012-10-06 00:53:28 +00001052
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001053namespace {
1054template <int Shift, bool PerformShift>
1055void createShiftOr(int64_t Value, unsigned RegNo, SMLoc IDLoc,
1056 SmallVectorImpl<MCInst> &Instructions) {
1057 MCInst tmpInst;
1058 if (PerformShift) {
1059 tmpInst.setOpcode(Mips::DSLL);
1060 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1061 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1062 tmpInst.addOperand(MCOperand::CreateImm(16));
1063 tmpInst.setLoc(IDLoc);
1064 Instructions.push_back(tmpInst);
1065 tmpInst.clear();
1066 }
1067 tmpInst.setOpcode(Mips::ORi);
1068 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1069 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1070 tmpInst.addOperand(
1071 MCOperand::CreateImm(((Value & (0xffffLL << Shift)) >> Shift)));
1072 tmpInst.setLoc(IDLoc);
1073 Instructions.push_back(tmpInst);
1074}
1075}
1076
Matheus Almeida3813d572014-06-19 14:39:14 +00001077bool MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001078 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +00001079 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +00001080 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +00001081 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +00001082 const MCOperand &RegOp = Inst.getOperand(0);
1083 assert(RegOp.isReg() && "expected register operand kind");
1084
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001085 int64_t ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +00001086 tmpInst.setLoc(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001087 // FIXME: gas has a special case for values that are 000...1111, which
1088 // becomes a li -1 and then a dsrl
Jack Carterd0bd6422013-04-18 00:41:53 +00001089 if (0 <= ImmValue && ImmValue <= 65535) {
1090 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +00001091 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001092 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +00001093 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001094 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001095 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001096 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001097 } else if (ImmValue < 0 && ImmValue >= -32768) {
1098 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +00001099 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001100 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +00001101 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001102 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001103 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001104 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001105 } else if ((ImmValue & 0xffffffff) == ImmValue) {
1106 // For any value of j that is representable as a 32-bit integer, create
1107 // a sequence of:
Jack Carter30a59822012-10-04 04:03:53 +00001108 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001109 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001110 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001111 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1112 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +00001113 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001114 createShiftOr<0, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1115 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001116 if (!isGP64bit()) {
1117 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001118 return true;
1119 }
1120
1121 // <------- lo32 ------>
1122 // <------- hi32 ------>
1123 // <- hi16 -> <- lo16 ->
1124 // _________________________________
1125 // | | | |
1126 // | 16-bytes | 16-bytes | 16-bytes |
1127 // |__________|__________|__________|
1128 //
1129 // For any value of j that is representable as a 48-bit integer, create
1130 // a sequence of:
1131 // li d,j => lui d,hi16(j)
1132 // ori d,d,hi16(lo32(j))
1133 // dsll d,d,16
1134 // ori d,d,lo16(lo32(j))
1135 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001136 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001137 tmpInst.addOperand(
1138 MCOperand::CreateImm((ImmValue & (0xffffLL << 32)) >> 32));
Jack Carter30a59822012-10-04 04:03:53 +00001139 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001140 createShiftOr<16, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1141 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1142 } else {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001143 if (!isGP64bit()) {
1144 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001145 return true;
1146 }
1147
1148 // <------- hi32 ------> <------- lo32 ------>
1149 // <- hi16 -> <- lo16 ->
1150 // ___________________________________________
1151 // | | | | |
1152 // | 16-bytes | 16-bytes | 16-bytes | 16-bytes |
1153 // |__________|__________|__________|__________|
1154 //
1155 // For any value of j that isn't representable as a 48-bit integer.
1156 // li d,j => lui d,hi16(j)
1157 // ori d,d,lo16(hi32(j))
1158 // dsll d,d,16
1159 // ori d,d,hi16(lo32(j))
1160 // dsll d,d,16
1161 // ori d,d,lo16(lo32(j))
1162 tmpInst.setOpcode(Mips::LUi);
1163 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1164 tmpInst.addOperand(
1165 MCOperand::CreateImm((ImmValue & (0xffffLL << 48)) >> 48));
1166 Instructions.push_back(tmpInst);
1167 createShiftOr<32, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1168 createShiftOr<16, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1169 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
Jack Carter30a59822012-10-04 04:03:53 +00001170 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001171 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001172}
Jack Carter92995f12012-10-06 00:53:28 +00001173
Matheus Almeida3813d572014-06-19 14:39:14 +00001174bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001175MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
1176 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001177 MCInst tmpInst;
1178 const MCOperand &ImmOp = Inst.getOperand(2);
1179 assert(ImmOp.isImm() && "expected immediate operand kind");
1180 const MCOperand &SrcRegOp = Inst.getOperand(1);
1181 assert(SrcRegOp.isReg() && "expected register operand kind");
1182 const MCOperand &DstRegOp = Inst.getOperand(0);
1183 assert(DstRegOp.isReg() && "expected register operand kind");
1184 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001185 if (-32768 <= ImmValue && ImmValue <= 65535) {
1186 // For -32768 <= j <= 65535.
1187 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +00001188 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +00001189 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1190 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1191 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1192 Instructions.push_back(tmpInst);
1193 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001194 // For any other value of j that is representable as a 32-bit integer.
1195 // la d,j(s) => lui d,hi16(j)
1196 // ori d,d,lo16(j)
1197 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +00001198 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001199 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1200 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1201 Instructions.push_back(tmpInst);
1202 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001203 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001204 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1205 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1206 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1207 Instructions.push_back(tmpInst);
1208 tmpInst.clear();
1209 tmpInst.setOpcode(Mips::ADDu);
1210 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1211 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1212 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1213 Instructions.push_back(tmpInst);
1214 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001215 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001216}
1217
Matheus Almeida3813d572014-06-19 14:39:14 +00001218bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001219MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1220 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001221 MCInst tmpInst;
1222 const MCOperand &ImmOp = Inst.getOperand(1);
1223 assert(ImmOp.isImm() && "expected immediate operand kind");
1224 const MCOperand &RegOp = Inst.getOperand(0);
1225 assert(RegOp.isReg() && "expected register operand kind");
1226 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001227 if (-32768 <= ImmValue && ImmValue <= 65535) {
1228 // For -32768 <= j <= 65535.
1229 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +00001230 tmpInst.setOpcode(Mips::ADDiu);
1231 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001232 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +00001233 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1234 Instructions.push_back(tmpInst);
1235 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001236 // For any other value of j that is representable as a 32-bit integer.
1237 // la d,j => lui d,hi16(j)
1238 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001239 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001240 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1241 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1242 Instructions.push_back(tmpInst);
1243 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001244 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001245 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1246 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1247 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1248 Instructions.push_back(tmpInst);
1249 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001250 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001251}
1252
Jack Carter9e65aa32013-03-22 00:05:30 +00001253void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001254 SmallVectorImpl<MCInst> &Instructions,
1255 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001256 const MCSymbolRefExpr *SR;
1257 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00001258 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00001259 const MCExpr *ExprOffset;
1260 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00001261 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001262 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1263 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001264 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001265 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1266 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001267 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00001268 if (isImmOpnd) {
1269 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
1270 ImmOffset = Inst.getOperand(2).getImm();
1271 LoOffset = ImmOffset & 0x0000ffff;
1272 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00001273 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00001274 if (LoOffset & 0x8000)
1275 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00001276 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001277 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001278 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00001279 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00001280 // These are some of the types of expansions we perform here:
1281 // 1) lw $8, sym => lui $8, %hi(sym)
1282 // lw $8, %lo(sym)($8)
1283 // 2) lw $8, offset($9) => lui $8, %hi(offset)
1284 // add $8, $8, $9
1285 // lw $8, %lo(offset)($9)
1286 // 3) lw $8, offset($8) => lui $at, %hi(offset)
1287 // add $at, $at, $8
1288 // lw $8, %lo(offset)($at)
1289 // 4) sw $8, sym => lui $at, %hi(sym)
1290 // sw $8, %lo(sym)($at)
1291 // 5) sw $8, offset($8) => lui $at, %hi(offset)
1292 // add $at, $at, $8
1293 // sw $8, %lo(offset)($at)
1294 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
1295 // ldc1 $f0, %lo(sym)($at)
1296 //
1297 // For load instructions we can use the destination register as a temporary
1298 // if base and dst are different (examples 1 and 2) and if the base register
1299 // is general purpose otherwise we must use $at (example 6) and error if it's
1300 // not available. For stores we must use $at (examples 4 and 5) because we
1301 // must not clobber the source register setting up the offset.
1302 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
1303 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
1304 unsigned RegClassIDOp0 =
1305 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
1306 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
1307 (RegClassIDOp0 == Mips::GPR64RegClassID);
1308 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00001309 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00001310 else {
1311 int AT = getATReg(IDLoc);
1312 // At this point we need AT to perform the expansions and we exit if it is
1313 // not available.
1314 if (!AT)
1315 return;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001316 TmpRegNum = getReg(
1317 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, AT);
Matheus Almeida7de68e72014-06-18 14:46:05 +00001318 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00001319
Jack Carter9e65aa32013-03-22 00:05:30 +00001320 TempInst.setOpcode(Mips::LUi);
1321 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1322 if (isImmOpnd)
1323 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
1324 else {
1325 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001326 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00001327 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
1328 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
1329 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001330 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001331 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001332 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00001333 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001334 }
1335 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001336 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00001337 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001338 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00001339 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00001340 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001341 TempInst.setOpcode(Mips::ADDu);
1342 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1343 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1344 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
1345 Instructions.push_back(TempInst);
1346 TempInst.clear();
Alp Tokercb402912014-01-24 17:20:08 +00001347 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00001348 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001349 TempInst.setOpcode(Inst.getOpcode());
1350 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
1351 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1352 if (isImmOpnd)
1353 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
1354 else {
1355 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001356 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
1357 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
1358 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001359 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001360 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001361 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00001362 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001363 }
1364 }
1365 Instructions.push_back(TempInst);
1366 TempInst.clear();
1367}
1368
Matheus Almeida595fcab2014-06-11 15:05:56 +00001369unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1370 // As described by the Mips32r2 spec, the registers Rd and Rs for
1371 // jalr.hb must be different.
1372 unsigned Opcode = Inst.getOpcode();
1373
1374 if (Opcode == Mips::JALR_HB &&
1375 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
1376 return Match_RequiresDifferentSrcAndDst;
1377
1378 return Match_Success;
1379}
1380
David Blaikie960ea3f2014-06-08 16:18:35 +00001381bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1382 OperandVector &Operands,
1383 MCStreamer &Out,
1384 unsigned &ErrorInfo,
1385 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00001386
Jack Carterb4dbc172012-09-05 23:34:03 +00001387 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00001388 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00001389 unsigned MatchResult =
1390 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00001391
1392 switch (MatchResult) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001393 default:
1394 break;
Jack Carterb4dbc172012-09-05 23:34:03 +00001395 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001396 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00001397 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001398 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00001399 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00001400 return false;
1401 }
1402 case Match_MissingFeature:
1403 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1404 return true;
1405 case Match_InvalidOperand: {
1406 SMLoc ErrorLoc = IDLoc;
1407 if (ErrorInfo != ~0U) {
1408 if (ErrorInfo >= Operands.size())
1409 return Error(IDLoc, "too few operands for instruction");
1410
David Blaikie960ea3f2014-06-08 16:18:35 +00001411 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001412 if (ErrorLoc == SMLoc())
1413 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00001414 }
1415
1416 return Error(ErrorLoc, "invalid operand for instruction");
1417 }
1418 case Match_MnemonicFail:
1419 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00001420 case Match_RequiresDifferentSrcAndDst:
1421 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00001422 }
Rafael Espindola870c4e92012-01-11 03:56:41 +00001423 return true;
1424}
1425
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001426void MipsAsmParser::WarnIfAssemblerTemporary(int RegIndex, SMLoc Loc) {
1427 if ((RegIndex != 0) && ((int)Options.getATRegNum() == RegIndex)) {
1428 if (RegIndex == 1)
1429 Warning(Loc, "Used $at without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001430 else
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001431 Warning(Loc, Twine("Used $") + Twine(RegIndex) + " with \".set at=$" +
1432 Twine(RegIndex) + "\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001433 }
1434}
1435
Jack Carter1ac53222013-02-20 23:11:17 +00001436int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001437 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00001438
Vladimir Medic4c299852013-11-06 11:27:05 +00001439 CC = StringSwitch<unsigned>(Name)
1440 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001441 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00001442 .Case("a0", 4)
1443 .Case("a1", 5)
1444 .Case("a2", 6)
1445 .Case("a3", 7)
1446 .Case("v0", 2)
1447 .Case("v1", 3)
1448 .Case("s0", 16)
1449 .Case("s1", 17)
1450 .Case("s2", 18)
1451 .Case("s3", 19)
1452 .Case("s4", 20)
1453 .Case("s5", 21)
1454 .Case("s6", 22)
1455 .Case("s7", 23)
1456 .Case("k0", 26)
1457 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001458 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00001459 .Case("sp", 29)
1460 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001461 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00001462 .Case("ra", 31)
1463 .Case("t0", 8)
1464 .Case("t1", 9)
1465 .Case("t2", 10)
1466 .Case("t3", 11)
1467 .Case("t4", 12)
1468 .Case("t5", 13)
1469 .Case("t6", 14)
1470 .Case("t7", 15)
1471 .Case("t8", 24)
1472 .Case("t9", 25)
1473 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00001474
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001475 if (isABI_N32() || isABI_N64()) {
Daniel Sandersa4b0c742014-03-26 11:39:07 +00001476 // Although SGI documentation just cuts out t0-t3 for n32/n64,
1477 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
1478 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
1479 if (8 <= CC && CC <= 11)
1480 CC += 4;
Jack Carter1ac53222013-02-20 23:11:17 +00001481
Daniel Sandersa4b0c742014-03-26 11:39:07 +00001482 if (CC == -1)
1483 CC = StringSwitch<unsigned>(Name)
1484 .Case("a4", 8)
1485 .Case("a5", 9)
1486 .Case("a6", 10)
1487 .Case("a7", 11)
1488 .Case("kt0", 26)
1489 .Case("kt1", 27)
1490 .Default(-1);
1491 }
Jack Carter1ac53222013-02-20 23:11:17 +00001492
1493 return CC;
1494}
Jack Carterd0bd6422013-04-18 00:41:53 +00001495
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001496int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001497
Jack Cartera63b16a2012-09-07 00:23:42 +00001498 if (Name[0] == 'f') {
1499 StringRef NumString = Name.substr(1);
1500 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001501 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001502 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001503 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00001504 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001505 return IntVal;
1506 }
1507 return -1;
1508}
Jack Cartera63b16a2012-09-07 00:23:42 +00001509
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001510int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
1511
1512 if (Name.startswith("fcc")) {
1513 StringRef NumString = Name.substr(3);
1514 unsigned IntVal;
1515 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001516 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001517 if (IntVal > 7) // There are only 8 fcc registers.
1518 return -1;
1519 return IntVal;
1520 }
1521 return -1;
1522}
1523
1524int MipsAsmParser::matchACRegisterName(StringRef Name) {
1525
Akira Hatanaka274d24c2013-08-14 01:15:52 +00001526 if (Name.startswith("ac")) {
1527 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001528 unsigned IntVal;
1529 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001530 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001531 if (IntVal > 3) // There are only 3 acc registers.
1532 return -1;
1533 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00001534 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001535 return -1;
1536}
Jack Carterd0bd6422013-04-18 00:41:53 +00001537
Jack Carter5dc8ac92013-09-25 23:50:44 +00001538int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
1539 unsigned IntVal;
1540
1541 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
1542 return -1;
1543
1544 if (IntVal > 31)
1545 return -1;
1546
1547 return IntVal;
1548}
1549
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001550int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
1551 int CC;
1552
1553 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00001554 .Case("msair", 0)
1555 .Case("msacsr", 1)
1556 .Case("msaaccess", 2)
1557 .Case("msasave", 3)
1558 .Case("msamodify", 4)
1559 .Case("msarequest", 5)
1560 .Case("msamap", 6)
1561 .Case("msaunmap", 7)
1562 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001563
1564 return CC;
1565}
1566
Jack Carter0b744b32012-10-04 02:29:46 +00001567bool MipsAssemblerOptions::setATReg(unsigned Reg) {
1568 if (Reg > 31)
1569 return false;
1570
1571 aTReg = Reg;
1572 return true;
1573}
1574
Matheus Almeida7de68e72014-06-18 14:46:05 +00001575int MipsAsmParser::getATReg(SMLoc Loc) {
Daniel Sandersd89b1362014-03-24 16:48:01 +00001576 int AT = Options.getATRegNum();
1577 if (AT == 0)
Matheus Almeida7de68e72014-06-18 14:46:05 +00001578 reportParseError(Loc,
1579 "Pseudo instruction requires $at, which is not available");
Daniel Sandersd89b1362014-03-24 16:48:01 +00001580 return AT;
1581}
Jack Carter0b744b32012-10-04 02:29:46 +00001582
Jack Carterd0bd6422013-04-18 00:41:53 +00001583unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00001584 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00001585}
1586
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001587unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001588 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00001589 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001590}
1591
Jack Carter873c7242013-01-12 01:03:14 +00001592int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001593 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00001594 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00001595 return -1;
1596
Jack Carter873c7242013-01-12 01:03:14 +00001597 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00001598}
1599
David Blaikie960ea3f2014-06-08 16:18:35 +00001600bool MipsAsmParser::ParseOperand(OperandVector &Operands, StringRef Mnemonic) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001601 DEBUG(dbgs() << "ParseOperand\n");
1602
Jack Carter30a59822012-10-04 04:03:53 +00001603 // Check if the current operand has a custom associated parser, if so, try to
1604 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00001605 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
1606 if (ResTy == MatchOperand_Success)
1607 return false;
1608 // If there wasn't a custom match, try the generic matcher below. Otherwise,
1609 // there was a match, but an error occurred, in which case, just return that
1610 // the operand parsing failed.
1611 if (ResTy == MatchOperand_ParseFail)
1612 return true;
1613
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001614 DEBUG(dbgs() << ".. Generic Parser\n");
1615
Jack Carterb4dbc172012-09-05 23:34:03 +00001616 switch (getLexer().getKind()) {
1617 default:
1618 Error(Parser.getTok().getLoc(), "unexpected token in operand");
1619 return true;
1620 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001621 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00001622 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00001623
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001624 // Almost all registers have been parsed by custom parsers. There is only
1625 // one exception to this. $zero (and it's alias $0) will reach this point
1626 // for div, divu, and similar instructions because it is not an operand
1627 // to the instruction definition but an explicit register. Special case
1628 // this situation for now.
1629 if (ParseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00001630 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001631
Jack Carterd0bd6422013-04-18 00:41:53 +00001632 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00001633 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001634 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00001635 return true;
1636
Jack Carter873c7242013-01-12 01:03:14 +00001637 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00001638 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00001639 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00001640 const MCExpr *Res =
1641 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00001642
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001643 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00001644 return false;
1645 }
Vladimir Medic4c299852013-11-06 11:27:05 +00001646 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00001647 case AsmToken::LParen:
1648 case AsmToken::Minus:
1649 case AsmToken::Plus:
1650 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00001651 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00001652 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001653 DEBUG(dbgs() << ".. generic integer\n");
1654 OperandMatchResultTy ResTy = ParseImm(Operands);
1655 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00001656 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00001657 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001658 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001659 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001660 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00001661 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00001662 return true;
1663
Jack Carter873c7242013-01-12 01:03:14 +00001664 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1665
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001666 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001667 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001668 } // case AsmToken::Percent
1669 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00001670 return true;
1671}
1672
Vladimir Medic4c299852013-11-06 11:27:05 +00001673const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00001674 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00001675 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00001676 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001677 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00001678 // It's a constant, evaluate reloc value.
1679 int16_t Val;
1680 switch (getVariantKind(RelocStr)) {
1681 case MCSymbolRefExpr::VK_Mips_ABS_LO:
1682 // Get the 1st 16-bits.
1683 Val = MCE->getValue() & 0xffff;
1684 break;
1685 case MCSymbolRefExpr::VK_Mips_ABS_HI:
1686 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
1687 // 16 bits being negative.
1688 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
1689 break;
1690 case MCSymbolRefExpr::VK_Mips_HIGHER:
1691 // Get the 3rd 16-bits.
1692 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
1693 break;
1694 case MCSymbolRefExpr::VK_Mips_HIGHEST:
1695 // Get the 4th 16-bits.
1696 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
1697 break;
1698 default:
1699 report_fatal_error("Unsupported reloc value!");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001700 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00001701 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00001702 }
1703
Jack Carterb5cf5902013-04-17 00:18:04 +00001704 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001705 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00001706 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00001707 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00001708 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001709 return Res;
1710 }
1711
1712 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00001713 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
1714
Sasa Stankovic06c47802014-04-03 10:37:45 +00001715 // Try to create target expression.
1716 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
1717 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00001718
Jack Carterd0bd6422013-04-18 00:41:53 +00001719 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
1720 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00001721 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
1722 return Res;
1723 }
1724
1725 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001726 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
1727 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
1728 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00001729 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001730 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001731 return Expr;
1732}
1733
1734bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
1735
1736 switch (Expr->getKind()) {
1737 case MCExpr::Constant:
1738 return true;
1739 case MCExpr::SymbolRef:
1740 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
1741 case MCExpr::Binary:
1742 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
1743 if (!isEvaluated(BE->getLHS()))
1744 return false;
1745 return isEvaluated(BE->getRHS());
1746 }
1747 case MCExpr::Unary:
1748 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00001749 case MCExpr::Target:
1750 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001751 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001752 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00001753}
Jack Carterd0bd6422013-04-18 00:41:53 +00001754
Jack Carterb5cf5902013-04-17 00:18:04 +00001755bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001756 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00001757 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00001758 if (Tok.isNot(AsmToken::Identifier))
1759 return true;
1760
1761 std::string Str = Tok.getIdentifier().str();
1762
Jack Carterd0bd6422013-04-18 00:41:53 +00001763 Parser.Lex(); // Eat the identifier.
1764 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001765 const MCExpr *IdVal;
1766 SMLoc EndLoc;
1767
1768 if (getLexer().getKind() == AsmToken::LParen) {
1769 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001770 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001771 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001772 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001773 const AsmToken &nextTok = Parser.getTok();
1774 if (nextTok.isNot(AsmToken::Identifier))
1775 return true;
1776 Str += "(%";
1777 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00001778 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00001779 if (getLexer().getKind() != AsmToken::LParen)
1780 return true;
1781 } else
1782 break;
1783 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001784 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00001785 return true;
1786
1787 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00001788 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001789
1790 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00001791 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001792
Jack Carterd0bd6422013-04-18 00:41:53 +00001793 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00001794 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001795}
1796
Jack Carterb4dbc172012-09-05 23:34:03 +00001797bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1798 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001799 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001800 OperandMatchResultTy ResTy = ParseAnyRegister(Operands);
1801 if (ResTy == MatchOperand_Success) {
1802 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00001803 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001804 StartLoc = Operand.getStartLoc();
1805 EndLoc = Operand.getEndLoc();
1806
1807 // AFAIK, we only support numeric registers and named GPR's in CFI
1808 // directives.
1809 // Don't worry about eating tokens before failing. Using an unrecognised
1810 // register is a parse error.
1811 if (Operand.isGPRAsmReg()) {
1812 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001813 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001814 }
1815
1816 return (RegNo == (unsigned)-1);
1817 }
1818
1819 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00001820 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00001821}
1822
Jack Carterb5cf5902013-04-17 00:18:04 +00001823bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00001824 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001825 bool Result = true;
1826
1827 while (getLexer().getKind() == AsmToken::LParen)
1828 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00001829
Jack Carterd0bd6422013-04-18 00:41:53 +00001830 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001831 default:
1832 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00001833 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00001834 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00001835 case AsmToken::Integer:
1836 case AsmToken::Minus:
1837 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00001838 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00001839 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00001840 else
1841 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00001842 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00001843 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001844 break;
Jack Carter873c7242013-01-12 01:03:14 +00001845 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00001846 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00001847 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001848 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001849}
1850
David Blaikie960ea3f2014-06-08 16:18:35 +00001851MipsAsmParser::OperandMatchResultTy
1852MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001853 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00001854 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00001855 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001856 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001857 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00001858 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00001859 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001860
Jack Carterb5cf5902013-04-17 00:18:04 +00001861 if (getLexer().getKind() == AsmToken::LParen) {
1862 Parser.Lex();
1863 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001864 }
1865
Jack Carterb5cf5902013-04-17 00:18:04 +00001866 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001867 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00001868 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001869
Jack Carterd0bd6422013-04-18 00:41:53 +00001870 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001871 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001872 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
1873 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00001874 SMLoc E =
1875 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001876 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00001877 return MatchOperand_Success;
1878 }
1879 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001880 SMLoc E =
1881 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00001882
Jack Carterd0bd6422013-04-18 00:41:53 +00001883 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001884 // "Base" will be managed by k_Memory.
David Blaikie960ea3f2014-06-08 16:18:35 +00001885 auto Base = MipsOperand::CreateGPRReg(0, getContext().getRegisterInfo(),
1886 S, E, *this);
1887 Operands.push_back(
1888 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00001889 return MatchOperand_Success;
1890 }
1891 Error(Parser.getTok().getLoc(), "'(' expected");
1892 return MatchOperand_ParseFail;
1893 }
1894
Jack Carterd0bd6422013-04-18 00:41:53 +00001895 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001896 }
1897
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001898 Res = ParseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001899 if (Res != MatchOperand_Success)
1900 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001901
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001902 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001903 Error(Parser.getTok().getLoc(), "')' expected");
1904 return MatchOperand_ParseFail;
1905 }
1906
Jack Carter873c7242013-01-12 01:03:14 +00001907 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1908
Jack Carterd0bd6422013-04-18 00:41:53 +00001909 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001910
Craig Topper062a2ba2014-04-25 05:30:21 +00001911 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00001912 IdVal = MCConstantExpr::Create(0, getContext());
1913
Jack Carterd0bd6422013-04-18 00:41:53 +00001914 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00001915 std::unique_ptr<MipsOperand> op(
1916 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001917 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001918 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001919 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00001920 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001921 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
1922 int64_t Imm;
1923 if (IdVal->EvaluateAsAbsolute(Imm))
1924 IdVal = MCConstantExpr::Create(Imm, getContext());
1925 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
1926 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
1927 getContext());
1928 }
1929
David Blaikie960ea3f2014-06-08 16:18:35 +00001930 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00001931 return MatchOperand_Success;
1932}
1933
David Blaikie960ea3f2014-06-08 16:18:35 +00001934bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Daniel Sanderse34a1202014-03-31 18:51:43 +00001935
Jack Carterd76b2372013-03-21 21:44:16 +00001936 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
1937 if (Sym) {
1938 SMLoc S = Parser.getTok().getLoc();
1939 const MCExpr *Expr;
1940 if (Sym->isVariable())
1941 Expr = Sym->getVariableValue();
1942 else
1943 return false;
1944 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001945 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carterd76b2372013-03-21 21:44:16 +00001946 const StringRef DefSymbol = Ref->getSymbol().getName();
1947 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001948 OperandMatchResultTy ResTy =
1949 MatchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00001950 if (ResTy == MatchOperand_Success) {
1951 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00001952 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00001953 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001954 llvm_unreachable("Should never ParseFail");
1955 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00001956 }
1957 } else if (Expr->getKind() == MCExpr::Constant) {
1958 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00001959 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00001960 Operands.push_back(
1961 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00001962 return true;
1963 }
1964 }
1965 return false;
1966}
Jack Carterd0bd6422013-04-18 00:41:53 +00001967
Jack Carter873c7242013-01-12 01:03:14 +00001968MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00001969MipsAsmParser::MatchAnyRegisterNameWithoutDollar(OperandVector &Operands,
1970 StringRef Identifier,
1971 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001972 int Index = matchCPURegisterName(Identifier);
1973 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001974 Operands.push_back(MipsOperand::CreateGPRReg(
1975 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1976 return MatchOperand_Success;
1977 }
1978
1979 Index = matchFPURegisterName(Identifier);
1980 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001981 Operands.push_back(MipsOperand::CreateFGRReg(
1982 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1983 return MatchOperand_Success;
1984 }
1985
1986 Index = matchFCCRegisterName(Identifier);
1987 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001988 Operands.push_back(MipsOperand::CreateFCCReg(
1989 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1990 return MatchOperand_Success;
1991 }
1992
1993 Index = matchACRegisterName(Identifier);
1994 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001995 Operands.push_back(MipsOperand::CreateACCReg(
1996 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1997 return MatchOperand_Success;
1998 }
1999
2000 Index = matchMSA128RegisterName(Identifier);
2001 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002002 Operands.push_back(MipsOperand::CreateMSA128Reg(
2003 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2004 return MatchOperand_Success;
2005 }
2006
2007 Index = matchMSA128CtrlRegisterName(Identifier);
2008 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002009 Operands.push_back(MipsOperand::CreateMSACtrlReg(
2010 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2011 return MatchOperand_Success;
2012 }
2013
2014 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00002015}
2016
2017MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002018MipsAsmParser::MatchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Daniel Sanders315386c2014-04-01 10:40:14 +00002019 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002020
2021 if (Token.is(AsmToken::Identifier)) {
2022 DEBUG(dbgs() << ".. identifier\n");
2023 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00002024 OperandMatchResultTy ResTy =
2025 MatchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00002026 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002027 } else if (Token.is(AsmToken::Integer)) {
2028 DEBUG(dbgs() << ".. integer\n");
2029 Operands.push_back(MipsOperand::CreateNumericReg(
2030 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
2031 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002032 return MatchOperand_Success;
2033 }
2034
2035 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
2036
2037 return MatchOperand_NoMatch;
2038}
2039
David Blaikie960ea3f2014-06-08 16:18:35 +00002040MipsAsmParser::OperandMatchResultTy
2041MipsAsmParser::ParseAnyRegister(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002042 DEBUG(dbgs() << "ParseAnyRegister\n");
2043
2044 auto Token = Parser.getTok();
2045
2046 SMLoc S = Token.getLoc();
2047
2048 if (Token.isNot(AsmToken::Dollar)) {
2049 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
2050 if (Token.is(AsmToken::Identifier)) {
2051 if (searchSymbolAlias(Operands))
2052 return MatchOperand_Success;
2053 }
2054 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
2055 return MatchOperand_NoMatch;
2056 }
2057 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002058
Daniel Sanders21bce302014-04-01 12:35:23 +00002059 OperandMatchResultTy ResTy = MatchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00002060 if (ResTy == MatchOperand_Success) {
2061 Parser.Lex(); // $
2062 Parser.Lex(); // identifier
2063 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002064 return ResTy;
2065}
2066
2067MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002068MipsAsmParser::ParseImm(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002069 switch (getLexer().getKind()) {
2070 default:
2071 return MatchOperand_NoMatch;
2072 case AsmToken::LParen:
2073 case AsmToken::Minus:
2074 case AsmToken::Plus:
2075 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002076 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002077 case AsmToken::String:
2078 break;
2079 }
2080
2081 const MCExpr *IdVal;
2082 SMLoc S = Parser.getTok().getLoc();
2083 if (getParser().parseExpression(IdVal))
2084 return MatchOperand_ParseFail;
2085
2086 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2087 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
2088 return MatchOperand_Success;
2089}
2090
David Blaikie960ea3f2014-06-08 16:18:35 +00002091MipsAsmParser::OperandMatchResultTy
2092MipsAsmParser::ParseJumpTarget(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002093 DEBUG(dbgs() << "ParseJumpTarget\n");
2094
2095 SMLoc S = getLexer().getLoc();
2096
2097 // Integers and expressions are acceptable
2098 OperandMatchResultTy ResTy = ParseImm(Operands);
2099 if (ResTy != MatchOperand_NoMatch)
2100 return ResTy;
2101
Daniel Sanders315386c2014-04-01 10:40:14 +00002102 // Registers are a valid target and have priority over symbols.
2103 ResTy = ParseAnyRegister(Operands);
2104 if (ResTy != MatchOperand_NoMatch)
2105 return ResTy;
2106
Daniel Sandersffd84362014-04-01 10:41:48 +00002107 const MCExpr *Expr = nullptr;
2108 if (Parser.parseExpression(Expr)) {
2109 // We have no way of knowing if a symbol was consumed so we must ParseFail
2110 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002111 }
Daniel Sandersffd84362014-04-01 10:41:48 +00002112 Operands.push_back(
2113 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002114 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00002115}
2116
Vladimir Medic2b953d02013-10-01 09:48:56 +00002117MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002118MipsAsmParser::parseInvNum(OperandVector &Operands) {
Vladimir Medic2b953d02013-10-01 09:48:56 +00002119 const MCExpr *IdVal;
2120 // If the first token is '$' we may have register operand.
2121 if (Parser.getTok().is(AsmToken::Dollar))
2122 return MatchOperand_NoMatch;
2123 SMLoc S = Parser.getTok().getLoc();
2124 if (getParser().parseExpression(IdVal))
2125 return MatchOperand_ParseFail;
2126 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00002127 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00002128 int64_t Val = MCE->getValue();
2129 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2130 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002131 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00002132 return MatchOperand_Success;
2133}
2134
Matheus Almeida779c5932013-11-18 12:32:49 +00002135MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002136MipsAsmParser::ParseLSAImm(OperandVector &Operands) {
Matheus Almeida779c5932013-11-18 12:32:49 +00002137 switch (getLexer().getKind()) {
2138 default:
2139 return MatchOperand_NoMatch;
2140 case AsmToken::LParen:
2141 case AsmToken::Plus:
2142 case AsmToken::Minus:
2143 case AsmToken::Integer:
2144 break;
2145 }
2146
2147 const MCExpr *Expr;
2148 SMLoc S = Parser.getTok().getLoc();
2149
2150 if (getParser().parseExpression(Expr))
2151 return MatchOperand_ParseFail;
2152
2153 int64_t Val;
2154 if (!Expr->EvaluateAsAbsolute(Val)) {
2155 Error(S, "expected immediate value");
2156 return MatchOperand_ParseFail;
2157 }
2158
2159 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
2160 // and because the CPU always adds one to the immediate field, the allowed
2161 // range becomes 1..4. We'll only check the range here and will deal
2162 // with the addition/subtraction when actually decoding/encoding
2163 // the instruction.
2164 if (Val < 1 || Val > 4) {
2165 Error(S, "immediate not in range (1..4)");
2166 return MatchOperand_ParseFail;
2167 }
2168
Jack Carter3b2c96e2014-01-22 23:31:38 +00002169 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002170 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00002171 return MatchOperand_Success;
2172}
2173
Jack Carterdc1e35d2012-09-06 20:00:02 +00002174MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
2175
Vladimir Medic4c299852013-11-06 11:27:05 +00002176 MCSymbolRefExpr::VariantKind VK =
2177 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
2178 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
2179 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
2180 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
2181 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
2182 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
2183 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
2184 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
2185 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
2186 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
2187 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
2188 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
2189 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
2190 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
2191 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
2192 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
2193 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
2194 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00002195 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
2196 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
2197 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
2198 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
2199 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
2200 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00002201 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
2202 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00002203 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002204
Matheus Almeida2852af82014-04-22 10:15:54 +00002205 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00002206
Jack Carterdc1e35d2012-09-06 20:00:02 +00002207 return VK;
2208}
Jack Cartera63b16a2012-09-07 00:23:42 +00002209
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002210/// Sometimes (i.e. load/stores) the operand may be followed immediately by
2211/// either this.
2212/// ::= '(', register, ')'
2213/// handle it before we iterate so we don't get tripped up by the lack of
2214/// a comma.
David Blaikie960ea3f2014-06-08 16:18:35 +00002215bool MipsAsmParser::ParseParenSuffix(StringRef Name, OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002216 if (getLexer().is(AsmToken::LParen)) {
2217 Operands.push_back(
2218 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
2219 Parser.Lex();
2220 if (ParseOperand(Operands, Name)) {
2221 SMLoc Loc = getLexer().getLoc();
2222 Parser.eatToEndOfStatement();
2223 return Error(Loc, "unexpected token in argument list");
2224 }
2225 if (Parser.getTok().isNot(AsmToken::RParen)) {
2226 SMLoc Loc = getLexer().getLoc();
2227 Parser.eatToEndOfStatement();
2228 return Error(Loc, "unexpected token, expected ')'");
2229 }
2230 Operands.push_back(
2231 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
2232 Parser.Lex();
2233 }
2234 return false;
2235}
2236
2237/// Sometimes (i.e. in MSA) the operand may be followed immediately by
2238/// either one of these.
2239/// ::= '[', register, ']'
2240/// ::= '[', integer, ']'
2241/// handle it before we iterate so we don't get tripped up by the lack of
2242/// a comma.
David Blaikie960ea3f2014-06-08 16:18:35 +00002243bool MipsAsmParser::ParseBracketSuffix(StringRef Name,
2244 OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002245 if (getLexer().is(AsmToken::LBrac)) {
2246 Operands.push_back(
2247 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
2248 Parser.Lex();
2249 if (ParseOperand(Operands, Name)) {
2250 SMLoc Loc = getLexer().getLoc();
2251 Parser.eatToEndOfStatement();
2252 return Error(Loc, "unexpected token in argument list");
2253 }
2254 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2255 SMLoc Loc = getLexer().getLoc();
2256 Parser.eatToEndOfStatement();
2257 return Error(Loc, "unexpected token, expected ']'");
2258 }
2259 Operands.push_back(
2260 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
2261 Parser.Lex();
2262 }
2263 return false;
2264}
2265
David Blaikie960ea3f2014-06-08 16:18:35 +00002266bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
2267 SMLoc NameLoc, OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002268 DEBUG(dbgs() << "ParseInstruction\n");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002269 // We have reached first instruction, module directive after
2270 // this is forbidden.
2271 getTargetStreamer().setCanHaveModuleDir(false);
Vladimir Medic74593e62013-07-17 15:00:42 +00002272 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00002273 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00002274 Parser.eatToEndOfStatement();
2275 return Error(NameLoc, "Unknown instruction");
2276 }
Vladimir Medic64828a12013-07-16 10:07:14 +00002277 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002278 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002279
2280 // Read the remaining operands.
2281 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2282 // Read the first operand.
Vladimir Medic64828a12013-07-16 10:07:14 +00002283 if (ParseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002284 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 if (getLexer().is(AsmToken::LBrac) && ParseBracketSuffix(Name, Operands))
2289 return true;
2290 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00002291
Jack Carterd0bd6422013-04-18 00:41:53 +00002292 while (getLexer().is(AsmToken::Comma)) {
2293 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00002294 // Parse and remember the operand.
2295 if (ParseOperand(Operands, Name)) {
2296 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002297 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002298 return Error(Loc, "unexpected token in argument list");
2299 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002300 // Parse bracket and parenthesis suffixes before we iterate
2301 if (getLexer().is(AsmToken::LBrac)) {
2302 if (ParseBracketSuffix(Name, Operands))
2303 return true;
2304 } else if (getLexer().is(AsmToken::LParen) &&
2305 ParseParenSuffix(Name, Operands))
2306 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00002307 }
2308 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002309 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2310 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002311 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002312 return Error(Loc, "unexpected token in argument list");
2313 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002314 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00002315 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00002316}
2317
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002318bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002319 SMLoc Loc = getLexer().getLoc();
2320 Parser.eatToEndOfStatement();
2321 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00002322}
2323
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002324bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002325 return Error(Loc, ErrorMsg);
2326}
2327
Jack Carter0b744b32012-10-04 02:29:46 +00002328bool MipsAsmParser::parseSetNoAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002329 // Line should look like: ".set noat".
2330 // set at reg to 0.
Jack Carter99d2afe2012-10-05 23:55:28 +00002331 Options.setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00002332 // eat noat
2333 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002334 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002335 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2336 reportParseError("unexpected token in statement");
2337 return false;
2338 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002339 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002340 return false;
2341}
Jack Carterd0bd6422013-04-18 00:41:53 +00002342
Jack Carter0b744b32012-10-04 02:29:46 +00002343bool MipsAsmParser::parseSetAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002344 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00002345 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00002346 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00002347 getParser().Lex();
2348 if (getLexer().is(AsmToken::EndOfStatement)) {
Jack Carter99d2afe2012-10-05 23:55:28 +00002349 Options.setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00002350 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002351 return false;
2352 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002353 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00002354 if (getLexer().isNot(AsmToken::Dollar)) {
2355 reportParseError("unexpected token in statement");
2356 return false;
2357 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002358 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00002359 const AsmToken &Reg = Parser.getTok();
2360 if (Reg.is(AsmToken::Identifier)) {
2361 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
2362 } else if (Reg.is(AsmToken::Integer)) {
2363 AtRegNo = Reg.getIntVal();
2364 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00002365 reportParseError("unexpected token in statement");
2366 return false;
2367 }
Jack Carter1ac53222013-02-20 23:11:17 +00002368
Daniel Sanders71a89d922014-03-25 13:01:06 +00002369 if (AtRegNo < 0 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00002370 reportParseError("unexpected token in statement");
2371 return false;
2372 }
2373
2374 if (!Options.setATReg(AtRegNo)) {
Jack Carter0b744b32012-10-04 02:29:46 +00002375 reportParseError("unexpected token in statement");
2376 return false;
2377 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002378 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00002379
2380 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2381 reportParseError("unexpected token in statement");
2382 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002383 }
2384 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002385 return false;
2386 } else {
2387 reportParseError("unexpected token in statement");
2388 return false;
2389 }
2390}
2391
2392bool MipsAsmParser::parseSetReorderDirective() {
2393 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002394 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002395 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2396 reportParseError("unexpected token in statement");
2397 return false;
2398 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002399 Options.setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00002400 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002401 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002402 return false;
2403}
2404
2405bool MipsAsmParser::parseSetNoReorderDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002406 Parser.Lex();
2407 // If this is not the end of the statement, report an error.
2408 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2409 reportParseError("unexpected token in statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002410 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002411 }
2412 Options.setNoreorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00002413 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002414 Parser.Lex(); // Consume the EndOfStatement.
2415 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002416}
2417
2418bool MipsAsmParser::parseSetMacroDirective() {
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("unexpected token in statement");
2423 return false;
2424 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002425 Options.setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002426 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002427 return false;
2428}
2429
2430bool MipsAsmParser::parseSetNoMacroDirective() {
2431 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002432 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002433 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2434 reportParseError("`noreorder' must be set before `nomacro'");
2435 return false;
2436 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002437 if (Options.isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00002438 reportParseError("`noreorder' must be set before `nomacro'");
2439 return false;
2440 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002441 Options.setNomacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002442 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002443 return false;
2444}
Jack Carterd76b2372013-03-21 21:44:16 +00002445
Jack Carter39536722014-01-22 23:08:42 +00002446bool MipsAsmParser::parseSetNoMips16Directive() {
2447 Parser.Lex();
2448 // If this is not the end of the statement, report an error.
2449 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2450 reportParseError("unexpected token in statement");
2451 return false;
2452 }
2453 // For now do nothing.
2454 Parser.Lex(); // Consume the EndOfStatement.
2455 return false;
2456}
2457
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002458bool MipsAsmParser::parseSetFpDirective() {
Daniel Sanders7e527422014-07-10 13:38:23 +00002459 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002460 // Line can be: .set fp=32
2461 // .set fp=xx
2462 // .set fp=64
2463 Parser.Lex(); // Eat fp token
2464 AsmToken Tok = Parser.getTok();
2465 if (Tok.isNot(AsmToken::Equal)) {
2466 reportParseError("unexpected token in statement");
2467 return false;
2468 }
2469 Parser.Lex(); // Eat '=' token.
2470 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002471
2472 if (!parseFpABIValue(FpAbiVal, ".set"))
2473 return false;
2474
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002475 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2476 reportParseError("unexpected token in statement");
2477 return false;
2478 }
Daniel Sanders7e527422014-07-10 13:38:23 +00002479 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002480 Parser.Lex(); // Consume the EndOfStatement.
2481 return false;
2482}
2483
Jack Carterd76b2372013-03-21 21:44:16 +00002484bool MipsAsmParser::parseSetAssignment() {
2485 StringRef Name;
2486 const MCExpr *Value;
2487
2488 if (Parser.parseIdentifier(Name))
2489 reportParseError("expected identifier after .set");
2490
2491 if (getLexer().isNot(AsmToken::Comma))
2492 return reportParseError("unexpected token in .set directive");
Jack Carterb5cf5902013-04-17 00:18:04 +00002493 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00002494
Jack Carter3b2c96e2014-01-22 23:31:38 +00002495 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00002496 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00002497
Jack Carterd0bd6422013-04-18 00:41:53 +00002498 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00002499 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00002500 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00002501 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00002502 Sym = getContext().GetOrCreateSymbol(Name);
2503 Sym->setVariableValue(Value);
2504
2505 return false;
2506}
Jack Carterd0bd6422013-04-18 00:41:53 +00002507
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002508bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
2509 Parser.Lex();
2510 if (getLexer().isNot(AsmToken::EndOfStatement))
2511 return reportParseError("unexpected token in .set directive");
2512
Matheus Almeida2852af82014-04-22 10:15:54 +00002513 switch (Feature) {
2514 default:
2515 llvm_unreachable("Unimplemented feature");
2516 case Mips::FeatureDSP:
2517 setFeatureBits(Mips::FeatureDSP, "dsp");
2518 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002519 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002520 case Mips::FeatureMicroMips:
2521 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002522 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002523 case Mips::FeatureMips16:
2524 getTargetStreamer().emitDirectiveSetMips16();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002525 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002526 case Mips::FeatureMips32r2:
2527 setFeatureBits(Mips::FeatureMips32r2, "mips32r2");
2528 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002529 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002530 case Mips::FeatureMips64:
2531 setFeatureBits(Mips::FeatureMips64, "mips64");
2532 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00002533 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002534 case Mips::FeatureMips64r2:
2535 setFeatureBits(Mips::FeatureMips64r2, "mips64r2");
2536 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00002537 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002538 }
2539 return false;
2540}
2541
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002542bool MipsAsmParser::eatComma(StringRef ErrorStr) {
2543 if (getLexer().isNot(AsmToken::Comma)) {
2544 SMLoc Loc = getLexer().getLoc();
2545 Parser.eatToEndOfStatement();
2546 return Error(Loc, ErrorStr);
2547 }
2548
Matheus Almeida2852af82014-04-22 10:15:54 +00002549 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002550 return true;
2551}
2552
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002553bool MipsAsmParser::parseDirectiveCPLoad(SMLoc Loc) {
2554 if (Options.isReorder())
2555 Warning(Loc, ".cpload in reorder section");
2556
2557 // FIXME: Warn if cpload is used in Mips16 mode.
2558
David Blaikie960ea3f2014-06-08 16:18:35 +00002559 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002560 OperandMatchResultTy ResTy = ParseAnyRegister(Reg);
2561 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
2562 reportParseError("expected register containing function address");
2563 return false;
2564 }
2565
David Blaikie960ea3f2014-06-08 16:18:35 +00002566 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
2567 if (!RegOpnd.isGPRAsmReg()) {
2568 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002569 return false;
2570 }
2571
David Blaikie960ea3f2014-06-08 16:18:35 +00002572 getTargetStreamer().emitDirectiveCpload(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002573 return false;
2574}
2575
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002576bool MipsAsmParser::parseDirectiveCPSetup() {
2577 unsigned FuncReg;
2578 unsigned Save;
2579 bool SaveIsReg = true;
2580
Matheus Almeida7e815762014-06-18 13:08:59 +00002581 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
2582 OperandMatchResultTy ResTy = ParseAnyRegister(TmpReg);
2583 if (ResTy == MatchOperand_NoMatch) {
2584 reportParseError("expected register containing function address");
2585 Parser.eatToEndOfStatement();
2586 return false;
2587 }
2588
2589 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
2590 if (!FuncRegOpnd.isGPRAsmReg()) {
2591 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
2592 Parser.eatToEndOfStatement();
2593 return false;
2594 }
2595
2596 FuncReg = FuncRegOpnd.getGPR32Reg();
2597 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002598
2599 if (!eatComma("expected comma parsing directive"))
2600 return true;
2601
Matheus Almeida7e815762014-06-18 13:08:59 +00002602 ResTy = ParseAnyRegister(TmpReg);
2603 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002604 const AsmToken &Tok = Parser.getTok();
2605 if (Tok.is(AsmToken::Integer)) {
2606 Save = Tok.getIntVal();
2607 SaveIsReg = false;
2608 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00002609 } else {
2610 reportParseError("expected save register or stack offset");
2611 Parser.eatToEndOfStatement();
2612 return false;
2613 }
2614 } else {
2615 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
2616 if (!SaveOpnd.isGPRAsmReg()) {
2617 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
2618 Parser.eatToEndOfStatement();
2619 return false;
2620 }
2621 Save = SaveOpnd.getGPR32Reg();
2622 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002623
2624 if (!eatComma("expected comma parsing directive"))
2625 return true;
2626
2627 StringRef Name;
2628 if (Parser.parseIdentifier(Name))
2629 reportParseError("expected identifier");
2630 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002631
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00002632 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, *Sym, SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002633 return false;
2634}
2635
Matheus Almeida0051f2d2014-04-16 15:48:55 +00002636bool MipsAsmParser::parseDirectiveNaN() {
2637 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2638 const AsmToken &Tok = Parser.getTok();
2639
2640 if (Tok.getString() == "2008") {
2641 Parser.Lex();
2642 getTargetStreamer().emitDirectiveNaN2008();
2643 return false;
2644 } else if (Tok.getString() == "legacy") {
2645 Parser.Lex();
2646 getTargetStreamer().emitDirectiveNaNLegacy();
2647 return false;
2648 }
2649 }
2650 // If we don't recognize the option passed to the .nan
2651 // directive (e.g. no option or unknown option), emit an error.
2652 reportParseError("invalid option in .nan directive");
2653 return false;
2654}
2655
Jack Carter0b744b32012-10-04 02:29:46 +00002656bool MipsAsmParser::parseDirectiveSet() {
2657
Jack Carterd0bd6422013-04-18 00:41:53 +00002658 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00002659 const AsmToken &Tok = Parser.getTok();
2660
2661 if (Tok.getString() == "noat") {
2662 return parseSetNoAtDirective();
2663 } else if (Tok.getString() == "at") {
2664 return parseSetAtDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002665 } else if (Tok.getString() == "fp") {
2666 return parseSetFpDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00002667 } else if (Tok.getString() == "reorder") {
2668 return parseSetReorderDirective();
2669 } else if (Tok.getString() == "noreorder") {
2670 return parseSetNoReorderDirective();
2671 } else if (Tok.getString() == "macro") {
2672 return parseSetMacroDirective();
2673 } else if (Tok.getString() == "nomacro") {
2674 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00002675 } else if (Tok.getString() == "mips16") {
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002676 return parseSetFeature(Mips::FeatureMips16);
Jack Carter0b744b32012-10-04 02:29:46 +00002677 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00002678 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00002679 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00002680 getTargetStreamer().emitDirectiveSetNoMicroMips();
2681 Parser.eatToEndOfStatement();
2682 return false;
2683 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002684 return parseSetFeature(Mips::FeatureMicroMips);
Vladimir Medic615b26e2014-03-04 09:54:09 +00002685 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002686 return parseSetFeature(Mips::FeatureMips32r2);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00002687 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002688 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00002689 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002690 return parseSetFeature(Mips::FeatureMips64r2);
Vladimir Medic27c398e2014-03-05 11:05:09 +00002691 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002692 return parseSetFeature(Mips::FeatureDSP);
Jack Carterd76b2372013-03-21 21:44:16 +00002693 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002694 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00002695 parseSetAssignment();
2696 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002697 }
Jack Carter07c818d2013-01-25 01:31:34 +00002698
Jack Carter0b744b32012-10-04 02:29:46 +00002699 return true;
2700}
2701
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002702/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00002703/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002704bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Jack Carter07c818d2013-01-25 01:31:34 +00002705 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2706 for (;;) {
2707 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002708 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00002709 return true;
2710
2711 getParser().getStreamer().EmitValue(Value, Size);
2712
2713 if (getLexer().is(AsmToken::EndOfStatement))
2714 break;
2715
2716 // FIXME: Improve diagnostic.
2717 if (getLexer().isNot(AsmToken::Comma))
2718 return Error(L, "unexpected token in directive");
2719 Parser.Lex();
2720 }
2721 }
2722
2723 Parser.Lex();
2724 return false;
2725}
2726
Vladimir Medic4c299852013-11-06 11:27:05 +00002727/// parseDirectiveGpWord
2728/// ::= .gpword local_sym
2729bool MipsAsmParser::parseDirectiveGpWord() {
2730 const MCExpr *Value;
2731 // EmitGPRel32Value requires an expression, so we are using base class
2732 // method to evaluate the expression.
2733 if (getParser().parseExpression(Value))
2734 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00002735 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00002736
Vladimir Medice10c1122013-11-13 13:18:04 +00002737 if (getLexer().isNot(AsmToken::EndOfStatement))
Vladimir Medic4c299852013-11-06 11:27:05 +00002738 return Error(getLexer().getLoc(), "unexpected token in directive");
Vladimir Medice10c1122013-11-13 13:18:04 +00002739 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00002740 return false;
2741}
2742
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002743/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00002744/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002745bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindolab59fb732014-03-28 18:50:26 +00002746 const MCExpr *Value;
2747 // EmitGPRel64Value requires an expression, so we are using base class
2748 // method to evaluate the expression.
2749 if (getParser().parseExpression(Value))
2750 return true;
2751 getParser().getStreamer().EmitGPRel64Value(Value);
2752
2753 if (getLexer().isNot(AsmToken::EndOfStatement))
2754 return Error(getLexer().getLoc(), "unexpected token in directive");
2755 Parser.Lex(); // Eat EndOfStatement token.
2756 return false;
2757}
2758
Jack Carter0cd3c192014-01-06 23:27:31 +00002759bool MipsAsmParser::parseDirectiveOption() {
2760 // Get the option token.
2761 AsmToken Tok = Parser.getTok();
2762 // At the moment only identifiers are supported.
2763 if (Tok.isNot(AsmToken::Identifier)) {
2764 Error(Parser.getTok().getLoc(), "unexpected token in .option directive");
2765 Parser.eatToEndOfStatement();
2766 return false;
2767 }
2768
2769 StringRef Option = Tok.getIdentifier();
2770
2771 if (Option == "pic0") {
2772 getTargetStreamer().emitDirectiveOptionPic0();
2773 Parser.Lex();
2774 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2775 Error(Parser.getTok().getLoc(),
2776 "unexpected token in .option pic0 directive");
2777 Parser.eatToEndOfStatement();
2778 }
2779 return false;
2780 }
2781
Matheus Almeidaf79b2812014-03-26 13:40:29 +00002782 if (Option == "pic2") {
2783 getTargetStreamer().emitDirectiveOptionPic2();
2784 Parser.Lex();
2785 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2786 Error(Parser.getTok().getLoc(),
2787 "unexpected token in .option pic2 directive");
2788 Parser.eatToEndOfStatement();
2789 }
2790 return false;
2791 }
2792
Jack Carter0cd3c192014-01-06 23:27:31 +00002793 // Unknown option.
2794 Warning(Parser.getTok().getLoc(), "unknown option in .option directive");
2795 Parser.eatToEndOfStatement();
2796 return false;
2797}
2798
Daniel Sanders7e527422014-07-10 13:38:23 +00002799/// parseDirectiveModule
2800/// ::= .module oddspreg
2801/// ::= .module nooddspreg
2802/// ::= .module fp=value
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002803bool MipsAsmParser::parseDirectiveModule() {
Daniel Sanders7e527422014-07-10 13:38:23 +00002804 MCAsmLexer &Lexer = getLexer();
2805 SMLoc L = Lexer.getLoc();
2806
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002807 if (!getTargetStreamer().getCanHaveModuleDir()) {
2808 // TODO : get a better message.
2809 reportParseError(".module directive must appear before any code");
2810 return false;
2811 }
Daniel Sanders7e527422014-07-10 13:38:23 +00002812
2813 if (Lexer.is(AsmToken::Identifier)) {
2814 StringRef Option = Parser.getTok().getString();
2815 Parser.Lex();
2816
2817 if (Option == "oddspreg") {
2818 getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32());
2819 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
2820
2821 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2822 reportParseError("Expected end of statement");
2823 return false;
2824 }
2825
2826 return false;
2827 } else if (Option == "nooddspreg") {
2828 if (!isABI_O32()) {
2829 Error(L, "'.module nooddspreg' requires the O32 ABI");
2830 return false;
2831 }
2832
2833 getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32());
2834 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
2835
2836 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2837 reportParseError("Expected end of statement");
2838 return false;
2839 }
2840
2841 return false;
2842 } else if (Option == "fp") {
2843 return parseDirectiveModuleFP();
2844 }
2845
2846 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002847 }
Daniel Sanders7e527422014-07-10 13:38:23 +00002848
2849 return false;
2850}
2851
2852/// parseDirectiveModuleFP
2853/// ::= =32
2854/// ::= =xx
2855/// ::= =64
2856bool MipsAsmParser::parseDirectiveModuleFP() {
2857 MCAsmLexer &Lexer = getLexer();
2858
2859 if (Lexer.isNot(AsmToken::Equal)) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002860 reportParseError("unexpected token in statement");
2861 return false;
2862 }
2863 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002864
Daniel Sanders7e527422014-07-10 13:38:23 +00002865 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002866 if (!parseFpABIValue(FpABI, ".module"))
2867 return false;
2868
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002869 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2870 reportParseError("unexpected token in statement");
2871 return false;
2872 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002873
Daniel Sanders7201a3e2014-07-08 10:35:52 +00002874 // Emit appropriate flags.
2875 getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
Daniel Sanders7e527422014-07-10 13:38:23 +00002876 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002877 return false;
2878}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002879
Daniel Sanders7e527422014-07-10 13:38:23 +00002880bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002881 StringRef Directive) {
2882 MCAsmLexer &Lexer = getLexer();
2883
2884 if (Lexer.is(AsmToken::Identifier)) {
2885 StringRef Value = Parser.getTok().getString();
2886 Parser.Lex();
2887
2888 if (Value != "xx") {
2889 reportParseError("unsupported value, expected 'xx', '32' or '64'");
2890 return false;
2891 }
2892
2893 if (!isABI_O32()) {
2894 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
2895 return false;
2896 }
2897
Daniel Sanders7e527422014-07-10 13:38:23 +00002898 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002899 return true;
2900 }
2901
2902 if (Lexer.is(AsmToken::Integer)) {
2903 unsigned Value = Parser.getTok().getIntVal();
2904 Parser.Lex();
2905
2906 if (Value != 32 && Value != 64) {
2907 reportParseError("unsupported value, expected 'xx', '32' or '64'");
2908 return false;
2909 }
2910
2911 if (Value == 32) {
2912 if (!isABI_O32()) {
2913 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
2914 return false;
2915 }
2916
Daniel Sanders7e527422014-07-10 13:38:23 +00002917 FpABI = MipsABIFlagsSection::FpABIKind::S32;
2918 } else
2919 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002920
Daniel Sanders7e527422014-07-10 13:38:23 +00002921 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002922 }
2923
2924 return false;
2925}
2926
Jack Carter0b744b32012-10-04 02:29:46 +00002927bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carter07c818d2013-01-25 01:31:34 +00002928 StringRef IDVal = DirectiveID.getString();
2929
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002930 if (IDVal == ".cpload")
2931 return parseDirectiveCPLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00002932 if (IDVal == ".dword") {
2933 parseDataDirective(8, DirectiveID.getLoc());
2934 return false;
2935 }
2936
Jack Carterd0bd6422013-04-18 00:41:53 +00002937 if (IDVal == ".ent") {
2938 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00002939 Parser.Lex();
2940 return false;
2941 }
2942
Jack Carter07c818d2013-01-25 01:31:34 +00002943 if (IDVal == ".end") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002944 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00002945 Parser.Lex();
2946 return false;
2947 }
2948
Jack Carter07c818d2013-01-25 01:31:34 +00002949 if (IDVal == ".frame") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002950 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002951 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002952 return false;
2953 }
2954
Jack Carter07c818d2013-01-25 01:31:34 +00002955 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00002956 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00002957 }
2958
Jack Carter07c818d2013-01-25 01:31:34 +00002959 if (IDVal == ".fmask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002960 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002961 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002962 return false;
2963 }
2964
Jack Carter07c818d2013-01-25 01:31:34 +00002965 if (IDVal == ".mask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002966 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002967 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002968 return false;
2969 }
2970
Matheus Almeida0051f2d2014-04-16 15:48:55 +00002971 if (IDVal == ".nan")
2972 return parseDirectiveNaN();
2973
Jack Carter07c818d2013-01-25 01:31:34 +00002974 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002975 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00002976 return false;
2977 }
2978
Rafael Espindolab59fb732014-03-28 18:50:26 +00002979 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002980 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00002981 return false;
2982 }
2983
Jack Carter07c818d2013-01-25 01:31:34 +00002984 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002985 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00002986 return false;
2987 }
2988
Jack Carter0cd3c192014-01-06 23:27:31 +00002989 if (IDVal == ".option")
2990 return parseDirectiveOption();
2991
2992 if (IDVal == ".abicalls") {
2993 getTargetStreamer().emitDirectiveAbiCalls();
2994 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2995 Error(Parser.getTok().getLoc(), "unexpected token in directive");
2996 // Clear line
2997 Parser.eatToEndOfStatement();
2998 }
2999 return false;
3000 }
3001
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003002 if (IDVal == ".cpsetup")
3003 return parseDirectiveCPSetup();
3004
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003005 if (IDVal == ".module")
3006 return parseDirectiveModule();
3007
Rafael Espindola870c4e92012-01-11 03:56:41 +00003008 return true;
3009}
3010
Rafael Espindola870c4e92012-01-11 03:56:41 +00003011extern "C" void LLVMInitializeMipsAsmParser() {
3012 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
3013 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
3014 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
3015 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
3016}
Jack Carterb4dbc172012-09-05 23:34:03 +00003017
3018#define GET_REGISTER_MATCHER
3019#define GET_MATCHER_IMPLEMENTATION
3020#include "MipsGenAsmMatcher.inc"