blob: 7a731eb3a091093f96389488bba74a41c3f43a6d [file] [log] [blame]
Jia Liu9f610112012-02-17 08:55:11 +00001//===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
Rafael Espindola870c4e92012-01-11 03:56:41 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Petar Jovanovica5da5882014-02-04 18:41:57 +000010#include "MCTargetDesc/MipsMCExpr.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000011#include "MCTargetDesc/MipsMCTargetDesc.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000012#include "MipsRegisterInfo.h"
Rafael Espindolaa17151a2013-10-08 13:08:17 +000013#include "MipsTargetStreamer.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000014#include "llvm/ADT/APInt.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000015#include "llvm/ADT/StringSwitch.h"
16#include "llvm/MC/MCContext.h"
17#include "llvm/MC/MCExpr.h"
18#include "llvm/MC/MCInst.h"
Daniel Sandersa771fef2014-03-24 14:05:39 +000019#include "llvm/MC/MCInstBuilder.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000020#include "llvm/MC/MCParser/MCAsmLexer.h"
21#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000022#include "llvm/MC/MCStreamer.h"
23#include "llvm/MC/MCSubtargetInfo.h"
24#include "llvm/MC/MCSymbol.h"
Akira Hatanaka7605630c2012-08-17 20:16:42 +000025#include "llvm/MC/MCTargetAsmParser.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000026#include "llvm/Support/MathExtras.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000027#include "llvm/Support/TargetRegistry.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000028
29using namespace llvm;
30
Joey Gouly0e76fa72013-09-12 10:28:05 +000031namespace llvm {
32class MCInstrInfo;
33}
34
Rafael Espindola870c4e92012-01-11 03:56:41 +000035namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000036class MipsAssemblerOptions {
37public:
Vladimir Medic4c299852013-11-06 11:27:05 +000038 MipsAssemblerOptions() : aTReg(1), reorder(true), macro(true) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000039
Vladimir Medic4c299852013-11-06 11:27:05 +000040 unsigned getATRegNum() { return aTReg; }
Jack Carter0b744b32012-10-04 02:29:46 +000041 bool setATReg(unsigned Reg);
42
Vladimir Medic4c299852013-11-06 11:27:05 +000043 bool isReorder() { return reorder; }
44 void setReorder() { reorder = true; }
45 void setNoreorder() { reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000046
Vladimir Medic4c299852013-11-06 11:27:05 +000047 bool isMacro() { return macro; }
48 void setMacro() { macro = true; }
49 void setNomacro() { macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000050
51private:
52 unsigned aTReg;
53 bool reorder;
54 bool macro;
55};
56}
57
58namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +000059class MipsAsmParser : public MCTargetAsmParser {
Akira Hatanaka7605630c2012-08-17 20:16:42 +000060
Rafael Espindolaa17151a2013-10-08 13:08:17 +000061 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola4a1a3602014-01-14 01:21:46 +000062 MCTargetStreamer &TS = *Parser.getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +000063 return static_cast<MipsTargetStreamer &>(TS);
64 }
65
Jack Carterb4dbc172012-09-05 23:34:03 +000066 MCSubtargetInfo &STI;
67 MCAsmParser &Parser;
Jack Carter99d2afe2012-10-05 23:55:28 +000068 MipsAssemblerOptions Options;
Vladimir Medic27c87ea2013-08-13 13:07:09 +000069 bool hasConsumedDollar;
Jack Carter0b744b32012-10-04 02:29:46 +000070
Akira Hatanaka7605630c2012-08-17 20:16:42 +000071#define GET_ASSEMBLER_HEADER
72#include "MipsGenAsmMatcher.inc"
73
Chad Rosier49963552012-10-13 00:26:04 +000074 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
Vladimir Medic4c299852013-11-06 11:27:05 +000075 SmallVectorImpl<MCParsedAsmOperand *> &Operands,
Chad Rosier49963552012-10-13 00:26:04 +000076 MCStreamer &Out, unsigned &ErrorInfo,
77 bool MatchingInlineAsm);
Rafael Espindola870c4e92012-01-11 03:56:41 +000078
79 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
80
Chad Rosierf0e87202012-10-25 20:41:34 +000081 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
82 SMLoc NameLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +000083 SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Rafael Espindola870c4e92012-01-11 03:56:41 +000084
85 bool ParseDirective(AsmToken DirectiveID);
86
Jack Carterb4dbc172012-09-05 23:34:03 +000087 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +000088 parseRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands, int RegKind);
Vladimir Medic64828a12013-07-16 10:07:14 +000089
90 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +000091 parseMSARegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands, int RegKind);
Jack Carter5dc8ac92013-09-25 23:50:44 +000092
93 MipsAsmParser::OperandMatchResultTy
Matheus Almeidaa591fdc2013-10-21 12:26:50 +000094 parseMSACtrlRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
95 int RegKind);
96
97 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +000098 parseMemOperand(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Jack Carter873c7242013-01-12 01:03:14 +000099
Vladimir Medic4c299852013-11-06 11:27:05 +0000100 bool parsePtrReg(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
101 int RegKind);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000102
103 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +0000104 parsePtrReg(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000105
Jack Carter873c7242013-01-12 01:03:14 +0000106 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +0000107 parseGPR32(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Jack Carter873c7242013-01-12 01:03:14 +0000108
109 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +0000110 parseGPR64(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Jack Carter873c7242013-01-12 01:03:14 +0000111
112 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +0000113 parseHWRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Jack Carter873c7242013-01-12 01:03:14 +0000114
115 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +0000116 parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Chad Rosier391d29972012-09-03 18:47:45 +0000117
Vladimir Medic233dd512013-06-24 10:05:34 +0000118 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +0000119 parseAFGR64Regs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Vladimir Medic233dd512013-06-24 10:05:34 +0000120
121 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +0000122 parseFGR64Regs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Vladimir Medic233dd512013-06-24 10:05:34 +0000123
124 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +0000125 parseFGR32Regs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Vladimir Medic233dd512013-06-24 10:05:34 +0000126
Vladimir Medic643b3982013-07-30 10:12:14 +0000127 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +0000128 parseFGRH32Regs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Akira Hatanaka14e31a22013-08-20 22:58:56 +0000129
130 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +0000131 parseFCCRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Vladimir Medic643b3982013-07-30 10:12:14 +0000132
Akira Hatanaka34a32c02013-08-06 22:20:40 +0000133 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +0000134 parseACC64DSP(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Akira Hatanaka34a32c02013-08-06 22:20:40 +0000135
Akira Hatanakafeb7ee82013-08-14 01:02:20 +0000136 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +0000137 parseLO32DSP(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Akira Hatanakafeb7ee82013-08-14 01:02:20 +0000138
139 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +0000140 parseHI32DSP(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Akira Hatanakafeb7ee82013-08-14 01:02:20 +0000141
Vladimir Medic05bcde62013-09-16 10:29:42 +0000142 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +0000143 parseCOP2(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Vladimir Medic05bcde62013-09-16 10:29:42 +0000144
Jack Carter5dc8ac92013-09-25 23:50:44 +0000145 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +0000146 parseMSA128BRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Jack Carter5dc8ac92013-09-25 23:50:44 +0000147
148 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +0000149 parseMSA128HRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Jack Carter5dc8ac92013-09-25 23:50:44 +0000150
151 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +0000152 parseMSA128WRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Jack Carter5dc8ac92013-09-25 23:50:44 +0000153
154 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +0000155 parseMSA128DRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Jack Carter5dc8ac92013-09-25 23:50:44 +0000156
Vladimir Medic2b953d02013-10-01 09:48:56 +0000157 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +0000158 parseMSA128CtrlRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000159
160 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +0000161 parseInvNum(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Vladimir Medic2b953d02013-10-01 09:48:56 +0000162
Matheus Almeida779c5932013-11-18 12:32:49 +0000163 MipsAsmParser::OperandMatchResultTy
164 parseLSAImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
165
Jack Carter3b2c96e2014-01-22 23:31:38 +0000166 bool searchSymbolAlias(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
Vladimir Medic8cd17102013-06-20 11:21:49 +0000167 unsigned RegKind);
Jack Carterd76b2372013-03-21 21:44:16 +0000168
Vladimir Medic4c299852013-11-06 11:27:05 +0000169 bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand *> &,
Jack Carterb4dbc172012-09-05 23:34:03 +0000170 StringRef Mnemonic);
171
Jack Carter873c7242013-01-12 01:03:14 +0000172 int tryParseRegister(bool is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000173
Vladimir Medic4c299852013-11-06 11:27:05 +0000174 bool tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
Jack Carter873c7242013-01-12 01:03:14 +0000175 bool is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000176
Jack Carter30a59822012-10-04 04:03:53 +0000177 bool needsExpansion(MCInst &Inst);
178
179 void expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000180 SmallVectorImpl<MCInst> &Instructions);
Jack Carter30a59822012-10-04 04:03:53 +0000181 void expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000182 SmallVectorImpl<MCInst> &Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +0000183 void expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
184 SmallVectorImpl<MCInst> &Instructions);
185 void expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
186 SmallVectorImpl<MCInst> &Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +0000187 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000188 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
189 bool isImmOpnd);
Jack Carter0b744b32012-10-04 02:29:46 +0000190 bool reportParseError(StringRef ErrorMsg);
191
Jack Carterb5cf5902013-04-17 00:18:04 +0000192 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000193 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000194
Vladimir Medic4c299852013-11-06 11:27:05 +0000195 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000196
197 bool isEvaluated(const MCExpr *Expr);
Matheus Almeidafe1e39d2014-03-26 14:26:27 +0000198 bool parseSetFeature(uint64_t Feature);
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000199 bool parseDirectiveCPSetup();
Jack Carter0b744b32012-10-04 02:29:46 +0000200 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000201 bool parseDirectiveOption();
Jack Carter0b744b32012-10-04 02:29:46 +0000202
203 bool parseSetAtDirective();
204 bool parseSetNoAtDirective();
205 bool parseSetMacroDirective();
206 bool parseSetNoMacroDirective();
207 bool parseSetReorderDirective();
208 bool parseSetNoReorderDirective();
Jack Carter39536722014-01-22 23:08:42 +0000209 bool parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +0000210
Jack Carterd76b2372013-03-21 21:44:16 +0000211 bool parseSetAssignment();
212
Matheus Almeida3e2a7022014-03-26 15:24:36 +0000213 bool parseDataDirective(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000214 bool parseDirectiveGpWord();
Rafael Espindola2378d4c2014-03-31 14:15:07 +0000215 bool parseDirectiveGpDWord();
Jack Carter07c818d2013-01-25 01:31:34 +0000216
Jack Carterdc1e35d2012-09-06 20:00:02 +0000217 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000218
Daniel Sanders5e94e682014-03-27 16:42:17 +0000219 bool isGP64() const {
220 return (STI.getFeatureBits() & Mips::FeatureGP64Bit) != 0;
Jack Carterb4dbc172012-09-05 23:34:03 +0000221 }
222
Jack Cartera63b16a2012-09-07 00:23:42 +0000223 bool isFP64() const {
224 return (STI.getFeatureBits() & Mips::FeatureFP64Bit) != 0;
225 }
226
Daniel Sandersa4b0c742014-03-26 11:39:07 +0000227 bool isN32() const { return STI.getFeatureBits() & Mips::FeatureN32; }
Vladimir Medic4c299852013-11-06 11:27:05 +0000228 bool isN64() const { return STI.getFeatureBits() & Mips::FeatureN64; }
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000229
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000230 bool isMicroMips() const {
231 return STI.getFeatureBits() & Mips::FeatureMicroMips;
232 }
233
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000234 bool parseRegister(unsigned &RegNum);
235
236 bool eatComma(StringRef ErrorStr);
237
Jack Carter873c7242013-01-12 01:03:14 +0000238 int matchRegisterName(StringRef Symbol, bool is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000239
Jack Carter1ac53222013-02-20 23:11:17 +0000240 int matchCPURegisterName(StringRef Symbol);
241
Jack Carter873c7242013-01-12 01:03:14 +0000242 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000243
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000244 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000245
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000246 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000247
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000248 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000249
Jack Carter5dc8ac92013-09-25 23:50:44 +0000250 int matchMSA128RegisterName(StringRef Name);
251
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000252 int matchMSA128CtrlRegisterName(StringRef Name);
253
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000254 int regKindToRegClass(int RegKind);
Jack Cartera63b16a2012-09-07 00:23:42 +0000255
Jack Carterd0bd6422013-04-18 00:41:53 +0000256 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000257
Daniel Sanders5bce5f62014-03-27 13:52:53 +0000258 unsigned getGPR(int RegNo);
259
Jack Carter1ac53222013-02-20 23:11:17 +0000260 int getATReg();
Jack Carter9e65aa32013-03-22 00:05:30 +0000261
Daniel Sandersb1d7e532014-03-25 11:16:03 +0000262 // Warn if RegNo is the current assembler temporary.
263 void warnIfAssemblerTemporary(int RegNo);
264
Jack Carter9e65aa32013-03-22 00:05:30 +0000265 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000266 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000267
268 // Helper function that checks if the value of a vector index is within the
269 // boundaries of accepted values for each RegisterKind
270 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
271 bool validateMSAIndex(int Val, int RegKind);
272
Vladimir Medic615b26e2014-03-04 09:54:09 +0000273 void setFeatureBits(unsigned Feature, StringRef FeatureString) {
274 if (!(STI.getFeatureBits() & Feature)) {
275 setAvailableFeatures(ComputeAvailableFeatures(
276 STI.ToggleFeature(FeatureString)));
277 }
278 }
279
280 void clearFeatureBits(unsigned Feature, StringRef FeatureString) {
281 if (STI.getFeatureBits() & Feature) {
282 setAvailableFeatures(ComputeAvailableFeatures(
283 STI.ToggleFeature(FeatureString)));
284 }
285 }
286
Rafael Espindola870c4e92012-01-11 03:56:41 +0000287public:
Joey Gouly0e76fa72013-09-12 10:28:05 +0000288 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
289 const MCInstrInfo &MII)
290 : MCTargetAsmParser(), STI(sti), Parser(parser),
291 hasConsumedDollar(false) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000292 // Initialize the set of available features.
293 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Daniel Sanders5a1449d2014-02-20 14:58:19 +0000294
295 // Assert exactly one ABI was chosen.
296 assert((((STI.getFeatureBits() & Mips::FeatureO32) != 0) +
297 ((STI.getFeatureBits() & Mips::FeatureEABI) != 0) +
298 ((STI.getFeatureBits() & Mips::FeatureN32) != 0) +
299 ((STI.getFeatureBits() & Mips::FeatureN64) != 0)) == 1);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000300 }
301
Jack Carterb4dbc172012-09-05 23:34:03 +0000302 MCAsmParser &getParser() const { return Parser; }
303 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000304};
305}
306
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000307namespace {
308
309/// MipsOperand - Instances of this class represent a parsed Mips machine
310/// instruction.
311class MipsOperand : public MCParsedAsmOperand {
Jack Carterb4dbc172012-09-05 23:34:03 +0000312
Jack Carter873c7242013-01-12 01:03:14 +0000313public:
314 enum RegisterKind {
315 Kind_None,
Akira Hatanaka13e6ccf2013-08-06 23:08:38 +0000316 Kind_GPR32,
317 Kind_GPR64,
Jack Carter873c7242013-01-12 01:03:14 +0000318 Kind_HWRegs,
Jack Carter873c7242013-01-12 01:03:14 +0000319 Kind_FGR32Regs,
Akira Hatanaka14e31a22013-08-20 22:58:56 +0000320 Kind_FGRH32Regs,
Jack Carter873c7242013-01-12 01:03:14 +0000321 Kind_FGR64Regs,
Jack Carter1ac53222013-02-20 23:11:17 +0000322 Kind_AFGR64Regs,
Vladimir Medic643b3982013-07-30 10:12:14 +0000323 Kind_CCRRegs,
Akira Hatanaka34a32c02013-08-06 22:20:40 +0000324 Kind_FCCRegs,
Akira Hatanakafeb7ee82013-08-14 01:02:20 +0000325 Kind_ACC64DSP,
326 Kind_LO32DSP,
Vladimir Medic05bcde62013-09-16 10:29:42 +0000327 Kind_HI32DSP,
Jack Carter5dc8ac92013-09-25 23:50:44 +0000328 Kind_COP2,
329 Kind_MSA128BRegs,
330 Kind_MSA128HRegs,
331 Kind_MSA128WRegs,
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000332 Kind_MSA128DRegs,
333 Kind_MSA128CtrlRegs
Jack Carter873c7242013-01-12 01:03:14 +0000334 };
335
336private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000337 enum KindTy {
338 k_CondCode,
339 k_CoprocNum,
340 k_Immediate,
341 k_Memory,
342 k_PostIndexRegister,
343 k_Register,
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000344 k_PtrReg,
Matheus Almeida779c5932013-11-18 12:32:49 +0000345 k_Token,
346 k_LSAImm
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000347 } Kind;
348
349 MipsOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
Jack Carterb4dbc172012-09-05 23:34:03 +0000350
Eric Christopher8996c5d2013-03-15 00:42:55 +0000351 struct Token {
352 const char *Data;
353 unsigned Length;
354 };
355
356 struct RegOp {
357 unsigned RegNum;
358 RegisterKind Kind;
359 };
360
361 struct ImmOp {
362 const MCExpr *Val;
363 };
364
365 struct MemOp {
366 unsigned Base;
367 const MCExpr *Off;
368 };
369
Jack Carterb4dbc172012-09-05 23:34:03 +0000370 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000371 struct Token Tok;
372 struct RegOp Reg;
373 struct ImmOp Imm;
374 struct MemOp Mem;
Jack Carterb4dbc172012-09-05 23:34:03 +0000375 };
376
377 SMLoc StartLoc, EndLoc;
378
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000379public:
380 void addRegOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000381 assert(N == 1 && "Invalid number of operands!");
382 Inst.addOperand(MCOperand::CreateReg(getReg()));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000383 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000384
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000385 void addPtrRegOperands(MCInst &Inst, unsigned N) const {
386 assert(N == 1 && "Invalid number of operands!");
387 Inst.addOperand(MCOperand::CreateReg(getPtrReg()));
388 }
389
Vladimir Medic4c299852013-11-06 11:27:05 +0000390 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000391 // Add as immediate when possible. Null MCExpr = 0.
392 if (Expr == 0)
393 Inst.addOperand(MCOperand::CreateImm(0));
394 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
395 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
396 else
397 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000398 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000399
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000400 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000401 assert(N == 1 && "Invalid number of operands!");
402 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000403 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000404 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000405
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000406 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000407 assert(N == 2 && "Invalid number of operands!");
408
409 Inst.addOperand(MCOperand::CreateReg(getMemBase()));
410
411 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000412 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000413 }
414
415 bool isReg() const { return Kind == k_Register; }
416 bool isImm() const { return Kind == k_Immediate; }
417 bool isToken() const { return Kind == k_Token; }
418 bool isMem() const { return Kind == k_Memory; }
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000419 bool isPtrReg() const { return Kind == k_PtrReg; }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000420 bool isInvNum() const { return Kind == k_Immediate; }
Matheus Almeida779c5932013-11-18 12:32:49 +0000421 bool isLSAImm() const { return Kind == k_LSAImm; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000422
423 StringRef getToken() const {
424 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000425 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000426 }
427
428 unsigned getReg() const {
429 assert((Kind == k_Register) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000430 return Reg.RegNum;
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000431 }
432
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000433 unsigned getPtrReg() const {
434 assert((Kind == k_PtrReg) && "Invalid access!");
435 return Reg.RegNum;
436 }
437
Jack Carter873c7242013-01-12 01:03:14 +0000438 void setRegKind(RegisterKind RegKind) {
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000439 assert((Kind == k_Register || Kind == k_PtrReg) && "Invalid access!");
Jack Carter873c7242013-01-12 01:03:14 +0000440 Reg.Kind = RegKind;
441 }
442
Jack Carterb4dbc172012-09-05 23:34:03 +0000443 const MCExpr *getImm() const {
Matheus Almeida779c5932013-11-18 12:32:49 +0000444 assert((Kind == k_Immediate || Kind == k_LSAImm) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000445 return Imm.Val;
446 }
447
Jack Carterdc1e35d2012-09-06 20:00:02 +0000448 unsigned getMemBase() const {
449 assert((Kind == k_Memory) && "Invalid access!");
450 return Mem.Base;
451 }
452
453 const MCExpr *getMemOff() const {
454 assert((Kind == k_Memory) && "Invalid access!");
455 return Mem.Off;
456 }
457
Jack Carterb4dbc172012-09-05 23:34:03 +0000458 static MipsOperand *CreateToken(StringRef Str, SMLoc S) {
459 MipsOperand *Op = new MipsOperand(k_Token);
460 Op->Tok.Data = Str.data();
461 Op->Tok.Length = Str.size();
462 Op->StartLoc = S;
463 Op->EndLoc = S;
464 return Op;
465 }
466
467 static MipsOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
468 MipsOperand *Op = new MipsOperand(k_Register);
469 Op->Reg.RegNum = RegNum;
470 Op->StartLoc = S;
471 Op->EndLoc = E;
472 return Op;
473 }
474
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000475 static MipsOperand *CreatePtrReg(unsigned RegNum, SMLoc S, SMLoc E) {
476 MipsOperand *Op = new MipsOperand(k_PtrReg);
477 Op->Reg.RegNum = RegNum;
478 Op->StartLoc = S;
479 Op->EndLoc = E;
480 return Op;
481 }
482
Jack Carterb4dbc172012-09-05 23:34:03 +0000483 static MipsOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
484 MipsOperand *Op = new MipsOperand(k_Immediate);
485 Op->Imm.Val = Val;
486 Op->StartLoc = S;
487 Op->EndLoc = E;
488 return Op;
489 }
490
Matheus Almeida779c5932013-11-18 12:32:49 +0000491 static MipsOperand *CreateLSAImm(const MCExpr *Val, SMLoc S, SMLoc E) {
492 MipsOperand *Op = new MipsOperand(k_LSAImm);
493 Op->Imm.Val = Val;
494 Op->StartLoc = S;
495 Op->EndLoc = E;
496 return Op;
497 }
498
Jack Carter3b2c96e2014-01-22 23:31:38 +0000499 static MipsOperand *CreateMem(unsigned Base, const MCExpr *Off, SMLoc S,
500 SMLoc E) {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000501 MipsOperand *Op = new MipsOperand(k_Memory);
502 Op->Mem.Base = Base;
503 Op->Mem.Off = Off;
504 Op->StartLoc = S;
505 Op->EndLoc = E;
506 return Op;
507 }
508
Akira Hatanaka13e6ccf2013-08-06 23:08:38 +0000509 bool isGPR32Asm() const {
510 return Kind == k_Register && Reg.Kind == Kind_GPR32;
Jack Carter873c7242013-01-12 01:03:14 +0000511 }
Vladimir Medicc6960592013-06-19 10:14:36 +0000512 void addRegAsmOperands(MCInst &Inst, unsigned N) const {
Jack Carter873c7242013-01-12 01:03:14 +0000513 Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
514 }
515
Akira Hatanaka13e6ccf2013-08-06 23:08:38 +0000516 bool isGPR64Asm() const {
517 return Kind == k_Register && Reg.Kind == Kind_GPR64;
Jack Carter873c7242013-01-12 01:03:14 +0000518 }
Jack Carter873c7242013-01-12 01:03:14 +0000519
520 bool isHWRegsAsm() const {
521 assert((Kind == k_Register) && "Invalid access!");
522 return Reg.Kind == Kind_HWRegs;
523 }
Jack Carter873c7242013-01-12 01:03:14 +0000524
Jack Carter873c7242013-01-12 01:03:14 +0000525 bool isCCRAsm() const {
526 assert((Kind == k_Register) && "Invalid access!");
527 return Reg.Kind == Kind_CCRRegs;
528 }
529
Vladimir Medic4c299852013-11-06 11:27:05 +0000530 bool isAFGR64Asm() const {
Vladimir Medic233dd512013-06-24 10:05:34 +0000531 return Kind == k_Register && Reg.Kind == Kind_AFGR64Regs;
532 }
533
534 bool isFGR64Asm() const {
535 return Kind == k_Register && Reg.Kind == Kind_FGR64Regs;
536 }
537
538 bool isFGR32Asm() const {
539 return (Kind == k_Register) && Reg.Kind == Kind_FGR32Regs;
540 }
541
Akira Hatanaka14e31a22013-08-20 22:58:56 +0000542 bool isFGRH32Asm() const {
543 return (Kind == k_Register) && Reg.Kind == Kind_FGRH32Regs;
544 }
545
Vladimir Medic643b3982013-07-30 10:12:14 +0000546 bool isFCCRegsAsm() const {
547 return (Kind == k_Register) && Reg.Kind == Kind_FCCRegs;
548 }
549
Akira Hatanaka00fcf2e2013-08-08 21:54:26 +0000550 bool isACC64DSPAsm() const {
551 return Kind == k_Register && Reg.Kind == Kind_ACC64DSP;
Akira Hatanaka34a32c02013-08-06 22:20:40 +0000552 }
553
Akira Hatanakafeb7ee82013-08-14 01:02:20 +0000554 bool isLO32DSPAsm() const {
555 return Kind == k_Register && Reg.Kind == Kind_LO32DSP;
556 }
557
558 bool isHI32DSPAsm() const {
559 return Kind == k_Register && Reg.Kind == Kind_HI32DSP;
560 }
561
Vladimir Medic4c299852013-11-06 11:27:05 +0000562 bool isCOP2Asm() const { return Kind == k_Register && Reg.Kind == Kind_COP2; }
Vladimir Medic05bcde62013-09-16 10:29:42 +0000563
Jack Carter5dc8ac92013-09-25 23:50:44 +0000564 bool isMSA128BAsm() const {
565 return Kind == k_Register && Reg.Kind == Kind_MSA128BRegs;
566 }
567
568 bool isMSA128HAsm() const {
569 return Kind == k_Register && Reg.Kind == Kind_MSA128HRegs;
570 }
571
572 bool isMSA128WAsm() const {
573 return Kind == k_Register && Reg.Kind == Kind_MSA128WRegs;
574 }
575
576 bool isMSA128DAsm() const {
577 return Kind == k_Register && Reg.Kind == Kind_MSA128DRegs;
578 }
579
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000580 bool isMSA128CRAsm() const {
581 return Kind == k_Register && Reg.Kind == Kind_MSA128CtrlRegs;
582 }
583
Jack Carterb4dbc172012-09-05 23:34:03 +0000584 /// getStartLoc - Get the location of the first token of this operand.
Vladimir Medic4c299852013-11-06 11:27:05 +0000585 SMLoc getStartLoc() const { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +0000586 /// getEndLoc - Get the location of the last token of this operand.
Vladimir Medic4c299852013-11-06 11:27:05 +0000587 SMLoc getEndLoc() const { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +0000588
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000589 virtual void print(raw_ostream &OS) const {
590 llvm_unreachable("unimplemented!");
591 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000592}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +0000593} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000594
Jack Carter9e65aa32013-03-22 00:05:30 +0000595namespace llvm {
596extern const MCInstrDesc MipsInsts[];
597}
598static const MCInstrDesc &getInstDesc(unsigned Opcode) {
599 return MipsInsts[Opcode];
600}
601
602bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +0000603 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000604 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Daniel Sandersa771fef2014-03-24 14:05:39 +0000605
Jack Carter9e65aa32013-03-22 00:05:30 +0000606 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000607
608 if (MCID.isBranch() || MCID.isCall()) {
609 const unsigned Opcode = Inst.getOpcode();
610 MCOperand Offset;
611
612 switch (Opcode) {
613 default:
614 break;
615 case Mips::BEQ:
616 case Mips::BNE:
Jack Carter3b2c96e2014-01-22 23:31:38 +0000617 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000618 Offset = Inst.getOperand(2);
619 if (!Offset.isImm())
620 break; // We'll deal with this situation later on when applying fixups.
621 if (!isIntN(isMicroMips() ? 17 : 18, Offset.getImm()))
622 return Error(IDLoc, "branch target out of range");
Jack Carter3b2c96e2014-01-22 23:31:38 +0000623 if (OffsetToAlignment(Offset.getImm(), 1LL << (isMicroMips() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000624 return Error(IDLoc, "branch to misaligned address");
625 break;
626 case Mips::BGEZ:
627 case Mips::BGTZ:
628 case Mips::BLEZ:
629 case Mips::BLTZ:
630 case Mips::BGEZAL:
631 case Mips::BLTZAL:
632 case Mips::BC1F:
633 case Mips::BC1T:
Jack Carter3b2c96e2014-01-22 23:31:38 +0000634 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000635 Offset = Inst.getOperand(1);
636 if (!Offset.isImm())
637 break; // We'll deal with this situation later on when applying fixups.
638 if (!isIntN(isMicroMips() ? 17 : 18, Offset.getImm()))
639 return Error(IDLoc, "branch target out of range");
Jack Carter3b2c96e2014-01-22 23:31:38 +0000640 if (OffsetToAlignment(Offset.getImm(), 1LL << (isMicroMips() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000641 return Error(IDLoc, "branch to misaligned address");
642 break;
643 }
644 }
645
Jack Carterc15c1d22013-04-25 23:31:35 +0000646 if (MCID.hasDelaySlot() && Options.isReorder()) {
647 // If this instruction has a delay slot and .set reorder is active,
648 // emit a NOP after it.
649 Instructions.push_back(Inst);
650 MCInst NopInst;
651 NopInst.setOpcode(Mips::SLL);
652 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
653 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
654 NopInst.addOperand(MCOperand::CreateImm(0));
655 Instructions.push_back(NopInst);
656 return false;
657 }
658
Jack Carter9e65aa32013-03-22 00:05:30 +0000659 if (MCID.mayLoad() || MCID.mayStore()) {
660 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +0000661 // reference or immediate we may have to expand instructions.
662 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000663 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +0000664 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
665 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000666 MCOperand &Op = Inst.getOperand(i);
667 if (Op.isImm()) {
668 int MemOffset = Op.getImm();
669 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000670 // Offset can't exceed 16bit value.
671 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +0000672 return false;
673 }
674 } else if (Op.isExpr()) {
675 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +0000676 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000677 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +0000678 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +0000679 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000680 // Expand symbol.
681 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +0000682 return false;
683 }
Jack Carterb5cf5902013-04-17 00:18:04 +0000684 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000685 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +0000686 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +0000687 }
688 }
689 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000690 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +0000691 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +0000692
693 if (needsExpansion(Inst))
694 expandInstruction(Inst, IDLoc, Instructions);
695 else
696 Instructions.push_back(Inst);
697
698 return false;
699}
700
Jack Carter30a59822012-10-04 04:03:53 +0000701bool MipsAsmParser::needsExpansion(MCInst &Inst) {
702
Jack Carterd0bd6422013-04-18 00:41:53 +0000703 switch (Inst.getOpcode()) {
704 case Mips::LoadImm32Reg:
705 case Mips::LoadAddr32Imm:
706 case Mips::LoadAddr32Reg:
Daniel Sandersa771fef2014-03-24 14:05:39 +0000707 case Mips::SUBi:
708 case Mips::SUBiu:
709 case Mips::DSUBi:
710 case Mips::DSUBiu:
Jack Carterd0bd6422013-04-18 00:41:53 +0000711 return true;
712 default:
713 return false;
Jack Carter30a59822012-10-04 04:03:53 +0000714 }
715}
Jack Carter92995f12012-10-06 00:53:28 +0000716
Jack Carter30a59822012-10-04 04:03:53 +0000717void MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000718 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000719 switch (Inst.getOpcode()) {
720 case Mips::LoadImm32Reg:
721 return expandLoadImm(Inst, IDLoc, Instructions);
722 case Mips::LoadAddr32Imm:
723 return expandLoadAddressImm(Inst, IDLoc, Instructions);
724 case Mips::LoadAddr32Reg:
725 return expandLoadAddressReg(Inst, IDLoc, Instructions);
Daniel Sandersa771fef2014-03-24 14:05:39 +0000726 case Mips::SUBi:
727 Instructions.push_back(MCInstBuilder(Mips::ADDi)
728 .addReg(Inst.getOperand(0).getReg())
729 .addReg(Inst.getOperand(1).getReg())
730 .addImm(-Inst.getOperand(2).getImm()));
731 return;
732 case Mips::SUBiu:
733 Instructions.push_back(MCInstBuilder(Mips::ADDiu)
734 .addReg(Inst.getOperand(0).getReg())
735 .addReg(Inst.getOperand(1).getReg())
736 .addImm(-Inst.getOperand(2).getImm()));
737 return;
738 case Mips::DSUBi:
739 Instructions.push_back(MCInstBuilder(Mips::DADDi)
740 .addReg(Inst.getOperand(0).getReg())
741 .addReg(Inst.getOperand(1).getReg())
742 .addImm(-Inst.getOperand(2).getImm()));
743 return;
744 case Mips::DSUBiu:
745 Instructions.push_back(MCInstBuilder(Mips::DADDiu)
746 .addReg(Inst.getOperand(0).getReg())
747 .addReg(Inst.getOperand(1).getReg())
748 .addImm(-Inst.getOperand(2).getImm()));
749 return;
Jack Carterd0bd6422013-04-18 00:41:53 +0000750 }
Jack Carter30a59822012-10-04 04:03:53 +0000751}
Jack Carter92995f12012-10-06 00:53:28 +0000752
Jack Carter30a59822012-10-04 04:03:53 +0000753void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000754 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +0000755 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +0000756 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +0000757 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +0000758 const MCOperand &RegOp = Inst.getOperand(0);
759 assert(RegOp.isReg() && "expected register operand kind");
760
761 int ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +0000762 tmpInst.setLoc(IDLoc);
Jack Carterd0bd6422013-04-18 00:41:53 +0000763 if (0 <= ImmValue && ImmValue <= 65535) {
764 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +0000765 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +0000766 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +0000767 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +0000768 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +0000769 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +0000770 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +0000771 } else if (ImmValue < 0 && ImmValue >= -32768) {
772 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +0000773 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +0000774 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +0000775 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +0000776 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +0000777 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +0000778 Instructions.push_back(tmpInst);
779 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000780 // For any other value of j that is representable as a 32-bit integer.
Jack Carter30a59822012-10-04 04:03:53 +0000781 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +0000782 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +0000783 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +0000784 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
785 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +0000786 Instructions.push_back(tmpInst);
Jack Carter92995f12012-10-06 00:53:28 +0000787 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +0000788 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +0000789 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
790 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
791 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
792 tmpInst.setLoc(IDLoc);
Jack Carter30a59822012-10-04 04:03:53 +0000793 Instructions.push_back(tmpInst);
794 }
795}
Jack Carter92995f12012-10-06 00:53:28 +0000796
Vladimir Medic4c299852013-11-06 11:27:05 +0000797void
798MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
799 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +0000800 MCInst tmpInst;
801 const MCOperand &ImmOp = Inst.getOperand(2);
802 assert(ImmOp.isImm() && "expected immediate operand kind");
803 const MCOperand &SrcRegOp = Inst.getOperand(1);
804 assert(SrcRegOp.isReg() && "expected register operand kind");
805 const MCOperand &DstRegOp = Inst.getOperand(0);
806 assert(DstRegOp.isReg() && "expected register operand kind");
807 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000808 if (-32768 <= ImmValue && ImmValue <= 65535) {
809 // For -32768 <= j <= 65535.
810 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +0000811 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +0000812 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
813 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
814 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
815 Instructions.push_back(tmpInst);
816 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000817 // For any other value of j that is representable as a 32-bit integer.
818 // la d,j(s) => lui d,hi16(j)
819 // ori d,d,lo16(j)
820 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +0000821 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +0000822 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
823 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
824 Instructions.push_back(tmpInst);
825 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +0000826 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +0000827 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
828 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
829 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
830 Instructions.push_back(tmpInst);
831 tmpInst.clear();
832 tmpInst.setOpcode(Mips::ADDu);
833 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
834 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
835 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
836 Instructions.push_back(tmpInst);
837 }
838}
839
Vladimir Medic4c299852013-11-06 11:27:05 +0000840void
841MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
842 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +0000843 MCInst tmpInst;
844 const MCOperand &ImmOp = Inst.getOperand(1);
845 assert(ImmOp.isImm() && "expected immediate operand kind");
846 const MCOperand &RegOp = Inst.getOperand(0);
847 assert(RegOp.isReg() && "expected register operand kind");
848 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000849 if (-32768 <= ImmValue && ImmValue <= 65535) {
850 // For -32768 <= j <= 65535.
851 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +0000852 tmpInst.setOpcode(Mips::ADDiu);
853 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +0000854 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +0000855 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
856 Instructions.push_back(tmpInst);
857 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000858 // For any other value of j that is representable as a 32-bit integer.
859 // la d,j => lui d,hi16(j)
860 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +0000861 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +0000862 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
863 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
864 Instructions.push_back(tmpInst);
865 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +0000866 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +0000867 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
868 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
869 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
870 Instructions.push_back(tmpInst);
871 }
872}
873
Jack Carter9e65aa32013-03-22 00:05:30 +0000874void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000875 SmallVectorImpl<MCInst> &Instructions,
876 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000877 const MCSymbolRefExpr *SR;
878 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +0000879 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +0000880 const MCExpr *ExprOffset;
881 unsigned TmpRegNum;
Vladimir Medic4c299852013-11-06 11:27:05 +0000882 unsigned AtRegNum = getReg(
Daniel Sanders5e94e682014-03-27 16:42:17 +0000883 (isGP64()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, getATReg());
Jack Carterd0bd6422013-04-18 00:41:53 +0000884 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +0000885 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
886 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +0000887 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +0000888 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
889 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +0000890 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +0000891 if (isImmOpnd) {
892 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
893 ImmOffset = Inst.getOperand(2).getImm();
894 LoOffset = ImmOffset & 0x0000ffff;
895 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +0000896 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +0000897 if (LoOffset & 0x8000)
898 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +0000899 } else
Jack Carter9e65aa32013-03-22 00:05:30 +0000900 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +0000901 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +0000902 TempInst.setLoc(IDLoc);
903 // 1st instruction in expansion is LUi. For load instruction we can use
904 // the dst register as a temporary if base and dst are different,
Jack Carterd0bd6422013-04-18 00:41:53 +0000905 // but for stores we must use $at.
906 TmpRegNum = (isLoad && (BaseRegNum != RegOpNum)) ? RegOpNum : AtRegNum;
Jack Carter9e65aa32013-03-22 00:05:30 +0000907 TempInst.setOpcode(Mips::LUi);
908 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
909 if (isImmOpnd)
910 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
911 else {
912 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +0000913 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +0000914 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
915 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
916 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +0000917 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +0000918 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000919 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +0000920 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +0000921 }
922 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000923 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +0000924 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +0000925 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +0000926 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +0000927 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +0000928 TempInst.setOpcode(Mips::ADDu);
929 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
930 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
931 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
932 Instructions.push_back(TempInst);
933 TempInst.clear();
Alp Tokercb402912014-01-24 17:20:08 +0000934 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +0000935 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +0000936 TempInst.setOpcode(Inst.getOpcode());
937 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
938 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
939 if (isImmOpnd)
940 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
941 else {
942 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000943 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
944 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
945 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +0000946 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +0000947 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000948 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +0000949 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +0000950 }
951 }
952 Instructions.push_back(TempInst);
953 TempInst.clear();
954}
955
Vladimir Medic4c299852013-11-06 11:27:05 +0000956bool MipsAsmParser::MatchAndEmitInstruction(
957 SMLoc IDLoc, unsigned &Opcode,
958 SmallVectorImpl<MCParsedAsmOperand *> &Operands, MCStreamer &Out,
959 unsigned &ErrorInfo, bool MatchingInlineAsm) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000960 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +0000961 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +0000962 unsigned MatchResult =
963 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +0000964
965 switch (MatchResult) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000966 default:
967 break;
Jack Carterb4dbc172012-09-05 23:34:03 +0000968 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +0000969 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +0000970 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +0000971 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +0000972 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +0000973 return false;
974 }
975 case Match_MissingFeature:
976 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
977 return true;
978 case Match_InvalidOperand: {
979 SMLoc ErrorLoc = IDLoc;
980 if (ErrorInfo != ~0U) {
981 if (ErrorInfo >= Operands.size())
982 return Error(IDLoc, "too few operands for instruction");
983
Vladimir Medic4c299852013-11-06 11:27:05 +0000984 ErrorLoc = ((MipsOperand *)Operands[ErrorInfo])->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +0000985 if (ErrorLoc == SMLoc())
986 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +0000987 }
988
989 return Error(ErrorLoc, "invalid operand for instruction");
990 }
991 case Match_MnemonicFail:
992 return Error(IDLoc, "invalid instruction");
993 }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000994 return true;
995}
996
Daniel Sandersb1d7e532014-03-25 11:16:03 +0000997void MipsAsmParser::warnIfAssemblerTemporary(int RegNo) {
998 if ((RegNo != 0) && ((int)Options.getATRegNum() == RegNo)) {
999 if (RegNo == 1)
1000 Warning(getLexer().getLoc(), "Used $at without \".set noat\"");
1001 else
1002 Warning(getLexer().getLoc(), Twine("Used $") + Twine(RegNo) +
1003 " with \".set at=$" + Twine(RegNo) +
1004 "\"");
1005 }
1006}
1007
Jack Carter1ac53222013-02-20 23:11:17 +00001008int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001009 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +00001010
Vladimir Medic4c299852013-11-06 11:27:05 +00001011 CC = StringSwitch<unsigned>(Name)
1012 .Case("zero", 0)
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001013 .Case("at", 1)
Vladimir Medic4c299852013-11-06 11:27:05 +00001014 .Case("a0", 4)
1015 .Case("a1", 5)
1016 .Case("a2", 6)
1017 .Case("a3", 7)
1018 .Case("v0", 2)
1019 .Case("v1", 3)
1020 .Case("s0", 16)
1021 .Case("s1", 17)
1022 .Case("s2", 18)
1023 .Case("s3", 19)
1024 .Case("s4", 20)
1025 .Case("s5", 21)
1026 .Case("s6", 22)
1027 .Case("s7", 23)
1028 .Case("k0", 26)
1029 .Case("k1", 27)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001030 .Case("gp", 28)
Vladimir Medic4c299852013-11-06 11:27:05 +00001031 .Case("sp", 29)
1032 .Case("fp", 30)
Daniel Sanders85f482b2014-03-26 11:05:24 +00001033 .Case("s8", 30)
Vladimir Medic4c299852013-11-06 11:27:05 +00001034 .Case("ra", 31)
1035 .Case("t0", 8)
1036 .Case("t1", 9)
1037 .Case("t2", 10)
1038 .Case("t3", 11)
1039 .Case("t4", 12)
1040 .Case("t5", 13)
1041 .Case("t6", 14)
1042 .Case("t7", 15)
1043 .Case("t8", 24)
1044 .Case("t9", 25)
1045 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +00001046
Daniel Sandersa4b0c742014-03-26 11:39:07 +00001047 if (isN32() || isN64()) {
1048 // Although SGI documentation just cuts out t0-t3 for n32/n64,
1049 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
1050 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
1051 if (8 <= CC && CC <= 11)
1052 CC += 4;
Jack Carter1ac53222013-02-20 23:11:17 +00001053
Daniel Sandersa4b0c742014-03-26 11:39:07 +00001054 if (CC == -1)
1055 CC = StringSwitch<unsigned>(Name)
1056 .Case("a4", 8)
1057 .Case("a5", 9)
1058 .Case("a6", 10)
1059 .Case("a7", 11)
1060 .Case("kt0", 26)
1061 .Case("kt1", 27)
1062 .Default(-1);
1063 }
Jack Carter1ac53222013-02-20 23:11:17 +00001064
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001065 warnIfAssemblerTemporary(CC);
Daniel Sanderse231ae92014-03-25 10:57:07 +00001066
Jack Carter1ac53222013-02-20 23:11:17 +00001067 return CC;
1068}
Jack Carterd0bd6422013-04-18 00:41:53 +00001069
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001070int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001071
Jack Cartera63b16a2012-09-07 00:23:42 +00001072 if (Name[0] == 'f') {
1073 StringRef NumString = Name.substr(1);
1074 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001075 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001076 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001077 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00001078 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001079 return IntVal;
1080 }
1081 return -1;
1082}
Jack Cartera63b16a2012-09-07 00:23:42 +00001083
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001084int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
1085
1086 if (Name.startswith("fcc")) {
1087 StringRef NumString = Name.substr(3);
1088 unsigned IntVal;
1089 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001090 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001091 if (IntVal > 7) // There are only 8 fcc registers.
1092 return -1;
1093 return IntVal;
1094 }
1095 return -1;
1096}
1097
1098int MipsAsmParser::matchACRegisterName(StringRef Name) {
1099
Akira Hatanaka274d24c2013-08-14 01:15:52 +00001100 if (Name.startswith("ac")) {
1101 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001102 unsigned IntVal;
1103 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001104 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001105 if (IntVal > 3) // There are only 3 acc registers.
1106 return -1;
1107 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00001108 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001109 return -1;
1110}
Jack Carterd0bd6422013-04-18 00:41:53 +00001111
Jack Carter5dc8ac92013-09-25 23:50:44 +00001112int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
1113 unsigned IntVal;
1114
1115 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
1116 return -1;
1117
1118 if (IntVal > 31)
1119 return -1;
1120
1121 return IntVal;
1122}
1123
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001124int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
1125 int CC;
1126
1127 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00001128 .Case("msair", 0)
1129 .Case("msacsr", 1)
1130 .Case("msaaccess", 2)
1131 .Case("msasave", 3)
1132 .Case("msamodify", 4)
1133 .Case("msarequest", 5)
1134 .Case("msamap", 6)
1135 .Case("msaunmap", 7)
1136 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001137
1138 return CC;
1139}
1140
Vladimir Medic8cd17102013-06-20 11:21:49 +00001141int MipsAsmParser::matchRegisterName(StringRef Name, bool is64BitReg) {
1142
Vladimir Medic8cd17102013-06-20 11:21:49 +00001143 int CC;
1144 CC = matchCPURegisterName(Name);
1145 if (CC != -1)
Akira Hatanaka13e6ccf2013-08-06 23:08:38 +00001146 return matchRegisterByNumber(CC, is64BitReg ? Mips::GPR64RegClassID
1147 : Mips::GPR32RegClassID);
Jack Carter5dc8ac92013-09-25 23:50:44 +00001148 CC = matchFPURegisterName(Name);
Vladimir Medic4c299852013-11-06 11:27:05 +00001149 // TODO: decide about fpu register class
Jack Carter5dc8ac92013-09-25 23:50:44 +00001150 if (CC != -1)
1151 return matchRegisterByNumber(CC, isFP64() ? Mips::FGR64RegClassID
1152 : Mips::FGR32RegClassID);
1153 return matchMSA128RegisterName(Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +00001154}
1155
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001156int MipsAsmParser::regKindToRegClass(int RegKind) {
Jack Cartera63b16a2012-09-07 00:23:42 +00001157
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001158 switch (RegKind) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001159 case MipsOperand::Kind_GPR32:
1160 return Mips::GPR32RegClassID;
1161 case MipsOperand::Kind_GPR64:
1162 return Mips::GPR64RegClassID;
1163 case MipsOperand::Kind_HWRegs:
1164 return Mips::HWRegsRegClassID;
1165 case MipsOperand::Kind_FGR32Regs:
1166 return Mips::FGR32RegClassID;
1167 case MipsOperand::Kind_FGRH32Regs:
1168 return Mips::FGRH32RegClassID;
1169 case MipsOperand::Kind_FGR64Regs:
1170 return Mips::FGR64RegClassID;
1171 case MipsOperand::Kind_AFGR64Regs:
1172 return Mips::AFGR64RegClassID;
1173 case MipsOperand::Kind_CCRRegs:
1174 return Mips::CCRRegClassID;
1175 case MipsOperand::Kind_ACC64DSP:
1176 return Mips::ACC64DSPRegClassID;
1177 case MipsOperand::Kind_FCCRegs:
1178 return Mips::FCCRegClassID;
1179 case MipsOperand::Kind_MSA128BRegs:
1180 return Mips::MSA128BRegClassID;
1181 case MipsOperand::Kind_MSA128HRegs:
1182 return Mips::MSA128HRegClassID;
1183 case MipsOperand::Kind_MSA128WRegs:
1184 return Mips::MSA128WRegClassID;
1185 case MipsOperand::Kind_MSA128DRegs:
1186 return Mips::MSA128DRegClassID;
1187 case MipsOperand::Kind_MSA128CtrlRegs:
1188 return Mips::MSACtrlRegClassID;
1189 default:
1190 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001191 }
Jack Cartera63b16a2012-09-07 00:23:42 +00001192}
Jack Carterb4dbc172012-09-05 23:34:03 +00001193
Jack Carter0b744b32012-10-04 02:29:46 +00001194bool MipsAssemblerOptions::setATReg(unsigned Reg) {
1195 if (Reg > 31)
1196 return false;
1197
1198 aTReg = Reg;
1199 return true;
1200}
1201
Daniel Sandersd89b1362014-03-24 16:48:01 +00001202int MipsAsmParser::getATReg() {
1203 int AT = Options.getATRegNum();
1204 if (AT == 0)
1205 TokError("Pseudo instruction requires $at, which is not available");
1206 return AT;
1207}
Jack Carter0b744b32012-10-04 02:29:46 +00001208
Jack Carterd0bd6422013-04-18 00:41:53 +00001209unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00001210 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00001211}
1212
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001213unsigned MipsAsmParser::getGPR(int RegNo) {
Daniel Sanders5e94e682014-03-27 16:42:17 +00001214 return getReg(isGP64() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
1215 RegNo);
Daniel Sanders5bce5f62014-03-27 13:52:53 +00001216}
1217
Jack Carter873c7242013-01-12 01:03:14 +00001218int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001219 if (RegNum >
Daniel Sanders64cf5a42014-03-27 15:00:44 +00001220 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
Jack Carterb4dbc172012-09-05 23:34:03 +00001221 return -1;
1222
Daniel Sandersb1d7e532014-03-25 11:16:03 +00001223 if (RegClass == Mips::GPR32RegClassID || RegClass == Mips::GPR64RegClassID)
1224 warnIfAssemblerTemporary(RegNum);
1225
Jack Carter873c7242013-01-12 01:03:14 +00001226 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00001227}
1228
Jack Carter873c7242013-01-12 01:03:14 +00001229int MipsAsmParser::tryParseRegister(bool is64BitReg) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001230 const AsmToken &Tok = Parser.getTok();
1231 int RegNum = -1;
1232
1233 if (Tok.is(AsmToken::Identifier)) {
1234 std::string lowerCase = Tok.getString().lower();
Jack Carter873c7242013-01-12 01:03:14 +00001235 RegNum = matchRegisterName(lowerCase, is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +00001236 } else if (Tok.is(AsmToken::Integer))
Jack Carter30a59822012-10-04 04:03:53 +00001237 RegNum = matchRegisterByNumber(static_cast<unsigned>(Tok.getIntVal()),
Vladimir Medic4c299852013-11-06 11:27:05 +00001238 is64BitReg ? Mips::GPR64RegClassID
1239 : Mips::GPR32RegClassID);
Jack Carterb4dbc172012-09-05 23:34:03 +00001240 return RegNum;
1241}
1242
Jack Carterd0bd6422013-04-18 00:41:53 +00001243bool MipsAsmParser::tryParseRegisterOperand(
Vladimir Medic4c299852013-11-06 11:27:05 +00001244 SmallVectorImpl<MCParsedAsmOperand *> &Operands, bool is64BitReg) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001245
1246 SMLoc S = Parser.getTok().getLoc();
1247 int RegNo = -1;
Jack Cartera63b16a2012-09-07 00:23:42 +00001248
Jack Carter873c7242013-01-12 01:03:14 +00001249 RegNo = tryParseRegister(is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +00001250 if (RegNo == -1)
1251 return true;
1252
Vladimir Medic4c299852013-11-06 11:27:05 +00001253 Operands.push_back(
1254 MipsOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Jack Carterb4dbc172012-09-05 23:34:03 +00001255 Parser.Lex(); // Eat register token.
1256 return false;
1257}
1258
Vladimir Medic4c299852013-11-06 11:27:05 +00001259bool
1260MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
1261 StringRef Mnemonic) {
Jack Carter30a59822012-10-04 04:03:53 +00001262 // Check if the current operand has a custom associated parser, if so, try to
1263 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00001264 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
1265 if (ResTy == MatchOperand_Success)
1266 return false;
1267 // If there wasn't a custom match, try the generic matcher below. Otherwise,
1268 // there was a match, but an error occurred, in which case, just return that
1269 // the operand parsing failed.
1270 if (ResTy == MatchOperand_ParseFail)
1271 return true;
1272
1273 switch (getLexer().getKind()) {
1274 default:
1275 Error(Parser.getTok().getLoc(), "unexpected token in operand");
1276 return true;
1277 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001278 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00001279 SMLoc S = Parser.getTok().getLoc();
1280 Parser.Lex(); // Eat dollar token.
Jack Carterd0bd6422013-04-18 00:41:53 +00001281 // Parse the register operand.
Daniel Sanders5e94e682014-03-27 16:42:17 +00001282 if (!tryParseRegisterOperand(Operands, isGP64())) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001283 if (getLexer().is(AsmToken::LParen)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001284 // Check if it is indexed addressing operand.
Jack Carterb4dbc172012-09-05 23:34:03 +00001285 Operands.push_back(MipsOperand::CreateToken("(", S));
Jack Carterd0bd6422013-04-18 00:41:53 +00001286 Parser.Lex(); // Eat the parenthesis.
Jack Carterb4dbc172012-09-05 23:34:03 +00001287 if (getLexer().isNot(AsmToken::Dollar))
1288 return true;
1289
Jack Carterd0bd6422013-04-18 00:41:53 +00001290 Parser.Lex(); // Eat the dollar
Daniel Sanders5e94e682014-03-27 16:42:17 +00001291 if (tryParseRegisterOperand(Operands, isGP64()))
Jack Carterb4dbc172012-09-05 23:34:03 +00001292 return true;
1293
1294 if (!getLexer().is(AsmToken::RParen))
1295 return true;
1296
1297 S = Parser.getTok().getLoc();
1298 Operands.push_back(MipsOperand::CreateToken(")", S));
1299 Parser.Lex();
1300 }
1301 return false;
1302 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001303 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00001304 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001305 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00001306 return true;
1307
Jack Carter873c7242013-01-12 01:03:14 +00001308 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00001309 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00001310 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00001311 const MCExpr *Res =
1312 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00001313
1314 Operands.push_back(MipsOperand::CreateImm(Res, S, E));
1315 return false;
1316 }
1317 case AsmToken::Identifier:
Vladimir Medic77ffd7a2013-11-13 09:48:53 +00001318 // For instruction aliases like "bc1f $Label" dedicated parser will
1319 // eat the '$' sign before failing. So in order to look for appropriate
1320 // label we must check first if we have already consumed '$'.
1321 if (hasConsumedDollar) {
1322 hasConsumedDollar = false;
1323 SMLoc S = Parser.getTok().getLoc();
1324 StringRef Identifier;
1325 if (Parser.parseIdentifier(Identifier))
1326 return true;
1327 SMLoc E =
1328 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1329 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
1330 // Create a symbol reference.
1331 const MCExpr *Res =
1332 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
1333
1334 Operands.push_back(MipsOperand::CreateImm(Res, S, E));
1335 return false;
1336 }
Jack Carterd76b2372013-03-21 21:44:16 +00001337 // Look for the existing symbol, we should check if
Matheus Almeidad534fc32014-01-30 13:40:26 +00001338 // we need to assign the proper RegisterKind.
Jack Carterd0bd6422013-04-18 00:41:53 +00001339 if (searchSymbolAlias(Operands, MipsOperand::Kind_None))
1340 return false;
Vladimir Medic4c299852013-11-06 11:27:05 +00001341 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00001342 case AsmToken::LParen:
1343 case AsmToken::Minus:
1344 case AsmToken::Plus:
1345 case AsmToken::Integer:
1346 case AsmToken::String: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001347 // Quoted label names.
Jack Carterb4dbc172012-09-05 23:34:03 +00001348 const MCExpr *IdVal;
1349 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001350 if (getParser().parseExpression(IdVal))
Jack Carterb4dbc172012-09-05 23:34:03 +00001351 return true;
Jack Carter873c7242013-01-12 01:03:14 +00001352 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb4dbc172012-09-05 23:34:03 +00001353 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
1354 return false;
1355 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00001356 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001357 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001358 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001359 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00001360 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00001361 return true;
1362
Jack Carter873c7242013-01-12 01:03:14 +00001363 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1364
Jack Carterdc1e35d2012-09-06 20:00:02 +00001365 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
1366 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001367 } // case AsmToken::Percent
1368 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00001369 return true;
1370}
1371
Vladimir Medic4c299852013-11-06 11:27:05 +00001372const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00001373 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00001374 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00001375 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001376 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001377 // It's a constant, evaluate lo or hi value.
Jack Carterb5cf5902013-04-17 00:18:04 +00001378 if (RelocStr == "lo") {
Jack Carter9e65aa32013-03-22 00:05:30 +00001379 short Val = MCE->getValue();
1380 Res = MCConstantExpr::Create(Val, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001381 } else if (RelocStr == "hi") {
Jack Carter9e65aa32013-03-22 00:05:30 +00001382 int Val = MCE->getValue();
Jack Carterdc463382013-02-21 02:09:31 +00001383 int LoSign = Val & 0x8000;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001384 Val = (Val & 0xffff0000) >> 16;
Jack Carter9e65aa32013-03-22 00:05:30 +00001385 // Lower part is treated as a signed int, so if it is negative
Jack Carterd0bd6422013-04-18 00:41:53 +00001386 // we must add 1 to the hi part to compensate.
Jack Carterdc463382013-02-21 02:09:31 +00001387 if (LoSign)
1388 Val++;
Jack Carter9e65aa32013-03-22 00:05:30 +00001389 Res = MCConstantExpr::Create(Val, getContext());
Evgeniy Stepanov3d8ab192013-04-17 06:45:11 +00001390 } else {
1391 llvm_unreachable("Invalid RelocStr value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001392 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001393 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001394 }
1395
Jack Carterb5cf5902013-04-17 00:18:04 +00001396 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001397 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00001398 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00001399 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00001400 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001401 return Res;
1402 }
1403
1404 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Petar Jovanovica5da5882014-02-04 18:41:57 +00001405 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
1406
1407 // Check for %hi(sym1-sym2) and %lo(sym1-sym2) expressions.
1408 if (isa<MCSymbolRefExpr>(BE->getLHS()) && isa<MCSymbolRefExpr>(BE->getRHS())
1409 && (VK == MCSymbolRefExpr::VK_Mips_ABS_HI
1410 || VK == MCSymbolRefExpr::VK_Mips_ABS_LO)) {
1411 // Create target expression for %hi(sym1-sym2) and %lo(sym1-sym2).
1412 if (VK == MCSymbolRefExpr::VK_Mips_ABS_HI)
1413 return MipsMCExpr::CreateHi(Expr, getContext());
1414 return MipsMCExpr::CreateLo(Expr, getContext());
1415 }
1416
Jack Carterd0bd6422013-04-18 00:41:53 +00001417 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
1418 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00001419 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
1420 return Res;
1421 }
1422
1423 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001424 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
1425 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
1426 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00001427 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001428 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001429 return Expr;
1430}
1431
1432bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
1433
1434 switch (Expr->getKind()) {
1435 case MCExpr::Constant:
1436 return true;
1437 case MCExpr::SymbolRef:
1438 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
1439 case MCExpr::Binary:
1440 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
1441 if (!isEvaluated(BE->getLHS()))
1442 return false;
1443 return isEvaluated(BE->getRHS());
1444 }
1445 case MCExpr::Unary:
1446 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
Petar Jovanovica5da5882014-02-04 18:41:57 +00001447 case MCExpr::Target:
1448 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001449 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001450 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00001451}
Jack Carterd0bd6422013-04-18 00:41:53 +00001452
Jack Carterb5cf5902013-04-17 00:18:04 +00001453bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001454 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00001455 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00001456 if (Tok.isNot(AsmToken::Identifier))
1457 return true;
1458
1459 std::string Str = Tok.getIdentifier().str();
1460
Jack Carterd0bd6422013-04-18 00:41:53 +00001461 Parser.Lex(); // Eat the identifier.
1462 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001463 const MCExpr *IdVal;
1464 SMLoc EndLoc;
1465
1466 if (getLexer().getKind() == AsmToken::LParen) {
1467 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001468 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001469 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001470 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001471 const AsmToken &nextTok = Parser.getTok();
1472 if (nextTok.isNot(AsmToken::Identifier))
1473 return true;
1474 Str += "(%";
1475 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00001476 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00001477 if (getLexer().getKind() != AsmToken::LParen)
1478 return true;
1479 } else
1480 break;
1481 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001482 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00001483 return true;
1484
1485 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00001486 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001487
1488 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00001489 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001490
Jack Carterd0bd6422013-04-18 00:41:53 +00001491 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00001492 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001493}
1494
Jack Carterb4dbc172012-09-05 23:34:03 +00001495bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1496 SMLoc &EndLoc) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001497 StartLoc = Parser.getTok().getLoc();
Daniel Sanders5e94e682014-03-27 16:42:17 +00001498 RegNo = tryParseRegister(isGP64());
Jack Carter873c7242013-01-12 01:03:14 +00001499 EndLoc = Parser.getTok().getLoc();
Vladimir Medic4c299852013-11-06 11:27:05 +00001500 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00001501}
1502
Jack Carterb5cf5902013-04-17 00:18:04 +00001503bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00001504 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001505 bool Result = true;
1506
1507 while (getLexer().getKind() == AsmToken::LParen)
1508 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00001509
Jack Carterd0bd6422013-04-18 00:41:53 +00001510 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001511 default:
1512 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00001513 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00001514 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00001515 case AsmToken::Integer:
1516 case AsmToken::Minus:
1517 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00001518 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00001519 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00001520 else
1521 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00001522 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00001523 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001524 break;
Jack Carter873c7242013-01-12 01:03:14 +00001525 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00001526 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00001527 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001528 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001529}
1530
Jack Carterb4dbc172012-09-05 23:34:03 +00001531MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
Vladimir Medic4c299852013-11-06 11:27:05 +00001532 SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001533
1534 const MCExpr *IdVal = 0;
Jack Carter873c7242013-01-12 01:03:14 +00001535 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001536 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001537 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00001538 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00001539 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001540
Jack Carterb5cf5902013-04-17 00:18:04 +00001541 if (getLexer().getKind() == AsmToken::LParen) {
1542 Parser.Lex();
1543 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001544 }
1545
Jack Carterb5cf5902013-04-17 00:18:04 +00001546 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001547 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00001548 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001549
Jack Carterd0bd6422013-04-18 00:41:53 +00001550 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001551 if (Tok.isNot(AsmToken::LParen)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001552 MipsOperand *Mnemonic = static_cast<MipsOperand *>(Operands[0]);
Jack Carterb5cf5902013-04-17 00:18:04 +00001553 if (Mnemonic->getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00001554 SMLoc E =
1555 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00001556 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
1557 return MatchOperand_Success;
1558 }
1559 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001560 SMLoc E =
1561 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00001562
Jack Carterd0bd6422013-04-18 00:41:53 +00001563 // Zero register assumed, add a memory operand with ZERO as its base.
Vladimir Medic4c299852013-11-06 11:27:05 +00001564 Operands.push_back(MipsOperand::CreateMem(
Daniel Sanders5e94e682014-03-27 16:42:17 +00001565 isGP64() ? Mips::ZERO_64 : Mips::ZERO, IdVal, S, E));
Jack Carterb5cf5902013-04-17 00:18:04 +00001566 return MatchOperand_Success;
1567 }
1568 Error(Parser.getTok().getLoc(), "'(' expected");
1569 return MatchOperand_ParseFail;
1570 }
1571
Jack Carterd0bd6422013-04-18 00:41:53 +00001572 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001573 }
1574
Daniel Sanders5e94e682014-03-27 16:42:17 +00001575 Res = parseRegs(Operands, isGP64() ? (int)MipsOperand::Kind_GPR64
1576 : (int)MipsOperand::Kind_GPR32);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001577 if (Res != MatchOperand_Success)
1578 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001579
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001580 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001581 Error(Parser.getTok().getLoc(), "')' expected");
1582 return MatchOperand_ParseFail;
1583 }
1584
Jack Carter873c7242013-01-12 01:03:14 +00001585 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1586
Jack Carterd0bd6422013-04-18 00:41:53 +00001587 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001588
1589 if (IdVal == 0)
1590 IdVal = MCConstantExpr::Create(0, getContext());
1591
Jack Carterd0bd6422013-04-18 00:41:53 +00001592 // Replace the register operand with the memory operand.
Vladimir Medic4c299852013-11-06 11:27:05 +00001593 MipsOperand *op = static_cast<MipsOperand *>(Operands.back());
Jack Carterdc1e35d2012-09-06 20:00:02 +00001594 int RegNo = op->getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001595 // Remove the register from the operands.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001596 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00001597 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001598 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
1599 int64_t Imm;
1600 if (IdVal->EvaluateAsAbsolute(Imm))
1601 IdVal = MCConstantExpr::Create(Imm, getContext());
1602 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
1603 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
1604 getContext());
1605 }
1606
Jack Carterdc1e35d2012-09-06 20:00:02 +00001607 Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
1608 delete op;
Jack Carterb4dbc172012-09-05 23:34:03 +00001609 return MatchOperand_Success;
1610}
1611
Vladimir Medic4c299852013-11-06 11:27:05 +00001612bool MipsAsmParser::parsePtrReg(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
1613 int RegKind) {
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001614 // If the first token is not '$' we have an error.
1615 if (Parser.getTok().isNot(AsmToken::Dollar))
1616 return false;
1617
1618 SMLoc S = Parser.getTok().getLoc();
1619 Parser.Lex();
1620 AsmToken::TokenKind TkKind = getLexer().getKind();
1621 int Reg;
1622
1623 if (TkKind == AsmToken::Integer) {
1624 Reg = matchRegisterByNumber(Parser.getTok().getIntVal(),
1625 regKindToRegClass(RegKind));
1626 if (Reg == -1)
1627 return false;
1628 } else if (TkKind == AsmToken::Identifier) {
1629 if ((Reg = matchCPURegisterName(Parser.getTok().getString().lower())) == -1)
1630 return false;
1631 Reg = getReg(regKindToRegClass(RegKind), Reg);
1632 } else {
1633 return false;
1634 }
1635
1636 MipsOperand *Op = MipsOperand::CreatePtrReg(Reg, S, Parser.getTok().getLoc());
1637 Op->setRegKind((MipsOperand::RegisterKind)RegKind);
1638 Operands.push_back(Op);
1639 Parser.Lex();
1640 return true;
1641}
1642
1643MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +00001644MipsAsmParser::parsePtrReg(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
1645 MipsOperand::RegisterKind RegKind =
1646 isN64() ? MipsOperand::Kind_GPR64 : MipsOperand::Kind_GPR32;
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001647
1648 // Parse index register.
1649 if (!parsePtrReg(Operands, RegKind))
1650 return MatchOperand_NoMatch;
1651
1652 // Parse '('.
1653 if (Parser.getTok().isNot(AsmToken::LParen))
1654 return MatchOperand_NoMatch;
1655
1656 Operands.push_back(MipsOperand::CreateToken("(", getLexer().getLoc()));
1657 Parser.Lex();
1658
1659 // Parse base register.
1660 if (!parsePtrReg(Operands, RegKind))
1661 return MatchOperand_NoMatch;
1662
1663 // Parse ')'.
1664 if (Parser.getTok().isNot(AsmToken::RParen))
1665 return MatchOperand_NoMatch;
1666
1667 Operands.push_back(MipsOperand::CreateToken(")", getLexer().getLoc()));
1668 Parser.Lex();
1669
1670 return MatchOperand_Success;
1671}
1672
Jack Carter873c7242013-01-12 01:03:14 +00001673MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +00001674MipsAsmParser::parseRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
Vladimir Medic8cd17102013-06-20 11:21:49 +00001675 int RegKind) {
1676 MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind)RegKind;
Vladimir Medic4c299852013-11-06 11:27:05 +00001677 if (getLexer().getKind() == AsmToken::Identifier && !hasConsumedDollar) {
Vladimir Medic8cd17102013-06-20 11:21:49 +00001678 if (searchSymbolAlias(Operands, Kind))
Jack Carterd76b2372013-03-21 21:44:16 +00001679 return MatchOperand_Success;
1680 return MatchOperand_NoMatch;
1681 }
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001682 SMLoc S = Parser.getTok().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001683 // If the first token is not '$', we have an error.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001684 if (Parser.getTok().isNot(AsmToken::Dollar) && !hasConsumedDollar)
Jack Carter873c7242013-01-12 01:03:14 +00001685 return MatchOperand_NoMatch;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001686 if (!hasConsumedDollar) {
1687 Parser.Lex(); // Eat the '$'
1688 hasConsumedDollar = true;
1689 }
1690 if (getLexer().getKind() == AsmToken::Identifier) {
1691 int RegNum = -1;
1692 std::string RegName = Parser.getTok().getString().lower();
Vladimir Medic4c299852013-11-06 11:27:05 +00001693 // Match register by name
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001694 switch (RegKind) {
1695 case MipsOperand::Kind_GPR32:
1696 case MipsOperand::Kind_GPR64:
1697 RegNum = matchCPURegisterName(RegName);
1698 break;
1699 case MipsOperand::Kind_AFGR64Regs:
1700 case MipsOperand::Kind_FGR64Regs:
1701 case MipsOperand::Kind_FGR32Regs:
Akira Hatanaka14e31a22013-08-20 22:58:56 +00001702 case MipsOperand::Kind_FGRH32Regs:
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001703 RegNum = matchFPURegisterName(RegName);
1704 if (RegKind == MipsOperand::Kind_AFGR64Regs)
1705 RegNum /= 2;
Vladimir Medic4c299852013-11-06 11:27:05 +00001706 else if (RegKind == MipsOperand::Kind_FGRH32Regs && !isFP64())
1707 if (RegNum != -1 && RegNum % 2 != 0)
Vladimir Medic65cd5742013-09-10 09:50:01 +00001708 Warning(S, "Float register should be even.");
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001709 break;
1710 case MipsOperand::Kind_FCCRegs:
1711 RegNum = matchFCCRegisterName(RegName);
1712 break;
1713 case MipsOperand::Kind_ACC64DSP:
1714 RegNum = matchACRegisterName(RegName);
1715 break;
Vladimir Medic4c299852013-11-06 11:27:05 +00001716 default:
1717 break; // No match, value is set to -1.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001718 }
1719 // No match found, return _NoMatch to give a chance to other round.
1720 if (RegNum < 0)
1721 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00001722
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001723 int RegVal = getReg(regKindToRegClass(Kind), RegNum);
1724 if (RegVal == -1)
1725 return MatchOperand_NoMatch;
1726
Vladimir Medic4c299852013-11-06 11:27:05 +00001727 MipsOperand *Op =
1728 MipsOperand::CreateReg(RegVal, S, Parser.getTok().getLoc());
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001729 Op->setRegKind(Kind);
1730 Operands.push_back(Op);
1731 hasConsumedDollar = false;
1732 Parser.Lex(); // Eat the register name.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001733 return MatchOperand_Success;
1734 } else if (getLexer().getKind() == AsmToken::Integer) {
1735 unsigned RegNum = Parser.getTok().getIntVal();
1736 if (Kind == MipsOperand::Kind_HWRegs) {
1737 if (RegNum != 29)
1738 return MatchOperand_NoMatch;
1739 // Only hwreg 29 is supported, found at index 0.
1740 RegNum = 0;
1741 }
1742 int Reg = matchRegisterByNumber(RegNum, regKindToRegClass(Kind));
1743 if (Reg == -1)
1744 return MatchOperand_NoMatch;
1745 MipsOperand *Op = MipsOperand::CreateReg(Reg, S, Parser.getTok().getLoc());
1746 Op->setRegKind(Kind);
1747 Operands.push_back(Op);
1748 hasConsumedDollar = false;
1749 Parser.Lex(); // Eat the register number.
Vladimir Medic4c299852013-11-06 11:27:05 +00001750 if ((RegKind == MipsOperand::Kind_GPR32) &&
1751 (getLexer().is(AsmToken::LParen))) {
Vladimir Medic3467b902013-07-18 09:28:35 +00001752 // Check if it is indexed addressing operand.
1753 Operands.push_back(MipsOperand::CreateToken("(", getLexer().getLoc()));
1754 Parser.Lex(); // Eat the parenthesis.
Vladimir Medic4c299852013-11-06 11:27:05 +00001755 if (parseRegs(Operands, RegKind) != MatchOperand_Success)
Vladimir Medic3467b902013-07-18 09:28:35 +00001756 return MatchOperand_NoMatch;
1757 if (getLexer().isNot(AsmToken::RParen))
1758 return MatchOperand_NoMatch;
1759 Operands.push_back(MipsOperand::CreateToken(")", getLexer().getLoc()));
1760 Parser.Lex();
1761 }
Jack Carter873c7242013-01-12 01:03:14 +00001762 return MatchOperand_Success;
1763 }
1764 return MatchOperand_NoMatch;
1765}
Vladimir Medic64828a12013-07-16 10:07:14 +00001766
Matheus Almeidab74293d2013-10-14 11:49:30 +00001767bool MipsAsmParser::validateMSAIndex(int Val, int RegKind) {
1768 MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind)RegKind;
1769
1770 if (Val < 0)
1771 return false;
1772
1773 switch (Kind) {
1774 default:
1775 return false;
1776 case MipsOperand::Kind_MSA128BRegs:
1777 return Val < 16;
1778 case MipsOperand::Kind_MSA128HRegs:
1779 return Val < 8;
1780 case MipsOperand::Kind_MSA128WRegs:
1781 return Val < 4;
1782 case MipsOperand::Kind_MSA128DRegs:
1783 return Val < 2;
1784 }
1785}
1786
Vladimir Medic8cd17102013-06-20 11:21:49 +00001787MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +00001788MipsAsmParser::parseMSARegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
Jack Carter5dc8ac92013-09-25 23:50:44 +00001789 int RegKind) {
1790 MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind)RegKind;
1791 SMLoc S = Parser.getTok().getLoc();
1792 std::string RegName;
1793
1794 if (Parser.getTok().isNot(AsmToken::Dollar))
1795 return MatchOperand_NoMatch;
1796
1797 switch (RegKind) {
1798 default:
1799 return MatchOperand_ParseFail;
1800 case MipsOperand::Kind_MSA128BRegs:
1801 case MipsOperand::Kind_MSA128HRegs:
1802 case MipsOperand::Kind_MSA128WRegs:
1803 case MipsOperand::Kind_MSA128DRegs:
1804 break;
1805 }
1806
1807 Parser.Lex(); // Eat the '$'.
1808 if (getLexer().getKind() == AsmToken::Identifier)
1809 RegName = Parser.getTok().getString().lower();
1810 else
1811 return MatchOperand_ParseFail;
1812
1813 int RegNum = matchMSA128RegisterName(RegName);
1814
1815 if (RegNum < 0 || RegNum > 31)
1816 return MatchOperand_ParseFail;
1817
1818 int RegVal = getReg(regKindToRegClass(Kind), RegNum);
1819 if (RegVal == -1)
1820 return MatchOperand_ParseFail;
1821
Vladimir Medic4c299852013-11-06 11:27:05 +00001822 MipsOperand *Op = MipsOperand::CreateReg(RegVal, S, Parser.getTok().getLoc());
Jack Carter5dc8ac92013-09-25 23:50:44 +00001823 Op->setRegKind(Kind);
1824 Operands.push_back(Op);
1825
1826 Parser.Lex(); // Eat the register identifier.
1827
Matheus Almeidab74293d2013-10-14 11:49:30 +00001828 // MSA registers may be suffixed with an index in the form of:
1829 // 1) Immediate expression.
1830 // 2) General Purpose Register.
1831 // Examples:
1832 // 1) copy_s.b $29,$w0[0]
1833 // 2) sld.b $w0,$w1[$1]
1834
1835 if (Parser.getTok().isNot(AsmToken::LBrac))
1836 return MatchOperand_Success;
1837
1838 MipsOperand *Mnemonic = static_cast<MipsOperand *>(Operands[0]);
1839
1840 Operands.push_back(MipsOperand::CreateToken("[", Parser.getTok().getLoc()));
1841 Parser.Lex(); // Parse the '[' token.
1842
1843 if (Parser.getTok().is(AsmToken::Dollar)) {
1844 // This must be a GPR.
1845 MipsOperand *RegOp;
1846 SMLoc VIdx = Parser.getTok().getLoc();
1847 Parser.Lex(); // Parse the '$' token.
1848
1849 // GPR have aliases and we must account for that. Example: $30 == $fp
1850 if (getLexer().getKind() == AsmToken::Integer) {
1851 unsigned RegNum = Parser.getTok().getIntVal();
1852 int Reg = matchRegisterByNumber(
1853 RegNum, regKindToRegClass(MipsOperand::Kind_GPR32));
1854 if (Reg == -1) {
1855 Error(VIdx, "invalid general purpose register");
1856 return MatchOperand_ParseFail;
1857 }
1858
1859 RegOp = MipsOperand::CreateReg(Reg, VIdx, Parser.getTok().getLoc());
1860 } else if (getLexer().getKind() == AsmToken::Identifier) {
1861 int RegNum = -1;
1862 std::string RegName = Parser.getTok().getString().lower();
1863
1864 RegNum = matchCPURegisterName(RegName);
1865 if (RegNum == -1) {
1866 Error(VIdx, "general purpose register expected");
1867 return MatchOperand_ParseFail;
1868 }
1869 RegNum = getReg(regKindToRegClass(MipsOperand::Kind_GPR32), RegNum);
1870 RegOp = MipsOperand::CreateReg(RegNum, VIdx, Parser.getTok().getLoc());
1871 } else
1872 return MatchOperand_ParseFail;
1873
1874 RegOp->setRegKind(MipsOperand::Kind_GPR32);
1875 Operands.push_back(RegOp);
1876 Parser.Lex(); // Eat the register identifier.
1877
1878 if (Parser.getTok().isNot(AsmToken::RBrac))
1879 return MatchOperand_ParseFail;
1880
1881 Operands.push_back(MipsOperand::CreateToken("]", Parser.getTok().getLoc()));
1882 Parser.Lex(); // Parse the ']' token.
1883
1884 return MatchOperand_Success;
1885 }
1886
1887 // The index must be a constant expression then.
1888 SMLoc VIdx = Parser.getTok().getLoc();
1889 const MCExpr *ImmVal;
1890
1891 if (getParser().parseExpression(ImmVal))
1892 return MatchOperand_ParseFail;
1893
1894 const MCConstantExpr *expr = dyn_cast<MCConstantExpr>(ImmVal);
1895 if (!expr || !validateMSAIndex((int)expr->getValue(), Kind)) {
1896 Error(VIdx, "invalid immediate value");
1897 return MatchOperand_ParseFail;
1898 }
1899
1900 SMLoc E = Parser.getTok().getEndLoc();
1901
1902 if (Parser.getTok().isNot(AsmToken::RBrac))
1903 return MatchOperand_ParseFail;
1904
Vladimir Medic4c299852013-11-06 11:27:05 +00001905 bool insve =
1906 Mnemonic->getToken() == "insve.b" || Mnemonic->getToken() == "insve.h" ||
1907 Mnemonic->getToken() == "insve.w" || Mnemonic->getToken() == "insve.d";
Matheus Almeidab74293d2013-10-14 11:49:30 +00001908
1909 // The second vector index of insve instructions is always 0.
1910 if (insve && Operands.size() > 6) {
1911 if (expr->getValue() != 0) {
1912 Error(VIdx, "immediate value must be 0");
1913 return MatchOperand_ParseFail;
1914 }
1915 Operands.push_back(MipsOperand::CreateToken("0", VIdx));
1916 } else
1917 Operands.push_back(MipsOperand::CreateImm(expr, VIdx, E));
1918
1919 Operands.push_back(MipsOperand::CreateToken("]", Parser.getTok().getLoc()));
1920
1921 Parser.Lex(); // Parse the ']' token.
1922
Jack Carter5dc8ac92013-09-25 23:50:44 +00001923 return MatchOperand_Success;
1924}
1925
1926MipsAsmParser::OperandMatchResultTy
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001927MipsAsmParser::parseMSACtrlRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
1928 int RegKind) {
1929 MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind)RegKind;
1930
1931 if (Kind != MipsOperand::Kind_MSA128CtrlRegs)
1932 return MatchOperand_NoMatch;
1933
1934 if (Parser.getTok().isNot(AsmToken::Dollar))
1935 return MatchOperand_ParseFail;
1936
1937 SMLoc S = Parser.getTok().getLoc();
1938
1939 Parser.Lex(); // Eat the '$' symbol.
1940
1941 int RegNum = -1;
1942 if (getLexer().getKind() == AsmToken::Identifier)
1943 RegNum = matchMSA128CtrlRegisterName(Parser.getTok().getString().lower());
1944 else if (getLexer().getKind() == AsmToken::Integer)
1945 RegNum = Parser.getTok().getIntVal();
1946 else
1947 return MatchOperand_ParseFail;
1948
1949 if (RegNum < 0 || RegNum > 7)
1950 return MatchOperand_ParseFail;
1951
1952 int RegVal = getReg(regKindToRegClass(Kind), RegNum);
1953 if (RegVal == -1)
1954 return MatchOperand_ParseFail;
1955
Vladimir Medic4c299852013-11-06 11:27:05 +00001956 MipsOperand *RegOp =
1957 MipsOperand::CreateReg(RegVal, S, Parser.getTok().getLoc());
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001958 RegOp->setRegKind(MipsOperand::Kind_MSA128CtrlRegs);
1959 Operands.push_back(RegOp);
1960 Parser.Lex(); // Eat the register identifier.
1961
1962 return MatchOperand_Success;
1963}
1964
1965MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +00001966MipsAsmParser::parseGPR64(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
Vladimir Medic8cd17102013-06-20 11:21:49 +00001967
Daniel Sanders5e94e682014-03-27 16:42:17 +00001968 if (!isGP64())
Vladimir Medic8cd17102013-06-20 11:21:49 +00001969 return MatchOperand_NoMatch;
Vladimir Medic4c299852013-11-06 11:27:05 +00001970 return parseRegs(Operands, (int)MipsOperand::Kind_GPR64);
Vladimir Medic8cd17102013-06-20 11:21:49 +00001971}
1972
1973MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +00001974MipsAsmParser::parseGPR32(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
1975 return parseRegs(Operands, (int)MipsOperand::Kind_GPR32);
Vladimir Medic8cd17102013-06-20 11:21:49 +00001976}
Jack Carter873c7242013-01-12 01:03:14 +00001977
Vladimir Medic4c299852013-11-06 11:27:05 +00001978MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseAFGR64Regs(
1979 SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
Vladimir Medic233dd512013-06-24 10:05:34 +00001980
1981 if (isFP64())
1982 return MatchOperand_NoMatch;
Vladimir Medic4c299852013-11-06 11:27:05 +00001983 return parseRegs(Operands, (int)MipsOperand::Kind_AFGR64Regs);
Vladimir Medic233dd512013-06-24 10:05:34 +00001984}
1985
1986MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +00001987MipsAsmParser::parseFGR64Regs(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
Vladimir Medic233dd512013-06-24 10:05:34 +00001988 if (!isFP64())
1989 return MatchOperand_NoMatch;
Vladimir Medic4c299852013-11-06 11:27:05 +00001990 return parseRegs(Operands, (int)MipsOperand::Kind_FGR64Regs);
Vladimir Medic233dd512013-06-24 10:05:34 +00001991}
1992
1993MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +00001994MipsAsmParser::parseFGR32Regs(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
1995 return parseRegs(Operands, (int)MipsOperand::Kind_FGR32Regs);
1996}
1997
1998MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseFGRH32Regs(
1999 SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
2000 return parseRegs(Operands, (int)MipsOperand::Kind_FGRH32Regs);
Vladimir Medic233dd512013-06-24 10:05:34 +00002001}
2002
Vladimir Medic643b3982013-07-30 10:12:14 +00002003MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +00002004MipsAsmParser::parseFCCRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
2005 return parseRegs(Operands, (int)MipsOperand::Kind_FCCRegs);
Akira Hatanaka14e31a22013-08-20 22:58:56 +00002006}
2007
2008MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +00002009MipsAsmParser::parseACC64DSP(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
2010 return parseRegs(Operands, (int)MipsOperand::Kind_ACC64DSP);
Vladimir Medic643b3982013-07-30 10:12:14 +00002011}
2012
Akira Hatanaka34a32c02013-08-06 22:20:40 +00002013MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +00002014MipsAsmParser::parseLO32DSP(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
Akira Hatanakafeb7ee82013-08-14 01:02:20 +00002015 // If the first token is not '$' we have an error.
2016 if (Parser.getTok().isNot(AsmToken::Dollar))
2017 return MatchOperand_NoMatch;
2018
2019 SMLoc S = Parser.getTok().getLoc();
2020 Parser.Lex(); // Eat the '$'
2021
2022 const AsmToken &Tok = Parser.getTok(); // Get next token.
2023
2024 if (Tok.isNot(AsmToken::Identifier))
2025 return MatchOperand_NoMatch;
2026
2027 if (!Tok.getIdentifier().startswith("ac"))
2028 return MatchOperand_NoMatch;
2029
2030 StringRef NumString = Tok.getIdentifier().substr(2);
2031
2032 unsigned IntVal;
2033 if (NumString.getAsInteger(10, IntVal))
2034 return MatchOperand_NoMatch;
2035
2036 unsigned Reg = matchRegisterByNumber(IntVal, Mips::LO32DSPRegClassID);
2037
2038 MipsOperand *Op = MipsOperand::CreateReg(Reg, S, Parser.getTok().getLoc());
2039 Op->setRegKind(MipsOperand::Kind_LO32DSP);
2040 Operands.push_back(Op);
2041
2042 Parser.Lex(); // Eat the register number.
2043 return MatchOperand_Success;
2044}
2045
2046MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +00002047MipsAsmParser::parseHI32DSP(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
Akira Hatanakafeb7ee82013-08-14 01:02:20 +00002048 // If the first token is not '$' we have an error.
2049 if (Parser.getTok().isNot(AsmToken::Dollar))
2050 return MatchOperand_NoMatch;
2051
2052 SMLoc S = Parser.getTok().getLoc();
2053 Parser.Lex(); // Eat the '$'
2054
2055 const AsmToken &Tok = Parser.getTok(); // Get next token.
2056
2057 if (Tok.isNot(AsmToken::Identifier))
2058 return MatchOperand_NoMatch;
2059
2060 if (!Tok.getIdentifier().startswith("ac"))
2061 return MatchOperand_NoMatch;
2062
2063 StringRef NumString = Tok.getIdentifier().substr(2);
2064
2065 unsigned IntVal;
2066 if (NumString.getAsInteger(10, IntVal))
2067 return MatchOperand_NoMatch;
2068
2069 unsigned Reg = matchRegisterByNumber(IntVal, Mips::HI32DSPRegClassID);
2070
2071 MipsOperand *Op = MipsOperand::CreateReg(Reg, S, Parser.getTok().getLoc());
2072 Op->setRegKind(MipsOperand::Kind_HI32DSP);
2073 Operands.push_back(Op);
2074
2075 Parser.Lex(); // Eat the register number.
2076 return MatchOperand_Success;
2077}
2078
Vladimir Medic05bcde62013-09-16 10:29:42 +00002079MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +00002080MipsAsmParser::parseCOP2(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
Vladimir Medic05bcde62013-09-16 10:29:42 +00002081 // If the first token is not '$' we have an error.
2082 if (Parser.getTok().isNot(AsmToken::Dollar))
2083 return MatchOperand_NoMatch;
2084
2085 SMLoc S = Parser.getTok().getLoc();
2086 Parser.Lex(); // Eat the '$'
2087
2088 const AsmToken &Tok = Parser.getTok(); // Get next token.
2089
2090 if (Tok.isNot(AsmToken::Integer))
2091 return MatchOperand_NoMatch;
2092
2093 unsigned IntVal = Tok.getIntVal();
2094
2095 unsigned Reg = matchRegisterByNumber(IntVal, Mips::COP2RegClassID);
2096
2097 MipsOperand *Op = MipsOperand::CreateReg(Reg, S, Parser.getTok().getLoc());
2098 Op->setRegKind(MipsOperand::Kind_COP2);
2099 Operands.push_back(Op);
2100
2101 Parser.Lex(); // Eat the register number.
2102 return MatchOperand_Success;
2103}
2104
Vladimir Medic4c299852013-11-06 11:27:05 +00002105MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMSA128BRegs(
2106 SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
2107 return parseMSARegs(Operands, (int)MipsOperand::Kind_MSA128BRegs);
Jack Carter5dc8ac92013-09-25 23:50:44 +00002108}
2109
Vladimir Medic4c299852013-11-06 11:27:05 +00002110MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMSA128HRegs(
2111 SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
2112 return parseMSARegs(Operands, (int)MipsOperand::Kind_MSA128HRegs);
Jack Carter5dc8ac92013-09-25 23:50:44 +00002113}
2114
Vladimir Medic4c299852013-11-06 11:27:05 +00002115MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMSA128WRegs(
2116 SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
2117 return parseMSARegs(Operands, (int)MipsOperand::Kind_MSA128WRegs);
Jack Carter5dc8ac92013-09-25 23:50:44 +00002118}
2119
Vladimir Medic4c299852013-11-06 11:27:05 +00002120MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMSA128DRegs(
2121 SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
2122 return parseMSARegs(Operands, (int)MipsOperand::Kind_MSA128DRegs);
Jack Carter5dc8ac92013-09-25 23:50:44 +00002123}
2124
Vladimir Medic4c299852013-11-06 11:27:05 +00002125MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMSA128CtrlRegs(
2126 SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
2127 return parseMSACtrlRegs(Operands, (int)MipsOperand::Kind_MSA128CtrlRegs);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002128}
2129
Jack Carterd0bd6422013-04-18 00:41:53 +00002130bool MipsAsmParser::searchSymbolAlias(
Vladimir Medic4c299852013-11-06 11:27:05 +00002131 SmallVectorImpl<MCParsedAsmOperand *> &Operands, unsigned RegKind) {
Jack Carterd76b2372013-03-21 21:44:16 +00002132
2133 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
2134 if (Sym) {
2135 SMLoc S = Parser.getTok().getLoc();
2136 const MCExpr *Expr;
2137 if (Sym->isVariable())
2138 Expr = Sym->getVariableValue();
2139 else
2140 return false;
2141 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002142 MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind)RegKind;
2143 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carterd76b2372013-03-21 21:44:16 +00002144 const StringRef DefSymbol = Ref->getSymbol().getName();
2145 if (DefSymbol.startswith("$")) {
Jack Carter02593002013-05-28 22:21:05 +00002146 int RegNum = -1;
2147 APInt IntVal(32, -1);
2148 if (!DefSymbol.substr(1).getAsInteger(10, IntVal))
2149 RegNum = matchRegisterByNumber(IntVal.getZExtValue(),
Daniel Sanders5e94e682014-03-27 16:42:17 +00002150 isGP64() ? Mips::GPR64RegClassID
2151 : Mips::GPR32RegClassID);
Vladimir Medic8cd17102013-06-20 11:21:49 +00002152 else {
2153 // Lookup for the register with the corresponding name.
2154 switch (Kind) {
2155 case MipsOperand::Kind_AFGR64Regs:
2156 case MipsOperand::Kind_FGR64Regs:
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002157 RegNum = matchFPURegisterName(DefSymbol.substr(1));
Vladimir Medic8cd17102013-06-20 11:21:49 +00002158 break;
2159 case MipsOperand::Kind_FGR32Regs:
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002160 RegNum = matchFPURegisterName(DefSymbol.substr(1));
Vladimir Medic8cd17102013-06-20 11:21:49 +00002161 break;
Akira Hatanaka13e6ccf2013-08-06 23:08:38 +00002162 case MipsOperand::Kind_GPR64:
2163 case MipsOperand::Kind_GPR32:
Vladimir Medic8cd17102013-06-20 11:21:49 +00002164 default:
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002165 RegNum = matchCPURegisterName(DefSymbol.substr(1));
Vladimir Medic8cd17102013-06-20 11:21:49 +00002166 break;
2167 }
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002168 if (RegNum > -1)
2169 RegNum = getReg(regKindToRegClass(Kind), RegNum);
Vladimir Medic8cd17102013-06-20 11:21:49 +00002170 }
Jack Carterd76b2372013-03-21 21:44:16 +00002171 if (RegNum > -1) {
2172 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00002173 MipsOperand *op =
2174 MipsOperand::CreateReg(RegNum, S, Parser.getTok().getLoc());
Vladimir Medic8cd17102013-06-20 11:21:49 +00002175 op->setRegKind(Kind);
Jack Carterd76b2372013-03-21 21:44:16 +00002176 Operands.push_back(op);
2177 return true;
2178 }
2179 }
2180 } else if (Expr->getKind() == MCExpr::Constant) {
2181 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00002182 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
2183 MipsOperand *op =
2184 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc());
Jack Carterd76b2372013-03-21 21:44:16 +00002185 Operands.push_back(op);
2186 return true;
2187 }
2188 }
2189 return false;
2190}
Jack Carterd0bd6422013-04-18 00:41:53 +00002191
Jack Carter873c7242013-01-12 01:03:14 +00002192MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +00002193MipsAsmParser::parseHWRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
2194 return parseRegs(Operands, (int)MipsOperand::Kind_HWRegs);
Jack Carter873c7242013-01-12 01:03:14 +00002195}
2196
2197MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +00002198MipsAsmParser::parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
2199 return parseRegs(Operands, (int)MipsOperand::Kind_CCRRegs);
Jack Carter873c7242013-01-12 01:03:14 +00002200}
2201
Vladimir Medic2b953d02013-10-01 09:48:56 +00002202MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +00002203MipsAsmParser::parseInvNum(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
Vladimir Medic2b953d02013-10-01 09:48:56 +00002204 const MCExpr *IdVal;
2205 // If the first token is '$' we may have register operand.
2206 if (Parser.getTok().is(AsmToken::Dollar))
2207 return MatchOperand_NoMatch;
2208 SMLoc S = Parser.getTok().getLoc();
2209 if (getParser().parseExpression(IdVal))
2210 return MatchOperand_ParseFail;
2211 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00002212 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00002213 int64_t Val = MCE->getValue();
2214 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2215 Operands.push_back(MipsOperand::CreateImm(
Vladimir Medic4c299852013-11-06 11:27:05 +00002216 MCConstantExpr::Create(0 - Val, getContext()), S, E));
Vladimir Medic2b953d02013-10-01 09:48:56 +00002217 return MatchOperand_Success;
2218}
2219
Matheus Almeida779c5932013-11-18 12:32:49 +00002220MipsAsmParser::OperandMatchResultTy
2221MipsAsmParser::parseLSAImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
2222 switch (getLexer().getKind()) {
2223 default:
2224 return MatchOperand_NoMatch;
2225 case AsmToken::LParen:
2226 case AsmToken::Plus:
2227 case AsmToken::Minus:
2228 case AsmToken::Integer:
2229 break;
2230 }
2231
2232 const MCExpr *Expr;
2233 SMLoc S = Parser.getTok().getLoc();
2234
2235 if (getParser().parseExpression(Expr))
2236 return MatchOperand_ParseFail;
2237
2238 int64_t Val;
2239 if (!Expr->EvaluateAsAbsolute(Val)) {
2240 Error(S, "expected immediate value");
2241 return MatchOperand_ParseFail;
2242 }
2243
2244 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
2245 // and because the CPU always adds one to the immediate field, the allowed
2246 // range becomes 1..4. We'll only check the range here and will deal
2247 // with the addition/subtraction when actually decoding/encoding
2248 // the instruction.
2249 if (Val < 1 || Val > 4) {
2250 Error(S, "immediate not in range (1..4)");
2251 return MatchOperand_ParseFail;
2252 }
2253
Jack Carter3b2c96e2014-01-22 23:31:38 +00002254 Operands.push_back(
2255 MipsOperand::CreateLSAImm(Expr, S, Parser.getTok().getLoc()));
Matheus Almeida779c5932013-11-18 12:32:49 +00002256 return MatchOperand_Success;
2257}
2258
Jack Carterdc1e35d2012-09-06 20:00:02 +00002259MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
2260
Vladimir Medic4c299852013-11-06 11:27:05 +00002261 MCSymbolRefExpr::VariantKind VK =
2262 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
2263 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
2264 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
2265 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
2266 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
2267 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
2268 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
2269 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
2270 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
2271 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
2272 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
2273 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
2274 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
2275 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
2276 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
2277 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
2278 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
2279 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
2280 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002281
2282 return VK;
2283}
Jack Cartera63b16a2012-09-07 00:23:42 +00002284
Vladimir Medic4c299852013-11-06 11:27:05 +00002285bool MipsAsmParser::ParseInstruction(
2286 ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
2287 SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
Vladimir Medic74593e62013-07-17 15:00:42 +00002288 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00002289 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00002290 Parser.eatToEndOfStatement();
2291 return Error(NameLoc, "Unknown instruction");
2292 }
Vladimir Medic64828a12013-07-16 10:07:14 +00002293 // First operand in MCInst is instruction mnemonic.
2294 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
Jack Carterb4dbc172012-09-05 23:34:03 +00002295
2296 // Read the remaining operands.
2297 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2298 // Read the first operand.
Vladimir Medic64828a12013-07-16 10:07:14 +00002299 if (ParseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002300 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002301 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002302 return Error(Loc, "unexpected token in argument list");
2303 }
2304
Jack Carterd0bd6422013-04-18 00:41:53 +00002305 while (getLexer().is(AsmToken::Comma)) {
2306 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00002307 // Parse and remember the operand.
2308 if (ParseOperand(Operands, Name)) {
2309 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002310 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002311 return Error(Loc, "unexpected token in argument list");
2312 }
2313 }
2314 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002315 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2316 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002317 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002318 return Error(Loc, "unexpected token in argument list");
2319 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002320 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00002321 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00002322}
2323
Jack Carter0b744b32012-10-04 02:29:46 +00002324bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002325 SMLoc Loc = getLexer().getLoc();
2326 Parser.eatToEndOfStatement();
2327 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00002328}
2329
2330bool MipsAsmParser::parseSetNoAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002331 // Line should look like: ".set noat".
2332 // set at reg to 0.
Jack Carter99d2afe2012-10-05 23:55:28 +00002333 Options.setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00002334 // eat noat
2335 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002336 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002337 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2338 reportParseError("unexpected token in statement");
2339 return false;
2340 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002341 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002342 return false;
2343}
Jack Carterd0bd6422013-04-18 00:41:53 +00002344
Jack Carter0b744b32012-10-04 02:29:46 +00002345bool MipsAsmParser::parseSetAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002346 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00002347 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00002348 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00002349 getParser().Lex();
2350 if (getLexer().is(AsmToken::EndOfStatement)) {
Jack Carter99d2afe2012-10-05 23:55:28 +00002351 Options.setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00002352 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002353 return false;
2354 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002355 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00002356 if (getLexer().isNot(AsmToken::Dollar)) {
2357 reportParseError("unexpected token in statement");
2358 return false;
2359 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002360 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00002361 const AsmToken &Reg = Parser.getTok();
2362 if (Reg.is(AsmToken::Identifier)) {
2363 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
2364 } else if (Reg.is(AsmToken::Integer)) {
2365 AtRegNo = Reg.getIntVal();
2366 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00002367 reportParseError("unexpected token in statement");
2368 return false;
2369 }
Jack Carter1ac53222013-02-20 23:11:17 +00002370
Daniel Sanders71a89d922014-03-25 13:01:06 +00002371 if (AtRegNo < 0 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00002372 reportParseError("unexpected token in statement");
2373 return false;
2374 }
2375
2376 if (!Options.setATReg(AtRegNo)) {
Jack Carter0b744b32012-10-04 02:29:46 +00002377 reportParseError("unexpected token in statement");
2378 return false;
2379 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002380 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00002381
2382 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2383 reportParseError("unexpected token in statement");
2384 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002385 }
2386 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002387 return false;
2388 } else {
2389 reportParseError("unexpected token in statement");
2390 return false;
2391 }
2392}
2393
2394bool MipsAsmParser::parseSetReorderDirective() {
2395 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002396 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002397 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2398 reportParseError("unexpected token in statement");
2399 return false;
2400 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002401 Options.setReorder();
Matheus Almeida64459d22014-03-10 13:21:10 +00002402 getTargetStreamer().emitDirectiveSetReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002403 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002404 return false;
2405}
2406
2407bool MipsAsmParser::parseSetNoReorderDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002408 Parser.Lex();
2409 // If this is not the end of the statement, report an error.
2410 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2411 reportParseError("unexpected token in statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002412 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002413 }
2414 Options.setNoreorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00002415 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002416 Parser.Lex(); // Consume the EndOfStatement.
2417 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002418}
2419
2420bool MipsAsmParser::parseSetMacroDirective() {
2421 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002422 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002423 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2424 reportParseError("unexpected token in statement");
2425 return false;
2426 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002427 Options.setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002428 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002429 return false;
2430}
2431
2432bool MipsAsmParser::parseSetNoMacroDirective() {
2433 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002434 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002435 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2436 reportParseError("`noreorder' must be set before `nomacro'");
2437 return false;
2438 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002439 if (Options.isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00002440 reportParseError("`noreorder' must be set before `nomacro'");
2441 return false;
2442 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002443 Options.setNomacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002444 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002445 return false;
2446}
Jack Carterd76b2372013-03-21 21:44:16 +00002447
Jack Carter39536722014-01-22 23:08:42 +00002448bool MipsAsmParser::parseSetNoMips16Directive() {
2449 Parser.Lex();
2450 // If this is not the end of the statement, report an error.
2451 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2452 reportParseError("unexpected token in statement");
2453 return false;
2454 }
2455 // For now do nothing.
2456 Parser.Lex(); // Consume the EndOfStatement.
2457 return false;
2458}
2459
Jack Carterd76b2372013-03-21 21:44:16 +00002460bool MipsAsmParser::parseSetAssignment() {
2461 StringRef Name;
2462 const MCExpr *Value;
2463
2464 if (Parser.parseIdentifier(Name))
2465 reportParseError("expected identifier after .set");
2466
2467 if (getLexer().isNot(AsmToken::Comma))
2468 return reportParseError("unexpected token in .set directive");
Jack Carterb5cf5902013-04-17 00:18:04 +00002469 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00002470
Jack Carter3b2c96e2014-01-22 23:31:38 +00002471 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00002472 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00002473
Jack Carterd0bd6422013-04-18 00:41:53 +00002474 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00002475 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00002476 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00002477 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00002478 Sym = getContext().GetOrCreateSymbol(Name);
2479 Sym->setVariableValue(Value);
2480
2481 return false;
2482}
Jack Carterd0bd6422013-04-18 00:41:53 +00002483
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002484bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
2485 Parser.Lex();
2486 if (getLexer().isNot(AsmToken::EndOfStatement))
2487 return reportParseError("unexpected token in .set directive");
2488
2489 switch(Feature) {
2490 default: llvm_unreachable("Unimplemented feature");
2491 case Mips::FeatureDSP:
2492 setFeatureBits(Mips::FeatureDSP, "dsp");
2493 getTargetStreamer().emitDirectiveSetDsp();
2494 break;
2495 case Mips::FeatureMicroMips:
2496 getTargetStreamer().emitDirectiveSetMicroMips();
2497 break;
2498 case Mips::FeatureMips16:
2499 getTargetStreamer().emitDirectiveSetMips16();
2500 break;
2501 case Mips::FeatureMips32r2:
2502 setFeatureBits(Mips::FeatureMips32r2, "mips32r2");
2503 getTargetStreamer().emitDirectiveSetMips32R2();
2504 break;
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00002505 case Mips::FeatureMips64:
2506 setFeatureBits(Mips::FeatureMips64, "mips64");
2507 getTargetStreamer().emitDirectiveSetMips64();
2508 break;
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00002509 case Mips::FeatureMips64r2:
2510 setFeatureBits(Mips::FeatureMips64r2, "mips64r2");
2511 getTargetStreamer().emitDirectiveSetMips64R2();
2512 break;
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002513 }
2514 return false;
2515}
2516
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002517bool MipsAsmParser::parseRegister(unsigned &RegNum) {
2518 if (!getLexer().is(AsmToken::Dollar))
2519 return false;
2520
2521 Parser.Lex();
2522
2523 const AsmToken &Reg = Parser.getTok();
2524 if (Reg.is(AsmToken::Identifier)) {
2525 RegNum = matchCPURegisterName(Reg.getIdentifier());
2526 } else if (Reg.is(AsmToken::Integer)) {
2527 RegNum = Reg.getIntVal();
2528 } else {
2529 return false;
2530 }
2531
2532 Parser.Lex();
2533 return true;
2534}
2535
2536bool MipsAsmParser::eatComma(StringRef ErrorStr) {
2537 if (getLexer().isNot(AsmToken::Comma)) {
2538 SMLoc Loc = getLexer().getLoc();
2539 Parser.eatToEndOfStatement();
2540 return Error(Loc, ErrorStr);
2541 }
2542
2543 Parser.Lex(); // Eat the comma.
2544 return true;
2545}
2546
2547bool MipsAsmParser::parseDirectiveCPSetup() {
2548 unsigned FuncReg;
2549 unsigned Save;
2550 bool SaveIsReg = true;
2551
2552 if (!parseRegister(FuncReg))
2553 return reportParseError("expected register containing function address");
2554 FuncReg = getGPR(FuncReg);
2555
2556 if (!eatComma("expected comma parsing directive"))
2557 return true;
2558
2559 if (!parseRegister(Save)) {
2560 const AsmToken &Tok = Parser.getTok();
2561 if (Tok.is(AsmToken::Integer)) {
2562 Save = Tok.getIntVal();
2563 SaveIsReg = false;
2564 Parser.Lex();
2565 } else
2566 return reportParseError("expected save register or stack offset");
2567 } else
2568 Save = getGPR(Save);
2569
2570 if (!eatComma("expected comma parsing directive"))
2571 return true;
2572
2573 StringRef Name;
2574 if (Parser.parseIdentifier(Name))
2575 reportParseError("expected identifier");
2576 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
2577 unsigned GPReg = getGPR(matchCPURegisterName("gp"));
2578
2579 // FIXME: The code below this point should be in the TargetStreamers.
2580 // Only N32 and N64 emit anything for .cpsetup
2581 // FIXME: We should only emit something for PIC mode too.
2582 if (!isN32() && !isN64())
2583 return false;
2584
2585 MCStreamer &TS = getStreamer();
2586 MCInst Inst;
2587 // Either store the old $gp in a register or on the stack
2588 if (SaveIsReg) {
2589 // move $save, $gpreg
2590 Inst.setOpcode(Mips::DADDu);
2591 Inst.addOperand(MCOperand::CreateReg(Save));
2592 Inst.addOperand(MCOperand::CreateReg(GPReg));
2593 Inst.addOperand(MCOperand::CreateReg(getGPR(0)));
2594 } else {
2595 // sd $gpreg, offset($sp)
2596 Inst.setOpcode(Mips::SD);
2597 Inst.addOperand(MCOperand::CreateReg(GPReg));
2598 Inst.addOperand(MCOperand::CreateReg(getGPR(matchCPURegisterName("sp"))));
2599 Inst.addOperand(MCOperand::CreateImm(Save));
2600 }
2601 TS.EmitInstruction(Inst, STI);
2602 Inst.clear();
2603
2604 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
2605 Sym->getName(), MCSymbolRefExpr::VK_Mips_GPOFF_HI,
2606 getContext());
2607 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
2608 Sym->getName(), MCSymbolRefExpr::VK_Mips_GPOFF_LO,
2609 getContext());
2610 // lui $gp, %hi(%neg(%gp_rel(funcSym)))
2611 Inst.setOpcode(Mips::LUi);
2612 Inst.addOperand(MCOperand::CreateReg(GPReg));
2613 Inst.addOperand(MCOperand::CreateExpr(HiExpr));
2614 TS.EmitInstruction(Inst, STI);
2615 Inst.clear();
2616
2617 // addiu $gp, $gp, %lo(%neg(%gp_rel(funcSym)))
2618 Inst.setOpcode(Mips::ADDiu);
2619 Inst.addOperand(MCOperand::CreateReg(GPReg));
2620 Inst.addOperand(MCOperand::CreateReg(GPReg));
2621 Inst.addOperand(MCOperand::CreateExpr(LoExpr));
2622 TS.EmitInstruction(Inst, STI);
2623 Inst.clear();
2624
2625 // daddu $gp, $gp, $funcreg
2626 Inst.setOpcode(Mips::DADDu);
2627 Inst.addOperand(MCOperand::CreateReg(GPReg));
2628 Inst.addOperand(MCOperand::CreateReg(GPReg));
2629 Inst.addOperand(MCOperand::CreateReg(FuncReg));
2630 TS.EmitInstruction(Inst, STI);
2631 return false;
2632}
2633
Jack Carter0b744b32012-10-04 02:29:46 +00002634bool MipsAsmParser::parseDirectiveSet() {
2635
Jack Carterd0bd6422013-04-18 00:41:53 +00002636 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00002637 const AsmToken &Tok = Parser.getTok();
2638
2639 if (Tok.getString() == "noat") {
2640 return parseSetNoAtDirective();
2641 } else if (Tok.getString() == "at") {
2642 return parseSetAtDirective();
2643 } else if (Tok.getString() == "reorder") {
2644 return parseSetReorderDirective();
2645 } else if (Tok.getString() == "noreorder") {
2646 return parseSetNoReorderDirective();
2647 } else if (Tok.getString() == "macro") {
2648 return parseSetMacroDirective();
2649 } else if (Tok.getString() == "nomacro") {
2650 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00002651 } else if (Tok.getString() == "mips16") {
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002652 return parseSetFeature(Mips::FeatureMips16);
Jack Carter0b744b32012-10-04 02:29:46 +00002653 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00002654 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00002655 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00002656 getTargetStreamer().emitDirectiveSetNoMicroMips();
2657 Parser.eatToEndOfStatement();
2658 return false;
2659 } else if (Tok.getString() == "micromips") {
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002660 return parseSetFeature(Mips::FeatureMicroMips);
Vladimir Medic615b26e2014-03-04 09:54:09 +00002661 } else if (Tok.getString() == "mips32r2") {
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002662 return parseSetFeature(Mips::FeatureMips32r2);
Matheus Almeida3b9c63d2014-03-26 15:14:32 +00002663 } else if (Tok.getString() == "mips64") {
2664 return parseSetFeature(Mips::FeatureMips64);
Matheus Almeidaa2cd0092014-03-26 14:52:22 +00002665 } else if (Tok.getString() == "mips64r2") {
2666 return parseSetFeature(Mips::FeatureMips64r2);
Vladimir Medic27c398e2014-03-05 11:05:09 +00002667 } else if (Tok.getString() == "dsp") {
Matheus Almeidafe1e39d2014-03-26 14:26:27 +00002668 return parseSetFeature(Mips::FeatureDSP);
Jack Carterd76b2372013-03-21 21:44:16 +00002669 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002670 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00002671 parseSetAssignment();
2672 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002673 }
Jack Carter07c818d2013-01-25 01:31:34 +00002674
Jack Carter0b744b32012-10-04 02:29:46 +00002675 return true;
2676}
2677
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002678/// parseDataDirective
Jack Carter07c818d2013-01-25 01:31:34 +00002679/// ::= .word [ expression (, expression)* ]
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002680bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) {
Jack Carter07c818d2013-01-25 01:31:34 +00002681 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2682 for (;;) {
2683 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002684 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00002685 return true;
2686
2687 getParser().getStreamer().EmitValue(Value, Size);
2688
2689 if (getLexer().is(AsmToken::EndOfStatement))
2690 break;
2691
2692 // FIXME: Improve diagnostic.
2693 if (getLexer().isNot(AsmToken::Comma))
2694 return Error(L, "unexpected token in directive");
2695 Parser.Lex();
2696 }
2697 }
2698
2699 Parser.Lex();
2700 return false;
2701}
2702
Vladimir Medic4c299852013-11-06 11:27:05 +00002703/// parseDirectiveGpWord
2704/// ::= .gpword local_sym
2705bool MipsAsmParser::parseDirectiveGpWord() {
2706 const MCExpr *Value;
2707 // EmitGPRel32Value requires an expression, so we are using base class
2708 // method to evaluate the expression.
2709 if (getParser().parseExpression(Value))
2710 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00002711 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00002712
Vladimir Medice10c1122013-11-13 13:18:04 +00002713 if (getLexer().isNot(AsmToken::EndOfStatement))
Vladimir Medic4c299852013-11-06 11:27:05 +00002714 return Error(getLexer().getLoc(), "unexpected token in directive");
Vladimir Medice10c1122013-11-13 13:18:04 +00002715 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00002716 return false;
2717}
2718
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002719/// parseDirectiveGpDWord
Rafael Espindolab59fb732014-03-28 18:50:26 +00002720/// ::= .gpdword local_sym
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002721bool MipsAsmParser::parseDirectiveGpDWord() {
Rafael Espindolab59fb732014-03-28 18:50:26 +00002722 const MCExpr *Value;
2723 // EmitGPRel64Value requires an expression, so we are using base class
2724 // method to evaluate the expression.
2725 if (getParser().parseExpression(Value))
2726 return true;
2727 getParser().getStreamer().EmitGPRel64Value(Value);
2728
2729 if (getLexer().isNot(AsmToken::EndOfStatement))
2730 return Error(getLexer().getLoc(), "unexpected token in directive");
2731 Parser.Lex(); // Eat EndOfStatement token.
2732 return false;
2733}
2734
Jack Carter0cd3c192014-01-06 23:27:31 +00002735bool MipsAsmParser::parseDirectiveOption() {
2736 // Get the option token.
2737 AsmToken Tok = Parser.getTok();
2738 // At the moment only identifiers are supported.
2739 if (Tok.isNot(AsmToken::Identifier)) {
2740 Error(Parser.getTok().getLoc(), "unexpected token in .option directive");
2741 Parser.eatToEndOfStatement();
2742 return false;
2743 }
2744
2745 StringRef Option = Tok.getIdentifier();
2746
2747 if (Option == "pic0") {
2748 getTargetStreamer().emitDirectiveOptionPic0();
2749 Parser.Lex();
2750 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2751 Error(Parser.getTok().getLoc(),
2752 "unexpected token in .option pic0 directive");
2753 Parser.eatToEndOfStatement();
2754 }
2755 return false;
2756 }
2757
Matheus Almeidaf79b2812014-03-26 13:40:29 +00002758 if (Option == "pic2") {
2759 getTargetStreamer().emitDirectiveOptionPic2();
2760 Parser.Lex();
2761 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2762 Error(Parser.getTok().getLoc(),
2763 "unexpected token in .option pic2 directive");
2764 Parser.eatToEndOfStatement();
2765 }
2766 return false;
2767 }
2768
Jack Carter0cd3c192014-01-06 23:27:31 +00002769 // Unknown option.
2770 Warning(Parser.getTok().getLoc(), "unknown option in .option directive");
2771 Parser.eatToEndOfStatement();
2772 return false;
2773}
2774
Jack Carter0b744b32012-10-04 02:29:46 +00002775bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carter07c818d2013-01-25 01:31:34 +00002776 StringRef IDVal = DirectiveID.getString();
2777
Matheus Almeidaab5633b2014-03-26 15:44:18 +00002778 if (IDVal == ".dword") {
2779 parseDataDirective(8, DirectiveID.getLoc());
2780 return false;
2781 }
2782
Jack Carterd0bd6422013-04-18 00:41:53 +00002783 if (IDVal == ".ent") {
2784 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00002785 Parser.Lex();
2786 return false;
2787 }
2788
Jack Carter07c818d2013-01-25 01:31:34 +00002789 if (IDVal == ".end") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002790 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00002791 Parser.Lex();
2792 return false;
2793 }
2794
Jack Carter07c818d2013-01-25 01:31:34 +00002795 if (IDVal == ".frame") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002796 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002797 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002798 return false;
2799 }
2800
Jack Carter07c818d2013-01-25 01:31:34 +00002801 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00002802 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00002803 }
2804
Jack Carter07c818d2013-01-25 01:31:34 +00002805 if (IDVal == ".fmask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002806 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002807 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002808 return false;
2809 }
2810
Jack Carter07c818d2013-01-25 01:31:34 +00002811 if (IDVal == ".mask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002812 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002813 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002814 return false;
2815 }
2816
Jack Carter07c818d2013-01-25 01:31:34 +00002817 if (IDVal == ".gpword") {
Vladimir Medic4c299852013-11-06 11:27:05 +00002818 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00002819 return false;
2820 }
2821
Rafael Espindolab59fb732014-03-28 18:50:26 +00002822 if (IDVal == ".gpdword") {
Rafael Espindola2378d4c2014-03-31 14:15:07 +00002823 parseDirectiveGpDWord();
Rafael Espindolab59fb732014-03-28 18:50:26 +00002824 return false;
2825 }
2826
Jack Carter07c818d2013-01-25 01:31:34 +00002827 if (IDVal == ".word") {
Matheus Almeida3e2a7022014-03-26 15:24:36 +00002828 parseDataDirective(4, DirectiveID.getLoc());
Jack Carter07c818d2013-01-25 01:31:34 +00002829 return false;
2830 }
2831
Jack Carter0cd3c192014-01-06 23:27:31 +00002832 if (IDVal == ".option")
2833 return parseDirectiveOption();
2834
2835 if (IDVal == ".abicalls") {
2836 getTargetStreamer().emitDirectiveAbiCalls();
2837 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2838 Error(Parser.getTok().getLoc(), "unexpected token in directive");
2839 // Clear line
2840 Parser.eatToEndOfStatement();
2841 }
2842 return false;
2843 }
2844
Daniel Sanders5bce5f62014-03-27 13:52:53 +00002845 if (IDVal == ".cpsetup")
2846 return parseDirectiveCPSetup();
2847
Rafael Espindola870c4e92012-01-11 03:56:41 +00002848 return true;
2849}
2850
Rafael Espindola870c4e92012-01-11 03:56:41 +00002851extern "C" void LLVMInitializeMipsAsmParser() {
2852 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
2853 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
2854 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
2855 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
2856}
Jack Carterb4dbc172012-09-05 23:34:03 +00002857
2858#define GET_REGISTER_MATCHER
2859#define GET_MATCHER_IMPLEMENTATION
2860#include "MipsGenAsmMatcher.inc"