blob: acdd8463f72629c327af7e3a675874626e95faa0 [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 unsigned
62 getMCInstOperandNum(unsigned Kind, MCInst &Inst,
63 const SmallVectorImpl<MCParsedAsmOperand*> &Operands,
64 unsigned OperandNum, unsigned &NumMCOperands);
65
66 bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &,
67 StringRef Mnemonic);
68
69 int tryParseRegister(StringRef Mnemonic);
70
71 bool tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
72 StringRef Mnemonic);
73
Jack Carter6b96c3f2012-09-06 20:00:02 +000074 bool parseMemOffset(const MCExpr *&Res);
75 bool parseRelocOperand(const MCExpr *&Res);
76 MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
Jack Carterf740d6e2012-09-07 00:23:42 +000077
Jack Carterec65be82012-09-05 23:34:03 +000078 bool isMips64() const {
79 return (STI.getFeatureBits() & Mips::FeatureMips64) != 0;
80 }
81
Jack Carterf740d6e2012-09-07 00:23:42 +000082 bool isFP64() const {
83 return (STI.getFeatureBits() & Mips::FeatureFP64Bit) != 0;
84 }
85
Jack Carterec65be82012-09-05 23:34:03 +000086 int matchRegisterName(StringRef Symbol);
87
88 int matchRegisterByNumber(unsigned RegNum, StringRef Mnemonic);
89
Jack Carterf740d6e2012-09-07 00:23:42 +000090 void setFpFormat(FpFormatTy Format) {
91 FpFormat = Format;
92 }
93
94 void setDefaultFpFormat();
95
96 void setFpFormat(StringRef Format);
97
98 FpFormatTy getFpFormat() {return FpFormat;}
99
100 bool requestsDoubleOperand(StringRef Mnemonic);
101
Jack Carterec65be82012-09-05 23:34:03 +0000102 unsigned getReg(int RC,int RegNo);
Chad Rosier038f3e32012-09-03 18:47:45 +0000103
Rafael Espindolafddf8042012-01-11 03:56:41 +0000104public:
105 MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser)
Jack Carterec65be82012-09-05 23:34:03 +0000106 : MCTargetAsmParser(), STI(sti), Parser(parser) {
107 // Initialize the set of available features.
108 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Rafael Espindolafddf8042012-01-11 03:56:41 +0000109 }
110
Jack Carterec65be82012-09-05 23:34:03 +0000111 MCAsmParser &getParser() const { return Parser; }
112 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
113
Rafael Espindolafddf8042012-01-11 03:56:41 +0000114};
115}
116
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000117namespace {
118
119/// MipsOperand - Instances of this class represent a parsed Mips machine
120/// instruction.
121class MipsOperand : public MCParsedAsmOperand {
Jack Carterec65be82012-09-05 23:34:03 +0000122
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000123 enum KindTy {
124 k_CondCode,
125 k_CoprocNum,
126 k_Immediate,
127 k_Memory,
128 k_PostIndexRegister,
129 k_Register,
130 k_Token
131 } Kind;
132
133 MipsOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
Jack Carterec65be82012-09-05 23:34:03 +0000134
135 union {
136 struct {
137 const char *Data;
138 unsigned Length;
139 } Tok;
140
141 struct {
142 unsigned RegNum;
143 } Reg;
144
145 struct {
146 const MCExpr *Val;
147 } Imm;
Jack Carter6b96c3f2012-09-06 20:00:02 +0000148
149 struct {
150 unsigned Base;
151 const MCExpr *Off;
152 } Mem;
Jack Carterec65be82012-09-05 23:34:03 +0000153 };
154
155 SMLoc StartLoc, EndLoc;
156
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000157public:
158 void addRegOperands(MCInst &Inst, unsigned N) const {
Jack Carterec65be82012-09-05 23:34:03 +0000159 assert(N == 1 && "Invalid number of operands!");
160 Inst.addOperand(MCOperand::CreateReg(getReg()));
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000161 }
Jack Carterec65be82012-09-05 23:34:03 +0000162
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000163 void addExpr(MCInst &Inst, const MCExpr *Expr) const{
Jack Carterec65be82012-09-05 23:34:03 +0000164 // Add as immediate when possible. Null MCExpr = 0.
165 if (Expr == 0)
166 Inst.addOperand(MCOperand::CreateImm(0));
167 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
168 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
169 else
170 Inst.addOperand(MCOperand::CreateExpr(Expr));
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000171 }
Jack Carterec65be82012-09-05 23:34:03 +0000172
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000173 void addImmOperands(MCInst &Inst, unsigned N) const {
Jack Carterec65be82012-09-05 23:34:03 +0000174 assert(N == 1 && "Invalid number of operands!");
175 const MCExpr *Expr = getImm();
176 addExpr(Inst,Expr);
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000177 }
Jack Carterec65be82012-09-05 23:34:03 +0000178
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000179 void addMemOperands(MCInst &Inst, unsigned N) const {
Jack Carter6b96c3f2012-09-06 20:00:02 +0000180 assert(N == 2 && "Invalid number of operands!");
181
182 Inst.addOperand(MCOperand::CreateReg(getMemBase()));
183
184 const MCExpr *Expr = getMemOff();
185 addExpr(Inst,Expr);
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000186 }
187
188 bool isReg() const { return Kind == k_Register; }
189 bool isImm() const { return Kind == k_Immediate; }
190 bool isToken() const { return Kind == k_Token; }
191 bool isMem() const { return Kind == k_Memory; }
192
193 StringRef getToken() const {
194 assert(Kind == k_Token && "Invalid access!");
Jack Carterec65be82012-09-05 23:34:03 +0000195 return StringRef(Tok.Data, Tok.Length);
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000196 }
197
198 unsigned getReg() const {
199 assert((Kind == k_Register) && "Invalid access!");
Jack Carterec65be82012-09-05 23:34:03 +0000200 return Reg.RegNum;
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000201 }
202
Jack Carterec65be82012-09-05 23:34:03 +0000203 const MCExpr *getImm() const {
204 assert((Kind == k_Immediate) && "Invalid access!");
205 return Imm.Val;
206 }
207
Jack Carter6b96c3f2012-09-06 20:00:02 +0000208 unsigned getMemBase() const {
209 assert((Kind == k_Memory) && "Invalid access!");
210 return Mem.Base;
211 }
212
213 const MCExpr *getMemOff() const {
214 assert((Kind == k_Memory) && "Invalid access!");
215 return Mem.Off;
216 }
217
Jack Carterec65be82012-09-05 23:34:03 +0000218 static MipsOperand *CreateToken(StringRef Str, SMLoc S) {
219 MipsOperand *Op = new MipsOperand(k_Token);
220 Op->Tok.Data = Str.data();
221 Op->Tok.Length = Str.size();
222 Op->StartLoc = S;
223 Op->EndLoc = S;
224 return Op;
225 }
226
227 static MipsOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
228 MipsOperand *Op = new MipsOperand(k_Register);
229 Op->Reg.RegNum = RegNum;
230 Op->StartLoc = S;
231 Op->EndLoc = E;
232 return Op;
233 }
234
235 static MipsOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
236 MipsOperand *Op = new MipsOperand(k_Immediate);
237 Op->Imm.Val = Val;
238 Op->StartLoc = S;
239 Op->EndLoc = E;
240 return Op;
241 }
242
Jack Carter6b96c3f2012-09-06 20:00:02 +0000243 static MipsOperand *CreateMem(unsigned Base, const MCExpr *Off,
244 SMLoc S, SMLoc E) {
245 MipsOperand *Op = new MipsOperand(k_Memory);
246 Op->Mem.Base = Base;
247 Op->Mem.Off = Off;
248 Op->StartLoc = S;
249 Op->EndLoc = E;
250 return Op;
251 }
252
Jack Carterec65be82012-09-05 23:34:03 +0000253 /// getStartLoc - Get the location of the first token of this operand.
254 SMLoc getStartLoc() const { return StartLoc; }
255 /// getEndLoc - Get the location of the last token of this operand.
256 SMLoc getEndLoc() const { return EndLoc; }
257
Akira Hatanaka72e9b6a2012-08-17 20:16:42 +0000258 virtual void print(raw_ostream &OS) const {
259 llvm_unreachable("unimplemented!");
260 }
261};
262}
263
Chad Rosier038f3e32012-09-03 18:47:45 +0000264unsigned MipsAsmParser::
Chad Rosier5d637d72012-09-05 01:15:43 +0000265getMCInstOperandNum(unsigned Kind, MCInst &Inst,
Chad Rosier038f3e32012-09-03 18:47:45 +0000266 const SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Chad Rosier2cc97de2012-09-03 20:31:23 +0000267 unsigned OperandNum, unsigned &NumMCOperands) {
Chad Rosier5d637d72012-09-05 01:15:43 +0000268 assert (0 && "getMCInstOperandNum() not supported by the Mips target.");
Chad Rosierefeaae82012-09-03 19:04:35 +0000269 // The Mips backend doesn't currently include the matcher implementation, so
Chad Rosier5d637d72012-09-05 01:15:43 +0000270 // the getMCInstOperandNumImpl() is undefined. This is a temporary
Chad Rosierefeaae82012-09-03 19:04:35 +0000271 // work around.
Chad Rosier2cc97de2012-09-03 20:31:23 +0000272 NumMCOperands = 0;
Chad Rosier038f3e32012-09-03 18:47:45 +0000273 return 0;
274}
275
Rafael Espindolafddf8042012-01-11 03:56:41 +0000276bool MipsAsmParser::
277MatchAndEmitInstruction(SMLoc IDLoc,
278 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
279 MCStreamer &Out) {
Jack Carterec65be82012-09-05 23:34:03 +0000280 MCInst Inst;
281 unsigned ErrorInfo;
282 unsigned Kind;
283 unsigned MatchResult = MatchInstructionImpl(Operands, Kind, Inst, ErrorInfo);
284
285 switch (MatchResult) {
286 default: break;
287 case Match_Success: {
288 Inst.setLoc(IDLoc);
289 Out.EmitInstruction(Inst);
290 return false;
291 }
292 case Match_MissingFeature:
293 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
294 return true;
295 case Match_InvalidOperand: {
296 SMLoc ErrorLoc = IDLoc;
297 if (ErrorInfo != ~0U) {
298 if (ErrorInfo >= Operands.size())
299 return Error(IDLoc, "too few operands for instruction");
300
301 ErrorLoc = ((MipsOperand*)Operands[ErrorInfo])->getStartLoc();
302 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
303 }
304
305 return Error(ErrorLoc, "invalid operand for instruction");
306 }
307 case Match_MnemonicFail:
308 return Error(IDLoc, "invalid instruction");
309 }
Rafael Espindolafddf8042012-01-11 03:56:41 +0000310 return true;
311}
312
Jack Carterec65be82012-09-05 23:34:03 +0000313int MipsAsmParser::matchRegisterName(StringRef Name) {
314
315 int CC = StringSwitch<unsigned>(Name)
316 .Case("zero", Mips::ZERO)
317 .Case("a0", Mips::A0)
318 .Case("a1", Mips::A1)
319 .Case("a2", Mips::A2)
320 .Case("a3", Mips::A3)
321 .Case("v0", Mips::V0)
322 .Case("v1", Mips::V1)
323 .Case("s0", Mips::S0)
324 .Case("s1", Mips::S1)
325 .Case("s2", Mips::S2)
326 .Case("s3", Mips::S3)
327 .Case("s4", Mips::S4)
328 .Case("s5", Mips::S5)
329 .Case("s6", Mips::S6)
330 .Case("s7", Mips::S7)
331 .Case("k0", Mips::K0)
332 .Case("k1", Mips::K1)
333 .Case("sp", Mips::SP)
334 .Case("fp", Mips::FP)
335 .Case("gp", Mips::GP)
336 .Case("ra", Mips::RA)
337 .Case("t0", Mips::T0)
338 .Case("t1", Mips::T1)
339 .Case("t2", Mips::T2)
340 .Case("t3", Mips::T3)
341 .Case("t4", Mips::T4)
342 .Case("t5", Mips::T5)
343 .Case("t6", Mips::T6)
344 .Case("t7", Mips::T7)
345 .Case("t8", Mips::T8)
346 .Case("t9", Mips::T9)
347 .Case("at", Mips::AT)
348 .Case("fcc0", Mips::FCC0)
349 .Default(-1);
350
351 if (CC != -1) {
352 //64 bit register in Mips are following 32 bit definitions.
353 if (isMips64())
354 CC++;
355 return CC;
356 }
357
Jack Carterf740d6e2012-09-07 00:23:42 +0000358 if (Name[0] == 'f') {
359 StringRef NumString = Name.substr(1);
360 unsigned IntVal;
361 if( NumString.getAsInteger(10, IntVal))
362 return -1; //not integer
363 if (IntVal > 31)
364 return -1;
365
366 FpFormatTy Format = getFpFormat();
367
368 if (Format == FP_FORMAT_S || Format == FP_FORMAT_W)
369 return getReg(Mips::FGR32RegClassID, IntVal);
370 if (Format == FP_FORMAT_D) {
371 if(isFP64()) {
372 return getReg(Mips::FGR64RegClassID, IntVal);
373 }
374 //only even numbers available as register pairs
375 if (( IntVal > 31) || (IntVal%2 != 0))
376 return -1;
377 return getReg(Mips::AFGR64RegClassID, IntVal/2);
378 }
379 }
380
Jack Carterec65be82012-09-05 23:34:03 +0000381 return -1;
382}
Jack Carterf740d6e2012-09-07 00:23:42 +0000383void MipsAsmParser::setDefaultFpFormat() {
384
385 if (isMips64() || isFP64())
386 FpFormat = FP_FORMAT_D;
387 else
388 FpFormat = FP_FORMAT_S;
389}
390
391bool MipsAsmParser::requestsDoubleOperand(StringRef Mnemonic){
392
393 bool IsDouble = StringSwitch<bool>(Mnemonic.lower())
394 .Case("ldxc1", true)
395 .Case("ldc1", true)
396 .Case("sdxc1", true)
397 .Case("sdc1", true)
398 .Default(false);
399
400 return IsDouble;
401}
402void MipsAsmParser::setFpFormat(StringRef Format) {
403
404 FpFormat = StringSwitch<FpFormatTy>(Format.lower())
405 .Case(".s", FP_FORMAT_S)
406 .Case(".d", FP_FORMAT_D)
407 .Case(".l", FP_FORMAT_L)
408 .Case(".w", FP_FORMAT_W)
409 .Default(FP_FORMAT_NONE);
410}
Jack Carterec65be82012-09-05 23:34:03 +0000411
412unsigned MipsAsmParser::getReg(int RC,int RegNo){
413 return *(getContext().getRegisterInfo().getRegClass(RC).begin() + RegNo);
414}
415
416int MipsAsmParser::matchRegisterByNumber(unsigned RegNum,StringRef Mnemonic) {
417
418 if (Mnemonic.lower() == "rdhwr") {
419 //at the moment only hwreg29 is supported
420 if (RegNum != 29)
421 return -1;
422 return Mips::HWR29;
423 }
424
425 if (RegNum > 31)
426 return -1;
427
428 return getReg(Mips::CPURegsRegClassID,RegNum);
429}
430
431int MipsAsmParser::tryParseRegister(StringRef Mnemonic) {
432 const AsmToken &Tok = Parser.getTok();
433 int RegNum = -1;
434
435 if (Tok.is(AsmToken::Identifier)) {
436 std::string lowerCase = Tok.getString().lower();
437 RegNum = matchRegisterName(lowerCase);
438 } else if (Tok.is(AsmToken::Integer))
Jack Carter6b96c3f2012-09-06 20:00:02 +0000439 RegNum = matchRegisterByNumber(static_cast<unsigned> (Tok.getIntVal()),
440 Mnemonic.lower());
Jack Carterf740d6e2012-09-07 00:23:42 +0000441 else
442 return RegNum; //error
443 //64 bit div operations require Mips::ZERO instead of MIPS::ZERO_64
444 if (isMips64() && RegNum == Mips::ZERO_64) {
445 if (Mnemonic.find("ddiv") != StringRef::npos)
446 RegNum = Mips::ZERO;
447 }
Jack Carterec65be82012-09-05 23:34:03 +0000448 return RegNum;
449}
450
Rafael Espindolafddf8042012-01-11 03:56:41 +0000451bool MipsAsmParser::
Jack Carterec65be82012-09-05 23:34:03 +0000452 tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
453 StringRef Mnemonic){
454
455 SMLoc S = Parser.getTok().getLoc();
456 int RegNo = -1;
Jack Carterf740d6e2012-09-07 00:23:42 +0000457
458 //FIXME: we should make a more generic method for CCR
459 if ((Mnemonic == "cfc1" || Mnemonic == "ctc1")
460 && Operands.size() == 2 && Parser.getTok().is(AsmToken::Integer)){
461 RegNo = Parser.getTok().getIntVal(); //get the int value
462 //at the moment only fcc0 is supported
463 if (RegNo == 0)
464 RegNo = Mips::FCC0;
465 } else
466 RegNo = tryParseRegister(Mnemonic);
Jack Carterec65be82012-09-05 23:34:03 +0000467 if (RegNo == -1)
468 return true;
469
470 Operands.push_back(MipsOperand::CreateReg(RegNo, S,
Jack Carterf740d6e2012-09-07 00:23:42 +0000471 Parser.getTok().getLoc()));
Jack Carterec65be82012-09-05 23:34:03 +0000472 Parser.Lex(); // Eat register token.
473 return false;
474}
475
476bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
477 StringRef Mnemonic) {
478 //Check if the current operand has a custom associated parser, if so, try to
479 //custom parse the operand, or fallback to the general approach.
480 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
481 if (ResTy == MatchOperand_Success)
482 return false;
483 // If there wasn't a custom match, try the generic matcher below. Otherwise,
484 // there was a match, but an error occurred, in which case, just return that
485 // the operand parsing failed.
486 if (ResTy == MatchOperand_ParseFail)
487 return true;
488
489 switch (getLexer().getKind()) {
490 default:
491 Error(Parser.getTok().getLoc(), "unexpected token in operand");
492 return true;
493 case AsmToken::Dollar: {
494 //parse register
495 SMLoc S = Parser.getTok().getLoc();
496 Parser.Lex(); // Eat dollar token.
497 //parse register operand
498 if (!tryParseRegisterOperand(Operands,Mnemonic)) {
499 if (getLexer().is(AsmToken::LParen)) {
500 //check if it is indexed addressing operand
501 Operands.push_back(MipsOperand::CreateToken("(", S));
502 Parser.Lex(); //eat parenthesis
503 if (getLexer().isNot(AsmToken::Dollar))
504 return true;
505
506 Parser.Lex(); //eat dollar
507 if (tryParseRegisterOperand(Operands,Mnemonic))
508 return true;
509
510 if (!getLexer().is(AsmToken::RParen))
511 return true;
512
513 S = Parser.getTok().getLoc();
514 Operands.push_back(MipsOperand::CreateToken(")", S));
515 Parser.Lex();
516 }
517 return false;
518 }
519 //maybe it is a symbol reference
520 StringRef Identifier;
521 if (Parser.ParseIdentifier(Identifier))
522 return true;
523
Jack Carter6b96c3f2012-09-06 20:00:02 +0000524 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterec65be82012-09-05 23:34:03 +0000525
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000526 MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
Jack Carterec65be82012-09-05 23:34:03 +0000527
528 // Otherwise create a symbol ref.
Jack Carter6b96c3f2012-09-06 20:00:02 +0000529 const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
Jack Carterec65be82012-09-05 23:34:03 +0000530 getContext());
531
532 Operands.push_back(MipsOperand::CreateImm(Res, S, E));
533 return false;
534 }
535 case AsmToken::Identifier:
536 case AsmToken::LParen:
537 case AsmToken::Minus:
538 case AsmToken::Plus:
539 case AsmToken::Integer:
540 case AsmToken::String: {
541 // quoted label names
542 const MCExpr *IdVal;
543 SMLoc S = Parser.getTok().getLoc();
544 if (getParser().ParseExpression(IdVal))
545 return true;
Jack Carter6b96c3f2012-09-06 20:00:02 +0000546 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Jack Carterec65be82012-09-05 23:34:03 +0000547 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
548 return false;
549 }
Jack Carter6b96c3f2012-09-06 20:00:02 +0000550 case AsmToken::Percent: {
551 //it is a symbol reference or constant expression
552 const MCExpr *IdVal;
553 SMLoc S = Parser.getTok().getLoc(); //start location of the operand
554 if (parseRelocOperand(IdVal))
555 return true;
556
557 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
558
559 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
560 return false;
561 }//case AsmToken::Percent
Jack Carterec65be82012-09-05 23:34:03 +0000562 }//switch(getLexer().getKind())
Rafael Espindolafddf8042012-01-11 03:56:41 +0000563 return true;
564}
565
Jack Carter6b96c3f2012-09-06 20:00:02 +0000566bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
567
568 Parser.Lex(); //eat % token
569 const AsmToken &Tok = Parser.getTok(); //get next token, operation
570 if (Tok.isNot(AsmToken::Identifier))
571 return true;
572
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000573 std::string Str = Tok.getIdentifier().str();
Jack Carter6b96c3f2012-09-06 20:00:02 +0000574
575 Parser.Lex(); //eat identifier
576 //now make expression from the rest of the operand
577 const MCExpr *IdVal;
578 SMLoc EndLoc;
579
580 if (getLexer().getKind() == AsmToken::LParen) {
581 while (1) {
582 Parser.Lex(); //eat '(' token
583 if (getLexer().getKind() == AsmToken::Percent) {
584 Parser.Lex(); //eat % token
585 const AsmToken &nextTok = Parser.getTok();
586 if (nextTok.isNot(AsmToken::Identifier))
587 return true;
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000588 Str += "(%";
589 Str += nextTok.getIdentifier();
Jack Carter6b96c3f2012-09-06 20:00:02 +0000590 Parser.Lex(); //eat identifier
591 if (getLexer().getKind() != AsmToken::LParen)
592 return true;
593 } else
594 break;
595 }
596 if (getParser().ParseParenExpression(IdVal,EndLoc))
597 return true;
598
599 while (getLexer().getKind() == AsmToken::RParen)
600 Parser.Lex(); //eat ')' token
601
602 } else
603 return true; //parenthesis must follow reloc operand
604
Jack Carter6b96c3f2012-09-06 20:00:02 +0000605 //Check the type of the expression
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000606 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal)) {
Jack Carter6b96c3f2012-09-06 20:00:02 +0000607 //it's a constant, evaluate lo or hi value
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000608 int Val = MCE->getValue();
Jack Carter6b96c3f2012-09-06 20:00:02 +0000609 if (Str == "lo") {
610 Val = Val & 0xffff;
611 } else if (Str == "hi") {
612 Val = (Val & 0xffff0000) >> 16;
613 }
614 Res = MCConstantExpr::Create(Val, getContext());
615 return false;
616 }
617
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000618 if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(IdVal)) {
Jack Carter6b96c3f2012-09-06 20:00:02 +0000619 //it's a symbol, create symbolic expression from symbol
Benjamin Kramer38539eb2012-09-07 09:47:42 +0000620 StringRef Symbol = MSRE->getSymbol().getName();
Jack Carter6b96c3f2012-09-06 20:00:02 +0000621 MCSymbolRefExpr::VariantKind VK = getVariantKind(Str);
622 Res = MCSymbolRefExpr::Create(Symbol,VK,getContext());
623 return false;
624 }
625 return true;
626}
627
Jack Carterec65be82012-09-05 23:34:03 +0000628bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
629 SMLoc &EndLoc) {
630
631 StartLoc = Parser.getTok().getLoc();
632 RegNo = tryParseRegister("");
633 EndLoc = Parser.getTok().getLoc();
634 return (RegNo == (unsigned)-1);
635}
636
Jack Carter6b96c3f2012-09-06 20:00:02 +0000637bool MipsAsmParser::parseMemOffset(const MCExpr *&Res) {
638
639 SMLoc S;
640
641 switch(getLexer().getKind()) {
642 default:
643 return true;
644 case AsmToken::Integer:
645 case AsmToken::Minus:
646 case AsmToken::Plus:
647 return (getParser().ParseExpression(Res));
Jack Carterf740d6e2012-09-07 00:23:42 +0000648 case AsmToken::Percent:
Jack Carter6b96c3f2012-09-06 20:00:02 +0000649 return parseRelocOperand(Res);
Jack Carter6b96c3f2012-09-06 20:00:02 +0000650 case AsmToken::LParen:
651 return false; //it's probably assuming 0
652 }
653 return true;
654}
655
Jack Carterec65be82012-09-05 23:34:03 +0000656MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
657 SmallVectorImpl<MCParsedAsmOperand*>&Operands) {
Jack Carter6b96c3f2012-09-06 20:00:02 +0000658
659 const MCExpr *IdVal = 0;
660 SMLoc S;
661 //first operand is the offset
662 S = Parser.getTok().getLoc();
663
664 if (parseMemOffset(IdVal))
665 return MatchOperand_ParseFail;
666
667 const AsmToken &Tok = Parser.getTok(); //get next token
668 if (Tok.isNot(AsmToken::LParen)) {
669 Error(Parser.getTok().getLoc(), "'(' expected");
670 return MatchOperand_ParseFail;
671 }
672
673 Parser.Lex(); // Eat '(' token.
674
675 const AsmToken &Tok1 = Parser.getTok(); //get next token
676 if (Tok1.is(AsmToken::Dollar)) {
677 Parser.Lex(); // Eat '$' token.
678 if (tryParseRegisterOperand(Operands,"")) {
679 Error(Parser.getTok().getLoc(), "unexpected token in operand");
680 return MatchOperand_ParseFail;
681 }
682
683 } else {
684 Error(Parser.getTok().getLoc(),"unexpected token in operand");
685 return MatchOperand_ParseFail;
686 }
687
688 const AsmToken &Tok2 = Parser.getTok(); //get next token
689 if (Tok2.isNot(AsmToken::RParen)) {
690 Error(Parser.getTok().getLoc(), "')' expected");
691 return MatchOperand_ParseFail;
692 }
693
694 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
695
696 Parser.Lex(); // Eat ')' token.
697
698 if (IdVal == 0)
699 IdVal = MCConstantExpr::Create(0, getContext());
700
701 //now replace register operand with the mem operand
702 MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
703 int RegNo = op->getReg();
704 //remove register from operands
705 Operands.pop_back();
706 //and add memory operand
707 Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
708 delete op;
Jack Carterec65be82012-09-05 23:34:03 +0000709 return MatchOperand_Success;
710}
711
Jack Carter6b96c3f2012-09-06 20:00:02 +0000712MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
713
714 MCSymbolRefExpr::VariantKind VK
715 = StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
716 .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
717 .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
718 .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
719 .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
720 .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
721 .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
722 .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
723 .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
724 .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
725 .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
726 .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
727 .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
728 .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
729 .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
730 .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
731 .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
732 .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
733 .Default(MCSymbolRefExpr::VK_None);
734
735 return VK;
736}
737
Jack Carterf740d6e2012-09-07 00:23:42 +0000738int ConvertCcString(StringRef CondString){
739
740 int CC = StringSwitch<unsigned>(CondString)
741 .Case(".f", 0)
742 .Case(".un", 1)
743 .Case(".eq", 2)
744 .Case(".ueq", 3)
745 .Case(".olt", 4)
746 .Case(".ult", 5)
747 .Case(".ole", 6)
748 .Case(".ule", 7)
749 .Case(".sf", 8)
750 .Case(".ngle", 9)
751 .Case(".seq", 10)
752 .Case(".ngl", 11)
753 .Case(".lt", 12)
754 .Case(".nge", 13)
755 .Case(".le", 14)
756 .Case(".ngt", 15)
757 .Default(-1);
758
759 return CC;
760}
761
762bool MipsAsmParser::
763parseMathOperation(StringRef Name, SMLoc NameLoc,
764 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
765 //split the format
766 size_t Start = Name.find('.'), Next = Name.rfind('.');
767 StringRef Format1 = Name.slice(Start, Next);
768 //and add the first format to the operands
769 Operands.push_back(MipsOperand::CreateToken(Format1, NameLoc));
770 //now for the second format
771 StringRef Format2 = Name.slice(Next, StringRef::npos);
772 Operands.push_back(MipsOperand::CreateToken(Format2, NameLoc));
773
774 //set the format for the first register
775 setFpFormat(Format1);
776
777 // Read the remaining operands.
778 if (getLexer().isNot(AsmToken::EndOfStatement)) {
779 // Read the first 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 if (getLexer().isNot(AsmToken::Comma)) {
787 SMLoc Loc = getLexer().getLoc();
788 Parser.EatToEndOfStatement();
789 return Error(Loc, "unexpected token in argument list");
790
791 }
792 Parser.Lex(); // Eat the comma.
793
794 //set the format for the first register
795 setFpFormat(Format2);
796
797 // Parse and remember the operand.
798 if (ParseOperand(Operands, Name)) {
799 SMLoc Loc = getLexer().getLoc();
800 Parser.EatToEndOfStatement();
801 return Error(Loc, "unexpected token in argument list");
802 }
803 }
804
805 if (getLexer().isNot(AsmToken::EndOfStatement)) {
806 SMLoc Loc = getLexer().getLoc();
807 Parser.EatToEndOfStatement();
808 return Error(Loc, "unexpected token in argument list");
809 }
810
811 Parser.Lex(); // Consume the EndOfStatement
812 return false;
813}
814
Rafael Espindolafddf8042012-01-11 03:56:41 +0000815bool MipsAsmParser::
816ParseInstruction(StringRef Name, SMLoc NameLoc,
817 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jack Carterf740d6e2012-09-07 00:23:42 +0000818 //floating point instructions: should register be treated as double?
819 if (requestsDoubleOperand(Name)) {
820 setFpFormat(FP_FORMAT_D);
Jack Carterec65be82012-09-05 23:34:03 +0000821 Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
Jack Carterf740d6e2012-09-07 00:23:42 +0000822 }
823 else {
824 setDefaultFpFormat();
825 // Create the leading tokens for the mnemonic, split by '.' characters.
826 size_t Start = 0, Next = Name.find('.');
827 StringRef Mnemonic = Name.slice(Start, Next);
828
829 Operands.push_back(MipsOperand::CreateToken(Mnemonic, NameLoc));
830
831 if (Next != StringRef::npos) {
832 //there is a format token in mnemonic
833 //StringRef Rest = Name.slice(Next, StringRef::npos);
834 size_t Dot = Name.find('.', Next+1);
835 StringRef Format = Name.slice(Next, Dot);
836 if (Dot == StringRef::npos) //only one '.' in a string, it's a format
837 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
838 else {
839 if (Name.startswith("c.")){
840 // floating point compare, add '.' and immediate represent for cc
841 Operands.push_back(MipsOperand::CreateToken(".", NameLoc));
842 int Cc = ConvertCcString(Format);
843 if (Cc == -1) {
844 return Error(NameLoc, "Invalid conditional code");
845 }
846 SMLoc E = SMLoc::getFromPointer(
847 Parser.getTok().getLoc().getPointer() -1 );
848 Operands.push_back(MipsOperand::CreateImm(
849 MCConstantExpr::Create(Cc, getContext()), NameLoc, E));
850 } else {
851 //trunc, ceil, floor ...
852 return parseMathOperation(Name, NameLoc, Operands);
853 }
854
855 //the rest is a format
856 Format = Name.slice(Dot, StringRef::npos);
857 Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
858 }
859
860 setFpFormat(Format);
861 }
862 }
Jack Carterec65be82012-09-05 23:34:03 +0000863
864 // Read the remaining operands.
865 if (getLexer().isNot(AsmToken::EndOfStatement)) {
866 // Read the first operand.
867 if (ParseOperand(Operands, Name)) {
868 SMLoc Loc = getLexer().getLoc();
869 Parser.EatToEndOfStatement();
870 return Error(Loc, "unexpected token in argument list");
871 }
872
873 while (getLexer().is(AsmToken::Comma) ) {
874 Parser.Lex(); // Eat the comma.
875
876 // Parse and remember the operand.
877 if (ParseOperand(Operands, Name)) {
878 SMLoc Loc = getLexer().getLoc();
879 Parser.EatToEndOfStatement();
880 return Error(Loc, "unexpected token in argument list");
881 }
882 }
883 }
884
885 if (getLexer().isNot(AsmToken::EndOfStatement)) {
886 SMLoc Loc = getLexer().getLoc();
887 Parser.EatToEndOfStatement();
888 return Error(Loc, "unexpected token in argument list");
889 }
890
891 Parser.Lex(); // Consume the EndOfStatement
892 return false;
Rafael Espindolafddf8042012-01-11 03:56:41 +0000893}
894
895bool MipsAsmParser::
896ParseDirective(AsmToken DirectiveID) {
Jack Carteracbea452012-09-07 00:48:02 +0000897
898 if (DirectiveID.getString() == ".ent") {
899 //ignore this directive for now
900 Parser.Lex();
901 return false;
902 }
903
904 if (DirectiveID.getString() == ".end") {
905 //ignore this directive for now
906 Parser.Lex();
907 return false;
908 }
909
910 if (DirectiveID.getString() == ".frame") {
911 //ignore this directive for now
912 Parser.EatToEndOfStatement();
913 return false;
914 }
915
916 if (DirectiveID.getString() == ".set") {
917 //ignore this directive for now
918 Parser.EatToEndOfStatement();
919 return false;
920 }
921
922 if (DirectiveID.getString() == ".fmask") {
923 //ignore this directive for now
924 Parser.EatToEndOfStatement();
925 return false;
926 }
927
928 if (DirectiveID.getString() == ".mask") {
929 //ignore this directive for now
930 Parser.EatToEndOfStatement();
931 return false;
932 }
933
934 if (DirectiveID.getString() == ".gpword") {
935 //ignore this directive for now
936 Parser.EatToEndOfStatement();
937 return false;
938 }
939
Rafael Espindolafddf8042012-01-11 03:56:41 +0000940 return true;
941}
942
Rafael Espindolafddf8042012-01-11 03:56:41 +0000943extern "C" void LLVMInitializeMipsAsmParser() {
944 RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget);
945 RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget);
946 RegisterMCAsmParser<MipsAsmParser> A(TheMips64Target);
947 RegisterMCAsmParser<MipsAsmParser> B(TheMips64elTarget);
948}
Jack Carterec65be82012-09-05 23:34:03 +0000949
950#define GET_REGISTER_MATCHER
951#define GET_MATCHER_IMPLEMENTATION
952#include "MipsGenAsmMatcher.inc"