blob: b425dc8412f4034a6a8b3ed02ee69aff97eda882 [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);
Toma Tabacu85618b32014-08-19 14:22:52 +0000166 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000167 bool parseSetFeature(uint64_t Feature);
Matheus Almeida525bc4f2014-04-30 11:28:42 +0000168 bool parseDirectiveCPLoad(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000169 bool parseDirectiveCPSetup();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000170 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000171 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000172 bool parseDirectiveOption();
Jack Carter0b744b32012-10-04 02:29:46 +0000173
174 bool parseSetAtDirective();
175 bool parseSetNoAtDirective();
176 bool parseSetMacroDirective();
177 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000178 bool parseSetMsaDirective();
179 bool parseSetNoMsaDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000180 bool parseSetReorderDirective();
181 bool parseSetNoReorderDirective();
Jack Carter39536722014-01-22 23:08:42 +0000182 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000183 bool parseSetFpDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000184
Jack Carterd76b2372013-03-21 21:44:16 +0000185 bool parseSetAssignment();
186
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000187 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000188 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000189 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000190 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000191 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000192 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
193 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000194
Jack Carterdc1e35d2012-09-06 20:00:02 +0000195 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000196
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000197 bool eatComma(StringRef ErrorStr);
198
Jack Carter1ac53222013-02-20 23:11:17 +0000199 int matchCPURegisterName(StringRef Symbol);
200
Jack Carter873c7242013-01-12 01:03:14 +0000201 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000202
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000203 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000204
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000205 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000206
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000207 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000208
Jack Carter5dc8ac92013-09-25 23:50:44 +0000209 int matchMSA128RegisterName(StringRef Name);
210
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000211 int matchMSA128CtrlRegisterName(StringRef Name);
212
Jack Carterd0bd6422013-04-18 00:41:53 +0000213 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000214
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000215 unsigned getGPR(int RegNo);
216
Matheus Almeida7de68e72014-06-18 14:46:05 +0000217 int getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000218
219 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000220 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000221
222 // Helper function that checks if the value of a vector index is within the
223 // boundaries of accepted values for each RegisterKind
224 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
225 bool validateMSAIndex(int Val, int RegKind);
226
Daniel Sandersf0df2212014-08-04 12:20:00 +0000227 // Selects a new architecture by updating the FeatureBits with the necessary
228 // info including implied dependencies.
229 // Internally, it clears all the feature bits related to *any* architecture
230 // and selects the new one using the ToggleFeature functionality of the
231 // MCSubtargetInfo object that handles implied dependencies. The reason we
232 // clear all the arch related bits manually is because ToggleFeature only
233 // clears the features that imply the feature being cleared and not the
234 // features implied by the feature being cleared. This is easier to see
235 // with an example:
236 // --------------------------------------------------
237 // | Feature | Implies |
238 // | -------------------------------------------------|
239 // | FeatureMips1 | None |
240 // | FeatureMips2 | FeatureMips1 |
241 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
242 // | FeatureMips4 | FeatureMips3 |
243 // | ... | |
244 // --------------------------------------------------
245 //
246 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
247 // FeatureMipsGP64 | FeatureMips1)
248 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
249 void selectArch(StringRef ArchFeature) {
250 uint64_t FeatureBits = STI.getFeatureBits();
251 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
252 STI.setFeatureBits(FeatureBits);
253 setAvailableFeatures(
254 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
255 }
256
Vladimir Medic615b26e2014-03-04 09:54:09 +0000257 void setFeatureBits(unsigned Feature, StringRef FeatureString) {
258 if (!(STI.getFeatureBits() & Feature)) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000259 setAvailableFeatures(
260 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000261 }
262 }
263
264 void clearFeatureBits(unsigned Feature, StringRef FeatureString) {
265 if (STI.getFeatureBits() & Feature) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000266 setAvailableFeatures(
267 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000268 }
269 }
270
Rafael Espindola870c4e92012-01-11 03:56:41 +0000271public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000272 enum MipsMatchResultTy {
273 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
274#define GET_OPERAND_DIAGNOSTIC_TYPES
275#include "MipsGenAsmMatcher.inc"
276#undef GET_OPERAND_DIAGNOSTIC_TYPES
277
278 };
279
Joey Gouly0e76fa72013-09-12 10:28:05 +0000280 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000281 const MCInstrInfo &MII, const MCTargetOptions &Options)
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000282 : MCTargetAsmParser(), STI(sti), Parser(parser) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000283 // Initialize the set of available features.
284 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000285
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000286 getTargetStreamer().updateABIInfo(*this);
287
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000288 // Assert exactly one ABI was chosen.
289 assert((((STI.getFeatureBits() & Mips::FeatureO32) != 0) +
290 ((STI.getFeatureBits() & Mips::FeatureEABI) != 0) +
291 ((STI.getFeatureBits() & Mips::FeatureN32) != 0) +
292 ((STI.getFeatureBits() & Mips::FeatureN64) != 0)) == 1);
Daniel Sanders7e527422014-07-10 13:38:23 +0000293
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000294 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000295 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000296
297 CurrentFn = nullptr;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000298 }
299
Jack Carterb4dbc172012-09-05 23:34:03 +0000300 MCAsmParser &getParser() const { return Parser; }
301 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000302
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000303 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
304 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
305
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000306 bool isGP64bit() const { return STI.getFeatureBits() & Mips::FeatureGP64Bit; }
307 bool isFP64bit() const { return STI.getFeatureBits() & Mips::FeatureFP64Bit; }
308 bool isABI_N32() const { return STI.getFeatureBits() & Mips::FeatureN32; }
309 bool isABI_N64() const { return STI.getFeatureBits() & Mips::FeatureN64; }
310 bool isABI_O32() const { return STI.getFeatureBits() & Mips::FeatureO32; }
Daniel Sandersa6e125f2014-07-15 15:31:39 +0000311 bool isABI_FPXX() const { return STI.getFeatureBits() & Mips::FeatureFPXX; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000312
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000313 bool useOddSPReg() const {
Daniel Sanders7e527422014-07-10 13:38:23 +0000314 return !(STI.getFeatureBits() & Mips::FeatureNoOddSPReg);
315 }
316
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000317 bool inMicroMipsMode() const {
318 return STI.getFeatureBits() & Mips::FeatureMicroMips;
319 }
320 bool hasMips1() const { return STI.getFeatureBits() & Mips::FeatureMips1; }
321 bool hasMips2() const { return STI.getFeatureBits() & Mips::FeatureMips2; }
322 bool hasMips3() const { return STI.getFeatureBits() & Mips::FeatureMips3; }
323 bool hasMips4() const { return STI.getFeatureBits() & Mips::FeatureMips4; }
324 bool hasMips5() const { return STI.getFeatureBits() & Mips::FeatureMips5; }
325 bool hasMips32() const {
326 return (STI.getFeatureBits() & Mips::FeatureMips32);
327 }
328 bool hasMips64() const {
329 return (STI.getFeatureBits() & Mips::FeatureMips64);
330 }
331 bool hasMips32r2() const {
332 return (STI.getFeatureBits() & Mips::FeatureMips32r2);
333 }
334 bool hasMips64r2() const {
335 return (STI.getFeatureBits() & Mips::FeatureMips64r2);
336 }
337 bool hasMips32r6() const {
338 return (STI.getFeatureBits() & Mips::FeatureMips32r6);
339 }
340 bool hasMips64r6() const {
341 return (STI.getFeatureBits() & Mips::FeatureMips64r6);
342 }
343 bool hasDSP() const { return (STI.getFeatureBits() & Mips::FeatureDSP); }
344 bool hasDSPR2() const { return (STI.getFeatureBits() & Mips::FeatureDSPR2); }
345 bool hasMSA() const { return (STI.getFeatureBits() & Mips::FeatureMSA); }
346
347 bool inMips16Mode() const {
348 return STI.getFeatureBits() & Mips::FeatureMips16;
349 }
350 // TODO: see how can we get this info.
Eric Christopher7394e232014-07-18 00:08:50 +0000351 bool abiUsesSoftFloat() const { return false; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000352
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000353 /// Warn if RegNo is the current assembler temporary.
354 void WarnIfAssemblerTemporary(int RegNo, SMLoc Loc);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000355};
356}
357
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000358namespace {
359
360/// MipsOperand - Instances of this class represent a parsed Mips machine
361/// instruction.
362class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000363public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000364 /// Broad categories of register classes
365 /// The exact class is finalized by the render method.
366 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000367 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000368 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000369 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000370 RegKind_FCC = 4, /// FCC
371 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
372 RegKind_MSACtrl = 16, /// MSA control registers
373 RegKind_COP2 = 32, /// COP2
374 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
375 /// context).
376 RegKind_CCR = 128, /// CCR
377 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000378 RegKind_COP3 = 512, /// COP3
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000379
380 /// Potentially any (e.g. $1)
381 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
382 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000383 RegKind_CCR | RegKind_HWRegs | RegKind_COP3
Jack Carter873c7242013-01-12 01:03:14 +0000384 };
385
386private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000387 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000388 k_Immediate, /// An immediate (possibly involving symbol references)
389 k_Memory, /// Base + Offset Memory Address
390 k_PhysRegister, /// A physical register from the Mips namespace
391 k_RegisterIndex, /// A register index in one or more RegKind.
392 k_Token /// A simple token
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000393 } Kind;
394
David Blaikie960ea3f2014-06-08 16:18:35 +0000395public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000396 MipsOperand(KindTy K, MipsAsmParser &Parser)
397 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
398
David Blaikie960ea3f2014-06-08 16:18:35 +0000399private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000400 /// For diagnostics, and checking the assembler temporary
401 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000402
Eric Christopher8996c5d2013-03-15 00:42:55 +0000403 struct Token {
404 const char *Data;
405 unsigned Length;
406 };
407
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000408 struct PhysRegOp {
409 unsigned Num; /// Register Number
410 };
411
412 struct RegIdxOp {
413 unsigned Index; /// Index into the register class
414 RegKind Kind; /// Bitfield of the kinds it could possibly be
415 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000416 };
417
418 struct ImmOp {
419 const MCExpr *Val;
420 };
421
422 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000423 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000424 const MCExpr *Off;
425 };
426
Jack Carterb4dbc172012-09-05 23:34:03 +0000427 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000428 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000429 struct PhysRegOp PhysReg;
430 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000431 struct ImmOp Imm;
432 struct MemOp Mem;
Jack Carterb4dbc172012-09-05 23:34:03 +0000433 };
434
435 SMLoc StartLoc, EndLoc;
436
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000437 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000438 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
439 const MCRegisterInfo *RegInfo,
440 SMLoc S, SMLoc E,
441 MipsAsmParser &Parser) {
442 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000443 Op->RegIdx.Index = Index;
444 Op->RegIdx.RegInfo = RegInfo;
445 Op->RegIdx.Kind = RegKind;
446 Op->StartLoc = S;
447 Op->EndLoc = E;
448 return Op;
449 }
450
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000451public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000452 /// Coerce the register to GPR32 and return the real register for the current
453 /// target.
454 unsigned getGPR32Reg() const {
455 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
456 AsmParser.WarnIfAssemblerTemporary(RegIdx.Index, StartLoc);
457 unsigned ClassID = Mips::GPR32RegClassID;
458 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000459 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000460
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000461 /// Coerce the register to GPR64 and return the real register for the current
462 /// target.
463 unsigned getGPR64Reg() const {
464 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
465 unsigned ClassID = Mips::GPR64RegClassID;
466 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000467 }
468
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000469private:
470 /// Coerce the register to AFGR64 and return the real register for the current
471 /// target.
472 unsigned getAFGR64Reg() const {
473 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
474 if (RegIdx.Index % 2 != 0)
475 AsmParser.Warning(StartLoc, "Float register should be even.");
476 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
477 .getRegister(RegIdx.Index / 2);
478 }
479
480 /// Coerce the register to FGR64 and return the real register for the current
481 /// target.
482 unsigned getFGR64Reg() const {
483 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
484 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
485 .getRegister(RegIdx.Index);
486 }
487
488 /// Coerce the register to FGR32 and return the real register for the current
489 /// target.
490 unsigned getFGR32Reg() const {
491 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
492 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
493 .getRegister(RegIdx.Index);
494 }
495
496 /// Coerce the register to FGRH32 and return the real register for the current
497 /// target.
498 unsigned getFGRH32Reg() const {
499 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
500 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
501 .getRegister(RegIdx.Index);
502 }
503
504 /// Coerce the register to FCC and return the real register for the current
505 /// target.
506 unsigned getFCCReg() const {
507 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
508 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
509 .getRegister(RegIdx.Index);
510 }
511
512 /// Coerce the register to MSA128 and return the real register for the current
513 /// target.
514 unsigned getMSA128Reg() const {
515 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
516 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
517 // identical
518 unsigned ClassID = Mips::MSA128BRegClassID;
519 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
520 }
521
522 /// Coerce the register to MSACtrl and return the real register for the
523 /// current target.
524 unsigned getMSACtrlReg() const {
525 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
526 unsigned ClassID = Mips::MSACtrlRegClassID;
527 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
528 }
529
530 /// Coerce the register to COP2 and return the real register for the
531 /// current target.
532 unsigned getCOP2Reg() const {
533 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
534 unsigned ClassID = Mips::COP2RegClassID;
535 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
536 }
537
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000538 /// Coerce the register to COP3 and return the real register for the
539 /// current target.
540 unsigned getCOP3Reg() const {
541 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
542 unsigned ClassID = Mips::COP3RegClassID;
543 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
544 }
545
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000546 /// Coerce the register to ACC64DSP and return the real register for the
547 /// current target.
548 unsigned getACC64DSPReg() const {
549 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
550 unsigned ClassID = Mips::ACC64DSPRegClassID;
551 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
552 }
553
554 /// Coerce the register to HI32DSP and return the real register for the
555 /// current target.
556 unsigned getHI32DSPReg() const {
557 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
558 unsigned ClassID = Mips::HI32DSPRegClassID;
559 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
560 }
561
562 /// Coerce the register to LO32DSP and return the real register for the
563 /// current target.
564 unsigned getLO32DSPReg() const {
565 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
566 unsigned ClassID = Mips::LO32DSPRegClassID;
567 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
568 }
569
570 /// Coerce the register to CCR and return the real register for the
571 /// current target.
572 unsigned getCCRReg() const {
573 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
574 unsigned ClassID = Mips::CCRRegClassID;
575 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
576 }
577
578 /// Coerce the register to HWRegs and return the real register for the
579 /// current target.
580 unsigned getHWRegsReg() const {
581 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
582 unsigned ClassID = Mips::HWRegsRegClassID;
583 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
584 }
585
586public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000587 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000588 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000589 if (!Expr)
Jack Carterb4dbc172012-09-05 23:34:03 +0000590 Inst.addOperand(MCOperand::CreateImm(0));
591 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
592 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
593 else
594 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000595 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000596
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000597 void addRegOperands(MCInst &Inst, unsigned N) const {
598 llvm_unreachable("Use a custom parser instead");
599 }
600
Daniel Sanders21bce302014-04-01 12:35:23 +0000601 /// Render the operand to an MCInst as a GPR32
602 /// Asserts if the wrong number of operands are requested, or the operand
603 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000604 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
605 assert(N == 1 && "Invalid number of operands!");
606 Inst.addOperand(MCOperand::CreateReg(getGPR32Reg()));
607 }
608
Daniel Sanders21bce302014-04-01 12:35:23 +0000609 /// Render the operand to an MCInst as a GPR64
610 /// Asserts if the wrong number of operands are requested, or the operand
611 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000612 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
613 assert(N == 1 && "Invalid number of operands!");
614 Inst.addOperand(MCOperand::CreateReg(getGPR64Reg()));
615 }
616
617 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
618 assert(N == 1 && "Invalid number of operands!");
619 Inst.addOperand(MCOperand::CreateReg(getAFGR64Reg()));
620 }
621
622 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
623 assert(N == 1 && "Invalid number of operands!");
624 Inst.addOperand(MCOperand::CreateReg(getFGR64Reg()));
625 }
626
627 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
628 assert(N == 1 && "Invalid number of operands!");
629 Inst.addOperand(MCOperand::CreateReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000630 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000631 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000632 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
633 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000634 }
635
636 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
637 assert(N == 1 && "Invalid number of operands!");
638 Inst.addOperand(MCOperand::CreateReg(getFGRH32Reg()));
639 }
640
641 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
642 assert(N == 1 && "Invalid number of operands!");
643 Inst.addOperand(MCOperand::CreateReg(getFCCReg()));
644 }
645
646 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
647 assert(N == 1 && "Invalid number of operands!");
648 Inst.addOperand(MCOperand::CreateReg(getMSA128Reg()));
649 }
650
651 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
652 assert(N == 1 && "Invalid number of operands!");
653 Inst.addOperand(MCOperand::CreateReg(getMSACtrlReg()));
654 }
655
656 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
657 assert(N == 1 && "Invalid number of operands!");
658 Inst.addOperand(MCOperand::CreateReg(getCOP2Reg()));
659 }
660
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000661 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
662 assert(N == 1 && "Invalid number of operands!");
663 Inst.addOperand(MCOperand::CreateReg(getCOP3Reg()));
664 }
665
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000666 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
667 assert(N == 1 && "Invalid number of operands!");
668 Inst.addOperand(MCOperand::CreateReg(getACC64DSPReg()));
669 }
670
671 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
672 assert(N == 1 && "Invalid number of operands!");
673 Inst.addOperand(MCOperand::CreateReg(getHI32DSPReg()));
674 }
675
676 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
677 assert(N == 1 && "Invalid number of operands!");
678 Inst.addOperand(MCOperand::CreateReg(getLO32DSPReg()));
679 }
680
681 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
682 assert(N == 1 && "Invalid number of operands!");
683 Inst.addOperand(MCOperand::CreateReg(getCCRReg()));
684 }
685
686 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
687 assert(N == 1 && "Invalid number of operands!");
688 Inst.addOperand(MCOperand::CreateReg(getHWRegsReg()));
689 }
690
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000691 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000692 assert(N == 1 && "Invalid number of operands!");
693 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000694 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000695 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000696
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000697 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000698 assert(N == 2 && "Invalid number of operands!");
699
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000700 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000701
702 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000703 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000704 }
705
Craig Topper56c590a2014-04-29 07:58:02 +0000706 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000707 // As a special case until we sort out the definition of div/divu, pretend
708 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
709 if (isGPRAsmReg() && RegIdx.Index == 0)
710 return true;
711
712 return Kind == k_PhysRegister;
713 }
714 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000715 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000716 bool isConstantImm() const {
717 return isImm() && dyn_cast<MCConstantExpr>(getImm());
718 }
Craig Topper56c590a2014-04-29 07:58:02 +0000719 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000720 // Note: It's not possible to pretend that other operand kinds are tokens.
721 // The matcher emitter checks tokens first.
722 return Kind == k_Token;
723 }
Craig Topper56c590a2014-04-29 07:58:02 +0000724 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000725 bool isConstantMemOff() const {
726 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
727 }
728 template <unsigned Bits> bool isMemWithSimmOffset() const {
729 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff());
730 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000731 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000732 bool isLSAImm() const {
733 if (!isConstantImm())
734 return false;
735 int64_t Val = getConstantImm();
736 return 1 <= Val && Val <= 4;
737 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000738
739 StringRef getToken() const {
740 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000741 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000742 }
743
Craig Topper56c590a2014-04-29 07:58:02 +0000744 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000745 // As a special case until we sort out the definition of div/divu, pretend
746 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
747 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
748 RegIdx.Kind & RegKind_GPR)
749 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000750
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000751 assert(Kind == k_PhysRegister && "Invalid access!");
752 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +0000753 }
754
Jack Carterb4dbc172012-09-05 23:34:03 +0000755 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000756 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000757 return Imm.Val;
758 }
759
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000760 int64_t getConstantImm() const {
761 const MCExpr *Val = getImm();
762 return static_cast<const MCConstantExpr *>(Val)->getValue();
763 }
764
765 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000766 assert((Kind == k_Memory) && "Invalid access!");
767 return Mem.Base;
768 }
769
770 const MCExpr *getMemOff() const {
771 assert((Kind == k_Memory) && "Invalid access!");
772 return Mem.Off;
773 }
774
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000775 int64_t getConstantMemOff() const {
776 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
777 }
778
David Blaikie960ea3f2014-06-08 16:18:35 +0000779 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
780 MipsAsmParser &Parser) {
781 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000782 Op->Tok.Data = Str.data();
783 Op->Tok.Length = Str.size();
784 Op->StartLoc = S;
785 Op->EndLoc = S;
786 return Op;
787 }
788
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000789 /// Create a numeric register (e.g. $1). The exact register remains
790 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +0000791 static std::unique_ptr<MipsOperand>
792 CreateNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
793 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000794 DEBUG(dbgs() << "CreateNumericReg(" << Index << ", ...)\n");
795 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000796 }
797
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000798 /// Create a register that is definitely a GPR.
799 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +0000800 static std::unique_ptr<MipsOperand>
801 CreateGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
802 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000803 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000804 }
805
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000806 /// Create a register that is definitely a FGR.
807 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000808 static std::unique_ptr<MipsOperand>
809 CreateFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
810 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000811 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
812 }
813
814 /// Create a register that is definitely an FCC.
815 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000816 static std::unique_ptr<MipsOperand>
817 CreateFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
818 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000819 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
820 }
821
822 /// Create a register that is definitely an ACC.
823 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000824 static std::unique_ptr<MipsOperand>
825 CreateACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
826 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000827 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
828 }
829
830 /// Create a register that is definitely an MSA128.
831 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000832 static std::unique_ptr<MipsOperand>
833 CreateMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
834 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000835 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
836 }
837
838 /// Create a register that is definitely an MSACtrl.
839 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +0000840 static std::unique_ptr<MipsOperand>
841 CreateMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
842 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000843 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
844 }
845
David Blaikie960ea3f2014-06-08 16:18:35 +0000846 static std::unique_ptr<MipsOperand>
847 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
848 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000849 Op->Imm.Val = Val;
850 Op->StartLoc = S;
851 Op->EndLoc = E;
852 return Op;
853 }
854
David Blaikie960ea3f2014-06-08 16:18:35 +0000855 static std::unique_ptr<MipsOperand>
856 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
857 SMLoc E, MipsAsmParser &Parser) {
858 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
859 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +0000860 Op->Mem.Off = Off;
861 Op->StartLoc = S;
862 Op->EndLoc = E;
863 return Op;
864 }
865
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000866 bool isGPRAsmReg() const {
867 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000868 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000869 bool isFGRAsmReg() const {
870 // AFGR64 is $0-$15 but we handle this in getAFGR64()
871 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000872 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000873 bool isHWRegsAsmReg() const {
874 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000875 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000876 bool isCCRAsmReg() const {
877 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000878 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000879 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000880 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
881 return false;
882 if (!AsmParser.hasEightFccRegisters())
883 return RegIdx.Index == 0;
884 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +0000885 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000886 bool isACCAsmReg() const {
887 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +0000888 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000889 bool isCOP2AsmReg() const {
890 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +0000891 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000892 bool isCOP3AsmReg() const {
893 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
894 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000895 bool isMSA128AsmReg() const {
896 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +0000897 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000898 bool isMSACtrlAsmReg() const {
899 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000900 }
901
Jack Carterb4dbc172012-09-05 23:34:03 +0000902 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +0000903 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +0000904 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +0000905 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +0000906
NAKAMURA Takumie1f35832014-04-15 14:13:21 +0000907 virtual ~MipsOperand() {
908 switch (Kind) {
909 case k_Immediate:
910 break;
911 case k_Memory:
912 delete Mem.Base;
913 break;
914 case k_PhysRegister:
915 case k_RegisterIndex:
916 case k_Token:
917 break;
918 }
919 }
920
Craig Topper56c590a2014-04-29 07:58:02 +0000921 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000922 switch (Kind) {
923 case k_Immediate:
924 OS << "Imm<";
925 Imm.Val->print(OS);
926 OS << ">";
927 break;
928 case k_Memory:
929 OS << "Mem<";
930 Mem.Base->print(OS);
931 OS << ", ";
932 Mem.Off->print(OS);
933 OS << ">";
934 break;
935 case k_PhysRegister:
936 OS << "PhysReg<" << PhysReg.Num << ">";
937 break;
938 case k_RegisterIndex:
939 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
940 break;
941 case k_Token:
942 OS << Tok.Data;
943 break;
944 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000945 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000946}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +0000947} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000948
Jack Carter9e65aa32013-03-22 00:05:30 +0000949namespace llvm {
950extern const MCInstrDesc MipsInsts[];
951}
952static const MCInstrDesc &getInstDesc(unsigned Opcode) {
953 return MipsInsts[Opcode];
954}
955
956bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +0000957 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000958 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +0000959
Jack Carter9e65aa32013-03-22 00:05:30 +0000960 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000961
962 if (MCID.isBranch() || MCID.isCall()) {
963 const unsigned Opcode = Inst.getOpcode();
964 MCOperand Offset;
965
966 switch (Opcode) {
967 default:
968 break;
969 case Mips::BEQ:
970 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000971 case Mips::BEQ_MM:
972 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +0000973 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000974 Offset = Inst.getOperand(2);
975 if (!Offset.isImm())
976 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000977 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000978 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000979 if (OffsetToAlignment(Offset.getImm(),
980 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000981 return Error(IDLoc, "branch to misaligned address");
982 break;
983 case Mips::BGEZ:
984 case Mips::BGTZ:
985 case Mips::BLEZ:
986 case Mips::BLTZ:
987 case Mips::BGEZAL:
988 case Mips::BLTZAL:
989 case Mips::BC1F:
990 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000991 case Mips::BGEZ_MM:
992 case Mips::BGTZ_MM:
993 case Mips::BLEZ_MM:
994 case Mips::BLTZ_MM:
995 case Mips::BGEZAL_MM:
996 case Mips::BLTZAL_MM:
997 case Mips::BC1F_MM:
998 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +0000999 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001000 Offset = Inst.getOperand(1);
1001 if (!Offset.isImm())
1002 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001003 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001004 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001005 if (OffsetToAlignment(Offset.getImm(),
1006 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001007 return Error(IDLoc, "branch to misaligned address");
1008 break;
1009 }
1010 }
1011
Daniel Sandersa84989a2014-06-16 13:25:35 +00001012 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1013 // We still accept it but it is a normal nop.
1014 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1015 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1016 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1017 "nop instruction");
1018 }
1019
Jack Carterc15c1d22013-04-25 23:31:35 +00001020 if (MCID.hasDelaySlot() && Options.isReorder()) {
1021 // If this instruction has a delay slot and .set reorder is active,
1022 // emit a NOP after it.
1023 Instructions.push_back(Inst);
1024 MCInst NopInst;
1025 NopInst.setOpcode(Mips::SLL);
1026 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1027 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1028 NopInst.addOperand(MCOperand::CreateImm(0));
1029 Instructions.push_back(NopInst);
1030 return false;
1031 }
1032
Jack Carter9e65aa32013-03-22 00:05:30 +00001033 if (MCID.mayLoad() || MCID.mayStore()) {
1034 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001035 // reference or immediate we may have to expand instructions.
1036 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001037 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001038 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1039 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001040 MCOperand &Op = Inst.getOperand(i);
1041 if (Op.isImm()) {
1042 int MemOffset = Op.getImm();
1043 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001044 // Offset can't exceed 16bit value.
1045 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001046 return false;
1047 }
1048 } else if (Op.isExpr()) {
1049 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001050 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001051 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001052 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001053 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001054 // Expand symbol.
1055 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001056 return false;
1057 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001058 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001059 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001060 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001061 }
1062 }
1063 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001064 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001065 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001066
1067 if (needsExpansion(Inst))
Matheus Almeida3813d572014-06-19 14:39:14 +00001068 return expandInstruction(Inst, IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +00001069 else
1070 Instructions.push_back(Inst);
1071
1072 return false;
1073}
1074
Jack Carter30a59822012-10-04 04:03:53 +00001075bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1076
Jack Carterd0bd6422013-04-18 00:41:53 +00001077 switch (Inst.getOpcode()) {
1078 case Mips::LoadImm32Reg:
1079 case Mips::LoadAddr32Imm:
1080 case Mips::LoadAddr32Reg:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001081 case Mips::LoadImm64Reg:
Jack Carterd0bd6422013-04-18 00:41:53 +00001082 return true;
1083 default:
1084 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001085 }
1086}
Jack Carter92995f12012-10-06 00:53:28 +00001087
Matheus Almeida3813d572014-06-19 14:39:14 +00001088bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001089 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001090 switch (Inst.getOpcode()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001091 default:
1092 assert(0 && "unimplemented expansion");
Matheus Almeida3813d572014-06-19 14:39:14 +00001093 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001094 case Mips::LoadImm32Reg:
1095 return expandLoadImm(Inst, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001096 case Mips::LoadImm64Reg:
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001097 if (!isGP64bit()) {
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001098 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1099 return true;
1100 }
1101 return expandLoadImm(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001102 case Mips::LoadAddr32Imm:
1103 return expandLoadAddressImm(Inst, IDLoc, Instructions);
1104 case Mips::LoadAddr32Reg:
1105 return expandLoadAddressReg(Inst, IDLoc, Instructions);
1106 }
Jack Carter30a59822012-10-04 04:03:53 +00001107}
Jack Carter92995f12012-10-06 00:53:28 +00001108
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001109namespace {
Toma Tabacu0d64b202014-08-14 10:29:17 +00001110template <bool PerformShift>
1111void createShiftOr(MCOperand Operand, unsigned RegNo, SMLoc IDLoc,
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001112 SmallVectorImpl<MCInst> &Instructions) {
1113 MCInst tmpInst;
1114 if (PerformShift) {
1115 tmpInst.setOpcode(Mips::DSLL);
1116 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1117 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1118 tmpInst.addOperand(MCOperand::CreateImm(16));
1119 tmpInst.setLoc(IDLoc);
1120 Instructions.push_back(tmpInst);
1121 tmpInst.clear();
1122 }
1123 tmpInst.setOpcode(Mips::ORi);
1124 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1125 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001126 tmpInst.addOperand(Operand);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001127 tmpInst.setLoc(IDLoc);
1128 Instructions.push_back(tmpInst);
1129}
Toma Tabacu0d64b202014-08-14 10:29:17 +00001130
1131template <int Shift, bool PerformShift>
1132void createShiftOr(int64_t Value, unsigned RegNo, SMLoc IDLoc,
1133 SmallVectorImpl<MCInst> &Instructions) {
1134 createShiftOr<PerformShift>(
1135 MCOperand::CreateImm(((Value & (0xffffLL << Shift)) >> Shift)), RegNo,
1136 IDLoc, Instructions);
1137}
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001138}
1139
Matheus Almeida3813d572014-06-19 14:39:14 +00001140bool MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001141 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +00001142 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +00001143 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +00001144 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +00001145 const MCOperand &RegOp = Inst.getOperand(0);
1146 assert(RegOp.isReg() && "expected register operand kind");
1147
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001148 int64_t ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +00001149 tmpInst.setLoc(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001150 // FIXME: gas has a special case for values that are 000...1111, which
1151 // becomes a li -1 and then a dsrl
Jack Carterd0bd6422013-04-18 00:41:53 +00001152 if (0 <= ImmValue && ImmValue <= 65535) {
1153 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +00001154 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001155 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +00001156 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001157 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001158 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001159 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001160 } else if (ImmValue < 0 && ImmValue >= -32768) {
1161 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +00001162 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001163 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +00001164 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001165 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001166 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001167 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001168 } else if ((ImmValue & 0xffffffff) == ImmValue) {
1169 // For any value of j that is representable as a 32-bit integer, create
1170 // a sequence of:
Jack Carter30a59822012-10-04 04:03:53 +00001171 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001172 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001173 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001174 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1175 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +00001176 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001177 createShiftOr<0, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1178 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001179 if (!isGP64bit()) {
1180 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001181 return true;
1182 }
1183
1184 // <------- lo32 ------>
1185 // <------- hi32 ------>
1186 // <- hi16 -> <- lo16 ->
1187 // _________________________________
1188 // | | | |
1189 // | 16-bytes | 16-bytes | 16-bytes |
1190 // |__________|__________|__________|
1191 //
1192 // For any value of j that is representable as a 48-bit integer, create
1193 // a sequence of:
1194 // li d,j => lui d,hi16(j)
1195 // ori d,d,hi16(lo32(j))
1196 // dsll d,d,16
1197 // ori d,d,lo16(lo32(j))
1198 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001199 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001200 tmpInst.addOperand(
1201 MCOperand::CreateImm((ImmValue & (0xffffLL << 32)) >> 32));
Jack Carter30a59822012-10-04 04:03:53 +00001202 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001203 createShiftOr<16, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1204 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1205 } else {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001206 if (!isGP64bit()) {
1207 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001208 return true;
1209 }
1210
1211 // <------- hi32 ------> <------- lo32 ------>
1212 // <- hi16 -> <- lo16 ->
1213 // ___________________________________________
1214 // | | | | |
1215 // | 16-bytes | 16-bytes | 16-bytes | 16-bytes |
1216 // |__________|__________|__________|__________|
1217 //
1218 // For any value of j that isn't representable as a 48-bit integer.
1219 // li d,j => lui d,hi16(j)
1220 // ori d,d,lo16(hi32(j))
1221 // dsll d,d,16
1222 // ori d,d,hi16(lo32(j))
1223 // dsll d,d,16
1224 // ori d,d,lo16(lo32(j))
1225 tmpInst.setOpcode(Mips::LUi);
1226 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1227 tmpInst.addOperand(
1228 MCOperand::CreateImm((ImmValue & (0xffffLL << 48)) >> 48));
1229 Instructions.push_back(tmpInst);
1230 createShiftOr<32, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1231 createShiftOr<16, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1232 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
Jack Carter30a59822012-10-04 04:03:53 +00001233 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001234 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001235}
Jack Carter92995f12012-10-06 00:53:28 +00001236
Matheus Almeida3813d572014-06-19 14:39:14 +00001237bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001238MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
1239 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001240 MCInst tmpInst;
1241 const MCOperand &ImmOp = Inst.getOperand(2);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001242 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1243 "expected immediate operand kind");
1244 if (!ImmOp.isImm()) {
1245 expandLoadAddressSym(Inst, IDLoc, Instructions);
1246 return false;
1247 }
Jack Carter543fdf82012-10-09 23:29:45 +00001248 const MCOperand &SrcRegOp = Inst.getOperand(1);
1249 assert(SrcRegOp.isReg() && "expected register operand kind");
1250 const MCOperand &DstRegOp = Inst.getOperand(0);
1251 assert(DstRegOp.isReg() && "expected register operand kind");
1252 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001253 if (-32768 <= ImmValue && ImmValue <= 65535) {
1254 // For -32768 <= j <= 65535.
1255 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +00001256 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +00001257 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1258 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1259 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1260 Instructions.push_back(tmpInst);
1261 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001262 // For any other value of j that is representable as a 32-bit integer.
1263 // la d,j(s) => lui d,hi16(j)
1264 // ori d,d,lo16(j)
1265 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +00001266 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001267 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1268 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1269 Instructions.push_back(tmpInst);
1270 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001271 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001272 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1273 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1274 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1275 Instructions.push_back(tmpInst);
1276 tmpInst.clear();
1277 tmpInst.setOpcode(Mips::ADDu);
1278 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1279 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1280 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1281 Instructions.push_back(tmpInst);
1282 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001283 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001284}
1285
Matheus Almeida3813d572014-06-19 14:39:14 +00001286bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001287MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1288 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001289 MCInst tmpInst;
1290 const MCOperand &ImmOp = Inst.getOperand(1);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001291 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1292 "expected immediate operand kind");
1293 if (!ImmOp.isImm()) {
1294 expandLoadAddressSym(Inst, IDLoc, Instructions);
1295 return false;
1296 }
Jack Carter543fdf82012-10-09 23:29:45 +00001297 const MCOperand &RegOp = Inst.getOperand(0);
1298 assert(RegOp.isReg() && "expected register operand kind");
1299 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001300 if (-32768 <= ImmValue && ImmValue <= 65535) {
1301 // For -32768 <= j <= 65535.
1302 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +00001303 tmpInst.setOpcode(Mips::ADDiu);
1304 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001305 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +00001306 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1307 Instructions.push_back(tmpInst);
1308 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001309 // For any other value of j that is representable as a 32-bit integer.
1310 // la d,j => lui d,hi16(j)
1311 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001312 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001313 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1314 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1315 Instructions.push_back(tmpInst);
1316 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001317 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001318 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1319 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1320 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1321 Instructions.push_back(tmpInst);
1322 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001323 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001324}
1325
Toma Tabacu0d64b202014-08-14 10:29:17 +00001326void
1327MipsAsmParser::expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
1328 SmallVectorImpl<MCInst> &Instructions) {
1329 // FIXME: If we do have a valid at register to use, we should generate a
1330 // slightly shorter sequence here.
1331 MCInst tmpInst;
1332 int ExprOperandNo = 1;
1333 // Sometimes the assembly parser will get the immediate expression as
1334 // a $zero + an immediate.
1335 if (Inst.getNumOperands() == 3) {
1336 assert(Inst.getOperand(1).getReg() ==
1337 (isGP64bit() ? Mips::ZERO_64 : Mips::ZERO));
1338 ExprOperandNo = 2;
1339 }
1340 const MCOperand &SymOp = Inst.getOperand(ExprOperandNo);
1341 assert(SymOp.isExpr() && "expected symbol operand kind");
1342 const MCOperand &RegOp = Inst.getOperand(0);
1343 unsigned RegNo = RegOp.getReg();
1344 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymOp.getExpr());
1345 const MCSymbolRefExpr *HiExpr =
1346 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1347 MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
1348 const MCSymbolRefExpr *LoExpr =
1349 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1350 MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
1351 if (isGP64bit()) {
1352 // If it's a 64-bit architecture, expand to:
1353 // la d,sym => lui d,highest(sym)
1354 // ori d,d,higher(sym)
1355 // dsll d,d,16
1356 // ori d,d,hi16(sym)
1357 // dsll d,d,16
1358 // ori d,d,lo16(sym)
1359 const MCSymbolRefExpr *HighestExpr =
1360 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1361 MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
1362 const MCSymbolRefExpr *HigherExpr =
1363 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1364 MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
1365
1366 tmpInst.setOpcode(Mips::LUi);
1367 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1368 tmpInst.addOperand(MCOperand::CreateExpr(HighestExpr));
1369 Instructions.push_back(tmpInst);
1370
1371 createShiftOr<false>(MCOperand::CreateExpr(HigherExpr), RegNo, SMLoc(),
1372 Instructions);
1373 createShiftOr<true>(MCOperand::CreateExpr(HiExpr), RegNo, SMLoc(),
1374 Instructions);
1375 createShiftOr<true>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1376 Instructions);
1377 } else {
1378 // Otherwise, expand to:
1379 // la d,sym => lui d,hi16(sym)
1380 // ori d,d,lo16(sym)
1381 tmpInst.setOpcode(Mips::LUi);
1382 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1383 tmpInst.addOperand(MCOperand::CreateExpr(HiExpr));
1384 Instructions.push_back(tmpInst);
1385
1386 createShiftOr<false>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1387 Instructions);
1388 }
1389}
1390
Jack Carter9e65aa32013-03-22 00:05:30 +00001391void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001392 SmallVectorImpl<MCInst> &Instructions,
1393 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001394 const MCSymbolRefExpr *SR;
1395 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00001396 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00001397 const MCExpr *ExprOffset;
1398 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00001399 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001400 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1401 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001402 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001403 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1404 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001405 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00001406 if (isImmOpnd) {
1407 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
1408 ImmOffset = Inst.getOperand(2).getImm();
1409 LoOffset = ImmOffset & 0x0000ffff;
1410 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00001411 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00001412 if (LoOffset & 0x8000)
1413 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00001414 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001415 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001416 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00001417 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00001418 // These are some of the types of expansions we perform here:
1419 // 1) lw $8, sym => lui $8, %hi(sym)
1420 // lw $8, %lo(sym)($8)
1421 // 2) lw $8, offset($9) => lui $8, %hi(offset)
1422 // add $8, $8, $9
1423 // lw $8, %lo(offset)($9)
1424 // 3) lw $8, offset($8) => lui $at, %hi(offset)
1425 // add $at, $at, $8
1426 // lw $8, %lo(offset)($at)
1427 // 4) sw $8, sym => lui $at, %hi(sym)
1428 // sw $8, %lo(sym)($at)
1429 // 5) sw $8, offset($8) => lui $at, %hi(offset)
1430 // add $at, $at, $8
1431 // sw $8, %lo(offset)($at)
1432 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
1433 // ldc1 $f0, %lo(sym)($at)
1434 //
1435 // For load instructions we can use the destination register as a temporary
1436 // if base and dst are different (examples 1 and 2) and if the base register
1437 // is general purpose otherwise we must use $at (example 6) and error if it's
1438 // not available. For stores we must use $at (examples 4 and 5) because we
1439 // must not clobber the source register setting up the offset.
1440 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
1441 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
1442 unsigned RegClassIDOp0 =
1443 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
1444 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
1445 (RegClassIDOp0 == Mips::GPR64RegClassID);
1446 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00001447 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00001448 else {
1449 int AT = getATReg(IDLoc);
1450 // At this point we need AT to perform the expansions and we exit if it is
1451 // not available.
1452 if (!AT)
1453 return;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001454 TmpRegNum = getReg(
1455 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, AT);
Matheus Almeida7de68e72014-06-18 14:46:05 +00001456 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00001457
Jack Carter9e65aa32013-03-22 00:05:30 +00001458 TempInst.setOpcode(Mips::LUi);
1459 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1460 if (isImmOpnd)
1461 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
1462 else {
1463 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001464 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00001465 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
1466 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
1467 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001468 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001469 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001470 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00001471 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001472 }
1473 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001474 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00001475 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001476 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00001477 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00001478 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001479 TempInst.setOpcode(Mips::ADDu);
1480 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1481 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1482 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
1483 Instructions.push_back(TempInst);
1484 TempInst.clear();
Alp Tokercb402912014-01-24 17:20:08 +00001485 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00001486 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001487 TempInst.setOpcode(Inst.getOpcode());
1488 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
1489 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1490 if (isImmOpnd)
1491 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
1492 else {
1493 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001494 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
1495 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
1496 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001497 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001498 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001499 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00001500 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001501 }
1502 }
1503 Instructions.push_back(TempInst);
1504 TempInst.clear();
1505}
1506
Matheus Almeida595fcab2014-06-11 15:05:56 +00001507unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1508 // As described by the Mips32r2 spec, the registers Rd and Rs for
1509 // jalr.hb must be different.
1510 unsigned Opcode = Inst.getOpcode();
1511
1512 if (Opcode == Mips::JALR_HB &&
1513 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
1514 return Match_RequiresDifferentSrcAndDst;
1515
1516 return Match_Success;
1517}
1518
David Blaikie960ea3f2014-06-08 16:18:35 +00001519bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1520 OperandVector &Operands,
1521 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00001522 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00001523 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00001524
Jack Carterb4dbc172012-09-05 23:34:03 +00001525 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00001526 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00001527 unsigned MatchResult =
1528 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00001529
1530 switch (MatchResult) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001531 default:
1532 break;
Jack Carterb4dbc172012-09-05 23:34:03 +00001533 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001534 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00001535 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001536 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00001537 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00001538 return false;
1539 }
1540 case Match_MissingFeature:
1541 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1542 return true;
1543 case Match_InvalidOperand: {
1544 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00001545 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001546 if (ErrorInfo >= Operands.size())
1547 return Error(IDLoc, "too few operands for instruction");
1548
David Blaikie960ea3f2014-06-08 16:18:35 +00001549 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001550 if (ErrorLoc == SMLoc())
1551 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00001552 }
1553
1554 return Error(ErrorLoc, "invalid operand for instruction");
1555 }
1556 case Match_MnemonicFail:
1557 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00001558 case Match_RequiresDifferentSrcAndDst:
1559 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00001560 }
Rafael Espindola870c4e92012-01-11 03:56:41 +00001561 return true;
1562}
1563
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001564void MipsAsmParser::WarnIfAssemblerTemporary(int RegIndex, SMLoc Loc) {
1565 if ((RegIndex != 0) && ((int)Options.getATRegNum() == RegIndex)) {
1566 if (RegIndex == 1)
1567 Warning(Loc, "Used $at without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001568 else
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001569 Warning(Loc, Twine("Used $") + Twine(RegIndex) + " with \".set at=$" +
1570 Twine(RegIndex) + "\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001571 }
1572}
1573
Jack Carter1ac53222013-02-20 23:11:17 +00001574int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001575 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00001576
Vladimir Medic4c299852013-11-06 11:27:05 +00001577 CC = StringSwitch<unsigned>(Name)
1578 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001579 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00001580 .Case("a0", 4)
1581 .Case("a1", 5)
1582 .Case("a2", 6)
1583 .Case("a3", 7)
1584 .Case("v0", 2)
1585 .Case("v1", 3)
1586 .Case("s0", 16)
1587 .Case("s1", 17)
1588 .Case("s2", 18)
1589 .Case("s3", 19)
1590 .Case("s4", 20)
1591 .Case("s5", 21)
1592 .Case("s6", 22)
1593 .Case("s7", 23)
1594 .Case("k0", 26)
1595 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001596 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00001597 .Case("sp", 29)
1598 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001599 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00001600 .Case("ra", 31)
1601 .Case("t0", 8)
1602 .Case("t1", 9)
1603 .Case("t2", 10)
1604 .Case("t3", 11)
1605 .Case("t4", 12)
1606 .Case("t5", 13)
1607 .Case("t6", 14)
1608 .Case("t7", 15)
1609 .Case("t8", 24)
1610 .Case("t9", 25)
1611 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00001612
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001613 if (isABI_N32() || isABI_N64()) {
Daniel Sandersa4b0c742014-03-26 11:39:07 +00001614 // Although SGI documentation just cuts out t0-t3 for n32/n64,
1615 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
1616 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
1617 if (8 <= CC && CC <= 11)
1618 CC += 4;
Jack Carter1ac53222013-02-20 23:11:17 +00001619
Daniel Sandersa4b0c742014-03-26 11:39:07 +00001620 if (CC == -1)
1621 CC = StringSwitch<unsigned>(Name)
1622 .Case("a4", 8)
1623 .Case("a5", 9)
1624 .Case("a6", 10)
1625 .Case("a7", 11)
1626 .Case("kt0", 26)
1627 .Case("kt1", 27)
1628 .Default(-1);
1629 }
Jack Carter1ac53222013-02-20 23:11:17 +00001630
1631 return CC;
1632}
Jack Carterd0bd6422013-04-18 00:41:53 +00001633
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001634int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001635
Jack Cartera63b16a2012-09-07 00:23:42 +00001636 if (Name[0] == 'f') {
1637 StringRef NumString = Name.substr(1);
1638 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001639 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001640 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001641 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00001642 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001643 return IntVal;
1644 }
1645 return -1;
1646}
Jack Cartera63b16a2012-09-07 00:23:42 +00001647
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001648int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
1649
1650 if (Name.startswith("fcc")) {
1651 StringRef NumString = Name.substr(3);
1652 unsigned IntVal;
1653 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001654 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001655 if (IntVal > 7) // There are only 8 fcc registers.
1656 return -1;
1657 return IntVal;
1658 }
1659 return -1;
1660}
1661
1662int MipsAsmParser::matchACRegisterName(StringRef Name) {
1663
Akira Hatanaka274d24c2013-08-14 01:15:52 +00001664 if (Name.startswith("ac")) {
1665 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001666 unsigned IntVal;
1667 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001668 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001669 if (IntVal > 3) // There are only 3 acc registers.
1670 return -1;
1671 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00001672 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001673 return -1;
1674}
Jack Carterd0bd6422013-04-18 00:41:53 +00001675
Jack Carter5dc8ac92013-09-25 23:50:44 +00001676int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
1677 unsigned IntVal;
1678
1679 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
1680 return -1;
1681
1682 if (IntVal > 31)
1683 return -1;
1684
1685 return IntVal;
1686}
1687
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001688int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
1689 int CC;
1690
1691 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00001692 .Case("msair", 0)
1693 .Case("msacsr", 1)
1694 .Case("msaaccess", 2)
1695 .Case("msasave", 3)
1696 .Case("msamodify", 4)
1697 .Case("msarequest", 5)
1698 .Case("msamap", 6)
1699 .Case("msaunmap", 7)
1700 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001701
1702 return CC;
1703}
1704
Jack Carter0b744b32012-10-04 02:29:46 +00001705bool MipsAssemblerOptions::setATReg(unsigned Reg) {
1706 if (Reg > 31)
1707 return false;
1708
1709 aTReg = Reg;
1710 return true;
1711}
1712
Matheus Almeida7de68e72014-06-18 14:46:05 +00001713int MipsAsmParser::getATReg(SMLoc Loc) {
Daniel Sandersd89b1362014-03-24 16:48:01 +00001714 int AT = Options.getATRegNum();
1715 if (AT == 0)
Matheus Almeida7de68e72014-06-18 14:46:05 +00001716 reportParseError(Loc,
1717 "Pseudo instruction requires $at, which is not available");
Daniel Sandersd89b1362014-03-24 16:48:01 +00001718 return AT;
1719}
Jack Carter0b744b32012-10-04 02:29:46 +00001720
Jack Carterd0bd6422013-04-18 00:41:53 +00001721unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00001722 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00001723}
1724
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001725unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001726 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00001727 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001728}
1729
Jack Carter873c7242013-01-12 01:03:14 +00001730int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001731 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00001732 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00001733 return -1;
1734
Jack Carter873c7242013-01-12 01:03:14 +00001735 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00001736}
1737
David Blaikie960ea3f2014-06-08 16:18:35 +00001738bool MipsAsmParser::ParseOperand(OperandVector &Operands, StringRef Mnemonic) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001739 DEBUG(dbgs() << "ParseOperand\n");
1740
Jack Carter30a59822012-10-04 04:03:53 +00001741 // Check if the current operand has a custom associated parser, if so, try to
1742 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00001743 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
1744 if (ResTy == MatchOperand_Success)
1745 return false;
1746 // If there wasn't a custom match, try the generic matcher below. Otherwise,
1747 // there was a match, but an error occurred, in which case, just return that
1748 // the operand parsing failed.
1749 if (ResTy == MatchOperand_ParseFail)
1750 return true;
1751
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001752 DEBUG(dbgs() << ".. Generic Parser\n");
1753
Jack Carterb4dbc172012-09-05 23:34:03 +00001754 switch (getLexer().getKind()) {
1755 default:
1756 Error(Parser.getTok().getLoc(), "unexpected token in operand");
1757 return true;
1758 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001759 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00001760 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00001761
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001762 // Almost all registers have been parsed by custom parsers. There is only
1763 // one exception to this. $zero (and it's alias $0) will reach this point
1764 // for div, divu, and similar instructions because it is not an operand
1765 // to the instruction definition but an explicit register. Special case
1766 // this situation for now.
1767 if (ParseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00001768 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001769
Jack Carterd0bd6422013-04-18 00:41:53 +00001770 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00001771 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001772 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00001773 return true;
1774
Jack Carter873c7242013-01-12 01:03:14 +00001775 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00001776 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00001777 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00001778 const MCExpr *Res =
1779 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00001780
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001781 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00001782 return false;
1783 }
Vladimir Medic4c299852013-11-06 11:27:05 +00001784 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00001785 case AsmToken::LParen:
1786 case AsmToken::Minus:
1787 case AsmToken::Plus:
1788 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00001789 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00001790 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001791 DEBUG(dbgs() << ".. generic integer\n");
1792 OperandMatchResultTy ResTy = ParseImm(Operands);
1793 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00001794 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00001795 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001796 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001797 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001798 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00001799 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00001800 return true;
1801
Jack Carter873c7242013-01-12 01:03:14 +00001802 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1803
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001804 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001805 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001806 } // case AsmToken::Percent
1807 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00001808 return true;
1809}
1810
Vladimir Medic4c299852013-11-06 11:27:05 +00001811const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00001812 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00001813 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00001814 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001815 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00001816 // It's a constant, evaluate reloc value.
1817 int16_t Val;
1818 switch (getVariantKind(RelocStr)) {
1819 case MCSymbolRefExpr::VK_Mips_ABS_LO:
1820 // Get the 1st 16-bits.
1821 Val = MCE->getValue() & 0xffff;
1822 break;
1823 case MCSymbolRefExpr::VK_Mips_ABS_HI:
1824 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
1825 // 16 bits being negative.
1826 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
1827 break;
1828 case MCSymbolRefExpr::VK_Mips_HIGHER:
1829 // Get the 3rd 16-bits.
1830 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
1831 break;
1832 case MCSymbolRefExpr::VK_Mips_HIGHEST:
1833 // Get the 4th 16-bits.
1834 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
1835 break;
1836 default:
1837 report_fatal_error("Unsupported reloc value!");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001838 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00001839 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00001840 }
1841
Jack Carterb5cf5902013-04-17 00:18:04 +00001842 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001843 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00001844 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00001845 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00001846 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001847 return Res;
1848 }
1849
1850 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00001851 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
1852
Sasa Stankovic06c47802014-04-03 10:37:45 +00001853 // Try to create target expression.
1854 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
1855 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00001856
Jack Carterd0bd6422013-04-18 00:41:53 +00001857 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
1858 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00001859 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
1860 return Res;
1861 }
1862
1863 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001864 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
1865 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
1866 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00001867 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001868 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001869 return Expr;
1870}
1871
1872bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
1873
1874 switch (Expr->getKind()) {
1875 case MCExpr::Constant:
1876 return true;
1877 case MCExpr::SymbolRef:
1878 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
1879 case MCExpr::Binary:
1880 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
1881 if (!isEvaluated(BE->getLHS()))
1882 return false;
1883 return isEvaluated(BE->getRHS());
1884 }
1885 case MCExpr::Unary:
1886 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00001887 case MCExpr::Target:
1888 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001889 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001890 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00001891}
Jack Carterd0bd6422013-04-18 00:41:53 +00001892
Jack Carterb5cf5902013-04-17 00:18:04 +00001893bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001894 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00001895 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00001896 if (Tok.isNot(AsmToken::Identifier))
1897 return true;
1898
1899 std::string Str = Tok.getIdentifier().str();
1900
Jack Carterd0bd6422013-04-18 00:41:53 +00001901 Parser.Lex(); // Eat the identifier.
1902 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001903 const MCExpr *IdVal;
1904 SMLoc EndLoc;
1905
1906 if (getLexer().getKind() == AsmToken::LParen) {
1907 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001908 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001909 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001910 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001911 const AsmToken &nextTok = Parser.getTok();
1912 if (nextTok.isNot(AsmToken::Identifier))
1913 return true;
1914 Str += "(%";
1915 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00001916 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00001917 if (getLexer().getKind() != AsmToken::LParen)
1918 return true;
1919 } else
1920 break;
1921 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001922 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00001923 return true;
1924
1925 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00001926 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001927
1928 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00001929 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001930
Jack Carterd0bd6422013-04-18 00:41:53 +00001931 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00001932 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001933}
1934
Jack Carterb4dbc172012-09-05 23:34:03 +00001935bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1936 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001937 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001938 OperandMatchResultTy ResTy = ParseAnyRegister(Operands);
1939 if (ResTy == MatchOperand_Success) {
1940 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00001941 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001942 StartLoc = Operand.getStartLoc();
1943 EndLoc = Operand.getEndLoc();
1944
1945 // AFAIK, we only support numeric registers and named GPR's in CFI
1946 // directives.
1947 // Don't worry about eating tokens before failing. Using an unrecognised
1948 // register is a parse error.
1949 if (Operand.isGPRAsmReg()) {
1950 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001951 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001952 }
1953
1954 return (RegNo == (unsigned)-1);
1955 }
1956
1957 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00001958 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00001959}
1960
Jack Carterb5cf5902013-04-17 00:18:04 +00001961bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00001962 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001963 bool Result = true;
1964
1965 while (getLexer().getKind() == AsmToken::LParen)
1966 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00001967
Jack Carterd0bd6422013-04-18 00:41:53 +00001968 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001969 default:
1970 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00001971 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00001972 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00001973 case AsmToken::Integer:
1974 case AsmToken::Minus:
1975 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00001976 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00001977 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00001978 else
1979 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00001980 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00001981 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001982 break;
Jack Carter873c7242013-01-12 01:03:14 +00001983 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00001984 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00001985 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001986 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001987}
1988
David Blaikie960ea3f2014-06-08 16:18:35 +00001989MipsAsmParser::OperandMatchResultTy
1990MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001991 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00001992 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00001993 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001994 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001995 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00001996 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00001997 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001998
Jack Carterb5cf5902013-04-17 00:18:04 +00001999 if (getLexer().getKind() == AsmToken::LParen) {
2000 Parser.Lex();
2001 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002002 }
2003
Jack Carterb5cf5902013-04-17 00:18:04 +00002004 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002005 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00002006 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002007
Jack Carterd0bd6422013-04-18 00:41:53 +00002008 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002009 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002010 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
2011 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002012 SMLoc E =
2013 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002014 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002015 return MatchOperand_Success;
2016 }
2017 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002018 SMLoc E =
2019 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00002020
Jack Carterd0bd6422013-04-18 00:41:53 +00002021 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002022 // "Base" will be managed by k_Memory.
David Blaikie960ea3f2014-06-08 16:18:35 +00002023 auto Base = MipsOperand::CreateGPRReg(0, getContext().getRegisterInfo(),
2024 S, E, *this);
2025 Operands.push_back(
2026 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002027 return MatchOperand_Success;
2028 }
2029 Error(Parser.getTok().getLoc(), "'(' expected");
2030 return MatchOperand_ParseFail;
2031 }
2032
Jack Carterd0bd6422013-04-18 00:41:53 +00002033 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002034 }
2035
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002036 Res = ParseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002037 if (Res != MatchOperand_Success)
2038 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002039
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002040 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002041 Error(Parser.getTok().getLoc(), "')' expected");
2042 return MatchOperand_ParseFail;
2043 }
2044
Jack Carter873c7242013-01-12 01:03:14 +00002045 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2046
Jack Carterd0bd6422013-04-18 00:41:53 +00002047 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002048
Craig Topper062a2ba2014-04-25 05:30:21 +00002049 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00002050 IdVal = MCConstantExpr::Create(0, getContext());
2051
Jack Carterd0bd6422013-04-18 00:41:53 +00002052 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00002053 std::unique_ptr<MipsOperand> op(
2054 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00002055 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002056 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002057 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00002058 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002059 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
2060 int64_t Imm;
2061 if (IdVal->EvaluateAsAbsolute(Imm))
2062 IdVal = MCConstantExpr::Create(Imm, getContext());
2063 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
2064 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
2065 getContext());
2066 }
2067
David Blaikie960ea3f2014-06-08 16:18:35 +00002068 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002069 return MatchOperand_Success;
2070}
2071
David Blaikie960ea3f2014-06-08 16:18:35 +00002072bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Daniel Sanderse34a1202014-03-31 18:51:43 +00002073
Jack Carterd76b2372013-03-21 21:44:16 +00002074 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
2075 if (Sym) {
2076 SMLoc S = Parser.getTok().getLoc();
2077 const MCExpr *Expr;
2078 if (Sym->isVariable())
2079 Expr = Sym->getVariableValue();
2080 else
2081 return false;
2082 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002083 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00002084 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00002085 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002086 OperandMatchResultTy ResTy =
2087 MatchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00002088 if (ResTy == MatchOperand_Success) {
2089 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00002090 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00002091 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002092 llvm_unreachable("Should never ParseFail");
2093 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00002094 }
2095 } else if (Expr->getKind() == MCExpr::Constant) {
2096 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00002097 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00002098 Operands.push_back(
2099 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00002100 return true;
2101 }
2102 }
2103 return false;
2104}
Jack Carterd0bd6422013-04-18 00:41:53 +00002105
Jack Carter873c7242013-01-12 01:03:14 +00002106MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002107MipsAsmParser::MatchAnyRegisterNameWithoutDollar(OperandVector &Operands,
2108 StringRef Identifier,
2109 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002110 int Index = matchCPURegisterName(Identifier);
2111 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002112 Operands.push_back(MipsOperand::CreateGPRReg(
2113 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2114 return MatchOperand_Success;
2115 }
2116
2117 Index = matchFPURegisterName(Identifier);
2118 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002119 Operands.push_back(MipsOperand::CreateFGRReg(
2120 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2121 return MatchOperand_Success;
2122 }
2123
2124 Index = matchFCCRegisterName(Identifier);
2125 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002126 Operands.push_back(MipsOperand::CreateFCCReg(
2127 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2128 return MatchOperand_Success;
2129 }
2130
2131 Index = matchACRegisterName(Identifier);
2132 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002133 Operands.push_back(MipsOperand::CreateACCReg(
2134 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2135 return MatchOperand_Success;
2136 }
2137
2138 Index = matchMSA128RegisterName(Identifier);
2139 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002140 Operands.push_back(MipsOperand::CreateMSA128Reg(
2141 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2142 return MatchOperand_Success;
2143 }
2144
2145 Index = matchMSA128CtrlRegisterName(Identifier);
2146 if (Index != -1) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002147 Operands.push_back(MipsOperand::CreateMSACtrlReg(
2148 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2149 return MatchOperand_Success;
2150 }
2151
2152 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00002153}
2154
2155MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002156MipsAsmParser::MatchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Daniel Sanders315386c2014-04-01 10:40:14 +00002157 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002158
2159 if (Token.is(AsmToken::Identifier)) {
2160 DEBUG(dbgs() << ".. identifier\n");
2161 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00002162 OperandMatchResultTy ResTy =
2163 MatchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00002164 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002165 } else if (Token.is(AsmToken::Integer)) {
2166 DEBUG(dbgs() << ".. integer\n");
2167 Operands.push_back(MipsOperand::CreateNumericReg(
2168 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
2169 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002170 return MatchOperand_Success;
2171 }
2172
2173 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
2174
2175 return MatchOperand_NoMatch;
2176}
2177
David Blaikie960ea3f2014-06-08 16:18:35 +00002178MipsAsmParser::OperandMatchResultTy
2179MipsAsmParser::ParseAnyRegister(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002180 DEBUG(dbgs() << "ParseAnyRegister\n");
2181
2182 auto Token = Parser.getTok();
2183
2184 SMLoc S = Token.getLoc();
2185
2186 if (Token.isNot(AsmToken::Dollar)) {
2187 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
2188 if (Token.is(AsmToken::Identifier)) {
2189 if (searchSymbolAlias(Operands))
2190 return MatchOperand_Success;
2191 }
2192 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
2193 return MatchOperand_NoMatch;
2194 }
2195 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002196
Daniel Sanders21bce302014-04-01 12:35:23 +00002197 OperandMatchResultTy ResTy = MatchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00002198 if (ResTy == MatchOperand_Success) {
2199 Parser.Lex(); // $
2200 Parser.Lex(); // identifier
2201 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002202 return ResTy;
2203}
2204
2205MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002206MipsAsmParser::ParseImm(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002207 switch (getLexer().getKind()) {
2208 default:
2209 return MatchOperand_NoMatch;
2210 case AsmToken::LParen:
2211 case AsmToken::Minus:
2212 case AsmToken::Plus:
2213 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002214 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002215 case AsmToken::String:
2216 break;
2217 }
2218
2219 const MCExpr *IdVal;
2220 SMLoc S = Parser.getTok().getLoc();
2221 if (getParser().parseExpression(IdVal))
2222 return MatchOperand_ParseFail;
2223
2224 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2225 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
2226 return MatchOperand_Success;
2227}
2228
David Blaikie960ea3f2014-06-08 16:18:35 +00002229MipsAsmParser::OperandMatchResultTy
2230MipsAsmParser::ParseJumpTarget(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002231 DEBUG(dbgs() << "ParseJumpTarget\n");
2232
2233 SMLoc S = getLexer().getLoc();
2234
2235 // Integers and expressions are acceptable
2236 OperandMatchResultTy ResTy = ParseImm(Operands);
2237 if (ResTy != MatchOperand_NoMatch)
2238 return ResTy;
2239
Daniel Sanders315386c2014-04-01 10:40:14 +00002240 // Registers are a valid target and have priority over symbols.
2241 ResTy = ParseAnyRegister(Operands);
2242 if (ResTy != MatchOperand_NoMatch)
2243 return ResTy;
2244
Daniel Sandersffd84362014-04-01 10:41:48 +00002245 const MCExpr *Expr = nullptr;
2246 if (Parser.parseExpression(Expr)) {
2247 // We have no way of knowing if a symbol was consumed so we must ParseFail
2248 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002249 }
Daniel Sandersffd84362014-04-01 10:41:48 +00002250 Operands.push_back(
2251 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002252 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00002253}
2254
Vladimir Medic2b953d02013-10-01 09:48:56 +00002255MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002256MipsAsmParser::parseInvNum(OperandVector &Operands) {
Vladimir Medic2b953d02013-10-01 09:48:56 +00002257 const MCExpr *IdVal;
2258 // If the first token is '$' we may have register operand.
2259 if (Parser.getTok().is(AsmToken::Dollar))
2260 return MatchOperand_NoMatch;
2261 SMLoc S = Parser.getTok().getLoc();
2262 if (getParser().parseExpression(IdVal))
2263 return MatchOperand_ParseFail;
2264 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00002265 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00002266 int64_t Val = MCE->getValue();
2267 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2268 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002269 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00002270 return MatchOperand_Success;
2271}
2272
Matheus Almeida779c5932013-11-18 12:32:49 +00002273MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002274MipsAsmParser::ParseLSAImm(OperandVector &Operands) {
Matheus Almeida779c5932013-11-18 12:32:49 +00002275 switch (getLexer().getKind()) {
2276 default:
2277 return MatchOperand_NoMatch;
2278 case AsmToken::LParen:
2279 case AsmToken::Plus:
2280 case AsmToken::Minus:
2281 case AsmToken::Integer:
2282 break;
2283 }
2284
2285 const MCExpr *Expr;
2286 SMLoc S = Parser.getTok().getLoc();
2287
2288 if (getParser().parseExpression(Expr))
2289 return MatchOperand_ParseFail;
2290
2291 int64_t Val;
2292 if (!Expr->EvaluateAsAbsolute(Val)) {
2293 Error(S, "expected immediate value");
2294 return MatchOperand_ParseFail;
2295 }
2296
2297 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
2298 // and because the CPU always adds one to the immediate field, the allowed
2299 // range becomes 1..4. We'll only check the range here and will deal
2300 // with the addition/subtraction when actually decoding/encoding
2301 // the instruction.
2302 if (Val < 1 || Val > 4) {
2303 Error(S, "immediate not in range (1..4)");
2304 return MatchOperand_ParseFail;
2305 }
2306
Jack Carter3b2c96e2014-01-22 23:31:38 +00002307 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002308 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00002309 return MatchOperand_Success;
2310}
2311
Jack Carterdc1e35d2012-09-06 20:00:02 +00002312MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
2313
Vladimir Medic4c299852013-11-06 11:27:05 +00002314 MCSymbolRefExpr::VariantKind VK =
2315 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
2316 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
2317 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
2318 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
2319 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
2320 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
2321 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
2322 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
2323 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
2324 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
2325 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
2326 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
2327 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
2328 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
2329 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
2330 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
2331 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
2332 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00002333 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
2334 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
2335 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
2336 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
2337 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
2338 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00002339 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
2340 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00002341 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002342
Matheus Almeida2852af82014-04-22 10:15:54 +00002343 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00002344
Jack Carterdc1e35d2012-09-06 20:00:02 +00002345 return VK;
2346}
Jack Cartera63b16a2012-09-07 00:23:42 +00002347
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002348/// Sometimes (i.e. load/stores) the operand may be followed immediately by
2349/// either this.
2350/// ::= '(', register, ')'
2351/// handle it before we iterate so we don't get tripped up by the lack of
2352/// a comma.
David Blaikie960ea3f2014-06-08 16:18:35 +00002353bool MipsAsmParser::ParseParenSuffix(StringRef Name, OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002354 if (getLexer().is(AsmToken::LParen)) {
2355 Operands.push_back(
2356 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
2357 Parser.Lex();
2358 if (ParseOperand(Operands, Name)) {
2359 SMLoc Loc = getLexer().getLoc();
2360 Parser.eatToEndOfStatement();
2361 return Error(Loc, "unexpected token in argument list");
2362 }
2363 if (Parser.getTok().isNot(AsmToken::RParen)) {
2364 SMLoc Loc = getLexer().getLoc();
2365 Parser.eatToEndOfStatement();
2366 return Error(Loc, "unexpected token, expected ')'");
2367 }
2368 Operands.push_back(
2369 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
2370 Parser.Lex();
2371 }
2372 return false;
2373}
2374
2375/// Sometimes (i.e. in MSA) the operand may be followed immediately by
2376/// either one of these.
2377/// ::= '[', register, ']'
2378/// ::= '[', integer, ']'
2379/// handle it before we iterate so we don't get tripped up by the lack of
2380/// a comma.
David Blaikie960ea3f2014-06-08 16:18:35 +00002381bool MipsAsmParser::ParseBracketSuffix(StringRef Name,
2382 OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002383 if (getLexer().is(AsmToken::LBrac)) {
2384 Operands.push_back(
2385 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
2386 Parser.Lex();
2387 if (ParseOperand(Operands, Name)) {
2388 SMLoc Loc = getLexer().getLoc();
2389 Parser.eatToEndOfStatement();
2390 return Error(Loc, "unexpected token in argument list");
2391 }
2392 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2393 SMLoc Loc = getLexer().getLoc();
2394 Parser.eatToEndOfStatement();
2395 return Error(Loc, "unexpected token, expected ']'");
2396 }
2397 Operands.push_back(
2398 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
2399 Parser.Lex();
2400 }
2401 return false;
2402}
2403
David Blaikie960ea3f2014-06-08 16:18:35 +00002404bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
2405 SMLoc NameLoc, OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002406 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00002407
2408 // We have reached first instruction, module directive are now forbidden.
2409 getTargetStreamer().forbidModuleDirective();
2410
Vladimir Medic74593e62013-07-17 15:00:42 +00002411 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00002412 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00002413 Parser.eatToEndOfStatement();
2414 return Error(NameLoc, "Unknown instruction");
2415 }
Vladimir Medic64828a12013-07-16 10:07:14 +00002416 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002417 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002418
2419 // Read the remaining operands.
2420 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2421 // Read the first operand.
Vladimir Medic64828a12013-07-16 10:07:14 +00002422 if (ParseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002423 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002424 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002425 return Error(Loc, "unexpected token in argument list");
2426 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002427 if (getLexer().is(AsmToken::LBrac) && ParseBracketSuffix(Name, Operands))
2428 return true;
2429 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00002430
Jack Carterd0bd6422013-04-18 00:41:53 +00002431 while (getLexer().is(AsmToken::Comma)) {
2432 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00002433 // Parse and remember the operand.
2434 if (ParseOperand(Operands, Name)) {
2435 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002436 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002437 return Error(Loc, "unexpected token in argument list");
2438 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002439 // Parse bracket and parenthesis suffixes before we iterate
2440 if (getLexer().is(AsmToken::LBrac)) {
2441 if (ParseBracketSuffix(Name, Operands))
2442 return true;
2443 } else if (getLexer().is(AsmToken::LParen) &&
2444 ParseParenSuffix(Name, Operands))
2445 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00002446 }
2447 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002448 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2449 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002450 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002451 return Error(Loc, "unexpected token in argument list");
2452 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002453 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00002454 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00002455}
2456
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002457bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002458 SMLoc Loc = getLexer().getLoc();
2459 Parser.eatToEndOfStatement();
2460 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00002461}
2462
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002463bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002464 return Error(Loc, ErrorMsg);
2465}
2466
Jack Carter0b744b32012-10-04 02:29:46 +00002467bool MipsAsmParser::parseSetNoAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002468 // Line should look like: ".set noat".
2469 // set at reg to 0.
Jack Carter99d2afe2012-10-05 23:55:28 +00002470 Options.setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00002471 // eat noat
2472 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002473 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002474 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2475 reportParseError("unexpected token in statement");
2476 return false;
2477 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002478 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002479 return false;
2480}
Jack Carterd0bd6422013-04-18 00:41:53 +00002481
Jack Carter0b744b32012-10-04 02:29:46 +00002482bool MipsAsmParser::parseSetAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002483 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00002484 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00002485 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00002486 getParser().Lex();
2487 if (getLexer().is(AsmToken::EndOfStatement)) {
Jack Carter99d2afe2012-10-05 23:55:28 +00002488 Options.setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00002489 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002490 return false;
2491 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002492 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00002493 if (getLexer().isNot(AsmToken::Dollar)) {
2494 reportParseError("unexpected token in statement");
2495 return false;
2496 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002497 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00002498 const AsmToken &Reg = Parser.getTok();
2499 if (Reg.is(AsmToken::Identifier)) {
2500 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
2501 } else if (Reg.is(AsmToken::Integer)) {
2502 AtRegNo = Reg.getIntVal();
2503 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00002504 reportParseError("unexpected token in statement");
2505 return false;
2506 }
Jack Carter1ac53222013-02-20 23:11:17 +00002507
Daniel Sanders71a89d922014-03-25 13:01:06 +00002508 if (AtRegNo < 0 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00002509 reportParseError("unexpected token in statement");
2510 return false;
2511 }
2512
2513 if (!Options.setATReg(AtRegNo)) {
Jack Carter0b744b32012-10-04 02:29:46 +00002514 reportParseError("unexpected token in statement");
2515 return false;
2516 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002517 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00002518
2519 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2520 reportParseError("unexpected token in statement");
2521 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002522 }
2523 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002524 return false;
2525 } else {
2526 reportParseError("unexpected token in statement");
2527 return false;
2528 }
2529}
2530
2531bool MipsAsmParser::parseSetReorderDirective() {
2532 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002533 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002534 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2535 reportParseError("unexpected token in statement");
2536 return false;
2537 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002538 Options.setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00002539 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002540 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002541 return false;
2542}
2543
2544bool MipsAsmParser::parseSetNoReorderDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002545 Parser.Lex();
2546 // If this is not the end of the statement, report an error.
2547 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2548 reportParseError("unexpected token in statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002549 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002550 }
2551 Options.setNoreorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00002552 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002553 Parser.Lex(); // Consume the EndOfStatement.
2554 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002555}
2556
2557bool MipsAsmParser::parseSetMacroDirective() {
2558 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002559 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002560 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2561 reportParseError("unexpected token in statement");
2562 return false;
2563 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002564 Options.setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002565 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002566 return false;
2567}
2568
2569bool MipsAsmParser::parseSetNoMacroDirective() {
2570 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002571 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002572 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2573 reportParseError("`noreorder' must be set before `nomacro'");
2574 return false;
2575 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002576 if (Options.isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00002577 reportParseError("`noreorder' must be set before `nomacro'");
2578 return false;
2579 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002580 Options.setNomacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002581 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002582 return false;
2583}
Jack Carterd76b2372013-03-21 21:44:16 +00002584
Daniel Sanders44934432014-08-07 12:03:36 +00002585bool MipsAsmParser::parseSetMsaDirective() {
2586 Parser.Lex();
2587
2588 // If this is not the end of the statement, report an error.
2589 if (getLexer().isNot(AsmToken::EndOfStatement))
2590 return reportParseError("unexpected token in statement");
2591
2592 setFeatureBits(Mips::FeatureMSA, "msa");
2593 getTargetStreamer().emitDirectiveSetMsa();
2594 return false;
2595}
2596
2597bool MipsAsmParser::parseSetNoMsaDirective() {
2598 Parser.Lex();
2599
2600 // If this is not the end of the statement, report an error.
2601 if (getLexer().isNot(AsmToken::EndOfStatement))
2602 return reportParseError("unexpected token in statement");
2603
2604 clearFeatureBits(Mips::FeatureMSA, "msa");
2605 getTargetStreamer().emitDirectiveSetNoMsa();
2606 return false;
2607}
2608
Jack Carter39536722014-01-22 23:08:42 +00002609bool MipsAsmParser::parseSetNoMips16Directive() {
2610 Parser.Lex();
2611 // If this is not the end of the statement, report an error.
2612 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2613 reportParseError("unexpected token in statement");
2614 return false;
2615 }
2616 // For now do nothing.
2617 Parser.Lex(); // Consume the EndOfStatement.
2618 return false;
2619}
2620
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002621bool MipsAsmParser::parseSetFpDirective() {
Daniel Sanders7e527422014-07-10 13:38:23 +00002622 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002623 // Line can be: .set fp=32
2624 // .set fp=xx
2625 // .set fp=64
2626 Parser.Lex(); // Eat fp token
2627 AsmToken Tok = Parser.getTok();
2628 if (Tok.isNot(AsmToken::Equal)) {
2629 reportParseError("unexpected token in statement");
2630 return false;
2631 }
2632 Parser.Lex(); // Eat '=' token.
2633 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002634
2635 if (!parseFpABIValue(FpAbiVal, ".set"))
2636 return false;
2637
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002638 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2639 reportParseError("unexpected token in statement");
2640 return false;
2641 }
Daniel Sanders7e527422014-07-10 13:38:23 +00002642 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002643 Parser.Lex(); // Consume the EndOfStatement.
2644 return false;
2645}
2646
Jack Carterd76b2372013-03-21 21:44:16 +00002647bool MipsAsmParser::parseSetAssignment() {
2648 StringRef Name;
2649 const MCExpr *Value;
2650
2651 if (Parser.parseIdentifier(Name))
2652 reportParseError("expected identifier after .set");
2653
2654 if (getLexer().isNot(AsmToken::Comma))
2655 return reportParseError("unexpected token in .set directive");
Jack Carterb5cf5902013-04-17 00:18:04 +00002656 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00002657
Jack Carter3b2c96e2014-01-22 23:31:38 +00002658 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00002659 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00002660
Jack Carterd0bd6422013-04-18 00:41:53 +00002661 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00002662 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00002663 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00002664 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00002665 Sym = getContext().GetOrCreateSymbol(Name);
2666 Sym->setVariableValue(Value);
2667
2668 return false;
2669}
Jack Carterd0bd6422013-04-18 00:41:53 +00002670
Toma Tabacu85618b32014-08-19 14:22:52 +00002671bool MipsAsmParser::parseSetArchDirective() {
2672 Parser.Lex();
2673 if (getLexer().isNot(AsmToken::Equal))
2674 return reportParseError("unexpected token, expected equals sign");
2675
2676 Parser.Lex();
2677 StringRef Arch;
2678 if (Parser.parseIdentifier(Arch))
2679 return reportParseError("expected arch identifier");
2680
2681 StringRef ArchFeatureName =
2682 StringSwitch<StringRef>(Arch)
2683 .Case("mips1", "mips1")
2684 .Case("mips2", "mips2")
2685 .Case("mips3", "mips3")
2686 .Case("mips4", "mips4")
2687 .Case("mips5", "mips5")
2688 .Case("mips32", "mips32")
2689 .Case("mips32r2", "mips32r2")
2690 .Case("mips32r6", "mips32r6")
2691 .Case("mips64", "mips64")
2692 .Case("mips64r2", "mips64r2")
2693 .Case("mips64r6", "mips64r6")
2694 .Case("cnmips", "cnmips")
2695 .Case("r4000", "mips3") // This is an implementation of Mips3.
2696 .Default("");
2697
2698 if (ArchFeatureName.empty())
2699 return reportParseError("unsupported architecture");
2700
2701 selectArch(ArchFeatureName);
2702 getTargetStreamer().emitDirectiveSetArch(Arch);
2703 return false;
2704}
2705
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002706bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
2707 Parser.Lex();
2708 if (getLexer().isNot(AsmToken::EndOfStatement))
2709 return reportParseError("unexpected token in .set directive");
2710
Matheus Almeida2852af82014-04-22 10:15:54 +00002711 switch (Feature) {
2712 default:
2713 llvm_unreachable("Unimplemented feature");
2714 case Mips::FeatureDSP:
2715 setFeatureBits(Mips::FeatureDSP, "dsp");
2716 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002717 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002718 case Mips::FeatureMicroMips:
2719 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002720 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002721 case Mips::FeatureMips16:
2722 getTargetStreamer().emitDirectiveSetMips16();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002723 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00002724 case Mips::FeatureMips1:
2725 selectArch("mips1");
2726 getTargetStreamer().emitDirectiveSetMips1();
2727 break;
2728 case Mips::FeatureMips2:
2729 selectArch("mips2");
2730 getTargetStreamer().emitDirectiveSetMips2();
2731 break;
2732 case Mips::FeatureMips3:
2733 selectArch("mips3");
2734 getTargetStreamer().emitDirectiveSetMips3();
2735 break;
2736 case Mips::FeatureMips4:
2737 selectArch("mips4");
2738 getTargetStreamer().emitDirectiveSetMips4();
2739 break;
2740 case Mips::FeatureMips5:
2741 selectArch("mips5");
2742 getTargetStreamer().emitDirectiveSetMips5();
2743 break;
2744 case Mips::FeatureMips32:
2745 selectArch("mips32");
2746 getTargetStreamer().emitDirectiveSetMips32();
2747 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002748 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00002749 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00002750 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002751 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00002752 case Mips::FeatureMips32r6:
2753 selectArch("mips32r6");
2754 getTargetStreamer().emitDirectiveSetMips32R6();
2755 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002756 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00002757 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00002758 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00002759 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002760 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00002761 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00002762 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00002763 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00002764 case Mips::FeatureMips64r6:
2765 selectArch("mips64r6");
2766 getTargetStreamer().emitDirectiveSetMips64R6();
2767 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002768 }
2769 return false;
2770}
2771
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002772bool MipsAsmParser::eatComma(StringRef ErrorStr) {
2773 if (getLexer().isNot(AsmToken::Comma)) {
2774 SMLoc Loc = getLexer().getLoc();
2775 Parser.eatToEndOfStatement();
2776 return Error(Loc, ErrorStr);
2777 }
2778
Matheus Almeida2852af82014-04-22 10:15:54 +00002779 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002780 return true;
2781}
2782
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002783bool MipsAsmParser::parseDirectiveCPLoad(SMLoc Loc) {
2784 if (Options.isReorder())
2785 Warning(Loc, ".cpload in reorder section");
2786
2787 // FIXME: Warn if cpload is used in Mips16 mode.
2788
David Blaikie960ea3f2014-06-08 16:18:35 +00002789 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002790 OperandMatchResultTy ResTy = ParseAnyRegister(Reg);
2791 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
2792 reportParseError("expected register containing function address");
2793 return false;
2794 }
2795
David Blaikie960ea3f2014-06-08 16:18:35 +00002796 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
2797 if (!RegOpnd.isGPRAsmReg()) {
2798 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002799 return false;
2800 }
2801
David Blaikie960ea3f2014-06-08 16:18:35 +00002802 getTargetStreamer().emitDirectiveCpload(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002803 return false;
2804}
2805
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002806bool MipsAsmParser::parseDirectiveCPSetup() {
2807 unsigned FuncReg;
2808 unsigned Save;
2809 bool SaveIsReg = true;
2810
Matheus Almeida7e815762014-06-18 13:08:59 +00002811 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
2812 OperandMatchResultTy ResTy = ParseAnyRegister(TmpReg);
2813 if (ResTy == MatchOperand_NoMatch) {
2814 reportParseError("expected register containing function address");
2815 Parser.eatToEndOfStatement();
2816 return false;
2817 }
2818
2819 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
2820 if (!FuncRegOpnd.isGPRAsmReg()) {
2821 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
2822 Parser.eatToEndOfStatement();
2823 return false;
2824 }
2825
2826 FuncReg = FuncRegOpnd.getGPR32Reg();
2827 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002828
2829 if (!eatComma("expected comma parsing directive"))
2830 return true;
2831
Matheus Almeida7e815762014-06-18 13:08:59 +00002832 ResTy = ParseAnyRegister(TmpReg);
2833 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002834 const AsmToken &Tok = Parser.getTok();
2835 if (Tok.is(AsmToken::Integer)) {
2836 Save = Tok.getIntVal();
2837 SaveIsReg = false;
2838 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00002839 } else {
2840 reportParseError("expected save register or stack offset");
2841 Parser.eatToEndOfStatement();
2842 return false;
2843 }
2844 } else {
2845 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
2846 if (!SaveOpnd.isGPRAsmReg()) {
2847 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
2848 Parser.eatToEndOfStatement();
2849 return false;
2850 }
2851 Save = SaveOpnd.getGPR32Reg();
2852 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002853
2854 if (!eatComma("expected comma parsing directive"))
2855 return true;
2856
2857 StringRef Name;
2858 if (Parser.parseIdentifier(Name))
2859 reportParseError("expected identifier");
2860 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002861
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00002862 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, *Sym, SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002863 return false;
2864}
2865
Matheus Almeida0051f2d2014-04-16 15:48:55 +00002866bool MipsAsmParser::parseDirectiveNaN() {
2867 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2868 const AsmToken &Tok = Parser.getTok();
2869
2870 if (Tok.getString() == "2008") {
2871 Parser.Lex();
2872 getTargetStreamer().emitDirectiveNaN2008();
2873 return false;
2874 } else if (Tok.getString() == "legacy") {
2875 Parser.Lex();
2876 getTargetStreamer().emitDirectiveNaNLegacy();
2877 return false;
2878 }
2879 }
2880 // If we don't recognize the option passed to the .nan
2881 // directive (e.g. no option or unknown option), emit an error.
2882 reportParseError("invalid option in .nan directive");
2883 return false;
2884}
2885
Jack Carter0b744b32012-10-04 02:29:46 +00002886bool MipsAsmParser::parseDirectiveSet() {
2887
Jack Carterd0bd6422013-04-18 00:41:53 +00002888 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00002889 const AsmToken &Tok = Parser.getTok();
2890
2891 if (Tok.getString() == "noat") {
2892 return parseSetNoAtDirective();
2893 } else if (Tok.getString() == "at") {
2894 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00002895 } else if (Tok.getString() == "arch") {
2896 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002897 } else if (Tok.getString() == "fp") {
2898 return parseSetFpDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00002899 } else if (Tok.getString() == "reorder") {
2900 return parseSetReorderDirective();
2901 } else if (Tok.getString() == "noreorder") {
2902 return parseSetNoReorderDirective();
2903 } else if (Tok.getString() == "macro") {
2904 return parseSetMacroDirective();
2905 } else if (Tok.getString() == "nomacro") {
2906 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00002907 } else if (Tok.getString() == "mips16") {
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002908 return parseSetFeature(Mips::FeatureMips16);
Jack Carter0b744b32012-10-04 02:29:46 +00002909 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00002910 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00002911 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00002912 getTargetStreamer().emitDirectiveSetNoMicroMips();
2913 Parser.eatToEndOfStatement();
2914 return false;
2915 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002916 return parseSetFeature(Mips::FeatureMicroMips);
Daniel Sandersf0df2212014-08-04 12:20:00 +00002917 } else if (Tok.getString() == "mips1") {
2918 return parseSetFeature(Mips::FeatureMips1);
2919 } else if (Tok.getString() == "mips2") {
2920 return parseSetFeature(Mips::FeatureMips2);
2921 } else if (Tok.getString() == "mips3") {
2922 return parseSetFeature(Mips::FeatureMips3);
2923 } else if (Tok.getString() == "mips4") {
2924 return parseSetFeature(Mips::FeatureMips4);
2925 } else if (Tok.getString() == "mips5") {
2926 return parseSetFeature(Mips::FeatureMips5);
2927 } else if (Tok.getString() == "mips32") {
2928 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00002929 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002930 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sandersf0df2212014-08-04 12:20:00 +00002931 } else if (Tok.getString() == "mips32r6") {
2932 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00002933 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002934 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00002935 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002936 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sandersf0df2212014-08-04 12:20:00 +00002937 } else if (Tok.getString() == "mips64r6") {
2938 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00002939 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002940 return parseSetFeature(Mips::FeatureDSP);
Daniel Sanders44934432014-08-07 12:03:36 +00002941 } else if (Tok.getString() == "msa") {
2942 return parseSetMsaDirective();
2943 } else if (Tok.getString() == "nomsa") {
2944 return parseSetNoMsaDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00002945 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002946 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00002947 parseSetAssignment();
2948 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002949 }
Jack Carter07c818d2013-01-25 01:31:34 +00002950
Jack Carter0b744b32012-10-04 02:29:46 +00002951 return true;
2952}
2953
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002954/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00002955/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002956bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Jack Carter07c818d2013-01-25 01:31:34 +00002957 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2958 for (;;) {
2959 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002960 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00002961 return true;
2962
2963 getParser().getStreamer().EmitValue(Value, Size);
2964
2965 if (getLexer().is(AsmToken::EndOfStatement))
2966 break;
2967
2968 // FIXME: Improve diagnostic.
2969 if (getLexer().isNot(AsmToken::Comma))
2970 return Error(L, "unexpected token in directive");
2971 Parser.Lex();
2972 }
2973 }
2974
2975 Parser.Lex();
2976 return false;
2977}
2978
Vladimir Medic4c299852013-11-06 11:27:05 +00002979/// parseDirectiveGpWord
2980/// ::= .gpword local_sym
2981bool MipsAsmParser::parseDirectiveGpWord() {
2982 const MCExpr *Value;
2983 // EmitGPRel32Value requires an expression, so we are using base class
2984 // method to evaluate the expression.
2985 if (getParser().parseExpression(Value))
2986 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00002987 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00002988
Vladimir Medice10c1122013-11-13 13:18:04 +00002989 if (getLexer().isNot(AsmToken::EndOfStatement))
Vladimir Medic4c299852013-11-06 11:27:05 +00002990 return Error(getLexer().getLoc(), "unexpected token in directive");
Vladimir Medice10c1122013-11-13 13:18:04 +00002991 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00002992 return false;
2993}
2994
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002995/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00002996/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002997bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindolab59fb732014-03-28 18:50:26 +00002998 const MCExpr *Value;
2999 // EmitGPRel64Value requires an expression, so we are using base class
3000 // method to evaluate the expression.
3001 if (getParser().parseExpression(Value))
3002 return true;
3003 getParser().getStreamer().EmitGPRel64Value(Value);
3004
3005 if (getLexer().isNot(AsmToken::EndOfStatement))
3006 return Error(getLexer().getLoc(), "unexpected token in directive");
3007 Parser.Lex(); // Eat EndOfStatement token.
3008 return false;
3009}
3010
Jack Carter0cd3c192014-01-06 23:27:31 +00003011bool MipsAsmParser::parseDirectiveOption() {
3012 // Get the option token.
3013 AsmToken Tok = Parser.getTok();
3014 // At the moment only identifiers are supported.
3015 if (Tok.isNot(AsmToken::Identifier)) {
3016 Error(Parser.getTok().getLoc(), "unexpected token in .option directive");
3017 Parser.eatToEndOfStatement();
3018 return false;
3019 }
3020
3021 StringRef Option = Tok.getIdentifier();
3022
3023 if (Option == "pic0") {
3024 getTargetStreamer().emitDirectiveOptionPic0();
3025 Parser.Lex();
3026 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3027 Error(Parser.getTok().getLoc(),
3028 "unexpected token in .option pic0 directive");
3029 Parser.eatToEndOfStatement();
3030 }
3031 return false;
3032 }
3033
Matheus Almeidaf79b2812014-03-26 13:40:29 +00003034 if (Option == "pic2") {
3035 getTargetStreamer().emitDirectiveOptionPic2();
3036 Parser.Lex();
3037 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3038 Error(Parser.getTok().getLoc(),
3039 "unexpected token in .option pic2 directive");
3040 Parser.eatToEndOfStatement();
3041 }
3042 return false;
3043 }
3044
Jack Carter0cd3c192014-01-06 23:27:31 +00003045 // Unknown option.
3046 Warning(Parser.getTok().getLoc(), "unknown option in .option directive");
3047 Parser.eatToEndOfStatement();
3048 return false;
3049}
3050
Daniel Sanders7e527422014-07-10 13:38:23 +00003051/// parseDirectiveModule
3052/// ::= .module oddspreg
3053/// ::= .module nooddspreg
3054/// ::= .module fp=value
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003055bool MipsAsmParser::parseDirectiveModule() {
Daniel Sanders7e527422014-07-10 13:38:23 +00003056 MCAsmLexer &Lexer = getLexer();
3057 SMLoc L = Lexer.getLoc();
3058
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00003059 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003060 // TODO : get a better message.
3061 reportParseError(".module directive must appear before any code");
3062 return false;
3063 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003064
3065 if (Lexer.is(AsmToken::Identifier)) {
3066 StringRef Option = Parser.getTok().getString();
3067 Parser.Lex();
3068
3069 if (Option == "oddspreg") {
3070 getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32());
3071 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
3072
3073 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3074 reportParseError("Expected end of statement");
3075 return false;
3076 }
3077
3078 return false;
3079 } else if (Option == "nooddspreg") {
3080 if (!isABI_O32()) {
3081 Error(L, "'.module nooddspreg' requires the O32 ABI");
3082 return false;
3083 }
3084
3085 getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32());
3086 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
3087
3088 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3089 reportParseError("Expected end of statement");
3090 return false;
3091 }
3092
3093 return false;
3094 } else if (Option == "fp") {
3095 return parseDirectiveModuleFP();
3096 }
3097
3098 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003099 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003100
3101 return false;
3102}
3103
3104/// parseDirectiveModuleFP
3105/// ::= =32
3106/// ::= =xx
3107/// ::= =64
3108bool MipsAsmParser::parseDirectiveModuleFP() {
3109 MCAsmLexer &Lexer = getLexer();
3110
3111 if (Lexer.isNot(AsmToken::Equal)) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003112 reportParseError("unexpected token in statement");
3113 return false;
3114 }
3115 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003116
Daniel Sanders7e527422014-07-10 13:38:23 +00003117 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003118 if (!parseFpABIValue(FpABI, ".module"))
3119 return false;
3120
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003121 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3122 reportParseError("unexpected token in statement");
3123 return false;
3124 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003125
Daniel Sanders7201a3e2014-07-08 10:35:52 +00003126 // Emit appropriate flags.
3127 getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
Daniel Sanders7e527422014-07-10 13:38:23 +00003128 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003129 return false;
3130}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003131
Daniel Sanders7e527422014-07-10 13:38:23 +00003132bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003133 StringRef Directive) {
3134 MCAsmLexer &Lexer = getLexer();
3135
3136 if (Lexer.is(AsmToken::Identifier)) {
3137 StringRef Value = Parser.getTok().getString();
3138 Parser.Lex();
3139
3140 if (Value != "xx") {
3141 reportParseError("unsupported value, expected 'xx', '32' or '64'");
3142 return false;
3143 }
3144
3145 if (!isABI_O32()) {
3146 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
3147 return false;
3148 }
3149
Daniel Sanders7e527422014-07-10 13:38:23 +00003150 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003151 return true;
3152 }
3153
3154 if (Lexer.is(AsmToken::Integer)) {
3155 unsigned Value = Parser.getTok().getIntVal();
3156 Parser.Lex();
3157
3158 if (Value != 32 && Value != 64) {
3159 reportParseError("unsupported value, expected 'xx', '32' or '64'");
3160 return false;
3161 }
3162
3163 if (Value == 32) {
3164 if (!isABI_O32()) {
3165 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
3166 return false;
3167 }
3168
Daniel Sanders7e527422014-07-10 13:38:23 +00003169 FpABI = MipsABIFlagsSection::FpABIKind::S32;
3170 } else
3171 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003172
Daniel Sanders7e527422014-07-10 13:38:23 +00003173 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003174 }
3175
3176 return false;
3177}
3178
Jack Carter0b744b32012-10-04 02:29:46 +00003179bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carter07c818d2013-01-25 01:31:34 +00003180 StringRef IDVal = DirectiveID.getString();
3181
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003182 if (IDVal == ".cpload")
3183 return parseDirectiveCPLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00003184 if (IDVal == ".dword") {
3185 parseDataDirective(8, DirectiveID.getLoc());
3186 return false;
3187 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003188 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003189 StringRef SymbolName;
3190
3191 if (Parser.parseIdentifier(SymbolName)) {
3192 reportParseError("expected identifier after .ent");
3193 return false;
3194 }
3195
3196 // There's an undocumented extension that allows an integer to
3197 // follow the name of the procedure which AFAICS is ignored by GAS.
3198 // Example: .ent foo,2
3199 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3200 if (getLexer().isNot(AsmToken::Comma)) {
3201 // Even though we accept this undocumented extension for compatibility
3202 // reasons, the additional integer argument does not actually change
3203 // the behaviour of the '.ent' directive, so we would like to discourage
3204 // its use. We do this by not referring to the extended version in
3205 // error messages which are not directly related to its use.
3206 reportParseError("unexpected token, expected end of statement");
3207 return false;
3208 }
3209 Parser.Lex(); // Eat the comma.
3210 const MCExpr *DummyNumber;
3211 int64_t DummyNumberVal;
3212 // If the user was explicitly trying to use the extended version,
3213 // we still give helpful extension-related error messages.
3214 if (Parser.parseExpression(DummyNumber)) {
3215 reportParseError("expected number after comma");
3216 return false;
3217 }
3218 if (!DummyNumber->EvaluateAsAbsolute(DummyNumberVal)) {
3219 reportParseError("expected an absolute expression after comma");
3220 return false;
3221 }
3222 }
3223
3224 // If this is not the end of the statement, report an error.
3225 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3226 reportParseError("unexpected token, expected end of statement");
3227 return false;
3228 }
3229
3230 MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
3231
3232 getTargetStreamer().emitDirectiveEnt(*Sym);
3233 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00003234 return false;
3235 }
3236
Jack Carter07c818d2013-01-25 01:31:34 +00003237 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003238 StringRef SymbolName;
3239
3240 if (Parser.parseIdentifier(SymbolName)) {
3241 reportParseError("expected identifier after .end");
3242 return false;
3243 }
3244
3245 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3246 reportParseError("unexpected token, expected end of statement");
3247 return false;
3248 }
3249
3250 if (CurrentFn == nullptr) {
3251 reportParseError(".end used without .ent");
3252 return false;
3253 }
3254
3255 if ((SymbolName != CurrentFn->getName())) {
3256 reportParseError(".end symbol does not match .ent symbol");
3257 return false;
3258 }
3259
3260 getTargetStreamer().emitDirectiveEnd(SymbolName);
3261 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00003262 return false;
3263 }
3264
Jack Carter07c818d2013-01-25 01:31:34 +00003265 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003266 // .frame $stack_reg, frame_size_in_bytes, $return_reg
3267 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
3268 OperandMatchResultTy ResTy = ParseAnyRegister(TmpReg);
3269 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3270 reportParseError("expected stack register");
3271 return false;
3272 }
3273
3274 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3275 if (!StackRegOpnd.isGPRAsmReg()) {
3276 reportParseError(StackRegOpnd.getStartLoc(),
3277 "expected general purpose register");
3278 return false;
3279 }
3280 unsigned StackReg = StackRegOpnd.getGPR32Reg();
3281
3282 if (Parser.getTok().is(AsmToken::Comma))
3283 Parser.Lex();
3284 else {
3285 reportParseError("unexpected token, expected comma");
3286 return false;
3287 }
3288
3289 // Parse the frame size.
3290 const MCExpr *FrameSize;
3291 int64_t FrameSizeVal;
3292
3293 if (Parser.parseExpression(FrameSize)) {
3294 reportParseError("expected frame size value");
3295 return false;
3296 }
3297
3298 if (!FrameSize->EvaluateAsAbsolute(FrameSizeVal)) {
3299 reportParseError("frame size not an absolute expression");
3300 return false;
3301 }
3302
3303 if (Parser.getTok().is(AsmToken::Comma))
3304 Parser.Lex();
3305 else {
3306 reportParseError("unexpected token, expected comma");
3307 return false;
3308 }
3309
3310 // Parse the return register.
3311 TmpReg.clear();
3312 ResTy = ParseAnyRegister(TmpReg);
3313 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3314 reportParseError("expected return register");
3315 return false;
3316 }
3317
3318 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3319 if (!ReturnRegOpnd.isGPRAsmReg()) {
3320 reportParseError(ReturnRegOpnd.getStartLoc(),
3321 "expected general purpose register");
3322 return false;
3323 }
3324
3325 // If this is not the end of the statement, report an error.
3326 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3327 reportParseError("unexpected token, expected end of statement");
3328 return false;
3329 }
3330
3331 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
3332 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00003333 return false;
3334 }
3335
Jack Carter07c818d2013-01-25 01:31:34 +00003336 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00003337 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00003338 }
3339
Daniel Sandersd97a6342014-08-13 10:07:34 +00003340 if (IDVal == ".mask" || IDVal == ".fmask") {
3341 // .mask bitmask, frame_offset
3342 // bitmask: One bit for each register used.
3343 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
3344 // first register is expected to be saved.
3345 // Examples:
3346 // .mask 0x80000000, -4
3347 // .fmask 0x80000000, -4
3348 //
Jack Carterbe332172012-09-07 00:48:02 +00003349
Daniel Sandersd97a6342014-08-13 10:07:34 +00003350 // Parse the bitmask
3351 const MCExpr *BitMask;
3352 int64_t BitMaskVal;
3353
3354 if (Parser.parseExpression(BitMask)) {
3355 reportParseError("expected bitmask value");
3356 return false;
3357 }
3358
3359 if (!BitMask->EvaluateAsAbsolute(BitMaskVal)) {
3360 reportParseError("bitmask not an absolute expression");
3361 return false;
3362 }
3363
3364 if (Parser.getTok().is(AsmToken::Comma))
3365 Parser.Lex();
3366 else {
3367 reportParseError("unexpected token, expected comma");
3368 return false;
3369 }
3370
3371 // Parse the frame_offset
3372 const MCExpr *FrameOffset;
3373 int64_t FrameOffsetVal;
3374
3375 if (Parser.parseExpression(FrameOffset)) {
3376 reportParseError("expected frame offset value");
3377 return false;
3378 }
3379
3380 if (!FrameOffset->EvaluateAsAbsolute(FrameOffsetVal)) {
3381 reportParseError("frame offset not an absolute expression");
3382 return false;
3383 }
3384
3385 // If this is not the end of the statement, report an error.
3386 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3387 reportParseError("unexpected token, expected end of statement");
3388 return false;
3389 }
3390
3391 if (IDVal == ".mask")
3392 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
3393 else
3394 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00003395 return false;
3396 }
3397
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003398 if (IDVal == ".nan")
3399 return parseDirectiveNaN();
3400
Jack Carter07c818d2013-01-25 01:31:34 +00003401 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00003402 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00003403 return false;
3404 }
3405
Rafael Espindolab59fb732014-03-28 18:50:26 +00003406 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003407 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00003408 return false;
3409 }
3410
Jack Carter07c818d2013-01-25 01:31:34 +00003411 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003412 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00003413 return false;
3414 }
3415
Jack Carter0cd3c192014-01-06 23:27:31 +00003416 if (IDVal == ".option")
3417 return parseDirectiveOption();
3418
3419 if (IDVal == ".abicalls") {
3420 getTargetStreamer().emitDirectiveAbiCalls();
3421 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3422 Error(Parser.getTok().getLoc(), "unexpected token in directive");
3423 // Clear line
3424 Parser.eatToEndOfStatement();
3425 }
3426 return false;
3427 }
3428
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003429 if (IDVal == ".cpsetup")
3430 return parseDirectiveCPSetup();
3431
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003432 if (IDVal == ".module")
3433 return parseDirectiveModule();
3434
Rafael Espindola870c4e92012-01-11 03:56:41 +00003435 return true;
3436}
3437
Rafael Espindola870c4e92012-01-11 03:56:41 +00003438extern "C" void LLVMInitializeMipsAsmParser() {
3439 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
3440 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
3441 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
3442 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
3443}
Jack Carterb4dbc172012-09-05 23:34:03 +00003444
3445#define GET_REGISTER_MATCHER
3446#define GET_MATCHER_IMPLEMENTATION
3447#include "MipsGenAsmMatcher.inc"