blob: 0a9b36fba4a014c2277063a19e71ca80fe887316 [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"
Toma Tabacu9db22db2014-09-09 10:15:38 +000016#include "llvm/ADT/SmallVector.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000017#include "llvm/MC/MCContext.h"
18#include "llvm/MC/MCExpr.h"
19#include "llvm/MC/MCInst.h"
Daniel Sandersa771fef2014-03-24 14:05:39 +000020#include "llvm/MC/MCInstBuilder.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000021#include "llvm/MC/MCParser/MCAsmLexer.h"
22#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000023#include "llvm/MC/MCStreamer.h"
24#include "llvm/MC/MCSubtargetInfo.h"
25#include "llvm/MC/MCSymbol.h"
Akira Hatanaka7605630c2012-08-17 20:16:42 +000026#include "llvm/MC/MCTargetAsmParser.h"
Daniel Sandersb50ccf82014-04-01 10:35:28 +000027#include "llvm/Support/Debug.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000028#include "llvm/Support/MathExtras.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000029#include "llvm/Support/TargetRegistry.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000030#include <memory>
Rafael Espindola870c4e92012-01-11 03:56:41 +000031
32using namespace llvm;
33
Chandler Carruthe96dd892014-04-21 22:55:11 +000034#define DEBUG_TYPE "mips-asm-parser"
35
Joey Gouly0e76fa72013-09-12 10:28:05 +000036namespace llvm {
37class MCInstrInfo;
38}
39
Rafael Espindola870c4e92012-01-11 03:56:41 +000040namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000041class MipsAssemblerOptions {
42public:
Toma Tabacu9db22db2014-09-09 10:15:38 +000043 MipsAssemblerOptions(uint64_t Features_) :
44 ATReg(1), Reorder(true), Macro(true), Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000045
Toma Tabacu9db22db2014-09-09 10:15:38 +000046 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
47 ATReg = Opts->getATRegNum();
48 Reorder = Opts->isReorder();
49 Macro = Opts->isMacro();
50 Features = Opts->getFeatures();
51 }
52
53 unsigned getATRegNum() const { return ATReg; }
Jack Carter0b744b32012-10-04 02:29:46 +000054 bool setATReg(unsigned Reg);
55
Toma Tabacu9db22db2014-09-09 10:15:38 +000056 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000057 void setReorder() { Reorder = true; }
58 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000059
Toma Tabacu9db22db2014-09-09 10:15:38 +000060 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000061 void setMacro() { Macro = true; }
62 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000063
Toma Tabacu9db22db2014-09-09 10:15:38 +000064 uint64_t getFeatures() const { return Features; }
65 void setFeatures(uint64_t Features_) { Features = Features_; }
66
Daniel Sandersf0df2212014-08-04 12:20:00 +000067 // Set of features that are either architecture features or referenced
68 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
69 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
70 // The reason we need this mask is explained in the selectArch function.
71 // FIXME: Ideally we would like TableGen to generate this information.
72 static const uint64_t AllArchRelatedMask =
73 Mips::FeatureMips1 | Mips::FeatureMips2 | Mips::FeatureMips3 |
74 Mips::FeatureMips3_32 | Mips::FeatureMips3_32r2 | Mips::FeatureMips4 |
75 Mips::FeatureMips4_32 | Mips::FeatureMips4_32r2 | Mips::FeatureMips5 |
76 Mips::FeatureMips5_32r2 | Mips::FeatureMips32 | Mips::FeatureMips32r2 |
77 Mips::FeatureMips32r6 | Mips::FeatureMips64 | Mips::FeatureMips64r2 |
78 Mips::FeatureMips64r6 | Mips::FeatureCnMips | Mips::FeatureFP64Bit |
79 Mips::FeatureGP64Bit | Mips::FeatureNaN2008;
80
Jack Carter0b744b32012-10-04 02:29:46 +000081private:
Toma Tabacu3c24b042014-09-05 15:43:21 +000082 unsigned ATReg;
83 bool Reorder;
84 bool Macro;
Toma Tabacu9db22db2014-09-09 10:15:38 +000085 uint64_t Features;
Jack Carter0b744b32012-10-04 02:29:46 +000086};
87}
88
89namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +000090class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +000091 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola4a1a3602014-01-14 01:21:46 +000092 MCTargetStreamer &TS = *Parser.getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +000093 return static_cast<MipsTargetStreamer &>(TS);
94 }
95
Jack Carterb4dbc172012-09-05 23:34:03 +000096 MCSubtargetInfo &STI;
97 MCAsmParser &Parser;
Toma Tabacu9db22db2014-09-09 10:15:38 +000098 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +000099 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
100 // nullptr, which indicates that no function is currently
101 // selected. This usually happens after an '.end func'
102 // directive.
Jack Carter0b744b32012-10-04 02:29:46 +0000103
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000104#define GET_ASSEMBLER_HEADER
105#include "MipsGenAsmMatcher.inc"
106
Matheus Almeida595fcab2014-06-11 15:05:56 +0000107 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
108
Chad Rosier49963552012-10-13 00:26:04 +0000109 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000110 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000111 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000112 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000113
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000114 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000115 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000116
Toma Tabacu13964452014-09-04 13:23:44 +0000117 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000118
Toma Tabacu13964452014-09-04 13:23:44 +0000119 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000120
David Blaikie960ea3f2014-06-08 16:18:35 +0000121 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
122 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000123
Craig Topper56c590a2014-04-29 07:58:02 +0000124 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000125
David Blaikie960ea3f2014-06-08 16:18:35 +0000126 MipsAsmParser::OperandMatchResultTy parseMemOperand(OperandVector &Operands);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000127
128 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000129 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000130 StringRef Identifier, SMLoc S);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000131
Jack Carter873c7242013-01-12 01:03:14 +0000132 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000133 matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S);
Jack Carter873c7242013-01-12 01:03:14 +0000134
Toma Tabacu13964452014-09-04 13:23:44 +0000135 MipsAsmParser::OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
Jack Carter873c7242013-01-12 01:03:14 +0000136
Toma Tabacu13964452014-09-04 13:23:44 +0000137 MipsAsmParser::OperandMatchResultTy parseImm(OperandVector &Operands);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000138
Toma Tabacu13964452014-09-04 13:23:44 +0000139 MipsAsmParser::OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
Vladimir Medic2b953d02013-10-01 09:48:56 +0000140
David Blaikie960ea3f2014-06-08 16:18:35 +0000141 MipsAsmParser::OperandMatchResultTy parseInvNum(OperandVector &Operands);
Matheus Almeida779c5932013-11-18 12:32:49 +0000142
Toma Tabacu13964452014-09-04 13:23:44 +0000143 MipsAsmParser::OperandMatchResultTy parseLSAImm(OperandVector &Operands);
Jack Carterd76b2372013-03-21 21:44:16 +0000144
David Blaikie960ea3f2014-06-08 16:18:35 +0000145 bool searchSymbolAlias(OperandVector &Operands);
146
Toma Tabacu13964452014-09-04 13:23:44 +0000147 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000148
Jack Carter30a59822012-10-04 04:03:53 +0000149 bool needsExpansion(MCInst &Inst);
150
Matheus Almeida3813d572014-06-19 14:39:14 +0000151 // Expands assembly pseudo instructions.
152 // Returns false on success, true otherwise.
153 bool expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000154 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000155
156 bool expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000157 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000158
159 bool expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000160 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000161
162 bool expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000163 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000164
Toma Tabacu0d64b202014-08-14 10:29:17 +0000165 void expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
166 SmallVectorImpl<MCInst> &Instructions);
167
Jack Carter9e65aa32013-03-22 00:05:30 +0000168 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000169 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
170 bool isImmOpnd);
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000171 bool reportParseError(Twine ErrorMsg);
172 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000173
Jack Carterb5cf5902013-04-17 00:18:04 +0000174 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000175 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000176
Vladimir Medic4c299852013-11-06 11:27:05 +0000177 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000178
179 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu85618b32014-08-19 14:22:52 +0000180 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000181 bool parseSetFeature(uint64_t Feature);
Matheus Almeida525bc4f2014-04-30 11:28:42 +0000182 bool parseDirectiveCPLoad(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000183 bool parseDirectiveCPSetup();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000184 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000185 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000186 bool parseDirectiveOption();
Jack Carter0b744b32012-10-04 02:29:46 +0000187
188 bool parseSetAtDirective();
189 bool parseSetNoAtDirective();
190 bool parseSetMacroDirective();
191 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000192 bool parseSetMsaDirective();
193 bool parseSetNoMsaDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000194 bool parseSetReorderDirective();
195 bool parseSetNoReorderDirective();
Jack Carter39536722014-01-22 23:08:42 +0000196 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000197 bool parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000198 bool parseSetPopDirective();
199 bool parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000200
Jack Carterd76b2372013-03-21 21:44:16 +0000201 bool parseSetAssignment();
202
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000203 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000204 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000205 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000206 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000207 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000208 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
209 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000210
Jack Carterdc1e35d2012-09-06 20:00:02 +0000211 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000212
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000213 bool eatComma(StringRef ErrorStr);
214
Jack Carter1ac53222013-02-20 23:11:17 +0000215 int matchCPURegisterName(StringRef Symbol);
216
Jack Carter873c7242013-01-12 01:03:14 +0000217 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000218
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000219 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000220
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000221 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000222
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000223 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000224
Jack Carter5dc8ac92013-09-25 23:50:44 +0000225 int matchMSA128RegisterName(StringRef Name);
226
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000227 int matchMSA128CtrlRegisterName(StringRef Name);
228
Jack Carterd0bd6422013-04-18 00:41:53 +0000229 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000230
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000231 unsigned getGPR(int RegNo);
232
Matheus Almeida7de68e72014-06-18 14:46:05 +0000233 int getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000234
235 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000236 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000237
238 // Helper function that checks if the value of a vector index is within the
239 // boundaries of accepted values for each RegisterKind
240 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
241 bool validateMSAIndex(int Val, int RegKind);
242
Daniel Sandersf0df2212014-08-04 12:20:00 +0000243 // Selects a new architecture by updating the FeatureBits with the necessary
244 // info including implied dependencies.
245 // Internally, it clears all the feature bits related to *any* architecture
246 // and selects the new one using the ToggleFeature functionality of the
247 // MCSubtargetInfo object that handles implied dependencies. The reason we
248 // clear all the arch related bits manually is because ToggleFeature only
249 // clears the features that imply the feature being cleared and not the
250 // features implied by the feature being cleared. This is easier to see
251 // with an example:
252 // --------------------------------------------------
253 // | Feature | Implies |
254 // | -------------------------------------------------|
255 // | FeatureMips1 | None |
256 // | FeatureMips2 | FeatureMips1 |
257 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
258 // | FeatureMips4 | FeatureMips3 |
259 // | ... | |
260 // --------------------------------------------------
261 //
262 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
263 // FeatureMipsGP64 | FeatureMips1)
264 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
265 void selectArch(StringRef ArchFeature) {
266 uint64_t FeatureBits = STI.getFeatureBits();
267 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
268 STI.setFeatureBits(FeatureBits);
269 setAvailableFeatures(
270 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000271 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000272 }
273
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000274 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Vladimir Medic615b26e2014-03-04 09:54:09 +0000275 if (!(STI.getFeatureBits() & Feature)) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000276 setAvailableFeatures(
277 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000278 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000279 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000280 }
281
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000282 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Vladimir Medic615b26e2014-03-04 09:54:09 +0000283 if (STI.getFeatureBits() & Feature) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000284 setAvailableFeatures(
285 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000286 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000287 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000288 }
289
Rafael Espindola870c4e92012-01-11 03:56:41 +0000290public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000291 enum MipsMatchResultTy {
292 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
293#define GET_OPERAND_DIAGNOSTIC_TYPES
294#include "MipsGenAsmMatcher.inc"
295#undef GET_OPERAND_DIAGNOSTIC_TYPES
296
297 };
298
Joey Gouly0e76fa72013-09-12 10:28:05 +0000299 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000300 const MCInstrInfo &MII, const MCTargetOptions &Options)
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000301 : MCTargetAsmParser(), STI(sti), Parser(parser) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000302 // Initialize the set of available features.
303 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000304
305 // Remember the initial assembler options. The user can not modify these.
306 MipsAssemblerOptions *TmpAOPtr =
307 new MipsAssemblerOptions(getAvailableFeatures());
308 AssemblerOptions.push_back(std::unique_ptr<MipsAssemblerOptions>(TmpAOPtr));
309
310 // Create an assembler options environment for the user to modify.
311 TmpAOPtr = new MipsAssemblerOptions(getAvailableFeatures());
312 AssemblerOptions.push_back(std::unique_ptr<MipsAssemblerOptions>(TmpAOPtr));
313 TmpAOPtr = nullptr;
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000314
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000315 getTargetStreamer().updateABIInfo(*this);
316
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000317 // Assert exactly one ABI was chosen.
318 assert((((STI.getFeatureBits() & Mips::FeatureO32) != 0) +
319 ((STI.getFeatureBits() & Mips::FeatureEABI) != 0) +
320 ((STI.getFeatureBits() & Mips::FeatureN32) != 0) +
321 ((STI.getFeatureBits() & Mips::FeatureN64) != 0)) == 1);
Daniel Sanders7e527422014-07-10 13:38:23 +0000322
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000323 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000324 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000325
326 CurrentFn = nullptr;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000327 }
328
Jack Carterb4dbc172012-09-05 23:34:03 +0000329 MCAsmParser &getParser() const { return Parser; }
330 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000331
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000332 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
333 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
334
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000335 bool isGP64bit() const { return STI.getFeatureBits() & Mips::FeatureGP64Bit; }
336 bool isFP64bit() const { return STI.getFeatureBits() & Mips::FeatureFP64Bit; }
337 bool isABI_N32() const { return STI.getFeatureBits() & Mips::FeatureN32; }
338 bool isABI_N64() const { return STI.getFeatureBits() & Mips::FeatureN64; }
339 bool isABI_O32() const { return STI.getFeatureBits() & Mips::FeatureO32; }
Daniel Sandersa6e125f2014-07-15 15:31:39 +0000340 bool isABI_FPXX() const { return STI.getFeatureBits() & Mips::FeatureFPXX; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000341
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000342 bool useOddSPReg() const {
Daniel Sanders7e527422014-07-10 13:38:23 +0000343 return !(STI.getFeatureBits() & Mips::FeatureNoOddSPReg);
344 }
345
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000346 bool inMicroMipsMode() const {
347 return STI.getFeatureBits() & Mips::FeatureMicroMips;
348 }
349 bool hasMips1() const { return STI.getFeatureBits() & Mips::FeatureMips1; }
350 bool hasMips2() const { return STI.getFeatureBits() & Mips::FeatureMips2; }
351 bool hasMips3() const { return STI.getFeatureBits() & Mips::FeatureMips3; }
352 bool hasMips4() const { return STI.getFeatureBits() & Mips::FeatureMips4; }
353 bool hasMips5() const { return STI.getFeatureBits() & Mips::FeatureMips5; }
354 bool hasMips32() const {
355 return (STI.getFeatureBits() & Mips::FeatureMips32);
356 }
357 bool hasMips64() const {
358 return (STI.getFeatureBits() & Mips::FeatureMips64);
359 }
360 bool hasMips32r2() const {
361 return (STI.getFeatureBits() & Mips::FeatureMips32r2);
362 }
363 bool hasMips64r2() const {
364 return (STI.getFeatureBits() & Mips::FeatureMips64r2);
365 }
366 bool hasMips32r6() const {
367 return (STI.getFeatureBits() & Mips::FeatureMips32r6);
368 }
369 bool hasMips64r6() const {
370 return (STI.getFeatureBits() & Mips::FeatureMips64r6);
371 }
372 bool hasDSP() const { return (STI.getFeatureBits() & Mips::FeatureDSP); }
373 bool hasDSPR2() const { return (STI.getFeatureBits() & Mips::FeatureDSPR2); }
374 bool hasMSA() const { return (STI.getFeatureBits() & Mips::FeatureMSA); }
375
376 bool inMips16Mode() const {
377 return STI.getFeatureBits() & Mips::FeatureMips16;
378 }
379 // TODO: see how can we get this info.
Eric Christopher7394e232014-07-18 00:08:50 +0000380 bool abiUsesSoftFloat() const { return false; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000381
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000382 /// Warn if RegNo is the current assembler temporary.
Toma Tabacu13964452014-09-04 13:23:44 +0000383 void warnIfAssemblerTemporary(int RegNo, SMLoc Loc);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000384};
385}
386
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000387namespace {
388
389/// MipsOperand - Instances of this class represent a parsed Mips machine
390/// instruction.
391class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000392public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000393 /// Broad categories of register classes
394 /// The exact class is finalized by the render method.
395 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000396 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000397 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000398 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000399 RegKind_FCC = 4, /// FCC
400 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
401 RegKind_MSACtrl = 16, /// MSA control registers
402 RegKind_COP2 = 32, /// COP2
403 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
404 /// context).
405 RegKind_CCR = 128, /// CCR
406 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000407 RegKind_COP3 = 512, /// COP3
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000408
409 /// Potentially any (e.g. $1)
410 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
411 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000412 RegKind_CCR | RegKind_HWRegs | RegKind_COP3
Jack Carter873c7242013-01-12 01:03:14 +0000413 };
414
415private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000416 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000417 k_Immediate, /// An immediate (possibly involving symbol references)
418 k_Memory, /// Base + Offset Memory Address
419 k_PhysRegister, /// A physical register from the Mips namespace
420 k_RegisterIndex, /// A register index in one or more RegKind.
421 k_Token /// A simple token
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000422 } Kind;
423
David Blaikie960ea3f2014-06-08 16:18:35 +0000424public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000425 MipsOperand(KindTy K, MipsAsmParser &Parser)
426 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
427
David Blaikie960ea3f2014-06-08 16:18:35 +0000428private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000429 /// For diagnostics, and checking the assembler temporary
430 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000431
Eric Christopher8996c5d2013-03-15 00:42:55 +0000432 struct Token {
433 const char *Data;
434 unsigned Length;
435 };
436
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000437 struct PhysRegOp {
438 unsigned Num; /// Register Number
439 };
440
441 struct RegIdxOp {
442 unsigned Index; /// Index into the register class
443 RegKind Kind; /// Bitfield of the kinds it could possibly be
444 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000445 };
446
447 struct ImmOp {
448 const MCExpr *Val;
449 };
450
451 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000452 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000453 const MCExpr *Off;
454 };
455
Jack Carterb4dbc172012-09-05 23:34:03 +0000456 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000457 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000458 struct PhysRegOp PhysReg;
459 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000460 struct ImmOp Imm;
461 struct MemOp Mem;
Jack Carterb4dbc172012-09-05 23:34:03 +0000462 };
463
464 SMLoc StartLoc, EndLoc;
465
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000466 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000467 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
468 const MCRegisterInfo *RegInfo,
469 SMLoc S, SMLoc E,
470 MipsAsmParser &Parser) {
471 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000472 Op->RegIdx.Index = Index;
473 Op->RegIdx.RegInfo = RegInfo;
474 Op->RegIdx.Kind = RegKind;
475 Op->StartLoc = S;
476 Op->EndLoc = E;
477 return Op;
478 }
479
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000480public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000481 /// Coerce the register to GPR32 and return the real register for the current
482 /// target.
483 unsigned getGPR32Reg() const {
484 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacu13964452014-09-04 13:23:44 +0000485 AsmParser.warnIfAssemblerTemporary(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000486 unsigned ClassID = Mips::GPR32RegClassID;
487 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000488 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000489
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000490 /// Coerce the register to GPR64 and return the real register for the current
491 /// target.
492 unsigned getGPR64Reg() const {
493 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
494 unsigned ClassID = Mips::GPR64RegClassID;
495 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000496 }
497
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000498private:
499 /// Coerce the register to AFGR64 and return the real register for the current
500 /// target.
501 unsigned getAFGR64Reg() const {
502 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
503 if (RegIdx.Index % 2 != 0)
504 AsmParser.Warning(StartLoc, "Float register should be even.");
505 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
506 .getRegister(RegIdx.Index / 2);
507 }
508
509 /// Coerce the register to FGR64 and return the real register for the current
510 /// target.
511 unsigned getFGR64Reg() const {
512 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
513 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
514 .getRegister(RegIdx.Index);
515 }
516
517 /// Coerce the register to FGR32 and return the real register for the current
518 /// target.
519 unsigned getFGR32Reg() const {
520 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
521 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
522 .getRegister(RegIdx.Index);
523 }
524
525 /// Coerce the register to FGRH32 and return the real register for the current
526 /// target.
527 unsigned getFGRH32Reg() const {
528 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
529 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
530 .getRegister(RegIdx.Index);
531 }
532
533 /// Coerce the register to FCC and return the real register for the current
534 /// target.
535 unsigned getFCCReg() const {
536 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
537 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
538 .getRegister(RegIdx.Index);
539 }
540
541 /// Coerce the register to MSA128 and return the real register for the current
542 /// target.
543 unsigned getMSA128Reg() const {
544 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
545 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
546 // identical
547 unsigned ClassID = Mips::MSA128BRegClassID;
548 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
549 }
550
551 /// Coerce the register to MSACtrl and return the real register for the
552 /// current target.
553 unsigned getMSACtrlReg() const {
554 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
555 unsigned ClassID = Mips::MSACtrlRegClassID;
556 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
557 }
558
559 /// Coerce the register to COP2 and return the real register for the
560 /// current target.
561 unsigned getCOP2Reg() const {
562 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
563 unsigned ClassID = Mips::COP2RegClassID;
564 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
565 }
566
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000567 /// Coerce the register to COP3 and return the real register for the
568 /// current target.
569 unsigned getCOP3Reg() const {
570 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
571 unsigned ClassID = Mips::COP3RegClassID;
572 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
573 }
574
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000575 /// Coerce the register to ACC64DSP and return the real register for the
576 /// current target.
577 unsigned getACC64DSPReg() const {
578 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
579 unsigned ClassID = Mips::ACC64DSPRegClassID;
580 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
581 }
582
583 /// Coerce the register to HI32DSP and return the real register for the
584 /// current target.
585 unsigned getHI32DSPReg() const {
586 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
587 unsigned ClassID = Mips::HI32DSPRegClassID;
588 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
589 }
590
591 /// Coerce the register to LO32DSP and return the real register for the
592 /// current target.
593 unsigned getLO32DSPReg() const {
594 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
595 unsigned ClassID = Mips::LO32DSPRegClassID;
596 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
597 }
598
599 /// Coerce the register to CCR and return the real register for the
600 /// current target.
601 unsigned getCCRReg() const {
602 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
603 unsigned ClassID = Mips::CCRRegClassID;
604 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
605 }
606
607 /// Coerce the register to HWRegs and return the real register for the
608 /// current target.
609 unsigned getHWRegsReg() const {
610 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
611 unsigned ClassID = Mips::HWRegsRegClassID;
612 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
613 }
614
615public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000616 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000617 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000618 if (!Expr)
Jack Carterb4dbc172012-09-05 23:34:03 +0000619 Inst.addOperand(MCOperand::CreateImm(0));
620 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
621 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
622 else
623 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000624 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000625
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000626 void addRegOperands(MCInst &Inst, unsigned N) const {
627 llvm_unreachable("Use a custom parser instead");
628 }
629
Daniel Sanders21bce302014-04-01 12:35:23 +0000630 /// Render the operand to an MCInst as a GPR32
631 /// Asserts if the wrong number of operands are requested, or the operand
632 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000633 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
634 assert(N == 1 && "Invalid number of operands!");
635 Inst.addOperand(MCOperand::CreateReg(getGPR32Reg()));
636 }
637
Daniel Sanders21bce302014-04-01 12:35:23 +0000638 /// Render the operand to an MCInst as a GPR64
639 /// Asserts if the wrong number of operands are requested, or the operand
640 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000641 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
642 assert(N == 1 && "Invalid number of operands!");
643 Inst.addOperand(MCOperand::CreateReg(getGPR64Reg()));
644 }
645
646 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
647 assert(N == 1 && "Invalid number of operands!");
648 Inst.addOperand(MCOperand::CreateReg(getAFGR64Reg()));
649 }
650
651 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
652 assert(N == 1 && "Invalid number of operands!");
653 Inst.addOperand(MCOperand::CreateReg(getFGR64Reg()));
654 }
655
656 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
657 assert(N == 1 && "Invalid number of operands!");
658 Inst.addOperand(MCOperand::CreateReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000659 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000660 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000661 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
662 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000663 }
664
665 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
666 assert(N == 1 && "Invalid number of operands!");
667 Inst.addOperand(MCOperand::CreateReg(getFGRH32Reg()));
668 }
669
670 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
671 assert(N == 1 && "Invalid number of operands!");
672 Inst.addOperand(MCOperand::CreateReg(getFCCReg()));
673 }
674
675 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
676 assert(N == 1 && "Invalid number of operands!");
677 Inst.addOperand(MCOperand::CreateReg(getMSA128Reg()));
678 }
679
680 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
681 assert(N == 1 && "Invalid number of operands!");
682 Inst.addOperand(MCOperand::CreateReg(getMSACtrlReg()));
683 }
684
685 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
686 assert(N == 1 && "Invalid number of operands!");
687 Inst.addOperand(MCOperand::CreateReg(getCOP2Reg()));
688 }
689
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000690 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
691 assert(N == 1 && "Invalid number of operands!");
692 Inst.addOperand(MCOperand::CreateReg(getCOP3Reg()));
693 }
694
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000695 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
696 assert(N == 1 && "Invalid number of operands!");
697 Inst.addOperand(MCOperand::CreateReg(getACC64DSPReg()));
698 }
699
700 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
701 assert(N == 1 && "Invalid number of operands!");
702 Inst.addOperand(MCOperand::CreateReg(getHI32DSPReg()));
703 }
704
705 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
706 assert(N == 1 && "Invalid number of operands!");
707 Inst.addOperand(MCOperand::CreateReg(getLO32DSPReg()));
708 }
709
710 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
711 assert(N == 1 && "Invalid number of operands!");
712 Inst.addOperand(MCOperand::CreateReg(getCCRReg()));
713 }
714
715 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
716 assert(N == 1 && "Invalid number of operands!");
717 Inst.addOperand(MCOperand::CreateReg(getHWRegsReg()));
718 }
719
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000720 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000721 assert(N == 1 && "Invalid number of operands!");
722 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000723 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000724 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000725
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000726 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000727 assert(N == 2 && "Invalid number of operands!");
728
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000729 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000730
731 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000732 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000733 }
734
Craig Topper56c590a2014-04-29 07:58:02 +0000735 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000736 // As a special case until we sort out the definition of div/divu, pretend
737 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
738 if (isGPRAsmReg() && RegIdx.Index == 0)
739 return true;
740
741 return Kind == k_PhysRegister;
742 }
743 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000744 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000745 bool isConstantImm() const {
746 return isImm() && dyn_cast<MCConstantExpr>(getImm());
747 }
Craig Topper56c590a2014-04-29 07:58:02 +0000748 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000749 // Note: It's not possible to pretend that other operand kinds are tokens.
750 // The matcher emitter checks tokens first.
751 return Kind == k_Token;
752 }
Craig Topper56c590a2014-04-29 07:58:02 +0000753 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000754 bool isConstantMemOff() const {
755 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
756 }
757 template <unsigned Bits> bool isMemWithSimmOffset() const {
758 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff());
759 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000760 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000761 bool isLSAImm() const {
762 if (!isConstantImm())
763 return false;
764 int64_t Val = getConstantImm();
765 return 1 <= Val && Val <= 4;
766 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000767
768 StringRef getToken() const {
769 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000770 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000771 }
772
Craig Topper56c590a2014-04-29 07:58:02 +0000773 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000774 // As a special case until we sort out the definition of div/divu, pretend
775 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
776 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
777 RegIdx.Kind & RegKind_GPR)
778 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000779
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000780 assert(Kind == k_PhysRegister && "Invalid access!");
781 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +0000782 }
783
Jack Carterb4dbc172012-09-05 23:34:03 +0000784 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000785 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000786 return Imm.Val;
787 }
788
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000789 int64_t getConstantImm() const {
790 const MCExpr *Val = getImm();
791 return static_cast<const MCConstantExpr *>(Val)->getValue();
792 }
793
794 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000795 assert((Kind == k_Memory) && "Invalid access!");
796 return Mem.Base;
797 }
798
799 const MCExpr *getMemOff() const {
800 assert((Kind == k_Memory) && "Invalid access!");
801 return Mem.Off;
802 }
803
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000804 int64_t getConstantMemOff() const {
805 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
806 }
807
David Blaikie960ea3f2014-06-08 16:18:35 +0000808 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
809 MipsAsmParser &Parser) {
810 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000811 Op->Tok.Data = Str.data();
812 Op->Tok.Length = Str.size();
813 Op->StartLoc = S;
814 Op->EndLoc = S;
815 return Op;
816 }
817
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000818 /// Create a numeric register (e.g. $1). The exact register remains
819 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +0000820 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000821 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +0000822 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +0000823 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000824 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000825 }
826
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000827 /// Create a register that is definitely a GPR.
828 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +0000829 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000830 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000831 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000832 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000833 }
834
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000835 /// Create a register that is definitely a FGR.
836 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000837 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000838 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000839 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000840 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
841 }
842
843 /// Create a register that is definitely an FCC.
844 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000845 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000846 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000847 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000848 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
849 }
850
851 /// Create a register that is definitely an ACC.
852 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000853 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000854 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000855 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000856 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
857 }
858
859 /// Create a register that is definitely an MSA128.
860 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000861 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000862 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +0000863 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000864 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
865 }
866
867 /// Create a register that is definitely an MSACtrl.
868 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +0000869 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000870 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +0000871 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000872 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
873 }
874
David Blaikie960ea3f2014-06-08 16:18:35 +0000875 static std::unique_ptr<MipsOperand>
876 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
877 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000878 Op->Imm.Val = Val;
879 Op->StartLoc = S;
880 Op->EndLoc = E;
881 return Op;
882 }
883
David Blaikie960ea3f2014-06-08 16:18:35 +0000884 static std::unique_ptr<MipsOperand>
885 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
886 SMLoc E, MipsAsmParser &Parser) {
887 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
888 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +0000889 Op->Mem.Off = Off;
890 Op->StartLoc = S;
891 Op->EndLoc = E;
892 return Op;
893 }
894
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000895 bool isGPRAsmReg() const {
896 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000897 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000898 bool isFGRAsmReg() const {
899 // AFGR64 is $0-$15 but we handle this in getAFGR64()
900 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000901 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000902 bool isHWRegsAsmReg() const {
903 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000904 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000905 bool isCCRAsmReg() const {
906 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000907 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000908 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000909 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
910 return false;
911 if (!AsmParser.hasEightFccRegisters())
912 return RegIdx.Index == 0;
913 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +0000914 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000915 bool isACCAsmReg() const {
916 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +0000917 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000918 bool isCOP2AsmReg() const {
919 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +0000920 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000921 bool isCOP3AsmReg() const {
922 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
923 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000924 bool isMSA128AsmReg() const {
925 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +0000926 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000927 bool isMSACtrlAsmReg() const {
928 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000929 }
930
Jack Carterb4dbc172012-09-05 23:34:03 +0000931 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +0000932 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +0000933 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +0000934 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +0000935
NAKAMURA Takumie1f35832014-04-15 14:13:21 +0000936 virtual ~MipsOperand() {
937 switch (Kind) {
938 case k_Immediate:
939 break;
940 case k_Memory:
941 delete Mem.Base;
942 break;
943 case k_PhysRegister:
944 case k_RegisterIndex:
945 case k_Token:
946 break;
947 }
948 }
949
Craig Topper56c590a2014-04-29 07:58:02 +0000950 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000951 switch (Kind) {
952 case k_Immediate:
953 OS << "Imm<";
954 Imm.Val->print(OS);
955 OS << ">";
956 break;
957 case k_Memory:
958 OS << "Mem<";
959 Mem.Base->print(OS);
960 OS << ", ";
961 Mem.Off->print(OS);
962 OS << ">";
963 break;
964 case k_PhysRegister:
965 OS << "PhysReg<" << PhysReg.Num << ">";
966 break;
967 case k_RegisterIndex:
968 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
969 break;
970 case k_Token:
971 OS << Tok.Data;
972 break;
973 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000974 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000975}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +0000976} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000977
Jack Carter9e65aa32013-03-22 00:05:30 +0000978namespace llvm {
979extern const MCInstrDesc MipsInsts[];
980}
981static const MCInstrDesc &getInstDesc(unsigned Opcode) {
982 return MipsInsts[Opcode];
983}
984
985bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +0000986 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000987 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +0000988
Jack Carter9e65aa32013-03-22 00:05:30 +0000989 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000990
991 if (MCID.isBranch() || MCID.isCall()) {
992 const unsigned Opcode = Inst.getOpcode();
993 MCOperand Offset;
994
995 switch (Opcode) {
996 default:
997 break;
998 case Mips::BEQ:
999 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001000 case Mips::BEQ_MM:
1001 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001002 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001003 Offset = Inst.getOperand(2);
1004 if (!Offset.isImm())
1005 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001006 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001007 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001008 if (OffsetToAlignment(Offset.getImm(),
1009 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001010 return Error(IDLoc, "branch to misaligned address");
1011 break;
1012 case Mips::BGEZ:
1013 case Mips::BGTZ:
1014 case Mips::BLEZ:
1015 case Mips::BLTZ:
1016 case Mips::BGEZAL:
1017 case Mips::BLTZAL:
1018 case Mips::BC1F:
1019 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001020 case Mips::BGEZ_MM:
1021 case Mips::BGTZ_MM:
1022 case Mips::BLEZ_MM:
1023 case Mips::BLTZ_MM:
1024 case Mips::BGEZAL_MM:
1025 case Mips::BLTZAL_MM:
1026 case Mips::BC1F_MM:
1027 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001028 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001029 Offset = Inst.getOperand(1);
1030 if (!Offset.isImm())
1031 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001032 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001033 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001034 if (OffsetToAlignment(Offset.getImm(),
1035 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001036 return Error(IDLoc, "branch to misaligned address");
1037 break;
1038 }
1039 }
1040
Daniel Sandersa84989a2014-06-16 13:25:35 +00001041 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1042 // We still accept it but it is a normal nop.
1043 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1044 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1045 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1046 "nop instruction");
1047 }
1048
Toma Tabacu9db22db2014-09-09 10:15:38 +00001049 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
Jack Carterc15c1d22013-04-25 23:31:35 +00001050 // If this instruction has a delay slot and .set reorder is active,
1051 // emit a NOP after it.
1052 Instructions.push_back(Inst);
1053 MCInst NopInst;
1054 NopInst.setOpcode(Mips::SLL);
1055 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1056 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1057 NopInst.addOperand(MCOperand::CreateImm(0));
1058 Instructions.push_back(NopInst);
1059 return false;
1060 }
1061
Jack Carter9e65aa32013-03-22 00:05:30 +00001062 if (MCID.mayLoad() || MCID.mayStore()) {
1063 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001064 // reference or immediate we may have to expand instructions.
1065 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001066 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001067 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1068 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001069 MCOperand &Op = Inst.getOperand(i);
1070 if (Op.isImm()) {
1071 int MemOffset = Op.getImm();
1072 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001073 // Offset can't exceed 16bit value.
1074 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001075 return false;
1076 }
1077 } else if (Op.isExpr()) {
1078 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001079 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001080 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001081 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001082 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001083 // Expand symbol.
1084 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001085 return false;
1086 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001087 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001088 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001089 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001090 }
1091 }
1092 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001093 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001094 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001095
1096 if (needsExpansion(Inst))
Matheus Almeida3813d572014-06-19 14:39:14 +00001097 return expandInstruction(Inst, IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +00001098 else
1099 Instructions.push_back(Inst);
1100
1101 return false;
1102}
1103
Jack Carter30a59822012-10-04 04:03:53 +00001104bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1105
Jack Carterd0bd6422013-04-18 00:41:53 +00001106 switch (Inst.getOpcode()) {
1107 case Mips::LoadImm32Reg:
1108 case Mips::LoadAddr32Imm:
1109 case Mips::LoadAddr32Reg:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001110 case Mips::LoadImm64Reg:
Jack Carterd0bd6422013-04-18 00:41:53 +00001111 return true;
1112 default:
1113 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001114 }
1115}
Jack Carter92995f12012-10-06 00:53:28 +00001116
Matheus Almeida3813d572014-06-19 14:39:14 +00001117bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001118 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001119 switch (Inst.getOpcode()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001120 default:
1121 assert(0 && "unimplemented expansion");
Matheus Almeida3813d572014-06-19 14:39:14 +00001122 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001123 case Mips::LoadImm32Reg:
1124 return expandLoadImm(Inst, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001125 case Mips::LoadImm64Reg:
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001126 if (!isGP64bit()) {
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001127 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1128 return true;
1129 }
1130 return expandLoadImm(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001131 case Mips::LoadAddr32Imm:
1132 return expandLoadAddressImm(Inst, IDLoc, Instructions);
1133 case Mips::LoadAddr32Reg:
1134 return expandLoadAddressReg(Inst, IDLoc, Instructions);
1135 }
Jack Carter30a59822012-10-04 04:03:53 +00001136}
Jack Carter92995f12012-10-06 00:53:28 +00001137
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001138namespace {
Toma Tabacu0d64b202014-08-14 10:29:17 +00001139template <bool PerformShift>
1140void createShiftOr(MCOperand Operand, unsigned RegNo, SMLoc IDLoc,
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001141 SmallVectorImpl<MCInst> &Instructions) {
1142 MCInst tmpInst;
1143 if (PerformShift) {
1144 tmpInst.setOpcode(Mips::DSLL);
1145 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1146 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1147 tmpInst.addOperand(MCOperand::CreateImm(16));
1148 tmpInst.setLoc(IDLoc);
1149 Instructions.push_back(tmpInst);
1150 tmpInst.clear();
1151 }
1152 tmpInst.setOpcode(Mips::ORi);
1153 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1154 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001155 tmpInst.addOperand(Operand);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001156 tmpInst.setLoc(IDLoc);
1157 Instructions.push_back(tmpInst);
1158}
Toma Tabacu0d64b202014-08-14 10:29:17 +00001159
1160template <int Shift, bool PerformShift>
1161void createShiftOr(int64_t Value, unsigned RegNo, SMLoc IDLoc,
1162 SmallVectorImpl<MCInst> &Instructions) {
1163 createShiftOr<PerformShift>(
1164 MCOperand::CreateImm(((Value & (0xffffLL << Shift)) >> Shift)), RegNo,
1165 IDLoc, Instructions);
1166}
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001167}
1168
Matheus Almeida3813d572014-06-19 14:39:14 +00001169bool MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001170 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +00001171 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +00001172 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +00001173 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +00001174 const MCOperand &RegOp = Inst.getOperand(0);
1175 assert(RegOp.isReg() && "expected register operand kind");
1176
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001177 int64_t ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +00001178 tmpInst.setLoc(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001179 // FIXME: gas has a special case for values that are 000...1111, which
1180 // becomes a li -1 and then a dsrl
Jack Carterd0bd6422013-04-18 00:41:53 +00001181 if (0 <= ImmValue && ImmValue <= 65535) {
1182 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +00001183 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001184 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +00001185 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001186 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001187 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001188 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001189 } else if (ImmValue < 0 && ImmValue >= -32768) {
1190 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +00001191 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001192 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +00001193 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001194 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001195 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001196 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001197 } else if ((ImmValue & 0xffffffff) == ImmValue) {
1198 // For any value of j that is representable as a 32-bit integer, create
1199 // a sequence of:
Jack Carter30a59822012-10-04 04:03:53 +00001200 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001201 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001202 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001203 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1204 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +00001205 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001206 createShiftOr<0, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1207 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001208 if (!isGP64bit()) {
1209 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001210 return true;
1211 }
1212
1213 // <------- lo32 ------>
1214 // <------- hi32 ------>
1215 // <- hi16 -> <- lo16 ->
1216 // _________________________________
1217 // | | | |
1218 // | 16-bytes | 16-bytes | 16-bytes |
1219 // |__________|__________|__________|
1220 //
1221 // For any value of j that is representable as a 48-bit integer, create
1222 // a sequence of:
1223 // li d,j => lui d,hi16(j)
1224 // ori d,d,hi16(lo32(j))
1225 // dsll d,d,16
1226 // ori d,d,lo16(lo32(j))
1227 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001228 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001229 tmpInst.addOperand(
1230 MCOperand::CreateImm((ImmValue & (0xffffLL << 32)) >> 32));
Jack Carter30a59822012-10-04 04:03:53 +00001231 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001232 createShiftOr<16, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1233 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1234 } else {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001235 if (!isGP64bit()) {
1236 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001237 return true;
1238 }
1239
1240 // <------- hi32 ------> <------- lo32 ------>
1241 // <- hi16 -> <- lo16 ->
1242 // ___________________________________________
1243 // | | | | |
1244 // | 16-bytes | 16-bytes | 16-bytes | 16-bytes |
1245 // |__________|__________|__________|__________|
1246 //
1247 // For any value of j that isn't representable as a 48-bit integer.
1248 // li d,j => lui d,hi16(j)
1249 // ori d,d,lo16(hi32(j))
1250 // dsll d,d,16
1251 // ori d,d,hi16(lo32(j))
1252 // dsll d,d,16
1253 // ori d,d,lo16(lo32(j))
1254 tmpInst.setOpcode(Mips::LUi);
1255 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1256 tmpInst.addOperand(
1257 MCOperand::CreateImm((ImmValue & (0xffffLL << 48)) >> 48));
1258 Instructions.push_back(tmpInst);
1259 createShiftOr<32, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1260 createShiftOr<16, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1261 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
Jack Carter30a59822012-10-04 04:03:53 +00001262 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001263 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001264}
Jack Carter92995f12012-10-06 00:53:28 +00001265
Matheus Almeida3813d572014-06-19 14:39:14 +00001266bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001267MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
1268 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001269 MCInst tmpInst;
1270 const MCOperand &ImmOp = Inst.getOperand(2);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001271 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1272 "expected immediate operand kind");
1273 if (!ImmOp.isImm()) {
1274 expandLoadAddressSym(Inst, IDLoc, Instructions);
1275 return false;
1276 }
Jack Carter543fdf82012-10-09 23:29:45 +00001277 const MCOperand &SrcRegOp = Inst.getOperand(1);
1278 assert(SrcRegOp.isReg() && "expected register operand kind");
1279 const MCOperand &DstRegOp = Inst.getOperand(0);
1280 assert(DstRegOp.isReg() && "expected register operand kind");
1281 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001282 if (-32768 <= ImmValue && ImmValue <= 65535) {
1283 // For -32768 <= j <= 65535.
1284 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +00001285 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +00001286 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1287 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1288 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1289 Instructions.push_back(tmpInst);
1290 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001291 // For any other value of j that is representable as a 32-bit integer.
1292 // la d,j(s) => lui d,hi16(j)
1293 // ori d,d,lo16(j)
1294 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +00001295 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001296 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1297 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1298 Instructions.push_back(tmpInst);
1299 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001300 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001301 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1302 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1303 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1304 Instructions.push_back(tmpInst);
1305 tmpInst.clear();
1306 tmpInst.setOpcode(Mips::ADDu);
1307 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1308 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1309 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1310 Instructions.push_back(tmpInst);
1311 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001312 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001313}
1314
Matheus Almeida3813d572014-06-19 14:39:14 +00001315bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001316MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1317 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001318 MCInst tmpInst;
1319 const MCOperand &ImmOp = Inst.getOperand(1);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001320 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1321 "expected immediate operand kind");
1322 if (!ImmOp.isImm()) {
1323 expandLoadAddressSym(Inst, IDLoc, Instructions);
1324 return false;
1325 }
Jack Carter543fdf82012-10-09 23:29:45 +00001326 const MCOperand &RegOp = Inst.getOperand(0);
1327 assert(RegOp.isReg() && "expected register operand kind");
1328 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001329 if (-32768 <= ImmValue && ImmValue <= 65535) {
1330 // For -32768 <= j <= 65535.
1331 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +00001332 tmpInst.setOpcode(Mips::ADDiu);
1333 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001334 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +00001335 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1336 Instructions.push_back(tmpInst);
1337 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001338 // For any other value of j that is representable as a 32-bit integer.
1339 // la d,j => lui d,hi16(j)
1340 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001341 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001342 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1343 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1344 Instructions.push_back(tmpInst);
1345 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001346 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001347 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1348 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1349 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1350 Instructions.push_back(tmpInst);
1351 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001352 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001353}
1354
Toma Tabacu0d64b202014-08-14 10:29:17 +00001355void
1356MipsAsmParser::expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
1357 SmallVectorImpl<MCInst> &Instructions) {
1358 // FIXME: If we do have a valid at register to use, we should generate a
1359 // slightly shorter sequence here.
1360 MCInst tmpInst;
1361 int ExprOperandNo = 1;
1362 // Sometimes the assembly parser will get the immediate expression as
1363 // a $zero + an immediate.
1364 if (Inst.getNumOperands() == 3) {
1365 assert(Inst.getOperand(1).getReg() ==
1366 (isGP64bit() ? Mips::ZERO_64 : Mips::ZERO));
1367 ExprOperandNo = 2;
1368 }
1369 const MCOperand &SymOp = Inst.getOperand(ExprOperandNo);
1370 assert(SymOp.isExpr() && "expected symbol operand kind");
1371 const MCOperand &RegOp = Inst.getOperand(0);
1372 unsigned RegNo = RegOp.getReg();
1373 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymOp.getExpr());
1374 const MCSymbolRefExpr *HiExpr =
1375 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1376 MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
1377 const MCSymbolRefExpr *LoExpr =
1378 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1379 MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
1380 if (isGP64bit()) {
1381 // If it's a 64-bit architecture, expand to:
1382 // la d,sym => lui d,highest(sym)
1383 // ori d,d,higher(sym)
1384 // dsll d,d,16
1385 // ori d,d,hi16(sym)
1386 // dsll d,d,16
1387 // ori d,d,lo16(sym)
1388 const MCSymbolRefExpr *HighestExpr =
1389 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1390 MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
1391 const MCSymbolRefExpr *HigherExpr =
1392 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1393 MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
1394
1395 tmpInst.setOpcode(Mips::LUi);
1396 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1397 tmpInst.addOperand(MCOperand::CreateExpr(HighestExpr));
1398 Instructions.push_back(tmpInst);
1399
1400 createShiftOr<false>(MCOperand::CreateExpr(HigherExpr), RegNo, SMLoc(),
1401 Instructions);
1402 createShiftOr<true>(MCOperand::CreateExpr(HiExpr), RegNo, SMLoc(),
1403 Instructions);
1404 createShiftOr<true>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1405 Instructions);
1406 } else {
1407 // Otherwise, expand to:
1408 // la d,sym => lui d,hi16(sym)
1409 // ori d,d,lo16(sym)
1410 tmpInst.setOpcode(Mips::LUi);
1411 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1412 tmpInst.addOperand(MCOperand::CreateExpr(HiExpr));
1413 Instructions.push_back(tmpInst);
1414
1415 createShiftOr<false>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1416 Instructions);
1417 }
1418}
1419
Jack Carter9e65aa32013-03-22 00:05:30 +00001420void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001421 SmallVectorImpl<MCInst> &Instructions,
1422 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001423 const MCSymbolRefExpr *SR;
1424 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00001425 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00001426 const MCExpr *ExprOffset;
1427 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00001428 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001429 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1430 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001431 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001432 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1433 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001434 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00001435 if (isImmOpnd) {
1436 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
1437 ImmOffset = Inst.getOperand(2).getImm();
1438 LoOffset = ImmOffset & 0x0000ffff;
1439 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00001440 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00001441 if (LoOffset & 0x8000)
1442 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00001443 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001444 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001445 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00001446 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00001447 // These are some of the types of expansions we perform here:
1448 // 1) lw $8, sym => lui $8, %hi(sym)
1449 // lw $8, %lo(sym)($8)
1450 // 2) lw $8, offset($9) => lui $8, %hi(offset)
1451 // add $8, $8, $9
1452 // lw $8, %lo(offset)($9)
1453 // 3) lw $8, offset($8) => lui $at, %hi(offset)
1454 // add $at, $at, $8
1455 // lw $8, %lo(offset)($at)
1456 // 4) sw $8, sym => lui $at, %hi(sym)
1457 // sw $8, %lo(sym)($at)
1458 // 5) sw $8, offset($8) => lui $at, %hi(offset)
1459 // add $at, $at, $8
1460 // sw $8, %lo(offset)($at)
1461 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
1462 // ldc1 $f0, %lo(sym)($at)
1463 //
1464 // For load instructions we can use the destination register as a temporary
1465 // if base and dst are different (examples 1 and 2) and if the base register
1466 // is general purpose otherwise we must use $at (example 6) and error if it's
1467 // not available. For stores we must use $at (examples 4 and 5) because we
1468 // must not clobber the source register setting up the offset.
1469 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
1470 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
1471 unsigned RegClassIDOp0 =
1472 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
1473 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
1474 (RegClassIDOp0 == Mips::GPR64RegClassID);
1475 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00001476 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00001477 else {
1478 int AT = getATReg(IDLoc);
1479 // At this point we need AT to perform the expansions and we exit if it is
1480 // not available.
1481 if (!AT)
1482 return;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001483 TmpRegNum = getReg(
1484 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, AT);
Matheus Almeida7de68e72014-06-18 14:46:05 +00001485 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00001486
Jack Carter9e65aa32013-03-22 00:05:30 +00001487 TempInst.setOpcode(Mips::LUi);
1488 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1489 if (isImmOpnd)
1490 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
1491 else {
1492 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001493 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00001494 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
1495 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
1496 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001497 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001498 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001499 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00001500 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001501 }
1502 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001503 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00001504 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001505 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00001506 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00001507 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001508 TempInst.setOpcode(Mips::ADDu);
1509 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1510 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1511 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
1512 Instructions.push_back(TempInst);
1513 TempInst.clear();
Alp Tokercb402912014-01-24 17:20:08 +00001514 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00001515 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001516 TempInst.setOpcode(Inst.getOpcode());
1517 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
1518 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1519 if (isImmOpnd)
1520 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
1521 else {
1522 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001523 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
1524 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
1525 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001526 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001527 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001528 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00001529 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001530 }
1531 }
1532 Instructions.push_back(TempInst);
1533 TempInst.clear();
1534}
1535
Matheus Almeida595fcab2014-06-11 15:05:56 +00001536unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1537 // As described by the Mips32r2 spec, the registers Rd and Rs for
1538 // jalr.hb must be different.
1539 unsigned Opcode = Inst.getOpcode();
1540
1541 if (Opcode == Mips::JALR_HB &&
1542 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
1543 return Match_RequiresDifferentSrcAndDst;
1544
1545 return Match_Success;
1546}
1547
David Blaikie960ea3f2014-06-08 16:18:35 +00001548bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1549 OperandVector &Operands,
1550 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00001551 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00001552 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00001553
Jack Carterb4dbc172012-09-05 23:34:03 +00001554 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00001555 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00001556 unsigned MatchResult =
1557 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00001558
1559 switch (MatchResult) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001560 default:
1561 break;
Jack Carterb4dbc172012-09-05 23:34:03 +00001562 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001563 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00001564 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001565 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00001566 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00001567 return false;
1568 }
1569 case Match_MissingFeature:
1570 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1571 return true;
1572 case Match_InvalidOperand: {
1573 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00001574 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001575 if (ErrorInfo >= Operands.size())
1576 return Error(IDLoc, "too few operands for instruction");
1577
David Blaikie960ea3f2014-06-08 16:18:35 +00001578 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001579 if (ErrorLoc == SMLoc())
1580 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00001581 }
1582
1583 return Error(ErrorLoc, "invalid operand for instruction");
1584 }
1585 case Match_MnemonicFail:
1586 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00001587 case Match_RequiresDifferentSrcAndDst:
1588 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00001589 }
Rafael Espindola870c4e92012-01-11 03:56:41 +00001590 return true;
1591}
1592
Toma Tabacu13964452014-09-04 13:23:44 +00001593void MipsAsmParser::warnIfAssemblerTemporary(int RegIndex, SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00001594 if ((RegIndex != 0) &&
1595 ((int)AssemblerOptions.back()->getATRegNum() == RegIndex)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001596 if (RegIndex == 1)
1597 Warning(Loc, "Used $at without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001598 else
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001599 Warning(Loc, Twine("Used $") + Twine(RegIndex) + " with \".set at=$" +
1600 Twine(RegIndex) + "\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001601 }
1602}
1603
Jack Carter1ac53222013-02-20 23:11:17 +00001604int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001605 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00001606
Vladimir Medic4c299852013-11-06 11:27:05 +00001607 CC = StringSwitch<unsigned>(Name)
1608 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001609 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00001610 .Case("a0", 4)
1611 .Case("a1", 5)
1612 .Case("a2", 6)
1613 .Case("a3", 7)
1614 .Case("v0", 2)
1615 .Case("v1", 3)
1616 .Case("s0", 16)
1617 .Case("s1", 17)
1618 .Case("s2", 18)
1619 .Case("s3", 19)
1620 .Case("s4", 20)
1621 .Case("s5", 21)
1622 .Case("s6", 22)
1623 .Case("s7", 23)
1624 .Case("k0", 26)
1625 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001626 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00001627 .Case("sp", 29)
1628 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001629 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00001630 .Case("ra", 31)
1631 .Case("t0", 8)
1632 .Case("t1", 9)
1633 .Case("t2", 10)
1634 .Case("t3", 11)
1635 .Case("t4", 12)
1636 .Case("t5", 13)
1637 .Case("t6", 14)
1638 .Case("t7", 15)
1639 .Case("t8", 24)
1640 .Case("t9", 25)
1641 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00001642
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001643 if (isABI_N32() || isABI_N64()) {
Daniel Sandersa4b0c742014-03-26 11:39:07 +00001644 // Although SGI documentation just cuts out t0-t3 for n32/n64,
1645 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
1646 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
1647 if (8 <= CC && CC <= 11)
1648 CC += 4;
Jack Carter1ac53222013-02-20 23:11:17 +00001649
Daniel Sandersa4b0c742014-03-26 11:39:07 +00001650 if (CC == -1)
1651 CC = StringSwitch<unsigned>(Name)
1652 .Case("a4", 8)
1653 .Case("a5", 9)
1654 .Case("a6", 10)
1655 .Case("a7", 11)
1656 .Case("kt0", 26)
1657 .Case("kt1", 27)
1658 .Default(-1);
1659 }
Jack Carter1ac53222013-02-20 23:11:17 +00001660
1661 return CC;
1662}
Jack Carterd0bd6422013-04-18 00:41:53 +00001663
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001664int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001665
Jack Cartera63b16a2012-09-07 00:23:42 +00001666 if (Name[0] == 'f') {
1667 StringRef NumString = Name.substr(1);
1668 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001669 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001670 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001671 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00001672 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001673 return IntVal;
1674 }
1675 return -1;
1676}
Jack Cartera63b16a2012-09-07 00:23:42 +00001677
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001678int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
1679
1680 if (Name.startswith("fcc")) {
1681 StringRef NumString = Name.substr(3);
1682 unsigned IntVal;
1683 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001684 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001685 if (IntVal > 7) // There are only 8 fcc registers.
1686 return -1;
1687 return IntVal;
1688 }
1689 return -1;
1690}
1691
1692int MipsAsmParser::matchACRegisterName(StringRef Name) {
1693
Akira Hatanaka274d24c2013-08-14 01:15:52 +00001694 if (Name.startswith("ac")) {
1695 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001696 unsigned IntVal;
1697 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001698 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001699 if (IntVal > 3) // There are only 3 acc registers.
1700 return -1;
1701 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00001702 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001703 return -1;
1704}
Jack Carterd0bd6422013-04-18 00:41:53 +00001705
Jack Carter5dc8ac92013-09-25 23:50:44 +00001706int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
1707 unsigned IntVal;
1708
1709 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
1710 return -1;
1711
1712 if (IntVal > 31)
1713 return -1;
1714
1715 return IntVal;
1716}
1717
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001718int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
1719 int CC;
1720
1721 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00001722 .Case("msair", 0)
1723 .Case("msacsr", 1)
1724 .Case("msaaccess", 2)
1725 .Case("msasave", 3)
1726 .Case("msamodify", 4)
1727 .Case("msarequest", 5)
1728 .Case("msamap", 6)
1729 .Case("msaunmap", 7)
1730 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001731
1732 return CC;
1733}
1734
Jack Carter0b744b32012-10-04 02:29:46 +00001735bool MipsAssemblerOptions::setATReg(unsigned Reg) {
1736 if (Reg > 31)
1737 return false;
1738
Toma Tabacu3c24b042014-09-05 15:43:21 +00001739 ATReg = Reg;
Jack Carter0b744b32012-10-04 02:29:46 +00001740 return true;
1741}
1742
Matheus Almeida7de68e72014-06-18 14:46:05 +00001743int MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00001744 int AT = AssemblerOptions.back()->getATRegNum();
Daniel Sandersd89b1362014-03-24 16:48:01 +00001745 if (AT == 0)
Matheus Almeida7de68e72014-06-18 14:46:05 +00001746 reportParseError(Loc,
1747 "Pseudo instruction requires $at, which is not available");
Daniel Sandersd89b1362014-03-24 16:48:01 +00001748 return AT;
1749}
Jack Carter0b744b32012-10-04 02:29:46 +00001750
Jack Carterd0bd6422013-04-18 00:41:53 +00001751unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00001752 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00001753}
1754
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001755unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001756 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00001757 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001758}
1759
Jack Carter873c7242013-01-12 01:03:14 +00001760int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001761 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00001762 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00001763 return -1;
1764
Jack Carter873c7242013-01-12 01:03:14 +00001765 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00001766}
1767
Toma Tabacu13964452014-09-04 13:23:44 +00001768bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
1769 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001770
Jack Carter30a59822012-10-04 04:03:53 +00001771 // Check if the current operand has a custom associated parser, if so, try to
1772 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00001773 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
1774 if (ResTy == MatchOperand_Success)
1775 return false;
1776 // If there wasn't a custom match, try the generic matcher below. Otherwise,
1777 // there was a match, but an error occurred, in which case, just return that
1778 // the operand parsing failed.
1779 if (ResTy == MatchOperand_ParseFail)
1780 return true;
1781
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001782 DEBUG(dbgs() << ".. Generic Parser\n");
1783
Jack Carterb4dbc172012-09-05 23:34:03 +00001784 switch (getLexer().getKind()) {
1785 default:
1786 Error(Parser.getTok().getLoc(), "unexpected token in operand");
1787 return true;
1788 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001789 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00001790 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00001791
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001792 // Almost all registers have been parsed by custom parsers. There is only
1793 // one exception to this. $zero (and it's alias $0) will reach this point
1794 // for div, divu, and similar instructions because it is not an operand
1795 // to the instruction definition but an explicit register. Special case
1796 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00001797 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00001798 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001799
Jack Carterd0bd6422013-04-18 00:41:53 +00001800 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00001801 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001802 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00001803 return true;
1804
Jack Carter873c7242013-01-12 01:03:14 +00001805 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00001806 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00001807 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00001808 const MCExpr *Res =
1809 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00001810
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001811 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00001812 return false;
1813 }
Vladimir Medic4c299852013-11-06 11:27:05 +00001814 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00001815 case AsmToken::LParen:
1816 case AsmToken::Minus:
1817 case AsmToken::Plus:
1818 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00001819 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00001820 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001821 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00001822 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001823 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00001824 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00001825 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001826 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001827 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001828 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00001829 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00001830 return true;
1831
Jack Carter873c7242013-01-12 01:03:14 +00001832 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1833
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001834 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001835 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001836 } // case AsmToken::Percent
1837 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00001838 return true;
1839}
1840
Vladimir Medic4c299852013-11-06 11:27:05 +00001841const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00001842 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00001843 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00001844 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001845 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00001846 // It's a constant, evaluate reloc value.
1847 int16_t Val;
1848 switch (getVariantKind(RelocStr)) {
1849 case MCSymbolRefExpr::VK_Mips_ABS_LO:
1850 // Get the 1st 16-bits.
1851 Val = MCE->getValue() & 0xffff;
1852 break;
1853 case MCSymbolRefExpr::VK_Mips_ABS_HI:
1854 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
1855 // 16 bits being negative.
1856 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
1857 break;
1858 case MCSymbolRefExpr::VK_Mips_HIGHER:
1859 // Get the 3rd 16-bits.
1860 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
1861 break;
1862 case MCSymbolRefExpr::VK_Mips_HIGHEST:
1863 // Get the 4th 16-bits.
1864 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
1865 break;
1866 default:
1867 report_fatal_error("Unsupported reloc value!");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001868 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00001869 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00001870 }
1871
Jack Carterb5cf5902013-04-17 00:18:04 +00001872 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001873 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00001874 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00001875 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00001876 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001877 return Res;
1878 }
1879
1880 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00001881 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
1882
Sasa Stankovic06c47802014-04-03 10:37:45 +00001883 // Try to create target expression.
1884 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
1885 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00001886
Jack Carterd0bd6422013-04-18 00:41:53 +00001887 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
1888 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00001889 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
1890 return Res;
1891 }
1892
1893 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001894 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
1895 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
1896 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00001897 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001898 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001899 return Expr;
1900}
1901
1902bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
1903
1904 switch (Expr->getKind()) {
1905 case MCExpr::Constant:
1906 return true;
1907 case MCExpr::SymbolRef:
1908 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
1909 case MCExpr::Binary:
1910 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
1911 if (!isEvaluated(BE->getLHS()))
1912 return false;
1913 return isEvaluated(BE->getRHS());
1914 }
1915 case MCExpr::Unary:
1916 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00001917 case MCExpr::Target:
1918 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001919 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001920 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00001921}
Jack Carterd0bd6422013-04-18 00:41:53 +00001922
Jack Carterb5cf5902013-04-17 00:18:04 +00001923bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001924 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00001925 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00001926 if (Tok.isNot(AsmToken::Identifier))
1927 return true;
1928
1929 std::string Str = Tok.getIdentifier().str();
1930
Jack Carterd0bd6422013-04-18 00:41:53 +00001931 Parser.Lex(); // Eat the identifier.
1932 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001933 const MCExpr *IdVal;
1934 SMLoc EndLoc;
1935
1936 if (getLexer().getKind() == AsmToken::LParen) {
1937 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001938 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001939 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001940 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001941 const AsmToken &nextTok = Parser.getTok();
1942 if (nextTok.isNot(AsmToken::Identifier))
1943 return true;
1944 Str += "(%";
1945 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00001946 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00001947 if (getLexer().getKind() != AsmToken::LParen)
1948 return true;
1949 } else
1950 break;
1951 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001952 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00001953 return true;
1954
1955 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00001956 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001957
1958 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00001959 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001960
Jack Carterd0bd6422013-04-18 00:41:53 +00001961 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00001962 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001963}
1964
Jack Carterb4dbc172012-09-05 23:34:03 +00001965bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1966 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001967 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00001968 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001969 if (ResTy == MatchOperand_Success) {
1970 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00001971 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001972 StartLoc = Operand.getStartLoc();
1973 EndLoc = Operand.getEndLoc();
1974
1975 // AFAIK, we only support numeric registers and named GPR's in CFI
1976 // directives.
1977 // Don't worry about eating tokens before failing. Using an unrecognised
1978 // register is a parse error.
1979 if (Operand.isGPRAsmReg()) {
1980 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001981 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001982 }
1983
1984 return (RegNo == (unsigned)-1);
1985 }
1986
1987 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00001988 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00001989}
1990
Jack Carterb5cf5902013-04-17 00:18:04 +00001991bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00001992 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001993 bool Result = true;
1994
1995 while (getLexer().getKind() == AsmToken::LParen)
1996 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00001997
Jack Carterd0bd6422013-04-18 00:41:53 +00001998 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001999 default:
2000 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00002001 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00002002 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00002003 case AsmToken::Integer:
2004 case AsmToken::Minus:
2005 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00002006 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00002007 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00002008 else
2009 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00002010 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00002011 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002012 break;
Jack Carter873c7242013-01-12 01:03:14 +00002013 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00002014 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002015 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002016 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002017}
2018
David Blaikie960ea3f2014-06-08 16:18:35 +00002019MipsAsmParser::OperandMatchResultTy
2020MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002021 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00002022 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00002023 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002024 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002025 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00002026 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00002027 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00002028
Jack Carterb5cf5902013-04-17 00:18:04 +00002029 if (getLexer().getKind() == AsmToken::LParen) {
2030 Parser.Lex();
2031 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002032 }
2033
Jack Carterb5cf5902013-04-17 00:18:04 +00002034 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002035 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00002036 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002037
Jack Carterd0bd6422013-04-18 00:41:53 +00002038 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002039 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002040 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
2041 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002042 SMLoc E =
2043 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002044 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002045 return MatchOperand_Success;
2046 }
2047 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002048 SMLoc E =
2049 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00002050
Jack Carterd0bd6422013-04-18 00:41:53 +00002051 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002052 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00002053 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00002054 S, E, *this);
2055 Operands.push_back(
2056 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002057 return MatchOperand_Success;
2058 }
2059 Error(Parser.getTok().getLoc(), "'(' expected");
2060 return MatchOperand_ParseFail;
2061 }
2062
Jack Carterd0bd6422013-04-18 00:41:53 +00002063 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002064 }
2065
Toma Tabacu13964452014-09-04 13:23:44 +00002066 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002067 if (Res != MatchOperand_Success)
2068 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002069
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002070 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002071 Error(Parser.getTok().getLoc(), "')' expected");
2072 return MatchOperand_ParseFail;
2073 }
2074
Jack Carter873c7242013-01-12 01:03:14 +00002075 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2076
Jack Carterd0bd6422013-04-18 00:41:53 +00002077 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002078
Craig Topper062a2ba2014-04-25 05:30:21 +00002079 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00002080 IdVal = MCConstantExpr::Create(0, getContext());
2081
Jack Carterd0bd6422013-04-18 00:41:53 +00002082 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00002083 std::unique_ptr<MipsOperand> op(
2084 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00002085 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002086 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002087 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00002088 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002089 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
2090 int64_t Imm;
2091 if (IdVal->EvaluateAsAbsolute(Imm))
2092 IdVal = MCConstantExpr::Create(Imm, getContext());
2093 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
2094 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
2095 getContext());
2096 }
2097
David Blaikie960ea3f2014-06-08 16:18:35 +00002098 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002099 return MatchOperand_Success;
2100}
2101
David Blaikie960ea3f2014-06-08 16:18:35 +00002102bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Daniel Sanderse34a1202014-03-31 18:51:43 +00002103
Jack Carterd76b2372013-03-21 21:44:16 +00002104 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
2105 if (Sym) {
2106 SMLoc S = Parser.getTok().getLoc();
2107 const MCExpr *Expr;
2108 if (Sym->isVariable())
2109 Expr = Sym->getVariableValue();
2110 else
2111 return false;
2112 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002113 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00002114 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00002115 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002116 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002117 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00002118 if (ResTy == MatchOperand_Success) {
2119 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00002120 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00002121 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002122 llvm_unreachable("Should never ParseFail");
2123 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00002124 }
2125 } else if (Expr->getKind() == MCExpr::Constant) {
2126 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00002127 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00002128 Operands.push_back(
2129 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00002130 return true;
2131 }
2132 }
2133 return false;
2134}
Jack Carterd0bd6422013-04-18 00:41:53 +00002135
Jack Carter873c7242013-01-12 01:03:14 +00002136MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002137MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00002138 StringRef Identifier,
2139 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002140 int Index = matchCPURegisterName(Identifier);
2141 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002142 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002143 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2144 return MatchOperand_Success;
2145 }
2146
2147 Index = matchFPURegisterName(Identifier);
2148 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002149 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002150 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2151 return MatchOperand_Success;
2152 }
2153
2154 Index = matchFCCRegisterName(Identifier);
2155 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002156 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002157 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2158 return MatchOperand_Success;
2159 }
2160
2161 Index = matchACRegisterName(Identifier);
2162 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002163 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002164 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2165 return MatchOperand_Success;
2166 }
2167
2168 Index = matchMSA128RegisterName(Identifier);
2169 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002170 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002171 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2172 return MatchOperand_Success;
2173 }
2174
2175 Index = matchMSA128CtrlRegisterName(Identifier);
2176 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002177 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002178 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2179 return MatchOperand_Success;
2180 }
2181
2182 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00002183}
2184
2185MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002186MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Daniel Sanders315386c2014-04-01 10:40:14 +00002187 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002188
2189 if (Token.is(AsmToken::Identifier)) {
2190 DEBUG(dbgs() << ".. identifier\n");
2191 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00002192 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002193 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00002194 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002195 } else if (Token.is(AsmToken::Integer)) {
2196 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002197 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002198 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
2199 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002200 return MatchOperand_Success;
2201 }
2202
2203 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
2204
2205 return MatchOperand_NoMatch;
2206}
2207
David Blaikie960ea3f2014-06-08 16:18:35 +00002208MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002209MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
2210 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002211
2212 auto Token = Parser.getTok();
2213
2214 SMLoc S = Token.getLoc();
2215
2216 if (Token.isNot(AsmToken::Dollar)) {
2217 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
2218 if (Token.is(AsmToken::Identifier)) {
2219 if (searchSymbolAlias(Operands))
2220 return MatchOperand_Success;
2221 }
2222 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
2223 return MatchOperand_NoMatch;
2224 }
2225 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002226
Toma Tabacu13964452014-09-04 13:23:44 +00002227 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00002228 if (ResTy == MatchOperand_Success) {
2229 Parser.Lex(); // $
2230 Parser.Lex(); // identifier
2231 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002232 return ResTy;
2233}
2234
2235MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002236MipsAsmParser::parseImm(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002237 switch (getLexer().getKind()) {
2238 default:
2239 return MatchOperand_NoMatch;
2240 case AsmToken::LParen:
2241 case AsmToken::Minus:
2242 case AsmToken::Plus:
2243 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002244 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002245 case AsmToken::String:
2246 break;
2247 }
2248
2249 const MCExpr *IdVal;
2250 SMLoc S = Parser.getTok().getLoc();
2251 if (getParser().parseExpression(IdVal))
2252 return MatchOperand_ParseFail;
2253
2254 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2255 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
2256 return MatchOperand_Success;
2257}
2258
David Blaikie960ea3f2014-06-08 16:18:35 +00002259MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002260MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
2261 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002262
2263 SMLoc S = getLexer().getLoc();
2264
2265 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00002266 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002267 if (ResTy != MatchOperand_NoMatch)
2268 return ResTy;
2269
Daniel Sanders315386c2014-04-01 10:40:14 +00002270 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00002271 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00002272 if (ResTy != MatchOperand_NoMatch)
2273 return ResTy;
2274
Daniel Sandersffd84362014-04-01 10:41:48 +00002275 const MCExpr *Expr = nullptr;
2276 if (Parser.parseExpression(Expr)) {
2277 // We have no way of knowing if a symbol was consumed so we must ParseFail
2278 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002279 }
Daniel Sandersffd84362014-04-01 10:41:48 +00002280 Operands.push_back(
2281 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002282 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00002283}
2284
Vladimir Medic2b953d02013-10-01 09:48:56 +00002285MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002286MipsAsmParser::parseInvNum(OperandVector &Operands) {
Vladimir Medic2b953d02013-10-01 09:48:56 +00002287 const MCExpr *IdVal;
2288 // If the first token is '$' we may have register operand.
2289 if (Parser.getTok().is(AsmToken::Dollar))
2290 return MatchOperand_NoMatch;
2291 SMLoc S = Parser.getTok().getLoc();
2292 if (getParser().parseExpression(IdVal))
2293 return MatchOperand_ParseFail;
2294 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00002295 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00002296 int64_t Val = MCE->getValue();
2297 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2298 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002299 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00002300 return MatchOperand_Success;
2301}
2302
Matheus Almeida779c5932013-11-18 12:32:49 +00002303MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002304MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Matheus Almeida779c5932013-11-18 12:32:49 +00002305 switch (getLexer().getKind()) {
2306 default:
2307 return MatchOperand_NoMatch;
2308 case AsmToken::LParen:
2309 case AsmToken::Plus:
2310 case AsmToken::Minus:
2311 case AsmToken::Integer:
2312 break;
2313 }
2314
2315 const MCExpr *Expr;
2316 SMLoc S = Parser.getTok().getLoc();
2317
2318 if (getParser().parseExpression(Expr))
2319 return MatchOperand_ParseFail;
2320
2321 int64_t Val;
2322 if (!Expr->EvaluateAsAbsolute(Val)) {
2323 Error(S, "expected immediate value");
2324 return MatchOperand_ParseFail;
2325 }
2326
2327 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
2328 // and because the CPU always adds one to the immediate field, the allowed
2329 // range becomes 1..4. We'll only check the range here and will deal
2330 // with the addition/subtraction when actually decoding/encoding
2331 // the instruction.
2332 if (Val < 1 || Val > 4) {
2333 Error(S, "immediate not in range (1..4)");
2334 return MatchOperand_ParseFail;
2335 }
2336
Jack Carter3b2c96e2014-01-22 23:31:38 +00002337 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002338 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00002339 return MatchOperand_Success;
2340}
2341
Jack Carterdc1e35d2012-09-06 20:00:02 +00002342MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
2343
Vladimir Medic4c299852013-11-06 11:27:05 +00002344 MCSymbolRefExpr::VariantKind VK =
2345 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
2346 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
2347 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
2348 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
2349 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
2350 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
2351 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
2352 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
2353 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
2354 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
2355 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
2356 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
2357 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
2358 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
2359 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
2360 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
2361 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
2362 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00002363 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
2364 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
2365 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
2366 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
2367 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
2368 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00002369 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
2370 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00002371 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002372
Matheus Almeida2852af82014-04-22 10:15:54 +00002373 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00002374
Jack Carterdc1e35d2012-09-06 20:00:02 +00002375 return VK;
2376}
Jack Cartera63b16a2012-09-07 00:23:42 +00002377
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002378/// Sometimes (i.e. load/stores) the operand may be followed immediately by
2379/// either this.
2380/// ::= '(', register, ')'
2381/// handle it before we iterate so we don't get tripped up by the lack of
2382/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00002383bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002384 if (getLexer().is(AsmToken::LParen)) {
2385 Operands.push_back(
2386 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
2387 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00002388 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002389 SMLoc Loc = getLexer().getLoc();
2390 Parser.eatToEndOfStatement();
2391 return Error(Loc, "unexpected token in argument list");
2392 }
2393 if (Parser.getTok().isNot(AsmToken::RParen)) {
2394 SMLoc Loc = getLexer().getLoc();
2395 Parser.eatToEndOfStatement();
2396 return Error(Loc, "unexpected token, expected ')'");
2397 }
2398 Operands.push_back(
2399 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
2400 Parser.Lex();
2401 }
2402 return false;
2403}
2404
2405/// Sometimes (i.e. in MSA) the operand may be followed immediately by
2406/// either one of these.
2407/// ::= '[', register, ']'
2408/// ::= '[', integer, ']'
2409/// handle it before we iterate so we don't get tripped up by the lack of
2410/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00002411bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00002412 OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002413 if (getLexer().is(AsmToken::LBrac)) {
2414 Operands.push_back(
2415 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
2416 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00002417 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002418 SMLoc Loc = getLexer().getLoc();
2419 Parser.eatToEndOfStatement();
2420 return Error(Loc, "unexpected token in argument list");
2421 }
2422 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2423 SMLoc Loc = getLexer().getLoc();
2424 Parser.eatToEndOfStatement();
2425 return Error(Loc, "unexpected token, expected ']'");
2426 }
2427 Operands.push_back(
2428 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
2429 Parser.Lex();
2430 }
2431 return false;
2432}
2433
David Blaikie960ea3f2014-06-08 16:18:35 +00002434bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
2435 SMLoc NameLoc, OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002436 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00002437
2438 // We have reached first instruction, module directive are now forbidden.
2439 getTargetStreamer().forbidModuleDirective();
2440
Vladimir Medic74593e62013-07-17 15:00:42 +00002441 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00002442 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00002443 Parser.eatToEndOfStatement();
2444 return Error(NameLoc, "Unknown instruction");
2445 }
Vladimir Medic64828a12013-07-16 10:07:14 +00002446 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002447 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002448
2449 // Read the remaining operands.
2450 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2451 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00002452 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002453 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002454 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002455 return Error(Loc, "unexpected token in argument list");
2456 }
Toma Tabacu13964452014-09-04 13:23:44 +00002457 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002458 return true;
2459 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00002460
Jack Carterd0bd6422013-04-18 00:41:53 +00002461 while (getLexer().is(AsmToken::Comma)) {
2462 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00002463 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00002464 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002465 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002466 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002467 return Error(Loc, "unexpected token in argument list");
2468 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002469 // Parse bracket and parenthesis suffixes before we iterate
2470 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00002471 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002472 return true;
2473 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00002474 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002475 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00002476 }
2477 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002478 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2479 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002480 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002481 return Error(Loc, "unexpected token in argument list");
2482 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002483 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00002484 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00002485}
2486
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002487bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002488 SMLoc Loc = getLexer().getLoc();
2489 Parser.eatToEndOfStatement();
2490 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00002491}
2492
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002493bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002494 return Error(Loc, ErrorMsg);
2495}
2496
Jack Carter0b744b32012-10-04 02:29:46 +00002497bool MipsAsmParser::parseSetNoAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002498 // Line should look like: ".set noat".
2499 // set at reg to 0.
Toma Tabacu9db22db2014-09-09 10:15:38 +00002500 AssemblerOptions.back()->setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00002501 // eat noat
2502 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002503 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002504 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2505 reportParseError("unexpected token in statement");
2506 return false;
2507 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002508 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002509 return false;
2510}
Jack Carterd0bd6422013-04-18 00:41:53 +00002511
Jack Carter0b744b32012-10-04 02:29:46 +00002512bool MipsAsmParser::parseSetAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002513 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00002514 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00002515 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00002516 getParser().Lex();
2517 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00002518 AssemblerOptions.back()->setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00002519 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002520 return false;
2521 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002522 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00002523 if (getLexer().isNot(AsmToken::Dollar)) {
2524 reportParseError("unexpected token in statement");
2525 return false;
2526 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002527 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00002528 const AsmToken &Reg = Parser.getTok();
2529 if (Reg.is(AsmToken::Identifier)) {
2530 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
2531 } else if (Reg.is(AsmToken::Integer)) {
2532 AtRegNo = Reg.getIntVal();
2533 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00002534 reportParseError("unexpected token in statement");
2535 return false;
2536 }
Jack Carter1ac53222013-02-20 23:11:17 +00002537
Daniel Sanders71a89d922014-03-25 13:01:06 +00002538 if (AtRegNo < 0 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00002539 reportParseError("unexpected token in statement");
2540 return false;
2541 }
2542
Toma Tabacu9db22db2014-09-09 10:15:38 +00002543 if (!AssemblerOptions.back()->setATReg(AtRegNo)) {
Jack Carter0b744b32012-10-04 02:29:46 +00002544 reportParseError("unexpected token in statement");
2545 return false;
2546 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002547 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00002548
2549 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2550 reportParseError("unexpected token in statement");
2551 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002552 }
2553 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002554 return false;
2555 } else {
2556 reportParseError("unexpected token in statement");
2557 return false;
2558 }
2559}
2560
2561bool MipsAsmParser::parseSetReorderDirective() {
2562 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002563 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002564 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2565 reportParseError("unexpected token in statement");
2566 return false;
2567 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002568 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00002569 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002570 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002571 return false;
2572}
2573
2574bool MipsAsmParser::parseSetNoReorderDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002575 Parser.Lex();
2576 // If this is not the end of the statement, report an error.
2577 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2578 reportParseError("unexpected token in statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002579 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002580 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002581 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00002582 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002583 Parser.Lex(); // Consume the EndOfStatement.
2584 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002585}
2586
2587bool MipsAsmParser::parseSetMacroDirective() {
2588 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002589 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002590 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2591 reportParseError("unexpected token in statement");
2592 return false;
2593 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002594 AssemblerOptions.back()->setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002595 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002596 return false;
2597}
2598
2599bool MipsAsmParser::parseSetNoMacroDirective() {
2600 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002601 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002602 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2603 reportParseError("`noreorder' must be set before `nomacro'");
2604 return false;
2605 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002606 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00002607 reportParseError("`noreorder' must be set before `nomacro'");
2608 return false;
2609 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002610 AssemblerOptions.back()->setNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002611 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002612 return false;
2613}
Jack Carterd76b2372013-03-21 21:44:16 +00002614
Daniel Sanders44934432014-08-07 12:03:36 +00002615bool MipsAsmParser::parseSetMsaDirective() {
2616 Parser.Lex();
2617
2618 // If this is not the end of the statement, report an error.
2619 if (getLexer().isNot(AsmToken::EndOfStatement))
2620 return reportParseError("unexpected token in statement");
2621
2622 setFeatureBits(Mips::FeatureMSA, "msa");
2623 getTargetStreamer().emitDirectiveSetMsa();
2624 return false;
2625}
2626
2627bool MipsAsmParser::parseSetNoMsaDirective() {
2628 Parser.Lex();
2629
2630 // If this is not the end of the statement, report an error.
2631 if (getLexer().isNot(AsmToken::EndOfStatement))
2632 return reportParseError("unexpected token in statement");
2633
2634 clearFeatureBits(Mips::FeatureMSA, "msa");
2635 getTargetStreamer().emitDirectiveSetNoMsa();
2636 return false;
2637}
2638
Jack Carter39536722014-01-22 23:08:42 +00002639bool MipsAsmParser::parseSetNoMips16Directive() {
2640 Parser.Lex();
2641 // If this is not the end of the statement, report an error.
2642 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2643 reportParseError("unexpected token in statement");
2644 return false;
2645 }
2646 // For now do nothing.
2647 Parser.Lex(); // Consume the EndOfStatement.
2648 return false;
2649}
2650
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002651bool MipsAsmParser::parseSetFpDirective() {
Daniel Sanders7e527422014-07-10 13:38:23 +00002652 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002653 // Line can be: .set fp=32
2654 // .set fp=xx
2655 // .set fp=64
2656 Parser.Lex(); // Eat fp token
2657 AsmToken Tok = Parser.getTok();
2658 if (Tok.isNot(AsmToken::Equal)) {
2659 reportParseError("unexpected token in statement");
2660 return false;
2661 }
2662 Parser.Lex(); // Eat '=' token.
2663 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002664
2665 if (!parseFpABIValue(FpAbiVal, ".set"))
2666 return false;
2667
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002668 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2669 reportParseError("unexpected token in statement");
2670 return false;
2671 }
Daniel Sanders7e527422014-07-10 13:38:23 +00002672 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002673 Parser.Lex(); // Consume the EndOfStatement.
2674 return false;
2675}
2676
Toma Tabacu9db22db2014-09-09 10:15:38 +00002677bool MipsAsmParser::parseSetPopDirective() {
2678 SMLoc Loc = getLexer().getLoc();
2679
2680 Parser.Lex();
2681 if (getLexer().isNot(AsmToken::EndOfStatement))
2682 return reportParseError("unexpected token, expected end of statement");
2683
2684 // Always keep an element on the options "stack" to prevent the user
2685 // from changing the initial options. This is how we remember them.
2686 if (AssemblerOptions.size() == 2)
2687 return reportParseError(Loc, ".set pop with no .set push");
2688
2689 AssemblerOptions.pop_back();
2690 setAvailableFeatures(AssemblerOptions.back()->getFeatures());
2691
2692 getTargetStreamer().emitDirectiveSetPop();
2693 return false;
2694}
2695
2696bool MipsAsmParser::parseSetPushDirective() {
2697 Parser.Lex();
2698 if (getLexer().isNot(AsmToken::EndOfStatement))
2699 return reportParseError("unexpected token, expected end of statement");
2700
2701 // Create a copy of the current assembler options environment and push it.
2702 MipsAssemblerOptions *TmpAOPtr =
2703 new MipsAssemblerOptions(AssemblerOptions.back().get());
2704 AssemblerOptions.push_back(std::unique_ptr<MipsAssemblerOptions>(TmpAOPtr));
2705
2706 getTargetStreamer().emitDirectiveSetPush();
2707 return false;
2708}
2709
Jack Carterd76b2372013-03-21 21:44:16 +00002710bool MipsAsmParser::parseSetAssignment() {
2711 StringRef Name;
2712 const MCExpr *Value;
2713
2714 if (Parser.parseIdentifier(Name))
2715 reportParseError("expected identifier after .set");
2716
2717 if (getLexer().isNot(AsmToken::Comma))
2718 return reportParseError("unexpected token in .set directive");
Jack Carterb5cf5902013-04-17 00:18:04 +00002719 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00002720
Jack Carter3b2c96e2014-01-22 23:31:38 +00002721 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00002722 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00002723
Jack Carterd0bd6422013-04-18 00:41:53 +00002724 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00002725 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00002726 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00002727 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00002728 Sym = getContext().GetOrCreateSymbol(Name);
2729 Sym->setVariableValue(Value);
2730
2731 return false;
2732}
Jack Carterd0bd6422013-04-18 00:41:53 +00002733
Toma Tabacu85618b32014-08-19 14:22:52 +00002734bool MipsAsmParser::parseSetArchDirective() {
2735 Parser.Lex();
2736 if (getLexer().isNot(AsmToken::Equal))
2737 return reportParseError("unexpected token, expected equals sign");
2738
2739 Parser.Lex();
2740 StringRef Arch;
2741 if (Parser.parseIdentifier(Arch))
2742 return reportParseError("expected arch identifier");
2743
2744 StringRef ArchFeatureName =
2745 StringSwitch<StringRef>(Arch)
2746 .Case("mips1", "mips1")
2747 .Case("mips2", "mips2")
2748 .Case("mips3", "mips3")
2749 .Case("mips4", "mips4")
2750 .Case("mips5", "mips5")
2751 .Case("mips32", "mips32")
2752 .Case("mips32r2", "mips32r2")
2753 .Case("mips32r6", "mips32r6")
2754 .Case("mips64", "mips64")
2755 .Case("mips64r2", "mips64r2")
2756 .Case("mips64r6", "mips64r6")
2757 .Case("cnmips", "cnmips")
2758 .Case("r4000", "mips3") // This is an implementation of Mips3.
2759 .Default("");
2760
2761 if (ArchFeatureName.empty())
2762 return reportParseError("unsupported architecture");
2763
2764 selectArch(ArchFeatureName);
2765 getTargetStreamer().emitDirectiveSetArch(Arch);
2766 return false;
2767}
2768
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002769bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
2770 Parser.Lex();
2771 if (getLexer().isNot(AsmToken::EndOfStatement))
2772 return reportParseError("unexpected token in .set directive");
2773
Matheus Almeida2852af82014-04-22 10:15:54 +00002774 switch (Feature) {
2775 default:
2776 llvm_unreachable("Unimplemented feature");
2777 case Mips::FeatureDSP:
2778 setFeatureBits(Mips::FeatureDSP, "dsp");
2779 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002780 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002781 case Mips::FeatureMicroMips:
2782 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002783 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002784 case Mips::FeatureMips16:
2785 getTargetStreamer().emitDirectiveSetMips16();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002786 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00002787 case Mips::FeatureMips1:
2788 selectArch("mips1");
2789 getTargetStreamer().emitDirectiveSetMips1();
2790 break;
2791 case Mips::FeatureMips2:
2792 selectArch("mips2");
2793 getTargetStreamer().emitDirectiveSetMips2();
2794 break;
2795 case Mips::FeatureMips3:
2796 selectArch("mips3");
2797 getTargetStreamer().emitDirectiveSetMips3();
2798 break;
2799 case Mips::FeatureMips4:
2800 selectArch("mips4");
2801 getTargetStreamer().emitDirectiveSetMips4();
2802 break;
2803 case Mips::FeatureMips5:
2804 selectArch("mips5");
2805 getTargetStreamer().emitDirectiveSetMips5();
2806 break;
2807 case Mips::FeatureMips32:
2808 selectArch("mips32");
2809 getTargetStreamer().emitDirectiveSetMips32();
2810 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002811 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00002812 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00002813 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002814 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00002815 case Mips::FeatureMips32r6:
2816 selectArch("mips32r6");
2817 getTargetStreamer().emitDirectiveSetMips32R6();
2818 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002819 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00002820 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00002821 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00002822 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002823 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00002824 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00002825 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00002826 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00002827 case Mips::FeatureMips64r6:
2828 selectArch("mips64r6");
2829 getTargetStreamer().emitDirectiveSetMips64R6();
2830 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002831 }
2832 return false;
2833}
2834
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002835bool MipsAsmParser::eatComma(StringRef ErrorStr) {
2836 if (getLexer().isNot(AsmToken::Comma)) {
2837 SMLoc Loc = getLexer().getLoc();
2838 Parser.eatToEndOfStatement();
2839 return Error(Loc, ErrorStr);
2840 }
2841
Matheus Almeida2852af82014-04-22 10:15:54 +00002842 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002843 return true;
2844}
2845
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002846bool MipsAsmParser::parseDirectiveCPLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00002847 if (AssemblerOptions.back()->isReorder())
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002848 Warning(Loc, ".cpload in reorder section");
2849
2850 // FIXME: Warn if cpload is used in Mips16 mode.
2851
David Blaikie960ea3f2014-06-08 16:18:35 +00002852 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00002853 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002854 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
2855 reportParseError("expected register containing function address");
2856 return false;
2857 }
2858
David Blaikie960ea3f2014-06-08 16:18:35 +00002859 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
2860 if (!RegOpnd.isGPRAsmReg()) {
2861 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002862 return false;
2863 }
2864
David Blaikie960ea3f2014-06-08 16:18:35 +00002865 getTargetStreamer().emitDirectiveCpload(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002866 return false;
2867}
2868
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002869bool MipsAsmParser::parseDirectiveCPSetup() {
2870 unsigned FuncReg;
2871 unsigned Save;
2872 bool SaveIsReg = true;
2873
Matheus Almeida7e815762014-06-18 13:08:59 +00002874 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00002875 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00002876 if (ResTy == MatchOperand_NoMatch) {
2877 reportParseError("expected register containing function address");
2878 Parser.eatToEndOfStatement();
2879 return false;
2880 }
2881
2882 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
2883 if (!FuncRegOpnd.isGPRAsmReg()) {
2884 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
2885 Parser.eatToEndOfStatement();
2886 return false;
2887 }
2888
2889 FuncReg = FuncRegOpnd.getGPR32Reg();
2890 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002891
2892 if (!eatComma("expected comma parsing directive"))
2893 return true;
2894
Toma Tabacu13964452014-09-04 13:23:44 +00002895 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00002896 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002897 const AsmToken &Tok = Parser.getTok();
2898 if (Tok.is(AsmToken::Integer)) {
2899 Save = Tok.getIntVal();
2900 SaveIsReg = false;
2901 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00002902 } else {
2903 reportParseError("expected save register or stack offset");
2904 Parser.eatToEndOfStatement();
2905 return false;
2906 }
2907 } else {
2908 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
2909 if (!SaveOpnd.isGPRAsmReg()) {
2910 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
2911 Parser.eatToEndOfStatement();
2912 return false;
2913 }
2914 Save = SaveOpnd.getGPR32Reg();
2915 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002916
2917 if (!eatComma("expected comma parsing directive"))
2918 return true;
2919
2920 StringRef Name;
2921 if (Parser.parseIdentifier(Name))
2922 reportParseError("expected identifier");
2923 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002924
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00002925 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, *Sym, SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002926 return false;
2927}
2928
Matheus Almeida0051f2d2014-04-16 15:48:55 +00002929bool MipsAsmParser::parseDirectiveNaN() {
2930 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2931 const AsmToken &Tok = Parser.getTok();
2932
2933 if (Tok.getString() == "2008") {
2934 Parser.Lex();
2935 getTargetStreamer().emitDirectiveNaN2008();
2936 return false;
2937 } else if (Tok.getString() == "legacy") {
2938 Parser.Lex();
2939 getTargetStreamer().emitDirectiveNaNLegacy();
2940 return false;
2941 }
2942 }
2943 // If we don't recognize the option passed to the .nan
2944 // directive (e.g. no option or unknown option), emit an error.
2945 reportParseError("invalid option in .nan directive");
2946 return false;
2947}
2948
Jack Carter0b744b32012-10-04 02:29:46 +00002949bool MipsAsmParser::parseDirectiveSet() {
2950
Jack Carterd0bd6422013-04-18 00:41:53 +00002951 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00002952 const AsmToken &Tok = Parser.getTok();
2953
2954 if (Tok.getString() == "noat") {
2955 return parseSetNoAtDirective();
2956 } else if (Tok.getString() == "at") {
2957 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00002958 } else if (Tok.getString() == "arch") {
2959 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002960 } else if (Tok.getString() == "fp") {
2961 return parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00002962 } else if (Tok.getString() == "pop") {
2963 return parseSetPopDirective();
2964 } else if (Tok.getString() == "push") {
2965 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00002966 } else if (Tok.getString() == "reorder") {
2967 return parseSetReorderDirective();
2968 } else if (Tok.getString() == "noreorder") {
2969 return parseSetNoReorderDirective();
2970 } else if (Tok.getString() == "macro") {
2971 return parseSetMacroDirective();
2972 } else if (Tok.getString() == "nomacro") {
2973 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00002974 } else if (Tok.getString() == "mips16") {
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002975 return parseSetFeature(Mips::FeatureMips16);
Jack Carter0b744b32012-10-04 02:29:46 +00002976 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00002977 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00002978 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00002979 getTargetStreamer().emitDirectiveSetNoMicroMips();
2980 Parser.eatToEndOfStatement();
2981 return false;
2982 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002983 return parseSetFeature(Mips::FeatureMicroMips);
Daniel Sandersf0df2212014-08-04 12:20:00 +00002984 } else if (Tok.getString() == "mips1") {
2985 return parseSetFeature(Mips::FeatureMips1);
2986 } else if (Tok.getString() == "mips2") {
2987 return parseSetFeature(Mips::FeatureMips2);
2988 } else if (Tok.getString() == "mips3") {
2989 return parseSetFeature(Mips::FeatureMips3);
2990 } else if (Tok.getString() == "mips4") {
2991 return parseSetFeature(Mips::FeatureMips4);
2992 } else if (Tok.getString() == "mips5") {
2993 return parseSetFeature(Mips::FeatureMips5);
2994 } else if (Tok.getString() == "mips32") {
2995 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00002996 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00002997 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sandersf0df2212014-08-04 12:20:00 +00002998 } else if (Tok.getString() == "mips32r6") {
2999 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003000 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003001 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003002 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003003 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003004 } else if (Tok.getString() == "mips64r6") {
3005 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00003006 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003007 return parseSetFeature(Mips::FeatureDSP);
Daniel Sanders44934432014-08-07 12:03:36 +00003008 } else if (Tok.getString() == "msa") {
3009 return parseSetMsaDirective();
3010 } else if (Tok.getString() == "nomsa") {
3011 return parseSetNoMsaDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00003012 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00003013 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00003014 parseSetAssignment();
3015 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003016 }
Jack Carter07c818d2013-01-25 01:31:34 +00003017
Jack Carter0b744b32012-10-04 02:29:46 +00003018 return true;
3019}
3020
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003021/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00003022/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003023bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Jack Carter07c818d2013-01-25 01:31:34 +00003024 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3025 for (;;) {
3026 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003027 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00003028 return true;
3029
3030 getParser().getStreamer().EmitValue(Value, Size);
3031
3032 if (getLexer().is(AsmToken::EndOfStatement))
3033 break;
3034
3035 // FIXME: Improve diagnostic.
3036 if (getLexer().isNot(AsmToken::Comma))
3037 return Error(L, "unexpected token in directive");
3038 Parser.Lex();
3039 }
3040 }
3041
3042 Parser.Lex();
3043 return false;
3044}
3045
Vladimir Medic4c299852013-11-06 11:27:05 +00003046/// parseDirectiveGpWord
3047/// ::= .gpword local_sym
3048bool MipsAsmParser::parseDirectiveGpWord() {
3049 const MCExpr *Value;
3050 // EmitGPRel32Value requires an expression, so we are using base class
3051 // method to evaluate the expression.
3052 if (getParser().parseExpression(Value))
3053 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00003054 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00003055
Vladimir Medice10c1122013-11-13 13:18:04 +00003056 if (getLexer().isNot(AsmToken::EndOfStatement))
Vladimir Medic4c299852013-11-06 11:27:05 +00003057 return Error(getLexer().getLoc(), "unexpected token in directive");
Vladimir Medice10c1122013-11-13 13:18:04 +00003058 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00003059 return false;
3060}
3061
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003062/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00003063/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003064bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindolab59fb732014-03-28 18:50:26 +00003065 const MCExpr *Value;
3066 // EmitGPRel64Value requires an expression, so we are using base class
3067 // method to evaluate the expression.
3068 if (getParser().parseExpression(Value))
3069 return true;
3070 getParser().getStreamer().EmitGPRel64Value(Value);
3071
3072 if (getLexer().isNot(AsmToken::EndOfStatement))
3073 return Error(getLexer().getLoc(), "unexpected token in directive");
3074 Parser.Lex(); // Eat EndOfStatement token.
3075 return false;
3076}
3077
Jack Carter0cd3c192014-01-06 23:27:31 +00003078bool MipsAsmParser::parseDirectiveOption() {
3079 // Get the option token.
3080 AsmToken Tok = Parser.getTok();
3081 // At the moment only identifiers are supported.
3082 if (Tok.isNot(AsmToken::Identifier)) {
3083 Error(Parser.getTok().getLoc(), "unexpected token in .option directive");
3084 Parser.eatToEndOfStatement();
3085 return false;
3086 }
3087
3088 StringRef Option = Tok.getIdentifier();
3089
3090 if (Option == "pic0") {
3091 getTargetStreamer().emitDirectiveOptionPic0();
3092 Parser.Lex();
3093 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3094 Error(Parser.getTok().getLoc(),
3095 "unexpected token in .option pic0 directive");
3096 Parser.eatToEndOfStatement();
3097 }
3098 return false;
3099 }
3100
Matheus Almeidaf79b2812014-03-26 13:40:29 +00003101 if (Option == "pic2") {
3102 getTargetStreamer().emitDirectiveOptionPic2();
3103 Parser.Lex();
3104 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3105 Error(Parser.getTok().getLoc(),
3106 "unexpected token in .option pic2 directive");
3107 Parser.eatToEndOfStatement();
3108 }
3109 return false;
3110 }
3111
Jack Carter0cd3c192014-01-06 23:27:31 +00003112 // Unknown option.
3113 Warning(Parser.getTok().getLoc(), "unknown option in .option directive");
3114 Parser.eatToEndOfStatement();
3115 return false;
3116}
3117
Daniel Sanders7e527422014-07-10 13:38:23 +00003118/// parseDirectiveModule
3119/// ::= .module oddspreg
3120/// ::= .module nooddspreg
3121/// ::= .module fp=value
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003122bool MipsAsmParser::parseDirectiveModule() {
Daniel Sanders7e527422014-07-10 13:38:23 +00003123 MCAsmLexer &Lexer = getLexer();
3124 SMLoc L = Lexer.getLoc();
3125
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00003126 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003127 // TODO : get a better message.
3128 reportParseError(".module directive must appear before any code");
3129 return false;
3130 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003131
3132 if (Lexer.is(AsmToken::Identifier)) {
3133 StringRef Option = Parser.getTok().getString();
3134 Parser.Lex();
3135
3136 if (Option == "oddspreg") {
3137 getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32());
3138 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
3139
3140 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3141 reportParseError("Expected end of statement");
3142 return false;
3143 }
3144
3145 return false;
3146 } else if (Option == "nooddspreg") {
3147 if (!isABI_O32()) {
3148 Error(L, "'.module nooddspreg' requires the O32 ABI");
3149 return false;
3150 }
3151
3152 getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32());
3153 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
3154
3155 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3156 reportParseError("Expected end of statement");
3157 return false;
3158 }
3159
3160 return false;
3161 } else if (Option == "fp") {
3162 return parseDirectiveModuleFP();
3163 }
3164
3165 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003166 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003167
3168 return false;
3169}
3170
3171/// parseDirectiveModuleFP
3172/// ::= =32
3173/// ::= =xx
3174/// ::= =64
3175bool MipsAsmParser::parseDirectiveModuleFP() {
3176 MCAsmLexer &Lexer = getLexer();
3177
3178 if (Lexer.isNot(AsmToken::Equal)) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003179 reportParseError("unexpected token in statement");
3180 return false;
3181 }
3182 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003183
Daniel Sanders7e527422014-07-10 13:38:23 +00003184 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003185 if (!parseFpABIValue(FpABI, ".module"))
3186 return false;
3187
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003188 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3189 reportParseError("unexpected token in statement");
3190 return false;
3191 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003192
Daniel Sanders7201a3e2014-07-08 10:35:52 +00003193 // Emit appropriate flags.
3194 getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
Daniel Sanders7e527422014-07-10 13:38:23 +00003195 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003196 return false;
3197}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003198
Daniel Sanders7e527422014-07-10 13:38:23 +00003199bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003200 StringRef Directive) {
3201 MCAsmLexer &Lexer = getLexer();
3202
3203 if (Lexer.is(AsmToken::Identifier)) {
3204 StringRef Value = Parser.getTok().getString();
3205 Parser.Lex();
3206
3207 if (Value != "xx") {
3208 reportParseError("unsupported value, expected 'xx', '32' or '64'");
3209 return false;
3210 }
3211
3212 if (!isABI_O32()) {
3213 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
3214 return false;
3215 }
3216
Daniel Sanders7e527422014-07-10 13:38:23 +00003217 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003218 return true;
3219 }
3220
3221 if (Lexer.is(AsmToken::Integer)) {
3222 unsigned Value = Parser.getTok().getIntVal();
3223 Parser.Lex();
3224
3225 if (Value != 32 && Value != 64) {
3226 reportParseError("unsupported value, expected 'xx', '32' or '64'");
3227 return false;
3228 }
3229
3230 if (Value == 32) {
3231 if (!isABI_O32()) {
3232 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
3233 return false;
3234 }
3235
Daniel Sanders7e527422014-07-10 13:38:23 +00003236 FpABI = MipsABIFlagsSection::FpABIKind::S32;
3237 } else
3238 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003239
Daniel Sanders7e527422014-07-10 13:38:23 +00003240 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003241 }
3242
3243 return false;
3244}
3245
Jack Carter0b744b32012-10-04 02:29:46 +00003246bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carter07c818d2013-01-25 01:31:34 +00003247 StringRef IDVal = DirectiveID.getString();
3248
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003249 if (IDVal == ".cpload")
3250 return parseDirectiveCPLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00003251 if (IDVal == ".dword") {
3252 parseDataDirective(8, DirectiveID.getLoc());
3253 return false;
3254 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003255 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003256 StringRef SymbolName;
3257
3258 if (Parser.parseIdentifier(SymbolName)) {
3259 reportParseError("expected identifier after .ent");
3260 return false;
3261 }
3262
3263 // There's an undocumented extension that allows an integer to
3264 // follow the name of the procedure which AFAICS is ignored by GAS.
3265 // Example: .ent foo,2
3266 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3267 if (getLexer().isNot(AsmToken::Comma)) {
3268 // Even though we accept this undocumented extension for compatibility
3269 // reasons, the additional integer argument does not actually change
3270 // the behaviour of the '.ent' directive, so we would like to discourage
3271 // its use. We do this by not referring to the extended version in
3272 // error messages which are not directly related to its use.
3273 reportParseError("unexpected token, expected end of statement");
3274 return false;
3275 }
3276 Parser.Lex(); // Eat the comma.
3277 const MCExpr *DummyNumber;
3278 int64_t DummyNumberVal;
3279 // If the user was explicitly trying to use the extended version,
3280 // we still give helpful extension-related error messages.
3281 if (Parser.parseExpression(DummyNumber)) {
3282 reportParseError("expected number after comma");
3283 return false;
3284 }
3285 if (!DummyNumber->EvaluateAsAbsolute(DummyNumberVal)) {
3286 reportParseError("expected an absolute expression after comma");
3287 return false;
3288 }
3289 }
3290
3291 // If this is not the end of the statement, report an error.
3292 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3293 reportParseError("unexpected token, expected end of statement");
3294 return false;
3295 }
3296
3297 MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
3298
3299 getTargetStreamer().emitDirectiveEnt(*Sym);
3300 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00003301 return false;
3302 }
3303
Jack Carter07c818d2013-01-25 01:31:34 +00003304 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003305 StringRef SymbolName;
3306
3307 if (Parser.parseIdentifier(SymbolName)) {
3308 reportParseError("expected identifier after .end");
3309 return false;
3310 }
3311
3312 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3313 reportParseError("unexpected token, expected end of statement");
3314 return false;
3315 }
3316
3317 if (CurrentFn == nullptr) {
3318 reportParseError(".end used without .ent");
3319 return false;
3320 }
3321
3322 if ((SymbolName != CurrentFn->getName())) {
3323 reportParseError(".end symbol does not match .ent symbol");
3324 return false;
3325 }
3326
3327 getTargetStreamer().emitDirectiveEnd(SymbolName);
3328 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00003329 return false;
3330 }
3331
Jack Carter07c818d2013-01-25 01:31:34 +00003332 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003333 // .frame $stack_reg, frame_size_in_bytes, $return_reg
3334 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003335 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00003336 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3337 reportParseError("expected stack register");
3338 return false;
3339 }
3340
3341 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3342 if (!StackRegOpnd.isGPRAsmReg()) {
3343 reportParseError(StackRegOpnd.getStartLoc(),
3344 "expected general purpose register");
3345 return false;
3346 }
3347 unsigned StackReg = StackRegOpnd.getGPR32Reg();
3348
3349 if (Parser.getTok().is(AsmToken::Comma))
3350 Parser.Lex();
3351 else {
3352 reportParseError("unexpected token, expected comma");
3353 return false;
3354 }
3355
3356 // Parse the frame size.
3357 const MCExpr *FrameSize;
3358 int64_t FrameSizeVal;
3359
3360 if (Parser.parseExpression(FrameSize)) {
3361 reportParseError("expected frame size value");
3362 return false;
3363 }
3364
3365 if (!FrameSize->EvaluateAsAbsolute(FrameSizeVal)) {
3366 reportParseError("frame size not an absolute expression");
3367 return false;
3368 }
3369
3370 if (Parser.getTok().is(AsmToken::Comma))
3371 Parser.Lex();
3372 else {
3373 reportParseError("unexpected token, expected comma");
3374 return false;
3375 }
3376
3377 // Parse the return register.
3378 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00003379 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00003380 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3381 reportParseError("expected return register");
3382 return false;
3383 }
3384
3385 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3386 if (!ReturnRegOpnd.isGPRAsmReg()) {
3387 reportParseError(ReturnRegOpnd.getStartLoc(),
3388 "expected general purpose register");
3389 return false;
3390 }
3391
3392 // If this is not the end of the statement, report an error.
3393 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3394 reportParseError("unexpected token, expected end of statement");
3395 return false;
3396 }
3397
3398 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
3399 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00003400 return false;
3401 }
3402
Jack Carter07c818d2013-01-25 01:31:34 +00003403 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00003404 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00003405 }
3406
Daniel Sandersd97a6342014-08-13 10:07:34 +00003407 if (IDVal == ".mask" || IDVal == ".fmask") {
3408 // .mask bitmask, frame_offset
3409 // bitmask: One bit for each register used.
3410 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
3411 // first register is expected to be saved.
3412 // Examples:
3413 // .mask 0x80000000, -4
3414 // .fmask 0x80000000, -4
3415 //
Jack Carterbe332172012-09-07 00:48:02 +00003416
Daniel Sandersd97a6342014-08-13 10:07:34 +00003417 // Parse the bitmask
3418 const MCExpr *BitMask;
3419 int64_t BitMaskVal;
3420
3421 if (Parser.parseExpression(BitMask)) {
3422 reportParseError("expected bitmask value");
3423 return false;
3424 }
3425
3426 if (!BitMask->EvaluateAsAbsolute(BitMaskVal)) {
3427 reportParseError("bitmask not an absolute expression");
3428 return false;
3429 }
3430
3431 if (Parser.getTok().is(AsmToken::Comma))
3432 Parser.Lex();
3433 else {
3434 reportParseError("unexpected token, expected comma");
3435 return false;
3436 }
3437
3438 // Parse the frame_offset
3439 const MCExpr *FrameOffset;
3440 int64_t FrameOffsetVal;
3441
3442 if (Parser.parseExpression(FrameOffset)) {
3443 reportParseError("expected frame offset value");
3444 return false;
3445 }
3446
3447 if (!FrameOffset->EvaluateAsAbsolute(FrameOffsetVal)) {
3448 reportParseError("frame offset not an absolute expression");
3449 return false;
3450 }
3451
3452 // If this is not the end of the statement, report an error.
3453 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3454 reportParseError("unexpected token, expected end of statement");
3455 return false;
3456 }
3457
3458 if (IDVal == ".mask")
3459 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
3460 else
3461 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00003462 return false;
3463 }
3464
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003465 if (IDVal == ".nan")
3466 return parseDirectiveNaN();
3467
Jack Carter07c818d2013-01-25 01:31:34 +00003468 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00003469 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00003470 return false;
3471 }
3472
Rafael Espindolab59fb732014-03-28 18:50:26 +00003473 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003474 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00003475 return false;
3476 }
3477
Jack Carter07c818d2013-01-25 01:31:34 +00003478 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003479 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00003480 return false;
3481 }
3482
Jack Carter0cd3c192014-01-06 23:27:31 +00003483 if (IDVal == ".option")
3484 return parseDirectiveOption();
3485
3486 if (IDVal == ".abicalls") {
3487 getTargetStreamer().emitDirectiveAbiCalls();
3488 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3489 Error(Parser.getTok().getLoc(), "unexpected token in directive");
3490 // Clear line
3491 Parser.eatToEndOfStatement();
3492 }
3493 return false;
3494 }
3495
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003496 if (IDVal == ".cpsetup")
3497 return parseDirectiveCPSetup();
3498
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003499 if (IDVal == ".module")
3500 return parseDirectiveModule();
3501
Rafael Espindola870c4e92012-01-11 03:56:41 +00003502 return true;
3503}
3504
Rafael Espindola870c4e92012-01-11 03:56:41 +00003505extern "C" void LLVMInitializeMipsAsmParser() {
3506 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
3507 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
3508 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
3509 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
3510}
Jack Carterb4dbc172012-09-05 23:34:03 +00003511
3512#define GET_REGISTER_MATCHER
3513#define GET_MATCHER_IMPLEMENTATION
3514#include "MipsGenAsmMatcher.inc"