blob: 6e8639c0914f775d5b17a2916c18866a932b733f [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"
Daniel Sandersef638fe2014-10-03 15:37:37 +000030#include "llvm/Support/SourceMgr.h"
Toma Tabacu9db22db2014-09-09 10:15:38 +000031#include <memory>
Rafael Espindola870c4e92012-01-11 03:56:41 +000032
33using namespace llvm;
34
Chandler Carruthe96dd892014-04-21 22:55:11 +000035#define DEBUG_TYPE "mips-asm-parser"
36
Joey Gouly0e76fa72013-09-12 10:28:05 +000037namespace llvm {
38class MCInstrInfo;
39}
40
Rafael Espindola870c4e92012-01-11 03:56:41 +000041namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000042class MipsAssemblerOptions {
43public:
Toma Tabacu9db22db2014-09-09 10:15:38 +000044 MipsAssemblerOptions(uint64_t Features_) :
45 ATReg(1), Reorder(true), Macro(true), Features(Features_) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000046
Toma Tabacu9db22db2014-09-09 10:15:38 +000047 MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
48 ATReg = Opts->getATRegNum();
49 Reorder = Opts->isReorder();
50 Macro = Opts->isMacro();
51 Features = Opts->getFeatures();
52 }
53
54 unsigned getATRegNum() const { return ATReg; }
Jack Carter0b744b32012-10-04 02:29:46 +000055 bool setATReg(unsigned Reg);
56
Toma Tabacu9db22db2014-09-09 10:15:38 +000057 bool isReorder() const { return Reorder; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000058 void setReorder() { Reorder = true; }
59 void setNoReorder() { Reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000060
Toma Tabacu9db22db2014-09-09 10:15:38 +000061 bool isMacro() const { return Macro; }
Toma Tabacu3c24b042014-09-05 15:43:21 +000062 void setMacro() { Macro = true; }
63 void setNoMacro() { Macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000064
Toma Tabacu9db22db2014-09-09 10:15:38 +000065 uint64_t getFeatures() const { return Features; }
66 void setFeatures(uint64_t Features_) { Features = Features_; }
67
Daniel Sandersf0df2212014-08-04 12:20:00 +000068 // Set of features that are either architecture features or referenced
69 // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6).
70 // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]).
71 // The reason we need this mask is explained in the selectArch function.
72 // FIXME: Ideally we would like TableGen to generate this information.
73 static const uint64_t AllArchRelatedMask =
74 Mips::FeatureMips1 | Mips::FeatureMips2 | Mips::FeatureMips3 |
75 Mips::FeatureMips3_32 | Mips::FeatureMips3_32r2 | Mips::FeatureMips4 |
76 Mips::FeatureMips4_32 | Mips::FeatureMips4_32r2 | Mips::FeatureMips5 |
77 Mips::FeatureMips5_32r2 | Mips::FeatureMips32 | Mips::FeatureMips32r2 |
78 Mips::FeatureMips32r6 | Mips::FeatureMips64 | Mips::FeatureMips64r2 |
79 Mips::FeatureMips64r6 | Mips::FeatureCnMips | Mips::FeatureFP64Bit |
80 Mips::FeatureGP64Bit | Mips::FeatureNaN2008;
81
Jack Carter0b744b32012-10-04 02:29:46 +000082private:
Toma Tabacu3c24b042014-09-05 15:43:21 +000083 unsigned ATReg;
84 bool Reorder;
85 bool Macro;
Toma Tabacu9db22db2014-09-09 10:15:38 +000086 uint64_t Features;
Jack Carter0b744b32012-10-04 02:29:46 +000087};
88}
89
90namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +000091class MipsAsmParser : public MCTargetAsmParser {
Rafael Espindolaa17151a2013-10-08 13:08:17 +000092 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola4a1a3602014-01-14 01:21:46 +000093 MCTargetStreamer &TS = *Parser.getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +000094 return static_cast<MipsTargetStreamer &>(TS);
95 }
96
Jack Carterb4dbc172012-09-05 23:34:03 +000097 MCSubtargetInfo &STI;
98 MCAsmParser &Parser;
Toma Tabacu9db22db2014-09-09 10:15:38 +000099 SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;
Daniel Sandersd97a6342014-08-13 10:07:34 +0000100 MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
101 // nullptr, which indicates that no function is currently
102 // selected. This usually happens after an '.end func'
103 // directive.
Jack Carter0b744b32012-10-04 02:29:46 +0000104
Daniel Sandersef638fe2014-10-03 15:37:37 +0000105 // Print a warning along with its fix-it message at the given range.
106 void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
107 SMRange Range, bool ShowColors = true);
108
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000109#define GET_ASSEMBLER_HEADER
110#include "MipsGenAsmMatcher.inc"
111
Matheus Almeida595fcab2014-06-11 15:05:56 +0000112 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
113
Chad Rosier49963552012-10-13 00:26:04 +0000114 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000115 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000116 uint64_t &ErrorInfo,
Craig Topper56c590a2014-04-29 07:58:02 +0000117 bool MatchingInlineAsm) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000118
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000119 /// Parse a register as used in CFI directives
Craig Topper56c590a2014-04-29 07:58:02 +0000120 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000121
Toma Tabacu13964452014-09-04 13:23:44 +0000122 bool parseParenSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000123
Toma Tabacu13964452014-09-04 13:23:44 +0000124 bool parseBracketSuffix(StringRef Name, OperandVector &Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000125
David Blaikie960ea3f2014-06-08 16:18:35 +0000126 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
127 SMLoc NameLoc, OperandVector &Operands) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000128
Craig Topper56c590a2014-04-29 07:58:02 +0000129 bool ParseDirective(AsmToken DirectiveID) override;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000130
David Blaikie960ea3f2014-06-08 16:18:35 +0000131 MipsAsmParser::OperandMatchResultTy parseMemOperand(OperandVector &Operands);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000132
133 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000134 matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +0000135 StringRef Identifier, SMLoc S);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000136
Jack Carter873c7242013-01-12 01:03:14 +0000137 MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +0000138 matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S);
Jack Carter873c7242013-01-12 01:03:14 +0000139
Toma Tabacu13964452014-09-04 13:23:44 +0000140 MipsAsmParser::OperandMatchResultTy parseAnyRegister(OperandVector &Operands);
Jack Carter873c7242013-01-12 01:03:14 +0000141
Toma Tabacu13964452014-09-04 13:23:44 +0000142 MipsAsmParser::OperandMatchResultTy parseImm(OperandVector &Operands);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000143
Toma Tabacu13964452014-09-04 13:23:44 +0000144 MipsAsmParser::OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
Vladimir Medic2b953d02013-10-01 09:48:56 +0000145
David Blaikie960ea3f2014-06-08 16:18:35 +0000146 MipsAsmParser::OperandMatchResultTy parseInvNum(OperandVector &Operands);
Matheus Almeida779c5932013-11-18 12:32:49 +0000147
Toma Tabacu13964452014-09-04 13:23:44 +0000148 MipsAsmParser::OperandMatchResultTy parseLSAImm(OperandVector &Operands);
Jack Carterd76b2372013-03-21 21:44:16 +0000149
David Blaikie960ea3f2014-06-08 16:18:35 +0000150 bool searchSymbolAlias(OperandVector &Operands);
151
Toma Tabacu13964452014-09-04 13:23:44 +0000152 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000153
Jack Carter30a59822012-10-04 04:03:53 +0000154 bool needsExpansion(MCInst &Inst);
155
Matheus Almeida3813d572014-06-19 14:39:14 +0000156 // Expands assembly pseudo instructions.
157 // Returns false on success, true otherwise.
158 bool expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000159 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000160
161 bool expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000162 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000163
164 bool expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000165 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000166
167 bool expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
Jack Carter543fdf82012-10-09 23:29:45 +0000168 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeida3813d572014-06-19 14:39:14 +0000169
Toma Tabacu0d64b202014-08-14 10:29:17 +0000170 void expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
171 SmallVectorImpl<MCInst> &Instructions);
172
Jack Carter9e65aa32013-03-22 00:05:30 +0000173 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000174 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
175 bool isImmOpnd);
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000176 bool reportParseError(Twine ErrorMsg);
177 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +0000178
Jack Carterb5cf5902013-04-17 00:18:04 +0000179 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000180 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000181
Vladimir Medic4c299852013-11-06 11:27:05 +0000182 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000183
184 bool isEvaluated(const MCExpr *Expr);
Toma Tabacu26647792014-09-09 12:52:14 +0000185 bool parseSetMips0Directive();
Toma Tabacu85618b32014-08-19 14:22:52 +0000186 bool parseSetArchDirective();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000187 bool parseSetFeature(uint64_t Feature);
Toma Tabacuc4c202a2014-10-01 14:53:19 +0000188 bool parseDirectiveCpLoad(SMLoc Loc);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000189 bool parseDirectiveCPSetup();
Matheus Almeida0051f2d2014-04-16 15:48:55 +0000190 bool parseDirectiveNaN();
Jack Carter0b744b32012-10-04 02:29:46 +0000191 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000192 bool parseDirectiveOption();
Jack Carter0b744b32012-10-04 02:29:46 +0000193
194 bool parseSetAtDirective();
195 bool parseSetNoAtDirective();
196 bool parseSetMacroDirective();
197 bool parseSetNoMacroDirective();
Daniel Sanders44934432014-08-07 12:03:36 +0000198 bool parseSetMsaDirective();
199 bool parseSetNoMsaDirective();
Toma Tabacu351b2fe2014-09-17 09:01:54 +0000200 bool parseSetNoDspDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000201 bool parseSetReorderDirective();
202 bool parseSetNoReorderDirective();
Jack Carter39536722014-01-22 23:08:42 +0000203 bool parseSetNoMips16Directive();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000204 bool parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +0000205 bool parseSetPopDirective();
206 bool parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +0000207
Jack Carterd76b2372013-03-21 21:44:16 +0000208 bool parseSetAssignment();
209
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000210 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000211 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000212 bool parseDirectiveGpDWord();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000213 bool parseDirectiveModule();
Daniel Sandersc7dbc632014-07-08 10:11:38 +0000214 bool parseDirectiveModuleFP();
Daniel Sanders7e527422014-07-10 13:38:23 +0000215 bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
216 StringRef Directive);
Jack Carter07c818d2013-01-25 01:31:34 +0000217
Jack Carterdc1e35d2012-09-06 20:00:02 +0000218 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000219
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000220 bool eatComma(StringRef ErrorStr);
221
Jack Carter1ac53222013-02-20 23:11:17 +0000222 int matchCPURegisterName(StringRef Symbol);
223
Jack Carter873c7242013-01-12 01:03:14 +0000224 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000225
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000226 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000227
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000228 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000229
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000230 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000231
Jack Carter5dc8ac92013-09-25 23:50:44 +0000232 int matchMSA128RegisterName(StringRef Name);
233
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000234 int matchMSA128CtrlRegisterName(StringRef Name);
235
Jack Carterd0bd6422013-04-18 00:41:53 +0000236 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000237
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000238 unsigned getGPR(int RegNo);
239
Matheus Almeida7de68e72014-06-18 14:46:05 +0000240 int getATReg(SMLoc Loc);
Jack Carter9e65aa32013-03-22 00:05:30 +0000241
242 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000243 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000244
245 // Helper function that checks if the value of a vector index is within the
246 // boundaries of accepted values for each RegisterKind
247 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
248 bool validateMSAIndex(int Val, int RegKind);
249
Daniel Sandersf0df2212014-08-04 12:20:00 +0000250 // Selects a new architecture by updating the FeatureBits with the necessary
251 // info including implied dependencies.
252 // Internally, it clears all the feature bits related to *any* architecture
253 // and selects the new one using the ToggleFeature functionality of the
254 // MCSubtargetInfo object that handles implied dependencies. The reason we
255 // clear all the arch related bits manually is because ToggleFeature only
256 // clears the features that imply the feature being cleared and not the
257 // features implied by the feature being cleared. This is easier to see
258 // with an example:
259 // --------------------------------------------------
260 // | Feature | Implies |
261 // | -------------------------------------------------|
262 // | FeatureMips1 | None |
263 // | FeatureMips2 | FeatureMips1 |
264 // | FeatureMips3 | FeatureMips2 | FeatureMipsGP64 |
265 // | FeatureMips4 | FeatureMips3 |
266 // | ... | |
267 // --------------------------------------------------
268 //
269 // Setting Mips3 is equivalent to set: (FeatureMips3 | FeatureMips2 |
270 // FeatureMipsGP64 | FeatureMips1)
271 // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4).
272 void selectArch(StringRef ArchFeature) {
273 uint64_t FeatureBits = STI.getFeatureBits();
274 FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask;
275 STI.setFeatureBits(FeatureBits);
276 setAvailableFeatures(
277 ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature)));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000278 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Daniel Sandersf0df2212014-08-04 12:20:00 +0000279 }
280
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000281 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
Vladimir Medic615b26e2014-03-04 09:54:09 +0000282 if (!(STI.getFeatureBits() & Feature)) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000283 setAvailableFeatures(
284 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000285 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000286 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000287 }
288
Toma Tabacu901ba6e2014-09-05 16:32:09 +0000289 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
Vladimir Medic615b26e2014-03-04 09:54:09 +0000290 if (STI.getFeatureBits() & Feature) {
Matheus Almeida2852af82014-04-22 10:15:54 +0000291 setAvailableFeatures(
292 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
Vladimir Medic615b26e2014-03-04 09:54:09 +0000293 }
Toma Tabacu9db22db2014-09-09 10:15:38 +0000294 AssemblerOptions.back()->setFeatures(getAvailableFeatures());
Vladimir Medic615b26e2014-03-04 09:54:09 +0000295 }
296
Rafael Espindola870c4e92012-01-11 03:56:41 +0000297public:
Matheus Almeida595fcab2014-06-11 15:05:56 +0000298 enum MipsMatchResultTy {
299 Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
300#define GET_OPERAND_DIAGNOSTIC_TYPES
301#include "MipsGenAsmMatcher.inc"
302#undef GET_OPERAND_DIAGNOSTIC_TYPES
303
304 };
305
Joey Gouly0e76fa72013-09-12 10:28:05 +0000306 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000307 const MCInstrInfo &MII, const MCTargetOptions &Options)
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000308 : MCTargetAsmParser(), STI(sti), Parser(parser) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000309 // Initialize the set of available features.
310 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000311
312 // Remember the initial assembler options. The user can not modify these.
Craig Topperfec61ef2014-09-12 05:17:20 +0000313 AssemblerOptions.push_back(
314 make_unique<MipsAssemblerOptions>(getAvailableFeatures()));
Toma Tabacu9db22db2014-09-09 10:15:38 +0000315
316 // Create an assembler options environment for the user to modify.
Craig Topperfec61ef2014-09-12 05:17:20 +0000317 AssemblerOptions.push_back(
318 make_unique<MipsAssemblerOptions>(getAvailableFeatures()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000319
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000320 getTargetStreamer().updateABIInfo(*this);
321
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000322 // Assert exactly one ABI was chosen.
323 assert((((STI.getFeatureBits() & Mips::FeatureO32) != 0) +
324 ((STI.getFeatureBits() & Mips::FeatureEABI) != 0) +
325 ((STI.getFeatureBits() & Mips::FeatureN32) != 0) +
326 ((STI.getFeatureBits() & Mips::FeatureN64) != 0)) == 1);
Daniel Sanders7e527422014-07-10 13:38:23 +0000327
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000328 if (!isABI_O32() && !useOddSPReg() != 0)
Daniel Sanders7e527422014-07-10 13:38:23 +0000329 report_fatal_error("-mno-odd-spreg requires the O32 ABI");
Daniel Sandersd97a6342014-08-13 10:07:34 +0000330
331 CurrentFn = nullptr;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000332 }
333
Jack Carterb4dbc172012-09-05 23:34:03 +0000334 MCAsmParser &getParser() const { return Parser; }
335 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000336
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000337 /// True if all of $fcc0 - $fcc7 exist for the current ISA.
338 bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); }
339
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000340 bool isGP64bit() const { return STI.getFeatureBits() & Mips::FeatureGP64Bit; }
341 bool isFP64bit() const { return STI.getFeatureBits() & Mips::FeatureFP64Bit; }
342 bool isABI_N32() const { return STI.getFeatureBits() & Mips::FeatureN32; }
343 bool isABI_N64() const { return STI.getFeatureBits() & Mips::FeatureN64; }
344 bool isABI_O32() const { return STI.getFeatureBits() & Mips::FeatureO32; }
Daniel Sandersa6e125f2014-07-15 15:31:39 +0000345 bool isABI_FPXX() const { return STI.getFeatureBits() & Mips::FeatureFPXX; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000346
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000347 bool useOddSPReg() const {
Daniel Sanders7e527422014-07-10 13:38:23 +0000348 return !(STI.getFeatureBits() & Mips::FeatureNoOddSPReg);
349 }
350
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000351 bool inMicroMipsMode() const {
352 return STI.getFeatureBits() & Mips::FeatureMicroMips;
353 }
354 bool hasMips1() const { return STI.getFeatureBits() & Mips::FeatureMips1; }
355 bool hasMips2() const { return STI.getFeatureBits() & Mips::FeatureMips2; }
356 bool hasMips3() const { return STI.getFeatureBits() & Mips::FeatureMips3; }
357 bool hasMips4() const { return STI.getFeatureBits() & Mips::FeatureMips4; }
358 bool hasMips5() const { return STI.getFeatureBits() & Mips::FeatureMips5; }
359 bool hasMips32() const {
360 return (STI.getFeatureBits() & Mips::FeatureMips32);
361 }
362 bool hasMips64() const {
363 return (STI.getFeatureBits() & Mips::FeatureMips64);
364 }
365 bool hasMips32r2() const {
366 return (STI.getFeatureBits() & Mips::FeatureMips32r2);
367 }
368 bool hasMips64r2() const {
369 return (STI.getFeatureBits() & Mips::FeatureMips64r2);
370 }
371 bool hasMips32r6() const {
372 return (STI.getFeatureBits() & Mips::FeatureMips32r6);
373 }
374 bool hasMips64r6() const {
375 return (STI.getFeatureBits() & Mips::FeatureMips64r6);
376 }
377 bool hasDSP() const { return (STI.getFeatureBits() & Mips::FeatureDSP); }
378 bool hasDSPR2() const { return (STI.getFeatureBits() & Mips::FeatureDSPR2); }
379 bool hasMSA() const { return (STI.getFeatureBits() & Mips::FeatureMSA); }
380
381 bool inMips16Mode() const {
382 return STI.getFeatureBits() & Mips::FeatureMips16;
383 }
384 // TODO: see how can we get this info.
Eric Christopher7394e232014-07-18 00:08:50 +0000385 bool abiUsesSoftFloat() const { return false; }
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000386
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000387 /// Warn if RegNo is the current assembler temporary.
Toma Tabacu13964452014-09-04 13:23:44 +0000388 void warnIfAssemblerTemporary(int RegNo, SMLoc Loc);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000389};
390}
391
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000392namespace {
393
394/// MipsOperand - Instances of this class represent a parsed Mips machine
395/// instruction.
396class MipsOperand : public MCParsedAsmOperand {
Daniel Sanderse34a1202014-03-31 18:51:43 +0000397public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000398 /// Broad categories of register classes
399 /// The exact class is finalized by the render method.
400 enum RegKind {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000401 RegKind_GPR = 1, /// GPR32 and GPR64 (depending on isGP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000402 RegKind_FGR = 2, /// FGR32, FGR64, AFGR64 (depending on context and
Vladimir Medicfb8a2a92014-07-08 08:59:22 +0000403 /// isFP64bit())
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000404 RegKind_FCC = 4, /// FCC
405 RegKind_MSA128 = 8, /// MSA128[BHWD] (makes no difference which)
406 RegKind_MSACtrl = 16, /// MSA control registers
407 RegKind_COP2 = 32, /// COP2
408 RegKind_ACC = 64, /// HI32DSP, LO32DSP, and ACC64DSP (depending on
409 /// context).
410 RegKind_CCR = 128, /// CCR
411 RegKind_HWRegs = 256, /// HWRegs
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000412 RegKind_COP3 = 512, /// COP3
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000413
414 /// Potentially any (e.g. $1)
415 RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
416 RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000417 RegKind_CCR | RegKind_HWRegs | RegKind_COP3
Jack Carter873c7242013-01-12 01:03:14 +0000418 };
419
420private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000421 enum KindTy {
Daniel Sanders21bce302014-04-01 12:35:23 +0000422 k_Immediate, /// An immediate (possibly involving symbol references)
423 k_Memory, /// Base + Offset Memory Address
424 k_PhysRegister, /// A physical register from the Mips namespace
425 k_RegisterIndex, /// A register index in one or more RegKind.
426 k_Token /// A simple token
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000427 } Kind;
428
David Blaikie960ea3f2014-06-08 16:18:35 +0000429public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000430 MipsOperand(KindTy K, MipsAsmParser &Parser)
431 : MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
432
David Blaikie960ea3f2014-06-08 16:18:35 +0000433private:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000434 /// For diagnostics, and checking the assembler temporary
435 MipsAsmParser &AsmParser;
Jack Carterb4dbc172012-09-05 23:34:03 +0000436
Eric Christopher8996c5d2013-03-15 00:42:55 +0000437 struct Token {
438 const char *Data;
439 unsigned Length;
440 };
441
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000442 struct PhysRegOp {
443 unsigned Num; /// Register Number
444 };
445
446 struct RegIdxOp {
447 unsigned Index; /// Index into the register class
448 RegKind Kind; /// Bitfield of the kinds it could possibly be
449 const MCRegisterInfo *RegInfo;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000450 };
451
452 struct ImmOp {
453 const MCExpr *Val;
454 };
455
456 struct MemOp {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000457 MipsOperand *Base;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000458 const MCExpr *Off;
459 };
460
Jack Carterb4dbc172012-09-05 23:34:03 +0000461 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000462 struct Token Tok;
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000463 struct PhysRegOp PhysReg;
464 struct RegIdxOp RegIdx;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000465 struct ImmOp Imm;
466 struct MemOp Mem;
Jack Carterb4dbc172012-09-05 23:34:03 +0000467 };
468
469 SMLoc StartLoc, EndLoc;
470
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000471 /// Internal constructor for register kinds
David Blaikie960ea3f2014-06-08 16:18:35 +0000472 static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
473 const MCRegisterInfo *RegInfo,
474 SMLoc S, SMLoc E,
475 MipsAsmParser &Parser) {
476 auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000477 Op->RegIdx.Index = Index;
478 Op->RegIdx.RegInfo = RegInfo;
479 Op->RegIdx.Kind = RegKind;
480 Op->StartLoc = S;
481 Op->EndLoc = E;
482 return Op;
483 }
484
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000485public:
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000486 /// Coerce the register to GPR32 and return the real register for the current
487 /// target.
488 unsigned getGPR32Reg() const {
489 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
Toma Tabacu13964452014-09-04 13:23:44 +0000490 AsmParser.warnIfAssemblerTemporary(RegIdx.Index, StartLoc);
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000491 unsigned ClassID = Mips::GPR32RegClassID;
492 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000493 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000494
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000495 /// Coerce the register to GPR32 and return the real register for the current
496 /// target.
497 unsigned getGPRMM16Reg() const {
498 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
499 unsigned ClassID = Mips::GPR32RegClassID;
500 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
501 }
502
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000503 /// Coerce the register to GPR64 and return the real register for the current
504 /// target.
505 unsigned getGPR64Reg() const {
506 assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!");
507 unsigned ClassID = Mips::GPR64RegClassID;
508 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000509 }
510
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000511private:
512 /// Coerce the register to AFGR64 and return the real register for the current
513 /// target.
514 unsigned getAFGR64Reg() const {
515 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
516 if (RegIdx.Index % 2 != 0)
517 AsmParser.Warning(StartLoc, "Float register should be even.");
518 return RegIdx.RegInfo->getRegClass(Mips::AFGR64RegClassID)
519 .getRegister(RegIdx.Index / 2);
520 }
521
522 /// Coerce the register to FGR64 and return the real register for the current
523 /// target.
524 unsigned getFGR64Reg() const {
525 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
526 return RegIdx.RegInfo->getRegClass(Mips::FGR64RegClassID)
527 .getRegister(RegIdx.Index);
528 }
529
530 /// Coerce the register to FGR32 and return the real register for the current
531 /// target.
532 unsigned getFGR32Reg() const {
533 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
534 return RegIdx.RegInfo->getRegClass(Mips::FGR32RegClassID)
535 .getRegister(RegIdx.Index);
536 }
537
538 /// Coerce the register to FGRH32 and return the real register for the current
539 /// target.
540 unsigned getFGRH32Reg() const {
541 assert(isRegIdx() && (RegIdx.Kind & RegKind_FGR) && "Invalid access!");
542 return RegIdx.RegInfo->getRegClass(Mips::FGRH32RegClassID)
543 .getRegister(RegIdx.Index);
544 }
545
546 /// Coerce the register to FCC and return the real register for the current
547 /// target.
548 unsigned getFCCReg() const {
549 assert(isRegIdx() && (RegIdx.Kind & RegKind_FCC) && "Invalid access!");
550 return RegIdx.RegInfo->getRegClass(Mips::FCCRegClassID)
551 .getRegister(RegIdx.Index);
552 }
553
554 /// Coerce the register to MSA128 and return the real register for the current
555 /// target.
556 unsigned getMSA128Reg() const {
557 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSA128) && "Invalid access!");
558 // It doesn't matter which of the MSA128[BHWD] classes we use. They are all
559 // identical
560 unsigned ClassID = Mips::MSA128BRegClassID;
561 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
562 }
563
564 /// Coerce the register to MSACtrl and return the real register for the
565 /// current target.
566 unsigned getMSACtrlReg() const {
567 assert(isRegIdx() && (RegIdx.Kind & RegKind_MSACtrl) && "Invalid access!");
568 unsigned ClassID = Mips::MSACtrlRegClassID;
569 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
570 }
571
572 /// Coerce the register to COP2 and return the real register for the
573 /// current target.
574 unsigned getCOP2Reg() const {
575 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP2) && "Invalid access!");
576 unsigned ClassID = Mips::COP2RegClassID;
577 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
578 }
579
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000580 /// Coerce the register to COP3 and return the real register for the
581 /// current target.
582 unsigned getCOP3Reg() const {
583 assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
584 unsigned ClassID = Mips::COP3RegClassID;
585 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
586 }
587
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000588 /// Coerce the register to ACC64DSP and return the real register for the
589 /// current target.
590 unsigned getACC64DSPReg() const {
591 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
592 unsigned ClassID = Mips::ACC64DSPRegClassID;
593 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
594 }
595
596 /// Coerce the register to HI32DSP and return the real register for the
597 /// current target.
598 unsigned getHI32DSPReg() const {
599 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
600 unsigned ClassID = Mips::HI32DSPRegClassID;
601 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
602 }
603
604 /// Coerce the register to LO32DSP and return the real register for the
605 /// current target.
606 unsigned getLO32DSPReg() const {
607 assert(isRegIdx() && (RegIdx.Kind & RegKind_ACC) && "Invalid access!");
608 unsigned ClassID = Mips::LO32DSPRegClassID;
609 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
610 }
611
612 /// Coerce the register to CCR and return the real register for the
613 /// current target.
614 unsigned getCCRReg() const {
615 assert(isRegIdx() && (RegIdx.Kind & RegKind_CCR) && "Invalid access!");
616 unsigned ClassID = Mips::CCRRegClassID;
617 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
618 }
619
620 /// Coerce the register to HWRegs and return the real register for the
621 /// current target.
622 unsigned getHWRegsReg() const {
623 assert(isRegIdx() && (RegIdx.Kind & RegKind_HWRegs) && "Invalid access!");
624 unsigned ClassID = Mips::HWRegsRegClassID;
625 return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
626 }
627
628public:
Vladimir Medic4c299852013-11-06 11:27:05 +0000629 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000630 // Add as immediate when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +0000631 if (!Expr)
Jack Carterb4dbc172012-09-05 23:34:03 +0000632 Inst.addOperand(MCOperand::CreateImm(0));
633 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
634 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
635 else
636 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000637 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000638
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000639 void addRegOperands(MCInst &Inst, unsigned N) const {
640 llvm_unreachable("Use a custom parser instead");
641 }
642
Daniel Sanders21bce302014-04-01 12:35:23 +0000643 /// Render the operand to an MCInst as a GPR32
644 /// Asserts if the wrong number of operands are requested, or the operand
645 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000646 void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const {
647 assert(N == 1 && "Invalid number of operands!");
648 Inst.addOperand(MCOperand::CreateReg(getGPR32Reg()));
649 }
650
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000651 void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const {
652 assert(N == 1 && "Invalid number of operands!");
653 Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg()));
654 }
655
Daniel Sanders21bce302014-04-01 12:35:23 +0000656 /// Render the operand to an MCInst as a GPR64
657 /// Asserts if the wrong number of operands are requested, or the operand
658 /// is not a k_RegisterIndex compatible with RegKind_GPR
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000659 void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const {
660 assert(N == 1 && "Invalid number of operands!");
661 Inst.addOperand(MCOperand::CreateReg(getGPR64Reg()));
662 }
663
664 void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
665 assert(N == 1 && "Invalid number of operands!");
666 Inst.addOperand(MCOperand::CreateReg(getAFGR64Reg()));
667 }
668
669 void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const {
670 assert(N == 1 && "Invalid number of operands!");
671 Inst.addOperand(MCOperand::CreateReg(getFGR64Reg()));
672 }
673
674 void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const {
675 assert(N == 1 && "Invalid number of operands!");
676 Inst.addOperand(MCOperand::CreateReg(getFGR32Reg()));
Daniel Sanders7e527422014-07-10 13:38:23 +0000677 // FIXME: We ought to do this for -integrated-as without -via-file-asm too.
Daniel Sanders9ee2aee2014-07-14 10:26:15 +0000678 if (!AsmParser.useOddSPReg() && RegIdx.Index & 1)
Daniel Sanders7e527422014-07-10 13:38:23 +0000679 AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU "
680 "registers");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000681 }
682
683 void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const {
684 assert(N == 1 && "Invalid number of operands!");
685 Inst.addOperand(MCOperand::CreateReg(getFGRH32Reg()));
686 }
687
688 void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const {
689 assert(N == 1 && "Invalid number of operands!");
690 Inst.addOperand(MCOperand::CreateReg(getFCCReg()));
691 }
692
693 void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const {
694 assert(N == 1 && "Invalid number of operands!");
695 Inst.addOperand(MCOperand::CreateReg(getMSA128Reg()));
696 }
697
698 void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const {
699 assert(N == 1 && "Invalid number of operands!");
700 Inst.addOperand(MCOperand::CreateReg(getMSACtrlReg()));
701 }
702
703 void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const {
704 assert(N == 1 && "Invalid number of operands!");
705 Inst.addOperand(MCOperand::CreateReg(getCOP2Reg()));
706 }
707
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000708 void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
709 assert(N == 1 && "Invalid number of operands!");
710 Inst.addOperand(MCOperand::CreateReg(getCOP3Reg()));
711 }
712
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000713 void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
714 assert(N == 1 && "Invalid number of operands!");
715 Inst.addOperand(MCOperand::CreateReg(getACC64DSPReg()));
716 }
717
718 void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
719 assert(N == 1 && "Invalid number of operands!");
720 Inst.addOperand(MCOperand::CreateReg(getHI32DSPReg()));
721 }
722
723 void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
724 assert(N == 1 && "Invalid number of operands!");
725 Inst.addOperand(MCOperand::CreateReg(getLO32DSPReg()));
726 }
727
728 void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const {
729 assert(N == 1 && "Invalid number of operands!");
730 Inst.addOperand(MCOperand::CreateReg(getCCRReg()));
731 }
732
733 void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const {
734 assert(N == 1 && "Invalid number of operands!");
735 Inst.addOperand(MCOperand::CreateReg(getHWRegsReg()));
736 }
737
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000738 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000739 assert(N == 1 && "Invalid number of operands!");
740 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000741 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000742 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000743
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000744 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000745 assert(N == 2 && "Invalid number of operands!");
746
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000747 Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPR32Reg()));
Jack Carterdc1e35d2012-09-06 20:00:02 +0000748
749 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000750 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000751 }
752
Craig Topper56c590a2014-04-29 07:58:02 +0000753 bool isReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000754 // As a special case until we sort out the definition of div/divu, pretend
755 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
756 if (isGPRAsmReg() && RegIdx.Index == 0)
757 return true;
758
759 return Kind == k_PhysRegister;
760 }
761 bool isRegIdx() const { return Kind == k_RegisterIndex; }
Craig Topper56c590a2014-04-29 07:58:02 +0000762 bool isImm() const override { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000763 bool isConstantImm() const {
764 return isImm() && dyn_cast<MCConstantExpr>(getImm());
765 }
Craig Topper56c590a2014-04-29 07:58:02 +0000766 bool isToken() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000767 // Note: It's not possible to pretend that other operand kinds are tokens.
768 // The matcher emitter checks tokens first.
769 return Kind == k_Token;
770 }
Craig Topper56c590a2014-04-29 07:58:02 +0000771 bool isMem() const override { return Kind == k_Memory; }
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000772 bool isConstantMemOff() const {
773 return isMem() && dyn_cast<MCConstantExpr>(getMemOff());
774 }
775 template <unsigned Bits> bool isMemWithSimmOffset() const {
776 return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff());
777 }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000778 bool isInvNum() const { return Kind == k_Immediate; }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000779 bool isLSAImm() const {
780 if (!isConstantImm())
781 return false;
782 int64_t Val = getConstantImm();
783 return 1 <= Val && Val <= 4;
784 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000785
786 StringRef getToken() const {
787 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000788 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000789 }
790
Craig Topper56c590a2014-04-29 07:58:02 +0000791 unsigned getReg() const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000792 // As a special case until we sort out the definition of div/divu, pretend
793 // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
794 if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
795 RegIdx.Kind & RegKind_GPR)
796 return getGPR32Reg(); // FIXME: GPR64 too
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000797
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000798 assert(Kind == k_PhysRegister && "Invalid access!");
799 return PhysReg.Num;
Jack Carter873c7242013-01-12 01:03:14 +0000800 }
801
Jack Carterb4dbc172012-09-05 23:34:03 +0000802 const MCExpr *getImm() const {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000803 assert((Kind == k_Immediate) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000804 return Imm.Val;
805 }
806
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000807 int64_t getConstantImm() const {
808 const MCExpr *Val = getImm();
809 return static_cast<const MCConstantExpr *>(Val)->getValue();
810 }
811
812 MipsOperand *getMemBase() const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000813 assert((Kind == k_Memory) && "Invalid access!");
814 return Mem.Base;
815 }
816
817 const MCExpr *getMemOff() const {
818 assert((Kind == k_Memory) && "Invalid access!");
819 return Mem.Off;
820 }
821
Daniel Sanders5e6f54e2014-06-16 10:00:45 +0000822 int64_t getConstantMemOff() const {
823 return static_cast<const MCConstantExpr *>(getMemOff())->getValue();
824 }
825
David Blaikie960ea3f2014-06-08 16:18:35 +0000826 static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
827 MipsAsmParser &Parser) {
828 auto Op = make_unique<MipsOperand>(k_Token, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000829 Op->Tok.Data = Str.data();
830 Op->Tok.Length = Str.size();
831 Op->StartLoc = S;
832 Op->EndLoc = S;
833 return Op;
834 }
835
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000836 /// Create a numeric register (e.g. $1). The exact register remains
837 /// unresolved until an instruction successfully matches
David Blaikie960ea3f2014-06-08 16:18:35 +0000838 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000839 createNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +0000840 SMLoc E, MipsAsmParser &Parser) {
Toma Tabacu13964452014-09-04 13:23:44 +0000841 DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000842 return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000843 }
844
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000845 /// Create a register that is definitely a GPR.
846 /// This is typically only used for named registers such as $gp.
David Blaikie960ea3f2014-06-08 16:18:35 +0000847 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000848 createGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000849 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000850 return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000851 }
852
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000853 /// Create a register that is definitely a FGR.
854 /// This is typically only used for named registers such as $f0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000855 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000856 createFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000857 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000858 return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
859 }
860
861 /// Create a register that is definitely an FCC.
862 /// This is typically only used for named registers such as $fcc0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000863 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000864 createFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000865 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000866 return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
867 }
868
869 /// Create a register that is definitely an ACC.
870 /// This is typically only used for named registers such as $ac0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000871 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000872 createACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
David Blaikie960ea3f2014-06-08 16:18:35 +0000873 MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000874 return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
875 }
876
877 /// Create a register that is definitely an MSA128.
878 /// This is typically only used for named registers such as $w0.
David Blaikie960ea3f2014-06-08 16:18:35 +0000879 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000880 createMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +0000881 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000882 return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
883 }
884
885 /// Create a register that is definitely an MSACtrl.
886 /// This is typically only used for named registers such as $msaaccess.
David Blaikie960ea3f2014-06-08 16:18:35 +0000887 static std::unique_ptr<MipsOperand>
Toma Tabacu13964452014-09-04 13:23:44 +0000888 createMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +0000889 SMLoc E, MipsAsmParser &Parser) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000890 return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
891 }
892
David Blaikie960ea3f2014-06-08 16:18:35 +0000893 static std::unique_ptr<MipsOperand>
894 CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
895 auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Jack Carterb4dbc172012-09-05 23:34:03 +0000896 Op->Imm.Val = Val;
897 Op->StartLoc = S;
898 Op->EndLoc = E;
899 return Op;
900 }
901
David Blaikie960ea3f2014-06-08 16:18:35 +0000902 static std::unique_ptr<MipsOperand>
903 CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
904 SMLoc E, MipsAsmParser &Parser) {
905 auto Op = make_unique<MipsOperand>(k_Memory, Parser);
906 Op->Mem.Base = Base.release();
Jack Carterdc1e35d2012-09-06 20:00:02 +0000907 Op->Mem.Off = Off;
908 Op->StartLoc = S;
909 Op->EndLoc = E;
910 return Op;
911 }
912
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000913 bool isGPRAsmReg() const {
914 return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000915 }
Zoran Jovanovicb0852e52014-10-21 08:23:11 +0000916 bool isMM16AsmReg() const {
917 if (!(isRegIdx() && RegIdx.Kind))
918 return false;
919 return ((RegIdx.Index >= 2 && RegIdx.Index <= 7)
920 || RegIdx.Index == 16 || RegIdx.Index == 17);
921 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000922 bool isFGRAsmReg() const {
923 // AFGR64 is $0-$15 but we handle this in getAFGR64()
924 return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000925 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000926 bool isHWRegsAsmReg() const {
927 return isRegIdx() && RegIdx.Kind & RegKind_HWRegs && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000928 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000929 bool isCCRAsmReg() const {
930 return isRegIdx() && RegIdx.Kind & RegKind_CCR && RegIdx.Index <= 31;
Jack Carter873c7242013-01-12 01:03:14 +0000931 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000932 bool isFCCAsmReg() const {
Daniel Sanders3d3ea532014-06-12 15:00:17 +0000933 if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
934 return false;
935 if (!AsmParser.hasEightFccRegisters())
936 return RegIdx.Index == 0;
937 return RegIdx.Index <= 7;
Jack Carter873c7242013-01-12 01:03:14 +0000938 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000939 bool isACCAsmReg() const {
940 return isRegIdx() && RegIdx.Kind & RegKind_ACC && RegIdx.Index <= 3;
Vladimir Medic233dd512013-06-24 10:05:34 +0000941 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000942 bool isCOP2AsmReg() const {
943 return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +0000944 }
Daniel Sanderscdbbe082014-05-08 13:02:11 +0000945 bool isCOP3AsmReg() const {
946 return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
947 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000948 bool isMSA128AsmReg() const {
949 return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
Vladimir Medic233dd512013-06-24 10:05:34 +0000950 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000951 bool isMSACtrlAsmReg() const {
952 return isRegIdx() && RegIdx.Kind & RegKind_MSACtrl && RegIdx.Index <= 7;
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000953 }
954
Jack Carterb4dbc172012-09-05 23:34:03 +0000955 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +0000956 SMLoc getStartLoc() const override { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +0000957 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper56c590a2014-04-29 07:58:02 +0000958 SMLoc getEndLoc() const override { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +0000959
NAKAMURA Takumie1f35832014-04-15 14:13:21 +0000960 virtual ~MipsOperand() {
961 switch (Kind) {
962 case k_Immediate:
963 break;
964 case k_Memory:
965 delete Mem.Base;
966 break;
967 case k_PhysRegister:
968 case k_RegisterIndex:
969 case k_Token:
970 break;
971 }
972 }
973
Craig Topper56c590a2014-04-29 07:58:02 +0000974 void print(raw_ostream &OS) const override {
Daniel Sandersb50ccf82014-04-01 10:35:28 +0000975 switch (Kind) {
976 case k_Immediate:
977 OS << "Imm<";
978 Imm.Val->print(OS);
979 OS << ">";
980 break;
981 case k_Memory:
982 OS << "Mem<";
983 Mem.Base->print(OS);
984 OS << ", ";
985 Mem.Off->print(OS);
986 OS << ">";
987 break;
988 case k_PhysRegister:
989 OS << "PhysReg<" << PhysReg.Num << ">";
990 break;
991 case k_RegisterIndex:
992 OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
993 break;
994 case k_Token:
995 OS << Tok.Data;
996 break;
997 }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000998 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000999}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +00001000} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +00001001
Jack Carter9e65aa32013-03-22 00:05:30 +00001002namespace llvm {
1003extern const MCInstrDesc MipsInsts[];
1004}
1005static const MCInstrDesc &getInstDesc(unsigned Opcode) {
1006 return MipsInsts[Opcode];
1007}
1008
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001009static bool hasShortDelaySlot(unsigned Opcode) {
1010 switch (Opcode) {
1011 case Mips::JALS_MM:
1012 case Mips::JALRS_MM:
Zoran Jovanovic6097bad2014-10-10 13:22:28 +00001013 case Mips::JALRS16_MM:
Zoran Jovanoviced6dd6b2014-09-12 13:51:58 +00001014 case Mips::BGEZALS_MM:
1015 case Mips::BLTZALS_MM:
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001016 return true;
1017 default:
1018 return false;
1019 }
1020}
1021
Jack Carter9e65aa32013-03-22 00:05:30 +00001022bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +00001023 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001024 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +00001025
Jack Carter9e65aa32013-03-22 00:05:30 +00001026 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001027
1028 if (MCID.isBranch() || MCID.isCall()) {
1029 const unsigned Opcode = Inst.getOpcode();
1030 MCOperand Offset;
1031
1032 switch (Opcode) {
1033 default:
1034 break;
1035 case Mips::BEQ:
1036 case Mips::BNE:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001037 case Mips::BEQ_MM:
1038 case Mips::BNE_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001039 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001040 Offset = Inst.getOperand(2);
1041 if (!Offset.isImm())
1042 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001043 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001044 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001045 if (OffsetToAlignment(Offset.getImm(),
1046 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001047 return Error(IDLoc, "branch to misaligned address");
1048 break;
1049 case Mips::BGEZ:
1050 case Mips::BGTZ:
1051 case Mips::BLEZ:
1052 case Mips::BLTZ:
1053 case Mips::BGEZAL:
1054 case Mips::BLTZAL:
1055 case Mips::BC1F:
1056 case Mips::BC1T:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001057 case Mips::BGEZ_MM:
1058 case Mips::BGTZ_MM:
1059 case Mips::BLEZ_MM:
1060 case Mips::BLTZ_MM:
1061 case Mips::BGEZAL_MM:
1062 case Mips::BLTZAL_MM:
1063 case Mips::BC1F_MM:
1064 case Mips::BC1T_MM:
Jack Carter3b2c96e2014-01-22 23:31:38 +00001065 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001066 Offset = Inst.getOperand(1);
1067 if (!Offset.isImm())
1068 break; // We'll deal with this situation later on when applying fixups.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001069 if (!isIntN(inMicroMipsMode() ? 17 : 18, Offset.getImm()))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001070 return Error(IDLoc, "branch target out of range");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001071 if (OffsetToAlignment(Offset.getImm(),
1072 1LL << (inMicroMipsMode() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +00001073 return Error(IDLoc, "branch to misaligned address");
1074 break;
1075 }
1076 }
1077
Daniel Sandersa84989a2014-06-16 13:25:35 +00001078 // SSNOP is deprecated on MIPS32r6/MIPS64r6
1079 // We still accept it but it is a normal nop.
1080 if (hasMips32r6() && Inst.getOpcode() == Mips::SSNOP) {
1081 std::string ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
1082 Warning(IDLoc, "ssnop is deprecated for " + ISA + " and is equivalent to a "
1083 "nop instruction");
1084 }
1085
Toma Tabacu9db22db2014-09-09 10:15:38 +00001086 if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
Jack Carterc15c1d22013-04-25 23:31:35 +00001087 // If this instruction has a delay slot and .set reorder is active,
1088 // emit a NOP after it.
1089 Instructions.push_back(Inst);
1090 MCInst NopInst;
Zoran Jovanovicac9ef122014-09-12 13:43:41 +00001091 if (hasShortDelaySlot(Inst.getOpcode())) {
1092 NopInst.setOpcode(Mips::MOVE16_MM);
1093 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1094 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1095 } else {
1096 NopInst.setOpcode(Mips::SLL);
1097 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1098 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
1099 NopInst.addOperand(MCOperand::CreateImm(0));
1100 }
Jack Carterc15c1d22013-04-25 23:31:35 +00001101 Instructions.push_back(NopInst);
1102 return false;
1103 }
1104
Jack Carter9e65aa32013-03-22 00:05:30 +00001105 if (MCID.mayLoad() || MCID.mayStore()) {
1106 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +00001107 // reference or immediate we may have to expand instructions.
1108 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001109 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +00001110 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
1111 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001112 MCOperand &Op = Inst.getOperand(i);
1113 if (Op.isImm()) {
1114 int MemOffset = Op.getImm();
1115 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001116 // Offset can't exceed 16bit value.
1117 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +00001118 return false;
1119 }
1120 } else if (Op.isExpr()) {
1121 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001122 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001123 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +00001124 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +00001125 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001126 // Expand symbol.
1127 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +00001128 return false;
1129 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001130 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001131 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +00001132 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +00001133 }
1134 }
1135 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001136 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +00001137 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +00001138
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001139 // TODO: Handle this with the AsmOperandClass.PredicateMethod.
1140 if (inMicroMipsMode()) {
1141 MCOperand Opnd;
1142 int Imm;
1143
1144 switch (Inst.getOpcode()) {
1145 default:
1146 break;
1147 case Mips::ADDIUS5_MM:
1148 Opnd = Inst.getOperand(2);
1149 if (!Opnd.isImm())
1150 return Error(IDLoc, "expected immediate operand kind");
1151 Imm = Opnd.getImm();
1152 if (Imm < -8 || Imm > 7)
1153 return Error(IDLoc, "immediate operand value out of range");
1154 break;
Zoran Jovanovic98bd58c2014-10-10 14:37:30 +00001155 case Mips::ADDIUSP_MM:
1156 Opnd = Inst.getOperand(0);
1157 if (!Opnd.isImm())
1158 return Error(IDLoc, "expected immediate operand kind");
1159 Imm = Opnd.getImm();
1160 if (Imm < -1032 || Imm > 1028 || (Imm < 8 && Imm > -12) ||
1161 Imm % 4 != 0)
1162 return Error(IDLoc, "immediate operand value out of range");
1163 break;
Zoran Jovanovic4a00fdc2014-10-23 10:42:01 +00001164 case Mips::SLL16_MM:
1165 case Mips::SRL16_MM:
1166 Opnd = Inst.getOperand(2);
1167 if (!Opnd.isImm())
1168 return Error(IDLoc, "expected immediate operand kind");
1169 Imm = Opnd.getImm();
1170 if (Imm < 1 || Imm > 8)
1171 return Error(IDLoc, "immediate operand value out of range");
1172 break;
Zoran Jovanovicb26f8892014-10-10 13:45:34 +00001173 }
1174 }
1175
Jack Carter9e65aa32013-03-22 00:05:30 +00001176 if (needsExpansion(Inst))
Matheus Almeida3813d572014-06-19 14:39:14 +00001177 return expandInstruction(Inst, IDLoc, Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +00001178 else
1179 Instructions.push_back(Inst);
1180
1181 return false;
1182}
1183
Jack Carter30a59822012-10-04 04:03:53 +00001184bool MipsAsmParser::needsExpansion(MCInst &Inst) {
1185
Jack Carterd0bd6422013-04-18 00:41:53 +00001186 switch (Inst.getOpcode()) {
1187 case Mips::LoadImm32Reg:
1188 case Mips::LoadAddr32Imm:
1189 case Mips::LoadAddr32Reg:
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001190 case Mips::LoadImm64Reg:
Jack Carterd0bd6422013-04-18 00:41:53 +00001191 return true;
1192 default:
1193 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001194 }
1195}
Jack Carter92995f12012-10-06 00:53:28 +00001196
Matheus Almeida3813d572014-06-19 14:39:14 +00001197bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001198 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001199 switch (Inst.getOpcode()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001200 default:
1201 assert(0 && "unimplemented expansion");
Matheus Almeida3813d572014-06-19 14:39:14 +00001202 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001203 case Mips::LoadImm32Reg:
1204 return expandLoadImm(Inst, IDLoc, Instructions);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001205 case Mips::LoadImm64Reg:
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001206 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001207 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001208 return true;
1209 }
1210 return expandLoadImm(Inst, IDLoc, Instructions);
Jack Carterd0bd6422013-04-18 00:41:53 +00001211 case Mips::LoadAddr32Imm:
1212 return expandLoadAddressImm(Inst, IDLoc, Instructions);
1213 case Mips::LoadAddr32Reg:
1214 return expandLoadAddressReg(Inst, IDLoc, Instructions);
1215 }
Jack Carter30a59822012-10-04 04:03:53 +00001216}
Jack Carter92995f12012-10-06 00:53:28 +00001217
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001218namespace {
Toma Tabacu0d64b202014-08-14 10:29:17 +00001219template <bool PerformShift>
1220void createShiftOr(MCOperand Operand, unsigned RegNo, SMLoc IDLoc,
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001221 SmallVectorImpl<MCInst> &Instructions) {
1222 MCInst tmpInst;
1223 if (PerformShift) {
1224 tmpInst.setOpcode(Mips::DSLL);
1225 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1226 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1227 tmpInst.addOperand(MCOperand::CreateImm(16));
1228 tmpInst.setLoc(IDLoc);
1229 Instructions.push_back(tmpInst);
1230 tmpInst.clear();
1231 }
1232 tmpInst.setOpcode(Mips::ORi);
1233 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1234 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
Toma Tabacu0d64b202014-08-14 10:29:17 +00001235 tmpInst.addOperand(Operand);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001236 tmpInst.setLoc(IDLoc);
1237 Instructions.push_back(tmpInst);
1238}
Toma Tabacu0d64b202014-08-14 10:29:17 +00001239
1240template <int Shift, bool PerformShift>
1241void createShiftOr(int64_t Value, unsigned RegNo, SMLoc IDLoc,
1242 SmallVectorImpl<MCInst> &Instructions) {
1243 createShiftOr<PerformShift>(
1244 MCOperand::CreateImm(((Value & (0xffffLL << Shift)) >> Shift)), RegNo,
1245 IDLoc, Instructions);
1246}
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001247}
1248
Matheus Almeida3813d572014-06-19 14:39:14 +00001249bool MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +00001250 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +00001251 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +00001252 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +00001253 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +00001254 const MCOperand &RegOp = Inst.getOperand(0);
1255 assert(RegOp.isReg() && "expected register operand kind");
1256
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001257 int64_t ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +00001258 tmpInst.setLoc(IDLoc);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001259 // FIXME: gas has a special case for values that are 000...1111, which
1260 // becomes a li -1 and then a dsrl
Jack Carterd0bd6422013-04-18 00:41:53 +00001261 if (0 <= ImmValue && ImmValue <= 65535) {
1262 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +00001263 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001264 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +00001265 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001266 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001267 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001268 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001269 } else if (ImmValue < 0 && ImmValue >= -32768) {
1270 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +00001271 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +00001272 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +00001273 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001274 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +00001275 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +00001276 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001277 } else if ((ImmValue & 0xffffffff) == ImmValue) {
1278 // For any value of j that is representable as a 32-bit integer, create
1279 // a sequence of:
Jack Carter30a59822012-10-04 04:03:53 +00001280 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +00001281 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001282 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001283 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1284 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +00001285 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001286 createShiftOr<0, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1287 } else if ((ImmValue & (0xffffLL << 48)) == 0) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001288 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001289 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001290 return true;
1291 }
1292
1293 // <------- lo32 ------>
1294 // <------- hi32 ------>
1295 // <- hi16 -> <- lo16 ->
1296 // _________________________________
1297 // | | | |
1298 // | 16-bytes | 16-bytes | 16-bytes |
1299 // |__________|__________|__________|
1300 //
1301 // For any value of j that is representable as a 48-bit integer, create
1302 // a sequence of:
1303 // li d,j => lui d,hi16(j)
1304 // ori d,d,hi16(lo32(j))
1305 // dsll d,d,16
1306 // ori d,d,lo16(lo32(j))
1307 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +00001308 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001309 tmpInst.addOperand(
1310 MCOperand::CreateImm((ImmValue & (0xffffLL << 32)) >> 32));
Jack Carter30a59822012-10-04 04:03:53 +00001311 Instructions.push_back(tmpInst);
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001312 createShiftOr<16, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1313 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1314 } else {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001315 if (!isGP64bit()) {
Toma Tabacu65f10572014-09-16 15:00:52 +00001316 Error(IDLoc, "instruction requires a 64-bit architecture");
Matheus Almeida4f7ef8c2014-06-19 15:08:04 +00001317 return true;
1318 }
1319
1320 // <------- hi32 ------> <------- lo32 ------>
1321 // <- hi16 -> <- lo16 ->
1322 // ___________________________________________
1323 // | | | | |
1324 // | 16-bytes | 16-bytes | 16-bytes | 16-bytes |
1325 // |__________|__________|__________|__________|
1326 //
1327 // For any value of j that isn't representable as a 48-bit integer.
1328 // li d,j => lui d,hi16(j)
1329 // ori d,d,lo16(hi32(j))
1330 // dsll d,d,16
1331 // ori d,d,hi16(lo32(j))
1332 // dsll d,d,16
1333 // ori d,d,lo16(lo32(j))
1334 tmpInst.setOpcode(Mips::LUi);
1335 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1336 tmpInst.addOperand(
1337 MCOperand::CreateImm((ImmValue & (0xffffLL << 48)) >> 48));
1338 Instructions.push_back(tmpInst);
1339 createShiftOr<32, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1340 createShiftOr<16, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
1341 createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions);
Jack Carter30a59822012-10-04 04:03:53 +00001342 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001343 return false;
Jack Carter30a59822012-10-04 04:03:53 +00001344}
Jack Carter92995f12012-10-06 00:53:28 +00001345
Matheus Almeida3813d572014-06-19 14:39:14 +00001346bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001347MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
1348 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001349 MCInst tmpInst;
1350 const MCOperand &ImmOp = Inst.getOperand(2);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001351 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1352 "expected immediate operand kind");
1353 if (!ImmOp.isImm()) {
1354 expandLoadAddressSym(Inst, IDLoc, Instructions);
1355 return false;
1356 }
Jack Carter543fdf82012-10-09 23:29:45 +00001357 const MCOperand &SrcRegOp = Inst.getOperand(1);
1358 assert(SrcRegOp.isReg() && "expected register operand kind");
1359 const MCOperand &DstRegOp = Inst.getOperand(0);
1360 assert(DstRegOp.isReg() && "expected register operand kind");
1361 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001362 if (-32768 <= ImmValue && ImmValue <= 65535) {
1363 // For -32768 <= j <= 65535.
1364 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +00001365 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +00001366 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1367 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1368 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1369 Instructions.push_back(tmpInst);
1370 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001371 // For any other value of j that is representable as a 32-bit integer.
1372 // la d,j(s) => lui d,hi16(j)
1373 // ori d,d,lo16(j)
1374 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +00001375 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001376 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1377 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1378 Instructions.push_back(tmpInst);
1379 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001380 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001381 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1382 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1383 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1384 Instructions.push_back(tmpInst);
1385 tmpInst.clear();
1386 tmpInst.setOpcode(Mips::ADDu);
1387 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1388 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
1389 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
1390 Instructions.push_back(tmpInst);
1391 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001392 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001393}
1394
Matheus Almeida3813d572014-06-19 14:39:14 +00001395bool
Vladimir Medic4c299852013-11-06 11:27:05 +00001396MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
1397 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +00001398 MCInst tmpInst;
1399 const MCOperand &ImmOp = Inst.getOperand(1);
Toma Tabacu0d64b202014-08-14 10:29:17 +00001400 assert((ImmOp.isImm() || ImmOp.isExpr()) &&
1401 "expected immediate operand kind");
1402 if (!ImmOp.isImm()) {
1403 expandLoadAddressSym(Inst, IDLoc, Instructions);
1404 return false;
1405 }
Jack Carter543fdf82012-10-09 23:29:45 +00001406 const MCOperand &RegOp = Inst.getOperand(0);
1407 assert(RegOp.isReg() && "expected register operand kind");
1408 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +00001409 if (-32768 <= ImmValue && ImmValue <= 65535) {
1410 // For -32768 <= j <= 65535.
1411 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +00001412 tmpInst.setOpcode(Mips::ADDiu);
1413 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +00001414 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +00001415 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
1416 Instructions.push_back(tmpInst);
1417 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001418 // For any other value of j that is representable as a 32-bit integer.
1419 // la d,j => lui d,hi16(j)
1420 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +00001421 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +00001422 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1423 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
1424 Instructions.push_back(tmpInst);
1425 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +00001426 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +00001427 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1428 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
1429 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
1430 Instructions.push_back(tmpInst);
1431 }
Matheus Almeida3813d572014-06-19 14:39:14 +00001432 return false;
Jack Carter543fdf82012-10-09 23:29:45 +00001433}
1434
Toma Tabacu0d64b202014-08-14 10:29:17 +00001435void
1436MipsAsmParser::expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc,
1437 SmallVectorImpl<MCInst> &Instructions) {
1438 // FIXME: If we do have a valid at register to use, we should generate a
1439 // slightly shorter sequence here.
1440 MCInst tmpInst;
1441 int ExprOperandNo = 1;
1442 // Sometimes the assembly parser will get the immediate expression as
1443 // a $zero + an immediate.
1444 if (Inst.getNumOperands() == 3) {
1445 assert(Inst.getOperand(1).getReg() ==
1446 (isGP64bit() ? Mips::ZERO_64 : Mips::ZERO));
1447 ExprOperandNo = 2;
1448 }
1449 const MCOperand &SymOp = Inst.getOperand(ExprOperandNo);
1450 assert(SymOp.isExpr() && "expected symbol operand kind");
1451 const MCOperand &RegOp = Inst.getOperand(0);
1452 unsigned RegNo = RegOp.getReg();
1453 const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymOp.getExpr());
1454 const MCSymbolRefExpr *HiExpr =
1455 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1456 MCSymbolRefExpr::VK_Mips_ABS_HI, getContext());
1457 const MCSymbolRefExpr *LoExpr =
1458 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1459 MCSymbolRefExpr::VK_Mips_ABS_LO, getContext());
1460 if (isGP64bit()) {
1461 // If it's a 64-bit architecture, expand to:
1462 // la d,sym => lui d,highest(sym)
1463 // ori d,d,higher(sym)
1464 // dsll d,d,16
1465 // ori d,d,hi16(sym)
1466 // dsll d,d,16
1467 // ori d,d,lo16(sym)
1468 const MCSymbolRefExpr *HighestExpr =
1469 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1470 MCSymbolRefExpr::VK_Mips_HIGHEST, getContext());
1471 const MCSymbolRefExpr *HigherExpr =
1472 MCSymbolRefExpr::Create(Symbol->getSymbol().getName(),
1473 MCSymbolRefExpr::VK_Mips_HIGHER, getContext());
1474
1475 tmpInst.setOpcode(Mips::LUi);
1476 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1477 tmpInst.addOperand(MCOperand::CreateExpr(HighestExpr));
1478 Instructions.push_back(tmpInst);
1479
1480 createShiftOr<false>(MCOperand::CreateExpr(HigherExpr), RegNo, SMLoc(),
1481 Instructions);
1482 createShiftOr<true>(MCOperand::CreateExpr(HiExpr), RegNo, SMLoc(),
1483 Instructions);
1484 createShiftOr<true>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1485 Instructions);
1486 } else {
1487 // Otherwise, expand to:
1488 // la d,sym => lui d,hi16(sym)
1489 // ori d,d,lo16(sym)
1490 tmpInst.setOpcode(Mips::LUi);
1491 tmpInst.addOperand(MCOperand::CreateReg(RegNo));
1492 tmpInst.addOperand(MCOperand::CreateExpr(HiExpr));
1493 Instructions.push_back(tmpInst);
1494
1495 createShiftOr<false>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(),
1496 Instructions);
1497 }
1498}
1499
Jack Carter9e65aa32013-03-22 00:05:30 +00001500void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +00001501 SmallVectorImpl<MCInst> &Instructions,
1502 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +00001503 const MCSymbolRefExpr *SR;
1504 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +00001505 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +00001506 const MCExpr *ExprOffset;
1507 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00001508 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001509 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
1510 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001511 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +00001512 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
1513 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001514 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +00001515 if (isImmOpnd) {
1516 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
1517 ImmOffset = Inst.getOperand(2).getImm();
1518 LoOffset = ImmOffset & 0x0000ffff;
1519 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +00001520 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +00001521 if (LoOffset & 0x8000)
1522 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +00001523 } else
Jack Carter9e65aa32013-03-22 00:05:30 +00001524 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +00001525 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +00001526 TempInst.setLoc(IDLoc);
Matheus Almeida78f8b7b2014-06-18 14:49:56 +00001527 // These are some of the types of expansions we perform here:
1528 // 1) lw $8, sym => lui $8, %hi(sym)
1529 // lw $8, %lo(sym)($8)
1530 // 2) lw $8, offset($9) => lui $8, %hi(offset)
1531 // add $8, $8, $9
1532 // lw $8, %lo(offset)($9)
1533 // 3) lw $8, offset($8) => lui $at, %hi(offset)
1534 // add $at, $at, $8
1535 // lw $8, %lo(offset)($at)
1536 // 4) sw $8, sym => lui $at, %hi(sym)
1537 // sw $8, %lo(sym)($at)
1538 // 5) sw $8, offset($8) => lui $at, %hi(offset)
1539 // add $at, $at, $8
1540 // sw $8, %lo(offset)($at)
1541 // 6) ldc1 $f0, sym => lui $at, %hi(sym)
1542 // ldc1 $f0, %lo(sym)($at)
1543 //
1544 // For load instructions we can use the destination register as a temporary
1545 // if base and dst are different (examples 1 and 2) and if the base register
1546 // is general purpose otherwise we must use $at (example 6) and error if it's
1547 // not available. For stores we must use $at (examples 4 and 5) because we
1548 // must not clobber the source register setting up the offset.
1549 const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
1550 int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
1551 unsigned RegClassIDOp0 =
1552 getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
1553 bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
1554 (RegClassIDOp0 == Mips::GPR64RegClassID);
1555 if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
Matheus Almeida29e254f2014-06-18 14:15:42 +00001556 TmpRegNum = RegOpNum;
Matheus Almeida7de68e72014-06-18 14:46:05 +00001557 else {
1558 int AT = getATReg(IDLoc);
1559 // At this point we need AT to perform the expansions and we exit if it is
1560 // not available.
1561 if (!AT)
1562 return;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001563 TmpRegNum = getReg(
1564 (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, AT);
Matheus Almeida7de68e72014-06-18 14:46:05 +00001565 }
Matheus Almeida29e254f2014-06-18 14:15:42 +00001566
Jack Carter9e65aa32013-03-22 00:05:30 +00001567 TempInst.setOpcode(Mips::LUi);
1568 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1569 if (isImmOpnd)
1570 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
1571 else {
1572 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001573 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +00001574 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
1575 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
1576 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001577 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001578 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001579 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +00001580 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001581 }
1582 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001583 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +00001584 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +00001585 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +00001586 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +00001587 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001588 TempInst.setOpcode(Mips::ADDu);
1589 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1590 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1591 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
1592 Instructions.push_back(TempInst);
1593 TempInst.clear();
Alp Tokercb402912014-01-24 17:20:08 +00001594 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +00001595 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +00001596 TempInst.setOpcode(Inst.getOpcode());
1597 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
1598 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
1599 if (isImmOpnd)
1600 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
1601 else {
1602 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001603 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
1604 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
1605 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +00001606 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +00001607 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001608 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +00001609 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +00001610 }
1611 }
1612 Instructions.push_back(TempInst);
1613 TempInst.clear();
1614}
1615
Matheus Almeida595fcab2014-06-11 15:05:56 +00001616unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1617 // As described by the Mips32r2 spec, the registers Rd and Rs for
1618 // jalr.hb must be different.
1619 unsigned Opcode = Inst.getOpcode();
1620
1621 if (Opcode == Mips::JALR_HB &&
1622 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
1623 return Match_RequiresDifferentSrcAndDst;
1624
1625 return Match_Success;
1626}
1627
David Blaikie960ea3f2014-06-08 16:18:35 +00001628bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1629 OperandVector &Operands,
1630 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00001631 uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00001632 bool MatchingInlineAsm) {
Matheus Almeida595fcab2014-06-11 15:05:56 +00001633
Jack Carterb4dbc172012-09-05 23:34:03 +00001634 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +00001635 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +00001636 unsigned MatchResult =
1637 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +00001638
1639 switch (MatchResult) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001640 default:
1641 break;
Jack Carterb4dbc172012-09-05 23:34:03 +00001642 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001643 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +00001644 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +00001645 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +00001646 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +00001647 return false;
1648 }
1649 case Match_MissingFeature:
1650 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1651 return true;
1652 case Match_InvalidOperand: {
1653 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00001654 if (ErrorInfo != ~0ULL) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001655 if (ErrorInfo >= Operands.size())
1656 return Error(IDLoc, "too few operands for instruction");
1657
David Blaikie960ea3f2014-06-08 16:18:35 +00001658 ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001659 if (ErrorLoc == SMLoc())
1660 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +00001661 }
1662
1663 return Error(ErrorLoc, "invalid operand for instruction");
1664 }
1665 case Match_MnemonicFail:
1666 return Error(IDLoc, "invalid instruction");
Matheus Almeida595fcab2014-06-11 15:05:56 +00001667 case Match_RequiresDifferentSrcAndDst:
1668 return Error(IDLoc, "source and destination must be different");
Jack Carterb4dbc172012-09-05 23:34:03 +00001669 }
Rafael Espindola870c4e92012-01-11 03:56:41 +00001670 return true;
1671}
1672
Toma Tabacu13964452014-09-04 13:23:44 +00001673void MipsAsmParser::warnIfAssemblerTemporary(int RegIndex, SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00001674 if ((RegIndex != 0) &&
1675 ((int)AssemblerOptions.back()->getATRegNum() == RegIndex)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001676 if (RegIndex == 1)
Toma Tabacu65f10572014-09-16 15:00:52 +00001677 Warning(Loc, "used $at without \".set noat\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001678 else
Toma Tabacu65f10572014-09-16 15:00:52 +00001679 Warning(Loc, Twine("used $") + Twine(RegIndex) + " with \".set at=$" +
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001680 Twine(RegIndex) + "\"");
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001681 }
1682}
1683
Daniel Sandersef638fe2014-10-03 15:37:37 +00001684void
1685MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg,
1686 SMRange Range, bool ShowColors) {
1687 getSourceManager().PrintMessage(Range.Start, SourceMgr::DK_Warning, Msg,
Hans Wennborg6a654332014-10-03 17:16:24 +00001688 Range, SMFixIt(Range, FixMsg),
Daniel Sandersef638fe2014-10-03 15:37:37 +00001689 ShowColors);
1690}
1691
Jack Carter1ac53222013-02-20 23:11:17 +00001692int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001693 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00001694
Vladimir Medic4c299852013-11-06 11:27:05 +00001695 CC = StringSwitch<unsigned>(Name)
1696 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001697 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00001698 .Case("a0", 4)
1699 .Case("a1", 5)
1700 .Case("a2", 6)
1701 .Case("a3", 7)
1702 .Case("v0", 2)
1703 .Case("v1", 3)
1704 .Case("s0", 16)
1705 .Case("s1", 17)
1706 .Case("s2", 18)
1707 .Case("s3", 19)
1708 .Case("s4", 20)
1709 .Case("s5", 21)
1710 .Case("s6", 22)
1711 .Case("s7", 23)
1712 .Case("k0", 26)
1713 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001714 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00001715 .Case("sp", 29)
1716 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001717 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00001718 .Case("ra", 31)
1719 .Case("t0", 8)
1720 .Case("t1", 9)
1721 .Case("t2", 10)
1722 .Case("t3", 11)
1723 .Case("t4", 12)
1724 .Case("t5", 13)
1725 .Case("t6", 14)
1726 .Case("t7", 15)
1727 .Case("t8", 24)
1728 .Case("t9", 25)
1729 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00001730
Toma Tabacufda445c2014-09-15 15:33:01 +00001731 if (!(isABI_N32() || isABI_N64()))
1732 return CC;
Jack Carter1ac53222013-02-20 23:11:17 +00001733
Daniel Sandersef638fe2014-10-03 15:37:37 +00001734 if (12 <= CC && CC <= 15) {
1735 // Name is one of t4-t7
1736 AsmToken RegTok = getLexer().peekTok();
1737 SMRange RegRange = RegTok.getLocRange();
1738
1739 StringRef FixedName = StringSwitch<StringRef>(Name)
1740 .Case("t4", "t0")
1741 .Case("t5", "t1")
1742 .Case("t6", "t2")
1743 .Case("t7", "t3")
1744 .Default("");
1745 assert(FixedName != "" && "Register name is not one of t4-t7.");
1746
1747 printWarningWithFixIt("register names $t4-$t7 are only available in O32.",
1748 "Did you mean $" + FixedName + "?", RegRange);
1749 }
1750
Toma Tabacufda445c2014-09-15 15:33:01 +00001751 // Although SGI documentation just cuts out t0-t3 for n32/n64,
1752 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
1753 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
1754 if (8 <= CC && CC <= 11)
1755 CC += 4;
1756
1757 if (CC == -1)
1758 CC = StringSwitch<unsigned>(Name)
1759 .Case("a4", 8)
1760 .Case("a5", 9)
1761 .Case("a6", 10)
1762 .Case("a7", 11)
1763 .Case("kt0", 26)
1764 .Case("kt1", 27)
1765 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00001766
1767 return CC;
1768}
Jack Carterd0bd6422013-04-18 00:41:53 +00001769
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001770int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001771
Jack Cartera63b16a2012-09-07 00:23:42 +00001772 if (Name[0] == 'f') {
1773 StringRef NumString = Name.substr(1);
1774 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001775 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001776 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001777 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00001778 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001779 return IntVal;
1780 }
1781 return -1;
1782}
Jack Cartera63b16a2012-09-07 00:23:42 +00001783
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001784int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
1785
1786 if (Name.startswith("fcc")) {
1787 StringRef NumString = Name.substr(3);
1788 unsigned IntVal;
1789 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001790 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001791 if (IntVal > 7) // There are only 8 fcc registers.
1792 return -1;
1793 return IntVal;
1794 }
1795 return -1;
1796}
1797
1798int MipsAsmParser::matchACRegisterName(StringRef Name) {
1799
Akira Hatanaka274d24c2013-08-14 01:15:52 +00001800 if (Name.startswith("ac")) {
1801 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001802 unsigned IntVal;
1803 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001804 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001805 if (IntVal > 3) // There are only 3 acc registers.
1806 return -1;
1807 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00001808 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001809 return -1;
1810}
Jack Carterd0bd6422013-04-18 00:41:53 +00001811
Jack Carter5dc8ac92013-09-25 23:50:44 +00001812int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
1813 unsigned IntVal;
1814
1815 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
1816 return -1;
1817
1818 if (IntVal > 31)
1819 return -1;
1820
1821 return IntVal;
1822}
1823
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001824int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
1825 int CC;
1826
1827 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00001828 .Case("msair", 0)
1829 .Case("msacsr", 1)
1830 .Case("msaaccess", 2)
1831 .Case("msasave", 3)
1832 .Case("msamodify", 4)
1833 .Case("msarequest", 5)
1834 .Case("msamap", 6)
1835 .Case("msaunmap", 7)
1836 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001837
1838 return CC;
1839}
1840
Jack Carter0b744b32012-10-04 02:29:46 +00001841bool MipsAssemblerOptions::setATReg(unsigned Reg) {
1842 if (Reg > 31)
1843 return false;
1844
Toma Tabacu3c24b042014-09-05 15:43:21 +00001845 ATReg = Reg;
Jack Carter0b744b32012-10-04 02:29:46 +00001846 return true;
1847}
1848
Matheus Almeida7de68e72014-06-18 14:46:05 +00001849int MipsAsmParser::getATReg(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00001850 int AT = AssemblerOptions.back()->getATRegNum();
Daniel Sandersd89b1362014-03-24 16:48:01 +00001851 if (AT == 0)
Matheus Almeida7de68e72014-06-18 14:46:05 +00001852 reportParseError(Loc,
Toma Tabacu65f10572014-09-16 15:00:52 +00001853 "pseudo-instruction requires $at, which is not available");
Daniel Sandersd89b1362014-03-24 16:48:01 +00001854 return AT;
1855}
Jack Carter0b744b32012-10-04 02:29:46 +00001856
Jack Carterd0bd6422013-04-18 00:41:53 +00001857unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00001858 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00001859}
1860
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001861unsigned MipsAsmParser::getGPR(int RegNo) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00001862 return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
Daniel Sanders5e94e682014-03-27 16:42:17 +00001863 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001864}
1865
Jack Carter873c7242013-01-12 01:03:14 +00001866int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001867 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00001868 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00001869 return -1;
1870
Jack Carter873c7242013-01-12 01:03:14 +00001871 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00001872}
1873
Toma Tabacu13964452014-09-04 13:23:44 +00001874bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
1875 DEBUG(dbgs() << "parseOperand\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001876
Jack Carter30a59822012-10-04 04:03:53 +00001877 // Check if the current operand has a custom associated parser, if so, try to
1878 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00001879 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
1880 if (ResTy == MatchOperand_Success)
1881 return false;
1882 // If there wasn't a custom match, try the generic matcher below. Otherwise,
1883 // there was a match, but an error occurred, in which case, just return that
1884 // the operand parsing failed.
1885 if (ResTy == MatchOperand_ParseFail)
1886 return true;
1887
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001888 DEBUG(dbgs() << ".. Generic Parser\n");
1889
Jack Carterb4dbc172012-09-05 23:34:03 +00001890 switch (getLexer().getKind()) {
1891 default:
1892 Error(Parser.getTok().getLoc(), "unexpected token in operand");
1893 return true;
1894 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001895 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00001896 SMLoc S = Parser.getTok().getLoc();
Jack Carterb4dbc172012-09-05 23:34:03 +00001897
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001898 // Almost all registers have been parsed by custom parsers. There is only
1899 // one exception to this. $zero (and it's alias $0) will reach this point
1900 // for div, divu, and similar instructions because it is not an operand
1901 // to the instruction definition but an explicit register. Special case
1902 // this situation for now.
Toma Tabacu13964452014-09-04 13:23:44 +00001903 if (parseAnyRegister(Operands) != MatchOperand_NoMatch)
Jack Carterb4dbc172012-09-05 23:34:03 +00001904 return false;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001905
Jack Carterd0bd6422013-04-18 00:41:53 +00001906 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00001907 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001908 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00001909 return true;
1910
Jack Carter873c7242013-01-12 01:03:14 +00001911 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00001912 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00001913 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00001914 const MCExpr *Res =
1915 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00001916
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001917 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00001918 return false;
1919 }
Vladimir Medic4c299852013-11-06 11:27:05 +00001920 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00001921 case AsmToken::LParen:
1922 case AsmToken::Minus:
1923 case AsmToken::Plus:
1924 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00001925 case AsmToken::Tilde:
Jack Carterb4dbc172012-09-05 23:34:03 +00001926 case AsmToken::String: {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001927 DEBUG(dbgs() << ".. generic integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00001928 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001929 return ResTy != MatchOperand_Success;
Jack Carterb4dbc172012-09-05 23:34:03 +00001930 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00001931 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001932 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001933 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001934 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00001935 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00001936 return true;
1937
Jack Carter873c7242013-01-12 01:03:14 +00001938 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1939
Daniel Sandersb50ccf82014-04-01 10:35:28 +00001940 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterdc1e35d2012-09-06 20:00:02 +00001941 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001942 } // case AsmToken::Percent
1943 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00001944 return true;
1945}
1946
Vladimir Medic4c299852013-11-06 11:27:05 +00001947const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00001948 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00001949 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00001950 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001951 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Sasa Stankovic06c47802014-04-03 10:37:45 +00001952 // It's a constant, evaluate reloc value.
1953 int16_t Val;
1954 switch (getVariantKind(RelocStr)) {
1955 case MCSymbolRefExpr::VK_Mips_ABS_LO:
1956 // Get the 1st 16-bits.
1957 Val = MCE->getValue() & 0xffff;
1958 break;
1959 case MCSymbolRefExpr::VK_Mips_ABS_HI:
1960 // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
1961 // 16 bits being negative.
1962 Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
1963 break;
1964 case MCSymbolRefExpr::VK_Mips_HIGHER:
1965 // Get the 3rd 16-bits.
1966 Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
1967 break;
1968 case MCSymbolRefExpr::VK_Mips_HIGHEST:
1969 // Get the 4th 16-bits.
1970 Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
1971 break;
1972 default:
Toma Tabacu65f10572014-09-16 15:00:52 +00001973 report_fatal_error("unsupported reloc value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001974 }
Sasa Stankovic06c47802014-04-03 10:37:45 +00001975 return MCConstantExpr::Create(Val, getContext());
Jack Carterdc1e35d2012-09-06 20:00:02 +00001976 }
1977
Jack Carterb5cf5902013-04-17 00:18:04 +00001978 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001979 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00001980 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00001981 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00001982 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001983 return Res;
1984 }
1985
1986 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00001987 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
1988
Sasa Stankovic06c47802014-04-03 10:37:45 +00001989 // Try to create target expression.
1990 if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
1991 return MipsMCExpr::Create(VK, Expr, getContext());
Petar Jovanovica5da5882014-02-04 18:41:57 +00001992
Jack Carterd0bd6422013-04-18 00:41:53 +00001993 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
1994 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00001995 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
1996 return Res;
1997 }
1998
1999 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002000 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
2001 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
2002 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00002003 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002004 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00002005 return Expr;
2006}
2007
2008bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
2009
2010 switch (Expr->getKind()) {
2011 case MCExpr::Constant:
2012 return true;
2013 case MCExpr::SymbolRef:
2014 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
2015 case MCExpr::Binary:
2016 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
2017 if (!isEvaluated(BE->getLHS()))
2018 return false;
2019 return isEvaluated(BE->getRHS());
2020 }
2021 case MCExpr::Unary:
2022 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00002023 case MCExpr::Target:
2024 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002025 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002026 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00002027}
Jack Carterd0bd6422013-04-18 00:41:53 +00002028
Jack Carterb5cf5902013-04-17 00:18:04 +00002029bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002030 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00002031 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00002032 if (Tok.isNot(AsmToken::Identifier))
2033 return true;
2034
2035 std::string Str = Tok.getIdentifier().str();
2036
Jack Carterd0bd6422013-04-18 00:41:53 +00002037 Parser.Lex(); // Eat the identifier.
2038 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002039 const MCExpr *IdVal;
2040 SMLoc EndLoc;
2041
2042 if (getLexer().getKind() == AsmToken::LParen) {
2043 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002044 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002045 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002046 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002047 const AsmToken &nextTok = Parser.getTok();
2048 if (nextTok.isNot(AsmToken::Identifier))
2049 return true;
2050 Str += "(%";
2051 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00002052 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00002053 if (getLexer().getKind() != AsmToken::LParen)
2054 return true;
2055 } else
2056 break;
2057 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002058 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00002059 return true;
2060
2061 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00002062 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002063
2064 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00002065 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002066
Jack Carterd0bd6422013-04-18 00:41:53 +00002067 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00002068 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002069}
2070
Jack Carterb4dbc172012-09-05 23:34:03 +00002071bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2072 SMLoc &EndLoc) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002073 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Toma Tabacu13964452014-09-04 13:23:44 +00002074 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002075 if (ResTy == MatchOperand_Success) {
2076 assert(Operands.size() == 1);
David Blaikie960ea3f2014-06-08 16:18:35 +00002077 MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002078 StartLoc = Operand.getStartLoc();
2079 EndLoc = Operand.getEndLoc();
2080
2081 // AFAIK, we only support numeric registers and named GPR's in CFI
2082 // directives.
2083 // Don't worry about eating tokens before failing. Using an unrecognised
2084 // register is a parse error.
2085 if (Operand.isGPRAsmReg()) {
2086 // Resolve to GPR32 or GPR64 appropriately.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002087 RegNo = isGP64bit() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002088 }
2089
2090 return (RegNo == (unsigned)-1);
2091 }
2092
2093 assert(Operands.size() == 0);
Vladimir Medic4c299852013-11-06 11:27:05 +00002094 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00002095}
2096
Jack Carterb5cf5902013-04-17 00:18:04 +00002097bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00002098 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002099 bool Result = true;
2100
2101 while (getLexer().getKind() == AsmToken::LParen)
2102 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00002103
Jack Carterd0bd6422013-04-18 00:41:53 +00002104 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002105 default:
2106 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00002107 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00002108 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00002109 case AsmToken::Integer:
2110 case AsmToken::Minus:
2111 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00002112 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00002113 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00002114 else
2115 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00002116 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00002117 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002118 break;
Jack Carter873c7242013-01-12 01:03:14 +00002119 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00002120 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002121 }
Jack Carterb5cf5902013-04-17 00:18:04 +00002122 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002123}
2124
David Blaikie960ea3f2014-06-08 16:18:35 +00002125MipsAsmParser::OperandMatchResultTy
2126MipsAsmParser::parseMemOperand(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002127 DEBUG(dbgs() << "parseMemOperand\n");
Craig Topper062a2ba2014-04-25 05:30:21 +00002128 const MCExpr *IdVal = nullptr;
Jack Carter873c7242013-01-12 01:03:14 +00002129 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00002130 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002131 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00002132 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00002133 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00002134
Jack Carterb5cf5902013-04-17 00:18:04 +00002135 if (getLexer().getKind() == AsmToken::LParen) {
2136 Parser.Lex();
2137 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002138 }
2139
Jack Carterb5cf5902013-04-17 00:18:04 +00002140 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002141 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00002142 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002143
Jack Carterd0bd6422013-04-18 00:41:53 +00002144 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002145 if (Tok.isNot(AsmToken::LParen)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00002146 MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
2147 if (Mnemonic.getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002148 SMLoc E =
2149 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002150 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002151 return MatchOperand_Success;
2152 }
2153 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002154 SMLoc E =
2155 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00002156
Jack Carterd0bd6422013-04-18 00:41:53 +00002157 // Zero register assumed, add a memory operand with ZERO as its base.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002158 // "Base" will be managed by k_Memory.
Toma Tabacu13964452014-09-04 13:23:44 +00002159 auto Base = MipsOperand::createGPRReg(0, getContext().getRegisterInfo(),
David Blaikie960ea3f2014-06-08 16:18:35 +00002160 S, E, *this);
2161 Operands.push_back(
2162 MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
Jack Carterb5cf5902013-04-17 00:18:04 +00002163 return MatchOperand_Success;
2164 }
2165 Error(Parser.getTok().getLoc(), "'(' expected");
2166 return MatchOperand_ParseFail;
2167 }
2168
Jack Carterd0bd6422013-04-18 00:41:53 +00002169 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00002170 }
2171
Toma Tabacu13964452014-09-04 13:23:44 +00002172 Res = parseAnyRegister(Operands);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002173 if (Res != MatchOperand_Success)
2174 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00002175
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002176 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00002177 Error(Parser.getTok().getLoc(), "')' expected");
2178 return MatchOperand_ParseFail;
2179 }
2180
Jack Carter873c7242013-01-12 01:03:14 +00002181 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2182
Jack Carterd0bd6422013-04-18 00:41:53 +00002183 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002184
Craig Topper062a2ba2014-04-25 05:30:21 +00002185 if (!IdVal)
Jack Carterdc1e35d2012-09-06 20:00:02 +00002186 IdVal = MCConstantExpr::Create(0, getContext());
2187
Jack Carterd0bd6422013-04-18 00:41:53 +00002188 // Replace the register operand with the memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00002189 std::unique_ptr<MipsOperand> op(
2190 static_cast<MipsOperand *>(Operands.back().release()));
Jack Carterd0bd6422013-04-18 00:41:53 +00002191 // Remove the register from the operands.
NAKAMURA Takumie1f35832014-04-15 14:13:21 +00002192 // "op" will be managed by k_Memory.
Jack Carterdc1e35d2012-09-06 20:00:02 +00002193 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00002194 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00002195 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
2196 int64_t Imm;
2197 if (IdVal->EvaluateAsAbsolute(Imm))
2198 IdVal = MCConstantExpr::Create(Imm, getContext());
2199 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
2200 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
2201 getContext());
2202 }
2203
David Blaikie960ea3f2014-06-08 16:18:35 +00002204 Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002205 return MatchOperand_Success;
2206}
2207
David Blaikie960ea3f2014-06-08 16:18:35 +00002208bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
Daniel Sanderse34a1202014-03-31 18:51:43 +00002209
Jack Carterd76b2372013-03-21 21:44:16 +00002210 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
2211 if (Sym) {
2212 SMLoc S = Parser.getTok().getLoc();
2213 const MCExpr *Expr;
2214 if (Sym->isVariable())
2215 Expr = Sym->getVariableValue();
2216 else
2217 return false;
2218 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002219 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Craig Topper6dc4a8bc2014-08-30 16:48:02 +00002220 StringRef DefSymbol = Ref->getSymbol().getName();
Jack Carterd76b2372013-03-21 21:44:16 +00002221 if (DefSymbol.startswith("$")) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002222 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002223 matchAnyRegisterNameWithoutDollar(Operands, DefSymbol.substr(1), S);
Daniel Sanders09934572014-04-01 10:37:46 +00002224 if (ResTy == MatchOperand_Success) {
2225 Parser.Lex();
Jack Carterd76b2372013-03-21 21:44:16 +00002226 return true;
Daniel Sanders09934572014-04-01 10:37:46 +00002227 } else if (ResTy == MatchOperand_ParseFail)
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002228 llvm_unreachable("Should never ParseFail");
2229 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00002230 }
2231 } else if (Expr->getKind() == MCExpr::Constant) {
2232 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00002233 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
David Blaikie960ea3f2014-06-08 16:18:35 +00002234 Operands.push_back(
2235 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
Jack Carterd76b2372013-03-21 21:44:16 +00002236 return true;
2237 }
2238 }
2239 return false;
2240}
Jack Carterd0bd6422013-04-18 00:41:53 +00002241
Jack Carter873c7242013-01-12 01:03:14 +00002242MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002243MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands,
David Blaikie960ea3f2014-06-08 16:18:35 +00002244 StringRef Identifier,
2245 SMLoc S) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002246 int Index = matchCPURegisterName(Identifier);
2247 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002248 Operands.push_back(MipsOperand::createGPRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002249 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2250 return MatchOperand_Success;
2251 }
2252
2253 Index = matchFPURegisterName(Identifier);
2254 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002255 Operands.push_back(MipsOperand::createFGRReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002256 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2257 return MatchOperand_Success;
2258 }
2259
2260 Index = matchFCCRegisterName(Identifier);
2261 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002262 Operands.push_back(MipsOperand::createFCCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002263 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2264 return MatchOperand_Success;
2265 }
2266
2267 Index = matchACRegisterName(Identifier);
2268 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002269 Operands.push_back(MipsOperand::createACCReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002270 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2271 return MatchOperand_Success;
2272 }
2273
2274 Index = matchMSA128RegisterName(Identifier);
2275 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002276 Operands.push_back(MipsOperand::createMSA128Reg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002277 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2278 return MatchOperand_Success;
2279 }
2280
2281 Index = matchMSA128CtrlRegisterName(Identifier);
2282 if (Index != -1) {
Toma Tabacu13964452014-09-04 13:23:44 +00002283 Operands.push_back(MipsOperand::createMSACtrlReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002284 Index, getContext().getRegisterInfo(), S, getLexer().getLoc(), *this));
2285 return MatchOperand_Success;
2286 }
2287
2288 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00002289}
2290
2291MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002292MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
Daniel Sanders315386c2014-04-01 10:40:14 +00002293 auto Token = Parser.getLexer().peekTok(false);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002294
2295 if (Token.is(AsmToken::Identifier)) {
2296 DEBUG(dbgs() << ".. identifier\n");
2297 StringRef Identifier = Token.getIdentifier();
Daniel Sanders09934572014-04-01 10:37:46 +00002298 OperandMatchResultTy ResTy =
Toma Tabacu13964452014-09-04 13:23:44 +00002299 matchAnyRegisterNameWithoutDollar(Operands, Identifier, S);
Daniel Sanders09934572014-04-01 10:37:46 +00002300 return ResTy;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002301 } else if (Token.is(AsmToken::Integer)) {
2302 DEBUG(dbgs() << ".. integer\n");
Toma Tabacu13964452014-09-04 13:23:44 +00002303 Operands.push_back(MipsOperand::createNumericReg(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002304 Token.getIntVal(), getContext().getRegisterInfo(), S, Token.getLoc(),
2305 *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002306 return MatchOperand_Success;
2307 }
2308
2309 DEBUG(dbgs() << Parser.getTok().getKind() << "\n");
2310
2311 return MatchOperand_NoMatch;
2312}
2313
David Blaikie960ea3f2014-06-08 16:18:35 +00002314MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002315MipsAsmParser::parseAnyRegister(OperandVector &Operands) {
2316 DEBUG(dbgs() << "parseAnyRegister\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002317
2318 auto Token = Parser.getTok();
2319
2320 SMLoc S = Token.getLoc();
2321
2322 if (Token.isNot(AsmToken::Dollar)) {
2323 DEBUG(dbgs() << ".. !$ -> try sym aliasing\n");
2324 if (Token.is(AsmToken::Identifier)) {
2325 if (searchSymbolAlias(Operands))
2326 return MatchOperand_Success;
2327 }
2328 DEBUG(dbgs() << ".. !symalias -> NoMatch\n");
2329 return MatchOperand_NoMatch;
2330 }
2331 DEBUG(dbgs() << ".. $\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002332
Toma Tabacu13964452014-09-04 13:23:44 +00002333 OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S);
Daniel Sanders315386c2014-04-01 10:40:14 +00002334 if (ResTy == MatchOperand_Success) {
2335 Parser.Lex(); // $
2336 Parser.Lex(); // identifier
2337 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002338 return ResTy;
2339}
2340
2341MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002342MipsAsmParser::parseImm(OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002343 switch (getLexer().getKind()) {
2344 default:
2345 return MatchOperand_NoMatch;
2346 case AsmToken::LParen:
2347 case AsmToken::Minus:
2348 case AsmToken::Plus:
2349 case AsmToken::Integer:
Matheus Almeidaee73cc52014-06-18 13:55:18 +00002350 case AsmToken::Tilde:
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002351 case AsmToken::String:
2352 break;
2353 }
2354
2355 const MCExpr *IdVal;
2356 SMLoc S = Parser.getTok().getLoc();
2357 if (getParser().parseExpression(IdVal))
2358 return MatchOperand_ParseFail;
2359
2360 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2361 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
2362 return MatchOperand_Success;
2363}
2364
David Blaikie960ea3f2014-06-08 16:18:35 +00002365MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002366MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
2367 DEBUG(dbgs() << "parseJumpTarget\n");
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002368
2369 SMLoc S = getLexer().getLoc();
2370
2371 // Integers and expressions are acceptable
Toma Tabacu13964452014-09-04 13:23:44 +00002372 OperandMatchResultTy ResTy = parseImm(Operands);
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002373 if (ResTy != MatchOperand_NoMatch)
2374 return ResTy;
2375
Daniel Sanders315386c2014-04-01 10:40:14 +00002376 // Registers are a valid target and have priority over symbols.
Toma Tabacu13964452014-09-04 13:23:44 +00002377 ResTy = parseAnyRegister(Operands);
Daniel Sanders315386c2014-04-01 10:40:14 +00002378 if (ResTy != MatchOperand_NoMatch)
2379 return ResTy;
2380
Daniel Sandersffd84362014-04-01 10:41:48 +00002381 const MCExpr *Expr = nullptr;
2382 if (Parser.parseExpression(Expr)) {
2383 // We have no way of knowing if a symbol was consumed so we must ParseFail
2384 return MatchOperand_ParseFail;
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002385 }
Daniel Sandersffd84362014-04-01 10:41:48 +00002386 Operands.push_back(
2387 MipsOperand::CreateImm(Expr, S, getLexer().getLoc(), *this));
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002388 return MatchOperand_Success;
Jack Carter873c7242013-01-12 01:03:14 +00002389}
2390
Vladimir Medic2b953d02013-10-01 09:48:56 +00002391MipsAsmParser::OperandMatchResultTy
David Blaikie960ea3f2014-06-08 16:18:35 +00002392MipsAsmParser::parseInvNum(OperandVector &Operands) {
Vladimir Medic2b953d02013-10-01 09:48:56 +00002393 const MCExpr *IdVal;
2394 // If the first token is '$' we may have register operand.
2395 if (Parser.getTok().is(AsmToken::Dollar))
2396 return MatchOperand_NoMatch;
2397 SMLoc S = Parser.getTok().getLoc();
2398 if (getParser().parseExpression(IdVal))
2399 return MatchOperand_ParseFail;
2400 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00002401 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00002402 int64_t Val = MCE->getValue();
2403 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2404 Operands.push_back(MipsOperand::CreateImm(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002405 MCConstantExpr::Create(0 - Val, getContext()), S, E, *this));
Vladimir Medic2b953d02013-10-01 09:48:56 +00002406 return MatchOperand_Success;
2407}
2408
Matheus Almeida779c5932013-11-18 12:32:49 +00002409MipsAsmParser::OperandMatchResultTy
Toma Tabacu13964452014-09-04 13:23:44 +00002410MipsAsmParser::parseLSAImm(OperandVector &Operands) {
Matheus Almeida779c5932013-11-18 12:32:49 +00002411 switch (getLexer().getKind()) {
2412 default:
2413 return MatchOperand_NoMatch;
2414 case AsmToken::LParen:
2415 case AsmToken::Plus:
2416 case AsmToken::Minus:
2417 case AsmToken::Integer:
2418 break;
2419 }
2420
2421 const MCExpr *Expr;
2422 SMLoc S = Parser.getTok().getLoc();
2423
2424 if (getParser().parseExpression(Expr))
2425 return MatchOperand_ParseFail;
2426
2427 int64_t Val;
2428 if (!Expr->EvaluateAsAbsolute(Val)) {
2429 Error(S, "expected immediate value");
2430 return MatchOperand_ParseFail;
2431 }
2432
2433 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
2434 // and because the CPU always adds one to the immediate field, the allowed
2435 // range becomes 1..4. We'll only check the range here and will deal
2436 // with the addition/subtraction when actually decoding/encoding
2437 // the instruction.
2438 if (Val < 1 || Val > 4) {
2439 Error(S, "immediate not in range (1..4)");
2440 return MatchOperand_ParseFail;
2441 }
2442
Jack Carter3b2c96e2014-01-22 23:31:38 +00002443 Operands.push_back(
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002444 MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
Matheus Almeida779c5932013-11-18 12:32:49 +00002445 return MatchOperand_Success;
2446}
2447
Jack Carterdc1e35d2012-09-06 20:00:02 +00002448MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
2449
Vladimir Medic4c299852013-11-06 11:27:05 +00002450 MCSymbolRefExpr::VariantKind VK =
2451 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
2452 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
2453 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
2454 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
2455 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
2456 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
2457 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
2458 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
2459 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
2460 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
2461 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
2462 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
2463 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
2464 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
2465 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
2466 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
2467 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
2468 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
Daniel Sandersa567da52014-03-31 15:15:02 +00002469 .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
2470 .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
2471 .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
2472 .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
2473 .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
2474 .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
Zoran Jovanovicb355e8f2014-05-27 14:58:51 +00002475 .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
2476 .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
Vladimir Medic4c299852013-11-06 11:27:05 +00002477 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002478
Matheus Almeida2852af82014-04-22 10:15:54 +00002479 assert(VK != MCSymbolRefExpr::VK_None);
Daniel Sandersa567da52014-03-31 15:15:02 +00002480
Jack Carterdc1e35d2012-09-06 20:00:02 +00002481 return VK;
2482}
Jack Cartera63b16a2012-09-07 00:23:42 +00002483
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002484/// Sometimes (i.e. load/stores) the operand may be followed immediately by
2485/// either this.
2486/// ::= '(', register, ')'
2487/// handle it before we iterate so we don't get tripped up by the lack of
2488/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00002489bool MipsAsmParser::parseParenSuffix(StringRef Name, OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002490 if (getLexer().is(AsmToken::LParen)) {
2491 Operands.push_back(
2492 MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
2493 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00002494 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002495 SMLoc Loc = getLexer().getLoc();
2496 Parser.eatToEndOfStatement();
2497 return Error(Loc, "unexpected token in argument list");
2498 }
2499 if (Parser.getTok().isNot(AsmToken::RParen)) {
2500 SMLoc Loc = getLexer().getLoc();
2501 Parser.eatToEndOfStatement();
2502 return Error(Loc, "unexpected token, expected ')'");
2503 }
2504 Operands.push_back(
2505 MipsOperand::CreateToken(")", getLexer().getLoc(), *this));
2506 Parser.Lex();
2507 }
2508 return false;
2509}
2510
2511/// Sometimes (i.e. in MSA) the operand may be followed immediately by
2512/// either one of these.
2513/// ::= '[', register, ']'
2514/// ::= '[', integer, ']'
2515/// handle it before we iterate so we don't get tripped up by the lack of
2516/// a comma.
Toma Tabacu13964452014-09-04 13:23:44 +00002517bool MipsAsmParser::parseBracketSuffix(StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00002518 OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002519 if (getLexer().is(AsmToken::LBrac)) {
2520 Operands.push_back(
2521 MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
2522 Parser.Lex();
Toma Tabacu13964452014-09-04 13:23:44 +00002523 if (parseOperand(Operands, Name)) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002524 SMLoc Loc = getLexer().getLoc();
2525 Parser.eatToEndOfStatement();
2526 return Error(Loc, "unexpected token in argument list");
2527 }
2528 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2529 SMLoc Loc = getLexer().getLoc();
2530 Parser.eatToEndOfStatement();
2531 return Error(Loc, "unexpected token, expected ']'");
2532 }
2533 Operands.push_back(
2534 MipsOperand::CreateToken("]", getLexer().getLoc(), *this));
2535 Parser.Lex();
2536 }
2537 return false;
2538}
2539
David Blaikie960ea3f2014-06-08 16:18:35 +00002540bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
2541 SMLoc NameLoc, OperandVector &Operands) {
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002542 DEBUG(dbgs() << "ParseInstruction\n");
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00002543
2544 // We have reached first instruction, module directive are now forbidden.
2545 getTargetStreamer().forbidModuleDirective();
2546
Vladimir Medic74593e62013-07-17 15:00:42 +00002547 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00002548 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00002549 Parser.eatToEndOfStatement();
Toma Tabacu65f10572014-09-16 15:00:52 +00002550 return Error(NameLoc, "unknown instruction");
Vladimir Medic74593e62013-07-17 15:00:42 +00002551 }
Vladimir Medic64828a12013-07-16 10:07:14 +00002552 // First operand in MCInst is instruction mnemonic.
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002553 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc, *this));
Jack Carterb4dbc172012-09-05 23:34:03 +00002554
2555 // Read the remaining operands.
2556 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2557 // Read the first operand.
Toma Tabacu13964452014-09-04 13:23:44 +00002558 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002559 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002560 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002561 return Error(Loc, "unexpected token in argument list");
2562 }
Toma Tabacu13964452014-09-04 13:23:44 +00002563 if (getLexer().is(AsmToken::LBrac) && parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002564 return true;
2565 // AFAIK, parenthesis suffixes are never on the first operand
Jack Carterb4dbc172012-09-05 23:34:03 +00002566
Jack Carterd0bd6422013-04-18 00:41:53 +00002567 while (getLexer().is(AsmToken::Comma)) {
2568 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00002569 // Parse and remember the operand.
Toma Tabacu13964452014-09-04 13:23:44 +00002570 if (parseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002571 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002572 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002573 return Error(Loc, "unexpected token in argument list");
2574 }
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002575 // Parse bracket and parenthesis suffixes before we iterate
2576 if (getLexer().is(AsmToken::LBrac)) {
Toma Tabacu13964452014-09-04 13:23:44 +00002577 if (parseBracketSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002578 return true;
2579 } else if (getLexer().is(AsmToken::LParen) &&
Toma Tabacu13964452014-09-04 13:23:44 +00002580 parseParenSuffix(Name, Operands))
Daniel Sandersb50ccf82014-04-01 10:35:28 +00002581 return true;
Jack Carterb4dbc172012-09-05 23:34:03 +00002582 }
2583 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002584 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2585 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002586 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002587 return Error(Loc, "unexpected token in argument list");
2588 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002589 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00002590 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00002591}
2592
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002593bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002594 SMLoc Loc = getLexer().getLoc();
2595 Parser.eatToEndOfStatement();
2596 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00002597}
2598
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002599bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002600 return Error(Loc, ErrorMsg);
2601}
2602
Jack Carter0b744b32012-10-04 02:29:46 +00002603bool MipsAsmParser::parseSetNoAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002604 // Line should look like: ".set noat".
2605 // set at reg to 0.
Toma Tabacu9db22db2014-09-09 10:15:38 +00002606 AssemblerOptions.back()->setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00002607 // eat noat
2608 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002609 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002610 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002611 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002612 return false;
2613 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002614 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002615 return false;
2616}
Jack Carterd0bd6422013-04-18 00:41:53 +00002617
Jack Carter0b744b32012-10-04 02:29:46 +00002618bool MipsAsmParser::parseSetAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002619 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00002620 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00002621 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00002622 getParser().Lex();
2623 if (getLexer().is(AsmToken::EndOfStatement)) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00002624 AssemblerOptions.back()->setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00002625 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002626 return false;
2627 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002628 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00002629 if (getLexer().isNot(AsmToken::Dollar)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002630 reportParseError("unexpected token, expected dollar sign '$'");
Jack Carter0b744b32012-10-04 02:29:46 +00002631 return false;
2632 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002633 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00002634 const AsmToken &Reg = Parser.getTok();
2635 if (Reg.is(AsmToken::Identifier)) {
2636 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
2637 } else if (Reg.is(AsmToken::Integer)) {
2638 AtRegNo = Reg.getIntVal();
2639 } else {
Toma Tabacu65f10572014-09-16 15:00:52 +00002640 reportParseError("unexpected token, expected identifier or integer");
Jack Carter0b744b32012-10-04 02:29:46 +00002641 return false;
2642 }
Jack Carter1ac53222013-02-20 23:11:17 +00002643
Daniel Sanders71a89d922014-03-25 13:01:06 +00002644 if (AtRegNo < 0 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00002645 reportParseError("unexpected token in statement");
2646 return false;
2647 }
2648
Toma Tabacu9db22db2014-09-09 10:15:38 +00002649 if (!AssemblerOptions.back()->setATReg(AtRegNo)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002650 reportParseError("invalid register");
Jack Carter0b744b32012-10-04 02:29:46 +00002651 return false;
2652 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002653 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00002654
2655 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002656 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002657 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002658 }
2659 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002660 return false;
2661 } else {
2662 reportParseError("unexpected token in statement");
2663 return false;
2664 }
2665}
2666
2667bool MipsAsmParser::parseSetReorderDirective() {
2668 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002669 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002670 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002671 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002672 return false;
2673 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002674 AssemblerOptions.back()->setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00002675 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002676 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002677 return false;
2678}
2679
2680bool MipsAsmParser::parseSetNoReorderDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002681 Parser.Lex();
2682 // If this is not the end of the statement, report an error.
2683 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002684 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002685 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002686 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002687 AssemblerOptions.back()->setNoReorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00002688 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002689 Parser.Lex(); // Consume the EndOfStatement.
2690 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002691}
2692
2693bool MipsAsmParser::parseSetMacroDirective() {
2694 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002695 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002696 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002697 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002698 return false;
2699 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002700 AssemblerOptions.back()->setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002701 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002702 return false;
2703}
2704
2705bool MipsAsmParser::parseSetNoMacroDirective() {
2706 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002707 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002708 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002709 reportParseError("unexpected token, expected end of statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002710 return false;
2711 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002712 if (AssemblerOptions.back()->isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00002713 reportParseError("`noreorder' must be set before `nomacro'");
2714 return false;
2715 }
Toma Tabacu9db22db2014-09-09 10:15:38 +00002716 AssemblerOptions.back()->setNoMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002717 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002718 return false;
2719}
Jack Carterd76b2372013-03-21 21:44:16 +00002720
Daniel Sanders44934432014-08-07 12:03:36 +00002721bool MipsAsmParser::parseSetMsaDirective() {
2722 Parser.Lex();
2723
2724 // If this is not the end of the statement, report an error.
2725 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00002726 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00002727
2728 setFeatureBits(Mips::FeatureMSA, "msa");
2729 getTargetStreamer().emitDirectiveSetMsa();
2730 return false;
2731}
2732
2733bool MipsAsmParser::parseSetNoMsaDirective() {
2734 Parser.Lex();
2735
2736 // If this is not the end of the statement, report an error.
2737 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00002738 return reportParseError("unexpected token, expected end of statement");
Daniel Sanders44934432014-08-07 12:03:36 +00002739
2740 clearFeatureBits(Mips::FeatureMSA, "msa");
2741 getTargetStreamer().emitDirectiveSetNoMsa();
2742 return false;
2743}
2744
Toma Tabacu351b2fe2014-09-17 09:01:54 +00002745bool MipsAsmParser::parseSetNoDspDirective() {
2746 Parser.Lex(); // Eat "nodsp".
2747
2748 // If this is not the end of the statement, report an error.
2749 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2750 reportParseError("unexpected token, expected end of statement");
2751 return false;
2752 }
2753
2754 clearFeatureBits(Mips::FeatureDSP, "dsp");
2755 getTargetStreamer().emitDirectiveSetNoDsp();
2756 return false;
2757}
2758
Jack Carter39536722014-01-22 23:08:42 +00002759bool MipsAsmParser::parseSetNoMips16Directive() {
2760 Parser.Lex();
2761 // If this is not the end of the statement, report an error.
2762 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002763 reportParseError("unexpected token, expected end of statement");
Jack Carter39536722014-01-22 23:08:42 +00002764 return false;
2765 }
2766 // For now do nothing.
2767 Parser.Lex(); // Consume the EndOfStatement.
2768 return false;
2769}
2770
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002771bool MipsAsmParser::parseSetFpDirective() {
Daniel Sanders7e527422014-07-10 13:38:23 +00002772 MipsABIFlagsSection::FpABIKind FpAbiVal;
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002773 // Line can be: .set fp=32
2774 // .set fp=xx
2775 // .set fp=64
2776 Parser.Lex(); // Eat fp token
2777 AsmToken Tok = Parser.getTok();
2778 if (Tok.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002779 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002780 return false;
2781 }
2782 Parser.Lex(); // Eat '=' token.
2783 Tok = Parser.getTok();
Daniel Sandersc7dbc632014-07-08 10:11:38 +00002784
2785 if (!parseFpABIValue(FpAbiVal, ".set"))
2786 return false;
2787
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002788 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00002789 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002790 return false;
2791 }
Daniel Sanders7e527422014-07-10 13:38:23 +00002792 getTargetStreamer().emitDirectiveSetFp(FpAbiVal);
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00002793 Parser.Lex(); // Consume the EndOfStatement.
2794 return false;
2795}
2796
Toma Tabacu9db22db2014-09-09 10:15:38 +00002797bool MipsAsmParser::parseSetPopDirective() {
2798 SMLoc Loc = getLexer().getLoc();
2799
2800 Parser.Lex();
2801 if (getLexer().isNot(AsmToken::EndOfStatement))
2802 return reportParseError("unexpected token, expected end of statement");
2803
2804 // Always keep an element on the options "stack" to prevent the user
2805 // from changing the initial options. This is how we remember them.
2806 if (AssemblerOptions.size() == 2)
2807 return reportParseError(Loc, ".set pop with no .set push");
2808
2809 AssemblerOptions.pop_back();
2810 setAvailableFeatures(AssemblerOptions.back()->getFeatures());
2811
2812 getTargetStreamer().emitDirectiveSetPop();
2813 return false;
2814}
2815
2816bool MipsAsmParser::parseSetPushDirective() {
2817 Parser.Lex();
2818 if (getLexer().isNot(AsmToken::EndOfStatement))
2819 return reportParseError("unexpected token, expected end of statement");
2820
2821 // Create a copy of the current assembler options environment and push it.
Craig Topperfec61ef2014-09-12 05:17:20 +00002822 AssemblerOptions.push_back(
2823 make_unique<MipsAssemblerOptions>(AssemblerOptions.back().get()));
Toma Tabacu9db22db2014-09-09 10:15:38 +00002824
2825 getTargetStreamer().emitDirectiveSetPush();
2826 return false;
2827}
2828
Jack Carterd76b2372013-03-21 21:44:16 +00002829bool MipsAsmParser::parseSetAssignment() {
2830 StringRef Name;
2831 const MCExpr *Value;
2832
2833 if (Parser.parseIdentifier(Name))
2834 reportParseError("expected identifier after .set");
2835
2836 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00002837 return reportParseError("unexpected token, expected comma");
Jack Carterb5cf5902013-04-17 00:18:04 +00002838 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00002839
Jack Carter3b2c96e2014-01-22 23:31:38 +00002840 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00002841 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00002842
Jack Carterd0bd6422013-04-18 00:41:53 +00002843 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00002844 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00002845 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00002846 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00002847 Sym = getContext().GetOrCreateSymbol(Name);
2848 Sym->setVariableValue(Value);
2849
2850 return false;
2851}
Jack Carterd0bd6422013-04-18 00:41:53 +00002852
Toma Tabacu26647792014-09-09 12:52:14 +00002853bool MipsAsmParser::parseSetMips0Directive() {
2854 Parser.Lex();
2855 if (getLexer().isNot(AsmToken::EndOfStatement))
2856 return reportParseError("unexpected token, expected end of statement");
2857
2858 // Reset assembler options to their initial values.
2859 setAvailableFeatures(AssemblerOptions.front()->getFeatures());
2860 AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures());
2861
2862 getTargetStreamer().emitDirectiveSetMips0();
2863 return false;
2864}
2865
Toma Tabacu85618b32014-08-19 14:22:52 +00002866bool MipsAsmParser::parseSetArchDirective() {
2867 Parser.Lex();
2868 if (getLexer().isNot(AsmToken::Equal))
2869 return reportParseError("unexpected token, expected equals sign");
2870
2871 Parser.Lex();
2872 StringRef Arch;
2873 if (Parser.parseIdentifier(Arch))
2874 return reportParseError("expected arch identifier");
2875
2876 StringRef ArchFeatureName =
2877 StringSwitch<StringRef>(Arch)
2878 .Case("mips1", "mips1")
2879 .Case("mips2", "mips2")
2880 .Case("mips3", "mips3")
2881 .Case("mips4", "mips4")
2882 .Case("mips5", "mips5")
2883 .Case("mips32", "mips32")
2884 .Case("mips32r2", "mips32r2")
2885 .Case("mips32r6", "mips32r6")
2886 .Case("mips64", "mips64")
2887 .Case("mips64r2", "mips64r2")
2888 .Case("mips64r6", "mips64r6")
2889 .Case("cnmips", "cnmips")
2890 .Case("r4000", "mips3") // This is an implementation of Mips3.
2891 .Default("");
2892
2893 if (ArchFeatureName.empty())
2894 return reportParseError("unsupported architecture");
2895
2896 selectArch(ArchFeatureName);
2897 getTargetStreamer().emitDirectiveSetArch(Arch);
2898 return false;
2899}
2900
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002901bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
2902 Parser.Lex();
2903 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00002904 return reportParseError("unexpected token, expected end of statement");
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002905
Matheus Almeida2852af82014-04-22 10:15:54 +00002906 switch (Feature) {
2907 default:
2908 llvm_unreachable("Unimplemented feature");
2909 case Mips::FeatureDSP:
2910 setFeatureBits(Mips::FeatureDSP, "dsp");
2911 getTargetStreamer().emitDirectiveSetDsp();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002912 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002913 case Mips::FeatureMicroMips:
2914 getTargetStreamer().emitDirectiveSetMicroMips();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002915 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002916 case Mips::FeatureMips16:
2917 getTargetStreamer().emitDirectiveSetMips16();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002918 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00002919 case Mips::FeatureMips1:
2920 selectArch("mips1");
2921 getTargetStreamer().emitDirectiveSetMips1();
2922 break;
2923 case Mips::FeatureMips2:
2924 selectArch("mips2");
2925 getTargetStreamer().emitDirectiveSetMips2();
2926 break;
2927 case Mips::FeatureMips3:
2928 selectArch("mips3");
2929 getTargetStreamer().emitDirectiveSetMips3();
2930 break;
2931 case Mips::FeatureMips4:
2932 selectArch("mips4");
2933 getTargetStreamer().emitDirectiveSetMips4();
2934 break;
2935 case Mips::FeatureMips5:
2936 selectArch("mips5");
2937 getTargetStreamer().emitDirectiveSetMips5();
2938 break;
2939 case Mips::FeatureMips32:
2940 selectArch("mips32");
2941 getTargetStreamer().emitDirectiveSetMips32();
2942 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002943 case Mips::FeatureMips32r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00002944 selectArch("mips32r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00002945 getTargetStreamer().emitDirectiveSetMips32R2();
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002946 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00002947 case Mips::FeatureMips32r6:
2948 selectArch("mips32r6");
2949 getTargetStreamer().emitDirectiveSetMips32R6();
2950 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002951 case Mips::FeatureMips64:
Daniel Sandersf0df2212014-08-04 12:20:00 +00002952 selectArch("mips64");
Matheus Almeida2852af82014-04-22 10:15:54 +00002953 getTargetStreamer().emitDirectiveSetMips64();
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00002954 break;
Matheus Almeida2852af82014-04-22 10:15:54 +00002955 case Mips::FeatureMips64r2:
Daniel Sandersf0df2212014-08-04 12:20:00 +00002956 selectArch("mips64r2");
Matheus Almeida2852af82014-04-22 10:15:54 +00002957 getTargetStreamer().emitDirectiveSetMips64R2();
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00002958 break;
Daniel Sandersf0df2212014-08-04 12:20:00 +00002959 case Mips::FeatureMips64r6:
2960 selectArch("mips64r6");
2961 getTargetStreamer().emitDirectiveSetMips64R6();
2962 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002963 }
2964 return false;
2965}
2966
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002967bool MipsAsmParser::eatComma(StringRef ErrorStr) {
2968 if (getLexer().isNot(AsmToken::Comma)) {
2969 SMLoc Loc = getLexer().getLoc();
2970 Parser.eatToEndOfStatement();
2971 return Error(Loc, ErrorStr);
2972 }
2973
Matheus Almeida2852af82014-04-22 10:15:54 +00002974 Parser.Lex(); // Eat the comma.
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002975 return true;
2976}
2977
Toma Tabacuc4c202a2014-10-01 14:53:19 +00002978bool MipsAsmParser::parseDirectiveCpLoad(SMLoc Loc) {
Toma Tabacu9db22db2014-09-09 10:15:38 +00002979 if (AssemblerOptions.back()->isReorder())
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002980 Warning(Loc, ".cpload in reorder section");
2981
2982 // FIXME: Warn if cpload is used in Mips16 mode.
2983
David Blaikie960ea3f2014-06-08 16:18:35 +00002984 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
Toma Tabacu13964452014-09-04 13:23:44 +00002985 OperandMatchResultTy ResTy = parseAnyRegister(Reg);
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002986 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
2987 reportParseError("expected register containing function address");
2988 return false;
2989 }
2990
David Blaikie960ea3f2014-06-08 16:18:35 +00002991 MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
2992 if (!RegOpnd.isGPRAsmReg()) {
2993 reportParseError(RegOpnd.getStartLoc(), "invalid register");
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002994 return false;
2995 }
2996
Toma Tabacuc4c202a2014-10-01 14:53:19 +00002997 getTargetStreamer().emitDirectiveCpLoad(RegOpnd.getGPR32Reg());
Matheus Almeida525bc4f2014-04-30 11:28:42 +00002998 return false;
2999}
3000
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003001bool MipsAsmParser::parseDirectiveCPSetup() {
3002 unsigned FuncReg;
3003 unsigned Save;
3004 bool SaveIsReg = true;
3005
Matheus Almeida7e815762014-06-18 13:08:59 +00003006 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003007 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003008 if (ResTy == MatchOperand_NoMatch) {
3009 reportParseError("expected register containing function address");
3010 Parser.eatToEndOfStatement();
3011 return false;
3012 }
3013
3014 MipsOperand &FuncRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3015 if (!FuncRegOpnd.isGPRAsmReg()) {
3016 reportParseError(FuncRegOpnd.getStartLoc(), "invalid register");
3017 Parser.eatToEndOfStatement();
3018 return false;
3019 }
3020
3021 FuncReg = FuncRegOpnd.getGPR32Reg();
3022 TmpReg.clear();
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003023
Toma Tabacu65f10572014-09-16 15:00:52 +00003024 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003025 return true;
3026
Toma Tabacu13964452014-09-04 13:23:44 +00003027 ResTy = parseAnyRegister(TmpReg);
Matheus Almeida7e815762014-06-18 13:08:59 +00003028 if (ResTy == MatchOperand_NoMatch) {
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003029 const AsmToken &Tok = Parser.getTok();
3030 if (Tok.is(AsmToken::Integer)) {
3031 Save = Tok.getIntVal();
3032 SaveIsReg = false;
3033 Parser.Lex();
Matheus Almeida7e815762014-06-18 13:08:59 +00003034 } else {
3035 reportParseError("expected save register or stack offset");
3036 Parser.eatToEndOfStatement();
3037 return false;
3038 }
3039 } else {
3040 MipsOperand &SaveOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3041 if (!SaveOpnd.isGPRAsmReg()) {
3042 reportParseError(SaveOpnd.getStartLoc(), "invalid register");
3043 Parser.eatToEndOfStatement();
3044 return false;
3045 }
3046 Save = SaveOpnd.getGPR32Reg();
3047 }
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003048
Toma Tabacu65f10572014-09-16 15:00:52 +00003049 if (!eatComma("unexpected token, expected comma"))
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003050 return true;
3051
3052 StringRef Name;
3053 if (Parser.parseIdentifier(Name))
3054 reportParseError("expected identifier");
3055 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003056
Matheus Almeidad92a3fa2014-05-01 10:24:46 +00003057 getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, *Sym, SaveIsReg);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003058 return false;
3059}
3060
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003061bool MipsAsmParser::parseDirectiveNaN() {
3062 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3063 const AsmToken &Tok = Parser.getTok();
3064
3065 if (Tok.getString() == "2008") {
3066 Parser.Lex();
3067 getTargetStreamer().emitDirectiveNaN2008();
3068 return false;
3069 } else if (Tok.getString() == "legacy") {
3070 Parser.Lex();
3071 getTargetStreamer().emitDirectiveNaNLegacy();
3072 return false;
3073 }
3074 }
3075 // If we don't recognize the option passed to the .nan
3076 // directive (e.g. no option or unknown option), emit an error.
3077 reportParseError("invalid option in .nan directive");
3078 return false;
3079}
3080
Jack Carter0b744b32012-10-04 02:29:46 +00003081bool MipsAsmParser::parseDirectiveSet() {
3082
Jack Carterd0bd6422013-04-18 00:41:53 +00003083 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00003084 const AsmToken &Tok = Parser.getTok();
3085
3086 if (Tok.getString() == "noat") {
3087 return parseSetNoAtDirective();
3088 } else if (Tok.getString() == "at") {
3089 return parseSetAtDirective();
Toma Tabacu85618b32014-08-19 14:22:52 +00003090 } else if (Tok.getString() == "arch") {
3091 return parseSetArchDirective();
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003092 } else if (Tok.getString() == "fp") {
3093 return parseSetFpDirective();
Toma Tabacu9db22db2014-09-09 10:15:38 +00003094 } else if (Tok.getString() == "pop") {
3095 return parseSetPopDirective();
3096 } else if (Tok.getString() == "push") {
3097 return parseSetPushDirective();
Jack Carter0b744b32012-10-04 02:29:46 +00003098 } else if (Tok.getString() == "reorder") {
3099 return parseSetReorderDirective();
3100 } else if (Tok.getString() == "noreorder") {
3101 return parseSetNoReorderDirective();
3102 } else if (Tok.getString() == "macro") {
3103 return parseSetMacroDirective();
3104 } else if (Tok.getString() == "nomacro") {
3105 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00003106 } else if (Tok.getString() == "mips16") {
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00003107 return parseSetFeature(Mips::FeatureMips16);
Jack Carter0b744b32012-10-04 02:29:46 +00003108 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00003109 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00003110 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00003111 getTargetStreamer().emitDirectiveSetNoMicroMips();
3112 Parser.eatToEndOfStatement();
3113 return false;
3114 } else if (Tok.getString() == "micromips") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003115 return parseSetFeature(Mips::FeatureMicroMips);
Toma Tabacu26647792014-09-09 12:52:14 +00003116 } else if (Tok.getString() == "mips0") {
3117 return parseSetMips0Directive();
Daniel Sandersf0df2212014-08-04 12:20:00 +00003118 } else if (Tok.getString() == "mips1") {
3119 return parseSetFeature(Mips::FeatureMips1);
3120 } else if (Tok.getString() == "mips2") {
3121 return parseSetFeature(Mips::FeatureMips2);
3122 } else if (Tok.getString() == "mips3") {
3123 return parseSetFeature(Mips::FeatureMips3);
3124 } else if (Tok.getString() == "mips4") {
3125 return parseSetFeature(Mips::FeatureMips4);
3126 } else if (Tok.getString() == "mips5") {
3127 return parseSetFeature(Mips::FeatureMips5);
3128 } else if (Tok.getString() == "mips32") {
3129 return parseSetFeature(Mips::FeatureMips32);
Vladimir Medic615b26e2014-03-04 09:54:09 +00003130 } else if (Tok.getString() == "mips32r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003131 return parseSetFeature(Mips::FeatureMips32r2);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003132 } else if (Tok.getString() == "mips32r6") {
3133 return parseSetFeature(Mips::FeatureMips32r6);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00003134 } else if (Tok.getString() == "mips64") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003135 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00003136 } else if (Tok.getString() == "mips64r2") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003137 return parseSetFeature(Mips::FeatureMips64r2);
Daniel Sandersf0df2212014-08-04 12:20:00 +00003138 } else if (Tok.getString() == "mips64r6") {
3139 return parseSetFeature(Mips::FeatureMips64r6);
Vladimir Medic27c398e2014-03-05 11:05:09 +00003140 } else if (Tok.getString() == "dsp") {
Matheus Almeida2852af82014-04-22 10:15:54 +00003141 return parseSetFeature(Mips::FeatureDSP);
Toma Tabacu351b2fe2014-09-17 09:01:54 +00003142 } else if (Tok.getString() == "nodsp") {
3143 return parseSetNoDspDirective();
Daniel Sanders44934432014-08-07 12:03:36 +00003144 } else if (Tok.getString() == "msa") {
3145 return parseSetMsaDirective();
3146 } else if (Tok.getString() == "nomsa") {
3147 return parseSetNoMsaDirective();
Jack Carterd76b2372013-03-21 21:44:16 +00003148 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00003149 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00003150 parseSetAssignment();
3151 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00003152 }
Jack Carter07c818d2013-01-25 01:31:34 +00003153
Jack Carter0b744b32012-10-04 02:29:46 +00003154 return true;
3155}
3156
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003157/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00003158/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003159bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Jack Carter07c818d2013-01-25 01:31:34 +00003160 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3161 for (;;) {
3162 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003163 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00003164 return true;
3165
3166 getParser().getStreamer().EmitValue(Value, Size);
3167
3168 if (getLexer().is(AsmToken::EndOfStatement))
3169 break;
3170
Jack Carter07c818d2013-01-25 01:31:34 +00003171 if (getLexer().isNot(AsmToken::Comma))
Toma Tabacu65f10572014-09-16 15:00:52 +00003172 return Error(L, "unexpected token, expected comma");
Jack Carter07c818d2013-01-25 01:31:34 +00003173 Parser.Lex();
3174 }
3175 }
3176
3177 Parser.Lex();
3178 return false;
3179}
3180
Vladimir Medic4c299852013-11-06 11:27:05 +00003181/// parseDirectiveGpWord
3182/// ::= .gpword local_sym
3183bool MipsAsmParser::parseDirectiveGpWord() {
3184 const MCExpr *Value;
3185 // EmitGPRel32Value requires an expression, so we are using base class
3186 // method to evaluate the expression.
3187 if (getParser().parseExpression(Value))
3188 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00003189 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00003190
Vladimir Medice10c1122013-11-13 13:18:04 +00003191 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003192 return Error(getLexer().getLoc(),
3193 "unexpected token, expected end of statement");
Vladimir Medice10c1122013-11-13 13:18:04 +00003194 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00003195 return false;
3196}
3197
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003198/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00003199/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003200bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindolab59fb732014-03-28 18:50:26 +00003201 const MCExpr *Value;
3202 // EmitGPRel64Value requires an expression, so we are using base class
3203 // method to evaluate the expression.
3204 if (getParser().parseExpression(Value))
3205 return true;
3206 getParser().getStreamer().EmitGPRel64Value(Value);
3207
3208 if (getLexer().isNot(AsmToken::EndOfStatement))
Toma Tabacu65f10572014-09-16 15:00:52 +00003209 return Error(getLexer().getLoc(),
3210 "unexpected token, expected end of statement");
Rafael Espindolab59fb732014-03-28 18:50:26 +00003211 Parser.Lex(); // Eat EndOfStatement token.
3212 return false;
3213}
3214
Jack Carter0cd3c192014-01-06 23:27:31 +00003215bool MipsAsmParser::parseDirectiveOption() {
3216 // Get the option token.
3217 AsmToken Tok = Parser.getTok();
3218 // At the moment only identifiers are supported.
3219 if (Tok.isNot(AsmToken::Identifier)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003220 Error(Parser.getTok().getLoc(), "unexpected token, expected identifier");
Jack Carter0cd3c192014-01-06 23:27:31 +00003221 Parser.eatToEndOfStatement();
3222 return false;
3223 }
3224
3225 StringRef Option = Tok.getIdentifier();
3226
3227 if (Option == "pic0") {
3228 getTargetStreamer().emitDirectiveOptionPic0();
3229 Parser.Lex();
3230 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3231 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00003232 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00003233 Parser.eatToEndOfStatement();
3234 }
3235 return false;
3236 }
3237
Matheus Almeidaf79b2812014-03-26 13:40:29 +00003238 if (Option == "pic2") {
3239 getTargetStreamer().emitDirectiveOptionPic2();
3240 Parser.Lex();
3241 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
3242 Error(Parser.getTok().getLoc(),
Toma Tabacu65f10572014-09-16 15:00:52 +00003243 "unexpected token, expected end of statement");
Matheus Almeidaf79b2812014-03-26 13:40:29 +00003244 Parser.eatToEndOfStatement();
3245 }
3246 return false;
3247 }
3248
Jack Carter0cd3c192014-01-06 23:27:31 +00003249 // Unknown option.
Toma Tabacu65f10572014-09-16 15:00:52 +00003250 Warning(Parser.getTok().getLoc(),
3251 "unknown option, expected 'pic0' or 'pic2'");
Jack Carter0cd3c192014-01-06 23:27:31 +00003252 Parser.eatToEndOfStatement();
3253 return false;
3254}
3255
Daniel Sanders7e527422014-07-10 13:38:23 +00003256/// parseDirectiveModule
3257/// ::= .module oddspreg
3258/// ::= .module nooddspreg
3259/// ::= .module fp=value
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003260bool MipsAsmParser::parseDirectiveModule() {
Daniel Sanders7e527422014-07-10 13:38:23 +00003261 MCAsmLexer &Lexer = getLexer();
3262 SMLoc L = Lexer.getLoc();
3263
Daniel Sanderscdb45fa2014-08-14 09:18:14 +00003264 if (!getTargetStreamer().isModuleDirectiveAllowed()) {
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003265 // TODO : get a better message.
3266 reportParseError(".module directive must appear before any code");
3267 return false;
3268 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003269
3270 if (Lexer.is(AsmToken::Identifier)) {
3271 StringRef Option = Parser.getTok().getString();
3272 Parser.Lex();
3273
3274 if (Option == "oddspreg") {
3275 getTargetStreamer().emitDirectiveModuleOddSPReg(true, isABI_O32());
3276 clearFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
3277
3278 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003279 reportParseError("unexpected token, expected end of statement");
Daniel Sanders7e527422014-07-10 13:38:23 +00003280 return false;
3281 }
3282
3283 return false;
3284 } else if (Option == "nooddspreg") {
3285 if (!isABI_O32()) {
3286 Error(L, "'.module nooddspreg' requires the O32 ABI");
3287 return false;
3288 }
3289
3290 getTargetStreamer().emitDirectiveModuleOddSPReg(false, isABI_O32());
3291 setFeatureBits(Mips::FeatureNoOddSPReg, "nooddspreg");
3292
3293 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003294 reportParseError("unexpected token, expected end of statement");
Daniel Sanders7e527422014-07-10 13:38:23 +00003295 return false;
3296 }
3297
3298 return false;
3299 } else if (Option == "fp") {
3300 return parseDirectiveModuleFP();
3301 }
3302
3303 return Error(L, "'" + Twine(Option) + "' is not a valid .module option.");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003304 }
Daniel Sanders7e527422014-07-10 13:38:23 +00003305
3306 return false;
3307}
3308
3309/// parseDirectiveModuleFP
3310/// ::= =32
3311/// ::= =xx
3312/// ::= =64
3313bool MipsAsmParser::parseDirectiveModuleFP() {
3314 MCAsmLexer &Lexer = getLexer();
3315
3316 if (Lexer.isNot(AsmToken::Equal)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003317 reportParseError("unexpected token, expected equals sign '='");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003318 return false;
3319 }
3320 Parser.Lex(); // Eat '=' token.
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003321
Daniel Sanders7e527422014-07-10 13:38:23 +00003322 MipsABIFlagsSection::FpABIKind FpABI;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003323 if (!parseFpABIValue(FpABI, ".module"))
3324 return false;
3325
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003326 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003327 reportParseError("unexpected token, expected end of statement");
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003328 return false;
3329 }
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003330
Daniel Sanders7201a3e2014-07-08 10:35:52 +00003331 // Emit appropriate flags.
3332 getTargetStreamer().emitDirectiveModuleFP(FpABI, isABI_O32());
Daniel Sanders7e527422014-07-10 13:38:23 +00003333 Parser.Lex(); // Consume the EndOfStatement.
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003334 return false;
3335}
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003336
Daniel Sanders7e527422014-07-10 13:38:23 +00003337bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003338 StringRef Directive) {
3339 MCAsmLexer &Lexer = getLexer();
3340
3341 if (Lexer.is(AsmToken::Identifier)) {
3342 StringRef Value = Parser.getTok().getString();
3343 Parser.Lex();
3344
3345 if (Value != "xx") {
3346 reportParseError("unsupported value, expected 'xx', '32' or '64'");
3347 return false;
3348 }
3349
3350 if (!isABI_O32()) {
3351 reportParseError("'" + Directive + " fp=xx' requires the O32 ABI");
3352 return false;
3353 }
3354
Daniel Sanders7e527422014-07-10 13:38:23 +00003355 FpABI = MipsABIFlagsSection::FpABIKind::XX;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003356 return true;
3357 }
3358
3359 if (Lexer.is(AsmToken::Integer)) {
3360 unsigned Value = Parser.getTok().getIntVal();
3361 Parser.Lex();
3362
3363 if (Value != 32 && Value != 64) {
3364 reportParseError("unsupported value, expected 'xx', '32' or '64'");
3365 return false;
3366 }
3367
3368 if (Value == 32) {
3369 if (!isABI_O32()) {
3370 reportParseError("'" + Directive + " fp=32' requires the O32 ABI");
3371 return false;
3372 }
3373
Daniel Sanders7e527422014-07-10 13:38:23 +00003374 FpABI = MipsABIFlagsSection::FpABIKind::S32;
3375 } else
3376 FpABI = MipsABIFlagsSection::FpABIKind::S64;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003377
Daniel Sanders7e527422014-07-10 13:38:23 +00003378 return true;
Daniel Sandersc7dbc632014-07-08 10:11:38 +00003379 }
3380
3381 return false;
3382}
3383
Jack Carter0b744b32012-10-04 02:29:46 +00003384bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carter07c818d2013-01-25 01:31:34 +00003385 StringRef IDVal = DirectiveID.getString();
3386
Matheus Almeida525bc4f2014-04-30 11:28:42 +00003387 if (IDVal == ".cpload")
Toma Tabacuc4c202a2014-10-01 14:53:19 +00003388 return parseDirectiveCpLoad(DirectiveID.getLoc());
Matheus Almeidaab5633b2014-03-26 15:44:18 +00003389 if (IDVal == ".dword") {
3390 parseDataDirective(8, DirectiveID.getLoc());
3391 return false;
3392 }
Jack Carterd0bd6422013-04-18 00:41:53 +00003393 if (IDVal == ".ent") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003394 StringRef SymbolName;
3395
3396 if (Parser.parseIdentifier(SymbolName)) {
3397 reportParseError("expected identifier after .ent");
3398 return false;
3399 }
3400
3401 // There's an undocumented extension that allows an integer to
3402 // follow the name of the procedure which AFAICS is ignored by GAS.
3403 // Example: .ent foo,2
3404 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3405 if (getLexer().isNot(AsmToken::Comma)) {
3406 // Even though we accept this undocumented extension for compatibility
3407 // reasons, the additional integer argument does not actually change
3408 // the behaviour of the '.ent' directive, so we would like to discourage
3409 // its use. We do this by not referring to the extended version in
3410 // error messages which are not directly related to its use.
3411 reportParseError("unexpected token, expected end of statement");
3412 return false;
3413 }
3414 Parser.Lex(); // Eat the comma.
3415 const MCExpr *DummyNumber;
3416 int64_t DummyNumberVal;
3417 // If the user was explicitly trying to use the extended version,
3418 // we still give helpful extension-related error messages.
3419 if (Parser.parseExpression(DummyNumber)) {
3420 reportParseError("expected number after comma");
3421 return false;
3422 }
3423 if (!DummyNumber->EvaluateAsAbsolute(DummyNumberVal)) {
3424 reportParseError("expected an absolute expression after comma");
3425 return false;
3426 }
3427 }
3428
3429 // If this is not the end of the statement, report an error.
3430 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3431 reportParseError("unexpected token, expected end of statement");
3432 return false;
3433 }
3434
3435 MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
3436
3437 getTargetStreamer().emitDirectiveEnt(*Sym);
3438 CurrentFn = Sym;
Jack Carterbe332172012-09-07 00:48:02 +00003439 return false;
3440 }
3441
Jack Carter07c818d2013-01-25 01:31:34 +00003442 if (IDVal == ".end") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003443 StringRef SymbolName;
3444
3445 if (Parser.parseIdentifier(SymbolName)) {
3446 reportParseError("expected identifier after .end");
3447 return false;
3448 }
3449
3450 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3451 reportParseError("unexpected token, expected end of statement");
3452 return false;
3453 }
3454
3455 if (CurrentFn == nullptr) {
3456 reportParseError(".end used without .ent");
3457 return false;
3458 }
3459
3460 if ((SymbolName != CurrentFn->getName())) {
3461 reportParseError(".end symbol does not match .ent symbol");
3462 return false;
3463 }
3464
3465 getTargetStreamer().emitDirectiveEnd(SymbolName);
3466 CurrentFn = nullptr;
Jack Carterbe332172012-09-07 00:48:02 +00003467 return false;
3468 }
3469
Jack Carter07c818d2013-01-25 01:31:34 +00003470 if (IDVal == ".frame") {
Daniel Sandersd97a6342014-08-13 10:07:34 +00003471 // .frame $stack_reg, frame_size_in_bytes, $return_reg
3472 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
Toma Tabacu13964452014-09-04 13:23:44 +00003473 OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00003474 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3475 reportParseError("expected stack register");
3476 return false;
3477 }
3478
3479 MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3480 if (!StackRegOpnd.isGPRAsmReg()) {
3481 reportParseError(StackRegOpnd.getStartLoc(),
3482 "expected general purpose register");
3483 return false;
3484 }
3485 unsigned StackReg = StackRegOpnd.getGPR32Reg();
3486
3487 if (Parser.getTok().is(AsmToken::Comma))
3488 Parser.Lex();
3489 else {
3490 reportParseError("unexpected token, expected comma");
3491 return false;
3492 }
3493
3494 // Parse the frame size.
3495 const MCExpr *FrameSize;
3496 int64_t FrameSizeVal;
3497
3498 if (Parser.parseExpression(FrameSize)) {
3499 reportParseError("expected frame size value");
3500 return false;
3501 }
3502
3503 if (!FrameSize->EvaluateAsAbsolute(FrameSizeVal)) {
3504 reportParseError("frame size not an absolute expression");
3505 return false;
3506 }
3507
3508 if (Parser.getTok().is(AsmToken::Comma))
3509 Parser.Lex();
3510 else {
3511 reportParseError("unexpected token, expected comma");
3512 return false;
3513 }
3514
3515 // Parse the return register.
3516 TmpReg.clear();
Toma Tabacu13964452014-09-04 13:23:44 +00003517 ResTy = parseAnyRegister(TmpReg);
Daniel Sandersd97a6342014-08-13 10:07:34 +00003518 if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3519 reportParseError("expected return register");
3520 return false;
3521 }
3522
3523 MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3524 if (!ReturnRegOpnd.isGPRAsmReg()) {
3525 reportParseError(ReturnRegOpnd.getStartLoc(),
3526 "expected general purpose register");
3527 return false;
3528 }
3529
3530 // If this is not the end of the statement, report an error.
3531 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3532 reportParseError("unexpected token, expected end of statement");
3533 return false;
3534 }
3535
3536 getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
3537 ReturnRegOpnd.getGPR32Reg());
Jack Carterbe332172012-09-07 00:48:02 +00003538 return false;
3539 }
3540
Jack Carter07c818d2013-01-25 01:31:34 +00003541 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00003542 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00003543 }
3544
Daniel Sandersd97a6342014-08-13 10:07:34 +00003545 if (IDVal == ".mask" || IDVal == ".fmask") {
3546 // .mask bitmask, frame_offset
3547 // bitmask: One bit for each register used.
3548 // frame_offset: Offset from Canonical Frame Address ($sp on entry) where
3549 // first register is expected to be saved.
3550 // Examples:
3551 // .mask 0x80000000, -4
3552 // .fmask 0x80000000, -4
3553 //
Jack Carterbe332172012-09-07 00:48:02 +00003554
Daniel Sandersd97a6342014-08-13 10:07:34 +00003555 // Parse the bitmask
3556 const MCExpr *BitMask;
3557 int64_t BitMaskVal;
3558
3559 if (Parser.parseExpression(BitMask)) {
3560 reportParseError("expected bitmask value");
3561 return false;
3562 }
3563
3564 if (!BitMask->EvaluateAsAbsolute(BitMaskVal)) {
3565 reportParseError("bitmask not an absolute expression");
3566 return false;
3567 }
3568
3569 if (Parser.getTok().is(AsmToken::Comma))
3570 Parser.Lex();
3571 else {
3572 reportParseError("unexpected token, expected comma");
3573 return false;
3574 }
3575
3576 // Parse the frame_offset
3577 const MCExpr *FrameOffset;
3578 int64_t FrameOffsetVal;
3579
3580 if (Parser.parseExpression(FrameOffset)) {
3581 reportParseError("expected frame offset value");
3582 return false;
3583 }
3584
3585 if (!FrameOffset->EvaluateAsAbsolute(FrameOffsetVal)) {
3586 reportParseError("frame offset not an absolute expression");
3587 return false;
3588 }
3589
3590 // If this is not the end of the statement, report an error.
3591 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3592 reportParseError("unexpected token, expected end of statement");
3593 return false;
3594 }
3595
3596 if (IDVal == ".mask")
3597 getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
3598 else
3599 getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
Jack Carterbe332172012-09-07 00:48:02 +00003600 return false;
3601 }
3602
Matheus Almeida0051f2d2014-04-16 15:48:55 +00003603 if (IDVal == ".nan")
3604 return parseDirectiveNaN();
3605
Jack Carter07c818d2013-01-25 01:31:34 +00003606 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00003607 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00003608 return false;
3609 }
3610
Rafael Espindolab59fb732014-03-28 18:50:26 +00003611 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00003612 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00003613 return false;
3614 }
3615
Jack Carter07c818d2013-01-25 01:31:34 +00003616 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00003617 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00003618 return false;
3619 }
3620
Jack Carter0cd3c192014-01-06 23:27:31 +00003621 if (IDVal == ".option")
3622 return parseDirectiveOption();
3623
3624 if (IDVal == ".abicalls") {
3625 getTargetStreamer().emitDirectiveAbiCalls();
3626 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Toma Tabacu65f10572014-09-16 15:00:52 +00003627 Error(Parser.getTok().getLoc(),
3628 "unexpected token, expected end of statement");
Jack Carter0cd3c192014-01-06 23:27:31 +00003629 // Clear line
3630 Parser.eatToEndOfStatement();
3631 }
3632 return false;
3633 }
3634
Daniel Sanders5bce5f62014-03-27 13:52:53 +00003635 if (IDVal == ".cpsetup")
3636 return parseDirectiveCPSetup();
3637
Vladimir Medicfb8a2a92014-07-08 08:59:22 +00003638 if (IDVal == ".module")
3639 return parseDirectiveModule();
3640
Rafael Espindola870c4e92012-01-11 03:56:41 +00003641 return true;
3642}
3643
Rafael Espindola870c4e92012-01-11 03:56:41 +00003644extern "C" void LLVMInitializeMipsAsmParser() {
3645 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
3646 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
3647 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
3648 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
3649}
Jack Carterb4dbc172012-09-05 23:34:03 +00003650
3651#define GET_REGISTER_MATCHER
3652#define GET_MATCHER_IMPLEMENTATION
3653#include "MipsGenAsmMatcher.inc"