blob: b1ada100f4956c7438af267fdc87d8688649d40e [file] [log] [blame]
Jia Liuc5707112012-02-17 08:55:11 +00001//===-- MipsAsmParser.cpp - Parse Mips assembly to MCInst instructions ----===//
Rafael Espindolafddf8042012-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 Carterec65be82012-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 Espindolafddf8042012-01-11 03:56:41 +000019#include "llvm/MC/MCParser/MCAsmLexer.h"
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +000020#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
21#include "llvm/MC/MCTargetAsmParser.h"
Jack Carterec65be82012-09-05 23:34:03 +000022#include "llvm/Support/TargetRegistry.h"
Rafael Espindolafddf8042012-01-11 03:56:41 +000023
24using namespace llvm;
25
26namespace {
Jack Carterec65be82012-09-05 23:34:03 +000027
Rafael Espindolafddf8042012-01-11 03:56:41 +000028class MipsAsmParser : public MCTargetAsmParser {
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +000029
Jack Carterf740d6e2012-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 Carterec65be82012-09-05 23:34:03 +000038 MCSubtargetInfo &STI;
39 MCAsmParser &Parser;
40
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +000041#define GET_ASSEMBLER_HEADER
42#include "MipsGenAsmMatcher.inc"
43
Rafael Espindolafddf8042012-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 Hatanaka72e9b6a2012-08-17 20:16:42 +000051 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Rafael Espindolafddf8042012-01-11 03:56:41 +000052
Jack Carterf740d6e2012-09-07 00:23:42 +000053 bool parseMathOperation(StringRef Name, SMLoc NameLoc,
54 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
55
Rafael Espindolafddf8042012-01-11 03:56:41 +000056 bool ParseDirective(AsmToken DirectiveID);
57
Jack Carterec65be82012-09-05 23:34:03 +000058 MipsAsmParser::OperandMatchResultTy
59 parseMemOperand(SmallVectorImpl<MCParsedAsmOperand*>&);
Chad Rosier038f3e32012-09-03 18:47:45 +000060
Jack Carterec65be82012-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 Carter6b96c3f2012-09-06 20:00:02 +000069 bool parseMemOffset(const MCExpr *&Res);
70 bool parseRelocOperand(const MCExpr *&Res);
71 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Carterf740d6e2012-09-07 00:23:42 +000072
Jack Carterec65be82012-09-05 23:34:03 +000073 bool isMips64() const {
74 return (STI.getFeatureBits() & Mips::FeatureMips64) != 0;
75 }
76
Jack Carterf740d6e2012-09-07 00:23:42 +000077 bool isFP64() const {
78 return (STI.getFeatureBits() & Mips::FeatureFP64Bit) != 0;
79 }
80
Jack Carterec65be82012-09-05 23:34:03 +000081 int matchRegisterName(StringRef Symbol);
82
83 int matchRegisterByNumber(unsigned RegNum, StringRef Mnemonic);
84
Jack Carterf740d6e2012-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 Carterec65be82012-09-05 23:34:03 +000097 unsigned getReg(int RC,int RegNo);
Chad Rosier038f3e32012-09-03 18:47:45 +000098
Rafael Espindolafddf8042012-01-11 03:56:41 +000099public:
100 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser)
Jack Carterec65be82012-09-05 23:34:03 +0000101 : MCTargetAsmParser(), STI(sti), Parser(parser) {
102 // Initialize the set of available features.
103 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Rafael Espindolafddf8042012-01-11 03:56:41 +0000104 }
105
Jack Carterec65be82012-09-05 23:34:03 +0000106 MCAsmParser &getParser() const { return Parser; }
107 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
108
Rafael Espindolafddf8042012-01-11 03:56:41 +0000109};
110}
111
Akira Hatanaka72e9b6a2012-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 Carterec65be82012-09-05 23:34:03 +0000117
Akira Hatanaka72e9b6a2012-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 Carterec65be82012-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 Carter6b96c3f2012-09-06 20:00:02 +0000143
144 struct {
145 unsigned Base;
146 const MCExpr *Off;
147 } Mem;
Jack Carterec65be82012-09-05 23:34:03 +0000148 };
149
150 SMLoc StartLoc, EndLoc;
151
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000152public:
153 void addRegOperands(MCInst &Inst, unsigned N) const {
Jack Carterec65be82012-09-05 23:34:03 +0000154 assert(N == 1 && "Invalid number of operands!");
155 Inst.addOperand(MCOperand::CreateReg(getReg()));
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000156 }
Jack Carterec65be82012-09-05 23:34:03 +0000157
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000158 void addExpr(MCInst &Inst, const MCExpr *Expr) const{
Jack Carterec65be82012-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 Hatanaka72e9b6a2012-08-17 20:16:42 +0000166 }
Jack Carterec65be82012-09-05 23:34:03 +0000167
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000168 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterec65be82012-09-05 23:34:03 +0000169 assert(N == 1 && "Invalid number of operands!");
170 const MCExpr *Expr = getImm();
171 addExpr(Inst,Expr);
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000172 }
Jack Carterec65be82012-09-05 23:34:03 +0000173
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000174 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carter6b96c3f2012-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 Hatanaka72e9b6a2012-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 Carterec65be82012-09-05 23:34:03 +0000190 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000191 }
192
193 unsigned getReg() const {
194 assert((Kind == k_Register) && "Invalid access!");
Jack Carterec65be82012-09-05 23:34:03 +0000195 return Reg.RegNum;
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000196 }
197
Jack Carterec65be82012-09-05 23:34:03 +0000198 const MCExpr *getImm() const {
199 assert((Kind == k_Immediate) && "Invalid access!");
200 return Imm.Val;
201 }
202
Jack Carter6b96c3f2012-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 Carterec65be82012-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 Carter6b96c3f2012-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 Carterec65be82012-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 Hatanaka72e9b6a2012-08-17 20:16:42 +0000253 virtual void print(raw_ostream &OS) const {
254 llvm_unreachable("unimplemented!");
255 }
256};
257}
258
Rafael Espindolafddf8042012-01-11 03:56:41 +0000259bool MipsAsmParser::
260MatchAndEmitInstruction(SMLoc IDLoc,
261 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
262 MCStreamer &Out) {
Jack Carterec65be82012-09-05 23:34:03 +0000263 MCInst Inst;
264 unsigned ErrorInfo;
265 unsigned Kind;
266 unsigned MatchResult = MatchInstructionImpl(Operands, Kind, Inst, ErrorInfo);
267
268 switch (MatchResult) {
269 default: break;
270 case Match_Success: {
271 Inst.setLoc(IDLoc);
272 Out.EmitInstruction(Inst);
273 return false;
274 }
275 case Match_MissingFeature:
276 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
277 return true;
278 case Match_InvalidOperand: {
279 SMLoc ErrorLoc = IDLoc;
280 if (ErrorInfo != ~0U) {
281 if (ErrorInfo >= Operands.size())
282 return Error(IDLoc, "too few operands for instruction");
283
284 ErrorLoc = ((MipsOperand*)Operands[ErrorInfo])->getStartLoc();
285 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
286 }
287
288 return Error(ErrorLoc, "invalid operand for instruction");
289 }
290 case Match_MnemonicFail:
291 return Error(IDLoc, "invalid instruction");
292 }
Rafael Espindolafddf8042012-01-11 03:56:41 +0000293 return true;
294}
295
Jack Carterec65be82012-09-05 23:34:03 +0000296int MipsAsmParser::matchRegisterName(StringRef Name) {
297
298 int CC = StringSwitch<unsigned>(Name)
299 .Case("zero", Mips::ZERO)
300 .Case("a0", Mips::A0)
301 .Case("a1", Mips::A1)
302 .Case("a2", Mips::A2)
303 .Case("a3", Mips::A3)
304 .Case("v0", Mips::V0)
305 .Case("v1", Mips::V1)
306 .Case("s0", Mips::S0)
307 .Case("s1", Mips::S1)
308 .Case("s2", Mips::S2)
309 .Case("s3", Mips::S3)
310 .Case("s4", Mips::S4)
311 .Case("s5", Mips::S5)
312 .Case("s6", Mips::S6)
313 .Case("s7", Mips::S7)
314 .Case("k0", Mips::K0)
315 .Case("k1", Mips::K1)
316 .Case("sp", Mips::SP)
317 .Case("fp", Mips::FP)
318 .Case("gp", Mips::GP)
319 .Case("ra", Mips::RA)
320 .Case("t0", Mips::T0)
321 .Case("t1", Mips::T1)
322 .Case("t2", Mips::T2)
323 .Case("t3", Mips::T3)
324 .Case("t4", Mips::T4)
325 .Case("t5", Mips::T5)
326 .Case("t6", Mips::T6)
327 .Case("t7", Mips::T7)
328 .Case("t8", Mips::T8)
329 .Case("t9", Mips::T9)
330 .Case("at", Mips::AT)
331 .Case("fcc0", Mips::FCC0)
332 .Default(-1);
333
334 if (CC != -1) {
335 //64 bit register in Mips are following 32 bit definitions.
336 if (isMips64())
337 CC++;
338 return CC;
339 }
340
Jack Carterf740d6e2012-09-07 00:23:42 +0000341 if (Name[0] == 'f') {
342 StringRef NumString = Name.substr(1);
343 unsigned IntVal;
344 if( NumString.getAsInteger(10, IntVal))
345 return -1; //not integer
346 if (IntVal > 31)
347 return -1;
348
349 FpFormatTy Format = getFpFormat();
350
351 if (Format == FP_FORMAT_S || Format == FP_FORMAT_W)
352 return getReg(Mips::FGR32RegClassID, IntVal);
353 if (Format == FP_FORMAT_D) {
354 if(isFP64()) {
355 return getReg(Mips::FGR64RegClassID, IntVal);
356 }
357 //only even numbers available as register pairs
358 if (( IntVal > 31) || (IntVal%2 != 0))
359 return -1;
360 return getReg(Mips::AFGR64RegClassID, IntVal/2);
361 }
362 }
363
Jack Carterec65be82012-09-05 23:34:03 +0000364 return -1;
365}
Jack Carterf740d6e2012-09-07 00:23:42 +0000366void MipsAsmParser::setDefaultFpFormat() {
367
368 if (isMips64() || isFP64())
369 FpFormat = FP_FORMAT_D;
370 else
371 FpFormat = FP_FORMAT_S;
372}
373
374bool MipsAsmParser::requestsDoubleOperand(StringRef Mnemonic){
375
376 bool IsDouble = StringSwitch<bool>(Mnemonic.lower())
377 .Case("ldxc1", true)
378 .Case("ldc1", true)
379 .Case("sdxc1", true)
380 .Case("sdc1", true)
381 .Default(false);
382
383 return IsDouble;
384}
385void MipsAsmParser::setFpFormat(StringRef Format) {
386
387 FpFormat = StringSwitch<FpFormatTy>(Format.lower())
388 .Case(".s", FP_FORMAT_S)
389 .Case(".d", FP_FORMAT_D)
390 .Case(".l", FP_FORMAT_L)
391 .Case(".w", FP_FORMAT_W)
392 .Default(FP_FORMAT_NONE);
393}
Jack Carterec65be82012-09-05 23:34:03 +0000394
395unsigned MipsAsmParser::getReg(int RC,int RegNo){
396 return *(getContext().getRegisterInfo().getRegClass(RC).begin() + RegNo);
397}
398
399int MipsAsmParser::matchRegisterByNumber(unsigned RegNum,StringRef Mnemonic) {
400
401 if (Mnemonic.lower() == "rdhwr") {
402 //at the moment only hwreg29 is supported
403 if (RegNum != 29)
404 return -1;
405 return Mips::HWR29;
406 }
407
408 if (RegNum > 31)
409 return -1;
410
411 return getReg(Mips::CPURegsRegClassID,RegNum);
412}
413
414int MipsAsmParser::tryParseRegister(StringRef Mnemonic) {
415 const AsmToken &Tok = Parser.getTok();
416 int RegNum = -1;
417
418 if (Tok.is(AsmToken::Identifier)) {
419 std::string lowerCase = Tok.getString().lower();
420 RegNum = matchRegisterName(lowerCase);
421 } else if (Tok.is(AsmToken::Integer))
Jack Carter6b96c3f2012-09-06 20:00:02 +0000422 RegNum = matchRegisterByNumber(static_cast<unsigned> (Tok.getIntVal()),
423 Mnemonic.lower());
Jack Carterf740d6e2012-09-07 00:23:42 +0000424 else
425 return RegNum; //error
426 //64 bit div operations require Mips::ZERO instead of MIPS::ZERO_64
427 if (isMips64() && RegNum == Mips::ZERO_64) {
428 if (Mnemonic.find("ddiv") != StringRef::npos)
429 RegNum = Mips::ZERO;
430 }
Jack Carterec65be82012-09-05 23:34:03 +0000431 return RegNum;
432}
433
Rafael Espindolafddf8042012-01-11 03:56:41 +0000434bool MipsAsmParser::
Jack Carterec65be82012-09-05 23:34:03 +0000435 tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
436 StringRef Mnemonic){
437
438 SMLoc S = Parser.getTok().getLoc();
439 int RegNo = -1;
Jack Carterf740d6e2012-09-07 00:23:42 +0000440
441 //FIXME: we should make a more generic method for CCR
442 if ((Mnemonic == "cfc1" || Mnemonic == "ctc1")
443 && Operands.size() == 2 && Parser.getTok().is(AsmToken::Integer)){
444 RegNo = Parser.getTok().getIntVal(); //get the int value
445 //at the moment only fcc0 is supported
446 if (RegNo == 0)
447 RegNo = Mips::FCC0;
448 } else
449 RegNo = tryParseRegister(Mnemonic);
Jack Carterec65be82012-09-05 23:34:03 +0000450 if (RegNo == -1)
451 return true;
452
453 Operands.push_back(MipsOperand::CreateReg(RegNo, S,
Jack Carterf740d6e2012-09-07 00:23:42 +0000454 Parser.getTok().getLoc()));
Jack Carterec65be82012-09-05 23:34:03 +0000455 Parser.Lex(); // Eat register token.
456 return false;
457}
458
459bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
460 StringRef Mnemonic) {
461 //Check if the current operand has a custom associated parser, if so, try to
462 //custom parse the operand, or fallback to the general approach.
463 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
464 if (ResTy == MatchOperand_Success)
465 return false;
466 // If there wasn't a custom match, try the generic matcher below. Otherwise,
467 // there was a match, but an error occurred, in which case, just return that
468 // the operand parsing failed.
469 if (ResTy == MatchOperand_ParseFail)
470 return true;
471
472 switch (getLexer().getKind()) {
473 default:
474 Error(Parser.getTok().getLoc(), "unexpected token in operand");
475 return true;
476 case AsmToken::Dollar: {
477 //parse register
478 SMLoc S = Parser.getTok().getLoc();
479 Parser.Lex(); // Eat dollar token.
480 //parse register operand
481 if (!tryParseRegisterOperand(Operands,Mnemonic)) {
482 if (getLexer().is(AsmToken::LParen)) {
483 //check if it is indexed addressing operand
484 Operands.push_back(MipsOperand::CreateToken("(", S));
485 Parser.Lex(); //eat parenthesis
486 if (getLexer().isNot(AsmToken::Dollar))
487 return true;
488
489 Parser.Lex(); //eat dollar
490 if (tryParseRegisterOperand(Operands,Mnemonic))
491 return true;
492
493 if (!getLexer().is(AsmToken::RParen))
494 return true;
495
496 S = Parser.getTok().getLoc();
497 Operands.push_back(MipsOperand::CreateToken(")", S));
498 Parser.Lex();
499 }
500 return false;
501 }
502 //maybe it is a symbol reference
503 StringRef Identifier;
504 if (Parser.ParseIdentifier(Identifier))
505 return true;
506
Jack Carter6b96c3f2012-09-06 20:00:02 +0000507 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterec65be82012-09-05 23:34:03 +0000508
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000509 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterec65be82012-09-05 23:34:03 +0000510
511 // Otherwise create a symbol ref.
Jack Carter6b96c3f2012-09-06 20:00:02 +0000512 const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
Jack Carterec65be82012-09-05 23:34:03 +0000513 getContext());
514
515 Operands.push_back(MipsOperand::CreateImm(Res, S, E));
516 return false;
517 }
518 case AsmToken::Identifier:
519 case AsmToken::LParen:
520 case AsmToken::Minus:
521 case AsmToken::Plus:
522 case AsmToken::Integer:
523 case AsmToken::String: {
524 // quoted label names
525 const MCExpr *IdVal;
526 SMLoc S = Parser.getTok().getLoc();
527 if (getParser().ParseExpression(IdVal))
528 return true;
Jack Carter6b96c3f2012-09-06 20:00:02 +0000529 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterec65be82012-09-05 23:34:03 +0000530 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
531 return false;
532 }
Jack Carter6b96c3f2012-09-06 20:00:02 +0000533 case AsmToken::Percent: {
534 //it is a symbol reference or constant expression
535 const MCExpr *IdVal;
536 SMLoc S = Parser.getTok().getLoc(); //start location of the operand
537 if (parseRelocOperand(IdVal))
538 return true;
539
540 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
541
542 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
543 return false;
544 }//case AsmToken::Percent
Jack Carterec65be82012-09-05 23:34:03 +0000545 }//switch(getLexer().getKind())
Rafael Espindolafddf8042012-01-11 03:56:41 +0000546 return true;
547}
548
Jack Carter6b96c3f2012-09-06 20:00:02 +0000549bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
550
551 Parser.Lex(); //eat % token
552 const AsmToken &Tok = Parser.getTok(); //get next token, operation
553 if (Tok.isNot(AsmToken::Identifier))
554 return true;
555
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000556 std::string Str = Tok.getIdentifier().str();
Jack Carter6b96c3f2012-09-06 20:00:02 +0000557
558 Parser.Lex(); //eat identifier
559 //now make expression from the rest of the operand
560 const MCExpr *IdVal;
561 SMLoc EndLoc;
562
563 if (getLexer().getKind() == AsmToken::LParen) {
564 while (1) {
565 Parser.Lex(); //eat '(' token
566 if (getLexer().getKind() == AsmToken::Percent) {
567 Parser.Lex(); //eat % token
568 const AsmToken &nextTok = Parser.getTok();
569 if (nextTok.isNot(AsmToken::Identifier))
570 return true;
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000571 Str += "(%";
572 Str += nextTok.getIdentifier();
Jack Carter6b96c3f2012-09-06 20:00:02 +0000573 Parser.Lex(); //eat identifier
574 if (getLexer().getKind() != AsmToken::LParen)
575 return true;
576 } else
577 break;
578 }
579 if (getParser().ParseParenExpression(IdVal,EndLoc))
580 return true;
581
582 while (getLexer().getKind() == AsmToken::RParen)
583 Parser.Lex(); //eat ')' token
584
585 } else
586 return true; //parenthesis must follow reloc operand
587
Jack Carter6b96c3f2012-09-06 20:00:02 +0000588 //Check the type of the expression
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000589 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal)) {
Jack Carter6b96c3f2012-09-06 20:00:02 +0000590 //it's a constant, evaluate lo or hi value
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000591 int Val = MCE->getValue();
Jack Carter6b96c3f2012-09-06 20:00:02 +0000592 if (Str == "lo") {
593 Val = Val & 0xffff;
594 } else if (Str == "hi") {
595 Val = (Val & 0xffff0000) >> 16;
596 }
597 Res = MCConstantExpr::Create(Val, getContext());
598 return false;
599 }
600
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000601 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(IdVal)) {
Jack Carter6b96c3f2012-09-06 20:00:02 +0000602 //it's a symbol, create symbolic expression from symbol
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000603 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carter6b96c3f2012-09-06 20:00:02 +0000604 MCSymbolRefExpr::VariantKind VK = getVariantKind(Str);
605 Res = MCSymbolRefExpr::Create(Symbol,VK,getContext());
606 return false;
607 }
608 return true;
609}
610
Jack Carterec65be82012-09-05 23:34:03 +0000611bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
612 SMLoc &EndLoc) {
613
614 StartLoc = Parser.getTok().getLoc();
615 RegNo = tryParseRegister("");
616 EndLoc = Parser.getTok().getLoc();
617 return (RegNo == (unsigned)-1);
618}
619
Jack Carter6b96c3f2012-09-06 20:00:02 +0000620bool MipsAsmParser::parseMemOffset(const MCExpr *&Res) {
621
622 SMLoc S;
623
624 switch(getLexer().getKind()) {
625 default:
626 return true;
627 case AsmToken::Integer:
628 case AsmToken::Minus:
629 case AsmToken::Plus:
630 return (getParser().ParseExpression(Res));
Jack Carterf740d6e2012-09-07 00:23:42 +0000631 case AsmToken::Percent:
Jack Carter6b96c3f2012-09-06 20:00:02 +0000632 return parseRelocOperand(Res);
Jack Carter6b96c3f2012-09-06 20:00:02 +0000633 case AsmToken::LParen:
634 return false; //it's probably assuming 0
635 }
636 return true;
637}
638
Jack Carterec65be82012-09-05 23:34:03 +0000639MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
640 SmallVectorImpl<MCParsedAsmOperand*>&Operands) {
Jack Carter6b96c3f2012-09-06 20:00:02 +0000641
642 const MCExpr *IdVal = 0;
643 SMLoc S;
644 //first operand is the offset
645 S = Parser.getTok().getLoc();
646
647 if (parseMemOffset(IdVal))
648 return MatchOperand_ParseFail;
649
650 const AsmToken &Tok = Parser.getTok(); //get next token
651 if (Tok.isNot(AsmToken::LParen)) {
652 Error(Parser.getTok().getLoc(), "'(' expected");
653 return MatchOperand_ParseFail;
654 }
655
656 Parser.Lex(); // Eat '(' token.
657
658 const AsmToken &Tok1 = Parser.getTok(); //get next token
659 if (Tok1.is(AsmToken::Dollar)) {
660 Parser.Lex(); // Eat '$' token.
661 if (tryParseRegisterOperand(Operands,"")) {
662 Error(Parser.getTok().getLoc(), "unexpected token in operand");
663 return MatchOperand_ParseFail;
664 }
665
666 } else {
667 Error(Parser.getTok().getLoc(),"unexpected token in operand");
668 return MatchOperand_ParseFail;
669 }
670
671 const AsmToken &Tok2 = Parser.getTok(); //get next token
672 if (Tok2.isNot(AsmToken::RParen)) {
673 Error(Parser.getTok().getLoc(), "')' expected");
674 return MatchOperand_ParseFail;
675 }
676
677 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
678
679 Parser.Lex(); // Eat ')' token.
680
681 if (IdVal == 0)
682 IdVal = MCConstantExpr::Create(0, getContext());
683
684 //now replace register operand with the mem operand
685 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
686 int RegNo = op->getReg();
687 //remove register from operands
688 Operands.pop_back();
689 //and add memory operand
690 Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
691 delete op;
Jack Carterec65be82012-09-05 23:34:03 +0000692 return MatchOperand_Success;
693}
694
Jack Carter6b96c3f2012-09-06 20:00:02 +0000695MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
696
697 MCSymbolRefExpr::VariantKind VK
698 = StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
699 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
700 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
701 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
702 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
703 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
704 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
705 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
706 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
707 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
708 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
709 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
710 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
711 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
712 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
713 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
714 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
715 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
716 .Default(MCSymbolRefExpr::VK_None);
717
718 return VK;
719}
720
Benjamin Kramer1ac45872012-09-10 11:52:14 +0000721static int ConvertCcString(StringRef CondString) {
Jack Carterf740d6e2012-09-07 00:23:42 +0000722 int CC = StringSwitch<unsigned>(CondString)
723 .Case(".f", 0)
724 .Case(".un", 1)
725 .Case(".eq", 2)
726 .Case(".ueq", 3)
727 .Case(".olt", 4)
728 .Case(".ult", 5)
729 .Case(".ole", 6)
730 .Case(".ule", 7)
731 .Case(".sf", 8)
732 .Case(".ngle", 9)
733 .Case(".seq", 10)
734 .Case(".ngl", 11)
735 .Case(".lt", 12)
736 .Case(".nge", 13)
737 .Case(".le", 14)
738 .Case(".ngt", 15)
739 .Default(-1);
740
741 return CC;
742}
743
744bool MipsAsmParser::
745parseMathOperation(StringRef Name, SMLoc NameLoc,
746 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
747 //split the format
748 size_t Start = Name.find('.'), Next = Name.rfind('.');
749 StringRef Format1 = Name.slice(Start, Next);
750 //and add the first format to the operands
751 Operands.push_back(MipsOperand::CreateToken(Format1, NameLoc));
752 //now for the second format
753 StringRef Format2 = Name.slice(Next, StringRef::npos);
754 Operands.push_back(MipsOperand::CreateToken(Format2, NameLoc));
755
756 //set the format for the first register
757 setFpFormat(Format1);
758
759 // Read the remaining operands.
760 if (getLexer().isNot(AsmToken::EndOfStatement)) {
761 // Read the first operand.
762 if (ParseOperand(Operands, Name)) {
763 SMLoc Loc = getLexer().getLoc();
764 Parser.EatToEndOfStatement();
765 return Error(Loc, "unexpected token in argument list");
766 }
767
768 if (getLexer().isNot(AsmToken::Comma)) {
769 SMLoc Loc = getLexer().getLoc();
770 Parser.EatToEndOfStatement();
771 return Error(Loc, "unexpected token in argument list");
772
773 }
774 Parser.Lex(); // Eat the comma.
775
776 //set the format for the first register
777 setFpFormat(Format2);
778
779 // Parse and remember the operand.
780 if (ParseOperand(Operands, Name)) {
781 SMLoc Loc = getLexer().getLoc();
782 Parser.EatToEndOfStatement();
783 return Error(Loc, "unexpected token in argument list");
784 }
785 }
786
787 if (getLexer().isNot(AsmToken::EndOfStatement)) {
788 SMLoc Loc = getLexer().getLoc();
789 Parser.EatToEndOfStatement();
790 return Error(Loc, "unexpected token in argument list");
791 }
792
793 Parser.Lex(); // Consume the EndOfStatement
794 return false;
795}
796
Rafael Espindolafddf8042012-01-11 03:56:41 +0000797bool MipsAsmParser::
798ParseInstruction(StringRef Name, SMLoc NameLoc,
799 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jack Carterf740d6e2012-09-07 00:23:42 +0000800 //floating point instructions: should register be treated as double?
801 if (requestsDoubleOperand(Name)) {
802 setFpFormat(FP_FORMAT_D);
Jack Carterec65be82012-09-05 23:34:03 +0000803 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
Jack Carterf740d6e2012-09-07 00:23:42 +0000804 }
805 else {
806 setDefaultFpFormat();
807 // Create the leading tokens for the mnemonic, split by '.' characters.
808 size_t Start = 0, Next = Name.find('.');
809 StringRef Mnemonic = Name.slice(Start, Next);
810
811 Operands.push_back(MipsOperand::CreateToken(Mnemonic, NameLoc));
812
813 if (Next != StringRef::npos) {
814 //there is a format token in mnemonic
815 //StringRef Rest = Name.slice(Next, StringRef::npos);
816 size_t Dot = Name.find('.', Next+1);
817 StringRef Format = Name.slice(Next, Dot);
818 if (Dot == StringRef::npos) //only one '.' in a string, it's a format
819 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
820 else {
821 if (Name.startswith("c.")){
822 // floating point compare, add '.' and immediate represent for cc
823 Operands.push_back(MipsOperand::CreateToken(".", NameLoc));
824 int Cc = ConvertCcString(Format);
825 if (Cc == -1) {
826 return Error(NameLoc, "Invalid conditional code");
827 }
828 SMLoc E = SMLoc::getFromPointer(
829 Parser.getTok().getLoc().getPointer() -1 );
830 Operands.push_back(MipsOperand::CreateImm(
831 MCConstantExpr::Create(Cc, getContext()), NameLoc, E));
832 } else {
833 //trunc, ceil, floor ...
834 return parseMathOperation(Name, NameLoc, Operands);
835 }
836
837 //the rest is a format
838 Format = Name.slice(Dot, StringRef::npos);
839 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
840 }
841
842 setFpFormat(Format);
843 }
844 }
Jack Carterec65be82012-09-05 23:34:03 +0000845
846 // Read the remaining operands.
847 if (getLexer().isNot(AsmToken::EndOfStatement)) {
848 // Read the first operand.
849 if (ParseOperand(Operands, Name)) {
850 SMLoc Loc = getLexer().getLoc();
851 Parser.EatToEndOfStatement();
852 return Error(Loc, "unexpected token in argument list");
853 }
854
855 while (getLexer().is(AsmToken::Comma) ) {
856 Parser.Lex(); // Eat the comma.
857
858 // Parse and remember the operand.
859 if (ParseOperand(Operands, Name)) {
860 SMLoc Loc = getLexer().getLoc();
861 Parser.EatToEndOfStatement();
862 return Error(Loc, "unexpected token in argument list");
863 }
864 }
865 }
866
867 if (getLexer().isNot(AsmToken::EndOfStatement)) {
868 SMLoc Loc = getLexer().getLoc();
869 Parser.EatToEndOfStatement();
870 return Error(Loc, "unexpected token in argument list");
871 }
872
873 Parser.Lex(); // Consume the EndOfStatement
874 return false;
Rafael Espindolafddf8042012-01-11 03:56:41 +0000875}
876
877bool MipsAsmParser::
878ParseDirective(AsmToken DirectiveID) {
Jack Carteracbea452012-09-07 00:48:02 +0000879
880 if (DirectiveID.getString() == ".ent") {
881 //ignore this directive for now
882 Parser.Lex();
883 return false;
884 }
885
886 if (DirectiveID.getString() == ".end") {
887 //ignore this directive for now
888 Parser.Lex();
889 return false;
890 }
891
892 if (DirectiveID.getString() == ".frame") {
893 //ignore this directive for now
894 Parser.EatToEndOfStatement();
895 return false;
896 }
897
898 if (DirectiveID.getString() == ".set") {
899 //ignore this directive for now
900 Parser.EatToEndOfStatement();
901 return false;
902 }
903
904 if (DirectiveID.getString() == ".fmask") {
905 //ignore this directive for now
906 Parser.EatToEndOfStatement();
907 return false;
908 }
909
910 if (DirectiveID.getString() == ".mask") {
911 //ignore this directive for now
912 Parser.EatToEndOfStatement();
913 return false;
914 }
915
916 if (DirectiveID.getString() == ".gpword") {
917 //ignore this directive for now
918 Parser.EatToEndOfStatement();
919 return false;
920 }
921
Rafael Espindolafddf8042012-01-11 03:56:41 +0000922 return true;
923}
924
Rafael Espindolafddf8042012-01-11 03:56:41 +0000925extern "C" void LLVMInitializeMipsAsmParser() {
926 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
927 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
928 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
929 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
930}
Jack Carterec65be82012-09-05 23:34:03 +0000931
932#define GET_REGISTER_MATCHER
933#define GET_MATCHER_IMPLEMENTATION
934#include "MipsGenAsmMatcher.inc"