blob: 30149d30ac03dda703e739a6b874a327be12ed0c [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"
12#include "llvm/ADT/StringSwitch.h"
13#include "llvm/MC/MCContext.h"
14#include "llvm/MC/MCExpr.h"
15#include "llvm/MC/MCInst.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000016#include "llvm/MC/MCParser/MCAsmLexer.h"
17#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000018#include "llvm/MC/MCStreamer.h"
19#include "llvm/MC/MCSubtargetInfo.h"
20#include "llvm/MC/MCSymbol.h"
Akira Hatanaka7605630c2012-08-17 20:16:42 +000021#include "llvm/MC/MCTargetAsmParser.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000022#include "llvm/Support/TargetRegistry.h"
Jack Carter02593002013-05-28 22:21:05 +000023#include "llvm/ADT/APInt.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000024
25using namespace llvm;
26
27namespace {
Jack Carter0b744b32012-10-04 02:29:46 +000028class MipsAssemblerOptions {
29public:
30 MipsAssemblerOptions():
31 aTReg(1), reorder(true), macro(true) {
32 }
Jack Carterb4dbc172012-09-05 23:34:03 +000033
Jack Carter0b744b32012-10-04 02:29:46 +000034 unsigned getATRegNum() {return aTReg;}
35 bool setATReg(unsigned Reg);
36
37 bool isReorder() {return reorder;}
38 void setReorder() {reorder = true;}
39 void setNoreorder() {reorder = false;}
40
41 bool isMacro() {return macro;}
42 void setMacro() {macro = true;}
43 void setNomacro() {macro = false;}
44
45private:
46 unsigned aTReg;
47 bool reorder;
48 bool macro;
49};
50}
51
52namespace {
Rafael Espindola870c4e92012-01-11 03:56:41 +000053class MipsAsmParser : public MCTargetAsmParser {
Akira Hatanaka7605630c2012-08-17 20:16:42 +000054
Jack Cartera63b16a2012-09-07 00:23:42 +000055 enum FpFormatTy {
56 FP_FORMAT_NONE = -1,
57 FP_FORMAT_S,
58 FP_FORMAT_D,
59 FP_FORMAT_L,
60 FP_FORMAT_W
61 } FpFormat;
62
Jack Carterb4dbc172012-09-05 23:34:03 +000063 MCSubtargetInfo &STI;
64 MCAsmParser &Parser;
Jack Carter99d2afe2012-10-05 23:55:28 +000065 MipsAssemblerOptions Options;
Jack Carter0b744b32012-10-04 02:29:46 +000066
Akira Hatanaka7605630c2012-08-17 20:16:42 +000067#define GET_ASSEMBLER_HEADER
68#include "MipsGenAsmMatcher.inc"
69
Chad Rosier49963552012-10-13 00:26:04 +000070 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
Rafael Espindola870c4e92012-01-11 03:56:41 +000071 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Chad Rosier49963552012-10-13 00:26:04 +000072 MCStreamer &Out, unsigned &ErrorInfo,
73 bool MatchingInlineAsm);
Rafael Espindola870c4e92012-01-11 03:56:41 +000074
75 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
76
Chad Rosierf0e87202012-10-25 20:41:34 +000077 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
78 SMLoc NameLoc,
Akira Hatanaka7605630c2012-08-17 20:16:42 +000079 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Rafael Espindola870c4e92012-01-11 03:56:41 +000080
Jack Cartera63b16a2012-09-07 00:23:42 +000081 bool parseMathOperation(StringRef Name, SMLoc NameLoc,
82 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
83
Rafael Espindola870c4e92012-01-11 03:56:41 +000084 bool ParseDirective(AsmToken DirectiveID);
85
Jack Carterb4dbc172012-09-05 23:34:03 +000086 MipsAsmParser::OperandMatchResultTy
Vladimir Medic8cd17102013-06-20 11:21:49 +000087 parseRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
88 int RegKind);
89 MipsAsmParser::OperandMatchResultTy
Jack Carter873c7242013-01-12 01:03:14 +000090 parseMemOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
91
92 MipsAsmParser::OperandMatchResultTy
93 parseCPURegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
94
95 MipsAsmParser::OperandMatchResultTy
96 parseCPU64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
97
98 MipsAsmParser::OperandMatchResultTy
99 parseHWRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
100
101 MipsAsmParser::OperandMatchResultTy
102 parseHW64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
103
104 MipsAsmParser::OperandMatchResultTy
105 parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Chad Rosier391d29972012-09-03 18:47:45 +0000106
Jack Carterd76b2372013-03-21 21:44:16 +0000107 bool searchSymbolAlias(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Vladimir Medic8cd17102013-06-20 11:21:49 +0000108 unsigned RegKind);
Jack Carterd76b2372013-03-21 21:44:16 +0000109
Jack Carterb4dbc172012-09-05 23:34:03 +0000110 bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &,
111 StringRef Mnemonic);
112
Jack Carter873c7242013-01-12 01:03:14 +0000113 int tryParseRegister(bool is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000114
115 bool tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Jack Carter873c7242013-01-12 01:03:14 +0000116 bool is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000117
Jack Carter30a59822012-10-04 04:03:53 +0000118 bool needsExpansion(MCInst &Inst);
119
120 void expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000121 SmallVectorImpl<MCInst> &Instructions);
Jack Carter30a59822012-10-04 04:03:53 +0000122 void expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carter92995f12012-10-06 00:53:28 +0000123 SmallVectorImpl<MCInst> &Instructions);
Jack Carter543fdf82012-10-09 23:29:45 +0000124 void expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
125 SmallVectorImpl<MCInst> &Instructions);
126 void expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
127 SmallVectorImpl<MCInst> &Instructions);
Jack Carter9e65aa32013-03-22 00:05:30 +0000128 void expandMemInst(MCInst &Inst, SMLoc IDLoc,
129 SmallVectorImpl<MCInst> &Instructions,
130 bool isLoad,bool isImmOpnd);
Jack Carter0b744b32012-10-04 02:29:46 +0000131 bool reportParseError(StringRef ErrorMsg);
132
Jack Carterb5cf5902013-04-17 00:18:04 +0000133 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
Jack Carter873c7242013-01-12 01:03:14 +0000134 bool parseRelocOperand(const MCExpr *&Res);
Jack Carter0b744b32012-10-04 02:29:46 +0000135
Jack Carterb5cf5902013-04-17 00:18:04 +0000136 const MCExpr* evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
137
138 bool isEvaluated(const MCExpr *Expr);
Jack Carter0b744b32012-10-04 02:29:46 +0000139 bool parseDirectiveSet();
140
141 bool parseSetAtDirective();
142 bool parseSetNoAtDirective();
143 bool parseSetMacroDirective();
144 bool parseSetNoMacroDirective();
145 bool parseSetReorderDirective();
146 bool parseSetNoReorderDirective();
147
Jack Carterd76b2372013-03-21 21:44:16 +0000148 bool parseSetAssignment();
149
Jack Carter07c818d2013-01-25 01:31:34 +0000150 bool parseDirectiveWord(unsigned Size, SMLoc L);
151
Jack Carterdc1e35d2012-09-06 20:00:02 +0000152 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +0000153
Jack Carterb4dbc172012-09-05 23:34:03 +0000154 bool isMips64() const {
155 return (STI.getFeatureBits() & Mips::FeatureMips64) != 0;
156 }
157
Jack Cartera63b16a2012-09-07 00:23:42 +0000158 bool isFP64() const {
159 return (STI.getFeatureBits() & Mips::FeatureFP64Bit) != 0;
160 }
161
Jack Carter873c7242013-01-12 01:03:14 +0000162 int matchRegisterName(StringRef Symbol, bool is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000163
Jack Carter1ac53222013-02-20 23:11:17 +0000164 int matchCPURegisterName(StringRef Symbol);
165
Jack Carter873c7242013-01-12 01:03:14 +0000166 int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
Jack Carterb4dbc172012-09-05 23:34:03 +0000167
Vladimir Medic8cd17102013-06-20 11:21:49 +0000168 int matchFPURegisterName(StringRef Name, FpFormatTy Format);
169
Jack Cartera63b16a2012-09-07 00:23:42 +0000170 void setFpFormat(FpFormatTy Format) {
171 FpFormat = Format;
172 }
173
174 void setDefaultFpFormat();
175
176 void setFpFormat(StringRef Format);
177
178 FpFormatTy getFpFormat() {return FpFormat;}
179
180 bool requestsDoubleOperand(StringRef Mnemonic);
181
Jack Carterd0bd6422013-04-18 00:41:53 +0000182 unsigned getReg(int RC, int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +0000183
Jack Carter1ac53222013-02-20 23:11:17 +0000184 int getATReg();
Jack Carter9e65aa32013-03-22 00:05:30 +0000185
186 bool processInstruction(MCInst &Inst, SMLoc IDLoc,
187 SmallVectorImpl<MCInst> &Instructions);
Rafael Espindola870c4e92012-01-11 03:56:41 +0000188public:
189 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser)
Jack Carterb4dbc172012-09-05 23:34:03 +0000190 : MCTargetAsmParser(), STI(sti), Parser(parser) {
191 // Initialize the set of available features.
192 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Rafael Espindola870c4e92012-01-11 03:56:41 +0000193 }
194
Jack Carterb4dbc172012-09-05 23:34:03 +0000195 MCAsmParser &getParser() const { return Parser; }
196 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
197
Rafael Espindola870c4e92012-01-11 03:56:41 +0000198};
199}
200
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000201namespace {
202
203/// MipsOperand - Instances of this class represent a parsed Mips machine
204/// instruction.
205class MipsOperand : public MCParsedAsmOperand {
Jack Carterb4dbc172012-09-05 23:34:03 +0000206
Jack Carter873c7242013-01-12 01:03:14 +0000207public:
208 enum RegisterKind {
209 Kind_None,
210 Kind_CPURegs,
211 Kind_CPU64Regs,
212 Kind_HWRegs,
213 Kind_HW64Regs,
214 Kind_FGR32Regs,
215 Kind_FGR64Regs,
Jack Carter1ac53222013-02-20 23:11:17 +0000216 Kind_AFGR64Regs,
Jack Carter873c7242013-01-12 01:03:14 +0000217 Kind_CCRRegs
218 };
219
220private:
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000221 enum KindTy {
222 k_CondCode,
223 k_CoprocNum,
224 k_Immediate,
225 k_Memory,
226 k_PostIndexRegister,
227 k_Register,
228 k_Token
229 } Kind;
230
231 MipsOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
Jack Carterb4dbc172012-09-05 23:34:03 +0000232
Eric Christopher8996c5d2013-03-15 00:42:55 +0000233 struct Token {
234 const char *Data;
235 unsigned Length;
236 };
237
238 struct RegOp {
239 unsigned RegNum;
240 RegisterKind Kind;
241 };
242
243 struct ImmOp {
244 const MCExpr *Val;
245 };
246
247 struct MemOp {
248 unsigned Base;
249 const MCExpr *Off;
250 };
251
Jack Carterb4dbc172012-09-05 23:34:03 +0000252 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000253 struct Token Tok;
254 struct RegOp Reg;
255 struct ImmOp Imm;
256 struct MemOp Mem;
Jack Carterb4dbc172012-09-05 23:34:03 +0000257 };
258
259 SMLoc StartLoc, EndLoc;
260
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000261public:
262 void addRegOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000263 assert(N == 1 && "Invalid number of operands!");
264 Inst.addOperand(MCOperand::CreateReg(getReg()));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000265 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000266
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000267 void addExpr(MCInst &Inst, const MCExpr *Expr) const{
Jack Carterb4dbc172012-09-05 23:34:03 +0000268 // Add as immediate when possible. Null MCExpr = 0.
269 if (Expr == 0)
270 Inst.addOperand(MCOperand::CreateImm(0));
271 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
272 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
273 else
274 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000275 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000276
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000277 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000278 assert(N == 1 && "Invalid number of operands!");
279 const MCExpr *Expr = getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000280 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000281 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000282
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000283 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000284 assert(N == 2 && "Invalid number of operands!");
285
286 Inst.addOperand(MCOperand::CreateReg(getMemBase()));
287
288 const MCExpr *Expr = getMemOff();
Jack Carterd0bd6422013-04-18 00:41:53 +0000289 addExpr(Inst, Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000290 }
291
292 bool isReg() const { return Kind == k_Register; }
293 bool isImm() const { return Kind == k_Immediate; }
294 bool isToken() const { return Kind == k_Token; }
295 bool isMem() const { return Kind == k_Memory; }
296
297 StringRef getToken() const {
298 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000299 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000300 }
301
302 unsigned getReg() const {
303 assert((Kind == k_Register) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000304 return Reg.RegNum;
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000305 }
306
Jack Carter873c7242013-01-12 01:03:14 +0000307 void setRegKind(RegisterKind RegKind) {
308 assert((Kind == k_Register) && "Invalid access!");
309 Reg.Kind = RegKind;
310 }
311
Jack Carterb4dbc172012-09-05 23:34:03 +0000312 const MCExpr *getImm() const {
313 assert((Kind == k_Immediate) && "Invalid access!");
314 return Imm.Val;
315 }
316
Jack Carterdc1e35d2012-09-06 20:00:02 +0000317 unsigned getMemBase() const {
318 assert((Kind == k_Memory) && "Invalid access!");
319 return Mem.Base;
320 }
321
322 const MCExpr *getMemOff() const {
323 assert((Kind == k_Memory) && "Invalid access!");
324 return Mem.Off;
325 }
326
Jack Carterb4dbc172012-09-05 23:34:03 +0000327 static MipsOperand *CreateToken(StringRef Str, SMLoc S) {
328 MipsOperand *Op = new MipsOperand(k_Token);
329 Op->Tok.Data = Str.data();
330 Op->Tok.Length = Str.size();
331 Op->StartLoc = S;
332 Op->EndLoc = S;
333 return Op;
334 }
335
336 static MipsOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
337 MipsOperand *Op = new MipsOperand(k_Register);
338 Op->Reg.RegNum = RegNum;
339 Op->StartLoc = S;
340 Op->EndLoc = E;
341 return Op;
342 }
343
344 static MipsOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
345 MipsOperand *Op = new MipsOperand(k_Immediate);
346 Op->Imm.Val = Val;
347 Op->StartLoc = S;
348 Op->EndLoc = E;
349 return Op;
350 }
351
Jack Carterdc1e35d2012-09-06 20:00:02 +0000352 static MipsOperand *CreateMem(unsigned Base, const MCExpr *Off,
353 SMLoc S, SMLoc E) {
354 MipsOperand *Op = new MipsOperand(k_Memory);
355 Op->Mem.Base = Base;
356 Op->Mem.Off = Off;
357 Op->StartLoc = S;
358 Op->EndLoc = E;
359 return Op;
360 }
361
Jack Carter873c7242013-01-12 01:03:14 +0000362 bool isCPURegsAsm() const {
NAKAMURA Takumi956c1232013-01-12 15:19:10 +0000363 return Kind == k_Register && Reg.Kind == Kind_CPURegs;
Jack Carter873c7242013-01-12 01:03:14 +0000364 }
Vladimir Medicc6960592013-06-19 10:14:36 +0000365 void addRegAsmOperands(MCInst &Inst, unsigned N) const {
Jack Carter873c7242013-01-12 01:03:14 +0000366 Inst.addOperand(MCOperand::CreateReg(Reg.RegNum));
367 }
368
369 bool isCPU64RegsAsm() const {
NAKAMURA Takumi956c1232013-01-12 15:19:10 +0000370 return Kind == k_Register && Reg.Kind == Kind_CPU64Regs;
Jack Carter873c7242013-01-12 01:03:14 +0000371 }
Jack Carter873c7242013-01-12 01:03:14 +0000372
373 bool isHWRegsAsm() const {
374 assert((Kind == k_Register) && "Invalid access!");
375 return Reg.Kind == Kind_HWRegs;
376 }
Jack Carter873c7242013-01-12 01:03:14 +0000377
378 bool isHW64RegsAsm() const {
379 assert((Kind == k_Register) && "Invalid access!");
380 return Reg.Kind == Kind_HW64Regs;
381 }
Jack Carter873c7242013-01-12 01:03:14 +0000382
383 bool isCCRAsm() const {
384 assert((Kind == k_Register) && "Invalid access!");
385 return Reg.Kind == Kind_CCRRegs;
386 }
387
Jack Carterb4dbc172012-09-05 23:34:03 +0000388 /// getStartLoc - Get the location of the first token of this operand.
Jack Carterd0bd6422013-04-18 00:41:53 +0000389 SMLoc getStartLoc() const {
390 return StartLoc;
391 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000392 /// getEndLoc - Get the location of the last token of this operand.
Jack Carterd0bd6422013-04-18 00:41:53 +0000393 SMLoc getEndLoc() const {
394 return EndLoc;
395 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000396
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000397 virtual void print(raw_ostream &OS) const {
398 llvm_unreachable("unimplemented!");
399 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000400}; // class MipsOperand
401} // namespace
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000402
Jack Carter9e65aa32013-03-22 00:05:30 +0000403namespace llvm {
404extern const MCInstrDesc MipsInsts[];
405}
406static const MCInstrDesc &getInstDesc(unsigned Opcode) {
407 return MipsInsts[Opcode];
408}
409
410bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterb5cf5902013-04-17 00:18:04 +0000411 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000412 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
413 Inst.setLoc(IDLoc);
Jack Carterc15c1d22013-04-25 23:31:35 +0000414 if (MCID.hasDelaySlot() && Options.isReorder()) {
415 // If this instruction has a delay slot and .set reorder is active,
416 // emit a NOP after it.
417 Instructions.push_back(Inst);
418 MCInst NopInst;
419 NopInst.setOpcode(Mips::SLL);
420 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
421 NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
422 NopInst.addOperand(MCOperand::CreateImm(0));
423 Instructions.push_back(NopInst);
424 return false;
425 }
426
Jack Carter9e65aa32013-03-22 00:05:30 +0000427 if (MCID.mayLoad() || MCID.mayStore()) {
428 // Check the offset of memory operand, if it is a symbol
Jack Carterd0bd6422013-04-18 00:41:53 +0000429 // reference or immediate we may have to expand instructions.
430 for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000431 const MCOperandInfo &OpInfo = MCID.OpInfo[i];
Jack Carterd0bd6422013-04-18 00:41:53 +0000432 if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY)
433 || (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000434 MCOperand &Op = Inst.getOperand(i);
435 if (Op.isImm()) {
436 int MemOffset = Op.getImm();
437 if (MemOffset < -32768 || MemOffset > 32767) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000438 // Offset can't exceed 16bit value.
439 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
Jack Carter9e65aa32013-03-22 00:05:30 +0000440 return false;
441 }
442 } else if (Op.isExpr()) {
443 const MCExpr *Expr = Op.getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +0000444 if (Expr->getKind() == MCExpr::SymbolRef) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000445 const MCSymbolRefExpr *SR =
Jack Carterb5cf5902013-04-17 00:18:04 +0000446 static_cast<const MCSymbolRefExpr*>(Expr);
Jack Carter9e65aa32013-03-22 00:05:30 +0000447 if (SR->getKind() == MCSymbolRefExpr::VK_None) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000448 // Expand symbol.
449 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carter9e65aa32013-03-22 00:05:30 +0000450 return false;
451 }
Jack Carterb5cf5902013-04-17 00:18:04 +0000452 } else if (!isEvaluated(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000453 expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
Jack Carterb5cf5902013-04-17 00:18:04 +0000454 return false;
Jack Carter9e65aa32013-03-22 00:05:30 +0000455 }
456 }
457 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000458 } // for
459 } // if load/store
Jack Carter9e65aa32013-03-22 00:05:30 +0000460
461 if (needsExpansion(Inst))
462 expandInstruction(Inst, IDLoc, Instructions);
463 else
464 Instructions.push_back(Inst);
465
466 return false;
467}
468
Jack Carter30a59822012-10-04 04:03:53 +0000469bool MipsAsmParser::needsExpansion(MCInst &Inst) {
470
Jack Carterd0bd6422013-04-18 00:41:53 +0000471 switch (Inst.getOpcode()) {
472 case Mips::LoadImm32Reg:
473 case Mips::LoadAddr32Imm:
474 case Mips::LoadAddr32Reg:
475 return true;
476 default:
477 return false;
Jack Carter30a59822012-10-04 04:03:53 +0000478 }
479}
Jack Carter92995f12012-10-06 00:53:28 +0000480
Jack Carter30a59822012-10-04 04:03:53 +0000481void MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000482 SmallVectorImpl<MCInst> &Instructions) {
483 switch (Inst.getOpcode()) {
484 case Mips::LoadImm32Reg:
485 return expandLoadImm(Inst, IDLoc, Instructions);
486 case Mips::LoadAddr32Imm:
487 return expandLoadAddressImm(Inst, IDLoc, Instructions);
488 case Mips::LoadAddr32Reg:
489 return expandLoadAddressReg(Inst, IDLoc, Instructions);
490 }
Jack Carter30a59822012-10-04 04:03:53 +0000491}
Jack Carter92995f12012-10-06 00:53:28 +0000492
Jack Carter30a59822012-10-04 04:03:53 +0000493void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000494 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter92995f12012-10-06 00:53:28 +0000495 MCInst tmpInst;
Jack Carter30a59822012-10-04 04:03:53 +0000496 const MCOperand &ImmOp = Inst.getOperand(1);
Jack Carter543fdf82012-10-09 23:29:45 +0000497 assert(ImmOp.isImm() && "expected immediate operand kind");
Jack Carter30a59822012-10-04 04:03:53 +0000498 const MCOperand &RegOp = Inst.getOperand(0);
499 assert(RegOp.isReg() && "expected register operand kind");
500
501 int ImmValue = ImmOp.getImm();
Jack Carter92995f12012-10-06 00:53:28 +0000502 tmpInst.setLoc(IDLoc);
Jack Carterd0bd6422013-04-18 00:41:53 +0000503 if (0 <= ImmValue && ImmValue <= 65535) {
504 // For 0 <= j <= 65535.
Jack Carter30a59822012-10-04 04:03:53 +0000505 // li d,j => ori d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +0000506 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +0000507 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +0000508 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +0000509 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +0000510 Instructions.push_back(tmpInst);
Jack Carterd0bd6422013-04-18 00:41:53 +0000511 } else if (ImmValue < 0 && ImmValue >= -32768) {
512 // For -32768 <= j < 0.
Jack Carter30a59822012-10-04 04:03:53 +0000513 // li d,j => addiu d,$zero,j
Jack Carter873c7242013-01-12 01:03:14 +0000514 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter92995f12012-10-06 00:53:28 +0000515 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +0000516 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter92995f12012-10-06 00:53:28 +0000517 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Jack Carter30a59822012-10-04 04:03:53 +0000518 Instructions.push_back(tmpInst);
519 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000520 // For any other value of j that is representable as a 32-bit integer.
Jack Carter30a59822012-10-04 04:03:53 +0000521 // li d,j => lui d,hi16(j)
Jack Carter543fdf82012-10-09 23:29:45 +0000522 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +0000523 tmpInst.setOpcode(Mips::LUi);
Jack Carter92995f12012-10-06 00:53:28 +0000524 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
525 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
Jack Carter30a59822012-10-04 04:03:53 +0000526 Instructions.push_back(tmpInst);
Jack Carter92995f12012-10-06 00:53:28 +0000527 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +0000528 tmpInst.setOpcode(Mips::ORi);
Jack Carter92995f12012-10-06 00:53:28 +0000529 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
530 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
531 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
532 tmpInst.setLoc(IDLoc);
Jack Carter30a59822012-10-04 04:03:53 +0000533 Instructions.push_back(tmpInst);
534 }
535}
Jack Carter92995f12012-10-06 00:53:28 +0000536
Jack Carter543fdf82012-10-09 23:29:45 +0000537void MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000538 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +0000539 MCInst tmpInst;
540 const MCOperand &ImmOp = Inst.getOperand(2);
541 assert(ImmOp.isImm() && "expected immediate operand kind");
542 const MCOperand &SrcRegOp = Inst.getOperand(1);
543 assert(SrcRegOp.isReg() && "expected register operand kind");
544 const MCOperand &DstRegOp = Inst.getOperand(0);
545 assert(DstRegOp.isReg() && "expected register operand kind");
546 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000547 if (-32768 <= ImmValue && ImmValue <= 65535) {
548 // For -32768 <= j <= 65535.
549 // la d,j(s) => addiu d,s,j
Jack Carter873c7242013-01-12 01:03:14 +0000550 tmpInst.setOpcode(Mips::ADDiu);
Jack Carter543fdf82012-10-09 23:29:45 +0000551 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
552 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
553 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
554 Instructions.push_back(tmpInst);
555 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000556 // For any other value of j that is representable as a 32-bit integer.
557 // la d,j(s) => lui d,hi16(j)
558 // ori d,d,lo16(j)
559 // addu d,d,s
Jack Carter873c7242013-01-12 01:03:14 +0000560 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +0000561 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
562 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
563 Instructions.push_back(tmpInst);
564 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +0000565 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +0000566 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
567 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
568 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
569 Instructions.push_back(tmpInst);
570 tmpInst.clear();
571 tmpInst.setOpcode(Mips::ADDu);
572 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
573 tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
574 tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
575 Instructions.push_back(tmpInst);
576 }
577}
578
579void MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000580 SmallVectorImpl<MCInst> &Instructions) {
Jack Carter543fdf82012-10-09 23:29:45 +0000581 MCInst tmpInst;
582 const MCOperand &ImmOp = Inst.getOperand(1);
583 assert(ImmOp.isImm() && "expected immediate operand kind");
584 const MCOperand &RegOp = Inst.getOperand(0);
585 assert(RegOp.isReg() && "expected register operand kind");
586 int ImmValue = ImmOp.getImm();
Jack Carterd0bd6422013-04-18 00:41:53 +0000587 if (-32768 <= ImmValue && ImmValue <= 65535) {
588 // For -32768 <= j <= 65535.
589 // la d,j => addiu d,$zero,j
Jack Carter543fdf82012-10-09 23:29:45 +0000590 tmpInst.setOpcode(Mips::ADDiu);
591 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
Jack Carterd0bd6422013-04-18 00:41:53 +0000592 tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
Jack Carter543fdf82012-10-09 23:29:45 +0000593 tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
594 Instructions.push_back(tmpInst);
595 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000596 // For any other value of j that is representable as a 32-bit integer.
597 // la d,j => lui d,hi16(j)
598 // ori d,d,lo16(j)
Jack Carter873c7242013-01-12 01:03:14 +0000599 tmpInst.setOpcode(Mips::LUi);
Jack Carter543fdf82012-10-09 23:29:45 +0000600 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
601 tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
602 Instructions.push_back(tmpInst);
603 tmpInst.clear();
Jack Carter873c7242013-01-12 01:03:14 +0000604 tmpInst.setOpcode(Mips::ORi);
Jack Carter543fdf82012-10-09 23:29:45 +0000605 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
606 tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
607 tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff));
608 Instructions.push_back(tmpInst);
609 }
610}
611
Jack Carter9e65aa32013-03-22 00:05:30 +0000612void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
Jack Carterd0bd6422013-04-18 00:41:53 +0000613 SmallVectorImpl<MCInst> &Instructions, bool isLoad, bool isImmOpnd) {
Jack Carter9e65aa32013-03-22 00:05:30 +0000614 const MCSymbolRefExpr *SR;
615 MCInst TempInst;
Jack Carterd0bd6422013-04-18 00:41:53 +0000616 unsigned ImmOffset, HiOffset, LoOffset;
Jack Carter9e65aa32013-03-22 00:05:30 +0000617 const MCExpr *ExprOffset;
618 unsigned TmpRegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +0000619 unsigned AtRegNum = getReg((isMips64()) ? Mips::CPU64RegsRegClassID
620 : Mips::CPURegsRegClassID, getATReg());
621 // 1st operand is either the source or destination register.
Jack Carter9e65aa32013-03-22 00:05:30 +0000622 assert(Inst.getOperand(0).isReg() && "expected register operand kind");
623 unsigned RegOpNum = Inst.getOperand(0).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +0000624 // 2nd operand is the base register.
Jack Carter9e65aa32013-03-22 00:05:30 +0000625 assert(Inst.getOperand(1).isReg() && "expected register operand kind");
626 unsigned BaseRegNum = Inst.getOperand(1).getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +0000627 // 3rd operand is either an immediate or expression.
Jack Carter9e65aa32013-03-22 00:05:30 +0000628 if (isImmOpnd) {
629 assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
630 ImmOffset = Inst.getOperand(2).getImm();
631 LoOffset = ImmOffset & 0x0000ffff;
632 HiOffset = (ImmOffset & 0xffff0000) >> 16;
Jack Carterd0bd6422013-04-18 00:41:53 +0000633 // If msb of LoOffset is 1(negative number) we must increment HiOffset.
Jack Carter9e65aa32013-03-22 00:05:30 +0000634 if (LoOffset & 0x8000)
635 HiOffset++;
Jack Carterd0bd6422013-04-18 00:41:53 +0000636 } else
Jack Carter9e65aa32013-03-22 00:05:30 +0000637 ExprOffset = Inst.getOperand(2).getExpr();
Jack Carterd0bd6422013-04-18 00:41:53 +0000638 // All instructions will have the same location.
Jack Carter9e65aa32013-03-22 00:05:30 +0000639 TempInst.setLoc(IDLoc);
640 // 1st instruction in expansion is LUi. For load instruction we can use
641 // the dst register as a temporary if base and dst are different,
Jack Carterd0bd6422013-04-18 00:41:53 +0000642 // but for stores we must use $at.
643 TmpRegNum = (isLoad && (BaseRegNum != RegOpNum)) ? RegOpNum : AtRegNum;
Jack Carter9e65aa32013-03-22 00:05:30 +0000644 TempInst.setOpcode(Mips::LUi);
645 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
646 if (isImmOpnd)
647 TempInst.addOperand(MCOperand::CreateImm(HiOffset));
648 else {
649 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
650 SR = static_cast<const MCSymbolRefExpr*>(ExprOffset);
Jack Carterd0bd6422013-04-18 00:41:53 +0000651 const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
652 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
653 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +0000654 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +0000655 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000656 const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
Jack Carterb5cf5902013-04-17 00:18:04 +0000657 TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +0000658 }
659 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000660 // Add the instruction to the list.
Jack Carter9e65aa32013-03-22 00:05:30 +0000661 Instructions.push_back(TempInst);
Jack Carterd0bd6422013-04-18 00:41:53 +0000662 // Prepare TempInst for next instruction.
Jack Carter9e65aa32013-03-22 00:05:30 +0000663 TempInst.clear();
Jack Carterd0bd6422013-04-18 00:41:53 +0000664 // Add temp register to base.
Jack Carter9e65aa32013-03-22 00:05:30 +0000665 TempInst.setOpcode(Mips::ADDu);
666 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
667 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
668 TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
669 Instructions.push_back(TempInst);
670 TempInst.clear();
Jack Carterb5cf5902013-04-17 00:18:04 +0000671 // And finaly, create original instruction with low part
Jack Carterd0bd6422013-04-18 00:41:53 +0000672 // of offset and new base.
Jack Carter9e65aa32013-03-22 00:05:30 +0000673 TempInst.setOpcode(Inst.getOpcode());
674 TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
675 TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
676 if (isImmOpnd)
677 TempInst.addOperand(MCOperand::CreateImm(LoOffset));
678 else {
679 if (ExprOffset->getKind() == MCExpr::SymbolRef) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000680 const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
681 SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
682 getContext());
Jack Carter9e65aa32013-03-22 00:05:30 +0000683 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carterb5cf5902013-04-17 00:18:04 +0000684 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +0000685 const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
Jack Carterb5cf5902013-04-17 00:18:04 +0000686 TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
Jack Carter9e65aa32013-03-22 00:05:30 +0000687 }
688 }
689 Instructions.push_back(TempInst);
690 TempInst.clear();
691}
692
Rafael Espindola870c4e92012-01-11 03:56:41 +0000693bool MipsAsmParser::
Chad Rosier49963552012-10-13 00:26:04 +0000694MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
Rafael Espindola870c4e92012-01-11 03:56:41 +0000695 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Chad Rosier49963552012-10-13 00:26:04 +0000696 MCStreamer &Out, unsigned &ErrorInfo,
697 bool MatchingInlineAsm) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000698 MCInst Inst;
Jack Carter9e65aa32013-03-22 00:05:30 +0000699 SmallVector<MCInst, 8> Instructions;
Chad Rosier2f480a82012-10-12 22:53:36 +0000700 unsigned MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo,
Chad Rosier49963552012-10-13 00:26:04 +0000701 MatchingInlineAsm);
Jack Carterb4dbc172012-09-05 23:34:03 +0000702
703 switch (MatchResult) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000704 default:
705 break;
Jack Carterb4dbc172012-09-05 23:34:03 +0000706 case Match_Success: {
Jack Carterd0bd6422013-04-18 00:41:53 +0000707 if (processInstruction(Inst, IDLoc, Instructions))
Jack Carter9e65aa32013-03-22 00:05:30 +0000708 return true;
Jack Carterd0bd6422013-04-18 00:41:53 +0000709 for (unsigned i = 0; i < Instructions.size(); i++)
Jack Carter9e65aa32013-03-22 00:05:30 +0000710 Out.EmitInstruction(Instructions[i]);
Jack Carterb4dbc172012-09-05 23:34:03 +0000711 return false;
712 }
713 case Match_MissingFeature:
714 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
715 return true;
716 case Match_InvalidOperand: {
717 SMLoc ErrorLoc = IDLoc;
718 if (ErrorInfo != ~0U) {
719 if (ErrorInfo >= Operands.size())
720 return Error(IDLoc, "too few operands for instruction");
721
Jack Carterd0bd6422013-04-18 00:41:53 +0000722 ErrorLoc = ((MipsOperand*) Operands[ErrorInfo])->getStartLoc();
723 if (ErrorLoc == SMLoc())
724 ErrorLoc = IDLoc;
Jack Carterb4dbc172012-09-05 23:34:03 +0000725 }
726
727 return Error(ErrorLoc, "invalid operand for instruction");
728 }
729 case Match_MnemonicFail:
730 return Error(IDLoc, "invalid instruction");
731 }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000732 return true;
733}
734
Jack Carter1ac53222013-02-20 23:11:17 +0000735int MipsAsmParser::matchCPURegisterName(StringRef Name) {
736 int CC;
737
738 if (Name == "at")
739 return getATReg();
740
741 CC = StringSwitch<unsigned>(Name)
742 .Case("zero", 0)
743 .Case("a0", 4)
744 .Case("a1", 5)
745 .Case("a2", 6)
746 .Case("a3", 7)
747 .Case("v0", 2)
748 .Case("v1", 3)
749 .Case("s0", 16)
750 .Case("s1", 17)
751 .Case("s2", 18)
752 .Case("s3", 19)
753 .Case("s4", 20)
754 .Case("s5", 21)
755 .Case("s6", 22)
756 .Case("s7", 23)
757 .Case("k0", 26)
758 .Case("k1", 27)
759 .Case("sp", 29)
760 .Case("fp", 30)
761 .Case("gp", 28)
762 .Case("ra", 31)
763 .Case("t0", 8)
764 .Case("t1", 9)
765 .Case("t2", 10)
766 .Case("t3", 11)
767 .Case("t4", 12)
768 .Case("t5", 13)
769 .Case("t6", 14)
770 .Case("t7", 15)
771 .Case("t8", 24)
772 .Case("t9", 25)
773 .Default(-1);
774
Jack Carterd0bd6422013-04-18 00:41:53 +0000775 // Although SGI documentation just cuts out t0-t3 for n32/n64,
Jack Carter1ac53222013-02-20 23:11:17 +0000776 // GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
777 // We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
Jack Carterd0bd6422013-04-18 00:41:53 +0000778 if (isMips64() && 8 <= CC && CC <= 11)
Jack Carter1ac53222013-02-20 23:11:17 +0000779 CC += 4;
780
781 if (CC == -1 && isMips64())
782 CC = StringSwitch<unsigned>(Name)
783 .Case("a4", 8)
784 .Case("a5", 9)
785 .Case("a6", 10)
786 .Case("a7", 11)
787 .Case("kt0", 26)
788 .Case("kt1", 27)
789 .Case("s8", 30)
790 .Default(-1);
791
792 return CC;
793}
Jack Carterd0bd6422013-04-18 00:41:53 +0000794
Vladimir Medic8cd17102013-06-20 11:21:49 +0000795int MipsAsmParser::matchFPURegisterName(StringRef Name, FpFormatTy Format) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000796
Jack Cartera63b16a2012-09-07 00:23:42 +0000797 if (Name[0] == 'f') {
798 StringRef NumString = Name.substr(1);
799 unsigned IntVal;
Jack Carterd0bd6422013-04-18 00:41:53 +0000800 if (NumString.getAsInteger(10, IntVal))
801 return -1; // This is not an integer.
Jack Cartera63b16a2012-09-07 00:23:42 +0000802 if (IntVal > 31)
803 return -1;
804
Jack Cartera63b16a2012-09-07 00:23:42 +0000805 if (Format == FP_FORMAT_S || Format == FP_FORMAT_W)
806 return getReg(Mips::FGR32RegClassID, IntVal);
807 if (Format == FP_FORMAT_D) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000808 if (isFP64()) {
Jack Cartera63b16a2012-09-07 00:23:42 +0000809 return getReg(Mips::FGR64RegClassID, IntVal);
810 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000811 // Only even numbers available as register pairs.
812 if ((IntVal > 31) || (IntVal % 2 != 0))
Jack Cartera63b16a2012-09-07 00:23:42 +0000813 return -1;
Jack Carterd0bd6422013-04-18 00:41:53 +0000814 return getReg(Mips::AFGR64RegClassID, IntVal / 2);
Jack Cartera63b16a2012-09-07 00:23:42 +0000815 }
816 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000817 return -1;
818}
Jack Carterd0bd6422013-04-18 00:41:53 +0000819
Vladimir Medic8cd17102013-06-20 11:21:49 +0000820int MipsAsmParser::matchRegisterName(StringRef Name, bool is64BitReg) {
821
822 if (Name.equals("fcc0"))
823 return Mips::FCC0;
824
825 int CC;
826 CC = matchCPURegisterName(Name);
827 if (CC != -1)
828 return matchRegisterByNumber(CC, is64BitReg ? Mips::CPU64RegsRegClassID
829 : Mips::CPURegsRegClassID);
830 return matchFPURegisterName(Name, getFpFormat());
831}
832
Jack Cartera63b16a2012-09-07 00:23:42 +0000833void MipsAsmParser::setDefaultFpFormat() {
834
835 if (isMips64() || isFP64())
836 FpFormat = FP_FORMAT_D;
837 else
838 FpFormat = FP_FORMAT_S;
839}
840
841bool MipsAsmParser::requestsDoubleOperand(StringRef Mnemonic){
842
843 bool IsDouble = StringSwitch<bool>(Mnemonic.lower())
844 .Case("ldxc1", true)
845 .Case("ldc1", true)
846 .Case("sdxc1", true)
847 .Case("sdc1", true)
848 .Default(false);
849
850 return IsDouble;
851}
Jack Carterd0bd6422013-04-18 00:41:53 +0000852
Jack Cartera63b16a2012-09-07 00:23:42 +0000853void MipsAsmParser::setFpFormat(StringRef Format) {
854
855 FpFormat = StringSwitch<FpFormatTy>(Format.lower())
856 .Case(".s", FP_FORMAT_S)
857 .Case(".d", FP_FORMAT_D)
858 .Case(".l", FP_FORMAT_L)
859 .Case(".w", FP_FORMAT_W)
860 .Default(FP_FORMAT_NONE);
861}
Jack Carterb4dbc172012-09-05 23:34:03 +0000862
Jack Carter0b744b32012-10-04 02:29:46 +0000863bool MipsAssemblerOptions::setATReg(unsigned Reg) {
864 if (Reg > 31)
865 return false;
866
867 aTReg = Reg;
868 return true;
869}
870
Jack Carter1ac53222013-02-20 23:11:17 +0000871int MipsAsmParser::getATReg() {
872 return Options.getATRegNum();
Jack Carter0b744b32012-10-04 02:29:46 +0000873}
874
Jack Carterd0bd6422013-04-18 00:41:53 +0000875unsigned MipsAsmParser::getReg(int RC, int RegNo) {
Bill Wendlingbc07a892013-06-18 07:20:20 +0000876 return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
Jack Carterb4dbc172012-09-05 23:34:03 +0000877}
878
Jack Carter873c7242013-01-12 01:03:14 +0000879int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000880
881 if (RegNum > 31)
882 return -1;
883
Jack Carter873c7242013-01-12 01:03:14 +0000884 return getReg(RegClass, RegNum);
Jack Carterb4dbc172012-09-05 23:34:03 +0000885}
886
Jack Carter873c7242013-01-12 01:03:14 +0000887int MipsAsmParser::tryParseRegister(bool is64BitReg) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000888 const AsmToken &Tok = Parser.getTok();
889 int RegNum = -1;
890
891 if (Tok.is(AsmToken::Identifier)) {
892 std::string lowerCase = Tok.getString().lower();
Jack Carter873c7242013-01-12 01:03:14 +0000893 RegNum = matchRegisterName(lowerCase, is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000894 } else if (Tok.is(AsmToken::Integer))
Jack Carter30a59822012-10-04 04:03:53 +0000895 RegNum = matchRegisterByNumber(static_cast<unsigned>(Tok.getIntVal()),
Jack Carterd0bd6422013-04-18 00:41:53 +0000896 is64BitReg ? Mips::CPU64RegsRegClassID : Mips::CPURegsRegClassID);
Jack Carterb4dbc172012-09-05 23:34:03 +0000897 return RegNum;
898}
899
Jack Carterd0bd6422013-04-18 00:41:53 +0000900bool MipsAsmParser::tryParseRegisterOperand(
901 SmallVectorImpl<MCParsedAsmOperand*> &Operands, bool is64BitReg) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000902
903 SMLoc S = Parser.getTok().getLoc();
904 int RegNo = -1;
Jack Cartera63b16a2012-09-07 00:23:42 +0000905
Jack Carter873c7242013-01-12 01:03:14 +0000906 RegNo = tryParseRegister(is64BitReg);
Jack Carterb4dbc172012-09-05 23:34:03 +0000907 if (RegNo == -1)
908 return true;
909
Jack Carter873c7242013-01-12 01:03:14 +0000910 Operands.push_back(MipsOperand::CreateReg(RegNo, S,
Jack Carterd0bd6422013-04-18 00:41:53 +0000911 Parser.getTok().getLoc()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000912 Parser.Lex(); // Eat register token.
913 return false;
914}
915
916bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
917 StringRef Mnemonic) {
Jack Carter30a59822012-10-04 04:03:53 +0000918 // Check if the current operand has a custom associated parser, if so, try to
919 // custom parse the operand, or fallback to the general approach.
Jack Carterb4dbc172012-09-05 23:34:03 +0000920 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
921 if (ResTy == MatchOperand_Success)
922 return false;
923 // If there wasn't a custom match, try the generic matcher below. Otherwise,
924 // there was a match, but an error occurred, in which case, just return that
925 // the operand parsing failed.
926 if (ResTy == MatchOperand_ParseFail)
927 return true;
928
929 switch (getLexer().getKind()) {
930 default:
931 Error(Parser.getTok().getLoc(), "unexpected token in operand");
932 return true;
933 case AsmToken::Dollar: {
Jack Carterd0bd6422013-04-18 00:41:53 +0000934 // Parse the register.
Jack Carterb4dbc172012-09-05 23:34:03 +0000935 SMLoc S = Parser.getTok().getLoc();
936 Parser.Lex(); // Eat dollar token.
Jack Carterd0bd6422013-04-18 00:41:53 +0000937 // Parse the register operand.
Jack Carter873c7242013-01-12 01:03:14 +0000938 if (!tryParseRegisterOperand(Operands, isMips64())) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000939 if (getLexer().is(AsmToken::LParen)) {
Jack Carterd0bd6422013-04-18 00:41:53 +0000940 // Check if it is indexed addressing operand.
Jack Carterb4dbc172012-09-05 23:34:03 +0000941 Operands.push_back(MipsOperand::CreateToken("(", S));
Jack Carterd0bd6422013-04-18 00:41:53 +0000942 Parser.Lex(); // Eat the parenthesis.
Jack Carterb4dbc172012-09-05 23:34:03 +0000943 if (getLexer().isNot(AsmToken::Dollar))
944 return true;
945
Jack Carterd0bd6422013-04-18 00:41:53 +0000946 Parser.Lex(); // Eat the dollar
Jack Carter873c7242013-01-12 01:03:14 +0000947 if (tryParseRegisterOperand(Operands, isMips64()))
Jack Carterb4dbc172012-09-05 23:34:03 +0000948 return true;
949
950 if (!getLexer().is(AsmToken::RParen))
951 return true;
952
953 S = Parser.getTok().getLoc();
954 Operands.push_back(MipsOperand::CreateToken(")", S));
955 Parser.Lex();
956 }
957 return false;
958 }
Jack Carterd0bd6422013-04-18 00:41:53 +0000959 // Maybe it is a symbol reference.
Jack Carterb4dbc172012-09-05 23:34:03 +0000960 StringRef Identifier;
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000961 if (Parser.parseIdentifier(Identifier))
Jack Carterb4dbc172012-09-05 23:34:03 +0000962 return true;
963
Jack Carter873c7242013-01-12 01:03:14 +0000964 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb4dbc172012-09-05 23:34:03 +0000965
Benjamin Kramerfa530572012-09-07 09:47:42 +0000966 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterb4dbc172012-09-05 23:34:03 +0000967
Jack Carterd0bd6422013-04-18 00:41:53 +0000968 // Otherwise create a symbol reference.
Jack Carterdc1e35d2012-09-06 20:00:02 +0000969 const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
Jack Carterb4dbc172012-09-05 23:34:03 +0000970 getContext());
971
972 Operands.push_back(MipsOperand::CreateImm(Res, S, E));
973 return false;
974 }
975 case AsmToken::Identifier:
Jack Carterd76b2372013-03-21 21:44:16 +0000976 // Look for the existing symbol, we should check if
Jack Carterd0bd6422013-04-18 00:41:53 +0000977 // we need to assigne the propper RegisterKind.
978 if (searchSymbolAlias(Operands, MipsOperand::Kind_None))
979 return false;
980 // Else drop to expression parsing.
Jack Carterb4dbc172012-09-05 23:34:03 +0000981 case AsmToken::LParen:
982 case AsmToken::Minus:
983 case AsmToken::Plus:
984 case AsmToken::Integer:
985 case AsmToken::String: {
Jack Carterd0bd6422013-04-18 00:41:53 +0000986 // Quoted label names.
Jack Carterb4dbc172012-09-05 23:34:03 +0000987 const MCExpr *IdVal;
988 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +0000989 if (getParser().parseExpression(IdVal))
Jack Carterb4dbc172012-09-05 23:34:03 +0000990 return true;
Jack Carter873c7242013-01-12 01:03:14 +0000991 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb4dbc172012-09-05 23:34:03 +0000992 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
993 return false;
994 }
Jack Carterdc1e35d2012-09-06 20:00:02 +0000995 case AsmToken::Percent: {
Jack Carterd0bd6422013-04-18 00:41:53 +0000996 // It is a symbol reference or constant expression.
Jack Carterdc1e35d2012-09-06 20:00:02 +0000997 const MCExpr *IdVal;
Jack Carterd0bd6422013-04-18 00:41:53 +0000998 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
Jack Carter873c7242013-01-12 01:03:14 +0000999 if (parseRelocOperand(IdVal))
Jack Carterdc1e35d2012-09-06 20:00:02 +00001000 return true;
1001
Jack Carter873c7242013-01-12 01:03:14 +00001002 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1003
Jack Carterdc1e35d2012-09-06 20:00:02 +00001004 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
1005 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001006 } // case AsmToken::Percent
1007 } // switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +00001008 return true;
1009}
1010
Jack Carterb5cf5902013-04-17 00:18:04 +00001011const MCExpr* MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
1012 StringRef RelocStr) {
Jack Carterb5cf5902013-04-17 00:18:04 +00001013 const MCExpr *Res;
Jack Carterd0bd6422013-04-18 00:41:53 +00001014 // Check the type of the expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001015 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001016 // It's a constant, evaluate lo or hi value.
Jack Carterb5cf5902013-04-17 00:18:04 +00001017 if (RelocStr == "lo") {
Jack Carter9e65aa32013-03-22 00:05:30 +00001018 short Val = MCE->getValue();
1019 Res = MCConstantExpr::Create(Val, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001020 } else if (RelocStr == "hi") {
Jack Carter9e65aa32013-03-22 00:05:30 +00001021 int Val = MCE->getValue();
Jack Carterdc463382013-02-21 02:09:31 +00001022 int LoSign = Val & 0x8000;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001023 Val = (Val & 0xffff0000) >> 16;
Jack Carter9e65aa32013-03-22 00:05:30 +00001024 // Lower part is treated as a signed int, so if it is negative
Jack Carterd0bd6422013-04-18 00:41:53 +00001025 // we must add 1 to the hi part to compensate.
Jack Carterdc463382013-02-21 02:09:31 +00001026 if (LoSign)
1027 Val++;
Jack Carter9e65aa32013-03-22 00:05:30 +00001028 Res = MCConstantExpr::Create(Val, getContext());
Evgeniy Stepanov3d8ab192013-04-17 06:45:11 +00001029 } else {
1030 llvm_unreachable("Invalid RelocStr value");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001031 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001032 return Res;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001033 }
1034
Jack Carterb5cf5902013-04-17 00:18:04 +00001035 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001036 // It's a symbol, create a symbolic expression from the symbol.
Benjamin Kramerfa530572012-09-07 09:47:42 +00001037 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterb5cf5902013-04-17 00:18:04 +00001038 MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Jack Carterd0bd6422013-04-18 00:41:53 +00001039 Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
Jack Carterb5cf5902013-04-17 00:18:04 +00001040 return Res;
1041 }
1042
1043 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001044 const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
1045 const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Jack Carterb5cf5902013-04-17 00:18:04 +00001046 Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
1047 return Res;
1048 }
1049
1050 if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001051 const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
1052 Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
1053 return Res;
Jack Carterb5cf5902013-04-17 00:18:04 +00001054 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001055 // Just return the original expression.
Jack Carterb5cf5902013-04-17 00:18:04 +00001056 return Expr;
1057}
1058
1059bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
1060
1061 switch (Expr->getKind()) {
1062 case MCExpr::Constant:
1063 return true;
1064 case MCExpr::SymbolRef:
1065 return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
1066 case MCExpr::Binary:
1067 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
1068 if (!isEvaluated(BE->getLHS()))
1069 return false;
1070 return isEvaluated(BE->getRHS());
1071 }
1072 case MCExpr::Unary:
1073 return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
1074 default:
Jack Carterdc1e35d2012-09-06 20:00:02 +00001075 return false;
1076 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001077 return false;
Jack Carterb5cf5902013-04-17 00:18:04 +00001078}
Jack Carterd0bd6422013-04-18 00:41:53 +00001079
Jack Carterb5cf5902013-04-17 00:18:04 +00001080bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001081 Parser.Lex(); // Eat the % token.
1082 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
Jack Carterb5cf5902013-04-17 00:18:04 +00001083 if (Tok.isNot(AsmToken::Identifier))
1084 return true;
1085
1086 std::string Str = Tok.getIdentifier().str();
1087
Jack Carterd0bd6422013-04-18 00:41:53 +00001088 Parser.Lex(); // Eat the identifier.
1089 // Now make an expression from the rest of the operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001090 const MCExpr *IdVal;
1091 SMLoc EndLoc;
1092
1093 if (getLexer().getKind() == AsmToken::LParen) {
1094 while (1) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001095 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001096 if (getLexer().getKind() == AsmToken::Percent) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001097 Parser.Lex(); // Eat the % token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001098 const AsmToken &nextTok = Parser.getTok();
1099 if (nextTok.isNot(AsmToken::Identifier))
1100 return true;
1101 Str += "(%";
1102 Str += nextTok.getIdentifier();
Jack Carterd0bd6422013-04-18 00:41:53 +00001103 Parser.Lex(); // Eat the identifier.
Jack Carterb5cf5902013-04-17 00:18:04 +00001104 if (getLexer().getKind() != AsmToken::LParen)
1105 return true;
1106 } else
1107 break;
1108 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001109 if (getParser().parseParenExpression(IdVal, EndLoc))
Jack Carterb5cf5902013-04-17 00:18:04 +00001110 return true;
1111
1112 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterd0bd6422013-04-18 00:41:53 +00001113 Parser.Lex(); // Eat the ')' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001114
1115 } else
Jack Carterd0bd6422013-04-18 00:41:53 +00001116 return true; // Parenthesis must follow the relocation operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001117
Jack Carterd0bd6422013-04-18 00:41:53 +00001118 Res = evaluateRelocExpr(IdVal, Str);
Jack Carterb5cf5902013-04-17 00:18:04 +00001119 return false;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001120}
1121
Jack Carterb4dbc172012-09-05 23:34:03 +00001122bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1123 SMLoc &EndLoc) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001124 StartLoc = Parser.getTok().getLoc();
Jack Carter873c7242013-01-12 01:03:14 +00001125 RegNo = tryParseRegister(isMips64());
1126 EndLoc = Parser.getTok().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001127 return (RegNo == (unsigned) -1);
Jack Carterb4dbc172012-09-05 23:34:03 +00001128}
1129
Jack Carterb5cf5902013-04-17 00:18:04 +00001130bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
Jack Carter873c7242013-01-12 01:03:14 +00001131 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001132 bool Result = true;
1133
1134 while (getLexer().getKind() == AsmToken::LParen)
1135 Parser.Lex();
Jack Carter873c7242013-01-12 01:03:14 +00001136
Jack Carterd0bd6422013-04-18 00:41:53 +00001137 switch (getLexer().getKind()) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001138 default:
1139 return true;
Jack Carter9e65aa32013-03-22 00:05:30 +00001140 case AsmToken::Identifier:
Jack Carterb5cf5902013-04-17 00:18:04 +00001141 case AsmToken::LParen:
Jack Carterdc1e35d2012-09-06 20:00:02 +00001142 case AsmToken::Integer:
1143 case AsmToken::Minus:
1144 case AsmToken::Plus:
Jack Carterb5cf5902013-04-17 00:18:04 +00001145 if (isParenExpr)
Jack Carterd0bd6422013-04-18 00:41:53 +00001146 Result = getParser().parseParenExpression(Res, S);
Jack Carterb5cf5902013-04-17 00:18:04 +00001147 else
1148 Result = (getParser().parseExpression(Res));
Jack Carterd0bd6422013-04-18 00:41:53 +00001149 while (getLexer().getKind() == AsmToken::RParen)
Jack Carterb5cf5902013-04-17 00:18:04 +00001150 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001151 break;
Jack Carter873c7242013-01-12 01:03:14 +00001152 case AsmToken::Percent:
Jack Carterb5cf5902013-04-17 00:18:04 +00001153 Result = parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +00001154 }
Jack Carterb5cf5902013-04-17 00:18:04 +00001155 return Result;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001156}
1157
Jack Carterb4dbc172012-09-05 23:34:03 +00001158MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
Jack Carterd0bd6422013-04-18 00:41:53 +00001159 SmallVectorImpl<MCParsedAsmOperand*>&Operands) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001160
1161 const MCExpr *IdVal = 0;
Jack Carter873c7242013-01-12 01:03:14 +00001162 SMLoc S;
Jack Carterb5cf5902013-04-17 00:18:04 +00001163 bool isParenExpr = false;
Jack Carterd0bd6422013-04-18 00:41:53 +00001164 // First operand is the offset.
Jack Carter873c7242013-01-12 01:03:14 +00001165 S = Parser.getTok().getLoc();
Jack Carterdc1e35d2012-09-06 20:00:02 +00001166
Jack Carterb5cf5902013-04-17 00:18:04 +00001167 if (getLexer().getKind() == AsmToken::LParen) {
1168 Parser.Lex();
1169 isParenExpr = true;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001170 }
1171
Jack Carterb5cf5902013-04-17 00:18:04 +00001172 if (getLexer().getKind() != AsmToken::Dollar) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001173 if (parseMemOffset(IdVal, isParenExpr))
Jack Carterb5cf5902013-04-17 00:18:04 +00001174 return MatchOperand_ParseFail;
Jack Carterdc1e35d2012-09-06 20:00:02 +00001175
Jack Carterd0bd6422013-04-18 00:41:53 +00001176 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001177 if (Tok.isNot(AsmToken::LParen)) {
1178 MipsOperand *Mnemonic = static_cast<MipsOperand*>(Operands[0]);
1179 if (Mnemonic->getToken() == "la") {
1180 SMLoc E = SMLoc::getFromPointer(
Jack Carterd0bd6422013-04-18 00:41:53 +00001181 Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00001182 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
1183 return MatchOperand_Success;
1184 }
1185 if (Tok.is(AsmToken::EndOfStatement)) {
1186 SMLoc E = SMLoc::getFromPointer(
Jack Carterd0bd6422013-04-18 00:41:53 +00001187 Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb5cf5902013-04-17 00:18:04 +00001188
Jack Carterd0bd6422013-04-18 00:41:53 +00001189 // Zero register assumed, add a memory operand with ZERO as its base.
1190 Operands.push_back(MipsOperand::CreateMem(isMips64() ? Mips::ZERO_64
1191 : Mips::ZERO,
1192 IdVal, S, E));
Jack Carterb5cf5902013-04-17 00:18:04 +00001193 return MatchOperand_Success;
1194 }
1195 Error(Parser.getTok().getLoc(), "'(' expected");
1196 return MatchOperand_ParseFail;
1197 }
1198
Jack Carterd0bd6422013-04-18 00:41:53 +00001199 Parser.Lex(); // Eat the '(' token.
Jack Carterb5cf5902013-04-17 00:18:04 +00001200 }
1201
1202 const AsmToken &Tok1 = Parser.getTok(); // Get next token
Jack Carterdc1e35d2012-09-06 20:00:02 +00001203 if (Tok1.is(AsmToken::Dollar)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001204 Parser.Lex(); // Eat the '$' token.
Jack Carter873c7242013-01-12 01:03:14 +00001205 if (tryParseRegisterOperand(Operands, isMips64())) {
Jack Carterdc1e35d2012-09-06 20:00:02 +00001206 Error(Parser.getTok().getLoc(), "unexpected token in operand");
1207 return MatchOperand_ParseFail;
1208 }
1209
1210 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00001211 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Jack Carterdc1e35d2012-09-06 20:00:02 +00001212 return MatchOperand_ParseFail;
1213 }
1214
Jack Carterd0bd6422013-04-18 00:41:53 +00001215 const AsmToken &Tok2 = Parser.getTok(); // Get next token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001216 if (Tok2.isNot(AsmToken::RParen)) {
1217 Error(Parser.getTok().getLoc(), "')' expected");
1218 return MatchOperand_ParseFail;
1219 }
1220
Jack Carter873c7242013-01-12 01:03:14 +00001221 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1222
Jack Carterd0bd6422013-04-18 00:41:53 +00001223 Parser.Lex(); // Eat the ')' token.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001224
1225 if (IdVal == 0)
1226 IdVal = MCConstantExpr::Create(0, getContext());
1227
Jack Carterd0bd6422013-04-18 00:41:53 +00001228 // Replace the register operand with the memory operand.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001229 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
1230 int RegNo = op->getReg();
Jack Carterd0bd6422013-04-18 00:41:53 +00001231 // Remove the register from the operands.
Jack Carterdc1e35d2012-09-06 20:00:02 +00001232 Operands.pop_back();
Jack Carterd0bd6422013-04-18 00:41:53 +00001233 // Add the memory operand.
Jack Carterb5cf5902013-04-17 00:18:04 +00001234 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
1235 int64_t Imm;
1236 if (IdVal->EvaluateAsAbsolute(Imm))
1237 IdVal = MCConstantExpr::Create(Imm, getContext());
1238 else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
1239 IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
1240 getContext());
1241 }
1242
Jack Carterdc1e35d2012-09-06 20:00:02 +00001243 Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
1244 delete op;
Jack Carterb4dbc172012-09-05 23:34:03 +00001245 return MatchOperand_Success;
1246}
1247
Jack Carter873c7242013-01-12 01:03:14 +00001248MipsAsmParser::OperandMatchResultTy
Vladimir Medic8cd17102013-06-20 11:21:49 +00001249MipsAsmParser::parseRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
1250 int RegKind) {
1251 MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind)RegKind;
Jack Carterd76b2372013-03-21 21:44:16 +00001252 if (getLexer().getKind() == AsmToken::Identifier) {
Vladimir Medic8cd17102013-06-20 11:21:49 +00001253 if (searchSymbolAlias(Operands, Kind))
Jack Carterd76b2372013-03-21 21:44:16 +00001254 return MatchOperand_Success;
1255 return MatchOperand_NoMatch;
1256 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001257 // If the first token is not '$', we have an error.
Jack Carter873c7242013-01-12 01:03:14 +00001258 if (Parser.getTok().isNot(AsmToken::Dollar))
1259 return MatchOperand_NoMatch;
1260
1261 Parser.Lex(); // Eat $
Vladimir Medic8cd17102013-06-20 11:21:49 +00001262 if (!tryParseRegisterOperand(Operands, isMips64())) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001263 // Set the proper register kind.
Jack Carter873c7242013-01-12 01:03:14 +00001264 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
Vladimir Medic8cd17102013-06-20 11:21:49 +00001265 op->setRegKind(Kind);
Jack Carter873c7242013-01-12 01:03:14 +00001266 return MatchOperand_Success;
1267 }
1268 return MatchOperand_NoMatch;
1269}
Vladimir Medic8cd17102013-06-20 11:21:49 +00001270MipsAsmParser::OperandMatchResultTy
1271MipsAsmParser::parseCPU64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1272
1273 if (!isMips64())
1274 return MatchOperand_NoMatch;
1275 return parseRegs(Operands, (int) MipsOperand::Kind_CPU64Regs);
1276}
1277
1278MipsAsmParser::OperandMatchResultTy
1279MipsAsmParser::parseCPURegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1280 return parseRegs(Operands, (int) MipsOperand::Kind_CPURegs);
1281}
Jack Carter873c7242013-01-12 01:03:14 +00001282
Jack Carterd0bd6422013-04-18 00:41:53 +00001283bool MipsAsmParser::searchSymbolAlias(
Vladimir Medic8cd17102013-06-20 11:21:49 +00001284 SmallVectorImpl<MCParsedAsmOperand*> &Operands, unsigned RegKind) {
Jack Carterd76b2372013-03-21 21:44:16 +00001285
1286 MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
1287 if (Sym) {
1288 SMLoc S = Parser.getTok().getLoc();
1289 const MCExpr *Expr;
1290 if (Sym->isVariable())
1291 Expr = Sym->getVariableValue();
1292 else
1293 return false;
1294 if (Expr->getKind() == MCExpr::SymbolRef) {
Vladimir Medic8cd17102013-06-20 11:21:49 +00001295 MipsOperand::RegisterKind Kind = (MipsOperand::RegisterKind) RegKind;
Jack Carterd76b2372013-03-21 21:44:16 +00001296 const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr*>(Expr);
1297 const StringRef DefSymbol = Ref->getSymbol().getName();
1298 if (DefSymbol.startswith("$")) {
Jack Carter02593002013-05-28 22:21:05 +00001299 int RegNum = -1;
1300 APInt IntVal(32, -1);
1301 if (!DefSymbol.substr(1).getAsInteger(10, IntVal))
1302 RegNum = matchRegisterByNumber(IntVal.getZExtValue(),
1303 isMips64()
1304 ? Mips::CPU64RegsRegClassID
1305 : Mips::CPURegsRegClassID);
Vladimir Medic8cd17102013-06-20 11:21:49 +00001306 else {
1307 // Lookup for the register with the corresponding name.
1308 switch (Kind) {
1309 case MipsOperand::Kind_AFGR64Regs:
1310 case MipsOperand::Kind_FGR64Regs:
1311 RegNum = matchFPURegisterName(DefSymbol.substr(1), FP_FORMAT_D);
1312 break;
1313 case MipsOperand::Kind_FGR32Regs:
1314 RegNum = matchFPURegisterName(DefSymbol.substr(1), FP_FORMAT_S);
1315 break;
1316 case MipsOperand::Kind_CPU64Regs:
1317 case MipsOperand::Kind_CPURegs:
1318 default:
1319 RegNum = matchRegisterName(DefSymbol.substr(1), isMips64());
1320 break;
1321 }
1322 }
Jack Carterd76b2372013-03-21 21:44:16 +00001323 if (RegNum > -1) {
1324 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001325 MipsOperand *op = MipsOperand::CreateReg(RegNum, S,
1326 Parser.getTok().getLoc());
Vladimir Medic8cd17102013-06-20 11:21:49 +00001327 op->setRegKind(Kind);
Jack Carterd76b2372013-03-21 21:44:16 +00001328 Operands.push_back(op);
1329 return true;
1330 }
1331 }
1332 } else if (Expr->getKind() == MCExpr::Constant) {
1333 Parser.Lex();
1334 const MCConstantExpr *Const = static_cast<const MCConstantExpr*>(Expr);
Jack Carterd0bd6422013-04-18 00:41:53 +00001335 MipsOperand *op = MipsOperand::CreateImm(Const, S,
Jack Carter02593002013-05-28 22:21:05 +00001336 Parser.getTok().getLoc());
Jack Carterd76b2372013-03-21 21:44:16 +00001337 Operands.push_back(op);
1338 return true;
1339 }
1340 }
1341 return false;
1342}
Jack Carterd0bd6422013-04-18 00:41:53 +00001343
Jack Carter873c7242013-01-12 01:03:14 +00001344MipsAsmParser::OperandMatchResultTy
Jack Carter873c7242013-01-12 01:03:14 +00001345MipsAsmParser::parseHWRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1346
Jack Carter2a74a87b2013-01-17 00:28:20 +00001347 if (isMips64())
1348 return MatchOperand_NoMatch;
1349
Jack Carterd0bd6422013-04-18 00:41:53 +00001350 // If the first token is not '$' we have error.
Jack Carter873c7242013-01-12 01:03:14 +00001351 if (Parser.getTok().isNot(AsmToken::Dollar))
1352 return MatchOperand_NoMatch;
1353 SMLoc S = Parser.getTok().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001354 Parser.Lex(); // Eat the '$'.
Jack Carter873c7242013-01-12 01:03:14 +00001355
Jack Carterd0bd6422013-04-18 00:41:53 +00001356 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carter873c7242013-01-12 01:03:14 +00001357 if (Tok.isNot(AsmToken::Integer))
1358 return MatchOperand_NoMatch;
1359
1360 unsigned RegNum = Tok.getIntVal();
Jack Carterd0bd6422013-04-18 00:41:53 +00001361 // At the moment only hwreg29 is supported.
Jack Carter873c7242013-01-12 01:03:14 +00001362 if (RegNum != 29)
1363 return MatchOperand_ParseFail;
1364
1365 MipsOperand *op = MipsOperand::CreateReg(Mips::HWR29, S,
Jack Carterd0bd6422013-04-18 00:41:53 +00001366 Parser.getTok().getLoc());
Jack Carter873c7242013-01-12 01:03:14 +00001367 op->setRegKind(MipsOperand::Kind_HWRegs);
1368 Operands.push_back(op);
1369
Jack Carterd0bd6422013-04-18 00:41:53 +00001370 Parser.Lex(); // Eat the register number.
Jack Carter873c7242013-01-12 01:03:14 +00001371 return MatchOperand_Success;
1372}
1373
1374MipsAsmParser::OperandMatchResultTy
Jack Carterd0bd6422013-04-18 00:41:53 +00001375MipsAsmParser::parseHW64Regs(
1376 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jack Carter2a74a87b2013-01-17 00:28:20 +00001377
1378 if (!isMips64())
1379 return MatchOperand_NoMatch;
Jack Carterd0bd6422013-04-18 00:41:53 +00001380 // If the first token is not '$' we have an error.
Jack Carter873c7242013-01-12 01:03:14 +00001381 if (Parser.getTok().isNot(AsmToken::Dollar))
1382 return MatchOperand_NoMatch;
1383 SMLoc S = Parser.getTok().getLoc();
1384 Parser.Lex(); // Eat $
1385
Jack Carterd0bd6422013-04-18 00:41:53 +00001386 const AsmToken &Tok = Parser.getTok(); // Get the next token.
Jack Carter873c7242013-01-12 01:03:14 +00001387 if (Tok.isNot(AsmToken::Integer))
1388 return MatchOperand_NoMatch;
1389
1390 unsigned RegNum = Tok.getIntVal();
Jack Carterd0bd6422013-04-18 00:41:53 +00001391 // At the moment only hwreg29 is supported.
Jack Carter873c7242013-01-12 01:03:14 +00001392 if (RegNum != 29)
1393 return MatchOperand_ParseFail;
1394
1395 MipsOperand *op = MipsOperand::CreateReg(Mips::HWR29_64, S,
Jack Carterd0bd6422013-04-18 00:41:53 +00001396 Parser.getTok().getLoc());
Jack Carter2a74a87b2013-01-17 00:28:20 +00001397 op->setRegKind(MipsOperand::Kind_HW64Regs);
Jack Carter873c7242013-01-12 01:03:14 +00001398 Operands.push_back(op);
1399
Jack Carterd0bd6422013-04-18 00:41:53 +00001400 Parser.Lex(); // Eat the register number.
Jack Carter873c7242013-01-12 01:03:14 +00001401 return MatchOperand_Success;
1402}
1403
1404MipsAsmParser::OperandMatchResultTy
1405MipsAsmParser::parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1406 unsigned RegNum;
Jack Carterd0bd6422013-04-18 00:41:53 +00001407 // If the first token is not '$' we have an error.
Jack Carter873c7242013-01-12 01:03:14 +00001408 if (Parser.getTok().isNot(AsmToken::Dollar))
1409 return MatchOperand_NoMatch;
1410 SMLoc S = Parser.getTok().getLoc();
Jack Carterd0bd6422013-04-18 00:41:53 +00001411 Parser.Lex(); // Eat the '$'
Jack Carter873c7242013-01-12 01:03:14 +00001412
Jack Carterd0bd6422013-04-18 00:41:53 +00001413 const AsmToken &Tok = Parser.getTok(); // Get next token.
Jack Carter873c7242013-01-12 01:03:14 +00001414 if (Tok.is(AsmToken::Integer)) {
1415 RegNum = Tok.getIntVal();
Jack Carterd0bd6422013-04-18 00:41:53 +00001416 // At the moment only fcc0 is supported.
Jack Carter873c7242013-01-12 01:03:14 +00001417 if (RegNum != 0)
1418 return MatchOperand_ParseFail;
1419 } else if (Tok.is(AsmToken::Identifier)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001420 // At the moment only fcc0 is supported.
Jack Carter873c7242013-01-12 01:03:14 +00001421 if (Tok.getIdentifier() != "fcc0")
1422 return MatchOperand_ParseFail;
1423 } else
1424 return MatchOperand_NoMatch;
1425
1426 MipsOperand *op = MipsOperand::CreateReg(Mips::FCC0, S,
Jack Carterd0bd6422013-04-18 00:41:53 +00001427 Parser.getTok().getLoc());
Jack Carter873c7242013-01-12 01:03:14 +00001428 op->setRegKind(MipsOperand::Kind_CCRRegs);
1429 Operands.push_back(op);
1430
Jack Carterd0bd6422013-04-18 00:41:53 +00001431 Parser.Lex(); // Eat the register number.
Jack Carter873c7242013-01-12 01:03:14 +00001432 return MatchOperand_Success;
1433}
1434
Jack Carterdc1e35d2012-09-06 20:00:02 +00001435MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
1436
1437 MCSymbolRefExpr::VariantKind VK
1438 = StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
1439 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
1440 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
1441 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
1442 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
1443 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
1444 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
1445 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
1446 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
1447 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
1448 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
1449 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
1450 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
1451 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
1452 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
1453 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
1454 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
1455 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
1456 .Default(MCSymbolRefExpr::VK_None);
1457
1458 return VK;
1459}
Vladimir Medicea381912013-06-04 08:28:53 +00001460// Converts condition string to immediate operand value.
Benjamin Kramer47b5c572012-09-10 11:52:14 +00001461static int ConvertCcString(StringRef CondString) {
Jack Cartera63b16a2012-09-07 00:23:42 +00001462 int CC = StringSwitch<unsigned>(CondString)
Jack Carterd0bd6422013-04-18 00:41:53 +00001463 .Case(".f", 0)
1464 .Case(".un", 1)
1465 .Case(".eq", 2)
1466 .Case(".ueq", 3)
1467 .Case(".olt", 4)
1468 .Case(".ult", 5)
1469 .Case(".ole", 6)
1470 .Case(".ule", 7)
1471 .Case(".sf", 8)
1472 .Case(".ngle", 9)
1473 .Case(".seq", 10)
1474 .Case(".ngl", 11)
1475 .Case(".lt", 12)
1476 .Case(".nge", 13)
1477 .Case(".le", 14)
1478 .Case(".ngt", 15)
1479 .Default(-1);
Jack Cartera63b16a2012-09-07 00:23:42 +00001480
1481 return CC;
1482}
1483
1484bool MipsAsmParser::
1485parseMathOperation(StringRef Name, SMLoc NameLoc,
Jack Carter0b744b32012-10-04 02:29:46 +00001486 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001487 // Split the format.
Jack Cartera63b16a2012-09-07 00:23:42 +00001488 size_t Start = Name.find('.'), Next = Name.rfind('.');
1489 StringRef Format1 = Name.slice(Start, Next);
Jack Carterd0bd6422013-04-18 00:41:53 +00001490 // Add the first format to the operands.
Jack Cartera63b16a2012-09-07 00:23:42 +00001491 Operands.push_back(MipsOperand::CreateToken(Format1, NameLoc));
Jack Carterd0bd6422013-04-18 00:41:53 +00001492 // Now for the second format.
Jack Cartera63b16a2012-09-07 00:23:42 +00001493 StringRef Format2 = Name.slice(Next, StringRef::npos);
1494 Operands.push_back(MipsOperand::CreateToken(Format2, NameLoc));
1495
Jack Carterd0bd6422013-04-18 00:41:53 +00001496 // Set the format for the first register.
Jack Cartera63b16a2012-09-07 00:23:42 +00001497 setFpFormat(Format1);
1498
1499 // Read the remaining operands.
1500 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1501 // Read the first operand.
1502 if (ParseOperand(Operands, Name)) {
1503 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001504 Parser.eatToEndOfStatement();
Jack Cartera63b16a2012-09-07 00:23:42 +00001505 return Error(Loc, "unexpected token in argument list");
1506 }
1507
1508 if (getLexer().isNot(AsmToken::Comma)) {
1509 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001510 Parser.eatToEndOfStatement();
Jack Cartera63b16a2012-09-07 00:23:42 +00001511 return Error(Loc, "unexpected token in argument list");
Jack Cartera63b16a2012-09-07 00:23:42 +00001512 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001513 Parser.Lex(); // Eat the comma.
Jack Cartera63b16a2012-09-07 00:23:42 +00001514
Jack Carterb5cf5902013-04-17 00:18:04 +00001515 // Set the format for the first register
Jack Cartera63b16a2012-09-07 00:23:42 +00001516 setFpFormat(Format2);
1517
1518 // Parse and remember the operand.
1519 if (ParseOperand(Operands, Name)) {
1520 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001521 Parser.eatToEndOfStatement();
Jack Cartera63b16a2012-09-07 00:23:42 +00001522 return Error(Loc, "unexpected token in argument list");
1523 }
1524 }
1525
1526 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1527 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001528 Parser.eatToEndOfStatement();
Jack Cartera63b16a2012-09-07 00:23:42 +00001529 return Error(Loc, "unexpected token in argument list");
1530 }
1531
Jack Carterd0bd6422013-04-18 00:41:53 +00001532 Parser.Lex(); // Consume the EndOfStatement.
Jack Cartera63b16a2012-09-07 00:23:42 +00001533 return false;
1534}
1535
Rafael Espindola870c4e92012-01-11 03:56:41 +00001536bool MipsAsmParser::
Chad Rosierf0e87202012-10-25 20:41:34 +00001537ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
Rafael Espindola870c4e92012-01-11 03:56:41 +00001538 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jack Carter1ac53222013-02-20 23:11:17 +00001539 StringRef Mnemonic;
Jack Carterd0bd6422013-04-18 00:41:53 +00001540 // Floating point instructions: Should the register be treated as a double?
Jack Cartera63b16a2012-09-07 00:23:42 +00001541 if (requestsDoubleOperand(Name)) {
1542 setFpFormat(FP_FORMAT_D);
Jack Carterd0bd6422013-04-18 00:41:53 +00001543 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
1544 Mnemonic = Name;
1545 } else {
Jack Cartera63b16a2012-09-07 00:23:42 +00001546 setDefaultFpFormat();
1547 // Create the leading tokens for the mnemonic, split by '.' characters.
1548 size_t Start = 0, Next = Name.find('.');
Jack Carter1ac53222013-02-20 23:11:17 +00001549 Mnemonic = Name.slice(Start, Next);
Jack Cartera63b16a2012-09-07 00:23:42 +00001550
1551 Operands.push_back(MipsOperand::CreateToken(Mnemonic, NameLoc));
1552
1553 if (Next != StringRef::npos) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001554 // There is a format token in mnemonic.
1555 size_t Dot = Name.find('.', Next + 1);
Jack Cartera63b16a2012-09-07 00:23:42 +00001556 StringRef Format = Name.slice(Next, Dot);
Jack Carterd0bd6422013-04-18 00:41:53 +00001557 if (Dot == StringRef::npos) // Only one '.' in a string, it's a format.
Jack Cartera63b16a2012-09-07 00:23:42 +00001558 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
1559 else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001560 if (Name.startswith("c.")) {
1561 // Floating point compare, add '.' and immediate represent for cc.
Jack Cartera63b16a2012-09-07 00:23:42 +00001562 Operands.push_back(MipsOperand::CreateToken(".", NameLoc));
1563 int Cc = ConvertCcString(Format);
1564 if (Cc == -1) {
1565 return Error(NameLoc, "Invalid conditional code");
1566 }
Jack Carter873c7242013-01-12 01:03:14 +00001567 SMLoc E = SMLoc::getFromPointer(
Jack Carterd0bd6422013-04-18 00:41:53 +00001568 Parser.getTok().getLoc().getPointer() - 1);
1569 Operands.push_back(
1570 MipsOperand::CreateImm(MCConstantExpr::Create(Cc, getContext()),
1571 NameLoc, E));
Jack Cartera63b16a2012-09-07 00:23:42 +00001572 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00001573 // trunc, ceil, floor ...
Jack Cartera63b16a2012-09-07 00:23:42 +00001574 return parseMathOperation(Name, NameLoc, Operands);
1575 }
1576
Jack Carterd0bd6422013-04-18 00:41:53 +00001577 // The rest is a format.
Jack Cartera63b16a2012-09-07 00:23:42 +00001578 Format = Name.slice(Dot, StringRef::npos);
1579 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
1580 }
1581
1582 setFpFormat(Format);
1583 }
1584 }
Jack Carterb4dbc172012-09-05 23:34:03 +00001585
1586 // Read the remaining operands.
1587 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1588 // Read the first operand.
Jack Carter1ac53222013-02-20 23:11:17 +00001589 if (ParseOperand(Operands, Mnemonic)) {
Jack Carterb4dbc172012-09-05 23:34:03 +00001590 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001591 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00001592 return Error(Loc, "unexpected token in argument list");
1593 }
1594
Jack Carterd0bd6422013-04-18 00:41:53 +00001595 while (getLexer().is(AsmToken::Comma)) {
1596 Parser.Lex(); // Eat the comma.
Jack Carterb4dbc172012-09-05 23:34:03 +00001597
1598 // Parse and remember the operand.
1599 if (ParseOperand(Operands, Name)) {
1600 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001601 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00001602 return Error(Loc, "unexpected token in argument list");
1603 }
1604 }
1605 }
1606
1607 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1608 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001609 Parser.eatToEndOfStatement();
Jack Carterb4dbc172012-09-05 23:34:03 +00001610 return Error(Loc, "unexpected token in argument list");
1611 }
1612
Jack Carterd0bd6422013-04-18 00:41:53 +00001613 Parser.Lex(); // Consume the EndOfStatement.
Jack Carterb4dbc172012-09-05 23:34:03 +00001614 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +00001615}
1616
Jack Carter0b744b32012-10-04 02:29:46 +00001617bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001618 SMLoc Loc = getLexer().getLoc();
1619 Parser.eatToEndOfStatement();
1620 return Error(Loc, ErrorMsg);
Jack Carter0b744b32012-10-04 02:29:46 +00001621}
1622
1623bool MipsAsmParser::parseSetNoAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00001624 // Line should look like: ".set noat".
1625 // set at reg to 0.
Jack Carter99d2afe2012-10-05 23:55:28 +00001626 Options.setATReg(0);
Jack Carter0b744b32012-10-04 02:29:46 +00001627 // eat noat
1628 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001629 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00001630 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1631 reportParseError("unexpected token in statement");
1632 return false;
1633 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001634 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001635 return false;
1636}
Jack Carterd0bd6422013-04-18 00:41:53 +00001637
Jack Carter0b744b32012-10-04 02:29:46 +00001638bool MipsAsmParser::parseSetAtDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00001639 // Line can be .set at - defaults to $1
Jack Carter0b744b32012-10-04 02:29:46 +00001640 // or .set at=$reg
Jack Carter1ac53222013-02-20 23:11:17 +00001641 int AtRegNo;
Jack Carter0b744b32012-10-04 02:29:46 +00001642 getParser().Lex();
1643 if (getLexer().is(AsmToken::EndOfStatement)) {
Jack Carter99d2afe2012-10-05 23:55:28 +00001644 Options.setATReg(1);
Jack Carterd0bd6422013-04-18 00:41:53 +00001645 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001646 return false;
1647 } else if (getLexer().is(AsmToken::Equal)) {
Jack Carterd0bd6422013-04-18 00:41:53 +00001648 getParser().Lex(); // Eat the '='.
Jack Carter0b744b32012-10-04 02:29:46 +00001649 if (getLexer().isNot(AsmToken::Dollar)) {
1650 reportParseError("unexpected token in statement");
1651 return false;
1652 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001653 Parser.Lex(); // Eat the '$'.
Jack Carter1ac53222013-02-20 23:11:17 +00001654 const AsmToken &Reg = Parser.getTok();
1655 if (Reg.is(AsmToken::Identifier)) {
1656 AtRegNo = matchCPURegisterName(Reg.getIdentifier());
1657 } else if (Reg.is(AsmToken::Integer)) {
1658 AtRegNo = Reg.getIntVal();
1659 } else {
Jack Carter0b744b32012-10-04 02:29:46 +00001660 reportParseError("unexpected token in statement");
1661 return false;
1662 }
Jack Carter1ac53222013-02-20 23:11:17 +00001663
Jack Carterd0bd6422013-04-18 00:41:53 +00001664 if (AtRegNo < 1 || AtRegNo > 31) {
Jack Carter1ac53222013-02-20 23:11:17 +00001665 reportParseError("unexpected token in statement");
1666 return false;
1667 }
1668
1669 if (!Options.setATReg(AtRegNo)) {
Jack Carter0b744b32012-10-04 02:29:46 +00001670 reportParseError("unexpected token in statement");
1671 return false;
1672 }
Jack Carterd0bd6422013-04-18 00:41:53 +00001673 getParser().Lex(); // Eat the register.
Jack Carter0b744b32012-10-04 02:29:46 +00001674
1675 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1676 reportParseError("unexpected token in statement");
1677 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00001678 }
1679 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001680 return false;
1681 } else {
1682 reportParseError("unexpected token in statement");
1683 return false;
1684 }
1685}
1686
1687bool MipsAsmParser::parseSetReorderDirective() {
1688 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001689 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00001690 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1691 reportParseError("unexpected token in statement");
1692 return false;
1693 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001694 Options.setReorder();
Jack Carterd0bd6422013-04-18 00:41:53 +00001695 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001696 return false;
1697}
1698
1699bool MipsAsmParser::parseSetNoReorderDirective() {
Jack Carterd0bd6422013-04-18 00:41:53 +00001700 Parser.Lex();
1701 // If this is not the end of the statement, report an error.
1702 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1703 reportParseError("unexpected token in statement");
Jack Carter0b744b32012-10-04 02:29:46 +00001704 return false;
Jack Carterd0bd6422013-04-18 00:41:53 +00001705 }
1706 Options.setNoreorder();
1707 Parser.Lex(); // Consume the EndOfStatement.
1708 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001709}
1710
1711bool MipsAsmParser::parseSetMacroDirective() {
1712 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001713 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00001714 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1715 reportParseError("unexpected token in statement");
1716 return false;
1717 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001718 Options.setMacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00001719 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001720 return false;
1721}
1722
1723bool MipsAsmParser::parseSetNoMacroDirective() {
1724 Parser.Lex();
Jack Carterd0bd6422013-04-18 00:41:53 +00001725 // If this is not the end of the statement, report an error.
Jack Carter0b744b32012-10-04 02:29:46 +00001726 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1727 reportParseError("`noreorder' must be set before `nomacro'");
1728 return false;
1729 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001730 if (Options.isReorder()) {
Jack Carter0b744b32012-10-04 02:29:46 +00001731 reportParseError("`noreorder' must be set before `nomacro'");
1732 return false;
1733 }
Jack Carter99d2afe2012-10-05 23:55:28 +00001734 Options.setNomacro();
Jack Carterd0bd6422013-04-18 00:41:53 +00001735 Parser.Lex(); // Consume the EndOfStatement.
Jack Carter0b744b32012-10-04 02:29:46 +00001736 return false;
1737}
Jack Carterd76b2372013-03-21 21:44:16 +00001738
1739bool MipsAsmParser::parseSetAssignment() {
1740 StringRef Name;
1741 const MCExpr *Value;
1742
1743 if (Parser.parseIdentifier(Name))
1744 reportParseError("expected identifier after .set");
1745
1746 if (getLexer().isNot(AsmToken::Comma))
1747 return reportParseError("unexpected token in .set directive");
Jack Carterb5cf5902013-04-17 00:18:04 +00001748 Lex(); // Eat comma
Jack Carterd76b2372013-03-21 21:44:16 +00001749
Jack Carter02593002013-05-28 22:21:05 +00001750 if (getLexer().is(AsmToken::Dollar)) {
1751 MCSymbol *Symbol;
1752 SMLoc DollarLoc = getLexer().getLoc();
1753 // Consume the dollar sign, and check for a following identifier.
1754 Parser.Lex();
1755 // We have a '$' followed by something, make sure they are adjacent.
1756 if (DollarLoc.getPointer() + 1 != getTok().getLoc().getPointer())
1757 return true;
1758 StringRef Res = StringRef(DollarLoc.getPointer(),
1759 getTok().getEndLoc().getPointer() - DollarLoc.getPointer());
1760 Symbol = getContext().GetOrCreateSymbol(Res);
1761 Parser.Lex();
1762 Value = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_None,
1763 getContext());
1764 } else if (Parser.parseExpression(Value))
1765 return reportParseError("expected valid expression after comma");
Jack Carterd76b2372013-03-21 21:44:16 +00001766
Jack Carterd0bd6422013-04-18 00:41:53 +00001767 // Check if the Name already exists as a symbol.
Jack Carterd76b2372013-03-21 21:44:16 +00001768 MCSymbol *Sym = getContext().LookupSymbol(Name);
Jack Carterd0bd6422013-04-18 00:41:53 +00001769 if (Sym)
Jack Carterd76b2372013-03-21 21:44:16 +00001770 return reportParseError("symbol already defined");
Jack Carterd76b2372013-03-21 21:44:16 +00001771 Sym = getContext().GetOrCreateSymbol(Name);
1772 Sym->setVariableValue(Value);
1773
1774 return false;
1775}
Jack Carterd0bd6422013-04-18 00:41:53 +00001776
Jack Carter0b744b32012-10-04 02:29:46 +00001777bool MipsAsmParser::parseDirectiveSet() {
1778
Jack Carterd0bd6422013-04-18 00:41:53 +00001779 // Get the next token.
Jack Carter0b744b32012-10-04 02:29:46 +00001780 const AsmToken &Tok = Parser.getTok();
1781
1782 if (Tok.getString() == "noat") {
1783 return parseSetNoAtDirective();
1784 } else if (Tok.getString() == "at") {
1785 return parseSetAtDirective();
1786 } else if (Tok.getString() == "reorder") {
1787 return parseSetReorderDirective();
1788 } else if (Tok.getString() == "noreorder") {
1789 return parseSetNoReorderDirective();
1790 } else if (Tok.getString() == "macro") {
1791 return parseSetMacroDirective();
1792 } else if (Tok.getString() == "nomacro") {
1793 return parseSetNoMacroDirective();
1794 } else if (Tok.getString() == "nomips16") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001795 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001796 Parser.eatToEndOfStatement();
Jack Carter0b744b32012-10-04 02:29:46 +00001797 return false;
1798 } else if (Tok.getString() == "nomicromips") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001799 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001800 Parser.eatToEndOfStatement();
Jack Carter0b744b32012-10-04 02:29:46 +00001801 return false;
Jack Carterd76b2372013-03-21 21:44:16 +00001802 } else {
Jack Carterd0bd6422013-04-18 00:41:53 +00001803 // It is just an identifier, look for an assignment.
Jack Carterd76b2372013-03-21 21:44:16 +00001804 parseSetAssignment();
1805 return false;
Jack Carter0b744b32012-10-04 02:29:46 +00001806 }
Jack Carter07c818d2013-01-25 01:31:34 +00001807
Jack Carter0b744b32012-10-04 02:29:46 +00001808 return true;
1809}
1810
Jack Carter07c818d2013-01-25 01:31:34 +00001811/// parseDirectiveWord
1812/// ::= .word [ expression (, expression)* ]
1813bool MipsAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
1814 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1815 for (;;) {
1816 const MCExpr *Value;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001817 if (getParser().parseExpression(Value))
Jack Carter07c818d2013-01-25 01:31:34 +00001818 return true;
1819
1820 getParser().getStreamer().EmitValue(Value, Size);
1821
1822 if (getLexer().is(AsmToken::EndOfStatement))
1823 break;
1824
1825 // FIXME: Improve diagnostic.
1826 if (getLexer().isNot(AsmToken::Comma))
1827 return Error(L, "unexpected token in directive");
1828 Parser.Lex();
1829 }
1830 }
1831
1832 Parser.Lex();
1833 return false;
1834}
1835
Jack Carter0b744b32012-10-04 02:29:46 +00001836bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
Jack Carterbe332172012-09-07 00:48:02 +00001837
Jack Carter07c818d2013-01-25 01:31:34 +00001838 StringRef IDVal = DirectiveID.getString();
1839
Jack Carterd0bd6422013-04-18 00:41:53 +00001840 if (IDVal == ".ent") {
1841 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00001842 Parser.Lex();
1843 return false;
1844 }
1845
Jack Carter07c818d2013-01-25 01:31:34 +00001846 if (IDVal == ".end") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001847 // Ignore this directive for now.
Jack Carterbe332172012-09-07 00:48:02 +00001848 Parser.Lex();
1849 return false;
1850 }
1851
Jack Carter07c818d2013-01-25 01:31:34 +00001852 if (IDVal == ".frame") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001853 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001854 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001855 return false;
1856 }
1857
Jack Carter07c818d2013-01-25 01:31:34 +00001858 if (IDVal == ".set") {
Jack Carter0b744b32012-10-04 02:29:46 +00001859 return parseDirectiveSet();
Jack Carterbe332172012-09-07 00:48:02 +00001860 }
1861
Jack Carter07c818d2013-01-25 01:31:34 +00001862 if (IDVal == ".fmask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001863 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001864 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001865 return false;
1866 }
1867
Jack Carter07c818d2013-01-25 01:31:34 +00001868 if (IDVal == ".mask") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001869 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001870 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001871 return false;
1872 }
1873
Jack Carter07c818d2013-01-25 01:31:34 +00001874 if (IDVal == ".gpword") {
Jack Carterd0bd6422013-04-18 00:41:53 +00001875 // Ignore this directive for now.
Jim Grosbachd2037eb2013-02-20 22:21:35 +00001876 Parser.eatToEndOfStatement();
Jack Carterbe332172012-09-07 00:48:02 +00001877 return false;
1878 }
1879
Jack Carter07c818d2013-01-25 01:31:34 +00001880 if (IDVal == ".word") {
1881 parseDirectiveWord(4, DirectiveID.getLoc());
1882 return false;
1883 }
1884
Rafael Espindola870c4e92012-01-11 03:56:41 +00001885 return true;
1886}
1887
Rafael Espindola870c4e92012-01-11 03:56:41 +00001888extern "C" void LLVMInitializeMipsAsmParser() {
1889 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
1890 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
1891 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
1892 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
1893}
Jack Carterb4dbc172012-09-05 23:34:03 +00001894
1895#define GET_REGISTER_MATCHER
1896#define GET_MATCHER_IMPLEMENTATION
1897#include "MipsGenAsmMatcher.inc"