blob: 4a0059d55a3fab8c5030f0be4d5dabfc41f35e3f [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:
Vladimir Medicfb8a2a92014-07-08 08:59:22 +000041 MipsAssemblerOptions() : aTReg(1), reorder(true), macro(true), fpAbiMode(0) {}
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; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +000049 void setFpAbiMode(int Mode) { fpAbiMode = Mode; }
Jack Carter0b744b32012-10-04 02:29:46 +000050
Vladimir Medic4c299852013-11-06 11:27:05 +000051 bool isMacro() { return macro; }
52 void setMacro() { macro = true; }
53 void setNomacro() { macro = false; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +000054 int getFpAbiMode() { return fpAbiMode; }
Jack Carter0b744b32012-10-04 02:29:46 +000055
56private:
57 unsigned aTReg;
58 bool reorder;
59 bool macro;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +000060 int fpAbiMode;
Jack Carter0b744b32012-10-04 02:29:46 +000061};
62}
63
64namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +000065class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +000066 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola4a1a3602014-01-14 01:21:46 +000067 MCTargetStreamer &TS = *Parser.getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +000068 return static_cast<MipsTargetStreamer &>(TS);
69 }
70
Jack Carterb4dbc172012-09-05 23:34:03 +000071 MCSubtargetInfo &STI;
72 MCAsmParser &Parser;
Jack Carter99d2afe2012-10-05 23:55:28 +000073 MipsAssemblerOptions Options;
Jack Carter0b744b32012-10-04 02:29:46 +000074
Akira Hatanaka7605630c2012-08-17 20:16:42 +000075#define GET_ASSEMBLER_HEADER
76#include "MipsGenAsmMatcher.inc"
77
Matheus Almeida595fcab2014-06-11 15:05:56 +000078 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
79
Chad Rosier49963552012-10-13 00:26:04 +000080 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +000081 OperandVector &Operands, MCStreamer &Out,
82 unsigned &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +000083 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +000084
Daniel Sandersb50ccf82014-04-01 10:35:28 +000085 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +000086 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +000087
David Blaikie960ea3f2014-06-08 16:18:35 +000088 bool ParseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +000089
David Blaikie960ea3f2014-06-08 16:18:35 +000090 bool ParseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +000091
David Blaikie960ea3f2014-06-08 16:18:35 +000092 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
93 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +000094
Craig Topper56c590a2014-04-29 07:58:02 +000095 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +000096
David Blaikie960ea3f2014-06-08 16:18:35 +000097 MipsAsmParser::OperandMatchResultTy parseMemOperand(OperandVector &Operands);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +000098
99 MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +0000100 MatchAnyRegisterNameWithoutDollar(OperandVector &Operands,
101 StringRef Identifier, SMLoc S);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000102
Jack Carter873c7242013-01-12 01:03:14 +0000103 MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +0000104 MatchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S);
Jack Carter873c7242013-01-12 01:03:14 +0000105
David Blaikie960ea3f2014-06-08 16:18:35 +0000106 MipsAsmParser::OperandMatchResultTy ParseAnyRegister(OperandVector &Operands);
Jack Carter873c7242013-01-12 01:03:14 +0000107
David Blaikie960ea3f2014-06-08 16:18:35 +0000108 MipsAsmParser::OperandMatchResultTy ParseImm(OperandVector &Operands);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000109
David Blaikie960ea3f2014-06-08 16:18:35 +0000110 MipsAsmParser::OperandMatchResultTy ParseJumpTarget(OperandVector &Operands);
Vladimir Medic2b953d02013-10-01 09:48:56 +0000111
David Blaikie960ea3f2014-06-08 16:18:35 +0000112 MipsAsmParser::OperandMatchResultTy parseInvNum(OperandVector &Operands);
Matheus Almeida779c5932013-11-18 12:32:49 +0000113
David Blaikie960ea3f2014-06-08 16:18:35 +0000114 MipsAsmParser::OperandMatchResultTy ParseLSAImm(OperandVector &Operands);
Jack Carterd76b2372013-03-21 21:44:16 +0000115
David Blaikie960ea3f2014-06-08 16:18:35 +0000116 bool searchSymbolAlias(OperandVector &Operands);
117
118 bool ParseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000119
Jack Carter30a59822012-10-04 04:03:53 +0000120 bool needsExpansion(MCInst &Inst);
121
Matheus Almeida3813d572014-06-19 14:39:14 +0000122 // Expands assembly pseudo instructions.
123 // Returns false on success, true otherwise.
124 bool expandInstruction(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 expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000128 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000129
130 bool expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000131 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000132
133 bool expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000134 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000135
Jack Carter9e65aa32013-03-22 00:05:30 +0000136 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000137 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
138 bool isImmOpnd);
Jack Carter0b744b32012-10-04 02:29:46 +0000139 bool reportParseError(StringRef ErrorMsg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +0000140 bool reportParseError(SMLoc Loc, StringRef ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000141
Jack Carterb5cf5902013-04-17 00:18:04 +0000142 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000143 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000144
Vladimir Medic4c299852013-11-06 11:27:05 +0000145 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000146
147 bool isEvaluated(const MCExpr *Expr);
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000148 bool parseSetFeature(uint64_t Feature);
Matheus Almeida525bc4f2014-04-30 11:28:42 +0000149 bool parseDirectiveCPLoad(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000150 bool parseDirectiveCPSetup();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000151 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000152 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000153 bool parseDirectiveOption();
Jack Carter0b744b32012-10-04 02:29:46 +0000154
155 bool parseSetAtDirective();
156 bool parseSetNoAtDirective();
157 bool parseSetMacroDirective();
158 bool parseSetNoMacroDirective();
159 bool parseSetReorderDirective();
160 bool parseSetNoReorderDirective();
Jack Carter39536722014-01-22 23:08:42 +0000161 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000162 bool parseSetFpDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000163
Jack Carterd76b2372013-03-21 21:44:16 +0000164 bool parseSetAssignment();
165
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000166 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000167 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000168 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000169 bool parseDirectiveModule();
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);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000239 }
240
Jack Carterb4dbc172012-09-05 23:34:03 +0000241 MCAsmParser &getParser() const { return Parser; }
242 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000243
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000244 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
245 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
246
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000247 bool isGP64bit() const { return STI.getFeatureBits() & Mips::FeatureGP64Bit; }
248 bool isFP64bit() const { return STI.getFeatureBits() & Mips::FeatureFP64Bit; }
249 bool isABI_N32() const { return STI.getFeatureBits() & Mips::FeatureN32; }
250 bool isABI_N64() const { return STI.getFeatureBits() & Mips::FeatureN64; }
251 bool isABI_O32() const { return STI.getFeatureBits() & Mips::FeatureO32; }
252 bool isABI_FPXX() const { return false; } // TODO: add check for FeatureXX
253
254 bool inMicroMipsMode() const {
255 return STI.getFeatureBits() & Mips::FeatureMicroMips;
256 }
257 bool hasMips1() const { return STI.getFeatureBits() & Mips::FeatureMips1; }
258 bool hasMips2() const { return STI.getFeatureBits() & Mips::FeatureMips2; }
259 bool hasMips3() const { return STI.getFeatureBits() & Mips::FeatureMips3; }
260 bool hasMips4() const { return STI.getFeatureBits() & Mips::FeatureMips4; }
261 bool hasMips5() const { return STI.getFeatureBits() & Mips::FeatureMips5; }
262 bool hasMips32() const {
263 return (STI.getFeatureBits() & Mips::FeatureMips32);
264 }
265 bool hasMips64() const {
266 return (STI.getFeatureBits() & Mips::FeatureMips64);
267 }
268 bool hasMips32r2() const {
269 return (STI.getFeatureBits() & Mips::FeatureMips32r2);
270 }
271 bool hasMips64r2() const {
272 return (STI.getFeatureBits() & Mips::FeatureMips64r2);
273 }
274 bool hasMips32r6() const {
275 return (STI.getFeatureBits() & Mips::FeatureMips32r6);
276 }
277 bool hasMips64r6() const {
278 return (STI.getFeatureBits() & Mips::FeatureMips64r6);
279 }
280 bool hasDSP() const { return (STI.getFeatureBits() & Mips::FeatureDSP); }
281 bool hasDSPR2() const { return (STI.getFeatureBits() & Mips::FeatureDSPR2); }
282 bool hasMSA() const { return (STI.getFeatureBits() & Mips::FeatureMSA); }
283
284 bool inMips16Mode() const {
285 return STI.getFeatureBits() & Mips::FeatureMips16;
286 }
287 // TODO: see how can we get this info.
288 bool mipsSEUsesSoftFloat() const { return false; }
289
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000290 /// Warn if RegNo is the current assembler temporary.
291 void WarnIfAssemblerTemporary(int RegNo, SMLoc Loc);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000292};
293}
294
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000295namespace {
296
297/// MipsOperand - Instances of this class represent a parsed Mips machine
298/// instruction.
299class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000300public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000301 /// Broad categories of register classes
302 /// The exact class is finalized by the render method.
303 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000304 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000305 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000306 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000307 RegKind_FCC = 4, /// FCC
308 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
309 RegKind_MSACtrl = 16, /// MSA control registers
310 RegKind_COP2 = 32, /// COP2
311 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
312 /// context).
313 RegKind_CCR = 128, /// CCR
314 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000315 RegKind_COP3 = 512, /// COP3
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000316
317 /// Potentially any (e.g. $1)
318 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
319 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000320 RegKind_CCR | RegKind_HWRegs | RegKind_COP3
Jack Carter873c7242013-01-12 01:03:14 +0000321 };
322
323private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000324 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000325 k_Immediate, /// An immediate (possibly involving symbol references)
326 k_Memory, /// Base + Offset Memory Address
327 k_PhysRegister, /// A physical register from the Mips namespace
328 k_RegisterIndex, /// A register index in one or more RegKind.
329 k_Token /// A simple token
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000330 } Kind;
331
David Blaikie960ea3f2014-06-08 16:18:35 +0000332public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000333 MipsOperand(KindTy K, MipsAsmParser &Parser)
334 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
335
David Blaikie960ea3f2014-06-08 16:18:35 +0000336private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000337 /// For diagnostics, and checking the assembler temporary
338 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000339
Eric Christopher8996c5d2013-03-15 00:42:55 +0000340 struct Token {
341 const char *Data;
342 unsigned Length;
343 };
344
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000345 struct PhysRegOp {
346 unsigned Num; /// Register Number
347 };
348
349 struct RegIdxOp {
350 unsigned Index; /// Index into the register class
351 RegKind Kind; /// Bitfield of the kinds it could possibly be
352 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000353 };
354
355 struct ImmOp {
356 const MCExpr *Val;
357 };
358
359 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000360 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000361 const MCExpr *Off;
362 };
363
Jack Carterb4dbc172012-09-05 23:34:03 +0000364 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000365 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000366 struct PhysRegOp PhysReg;
367 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000368 struct ImmOp Imm;
369 struct MemOp Mem;
Jack Carterb4dbc172012-09-05 23:34:03 +0000370 };
371
372 SMLoc StartLoc, EndLoc;
373
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000374 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000375 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
376 const MCRegisterInfo *RegInfo,
377 SMLoc S, SMLoc E,
378 MipsAsmParser &Parser) {
379 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000380 Op->RegIdx.Index = Index;
381 Op->RegIdx.RegInfo = RegInfo;
382 Op->RegIdx.Kind = RegKind;
383 Op->StartLoc = S;
384 Op->EndLoc = E;
385 return Op;
386 }
387
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000388public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000389 /// Coerce the register to GPR32 and return the real register for the current
390 /// target.
391 unsigned getGPR32Reg() const {
392 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
393 AsmParser.WarnIfAssemblerTemporary(RegIdx.Index, StartLoc);
394 unsigned ClassID = Mips::GPR32RegClassID;
395 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000396 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000397
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000398 /// Coerce the register to GPR64 and return the real register for the current
399 /// target.
400 unsigned getGPR64Reg() const {
401 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
402 unsigned ClassID = Mips::GPR64RegClassID;
403 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000404 }
405
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000406private:
407 /// Coerce the register to AFGR64 and return the real register for the current
408 /// target.
409 unsigned getAFGR64Reg() const {
410 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
411 if (RegIdx.Index % 2 != 0)
412 AsmParser.Warning(StartLoc, "Float register should be even.");
413 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
414 .getRegister(RegIdx.Index / 2);
415 }
416
417 /// Coerce the register to FGR64 and return the real register for the current
418 /// target.
419 unsigned getFGR64Reg() const {
420 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
421 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
422 .getRegister(RegIdx.Index);
423 }
424
425 /// Coerce the register to FGR32 and return the real register for the current
426 /// target.
427 unsigned getFGR32Reg() const {
428 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
429 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
430 .getRegister(RegIdx.Index);
431 }
432
433 /// Coerce the register to FGRH32 and return the real register for the current
434 /// target.
435 unsigned getFGRH32Reg() const {
436 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
437 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
438 .getRegister(RegIdx.Index);
439 }
440
441 /// Coerce the register to FCC and return the real register for the current
442 /// target.
443 unsigned getFCCReg() const {
444 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
445 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
446 .getRegister(RegIdx.Index);
447 }
448
449 /// Coerce the register to MSA128 and return the real register for the current
450 /// target.
451 unsigned getMSA128Reg() const {
452 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
453 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
454 // identical
455 unsigned ClassID = Mips::MSA128BRegClassID;
456 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
457 }
458
459 /// Coerce the register to MSACtrl and return the real register for the
460 /// current target.
461 unsigned getMSACtrlReg() const {
462 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
463 unsigned ClassID = Mips::MSACtrlRegClassID;
464 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
465 }
466
467 /// Coerce the register to COP2 and return the real register for the
468 /// current target.
469 unsigned getCOP2Reg() const {
470 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
471 unsigned ClassID = Mips::COP2RegClassID;
472 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
473 }
474
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000475 /// Coerce the register to COP3 and return the real register for the
476 /// current target.
477 unsigned getCOP3Reg() const {
478 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
479 unsigned ClassID = Mips::COP3RegClassID;
480 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
481 }
482
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000483 /// Coerce the register to ACC64DSP and return the real register for the
484 /// current target.
485 unsigned getACC64DSPReg() const {
486 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
487 unsigned ClassID = Mips::ACC64DSPRegClassID;
488 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
489 }
490
491 /// Coerce the register to HI32DSP and return the real register for the
492 /// current target.
493 unsigned getHI32DSPReg() const {
494 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
495 unsigned ClassID = Mips::HI32DSPRegClassID;
496 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
497 }
498
499 /// Coerce the register to LO32DSP and return the real register for the
500 /// current target.
501 unsigned getLO32DSPReg() const {
502 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
503 unsigned ClassID = Mips::LO32DSPRegClassID;
504 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
505 }
506
507 /// Coerce the register to CCR and return the real register for the
508 /// current target.
509 unsigned getCCRReg() const {
510 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
511 unsigned ClassID = Mips::CCRRegClassID;
512 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
513 }
514
515 /// Coerce the register to HWRegs and return the real register for the
516 /// current target.
517 unsigned getHWRegsReg() const {
518 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
519 unsigned ClassID = Mips::HWRegsRegClassID;
520 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
521 }
522
523public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000524 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000525 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000526 if (!Expr)
Jack Carterb4dbc172012-09-05 23:34:03 +0000527 Inst.addOperand(MCOperand::CreateImm(0));
528 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
529 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
530 else
531 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000532 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000533
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000534 void addRegOperands(MCInst &Inst, unsigned N) const {
535 llvm_unreachable("Use a custom parser instead");
536 }
537
Daniel Sanders21bce302014-04-01 12:35:23 +0000538 /// Render the operand to an MCInst as a GPR32
539 /// Asserts if the wrong number of operands are requested, or the operand
540 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000541 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
542 assert(N == 1 && "Invalid number of operands!");
543 Inst.addOperand(MCOperand::CreateReg(getGPR32Reg()));
544 }
545
Daniel Sanders21bce302014-04-01 12:35:23 +0000546 /// Render the operand to an MCInst as a GPR64
547 /// Asserts if the wrong number of operands are requested, or the operand
548 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000549 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
550 assert(N == 1 && "Invalid number of operands!");
551 Inst.addOperand(MCOperand::CreateReg(getGPR64Reg()));
552 }
553
554 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
555 assert(N == 1 && "Invalid number of operands!");
556 Inst.addOperand(MCOperand::CreateReg(getAFGR64Reg()));
557 }
558
559 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
560 assert(N == 1 && "Invalid number of operands!");
561 Inst.addOperand(MCOperand::CreateReg(getFGR64Reg()));
562 }
563
564 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
565 assert(N == 1 && "Invalid number of operands!");
566 Inst.addOperand(MCOperand::CreateReg(getFGR32Reg()));
567 }
568
569 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
570 assert(N == 1 && "Invalid number of operands!");
571 Inst.addOperand(MCOperand::CreateReg(getFGRH32Reg()));
572 }
573
574 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
575 assert(N == 1 && "Invalid number of operands!");
576 Inst.addOperand(MCOperand::CreateReg(getFCCReg()));
577 }
578
579 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
580 assert(N == 1 && "Invalid number of operands!");
581 Inst.addOperand(MCOperand::CreateReg(getMSA128Reg()));
582 }
583
584 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
585 assert(N == 1 && "Invalid number of operands!");
586 Inst.addOperand(MCOperand::CreateReg(getMSACtrlReg()));
587 }
588
589 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
590 assert(N == 1 && "Invalid number of operands!");
591 Inst.addOperand(MCOperand::CreateReg(getCOP2Reg()));
592 }
593
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000594 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
595 assert(N == 1 && "Invalid number of operands!");
596 Inst.addOperand(MCOperand::CreateReg(getCOP3Reg()));
597 }
598
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000599 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
600 assert(N == 1 && "Invalid number of operands!");
601 Inst.addOperand(MCOperand::CreateReg(getACC64DSPReg()));
602 }
603
604 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
605 assert(N == 1 && "Invalid number of operands!");
606 Inst.addOperand(MCOperand::CreateReg(getHI32DSPReg()));
607 }
608
609 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
610 assert(N == 1 && "Invalid number of operands!");
611 Inst.addOperand(MCOperand::CreateReg(getLO32DSPReg()));
612 }
613
614 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
615 assert(N == 1 && "Invalid number of operands!");
616 Inst.addOperand(MCOperand::CreateReg(getCCRReg()));
617 }
618
619 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
620 assert(N == 1 && "Invalid number of operands!");
621 Inst.addOperand(MCOperand::CreateReg(getHWRegsReg()));
622 }
623
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000624 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000625 assert(N == 1 && "Invalid number of operands!");
626 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000627 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000628 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000629
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000630 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000631 assert(N == 2 && "Invalid number of operands!");
632
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000633 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000634
635 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000636 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000637 }
638
Craig Topper56c590a2014-04-29 07:58:02 +0000639 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000640 // As a special case until we sort out the definition of div/divu, pretend
641 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
642 if (isGPRAsmReg() && RegIdx.Index == 0)
643 return true;
644
645 return Kind == k_PhysRegister;
646 }
647 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000648 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000649 bool isConstantImm() const {
650 return isImm() && dyn_cast<MCConstantExpr>(getImm());
651 }
Craig Topper56c590a2014-04-29 07:58:02 +0000652 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000653 // Note: It's not possible to pretend that other operand kinds are tokens.
654 // The matcher emitter checks tokens first.
655 return Kind == k_Token;
656 }
Craig Topper56c590a2014-04-29 07:58:02 +0000657 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000658 bool isConstantMemOff() const {
659 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
660 }
661 template <unsigned Bits> bool isMemWithSimmOffset() const {
662 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff());
663 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000664 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000665 bool isLSAImm() const {
666 if (!isConstantImm())
667 return false;
668 int64_t Val = getConstantImm();
669 return 1 <= Val && Val <= 4;
670 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000671
672 StringRef getToken() const {
673 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000674 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000675 }
676
Craig Topper56c590a2014-04-29 07:58:02 +0000677 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000678 // As a special case until we sort out the definition of div/divu, pretend
679 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
680 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
681 RegIdx.Kind & RegKind_GPR)
682 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000683
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000684 assert(Kind == k_PhysRegister && "Invalid access!");
685 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +0000686 }
687
Jack Carterb4dbc172012-09-05 23:34:03 +0000688 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000689 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000690 return Imm.Val;
691 }
692
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000693 int64_t getConstantImm() const {
694 const MCExpr *Val = getImm();
695 return static_cast<const MCConstantExpr *>(Val)->getValue();
696 }
697
698 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000699 assert((Kind == k_Memory) && "Invalid access!");
700 return Mem.Base;
701 }
702
703 const MCExpr *getMemOff() const {
704 assert((Kind == k_Memory) && "Invalid access!");
705 return Mem.Off;
706 }
707
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000708 int64_t getConstantMemOff() const {
709 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
710 }
711
David Blaikie960ea3f2014-06-08 16:18:35 +0000712 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
713 MipsAsmParser &Parser) {
714 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000715 Op->Tok.Data = Str.data();
716 Op->Tok.Length = Str.size();
717 Op->StartLoc = S;
718 Op->EndLoc = S;
719 return Op;
720 }
721
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000722 /// Create a numeric register (e.g. $1). The exact register remains
723 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +0000724 static std::unique_ptr<MipsOperand>
725 CreateNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
726 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000727 DEBUG(dbgs() << "CreateNumericReg(" << Index << ", ...)\n");
728 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000729 }
730
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000731 /// Create a register that is definitely a GPR.
732 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +0000733 static std::unique_ptr<MipsOperand>
734 CreateGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
735 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000736 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000737 }
738
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000739 /// Create a register that is definitely a FGR.
740 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000741 static std::unique_ptr<MipsOperand>
742 CreateFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
743 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000744 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
745 }
746
747 /// Create a register that is definitely an FCC.
748 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000749 static std::unique_ptr<MipsOperand>
750 CreateFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
751 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000752 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
753 }
754
755 /// Create a register that is definitely an ACC.
756 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000757 static std::unique_ptr<MipsOperand>
758 CreateACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
759 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000760 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
761 }
762
763 /// Create a register that is definitely an MSA128.
764 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000765 static std::unique_ptr<MipsOperand>
766 CreateMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
767 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000768 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
769 }
770
771 /// Create a register that is definitely an MSACtrl.
772 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +0000773 static std::unique_ptr<MipsOperand>
774 CreateMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
775 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000776 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
777 }
778
David Blaikie960ea3f2014-06-08 16:18:35 +0000779 static std::unique_ptr<MipsOperand>
780 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
781 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000782 Op->Imm.Val = Val;
783 Op->StartLoc = S;
784 Op->EndLoc = E;
785 return Op;
786 }
787
David Blaikie960ea3f2014-06-08 16:18:35 +0000788 static std::unique_ptr<MipsOperand>
789 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
790 SMLoc E, MipsAsmParser &Parser) {
791 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
792 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +0000793 Op->Mem.Off = Off;
794 Op->StartLoc = S;
795 Op->EndLoc = E;
796 return Op;
797 }
798
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000799 bool isGPRAsmReg() const {
800 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000801 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000802 bool isFGRAsmReg() const {
803 // AFGR64 is $0-$15 but we handle this in getAFGR64()
804 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000805 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000806 bool isHWRegsAsmReg() const {
807 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000808 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000809 bool isCCRAsmReg() const {
810 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000811 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000812 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000813 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
814 return false;
815 if (!AsmParser.hasEightFccRegisters())
816 return RegIdx.Index == 0;
817 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +0000818 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000819 bool isACCAsmReg() const {
820 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +0000821 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000822 bool isCOP2AsmReg() const {
823 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +0000824 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000825 bool isCOP3AsmReg() const {
826 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
827 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000828 bool isMSA128AsmReg() const {
829 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +0000830 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000831 bool isMSACtrlAsmReg() const {
832 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000833 }
834
Jack Carterb4dbc172012-09-05 23:34:03 +0000835 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +0000836 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +0000837 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +0000838 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +0000839
NAKAMURA Takumie1f35832014-04-15 14:13:21 +0000840 virtual ~MipsOperand() {
841 switch (Kind) {
842 case k_Immediate:
843 break;
844 case k_Memory:
845 delete Mem.Base;
846 break;
847 case k_PhysRegister:
848 case k_RegisterIndex:
849 case k_Token:
850 break;
851 }
852 }
853
Craig Topper56c590a2014-04-29 07:58:02 +0000854 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000855 switch (Kind) {
856 case k_Immediate:
857 OS << "Imm<";
858 Imm.Val->print(OS);
859 OS << ">";
860 break;
861 case k_Memory:
862 OS << "Mem<";
863 Mem.Base->print(OS);
864 OS << ", ";
865 Mem.Off->print(OS);
866 OS << ">";
867 break;
868 case k_PhysRegister:
869 OS << "PhysReg<" << PhysReg.Num << ">";
870 break;
871 case k_RegisterIndex:
872 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
873 break;
874 case k_Token:
875 OS << Tok.Data;
876 break;
877 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000878 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000879}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +0000880} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000881
Jack Carter9e65aa32013-03-22 00:05:30 +0000882namespace llvm {
883extern const MCInstrDesc MipsInsts[];
884}
885static const MCInstrDesc &getInstDesc(unsigned Opcode) {
886 return MipsInsts[Opcode];
887}
888
889bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +0000890 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000891 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +0000892
Jack Carter9e65aa32013-03-22 00:05:30 +0000893 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000894
895 if (MCID.isBranch() || MCID.isCall()) {
896 const unsigned Opcode = Inst.getOpcode();
897 MCOperand Offset;
898
899 switch (Opcode) {
900 default:
901 break;
902 case Mips::BEQ:
903 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000904 case Mips::BEQ_MM:
905 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +0000906 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000907 Offset = Inst.getOperand(2);
908 if (!Offset.isImm())
909 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000910 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000911 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000912 if (OffsetToAlignment(Offset.getImm(),
913 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000914 return Error(IDLoc, "branch to misaligned address");
915 break;
916 case Mips::BGEZ:
917 case Mips::BGTZ:
918 case Mips::BLEZ:
919 case Mips::BLTZ:
920 case Mips::BGEZAL:
921 case Mips::BLTZAL:
922 case Mips::BC1F:
923 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000924 case Mips::BGEZ_MM:
925 case Mips::BGTZ_MM:
926 case Mips::BLEZ_MM:
927 case Mips::BLTZ_MM:
928 case Mips::BGEZAL_MM:
929 case Mips::BLTZAL_MM:
930 case Mips::BC1F_MM:
931 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +0000932 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000933 Offset = Inst.getOperand(1);
934 if (!Offset.isImm())
935 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000936 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000937 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000938 if (OffsetToAlignment(Offset.getImm(),
939 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000940 return Error(IDLoc, "branch to misaligned address");
941 break;
942 }
943 }
944
Daniel Sandersa84989a2014-06-16 13:25:35 +0000945 // SSNOP is deprecated on MIPS32r6/MIPS64r6
946 // We still accept it but it is a normal nop.
947 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
948 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
949 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
950 "nop instruction");
951 }
952
Jack Carterc15c1d22013-04-25 23:31:35 +0000953 if (MCID.hasDelaySlot() && Options.isReorder()) {
954 // If this instruction has a delay slot and .set reorder is active,
955 // emit a NOP after it.
956 Instructions.push_back(Inst);
957 MCInst NopInst;
958 NopInst.setOpcode(Mips::SLL);
959 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
960 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
961 NopInst.addOperand(MCOperand::CreateImm(0));
962 Instructions.push_back(NopInst);
963 return false;
964 }
965
Jack Carter9e65aa32013-03-22 00:05:30 +0000966 if (MCID.mayLoad() || MCID.mayStore()) {
967 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +0000968 // reference or immediate we may have to expand instructions.
969 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000970 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +0000971 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
972 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000973 MCOperand &Op = Inst.getOperand(i);
974 if (Op.isImm()) {
975 int MemOffset = Op.getImm();
976 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000977 // Offset can't exceed 16bit value.
978 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +0000979 return false;
980 }
981 } else if (Op.isExpr()) {
982 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +0000983 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000984 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +0000985 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +0000986 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000987 // Expand symbol.
988 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +0000989 return false;
990 }
Jack Carterb5cf5902013-04-17 00:18:04 +0000991 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000992 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +0000993 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +0000994 }
995 }
996 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000997 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +0000998 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +0000999
1000 if (needsExpansion(Inst))
Matheus Almeida3813d572014-06-19 14:39:14 +00001001 return expandInstruction(Inst, IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +00001002 else
1003 Instructions.push_back(Inst);
1004
1005 return false;
1006}
1007
Jack Carter30a59822012-10-04 04:03:53 +00001008bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1009
Jack Carterd0bd6422013-04-18 00:41:53 +00001010 switch (Inst.getOpcode()) {
1011 case Mips::LoadImm32Reg:
1012 case Mips::LoadAddr32Imm:
1013 case Mips::LoadAddr32Reg:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001014 case Mips::LoadImm64Reg:
Jack Carterd0bd6422013-04-18 00:41:53 +00001015 return true;
1016 default:
1017 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001018 }
1019}
Jack Carter92995f12012-10-06 00:53:28 +00001020
Matheus Almeida3813d572014-06-19 14:39:14 +00001021bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001022 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001023 switch (Inst.getOpcode()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001024 default:
1025 assert(0 && "unimplemented expansion");
Matheus Almeida3813d572014-06-19 14:39:14 +00001026 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001027 case Mips::LoadImm32Reg:
1028 return expandLoadImm(Inst, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001029 case Mips::LoadImm64Reg:
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001030 if (!isGP64bit()) {
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001031 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1032 return true;
1033 }
1034 return expandLoadImm(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001035 case Mips::LoadAddr32Imm:
1036 return expandLoadAddressImm(Inst, IDLoc, Instructions);
1037 case Mips::LoadAddr32Reg:
1038 return expandLoadAddressReg(Inst, IDLoc, Instructions);
1039 }
Jack Carter30a59822012-10-04 04:03:53 +00001040}
Jack Carter92995f12012-10-06 00:53:28 +00001041
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001042namespace {
1043template <int Shift, bool PerformShift>
1044void createShiftOr(int64_t Value, unsigned RegNo, SMLoc IDLoc,
1045 SmallVectorImpl<MCInst> &Instructions) {
1046 MCInst tmpInst;
1047 if (PerformShift) {
1048 tmpInst.setOpcode(Mips::DSLL);
1049 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1050 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1051 tmpInst.addOperand(MCOperand::CreateImm(16));
1052 tmpInst.setLoc(IDLoc);
1053 Instructions.push_back(tmpInst);
1054 tmpInst.clear();
1055 }
1056 tmpInst.setOpcode(Mips::ORi);
1057 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1058 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1059 tmpInst.addOperand(
1060 MCOperand::CreateImm(((Value & (0xffffLL << Shift)) >> Shift)));
1061 tmpInst.setLoc(IDLoc);
1062 Instructions.push_back(tmpInst);
1063}
1064}
1065
Matheus Almeida3813d572014-06-19 14:39:14 +00001066bool MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001067 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +00001068 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +00001069 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +00001070 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +00001071 const MCOperand &RegOp = Inst.getOperand(0);
1072 assert(RegOp.isReg() && "expected register operand kind");
1073
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001074 int64_t ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +00001075 tmpInst.setLoc(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001076 // FIXME: gas has a special case for values that are 000...1111, which
1077 // becomes a li -1 and then a dsrl
Jack Carterd0bd6422013-04-18 00:41:53 +00001078 if (0 <= ImmValue && ImmValue <= 65535) {
1079 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +00001080 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001081 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +00001082 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001083 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001084 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001085 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001086 } else if (ImmValue < 0 && ImmValue >= -32768) {
1087 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +00001088 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001089 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +00001090 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001091 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001092 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001093 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001094 } else if ((ImmValue & 0xffffffff) == ImmValue) {
1095 // For any value of j that is representable as a 32-bit integer, create
1096 // a sequence of:
Jack Carter30a59822012-10-04 04:03:53 +00001097 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001098 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001099 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001100 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1101 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +00001102 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001103 createShiftOr<0, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1104 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001105 if (!isGP64bit()) {
1106 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001107 return true;
1108 }
1109
1110 // <------- lo32 ------>
1111 // <------- hi32 ------>
1112 // <- hi16 -> <- lo16 ->
1113 // _________________________________
1114 // | | | |
1115 // | 16-bytes | 16-bytes | 16-bytes |
1116 // |__________|__________|__________|
1117 //
1118 // For any value of j that is representable as a 48-bit integer, create
1119 // a sequence of:
1120 // li d,j => lui d,hi16(j)
1121 // ori d,d,hi16(lo32(j))
1122 // dsll d,d,16
1123 // ori d,d,lo16(lo32(j))
1124 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001125 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001126 tmpInst.addOperand(
1127 MCOperand::CreateImm((ImmValue & (0xffffLL << 32)) >> 32));
Jack Carter30a59822012-10-04 04:03:53 +00001128 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001129 createShiftOr<16, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1130 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1131 } else {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001132 if (!isGP64bit()) {
1133 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001134 return true;
1135 }
1136
1137 // <------- hi32 ------> <------- lo32 ------>
1138 // <- hi16 -> <- lo16 ->
1139 // ___________________________________________
1140 // | | | | |
1141 // | 16-bytes | 16-bytes | 16-bytes | 16-bytes |
1142 // |__________|__________|__________|__________|
1143 //
1144 // For any value of j that isn't representable as a 48-bit integer.
1145 // li d,j => lui d,hi16(j)
1146 // ori d,d,lo16(hi32(j))
1147 // dsll d,d,16
1148 // ori d,d,hi16(lo32(j))
1149 // dsll d,d,16
1150 // ori d,d,lo16(lo32(j))
1151 tmpInst.setOpcode(Mips::LUi);
1152 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1153 tmpInst.addOperand(
1154 MCOperand::CreateImm((ImmValue & (0xffffLL << 48)) >> 48));
1155 Instructions.push_back(tmpInst);
1156 createShiftOr<32, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1157 createShiftOr<16, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1158 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
Jack Carter30a59822012-10-04 04:03:53 +00001159 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001160 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001161}
Jack Carter92995f12012-10-06 00:53:28 +00001162
Matheus Almeida3813d572014-06-19 14:39:14 +00001163bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001164MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
1165 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001166 MCInst tmpInst;
1167 const MCOperand &ImmOp = Inst.getOperand(2);
1168 assert(ImmOp.isImm() && "expected immediate operand kind");
1169 const MCOperand &SrcRegOp = Inst.getOperand(1);
1170 assert(SrcRegOp.isReg() && "expected register operand kind");
1171 const MCOperand &DstRegOp = Inst.getOperand(0);
1172 assert(DstRegOp.isReg() && "expected register operand kind");
1173 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001174 if (-32768 <= ImmValue && ImmValue <= 65535) {
1175 // For -32768 <= j <= 65535.
1176 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +00001177 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +00001178 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1179 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1180 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1181 Instructions.push_back(tmpInst);
1182 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001183 // For any other value of j that is representable as a 32-bit integer.
1184 // la d,j(s) => lui d,hi16(j)
1185 // ori d,d,lo16(j)
1186 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +00001187 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001188 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1189 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1190 Instructions.push_back(tmpInst);
1191 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001192 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001193 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1194 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1195 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1196 Instructions.push_back(tmpInst);
1197 tmpInst.clear();
1198 tmpInst.setOpcode(Mips::ADDu);
1199 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1200 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1201 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1202 Instructions.push_back(tmpInst);
1203 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001204 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001205}
1206
Matheus Almeida3813d572014-06-19 14:39:14 +00001207bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001208MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1209 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001210 MCInst tmpInst;
1211 const MCOperand &ImmOp = Inst.getOperand(1);
1212 assert(ImmOp.isImm() && "expected immediate operand kind");
1213 const MCOperand &RegOp = Inst.getOperand(0);
1214 assert(RegOp.isReg() && "expected register operand kind");
1215 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001216 if (-32768 <= ImmValue && ImmValue <= 65535) {
1217 // For -32768 <= j <= 65535.
1218 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +00001219 tmpInst.setOpcode(Mips::ADDiu);
1220 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001221 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +00001222 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1223 Instructions.push_back(tmpInst);
1224 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001225 // For any other value of j that is representable as a 32-bit integer.
1226 // la d,j => lui d,hi16(j)
1227 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001228 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001229 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1230 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1231 Instructions.push_back(tmpInst);
1232 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001233 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001234 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1235 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1236 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1237 Instructions.push_back(tmpInst);
1238 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001239 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001240}
1241
Jack Carter9e65aa32013-03-22 00:05:30 +00001242void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001243 SmallVectorImpl<MCInst> &Instructions,
1244 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001245 const MCSymbolRefExpr *SR;
1246 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00001247 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00001248 const MCExpr *ExprOffset;
1249 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00001250 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001251 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1252 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001253 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001254 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1255 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001256 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00001257 if (isImmOpnd) {
1258 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
1259 ImmOffset = Inst.getOperand(2).getImm();
1260 LoOffset = ImmOffset & 0x0000ffff;
1261 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00001262 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00001263 if (LoOffset & 0x8000)
1264 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00001265 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001266 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001267 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00001268 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00001269 // These are some of the types of expansions we perform here:
1270 // 1) lw $8, sym => lui $8, %hi(sym)
1271 // lw $8, %lo(sym)($8)
1272 // 2) lw $8, offset($9) => lui $8, %hi(offset)
1273 // add $8, $8, $9
1274 // lw $8, %lo(offset)($9)
1275 // 3) lw $8, offset($8) => lui $at, %hi(offset)
1276 // add $at, $at, $8
1277 // lw $8, %lo(offset)($at)
1278 // 4) sw $8, sym => lui $at, %hi(sym)
1279 // sw $8, %lo(sym)($at)
1280 // 5) sw $8, offset($8) => lui $at, %hi(offset)
1281 // add $at, $at, $8
1282 // sw $8, %lo(offset)($at)
1283 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
1284 // ldc1 $f0, %lo(sym)($at)
1285 //
1286 // For load instructions we can use the destination register as a temporary
1287 // if base and dst are different (examples 1 and 2) and if the base register
1288 // is general purpose otherwise we must use $at (example 6) and error if it's
1289 // not available. For stores we must use $at (examples 4 and 5) because we
1290 // must not clobber the source register setting up the offset.
1291 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
1292 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
1293 unsigned RegClassIDOp0 =
1294 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
1295 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
1296 (RegClassIDOp0 == Mips::GPR64RegClassID);
1297 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00001298 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00001299 else {
1300 int AT = getATReg(IDLoc);
1301 // At this point we need AT to perform the expansions and we exit if it is
1302 // not available.
1303 if (!AT)
1304 return;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001305 TmpRegNum = getReg(
1306 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, AT);
Matheus Almeida7de68e72014-06-18 14:46:05 +00001307 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00001308
Jack Carter9e65aa32013-03-22 00:05:30 +00001309 TempInst.setOpcode(Mips::LUi);
1310 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1311 if (isImmOpnd)
1312 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
1313 else {
1314 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001315 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00001316 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
1317 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
1318 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001319 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001320 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001321 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00001322 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001323 }
1324 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001325 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00001326 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001327 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00001328 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00001329 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001330 TempInst.setOpcode(Mips::ADDu);
1331 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1332 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1333 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
1334 Instructions.push_back(TempInst);
1335 TempInst.clear();
Alp Tokercb402912014-01-24 17:20:08 +00001336 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00001337 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001338 TempInst.setOpcode(Inst.getOpcode());
1339 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
1340 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1341 if (isImmOpnd)
1342 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
1343 else {
1344 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001345 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
1346 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
1347 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001348 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001349 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001350 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00001351 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001352 }
1353 }
1354 Instructions.push_back(TempInst);
1355 TempInst.clear();
1356}
1357
Matheus Almeida595fcab2014-06-11 15:05:56 +00001358unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1359 // As described by the Mips32r2 spec, the registers Rd and Rs for
1360 // jalr.hb must be different.
1361 unsigned Opcode = Inst.getOpcode();
1362
1363 if (Opcode == Mips::JALR_HB &&
1364 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
1365 return Match_RequiresDifferentSrcAndDst;
1366
1367 return Match_Success;
1368}
1369
David Blaikie960ea3f2014-06-08 16:18:35 +00001370bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1371 OperandVector &Operands,
1372 MCStreamer &Out,
1373 unsigned &ErrorInfo,
1374 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00001375
Jack Carterb4dbc172012-09-05 23:34:03 +00001376 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00001377 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00001378 unsigned MatchResult =
1379 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00001380
1381 switch (MatchResult) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001382 default:
1383 break;
Jack Carterb4dbc172012-09-05 23:34:03 +00001384 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001385 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00001386 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001387 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00001388 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00001389 return false;
1390 }
1391 case Match_MissingFeature:
1392 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1393 return true;
1394 case Match_InvalidOperand: {
1395 SMLoc ErrorLoc = IDLoc;
1396 if (ErrorInfo != ~0U) {
1397 if (ErrorInfo >= Operands.size())
1398 return Error(IDLoc, "too few operands for instruction");
1399
David Blaikie960ea3f2014-06-08 16:18:35 +00001400 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001401 if (ErrorLoc == SMLoc())
1402 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00001403 }
1404
1405 return Error(ErrorLoc, "invalid operand for instruction");
1406 }
1407 case Match_MnemonicFail:
1408 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00001409 case Match_RequiresDifferentSrcAndDst:
1410 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00001411 }
Rafael Espindola870c4e92012-01-11 03:56:41 +00001412 return true;
1413}
1414
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001415void MipsAsmParser::WarnIfAssemblerTemporary(int RegIndex, SMLoc Loc) {
1416 if ((RegIndex != 0) && ((int)Options.getATRegNum() == RegIndex)) {
1417 if (RegIndex == 1)
1418 Warning(Loc, "Used $at without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001419 else
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001420 Warning(Loc, Twine("Used $") + Twine(RegIndex) + " with \".set at=$" +
1421 Twine(RegIndex) + "\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001422 }
1423}
1424
Jack Carter1ac53222013-02-20 23:11:17 +00001425int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001426 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00001427
Vladimir Medic4c299852013-11-06 11:27:05 +00001428 CC = StringSwitch<unsigned>(Name)
1429 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001430 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00001431 .Case("a0", 4)
1432 .Case("a1", 5)
1433 .Case("a2", 6)
1434 .Case("a3", 7)
1435 .Case("v0", 2)
1436 .Case("v1", 3)
1437 .Case("s0", 16)
1438 .Case("s1", 17)
1439 .Case("s2", 18)
1440 .Case("s3", 19)
1441 .Case("s4", 20)
1442 .Case("s5", 21)
1443 .Case("s6", 22)
1444 .Case("s7", 23)
1445 .Case("k0", 26)
1446 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001447 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00001448 .Case("sp", 29)
1449 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001450 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00001451 .Case("ra", 31)
1452 .Case("t0", 8)
1453 .Case("t1", 9)
1454 .Case("t2", 10)
1455 .Case("t3", 11)
1456 .Case("t4", 12)
1457 .Case("t5", 13)
1458 .Case("t6", 14)
1459 .Case("t7", 15)
1460 .Case("t8", 24)
1461 .Case("t9", 25)
1462 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00001463
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001464 if (isABI_N32() || isABI_N64()) {
Daniel Sandersa4b0c742014-03-26 11:39:07 +00001465 // Although SGI documentation just cuts out t0-t3 for n32/n64,
1466 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
1467 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
1468 if (8 <= CC && CC <= 11)
1469 CC += 4;
Jack Carter1ac53222013-02-20 23:11:17 +00001470
Daniel Sandersa4b0c742014-03-26 11:39:07 +00001471 if (CC == -1)
1472 CC = StringSwitch<unsigned>(Name)
1473 .Case("a4", 8)
1474 .Case("a5", 9)
1475 .Case("a6", 10)
1476 .Case("a7", 11)
1477 .Case("kt0", 26)
1478 .Case("kt1", 27)
1479 .Default(-1);
1480 }
Jack Carter1ac53222013-02-20 23:11:17 +00001481
1482 return CC;
1483}
Jack Carterd0bd6422013-04-18 00:41:53 +00001484
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001485int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001486
Jack Cartera63b16a2012-09-07 00:23:42 +00001487 if (Name[0] == 'f') {
1488 StringRef NumString = Name.substr(1);
1489 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001490 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001491 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001492 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00001493 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001494 return IntVal;
1495 }
1496 return -1;
1497}
Jack Cartera63b16a2012-09-07 00:23:42 +00001498
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001499int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
1500
1501 if (Name.startswith("fcc")) {
1502 StringRef NumString = Name.substr(3);
1503 unsigned IntVal;
1504 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001505 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001506 if (IntVal > 7) // There are only 8 fcc registers.
1507 return -1;
1508 return IntVal;
1509 }
1510 return -1;
1511}
1512
1513int MipsAsmParser::matchACRegisterName(StringRef Name) {
1514
Akira Hatanaka274d24c2013-08-14 01:15:52 +00001515 if (Name.startswith("ac")) {
1516 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001517 unsigned IntVal;
1518 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001519 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001520 if (IntVal > 3) // There are only 3 acc registers.
1521 return -1;
1522 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00001523 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001524 return -1;
1525}
Jack Carterd0bd6422013-04-18 00:41:53 +00001526
Jack Carter5dc8ac92013-09-25 23:50:44 +00001527int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
1528 unsigned IntVal;
1529
1530 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
1531 return -1;
1532
1533 if (IntVal > 31)
1534 return -1;
1535
1536 return IntVal;
1537}
1538
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001539int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
1540 int CC;
1541
1542 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00001543 .Case("msair", 0)
1544 .Case("msacsr", 1)
1545 .Case("msaaccess", 2)
1546 .Case("msasave", 3)
1547 .Case("msamodify", 4)
1548 .Case("msarequest", 5)
1549 .Case("msamap", 6)
1550 .Case("msaunmap", 7)
1551 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001552
1553 return CC;
1554}
1555
Jack Carter0b744b32012-10-04 02:29:46 +00001556bool MipsAssemblerOptions::setATReg(unsigned Reg) {
1557 if (Reg > 31)
1558 return false;
1559
1560 aTReg = Reg;
1561 return true;
1562}
1563
Matheus Almeida7de68e72014-06-18 14:46:05 +00001564int MipsAsmParser::getATReg(SMLoc Loc) {
Daniel Sandersd89b1362014-03-24 16:48:01 +00001565 int AT = Options.getATRegNum();
1566 if (AT == 0)
Matheus Almeida7de68e72014-06-18 14:46:05 +00001567 reportParseError(Loc,
1568 "Pseudo instruction requires $at, which is not available");
Daniel Sandersd89b1362014-03-24 16:48:01 +00001569 return AT;
1570}
Jack Carter0b744b32012-10-04 02:29:46 +00001571
Jack Carterd0bd6422013-04-18 00:41:53 +00001572unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00001573 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00001574}
1575
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001576unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001577 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00001578 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001579}
1580
Jack Carter873c7242013-01-12 01:03:14 +00001581int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001582 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00001583 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00001584 return -1;
1585
Jack Carter873c7242013-01-12 01:03:14 +00001586 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00001587}
1588
David Blaikie960ea3f2014-06-08 16:18:35 +00001589bool MipsAsmParser::ParseOperand(OperandVector &Operands, StringRef Mnemonic) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001590 DEBUG(dbgs() << "ParseOperand\n");
1591
Jack Carter30a59822012-10-04 04:03:53 +00001592 // Check if the current operand has a custom associated parser, if so, try to
1593 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00001594 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
1595 if (ResTy == MatchOperand_Success)
1596 return false;
1597 // If there wasn't a custom match, try the generic matcher below. Otherwise,
1598 // there was a match, but an error occurred, in which case, just return that
1599 // the operand parsing failed.
1600 if (ResTy == MatchOperand_ParseFail)
1601 return true;
1602
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001603 DEBUG(dbgs() << ".. Generic Parser\n");
1604
Jack Carterb4dbc172012-09-05 23:34:03 +00001605 switch (getLexer().getKind()) {
1606 default:
1607 Error(Parser.getTok().getLoc(), "unexpected token in operand");
1608 return true;
1609 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001610 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00001611 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00001612
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001613 // Almost all registers have been parsed by custom parsers. There is only
1614 // one exception to this. $zero (and it's alias $0) will reach this point
1615 // for div, divu, and similar instructions because it is not an operand
1616 // to the instruction definition but an explicit register. Special case
1617 // this situation for now.
1618 if (ParseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00001619 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001620
Jack Carterd0bd6422013-04-18 00:41:53 +00001621 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00001622 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001623 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00001624 return true;
1625
Jack Carter873c7242013-01-12 01:03:14 +00001626 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00001627 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00001628 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00001629 const MCExpr *Res =
1630 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00001631
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001632 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00001633 return false;
1634 }
Vladimir Medic4c299852013-11-06 11:27:05 +00001635 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00001636 case AsmToken::LParen:
1637 case AsmToken::Minus:
1638 case AsmToken::Plus:
1639 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00001640 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00001641 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001642 DEBUG(dbgs() << ".. generic integer\n");
1643 OperandMatchResultTy ResTy = ParseImm(Operands);
1644 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00001645 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00001646 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001647 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001648 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001649 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00001650 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00001651 return true;
1652
Jack Carter873c7242013-01-12 01:03:14 +00001653 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1654
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001655 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001656 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001657 } // case AsmToken::Percent
1658 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00001659 return true;
1660}
1661
Vladimir Medic4c299852013-11-06 11:27:05 +00001662const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00001663 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00001664 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00001665 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001666 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00001667 // It's a constant, evaluate reloc value.
1668 int16_t Val;
1669 switch (getVariantKind(RelocStr)) {
1670 case MCSymbolRefExpr::VK_Mips_ABS_LO:
1671 // Get the 1st 16-bits.
1672 Val = MCE->getValue() & 0xffff;
1673 break;
1674 case MCSymbolRefExpr::VK_Mips_ABS_HI:
1675 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
1676 // 16 bits being negative.
1677 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
1678 break;
1679 case MCSymbolRefExpr::VK_Mips_HIGHER:
1680 // Get the 3rd 16-bits.
1681 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
1682 break;
1683 case MCSymbolRefExpr::VK_Mips_HIGHEST:
1684 // Get the 4th 16-bits.
1685 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
1686 break;
1687 default:
1688 report_fatal_error("Unsupported reloc value!");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001689 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00001690 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00001691 }
1692
Jack Carterb5cf5902013-04-17 00:18:04 +00001693 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001694 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00001695 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00001696 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00001697 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001698 return Res;
1699 }
1700
1701 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00001702 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
1703
Sasa Stankovic06c47802014-04-03 10:37:45 +00001704 // Try to create target expression.
1705 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
1706 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00001707
Jack Carterd0bd6422013-04-18 00:41:53 +00001708 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
1709 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00001710 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
1711 return Res;
1712 }
1713
1714 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001715 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
1716 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
1717 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00001718 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001719 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001720 return Expr;
1721}
1722
1723bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
1724
1725 switch (Expr->getKind()) {
1726 case MCExpr::Constant:
1727 return true;
1728 case MCExpr::SymbolRef:
1729 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
1730 case MCExpr::Binary:
1731 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
1732 if (!isEvaluated(BE->getLHS()))
1733 return false;
1734 return isEvaluated(BE->getRHS());
1735 }
1736 case MCExpr::Unary:
1737 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00001738 case MCExpr::Target:
1739 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001740 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001741 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00001742}
Jack Carterd0bd6422013-04-18 00:41:53 +00001743
Jack Carterb5cf5902013-04-17 00:18:04 +00001744bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001745 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00001746 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00001747 if (Tok.isNot(AsmToken::Identifier))
1748 return true;
1749
1750 std::string Str = Tok.getIdentifier().str();
1751
Jack Carterd0bd6422013-04-18 00:41:53 +00001752 Parser.Lex(); // Eat the identifier.
1753 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001754 const MCExpr *IdVal;
1755 SMLoc EndLoc;
1756
1757 if (getLexer().getKind() == AsmToken::LParen) {
1758 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001759 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001760 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001761 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001762 const AsmToken &nextTok = Parser.getTok();
1763 if (nextTok.isNot(AsmToken::Identifier))
1764 return true;
1765 Str += "(%";
1766 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00001767 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00001768 if (getLexer().getKind() != AsmToken::LParen)
1769 return true;
1770 } else
1771 break;
1772 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001773 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00001774 return true;
1775
1776 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00001777 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001778
1779 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00001780 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001781
Jack Carterd0bd6422013-04-18 00:41:53 +00001782 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00001783 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001784}
1785
Jack Carterb4dbc172012-09-05 23:34:03 +00001786bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1787 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001788 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001789 OperandMatchResultTy ResTy = ParseAnyRegister(Operands);
1790 if (ResTy == MatchOperand_Success) {
1791 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00001792 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001793 StartLoc = Operand.getStartLoc();
1794 EndLoc = Operand.getEndLoc();
1795
1796 // AFAIK, we only support numeric registers and named GPR's in CFI
1797 // directives.
1798 // Don't worry about eating tokens before failing. Using an unrecognised
1799 // register is a parse error.
1800 if (Operand.isGPRAsmReg()) {
1801 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001802 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001803 }
1804
1805 return (RegNo == (unsigned)-1);
1806 }
1807
1808 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00001809 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00001810}
1811
Jack Carterb5cf5902013-04-17 00:18:04 +00001812bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00001813 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001814 bool Result = true;
1815
1816 while (getLexer().getKind() == AsmToken::LParen)
1817 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00001818
Jack Carterd0bd6422013-04-18 00:41:53 +00001819 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001820 default:
1821 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00001822 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00001823 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00001824 case AsmToken::Integer:
1825 case AsmToken::Minus:
1826 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00001827 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00001828 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00001829 else
1830 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00001831 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00001832 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001833 break;
Jack Carter873c7242013-01-12 01:03:14 +00001834 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00001835 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00001836 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001837 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001838}
1839
David Blaikie960ea3f2014-06-08 16:18:35 +00001840MipsAsmParser::OperandMatchResultTy
1841MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001842 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00001843 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00001844 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001845 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001846 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00001847 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00001848 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001849
Jack Carterb5cf5902013-04-17 00:18:04 +00001850 if (getLexer().getKind() == AsmToken::LParen) {
1851 Parser.Lex();
1852 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001853 }
1854
Jack Carterb5cf5902013-04-17 00:18:04 +00001855 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001856 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00001857 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001858
Jack Carterd0bd6422013-04-18 00:41:53 +00001859 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001860 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001861 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
1862 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00001863 SMLoc E =
1864 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001865 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00001866 return MatchOperand_Success;
1867 }
1868 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001869 SMLoc E =
1870 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00001871
Jack Carterd0bd6422013-04-18 00:41:53 +00001872 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001873 // "Base" will be managed by k_Memory.
David Blaikie960ea3f2014-06-08 16:18:35 +00001874 auto Base = MipsOperand::CreateGPRReg(0, getContext().getRegisterInfo(),
1875 S, E, *this);
1876 Operands.push_back(
1877 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00001878 return MatchOperand_Success;
1879 }
1880 Error(Parser.getTok().getLoc(), "'(' expected");
1881 return MatchOperand_ParseFail;
1882 }
1883
Jack Carterd0bd6422013-04-18 00:41:53 +00001884 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001885 }
1886
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001887 Res = ParseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001888 if (Res != MatchOperand_Success)
1889 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001890
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001891 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001892 Error(Parser.getTok().getLoc(), "')' expected");
1893 return MatchOperand_ParseFail;
1894 }
1895
Jack Carter873c7242013-01-12 01:03:14 +00001896 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1897
Jack Carterd0bd6422013-04-18 00:41:53 +00001898 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001899
Craig Topper062a2ba2014-04-25 05:30:21 +00001900 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00001901 IdVal = MCConstantExpr::Create(0, getContext());
1902
Jack Carterd0bd6422013-04-18 00:41:53 +00001903 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00001904 std::unique_ptr<MipsOperand> op(
1905 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001906 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001907 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001908 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00001909 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001910 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
1911 int64_t Imm;
1912 if (IdVal->EvaluateAsAbsolute(Imm))
1913 IdVal = MCConstantExpr::Create(Imm, getContext());
1914 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
1915 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
1916 getContext());
1917 }
1918
David Blaikie960ea3f2014-06-08 16:18:35 +00001919 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00001920 return MatchOperand_Success;
1921}
1922
David Blaikie960ea3f2014-06-08 16:18:35 +00001923bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Daniel Sanderse34a1202014-03-31 18:51:43 +00001924
Jack Carterd76b2372013-03-21 21:44:16 +00001925 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
1926 if (Sym) {
1927 SMLoc S = Parser.getTok().getLoc();
1928 const MCExpr *Expr;
1929 if (Sym->isVariable())
1930 Expr = Sym->getVariableValue();
1931 else
1932 return false;
1933 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001934 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carterd76b2372013-03-21 21:44:16 +00001935 const StringRef DefSymbol = Ref->getSymbol().getName();
1936 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001937 OperandMatchResultTy ResTy =
1938 MatchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00001939 if (ResTy == MatchOperand_Success) {
1940 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00001941 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00001942 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001943 llvm_unreachable("Should never ParseFail");
1944 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00001945 }
1946 } else if (Expr->getKind() == MCExpr::Constant) {
1947 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00001948 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00001949 Operands.push_back(
1950 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00001951 return true;
1952 }
1953 }
1954 return false;
1955}
Jack Carterd0bd6422013-04-18 00:41:53 +00001956
Jack Carter873c7242013-01-12 01:03:14 +00001957MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00001958MipsAsmParser::MatchAnyRegisterNameWithoutDollar(OperandVector &Operands,
1959 StringRef Identifier,
1960 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001961 int Index = matchCPURegisterName(Identifier);
1962 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001963 Operands.push_back(MipsOperand::CreateGPRReg(
1964 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1965 return MatchOperand_Success;
1966 }
1967
1968 Index = matchFPURegisterName(Identifier);
1969 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001970 Operands.push_back(MipsOperand::CreateFGRReg(
1971 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1972 return MatchOperand_Success;
1973 }
1974
1975 Index = matchFCCRegisterName(Identifier);
1976 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001977 Operands.push_back(MipsOperand::CreateFCCReg(
1978 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1979 return MatchOperand_Success;
1980 }
1981
1982 Index = matchACRegisterName(Identifier);
1983 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001984 Operands.push_back(MipsOperand::CreateACCReg(
1985 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1986 return MatchOperand_Success;
1987 }
1988
1989 Index = matchMSA128RegisterName(Identifier);
1990 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001991 Operands.push_back(MipsOperand::CreateMSA128Reg(
1992 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
1993 return MatchOperand_Success;
1994 }
1995
1996 Index = matchMSA128CtrlRegisterName(Identifier);
1997 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001998 Operands.push_back(MipsOperand::CreateMSACtrlReg(
1999 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2000 return MatchOperand_Success;
2001 }
2002
2003 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00002004}
2005
2006MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002007MipsAsmParser::MatchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Daniel Sanders315386c2014-04-01 10:40:14 +00002008 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002009
2010 if (Token.is(AsmToken::Identifier)) {
2011 DEBUG(dbgs() << ".. identifier\n");
2012 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00002013 OperandMatchResultTy ResTy =
2014 MatchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00002015 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002016 } else if (Token.is(AsmToken::Integer)) {
2017 DEBUG(dbgs() << ".. integer\n");
2018 Operands.push_back(MipsOperand::CreateNumericReg(
2019 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
2020 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002021 return MatchOperand_Success;
2022 }
2023
2024 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
2025
2026 return MatchOperand_NoMatch;
2027}
2028
David Blaikie960ea3f2014-06-08 16:18:35 +00002029MipsAsmParser::OperandMatchResultTy
2030MipsAsmParser::ParseAnyRegister(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002031 DEBUG(dbgs() << "ParseAnyRegister\n");
2032
2033 auto Token = Parser.getTok();
2034
2035 SMLoc S = Token.getLoc();
2036
2037 if (Token.isNot(AsmToken::Dollar)) {
2038 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
2039 if (Token.is(AsmToken::Identifier)) {
2040 if (searchSymbolAlias(Operands))
2041 return MatchOperand_Success;
2042 }
2043 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
2044 return MatchOperand_NoMatch;
2045 }
2046 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002047
Daniel Sanders21bce302014-04-01 12:35:23 +00002048 OperandMatchResultTy ResTy = MatchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00002049 if (ResTy == MatchOperand_Success) {
2050 Parser.Lex(); // $
2051 Parser.Lex(); // identifier
2052 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002053 return ResTy;
2054}
2055
2056MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002057MipsAsmParser::ParseImm(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002058 switch (getLexer().getKind()) {
2059 default:
2060 return MatchOperand_NoMatch;
2061 case AsmToken::LParen:
2062 case AsmToken::Minus:
2063 case AsmToken::Plus:
2064 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002065 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002066 case AsmToken::String:
2067 break;
2068 }
2069
2070 const MCExpr *IdVal;
2071 SMLoc S = Parser.getTok().getLoc();
2072 if (getParser().parseExpression(IdVal))
2073 return MatchOperand_ParseFail;
2074
2075 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2076 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
2077 return MatchOperand_Success;
2078}
2079
David Blaikie960ea3f2014-06-08 16:18:35 +00002080MipsAsmParser::OperandMatchResultTy
2081MipsAsmParser::ParseJumpTarget(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002082 DEBUG(dbgs() << "ParseJumpTarget\n");
2083
2084 SMLoc S = getLexer().getLoc();
2085
2086 // Integers and expressions are acceptable
2087 OperandMatchResultTy ResTy = ParseImm(Operands);
2088 if (ResTy != MatchOperand_NoMatch)
2089 return ResTy;
2090
Daniel Sanders315386c2014-04-01 10:40:14 +00002091 // Registers are a valid target and have priority over symbols.
2092 ResTy = ParseAnyRegister(Operands);
2093 if (ResTy != MatchOperand_NoMatch)
2094 return ResTy;
2095
Daniel Sandersffd84362014-04-01 10:41:48 +00002096 const MCExpr *Expr = nullptr;
2097 if (Parser.parseExpression(Expr)) {
2098 // We have no way of knowing if a symbol was consumed so we must ParseFail
2099 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002100 }
Daniel Sandersffd84362014-04-01 10:41:48 +00002101 Operands.push_back(
2102 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002103 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00002104}
2105
Vladimir Medic2b953d02013-10-01 09:48:56 +00002106MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002107MipsAsmParser::parseInvNum(OperandVector &Operands) {
Vladimir Medic2b953d02013-10-01 09:48:56 +00002108 const MCExpr *IdVal;
2109 // If the first token is '$' we may have register operand.
2110 if (Parser.getTok().is(AsmToken::Dollar))
2111 return MatchOperand_NoMatch;
2112 SMLoc S = Parser.getTok().getLoc();
2113 if (getParser().parseExpression(IdVal))
2114 return MatchOperand_ParseFail;
2115 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00002116 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00002117 int64_t Val = MCE->getValue();
2118 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2119 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002120 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00002121 return MatchOperand_Success;
2122}
2123
Matheus Almeida779c5932013-11-18 12:32:49 +00002124MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002125MipsAsmParser::ParseLSAImm(OperandVector &Operands) {
Matheus Almeida779c5932013-11-18 12:32:49 +00002126 switch (getLexer().getKind()) {
2127 default:
2128 return MatchOperand_NoMatch;
2129 case AsmToken::LParen:
2130 case AsmToken::Plus:
2131 case AsmToken::Minus:
2132 case AsmToken::Integer:
2133 break;
2134 }
2135
2136 const MCExpr *Expr;
2137 SMLoc S = Parser.getTok().getLoc();
2138
2139 if (getParser().parseExpression(Expr))
2140 return MatchOperand_ParseFail;
2141
2142 int64_t Val;
2143 if (!Expr->EvaluateAsAbsolute(Val)) {
2144 Error(S, "expected immediate value");
2145 return MatchOperand_ParseFail;
2146 }
2147
2148 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
2149 // and because the CPU always adds one to the immediate field, the allowed
2150 // range becomes 1..4. We'll only check the range here and will deal
2151 // with the addition/subtraction when actually decoding/encoding
2152 // the instruction.
2153 if (Val < 1 || Val > 4) {
2154 Error(S, "immediate not in range (1..4)");
2155 return MatchOperand_ParseFail;
2156 }
2157
Jack Carter3b2c96e2014-01-22 23:31:38 +00002158 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002159 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00002160 return MatchOperand_Success;
2161}
2162
Jack Carterdc1e35d2012-09-06 20:00:02 +00002163MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
2164
Vladimir Medic4c299852013-11-06 11:27:05 +00002165 MCSymbolRefExpr::VariantKind VK =
2166 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
2167 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
2168 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
2169 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
2170 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
2171 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
2172 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
2173 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
2174 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
2175 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
2176 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
2177 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
2178 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
2179 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
2180 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
2181 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
2182 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
2183 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00002184 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
2185 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
2186 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
2187 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
2188 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
2189 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00002190 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
2191 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00002192 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002193
Matheus Almeida2852af82014-04-22 10:15:54 +00002194 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00002195
Jack Carterdc1e35d2012-09-06 20:00:02 +00002196 return VK;
2197}
Jack Cartera63b16a2012-09-07 00:23:42 +00002198
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002199/// Sometimes (i.e. load/stores) the operand may be followed immediately by
2200/// either this.
2201/// ::= '(', register, ')'
2202/// handle it before we iterate so we don't get tripped up by the lack of
2203/// a comma.
David Blaikie960ea3f2014-06-08 16:18:35 +00002204bool MipsAsmParser::ParseParenSuffix(StringRef Name, OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002205 if (getLexer().is(AsmToken::LParen)) {
2206 Operands.push_back(
2207 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
2208 Parser.Lex();
2209 if (ParseOperand(Operands, Name)) {
2210 SMLoc Loc = getLexer().getLoc();
2211 Parser.eatToEndOfStatement();
2212 return Error(Loc, "unexpected token in argument list");
2213 }
2214 if (Parser.getTok().isNot(AsmToken::RParen)) {
2215 SMLoc Loc = getLexer().getLoc();
2216 Parser.eatToEndOfStatement();
2217 return Error(Loc, "unexpected token, expected ')'");
2218 }
2219 Operands.push_back(
2220 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
2221 Parser.Lex();
2222 }
2223 return false;
2224}
2225
2226/// Sometimes (i.e. in MSA) the operand may be followed immediately by
2227/// either one of these.
2228/// ::= '[', register, ']'
2229/// ::= '[', integer, ']'
2230/// handle it before we iterate so we don't get tripped up by the lack of
2231/// a comma.
David Blaikie960ea3f2014-06-08 16:18:35 +00002232bool MipsAsmParser::ParseBracketSuffix(StringRef Name,
2233 OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002234 if (getLexer().is(AsmToken::LBrac)) {
2235 Operands.push_back(
2236 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
2237 Parser.Lex();
2238 if (ParseOperand(Operands, Name)) {
2239 SMLoc Loc = getLexer().getLoc();
2240 Parser.eatToEndOfStatement();
2241 return Error(Loc, "unexpected token in argument list");
2242 }
2243 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2244 SMLoc Loc = getLexer().getLoc();
2245 Parser.eatToEndOfStatement();
2246 return Error(Loc, "unexpected token, expected ']'");
2247 }
2248 Operands.push_back(
2249 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
2250 Parser.Lex();
2251 }
2252 return false;
2253}
2254
David Blaikie960ea3f2014-06-08 16:18:35 +00002255bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
2256 SMLoc NameLoc, OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002257 DEBUG(dbgs() << "ParseInstruction\n");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002258 // We have reached first instruction, module directive after
2259 // this is forbidden.
2260 getTargetStreamer().setCanHaveModuleDir(false);
Vladimir Medic74593e62013-07-17 15:00:42 +00002261 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00002262 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00002263 Parser.eatToEndOfStatement();
2264 return Error(NameLoc, "Unknown instruction");
2265 }
Vladimir Medic64828a12013-07-16 10:07:14 +00002266 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002267 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002268
2269 // Read the remaining operands.
2270 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2271 // Read the first operand.
Vladimir Medic64828a12013-07-16 10:07:14 +00002272 if (ParseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002273 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002274 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002275 return Error(Loc, "unexpected token in argument list");
2276 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002277 if (getLexer().is(AsmToken::LBrac) && ParseBracketSuffix(Name, Operands))
2278 return true;
2279 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00002280
Jack Carterd0bd6422013-04-18 00:41:53 +00002281 while (getLexer().is(AsmToken::Comma)) {
2282 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00002283 // Parse and remember the operand.
2284 if (ParseOperand(Operands, Name)) {
2285 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002286 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002287 return Error(Loc, "unexpected token in argument list");
2288 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002289 // Parse bracket and parenthesis suffixes before we iterate
2290 if (getLexer().is(AsmToken::LBrac)) {
2291 if (ParseBracketSuffix(Name, Operands))
2292 return true;
2293 } else if (getLexer().is(AsmToken::LParen) &&
2294 ParseParenSuffix(Name, Operands))
2295 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00002296 }
2297 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002298 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2299 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002300 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002301 return Error(Loc, "unexpected token in argument list");
2302 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002303 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00002304 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00002305}
2306
Jack Carter0b744b32012-10-04 02:29:46 +00002307bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002308 SMLoc Loc = getLexer().getLoc();
2309 Parser.eatToEndOfStatement();
2310 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00002311}
2312
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002313bool MipsAsmParser::reportParseError(SMLoc Loc, StringRef ErrorMsg) {
2314 return Error(Loc, ErrorMsg);
2315}
2316
Jack Carter0b744b32012-10-04 02:29:46 +00002317bool MipsAsmParser::parseSetNoAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002318 // Line should look like: ".set noat".
2319 // set at reg to 0.
Jack Carter99d2afe2012-10-05 23:55:28 +00002320 Options.setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00002321 // eat noat
2322 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002323 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002324 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2325 reportParseError("unexpected token in statement");
2326 return false;
2327 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002328 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002329 return false;
2330}
Jack Carterd0bd6422013-04-18 00:41:53 +00002331
Jack Carter0b744b32012-10-04 02:29:46 +00002332bool MipsAsmParser::parseSetAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002333 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00002334 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00002335 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00002336 getParser().Lex();
2337 if (getLexer().is(AsmToken::EndOfStatement)) {
Jack Carter99d2afe2012-10-05 23:55:28 +00002338 Options.setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00002339 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002340 return false;
2341 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002342 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00002343 if (getLexer().isNot(AsmToken::Dollar)) {
2344 reportParseError("unexpected token in statement");
2345 return false;
2346 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002347 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00002348 const AsmToken &Reg = Parser.getTok();
2349 if (Reg.is(AsmToken::Identifier)) {
2350 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
2351 } else if (Reg.is(AsmToken::Integer)) {
2352 AtRegNo = Reg.getIntVal();
2353 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00002354 reportParseError("unexpected token in statement");
2355 return false;
2356 }
Jack Carter1ac53222013-02-20 23:11:17 +00002357
Daniel Sanders71a89d922014-03-25 13:01:06 +00002358 if (AtRegNo < 0 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00002359 reportParseError("unexpected token in statement");
2360 return false;
2361 }
2362
2363 if (!Options.setATReg(AtRegNo)) {
Jack Carter0b744b32012-10-04 02:29:46 +00002364 reportParseError("unexpected token in statement");
2365 return false;
2366 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002367 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00002368
2369 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2370 reportParseError("unexpected token in statement");
2371 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002372 }
2373 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002374 return false;
2375 } else {
2376 reportParseError("unexpected token in statement");
2377 return false;
2378 }
2379}
2380
2381bool MipsAsmParser::parseSetReorderDirective() {
2382 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002383 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002384 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2385 reportParseError("unexpected token in statement");
2386 return false;
2387 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002388 Options.setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00002389 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002390 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002391 return false;
2392}
2393
2394bool MipsAsmParser::parseSetNoReorderDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002395 Parser.Lex();
2396 // If this is not the end of the statement, report an error.
2397 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2398 reportParseError("unexpected token in statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002399 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002400 }
2401 Options.setNoreorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00002402 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002403 Parser.Lex(); // Consume the EndOfStatement.
2404 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002405}
2406
2407bool MipsAsmParser::parseSetMacroDirective() {
2408 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002409 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002410 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2411 reportParseError("unexpected token in statement");
2412 return false;
2413 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002414 Options.setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002415 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002416 return false;
2417}
2418
2419bool MipsAsmParser::parseSetNoMacroDirective() {
2420 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002421 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002422 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2423 reportParseError("`noreorder' must be set before `nomacro'");
2424 return false;
2425 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002426 if (Options.isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00002427 reportParseError("`noreorder' must be set before `nomacro'");
2428 return false;
2429 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002430 Options.setNomacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002431 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002432 return false;
2433}
Jack Carterd76b2372013-03-21 21:44:16 +00002434
Jack Carter39536722014-01-22 23:08:42 +00002435bool MipsAsmParser::parseSetNoMips16Directive() {
2436 Parser.Lex();
2437 // If this is not the end of the statement, report an error.
2438 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2439 reportParseError("unexpected token in statement");
2440 return false;
2441 }
2442 // For now do nothing.
2443 Parser.Lex(); // Consume the EndOfStatement.
2444 return false;
2445}
2446
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002447bool MipsAsmParser::parseSetFpDirective() {
2448 int FpAbiMode;
2449 // Line can be: .set fp=32
2450 // .set fp=xx
2451 // .set fp=64
2452 Parser.Lex(); // Eat fp token
2453 AsmToken Tok = Parser.getTok();
2454 if (Tok.isNot(AsmToken::Equal)) {
2455 reportParseError("unexpected token in statement");
2456 return false;
2457 }
2458 Parser.Lex(); // Eat '=' token.
2459 Tok = Parser.getTok();
2460 if (Tok.is(AsmToken::Identifier)) {
2461 StringRef XX = Tok.getString();
2462 if (XX != "xx") {
2463 reportParseError("unsupported option");
2464 return false;
2465 }
2466 if (!isABI_O32()) {
2467 reportParseError("'set fp=xx'option requires O32 ABI");
2468 return false;
2469 }
2470 FpAbiMode = Val_GNU_MIPS_ABI_FP_XX;
2471 } else if (Tok.is(AsmToken::Integer)) {
2472 unsigned Value = Tok.getIntVal();
2473 if (Value != 32 && Value != 64) {
2474 reportParseError("unsupported option");
2475 return false;
2476 }
2477 if (Value == 32) {
2478 if (!isABI_O32()) {
2479 reportParseError("'set fp=32'option requires O32 ABI");
2480 return false;
2481 }
2482 FpAbiMode = Val_GNU_MIPS_ABI_FP_DOUBLE;
2483 } else {
2484 if (isABI_N32() || isABI_N64())
2485 FpAbiMode = Val_GNU_MIPS_ABI_FP_DOUBLE;
2486 else if (isABI_O32())
2487 FpAbiMode = Val_GNU_MIPS_ABI_FP_64;
2488 }
2489 }
2490 Parser.Lex(); // Eat option token.
2491 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2492 reportParseError("unexpected token in statement");
2493 return false;
2494 }
2495 Options.setFpAbiMode(FpAbiMode);
2496 getTargetStreamer().emitDirectiveSetFp(FpAbiMode, isABI_O32());
2497 Parser.Lex(); // Consume the EndOfStatement.
2498 return false;
2499}
2500
Jack Carterd76b2372013-03-21 21:44:16 +00002501bool MipsAsmParser::parseSetAssignment() {
2502 StringRef Name;
2503 const MCExpr *Value;
2504
2505 if (Parser.parseIdentifier(Name))
2506 reportParseError("expected identifier after .set");
2507
2508 if (getLexer().isNot(AsmToken::Comma))
2509 return reportParseError("unexpected token in .set directive");
Jack Carterb5cf5902013-04-17 00:18:04 +00002510 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00002511
Jack Carter3b2c96e2014-01-22 23:31:38 +00002512 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00002513 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00002514
Jack Carterd0bd6422013-04-18 00:41:53 +00002515 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00002516 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00002517 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00002518 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00002519 Sym = getContext().GetOrCreateSymbol(Name);
2520 Sym->setVariableValue(Value);
2521
2522 return false;
2523}
Jack Carterd0bd6422013-04-18 00:41:53 +00002524
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002525bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
2526 Parser.Lex();
2527 if (getLexer().isNot(AsmToken::EndOfStatement))
2528 return reportParseError("unexpected token in .set directive");
2529
Matheus Almeida2852af82014-04-22 10:15:54 +00002530 switch (Feature) {
2531 default:
2532 llvm_unreachable("Unimplemented feature");
2533 case Mips::FeatureDSP:
2534 setFeatureBits(Mips::FeatureDSP, "dsp");
2535 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002536 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002537 case Mips::FeatureMicroMips:
2538 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002539 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002540 case Mips::FeatureMips16:
2541 getTargetStreamer().emitDirectiveSetMips16();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002542 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002543 case Mips::FeatureMips32r2:
2544 setFeatureBits(Mips::FeatureMips32r2, "mips32r2");
2545 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002546 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002547 case Mips::FeatureMips64:
2548 setFeatureBits(Mips::FeatureMips64, "mips64");
2549 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00002550 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002551 case Mips::FeatureMips64r2:
2552 setFeatureBits(Mips::FeatureMips64r2, "mips64r2");
2553 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00002554 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002555 }
2556 return false;
2557}
2558
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002559bool MipsAsmParser::eatComma(StringRef ErrorStr) {
2560 if (getLexer().isNot(AsmToken::Comma)) {
2561 SMLoc Loc = getLexer().getLoc();
2562 Parser.eatToEndOfStatement();
2563 return Error(Loc, ErrorStr);
2564 }
2565
Matheus Almeida2852af82014-04-22 10:15:54 +00002566 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002567 return true;
2568}
2569
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002570bool MipsAsmParser::parseDirectiveCPLoad(SMLoc Loc) {
2571 if (Options.isReorder())
2572 Warning(Loc, ".cpload in reorder section");
2573
2574 // FIXME: Warn if cpload is used in Mips16 mode.
2575
David Blaikie960ea3f2014-06-08 16:18:35 +00002576 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002577 OperandMatchResultTy ResTy = ParseAnyRegister(Reg);
2578 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
2579 reportParseError("expected register containing function address");
2580 return false;
2581 }
2582
David Blaikie960ea3f2014-06-08 16:18:35 +00002583 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
2584 if (!RegOpnd.isGPRAsmReg()) {
2585 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002586 return false;
2587 }
2588
David Blaikie960ea3f2014-06-08 16:18:35 +00002589 getTargetStreamer().emitDirectiveCpload(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002590 return false;
2591}
2592
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002593bool MipsAsmParser::parseDirectiveCPSetup() {
2594 unsigned FuncReg;
2595 unsigned Save;
2596 bool SaveIsReg = true;
2597
Matheus Almeida7e815762014-06-18 13:08:59 +00002598 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
2599 OperandMatchResultTy ResTy = ParseAnyRegister(TmpReg);
2600 if (ResTy == MatchOperand_NoMatch) {
2601 reportParseError("expected register containing function address");
2602 Parser.eatToEndOfStatement();
2603 return false;
2604 }
2605
2606 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
2607 if (!FuncRegOpnd.isGPRAsmReg()) {
2608 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
2609 Parser.eatToEndOfStatement();
2610 return false;
2611 }
2612
2613 FuncReg = FuncRegOpnd.getGPR32Reg();
2614 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002615
2616 if (!eatComma("expected comma parsing directive"))
2617 return true;
2618
Matheus Almeida7e815762014-06-18 13:08:59 +00002619 ResTy = ParseAnyRegister(TmpReg);
2620 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002621 const AsmToken &Tok = Parser.getTok();
2622 if (Tok.is(AsmToken::Integer)) {
2623 Save = Tok.getIntVal();
2624 SaveIsReg = false;
2625 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00002626 } else {
2627 reportParseError("expected save register or stack offset");
2628 Parser.eatToEndOfStatement();
2629 return false;
2630 }
2631 } else {
2632 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
2633 if (!SaveOpnd.isGPRAsmReg()) {
2634 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
2635 Parser.eatToEndOfStatement();
2636 return false;
2637 }
2638 Save = SaveOpnd.getGPR32Reg();
2639 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002640
2641 if (!eatComma("expected comma parsing directive"))
2642 return true;
2643
2644 StringRef Name;
2645 if (Parser.parseIdentifier(Name))
2646 reportParseError("expected identifier");
2647 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002648
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00002649 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, *Sym, SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002650 return false;
2651}
2652
Matheus Almeida0051f2d2014-04-16 15:48:55 +00002653bool MipsAsmParser::parseDirectiveNaN() {
2654 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2655 const AsmToken &Tok = Parser.getTok();
2656
2657 if (Tok.getString() == "2008") {
2658 Parser.Lex();
2659 getTargetStreamer().emitDirectiveNaN2008();
2660 return false;
2661 } else if (Tok.getString() == "legacy") {
2662 Parser.Lex();
2663 getTargetStreamer().emitDirectiveNaNLegacy();
2664 return false;
2665 }
2666 }
2667 // If we don't recognize the option passed to the .nan
2668 // directive (e.g. no option or unknown option), emit an error.
2669 reportParseError("invalid option in .nan directive");
2670 return false;
2671}
2672
Jack Carter0b744b32012-10-04 02:29:46 +00002673bool MipsAsmParser::parseDirectiveSet() {
2674
Jack Carterd0bd6422013-04-18 00:41:53 +00002675 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00002676 const AsmToken &Tok = Parser.getTok();
2677
2678 if (Tok.getString() == "noat") {
2679 return parseSetNoAtDirective();
2680 } else if (Tok.getString() == "at") {
2681 return parseSetAtDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002682 } else if (Tok.getString() == "fp") {
2683 return parseSetFpDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00002684 } else if (Tok.getString() == "reorder") {
2685 return parseSetReorderDirective();
2686 } else if (Tok.getString() == "noreorder") {
2687 return parseSetNoReorderDirective();
2688 } else if (Tok.getString() == "macro") {
2689 return parseSetMacroDirective();
2690 } else if (Tok.getString() == "nomacro") {
2691 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00002692 } else if (Tok.getString() == "mips16") {
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002693 return parseSetFeature(Mips::FeatureMips16);
Jack Carter0b744b32012-10-04 02:29:46 +00002694 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00002695 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00002696 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00002697 getTargetStreamer().emitDirectiveSetNoMicroMips();
2698 Parser.eatToEndOfStatement();
2699 return false;
2700 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002701 return parseSetFeature(Mips::FeatureMicroMips);
Vladimir Medic615b26e2014-03-04 09:54:09 +00002702 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002703 return parseSetFeature(Mips::FeatureMips32r2);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00002704 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002705 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00002706 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002707 return parseSetFeature(Mips::FeatureMips64r2);
Vladimir Medic27c398e2014-03-05 11:05:09 +00002708 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002709 return parseSetFeature(Mips::FeatureDSP);
Jack Carterd76b2372013-03-21 21:44:16 +00002710 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002711 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00002712 parseSetAssignment();
2713 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002714 }
Jack Carter07c818d2013-01-25 01:31:34 +00002715
Jack Carter0b744b32012-10-04 02:29:46 +00002716 return true;
2717}
2718
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002719/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00002720/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002721bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Jack Carter07c818d2013-01-25 01:31:34 +00002722 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2723 for (;;) {
2724 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002725 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00002726 return true;
2727
2728 getParser().getStreamer().EmitValue(Value, Size);
2729
2730 if (getLexer().is(AsmToken::EndOfStatement))
2731 break;
2732
2733 // FIXME: Improve diagnostic.
2734 if (getLexer().isNot(AsmToken::Comma))
2735 return Error(L, "unexpected token in directive");
2736 Parser.Lex();
2737 }
2738 }
2739
2740 Parser.Lex();
2741 return false;
2742}
2743
Vladimir Medic4c299852013-11-06 11:27:05 +00002744/// parseDirectiveGpWord
2745/// ::= .gpword local_sym
2746bool MipsAsmParser::parseDirectiveGpWord() {
2747 const MCExpr *Value;
2748 // EmitGPRel32Value requires an expression, so we are using base class
2749 // method to evaluate the expression.
2750 if (getParser().parseExpression(Value))
2751 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00002752 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00002753
Vladimir Medice10c1122013-11-13 13:18:04 +00002754 if (getLexer().isNot(AsmToken::EndOfStatement))
Vladimir Medic4c299852013-11-06 11:27:05 +00002755 return Error(getLexer().getLoc(), "unexpected token in directive");
Vladimir Medice10c1122013-11-13 13:18:04 +00002756 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00002757 return false;
2758}
2759
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002760/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00002761/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002762bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindolab59fb732014-03-28 18:50:26 +00002763 const MCExpr *Value;
2764 // EmitGPRel64Value requires an expression, so we are using base class
2765 // method to evaluate the expression.
2766 if (getParser().parseExpression(Value))
2767 return true;
2768 getParser().getStreamer().EmitGPRel64Value(Value);
2769
2770 if (getLexer().isNot(AsmToken::EndOfStatement))
2771 return Error(getLexer().getLoc(), "unexpected token in directive");
2772 Parser.Lex(); // Eat EndOfStatement token.
2773 return false;
2774}
2775
Jack Carter0cd3c192014-01-06 23:27:31 +00002776bool MipsAsmParser::parseDirectiveOption() {
2777 // Get the option token.
2778 AsmToken Tok = Parser.getTok();
2779 // At the moment only identifiers are supported.
2780 if (Tok.isNot(AsmToken::Identifier)) {
2781 Error(Parser.getTok().getLoc(), "unexpected token in .option directive");
2782 Parser.eatToEndOfStatement();
2783 return false;
2784 }
2785
2786 StringRef Option = Tok.getIdentifier();
2787
2788 if (Option == "pic0") {
2789 getTargetStreamer().emitDirectiveOptionPic0();
2790 Parser.Lex();
2791 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2792 Error(Parser.getTok().getLoc(),
2793 "unexpected token in .option pic0 directive");
2794 Parser.eatToEndOfStatement();
2795 }
2796 return false;
2797 }
2798
Matheus Almeidaf79b2812014-03-26 13:40:29 +00002799 if (Option == "pic2") {
2800 getTargetStreamer().emitDirectiveOptionPic2();
2801 Parser.Lex();
2802 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2803 Error(Parser.getTok().getLoc(),
2804 "unexpected token in .option pic2 directive");
2805 Parser.eatToEndOfStatement();
2806 }
2807 return false;
2808 }
2809
Jack Carter0cd3c192014-01-06 23:27:31 +00002810 // Unknown option.
2811 Warning(Parser.getTok().getLoc(), "unknown option in .option directive");
2812 Parser.eatToEndOfStatement();
2813 return false;
2814}
2815
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002816bool MipsAsmParser::parseDirectiveModule() {
2817 // Line can be: .module fp=32
2818 // .module fp=xx
2819 // .module fp=64
2820 unsigned FpAbiVal = 0;
2821 if (!getTargetStreamer().getCanHaveModuleDir()) {
2822 // TODO : get a better message.
2823 reportParseError(".module directive must appear before any code");
2824 return false;
2825 }
2826 AsmToken Tok = Parser.getTok();
2827 if (Tok.isNot(AsmToken::Identifier) && Tok.getString() != "fp") {
2828 reportParseError("unexpected token in .module directive, 'fp' expected");
2829 return false;
2830 }
2831 Parser.Lex(); // Eat fp token
2832 Tok = Parser.getTok();
2833 if (Tok.isNot(AsmToken::Equal)) {
2834 reportParseError("unexpected token in statement");
2835 return false;
2836 }
2837 Parser.Lex(); // Eat '=' token.
2838 Tok = Parser.getTok();
2839 if (Tok.is(AsmToken::Identifier)) {
2840 StringRef XX = Tok.getString();
2841 if (XX != "xx") {
2842 reportParseError("unsupported option");
2843 return false;
2844 }
2845 FpAbiVal = Val_GNU_MIPS_ABI_FP_XX;
2846 } else if (Tok.is(AsmToken::Integer)) {
2847 unsigned Value = Tok.getIntVal();
2848 if (Value != 32 && Value != 64) {
2849 reportParseError("unsupported value, expected 32 or 64");
2850 return false;
2851 }
2852 if (Value == 64) {
2853 if (isABI_N32() || isABI_N64())
2854 FpAbiVal = Val_GNU_MIPS_ABI_FP_DOUBLE;
2855 else if (isABI_O32())
2856 FpAbiVal = Val_GNU_MIPS_ABI_FP_64;
2857 } else if (isABI_O32())
2858 FpAbiVal = Val_GNU_MIPS_ABI_FP_DOUBLE;
2859 }
2860 Parser.Lex(); // Eat option token.
2861 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2862 reportParseError("unexpected token in statement");
2863 return false;
2864 }
2865 // Emit appropriate flags.
2866 getTargetStreamer().emitDirectiveModule(FpAbiVal, isABI_O32());
2867 getTargetStreamer().setFpABI(FpAbiVal);
2868 Parser.Lex(); // Consume the EndOfStatement.
2869 return false;
2870}
Jack Carter0b744b32012-10-04 02:29:46 +00002871bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carter07c818d2013-01-25 01:31:34 +00002872 StringRef IDVal = DirectiveID.getString();
2873
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002874 if (IDVal == ".cpload")
2875 return parseDirectiveCPLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00002876 if (IDVal == ".dword") {
2877 parseDataDirective(8, DirectiveID.getLoc());
2878 return false;
2879 }
2880
Jack Carterd0bd6422013-04-18 00:41:53 +00002881 if (IDVal == ".ent") {
2882 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00002883 Parser.Lex();
2884 return false;
2885 }
2886
Jack Carter07c818d2013-01-25 01:31:34 +00002887 if (IDVal == ".end") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002888 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00002889 Parser.Lex();
2890 return false;
2891 }
2892
Jack Carter07c818d2013-01-25 01:31:34 +00002893 if (IDVal == ".frame") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002894 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002895 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002896 return false;
2897 }
2898
Jack Carter07c818d2013-01-25 01:31:34 +00002899 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00002900 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00002901 }
2902
Jack Carter07c818d2013-01-25 01:31:34 +00002903 if (IDVal == ".fmask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002904 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002905 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002906 return false;
2907 }
2908
Jack Carter07c818d2013-01-25 01:31:34 +00002909 if (IDVal == ".mask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002910 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002911 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002912 return false;
2913 }
2914
Matheus Almeida0051f2d2014-04-16 15:48:55 +00002915 if (IDVal == ".nan")
2916 return parseDirectiveNaN();
2917
Jack Carter07c818d2013-01-25 01:31:34 +00002918 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002919 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00002920 return false;
2921 }
2922
Rafael Espindolab59fb732014-03-28 18:50:26 +00002923 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002924 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00002925 return false;
2926 }
2927
Jack Carter07c818d2013-01-25 01:31:34 +00002928 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002929 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00002930 return false;
2931 }
2932
Jack Carter0cd3c192014-01-06 23:27:31 +00002933 if (IDVal == ".option")
2934 return parseDirectiveOption();
2935
2936 if (IDVal == ".abicalls") {
2937 getTargetStreamer().emitDirectiveAbiCalls();
2938 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2939 Error(Parser.getTok().getLoc(), "unexpected token in directive");
2940 // Clear line
2941 Parser.eatToEndOfStatement();
2942 }
2943 return false;
2944 }
2945
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002946 if (IDVal == ".cpsetup")
2947 return parseDirectiveCPSetup();
2948
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002949 if (IDVal == ".module")
2950 return parseDirectiveModule();
2951
Rafael Espindola870c4e92012-01-11 03:56:41 +00002952 return true;
2953}
2954
Rafael Espindola870c4e92012-01-11 03:56:41 +00002955extern "C" void LLVMInitializeMipsAsmParser() {
2956 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
2957 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
2958 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
2959 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
2960}
Jack Carterb4dbc172012-09-05 23:34:03 +00002961
2962#define GET_REGISTER_MATCHER
2963#define GET_MATCHER_IMPLEMENTATION
2964#include "MipsGenAsmMatcher.inc"