blob: eb68c52745eb9aa7f009aabbe0fea186e5fa2fd9 [file] [log] [blame]
Jia Liu9f610112012-02-17 08:55:11 +00001//===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
Rafael Espindola870c4e92012-01-11 03:56:41 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Petar Jovanovica5da5882014-02-04 18:41:57 +000010#include "MCTargetDesc/MipsMCExpr.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000011#include "MCTargetDesc/MipsMCTargetDesc.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000012#include "MipsRegisterInfo.h"
Rafael Espindolaa17151a2013-10-08 13:08:17 +000013#include "MipsTargetStreamer.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000014#include "llvm/ADT/APInt.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000015#include "llvm/ADT/StringSwitch.h"
16#include "llvm/MC/MCContext.h"
17#include "llvm/MC/MCExpr.h"
18#include "llvm/MC/MCInst.h"
Daniel Sandersa771fef2014-03-24 14:05:39 +000019#include "llvm/MC/MCInstBuilder.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000020#include "llvm/MC/MCParser/MCAsmLexer.h"
21#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000022#include "llvm/MC/MCStreamer.h"
23#include "llvm/MC/MCSubtargetInfo.h"
24#include "llvm/MC/MCSymbol.h"
Akira Hatanaka7605630c2012-08-17 20:16:42 +000025#include "llvm/MC/MCTargetAsmParser.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000026#include "llvm/Support/Debug.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000027#include "llvm/Support/MathExtras.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000028#include "llvm/Support/TargetRegistry.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000029
30using namespace llvm;
31
Chandler Carruthe96dd892014-04-21 22:55:11 +000032#define DEBUG_TYPE "mips-asm-parser"
33
Joey Gouly0e76fa72013-09-12 10:28:05 +000034namespace llvm {
35class MCInstrInfo;
36}
37
Rafael Espindola870c4e92012-01-11 03:56:41 +000038namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000039class MipsAssemblerOptions {
40public:
Daniel Sandersc7dbc632014-07-08 10:11:38 +000041 MipsAssemblerOptions() : aTReg(1), reorder(true), macro(true) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000042
Vladimir Medic4c299852013-11-06 11:27:05 +000043 unsigned getATRegNum() { return aTReg; }
Jack Carter0b744b32012-10-04 02:29:46 +000044 bool setATReg(unsigned Reg);
45
Vladimir Medic4c299852013-11-06 11:27:05 +000046 bool isReorder() { return reorder; }
47 void setReorder() { reorder = true; }
48 void setNoreorder() { reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000049
Vladimir Medic4c299852013-11-06 11:27:05 +000050 bool isMacro() { return macro; }
51 void setMacro() { macro = true; }
52 void setNomacro() { macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000053
Daniel Sandersf0df2212014-08-04 12:20:00 +000054 // Set of features that are either architecture features or referenced
55 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
56 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
57 // The reason we need this mask is explained in the selectArch function.
58 // FIXME: Ideally we would like TableGen to generate this information.
59 static const uint64_t AllArchRelatedMask =
60 Mips::FeatureMips1 | Mips::FeatureMips2 | Mips::FeatureMips3 |
61 Mips::FeatureMips3_32 | Mips::FeatureMips3_32r2 | Mips::FeatureMips4 |
62 Mips::FeatureMips4_32 | Mips::FeatureMips4_32r2 | Mips::FeatureMips5 |
63 Mips::FeatureMips5_32r2 | Mips::FeatureMips32 | Mips::FeatureMips32r2 |
64 Mips::FeatureMips32r6 | Mips::FeatureMips64 | Mips::FeatureMips64r2 |
65 Mips::FeatureMips64r6 | Mips::FeatureCnMips | Mips::FeatureFP64Bit |
66 Mips::FeatureGP64Bit | Mips::FeatureNaN2008;
67
Jack Carter0b744b32012-10-04 02:29:46 +000068private:
69 unsigned aTReg;
70 bool reorder;
71 bool macro;
72};
73}
74
75namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +000076class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +000077 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola4a1a3602014-01-14 01:21:46 +000078 MCTargetStreamer &TS = *Parser.getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +000079 return static_cast<MipsTargetStreamer &>(TS);
80 }
81
Jack Carterb4dbc172012-09-05 23:34:03 +000082 MCSubtargetInfo &STI;
83 MCAsmParser &Parser;
Jack Carter99d2afe2012-10-05 23:55:28 +000084 MipsAssemblerOptions Options;
Daniel Sandersd97a6342014-08-13 10:07:34 +000085 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
86 // nullptr, which indicates that no function is currently
87 // selected. This usually happens after an '.end func'
88 // directive.
Jack Carter0b744b32012-10-04 02:29:46 +000089
Akira Hatanaka7605630c2012-08-17 20:16:42 +000090#define GET_ASSEMBLER_HEADER
91#include "MipsGenAsmMatcher.inc"
92
Matheus Almeida595fcab2014-06-11 15:05:56 +000093 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
94
Chad Rosier49963552012-10-13 00:26:04 +000095 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +000096 OperandVector &Operands, MCStreamer &Out,
97 unsigned &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +000098 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +000099
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000100 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000101 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000102
David Blaikie960ea3f2014-06-08 16:18:35 +0000103 bool ParseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000104
David Blaikie960ea3f2014-06-08 16:18:35 +0000105 bool ParseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000106
David Blaikie960ea3f2014-06-08 16:18:35 +0000107 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
108 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000109
Craig Topper56c590a2014-04-29 07:58:02 +0000110 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000111
David Blaikie960ea3f2014-06-08 16:18:35 +0000112 MipsAsmParser::OperandMatchResultTy parseMemOperand(OperandVector &Operands);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000113
114 MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +0000115 MatchAnyRegisterNameWithoutDollar(OperandVector &Operands,
116 StringRef Identifier, SMLoc S);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000117
Jack Carter873c7242013-01-12 01:03:14 +0000118 MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +0000119 MatchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S);
Jack Carter873c7242013-01-12 01:03:14 +0000120
David Blaikie960ea3f2014-06-08 16:18:35 +0000121 MipsAsmParser::OperandMatchResultTy ParseAnyRegister(OperandVector &Operands);
Jack Carter873c7242013-01-12 01:03:14 +0000122
David Blaikie960ea3f2014-06-08 16:18:35 +0000123 MipsAsmParser::OperandMatchResultTy ParseImm(OperandVector &Operands);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000124
David Blaikie960ea3f2014-06-08 16:18:35 +0000125 MipsAsmParser::OperandMatchResultTy ParseJumpTarget(OperandVector &Operands);
Vladimir Medic2b953d02013-10-01 09:48:56 +0000126
David Blaikie960ea3f2014-06-08 16:18:35 +0000127 MipsAsmParser::OperandMatchResultTy parseInvNum(OperandVector &Operands);
Matheus Almeida779c5932013-11-18 12:32:49 +0000128
David Blaikie960ea3f2014-06-08 16:18:35 +0000129 MipsAsmParser::OperandMatchResultTy ParseLSAImm(OperandVector &Operands);
Jack Carterd76b2372013-03-21 21:44:16 +0000130
David Blaikie960ea3f2014-06-08 16:18:35 +0000131 bool searchSymbolAlias(OperandVector &Operands);
132
133 bool ParseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000134
Jack Carter30a59822012-10-04 04:03:53 +0000135 bool needsExpansion(MCInst &Inst);
136
Matheus Almeida3813d572014-06-19 14:39:14 +0000137 // Expands assembly pseudo instructions.
138 // Returns false on success, true otherwise.
139 bool expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000140 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000141
142 bool expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000143 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000144
145 bool expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000146 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000147
148 bool expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000149 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000150
Jack Carter9e65aa32013-03-22 00:05:30 +0000151 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000152 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
153 bool isImmOpnd);
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000154 bool reportParseError(Twine ErrorMsg);
155 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000156
Jack Carterb5cf5902013-04-17 00:18:04 +0000157 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000158 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000159
Vladimir Medic4c299852013-11-06 11:27:05 +0000160 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000161
162 bool isEvaluated(const MCExpr *Expr);
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000163 bool parseSetFeature(uint64_t Feature);
Matheus Almeida525bc4f2014-04-30 11:28:42 +0000164 bool parseDirectiveCPLoad(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000165 bool parseDirectiveCPSetup();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000166 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000167 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000168 bool parseDirectiveOption();
Jack Carter0b744b32012-10-04 02:29:46 +0000169
170 bool parseSetAtDirective();
171 bool parseSetNoAtDirective();
172 bool parseSetMacroDirective();
173 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000174 bool parseSetMsaDirective();
175 bool parseSetNoMsaDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000176 bool parseSetReorderDirective();
177 bool parseSetNoReorderDirective();
Jack Carter39536722014-01-22 23:08:42 +0000178 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000179 bool parseSetFpDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000180
Jack Carterd76b2372013-03-21 21:44:16 +0000181 bool parseSetAssignment();
182
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000183 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000184 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000185 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000186 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000187 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000188 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
189 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000190
Jack Carterdc1e35d2012-09-06 20:00:02 +0000191 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000192
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000193 bool eatComma(StringRef ErrorStr);
194
Jack Carter1ac53222013-02-20 23:11:17 +0000195 int matchCPURegisterName(StringRef Symbol);
196
Jack Carter873c7242013-01-12 01:03:14 +0000197 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000198
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000199 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000200
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000201 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000202
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000203 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000204
Jack Carter5dc8ac92013-09-25 23:50:44 +0000205 int matchMSA128RegisterName(StringRef Name);
206
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000207 int matchMSA128CtrlRegisterName(StringRef Name);
208
Jack Carterd0bd6422013-04-18 00:41:53 +0000209 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000210
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000211 unsigned getGPR(int RegNo);
212
Matheus Almeida7de68e72014-06-18 14:46:05 +0000213 int getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000214
215 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000216 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000217
218 // Helper function that checks if the value of a vector index is within the
219 // boundaries of accepted values for each RegisterKind
220 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
221 bool validateMSAIndex(int Val, int RegKind);
222
Daniel Sandersf0df2212014-08-04 12:20:00 +0000223 // Selects a new architecture by updating the FeatureBits with the necessary
224 // info including implied dependencies.
225 // Internally, it clears all the feature bits related to *any* architecture
226 // and selects the new one using the ToggleFeature functionality of the
227 // MCSubtargetInfo object that handles implied dependencies. The reason we
228 // clear all the arch related bits manually is because ToggleFeature only
229 // clears the features that imply the feature being cleared and not the
230 // features implied by the feature being cleared. This is easier to see
231 // with an example:
232 // --------------------------------------------------
233 // | Feature | Implies |
234 // | -------------------------------------------------|
235 // | FeatureMips1 | None |
236 // | FeatureMips2 | FeatureMips1 |
237 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
238 // | FeatureMips4 | FeatureMips3 |
239 // | ... | |
240 // --------------------------------------------------
241 //
242 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
243 // FeatureMipsGP64 | FeatureMips1)
244 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
245 void selectArch(StringRef ArchFeature) {
246 uint64_t FeatureBits = STI.getFeatureBits();
247 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
248 STI.setFeatureBits(FeatureBits);
249 setAvailableFeatures(
250 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
251 }
252
Vladimir Medic615b26e2014-03-04 09:54:09 +0000253 void setFeatureBits(unsigned Feature, StringRef FeatureString) {
254 if (!(STI.getFeatureBits() & Feature)) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000255 setAvailableFeatures(
256 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000257 }
258 }
259
260 void clearFeatureBits(unsigned Feature, StringRef FeatureString) {
261 if (STI.getFeatureBits() & Feature) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000262 setAvailableFeatures(
263 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000264 }
265 }
266
Rafael Espindola870c4e92012-01-11 03:56:41 +0000267public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000268 enum MipsMatchResultTy {
269 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
270#define GET_OPERAND_DIAGNOSTIC_TYPES
271#include "MipsGenAsmMatcher.inc"
272#undef GET_OPERAND_DIAGNOSTIC_TYPES
273
274 };
275
Joey Gouly0e76fa72013-09-12 10:28:05 +0000276 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000277 const MCInstrInfo &MII, const MCTargetOptions &Options)
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000278 : MCTargetAsmParser(), STI(sti), Parser(parser) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000279 // Initialize the set of available features.
280 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000281
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000282 getTargetStreamer().updateABIInfo(*this);
283
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000284 // Assert exactly one ABI was chosen.
285 assert((((STI.getFeatureBits() & Mips::FeatureO32) != 0) +
286 ((STI.getFeatureBits() & Mips::FeatureEABI) != 0) +
287 ((STI.getFeatureBits() & Mips::FeatureN32) != 0) +
288 ((STI.getFeatureBits() & Mips::FeatureN64) != 0)) == 1);
Daniel Sanders7e527422014-07-10 13:38:23 +0000289
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000290 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000291 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000292
293 CurrentFn = nullptr;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000294 }
295
Jack Carterb4dbc172012-09-05 23:34:03 +0000296 MCAsmParser &getParser() const { return Parser; }
297 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000298
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000299 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
300 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
301
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000302 bool isGP64bit() const { return STI.getFeatureBits() & Mips::FeatureGP64Bit; }
303 bool isFP64bit() const { return STI.getFeatureBits() & Mips::FeatureFP64Bit; }
304 bool isABI_N32() const { return STI.getFeatureBits() & Mips::FeatureN32; }
305 bool isABI_N64() const { return STI.getFeatureBits() & Mips::FeatureN64; }
306 bool isABI_O32() const { return STI.getFeatureBits() & Mips::FeatureO32; }
Daniel Sandersa6e125f2014-07-15 15:31:39 +0000307 bool isABI_FPXX() const { return STI.getFeatureBits() & Mips::FeatureFPXX; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000308
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000309 bool useOddSPReg() const {
Daniel Sanders7e527422014-07-10 13:38:23 +0000310 return !(STI.getFeatureBits() & Mips::FeatureNoOddSPReg);
311 }
312
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000313 bool inMicroMipsMode() const {
314 return STI.getFeatureBits() & Mips::FeatureMicroMips;
315 }
316 bool hasMips1() const { return STI.getFeatureBits() & Mips::FeatureMips1; }
317 bool hasMips2() const { return STI.getFeatureBits() & Mips::FeatureMips2; }
318 bool hasMips3() const { return STI.getFeatureBits() & Mips::FeatureMips3; }
319 bool hasMips4() const { return STI.getFeatureBits() & Mips::FeatureMips4; }
320 bool hasMips5() const { return STI.getFeatureBits() & Mips::FeatureMips5; }
321 bool hasMips32() const {
322 return (STI.getFeatureBits() & Mips::FeatureMips32);
323 }
324 bool hasMips64() const {
325 return (STI.getFeatureBits() & Mips::FeatureMips64);
326 }
327 bool hasMips32r2() const {
328 return (STI.getFeatureBits() & Mips::FeatureMips32r2);
329 }
330 bool hasMips64r2() const {
331 return (STI.getFeatureBits() & Mips::FeatureMips64r2);
332 }
333 bool hasMips32r6() const {
334 return (STI.getFeatureBits() & Mips::FeatureMips32r6);
335 }
336 bool hasMips64r6() const {
337 return (STI.getFeatureBits() & Mips::FeatureMips64r6);
338 }
339 bool hasDSP() const { return (STI.getFeatureBits() & Mips::FeatureDSP); }
340 bool hasDSPR2() const { return (STI.getFeatureBits() & Mips::FeatureDSPR2); }
341 bool hasMSA() const { return (STI.getFeatureBits() & Mips::FeatureMSA); }
342
343 bool inMips16Mode() const {
344 return STI.getFeatureBits() & Mips::FeatureMips16;
345 }
346 // TODO: see how can we get this info.
Eric Christopher7394e232014-07-18 00:08:50 +0000347 bool abiUsesSoftFloat() const { return false; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000348
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000349 /// Warn if RegNo is the current assembler temporary.
350 void WarnIfAssemblerTemporary(int RegNo, SMLoc Loc);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000351};
352}
353
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000354namespace {
355
356/// MipsOperand - Instances of this class represent a parsed Mips machine
357/// instruction.
358class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000359public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000360 /// Broad categories of register classes
361 /// The exact class is finalized by the render method.
362 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000363 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000364 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000365 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000366 RegKind_FCC = 4, /// FCC
367 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
368 RegKind_MSACtrl = 16, /// MSA control registers
369 RegKind_COP2 = 32, /// COP2
370 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
371 /// context).
372 RegKind_CCR = 128, /// CCR
373 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000374 RegKind_COP3 = 512, /// COP3
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000375
376 /// Potentially any (e.g. $1)
377 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
378 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000379 RegKind_CCR | RegKind_HWRegs | RegKind_COP3
Jack Carter873c7242013-01-12 01:03:14 +0000380 };
381
382private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000383 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000384 k_Immediate, /// An immediate (possibly involving symbol references)
385 k_Memory, /// Base + Offset Memory Address
386 k_PhysRegister, /// A physical register from the Mips namespace
387 k_RegisterIndex, /// A register index in one or more RegKind.
388 k_Token /// A simple token
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000389 } Kind;
390
David Blaikie960ea3f2014-06-08 16:18:35 +0000391public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000392 MipsOperand(KindTy K, MipsAsmParser &Parser)
393 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
394
David Blaikie960ea3f2014-06-08 16:18:35 +0000395private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000396 /// For diagnostics, and checking the assembler temporary
397 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000398
Eric Christopher8996c5d2013-03-15 00:42:55 +0000399 struct Token {
400 const char *Data;
401 unsigned Length;
402 };
403
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000404 struct PhysRegOp {
405 unsigned Num; /// Register Number
406 };
407
408 struct RegIdxOp {
409 unsigned Index; /// Index into the register class
410 RegKind Kind; /// Bitfield of the kinds it could possibly be
411 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000412 };
413
414 struct ImmOp {
415 const MCExpr *Val;
416 };
417
418 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000419 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000420 const MCExpr *Off;
421 };
422
Jack Carterb4dbc172012-09-05 23:34:03 +0000423 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000424 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000425 struct PhysRegOp PhysReg;
426 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000427 struct ImmOp Imm;
428 struct MemOp Mem;
Jack Carterb4dbc172012-09-05 23:34:03 +0000429 };
430
431 SMLoc StartLoc, EndLoc;
432
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000433 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000434 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
435 const MCRegisterInfo *RegInfo,
436 SMLoc S, SMLoc E,
437 MipsAsmParser &Parser) {
438 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000439 Op->RegIdx.Index = Index;
440 Op->RegIdx.RegInfo = RegInfo;
441 Op->RegIdx.Kind = RegKind;
442 Op->StartLoc = S;
443 Op->EndLoc = E;
444 return Op;
445 }
446
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000447public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000448 /// Coerce the register to GPR32 and return the real register for the current
449 /// target.
450 unsigned getGPR32Reg() const {
451 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
452 AsmParser.WarnIfAssemblerTemporary(RegIdx.Index, StartLoc);
453 unsigned ClassID = Mips::GPR32RegClassID;
454 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000455 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000456
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000457 /// Coerce the register to GPR64 and return the real register for the current
458 /// target.
459 unsigned getGPR64Reg() const {
460 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
461 unsigned ClassID = Mips::GPR64RegClassID;
462 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000463 }
464
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000465private:
466 /// Coerce the register to AFGR64 and return the real register for the current
467 /// target.
468 unsigned getAFGR64Reg() const {
469 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
470 if (RegIdx.Index % 2 != 0)
471 AsmParser.Warning(StartLoc, "Float register should be even.");
472 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
473 .getRegister(RegIdx.Index / 2);
474 }
475
476 /// Coerce the register to FGR64 and return the real register for the current
477 /// target.
478 unsigned getFGR64Reg() const {
479 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
480 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
481 .getRegister(RegIdx.Index);
482 }
483
484 /// Coerce the register to FGR32 and return the real register for the current
485 /// target.
486 unsigned getFGR32Reg() const {
487 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
488 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
489 .getRegister(RegIdx.Index);
490 }
491
492 /// Coerce the register to FGRH32 and return the real register for the current
493 /// target.
494 unsigned getFGRH32Reg() const {
495 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
496 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
497 .getRegister(RegIdx.Index);
498 }
499
500 /// Coerce the register to FCC and return the real register for the current
501 /// target.
502 unsigned getFCCReg() const {
503 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
504 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
505 .getRegister(RegIdx.Index);
506 }
507
508 /// Coerce the register to MSA128 and return the real register for the current
509 /// target.
510 unsigned getMSA128Reg() const {
511 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
512 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
513 // identical
514 unsigned ClassID = Mips::MSA128BRegClassID;
515 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
516 }
517
518 /// Coerce the register to MSACtrl and return the real register for the
519 /// current target.
520 unsigned getMSACtrlReg() const {
521 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
522 unsigned ClassID = Mips::MSACtrlRegClassID;
523 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
524 }
525
526 /// Coerce the register to COP2 and return the real register for the
527 /// current target.
528 unsigned getCOP2Reg() const {
529 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
530 unsigned ClassID = Mips::COP2RegClassID;
531 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
532 }
533
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000534 /// Coerce the register to COP3 and return the real register for the
535 /// current target.
536 unsigned getCOP3Reg() const {
537 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
538 unsigned ClassID = Mips::COP3RegClassID;
539 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
540 }
541
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000542 /// Coerce the register to ACC64DSP and return the real register for the
543 /// current target.
544 unsigned getACC64DSPReg() const {
545 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
546 unsigned ClassID = Mips::ACC64DSPRegClassID;
547 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
548 }
549
550 /// Coerce the register to HI32DSP and return the real register for the
551 /// current target.
552 unsigned getHI32DSPReg() const {
553 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
554 unsigned ClassID = Mips::HI32DSPRegClassID;
555 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
556 }
557
558 /// Coerce the register to LO32DSP and return the real register for the
559 /// current target.
560 unsigned getLO32DSPReg() const {
561 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
562 unsigned ClassID = Mips::LO32DSPRegClassID;
563 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
564 }
565
566 /// Coerce the register to CCR and return the real register for the
567 /// current target.
568 unsigned getCCRReg() const {
569 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
570 unsigned ClassID = Mips::CCRRegClassID;
571 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
572 }
573
574 /// Coerce the register to HWRegs and return the real register for the
575 /// current target.
576 unsigned getHWRegsReg() const {
577 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
578 unsigned ClassID = Mips::HWRegsRegClassID;
579 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
580 }
581
582public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000583 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000584 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000585 if (!Expr)
Jack Carterb4dbc172012-09-05 23:34:03 +0000586 Inst.addOperand(MCOperand::CreateImm(0));
587 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
588 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
589 else
590 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000591 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000592
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000593 void addRegOperands(MCInst &Inst, unsigned N) const {
594 llvm_unreachable("Use a custom parser instead");
595 }
596
Daniel Sanders21bce302014-04-01 12:35:23 +0000597 /// Render the operand to an MCInst as a GPR32
598 /// Asserts if the wrong number of operands are requested, or the operand
599 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000600 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
601 assert(N == 1 && "Invalid number of operands!");
602 Inst.addOperand(MCOperand::CreateReg(getGPR32Reg()));
603 }
604
Daniel Sanders21bce302014-04-01 12:35:23 +0000605 /// Render the operand to an MCInst as a GPR64
606 /// Asserts if the wrong number of operands are requested, or the operand
607 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000608 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
609 assert(N == 1 && "Invalid number of operands!");
610 Inst.addOperand(MCOperand::CreateReg(getGPR64Reg()));
611 }
612
613 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
614 assert(N == 1 && "Invalid number of operands!");
615 Inst.addOperand(MCOperand::CreateReg(getAFGR64Reg()));
616 }
617
618 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
619 assert(N == 1 && "Invalid number of operands!");
620 Inst.addOperand(MCOperand::CreateReg(getFGR64Reg()));
621 }
622
623 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
624 assert(N == 1 && "Invalid number of operands!");
625 Inst.addOperand(MCOperand::CreateReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000626 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000627 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000628 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
629 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000630 }
631
632 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
633 assert(N == 1 && "Invalid number of operands!");
634 Inst.addOperand(MCOperand::CreateReg(getFGRH32Reg()));
635 }
636
637 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
638 assert(N == 1 && "Invalid number of operands!");
639 Inst.addOperand(MCOperand::CreateReg(getFCCReg()));
640 }
641
642 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
643 assert(N == 1 && "Invalid number of operands!");
644 Inst.addOperand(MCOperand::CreateReg(getMSA128Reg()));
645 }
646
647 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
648 assert(N == 1 && "Invalid number of operands!");
649 Inst.addOperand(MCOperand::CreateReg(getMSACtrlReg()));
650 }
651
652 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
653 assert(N == 1 && "Invalid number of operands!");
654 Inst.addOperand(MCOperand::CreateReg(getCOP2Reg()));
655 }
656
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000657 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
658 assert(N == 1 && "Invalid number of operands!");
659 Inst.addOperand(MCOperand::CreateReg(getCOP3Reg()));
660 }
661
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000662 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
663 assert(N == 1 && "Invalid number of operands!");
664 Inst.addOperand(MCOperand::CreateReg(getACC64DSPReg()));
665 }
666
667 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
668 assert(N == 1 && "Invalid number of operands!");
669 Inst.addOperand(MCOperand::CreateReg(getHI32DSPReg()));
670 }
671
672 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
673 assert(N == 1 && "Invalid number of operands!");
674 Inst.addOperand(MCOperand::CreateReg(getLO32DSPReg()));
675 }
676
677 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
678 assert(N == 1 && "Invalid number of operands!");
679 Inst.addOperand(MCOperand::CreateReg(getCCRReg()));
680 }
681
682 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
683 assert(N == 1 && "Invalid number of operands!");
684 Inst.addOperand(MCOperand::CreateReg(getHWRegsReg()));
685 }
686
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000687 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000688 assert(N == 1 && "Invalid number of operands!");
689 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000690 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000691 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000692
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000693 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000694 assert(N == 2 && "Invalid number of operands!");
695
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000696 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000697
698 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000699 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000700 }
701
Craig Topper56c590a2014-04-29 07:58:02 +0000702 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000703 // As a special case until we sort out the definition of div/divu, pretend
704 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
705 if (isGPRAsmReg() && RegIdx.Index == 0)
706 return true;
707
708 return Kind == k_PhysRegister;
709 }
710 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000711 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000712 bool isConstantImm() const {
713 return isImm() && dyn_cast<MCConstantExpr>(getImm());
714 }
Craig Topper56c590a2014-04-29 07:58:02 +0000715 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000716 // Note: It's not possible to pretend that other operand kinds are tokens.
717 // The matcher emitter checks tokens first.
718 return Kind == k_Token;
719 }
Craig Topper56c590a2014-04-29 07:58:02 +0000720 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000721 bool isConstantMemOff() const {
722 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
723 }
724 template <unsigned Bits> bool isMemWithSimmOffset() const {
725 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff());
726 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000727 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000728 bool isLSAImm() const {
729 if (!isConstantImm())
730 return false;
731 int64_t Val = getConstantImm();
732 return 1 <= Val && Val <= 4;
733 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000734
735 StringRef getToken() const {
736 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000737 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000738 }
739
Craig Topper56c590a2014-04-29 07:58:02 +0000740 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000741 // As a special case until we sort out the definition of div/divu, pretend
742 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
743 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
744 RegIdx.Kind & RegKind_GPR)
745 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000746
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000747 assert(Kind == k_PhysRegister && "Invalid access!");
748 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +0000749 }
750
Jack Carterb4dbc172012-09-05 23:34:03 +0000751 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000752 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000753 return Imm.Val;
754 }
755
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000756 int64_t getConstantImm() const {
757 const MCExpr *Val = getImm();
758 return static_cast<const MCConstantExpr *>(Val)->getValue();
759 }
760
761 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000762 assert((Kind == k_Memory) && "Invalid access!");
763 return Mem.Base;
764 }
765
766 const MCExpr *getMemOff() const {
767 assert((Kind == k_Memory) && "Invalid access!");
768 return Mem.Off;
769 }
770
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000771 int64_t getConstantMemOff() const {
772 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
773 }
774
David Blaikie960ea3f2014-06-08 16:18:35 +0000775 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
776 MipsAsmParser &Parser) {
777 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000778 Op->Tok.Data = Str.data();
779 Op->Tok.Length = Str.size();
780 Op->StartLoc = S;
781 Op->EndLoc = S;
782 return Op;
783 }
784
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000785 /// Create a numeric register (e.g. $1). The exact register remains
786 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +0000787 static std::unique_ptr<MipsOperand>
788 CreateNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
789 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000790 DEBUG(dbgs() << "CreateNumericReg(" << Index << ", ...)\n");
791 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000792 }
793
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000794 /// Create a register that is definitely a GPR.
795 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +0000796 static std::unique_ptr<MipsOperand>
797 CreateGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
798 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000799 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000800 }
801
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000802 /// Create a register that is definitely a FGR.
803 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000804 static std::unique_ptr<MipsOperand>
805 CreateFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
806 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000807 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
808 }
809
810 /// Create a register that is definitely an FCC.
811 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000812 static std::unique_ptr<MipsOperand>
813 CreateFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
814 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000815 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
816 }
817
818 /// Create a register that is definitely an ACC.
819 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000820 static std::unique_ptr<MipsOperand>
821 CreateACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
822 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000823 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
824 }
825
826 /// Create a register that is definitely an MSA128.
827 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000828 static std::unique_ptr<MipsOperand>
829 CreateMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
830 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000831 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
832 }
833
834 /// Create a register that is definitely an MSACtrl.
835 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +0000836 static std::unique_ptr<MipsOperand>
837 CreateMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
838 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000839 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
840 }
841
David Blaikie960ea3f2014-06-08 16:18:35 +0000842 static std::unique_ptr<MipsOperand>
843 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
844 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000845 Op->Imm.Val = Val;
846 Op->StartLoc = S;
847 Op->EndLoc = E;
848 return Op;
849 }
850
David Blaikie960ea3f2014-06-08 16:18:35 +0000851 static std::unique_ptr<MipsOperand>
852 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
853 SMLoc E, MipsAsmParser &Parser) {
854 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
855 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +0000856 Op->Mem.Off = Off;
857 Op->StartLoc = S;
858 Op->EndLoc = E;
859 return Op;
860 }
861
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000862 bool isGPRAsmReg() const {
863 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000864 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000865 bool isFGRAsmReg() const {
866 // AFGR64 is $0-$15 but we handle this in getAFGR64()
867 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000868 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000869 bool isHWRegsAsmReg() const {
870 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000871 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000872 bool isCCRAsmReg() const {
873 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000874 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000875 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000876 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
877 return false;
878 if (!AsmParser.hasEightFccRegisters())
879 return RegIdx.Index == 0;
880 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +0000881 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000882 bool isACCAsmReg() const {
883 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +0000884 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000885 bool isCOP2AsmReg() const {
886 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +0000887 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000888 bool isCOP3AsmReg() const {
889 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
890 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000891 bool isMSA128AsmReg() const {
892 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +0000893 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000894 bool isMSACtrlAsmReg() const {
895 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000896 }
897
Jack Carterb4dbc172012-09-05 23:34:03 +0000898 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +0000899 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +0000900 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +0000901 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +0000902
NAKAMURA Takumie1f35832014-04-15 14:13:21 +0000903 virtual ~MipsOperand() {
904 switch (Kind) {
905 case k_Immediate:
906 break;
907 case k_Memory:
908 delete Mem.Base;
909 break;
910 case k_PhysRegister:
911 case k_RegisterIndex:
912 case k_Token:
913 break;
914 }
915 }
916
Craig Topper56c590a2014-04-29 07:58:02 +0000917 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000918 switch (Kind) {
919 case k_Immediate:
920 OS << "Imm<";
921 Imm.Val->print(OS);
922 OS << ">";
923 break;
924 case k_Memory:
925 OS << "Mem<";
926 Mem.Base->print(OS);
927 OS << ", ";
928 Mem.Off->print(OS);
929 OS << ">";
930 break;
931 case k_PhysRegister:
932 OS << "PhysReg<" << PhysReg.Num << ">";
933 break;
934 case k_RegisterIndex:
935 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
936 break;
937 case k_Token:
938 OS << Tok.Data;
939 break;
940 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000941 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000942}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +0000943} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000944
Jack Carter9e65aa32013-03-22 00:05:30 +0000945namespace llvm {
946extern const MCInstrDesc MipsInsts[];
947}
948static const MCInstrDesc &getInstDesc(unsigned Opcode) {
949 return MipsInsts[Opcode];
950}
951
952bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +0000953 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000954 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +0000955
Jack Carter9e65aa32013-03-22 00:05:30 +0000956 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000957
958 if (MCID.isBranch() || MCID.isCall()) {
959 const unsigned Opcode = Inst.getOpcode();
960 MCOperand Offset;
961
962 switch (Opcode) {
963 default:
964 break;
965 case Mips::BEQ:
966 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000967 case Mips::BEQ_MM:
968 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +0000969 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000970 Offset = Inst.getOperand(2);
971 if (!Offset.isImm())
972 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000973 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000974 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000975 if (OffsetToAlignment(Offset.getImm(),
976 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000977 return Error(IDLoc, "branch to misaligned address");
978 break;
979 case Mips::BGEZ:
980 case Mips::BGTZ:
981 case Mips::BLEZ:
982 case Mips::BLTZ:
983 case Mips::BGEZAL:
984 case Mips::BLTZAL:
985 case Mips::BC1F:
986 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000987 case Mips::BGEZ_MM:
988 case Mips::BGTZ_MM:
989 case Mips::BLEZ_MM:
990 case Mips::BLTZ_MM:
991 case Mips::BGEZAL_MM:
992 case Mips::BLTZAL_MM:
993 case Mips::BC1F_MM:
994 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +0000995 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000996 Offset = Inst.getOperand(1);
997 if (!Offset.isImm())
998 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000999 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001000 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001001 if (OffsetToAlignment(Offset.getImm(),
1002 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001003 return Error(IDLoc, "branch to misaligned address");
1004 break;
1005 }
1006 }
1007
Daniel Sandersa84989a2014-06-16 13:25:35 +00001008 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1009 // We still accept it but it is a normal nop.
1010 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1011 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1012 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1013 "nop instruction");
1014 }
1015
Jack Carterc15c1d22013-04-25 23:31:35 +00001016 if (MCID.hasDelaySlot() && Options.isReorder()) {
1017 // If this instruction has a delay slot and .set reorder is active,
1018 // emit a NOP after it.
1019 Instructions.push_back(Inst);
1020 MCInst NopInst;
1021 NopInst.setOpcode(Mips::SLL);
1022 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1023 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1024 NopInst.addOperand(MCOperand::CreateImm(0));
1025 Instructions.push_back(NopInst);
1026 return false;
1027 }
1028
Jack Carter9e65aa32013-03-22 00:05:30 +00001029 if (MCID.mayLoad() || MCID.mayStore()) {
1030 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001031 // reference or immediate we may have to expand instructions.
1032 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001033 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001034 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1035 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001036 MCOperand &Op = Inst.getOperand(i);
1037 if (Op.isImm()) {
1038 int MemOffset = Op.getImm();
1039 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001040 // Offset can't exceed 16bit value.
1041 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001042 return false;
1043 }
1044 } else if (Op.isExpr()) {
1045 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001046 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001047 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001048 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001049 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001050 // Expand symbol.
1051 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001052 return false;
1053 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001054 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001055 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001056 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001057 }
1058 }
1059 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001060 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001061 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001062
1063 if (needsExpansion(Inst))
Matheus Almeida3813d572014-06-19 14:39:14 +00001064 return expandInstruction(Inst, IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +00001065 else
1066 Instructions.push_back(Inst);
1067
1068 return false;
1069}
1070
Jack Carter30a59822012-10-04 04:03:53 +00001071bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1072
Jack Carterd0bd6422013-04-18 00:41:53 +00001073 switch (Inst.getOpcode()) {
1074 case Mips::LoadImm32Reg:
1075 case Mips::LoadAddr32Imm:
1076 case Mips::LoadAddr32Reg:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001077 case Mips::LoadImm64Reg:
Jack Carterd0bd6422013-04-18 00:41:53 +00001078 return true;
1079 default:
1080 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001081 }
1082}
Jack Carter92995f12012-10-06 00:53:28 +00001083
Matheus Almeida3813d572014-06-19 14:39:14 +00001084bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001085 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001086 switch (Inst.getOpcode()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001087 default:
1088 assert(0 && "unimplemented expansion");
Matheus Almeida3813d572014-06-19 14:39:14 +00001089 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001090 case Mips::LoadImm32Reg:
1091 return expandLoadImm(Inst, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001092 case Mips::LoadImm64Reg:
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001093 if (!isGP64bit()) {
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001094 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1095 return true;
1096 }
1097 return expandLoadImm(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001098 case Mips::LoadAddr32Imm:
1099 return expandLoadAddressImm(Inst, IDLoc, Instructions);
1100 case Mips::LoadAddr32Reg:
1101 return expandLoadAddressReg(Inst, IDLoc, Instructions);
1102 }
Jack Carter30a59822012-10-04 04:03:53 +00001103}
Jack Carter92995f12012-10-06 00:53:28 +00001104
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001105namespace {
1106template <int Shift, bool PerformShift>
1107void createShiftOr(int64_t Value, unsigned RegNo, SMLoc IDLoc,
1108 SmallVectorImpl<MCInst> &Instructions) {
1109 MCInst tmpInst;
1110 if (PerformShift) {
1111 tmpInst.setOpcode(Mips::DSLL);
1112 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1113 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1114 tmpInst.addOperand(MCOperand::CreateImm(16));
1115 tmpInst.setLoc(IDLoc);
1116 Instructions.push_back(tmpInst);
1117 tmpInst.clear();
1118 }
1119 tmpInst.setOpcode(Mips::ORi);
1120 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1121 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1122 tmpInst.addOperand(
1123 MCOperand::CreateImm(((Value & (0xffffLL << Shift)) >> Shift)));
1124 tmpInst.setLoc(IDLoc);
1125 Instructions.push_back(tmpInst);
1126}
1127}
1128
Matheus Almeida3813d572014-06-19 14:39:14 +00001129bool MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001130 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +00001131 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +00001132 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +00001133 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +00001134 const MCOperand &RegOp = Inst.getOperand(0);
1135 assert(RegOp.isReg() && "expected register operand kind");
1136
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001137 int64_t ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +00001138 tmpInst.setLoc(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001139 // FIXME: gas has a special case for values that are 000...1111, which
1140 // becomes a li -1 and then a dsrl
Jack Carterd0bd6422013-04-18 00:41:53 +00001141 if (0 <= ImmValue && ImmValue <= 65535) {
1142 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +00001143 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001144 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +00001145 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001146 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001147 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001148 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001149 } else if (ImmValue < 0 && ImmValue >= -32768) {
1150 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +00001151 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001152 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +00001153 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001154 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001155 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001156 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001157 } else if ((ImmValue & 0xffffffff) == ImmValue) {
1158 // For any value of j that is representable as a 32-bit integer, create
1159 // a sequence of:
Jack Carter30a59822012-10-04 04:03:53 +00001160 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001161 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001162 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001163 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1164 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +00001165 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001166 createShiftOr<0, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1167 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001168 if (!isGP64bit()) {
1169 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001170 return true;
1171 }
1172
1173 // <------- lo32 ------>
1174 // <------- hi32 ------>
1175 // <- hi16 -> <- lo16 ->
1176 // _________________________________
1177 // | | | |
1178 // | 16-bytes | 16-bytes | 16-bytes |
1179 // |__________|__________|__________|
1180 //
1181 // For any value of j that is representable as a 48-bit integer, create
1182 // a sequence of:
1183 // li d,j => lui d,hi16(j)
1184 // ori d,d,hi16(lo32(j))
1185 // dsll d,d,16
1186 // ori d,d,lo16(lo32(j))
1187 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001188 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001189 tmpInst.addOperand(
1190 MCOperand::CreateImm((ImmValue & (0xffffLL << 32)) >> 32));
Jack Carter30a59822012-10-04 04:03:53 +00001191 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001192 createShiftOr<16, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1193 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1194 } else {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001195 if (!isGP64bit()) {
1196 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001197 return true;
1198 }
1199
1200 // <------- hi32 ------> <------- lo32 ------>
1201 // <- hi16 -> <- lo16 ->
1202 // ___________________________________________
1203 // | | | | |
1204 // | 16-bytes | 16-bytes | 16-bytes | 16-bytes |
1205 // |__________|__________|__________|__________|
1206 //
1207 // For any value of j that isn't representable as a 48-bit integer.
1208 // li d,j => lui d,hi16(j)
1209 // ori d,d,lo16(hi32(j))
1210 // dsll d,d,16
1211 // ori d,d,hi16(lo32(j))
1212 // dsll d,d,16
1213 // ori d,d,lo16(lo32(j))
1214 tmpInst.setOpcode(Mips::LUi);
1215 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1216 tmpInst.addOperand(
1217 MCOperand::CreateImm((ImmValue & (0xffffLL << 48)) >> 48));
1218 Instructions.push_back(tmpInst);
1219 createShiftOr<32, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1220 createShiftOr<16, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1221 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
Jack Carter30a59822012-10-04 04:03:53 +00001222 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001223 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001224}
Jack Carter92995f12012-10-06 00:53:28 +00001225
Matheus Almeida3813d572014-06-19 14:39:14 +00001226bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001227MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
1228 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001229 MCInst tmpInst;
1230 const MCOperand &ImmOp = Inst.getOperand(2);
1231 assert(ImmOp.isImm() && "expected immediate operand kind");
1232 const MCOperand &SrcRegOp = Inst.getOperand(1);
1233 assert(SrcRegOp.isReg() && "expected register operand kind");
1234 const MCOperand &DstRegOp = Inst.getOperand(0);
1235 assert(DstRegOp.isReg() && "expected register operand kind");
1236 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001237 if (-32768 <= ImmValue && ImmValue <= 65535) {
1238 // For -32768 <= j <= 65535.
1239 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +00001240 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +00001241 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1242 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1243 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1244 Instructions.push_back(tmpInst);
1245 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001246 // For any other value of j that is representable as a 32-bit integer.
1247 // la d,j(s) => lui d,hi16(j)
1248 // ori d,d,lo16(j)
1249 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +00001250 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001251 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1252 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1253 Instructions.push_back(tmpInst);
1254 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001255 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001256 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1257 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1258 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1259 Instructions.push_back(tmpInst);
1260 tmpInst.clear();
1261 tmpInst.setOpcode(Mips::ADDu);
1262 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1263 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1264 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1265 Instructions.push_back(tmpInst);
1266 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001267 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001268}
1269
Matheus Almeida3813d572014-06-19 14:39:14 +00001270bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001271MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1272 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001273 MCInst tmpInst;
1274 const MCOperand &ImmOp = Inst.getOperand(1);
1275 assert(ImmOp.isImm() && "expected immediate operand kind");
1276 const MCOperand &RegOp = Inst.getOperand(0);
1277 assert(RegOp.isReg() && "expected register operand kind");
1278 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001279 if (-32768 <= ImmValue && ImmValue <= 65535) {
1280 // For -32768 <= j <= 65535.
1281 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +00001282 tmpInst.setOpcode(Mips::ADDiu);
1283 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001284 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +00001285 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1286 Instructions.push_back(tmpInst);
1287 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001288 // For any other value of j that is representable as a 32-bit integer.
1289 // la d,j => lui d,hi16(j)
1290 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001291 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001292 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1293 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1294 Instructions.push_back(tmpInst);
1295 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001296 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001297 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1298 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1299 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1300 Instructions.push_back(tmpInst);
1301 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001302 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001303}
1304
Jack Carter9e65aa32013-03-22 00:05:30 +00001305void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001306 SmallVectorImpl<MCInst> &Instructions,
1307 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001308 const MCSymbolRefExpr *SR;
1309 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00001310 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00001311 const MCExpr *ExprOffset;
1312 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00001313 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001314 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1315 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001316 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001317 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1318 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001319 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00001320 if (isImmOpnd) {
1321 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
1322 ImmOffset = Inst.getOperand(2).getImm();
1323 LoOffset = ImmOffset & 0x0000ffff;
1324 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00001325 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00001326 if (LoOffset & 0x8000)
1327 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00001328 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001329 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001330 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00001331 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00001332 // These are some of the types of expansions we perform here:
1333 // 1) lw $8, sym => lui $8, %hi(sym)
1334 // lw $8, %lo(sym)($8)
1335 // 2) lw $8, offset($9) => lui $8, %hi(offset)
1336 // add $8, $8, $9
1337 // lw $8, %lo(offset)($9)
1338 // 3) lw $8, offset($8) => lui $at, %hi(offset)
1339 // add $at, $at, $8
1340 // lw $8, %lo(offset)($at)
1341 // 4) sw $8, sym => lui $at, %hi(sym)
1342 // sw $8, %lo(sym)($at)
1343 // 5) sw $8, offset($8) => lui $at, %hi(offset)
1344 // add $at, $at, $8
1345 // sw $8, %lo(offset)($at)
1346 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
1347 // ldc1 $f0, %lo(sym)($at)
1348 //
1349 // For load instructions we can use the destination register as a temporary
1350 // if base and dst are different (examples 1 and 2) and if the base register
1351 // is general purpose otherwise we must use $at (example 6) and error if it's
1352 // not available. For stores we must use $at (examples 4 and 5) because we
1353 // must not clobber the source register setting up the offset.
1354 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
1355 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
1356 unsigned RegClassIDOp0 =
1357 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
1358 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
1359 (RegClassIDOp0 == Mips::GPR64RegClassID);
1360 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00001361 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00001362 else {
1363 int AT = getATReg(IDLoc);
1364 // At this point we need AT to perform the expansions and we exit if it is
1365 // not available.
1366 if (!AT)
1367 return;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001368 TmpRegNum = getReg(
1369 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, AT);
Matheus Almeida7de68e72014-06-18 14:46:05 +00001370 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00001371
Jack Carter9e65aa32013-03-22 00:05:30 +00001372 TempInst.setOpcode(Mips::LUi);
1373 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1374 if (isImmOpnd)
1375 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
1376 else {
1377 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001378 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00001379 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
1380 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
1381 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001382 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001383 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001384 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00001385 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001386 }
1387 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001388 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00001389 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001390 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00001391 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00001392 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001393 TempInst.setOpcode(Mips::ADDu);
1394 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1395 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1396 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
1397 Instructions.push_back(TempInst);
1398 TempInst.clear();
Alp Tokercb402912014-01-24 17:20:08 +00001399 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00001400 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001401 TempInst.setOpcode(Inst.getOpcode());
1402 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
1403 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1404 if (isImmOpnd)
1405 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
1406 else {
1407 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001408 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
1409 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
1410 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001411 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001412 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001413 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00001414 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001415 }
1416 }
1417 Instructions.push_back(TempInst);
1418 TempInst.clear();
1419}
1420
Matheus Almeida595fcab2014-06-11 15:05:56 +00001421unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1422 // As described by the Mips32r2 spec, the registers Rd and Rs for
1423 // jalr.hb must be different.
1424 unsigned Opcode = Inst.getOpcode();
1425
1426 if (Opcode == Mips::JALR_HB &&
1427 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
1428 return Match_RequiresDifferentSrcAndDst;
1429
1430 return Match_Success;
1431}
1432
David Blaikie960ea3f2014-06-08 16:18:35 +00001433bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1434 OperandVector &Operands,
1435 MCStreamer &Out,
1436 unsigned &ErrorInfo,
1437 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00001438
Jack Carterb4dbc172012-09-05 23:34:03 +00001439 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00001440 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00001441 unsigned MatchResult =
1442 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00001443
1444 switch (MatchResult) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001445 default:
1446 break;
Jack Carterb4dbc172012-09-05 23:34:03 +00001447 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001448 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00001449 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001450 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00001451 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00001452 return false;
1453 }
1454 case Match_MissingFeature:
1455 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1456 return true;
1457 case Match_InvalidOperand: {
1458 SMLoc ErrorLoc = IDLoc;
1459 if (ErrorInfo != ~0U) {
1460 if (ErrorInfo >= Operands.size())
1461 return Error(IDLoc, "too few operands for instruction");
1462
David Blaikie960ea3f2014-06-08 16:18:35 +00001463 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001464 if (ErrorLoc == SMLoc())
1465 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00001466 }
1467
1468 return Error(ErrorLoc, "invalid operand for instruction");
1469 }
1470 case Match_MnemonicFail:
1471 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00001472 case Match_RequiresDifferentSrcAndDst:
1473 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00001474 }
Rafael Espindola870c4e92012-01-11 03:56:41 +00001475 return true;
1476}
1477
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001478void MipsAsmParser::WarnIfAssemblerTemporary(int RegIndex, SMLoc Loc) {
1479 if ((RegIndex != 0) && ((int)Options.getATRegNum() == RegIndex)) {
1480 if (RegIndex == 1)
1481 Warning(Loc, "Used $at without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001482 else
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001483 Warning(Loc, Twine("Used $") + Twine(RegIndex) + " with \".set at=$" +
1484 Twine(RegIndex) + "\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001485 }
1486}
1487
Jack Carter1ac53222013-02-20 23:11:17 +00001488int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001489 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00001490
Vladimir Medic4c299852013-11-06 11:27:05 +00001491 CC = StringSwitch<unsigned>(Name)
1492 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001493 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00001494 .Case("a0", 4)
1495 .Case("a1", 5)
1496 .Case("a2", 6)
1497 .Case("a3", 7)
1498 .Case("v0", 2)
1499 .Case("v1", 3)
1500 .Case("s0", 16)
1501 .Case("s1", 17)
1502 .Case("s2", 18)
1503 .Case("s3", 19)
1504 .Case("s4", 20)
1505 .Case("s5", 21)
1506 .Case("s6", 22)
1507 .Case("s7", 23)
1508 .Case("k0", 26)
1509 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001510 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00001511 .Case("sp", 29)
1512 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001513 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00001514 .Case("ra", 31)
1515 .Case("t0", 8)
1516 .Case("t1", 9)
1517 .Case("t2", 10)
1518 .Case("t3", 11)
1519 .Case("t4", 12)
1520 .Case("t5", 13)
1521 .Case("t6", 14)
1522 .Case("t7", 15)
1523 .Case("t8", 24)
1524 .Case("t9", 25)
1525 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00001526
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001527 if (isABI_N32() || isABI_N64()) {
Daniel Sandersa4b0c742014-03-26 11:39:07 +00001528 // Although SGI documentation just cuts out t0-t3 for n32/n64,
1529 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
1530 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
1531 if (8 <= CC && CC <= 11)
1532 CC += 4;
Jack Carter1ac53222013-02-20 23:11:17 +00001533
Daniel Sandersa4b0c742014-03-26 11:39:07 +00001534 if (CC == -1)
1535 CC = StringSwitch<unsigned>(Name)
1536 .Case("a4", 8)
1537 .Case("a5", 9)
1538 .Case("a6", 10)
1539 .Case("a7", 11)
1540 .Case("kt0", 26)
1541 .Case("kt1", 27)
1542 .Default(-1);
1543 }
Jack Carter1ac53222013-02-20 23:11:17 +00001544
1545 return CC;
1546}
Jack Carterd0bd6422013-04-18 00:41:53 +00001547
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001548int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001549
Jack Cartera63b16a2012-09-07 00:23:42 +00001550 if (Name[0] == 'f') {
1551 StringRef NumString = Name.substr(1);
1552 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001553 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001554 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001555 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00001556 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001557 return IntVal;
1558 }
1559 return -1;
1560}
Jack Cartera63b16a2012-09-07 00:23:42 +00001561
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001562int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
1563
1564 if (Name.startswith("fcc")) {
1565 StringRef NumString = Name.substr(3);
1566 unsigned IntVal;
1567 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001568 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001569 if (IntVal > 7) // There are only 8 fcc registers.
1570 return -1;
1571 return IntVal;
1572 }
1573 return -1;
1574}
1575
1576int MipsAsmParser::matchACRegisterName(StringRef Name) {
1577
Akira Hatanaka274d24c2013-08-14 01:15:52 +00001578 if (Name.startswith("ac")) {
1579 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001580 unsigned IntVal;
1581 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001582 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001583 if (IntVal > 3) // There are only 3 acc registers.
1584 return -1;
1585 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00001586 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001587 return -1;
1588}
Jack Carterd0bd6422013-04-18 00:41:53 +00001589
Jack Carter5dc8ac92013-09-25 23:50:44 +00001590int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
1591 unsigned IntVal;
1592
1593 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
1594 return -1;
1595
1596 if (IntVal > 31)
1597 return -1;
1598
1599 return IntVal;
1600}
1601
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001602int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
1603 int CC;
1604
1605 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00001606 .Case("msair", 0)
1607 .Case("msacsr", 1)
1608 .Case("msaaccess", 2)
1609 .Case("msasave", 3)
1610 .Case("msamodify", 4)
1611 .Case("msarequest", 5)
1612 .Case("msamap", 6)
1613 .Case("msaunmap", 7)
1614 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001615
1616 return CC;
1617}
1618
Jack Carter0b744b32012-10-04 02:29:46 +00001619bool MipsAssemblerOptions::setATReg(unsigned Reg) {
1620 if (Reg > 31)
1621 return false;
1622
1623 aTReg = Reg;
1624 return true;
1625}
1626
Matheus Almeida7de68e72014-06-18 14:46:05 +00001627int MipsAsmParser::getATReg(SMLoc Loc) {
Daniel Sandersd89b1362014-03-24 16:48:01 +00001628 int AT = Options.getATRegNum();
1629 if (AT == 0)
Matheus Almeida7de68e72014-06-18 14:46:05 +00001630 reportParseError(Loc,
1631 "Pseudo instruction requires $at, which is not available");
Daniel Sandersd89b1362014-03-24 16:48:01 +00001632 return AT;
1633}
Jack Carter0b744b32012-10-04 02:29:46 +00001634
Jack Carterd0bd6422013-04-18 00:41:53 +00001635unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00001636 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00001637}
1638
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001639unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001640 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00001641 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001642}
1643
Jack Carter873c7242013-01-12 01:03:14 +00001644int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001645 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00001646 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00001647 return -1;
1648
Jack Carter873c7242013-01-12 01:03:14 +00001649 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00001650}
1651
David Blaikie960ea3f2014-06-08 16:18:35 +00001652bool MipsAsmParser::ParseOperand(OperandVector &Operands, StringRef Mnemonic) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001653 DEBUG(dbgs() << "ParseOperand\n");
1654
Jack Carter30a59822012-10-04 04:03:53 +00001655 // Check if the current operand has a custom associated parser, if so, try to
1656 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00001657 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
1658 if (ResTy == MatchOperand_Success)
1659 return false;
1660 // If there wasn't a custom match, try the generic matcher below. Otherwise,
1661 // there was a match, but an error occurred, in which case, just return that
1662 // the operand parsing failed.
1663 if (ResTy == MatchOperand_ParseFail)
1664 return true;
1665
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001666 DEBUG(dbgs() << ".. Generic Parser\n");
1667
Jack Carterb4dbc172012-09-05 23:34:03 +00001668 switch (getLexer().getKind()) {
1669 default:
1670 Error(Parser.getTok().getLoc(), "unexpected token in operand");
1671 return true;
1672 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001673 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00001674 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00001675
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001676 // Almost all registers have been parsed by custom parsers. There is only
1677 // one exception to this. $zero (and it's alias $0) will reach this point
1678 // for div, divu, and similar instructions because it is not an operand
1679 // to the instruction definition but an explicit register. Special case
1680 // this situation for now.
1681 if (ParseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00001682 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001683
Jack Carterd0bd6422013-04-18 00:41:53 +00001684 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00001685 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001686 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00001687 return true;
1688
Jack Carter873c7242013-01-12 01:03:14 +00001689 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00001690 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00001691 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00001692 const MCExpr *Res =
1693 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00001694
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001695 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00001696 return false;
1697 }
Vladimir Medic4c299852013-11-06 11:27:05 +00001698 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00001699 case AsmToken::LParen:
1700 case AsmToken::Minus:
1701 case AsmToken::Plus:
1702 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00001703 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00001704 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001705 DEBUG(dbgs() << ".. generic integer\n");
1706 OperandMatchResultTy ResTy = ParseImm(Operands);
1707 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00001708 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00001709 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001710 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001711 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001712 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00001713 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00001714 return true;
1715
Jack Carter873c7242013-01-12 01:03:14 +00001716 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1717
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001718 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001719 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001720 } // case AsmToken::Percent
1721 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00001722 return true;
1723}
1724
Vladimir Medic4c299852013-11-06 11:27:05 +00001725const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00001726 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00001727 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00001728 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001729 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00001730 // It's a constant, evaluate reloc value.
1731 int16_t Val;
1732 switch (getVariantKind(RelocStr)) {
1733 case MCSymbolRefExpr::VK_Mips_ABS_LO:
1734 // Get the 1st 16-bits.
1735 Val = MCE->getValue() & 0xffff;
1736 break;
1737 case MCSymbolRefExpr::VK_Mips_ABS_HI:
1738 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
1739 // 16 bits being negative.
1740 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
1741 break;
1742 case MCSymbolRefExpr::VK_Mips_HIGHER:
1743 // Get the 3rd 16-bits.
1744 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
1745 break;
1746 case MCSymbolRefExpr::VK_Mips_HIGHEST:
1747 // Get the 4th 16-bits.
1748 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
1749 break;
1750 default:
1751 report_fatal_error("Unsupported reloc value!");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001752 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00001753 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00001754 }
1755
Jack Carterb5cf5902013-04-17 00:18:04 +00001756 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001757 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00001758 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00001759 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00001760 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001761 return Res;
1762 }
1763
1764 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00001765 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
1766
Sasa Stankovic06c47802014-04-03 10:37:45 +00001767 // Try to create target expression.
1768 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
1769 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00001770
Jack Carterd0bd6422013-04-18 00:41:53 +00001771 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
1772 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00001773 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
1774 return Res;
1775 }
1776
1777 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001778 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
1779 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
1780 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00001781 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001782 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001783 return Expr;
1784}
1785
1786bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
1787
1788 switch (Expr->getKind()) {
1789 case MCExpr::Constant:
1790 return true;
1791 case MCExpr::SymbolRef:
1792 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
1793 case MCExpr::Binary:
1794 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
1795 if (!isEvaluated(BE->getLHS()))
1796 return false;
1797 return isEvaluated(BE->getRHS());
1798 }
1799 case MCExpr::Unary:
1800 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00001801 case MCExpr::Target:
1802 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001803 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001804 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00001805}
Jack Carterd0bd6422013-04-18 00:41:53 +00001806
Jack Carterb5cf5902013-04-17 00:18:04 +00001807bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001808 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00001809 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00001810 if (Tok.isNot(AsmToken::Identifier))
1811 return true;
1812
1813 std::string Str = Tok.getIdentifier().str();
1814
Jack Carterd0bd6422013-04-18 00:41:53 +00001815 Parser.Lex(); // Eat the identifier.
1816 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001817 const MCExpr *IdVal;
1818 SMLoc EndLoc;
1819
1820 if (getLexer().getKind() == AsmToken::LParen) {
1821 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001822 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001823 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001824 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001825 const AsmToken &nextTok = Parser.getTok();
1826 if (nextTok.isNot(AsmToken::Identifier))
1827 return true;
1828 Str += "(%";
1829 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00001830 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00001831 if (getLexer().getKind() != AsmToken::LParen)
1832 return true;
1833 } else
1834 break;
1835 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001836 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00001837 return true;
1838
1839 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00001840 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001841
1842 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00001843 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001844
Jack Carterd0bd6422013-04-18 00:41:53 +00001845 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00001846 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001847}
1848
Jack Carterb4dbc172012-09-05 23:34:03 +00001849bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1850 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001851 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001852 OperandMatchResultTy ResTy = ParseAnyRegister(Operands);
1853 if (ResTy == MatchOperand_Success) {
1854 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00001855 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001856 StartLoc = Operand.getStartLoc();
1857 EndLoc = Operand.getEndLoc();
1858
1859 // AFAIK, we only support numeric registers and named GPR's in CFI
1860 // directives.
1861 // Don't worry about eating tokens before failing. Using an unrecognised
1862 // register is a parse error.
1863 if (Operand.isGPRAsmReg()) {
1864 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001865 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001866 }
1867
1868 return (RegNo == (unsigned)-1);
1869 }
1870
1871 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00001872 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00001873}
1874
Jack Carterb5cf5902013-04-17 00:18:04 +00001875bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00001876 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001877 bool Result = true;
1878
1879 while (getLexer().getKind() == AsmToken::LParen)
1880 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00001881
Jack Carterd0bd6422013-04-18 00:41:53 +00001882 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001883 default:
1884 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00001885 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00001886 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00001887 case AsmToken::Integer:
1888 case AsmToken::Minus:
1889 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00001890 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00001891 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00001892 else
1893 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00001894 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00001895 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001896 break;
Jack Carter873c7242013-01-12 01:03:14 +00001897 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00001898 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00001899 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001900 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001901}
1902
David Blaikie960ea3f2014-06-08 16:18:35 +00001903MipsAsmParser::OperandMatchResultTy
1904MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001905 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00001906 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00001907 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001908 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001909 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00001910 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00001911 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001912
Jack Carterb5cf5902013-04-17 00:18:04 +00001913 if (getLexer().getKind() == AsmToken::LParen) {
1914 Parser.Lex();
1915 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001916 }
1917
Jack Carterb5cf5902013-04-17 00:18:04 +00001918 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001919 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00001920 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001921
Jack Carterd0bd6422013-04-18 00:41:53 +00001922 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001923 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001924 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
1925 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00001926 SMLoc E =
1927 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001928 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00001929 return MatchOperand_Success;
1930 }
1931 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001932 SMLoc E =
1933 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00001934
Jack Carterd0bd6422013-04-18 00:41:53 +00001935 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001936 // "Base" will be managed by k_Memory.
David Blaikie960ea3f2014-06-08 16:18:35 +00001937 auto Base = MipsOperand::CreateGPRReg(0, getContext().getRegisterInfo(),
1938 S, E, *this);
1939 Operands.push_back(
1940 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00001941 return MatchOperand_Success;
1942 }
1943 Error(Parser.getTok().getLoc(), "'(' expected");
1944 return MatchOperand_ParseFail;
1945 }
1946
Jack Carterd0bd6422013-04-18 00:41:53 +00001947 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001948 }
1949
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001950 Res = ParseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001951 if (Res != MatchOperand_Success)
1952 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001953
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001954 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001955 Error(Parser.getTok().getLoc(), "')' expected");
1956 return MatchOperand_ParseFail;
1957 }
1958
Jack Carter873c7242013-01-12 01:03:14 +00001959 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1960
Jack Carterd0bd6422013-04-18 00:41:53 +00001961 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001962
Craig Topper062a2ba2014-04-25 05:30:21 +00001963 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00001964 IdVal = MCConstantExpr::Create(0, getContext());
1965
Jack Carterd0bd6422013-04-18 00:41:53 +00001966 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00001967 std::unique_ptr<MipsOperand> op(
1968 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001969 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00001970 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001971 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00001972 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001973 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
1974 int64_t Imm;
1975 if (IdVal->EvaluateAsAbsolute(Imm))
1976 IdVal = MCConstantExpr::Create(Imm, getContext());
1977 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
1978 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
1979 getContext());
1980 }
1981
David Blaikie960ea3f2014-06-08 16:18:35 +00001982 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00001983 return MatchOperand_Success;
1984}
1985
David Blaikie960ea3f2014-06-08 16:18:35 +00001986bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Daniel Sanderse34a1202014-03-31 18:51:43 +00001987
Jack Carterd76b2372013-03-21 21:44:16 +00001988 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
1989 if (Sym) {
1990 SMLoc S = Parser.getTok().getLoc();
1991 const MCExpr *Expr;
1992 if (Sym->isVariable())
1993 Expr = Sym->getVariableValue();
1994 else
1995 return false;
1996 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001997 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carterd76b2372013-03-21 21:44:16 +00001998 const StringRef DefSymbol = Ref->getSymbol().getName();
1999 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002000 OperandMatchResultTy ResTy =
2001 MatchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00002002 if (ResTy == MatchOperand_Success) {
2003 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00002004 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00002005 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002006 llvm_unreachable("Should never ParseFail");
2007 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00002008 }
2009 } else if (Expr->getKind() == MCExpr::Constant) {
2010 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00002011 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00002012 Operands.push_back(
2013 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00002014 return true;
2015 }
2016 }
2017 return false;
2018}
Jack Carterd0bd6422013-04-18 00:41:53 +00002019
Jack Carter873c7242013-01-12 01:03:14 +00002020MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002021MipsAsmParser::MatchAnyRegisterNameWithoutDollar(OperandVector &Operands,
2022 StringRef Identifier,
2023 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002024 int Index = matchCPURegisterName(Identifier);
2025 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002026 Operands.push_back(MipsOperand::CreateGPRReg(
2027 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2028 return MatchOperand_Success;
2029 }
2030
2031 Index = matchFPURegisterName(Identifier);
2032 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002033 Operands.push_back(MipsOperand::CreateFGRReg(
2034 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2035 return MatchOperand_Success;
2036 }
2037
2038 Index = matchFCCRegisterName(Identifier);
2039 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002040 Operands.push_back(MipsOperand::CreateFCCReg(
2041 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2042 return MatchOperand_Success;
2043 }
2044
2045 Index = matchACRegisterName(Identifier);
2046 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002047 Operands.push_back(MipsOperand::CreateACCReg(
2048 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2049 return MatchOperand_Success;
2050 }
2051
2052 Index = matchMSA128RegisterName(Identifier);
2053 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002054 Operands.push_back(MipsOperand::CreateMSA128Reg(
2055 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2056 return MatchOperand_Success;
2057 }
2058
2059 Index = matchMSA128CtrlRegisterName(Identifier);
2060 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002061 Operands.push_back(MipsOperand::CreateMSACtrlReg(
2062 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2063 return MatchOperand_Success;
2064 }
2065
2066 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00002067}
2068
2069MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002070MipsAsmParser::MatchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Daniel Sanders315386c2014-04-01 10:40:14 +00002071 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002072
2073 if (Token.is(AsmToken::Identifier)) {
2074 DEBUG(dbgs() << ".. identifier\n");
2075 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00002076 OperandMatchResultTy ResTy =
2077 MatchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00002078 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002079 } else if (Token.is(AsmToken::Integer)) {
2080 DEBUG(dbgs() << ".. integer\n");
2081 Operands.push_back(MipsOperand::CreateNumericReg(
2082 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
2083 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002084 return MatchOperand_Success;
2085 }
2086
2087 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
2088
2089 return MatchOperand_NoMatch;
2090}
2091
David Blaikie960ea3f2014-06-08 16:18:35 +00002092MipsAsmParser::OperandMatchResultTy
2093MipsAsmParser::ParseAnyRegister(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002094 DEBUG(dbgs() << "ParseAnyRegister\n");
2095
2096 auto Token = Parser.getTok();
2097
2098 SMLoc S = Token.getLoc();
2099
2100 if (Token.isNot(AsmToken::Dollar)) {
2101 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
2102 if (Token.is(AsmToken::Identifier)) {
2103 if (searchSymbolAlias(Operands))
2104 return MatchOperand_Success;
2105 }
2106 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
2107 return MatchOperand_NoMatch;
2108 }
2109 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002110
Daniel Sanders21bce302014-04-01 12:35:23 +00002111 OperandMatchResultTy ResTy = MatchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00002112 if (ResTy == MatchOperand_Success) {
2113 Parser.Lex(); // $
2114 Parser.Lex(); // identifier
2115 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002116 return ResTy;
2117}
2118
2119MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002120MipsAsmParser::ParseImm(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002121 switch (getLexer().getKind()) {
2122 default:
2123 return MatchOperand_NoMatch;
2124 case AsmToken::LParen:
2125 case AsmToken::Minus:
2126 case AsmToken::Plus:
2127 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002128 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002129 case AsmToken::String:
2130 break;
2131 }
2132
2133 const MCExpr *IdVal;
2134 SMLoc S = Parser.getTok().getLoc();
2135 if (getParser().parseExpression(IdVal))
2136 return MatchOperand_ParseFail;
2137
2138 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2139 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
2140 return MatchOperand_Success;
2141}
2142
David Blaikie960ea3f2014-06-08 16:18:35 +00002143MipsAsmParser::OperandMatchResultTy
2144MipsAsmParser::ParseJumpTarget(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002145 DEBUG(dbgs() << "ParseJumpTarget\n");
2146
2147 SMLoc S = getLexer().getLoc();
2148
2149 // Integers and expressions are acceptable
2150 OperandMatchResultTy ResTy = ParseImm(Operands);
2151 if (ResTy != MatchOperand_NoMatch)
2152 return ResTy;
2153
Daniel Sanders315386c2014-04-01 10:40:14 +00002154 // Registers are a valid target and have priority over symbols.
2155 ResTy = ParseAnyRegister(Operands);
2156 if (ResTy != MatchOperand_NoMatch)
2157 return ResTy;
2158
Daniel Sandersffd84362014-04-01 10:41:48 +00002159 const MCExpr *Expr = nullptr;
2160 if (Parser.parseExpression(Expr)) {
2161 // We have no way of knowing if a symbol was consumed so we must ParseFail
2162 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002163 }
Daniel Sandersffd84362014-04-01 10:41:48 +00002164 Operands.push_back(
2165 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002166 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00002167}
2168
Vladimir Medic2b953d02013-10-01 09:48:56 +00002169MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002170MipsAsmParser::parseInvNum(OperandVector &Operands) {
Vladimir Medic2b953d02013-10-01 09:48:56 +00002171 const MCExpr *IdVal;
2172 // If the first token is '$' we may have register operand.
2173 if (Parser.getTok().is(AsmToken::Dollar))
2174 return MatchOperand_NoMatch;
2175 SMLoc S = Parser.getTok().getLoc();
2176 if (getParser().parseExpression(IdVal))
2177 return MatchOperand_ParseFail;
2178 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00002179 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00002180 int64_t Val = MCE->getValue();
2181 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2182 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002183 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00002184 return MatchOperand_Success;
2185}
2186
Matheus Almeida779c5932013-11-18 12:32:49 +00002187MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002188MipsAsmParser::ParseLSAImm(OperandVector &Operands) {
Matheus Almeida779c5932013-11-18 12:32:49 +00002189 switch (getLexer().getKind()) {
2190 default:
2191 return MatchOperand_NoMatch;
2192 case AsmToken::LParen:
2193 case AsmToken::Plus:
2194 case AsmToken::Minus:
2195 case AsmToken::Integer:
2196 break;
2197 }
2198
2199 const MCExpr *Expr;
2200 SMLoc S = Parser.getTok().getLoc();
2201
2202 if (getParser().parseExpression(Expr))
2203 return MatchOperand_ParseFail;
2204
2205 int64_t Val;
2206 if (!Expr->EvaluateAsAbsolute(Val)) {
2207 Error(S, "expected immediate value");
2208 return MatchOperand_ParseFail;
2209 }
2210
2211 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
2212 // and because the CPU always adds one to the immediate field, the allowed
2213 // range becomes 1..4. We'll only check the range here and will deal
2214 // with the addition/subtraction when actually decoding/encoding
2215 // the instruction.
2216 if (Val < 1 || Val > 4) {
2217 Error(S, "immediate not in range (1..4)");
2218 return MatchOperand_ParseFail;
2219 }
2220
Jack Carter3b2c96e2014-01-22 23:31:38 +00002221 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002222 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00002223 return MatchOperand_Success;
2224}
2225
Jack Carterdc1e35d2012-09-06 20:00:02 +00002226MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
2227
Vladimir Medic4c299852013-11-06 11:27:05 +00002228 MCSymbolRefExpr::VariantKind VK =
2229 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
2230 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
2231 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
2232 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
2233 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
2234 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
2235 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
2236 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
2237 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
2238 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
2239 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
2240 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
2241 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
2242 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
2243 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
2244 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
2245 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
2246 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00002247 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
2248 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
2249 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
2250 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
2251 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
2252 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00002253 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
2254 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00002255 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002256
Matheus Almeida2852af82014-04-22 10:15:54 +00002257 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00002258
Jack Carterdc1e35d2012-09-06 20:00:02 +00002259 return VK;
2260}
Jack Cartera63b16a2012-09-07 00:23:42 +00002261
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002262/// Sometimes (i.e. load/stores) the operand may be followed immediately by
2263/// either this.
2264/// ::= '(', register, ')'
2265/// handle it before we iterate so we don't get tripped up by the lack of
2266/// a comma.
David Blaikie960ea3f2014-06-08 16:18:35 +00002267bool MipsAsmParser::ParseParenSuffix(StringRef Name, OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002268 if (getLexer().is(AsmToken::LParen)) {
2269 Operands.push_back(
2270 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
2271 Parser.Lex();
2272 if (ParseOperand(Operands, Name)) {
2273 SMLoc Loc = getLexer().getLoc();
2274 Parser.eatToEndOfStatement();
2275 return Error(Loc, "unexpected token in argument list");
2276 }
2277 if (Parser.getTok().isNot(AsmToken::RParen)) {
2278 SMLoc Loc = getLexer().getLoc();
2279 Parser.eatToEndOfStatement();
2280 return Error(Loc, "unexpected token, expected ')'");
2281 }
2282 Operands.push_back(
2283 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
2284 Parser.Lex();
2285 }
2286 return false;
2287}
2288
2289/// Sometimes (i.e. in MSA) the operand may be followed immediately by
2290/// either one of these.
2291/// ::= '[', register, ']'
2292/// ::= '[', integer, ']'
2293/// handle it before we iterate so we don't get tripped up by the lack of
2294/// a comma.
David Blaikie960ea3f2014-06-08 16:18:35 +00002295bool MipsAsmParser::ParseBracketSuffix(StringRef Name,
2296 OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002297 if (getLexer().is(AsmToken::LBrac)) {
2298 Operands.push_back(
2299 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
2300 Parser.Lex();
2301 if (ParseOperand(Operands, Name)) {
2302 SMLoc Loc = getLexer().getLoc();
2303 Parser.eatToEndOfStatement();
2304 return Error(Loc, "unexpected token in argument list");
2305 }
2306 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2307 SMLoc Loc = getLexer().getLoc();
2308 Parser.eatToEndOfStatement();
2309 return Error(Loc, "unexpected token, expected ']'");
2310 }
2311 Operands.push_back(
2312 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
2313 Parser.Lex();
2314 }
2315 return false;
2316}
2317
David Blaikie960ea3f2014-06-08 16:18:35 +00002318bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
2319 SMLoc NameLoc, OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002320 DEBUG(dbgs() << "ParseInstruction\n");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002321 // We have reached first instruction, module directive after
2322 // this is forbidden.
2323 getTargetStreamer().setCanHaveModuleDir(false);
Vladimir Medic74593e62013-07-17 15:00:42 +00002324 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00002325 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00002326 Parser.eatToEndOfStatement();
2327 return Error(NameLoc, "Unknown instruction");
2328 }
Vladimir Medic64828a12013-07-16 10:07:14 +00002329 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002330 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002331
2332 // Read the remaining operands.
2333 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2334 // Read the first operand.
Vladimir Medic64828a12013-07-16 10:07:14 +00002335 if (ParseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002336 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002337 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002338 return Error(Loc, "unexpected token in argument list");
2339 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002340 if (getLexer().is(AsmToken::LBrac) && ParseBracketSuffix(Name, Operands))
2341 return true;
2342 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00002343
Jack Carterd0bd6422013-04-18 00:41:53 +00002344 while (getLexer().is(AsmToken::Comma)) {
2345 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00002346 // Parse and remember the operand.
2347 if (ParseOperand(Operands, Name)) {
2348 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002349 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002350 return Error(Loc, "unexpected token in argument list");
2351 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002352 // Parse bracket and parenthesis suffixes before we iterate
2353 if (getLexer().is(AsmToken::LBrac)) {
2354 if (ParseBracketSuffix(Name, Operands))
2355 return true;
2356 } else if (getLexer().is(AsmToken::LParen) &&
2357 ParseParenSuffix(Name, Operands))
2358 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00002359 }
2360 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002361 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2362 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002363 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002364 return Error(Loc, "unexpected token in argument list");
2365 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002366 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00002367 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00002368}
2369
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002370bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002371 SMLoc Loc = getLexer().getLoc();
2372 Parser.eatToEndOfStatement();
2373 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00002374}
2375
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002376bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002377 return Error(Loc, ErrorMsg);
2378}
2379
Jack Carter0b744b32012-10-04 02:29:46 +00002380bool MipsAsmParser::parseSetNoAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002381 // Line should look like: ".set noat".
2382 // set at reg to 0.
Jack Carter99d2afe2012-10-05 23:55:28 +00002383 Options.setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00002384 // eat noat
2385 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002386 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002387 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2388 reportParseError("unexpected token in statement");
2389 return false;
2390 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002391 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002392 return false;
2393}
Jack Carterd0bd6422013-04-18 00:41:53 +00002394
Jack Carter0b744b32012-10-04 02:29:46 +00002395bool MipsAsmParser::parseSetAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002396 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00002397 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00002398 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00002399 getParser().Lex();
2400 if (getLexer().is(AsmToken::EndOfStatement)) {
Jack Carter99d2afe2012-10-05 23:55:28 +00002401 Options.setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00002402 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002403 return false;
2404 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002405 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00002406 if (getLexer().isNot(AsmToken::Dollar)) {
2407 reportParseError("unexpected token in statement");
2408 return false;
2409 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002410 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00002411 const AsmToken &Reg = Parser.getTok();
2412 if (Reg.is(AsmToken::Identifier)) {
2413 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
2414 } else if (Reg.is(AsmToken::Integer)) {
2415 AtRegNo = Reg.getIntVal();
2416 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00002417 reportParseError("unexpected token in statement");
2418 return false;
2419 }
Jack Carter1ac53222013-02-20 23:11:17 +00002420
Daniel Sanders71a89d922014-03-25 13:01:06 +00002421 if (AtRegNo < 0 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00002422 reportParseError("unexpected token in statement");
2423 return false;
2424 }
2425
2426 if (!Options.setATReg(AtRegNo)) {
Jack Carter0b744b32012-10-04 02:29:46 +00002427 reportParseError("unexpected token in statement");
2428 return false;
2429 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002430 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00002431
2432 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2433 reportParseError("unexpected token in statement");
2434 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002435 }
2436 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002437 return false;
2438 } else {
2439 reportParseError("unexpected token in statement");
2440 return false;
2441 }
2442}
2443
2444bool MipsAsmParser::parseSetReorderDirective() {
2445 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002446 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002447 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2448 reportParseError("unexpected token in statement");
2449 return false;
2450 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002451 Options.setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00002452 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002453 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002454 return false;
2455}
2456
2457bool MipsAsmParser::parseSetNoReorderDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002458 Parser.Lex();
2459 // If this is not the end of the statement, report an error.
2460 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2461 reportParseError("unexpected token in statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002462 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002463 }
2464 Options.setNoreorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00002465 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002466 Parser.Lex(); // Consume the EndOfStatement.
2467 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002468}
2469
2470bool MipsAsmParser::parseSetMacroDirective() {
2471 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002472 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002473 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2474 reportParseError("unexpected token in statement");
2475 return false;
2476 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002477 Options.setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002478 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002479 return false;
2480}
2481
2482bool MipsAsmParser::parseSetNoMacroDirective() {
2483 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002484 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002485 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2486 reportParseError("`noreorder' must be set before `nomacro'");
2487 return false;
2488 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002489 if (Options.isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00002490 reportParseError("`noreorder' must be set before `nomacro'");
2491 return false;
2492 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002493 Options.setNomacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002494 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002495 return false;
2496}
Jack Carterd76b2372013-03-21 21:44:16 +00002497
Daniel Sanders44934432014-08-07 12:03:36 +00002498bool MipsAsmParser::parseSetMsaDirective() {
2499 Parser.Lex();
2500
2501 // If this is not the end of the statement, report an error.
2502 if (getLexer().isNot(AsmToken::EndOfStatement))
2503 return reportParseError("unexpected token in statement");
2504
2505 setFeatureBits(Mips::FeatureMSA, "msa");
2506 getTargetStreamer().emitDirectiveSetMsa();
2507 return false;
2508}
2509
2510bool MipsAsmParser::parseSetNoMsaDirective() {
2511 Parser.Lex();
2512
2513 // If this is not the end of the statement, report an error.
2514 if (getLexer().isNot(AsmToken::EndOfStatement))
2515 return reportParseError("unexpected token in statement");
2516
2517 clearFeatureBits(Mips::FeatureMSA, "msa");
2518 getTargetStreamer().emitDirectiveSetNoMsa();
2519 return false;
2520}
2521
Jack Carter39536722014-01-22 23:08:42 +00002522bool MipsAsmParser::parseSetNoMips16Directive() {
2523 Parser.Lex();
2524 // If this is not the end of the statement, report an error.
2525 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2526 reportParseError("unexpected token in statement");
2527 return false;
2528 }
2529 // For now do nothing.
2530 Parser.Lex(); // Consume the EndOfStatement.
2531 return false;
2532}
2533
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002534bool MipsAsmParser::parseSetFpDirective() {
Daniel Sanders7e527422014-07-10 13:38:23 +00002535 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002536 // Line can be: .set fp=32
2537 // .set fp=xx
2538 // .set fp=64
2539 Parser.Lex(); // Eat fp token
2540 AsmToken Tok = Parser.getTok();
2541 if (Tok.isNot(AsmToken::Equal)) {
2542 reportParseError("unexpected token in statement");
2543 return false;
2544 }
2545 Parser.Lex(); // Eat '=' token.
2546 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002547
2548 if (!parseFpABIValue(FpAbiVal, ".set"))
2549 return false;
2550
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002551 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2552 reportParseError("unexpected token in statement");
2553 return false;
2554 }
Daniel Sanders7e527422014-07-10 13:38:23 +00002555 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002556 Parser.Lex(); // Consume the EndOfStatement.
2557 return false;
2558}
2559
Jack Carterd76b2372013-03-21 21:44:16 +00002560bool MipsAsmParser::parseSetAssignment() {
2561 StringRef Name;
2562 const MCExpr *Value;
2563
2564 if (Parser.parseIdentifier(Name))
2565 reportParseError("expected identifier after .set");
2566
2567 if (getLexer().isNot(AsmToken::Comma))
2568 return reportParseError("unexpected token in .set directive");
Jack Carterb5cf5902013-04-17 00:18:04 +00002569 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00002570
Jack Carter3b2c96e2014-01-22 23:31:38 +00002571 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00002572 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00002573
Jack Carterd0bd6422013-04-18 00:41:53 +00002574 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00002575 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00002576 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00002577 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00002578 Sym = getContext().GetOrCreateSymbol(Name);
2579 Sym->setVariableValue(Value);
2580
2581 return false;
2582}
Jack Carterd0bd6422013-04-18 00:41:53 +00002583
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002584bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
2585 Parser.Lex();
2586 if (getLexer().isNot(AsmToken::EndOfStatement))
2587 return reportParseError("unexpected token in .set directive");
2588
Matheus Almeida2852af82014-04-22 10:15:54 +00002589 switch (Feature) {
2590 default:
2591 llvm_unreachable("Unimplemented feature");
2592 case Mips::FeatureDSP:
2593 setFeatureBits(Mips::FeatureDSP, "dsp");
2594 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002595 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002596 case Mips::FeatureMicroMips:
2597 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002598 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002599 case Mips::FeatureMips16:
2600 getTargetStreamer().emitDirectiveSetMips16();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002601 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00002602 case Mips::FeatureMips1:
2603 selectArch("mips1");
2604 getTargetStreamer().emitDirectiveSetMips1();
2605 break;
2606 case Mips::FeatureMips2:
2607 selectArch("mips2");
2608 getTargetStreamer().emitDirectiveSetMips2();
2609 break;
2610 case Mips::FeatureMips3:
2611 selectArch("mips3");
2612 getTargetStreamer().emitDirectiveSetMips3();
2613 break;
2614 case Mips::FeatureMips4:
2615 selectArch("mips4");
2616 getTargetStreamer().emitDirectiveSetMips4();
2617 break;
2618 case Mips::FeatureMips5:
2619 selectArch("mips5");
2620 getTargetStreamer().emitDirectiveSetMips5();
2621 break;
2622 case Mips::FeatureMips32:
2623 selectArch("mips32");
2624 getTargetStreamer().emitDirectiveSetMips32();
2625 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002626 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00002627 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00002628 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002629 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00002630 case Mips::FeatureMips32r6:
2631 selectArch("mips32r6");
2632 getTargetStreamer().emitDirectiveSetMips32R6();
2633 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002634 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00002635 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00002636 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00002637 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002638 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00002639 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00002640 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00002641 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00002642 case Mips::FeatureMips64r6:
2643 selectArch("mips64r6");
2644 getTargetStreamer().emitDirectiveSetMips64R6();
2645 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002646 }
2647 return false;
2648}
2649
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002650bool MipsAsmParser::eatComma(StringRef ErrorStr) {
2651 if (getLexer().isNot(AsmToken::Comma)) {
2652 SMLoc Loc = getLexer().getLoc();
2653 Parser.eatToEndOfStatement();
2654 return Error(Loc, ErrorStr);
2655 }
2656
Matheus Almeida2852af82014-04-22 10:15:54 +00002657 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002658 return true;
2659}
2660
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002661bool MipsAsmParser::parseDirectiveCPLoad(SMLoc Loc) {
2662 if (Options.isReorder())
2663 Warning(Loc, ".cpload in reorder section");
2664
2665 // FIXME: Warn if cpload is used in Mips16 mode.
2666
David Blaikie960ea3f2014-06-08 16:18:35 +00002667 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002668 OperandMatchResultTy ResTy = ParseAnyRegister(Reg);
2669 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
2670 reportParseError("expected register containing function address");
2671 return false;
2672 }
2673
David Blaikie960ea3f2014-06-08 16:18:35 +00002674 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
2675 if (!RegOpnd.isGPRAsmReg()) {
2676 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002677 return false;
2678 }
2679
David Blaikie960ea3f2014-06-08 16:18:35 +00002680 getTargetStreamer().emitDirectiveCpload(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002681 return false;
2682}
2683
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002684bool MipsAsmParser::parseDirectiveCPSetup() {
2685 unsigned FuncReg;
2686 unsigned Save;
2687 bool SaveIsReg = true;
2688
Matheus Almeida7e815762014-06-18 13:08:59 +00002689 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
2690 OperandMatchResultTy ResTy = ParseAnyRegister(TmpReg);
2691 if (ResTy == MatchOperand_NoMatch) {
2692 reportParseError("expected register containing function address");
2693 Parser.eatToEndOfStatement();
2694 return false;
2695 }
2696
2697 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
2698 if (!FuncRegOpnd.isGPRAsmReg()) {
2699 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
2700 Parser.eatToEndOfStatement();
2701 return false;
2702 }
2703
2704 FuncReg = FuncRegOpnd.getGPR32Reg();
2705 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002706
2707 if (!eatComma("expected comma parsing directive"))
2708 return true;
2709
Matheus Almeida7e815762014-06-18 13:08:59 +00002710 ResTy = ParseAnyRegister(TmpReg);
2711 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002712 const AsmToken &Tok = Parser.getTok();
2713 if (Tok.is(AsmToken::Integer)) {
2714 Save = Tok.getIntVal();
2715 SaveIsReg = false;
2716 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00002717 } else {
2718 reportParseError("expected save register or stack offset");
2719 Parser.eatToEndOfStatement();
2720 return false;
2721 }
2722 } else {
2723 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
2724 if (!SaveOpnd.isGPRAsmReg()) {
2725 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
2726 Parser.eatToEndOfStatement();
2727 return false;
2728 }
2729 Save = SaveOpnd.getGPR32Reg();
2730 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002731
2732 if (!eatComma("expected comma parsing directive"))
2733 return true;
2734
2735 StringRef Name;
2736 if (Parser.parseIdentifier(Name))
2737 reportParseError("expected identifier");
2738 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002739
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00002740 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, *Sym, SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002741 return false;
2742}
2743
Matheus Almeida0051f2d2014-04-16 15:48:55 +00002744bool MipsAsmParser::parseDirectiveNaN() {
2745 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2746 const AsmToken &Tok = Parser.getTok();
2747
2748 if (Tok.getString() == "2008") {
2749 Parser.Lex();
2750 getTargetStreamer().emitDirectiveNaN2008();
2751 return false;
2752 } else if (Tok.getString() == "legacy") {
2753 Parser.Lex();
2754 getTargetStreamer().emitDirectiveNaNLegacy();
2755 return false;
2756 }
2757 }
2758 // If we don't recognize the option passed to the .nan
2759 // directive (e.g. no option or unknown option), emit an error.
2760 reportParseError("invalid option in .nan directive");
2761 return false;
2762}
2763
Jack Carter0b744b32012-10-04 02:29:46 +00002764bool MipsAsmParser::parseDirectiveSet() {
2765
Jack Carterd0bd6422013-04-18 00:41:53 +00002766 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00002767 const AsmToken &Tok = Parser.getTok();
2768
2769 if (Tok.getString() == "noat") {
2770 return parseSetNoAtDirective();
2771 } else if (Tok.getString() == "at") {
2772 return parseSetAtDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002773 } else if (Tok.getString() == "fp") {
2774 return parseSetFpDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00002775 } else if (Tok.getString() == "reorder") {
2776 return parseSetReorderDirective();
2777 } else if (Tok.getString() == "noreorder") {
2778 return parseSetNoReorderDirective();
2779 } else if (Tok.getString() == "macro") {
2780 return parseSetMacroDirective();
2781 } else if (Tok.getString() == "nomacro") {
2782 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00002783 } else if (Tok.getString() == "mips16") {
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002784 return parseSetFeature(Mips::FeatureMips16);
Jack Carter0b744b32012-10-04 02:29:46 +00002785 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00002786 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00002787 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00002788 getTargetStreamer().emitDirectiveSetNoMicroMips();
2789 Parser.eatToEndOfStatement();
2790 return false;
2791 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002792 return parseSetFeature(Mips::FeatureMicroMips);
Daniel Sandersf0df2212014-08-04 12:20:00 +00002793 } else if (Tok.getString() == "mips1") {
2794 return parseSetFeature(Mips::FeatureMips1);
2795 } else if (Tok.getString() == "mips2") {
2796 return parseSetFeature(Mips::FeatureMips2);
2797 } else if (Tok.getString() == "mips3") {
2798 return parseSetFeature(Mips::FeatureMips3);
2799 } else if (Tok.getString() == "mips4") {
2800 return parseSetFeature(Mips::FeatureMips4);
2801 } else if (Tok.getString() == "mips5") {
2802 return parseSetFeature(Mips::FeatureMips5);
2803 } else if (Tok.getString() == "mips32") {
2804 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00002805 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002806 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sandersf0df2212014-08-04 12:20:00 +00002807 } else if (Tok.getString() == "mips32r6") {
2808 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00002809 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002810 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00002811 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002812 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sandersf0df2212014-08-04 12:20:00 +00002813 } else if (Tok.getString() == "mips64r6") {
2814 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00002815 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002816 return parseSetFeature(Mips::FeatureDSP);
Daniel Sanders44934432014-08-07 12:03:36 +00002817 } else if (Tok.getString() == "msa") {
2818 return parseSetMsaDirective();
2819 } else if (Tok.getString() == "nomsa") {
2820 return parseSetNoMsaDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00002821 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002822 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00002823 parseSetAssignment();
2824 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002825 }
Jack Carter07c818d2013-01-25 01:31:34 +00002826
Jack Carter0b744b32012-10-04 02:29:46 +00002827 return true;
2828}
2829
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002830/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00002831/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002832bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Jack Carter07c818d2013-01-25 01:31:34 +00002833 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2834 for (;;) {
2835 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002836 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00002837 return true;
2838
2839 getParser().getStreamer().EmitValue(Value, Size);
2840
2841 if (getLexer().is(AsmToken::EndOfStatement))
2842 break;
2843
2844 // FIXME: Improve diagnostic.
2845 if (getLexer().isNot(AsmToken::Comma))
2846 return Error(L, "unexpected token in directive");
2847 Parser.Lex();
2848 }
2849 }
2850
2851 Parser.Lex();
2852 return false;
2853}
2854
Vladimir Medic4c299852013-11-06 11:27:05 +00002855/// parseDirectiveGpWord
2856/// ::= .gpword local_sym
2857bool MipsAsmParser::parseDirectiveGpWord() {
2858 const MCExpr *Value;
2859 // EmitGPRel32Value requires an expression, so we are using base class
2860 // method to evaluate the expression.
2861 if (getParser().parseExpression(Value))
2862 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00002863 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00002864
Vladimir Medice10c1122013-11-13 13:18:04 +00002865 if (getLexer().isNot(AsmToken::EndOfStatement))
Vladimir Medic4c299852013-11-06 11:27:05 +00002866 return Error(getLexer().getLoc(), "unexpected token in directive");
Vladimir Medice10c1122013-11-13 13:18:04 +00002867 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00002868 return false;
2869}
2870
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002871/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00002872/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002873bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindolab59fb732014-03-28 18:50:26 +00002874 const MCExpr *Value;
2875 // EmitGPRel64Value requires an expression, so we are using base class
2876 // method to evaluate the expression.
2877 if (getParser().parseExpression(Value))
2878 return true;
2879 getParser().getStreamer().EmitGPRel64Value(Value);
2880
2881 if (getLexer().isNot(AsmToken::EndOfStatement))
2882 return Error(getLexer().getLoc(), "unexpected token in directive");
2883 Parser.Lex(); // Eat EndOfStatement token.
2884 return false;
2885}
2886
Jack Carter0cd3c192014-01-06 23:27:31 +00002887bool MipsAsmParser::parseDirectiveOption() {
2888 // Get the option token.
2889 AsmToken Tok = Parser.getTok();
2890 // At the moment only identifiers are supported.
2891 if (Tok.isNot(AsmToken::Identifier)) {
2892 Error(Parser.getTok().getLoc(), "unexpected token in .option directive");
2893 Parser.eatToEndOfStatement();
2894 return false;
2895 }
2896
2897 StringRef Option = Tok.getIdentifier();
2898
2899 if (Option == "pic0") {
2900 getTargetStreamer().emitDirectiveOptionPic0();
2901 Parser.Lex();
2902 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2903 Error(Parser.getTok().getLoc(),
2904 "unexpected token in .option pic0 directive");
2905 Parser.eatToEndOfStatement();
2906 }
2907 return false;
2908 }
2909
Matheus Almeidaf79b2812014-03-26 13:40:29 +00002910 if (Option == "pic2") {
2911 getTargetStreamer().emitDirectiveOptionPic2();
2912 Parser.Lex();
2913 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2914 Error(Parser.getTok().getLoc(),
2915 "unexpected token in .option pic2 directive");
2916 Parser.eatToEndOfStatement();
2917 }
2918 return false;
2919 }
2920
Jack Carter0cd3c192014-01-06 23:27:31 +00002921 // Unknown option.
2922 Warning(Parser.getTok().getLoc(), "unknown option in .option directive");
2923 Parser.eatToEndOfStatement();
2924 return false;
2925}
2926
Daniel Sanders7e527422014-07-10 13:38:23 +00002927/// parseDirectiveModule
2928/// ::= .module oddspreg
2929/// ::= .module nooddspreg
2930/// ::= .module fp=value
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002931bool MipsAsmParser::parseDirectiveModule() {
Daniel Sanders7e527422014-07-10 13:38:23 +00002932 MCAsmLexer &Lexer = getLexer();
2933 SMLoc L = Lexer.getLoc();
2934
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002935 if (!getTargetStreamer().getCanHaveModuleDir()) {
2936 // TODO : get a better message.
2937 reportParseError(".module directive must appear before any code");
2938 return false;
2939 }
Daniel Sanders7e527422014-07-10 13:38:23 +00002940
2941 if (Lexer.is(AsmToken::Identifier)) {
2942 StringRef Option = Parser.getTok().getString();
2943 Parser.Lex();
2944
2945 if (Option == "oddspreg") {
2946 getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32());
2947 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
2948
2949 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2950 reportParseError("Expected end of statement");
2951 return false;
2952 }
2953
2954 return false;
2955 } else if (Option == "nooddspreg") {
2956 if (!isABI_O32()) {
2957 Error(L, "'.module nooddspreg' requires the O32 ABI");
2958 return false;
2959 }
2960
2961 getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32());
2962 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
2963
2964 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2965 reportParseError("Expected end of statement");
2966 return false;
2967 }
2968
2969 return false;
2970 } else if (Option == "fp") {
2971 return parseDirectiveModuleFP();
2972 }
2973
2974 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002975 }
Daniel Sanders7e527422014-07-10 13:38:23 +00002976
2977 return false;
2978}
2979
2980/// parseDirectiveModuleFP
2981/// ::= =32
2982/// ::= =xx
2983/// ::= =64
2984bool MipsAsmParser::parseDirectiveModuleFP() {
2985 MCAsmLexer &Lexer = getLexer();
2986
2987 if (Lexer.isNot(AsmToken::Equal)) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002988 reportParseError("unexpected token in statement");
2989 return false;
2990 }
2991 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002992
Daniel Sanders7e527422014-07-10 13:38:23 +00002993 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002994 if (!parseFpABIValue(FpABI, ".module"))
2995 return false;
2996
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002997 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2998 reportParseError("unexpected token in statement");
2999 return false;
3000 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003001
Daniel Sanders7201a3e2014-07-08 10:35:52 +00003002 // Emit appropriate flags.
3003 getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
Daniel Sanders7e527422014-07-10 13:38:23 +00003004 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003005 return false;
3006}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003007
Daniel Sanders7e527422014-07-10 13:38:23 +00003008bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003009 StringRef Directive) {
3010 MCAsmLexer &Lexer = getLexer();
3011
3012 if (Lexer.is(AsmToken::Identifier)) {
3013 StringRef Value = Parser.getTok().getString();
3014 Parser.Lex();
3015
3016 if (Value != "xx") {
3017 reportParseError("unsupported value, expected 'xx', '32' or '64'");
3018 return false;
3019 }
3020
3021 if (!isABI_O32()) {
3022 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
3023 return false;
3024 }
3025
Daniel Sanders7e527422014-07-10 13:38:23 +00003026 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003027 return true;
3028 }
3029
3030 if (Lexer.is(AsmToken::Integer)) {
3031 unsigned Value = Parser.getTok().getIntVal();
3032 Parser.Lex();
3033
3034 if (Value != 32 && Value != 64) {
3035 reportParseError("unsupported value, expected 'xx', '32' or '64'");
3036 return false;
3037 }
3038
3039 if (Value == 32) {
3040 if (!isABI_O32()) {
3041 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
3042 return false;
3043 }
3044
Daniel Sanders7e527422014-07-10 13:38:23 +00003045 FpABI = MipsABIFlagsSection::FpABIKind::S32;
3046 } else
3047 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003048
Daniel Sanders7e527422014-07-10 13:38:23 +00003049 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003050 }
3051
3052 return false;
3053}
3054
Jack Carter0b744b32012-10-04 02:29:46 +00003055bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carter07c818d2013-01-25 01:31:34 +00003056 StringRef IDVal = DirectiveID.getString();
3057
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003058 if (IDVal == ".cpload")
3059 return parseDirectiveCPLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00003060 if (IDVal == ".dword") {
3061 parseDataDirective(8, DirectiveID.getLoc());
3062 return false;
3063 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003064 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003065 StringRef SymbolName;
3066
3067 if (Parser.parseIdentifier(SymbolName)) {
3068 reportParseError("expected identifier after .ent");
3069 return false;
3070 }
3071
3072 // There's an undocumented extension that allows an integer to
3073 // follow the name of the procedure which AFAICS is ignored by GAS.
3074 // Example: .ent foo,2
3075 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3076 if (getLexer().isNot(AsmToken::Comma)) {
3077 // Even though we accept this undocumented extension for compatibility
3078 // reasons, the additional integer argument does not actually change
3079 // the behaviour of the '.ent' directive, so we would like to discourage
3080 // its use. We do this by not referring to the extended version in
3081 // error messages which are not directly related to its use.
3082 reportParseError("unexpected token, expected end of statement");
3083 return false;
3084 }
3085 Parser.Lex(); // Eat the comma.
3086 const MCExpr *DummyNumber;
3087 int64_t DummyNumberVal;
3088 // If the user was explicitly trying to use the extended version,
3089 // we still give helpful extension-related error messages.
3090 if (Parser.parseExpression(DummyNumber)) {
3091 reportParseError("expected number after comma");
3092 return false;
3093 }
3094 if (!DummyNumber->EvaluateAsAbsolute(DummyNumberVal)) {
3095 reportParseError("expected an absolute expression after comma");
3096 return false;
3097 }
3098 }
3099
3100 // If this is not the end of the statement, report an error.
3101 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3102 reportParseError("unexpected token, expected end of statement");
3103 return false;
3104 }
3105
3106 MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
3107
3108 getTargetStreamer().emitDirectiveEnt(*Sym);
3109 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00003110 return false;
3111 }
3112
Jack Carter07c818d2013-01-25 01:31:34 +00003113 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003114 StringRef SymbolName;
3115
3116 if (Parser.parseIdentifier(SymbolName)) {
3117 reportParseError("expected identifier after .end");
3118 return false;
3119 }
3120
3121 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3122 reportParseError("unexpected token, expected end of statement");
3123 return false;
3124 }
3125
3126 if (CurrentFn == nullptr) {
3127 reportParseError(".end used without .ent");
3128 return false;
3129 }
3130
3131 if ((SymbolName != CurrentFn->getName())) {
3132 reportParseError(".end symbol does not match .ent symbol");
3133 return false;
3134 }
3135
3136 getTargetStreamer().emitDirectiveEnd(SymbolName);
3137 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00003138 return false;
3139 }
3140
Jack Carter07c818d2013-01-25 01:31:34 +00003141 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003142 // .frame $stack_reg, frame_size_in_bytes, $return_reg
3143 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
3144 OperandMatchResultTy ResTy = ParseAnyRegister(TmpReg);
3145 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3146 reportParseError("expected stack register");
3147 return false;
3148 }
3149
3150 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3151 if (!StackRegOpnd.isGPRAsmReg()) {
3152 reportParseError(StackRegOpnd.getStartLoc(),
3153 "expected general purpose register");
3154 return false;
3155 }
3156 unsigned StackReg = StackRegOpnd.getGPR32Reg();
3157
3158 if (Parser.getTok().is(AsmToken::Comma))
3159 Parser.Lex();
3160 else {
3161 reportParseError("unexpected token, expected comma");
3162 return false;
3163 }
3164
3165 // Parse the frame size.
3166 const MCExpr *FrameSize;
3167 int64_t FrameSizeVal;
3168
3169 if (Parser.parseExpression(FrameSize)) {
3170 reportParseError("expected frame size value");
3171 return false;
3172 }
3173
3174 if (!FrameSize->EvaluateAsAbsolute(FrameSizeVal)) {
3175 reportParseError("frame size not an absolute expression");
3176 return false;
3177 }
3178
3179 if (Parser.getTok().is(AsmToken::Comma))
3180 Parser.Lex();
3181 else {
3182 reportParseError("unexpected token, expected comma");
3183 return false;
3184 }
3185
3186 // Parse the return register.
3187 TmpReg.clear();
3188 ResTy = ParseAnyRegister(TmpReg);
3189 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3190 reportParseError("expected return register");
3191 return false;
3192 }
3193
3194 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3195 if (!ReturnRegOpnd.isGPRAsmReg()) {
3196 reportParseError(ReturnRegOpnd.getStartLoc(),
3197 "expected general purpose register");
3198 return false;
3199 }
3200
3201 // If this is not the end of the statement, report an error.
3202 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3203 reportParseError("unexpected token, expected end of statement");
3204 return false;
3205 }
3206
3207 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
3208 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00003209 return false;
3210 }
3211
Jack Carter07c818d2013-01-25 01:31:34 +00003212 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00003213 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00003214 }
3215
Daniel Sandersd97a6342014-08-13 10:07:34 +00003216 if (IDVal == ".mask" || IDVal == ".fmask") {
3217 // .mask bitmask, frame_offset
3218 // bitmask: One bit for each register used.
3219 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
3220 // first register is expected to be saved.
3221 // Examples:
3222 // .mask 0x80000000, -4
3223 // .fmask 0x80000000, -4
3224 //
Jack Carterbe332172012-09-07 00:48:02 +00003225
Daniel Sandersd97a6342014-08-13 10:07:34 +00003226 // Parse the bitmask
3227 const MCExpr *BitMask;
3228 int64_t BitMaskVal;
3229
3230 if (Parser.parseExpression(BitMask)) {
3231 reportParseError("expected bitmask value");
3232 return false;
3233 }
3234
3235 if (!BitMask->EvaluateAsAbsolute(BitMaskVal)) {
3236 reportParseError("bitmask not an absolute expression");
3237 return false;
3238 }
3239
3240 if (Parser.getTok().is(AsmToken::Comma))
3241 Parser.Lex();
3242 else {
3243 reportParseError("unexpected token, expected comma");
3244 return false;
3245 }
3246
3247 // Parse the frame_offset
3248 const MCExpr *FrameOffset;
3249 int64_t FrameOffsetVal;
3250
3251 if (Parser.parseExpression(FrameOffset)) {
3252 reportParseError("expected frame offset value");
3253 return false;
3254 }
3255
3256 if (!FrameOffset->EvaluateAsAbsolute(FrameOffsetVal)) {
3257 reportParseError("frame offset not an absolute expression");
3258 return false;
3259 }
3260
3261 // If this is not the end of the statement, report an error.
3262 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3263 reportParseError("unexpected token, expected end of statement");
3264 return false;
3265 }
3266
3267 if (IDVal == ".mask")
3268 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
3269 else
3270 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00003271 return false;
3272 }
3273
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003274 if (IDVal == ".nan")
3275 return parseDirectiveNaN();
3276
Jack Carter07c818d2013-01-25 01:31:34 +00003277 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00003278 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00003279 return false;
3280 }
3281
Rafael Espindolab59fb732014-03-28 18:50:26 +00003282 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003283 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00003284 return false;
3285 }
3286
Jack Carter07c818d2013-01-25 01:31:34 +00003287 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003288 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00003289 return false;
3290 }
3291
Jack Carter0cd3c192014-01-06 23:27:31 +00003292 if (IDVal == ".option")
3293 return parseDirectiveOption();
3294
3295 if (IDVal == ".abicalls") {
3296 getTargetStreamer().emitDirectiveAbiCalls();
3297 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3298 Error(Parser.getTok().getLoc(), "unexpected token in directive");
3299 // Clear line
3300 Parser.eatToEndOfStatement();
3301 }
3302 return false;
3303 }
3304
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003305 if (IDVal == ".cpsetup")
3306 return parseDirectiveCPSetup();
3307
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003308 if (IDVal == ".module")
3309 return parseDirectiveModule();
3310
Rafael Espindola870c4e92012-01-11 03:56:41 +00003311 return true;
3312}
3313
Rafael Espindola870c4e92012-01-11 03:56:41 +00003314extern "C" void LLVMInitializeMipsAsmParser() {
3315 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
3316 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
3317 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
3318 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
3319}
Jack Carterb4dbc172012-09-05 23:34:03 +00003320
3321#define GET_REGISTER_MATCHER
3322#define GET_MATCHER_IMPLEMENTATION
3323#include "MipsGenAsmMatcher.inc"