blob: 54b422642ae7b51b4a8e2d426b2f1038a677d1e5 [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 Carterec65be82012-09-05 23:34:03 +000030 MCSubtargetInfo &STI;
31 MCAsmParser &Parser;
32
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +000033#define GET_ASSEMBLER_HEADER
34#include "MipsGenAsmMatcher.inc"
35
Rafael Espindolafddf8042012-01-11 03:56:41 +000036 bool MatchAndEmitInstruction(SMLoc IDLoc,
37 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
38 MCStreamer &Out);
39
40 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
41
42 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +000043 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Rafael Espindolafddf8042012-01-11 03:56:41 +000044
45 bool ParseDirective(AsmToken DirectiveID);
46
Jack Carterec65be82012-09-05 23:34:03 +000047 MipsAsmParser::OperandMatchResultTy
48 parseMemOperand(SmallVectorImpl<MCParsedAsmOperand*>&);
Chad Rosier038f3e32012-09-03 18:47:45 +000049
Jack Carterec65be82012-09-05 23:34:03 +000050 unsigned
51 getMCInstOperandNum(unsigned Kind, MCInst &Inst,
52 const SmallVectorImpl<MCParsedAsmOperand*> &Operands,
53 unsigned OperandNum, unsigned &NumMCOperands);
54
55 bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &,
56 StringRef Mnemonic);
57
58 int tryParseRegister(StringRef Mnemonic);
59
60 bool tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
61 StringRef Mnemonic);
62
63 bool isMips64() const {
64 return (STI.getFeatureBits() & Mips::FeatureMips64) != 0;
65 }
66
67 int matchRegisterName(StringRef Symbol);
68
69 int matchRegisterByNumber(unsigned RegNum, StringRef Mnemonic);
70
71 unsigned getReg(int RC,int RegNo);
Chad Rosier038f3e32012-09-03 18:47:45 +000072
Rafael Espindolafddf8042012-01-11 03:56:41 +000073public:
74 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser)
Jack Carterec65be82012-09-05 23:34:03 +000075 : MCTargetAsmParser(), STI(sti), Parser(parser) {
76 // Initialize the set of available features.
77 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Rafael Espindolafddf8042012-01-11 03:56:41 +000078 }
79
Jack Carterec65be82012-09-05 23:34:03 +000080 MCAsmParser &getParser() const { return Parser; }
81 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
82
Rafael Espindolafddf8042012-01-11 03:56:41 +000083};
84}
85
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +000086namespace {
87
88/// MipsOperand - Instances of this class represent a parsed Mips machine
89/// instruction.
90class MipsOperand : public MCParsedAsmOperand {
Jack Carterec65be82012-09-05 23:34:03 +000091
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +000092 enum KindTy {
93 k_CondCode,
94 k_CoprocNum,
95 k_Immediate,
96 k_Memory,
97 k_PostIndexRegister,
98 k_Register,
99 k_Token
100 } Kind;
101
102 MipsOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
Jack Carterec65be82012-09-05 23:34:03 +0000103
104 union {
105 struct {
106 const char *Data;
107 unsigned Length;
108 } Tok;
109
110 struct {
111 unsigned RegNum;
112 } Reg;
113
114 struct {
115 const MCExpr *Val;
116 } Imm;
117 };
118
119 SMLoc StartLoc, EndLoc;
120
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000121public:
122 void addRegOperands(MCInst &Inst, unsigned N) const {
Jack Carterec65be82012-09-05 23:34:03 +0000123 assert(N == 1 && "Invalid number of operands!");
124 Inst.addOperand(MCOperand::CreateReg(getReg()));
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000125 }
Jack Carterec65be82012-09-05 23:34:03 +0000126
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000127 void addExpr(MCInst &Inst, const MCExpr *Expr) const{
Jack Carterec65be82012-09-05 23:34:03 +0000128 // Add as immediate when possible. Null MCExpr = 0.
129 if (Expr == 0)
130 Inst.addOperand(MCOperand::CreateImm(0));
131 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
132 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
133 else
134 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000135 }
Jack Carterec65be82012-09-05 23:34:03 +0000136
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000137 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterec65be82012-09-05 23:34:03 +0000138 assert(N == 1 && "Invalid number of operands!");
139 const MCExpr *Expr = getImm();
140 addExpr(Inst,Expr);
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000141 }
Jack Carterec65be82012-09-05 23:34:03 +0000142
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000143 void addMemOperands(MCInst &Inst, unsigned N) const {
144 llvm_unreachable("unimplemented!");
145 }
146
147 bool isReg() const { return Kind == k_Register; }
148 bool isImm() const { return Kind == k_Immediate; }
149 bool isToken() const { return Kind == k_Token; }
150 bool isMem() const { return Kind == k_Memory; }
151
152 StringRef getToken() const {
153 assert(Kind == k_Token && "Invalid access!");
Jack Carterec65be82012-09-05 23:34:03 +0000154 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000155 }
156
157 unsigned getReg() const {
158 assert((Kind == k_Register) && "Invalid access!");
Jack Carterec65be82012-09-05 23:34:03 +0000159 return Reg.RegNum;
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000160 }
161
Jack Carterec65be82012-09-05 23:34:03 +0000162 const MCExpr *getImm() const {
163 assert((Kind == k_Immediate) && "Invalid access!");
164 return Imm.Val;
165 }
166
167 static MipsOperand *CreateToken(StringRef Str, SMLoc S) {
168 MipsOperand *Op = new MipsOperand(k_Token);
169 Op->Tok.Data = Str.data();
170 Op->Tok.Length = Str.size();
171 Op->StartLoc = S;
172 Op->EndLoc = S;
173 return Op;
174 }
175
176 static MipsOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
177 MipsOperand *Op = new MipsOperand(k_Register);
178 Op->Reg.RegNum = RegNum;
179 Op->StartLoc = S;
180 Op->EndLoc = E;
181 return Op;
182 }
183
184 static MipsOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
185 MipsOperand *Op = new MipsOperand(k_Immediate);
186 Op->Imm.Val = Val;
187 Op->StartLoc = S;
188 Op->EndLoc = E;
189 return Op;
190 }
191
192 /// getStartLoc - Get the location of the first token of this operand.
193 SMLoc getStartLoc() const { return StartLoc; }
194 /// getEndLoc - Get the location of the last token of this operand.
195 SMLoc getEndLoc() const { return EndLoc; }
196
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000197 virtual void print(raw_ostream &OS) const {
198 llvm_unreachable("unimplemented!");
199 }
200};
201}
202
Chad Rosier038f3e32012-09-03 18:47:45 +0000203unsigned MipsAsmParser::
Chad Rosier5d637d72012-09-05 01:15:43 +0000204getMCInstOperandNum(unsigned Kind, MCInst &Inst,
Chad Rosier038f3e32012-09-03 18:47:45 +0000205 const SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Chad Rosier2cc97de2012-09-03 20:31:23 +0000206 unsigned OperandNum, unsigned &NumMCOperands) {
Chad Rosier5d637d72012-09-05 01:15:43 +0000207 assert (0 && "getMCInstOperandNum() not supported by the Mips target.");
Chad Rosierefeaae82012-09-03 19:04:35 +0000208 // The Mips backend doesn't currently include the matcher implementation, so
Chad Rosier5d637d72012-09-05 01:15:43 +0000209 // the getMCInstOperandNumImpl() is undefined. This is a temporary
Chad Rosierefeaae82012-09-03 19:04:35 +0000210 // work around.
Chad Rosier2cc97de2012-09-03 20:31:23 +0000211 NumMCOperands = 0;
Chad Rosier038f3e32012-09-03 18:47:45 +0000212 return 0;
213}
214
Rafael Espindolafddf8042012-01-11 03:56:41 +0000215bool MipsAsmParser::
216MatchAndEmitInstruction(SMLoc IDLoc,
217 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
218 MCStreamer &Out) {
Jack Carterec65be82012-09-05 23:34:03 +0000219 MCInst Inst;
220 unsigned ErrorInfo;
221 unsigned Kind;
222 unsigned MatchResult = MatchInstructionImpl(Operands, Kind, Inst, ErrorInfo);
223
224 switch (MatchResult) {
225 default: break;
226 case Match_Success: {
227 Inst.setLoc(IDLoc);
228 Out.EmitInstruction(Inst);
229 return false;
230 }
231 case Match_MissingFeature:
232 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
233 return true;
234 case Match_InvalidOperand: {
235 SMLoc ErrorLoc = IDLoc;
236 if (ErrorInfo != ~0U) {
237 if (ErrorInfo >= Operands.size())
238 return Error(IDLoc, "too few operands for instruction");
239
240 ErrorLoc = ((MipsOperand*)Operands[ErrorInfo])->getStartLoc();
241 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
242 }
243
244 return Error(ErrorLoc, "invalid operand for instruction");
245 }
246 case Match_MnemonicFail:
247 return Error(IDLoc, "invalid instruction");
248 }
Rafael Espindolafddf8042012-01-11 03:56:41 +0000249 return true;
250}
251
Jack Carterec65be82012-09-05 23:34:03 +0000252int MipsAsmParser::matchRegisterName(StringRef Name) {
253
254 int CC = StringSwitch<unsigned>(Name)
255 .Case("zero", Mips::ZERO)
256 .Case("a0", Mips::A0)
257 .Case("a1", Mips::A1)
258 .Case("a2", Mips::A2)
259 .Case("a3", Mips::A3)
260 .Case("v0", Mips::V0)
261 .Case("v1", Mips::V1)
262 .Case("s0", Mips::S0)
263 .Case("s1", Mips::S1)
264 .Case("s2", Mips::S2)
265 .Case("s3", Mips::S3)
266 .Case("s4", Mips::S4)
267 .Case("s5", Mips::S5)
268 .Case("s6", Mips::S6)
269 .Case("s7", Mips::S7)
270 .Case("k0", Mips::K0)
271 .Case("k1", Mips::K1)
272 .Case("sp", Mips::SP)
273 .Case("fp", Mips::FP)
274 .Case("gp", Mips::GP)
275 .Case("ra", Mips::RA)
276 .Case("t0", Mips::T0)
277 .Case("t1", Mips::T1)
278 .Case("t2", Mips::T2)
279 .Case("t3", Mips::T3)
280 .Case("t4", Mips::T4)
281 .Case("t5", Mips::T5)
282 .Case("t6", Mips::T6)
283 .Case("t7", Mips::T7)
284 .Case("t8", Mips::T8)
285 .Case("t9", Mips::T9)
286 .Case("at", Mips::AT)
287 .Case("fcc0", Mips::FCC0)
288 .Default(-1);
289
290 if (CC != -1) {
291 //64 bit register in Mips are following 32 bit definitions.
292 if (isMips64())
293 CC++;
294 return CC;
295 }
296
297 return -1;
298}
299
300unsigned MipsAsmParser::getReg(int RC,int RegNo){
301 return *(getContext().getRegisterInfo().getRegClass(RC).begin() + RegNo);
302}
303
304int MipsAsmParser::matchRegisterByNumber(unsigned RegNum,StringRef Mnemonic) {
305
306 if (Mnemonic.lower() == "rdhwr") {
307 //at the moment only hwreg29 is supported
308 if (RegNum != 29)
309 return -1;
310 return Mips::HWR29;
311 }
312
313 if (RegNum > 31)
314 return -1;
315
316 return getReg(Mips::CPURegsRegClassID,RegNum);
317}
318
319int MipsAsmParser::tryParseRegister(StringRef Mnemonic) {
320 const AsmToken &Tok = Parser.getTok();
321 int RegNum = -1;
322
323 if (Tok.is(AsmToken::Identifier)) {
324 std::string lowerCase = Tok.getString().lower();
325 RegNum = matchRegisterName(lowerCase);
326 } else if (Tok.is(AsmToken::Integer))
327 RegNum = matchRegisterByNumber(static_cast<unsigned> (Tok.getIntVal()),
328 Mnemonic.lower());
329 return RegNum;
330}
331
Rafael Espindolafddf8042012-01-11 03:56:41 +0000332bool MipsAsmParser::
Jack Carterec65be82012-09-05 23:34:03 +0000333 tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
334 StringRef Mnemonic){
335
336 SMLoc S = Parser.getTok().getLoc();
337 int RegNo = -1;
338 RegNo = tryParseRegister(Mnemonic);
339 if (RegNo == -1)
340 return true;
341
342 Operands.push_back(MipsOperand::CreateReg(RegNo, S,
343 Parser.getTok().getLoc()));
344 Parser.Lex(); // Eat register token.
345 return false;
346}
347
348bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
349 StringRef Mnemonic) {
350 //Check if the current operand has a custom associated parser, if so, try to
351 //custom parse the operand, or fallback to the general approach.
352 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
353 if (ResTy == MatchOperand_Success)
354 return false;
355 // If there wasn't a custom match, try the generic matcher below. Otherwise,
356 // there was a match, but an error occurred, in which case, just return that
357 // the operand parsing failed.
358 if (ResTy == MatchOperand_ParseFail)
359 return true;
360
361 switch (getLexer().getKind()) {
362 default:
363 Error(Parser.getTok().getLoc(), "unexpected token in operand");
364 return true;
365 case AsmToken::Dollar: {
366 //parse register
367 SMLoc S = Parser.getTok().getLoc();
368 Parser.Lex(); // Eat dollar token.
369 //parse register operand
370 if (!tryParseRegisterOperand(Operands,Mnemonic)) {
371 if (getLexer().is(AsmToken::LParen)) {
372 //check if it is indexed addressing operand
373 Operands.push_back(MipsOperand::CreateToken("(", S));
374 Parser.Lex(); //eat parenthesis
375 if (getLexer().isNot(AsmToken::Dollar))
376 return true;
377
378 Parser.Lex(); //eat dollar
379 if (tryParseRegisterOperand(Operands,Mnemonic))
380 return true;
381
382 if (!getLexer().is(AsmToken::RParen))
383 return true;
384
385 S = Parser.getTok().getLoc();
386 Operands.push_back(MipsOperand::CreateToken(")", S));
387 Parser.Lex();
388 }
389 return false;
390 }
391 //maybe it is a symbol reference
392 StringRef Identifier;
393 if (Parser.ParseIdentifier(Identifier))
394 return true;
395
396 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer()-1);
397
398 StringRef Id = StringRef("$" + Identifier.str());
399 MCSymbol *Sym = getContext().GetOrCreateSymbol(Id);
400
401 // Otherwise create a symbol ref.
402 const MCExpr *Res = MCSymbolRefExpr::Create(Sym,
403 MCSymbolRefExpr::VK_None,
404 getContext());
405
406 Operands.push_back(MipsOperand::CreateImm(Res, S, E));
407 return false;
408 }
409 case AsmToken::Identifier:
410 case AsmToken::LParen:
411 case AsmToken::Minus:
412 case AsmToken::Plus:
413 case AsmToken::Integer:
414 case AsmToken::String: {
415 // quoted label names
416 const MCExpr *IdVal;
417 SMLoc S = Parser.getTok().getLoc();
418 if (getParser().ParseExpression(IdVal))
419 return true;
420 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer()-1);
421 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
422 return false;
423 }
424 }//switch(getLexer().getKind())
Rafael Espindolafddf8042012-01-11 03:56:41 +0000425 return true;
426}
427
Jack Carterec65be82012-09-05 23:34:03 +0000428bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
429 SMLoc &EndLoc) {
430
431 StartLoc = Parser.getTok().getLoc();
432 RegNo = tryParseRegister("");
433 EndLoc = Parser.getTok().getLoc();
434 return (RegNo == (unsigned)-1);
435}
436
437MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
438 SmallVectorImpl<MCParsedAsmOperand*>&Operands) {
439 return MatchOperand_Success;
440}
441
Rafael Espindolafddf8042012-01-11 03:56:41 +0000442bool MipsAsmParser::
443ParseInstruction(StringRef Name, SMLoc NameLoc,
444 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jack Carterec65be82012-09-05 23:34:03 +0000445
446 //first operand is a instruction mnemonic
447 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
448
449 // Read the remaining operands.
450 if (getLexer().isNot(AsmToken::EndOfStatement)) {
451 // Read the first operand.
452 if (ParseOperand(Operands, Name)) {
453 SMLoc Loc = getLexer().getLoc();
454 Parser.EatToEndOfStatement();
455 return Error(Loc, "unexpected token in argument list");
456 }
457
458 while (getLexer().is(AsmToken::Comma) ) {
459 Parser.Lex(); // Eat the comma.
460
461 // Parse and remember the operand.
462 if (ParseOperand(Operands, Name)) {
463 SMLoc Loc = getLexer().getLoc();
464 Parser.EatToEndOfStatement();
465 return Error(Loc, "unexpected token in argument list");
466 }
467 }
468 }
469
470 if (getLexer().isNot(AsmToken::EndOfStatement)) {
471 SMLoc Loc = getLexer().getLoc();
472 Parser.EatToEndOfStatement();
473 return Error(Loc, "unexpected token in argument list");
474 }
475
476 Parser.Lex(); // Consume the EndOfStatement
477 return false;
Rafael Espindolafddf8042012-01-11 03:56:41 +0000478}
479
480bool MipsAsmParser::
481ParseDirective(AsmToken DirectiveID) {
482 return true;
483}
484
Rafael Espindolafddf8042012-01-11 03:56:41 +0000485extern "C" void LLVMInitializeMipsAsmParser() {
486 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
487 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
488 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
489 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
490}
Jack Carterec65be82012-09-05 23:34:03 +0000491
492#define GET_REGISTER_MATCHER
493#define GET_MATCHER_IMPLEMENTATION
494#include "MipsGenAsmMatcher.inc"