blob: fde2dc4285169ed6bf6e3162da36f8fce80ceb35 [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,
Tim Northover26bb14e2014-08-18 11:49:42 +000097 uint64_t &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
Toma Tabacu0d64b202014-08-14 10:29:17 +0000151 void expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
152 SmallVectorImpl<MCInst> &Instructions);
153
Jack Carter9e65aa32013-03-22 00:05:30 +0000154 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000155 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
156 bool isImmOpnd);
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000157 bool reportParseError(Twine ErrorMsg);
158 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000159
Jack Carterb5cf5902013-04-17 00:18:04 +0000160 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000161 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000162
Vladimir Medic4c299852013-11-06 11:27:05 +0000163 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000164
165 bool isEvaluated(const MCExpr *Expr);
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000166 bool parseSetFeature(uint64_t Feature);
Matheus Almeida525bc4f2014-04-30 11:28:42 +0000167 bool parseDirectiveCPLoad(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000168 bool parseDirectiveCPSetup();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000169 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000170 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000171 bool parseDirectiveOption();
Jack Carter0b744b32012-10-04 02:29:46 +0000172
173 bool parseSetAtDirective();
174 bool parseSetNoAtDirective();
175 bool parseSetMacroDirective();
176 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000177 bool parseSetMsaDirective();
178 bool parseSetNoMsaDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000179 bool parseSetReorderDirective();
180 bool parseSetNoReorderDirective();
Jack Carter39536722014-01-22 23:08:42 +0000181 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000182 bool parseSetFpDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000183
Jack Carterd76b2372013-03-21 21:44:16 +0000184 bool parseSetAssignment();
185
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000186 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000187 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000188 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000189 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000190 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000191 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
192 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000193
Jack Carterdc1e35d2012-09-06 20:00:02 +0000194 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000195
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000196 bool eatComma(StringRef ErrorStr);
197
Jack Carter1ac53222013-02-20 23:11:17 +0000198 int matchCPURegisterName(StringRef Symbol);
199
Jack Carter873c7242013-01-12 01:03:14 +0000200 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000201
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000202 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000203
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000204 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000205
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000206 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000207
Jack Carter5dc8ac92013-09-25 23:50:44 +0000208 int matchMSA128RegisterName(StringRef Name);
209
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000210 int matchMSA128CtrlRegisterName(StringRef Name);
211
Jack Carterd0bd6422013-04-18 00:41:53 +0000212 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000213
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000214 unsigned getGPR(int RegNo);
215
Matheus Almeida7de68e72014-06-18 14:46:05 +0000216 int getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000217
218 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000219 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000220
221 // Helper function that checks if the value of a vector index is within the
222 // boundaries of accepted values for each RegisterKind
223 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
224 bool validateMSAIndex(int Val, int RegKind);
225
Daniel Sandersf0df2212014-08-04 12:20:00 +0000226 // Selects a new architecture by updating the FeatureBits with the necessary
227 // info including implied dependencies.
228 // Internally, it clears all the feature bits related to *any* architecture
229 // and selects the new one using the ToggleFeature functionality of the
230 // MCSubtargetInfo object that handles implied dependencies. The reason we
231 // clear all the arch related bits manually is because ToggleFeature only
232 // clears the features that imply the feature being cleared and not the
233 // features implied by the feature being cleared. This is easier to see
234 // with an example:
235 // --------------------------------------------------
236 // | Feature | Implies |
237 // | -------------------------------------------------|
238 // | FeatureMips1 | None |
239 // | FeatureMips2 | FeatureMips1 |
240 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
241 // | FeatureMips4 | FeatureMips3 |
242 // | ... | |
243 // --------------------------------------------------
244 //
245 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
246 // FeatureMipsGP64 | FeatureMips1)
247 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
248 void selectArch(StringRef ArchFeature) {
249 uint64_t FeatureBits = STI.getFeatureBits();
250 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
251 STI.setFeatureBits(FeatureBits);
252 setAvailableFeatures(
253 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
254 }
255
Vladimir Medic615b26e2014-03-04 09:54:09 +0000256 void setFeatureBits(unsigned Feature, StringRef FeatureString) {
257 if (!(STI.getFeatureBits() & Feature)) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000258 setAvailableFeatures(
259 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000260 }
261 }
262
263 void clearFeatureBits(unsigned Feature, StringRef FeatureString) {
264 if (STI.getFeatureBits() & Feature) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000265 setAvailableFeatures(
266 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000267 }
268 }
269
Rafael Espindola870c4e92012-01-11 03:56:41 +0000270public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000271 enum MipsMatchResultTy {
272 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
273#define GET_OPERAND_DIAGNOSTIC_TYPES
274#include "MipsGenAsmMatcher.inc"
275#undef GET_OPERAND_DIAGNOSTIC_TYPES
276
277 };
278
Joey Gouly0e76fa72013-09-12 10:28:05 +0000279 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000280 const MCInstrInfo &MII, const MCTargetOptions &Options)
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000281 : MCTargetAsmParser(), STI(sti), Parser(parser) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000282 // Initialize the set of available features.
283 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000284
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000285 getTargetStreamer().updateABIInfo(*this);
286
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000287 // Assert exactly one ABI was chosen.
288 assert((((STI.getFeatureBits() & Mips::FeatureO32) != 0) +
289 ((STI.getFeatureBits() & Mips::FeatureEABI) != 0) +
290 ((STI.getFeatureBits() & Mips::FeatureN32) != 0) +
291 ((STI.getFeatureBits() & Mips::FeatureN64) != 0)) == 1);
Daniel Sanders7e527422014-07-10 13:38:23 +0000292
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000293 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000294 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000295
296 CurrentFn = nullptr;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000297 }
298
Jack Carterb4dbc172012-09-05 23:34:03 +0000299 MCAsmParser &getParser() const { return Parser; }
300 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000301
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000302 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
303 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
304
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000305 bool isGP64bit() const { return STI.getFeatureBits() & Mips::FeatureGP64Bit; }
306 bool isFP64bit() const { return STI.getFeatureBits() & Mips::FeatureFP64Bit; }
307 bool isABI_N32() const { return STI.getFeatureBits() & Mips::FeatureN32; }
308 bool isABI_N64() const { return STI.getFeatureBits() & Mips::FeatureN64; }
309 bool isABI_O32() const { return STI.getFeatureBits() & Mips::FeatureO32; }
Daniel Sandersa6e125f2014-07-15 15:31:39 +0000310 bool isABI_FPXX() const { return STI.getFeatureBits() & Mips::FeatureFPXX; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000311
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000312 bool useOddSPReg() const {
Daniel Sanders7e527422014-07-10 13:38:23 +0000313 return !(STI.getFeatureBits() & Mips::FeatureNoOddSPReg);
314 }
315
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000316 bool inMicroMipsMode() const {
317 return STI.getFeatureBits() & Mips::FeatureMicroMips;
318 }
319 bool hasMips1() const { return STI.getFeatureBits() & Mips::FeatureMips1; }
320 bool hasMips2() const { return STI.getFeatureBits() & Mips::FeatureMips2; }
321 bool hasMips3() const { return STI.getFeatureBits() & Mips::FeatureMips3; }
322 bool hasMips4() const { return STI.getFeatureBits() & Mips::FeatureMips4; }
323 bool hasMips5() const { return STI.getFeatureBits() & Mips::FeatureMips5; }
324 bool hasMips32() const {
325 return (STI.getFeatureBits() & Mips::FeatureMips32);
326 }
327 bool hasMips64() const {
328 return (STI.getFeatureBits() & Mips::FeatureMips64);
329 }
330 bool hasMips32r2() const {
331 return (STI.getFeatureBits() & Mips::FeatureMips32r2);
332 }
333 bool hasMips64r2() const {
334 return (STI.getFeatureBits() & Mips::FeatureMips64r2);
335 }
336 bool hasMips32r6() const {
337 return (STI.getFeatureBits() & Mips::FeatureMips32r6);
338 }
339 bool hasMips64r6() const {
340 return (STI.getFeatureBits() & Mips::FeatureMips64r6);
341 }
342 bool hasDSP() const { return (STI.getFeatureBits() & Mips::FeatureDSP); }
343 bool hasDSPR2() const { return (STI.getFeatureBits() & Mips::FeatureDSPR2); }
344 bool hasMSA() const { return (STI.getFeatureBits() & Mips::FeatureMSA); }
345
346 bool inMips16Mode() const {
347 return STI.getFeatureBits() & Mips::FeatureMips16;
348 }
349 // TODO: see how can we get this info.
Eric Christopher7394e232014-07-18 00:08:50 +0000350 bool abiUsesSoftFloat() const { return false; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000351
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000352 /// Warn if RegNo is the current assembler temporary.
353 void WarnIfAssemblerTemporary(int RegNo, SMLoc Loc);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000354};
355}
356
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000357namespace {
358
359/// MipsOperand - Instances of this class represent a parsed Mips machine
360/// instruction.
361class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000362public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000363 /// Broad categories of register classes
364 /// The exact class is finalized by the render method.
365 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000366 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000367 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000368 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000369 RegKind_FCC = 4, /// FCC
370 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
371 RegKind_MSACtrl = 16, /// MSA control registers
372 RegKind_COP2 = 32, /// COP2
373 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
374 /// context).
375 RegKind_CCR = 128, /// CCR
376 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000377 RegKind_COP3 = 512, /// COP3
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000378
379 /// Potentially any (e.g. $1)
380 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
381 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000382 RegKind_CCR | RegKind_HWRegs | RegKind_COP3
Jack Carter873c7242013-01-12 01:03:14 +0000383 };
384
385private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000386 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000387 k_Immediate, /// An immediate (possibly involving symbol references)
388 k_Memory, /// Base + Offset Memory Address
389 k_PhysRegister, /// A physical register from the Mips namespace
390 k_RegisterIndex, /// A register index in one or more RegKind.
391 k_Token /// A simple token
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000392 } Kind;
393
David Blaikie960ea3f2014-06-08 16:18:35 +0000394public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000395 MipsOperand(KindTy K, MipsAsmParser &Parser)
396 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
397
David Blaikie960ea3f2014-06-08 16:18:35 +0000398private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000399 /// For diagnostics, and checking the assembler temporary
400 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000401
Eric Christopher8996c5d2013-03-15 00:42:55 +0000402 struct Token {
403 const char *Data;
404 unsigned Length;
405 };
406
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000407 struct PhysRegOp {
408 unsigned Num; /// Register Number
409 };
410
411 struct RegIdxOp {
412 unsigned Index; /// Index into the register class
413 RegKind Kind; /// Bitfield of the kinds it could possibly be
414 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000415 };
416
417 struct ImmOp {
418 const MCExpr *Val;
419 };
420
421 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000422 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000423 const MCExpr *Off;
424 };
425
Jack Carterb4dbc172012-09-05 23:34:03 +0000426 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000427 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000428 struct PhysRegOp PhysReg;
429 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000430 struct ImmOp Imm;
431 struct MemOp Mem;
Jack Carterb4dbc172012-09-05 23:34:03 +0000432 };
433
434 SMLoc StartLoc, EndLoc;
435
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000436 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000437 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
438 const MCRegisterInfo *RegInfo,
439 SMLoc S, SMLoc E,
440 MipsAsmParser &Parser) {
441 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000442 Op->RegIdx.Index = Index;
443 Op->RegIdx.RegInfo = RegInfo;
444 Op->RegIdx.Kind = RegKind;
445 Op->StartLoc = S;
446 Op->EndLoc = E;
447 return Op;
448 }
449
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000450public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000451 /// Coerce the register to GPR32 and return the real register for the current
452 /// target.
453 unsigned getGPR32Reg() const {
454 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
455 AsmParser.WarnIfAssemblerTemporary(RegIdx.Index, StartLoc);
456 unsigned ClassID = Mips::GPR32RegClassID;
457 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000458 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000459
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000460 /// Coerce the register to GPR64 and return the real register for the current
461 /// target.
462 unsigned getGPR64Reg() const {
463 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
464 unsigned ClassID = Mips::GPR64RegClassID;
465 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000466 }
467
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000468private:
469 /// Coerce the register to AFGR64 and return the real register for the current
470 /// target.
471 unsigned getAFGR64Reg() const {
472 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
473 if (RegIdx.Index % 2 != 0)
474 AsmParser.Warning(StartLoc, "Float register should be even.");
475 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
476 .getRegister(RegIdx.Index / 2);
477 }
478
479 /// Coerce the register to FGR64 and return the real register for the current
480 /// target.
481 unsigned getFGR64Reg() const {
482 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
483 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
484 .getRegister(RegIdx.Index);
485 }
486
487 /// Coerce the register to FGR32 and return the real register for the current
488 /// target.
489 unsigned getFGR32Reg() const {
490 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
491 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
492 .getRegister(RegIdx.Index);
493 }
494
495 /// Coerce the register to FGRH32 and return the real register for the current
496 /// target.
497 unsigned getFGRH32Reg() const {
498 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
499 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
500 .getRegister(RegIdx.Index);
501 }
502
503 /// Coerce the register to FCC and return the real register for the current
504 /// target.
505 unsigned getFCCReg() const {
506 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
507 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
508 .getRegister(RegIdx.Index);
509 }
510
511 /// Coerce the register to MSA128 and return the real register for the current
512 /// target.
513 unsigned getMSA128Reg() const {
514 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
515 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
516 // identical
517 unsigned ClassID = Mips::MSA128BRegClassID;
518 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
519 }
520
521 /// Coerce the register to MSACtrl and return the real register for the
522 /// current target.
523 unsigned getMSACtrlReg() const {
524 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
525 unsigned ClassID = Mips::MSACtrlRegClassID;
526 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
527 }
528
529 /// Coerce the register to COP2 and return the real register for the
530 /// current target.
531 unsigned getCOP2Reg() const {
532 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
533 unsigned ClassID = Mips::COP2RegClassID;
534 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
535 }
536
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000537 /// Coerce the register to COP3 and return the real register for the
538 /// current target.
539 unsigned getCOP3Reg() const {
540 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
541 unsigned ClassID = Mips::COP3RegClassID;
542 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
543 }
544
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000545 /// Coerce the register to ACC64DSP and return the real register for the
546 /// current target.
547 unsigned getACC64DSPReg() const {
548 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
549 unsigned ClassID = Mips::ACC64DSPRegClassID;
550 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
551 }
552
553 /// Coerce the register to HI32DSP and return the real register for the
554 /// current target.
555 unsigned getHI32DSPReg() const {
556 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
557 unsigned ClassID = Mips::HI32DSPRegClassID;
558 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
559 }
560
561 /// Coerce the register to LO32DSP and return the real register for the
562 /// current target.
563 unsigned getLO32DSPReg() const {
564 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
565 unsigned ClassID = Mips::LO32DSPRegClassID;
566 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
567 }
568
569 /// Coerce the register to CCR and return the real register for the
570 /// current target.
571 unsigned getCCRReg() const {
572 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
573 unsigned ClassID = Mips::CCRRegClassID;
574 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
575 }
576
577 /// Coerce the register to HWRegs and return the real register for the
578 /// current target.
579 unsigned getHWRegsReg() const {
580 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
581 unsigned ClassID = Mips::HWRegsRegClassID;
582 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
583 }
584
585public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000586 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000587 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000588 if (!Expr)
Jack Carterb4dbc172012-09-05 23:34:03 +0000589 Inst.addOperand(MCOperand::CreateImm(0));
590 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
591 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
592 else
593 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000594 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000595
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000596 void addRegOperands(MCInst &Inst, unsigned N) const {
597 llvm_unreachable("Use a custom parser instead");
598 }
599
Daniel Sanders21bce302014-04-01 12:35:23 +0000600 /// Render the operand to an MCInst as a GPR32
601 /// Asserts if the wrong number of operands are requested, or the operand
602 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000603 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
604 assert(N == 1 && "Invalid number of operands!");
605 Inst.addOperand(MCOperand::CreateReg(getGPR32Reg()));
606 }
607
Daniel Sanders21bce302014-04-01 12:35:23 +0000608 /// Render the operand to an MCInst as a GPR64
609 /// Asserts if the wrong number of operands are requested, or the operand
610 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000611 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
612 assert(N == 1 && "Invalid number of operands!");
613 Inst.addOperand(MCOperand::CreateReg(getGPR64Reg()));
614 }
615
616 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
617 assert(N == 1 && "Invalid number of operands!");
618 Inst.addOperand(MCOperand::CreateReg(getAFGR64Reg()));
619 }
620
621 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
622 assert(N == 1 && "Invalid number of operands!");
623 Inst.addOperand(MCOperand::CreateReg(getFGR64Reg()));
624 }
625
626 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
627 assert(N == 1 && "Invalid number of operands!");
628 Inst.addOperand(MCOperand::CreateReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000629 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000630 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000631 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
632 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000633 }
634
635 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
636 assert(N == 1 && "Invalid number of operands!");
637 Inst.addOperand(MCOperand::CreateReg(getFGRH32Reg()));
638 }
639
640 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
641 assert(N == 1 && "Invalid number of operands!");
642 Inst.addOperand(MCOperand::CreateReg(getFCCReg()));
643 }
644
645 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
646 assert(N == 1 && "Invalid number of operands!");
647 Inst.addOperand(MCOperand::CreateReg(getMSA128Reg()));
648 }
649
650 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
651 assert(N == 1 && "Invalid number of operands!");
652 Inst.addOperand(MCOperand::CreateReg(getMSACtrlReg()));
653 }
654
655 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
656 assert(N == 1 && "Invalid number of operands!");
657 Inst.addOperand(MCOperand::CreateReg(getCOP2Reg()));
658 }
659
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000660 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
661 assert(N == 1 && "Invalid number of operands!");
662 Inst.addOperand(MCOperand::CreateReg(getCOP3Reg()));
663 }
664
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000665 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
666 assert(N == 1 && "Invalid number of operands!");
667 Inst.addOperand(MCOperand::CreateReg(getACC64DSPReg()));
668 }
669
670 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
671 assert(N == 1 && "Invalid number of operands!");
672 Inst.addOperand(MCOperand::CreateReg(getHI32DSPReg()));
673 }
674
675 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
676 assert(N == 1 && "Invalid number of operands!");
677 Inst.addOperand(MCOperand::CreateReg(getLO32DSPReg()));
678 }
679
680 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
681 assert(N == 1 && "Invalid number of operands!");
682 Inst.addOperand(MCOperand::CreateReg(getCCRReg()));
683 }
684
685 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
686 assert(N == 1 && "Invalid number of operands!");
687 Inst.addOperand(MCOperand::CreateReg(getHWRegsReg()));
688 }
689
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000690 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000691 assert(N == 1 && "Invalid number of operands!");
692 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000693 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000694 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000695
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000696 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000697 assert(N == 2 && "Invalid number of operands!");
698
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000699 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000700
701 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000702 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000703 }
704
Craig Topper56c590a2014-04-29 07:58:02 +0000705 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000706 // As a special case until we sort out the definition of div/divu, pretend
707 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
708 if (isGPRAsmReg() && RegIdx.Index == 0)
709 return true;
710
711 return Kind == k_PhysRegister;
712 }
713 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000714 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000715 bool isConstantImm() const {
716 return isImm() && dyn_cast<MCConstantExpr>(getImm());
717 }
Craig Topper56c590a2014-04-29 07:58:02 +0000718 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000719 // Note: It's not possible to pretend that other operand kinds are tokens.
720 // The matcher emitter checks tokens first.
721 return Kind == k_Token;
722 }
Craig Topper56c590a2014-04-29 07:58:02 +0000723 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000724 bool isConstantMemOff() const {
725 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
726 }
727 template <unsigned Bits> bool isMemWithSimmOffset() const {
728 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff());
729 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000730 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000731 bool isLSAImm() const {
732 if (!isConstantImm())
733 return false;
734 int64_t Val = getConstantImm();
735 return 1 <= Val && Val <= 4;
736 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000737
738 StringRef getToken() const {
739 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000740 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000741 }
742
Craig Topper56c590a2014-04-29 07:58:02 +0000743 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000744 // As a special case until we sort out the definition of div/divu, pretend
745 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
746 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
747 RegIdx.Kind & RegKind_GPR)
748 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000749
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000750 assert(Kind == k_PhysRegister && "Invalid access!");
751 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +0000752 }
753
Jack Carterb4dbc172012-09-05 23:34:03 +0000754 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000755 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000756 return Imm.Val;
757 }
758
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000759 int64_t getConstantImm() const {
760 const MCExpr *Val = getImm();
761 return static_cast<const MCConstantExpr *>(Val)->getValue();
762 }
763
764 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000765 assert((Kind == k_Memory) && "Invalid access!");
766 return Mem.Base;
767 }
768
769 const MCExpr *getMemOff() const {
770 assert((Kind == k_Memory) && "Invalid access!");
771 return Mem.Off;
772 }
773
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000774 int64_t getConstantMemOff() const {
775 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
776 }
777
David Blaikie960ea3f2014-06-08 16:18:35 +0000778 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
779 MipsAsmParser &Parser) {
780 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000781 Op->Tok.Data = Str.data();
782 Op->Tok.Length = Str.size();
783 Op->StartLoc = S;
784 Op->EndLoc = S;
785 return Op;
786 }
787
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000788 /// Create a numeric register (e.g. $1). The exact register remains
789 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +0000790 static std::unique_ptr<MipsOperand>
791 CreateNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
792 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000793 DEBUG(dbgs() << "CreateNumericReg(" << Index << ", ...)\n");
794 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000795 }
796
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000797 /// Create a register that is definitely a GPR.
798 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +0000799 static std::unique_ptr<MipsOperand>
800 CreateGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
801 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000802 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000803 }
804
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000805 /// Create a register that is definitely a FGR.
806 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000807 static std::unique_ptr<MipsOperand>
808 CreateFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
809 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000810 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
811 }
812
813 /// Create a register that is definitely an FCC.
814 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000815 static std::unique_ptr<MipsOperand>
816 CreateFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
817 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000818 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
819 }
820
821 /// Create a register that is definitely an ACC.
822 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000823 static std::unique_ptr<MipsOperand>
824 CreateACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
825 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000826 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
827 }
828
829 /// Create a register that is definitely an MSA128.
830 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000831 static std::unique_ptr<MipsOperand>
832 CreateMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
833 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000834 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
835 }
836
837 /// Create a register that is definitely an MSACtrl.
838 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +0000839 static std::unique_ptr<MipsOperand>
840 CreateMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
841 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000842 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
843 }
844
David Blaikie960ea3f2014-06-08 16:18:35 +0000845 static std::unique_ptr<MipsOperand>
846 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
847 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000848 Op->Imm.Val = Val;
849 Op->StartLoc = S;
850 Op->EndLoc = E;
851 return Op;
852 }
853
David Blaikie960ea3f2014-06-08 16:18:35 +0000854 static std::unique_ptr<MipsOperand>
855 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
856 SMLoc E, MipsAsmParser &Parser) {
857 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
858 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +0000859 Op->Mem.Off = Off;
860 Op->StartLoc = S;
861 Op->EndLoc = E;
862 return Op;
863 }
864
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000865 bool isGPRAsmReg() const {
866 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000867 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000868 bool isFGRAsmReg() const {
869 // AFGR64 is $0-$15 but we handle this in getAFGR64()
870 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000871 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000872 bool isHWRegsAsmReg() const {
873 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000874 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000875 bool isCCRAsmReg() const {
876 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000877 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000878 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000879 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
880 return false;
881 if (!AsmParser.hasEightFccRegisters())
882 return RegIdx.Index == 0;
883 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +0000884 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000885 bool isACCAsmReg() const {
886 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +0000887 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000888 bool isCOP2AsmReg() const {
889 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +0000890 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000891 bool isCOP3AsmReg() const {
892 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
893 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000894 bool isMSA128AsmReg() const {
895 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +0000896 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000897 bool isMSACtrlAsmReg() const {
898 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000899 }
900
Jack Carterb4dbc172012-09-05 23:34:03 +0000901 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +0000902 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +0000903 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +0000904 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +0000905
NAKAMURA Takumie1f35832014-04-15 14:13:21 +0000906 virtual ~MipsOperand() {
907 switch (Kind) {
908 case k_Immediate:
909 break;
910 case k_Memory:
911 delete Mem.Base;
912 break;
913 case k_PhysRegister:
914 case k_RegisterIndex:
915 case k_Token:
916 break;
917 }
918 }
919
Craig Topper56c590a2014-04-29 07:58:02 +0000920 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000921 switch (Kind) {
922 case k_Immediate:
923 OS << "Imm<";
924 Imm.Val->print(OS);
925 OS << ">";
926 break;
927 case k_Memory:
928 OS << "Mem<";
929 Mem.Base->print(OS);
930 OS << ", ";
931 Mem.Off->print(OS);
932 OS << ">";
933 break;
934 case k_PhysRegister:
935 OS << "PhysReg<" << PhysReg.Num << ">";
936 break;
937 case k_RegisterIndex:
938 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
939 break;
940 case k_Token:
941 OS << Tok.Data;
942 break;
943 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000944 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000945}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +0000946} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000947
Jack Carter9e65aa32013-03-22 00:05:30 +0000948namespace llvm {
949extern const MCInstrDesc MipsInsts[];
950}
951static const MCInstrDesc &getInstDesc(unsigned Opcode) {
952 return MipsInsts[Opcode];
953}
954
955bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +0000956 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000957 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +0000958
Jack Carter9e65aa32013-03-22 00:05:30 +0000959 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000960
961 if (MCID.isBranch() || MCID.isCall()) {
962 const unsigned Opcode = Inst.getOpcode();
963 MCOperand Offset;
964
965 switch (Opcode) {
966 default:
967 break;
968 case Mips::BEQ:
969 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000970 case Mips::BEQ_MM:
971 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +0000972 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000973 Offset = Inst.getOperand(2);
974 if (!Offset.isImm())
975 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000976 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000977 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000978 if (OffsetToAlignment(Offset.getImm(),
979 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000980 return Error(IDLoc, "branch to misaligned address");
981 break;
982 case Mips::BGEZ:
983 case Mips::BGTZ:
984 case Mips::BLEZ:
985 case Mips::BLTZ:
986 case Mips::BGEZAL:
987 case Mips::BLTZAL:
988 case Mips::BC1F:
989 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000990 case Mips::BGEZ_MM:
991 case Mips::BGTZ_MM:
992 case Mips::BLEZ_MM:
993 case Mips::BLTZ_MM:
994 case Mips::BGEZAL_MM:
995 case Mips::BLTZAL_MM:
996 case Mips::BC1F_MM:
997 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +0000998 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000999 Offset = Inst.getOperand(1);
1000 if (!Offset.isImm())
1001 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001002 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001003 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001004 if (OffsetToAlignment(Offset.getImm(),
1005 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001006 return Error(IDLoc, "branch to misaligned address");
1007 break;
1008 }
1009 }
1010
Daniel Sandersa84989a2014-06-16 13:25:35 +00001011 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1012 // We still accept it but it is a normal nop.
1013 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1014 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1015 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1016 "nop instruction");
1017 }
1018
Jack Carterc15c1d22013-04-25 23:31:35 +00001019 if (MCID.hasDelaySlot() && Options.isReorder()) {
1020 // If this instruction has a delay slot and .set reorder is active,
1021 // emit a NOP after it.
1022 Instructions.push_back(Inst);
1023 MCInst NopInst;
1024 NopInst.setOpcode(Mips::SLL);
1025 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1026 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1027 NopInst.addOperand(MCOperand::CreateImm(0));
1028 Instructions.push_back(NopInst);
1029 return false;
1030 }
1031
Jack Carter9e65aa32013-03-22 00:05:30 +00001032 if (MCID.mayLoad() || MCID.mayStore()) {
1033 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001034 // reference or immediate we may have to expand instructions.
1035 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001036 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001037 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1038 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001039 MCOperand &Op = Inst.getOperand(i);
1040 if (Op.isImm()) {
1041 int MemOffset = Op.getImm();
1042 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001043 // Offset can't exceed 16bit value.
1044 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001045 return false;
1046 }
1047 } else if (Op.isExpr()) {
1048 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001049 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001050 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001051 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001052 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001053 // Expand symbol.
1054 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001055 return false;
1056 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001057 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001058 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001059 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001060 }
1061 }
1062 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001063 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001064 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001065
1066 if (needsExpansion(Inst))
Matheus Almeida3813d572014-06-19 14:39:14 +00001067 return expandInstruction(Inst, IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +00001068 else
1069 Instructions.push_back(Inst);
1070
1071 return false;
1072}
1073
Jack Carter30a59822012-10-04 04:03:53 +00001074bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1075
Jack Carterd0bd6422013-04-18 00:41:53 +00001076 switch (Inst.getOpcode()) {
1077 case Mips::LoadImm32Reg:
1078 case Mips::LoadAddr32Imm:
1079 case Mips::LoadAddr32Reg:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001080 case Mips::LoadImm64Reg:
Jack Carterd0bd6422013-04-18 00:41:53 +00001081 return true;
1082 default:
1083 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001084 }
1085}
Jack Carter92995f12012-10-06 00:53:28 +00001086
Matheus Almeida3813d572014-06-19 14:39:14 +00001087bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001088 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001089 switch (Inst.getOpcode()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001090 default:
1091 assert(0 && "unimplemented expansion");
Matheus Almeida3813d572014-06-19 14:39:14 +00001092 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001093 case Mips::LoadImm32Reg:
1094 return expandLoadImm(Inst, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001095 case Mips::LoadImm64Reg:
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001096 if (!isGP64bit()) {
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001097 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1098 return true;
1099 }
1100 return expandLoadImm(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001101 case Mips::LoadAddr32Imm:
1102 return expandLoadAddressImm(Inst, IDLoc, Instructions);
1103 case Mips::LoadAddr32Reg:
1104 return expandLoadAddressReg(Inst, IDLoc, Instructions);
1105 }
Jack Carter30a59822012-10-04 04:03:53 +00001106}
Jack Carter92995f12012-10-06 00:53:28 +00001107
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001108namespace {
Toma Tabacu0d64b202014-08-14 10:29:17 +00001109template <bool PerformShift>
1110void createShiftOr(MCOperand Operand, unsigned RegNo, SMLoc IDLoc,
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001111 SmallVectorImpl<MCInst> &Instructions) {
1112 MCInst tmpInst;
1113 if (PerformShift) {
1114 tmpInst.setOpcode(Mips::DSLL);
1115 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1116 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1117 tmpInst.addOperand(MCOperand::CreateImm(16));
1118 tmpInst.setLoc(IDLoc);
1119 Instructions.push_back(tmpInst);
1120 tmpInst.clear();
1121 }
1122 tmpInst.setOpcode(Mips::ORi);
1123 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1124 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001125 tmpInst.addOperand(Operand);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001126 tmpInst.setLoc(IDLoc);
1127 Instructions.push_back(tmpInst);
1128}
Toma Tabacu0d64b202014-08-14 10:29:17 +00001129
1130template <int Shift, bool PerformShift>
1131void createShiftOr(int64_t Value, unsigned RegNo, SMLoc IDLoc,
1132 SmallVectorImpl<MCInst> &Instructions) {
1133 createShiftOr<PerformShift>(
1134 MCOperand::CreateImm(((Value & (0xffffLL << Shift)) >> Shift)), RegNo,
1135 IDLoc, Instructions);
1136}
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001137}
1138
Matheus Almeida3813d572014-06-19 14:39:14 +00001139bool MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001140 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +00001141 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +00001142 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +00001143 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +00001144 const MCOperand &RegOp = Inst.getOperand(0);
1145 assert(RegOp.isReg() && "expected register operand kind");
1146
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001147 int64_t ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +00001148 tmpInst.setLoc(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001149 // FIXME: gas has a special case for values that are 000...1111, which
1150 // becomes a li -1 and then a dsrl
Jack Carterd0bd6422013-04-18 00:41:53 +00001151 if (0 <= ImmValue && ImmValue <= 65535) {
1152 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +00001153 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001154 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +00001155 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001156 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001157 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001158 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001159 } else if (ImmValue < 0 && ImmValue >= -32768) {
1160 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +00001161 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001162 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +00001163 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001164 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001165 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001166 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001167 } else if ((ImmValue & 0xffffffff) == ImmValue) {
1168 // For any value of j that is representable as a 32-bit integer, create
1169 // a sequence of:
Jack Carter30a59822012-10-04 04:03:53 +00001170 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001171 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001172 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001173 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1174 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +00001175 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001176 createShiftOr<0, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1177 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001178 if (!isGP64bit()) {
1179 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001180 return true;
1181 }
1182
1183 // <------- lo32 ------>
1184 // <------- hi32 ------>
1185 // <- hi16 -> <- lo16 ->
1186 // _________________________________
1187 // | | | |
1188 // | 16-bytes | 16-bytes | 16-bytes |
1189 // |__________|__________|__________|
1190 //
1191 // For any value of j that is representable as a 48-bit integer, create
1192 // a sequence of:
1193 // li d,j => lui d,hi16(j)
1194 // ori d,d,hi16(lo32(j))
1195 // dsll d,d,16
1196 // ori d,d,lo16(lo32(j))
1197 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001198 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001199 tmpInst.addOperand(
1200 MCOperand::CreateImm((ImmValue & (0xffffLL << 32)) >> 32));
Jack Carter30a59822012-10-04 04:03:53 +00001201 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001202 createShiftOr<16, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1203 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1204 } else {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001205 if (!isGP64bit()) {
1206 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001207 return true;
1208 }
1209
1210 // <------- hi32 ------> <------- lo32 ------>
1211 // <- hi16 -> <- lo16 ->
1212 // ___________________________________________
1213 // | | | | |
1214 // | 16-bytes | 16-bytes | 16-bytes | 16-bytes |
1215 // |__________|__________|__________|__________|
1216 //
1217 // For any value of j that isn't representable as a 48-bit integer.
1218 // li d,j => lui d,hi16(j)
1219 // ori d,d,lo16(hi32(j))
1220 // dsll d,d,16
1221 // ori d,d,hi16(lo32(j))
1222 // dsll d,d,16
1223 // ori d,d,lo16(lo32(j))
1224 tmpInst.setOpcode(Mips::LUi);
1225 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1226 tmpInst.addOperand(
1227 MCOperand::CreateImm((ImmValue & (0xffffLL << 48)) >> 48));
1228 Instructions.push_back(tmpInst);
1229 createShiftOr<32, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1230 createShiftOr<16, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1231 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
Jack Carter30a59822012-10-04 04:03:53 +00001232 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001233 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001234}
Jack Carter92995f12012-10-06 00:53:28 +00001235
Matheus Almeida3813d572014-06-19 14:39:14 +00001236bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001237MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
1238 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001239 MCInst tmpInst;
1240 const MCOperand &ImmOp = Inst.getOperand(2);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001241 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1242 "expected immediate operand kind");
1243 if (!ImmOp.isImm()) {
1244 expandLoadAddressSym(Inst, IDLoc, Instructions);
1245 return false;
1246 }
Jack Carter543fdf82012-10-09 23:29:45 +00001247 const MCOperand &SrcRegOp = Inst.getOperand(1);
1248 assert(SrcRegOp.isReg() && "expected register operand kind");
1249 const MCOperand &DstRegOp = Inst.getOperand(0);
1250 assert(DstRegOp.isReg() && "expected register operand kind");
1251 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001252 if (-32768 <= ImmValue && ImmValue <= 65535) {
1253 // For -32768 <= j <= 65535.
1254 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +00001255 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +00001256 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1257 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1258 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1259 Instructions.push_back(tmpInst);
1260 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001261 // For any other value of j that is representable as a 32-bit integer.
1262 // la d,j(s) => lui d,hi16(j)
1263 // ori d,d,lo16(j)
1264 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +00001265 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001266 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1267 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1268 Instructions.push_back(tmpInst);
1269 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001270 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001271 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1272 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1273 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1274 Instructions.push_back(tmpInst);
1275 tmpInst.clear();
1276 tmpInst.setOpcode(Mips::ADDu);
1277 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1278 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1279 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1280 Instructions.push_back(tmpInst);
1281 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001282 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001283}
1284
Matheus Almeida3813d572014-06-19 14:39:14 +00001285bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001286MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1287 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001288 MCInst tmpInst;
1289 const MCOperand &ImmOp = Inst.getOperand(1);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001290 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1291 "expected immediate operand kind");
1292 if (!ImmOp.isImm()) {
1293 expandLoadAddressSym(Inst, IDLoc, Instructions);
1294 return false;
1295 }
Jack Carter543fdf82012-10-09 23:29:45 +00001296 const MCOperand &RegOp = Inst.getOperand(0);
1297 assert(RegOp.isReg() && "expected register operand kind");
1298 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001299 if (-32768 <= ImmValue && ImmValue <= 65535) {
1300 // For -32768 <= j <= 65535.
1301 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +00001302 tmpInst.setOpcode(Mips::ADDiu);
1303 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001304 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +00001305 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1306 Instructions.push_back(tmpInst);
1307 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001308 // For any other value of j that is representable as a 32-bit integer.
1309 // la d,j => lui d,hi16(j)
1310 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001311 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001312 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1313 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1314 Instructions.push_back(tmpInst);
1315 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001316 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001317 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1318 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1319 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1320 Instructions.push_back(tmpInst);
1321 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001322 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001323}
1324
Toma Tabacu0d64b202014-08-14 10:29:17 +00001325void
1326MipsAsmParser::expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
1327 SmallVectorImpl<MCInst> &Instructions) {
1328 // FIXME: If we do have a valid at register to use, we should generate a
1329 // slightly shorter sequence here.
1330 MCInst tmpInst;
1331 int ExprOperandNo = 1;
1332 // Sometimes the assembly parser will get the immediate expression as
1333 // a $zero + an immediate.
1334 if (Inst.getNumOperands() == 3) {
1335 assert(Inst.getOperand(1).getReg() ==
1336 (isGP64bit() ? Mips::ZERO_64 : Mips::ZERO));
1337 ExprOperandNo = 2;
1338 }
1339 const MCOperand &SymOp = Inst.getOperand(ExprOperandNo);
1340 assert(SymOp.isExpr() && "expected symbol operand kind");
1341 const MCOperand &RegOp = Inst.getOperand(0);
1342 unsigned RegNo = RegOp.getReg();
1343 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymOp.getExpr());
1344 const MCSymbolRefExpr *HiExpr =
1345 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1346 MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
1347 const MCSymbolRefExpr *LoExpr =
1348 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1349 MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
1350 if (isGP64bit()) {
1351 // If it's a 64-bit architecture, expand to:
1352 // la d,sym => lui d,highest(sym)
1353 // ori d,d,higher(sym)
1354 // dsll d,d,16
1355 // ori d,d,hi16(sym)
1356 // dsll d,d,16
1357 // ori d,d,lo16(sym)
1358 const MCSymbolRefExpr *HighestExpr =
1359 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1360 MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
1361 const MCSymbolRefExpr *HigherExpr =
1362 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1363 MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
1364
1365 tmpInst.setOpcode(Mips::LUi);
1366 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1367 tmpInst.addOperand(MCOperand::CreateExpr(HighestExpr));
1368 Instructions.push_back(tmpInst);
1369
1370 createShiftOr<false>(MCOperand::CreateExpr(HigherExpr), RegNo, SMLoc(),
1371 Instructions);
1372 createShiftOr<true>(MCOperand::CreateExpr(HiExpr), RegNo, SMLoc(),
1373 Instructions);
1374 createShiftOr<true>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1375 Instructions);
1376 } else {
1377 // Otherwise, expand to:
1378 // la d,sym => lui d,hi16(sym)
1379 // ori d,d,lo16(sym)
1380 tmpInst.setOpcode(Mips::LUi);
1381 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1382 tmpInst.addOperand(MCOperand::CreateExpr(HiExpr));
1383 Instructions.push_back(tmpInst);
1384
1385 createShiftOr<false>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1386 Instructions);
1387 }
1388}
1389
Jack Carter9e65aa32013-03-22 00:05:30 +00001390void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001391 SmallVectorImpl<MCInst> &Instructions,
1392 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001393 const MCSymbolRefExpr *SR;
1394 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00001395 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00001396 const MCExpr *ExprOffset;
1397 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00001398 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001399 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1400 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001401 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001402 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1403 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001404 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00001405 if (isImmOpnd) {
1406 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
1407 ImmOffset = Inst.getOperand(2).getImm();
1408 LoOffset = ImmOffset & 0x0000ffff;
1409 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00001410 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00001411 if (LoOffset & 0x8000)
1412 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00001413 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001414 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001415 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00001416 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00001417 // These are some of the types of expansions we perform here:
1418 // 1) lw $8, sym => lui $8, %hi(sym)
1419 // lw $8, %lo(sym)($8)
1420 // 2) lw $8, offset($9) => lui $8, %hi(offset)
1421 // add $8, $8, $9
1422 // lw $8, %lo(offset)($9)
1423 // 3) lw $8, offset($8) => lui $at, %hi(offset)
1424 // add $at, $at, $8
1425 // lw $8, %lo(offset)($at)
1426 // 4) sw $8, sym => lui $at, %hi(sym)
1427 // sw $8, %lo(sym)($at)
1428 // 5) sw $8, offset($8) => lui $at, %hi(offset)
1429 // add $at, $at, $8
1430 // sw $8, %lo(offset)($at)
1431 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
1432 // ldc1 $f0, %lo(sym)($at)
1433 //
1434 // For load instructions we can use the destination register as a temporary
1435 // if base and dst are different (examples 1 and 2) and if the base register
1436 // is general purpose otherwise we must use $at (example 6) and error if it's
1437 // not available. For stores we must use $at (examples 4 and 5) because we
1438 // must not clobber the source register setting up the offset.
1439 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
1440 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
1441 unsigned RegClassIDOp0 =
1442 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
1443 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
1444 (RegClassIDOp0 == Mips::GPR64RegClassID);
1445 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00001446 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00001447 else {
1448 int AT = getATReg(IDLoc);
1449 // At this point we need AT to perform the expansions and we exit if it is
1450 // not available.
1451 if (!AT)
1452 return;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001453 TmpRegNum = getReg(
1454 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, AT);
Matheus Almeida7de68e72014-06-18 14:46:05 +00001455 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00001456
Jack Carter9e65aa32013-03-22 00:05:30 +00001457 TempInst.setOpcode(Mips::LUi);
1458 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1459 if (isImmOpnd)
1460 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
1461 else {
1462 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001463 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00001464 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
1465 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
1466 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001467 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001468 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001469 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00001470 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001471 }
1472 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001473 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00001474 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001475 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00001476 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00001477 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001478 TempInst.setOpcode(Mips::ADDu);
1479 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1480 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1481 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
1482 Instructions.push_back(TempInst);
1483 TempInst.clear();
Alp Tokercb402912014-01-24 17:20:08 +00001484 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00001485 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001486 TempInst.setOpcode(Inst.getOpcode());
1487 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
1488 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1489 if (isImmOpnd)
1490 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
1491 else {
1492 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001493 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
1494 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
1495 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001496 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001497 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001498 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00001499 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001500 }
1501 }
1502 Instructions.push_back(TempInst);
1503 TempInst.clear();
1504}
1505
Matheus Almeida595fcab2014-06-11 15:05:56 +00001506unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1507 // As described by the Mips32r2 spec, the registers Rd and Rs for
1508 // jalr.hb must be different.
1509 unsigned Opcode = Inst.getOpcode();
1510
1511 if (Opcode == Mips::JALR_HB &&
1512 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
1513 return Match_RequiresDifferentSrcAndDst;
1514
1515 return Match_Success;
1516}
1517
David Blaikie960ea3f2014-06-08 16:18:35 +00001518bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1519 OperandVector &Operands,
1520 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00001521 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00001522 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00001523
Jack Carterb4dbc172012-09-05 23:34:03 +00001524 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00001525 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00001526 unsigned MatchResult =
1527 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00001528
1529 switch (MatchResult) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001530 default:
1531 break;
Jack Carterb4dbc172012-09-05 23:34:03 +00001532 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001533 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00001534 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001535 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00001536 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00001537 return false;
1538 }
1539 case Match_MissingFeature:
1540 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1541 return true;
1542 case Match_InvalidOperand: {
1543 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00001544 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001545 if (ErrorInfo >= Operands.size())
1546 return Error(IDLoc, "too few operands for instruction");
1547
David Blaikie960ea3f2014-06-08 16:18:35 +00001548 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001549 if (ErrorLoc == SMLoc())
1550 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00001551 }
1552
1553 return Error(ErrorLoc, "invalid operand for instruction");
1554 }
1555 case Match_MnemonicFail:
1556 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00001557 case Match_RequiresDifferentSrcAndDst:
1558 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00001559 }
Rafael Espindola870c4e92012-01-11 03:56:41 +00001560 return true;
1561}
1562
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001563void MipsAsmParser::WarnIfAssemblerTemporary(int RegIndex, SMLoc Loc) {
1564 if ((RegIndex != 0) && ((int)Options.getATRegNum() == RegIndex)) {
1565 if (RegIndex == 1)
1566 Warning(Loc, "Used $at without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001567 else
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001568 Warning(Loc, Twine("Used $") + Twine(RegIndex) + " with \".set at=$" +
1569 Twine(RegIndex) + "\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001570 }
1571}
1572
Jack Carter1ac53222013-02-20 23:11:17 +00001573int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001574 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00001575
Vladimir Medic4c299852013-11-06 11:27:05 +00001576 CC = StringSwitch<unsigned>(Name)
1577 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001578 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00001579 .Case("a0", 4)
1580 .Case("a1", 5)
1581 .Case("a2", 6)
1582 .Case("a3", 7)
1583 .Case("v0", 2)
1584 .Case("v1", 3)
1585 .Case("s0", 16)
1586 .Case("s1", 17)
1587 .Case("s2", 18)
1588 .Case("s3", 19)
1589 .Case("s4", 20)
1590 .Case("s5", 21)
1591 .Case("s6", 22)
1592 .Case("s7", 23)
1593 .Case("k0", 26)
1594 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001595 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00001596 .Case("sp", 29)
1597 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001598 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00001599 .Case("ra", 31)
1600 .Case("t0", 8)
1601 .Case("t1", 9)
1602 .Case("t2", 10)
1603 .Case("t3", 11)
1604 .Case("t4", 12)
1605 .Case("t5", 13)
1606 .Case("t6", 14)
1607 .Case("t7", 15)
1608 .Case("t8", 24)
1609 .Case("t9", 25)
1610 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00001611
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001612 if (isABI_N32() || isABI_N64()) {
Daniel Sandersa4b0c742014-03-26 11:39:07 +00001613 // Although SGI documentation just cuts out t0-t3 for n32/n64,
1614 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
1615 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
1616 if (8 <= CC && CC <= 11)
1617 CC += 4;
Jack Carter1ac53222013-02-20 23:11:17 +00001618
Daniel Sandersa4b0c742014-03-26 11:39:07 +00001619 if (CC == -1)
1620 CC = StringSwitch<unsigned>(Name)
1621 .Case("a4", 8)
1622 .Case("a5", 9)
1623 .Case("a6", 10)
1624 .Case("a7", 11)
1625 .Case("kt0", 26)
1626 .Case("kt1", 27)
1627 .Default(-1);
1628 }
Jack Carter1ac53222013-02-20 23:11:17 +00001629
1630 return CC;
1631}
Jack Carterd0bd6422013-04-18 00:41:53 +00001632
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001633int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001634
Jack Cartera63b16a2012-09-07 00:23:42 +00001635 if (Name[0] == 'f') {
1636 StringRef NumString = Name.substr(1);
1637 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001638 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001639 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001640 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00001641 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001642 return IntVal;
1643 }
1644 return -1;
1645}
Jack Cartera63b16a2012-09-07 00:23:42 +00001646
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001647int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
1648
1649 if (Name.startswith("fcc")) {
1650 StringRef NumString = Name.substr(3);
1651 unsigned IntVal;
1652 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001653 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001654 if (IntVal > 7) // There are only 8 fcc registers.
1655 return -1;
1656 return IntVal;
1657 }
1658 return -1;
1659}
1660
1661int MipsAsmParser::matchACRegisterName(StringRef Name) {
1662
Akira Hatanaka274d24c2013-08-14 01:15:52 +00001663 if (Name.startswith("ac")) {
1664 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001665 unsigned IntVal;
1666 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001667 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001668 if (IntVal > 3) // There are only 3 acc registers.
1669 return -1;
1670 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00001671 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001672 return -1;
1673}
Jack Carterd0bd6422013-04-18 00:41:53 +00001674
Jack Carter5dc8ac92013-09-25 23:50:44 +00001675int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
1676 unsigned IntVal;
1677
1678 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
1679 return -1;
1680
1681 if (IntVal > 31)
1682 return -1;
1683
1684 return IntVal;
1685}
1686
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001687int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
1688 int CC;
1689
1690 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00001691 .Case("msair", 0)
1692 .Case("msacsr", 1)
1693 .Case("msaaccess", 2)
1694 .Case("msasave", 3)
1695 .Case("msamodify", 4)
1696 .Case("msarequest", 5)
1697 .Case("msamap", 6)
1698 .Case("msaunmap", 7)
1699 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001700
1701 return CC;
1702}
1703
Jack Carter0b744b32012-10-04 02:29:46 +00001704bool MipsAssemblerOptions::setATReg(unsigned Reg) {
1705 if (Reg > 31)
1706 return false;
1707
1708 aTReg = Reg;
1709 return true;
1710}
1711
Matheus Almeida7de68e72014-06-18 14:46:05 +00001712int MipsAsmParser::getATReg(SMLoc Loc) {
Daniel Sandersd89b1362014-03-24 16:48:01 +00001713 int AT = Options.getATRegNum();
1714 if (AT == 0)
Matheus Almeida7de68e72014-06-18 14:46:05 +00001715 reportParseError(Loc,
1716 "Pseudo instruction requires $at, which is not available");
Daniel Sandersd89b1362014-03-24 16:48:01 +00001717 return AT;
1718}
Jack Carter0b744b32012-10-04 02:29:46 +00001719
Jack Carterd0bd6422013-04-18 00:41:53 +00001720unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00001721 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00001722}
1723
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001724unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001725 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00001726 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001727}
1728
Jack Carter873c7242013-01-12 01:03:14 +00001729int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001730 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00001731 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00001732 return -1;
1733
Jack Carter873c7242013-01-12 01:03:14 +00001734 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00001735}
1736
David Blaikie960ea3f2014-06-08 16:18:35 +00001737bool MipsAsmParser::ParseOperand(OperandVector &Operands, StringRef Mnemonic) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001738 DEBUG(dbgs() << "ParseOperand\n");
1739
Jack Carter30a59822012-10-04 04:03:53 +00001740 // Check if the current operand has a custom associated parser, if so, try to
1741 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00001742 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
1743 if (ResTy == MatchOperand_Success)
1744 return false;
1745 // If there wasn't a custom match, try the generic matcher below. Otherwise,
1746 // there was a match, but an error occurred, in which case, just return that
1747 // the operand parsing failed.
1748 if (ResTy == MatchOperand_ParseFail)
1749 return true;
1750
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001751 DEBUG(dbgs() << ".. Generic Parser\n");
1752
Jack Carterb4dbc172012-09-05 23:34:03 +00001753 switch (getLexer().getKind()) {
1754 default:
1755 Error(Parser.getTok().getLoc(), "unexpected token in operand");
1756 return true;
1757 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001758 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00001759 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00001760
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001761 // Almost all registers have been parsed by custom parsers. There is only
1762 // one exception to this. $zero (and it's alias $0) will reach this point
1763 // for div, divu, and similar instructions because it is not an operand
1764 // to the instruction definition but an explicit register. Special case
1765 // this situation for now.
1766 if (ParseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00001767 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001768
Jack Carterd0bd6422013-04-18 00:41:53 +00001769 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00001770 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001771 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00001772 return true;
1773
Jack Carter873c7242013-01-12 01:03:14 +00001774 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00001775 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00001776 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00001777 const MCExpr *Res =
1778 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00001779
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001780 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00001781 return false;
1782 }
Vladimir Medic4c299852013-11-06 11:27:05 +00001783 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00001784 case AsmToken::LParen:
1785 case AsmToken::Minus:
1786 case AsmToken::Plus:
1787 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00001788 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00001789 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001790 DEBUG(dbgs() << ".. generic integer\n");
1791 OperandMatchResultTy ResTy = ParseImm(Operands);
1792 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00001793 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00001794 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001795 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001796 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001797 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00001798 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00001799 return true;
1800
Jack Carter873c7242013-01-12 01:03:14 +00001801 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1802
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001803 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001804 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001805 } // case AsmToken::Percent
1806 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00001807 return true;
1808}
1809
Vladimir Medic4c299852013-11-06 11:27:05 +00001810const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00001811 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00001812 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00001813 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001814 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00001815 // It's a constant, evaluate reloc value.
1816 int16_t Val;
1817 switch (getVariantKind(RelocStr)) {
1818 case MCSymbolRefExpr::VK_Mips_ABS_LO:
1819 // Get the 1st 16-bits.
1820 Val = MCE->getValue() & 0xffff;
1821 break;
1822 case MCSymbolRefExpr::VK_Mips_ABS_HI:
1823 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
1824 // 16 bits being negative.
1825 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
1826 break;
1827 case MCSymbolRefExpr::VK_Mips_HIGHER:
1828 // Get the 3rd 16-bits.
1829 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
1830 break;
1831 case MCSymbolRefExpr::VK_Mips_HIGHEST:
1832 // Get the 4th 16-bits.
1833 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
1834 break;
1835 default:
1836 report_fatal_error("Unsupported reloc value!");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001837 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00001838 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00001839 }
1840
Jack Carterb5cf5902013-04-17 00:18:04 +00001841 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001842 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00001843 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00001844 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00001845 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001846 return Res;
1847 }
1848
1849 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00001850 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
1851
Sasa Stankovic06c47802014-04-03 10:37:45 +00001852 // Try to create target expression.
1853 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
1854 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00001855
Jack Carterd0bd6422013-04-18 00:41:53 +00001856 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
1857 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00001858 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
1859 return Res;
1860 }
1861
1862 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001863 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
1864 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
1865 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00001866 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001867 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001868 return Expr;
1869}
1870
1871bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
1872
1873 switch (Expr->getKind()) {
1874 case MCExpr::Constant:
1875 return true;
1876 case MCExpr::SymbolRef:
1877 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
1878 case MCExpr::Binary:
1879 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
1880 if (!isEvaluated(BE->getLHS()))
1881 return false;
1882 return isEvaluated(BE->getRHS());
1883 }
1884 case MCExpr::Unary:
1885 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00001886 case MCExpr::Target:
1887 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001888 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001889 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00001890}
Jack Carterd0bd6422013-04-18 00:41:53 +00001891
Jack Carterb5cf5902013-04-17 00:18:04 +00001892bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001893 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00001894 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00001895 if (Tok.isNot(AsmToken::Identifier))
1896 return true;
1897
1898 std::string Str = Tok.getIdentifier().str();
1899
Jack Carterd0bd6422013-04-18 00:41:53 +00001900 Parser.Lex(); // Eat the identifier.
1901 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001902 const MCExpr *IdVal;
1903 SMLoc EndLoc;
1904
1905 if (getLexer().getKind() == AsmToken::LParen) {
1906 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001907 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001908 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001909 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001910 const AsmToken &nextTok = Parser.getTok();
1911 if (nextTok.isNot(AsmToken::Identifier))
1912 return true;
1913 Str += "(%";
1914 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00001915 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00001916 if (getLexer().getKind() != AsmToken::LParen)
1917 return true;
1918 } else
1919 break;
1920 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001921 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00001922 return true;
1923
1924 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00001925 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001926
1927 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00001928 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001929
Jack Carterd0bd6422013-04-18 00:41:53 +00001930 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00001931 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001932}
1933
Jack Carterb4dbc172012-09-05 23:34:03 +00001934bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1935 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001936 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001937 OperandMatchResultTy ResTy = ParseAnyRegister(Operands);
1938 if (ResTy == MatchOperand_Success) {
1939 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00001940 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001941 StartLoc = Operand.getStartLoc();
1942 EndLoc = Operand.getEndLoc();
1943
1944 // AFAIK, we only support numeric registers and named GPR's in CFI
1945 // directives.
1946 // Don't worry about eating tokens before failing. Using an unrecognised
1947 // register is a parse error.
1948 if (Operand.isGPRAsmReg()) {
1949 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001950 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001951 }
1952
1953 return (RegNo == (unsigned)-1);
1954 }
1955
1956 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00001957 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00001958}
1959
Jack Carterb5cf5902013-04-17 00:18:04 +00001960bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00001961 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001962 bool Result = true;
1963
1964 while (getLexer().getKind() == AsmToken::LParen)
1965 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00001966
Jack Carterd0bd6422013-04-18 00:41:53 +00001967 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001968 default:
1969 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00001970 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00001971 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00001972 case AsmToken::Integer:
1973 case AsmToken::Minus:
1974 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00001975 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00001976 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00001977 else
1978 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00001979 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00001980 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001981 break;
Jack Carter873c7242013-01-12 01:03:14 +00001982 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00001983 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00001984 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001985 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001986}
1987
David Blaikie960ea3f2014-06-08 16:18:35 +00001988MipsAsmParser::OperandMatchResultTy
1989MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001990 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00001991 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00001992 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001993 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001994 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00001995 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00001996 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001997
Jack Carterb5cf5902013-04-17 00:18:04 +00001998 if (getLexer().getKind() == AsmToken::LParen) {
1999 Parser.Lex();
2000 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002001 }
2002
Jack Carterb5cf5902013-04-17 00:18:04 +00002003 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002004 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00002005 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002006
Jack Carterd0bd6422013-04-18 00:41:53 +00002007 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002008 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002009 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
2010 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002011 SMLoc E =
2012 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002013 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002014 return MatchOperand_Success;
2015 }
2016 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002017 SMLoc E =
2018 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00002019
Jack Carterd0bd6422013-04-18 00:41:53 +00002020 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002021 // "Base" will be managed by k_Memory.
David Blaikie960ea3f2014-06-08 16:18:35 +00002022 auto Base = MipsOperand::CreateGPRReg(0, getContext().getRegisterInfo(),
2023 S, E, *this);
2024 Operands.push_back(
2025 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002026 return MatchOperand_Success;
2027 }
2028 Error(Parser.getTok().getLoc(), "'(' expected");
2029 return MatchOperand_ParseFail;
2030 }
2031
Jack Carterd0bd6422013-04-18 00:41:53 +00002032 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002033 }
2034
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002035 Res = ParseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002036 if (Res != MatchOperand_Success)
2037 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002038
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002039 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002040 Error(Parser.getTok().getLoc(), "')' expected");
2041 return MatchOperand_ParseFail;
2042 }
2043
Jack Carter873c7242013-01-12 01:03:14 +00002044 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2045
Jack Carterd0bd6422013-04-18 00:41:53 +00002046 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002047
Craig Topper062a2ba2014-04-25 05:30:21 +00002048 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00002049 IdVal = MCConstantExpr::Create(0, getContext());
2050
Jack Carterd0bd6422013-04-18 00:41:53 +00002051 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00002052 std::unique_ptr<MipsOperand> op(
2053 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00002054 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002055 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002056 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00002057 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002058 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
2059 int64_t Imm;
2060 if (IdVal->EvaluateAsAbsolute(Imm))
2061 IdVal = MCConstantExpr::Create(Imm, getContext());
2062 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
2063 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
2064 getContext());
2065 }
2066
David Blaikie960ea3f2014-06-08 16:18:35 +00002067 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002068 return MatchOperand_Success;
2069}
2070
David Blaikie960ea3f2014-06-08 16:18:35 +00002071bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Daniel Sanderse34a1202014-03-31 18:51:43 +00002072
Jack Carterd76b2372013-03-21 21:44:16 +00002073 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
2074 if (Sym) {
2075 SMLoc S = Parser.getTok().getLoc();
2076 const MCExpr *Expr;
2077 if (Sym->isVariable())
2078 Expr = Sym->getVariableValue();
2079 else
2080 return false;
2081 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002082 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carterd76b2372013-03-21 21:44:16 +00002083 const StringRef DefSymbol = Ref->getSymbol().getName();
2084 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002085 OperandMatchResultTy ResTy =
2086 MatchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00002087 if (ResTy == MatchOperand_Success) {
2088 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00002089 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00002090 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002091 llvm_unreachable("Should never ParseFail");
2092 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00002093 }
2094 } else if (Expr->getKind() == MCExpr::Constant) {
2095 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00002096 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00002097 Operands.push_back(
2098 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00002099 return true;
2100 }
2101 }
2102 return false;
2103}
Jack Carterd0bd6422013-04-18 00:41:53 +00002104
Jack Carter873c7242013-01-12 01:03:14 +00002105MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002106MipsAsmParser::MatchAnyRegisterNameWithoutDollar(OperandVector &Operands,
2107 StringRef Identifier,
2108 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002109 int Index = matchCPURegisterName(Identifier);
2110 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002111 Operands.push_back(MipsOperand::CreateGPRReg(
2112 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2113 return MatchOperand_Success;
2114 }
2115
2116 Index = matchFPURegisterName(Identifier);
2117 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002118 Operands.push_back(MipsOperand::CreateFGRReg(
2119 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2120 return MatchOperand_Success;
2121 }
2122
2123 Index = matchFCCRegisterName(Identifier);
2124 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002125 Operands.push_back(MipsOperand::CreateFCCReg(
2126 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2127 return MatchOperand_Success;
2128 }
2129
2130 Index = matchACRegisterName(Identifier);
2131 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002132 Operands.push_back(MipsOperand::CreateACCReg(
2133 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2134 return MatchOperand_Success;
2135 }
2136
2137 Index = matchMSA128RegisterName(Identifier);
2138 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002139 Operands.push_back(MipsOperand::CreateMSA128Reg(
2140 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2141 return MatchOperand_Success;
2142 }
2143
2144 Index = matchMSA128CtrlRegisterName(Identifier);
2145 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002146 Operands.push_back(MipsOperand::CreateMSACtrlReg(
2147 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2148 return MatchOperand_Success;
2149 }
2150
2151 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00002152}
2153
2154MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002155MipsAsmParser::MatchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Daniel Sanders315386c2014-04-01 10:40:14 +00002156 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002157
2158 if (Token.is(AsmToken::Identifier)) {
2159 DEBUG(dbgs() << ".. identifier\n");
2160 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00002161 OperandMatchResultTy ResTy =
2162 MatchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00002163 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002164 } else if (Token.is(AsmToken::Integer)) {
2165 DEBUG(dbgs() << ".. integer\n");
2166 Operands.push_back(MipsOperand::CreateNumericReg(
2167 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
2168 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002169 return MatchOperand_Success;
2170 }
2171
2172 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
2173
2174 return MatchOperand_NoMatch;
2175}
2176
David Blaikie960ea3f2014-06-08 16:18:35 +00002177MipsAsmParser::OperandMatchResultTy
2178MipsAsmParser::ParseAnyRegister(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002179 DEBUG(dbgs() << "ParseAnyRegister\n");
2180
2181 auto Token = Parser.getTok();
2182
2183 SMLoc S = Token.getLoc();
2184
2185 if (Token.isNot(AsmToken::Dollar)) {
2186 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
2187 if (Token.is(AsmToken::Identifier)) {
2188 if (searchSymbolAlias(Operands))
2189 return MatchOperand_Success;
2190 }
2191 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
2192 return MatchOperand_NoMatch;
2193 }
2194 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002195
Daniel Sanders21bce302014-04-01 12:35:23 +00002196 OperandMatchResultTy ResTy = MatchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00002197 if (ResTy == MatchOperand_Success) {
2198 Parser.Lex(); // $
2199 Parser.Lex(); // identifier
2200 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002201 return ResTy;
2202}
2203
2204MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002205MipsAsmParser::ParseImm(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002206 switch (getLexer().getKind()) {
2207 default:
2208 return MatchOperand_NoMatch;
2209 case AsmToken::LParen:
2210 case AsmToken::Minus:
2211 case AsmToken::Plus:
2212 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002213 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002214 case AsmToken::String:
2215 break;
2216 }
2217
2218 const MCExpr *IdVal;
2219 SMLoc S = Parser.getTok().getLoc();
2220 if (getParser().parseExpression(IdVal))
2221 return MatchOperand_ParseFail;
2222
2223 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2224 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
2225 return MatchOperand_Success;
2226}
2227
David Blaikie960ea3f2014-06-08 16:18:35 +00002228MipsAsmParser::OperandMatchResultTy
2229MipsAsmParser::ParseJumpTarget(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002230 DEBUG(dbgs() << "ParseJumpTarget\n");
2231
2232 SMLoc S = getLexer().getLoc();
2233
2234 // Integers and expressions are acceptable
2235 OperandMatchResultTy ResTy = ParseImm(Operands);
2236 if (ResTy != MatchOperand_NoMatch)
2237 return ResTy;
2238
Daniel Sanders315386c2014-04-01 10:40:14 +00002239 // Registers are a valid target and have priority over symbols.
2240 ResTy = ParseAnyRegister(Operands);
2241 if (ResTy != MatchOperand_NoMatch)
2242 return ResTy;
2243
Daniel Sandersffd84362014-04-01 10:41:48 +00002244 const MCExpr *Expr = nullptr;
2245 if (Parser.parseExpression(Expr)) {
2246 // We have no way of knowing if a symbol was consumed so we must ParseFail
2247 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002248 }
Daniel Sandersffd84362014-04-01 10:41:48 +00002249 Operands.push_back(
2250 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002251 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00002252}
2253
Vladimir Medic2b953d02013-10-01 09:48:56 +00002254MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002255MipsAsmParser::parseInvNum(OperandVector &Operands) {
Vladimir Medic2b953d02013-10-01 09:48:56 +00002256 const MCExpr *IdVal;
2257 // If the first token is '$' we may have register operand.
2258 if (Parser.getTok().is(AsmToken::Dollar))
2259 return MatchOperand_NoMatch;
2260 SMLoc S = Parser.getTok().getLoc();
2261 if (getParser().parseExpression(IdVal))
2262 return MatchOperand_ParseFail;
2263 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00002264 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00002265 int64_t Val = MCE->getValue();
2266 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2267 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002268 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00002269 return MatchOperand_Success;
2270}
2271
Matheus Almeida779c5932013-11-18 12:32:49 +00002272MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002273MipsAsmParser::ParseLSAImm(OperandVector &Operands) {
Matheus Almeida779c5932013-11-18 12:32:49 +00002274 switch (getLexer().getKind()) {
2275 default:
2276 return MatchOperand_NoMatch;
2277 case AsmToken::LParen:
2278 case AsmToken::Plus:
2279 case AsmToken::Minus:
2280 case AsmToken::Integer:
2281 break;
2282 }
2283
2284 const MCExpr *Expr;
2285 SMLoc S = Parser.getTok().getLoc();
2286
2287 if (getParser().parseExpression(Expr))
2288 return MatchOperand_ParseFail;
2289
2290 int64_t Val;
2291 if (!Expr->EvaluateAsAbsolute(Val)) {
2292 Error(S, "expected immediate value");
2293 return MatchOperand_ParseFail;
2294 }
2295
2296 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
2297 // and because the CPU always adds one to the immediate field, the allowed
2298 // range becomes 1..4. We'll only check the range here and will deal
2299 // with the addition/subtraction when actually decoding/encoding
2300 // the instruction.
2301 if (Val < 1 || Val > 4) {
2302 Error(S, "immediate not in range (1..4)");
2303 return MatchOperand_ParseFail;
2304 }
2305
Jack Carter3b2c96e2014-01-22 23:31:38 +00002306 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002307 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00002308 return MatchOperand_Success;
2309}
2310
Jack Carterdc1e35d2012-09-06 20:00:02 +00002311MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
2312
Vladimir Medic4c299852013-11-06 11:27:05 +00002313 MCSymbolRefExpr::VariantKind VK =
2314 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
2315 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
2316 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
2317 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
2318 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
2319 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
2320 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
2321 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
2322 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
2323 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
2324 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
2325 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
2326 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
2327 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
2328 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
2329 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
2330 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
2331 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00002332 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
2333 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
2334 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
2335 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
2336 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
2337 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00002338 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
2339 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00002340 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002341
Matheus Almeida2852af82014-04-22 10:15:54 +00002342 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00002343
Jack Carterdc1e35d2012-09-06 20:00:02 +00002344 return VK;
2345}
Jack Cartera63b16a2012-09-07 00:23:42 +00002346
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002347/// Sometimes (i.e. load/stores) the operand may be followed immediately by
2348/// either this.
2349/// ::= '(', register, ')'
2350/// handle it before we iterate so we don't get tripped up by the lack of
2351/// a comma.
David Blaikie960ea3f2014-06-08 16:18:35 +00002352bool MipsAsmParser::ParseParenSuffix(StringRef Name, OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002353 if (getLexer().is(AsmToken::LParen)) {
2354 Operands.push_back(
2355 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
2356 Parser.Lex();
2357 if (ParseOperand(Operands, Name)) {
2358 SMLoc Loc = getLexer().getLoc();
2359 Parser.eatToEndOfStatement();
2360 return Error(Loc, "unexpected token in argument list");
2361 }
2362 if (Parser.getTok().isNot(AsmToken::RParen)) {
2363 SMLoc Loc = getLexer().getLoc();
2364 Parser.eatToEndOfStatement();
2365 return Error(Loc, "unexpected token, expected ')'");
2366 }
2367 Operands.push_back(
2368 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
2369 Parser.Lex();
2370 }
2371 return false;
2372}
2373
2374/// Sometimes (i.e. in MSA) the operand may be followed immediately by
2375/// either one of these.
2376/// ::= '[', register, ']'
2377/// ::= '[', integer, ']'
2378/// handle it before we iterate so we don't get tripped up by the lack of
2379/// a comma.
David Blaikie960ea3f2014-06-08 16:18:35 +00002380bool MipsAsmParser::ParseBracketSuffix(StringRef Name,
2381 OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002382 if (getLexer().is(AsmToken::LBrac)) {
2383 Operands.push_back(
2384 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
2385 Parser.Lex();
2386 if (ParseOperand(Operands, Name)) {
2387 SMLoc Loc = getLexer().getLoc();
2388 Parser.eatToEndOfStatement();
2389 return Error(Loc, "unexpected token in argument list");
2390 }
2391 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2392 SMLoc Loc = getLexer().getLoc();
2393 Parser.eatToEndOfStatement();
2394 return Error(Loc, "unexpected token, expected ']'");
2395 }
2396 Operands.push_back(
2397 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
2398 Parser.Lex();
2399 }
2400 return false;
2401}
2402
David Blaikie960ea3f2014-06-08 16:18:35 +00002403bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
2404 SMLoc NameLoc, OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002405 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00002406
2407 // We have reached first instruction, module directive are now forbidden.
2408 getTargetStreamer().forbidModuleDirective();
2409
Vladimir Medic74593e62013-07-17 15:00:42 +00002410 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00002411 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00002412 Parser.eatToEndOfStatement();
2413 return Error(NameLoc, "Unknown instruction");
2414 }
Vladimir Medic64828a12013-07-16 10:07:14 +00002415 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002416 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002417
2418 // Read the remaining operands.
2419 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2420 // Read the first operand.
Vladimir Medic64828a12013-07-16 10:07:14 +00002421 if (ParseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002422 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002423 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002424 return Error(Loc, "unexpected token in argument list");
2425 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002426 if (getLexer().is(AsmToken::LBrac) && ParseBracketSuffix(Name, Operands))
2427 return true;
2428 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00002429
Jack Carterd0bd6422013-04-18 00:41:53 +00002430 while (getLexer().is(AsmToken::Comma)) {
2431 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00002432 // Parse and remember the operand.
2433 if (ParseOperand(Operands, Name)) {
2434 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002435 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002436 return Error(Loc, "unexpected token in argument list");
2437 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002438 // Parse bracket and parenthesis suffixes before we iterate
2439 if (getLexer().is(AsmToken::LBrac)) {
2440 if (ParseBracketSuffix(Name, Operands))
2441 return true;
2442 } else if (getLexer().is(AsmToken::LParen) &&
2443 ParseParenSuffix(Name, Operands))
2444 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00002445 }
2446 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002447 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2448 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002449 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002450 return Error(Loc, "unexpected token in argument list");
2451 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002452 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00002453 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00002454}
2455
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002456bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002457 SMLoc Loc = getLexer().getLoc();
2458 Parser.eatToEndOfStatement();
2459 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00002460}
2461
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002462bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002463 return Error(Loc, ErrorMsg);
2464}
2465
Jack Carter0b744b32012-10-04 02:29:46 +00002466bool MipsAsmParser::parseSetNoAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002467 // Line should look like: ".set noat".
2468 // set at reg to 0.
Jack Carter99d2afe2012-10-05 23:55:28 +00002469 Options.setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00002470 // eat noat
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 Carterd0bd6422013-04-18 00:41:53 +00002477 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002478 return false;
2479}
Jack Carterd0bd6422013-04-18 00:41:53 +00002480
Jack Carter0b744b32012-10-04 02:29:46 +00002481bool MipsAsmParser::parseSetAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002482 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00002483 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00002484 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00002485 getParser().Lex();
2486 if (getLexer().is(AsmToken::EndOfStatement)) {
Jack Carter99d2afe2012-10-05 23:55:28 +00002487 Options.setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00002488 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002489 return false;
2490 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002491 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00002492 if (getLexer().isNot(AsmToken::Dollar)) {
2493 reportParseError("unexpected token in statement");
2494 return false;
2495 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002496 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00002497 const AsmToken &Reg = Parser.getTok();
2498 if (Reg.is(AsmToken::Identifier)) {
2499 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
2500 } else if (Reg.is(AsmToken::Integer)) {
2501 AtRegNo = Reg.getIntVal();
2502 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00002503 reportParseError("unexpected token in statement");
2504 return false;
2505 }
Jack Carter1ac53222013-02-20 23:11:17 +00002506
Daniel Sanders71a89d922014-03-25 13:01:06 +00002507 if (AtRegNo < 0 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00002508 reportParseError("unexpected token in statement");
2509 return false;
2510 }
2511
2512 if (!Options.setATReg(AtRegNo)) {
Jack Carter0b744b32012-10-04 02:29:46 +00002513 reportParseError("unexpected token in statement");
2514 return false;
2515 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002516 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00002517
2518 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2519 reportParseError("unexpected token in statement");
2520 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002521 }
2522 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002523 return false;
2524 } else {
2525 reportParseError("unexpected token in statement");
2526 return false;
2527 }
2528}
2529
2530bool MipsAsmParser::parseSetReorderDirective() {
2531 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002532 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002533 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2534 reportParseError("unexpected token in statement");
2535 return false;
2536 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002537 Options.setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00002538 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002539 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002540 return false;
2541}
2542
2543bool MipsAsmParser::parseSetNoReorderDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002544 Parser.Lex();
2545 // If this is not the end of the statement, report an error.
2546 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2547 reportParseError("unexpected token in statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002548 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002549 }
2550 Options.setNoreorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00002551 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002552 Parser.Lex(); // Consume the EndOfStatement.
2553 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002554}
2555
2556bool MipsAsmParser::parseSetMacroDirective() {
2557 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002558 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002559 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2560 reportParseError("unexpected token in statement");
2561 return false;
2562 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002563 Options.setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002564 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002565 return false;
2566}
2567
2568bool MipsAsmParser::parseSetNoMacroDirective() {
2569 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002570 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002571 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2572 reportParseError("`noreorder' must be set before `nomacro'");
2573 return false;
2574 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002575 if (Options.isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00002576 reportParseError("`noreorder' must be set before `nomacro'");
2577 return false;
2578 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002579 Options.setNomacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002580 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002581 return false;
2582}
Jack Carterd76b2372013-03-21 21:44:16 +00002583
Daniel Sanders44934432014-08-07 12:03:36 +00002584bool MipsAsmParser::parseSetMsaDirective() {
2585 Parser.Lex();
2586
2587 // If this is not the end of the statement, report an error.
2588 if (getLexer().isNot(AsmToken::EndOfStatement))
2589 return reportParseError("unexpected token in statement");
2590
2591 setFeatureBits(Mips::FeatureMSA, "msa");
2592 getTargetStreamer().emitDirectiveSetMsa();
2593 return false;
2594}
2595
2596bool MipsAsmParser::parseSetNoMsaDirective() {
2597 Parser.Lex();
2598
2599 // If this is not the end of the statement, report an error.
2600 if (getLexer().isNot(AsmToken::EndOfStatement))
2601 return reportParseError("unexpected token in statement");
2602
2603 clearFeatureBits(Mips::FeatureMSA, "msa");
2604 getTargetStreamer().emitDirectiveSetNoMsa();
2605 return false;
2606}
2607
Jack Carter39536722014-01-22 23:08:42 +00002608bool MipsAsmParser::parseSetNoMips16Directive() {
2609 Parser.Lex();
2610 // If this is not the end of the statement, report an error.
2611 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2612 reportParseError("unexpected token in statement");
2613 return false;
2614 }
2615 // For now do nothing.
2616 Parser.Lex(); // Consume the EndOfStatement.
2617 return false;
2618}
2619
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002620bool MipsAsmParser::parseSetFpDirective() {
Daniel Sanders7e527422014-07-10 13:38:23 +00002621 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002622 // Line can be: .set fp=32
2623 // .set fp=xx
2624 // .set fp=64
2625 Parser.Lex(); // Eat fp token
2626 AsmToken Tok = Parser.getTok();
2627 if (Tok.isNot(AsmToken::Equal)) {
2628 reportParseError("unexpected token in statement");
2629 return false;
2630 }
2631 Parser.Lex(); // Eat '=' token.
2632 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002633
2634 if (!parseFpABIValue(FpAbiVal, ".set"))
2635 return false;
2636
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002637 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2638 reportParseError("unexpected token in statement");
2639 return false;
2640 }
Daniel Sanders7e527422014-07-10 13:38:23 +00002641 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002642 Parser.Lex(); // Consume the EndOfStatement.
2643 return false;
2644}
2645
Jack Carterd76b2372013-03-21 21:44:16 +00002646bool MipsAsmParser::parseSetAssignment() {
2647 StringRef Name;
2648 const MCExpr *Value;
2649
2650 if (Parser.parseIdentifier(Name))
2651 reportParseError("expected identifier after .set");
2652
2653 if (getLexer().isNot(AsmToken::Comma))
2654 return reportParseError("unexpected token in .set directive");
Jack Carterb5cf5902013-04-17 00:18:04 +00002655 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00002656
Jack Carter3b2c96e2014-01-22 23:31:38 +00002657 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00002658 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00002659
Jack Carterd0bd6422013-04-18 00:41:53 +00002660 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00002661 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00002662 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00002663 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00002664 Sym = getContext().GetOrCreateSymbol(Name);
2665 Sym->setVariableValue(Value);
2666
2667 return false;
2668}
Jack Carterd0bd6422013-04-18 00:41:53 +00002669
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002670bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
2671 Parser.Lex();
2672 if (getLexer().isNot(AsmToken::EndOfStatement))
2673 return reportParseError("unexpected token in .set directive");
2674
Matheus Almeida2852af82014-04-22 10:15:54 +00002675 switch (Feature) {
2676 default:
2677 llvm_unreachable("Unimplemented feature");
2678 case Mips::FeatureDSP:
2679 setFeatureBits(Mips::FeatureDSP, "dsp");
2680 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002681 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002682 case Mips::FeatureMicroMips:
2683 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002684 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002685 case Mips::FeatureMips16:
2686 getTargetStreamer().emitDirectiveSetMips16();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002687 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00002688 case Mips::FeatureMips1:
2689 selectArch("mips1");
2690 getTargetStreamer().emitDirectiveSetMips1();
2691 break;
2692 case Mips::FeatureMips2:
2693 selectArch("mips2");
2694 getTargetStreamer().emitDirectiveSetMips2();
2695 break;
2696 case Mips::FeatureMips3:
2697 selectArch("mips3");
2698 getTargetStreamer().emitDirectiveSetMips3();
2699 break;
2700 case Mips::FeatureMips4:
2701 selectArch("mips4");
2702 getTargetStreamer().emitDirectiveSetMips4();
2703 break;
2704 case Mips::FeatureMips5:
2705 selectArch("mips5");
2706 getTargetStreamer().emitDirectiveSetMips5();
2707 break;
2708 case Mips::FeatureMips32:
2709 selectArch("mips32");
2710 getTargetStreamer().emitDirectiveSetMips32();
2711 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002712 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00002713 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00002714 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002715 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00002716 case Mips::FeatureMips32r6:
2717 selectArch("mips32r6");
2718 getTargetStreamer().emitDirectiveSetMips32R6();
2719 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002720 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00002721 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00002722 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00002723 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002724 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00002725 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00002726 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00002727 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00002728 case Mips::FeatureMips64r6:
2729 selectArch("mips64r6");
2730 getTargetStreamer().emitDirectiveSetMips64R6();
2731 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002732 }
2733 return false;
2734}
2735
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002736bool MipsAsmParser::eatComma(StringRef ErrorStr) {
2737 if (getLexer().isNot(AsmToken::Comma)) {
2738 SMLoc Loc = getLexer().getLoc();
2739 Parser.eatToEndOfStatement();
2740 return Error(Loc, ErrorStr);
2741 }
2742
Matheus Almeida2852af82014-04-22 10:15:54 +00002743 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002744 return true;
2745}
2746
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002747bool MipsAsmParser::parseDirectiveCPLoad(SMLoc Loc) {
2748 if (Options.isReorder())
2749 Warning(Loc, ".cpload in reorder section");
2750
2751 // FIXME: Warn if cpload is used in Mips16 mode.
2752
David Blaikie960ea3f2014-06-08 16:18:35 +00002753 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002754 OperandMatchResultTy ResTy = ParseAnyRegister(Reg);
2755 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
2756 reportParseError("expected register containing function address");
2757 return false;
2758 }
2759
David Blaikie960ea3f2014-06-08 16:18:35 +00002760 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
2761 if (!RegOpnd.isGPRAsmReg()) {
2762 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002763 return false;
2764 }
2765
David Blaikie960ea3f2014-06-08 16:18:35 +00002766 getTargetStreamer().emitDirectiveCpload(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002767 return false;
2768}
2769
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002770bool MipsAsmParser::parseDirectiveCPSetup() {
2771 unsigned FuncReg;
2772 unsigned Save;
2773 bool SaveIsReg = true;
2774
Matheus Almeida7e815762014-06-18 13:08:59 +00002775 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
2776 OperandMatchResultTy ResTy = ParseAnyRegister(TmpReg);
2777 if (ResTy == MatchOperand_NoMatch) {
2778 reportParseError("expected register containing function address");
2779 Parser.eatToEndOfStatement();
2780 return false;
2781 }
2782
2783 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
2784 if (!FuncRegOpnd.isGPRAsmReg()) {
2785 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
2786 Parser.eatToEndOfStatement();
2787 return false;
2788 }
2789
2790 FuncReg = FuncRegOpnd.getGPR32Reg();
2791 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002792
2793 if (!eatComma("expected comma parsing directive"))
2794 return true;
2795
Matheus Almeida7e815762014-06-18 13:08:59 +00002796 ResTy = ParseAnyRegister(TmpReg);
2797 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002798 const AsmToken &Tok = Parser.getTok();
2799 if (Tok.is(AsmToken::Integer)) {
2800 Save = Tok.getIntVal();
2801 SaveIsReg = false;
2802 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00002803 } else {
2804 reportParseError("expected save register or stack offset");
2805 Parser.eatToEndOfStatement();
2806 return false;
2807 }
2808 } else {
2809 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
2810 if (!SaveOpnd.isGPRAsmReg()) {
2811 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
2812 Parser.eatToEndOfStatement();
2813 return false;
2814 }
2815 Save = SaveOpnd.getGPR32Reg();
2816 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002817
2818 if (!eatComma("expected comma parsing directive"))
2819 return true;
2820
2821 StringRef Name;
2822 if (Parser.parseIdentifier(Name))
2823 reportParseError("expected identifier");
2824 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002825
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00002826 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, *Sym, SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002827 return false;
2828}
2829
Matheus Almeida0051f2d2014-04-16 15:48:55 +00002830bool MipsAsmParser::parseDirectiveNaN() {
2831 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2832 const AsmToken &Tok = Parser.getTok();
2833
2834 if (Tok.getString() == "2008") {
2835 Parser.Lex();
2836 getTargetStreamer().emitDirectiveNaN2008();
2837 return false;
2838 } else if (Tok.getString() == "legacy") {
2839 Parser.Lex();
2840 getTargetStreamer().emitDirectiveNaNLegacy();
2841 return false;
2842 }
2843 }
2844 // If we don't recognize the option passed to the .nan
2845 // directive (e.g. no option or unknown option), emit an error.
2846 reportParseError("invalid option in .nan directive");
2847 return false;
2848}
2849
Jack Carter0b744b32012-10-04 02:29:46 +00002850bool MipsAsmParser::parseDirectiveSet() {
2851
Jack Carterd0bd6422013-04-18 00:41:53 +00002852 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00002853 const AsmToken &Tok = Parser.getTok();
2854
2855 if (Tok.getString() == "noat") {
2856 return parseSetNoAtDirective();
2857 } else if (Tok.getString() == "at") {
2858 return parseSetAtDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002859 } else if (Tok.getString() == "fp") {
2860 return parseSetFpDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00002861 } else if (Tok.getString() == "reorder") {
2862 return parseSetReorderDirective();
2863 } else if (Tok.getString() == "noreorder") {
2864 return parseSetNoReorderDirective();
2865 } else if (Tok.getString() == "macro") {
2866 return parseSetMacroDirective();
2867 } else if (Tok.getString() == "nomacro") {
2868 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00002869 } else if (Tok.getString() == "mips16") {
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002870 return parseSetFeature(Mips::FeatureMips16);
Jack Carter0b744b32012-10-04 02:29:46 +00002871 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00002872 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00002873 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00002874 getTargetStreamer().emitDirectiveSetNoMicroMips();
2875 Parser.eatToEndOfStatement();
2876 return false;
2877 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002878 return parseSetFeature(Mips::FeatureMicroMips);
Daniel Sandersf0df2212014-08-04 12:20:00 +00002879 } else if (Tok.getString() == "mips1") {
2880 return parseSetFeature(Mips::FeatureMips1);
2881 } else if (Tok.getString() == "mips2") {
2882 return parseSetFeature(Mips::FeatureMips2);
2883 } else if (Tok.getString() == "mips3") {
2884 return parseSetFeature(Mips::FeatureMips3);
2885 } else if (Tok.getString() == "mips4") {
2886 return parseSetFeature(Mips::FeatureMips4);
2887 } else if (Tok.getString() == "mips5") {
2888 return parseSetFeature(Mips::FeatureMips5);
2889 } else if (Tok.getString() == "mips32") {
2890 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00002891 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002892 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sandersf0df2212014-08-04 12:20:00 +00002893 } else if (Tok.getString() == "mips32r6") {
2894 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00002895 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002896 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00002897 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002898 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sandersf0df2212014-08-04 12:20:00 +00002899 } else if (Tok.getString() == "mips64r6") {
2900 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00002901 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002902 return parseSetFeature(Mips::FeatureDSP);
Daniel Sanders44934432014-08-07 12:03:36 +00002903 } else if (Tok.getString() == "msa") {
2904 return parseSetMsaDirective();
2905 } else if (Tok.getString() == "nomsa") {
2906 return parseSetNoMsaDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00002907 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002908 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00002909 parseSetAssignment();
2910 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002911 }
Jack Carter07c818d2013-01-25 01:31:34 +00002912
Jack Carter0b744b32012-10-04 02:29:46 +00002913 return true;
2914}
2915
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002916/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00002917/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002918bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Jack Carter07c818d2013-01-25 01:31:34 +00002919 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2920 for (;;) {
2921 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002922 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00002923 return true;
2924
2925 getParser().getStreamer().EmitValue(Value, Size);
2926
2927 if (getLexer().is(AsmToken::EndOfStatement))
2928 break;
2929
2930 // FIXME: Improve diagnostic.
2931 if (getLexer().isNot(AsmToken::Comma))
2932 return Error(L, "unexpected token in directive");
2933 Parser.Lex();
2934 }
2935 }
2936
2937 Parser.Lex();
2938 return false;
2939}
2940
Vladimir Medic4c299852013-11-06 11:27:05 +00002941/// parseDirectiveGpWord
2942/// ::= .gpword local_sym
2943bool MipsAsmParser::parseDirectiveGpWord() {
2944 const MCExpr *Value;
2945 // EmitGPRel32Value requires an expression, so we are using base class
2946 // method to evaluate the expression.
2947 if (getParser().parseExpression(Value))
2948 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00002949 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00002950
Vladimir Medice10c1122013-11-13 13:18:04 +00002951 if (getLexer().isNot(AsmToken::EndOfStatement))
Vladimir Medic4c299852013-11-06 11:27:05 +00002952 return Error(getLexer().getLoc(), "unexpected token in directive");
Vladimir Medice10c1122013-11-13 13:18:04 +00002953 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00002954 return false;
2955}
2956
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002957/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00002958/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002959bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindolab59fb732014-03-28 18:50:26 +00002960 const MCExpr *Value;
2961 // EmitGPRel64Value requires an expression, so we are using base class
2962 // method to evaluate the expression.
2963 if (getParser().parseExpression(Value))
2964 return true;
2965 getParser().getStreamer().EmitGPRel64Value(Value);
2966
2967 if (getLexer().isNot(AsmToken::EndOfStatement))
2968 return Error(getLexer().getLoc(), "unexpected token in directive");
2969 Parser.Lex(); // Eat EndOfStatement token.
2970 return false;
2971}
2972
Jack Carter0cd3c192014-01-06 23:27:31 +00002973bool MipsAsmParser::parseDirectiveOption() {
2974 // Get the option token.
2975 AsmToken Tok = Parser.getTok();
2976 // At the moment only identifiers are supported.
2977 if (Tok.isNot(AsmToken::Identifier)) {
2978 Error(Parser.getTok().getLoc(), "unexpected token in .option directive");
2979 Parser.eatToEndOfStatement();
2980 return false;
2981 }
2982
2983 StringRef Option = Tok.getIdentifier();
2984
2985 if (Option == "pic0") {
2986 getTargetStreamer().emitDirectiveOptionPic0();
2987 Parser.Lex();
2988 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2989 Error(Parser.getTok().getLoc(),
2990 "unexpected token in .option pic0 directive");
2991 Parser.eatToEndOfStatement();
2992 }
2993 return false;
2994 }
2995
Matheus Almeidaf79b2812014-03-26 13:40:29 +00002996 if (Option == "pic2") {
2997 getTargetStreamer().emitDirectiveOptionPic2();
2998 Parser.Lex();
2999 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3000 Error(Parser.getTok().getLoc(),
3001 "unexpected token in .option pic2 directive");
3002 Parser.eatToEndOfStatement();
3003 }
3004 return false;
3005 }
3006
Jack Carter0cd3c192014-01-06 23:27:31 +00003007 // Unknown option.
3008 Warning(Parser.getTok().getLoc(), "unknown option in .option directive");
3009 Parser.eatToEndOfStatement();
3010 return false;
3011}
3012
Daniel Sanders7e527422014-07-10 13:38:23 +00003013/// parseDirectiveModule
3014/// ::= .module oddspreg
3015/// ::= .module nooddspreg
3016/// ::= .module fp=value
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003017bool MipsAsmParser::parseDirectiveModule() {
Daniel Sanders7e527422014-07-10 13:38:23 +00003018 MCAsmLexer &Lexer = getLexer();
3019 SMLoc L = Lexer.getLoc();
3020
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00003021 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003022 // TODO : get a better message.
3023 reportParseError(".module directive must appear before any code");
3024 return false;
3025 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003026
3027 if (Lexer.is(AsmToken::Identifier)) {
3028 StringRef Option = Parser.getTok().getString();
3029 Parser.Lex();
3030
3031 if (Option == "oddspreg") {
3032 getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32());
3033 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
3034
3035 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3036 reportParseError("Expected end of statement");
3037 return false;
3038 }
3039
3040 return false;
3041 } else if (Option == "nooddspreg") {
3042 if (!isABI_O32()) {
3043 Error(L, "'.module nooddspreg' requires the O32 ABI");
3044 return false;
3045 }
3046
3047 getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32());
3048 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
3049
3050 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3051 reportParseError("Expected end of statement");
3052 return false;
3053 }
3054
3055 return false;
3056 } else if (Option == "fp") {
3057 return parseDirectiveModuleFP();
3058 }
3059
3060 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003061 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003062
3063 return false;
3064}
3065
3066/// parseDirectiveModuleFP
3067/// ::= =32
3068/// ::= =xx
3069/// ::= =64
3070bool MipsAsmParser::parseDirectiveModuleFP() {
3071 MCAsmLexer &Lexer = getLexer();
3072
3073 if (Lexer.isNot(AsmToken::Equal)) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003074 reportParseError("unexpected token in statement");
3075 return false;
3076 }
3077 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003078
Daniel Sanders7e527422014-07-10 13:38:23 +00003079 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003080 if (!parseFpABIValue(FpABI, ".module"))
3081 return false;
3082
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003083 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3084 reportParseError("unexpected token in statement");
3085 return false;
3086 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003087
Daniel Sanders7201a3e2014-07-08 10:35:52 +00003088 // Emit appropriate flags.
3089 getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
Daniel Sanders7e527422014-07-10 13:38:23 +00003090 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003091 return false;
3092}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003093
Daniel Sanders7e527422014-07-10 13:38:23 +00003094bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003095 StringRef Directive) {
3096 MCAsmLexer &Lexer = getLexer();
3097
3098 if (Lexer.is(AsmToken::Identifier)) {
3099 StringRef Value = Parser.getTok().getString();
3100 Parser.Lex();
3101
3102 if (Value != "xx") {
3103 reportParseError("unsupported value, expected 'xx', '32' or '64'");
3104 return false;
3105 }
3106
3107 if (!isABI_O32()) {
3108 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
3109 return false;
3110 }
3111
Daniel Sanders7e527422014-07-10 13:38:23 +00003112 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003113 return true;
3114 }
3115
3116 if (Lexer.is(AsmToken::Integer)) {
3117 unsigned Value = Parser.getTok().getIntVal();
3118 Parser.Lex();
3119
3120 if (Value != 32 && Value != 64) {
3121 reportParseError("unsupported value, expected 'xx', '32' or '64'");
3122 return false;
3123 }
3124
3125 if (Value == 32) {
3126 if (!isABI_O32()) {
3127 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
3128 return false;
3129 }
3130
Daniel Sanders7e527422014-07-10 13:38:23 +00003131 FpABI = MipsABIFlagsSection::FpABIKind::S32;
3132 } else
3133 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003134
Daniel Sanders7e527422014-07-10 13:38:23 +00003135 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003136 }
3137
3138 return false;
3139}
3140
Jack Carter0b744b32012-10-04 02:29:46 +00003141bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carter07c818d2013-01-25 01:31:34 +00003142 StringRef IDVal = DirectiveID.getString();
3143
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003144 if (IDVal == ".cpload")
3145 return parseDirectiveCPLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00003146 if (IDVal == ".dword") {
3147 parseDataDirective(8, DirectiveID.getLoc());
3148 return false;
3149 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003150 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003151 StringRef SymbolName;
3152
3153 if (Parser.parseIdentifier(SymbolName)) {
3154 reportParseError("expected identifier after .ent");
3155 return false;
3156 }
3157
3158 // There's an undocumented extension that allows an integer to
3159 // follow the name of the procedure which AFAICS is ignored by GAS.
3160 // Example: .ent foo,2
3161 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3162 if (getLexer().isNot(AsmToken::Comma)) {
3163 // Even though we accept this undocumented extension for compatibility
3164 // reasons, the additional integer argument does not actually change
3165 // the behaviour of the '.ent' directive, so we would like to discourage
3166 // its use. We do this by not referring to the extended version in
3167 // error messages which are not directly related to its use.
3168 reportParseError("unexpected token, expected end of statement");
3169 return false;
3170 }
3171 Parser.Lex(); // Eat the comma.
3172 const MCExpr *DummyNumber;
3173 int64_t DummyNumberVal;
3174 // If the user was explicitly trying to use the extended version,
3175 // we still give helpful extension-related error messages.
3176 if (Parser.parseExpression(DummyNumber)) {
3177 reportParseError("expected number after comma");
3178 return false;
3179 }
3180 if (!DummyNumber->EvaluateAsAbsolute(DummyNumberVal)) {
3181 reportParseError("expected an absolute expression after comma");
3182 return false;
3183 }
3184 }
3185
3186 // If this is not the end of the statement, report an error.
3187 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3188 reportParseError("unexpected token, expected end of statement");
3189 return false;
3190 }
3191
3192 MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
3193
3194 getTargetStreamer().emitDirectiveEnt(*Sym);
3195 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00003196 return false;
3197 }
3198
Jack Carter07c818d2013-01-25 01:31:34 +00003199 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003200 StringRef SymbolName;
3201
3202 if (Parser.parseIdentifier(SymbolName)) {
3203 reportParseError("expected identifier after .end");
3204 return false;
3205 }
3206
3207 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3208 reportParseError("unexpected token, expected end of statement");
3209 return false;
3210 }
3211
3212 if (CurrentFn == nullptr) {
3213 reportParseError(".end used without .ent");
3214 return false;
3215 }
3216
3217 if ((SymbolName != CurrentFn->getName())) {
3218 reportParseError(".end symbol does not match .ent symbol");
3219 return false;
3220 }
3221
3222 getTargetStreamer().emitDirectiveEnd(SymbolName);
3223 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00003224 return false;
3225 }
3226
Jack Carter07c818d2013-01-25 01:31:34 +00003227 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003228 // .frame $stack_reg, frame_size_in_bytes, $return_reg
3229 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
3230 OperandMatchResultTy ResTy = ParseAnyRegister(TmpReg);
3231 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3232 reportParseError("expected stack register");
3233 return false;
3234 }
3235
3236 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3237 if (!StackRegOpnd.isGPRAsmReg()) {
3238 reportParseError(StackRegOpnd.getStartLoc(),
3239 "expected general purpose register");
3240 return false;
3241 }
3242 unsigned StackReg = StackRegOpnd.getGPR32Reg();
3243
3244 if (Parser.getTok().is(AsmToken::Comma))
3245 Parser.Lex();
3246 else {
3247 reportParseError("unexpected token, expected comma");
3248 return false;
3249 }
3250
3251 // Parse the frame size.
3252 const MCExpr *FrameSize;
3253 int64_t FrameSizeVal;
3254
3255 if (Parser.parseExpression(FrameSize)) {
3256 reportParseError("expected frame size value");
3257 return false;
3258 }
3259
3260 if (!FrameSize->EvaluateAsAbsolute(FrameSizeVal)) {
3261 reportParseError("frame size not an absolute expression");
3262 return false;
3263 }
3264
3265 if (Parser.getTok().is(AsmToken::Comma))
3266 Parser.Lex();
3267 else {
3268 reportParseError("unexpected token, expected comma");
3269 return false;
3270 }
3271
3272 // Parse the return register.
3273 TmpReg.clear();
3274 ResTy = ParseAnyRegister(TmpReg);
3275 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3276 reportParseError("expected return register");
3277 return false;
3278 }
3279
3280 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3281 if (!ReturnRegOpnd.isGPRAsmReg()) {
3282 reportParseError(ReturnRegOpnd.getStartLoc(),
3283 "expected general purpose register");
3284 return false;
3285 }
3286
3287 // If this is not the end of the statement, report an error.
3288 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3289 reportParseError("unexpected token, expected end of statement");
3290 return false;
3291 }
3292
3293 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
3294 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00003295 return false;
3296 }
3297
Jack Carter07c818d2013-01-25 01:31:34 +00003298 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00003299 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00003300 }
3301
Daniel Sandersd97a6342014-08-13 10:07:34 +00003302 if (IDVal == ".mask" || IDVal == ".fmask") {
3303 // .mask bitmask, frame_offset
3304 // bitmask: One bit for each register used.
3305 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
3306 // first register is expected to be saved.
3307 // Examples:
3308 // .mask 0x80000000, -4
3309 // .fmask 0x80000000, -4
3310 //
Jack Carterbe332172012-09-07 00:48:02 +00003311
Daniel Sandersd97a6342014-08-13 10:07:34 +00003312 // Parse the bitmask
3313 const MCExpr *BitMask;
3314 int64_t BitMaskVal;
3315
3316 if (Parser.parseExpression(BitMask)) {
3317 reportParseError("expected bitmask value");
3318 return false;
3319 }
3320
3321 if (!BitMask->EvaluateAsAbsolute(BitMaskVal)) {
3322 reportParseError("bitmask not an absolute expression");
3323 return false;
3324 }
3325
3326 if (Parser.getTok().is(AsmToken::Comma))
3327 Parser.Lex();
3328 else {
3329 reportParseError("unexpected token, expected comma");
3330 return false;
3331 }
3332
3333 // Parse the frame_offset
3334 const MCExpr *FrameOffset;
3335 int64_t FrameOffsetVal;
3336
3337 if (Parser.parseExpression(FrameOffset)) {
3338 reportParseError("expected frame offset value");
3339 return false;
3340 }
3341
3342 if (!FrameOffset->EvaluateAsAbsolute(FrameOffsetVal)) {
3343 reportParseError("frame offset not an absolute expression");
3344 return false;
3345 }
3346
3347 // If this is not the end of the statement, report an error.
3348 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3349 reportParseError("unexpected token, expected end of statement");
3350 return false;
3351 }
3352
3353 if (IDVal == ".mask")
3354 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
3355 else
3356 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00003357 return false;
3358 }
3359
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003360 if (IDVal == ".nan")
3361 return parseDirectiveNaN();
3362
Jack Carter07c818d2013-01-25 01:31:34 +00003363 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00003364 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00003365 return false;
3366 }
3367
Rafael Espindolab59fb732014-03-28 18:50:26 +00003368 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003369 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00003370 return false;
3371 }
3372
Jack Carter07c818d2013-01-25 01:31:34 +00003373 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003374 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00003375 return false;
3376 }
3377
Jack Carter0cd3c192014-01-06 23:27:31 +00003378 if (IDVal == ".option")
3379 return parseDirectiveOption();
3380
3381 if (IDVal == ".abicalls") {
3382 getTargetStreamer().emitDirectiveAbiCalls();
3383 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3384 Error(Parser.getTok().getLoc(), "unexpected token in directive");
3385 // Clear line
3386 Parser.eatToEndOfStatement();
3387 }
3388 return false;
3389 }
3390
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003391 if (IDVal == ".cpsetup")
3392 return parseDirectiveCPSetup();
3393
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003394 if (IDVal == ".module")
3395 return parseDirectiveModule();
3396
Rafael Espindola870c4e92012-01-11 03:56:41 +00003397 return true;
3398}
3399
Rafael Espindola870c4e92012-01-11 03:56:41 +00003400extern "C" void LLVMInitializeMipsAsmParser() {
3401 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
3402 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
3403 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
3404 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
3405}
Jack Carterb4dbc172012-09-05 23:34:03 +00003406
3407#define GET_REGISTER_MATCHER
3408#define GET_MATCHER_IMPLEMENTATION
3409#include "MipsGenAsmMatcher.inc"