blob: b0e699064ed20cdfdd5e085e556766d0842696e1 [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
10#include "MCTargetDesc/MipsMCTargetDesc.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000011#include "MipsRegisterInfo.h"
Rafael Espindolaa17151a2013-10-08 13:08:17 +000012#include "MipsTargetStreamer.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000013#include "llvm/ADT/APInt.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000014#include "llvm/ADT/StringSwitch.h"
15#include "llvm/MC/MCContext.h"
16#include "llvm/MC/MCExpr.h"
17#include "llvm/MC/MCInst.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000018#include "llvm/MC/MCParser/MCAsmLexer.h"
19#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000020#include "llvm/MC/MCStreamer.h"
21#include "llvm/MC/MCSubtargetInfo.h"
22#include "llvm/MC/MCSymbol.h"
Akira Hatanaka7605630c2012-08-17 20:16:42 +000023#include "llvm/MC/MCTargetAsmParser.h"
Matheus Almeidae0d75aa2013-12-13 11:11:02 +000024#include "llvm/Support/MathExtras.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000025#include "llvm/Support/TargetRegistry.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000026
27using namespace llvm;
28
Joey Gouly0e76fa72013-09-12 10:28:05 +000029namespace llvm {
30class MCInstrInfo;
31}
32
Rafael Espindola870c4e92012-01-11 03:56:41 +000033namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000034class MipsAssemblerOptions {
35public:
Vladimir Medic4c299852013-11-06 11:27:05 +000036 MipsAssemblerOptions() : aTReg(1), reorder(true), macro(true) {}
Jack Carterb4dbc172012-09-05 23:34:03 +000037
Vladimir Medic4c299852013-11-06 11:27:05 +000038 unsigned getATRegNum() { return aTReg; }
Jack Carter0b744b32012-10-04 02:29:46 +000039 bool setATReg(unsigned Reg);
40
Vladimir Medic4c299852013-11-06 11:27:05 +000041 bool isReorder() { return reorder; }
42 void setReorder() { reorder = true; }
43 void setNoreorder() { reorder = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000044
Vladimir Medic4c299852013-11-06 11:27:05 +000045 bool isMacro() { return macro; }
46 void setMacro() { macro = true; }
47 void setNomacro() { macro = false; }
Jack Carter0b744b32012-10-04 02:29:46 +000048
49private:
50 unsigned aTReg;
51 bool reorder;
52 bool macro;
53};
54}
55
56namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +000057class MipsAsmParser : public MCTargetAsmParser {
Akira Hatanaka7605630c2012-08-17 20:16:42 +000058
Rafael Espindolaa17151a2013-10-08 13:08:17 +000059 MipsTargetStreamer &getTargetStreamer() {
Rafael Espindola4a1a3602014-01-14 01:21:46 +000060 MCTargetStreamer &TS = *Parser.getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +000061 return static_cast<MipsTargetStreamer &>(TS);
62 }
63
Jack Carterb4dbc172012-09-05 23:34:03 +000064 MCSubtargetInfo &STI;
65 MCAsmParser &Parser;
Jack Carter99d2afe2012-10-05 23:55:28 +000066 MipsAssemblerOptions Options;
Vladimir Medic27c87ea2013-08-13 13:07:09 +000067 bool hasConsumedDollar;
Jack Carter0b744b32012-10-04 02:29:46 +000068
Akira Hatanaka7605630c2012-08-17 20:16:42 +000069#define GET_ASSEMBLER_HEADER
70#include "MipsGenAsmMatcher.inc"
71
Chad Rosier49963552012-10-13 00:26:04 +000072 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
Vladimir Medic4c299852013-11-06 11:27:05 +000073 SmallVectorImpl<MCParsedAsmOperand *> &Operands,
Chad Rosier49963552012-10-13 00:26:04 +000074 MCStreamer &Out, unsigned &ErrorInfo,
75 bool MatchingInlineAsm);
Rafael Espindola870c4e92012-01-11 03:56:41 +000076
77 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
78
Chad Rosierf0e87202012-10-25 20:41:34 +000079 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
80 SMLoc NameLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +000081 SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Rafael Espindola870c4e92012-01-11 03:56:41 +000082
83 bool ParseDirective(AsmToken DirectiveID);
84
Jack Carterb4dbc172012-09-05 23:34:03 +000085 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +000086 parseRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands, int RegKind);
Vladimir Medic64828a12013-07-16 10:07:14 +000087
88 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +000089 parseMSARegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands, int RegKind);
Jack Carter5dc8ac92013-09-25 23:50:44 +000090
91 MipsAsmParser::OperandMatchResultTy
Matheus Almeidaa591fdc2013-10-21 12:26:50 +000092 parseMSACtrlRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
93 int RegKind);
94
95 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +000096 parseMemOperand(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Jack Carter873c7242013-01-12 01:03:14 +000097
Vladimir Medic4c299852013-11-06 11:27:05 +000098 bool parsePtrReg(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
99 int RegKind);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000100
101 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +0000102 parsePtrReg(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000103
Jack Carter873c7242013-01-12 01:03:14 +0000104 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +0000105 parseGPR32(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Jack Carter873c7242013-01-12 01:03:14 +0000106
107 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +0000108 parseGPR64(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Jack Carter873c7242013-01-12 01:03:14 +0000109
110 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +0000111 parseHWRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Jack Carter873c7242013-01-12 01:03:14 +0000112
113 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +0000114 parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Chad Rosier391d29972012-09-03 18:47:45 +0000115
Vladimir Medic233dd512013-06-24 10:05:34 +0000116 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +0000117 parseAFGR64Regs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Vladimir Medic233dd512013-06-24 10:05:34 +0000118
119 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +0000120 parseFGR64Regs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Vladimir Medic233dd512013-06-24 10:05:34 +0000121
122 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +0000123 parseFGR32Regs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Vladimir Medic233dd512013-06-24 10:05:34 +0000124
Vladimir Medic643b3982013-07-30 10:12:14 +0000125 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +0000126 parseFGRH32Regs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Akira Hatanaka14e31a22013-08-20 22:58:56 +0000127
128 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +0000129 parseFCCRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Vladimir Medic643b3982013-07-30 10:12:14 +0000130
Akira Hatanaka34a32c02013-08-06 22:20:40 +0000131 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +0000132 parseACC64DSP(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Akira Hatanaka34a32c02013-08-06 22:20:40 +0000133
Akira Hatanakafeb7ee82013-08-14 01:02:20 +0000134 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +0000135 parseLO32DSP(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Akira Hatanakafeb7ee82013-08-14 01:02:20 +0000136
137 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +0000138 parseHI32DSP(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Akira Hatanakafeb7ee82013-08-14 01:02:20 +0000139
Vladimir Medic05bcde62013-09-16 10:29:42 +0000140 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +0000141 parseCOP2(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Vladimir Medic05bcde62013-09-16 10:29:42 +0000142
Jack Carter5dc8ac92013-09-25 23:50:44 +0000143 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +0000144 parseMSA128BRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Jack Carter5dc8ac92013-09-25 23:50:44 +0000145
146 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +0000147 parseMSA128HRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Jack Carter5dc8ac92013-09-25 23:50:44 +0000148
149 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +0000150 parseMSA128WRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Jack Carter5dc8ac92013-09-25 23:50:44 +0000151
152 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +0000153 parseMSA128DRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Jack Carter5dc8ac92013-09-25 23:50:44 +0000154
Vladimir Medic2b953d02013-10-01 09:48:56 +0000155 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +0000156 parseMSA128CtrlRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000157
158 MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +0000159 parseInvNum(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
Vladimir Medic2b953d02013-10-01 09:48:56 +0000160
Matheus Almeida779c5932013-11-18 12:32:49 +0000161 MipsAsmParser::OperandMatchResultTy
162 parseLSAImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
163
Jack Carter3b2c96e2014-01-22 23:31:38 +0000164 bool searchSymbolAlias(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
Vladimir Medic8cd17102013-06-20 11:21:49 +0000165 unsigned RegKind);
Jack Carterd76b2372013-03-21 21:44:16 +0000166
Vladimir Medic4c299852013-11-06 11:27:05 +0000167 bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand *> &,
Jack Carterb4dbc172012-09-05 23:34:03 +0000168 StringRef Mnemonic);
169
Jack Carter873c7242013-01-12 01:03:14 +0000170 int tryParseRegister(bool is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000171
Vladimir Medic4c299852013-11-06 11:27:05 +0000172 bool tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
Jack Carter873c7242013-01-12 01:03:14 +0000173 bool is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000174
Jack Carter30a59822012-10-04 04:03:53 +0000175 bool needsExpansion(MCInst &Inst);
176
177 void expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000178 SmallVectorImpl<MCInst> &Instructions);
Jack Carter30a59822012-10-04 04:03:53 +0000179 void expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000180 SmallVectorImpl<MCInst> &Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +0000181 void expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
182 SmallVectorImpl<MCInst> &Instructions);
183 void expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
184 SmallVectorImpl<MCInst> &Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +0000185 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000186 SmallVectorImpl<MCInst> &Instructions, bool isLoad,
187 bool isImmOpnd);
Jack Carter0b744b32012-10-04 02:29:46 +0000188 bool reportParseError(StringRef ErrorMsg);
189
Jack Carterb5cf5902013-04-17 00:18:04 +0000190 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000191 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000192
Vladimir Medic4c299852013-11-06 11:27:05 +0000193 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +0000194
195 bool isEvaluated(const MCExpr *Expr);
Jack Carter0b744b32012-10-04 02:29:46 +0000196 bool parseDirectiveSet();
Jack Carter0cd3c192014-01-06 23:27:31 +0000197 bool parseDirectiveOption();
Jack Carter0b744b32012-10-04 02:29:46 +0000198
199 bool parseSetAtDirective();
200 bool parseSetNoAtDirective();
201 bool parseSetMacroDirective();
202 bool parseSetNoMacroDirective();
203 bool parseSetReorderDirective();
204 bool parseSetNoReorderDirective();
Jack Carter39536722014-01-22 23:08:42 +0000205 bool parseSetMips16Directive();
206 bool parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +0000207
Jack Carterd76b2372013-03-21 21:44:16 +0000208 bool parseSetAssignment();
209
Jack Carter07c818d2013-01-25 01:31:34 +0000210 bool parseDirectiveWord(unsigned Size, SMLoc L);
Vladimir Medic4c299852013-11-06 11:27:05 +0000211 bool parseDirectiveGpWord();
Jack Carter07c818d2013-01-25 01:31:34 +0000212
Jack Carterdc1e35d2012-09-06 20:00:02 +0000213 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000214
Jack Carterb4dbc172012-09-05 23:34:03 +0000215 bool isMips64() const {
216 return (STI.getFeatureBits() & Mips::FeatureMips64) != 0;
217 }
218
Jack Cartera63b16a2012-09-07 00:23:42 +0000219 bool isFP64() const {
220 return (STI.getFeatureBits() & Mips::FeatureFP64Bit) != 0;
221 }
222
Vladimir Medic4c299852013-11-06 11:27:05 +0000223 bool isN64() const { return STI.getFeatureBits() & Mips::FeatureN64; }
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000224
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000225 bool isMicroMips() const {
226 return STI.getFeatureBits() & Mips::FeatureMicroMips;
227 }
228
Jack Carter873c7242013-01-12 01:03:14 +0000229 int matchRegisterName(StringRef Symbol, bool is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000230
Jack Carter1ac53222013-02-20 23:11:17 +0000231 int matchCPURegisterName(StringRef Symbol);
232
Jack Carter873c7242013-01-12 01:03:14 +0000233 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000234
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000235 int matchFPURegisterName(StringRef Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +0000236
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000237 int matchFCCRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000238
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000239 int matchACRegisterName(StringRef Name);
Jack Cartera63b16a2012-09-07 00:23:42 +0000240
Jack Carter5dc8ac92013-09-25 23:50:44 +0000241 int matchMSA128RegisterName(StringRef Name);
242
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000243 int matchMSA128CtrlRegisterName(StringRef Name);
244
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000245 int regKindToRegClass(int RegKind);
Jack Cartera63b16a2012-09-07 00:23:42 +0000246
Jack Carterd0bd6422013-04-18 00:41:53 +0000247 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000248
Jack Carter1ac53222013-02-20 23:11:17 +0000249 int getATReg();
Jack Carter9e65aa32013-03-22 00:05:30 +0000250
251 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000252 SmallVectorImpl<MCInst> &Instructions);
Matheus Almeidab74293d2013-10-14 11:49:30 +0000253
254 // Helper function that checks if the value of a vector index is within the
255 // boundaries of accepted values for each RegisterKind
256 // Example: INSERT.B $w0[n], $1 => 16 > n >= 0
257 bool validateMSAIndex(int Val, int RegKind);
258
Rafael Espindola870c4e92012-01-11 03:56:41 +0000259public:
Joey Gouly0e76fa72013-09-12 10:28:05 +0000260 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
261 const MCInstrInfo &MII)
262 : MCTargetAsmParser(), STI(sti), Parser(parser),
263 hasConsumedDollar(false) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000264 // Initialize the set of available features.
265 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Rafael Espindola870c4e92012-01-11 03:56:41 +0000266 }
267
Jack Carterb4dbc172012-09-05 23:34:03 +0000268 MCAsmParser &getParser() const { return Parser; }
269 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000270};
271}
272
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000273namespace {
274
275/// MipsOperand - Instances of this class represent a parsed Mips machine
276/// instruction.
277class MipsOperand : public MCParsedAsmOperand {
Jack Carterb4dbc172012-09-05 23:34:03 +0000278
Jack Carter873c7242013-01-12 01:03:14 +0000279public:
280 enum RegisterKind {
281 Kind_None,
Akira Hatanaka13e6ccf2013-08-06 23:08:38 +0000282 Kind_GPR32,
283 Kind_GPR64,
Jack Carter873c7242013-01-12 01:03:14 +0000284 Kind_HWRegs,
Jack Carter873c7242013-01-12 01:03:14 +0000285 Kind_FGR32Regs,
Akira Hatanaka14e31a22013-08-20 22:58:56 +0000286 Kind_FGRH32Regs,
Jack Carter873c7242013-01-12 01:03:14 +0000287 Kind_FGR64Regs,
Jack Carter1ac53222013-02-20 23:11:17 +0000288 Kind_AFGR64Regs,
Vladimir Medic643b3982013-07-30 10:12:14 +0000289 Kind_CCRRegs,
Akira Hatanaka34a32c02013-08-06 22:20:40 +0000290 Kind_FCCRegs,
Akira Hatanakafeb7ee82013-08-14 01:02:20 +0000291 Kind_ACC64DSP,
292 Kind_LO32DSP,
Vladimir Medic05bcde62013-09-16 10:29:42 +0000293 Kind_HI32DSP,
Jack Carter5dc8ac92013-09-25 23:50:44 +0000294 Kind_COP2,
295 Kind_MSA128BRegs,
296 Kind_MSA128HRegs,
297 Kind_MSA128WRegs,
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000298 Kind_MSA128DRegs,
299 Kind_MSA128CtrlRegs
Jack Carter873c7242013-01-12 01:03:14 +0000300 };
301
302private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000303 enum KindTy {
304 k_CondCode,
305 k_CoprocNum,
306 k_Immediate,
307 k_Memory,
308 k_PostIndexRegister,
309 k_Register,
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000310 k_PtrReg,
Matheus Almeida779c5932013-11-18 12:32:49 +0000311 k_Token,
312 k_LSAImm
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000313 } Kind;
314
315 MipsOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
Jack Carterb4dbc172012-09-05 23:34:03 +0000316
Eric Christopher8996c5d2013-03-15 00:42:55 +0000317 struct Token {
318 const char *Data;
319 unsigned Length;
320 };
321
322 struct RegOp {
323 unsigned RegNum;
324 RegisterKind Kind;
325 };
326
327 struct ImmOp {
328 const MCExpr *Val;
329 };
330
331 struct MemOp {
332 unsigned Base;
333 const MCExpr *Off;
334 };
335
Jack Carterb4dbc172012-09-05 23:34:03 +0000336 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000337 struct Token Tok;
338 struct RegOp Reg;
339 struct ImmOp Imm;
340 struct MemOp Mem;
Jack Carterb4dbc172012-09-05 23:34:03 +0000341 };
342
343 SMLoc StartLoc, EndLoc;
344
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000345public:
346 void addRegOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000347 assert(N == 1 && "Invalid number of operands!");
348 Inst.addOperand(MCOperand::CreateReg(getReg()));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000349 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000350
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000351 void addPtrRegOperands(MCInst &Inst, unsigned N) const {
352 assert(N == 1 && "Invalid number of operands!");
353 Inst.addOperand(MCOperand::CreateReg(getPtrReg()));
354 }
355
Vladimir Medic4c299852013-11-06 11:27:05 +0000356 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000357 // Add as immediate when possible. Null MCExpr = 0.
358 if (Expr == 0)
359 Inst.addOperand(MCOperand::CreateImm(0));
360 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
361 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
362 else
363 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000364 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000365
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000366 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000367 assert(N == 1 && "Invalid number of operands!");
368 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000369 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000370 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000371
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000372 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000373 assert(N == 2 && "Invalid number of operands!");
374
375 Inst.addOperand(MCOperand::CreateReg(getMemBase()));
376
377 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000378 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000379 }
380
381 bool isReg() const { return Kind == k_Register; }
382 bool isImm() const { return Kind == k_Immediate; }
383 bool isToken() const { return Kind == k_Token; }
384 bool isMem() const { return Kind == k_Memory; }
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000385 bool isPtrReg() const { return Kind == k_PtrReg; }
Vladimir Medic2b953d02013-10-01 09:48:56 +0000386 bool isInvNum() const { return Kind == k_Immediate; }
Matheus Almeida779c5932013-11-18 12:32:49 +0000387 bool isLSAImm() const { return Kind == k_LSAImm; }
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000388
389 StringRef getToken() const {
390 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000391 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000392 }
393
394 unsigned getReg() const {
395 assert((Kind == k_Register) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000396 return Reg.RegNum;
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000397 }
398
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000399 unsigned getPtrReg() const {
400 assert((Kind == k_PtrReg) && "Invalid access!");
401 return Reg.RegNum;
402 }
403
Jack Carter873c7242013-01-12 01:03:14 +0000404 void setRegKind(RegisterKind RegKind) {
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000405 assert((Kind == k_Register || Kind == k_PtrReg) && "Invalid access!");
Jack Carter873c7242013-01-12 01:03:14 +0000406 Reg.Kind = RegKind;
407 }
408
Jack Carterb4dbc172012-09-05 23:34:03 +0000409 const MCExpr *getImm() const {
Matheus Almeida779c5932013-11-18 12:32:49 +0000410 assert((Kind == k_Immediate || Kind == k_LSAImm) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000411 return Imm.Val;
412 }
413
Jack Carterdc1e35d2012-09-06 20:00:02 +0000414 unsigned getMemBase() const {
415 assert((Kind == k_Memory) && "Invalid access!");
416 return Mem.Base;
417 }
418
419 const MCExpr *getMemOff() const {
420 assert((Kind == k_Memory) && "Invalid access!");
421 return Mem.Off;
422 }
423
Jack Carterb4dbc172012-09-05 23:34:03 +0000424 static MipsOperand *CreateToken(StringRef Str, SMLoc S) {
425 MipsOperand *Op = new MipsOperand(k_Token);
426 Op->Tok.Data = Str.data();
427 Op->Tok.Length = Str.size();
428 Op->StartLoc = S;
429 Op->EndLoc = S;
430 return Op;
431 }
432
433 static MipsOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
434 MipsOperand *Op = new MipsOperand(k_Register);
435 Op->Reg.RegNum = RegNum;
436 Op->StartLoc = S;
437 Op->EndLoc = E;
438 return Op;
439 }
440
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +0000441 static MipsOperand *CreatePtrReg(unsigned RegNum, SMLoc S, SMLoc E) {
442 MipsOperand *Op = new MipsOperand(k_PtrReg);
443 Op->Reg.RegNum = RegNum;
444 Op->StartLoc = S;
445 Op->EndLoc = E;
446 return Op;
447 }
448
Jack Carterb4dbc172012-09-05 23:34:03 +0000449 static MipsOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
450 MipsOperand *Op = new MipsOperand(k_Immediate);
451 Op->Imm.Val = Val;
452 Op->StartLoc = S;
453 Op->EndLoc = E;
454 return Op;
455 }
456
Matheus Almeida779c5932013-11-18 12:32:49 +0000457 static MipsOperand *CreateLSAImm(const MCExpr *Val, SMLoc S, SMLoc E) {
458 MipsOperand *Op = new MipsOperand(k_LSAImm);
459 Op->Imm.Val = Val;
460 Op->StartLoc = S;
461 Op->EndLoc = E;
462 return Op;
463 }
464
Jack Carter3b2c96e2014-01-22 23:31:38 +0000465 static MipsOperand *CreateMem(unsigned Base, const MCExpr *Off, SMLoc S,
466 SMLoc E) {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000467 MipsOperand *Op = new MipsOperand(k_Memory);
468 Op->Mem.Base = Base;
469 Op->Mem.Off = Off;
470 Op->StartLoc = S;
471 Op->EndLoc = E;
472 return Op;
473 }
474
Akira Hatanaka13e6ccf2013-08-06 23:08:38 +0000475 bool isGPR32Asm() const {
476 return Kind == k_Register && Reg.Kind == Kind_GPR32;
Jack Carter873c7242013-01-12 01:03:14 +0000477 }
Vladimir Medicc6960592013-06-19 10:14:36 +0000478 void addRegAsmOperands(MCInst &Inst, unsigned N) const {
Jack Carter873c7242013-01-12 01:03:14 +0000479 Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
480 }
481
Akira Hatanaka13e6ccf2013-08-06 23:08:38 +0000482 bool isGPR64Asm() const {
483 return Kind == k_Register && Reg.Kind == Kind_GPR64;
Jack Carter873c7242013-01-12 01:03:14 +0000484 }
Jack Carter873c7242013-01-12 01:03:14 +0000485
486 bool isHWRegsAsm() const {
487 assert((Kind == k_Register) && "Invalid access!");
488 return Reg.Kind == Kind_HWRegs;
489 }
Jack Carter873c7242013-01-12 01:03:14 +0000490
Jack Carter873c7242013-01-12 01:03:14 +0000491 bool isCCRAsm() const {
492 assert((Kind == k_Register) && "Invalid access!");
493 return Reg.Kind == Kind_CCRRegs;
494 }
495
Vladimir Medic4c299852013-11-06 11:27:05 +0000496 bool isAFGR64Asm() const {
Vladimir Medic233dd512013-06-24 10:05:34 +0000497 return Kind == k_Register && Reg.Kind == Kind_AFGR64Regs;
498 }
499
500 bool isFGR64Asm() const {
501 return Kind == k_Register && Reg.Kind == Kind_FGR64Regs;
502 }
503
504 bool isFGR32Asm() const {
505 return (Kind == k_Register) && Reg.Kind == Kind_FGR32Regs;
506 }
507
Akira Hatanaka14e31a22013-08-20 22:58:56 +0000508 bool isFGRH32Asm() const {
509 return (Kind == k_Register) && Reg.Kind == Kind_FGRH32Regs;
510 }
511
Vladimir Medic643b3982013-07-30 10:12:14 +0000512 bool isFCCRegsAsm() const {
513 return (Kind == k_Register) && Reg.Kind == Kind_FCCRegs;
514 }
515
Akira Hatanaka00fcf2e2013-08-08 21:54:26 +0000516 bool isACC64DSPAsm() const {
517 return Kind == k_Register && Reg.Kind == Kind_ACC64DSP;
Akira Hatanaka34a32c02013-08-06 22:20:40 +0000518 }
519
Akira Hatanakafeb7ee82013-08-14 01:02:20 +0000520 bool isLO32DSPAsm() const {
521 return Kind == k_Register && Reg.Kind == Kind_LO32DSP;
522 }
523
524 bool isHI32DSPAsm() const {
525 return Kind == k_Register && Reg.Kind == Kind_HI32DSP;
526 }
527
Vladimir Medic4c299852013-11-06 11:27:05 +0000528 bool isCOP2Asm() const { return Kind == k_Register && Reg.Kind == Kind_COP2; }
Vladimir Medic05bcde62013-09-16 10:29:42 +0000529
Jack Carter5dc8ac92013-09-25 23:50:44 +0000530 bool isMSA128BAsm() const {
531 return Kind == k_Register && Reg.Kind == Kind_MSA128BRegs;
532 }
533
534 bool isMSA128HAsm() const {
535 return Kind == k_Register && Reg.Kind == Kind_MSA128HRegs;
536 }
537
538 bool isMSA128WAsm() const {
539 return Kind == k_Register && Reg.Kind == Kind_MSA128WRegs;
540 }
541
542 bool isMSA128DAsm() const {
543 return Kind == k_Register && Reg.Kind == Kind_MSA128DRegs;
544 }
545
Matheus Almeidaa591fdc2013-10-21 12:26:50 +0000546 bool isMSA128CRAsm() const {
547 return Kind == k_Register && Reg.Kind == Kind_MSA128CtrlRegs;
548 }
549
Jack Carterb4dbc172012-09-05 23:34:03 +0000550 /// getStartLoc - Get the location of the first token of this operand.
Vladimir Medic4c299852013-11-06 11:27:05 +0000551 SMLoc getStartLoc() const { return StartLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +0000552 /// getEndLoc - Get the location of the last token of this operand.
Vladimir Medic4c299852013-11-06 11:27:05 +0000553 SMLoc getEndLoc() const { return EndLoc; }
Jack Carterb4dbc172012-09-05 23:34:03 +0000554
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000555 virtual void print(raw_ostream &OS) const {
556 llvm_unreachable("unimplemented!");
557 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000558}; // class MipsOperand
Vladimir Medic4c299852013-11-06 11:27:05 +0000559} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000560
Jack Carter9e65aa32013-03-22 00:05:30 +0000561namespace llvm {
562extern const MCInstrDesc MipsInsts[];
563}
564static const MCInstrDesc &getInstDesc(unsigned Opcode) {
565 return MipsInsts[Opcode];
566}
567
568bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +0000569 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000570 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
571 Inst.setLoc(IDLoc);
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000572
573 if (MCID.isBranch() || MCID.isCall()) {
574 const unsigned Opcode = Inst.getOpcode();
575 MCOperand Offset;
576
577 switch (Opcode) {
578 default:
579 break;
580 case Mips::BEQ:
581 case Mips::BNE:
Jack Carter3b2c96e2014-01-22 23:31:38 +0000582 assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000583 Offset = Inst.getOperand(2);
584 if (!Offset.isImm())
585 break; // We'll deal with this situation later on when applying fixups.
586 if (!isIntN(isMicroMips() ? 17 : 18, Offset.getImm()))
587 return Error(IDLoc, "branch target out of range");
Jack Carter3b2c96e2014-01-22 23:31:38 +0000588 if (OffsetToAlignment(Offset.getImm(), 1LL << (isMicroMips() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000589 return Error(IDLoc, "branch to misaligned address");
590 break;
591 case Mips::BGEZ:
592 case Mips::BGTZ:
593 case Mips::BLEZ:
594 case Mips::BLTZ:
595 case Mips::BGEZAL:
596 case Mips::BLTZAL:
597 case Mips::BC1F:
598 case Mips::BC1T:
Jack Carter3b2c96e2014-01-22 23:31:38 +0000599 assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000600 Offset = Inst.getOperand(1);
601 if (!Offset.isImm())
602 break; // We'll deal with this situation later on when applying fixups.
603 if (!isIntN(isMicroMips() ? 17 : 18, Offset.getImm()))
604 return Error(IDLoc, "branch target out of range");
Jack Carter3b2c96e2014-01-22 23:31:38 +0000605 if (OffsetToAlignment(Offset.getImm(), 1LL << (isMicroMips() ? 1 : 2)))
Matheus Almeidae0d75aa2013-12-13 11:11:02 +0000606 return Error(IDLoc, "branch to misaligned address");
607 break;
608 }
609 }
610
Jack Carterc15c1d22013-04-25 23:31:35 +0000611 if (MCID.hasDelaySlot() && Options.isReorder()) {
612 // If this instruction has a delay slot and .set reorder is active,
613 // emit a NOP after it.
614 Instructions.push_back(Inst);
615 MCInst NopInst;
616 NopInst.setOpcode(Mips::SLL);
617 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
618 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
619 NopInst.addOperand(MCOperand::CreateImm(0));
620 Instructions.push_back(NopInst);
621 return false;
622 }
623
Jack Carter9e65aa32013-03-22 00:05:30 +0000624 if (MCID.mayLoad() || MCID.mayStore()) {
625 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +0000626 // reference or immediate we may have to expand instructions.
627 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000628 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Vladimir Medic4c299852013-11-06 11:27:05 +0000629 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) ||
630 (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000631 MCOperand &Op = Inst.getOperand(i);
632 if (Op.isImm()) {
633 int MemOffset = Op.getImm();
634 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000635 // Offset can't exceed 16bit value.
636 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +0000637 return false;
638 }
639 } else if (Op.isExpr()) {
640 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +0000641 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000642 const MCSymbolRefExpr *SR =
Vladimir Medic4c299852013-11-06 11:27:05 +0000643 static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +0000644 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000645 // Expand symbol.
646 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +0000647 return false;
648 }
Jack Carterb5cf5902013-04-17 00:18:04 +0000649 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000650 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +0000651 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +0000652 }
653 }
654 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000655 } // for
Vladimir Medic4c299852013-11-06 11:27:05 +0000656 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +0000657
658 if (needsExpansion(Inst))
659 expandInstruction(Inst, IDLoc, Instructions);
660 else
661 Instructions.push_back(Inst);
662
663 return false;
664}
665
Jack Carter30a59822012-10-04 04:03:53 +0000666bool MipsAsmParser::needsExpansion(MCInst &Inst) {
667
Jack Carterd0bd6422013-04-18 00:41:53 +0000668 switch (Inst.getOpcode()) {
669 case Mips::LoadImm32Reg:
670 case Mips::LoadAddr32Imm:
671 case Mips::LoadAddr32Reg:
672 return true;
673 default:
674 return false;
Jack Carter30a59822012-10-04 04:03:53 +0000675 }
676}
Jack Carter92995f12012-10-06 00:53:28 +0000677
Jack Carter30a59822012-10-04 04:03:53 +0000678void MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000679 SmallVectorImpl<MCInst> &Instructions) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000680 switch (Inst.getOpcode()) {
681 case Mips::LoadImm32Reg:
682 return expandLoadImm(Inst, IDLoc, Instructions);
683 case Mips::LoadAddr32Imm:
684 return expandLoadAddressImm(Inst, IDLoc, Instructions);
685 case Mips::LoadAddr32Reg:
686 return expandLoadAddressReg(Inst, IDLoc, Instructions);
687 }
Jack Carter30a59822012-10-04 04:03:53 +0000688}
Jack Carter92995f12012-10-06 00:53:28 +0000689
Jack Carter30a59822012-10-04 04:03:53 +0000690void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000691 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +0000692 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +0000693 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +0000694 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +0000695 const MCOperand &RegOp = Inst.getOperand(0);
696 assert(RegOp.isReg() && "expected register operand kind");
697
698 int ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +0000699 tmpInst.setLoc(IDLoc);
Jack Carterd0bd6422013-04-18 00:41:53 +0000700 if (0 <= ImmValue && ImmValue <= 65535) {
701 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +0000702 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +0000703 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +0000704 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +0000705 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +0000706 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +0000707 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +0000708 } else if (ImmValue < 0 && ImmValue >= -32768) {
709 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +0000710 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +0000711 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +0000712 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +0000713 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +0000714 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +0000715 Instructions.push_back(tmpInst);
716 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000717 // For any other value of j that is representable as a 32-bit integer.
Jack Carter30a59822012-10-04 04:03:53 +0000718 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +0000719 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +0000720 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +0000721 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
722 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +0000723 Instructions.push_back(tmpInst);
Jack Carter92995f12012-10-06 00:53:28 +0000724 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +0000725 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +0000726 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
727 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
728 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
729 tmpInst.setLoc(IDLoc);
Jack Carter30a59822012-10-04 04:03:53 +0000730 Instructions.push_back(tmpInst);
731 }
732}
Jack Carter92995f12012-10-06 00:53:28 +0000733
Vladimir Medic4c299852013-11-06 11:27:05 +0000734void
735MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
736 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +0000737 MCInst tmpInst;
738 const MCOperand &ImmOp = Inst.getOperand(2);
739 assert(ImmOp.isImm() && "expected immediate operand kind");
740 const MCOperand &SrcRegOp = Inst.getOperand(1);
741 assert(SrcRegOp.isReg() && "expected register operand kind");
742 const MCOperand &DstRegOp = Inst.getOperand(0);
743 assert(DstRegOp.isReg() && "expected register operand kind");
744 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000745 if (-32768 <= ImmValue && ImmValue <= 65535) {
746 // For -32768 <= j <= 65535.
747 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +0000748 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +0000749 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
750 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
751 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
752 Instructions.push_back(tmpInst);
753 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000754 // For any other value of j that is representable as a 32-bit integer.
755 // la d,j(s) => lui d,hi16(j)
756 // ori d,d,lo16(j)
757 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +0000758 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +0000759 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
760 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
761 Instructions.push_back(tmpInst);
762 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +0000763 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +0000764 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
765 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
766 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
767 Instructions.push_back(tmpInst);
768 tmpInst.clear();
769 tmpInst.setOpcode(Mips::ADDu);
770 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
771 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
772 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
773 Instructions.push_back(tmpInst);
774 }
775}
776
Vladimir Medic4c299852013-11-06 11:27:05 +0000777void
778MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
779 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +0000780 MCInst tmpInst;
781 const MCOperand &ImmOp = Inst.getOperand(1);
782 assert(ImmOp.isImm() && "expected immediate operand kind");
783 const MCOperand &RegOp = Inst.getOperand(0);
784 assert(RegOp.isReg() && "expected register operand kind");
785 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000786 if (-32768 <= ImmValue && ImmValue <= 65535) {
787 // For -32768 <= j <= 65535.
788 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +0000789 tmpInst.setOpcode(Mips::ADDiu);
790 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +0000791 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +0000792 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
793 Instructions.push_back(tmpInst);
794 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000795 // For any other value of j that is representable as a 32-bit integer.
796 // la d,j => lui d,hi16(j)
797 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +0000798 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +0000799 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
800 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
801 Instructions.push_back(tmpInst);
802 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +0000803 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +0000804 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
805 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
806 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
807 Instructions.push_back(tmpInst);
808 }
809}
810
Jack Carter9e65aa32013-03-22 00:05:30 +0000811void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Vladimir Medic4c299852013-11-06 11:27:05 +0000812 SmallVectorImpl<MCInst> &Instructions,
813 bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000814 const MCSymbolRefExpr *SR;
815 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +0000816 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +0000817 const MCExpr *ExprOffset;
818 unsigned TmpRegNum;
Vladimir Medic4c299852013-11-06 11:27:05 +0000819 unsigned AtRegNum = getReg(
820 (isMips64()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, getATReg());
Jack Carterd0bd6422013-04-18 00:41:53 +0000821 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +0000822 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
823 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +0000824 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +0000825 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
826 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +0000827 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +0000828 if (isImmOpnd) {
829 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
830 ImmOffset = Inst.getOperand(2).getImm();
831 LoOffset = ImmOffset & 0x0000ffff;
832 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +0000833 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +0000834 if (LoOffset & 0x8000)
835 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +0000836 } else
Jack Carter9e65aa32013-03-22 00:05:30 +0000837 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +0000838 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +0000839 TempInst.setLoc(IDLoc);
840 // 1st instruction in expansion is LUi. For load instruction we can use
841 // the dst register as a temporary if base and dst are different,
Jack Carterd0bd6422013-04-18 00:41:53 +0000842 // but for stores we must use $at.
843 TmpRegNum = (isLoad && (BaseRegNum != RegOpNum)) ? RegOpNum : AtRegNum;
Jack Carter9e65aa32013-03-22 00:05:30 +0000844 TempInst.setOpcode(Mips::LUi);
845 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
846 if (isImmOpnd)
847 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
848 else {
849 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +0000850 SR = static_cast<const MCSymbolRefExpr *>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +0000851 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
852 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
853 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +0000854 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +0000855 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000856 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +0000857 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +0000858 }
859 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000860 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +0000861 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +0000862 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +0000863 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +0000864 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +0000865 TempInst.setOpcode(Mips::ADDu);
866 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
867 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
868 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
869 Instructions.push_back(TempInst);
870 TempInst.clear();
Alp Tokercb402912014-01-24 17:20:08 +0000871 // And finally, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +0000872 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +0000873 TempInst.setOpcode(Inst.getOpcode());
874 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
875 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
876 if (isImmOpnd)
877 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
878 else {
879 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000880 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
881 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
882 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +0000883 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +0000884 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000885 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +0000886 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +0000887 }
888 }
889 Instructions.push_back(TempInst);
890 TempInst.clear();
891}
892
Vladimir Medic4c299852013-11-06 11:27:05 +0000893bool MipsAsmParser::MatchAndEmitInstruction(
894 SMLoc IDLoc, unsigned &Opcode,
895 SmallVectorImpl<MCParsedAsmOperand *> &Operands, MCStreamer &Out,
896 unsigned &ErrorInfo, bool MatchingInlineAsm) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000897 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +0000898 SmallVector<MCInst, 8> Instructions;
Vladimir Medic4c299852013-11-06 11:27:05 +0000899 unsigned MatchResult =
900 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +0000901
902 switch (MatchResult) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000903 default:
904 break;
Jack Carterb4dbc172012-09-05 23:34:03 +0000905 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +0000906 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +0000907 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +0000908 for (unsigned i = 0; i < Instructions.size(); i++)
David Woodhousee6c13e42014-01-28 23:12:42 +0000909 Out.EmitInstruction(Instructions[i], STI);
Jack Carterb4dbc172012-09-05 23:34:03 +0000910 return false;
911 }
912 case Match_MissingFeature:
913 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
914 return true;
915 case Match_InvalidOperand: {
916 SMLoc ErrorLoc = IDLoc;
917 if (ErrorInfo != ~0U) {
918 if (ErrorInfo >= Operands.size())
919 return Error(IDLoc, "too few operands for instruction");
920
Vladimir Medic4c299852013-11-06 11:27:05 +0000921 ErrorLoc = ((MipsOperand *)Operands[ErrorInfo])->getStartLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +0000922 if (ErrorLoc == SMLoc())
923 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +0000924 }
925
926 return Error(ErrorLoc, "invalid operand for instruction");
927 }
928 case Match_MnemonicFail:
929 return Error(IDLoc, "invalid instruction");
930 }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000931 return true;
932}
933
Jack Carter1ac53222013-02-20 23:11:17 +0000934int MipsAsmParser::matchCPURegisterName(StringRef Name) {
Vladimir Medic4c299852013-11-06 11:27:05 +0000935 int CC;
Jack Carter1ac53222013-02-20 23:11:17 +0000936
937 if (Name == "at")
938 return getATReg();
939
Vladimir Medic4c299852013-11-06 11:27:05 +0000940 CC = StringSwitch<unsigned>(Name)
941 .Case("zero", 0)
942 .Case("a0", 4)
943 .Case("a1", 5)
944 .Case("a2", 6)
945 .Case("a3", 7)
946 .Case("v0", 2)
947 .Case("v1", 3)
948 .Case("s0", 16)
949 .Case("s1", 17)
950 .Case("s2", 18)
951 .Case("s3", 19)
952 .Case("s4", 20)
953 .Case("s5", 21)
954 .Case("s6", 22)
955 .Case("s7", 23)
956 .Case("k0", 26)
957 .Case("k1", 27)
958 .Case("sp", 29)
959 .Case("fp", 30)
960 .Case("gp", 28)
961 .Case("ra", 31)
962 .Case("t0", 8)
963 .Case("t1", 9)
964 .Case("t2", 10)
965 .Case("t3", 11)
966 .Case("t4", 12)
967 .Case("t5", 13)
968 .Case("t6", 14)
969 .Case("t7", 15)
970 .Case("t8", 24)
971 .Case("t9", 25)
972 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +0000973
Jack Carterd0bd6422013-04-18 00:41:53 +0000974 // Although SGI documentation just cuts out t0-t3 for n32/n64,
Jack Carter1ac53222013-02-20 23:11:17 +0000975 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
976 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
Jack Carterd0bd6422013-04-18 00:41:53 +0000977 if (isMips64() && 8 <= CC && CC <= 11)
Jack Carter1ac53222013-02-20 23:11:17 +0000978 CC += 4;
979
980 if (CC == -1 && isMips64())
981 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +0000982 .Case("a4", 8)
983 .Case("a5", 9)
984 .Case("a6", 10)
985 .Case("a7", 11)
986 .Case("kt0", 26)
987 .Case("kt1", 27)
988 .Case("s8", 30)
989 .Default(-1);
Jack Carter1ac53222013-02-20 23:11:17 +0000990
991 return CC;
992}
Jack Carterd0bd6422013-04-18 00:41:53 +0000993
Vladimir Medic27c87ea2013-08-13 13:07:09 +0000994int MipsAsmParser::matchFPURegisterName(StringRef Name) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000995
Jack Cartera63b16a2012-09-07 00:23:42 +0000996 if (Name[0] == 'f') {
997 StringRef NumString = Name.substr(1);
998 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +0000999 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001000 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001001 if (IntVal > 31) // Maximum index for fpu register.
Jack Cartera63b16a2012-09-07 00:23:42 +00001002 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001003 return IntVal;
1004 }
1005 return -1;
1006}
Jack Cartera63b16a2012-09-07 00:23:42 +00001007
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001008int MipsAsmParser::matchFCCRegisterName(StringRef Name) {
1009
1010 if (Name.startswith("fcc")) {
1011 StringRef NumString = Name.substr(3);
1012 unsigned IntVal;
1013 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001014 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001015 if (IntVal > 7) // There are only 8 fcc registers.
1016 return -1;
1017 return IntVal;
1018 }
1019 return -1;
1020}
1021
1022int MipsAsmParser::matchACRegisterName(StringRef Name) {
1023
Akira Hatanaka274d24c2013-08-14 01:15:52 +00001024 if (Name.startswith("ac")) {
1025 StringRef NumString = Name.substr(2);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001026 unsigned IntVal;
1027 if (NumString.getAsInteger(10, IntVal))
Vladimir Medic4c299852013-11-06 11:27:05 +00001028 return -1; // This is not an integer.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001029 if (IntVal > 3) // There are only 3 acc registers.
1030 return -1;
1031 return IntVal;
Jack Cartera63b16a2012-09-07 00:23:42 +00001032 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001033 return -1;
1034}
Jack Carterd0bd6422013-04-18 00:41:53 +00001035
Jack Carter5dc8ac92013-09-25 23:50:44 +00001036int MipsAsmParser::matchMSA128RegisterName(StringRef Name) {
1037 unsigned IntVal;
1038
1039 if (Name.front() != 'w' || Name.drop_front(1).getAsInteger(10, IntVal))
1040 return -1;
1041
1042 if (IntVal > 31)
1043 return -1;
1044
1045 return IntVal;
1046}
1047
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001048int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) {
1049 int CC;
1050
1051 CC = StringSwitch<unsigned>(Name)
Vladimir Medic4c299852013-11-06 11:27:05 +00001052 .Case("msair", 0)
1053 .Case("msacsr", 1)
1054 .Case("msaaccess", 2)
1055 .Case("msasave", 3)
1056 .Case("msamodify", 4)
1057 .Case("msarequest", 5)
1058 .Case("msamap", 6)
1059 .Case("msaunmap", 7)
1060 .Default(-1);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001061
1062 return CC;
1063}
1064
Vladimir Medic8cd17102013-06-20 11:21:49 +00001065int MipsAsmParser::matchRegisterName(StringRef Name, bool is64BitReg) {
1066
Vladimir Medic8cd17102013-06-20 11:21:49 +00001067 int CC;
1068 CC = matchCPURegisterName(Name);
1069 if (CC != -1)
Akira Hatanaka13e6ccf2013-08-06 23:08:38 +00001070 return matchRegisterByNumber(CC, is64BitReg ? Mips::GPR64RegClassID
1071 : Mips::GPR32RegClassID);
Jack Carter5dc8ac92013-09-25 23:50:44 +00001072 CC = matchFPURegisterName(Name);
Vladimir Medic4c299852013-11-06 11:27:05 +00001073 // TODO: decide about fpu register class
Jack Carter5dc8ac92013-09-25 23:50:44 +00001074 if (CC != -1)
1075 return matchRegisterByNumber(CC, isFP64() ? Mips::FGR64RegClassID
1076 : Mips::FGR32RegClassID);
1077 return matchMSA128RegisterName(Name);
Vladimir Medic8cd17102013-06-20 11:21:49 +00001078}
1079
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001080int MipsAsmParser::regKindToRegClass(int RegKind) {
Jack Cartera63b16a2012-09-07 00:23:42 +00001081
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001082 switch (RegKind) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001083 case MipsOperand::Kind_GPR32:
1084 return Mips::GPR32RegClassID;
1085 case MipsOperand::Kind_GPR64:
1086 return Mips::GPR64RegClassID;
1087 case MipsOperand::Kind_HWRegs:
1088 return Mips::HWRegsRegClassID;
1089 case MipsOperand::Kind_FGR32Regs:
1090 return Mips::FGR32RegClassID;
1091 case MipsOperand::Kind_FGRH32Regs:
1092 return Mips::FGRH32RegClassID;
1093 case MipsOperand::Kind_FGR64Regs:
1094 return Mips::FGR64RegClassID;
1095 case MipsOperand::Kind_AFGR64Regs:
1096 return Mips::AFGR64RegClassID;
1097 case MipsOperand::Kind_CCRRegs:
1098 return Mips::CCRRegClassID;
1099 case MipsOperand::Kind_ACC64DSP:
1100 return Mips::ACC64DSPRegClassID;
1101 case MipsOperand::Kind_FCCRegs:
1102 return Mips::FCCRegClassID;
1103 case MipsOperand::Kind_MSA128BRegs:
1104 return Mips::MSA128BRegClassID;
1105 case MipsOperand::Kind_MSA128HRegs:
1106 return Mips::MSA128HRegClassID;
1107 case MipsOperand::Kind_MSA128WRegs:
1108 return Mips::MSA128WRegClassID;
1109 case MipsOperand::Kind_MSA128DRegs:
1110 return Mips::MSA128DRegClassID;
1111 case MipsOperand::Kind_MSA128CtrlRegs:
1112 return Mips::MSACtrlRegClassID;
1113 default:
1114 return -1;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001115 }
Jack Cartera63b16a2012-09-07 00:23:42 +00001116}
Jack Carterb4dbc172012-09-05 23:34:03 +00001117
Jack Carter0b744b32012-10-04 02:29:46 +00001118bool MipsAssemblerOptions::setATReg(unsigned Reg) {
1119 if (Reg > 31)
1120 return false;
1121
1122 aTReg = Reg;
1123 return true;
1124}
1125
Vladimir Medic4c299852013-11-06 11:27:05 +00001126int MipsAsmParser::getATReg() { return Options.getATRegNum(); }
Jack Carter0b744b32012-10-04 02:29:46 +00001127
Jack Carterd0bd6422013-04-18 00:41:53 +00001128unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +00001129 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +00001130}
1131
Jack Carter873c7242013-01-12 01:03:14 +00001132int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001133 if (RegNum >
Vladimir Medic4c299852013-11-06 11:27:05 +00001134 getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs())
Jack Carterb4dbc172012-09-05 23:34:03 +00001135 return -1;
1136
Jack Carter873c7242013-01-12 01:03:14 +00001137 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +00001138}
1139
Jack Carter873c7242013-01-12 01:03:14 +00001140int MipsAsmParser::tryParseRegister(bool is64BitReg) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001141 const AsmToken &Tok = Parser.getTok();
1142 int RegNum = -1;
1143
1144 if (Tok.is(AsmToken::Identifier)) {
1145 std::string lowerCase = Tok.getString().lower();
Jack Carter873c7242013-01-12 01:03:14 +00001146 RegNum = matchRegisterName(lowerCase, is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +00001147 } else if (Tok.is(AsmToken::Integer))
Jack Carter30a59822012-10-04 04:03:53 +00001148 RegNum = matchRegisterByNumber(static_cast<unsigned>(Tok.getIntVal()),
Vladimir Medic4c299852013-11-06 11:27:05 +00001149 is64BitReg ? Mips::GPR64RegClassID
1150 : Mips::GPR32RegClassID);
Jack Carterb4dbc172012-09-05 23:34:03 +00001151 return RegNum;
1152}
1153
Jack Carterd0bd6422013-04-18 00:41:53 +00001154bool MipsAsmParser::tryParseRegisterOperand(
Vladimir Medic4c299852013-11-06 11:27:05 +00001155 SmallVectorImpl<MCParsedAsmOperand *> &Operands, bool is64BitReg) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001156
1157 SMLoc S = Parser.getTok().getLoc();
1158 int RegNo = -1;
Jack Cartera63b16a2012-09-07 00:23:42 +00001159
Jack Carter873c7242013-01-12 01:03:14 +00001160 RegNo = tryParseRegister(is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +00001161 if (RegNo == -1)
1162 return true;
1163
Vladimir Medic4c299852013-11-06 11:27:05 +00001164 Operands.push_back(
1165 MipsOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Jack Carterb4dbc172012-09-05 23:34:03 +00001166 Parser.Lex(); // Eat register token.
1167 return false;
1168}
1169
Vladimir Medic4c299852013-11-06 11:27:05 +00001170bool
1171MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
1172 StringRef Mnemonic) {
Jack Carter30a59822012-10-04 04:03:53 +00001173 // Check if the current operand has a custom associated parser, if so, try to
1174 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +00001175 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
1176 if (ResTy == MatchOperand_Success)
1177 return false;
1178 // If there wasn't a custom match, try the generic matcher below. Otherwise,
1179 // there was a match, but an error occurred, in which case, just return that
1180 // the operand parsing failed.
1181 if (ResTy == MatchOperand_ParseFail)
1182 return true;
1183
1184 switch (getLexer().getKind()) {
1185 default:
1186 Error(Parser.getTok().getLoc(), "unexpected token in operand");
1187 return true;
1188 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001189 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +00001190 SMLoc S = Parser.getTok().getLoc();
1191 Parser.Lex(); // Eat dollar token.
Jack Carterd0bd6422013-04-18 00:41:53 +00001192 // Parse the register operand.
Jack Carter873c7242013-01-12 01:03:14 +00001193 if (!tryParseRegisterOperand(Operands, isMips64())) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001194 if (getLexer().is(AsmToken::LParen)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001195 // Check if it is indexed addressing operand.
Jack Carterb4dbc172012-09-05 23:34:03 +00001196 Operands.push_back(MipsOperand::CreateToken("(", S));
Jack Carterd0bd6422013-04-18 00:41:53 +00001197 Parser.Lex(); // Eat the parenthesis.
Jack Carterb4dbc172012-09-05 23:34:03 +00001198 if (getLexer().isNot(AsmToken::Dollar))
1199 return true;
1200
Jack Carterd0bd6422013-04-18 00:41:53 +00001201 Parser.Lex(); // Eat the dollar
Jack Carter873c7242013-01-12 01:03:14 +00001202 if (tryParseRegisterOperand(Operands, isMips64()))
Jack Carterb4dbc172012-09-05 23:34:03 +00001203 return true;
1204
1205 if (!getLexer().is(AsmToken::RParen))
1206 return true;
1207
1208 S = Parser.getTok().getLoc();
1209 Operands.push_back(MipsOperand::CreateToken(")", S));
1210 Parser.Lex();
1211 }
1212 return false;
1213 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001214 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +00001215 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001216 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +00001217 return true;
1218
Jack Carter873c7242013-01-12 01:03:14 +00001219 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Benjamin Kramerfa530572012-09-07 09:47:42 +00001220 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterd0bd6422013-04-18 00:41:53 +00001221 // Otherwise create a symbol reference.
Vladimir Medic4c299852013-11-06 11:27:05 +00001222 const MCExpr *Res =
1223 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
Jack Carterb4dbc172012-09-05 23:34:03 +00001224
1225 Operands.push_back(MipsOperand::CreateImm(Res, S, E));
1226 return false;
1227 }
1228 case AsmToken::Identifier:
Vladimir Medic77ffd7a2013-11-13 09:48:53 +00001229 // For instruction aliases like "bc1f $Label" dedicated parser will
1230 // eat the '$' sign before failing. So in order to look for appropriate
1231 // label we must check first if we have already consumed '$'.
1232 if (hasConsumedDollar) {
1233 hasConsumedDollar = false;
1234 SMLoc S = Parser.getTok().getLoc();
1235 StringRef Identifier;
1236 if (Parser.parseIdentifier(Identifier))
1237 return true;
1238 SMLoc E =
1239 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1240 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
1241 // Create a symbol reference.
1242 const MCExpr *Res =
1243 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext());
1244
1245 Operands.push_back(MipsOperand::CreateImm(Res, S, E));
1246 return false;
1247 }
Jack Carterd76b2372013-03-21 21:44:16 +00001248 // Look for the existing symbol, we should check if
Matheus Almeidad534fc32014-01-30 13:40:26 +00001249 // we need to assign the proper RegisterKind.
Jack Carterd0bd6422013-04-18 00:41:53 +00001250 if (searchSymbolAlias(Operands, MipsOperand::Kind_None))
1251 return false;
Vladimir Medic4c299852013-11-06 11:27:05 +00001252 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +00001253 case AsmToken::LParen:
1254 case AsmToken::Minus:
1255 case AsmToken::Plus:
1256 case AsmToken::Integer:
1257 case AsmToken::String: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001258 // Quoted label names.
Jack Carterb4dbc172012-09-05 23:34:03 +00001259 const MCExpr *IdVal;
1260 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001261 if (getParser().parseExpression(IdVal))
Jack Carterb4dbc172012-09-05 23:34:03 +00001262 return true;
Jack Carter873c7242013-01-12 01:03:14 +00001263 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb4dbc172012-09-05 23:34:03 +00001264 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
1265 return false;
1266 }
Jack Carterdc1e35d2012-09-06 20:00:02 +00001267 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +00001268 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001269 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +00001270 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +00001271 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00001272 return true;
1273
Jack Carter873c7242013-01-12 01:03:14 +00001274 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1275
Jack Carterdc1e35d2012-09-06 20:00:02 +00001276 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
1277 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001278 } // case AsmToken::Percent
1279 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00001280 return true;
1281}
1282
Vladimir Medic4c299852013-11-06 11:27:05 +00001283const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
Jack Carterb5cf5902013-04-17 00:18:04 +00001284 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00001285 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00001286 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001287 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001288 // It's a constant, evaluate lo or hi value.
Jack Carterb5cf5902013-04-17 00:18:04 +00001289 if (RelocStr == "lo") {
Jack Carter9e65aa32013-03-22 00:05:30 +00001290 short Val = MCE->getValue();
1291 Res = MCConstantExpr::Create(Val, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001292 } else if (RelocStr == "hi") {
Jack Carter9e65aa32013-03-22 00:05:30 +00001293 int Val = MCE->getValue();
Jack Carterdc463382013-02-21 02:09:31 +00001294 int LoSign = Val & 0x8000;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001295 Val = (Val & 0xffff0000) >> 16;
Jack Carter9e65aa32013-03-22 00:05:30 +00001296 // Lower part is treated as a signed int, so if it is negative
Jack Carterd0bd6422013-04-18 00:41:53 +00001297 // we must add 1 to the hi part to compensate.
Jack Carterdc463382013-02-21 02:09:31 +00001298 if (LoSign)
1299 Val++;
Jack Carter9e65aa32013-03-22 00:05:30 +00001300 Res = MCConstantExpr::Create(Val, getContext());
Evgeniy Stepanov3d8ab192013-04-17 06:45:11 +00001301 } else {
1302 llvm_unreachable("Invalid RelocStr value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001303 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001304 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001305 }
1306
Jack Carterb5cf5902013-04-17 00:18:04 +00001307 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001308 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00001309 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00001310 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00001311 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001312 return Res;
1313 }
1314
1315 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001316 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
1317 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00001318 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
1319 return Res;
1320 }
1321
1322 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001323 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
1324 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
1325 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00001326 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001327 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001328 return Expr;
1329}
1330
1331bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
1332
1333 switch (Expr->getKind()) {
1334 case MCExpr::Constant:
1335 return true;
1336 case MCExpr::SymbolRef:
1337 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
1338 case MCExpr::Binary:
1339 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
1340 if (!isEvaluated(BE->getLHS()))
1341 return false;
1342 return isEvaluated(BE->getRHS());
1343 }
1344 case MCExpr::Unary:
1345 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
1346 default:
Jack Carterdc1e35d2012-09-06 20:00:02 +00001347 return false;
1348 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001349 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00001350}
Jack Carterd0bd6422013-04-18 00:41:53 +00001351
Jack Carterb5cf5902013-04-17 00:18:04 +00001352bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001353 Parser.Lex(); // Eat the % token.
Jack Carterd0bd6422013-04-18 00:41:53 +00001354 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00001355 if (Tok.isNot(AsmToken::Identifier))
1356 return true;
1357
1358 std::string Str = Tok.getIdentifier().str();
1359
Jack Carterd0bd6422013-04-18 00:41:53 +00001360 Parser.Lex(); // Eat the identifier.
1361 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001362 const MCExpr *IdVal;
1363 SMLoc EndLoc;
1364
1365 if (getLexer().getKind() == AsmToken::LParen) {
1366 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001367 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001368 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001369 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001370 const AsmToken &nextTok = Parser.getTok();
1371 if (nextTok.isNot(AsmToken::Identifier))
1372 return true;
1373 Str += "(%";
1374 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00001375 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00001376 if (getLexer().getKind() != AsmToken::LParen)
1377 return true;
1378 } else
1379 break;
1380 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001381 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00001382 return true;
1383
1384 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00001385 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001386
1387 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00001388 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001389
Jack Carterd0bd6422013-04-18 00:41:53 +00001390 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00001391 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001392}
1393
Jack Carterb4dbc172012-09-05 23:34:03 +00001394bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1395 SMLoc &EndLoc) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001396 StartLoc = Parser.getTok().getLoc();
Jack Carter873c7242013-01-12 01:03:14 +00001397 RegNo = tryParseRegister(isMips64());
1398 EndLoc = Parser.getTok().getLoc();
Vladimir Medic4c299852013-11-06 11:27:05 +00001399 return (RegNo == (unsigned)-1);
Jack Carterb4dbc172012-09-05 23:34:03 +00001400}
1401
Jack Carterb5cf5902013-04-17 00:18:04 +00001402bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00001403 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001404 bool Result = true;
1405
1406 while (getLexer().getKind() == AsmToken::LParen)
1407 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00001408
Jack Carterd0bd6422013-04-18 00:41:53 +00001409 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001410 default:
1411 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00001412 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00001413 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00001414 case AsmToken::Integer:
1415 case AsmToken::Minus:
1416 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00001417 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00001418 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00001419 else
1420 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00001421 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00001422 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001423 break;
Jack Carter873c7242013-01-12 01:03:14 +00001424 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00001425 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00001426 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001427 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001428}
1429
Jack Carterb4dbc172012-09-05 23:34:03 +00001430MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
Vladimir Medic4c299852013-11-06 11:27:05 +00001431 SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001432
1433 const MCExpr *IdVal = 0;
Jack Carter873c7242013-01-12 01:03:14 +00001434 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001435 bool isParenExpr = false;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001436 MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00001437 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00001438 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001439
Jack Carterb5cf5902013-04-17 00:18:04 +00001440 if (getLexer().getKind() == AsmToken::LParen) {
1441 Parser.Lex();
1442 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001443 }
1444
Jack Carterb5cf5902013-04-17 00:18:04 +00001445 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001446 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00001447 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001448
Jack Carterd0bd6422013-04-18 00:41:53 +00001449 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001450 if (Tok.isNot(AsmToken::LParen)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001451 MipsOperand *Mnemonic = static_cast<MipsOperand *>(Operands[0]);
Jack Carterb5cf5902013-04-17 00:18:04 +00001452 if (Mnemonic->getToken() == "la") {
Vladimir Medic4c299852013-11-06 11:27:05 +00001453 SMLoc E =
1454 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00001455 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
1456 return MatchOperand_Success;
1457 }
1458 if (Tok.is(AsmToken::EndOfStatement)) {
Vladimir Medic4c299852013-11-06 11:27:05 +00001459 SMLoc E =
1460 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00001461
Jack Carterd0bd6422013-04-18 00:41:53 +00001462 // Zero register assumed, add a memory operand with ZERO as its base.
Vladimir Medic4c299852013-11-06 11:27:05 +00001463 Operands.push_back(MipsOperand::CreateMem(
1464 isMips64() ? Mips::ZERO_64 : Mips::ZERO, IdVal, S, E));
Jack Carterb5cf5902013-04-17 00:18:04 +00001465 return MatchOperand_Success;
1466 }
1467 Error(Parser.getTok().getLoc(), "'(' expected");
1468 return MatchOperand_ParseFail;
1469 }
1470
Jack Carterd0bd6422013-04-18 00:41:53 +00001471 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001472 }
1473
Vladimir Medic4c299852013-11-06 11:27:05 +00001474 Res = parseRegs(Operands, isMips64() ? (int)MipsOperand::Kind_GPR64
1475 : (int)MipsOperand::Kind_GPR32);
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001476 if (Res != MatchOperand_Success)
1477 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001478
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001479 if (Parser.getTok().isNot(AsmToken::RParen)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001480 Error(Parser.getTok().getLoc(), "')' expected");
1481 return MatchOperand_ParseFail;
1482 }
1483
Jack Carter873c7242013-01-12 01:03:14 +00001484 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1485
Jack Carterd0bd6422013-04-18 00:41:53 +00001486 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001487
1488 if (IdVal == 0)
1489 IdVal = MCConstantExpr::Create(0, getContext());
1490
Jack Carterd0bd6422013-04-18 00:41:53 +00001491 // Replace the register operand with the memory operand.
Vladimir Medic4c299852013-11-06 11:27:05 +00001492 MipsOperand *op = static_cast<MipsOperand *>(Operands.back());
Jack Carterdc1e35d2012-09-06 20:00:02 +00001493 int RegNo = op->getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001494 // Remove the register from the operands.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001495 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00001496 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001497 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
1498 int64_t Imm;
1499 if (IdVal->EvaluateAsAbsolute(Imm))
1500 IdVal = MCConstantExpr::Create(Imm, getContext());
1501 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
1502 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
1503 getContext());
1504 }
1505
Jack Carterdc1e35d2012-09-06 20:00:02 +00001506 Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
1507 delete op;
Jack Carterb4dbc172012-09-05 23:34:03 +00001508 return MatchOperand_Success;
1509}
1510
Vladimir Medic4c299852013-11-06 11:27:05 +00001511bool MipsAsmParser::parsePtrReg(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
1512 int RegKind) {
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001513 // If the first token is not '$' we have an error.
1514 if (Parser.getTok().isNot(AsmToken::Dollar))
1515 return false;
1516
1517 SMLoc S = Parser.getTok().getLoc();
1518 Parser.Lex();
1519 AsmToken::TokenKind TkKind = getLexer().getKind();
1520 int Reg;
1521
1522 if (TkKind == AsmToken::Integer) {
1523 Reg = matchRegisterByNumber(Parser.getTok().getIntVal(),
1524 regKindToRegClass(RegKind));
1525 if (Reg == -1)
1526 return false;
1527 } else if (TkKind == AsmToken::Identifier) {
1528 if ((Reg = matchCPURegisterName(Parser.getTok().getString().lower())) == -1)
1529 return false;
1530 Reg = getReg(regKindToRegClass(RegKind), Reg);
1531 } else {
1532 return false;
1533 }
1534
1535 MipsOperand *Op = MipsOperand::CreatePtrReg(Reg, S, Parser.getTok().getLoc());
1536 Op->setRegKind((MipsOperand::RegisterKind)RegKind);
1537 Operands.push_back(Op);
1538 Parser.Lex();
1539 return true;
1540}
1541
1542MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +00001543MipsAsmParser::parsePtrReg(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
1544 MipsOperand::RegisterKind RegKind =
1545 isN64() ? MipsOperand::Kind_GPR64 : MipsOperand::Kind_GPR32;
Akira Hatanaka9bfa2e22013-08-28 00:55:15 +00001546
1547 // Parse index register.
1548 if (!parsePtrReg(Operands, RegKind))
1549 return MatchOperand_NoMatch;
1550
1551 // Parse '('.
1552 if (Parser.getTok().isNot(AsmToken::LParen))
1553 return MatchOperand_NoMatch;
1554
1555 Operands.push_back(MipsOperand::CreateToken("(", getLexer().getLoc()));
1556 Parser.Lex();
1557
1558 // Parse base register.
1559 if (!parsePtrReg(Operands, RegKind))
1560 return MatchOperand_NoMatch;
1561
1562 // Parse ')'.
1563 if (Parser.getTok().isNot(AsmToken::RParen))
1564 return MatchOperand_NoMatch;
1565
1566 Operands.push_back(MipsOperand::CreateToken(")", getLexer().getLoc()));
1567 Parser.Lex();
1568
1569 return MatchOperand_Success;
1570}
1571
Jack Carter873c7242013-01-12 01:03:14 +00001572MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +00001573MipsAsmParser::parseRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
Vladimir Medic8cd17102013-06-20 11:21:49 +00001574 int RegKind) {
1575 MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind)RegKind;
Vladimir Medic4c299852013-11-06 11:27:05 +00001576 if (getLexer().getKind() == AsmToken::Identifier && !hasConsumedDollar) {
Vladimir Medic8cd17102013-06-20 11:21:49 +00001577 if (searchSymbolAlias(Operands, Kind))
Jack Carterd76b2372013-03-21 21:44:16 +00001578 return MatchOperand_Success;
1579 return MatchOperand_NoMatch;
1580 }
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001581 SMLoc S = Parser.getTok().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001582 // If the first token is not '$', we have an error.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001583 if (Parser.getTok().isNot(AsmToken::Dollar) && !hasConsumedDollar)
Jack Carter873c7242013-01-12 01:03:14 +00001584 return MatchOperand_NoMatch;
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001585 if (!hasConsumedDollar) {
1586 Parser.Lex(); // Eat the '$'
1587 hasConsumedDollar = true;
1588 }
1589 if (getLexer().getKind() == AsmToken::Identifier) {
1590 int RegNum = -1;
1591 std::string RegName = Parser.getTok().getString().lower();
Vladimir Medic4c299852013-11-06 11:27:05 +00001592 // Match register by name
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001593 switch (RegKind) {
1594 case MipsOperand::Kind_GPR32:
1595 case MipsOperand::Kind_GPR64:
1596 RegNum = matchCPURegisterName(RegName);
1597 break;
1598 case MipsOperand::Kind_AFGR64Regs:
1599 case MipsOperand::Kind_FGR64Regs:
1600 case MipsOperand::Kind_FGR32Regs:
Akira Hatanaka14e31a22013-08-20 22:58:56 +00001601 case MipsOperand::Kind_FGRH32Regs:
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001602 RegNum = matchFPURegisterName(RegName);
1603 if (RegKind == MipsOperand::Kind_AFGR64Regs)
1604 RegNum /= 2;
Vladimir Medic4c299852013-11-06 11:27:05 +00001605 else if (RegKind == MipsOperand::Kind_FGRH32Regs && !isFP64())
1606 if (RegNum != -1 && RegNum % 2 != 0)
Vladimir Medic65cd5742013-09-10 09:50:01 +00001607 Warning(S, "Float register should be even.");
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001608 break;
1609 case MipsOperand::Kind_FCCRegs:
1610 RegNum = matchFCCRegisterName(RegName);
1611 break;
1612 case MipsOperand::Kind_ACC64DSP:
1613 RegNum = matchACRegisterName(RegName);
1614 break;
Vladimir Medic4c299852013-11-06 11:27:05 +00001615 default:
1616 break; // No match, value is set to -1.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001617 }
1618 // No match found, return _NoMatch to give a chance to other round.
1619 if (RegNum < 0)
1620 return MatchOperand_NoMatch;
Jack Carter873c7242013-01-12 01:03:14 +00001621
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001622 int RegVal = getReg(regKindToRegClass(Kind), RegNum);
1623 if (RegVal == -1)
1624 return MatchOperand_NoMatch;
1625
Vladimir Medic4c299852013-11-06 11:27:05 +00001626 MipsOperand *Op =
1627 MipsOperand::CreateReg(RegVal, S, Parser.getTok().getLoc());
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001628 Op->setRegKind(Kind);
1629 Operands.push_back(Op);
1630 hasConsumedDollar = false;
1631 Parser.Lex(); // Eat the register name.
Vladimir Medic27c87ea2013-08-13 13:07:09 +00001632 return MatchOperand_Success;
1633 } else if (getLexer().getKind() == AsmToken::Integer) {
1634 unsigned RegNum = Parser.getTok().getIntVal();
1635 if (Kind == MipsOperand::Kind_HWRegs) {
1636 if (RegNum != 29)
1637 return MatchOperand_NoMatch;
1638 // Only hwreg 29 is supported, found at index 0.
1639 RegNum = 0;
1640 }
1641 int Reg = matchRegisterByNumber(RegNum, regKindToRegClass(Kind));
1642 if (Reg == -1)
1643 return MatchOperand_NoMatch;
1644 MipsOperand *Op = MipsOperand::CreateReg(Reg, S, Parser.getTok().getLoc());
1645 Op->setRegKind(Kind);
1646 Operands.push_back(Op);
1647 hasConsumedDollar = false;
1648 Parser.Lex(); // Eat the register number.
Vladimir Medic4c299852013-11-06 11:27:05 +00001649 if ((RegKind == MipsOperand::Kind_GPR32) &&
1650 (getLexer().is(AsmToken::LParen))) {
Vladimir Medic3467b902013-07-18 09:28:35 +00001651 // Check if it is indexed addressing operand.
1652 Operands.push_back(MipsOperand::CreateToken("(", getLexer().getLoc()));
1653 Parser.Lex(); // Eat the parenthesis.
Vladimir Medic4c299852013-11-06 11:27:05 +00001654 if (parseRegs(Operands, RegKind) != MatchOperand_Success)
Vladimir Medic3467b902013-07-18 09:28:35 +00001655 return MatchOperand_NoMatch;
1656 if (getLexer().isNot(AsmToken::RParen))
1657 return MatchOperand_NoMatch;
1658 Operands.push_back(MipsOperand::CreateToken(")", getLexer().getLoc()));
1659 Parser.Lex();
1660 }
Jack Carter873c7242013-01-12 01:03:14 +00001661 return MatchOperand_Success;
1662 }
1663 return MatchOperand_NoMatch;
1664}
Vladimir Medic64828a12013-07-16 10:07:14 +00001665
Matheus Almeidab74293d2013-10-14 11:49:30 +00001666bool MipsAsmParser::validateMSAIndex(int Val, int RegKind) {
1667 MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind)RegKind;
1668
1669 if (Val < 0)
1670 return false;
1671
1672 switch (Kind) {
1673 default:
1674 return false;
1675 case MipsOperand::Kind_MSA128BRegs:
1676 return Val < 16;
1677 case MipsOperand::Kind_MSA128HRegs:
1678 return Val < 8;
1679 case MipsOperand::Kind_MSA128WRegs:
1680 return Val < 4;
1681 case MipsOperand::Kind_MSA128DRegs:
1682 return Val < 2;
1683 }
1684}
1685
Vladimir Medic8cd17102013-06-20 11:21:49 +00001686MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +00001687MipsAsmParser::parseMSARegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
Jack Carter5dc8ac92013-09-25 23:50:44 +00001688 int RegKind) {
1689 MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind)RegKind;
1690 SMLoc S = Parser.getTok().getLoc();
1691 std::string RegName;
1692
1693 if (Parser.getTok().isNot(AsmToken::Dollar))
1694 return MatchOperand_NoMatch;
1695
1696 switch (RegKind) {
1697 default:
1698 return MatchOperand_ParseFail;
1699 case MipsOperand::Kind_MSA128BRegs:
1700 case MipsOperand::Kind_MSA128HRegs:
1701 case MipsOperand::Kind_MSA128WRegs:
1702 case MipsOperand::Kind_MSA128DRegs:
1703 break;
1704 }
1705
1706 Parser.Lex(); // Eat the '$'.
1707 if (getLexer().getKind() == AsmToken::Identifier)
1708 RegName = Parser.getTok().getString().lower();
1709 else
1710 return MatchOperand_ParseFail;
1711
1712 int RegNum = matchMSA128RegisterName(RegName);
1713
1714 if (RegNum < 0 || RegNum > 31)
1715 return MatchOperand_ParseFail;
1716
1717 int RegVal = getReg(regKindToRegClass(Kind), RegNum);
1718 if (RegVal == -1)
1719 return MatchOperand_ParseFail;
1720
Vladimir Medic4c299852013-11-06 11:27:05 +00001721 MipsOperand *Op = MipsOperand::CreateReg(RegVal, S, Parser.getTok().getLoc());
Jack Carter5dc8ac92013-09-25 23:50:44 +00001722 Op->setRegKind(Kind);
1723 Operands.push_back(Op);
1724
1725 Parser.Lex(); // Eat the register identifier.
1726
Matheus Almeidab74293d2013-10-14 11:49:30 +00001727 // MSA registers may be suffixed with an index in the form of:
1728 // 1) Immediate expression.
1729 // 2) General Purpose Register.
1730 // Examples:
1731 // 1) copy_s.b $29,$w0[0]
1732 // 2) sld.b $w0,$w1[$1]
1733
1734 if (Parser.getTok().isNot(AsmToken::LBrac))
1735 return MatchOperand_Success;
1736
1737 MipsOperand *Mnemonic = static_cast<MipsOperand *>(Operands[0]);
1738
1739 Operands.push_back(MipsOperand::CreateToken("[", Parser.getTok().getLoc()));
1740 Parser.Lex(); // Parse the '[' token.
1741
1742 if (Parser.getTok().is(AsmToken::Dollar)) {
1743 // This must be a GPR.
1744 MipsOperand *RegOp;
1745 SMLoc VIdx = Parser.getTok().getLoc();
1746 Parser.Lex(); // Parse the '$' token.
1747
1748 // GPR have aliases and we must account for that. Example: $30 == $fp
1749 if (getLexer().getKind() == AsmToken::Integer) {
1750 unsigned RegNum = Parser.getTok().getIntVal();
1751 int Reg = matchRegisterByNumber(
1752 RegNum, regKindToRegClass(MipsOperand::Kind_GPR32));
1753 if (Reg == -1) {
1754 Error(VIdx, "invalid general purpose register");
1755 return MatchOperand_ParseFail;
1756 }
1757
1758 RegOp = MipsOperand::CreateReg(Reg, VIdx, Parser.getTok().getLoc());
1759 } else if (getLexer().getKind() == AsmToken::Identifier) {
1760 int RegNum = -1;
1761 std::string RegName = Parser.getTok().getString().lower();
1762
1763 RegNum = matchCPURegisterName(RegName);
1764 if (RegNum == -1) {
1765 Error(VIdx, "general purpose register expected");
1766 return MatchOperand_ParseFail;
1767 }
1768 RegNum = getReg(regKindToRegClass(MipsOperand::Kind_GPR32), RegNum);
1769 RegOp = MipsOperand::CreateReg(RegNum, VIdx, Parser.getTok().getLoc());
1770 } else
1771 return MatchOperand_ParseFail;
1772
1773 RegOp->setRegKind(MipsOperand::Kind_GPR32);
1774 Operands.push_back(RegOp);
1775 Parser.Lex(); // Eat the register identifier.
1776
1777 if (Parser.getTok().isNot(AsmToken::RBrac))
1778 return MatchOperand_ParseFail;
1779
1780 Operands.push_back(MipsOperand::CreateToken("]", Parser.getTok().getLoc()));
1781 Parser.Lex(); // Parse the ']' token.
1782
1783 return MatchOperand_Success;
1784 }
1785
1786 // The index must be a constant expression then.
1787 SMLoc VIdx = Parser.getTok().getLoc();
1788 const MCExpr *ImmVal;
1789
1790 if (getParser().parseExpression(ImmVal))
1791 return MatchOperand_ParseFail;
1792
1793 const MCConstantExpr *expr = dyn_cast<MCConstantExpr>(ImmVal);
1794 if (!expr || !validateMSAIndex((int)expr->getValue(), Kind)) {
1795 Error(VIdx, "invalid immediate value");
1796 return MatchOperand_ParseFail;
1797 }
1798
1799 SMLoc E = Parser.getTok().getEndLoc();
1800
1801 if (Parser.getTok().isNot(AsmToken::RBrac))
1802 return MatchOperand_ParseFail;
1803
Vladimir Medic4c299852013-11-06 11:27:05 +00001804 bool insve =
1805 Mnemonic->getToken() == "insve.b" || Mnemonic->getToken() == "insve.h" ||
1806 Mnemonic->getToken() == "insve.w" || Mnemonic->getToken() == "insve.d";
Matheus Almeidab74293d2013-10-14 11:49:30 +00001807
1808 // The second vector index of insve instructions is always 0.
1809 if (insve && Operands.size() > 6) {
1810 if (expr->getValue() != 0) {
1811 Error(VIdx, "immediate value must be 0");
1812 return MatchOperand_ParseFail;
1813 }
1814 Operands.push_back(MipsOperand::CreateToken("0", VIdx));
1815 } else
1816 Operands.push_back(MipsOperand::CreateImm(expr, VIdx, E));
1817
1818 Operands.push_back(MipsOperand::CreateToken("]", Parser.getTok().getLoc()));
1819
1820 Parser.Lex(); // Parse the ']' token.
1821
Jack Carter5dc8ac92013-09-25 23:50:44 +00001822 return MatchOperand_Success;
1823}
1824
1825MipsAsmParser::OperandMatchResultTy
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001826MipsAsmParser::parseMSACtrlRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
1827 int RegKind) {
1828 MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind)RegKind;
1829
1830 if (Kind != MipsOperand::Kind_MSA128CtrlRegs)
1831 return MatchOperand_NoMatch;
1832
1833 if (Parser.getTok().isNot(AsmToken::Dollar))
1834 return MatchOperand_ParseFail;
1835
1836 SMLoc S = Parser.getTok().getLoc();
1837
1838 Parser.Lex(); // Eat the '$' symbol.
1839
1840 int RegNum = -1;
1841 if (getLexer().getKind() == AsmToken::Identifier)
1842 RegNum = matchMSA128CtrlRegisterName(Parser.getTok().getString().lower());
1843 else if (getLexer().getKind() == AsmToken::Integer)
1844 RegNum = Parser.getTok().getIntVal();
1845 else
1846 return MatchOperand_ParseFail;
1847
1848 if (RegNum < 0 || RegNum > 7)
1849 return MatchOperand_ParseFail;
1850
1851 int RegVal = getReg(regKindToRegClass(Kind), RegNum);
1852 if (RegVal == -1)
1853 return MatchOperand_ParseFail;
1854
Vladimir Medic4c299852013-11-06 11:27:05 +00001855 MipsOperand *RegOp =
1856 MipsOperand::CreateReg(RegVal, S, Parser.getTok().getLoc());
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00001857 RegOp->setRegKind(MipsOperand::Kind_MSA128CtrlRegs);
1858 Operands.push_back(RegOp);
1859 Parser.Lex(); // Eat the register identifier.
1860
1861 return MatchOperand_Success;
1862}
1863
1864MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +00001865MipsAsmParser::parseGPR64(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
Vladimir Medic8cd17102013-06-20 11:21:49 +00001866
1867 if (!isMips64())
1868 return MatchOperand_NoMatch;
Vladimir Medic4c299852013-11-06 11:27:05 +00001869 return parseRegs(Operands, (int)MipsOperand::Kind_GPR64);
Vladimir Medic8cd17102013-06-20 11:21:49 +00001870}
1871
1872MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +00001873MipsAsmParser::parseGPR32(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
1874 return parseRegs(Operands, (int)MipsOperand::Kind_GPR32);
Vladimir Medic8cd17102013-06-20 11:21:49 +00001875}
Jack Carter873c7242013-01-12 01:03:14 +00001876
Vladimir Medic4c299852013-11-06 11:27:05 +00001877MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseAFGR64Regs(
1878 SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
Vladimir Medic233dd512013-06-24 10:05:34 +00001879
1880 if (isFP64())
1881 return MatchOperand_NoMatch;
Vladimir Medic4c299852013-11-06 11:27:05 +00001882 return parseRegs(Operands, (int)MipsOperand::Kind_AFGR64Regs);
Vladimir Medic233dd512013-06-24 10:05:34 +00001883}
1884
1885MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +00001886MipsAsmParser::parseFGR64Regs(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
Vladimir Medic233dd512013-06-24 10:05:34 +00001887 if (!isFP64())
1888 return MatchOperand_NoMatch;
Vladimir Medic4c299852013-11-06 11:27:05 +00001889 return parseRegs(Operands, (int)MipsOperand::Kind_FGR64Regs);
Vladimir Medic233dd512013-06-24 10:05:34 +00001890}
1891
1892MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +00001893MipsAsmParser::parseFGR32Regs(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
1894 return parseRegs(Operands, (int)MipsOperand::Kind_FGR32Regs);
1895}
1896
1897MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseFGRH32Regs(
1898 SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
1899 return parseRegs(Operands, (int)MipsOperand::Kind_FGRH32Regs);
Vladimir Medic233dd512013-06-24 10:05:34 +00001900}
1901
Vladimir Medic643b3982013-07-30 10:12:14 +00001902MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +00001903MipsAsmParser::parseFCCRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
1904 return parseRegs(Operands, (int)MipsOperand::Kind_FCCRegs);
Akira Hatanaka14e31a22013-08-20 22:58:56 +00001905}
1906
1907MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +00001908MipsAsmParser::parseACC64DSP(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
1909 return parseRegs(Operands, (int)MipsOperand::Kind_ACC64DSP);
Vladimir Medic643b3982013-07-30 10:12:14 +00001910}
1911
Akira Hatanaka34a32c02013-08-06 22:20:40 +00001912MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +00001913MipsAsmParser::parseLO32DSP(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
Akira Hatanakafeb7ee82013-08-14 01:02:20 +00001914 // If the first token is not '$' we have an error.
1915 if (Parser.getTok().isNot(AsmToken::Dollar))
1916 return MatchOperand_NoMatch;
1917
1918 SMLoc S = Parser.getTok().getLoc();
1919 Parser.Lex(); // Eat the '$'
1920
1921 const AsmToken &Tok = Parser.getTok(); // Get next token.
1922
1923 if (Tok.isNot(AsmToken::Identifier))
1924 return MatchOperand_NoMatch;
1925
1926 if (!Tok.getIdentifier().startswith("ac"))
1927 return MatchOperand_NoMatch;
1928
1929 StringRef NumString = Tok.getIdentifier().substr(2);
1930
1931 unsigned IntVal;
1932 if (NumString.getAsInteger(10, IntVal))
1933 return MatchOperand_NoMatch;
1934
1935 unsigned Reg = matchRegisterByNumber(IntVal, Mips::LO32DSPRegClassID);
1936
1937 MipsOperand *Op = MipsOperand::CreateReg(Reg, S, Parser.getTok().getLoc());
1938 Op->setRegKind(MipsOperand::Kind_LO32DSP);
1939 Operands.push_back(Op);
1940
1941 Parser.Lex(); // Eat the register number.
1942 return MatchOperand_Success;
1943}
1944
1945MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +00001946MipsAsmParser::parseHI32DSP(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
Akira Hatanakafeb7ee82013-08-14 01:02:20 +00001947 // If the first token is not '$' we have an error.
1948 if (Parser.getTok().isNot(AsmToken::Dollar))
1949 return MatchOperand_NoMatch;
1950
1951 SMLoc S = Parser.getTok().getLoc();
1952 Parser.Lex(); // Eat the '$'
1953
1954 const AsmToken &Tok = Parser.getTok(); // Get next token.
1955
1956 if (Tok.isNot(AsmToken::Identifier))
1957 return MatchOperand_NoMatch;
1958
1959 if (!Tok.getIdentifier().startswith("ac"))
1960 return MatchOperand_NoMatch;
1961
1962 StringRef NumString = Tok.getIdentifier().substr(2);
1963
1964 unsigned IntVal;
1965 if (NumString.getAsInteger(10, IntVal))
1966 return MatchOperand_NoMatch;
1967
1968 unsigned Reg = matchRegisterByNumber(IntVal, Mips::HI32DSPRegClassID);
1969
1970 MipsOperand *Op = MipsOperand::CreateReg(Reg, S, Parser.getTok().getLoc());
1971 Op->setRegKind(MipsOperand::Kind_HI32DSP);
1972 Operands.push_back(Op);
1973
1974 Parser.Lex(); // Eat the register number.
1975 return MatchOperand_Success;
1976}
1977
Vladimir Medic05bcde62013-09-16 10:29:42 +00001978MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +00001979MipsAsmParser::parseCOP2(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
Vladimir Medic05bcde62013-09-16 10:29:42 +00001980 // If the first token is not '$' we have an error.
1981 if (Parser.getTok().isNot(AsmToken::Dollar))
1982 return MatchOperand_NoMatch;
1983
1984 SMLoc S = Parser.getTok().getLoc();
1985 Parser.Lex(); // Eat the '$'
1986
1987 const AsmToken &Tok = Parser.getTok(); // Get next token.
1988
1989 if (Tok.isNot(AsmToken::Integer))
1990 return MatchOperand_NoMatch;
1991
1992 unsigned IntVal = Tok.getIntVal();
1993
1994 unsigned Reg = matchRegisterByNumber(IntVal, Mips::COP2RegClassID);
1995
1996 MipsOperand *Op = MipsOperand::CreateReg(Reg, S, Parser.getTok().getLoc());
1997 Op->setRegKind(MipsOperand::Kind_COP2);
1998 Operands.push_back(Op);
1999
2000 Parser.Lex(); // Eat the register number.
2001 return MatchOperand_Success;
2002}
2003
Vladimir Medic4c299852013-11-06 11:27:05 +00002004MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMSA128BRegs(
2005 SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
2006 return parseMSARegs(Operands, (int)MipsOperand::Kind_MSA128BRegs);
Jack Carter5dc8ac92013-09-25 23:50:44 +00002007}
2008
Vladimir Medic4c299852013-11-06 11:27:05 +00002009MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMSA128HRegs(
2010 SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
2011 return parseMSARegs(Operands, (int)MipsOperand::Kind_MSA128HRegs);
Jack Carter5dc8ac92013-09-25 23:50:44 +00002012}
2013
Vladimir Medic4c299852013-11-06 11:27:05 +00002014MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMSA128WRegs(
2015 SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
2016 return parseMSARegs(Operands, (int)MipsOperand::Kind_MSA128WRegs);
Jack Carter5dc8ac92013-09-25 23:50:44 +00002017}
2018
Vladimir Medic4c299852013-11-06 11:27:05 +00002019MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMSA128DRegs(
2020 SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
2021 return parseMSARegs(Operands, (int)MipsOperand::Kind_MSA128DRegs);
Jack Carter5dc8ac92013-09-25 23:50:44 +00002022}
2023
Vladimir Medic4c299852013-11-06 11:27:05 +00002024MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMSA128CtrlRegs(
2025 SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
2026 return parseMSACtrlRegs(Operands, (int)MipsOperand::Kind_MSA128CtrlRegs);
Matheus Almeidaa591fdc2013-10-21 12:26:50 +00002027}
2028
Jack Carterd0bd6422013-04-18 00:41:53 +00002029bool MipsAsmParser::searchSymbolAlias(
Vladimir Medic4c299852013-11-06 11:27:05 +00002030 SmallVectorImpl<MCParsedAsmOperand *> &Operands, unsigned RegKind) {
Jack Carterd76b2372013-03-21 21:44:16 +00002031
2032 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
2033 if (Sym) {
2034 SMLoc S = Parser.getTok().getLoc();
2035 const MCExpr *Expr;
2036 if (Sym->isVariable())
2037 Expr = Sym->getVariableValue();
2038 else
2039 return false;
2040 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic4c299852013-11-06 11:27:05 +00002041 MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind)RegKind;
2042 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr);
Jack Carterd76b2372013-03-21 21:44:16 +00002043 const StringRef DefSymbol = Ref->getSymbol().getName();
2044 if (DefSymbol.startswith("$")) {
Jack Carter02593002013-05-28 22:21:05 +00002045 int RegNum = -1;
2046 APInt IntVal(32, -1);
2047 if (!DefSymbol.substr(1).getAsInteger(10, IntVal))
2048 RegNum = matchRegisterByNumber(IntVal.getZExtValue(),
Vladimir Medic4c299852013-11-06 11:27:05 +00002049 isMips64() ? Mips::GPR64RegClassID
2050 : Mips::GPR32RegClassID);
Vladimir Medic8cd17102013-06-20 11:21:49 +00002051 else {
2052 // Lookup for the register with the corresponding name.
2053 switch (Kind) {
2054 case MipsOperand::Kind_AFGR64Regs:
2055 case MipsOperand::Kind_FGR64Regs:
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002056 RegNum = matchFPURegisterName(DefSymbol.substr(1));
Vladimir Medic8cd17102013-06-20 11:21:49 +00002057 break;
2058 case MipsOperand::Kind_FGR32Regs:
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002059 RegNum = matchFPURegisterName(DefSymbol.substr(1));
Vladimir Medic8cd17102013-06-20 11:21:49 +00002060 break;
Akira Hatanaka13e6ccf2013-08-06 23:08:38 +00002061 case MipsOperand::Kind_GPR64:
2062 case MipsOperand::Kind_GPR32:
Vladimir Medic8cd17102013-06-20 11:21:49 +00002063 default:
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002064 RegNum = matchCPURegisterName(DefSymbol.substr(1));
Vladimir Medic8cd17102013-06-20 11:21:49 +00002065 break;
2066 }
Vladimir Medic27c87ea2013-08-13 13:07:09 +00002067 if (RegNum > -1)
2068 RegNum = getReg(regKindToRegClass(Kind), RegNum);
Vladimir Medic8cd17102013-06-20 11:21:49 +00002069 }
Jack Carterd76b2372013-03-21 21:44:16 +00002070 if (RegNum > -1) {
2071 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00002072 MipsOperand *op =
2073 MipsOperand::CreateReg(RegNum, S, Parser.getTok().getLoc());
Vladimir Medic8cd17102013-06-20 11:21:49 +00002074 op->setRegKind(Kind);
Jack Carterd76b2372013-03-21 21:44:16 +00002075 Operands.push_back(op);
2076 return true;
2077 }
2078 }
2079 } else if (Expr->getKind() == MCExpr::Constant) {
2080 Parser.Lex();
Vladimir Medic4c299852013-11-06 11:27:05 +00002081 const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
2082 MipsOperand *op =
2083 MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc());
Jack Carterd76b2372013-03-21 21:44:16 +00002084 Operands.push_back(op);
2085 return true;
2086 }
2087 }
2088 return false;
2089}
Jack Carterd0bd6422013-04-18 00:41:53 +00002090
Jack Carter873c7242013-01-12 01:03:14 +00002091MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +00002092MipsAsmParser::parseHWRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
2093 return parseRegs(Operands, (int)MipsOperand::Kind_HWRegs);
Jack Carter873c7242013-01-12 01:03:14 +00002094}
2095
2096MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +00002097MipsAsmParser::parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
2098 return parseRegs(Operands, (int)MipsOperand::Kind_CCRRegs);
Jack Carter873c7242013-01-12 01:03:14 +00002099}
2100
Vladimir Medic2b953d02013-10-01 09:48:56 +00002101MipsAsmParser::OperandMatchResultTy
Vladimir Medic4c299852013-11-06 11:27:05 +00002102MipsAsmParser::parseInvNum(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
Vladimir Medic2b953d02013-10-01 09:48:56 +00002103 const MCExpr *IdVal;
2104 // If the first token is '$' we may have register operand.
2105 if (Parser.getTok().is(AsmToken::Dollar))
2106 return MatchOperand_NoMatch;
2107 SMLoc S = Parser.getTok().getLoc();
2108 if (getParser().parseExpression(IdVal))
2109 return MatchOperand_ParseFail;
2110 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
Vladimir Medic4c299852013-11-06 11:27:05 +00002111 assert(MCE && "Unexpected MCExpr type.");
Vladimir Medic2b953d02013-10-01 09:48:56 +00002112 int64_t Val = MCE->getValue();
2113 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
2114 Operands.push_back(MipsOperand::CreateImm(
Vladimir Medic4c299852013-11-06 11:27:05 +00002115 MCConstantExpr::Create(0 - Val, getContext()), S, E));
Vladimir Medic2b953d02013-10-01 09:48:56 +00002116 return MatchOperand_Success;
2117}
2118
Matheus Almeida779c5932013-11-18 12:32:49 +00002119MipsAsmParser::OperandMatchResultTy
2120MipsAsmParser::parseLSAImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
2121 switch (getLexer().getKind()) {
2122 default:
2123 return MatchOperand_NoMatch;
2124 case AsmToken::LParen:
2125 case AsmToken::Plus:
2126 case AsmToken::Minus:
2127 case AsmToken::Integer:
2128 break;
2129 }
2130
2131 const MCExpr *Expr;
2132 SMLoc S = Parser.getTok().getLoc();
2133
2134 if (getParser().parseExpression(Expr))
2135 return MatchOperand_ParseFail;
2136
2137 int64_t Val;
2138 if (!Expr->EvaluateAsAbsolute(Val)) {
2139 Error(S, "expected immediate value");
2140 return MatchOperand_ParseFail;
2141 }
2142
2143 // The LSA instruction allows a 2-bit unsigned immediate. For this reason
2144 // and because the CPU always adds one to the immediate field, the allowed
2145 // range becomes 1..4. We'll only check the range here and will deal
2146 // with the addition/subtraction when actually decoding/encoding
2147 // the instruction.
2148 if (Val < 1 || Val > 4) {
2149 Error(S, "immediate not in range (1..4)");
2150 return MatchOperand_ParseFail;
2151 }
2152
Jack Carter3b2c96e2014-01-22 23:31:38 +00002153 Operands.push_back(
2154 MipsOperand::CreateLSAImm(Expr, S, Parser.getTok().getLoc()));
Matheus Almeida779c5932013-11-18 12:32:49 +00002155 return MatchOperand_Success;
2156}
2157
Jack Carterdc1e35d2012-09-06 20:00:02 +00002158MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
2159
Vladimir Medic4c299852013-11-06 11:27:05 +00002160 MCSymbolRefExpr::VariantKind VK =
2161 StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
2162 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
2163 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
2164 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
2165 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
2166 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
2167 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
2168 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
2169 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
2170 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
2171 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
2172 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
2173 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
2174 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
2175 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
2176 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
2177 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
2178 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
2179 .Default(MCSymbolRefExpr::VK_None);
Jack Carterdc1e35d2012-09-06 20:00:02 +00002180
2181 return VK;
2182}
Jack Cartera63b16a2012-09-07 00:23:42 +00002183
Vladimir Medic4c299852013-11-06 11:27:05 +00002184bool MipsAsmParser::ParseInstruction(
2185 ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
2186 SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
Vladimir Medic74593e62013-07-17 15:00:42 +00002187 // Check if we have valid mnemonic
Craig Topper690d8ea2013-07-24 07:33:14 +00002188 if (!mnemonicIsValid(Name, 0)) {
Vladimir Medic74593e62013-07-17 15:00:42 +00002189 Parser.eatToEndOfStatement();
2190 return Error(NameLoc, "Unknown instruction");
2191 }
Vladimir Medic64828a12013-07-16 10:07:14 +00002192 // First operand in MCInst is instruction mnemonic.
2193 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
Jack Carterb4dbc172012-09-05 23:34:03 +00002194
2195 // Read the remaining operands.
2196 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2197 // Read the first operand.
Vladimir Medic64828a12013-07-16 10:07:14 +00002198 if (ParseOperand(Operands, Name)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00002199 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002200 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002201 return Error(Loc, "unexpected token in argument list");
2202 }
2203
Jack Carterd0bd6422013-04-18 00:41:53 +00002204 while (getLexer().is(AsmToken::Comma)) {
2205 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00002206 // Parse and remember the operand.
2207 if (ParseOperand(Operands, Name)) {
2208 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002209 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002210 return Error(Loc, "unexpected token in argument list");
2211 }
2212 }
2213 }
Jack Carterb4dbc172012-09-05 23:34:03 +00002214 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2215 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002216 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00002217 return Error(Loc, "unexpected token in argument list");
2218 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002219 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00002220 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00002221}
2222
Jack Carter0b744b32012-10-04 02:29:46 +00002223bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002224 SMLoc Loc = getLexer().getLoc();
2225 Parser.eatToEndOfStatement();
2226 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00002227}
2228
2229bool MipsAsmParser::parseSetNoAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002230 // Line should look like: ".set noat".
2231 // set at reg to 0.
Jack Carter99d2afe2012-10-05 23:55:28 +00002232 Options.setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00002233 // eat noat
2234 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002235 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002236 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2237 reportParseError("unexpected token in statement");
2238 return false;
2239 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002240 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002241 return false;
2242}
Jack Carterd0bd6422013-04-18 00:41:53 +00002243
Jack Carter0b744b32012-10-04 02:29:46 +00002244bool MipsAsmParser::parseSetAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002245 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00002246 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00002247 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00002248 getParser().Lex();
2249 if (getLexer().is(AsmToken::EndOfStatement)) {
Jack Carter99d2afe2012-10-05 23:55:28 +00002250 Options.setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00002251 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002252 return false;
2253 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00002254 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00002255 if (getLexer().isNot(AsmToken::Dollar)) {
2256 reportParseError("unexpected token in statement");
2257 return false;
2258 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002259 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00002260 const AsmToken &Reg = Parser.getTok();
2261 if (Reg.is(AsmToken::Identifier)) {
2262 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
2263 } else if (Reg.is(AsmToken::Integer)) {
2264 AtRegNo = Reg.getIntVal();
2265 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00002266 reportParseError("unexpected token in statement");
2267 return false;
2268 }
Jack Carter1ac53222013-02-20 23:11:17 +00002269
Jack Carterd0bd6422013-04-18 00:41:53 +00002270 if (AtRegNo < 1 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00002271 reportParseError("unexpected token in statement");
2272 return false;
2273 }
2274
2275 if (!Options.setATReg(AtRegNo)) {
Jack Carter0b744b32012-10-04 02:29:46 +00002276 reportParseError("unexpected token in statement");
2277 return false;
2278 }
Jack Carterd0bd6422013-04-18 00:41:53 +00002279 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00002280
2281 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2282 reportParseError("unexpected token in statement");
2283 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002284 }
2285 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002286 return false;
2287 } else {
2288 reportParseError("unexpected token in statement");
2289 return false;
2290 }
2291}
2292
2293bool MipsAsmParser::parseSetReorderDirective() {
2294 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002295 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002296 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2297 reportParseError("unexpected token in statement");
2298 return false;
2299 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002300 Options.setReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002301 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002302 return false;
2303}
2304
2305bool MipsAsmParser::parseSetNoReorderDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00002306 Parser.Lex();
2307 // If this is not the end of the statement, report an error.
2308 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2309 reportParseError("unexpected token in statement");
Jack Carter0b744b32012-10-04 02:29:46 +00002310 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00002311 }
2312 Options.setNoreorder();
Rafael Espindolacb1953f2014-01-26 06:57:13 +00002313 getTargetStreamer().emitDirectiveSetNoReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00002314 Parser.Lex(); // Consume the EndOfStatement.
2315 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002316}
2317
2318bool MipsAsmParser::parseSetMacroDirective() {
2319 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002320 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002321 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2322 reportParseError("unexpected token in statement");
2323 return false;
2324 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002325 Options.setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002326 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002327 return false;
2328}
2329
2330bool MipsAsmParser::parseSetNoMacroDirective() {
2331 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00002332 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00002333 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2334 reportParseError("`noreorder' must be set before `nomacro'");
2335 return false;
2336 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002337 if (Options.isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00002338 reportParseError("`noreorder' must be set before `nomacro'");
2339 return false;
2340 }
Jack Carter99d2afe2012-10-05 23:55:28 +00002341 Options.setNomacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00002342 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00002343 return false;
2344}
Jack Carterd76b2372013-03-21 21:44:16 +00002345
Jack Carter39536722014-01-22 23:08:42 +00002346bool MipsAsmParser::parseSetMips16Directive() {
2347 Parser.Lex();
2348 // If this is not the end of the statement, report an error.
2349 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2350 reportParseError("unexpected token in statement");
2351 return false;
2352 }
Rafael Espindolae7583752014-01-24 16:13:20 +00002353 getTargetStreamer().emitDirectiveSetMips16();
Jack Carter39536722014-01-22 23:08:42 +00002354 Parser.Lex(); // Consume the EndOfStatement.
2355 return false;
2356}
2357
2358bool MipsAsmParser::parseSetNoMips16Directive() {
2359 Parser.Lex();
2360 // If this is not the end of the statement, report an error.
2361 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2362 reportParseError("unexpected token in statement");
2363 return false;
2364 }
2365 // For now do nothing.
2366 Parser.Lex(); // Consume the EndOfStatement.
2367 return false;
2368}
2369
Jack Carterd76b2372013-03-21 21:44:16 +00002370bool MipsAsmParser::parseSetAssignment() {
2371 StringRef Name;
2372 const MCExpr *Value;
2373
2374 if (Parser.parseIdentifier(Name))
2375 reportParseError("expected identifier after .set");
2376
2377 if (getLexer().isNot(AsmToken::Comma))
2378 return reportParseError("unexpected token in .set directive");
Jack Carterb5cf5902013-04-17 00:18:04 +00002379 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00002380
Jack Carter3b2c96e2014-01-22 23:31:38 +00002381 if (Parser.parseExpression(Value))
Jack Carter02593002013-05-28 22:21:05 +00002382 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00002383
Jack Carterd0bd6422013-04-18 00:41:53 +00002384 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00002385 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00002386 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00002387 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00002388 Sym = getContext().GetOrCreateSymbol(Name);
2389 Sym->setVariableValue(Value);
2390
2391 return false;
2392}
Jack Carterd0bd6422013-04-18 00:41:53 +00002393
Jack Carter0b744b32012-10-04 02:29:46 +00002394bool MipsAsmParser::parseDirectiveSet() {
2395
Jack Carterd0bd6422013-04-18 00:41:53 +00002396 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00002397 const AsmToken &Tok = Parser.getTok();
2398
2399 if (Tok.getString() == "noat") {
2400 return parseSetNoAtDirective();
2401 } else if (Tok.getString() == "at") {
2402 return parseSetAtDirective();
2403 } else if (Tok.getString() == "reorder") {
2404 return parseSetReorderDirective();
2405 } else if (Tok.getString() == "noreorder") {
2406 return parseSetNoReorderDirective();
2407 } else if (Tok.getString() == "macro") {
2408 return parseSetMacroDirective();
2409 } else if (Tok.getString() == "nomacro") {
2410 return parseSetNoMacroDirective();
Jack Carter39536722014-01-22 23:08:42 +00002411 } else if (Tok.getString() == "mips16") {
2412 return parseSetMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00002413 } else if (Tok.getString() == "nomips16") {
Jack Carter39536722014-01-22 23:08:42 +00002414 return parseSetNoMips16Directive();
Jack Carter0b744b32012-10-04 02:29:46 +00002415 } else if (Tok.getString() == "nomicromips") {
Rafael Espindola6d5f7ce2014-01-14 04:25:13 +00002416 getTargetStreamer().emitDirectiveSetNoMicroMips();
2417 Parser.eatToEndOfStatement();
2418 return false;
2419 } else if (Tok.getString() == "micromips") {
2420 getTargetStreamer().emitDirectiveSetMicroMips();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002421 Parser.eatToEndOfStatement();
Jack Carter0b744b32012-10-04 02:29:46 +00002422 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00002423 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00002424 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00002425 parseSetAssignment();
2426 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00002427 }
Jack Carter07c818d2013-01-25 01:31:34 +00002428
Jack Carter0b744b32012-10-04 02:29:46 +00002429 return true;
2430}
2431
Jack Carter07c818d2013-01-25 01:31:34 +00002432/// parseDirectiveWord
2433/// ::= .word [ expression (, expression)* ]
2434bool MipsAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
2435 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2436 for (;;) {
2437 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002438 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00002439 return true;
2440
2441 getParser().getStreamer().EmitValue(Value, Size);
2442
2443 if (getLexer().is(AsmToken::EndOfStatement))
2444 break;
2445
2446 // FIXME: Improve diagnostic.
2447 if (getLexer().isNot(AsmToken::Comma))
2448 return Error(L, "unexpected token in directive");
2449 Parser.Lex();
2450 }
2451 }
2452
2453 Parser.Lex();
2454 return false;
2455}
2456
Vladimir Medic4c299852013-11-06 11:27:05 +00002457/// parseDirectiveGpWord
2458/// ::= .gpword local_sym
2459bool MipsAsmParser::parseDirectiveGpWord() {
2460 const MCExpr *Value;
2461 // EmitGPRel32Value requires an expression, so we are using base class
2462 // method to evaluate the expression.
2463 if (getParser().parseExpression(Value))
2464 return true;
Vladimir Medic4c299852013-11-06 11:27:05 +00002465 getParser().getStreamer().EmitGPRel32Value(Value);
Vladimir Medic4c299852013-11-06 11:27:05 +00002466
Vladimir Medice10c1122013-11-13 13:18:04 +00002467 if (getLexer().isNot(AsmToken::EndOfStatement))
Vladimir Medic4c299852013-11-06 11:27:05 +00002468 return Error(getLexer().getLoc(), "unexpected token in directive");
Vladimir Medice10c1122013-11-13 13:18:04 +00002469 Parser.Lex(); // Eat EndOfStatement token.
Vladimir Medic4c299852013-11-06 11:27:05 +00002470 return false;
2471}
2472
Jack Carter0cd3c192014-01-06 23:27:31 +00002473bool MipsAsmParser::parseDirectiveOption() {
2474 // Get the option token.
2475 AsmToken Tok = Parser.getTok();
2476 // At the moment only identifiers are supported.
2477 if (Tok.isNot(AsmToken::Identifier)) {
2478 Error(Parser.getTok().getLoc(), "unexpected token in .option directive");
2479 Parser.eatToEndOfStatement();
2480 return false;
2481 }
2482
2483 StringRef Option = Tok.getIdentifier();
2484
2485 if (Option == "pic0") {
2486 getTargetStreamer().emitDirectiveOptionPic0();
2487 Parser.Lex();
2488 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2489 Error(Parser.getTok().getLoc(),
2490 "unexpected token in .option pic0 directive");
2491 Parser.eatToEndOfStatement();
2492 }
2493 return false;
2494 }
2495
2496 // Unknown option.
2497 Warning(Parser.getTok().getLoc(), "unknown option in .option directive");
2498 Parser.eatToEndOfStatement();
2499 return false;
2500}
2501
Jack Carter0b744b32012-10-04 02:29:46 +00002502bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carter07c818d2013-01-25 01:31:34 +00002503 StringRef IDVal = DirectiveID.getString();
2504
Jack Carterd0bd6422013-04-18 00:41:53 +00002505 if (IDVal == ".ent") {
2506 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00002507 Parser.Lex();
2508 return false;
2509 }
2510
Jack Carter07c818d2013-01-25 01:31:34 +00002511 if (IDVal == ".end") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002512 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00002513 Parser.Lex();
2514 return false;
2515 }
2516
Jack Carter07c818d2013-01-25 01:31:34 +00002517 if (IDVal == ".frame") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002518 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002519 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002520 return false;
2521 }
2522
Jack Carter07c818d2013-01-25 01:31:34 +00002523 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00002524 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00002525 }
2526
Jack Carter07c818d2013-01-25 01:31:34 +00002527 if (IDVal == ".fmask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002528 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002529 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002530 return false;
2531 }
2532
Jack Carter07c818d2013-01-25 01:31:34 +00002533 if (IDVal == ".mask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002534 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00002535 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00002536 return false;
2537 }
2538
Jack Carter07c818d2013-01-25 01:31:34 +00002539 if (IDVal == ".gpword") {
Jack Carterd0bd6422013-04-18 00:41:53 +00002540 // Ignore this directive for now.
Vladimir Medic4c299852013-11-06 11:27:05 +00002541 parseDirectiveGpWord();
Jack Carterbe332172012-09-07 00:48:02 +00002542 return false;
2543 }
2544
Jack Carter07c818d2013-01-25 01:31:34 +00002545 if (IDVal == ".word") {
2546 parseDirectiveWord(4, DirectiveID.getLoc());
2547 return false;
2548 }
2549
Jack Carter0cd3c192014-01-06 23:27:31 +00002550 if (IDVal == ".option")
2551 return parseDirectiveOption();
2552
2553 if (IDVal == ".abicalls") {
2554 getTargetStreamer().emitDirectiveAbiCalls();
2555 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
2556 Error(Parser.getTok().getLoc(), "unexpected token in directive");
2557 // Clear line
2558 Parser.eatToEndOfStatement();
2559 }
2560 return false;
2561 }
2562
Rafael Espindola870c4e92012-01-11 03:56:41 +00002563 return true;
2564}
2565
Rafael Espindola870c4e92012-01-11 03:56:41 +00002566extern "C" void LLVMInitializeMipsAsmParser() {
2567 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
2568 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
2569 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
2570 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
2571}
Jack Carterb4dbc172012-09-05 23:34:03 +00002572
2573#define GET_REGISTER_MATCHER
2574#define GET_MATCHER_IMPLEMENTATION
2575#include "MipsGenAsmMatcher.inc"