blob: 349abef16be62cc1b7c4382cfd4c24776ca28bef [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"
16#include "llvm/MC/MCStreamer.h"
17#include "llvm/MC/MCSubtargetInfo.h"
18#include "llvm/MC/MCSymbol.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000019#include "llvm/MC/MCParser/MCAsmLexer.h"
Akira Hatanaka7605630c2012-08-17 20:16:42 +000020#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
21#include "llvm/MC/MCTargetAsmParser.h"
Jack Carterb4dbc172012-09-05 23:34:03 +000022#include "llvm/Support/TargetRegistry.h"
Rafael Espindola870c4e92012-01-11 03:56:41 +000023
24using namespace llvm;
25
26namespace {
Jack Carterb4dbc172012-09-05 23:34:03 +000027
Rafael Espindola870c4e92012-01-11 03:56:41 +000028class MipsAsmParser : public MCTargetAsmParser {
Akira Hatanaka7605630c2012-08-17 20:16:42 +000029
Jack Cartera63b16a2012-09-07 00:23:42 +000030 enum FpFormatTy {
31 FP_FORMAT_NONE = -1,
32 FP_FORMAT_S,
33 FP_FORMAT_D,
34 FP_FORMAT_L,
35 FP_FORMAT_W
36 } FpFormat;
37
Jack Carterb4dbc172012-09-05 23:34:03 +000038 MCSubtargetInfo &STI;
39 MCAsmParser &Parser;
40
Akira Hatanaka7605630c2012-08-17 20:16:42 +000041#define GET_ASSEMBLER_HEADER
42#include "MipsGenAsmMatcher.inc"
43
Rafael Espindola870c4e92012-01-11 03:56:41 +000044 bool MatchAndEmitInstruction(SMLoc IDLoc,
45 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
46 MCStreamer &Out);
47
48 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
49
50 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Akira Hatanaka7605630c2012-08-17 20:16:42 +000051 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Rafael Espindola870c4e92012-01-11 03:56:41 +000052
Jack Cartera63b16a2012-09-07 00:23:42 +000053 bool parseMathOperation(StringRef Name, SMLoc NameLoc,
54 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
55
Rafael Espindola870c4e92012-01-11 03:56:41 +000056 bool ParseDirective(AsmToken DirectiveID);
57
Jack Carterb4dbc172012-09-05 23:34:03 +000058 MipsAsmParser::OperandMatchResultTy
59 parseMemOperand(SmallVectorImpl<MCParsedAsmOperand*>&);
Chad Rosier391d29972012-09-03 18:47:45 +000060
Jack Carterb4dbc172012-09-05 23:34:03 +000061 bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &,
62 StringRef Mnemonic);
63
64 int tryParseRegister(StringRef Mnemonic);
65
66 bool tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
67 StringRef Mnemonic);
68
Jack Carterdc1e35d2012-09-06 20:00:02 +000069 bool parseMemOffset(const MCExpr *&Res);
70 bool parseRelocOperand(const MCExpr *&Res);
71 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Cartera63b16a2012-09-07 00:23:42 +000072
Jack Carterb4dbc172012-09-05 23:34:03 +000073 bool isMips64() const {
74 return (STI.getFeatureBits() & Mips::FeatureMips64) != 0;
75 }
76
Jack Cartera63b16a2012-09-07 00:23:42 +000077 bool isFP64() const {
78 return (STI.getFeatureBits() & Mips::FeatureFP64Bit) != 0;
79 }
80
Jack Carterb4dbc172012-09-05 23:34:03 +000081 int matchRegisterName(StringRef Symbol);
82
83 int matchRegisterByNumber(unsigned RegNum, StringRef Mnemonic);
84
Jack Cartera63b16a2012-09-07 00:23:42 +000085 void setFpFormat(FpFormatTy Format) {
86 FpFormat = Format;
87 }
88
89 void setDefaultFpFormat();
90
91 void setFpFormat(StringRef Format);
92
93 FpFormatTy getFpFormat() {return FpFormat;}
94
95 bool requestsDoubleOperand(StringRef Mnemonic);
96
Jack Carterb4dbc172012-09-05 23:34:03 +000097 unsigned getReg(int RC,int RegNo);
Chad Rosier391d29972012-09-03 18:47:45 +000098
Rafael Espindola870c4e92012-01-11 03:56:41 +000099public:
100 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser)
Jack Carterb4dbc172012-09-05 23:34:03 +0000101 : MCTargetAsmParser(), STI(sti), Parser(parser) {
102 // Initialize the set of available features.
103 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Rafael Espindola870c4e92012-01-11 03:56:41 +0000104 }
105
Jack Carterb4dbc172012-09-05 23:34:03 +0000106 MCAsmParser &getParser() const { return Parser; }
107 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
108
Rafael Espindola870c4e92012-01-11 03:56:41 +0000109};
110}
111
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000112namespace {
113
114/// MipsOperand - Instances of this class represent a parsed Mips machine
115/// instruction.
116class MipsOperand : public MCParsedAsmOperand {
Jack Carterb4dbc172012-09-05 23:34:03 +0000117
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000118 enum KindTy {
119 k_CondCode,
120 k_CoprocNum,
121 k_Immediate,
122 k_Memory,
123 k_PostIndexRegister,
124 k_Register,
125 k_Token
126 } Kind;
127
128 MipsOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
Jack Carterb4dbc172012-09-05 23:34:03 +0000129
130 union {
131 struct {
132 const char *Data;
133 unsigned Length;
134 } Tok;
135
136 struct {
137 unsigned RegNum;
138 } Reg;
139
140 struct {
141 const MCExpr *Val;
142 } Imm;
Jack Carterdc1e35d2012-09-06 20:00:02 +0000143
144 struct {
145 unsigned Base;
146 const MCExpr *Off;
147 } Mem;
Jack Carterb4dbc172012-09-05 23:34:03 +0000148 };
149
150 SMLoc StartLoc, EndLoc;
151
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000152public:
153 void addRegOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000154 assert(N == 1 && "Invalid number of operands!");
155 Inst.addOperand(MCOperand::CreateReg(getReg()));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000156 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000157
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000158 void addExpr(MCInst &Inst, const MCExpr *Expr) const{
Jack Carterb4dbc172012-09-05 23:34:03 +0000159 // Add as immediate when possible. Null MCExpr = 0.
160 if (Expr == 0)
161 Inst.addOperand(MCOperand::CreateImm(0));
162 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
163 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
164 else
165 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000166 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000167
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000168 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterb4dbc172012-09-05 23:34:03 +0000169 assert(N == 1 && "Invalid number of operands!");
170 const MCExpr *Expr = getImm();
171 addExpr(Inst,Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000172 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000173
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000174 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000175 assert(N == 2 && "Invalid number of operands!");
176
177 Inst.addOperand(MCOperand::CreateReg(getMemBase()));
178
179 const MCExpr *Expr = getMemOff();
180 addExpr(Inst,Expr);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000181 }
182
183 bool isReg() const { return Kind == k_Register; }
184 bool isImm() const { return Kind == k_Immediate; }
185 bool isToken() const { return Kind == k_Token; }
186 bool isMem() const { return Kind == k_Memory; }
187
188 StringRef getToken() const {
189 assert(Kind == k_Token && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000190 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000191 }
192
193 unsigned getReg() const {
194 assert((Kind == k_Register) && "Invalid access!");
Jack Carterb4dbc172012-09-05 23:34:03 +0000195 return Reg.RegNum;
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000196 }
197
Jack Carterb4dbc172012-09-05 23:34:03 +0000198 const MCExpr *getImm() const {
199 assert((Kind == k_Immediate) && "Invalid access!");
200 return Imm.Val;
201 }
202
Jack Carterdc1e35d2012-09-06 20:00:02 +0000203 unsigned getMemBase() const {
204 assert((Kind == k_Memory) && "Invalid access!");
205 return Mem.Base;
206 }
207
208 const MCExpr *getMemOff() const {
209 assert((Kind == k_Memory) && "Invalid access!");
210 return Mem.Off;
211 }
212
Jack Carterb4dbc172012-09-05 23:34:03 +0000213 static MipsOperand *CreateToken(StringRef Str, SMLoc S) {
214 MipsOperand *Op = new MipsOperand(k_Token);
215 Op->Tok.Data = Str.data();
216 Op->Tok.Length = Str.size();
217 Op->StartLoc = S;
218 Op->EndLoc = S;
219 return Op;
220 }
221
222 static MipsOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
223 MipsOperand *Op = new MipsOperand(k_Register);
224 Op->Reg.RegNum = RegNum;
225 Op->StartLoc = S;
226 Op->EndLoc = E;
227 return Op;
228 }
229
230 static MipsOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
231 MipsOperand *Op = new MipsOperand(k_Immediate);
232 Op->Imm.Val = Val;
233 Op->StartLoc = S;
234 Op->EndLoc = E;
235 return Op;
236 }
237
Jack Carterdc1e35d2012-09-06 20:00:02 +0000238 static MipsOperand *CreateMem(unsigned Base, const MCExpr *Off,
239 SMLoc S, SMLoc E) {
240 MipsOperand *Op = new MipsOperand(k_Memory);
241 Op->Mem.Base = Base;
242 Op->Mem.Off = Off;
243 Op->StartLoc = S;
244 Op->EndLoc = E;
245 return Op;
246 }
247
Jack Carterb4dbc172012-09-05 23:34:03 +0000248 /// getStartLoc - Get the location of the first token of this operand.
249 SMLoc getStartLoc() const { return StartLoc; }
250 /// getEndLoc - Get the location of the last token of this operand.
251 SMLoc getEndLoc() const { return EndLoc; }
252
Akira Hatanaka7605630c2012-08-17 20:16:42 +0000253 virtual void print(raw_ostream &OS) const {
254 llvm_unreachable("unimplemented!");
255 }
256};
257}
258
Rafael Espindola870c4e92012-01-11 03:56:41 +0000259bool MipsAsmParser::
260MatchAndEmitInstruction(SMLoc IDLoc,
261 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
262 MCStreamer &Out) {
Jack Carterb4dbc172012-09-05 23:34:03 +0000263 MCInst Inst;
Jack Carterb4dbc172012-09-05 23:34:03 +0000264 unsigned Kind;
Chad Rosierf4e35dc2012-10-01 23:45:51 +0000265 unsigned ErrorInfo;
266 SmallVector<std::pair< unsigned, std::string >, 4> MapAndConstraints;
267 unsigned MatchResult = MatchInstructionImpl(Operands, Kind, Inst,
268 MapAndConstraints, ErrorInfo,
269 /*matchingInlineAsm*/ false);
Jack Carterb4dbc172012-09-05 23:34:03 +0000270
271 switch (MatchResult) {
272 default: break;
273 case Match_Success: {
274 Inst.setLoc(IDLoc);
275 Out.EmitInstruction(Inst);
276 return false;
277 }
278 case Match_MissingFeature:
279 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
280 return true;
281 case Match_InvalidOperand: {
282 SMLoc ErrorLoc = IDLoc;
283 if (ErrorInfo != ~0U) {
284 if (ErrorInfo >= Operands.size())
285 return Error(IDLoc, "too few operands for instruction");
286
287 ErrorLoc = ((MipsOperand*)Operands[ErrorInfo])->getStartLoc();
288 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
289 }
290
291 return Error(ErrorLoc, "invalid operand for instruction");
292 }
293 case Match_MnemonicFail:
294 return Error(IDLoc, "invalid instruction");
295 }
Rafael Espindola870c4e92012-01-11 03:56:41 +0000296 return true;
297}
298
Jack Carterb4dbc172012-09-05 23:34:03 +0000299int MipsAsmParser::matchRegisterName(StringRef Name) {
300
301 int CC = StringSwitch<unsigned>(Name)
302 .Case("zero", Mips::ZERO)
303 .Case("a0", Mips::A0)
304 .Case("a1", Mips::A1)
305 .Case("a2", Mips::A2)
306 .Case("a3", Mips::A3)
307 .Case("v0", Mips::V0)
308 .Case("v1", Mips::V1)
309 .Case("s0", Mips::S0)
310 .Case("s1", Mips::S1)
311 .Case("s2", Mips::S2)
312 .Case("s3", Mips::S3)
313 .Case("s4", Mips::S4)
314 .Case("s5", Mips::S5)
315 .Case("s6", Mips::S6)
316 .Case("s7", Mips::S7)
317 .Case("k0", Mips::K0)
318 .Case("k1", Mips::K1)
319 .Case("sp", Mips::SP)
320 .Case("fp", Mips::FP)
321 .Case("gp", Mips::GP)
322 .Case("ra", Mips::RA)
323 .Case("t0", Mips::T0)
324 .Case("t1", Mips::T1)
325 .Case("t2", Mips::T2)
326 .Case("t3", Mips::T3)
327 .Case("t4", Mips::T4)
328 .Case("t5", Mips::T5)
329 .Case("t6", Mips::T6)
330 .Case("t7", Mips::T7)
331 .Case("t8", Mips::T8)
332 .Case("t9", Mips::T9)
333 .Case("at", Mips::AT)
334 .Case("fcc0", Mips::FCC0)
335 .Default(-1);
336
337 if (CC != -1) {
338 //64 bit register in Mips are following 32 bit definitions.
339 if (isMips64())
340 CC++;
341 return CC;
342 }
343
Jack Cartera63b16a2012-09-07 00:23:42 +0000344 if (Name[0] == 'f') {
345 StringRef NumString = Name.substr(1);
346 unsigned IntVal;
347 if( NumString.getAsInteger(10, IntVal))
348 return -1; //not integer
349 if (IntVal > 31)
350 return -1;
351
352 FpFormatTy Format = getFpFormat();
353
354 if (Format == FP_FORMAT_S || Format == FP_FORMAT_W)
355 return getReg(Mips::FGR32RegClassID, IntVal);
356 if (Format == FP_FORMAT_D) {
357 if(isFP64()) {
358 return getReg(Mips::FGR64RegClassID, IntVal);
359 }
360 //only even numbers available as register pairs
361 if (( IntVal > 31) || (IntVal%2 != 0))
362 return -1;
363 return getReg(Mips::AFGR64RegClassID, IntVal/2);
364 }
365 }
366
Jack Carterb4dbc172012-09-05 23:34:03 +0000367 return -1;
368}
Jack Cartera63b16a2012-09-07 00:23:42 +0000369void MipsAsmParser::setDefaultFpFormat() {
370
371 if (isMips64() || isFP64())
372 FpFormat = FP_FORMAT_D;
373 else
374 FpFormat = FP_FORMAT_S;
375}
376
377bool MipsAsmParser::requestsDoubleOperand(StringRef Mnemonic){
378
379 bool IsDouble = StringSwitch<bool>(Mnemonic.lower())
380 .Case("ldxc1", true)
381 .Case("ldc1", true)
382 .Case("sdxc1", true)
383 .Case("sdc1", true)
384 .Default(false);
385
386 return IsDouble;
387}
388void MipsAsmParser::setFpFormat(StringRef Format) {
389
390 FpFormat = StringSwitch<FpFormatTy>(Format.lower())
391 .Case(".s", FP_FORMAT_S)
392 .Case(".d", FP_FORMAT_D)
393 .Case(".l", FP_FORMAT_L)
394 .Case(".w", FP_FORMAT_W)
395 .Default(FP_FORMAT_NONE);
396}
Jack Carterb4dbc172012-09-05 23:34:03 +0000397
398unsigned MipsAsmParser::getReg(int RC,int RegNo){
399 return *(getContext().getRegisterInfo().getRegClass(RC).begin() + RegNo);
400}
401
402int MipsAsmParser::matchRegisterByNumber(unsigned RegNum,StringRef Mnemonic) {
403
404 if (Mnemonic.lower() == "rdhwr") {
405 //at the moment only hwreg29 is supported
406 if (RegNum != 29)
407 return -1;
408 return Mips::HWR29;
409 }
410
411 if (RegNum > 31)
412 return -1;
413
414 return getReg(Mips::CPURegsRegClassID,RegNum);
415}
416
417int MipsAsmParser::tryParseRegister(StringRef Mnemonic) {
418 const AsmToken &Tok = Parser.getTok();
419 int RegNum = -1;
420
421 if (Tok.is(AsmToken::Identifier)) {
422 std::string lowerCase = Tok.getString().lower();
423 RegNum = matchRegisterName(lowerCase);
424 } else if (Tok.is(AsmToken::Integer))
Jack Carterdc1e35d2012-09-06 20:00:02 +0000425 RegNum = matchRegisterByNumber(static_cast<unsigned> (Tok.getIntVal()),
426 Mnemonic.lower());
Jack Cartera63b16a2012-09-07 00:23:42 +0000427 else
428 return RegNum; //error
429 //64 bit div operations require Mips::ZERO instead of MIPS::ZERO_64
430 if (isMips64() && RegNum == Mips::ZERO_64) {
431 if (Mnemonic.find("ddiv") != StringRef::npos)
432 RegNum = Mips::ZERO;
433 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000434 return RegNum;
435}
436
Rafael Espindola870c4e92012-01-11 03:56:41 +0000437bool MipsAsmParser::
Jack Carterb4dbc172012-09-05 23:34:03 +0000438 tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
439 StringRef Mnemonic){
440
441 SMLoc S = Parser.getTok().getLoc();
442 int RegNo = -1;
Jack Cartera63b16a2012-09-07 00:23:42 +0000443
444 //FIXME: we should make a more generic method for CCR
445 if ((Mnemonic == "cfc1" || Mnemonic == "ctc1")
446 && Operands.size() == 2 && Parser.getTok().is(AsmToken::Integer)){
447 RegNo = Parser.getTok().getIntVal(); //get the int value
448 //at the moment only fcc0 is supported
449 if (RegNo == 0)
450 RegNo = Mips::FCC0;
451 } else
452 RegNo = tryParseRegister(Mnemonic);
Jack Carterb4dbc172012-09-05 23:34:03 +0000453 if (RegNo == -1)
454 return true;
455
456 Operands.push_back(MipsOperand::CreateReg(RegNo, S,
Jack Cartera63b16a2012-09-07 00:23:42 +0000457 Parser.getTok().getLoc()));
Jack Carterb4dbc172012-09-05 23:34:03 +0000458 Parser.Lex(); // Eat register token.
459 return false;
460}
461
462bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
463 StringRef Mnemonic) {
464 //Check if the current operand has a custom associated parser, if so, try to
465 //custom parse the operand, or fallback to the general approach.
466 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
467 if (ResTy == MatchOperand_Success)
468 return false;
469 // If there wasn't a custom match, try the generic matcher below. Otherwise,
470 // there was a match, but an error occurred, in which case, just return that
471 // the operand parsing failed.
472 if (ResTy == MatchOperand_ParseFail)
473 return true;
474
475 switch (getLexer().getKind()) {
476 default:
477 Error(Parser.getTok().getLoc(), "unexpected token in operand");
478 return true;
479 case AsmToken::Dollar: {
480 //parse register
481 SMLoc S = Parser.getTok().getLoc();
482 Parser.Lex(); // Eat dollar token.
483 //parse register operand
484 if (!tryParseRegisterOperand(Operands,Mnemonic)) {
485 if (getLexer().is(AsmToken::LParen)) {
486 //check if it is indexed addressing operand
487 Operands.push_back(MipsOperand::CreateToken("(", S));
488 Parser.Lex(); //eat parenthesis
489 if (getLexer().isNot(AsmToken::Dollar))
490 return true;
491
492 Parser.Lex(); //eat dollar
493 if (tryParseRegisterOperand(Operands,Mnemonic))
494 return true;
495
496 if (!getLexer().is(AsmToken::RParen))
497 return true;
498
499 S = Parser.getTok().getLoc();
500 Operands.push_back(MipsOperand::CreateToken(")", S));
501 Parser.Lex();
502 }
503 return false;
504 }
505 //maybe it is a symbol reference
506 StringRef Identifier;
507 if (Parser.ParseIdentifier(Identifier))
508 return true;
509
Jack Carterdc1e35d2012-09-06 20:00:02 +0000510 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb4dbc172012-09-05 23:34:03 +0000511
Benjamin Kramerfa530572012-09-07 09:47:42 +0000512 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterb4dbc172012-09-05 23:34:03 +0000513
514 // Otherwise create a symbol ref.
Jack Carterdc1e35d2012-09-06 20:00:02 +0000515 const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
Jack Carterb4dbc172012-09-05 23:34:03 +0000516 getContext());
517
518 Operands.push_back(MipsOperand::CreateImm(Res, S, E));
519 return false;
520 }
521 case AsmToken::Identifier:
522 case AsmToken::LParen:
523 case AsmToken::Minus:
524 case AsmToken::Plus:
525 case AsmToken::Integer:
526 case AsmToken::String: {
527 // quoted label names
528 const MCExpr *IdVal;
529 SMLoc S = Parser.getTok().getLoc();
530 if (getParser().ParseExpression(IdVal))
531 return true;
Jack Carterdc1e35d2012-09-06 20:00:02 +0000532 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterb4dbc172012-09-05 23:34:03 +0000533 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
534 return false;
535 }
Jack Carterdc1e35d2012-09-06 20:00:02 +0000536 case AsmToken::Percent: {
537 //it is a symbol reference or constant expression
538 const MCExpr *IdVal;
539 SMLoc S = Parser.getTok().getLoc(); //start location of the operand
540 if (parseRelocOperand(IdVal))
541 return true;
542
543 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
544
545 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
546 return false;
547 }//case AsmToken::Percent
Jack Carterb4dbc172012-09-05 23:34:03 +0000548 }//switch(getLexer().getKind())
Rafael Espindola870c4e92012-01-11 03:56:41 +0000549 return true;
550}
551
Jack Carterdc1e35d2012-09-06 20:00:02 +0000552bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
553
554 Parser.Lex(); //eat % token
555 const AsmToken &Tok = Parser.getTok(); //get next token, operation
556 if (Tok.isNot(AsmToken::Identifier))
557 return true;
558
Benjamin Kramerfa530572012-09-07 09:47:42 +0000559 std::string Str = Tok.getIdentifier().str();
Jack Carterdc1e35d2012-09-06 20:00:02 +0000560
561 Parser.Lex(); //eat identifier
562 //now make expression from the rest of the operand
563 const MCExpr *IdVal;
564 SMLoc EndLoc;
565
566 if (getLexer().getKind() == AsmToken::LParen) {
567 while (1) {
568 Parser.Lex(); //eat '(' token
569 if (getLexer().getKind() == AsmToken::Percent) {
570 Parser.Lex(); //eat % token
571 const AsmToken &nextTok = Parser.getTok();
572 if (nextTok.isNot(AsmToken::Identifier))
573 return true;
Benjamin Kramerfa530572012-09-07 09:47:42 +0000574 Str += "(%";
575 Str += nextTok.getIdentifier();
Jack Carterdc1e35d2012-09-06 20:00:02 +0000576 Parser.Lex(); //eat identifier
577 if (getLexer().getKind() != AsmToken::LParen)
578 return true;
579 } else
580 break;
581 }
582 if (getParser().ParseParenExpression(IdVal,EndLoc))
583 return true;
584
585 while (getLexer().getKind() == AsmToken::RParen)
586 Parser.Lex(); //eat ')' token
587
588 } else
589 return true; //parenthesis must follow reloc operand
590
Jack Carterdc1e35d2012-09-06 20:00:02 +0000591 //Check the type of the expression
Benjamin Kramerfa530572012-09-07 09:47:42 +0000592 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000593 //it's a constant, evaluate lo or hi value
Benjamin Kramerfa530572012-09-07 09:47:42 +0000594 int Val = MCE->getValue();
Jack Carterdc1e35d2012-09-06 20:00:02 +0000595 if (Str == "lo") {
596 Val = Val & 0xffff;
597 } else if (Str == "hi") {
598 Val = (Val & 0xffff0000) >> 16;
599 }
600 Res = MCConstantExpr::Create(Val, getContext());
601 return false;
602 }
603
Benjamin Kramerfa530572012-09-07 09:47:42 +0000604 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(IdVal)) {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000605 //it's a symbol, create symbolic expression from symbol
Benjamin Kramerfa530572012-09-07 09:47:42 +0000606 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carterdc1e35d2012-09-06 20:00:02 +0000607 MCSymbolRefExpr::VariantKind VK = getVariantKind(Str);
608 Res = MCSymbolRefExpr::Create(Symbol,VK,getContext());
609 return false;
610 }
611 return true;
612}
613
Jack Carterb4dbc172012-09-05 23:34:03 +0000614bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
615 SMLoc &EndLoc) {
616
617 StartLoc = Parser.getTok().getLoc();
618 RegNo = tryParseRegister("");
619 EndLoc = Parser.getTok().getLoc();
620 return (RegNo == (unsigned)-1);
621}
622
Jack Carterdc1e35d2012-09-06 20:00:02 +0000623bool MipsAsmParser::parseMemOffset(const MCExpr *&Res) {
624
625 SMLoc S;
626
627 switch(getLexer().getKind()) {
628 default:
629 return true;
630 case AsmToken::Integer:
631 case AsmToken::Minus:
632 case AsmToken::Plus:
633 return (getParser().ParseExpression(Res));
Jack Cartera63b16a2012-09-07 00:23:42 +0000634 case AsmToken::Percent:
Jack Carterdc1e35d2012-09-06 20:00:02 +0000635 return parseRelocOperand(Res);
Jack Carterdc1e35d2012-09-06 20:00:02 +0000636 case AsmToken::LParen:
637 return false; //it's probably assuming 0
638 }
639 return true;
640}
641
Jack Carterb4dbc172012-09-05 23:34:03 +0000642MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
643 SmallVectorImpl<MCParsedAsmOperand*>&Operands) {
Jack Carterdc1e35d2012-09-06 20:00:02 +0000644
645 const MCExpr *IdVal = 0;
646 SMLoc S;
647 //first operand is the offset
648 S = Parser.getTok().getLoc();
649
650 if (parseMemOffset(IdVal))
651 return MatchOperand_ParseFail;
652
653 const AsmToken &Tok = Parser.getTok(); //get next token
654 if (Tok.isNot(AsmToken::LParen)) {
655 Error(Parser.getTok().getLoc(), "'(' expected");
656 return MatchOperand_ParseFail;
657 }
658
659 Parser.Lex(); // Eat '(' token.
660
661 const AsmToken &Tok1 = Parser.getTok(); //get next token
662 if (Tok1.is(AsmToken::Dollar)) {
663 Parser.Lex(); // Eat '$' token.
664 if (tryParseRegisterOperand(Operands,"")) {
665 Error(Parser.getTok().getLoc(), "unexpected token in operand");
666 return MatchOperand_ParseFail;
667 }
668
669 } else {
670 Error(Parser.getTok().getLoc(),"unexpected token in operand");
671 return MatchOperand_ParseFail;
672 }
673
674 const AsmToken &Tok2 = Parser.getTok(); //get next token
675 if (Tok2.isNot(AsmToken::RParen)) {
676 Error(Parser.getTok().getLoc(), "')' expected");
677 return MatchOperand_ParseFail;
678 }
679
680 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
681
682 Parser.Lex(); // Eat ')' token.
683
684 if (IdVal == 0)
685 IdVal = MCConstantExpr::Create(0, getContext());
686
687 //now replace register operand with the mem operand
688 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
689 int RegNo = op->getReg();
690 //remove register from operands
691 Operands.pop_back();
692 //and add memory operand
693 Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
694 delete op;
Jack Carterb4dbc172012-09-05 23:34:03 +0000695 return MatchOperand_Success;
696}
697
Jack Carterdc1e35d2012-09-06 20:00:02 +0000698MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
699
700 MCSymbolRefExpr::VariantKind VK
701 = StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
702 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
703 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
704 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
705 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
706 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
707 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
708 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
709 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
710 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
711 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
712 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
713 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
714 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
715 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
716 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
717 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
718 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
719 .Default(MCSymbolRefExpr::VK_None);
720
721 return VK;
722}
723
Benjamin Kramer47b5c572012-09-10 11:52:14 +0000724static int ConvertCcString(StringRef CondString) {
Jack Cartera63b16a2012-09-07 00:23:42 +0000725 int CC = StringSwitch<unsigned>(CondString)
726 .Case(".f", 0)
727 .Case(".un", 1)
728 .Case(".eq", 2)
729 .Case(".ueq", 3)
730 .Case(".olt", 4)
731 .Case(".ult", 5)
732 .Case(".ole", 6)
733 .Case(".ule", 7)
734 .Case(".sf", 8)
735 .Case(".ngle", 9)
736 .Case(".seq", 10)
737 .Case(".ngl", 11)
738 .Case(".lt", 12)
739 .Case(".nge", 13)
740 .Case(".le", 14)
741 .Case(".ngt", 15)
742 .Default(-1);
743
744 return CC;
745}
746
747bool MipsAsmParser::
748parseMathOperation(StringRef Name, SMLoc NameLoc,
749 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
750 //split the format
751 size_t Start = Name.find('.'), Next = Name.rfind('.');
752 StringRef Format1 = Name.slice(Start, Next);
753 //and add the first format to the operands
754 Operands.push_back(MipsOperand::CreateToken(Format1, NameLoc));
755 //now for the second format
756 StringRef Format2 = Name.slice(Next, StringRef::npos);
757 Operands.push_back(MipsOperand::CreateToken(Format2, NameLoc));
758
759 //set the format for the first register
760 setFpFormat(Format1);
761
762 // Read the remaining operands.
763 if (getLexer().isNot(AsmToken::EndOfStatement)) {
764 // Read the first operand.
765 if (ParseOperand(Operands, Name)) {
766 SMLoc Loc = getLexer().getLoc();
767 Parser.EatToEndOfStatement();
768 return Error(Loc, "unexpected token in argument list");
769 }
770
771 if (getLexer().isNot(AsmToken::Comma)) {
772 SMLoc Loc = getLexer().getLoc();
773 Parser.EatToEndOfStatement();
774 return Error(Loc, "unexpected token in argument list");
775
776 }
777 Parser.Lex(); // Eat the comma.
778
779 //set the format for the first register
780 setFpFormat(Format2);
781
782 // Parse and remember the operand.
783 if (ParseOperand(Operands, Name)) {
784 SMLoc Loc = getLexer().getLoc();
785 Parser.EatToEndOfStatement();
786 return Error(Loc, "unexpected token in argument list");
787 }
788 }
789
790 if (getLexer().isNot(AsmToken::EndOfStatement)) {
791 SMLoc Loc = getLexer().getLoc();
792 Parser.EatToEndOfStatement();
793 return Error(Loc, "unexpected token in argument list");
794 }
795
796 Parser.Lex(); // Consume the EndOfStatement
797 return false;
798}
799
Rafael Espindola870c4e92012-01-11 03:56:41 +0000800bool MipsAsmParser::
801ParseInstruction(StringRef Name, SMLoc NameLoc,
802 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jack Cartera63b16a2012-09-07 00:23:42 +0000803 //floating point instructions: should register be treated as double?
804 if (requestsDoubleOperand(Name)) {
805 setFpFormat(FP_FORMAT_D);
Jack Carterb4dbc172012-09-05 23:34:03 +0000806 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
Jack Cartera63b16a2012-09-07 00:23:42 +0000807 }
808 else {
809 setDefaultFpFormat();
810 // Create the leading tokens for the mnemonic, split by '.' characters.
811 size_t Start = 0, Next = Name.find('.');
812 StringRef Mnemonic = Name.slice(Start, Next);
813
814 Operands.push_back(MipsOperand::CreateToken(Mnemonic, NameLoc));
815
816 if (Next != StringRef::npos) {
817 //there is a format token in mnemonic
818 //StringRef Rest = Name.slice(Next, StringRef::npos);
819 size_t Dot = Name.find('.', Next+1);
820 StringRef Format = Name.slice(Next, Dot);
821 if (Dot == StringRef::npos) //only one '.' in a string, it's a format
822 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
823 else {
824 if (Name.startswith("c.")){
825 // floating point compare, add '.' and immediate represent for cc
826 Operands.push_back(MipsOperand::CreateToken(".", NameLoc));
827 int Cc = ConvertCcString(Format);
828 if (Cc == -1) {
829 return Error(NameLoc, "Invalid conditional code");
830 }
831 SMLoc E = SMLoc::getFromPointer(
832 Parser.getTok().getLoc().getPointer() -1 );
833 Operands.push_back(MipsOperand::CreateImm(
834 MCConstantExpr::Create(Cc, getContext()), NameLoc, E));
835 } else {
836 //trunc, ceil, floor ...
837 return parseMathOperation(Name, NameLoc, Operands);
838 }
839
840 //the rest is a format
841 Format = Name.slice(Dot, StringRef::npos);
842 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
843 }
844
845 setFpFormat(Format);
846 }
847 }
Jack Carterb4dbc172012-09-05 23:34:03 +0000848
849 // Read the remaining operands.
850 if (getLexer().isNot(AsmToken::EndOfStatement)) {
851 // Read the first operand.
852 if (ParseOperand(Operands, Name)) {
853 SMLoc Loc = getLexer().getLoc();
854 Parser.EatToEndOfStatement();
855 return Error(Loc, "unexpected token in argument list");
856 }
857
858 while (getLexer().is(AsmToken::Comma) ) {
859 Parser.Lex(); // Eat the comma.
860
861 // Parse and remember the operand.
862 if (ParseOperand(Operands, Name)) {
863 SMLoc Loc = getLexer().getLoc();
864 Parser.EatToEndOfStatement();
865 return Error(Loc, "unexpected token in argument list");
866 }
867 }
868 }
869
870 if (getLexer().isNot(AsmToken::EndOfStatement)) {
871 SMLoc Loc = getLexer().getLoc();
872 Parser.EatToEndOfStatement();
873 return Error(Loc, "unexpected token in argument list");
874 }
875
876 Parser.Lex(); // Consume the EndOfStatement
877 return false;
Rafael Espindola870c4e92012-01-11 03:56:41 +0000878}
879
880bool MipsAsmParser::
881ParseDirective(AsmToken DirectiveID) {
Jack Carterbe332172012-09-07 00:48:02 +0000882
883 if (DirectiveID.getString() == ".ent") {
884 //ignore this directive for now
885 Parser.Lex();
886 return false;
887 }
888
889 if (DirectiveID.getString() == ".end") {
890 //ignore this directive for now
891 Parser.Lex();
892 return false;
893 }
894
895 if (DirectiveID.getString() == ".frame") {
896 //ignore this directive for now
897 Parser.EatToEndOfStatement();
898 return false;
899 }
900
901 if (DirectiveID.getString() == ".set") {
902 //ignore this directive for now
903 Parser.EatToEndOfStatement();
904 return false;
905 }
906
907 if (DirectiveID.getString() == ".fmask") {
908 //ignore this directive for now
909 Parser.EatToEndOfStatement();
910 return false;
911 }
912
913 if (DirectiveID.getString() == ".mask") {
914 //ignore this directive for now
915 Parser.EatToEndOfStatement();
916 return false;
917 }
918
919 if (DirectiveID.getString() == ".gpword") {
920 //ignore this directive for now
921 Parser.EatToEndOfStatement();
922 return false;
923 }
924
Rafael Espindola870c4e92012-01-11 03:56:41 +0000925 return true;
926}
927
Rafael Espindola870c4e92012-01-11 03:56:41 +0000928extern "C" void LLVMInitializeMipsAsmParser() {
929 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
930 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
931 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
932 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
933}
Jack Carterb4dbc172012-09-05 23:34:03 +0000934
935#define GET_REGISTER_MATCHER
936#define GET_MATCHER_IMPLEMENTATION
937#include "MipsGenAsmMatcher.inc"