1 //===-- MBlazeAsmParser.cpp - Parse MBlaze asm to MCInst instructions -----===//
2 //
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/MBlazeBaseInfo.h"
11 #include "llvm/MC/MCParser/MCAsmLexer.h"
12 #include "llvm/MC/MCParser/MCAsmParser.h"
13 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
14 #include "llvm/MC/MCStreamer.h"
15 #include "llvm/MC/MCExpr.h"
16 #include "llvm/MC/MCInst.h"
17 #include "llvm/MC/MCTargetAsmParser.h"
18 #include "llvm/Support/SourceMgr.h"
19 #include "llvm/Support/TargetRegistry.h"
20 #include "llvm/Support/raw_ostream.h"
21 #include "llvm/ADT/OwningPtr.h"
22 #include "llvm/ADT/SmallVector.h"
23 #include "llvm/ADT/StringSwitch.h"
24 #include "llvm/ADT/Twine.h"
25 using namespace llvm;
26
27 namespace {
28 struct MBlazeOperand;
29
30 class MBlazeAsmParser : public MCTargetAsmParser {
31 MCAsmParser &Parser;
32
getParser() const33 MCAsmParser &getParser() const { return Parser; }
getLexer() const34 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
35
Warning(SMLoc L,const Twine & Msg)36 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
Error(SMLoc L,const Twine & Msg)37 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
38
39 MBlazeOperand *ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
40 MBlazeOperand *ParseRegister(unsigned &RegNo);
41 MBlazeOperand *ParseImmediate();
42 MBlazeOperand *ParseFsl();
43 MBlazeOperand* ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
44
45 virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
46
47 bool ParseDirectiveWord(unsigned Size, SMLoc L);
48
49 bool MatchAndEmitInstruction(SMLoc IDLoc,
50 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
51 MCStreamer &Out);
52
53 /// @name Auto-generated Match Functions
54 /// {
55
56 #define GET_ASSEMBLER_HEADER
57 #include "MBlazeGenAsmMatcher.inc"
58
59 /// }
60
61
62 public:
MBlazeAsmParser(MCSubtargetInfo & _STI,MCAsmParser & _Parser)63 MBlazeAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
64 : MCTargetAsmParser(), Parser(_Parser) {}
65
66 virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc,
67 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
68
69 virtual bool ParseDirective(AsmToken DirectiveID);
70 };
71
72 /// MBlazeOperand - Instances of this class represent a parsed MBlaze machine
73 /// instruction.
74 struct MBlazeOperand : public MCParsedAsmOperand {
75 enum KindTy {
76 Token,
77 Immediate,
78 Register,
79 Memory,
80 Fsl
81 } Kind;
82
83 SMLoc StartLoc, EndLoc;
84
85 union {
86 struct {
87 const char *Data;
88 unsigned Length;
89 } Tok;
90
91 struct {
92 unsigned RegNum;
93 } Reg;
94
95 struct {
96 const MCExpr *Val;
97 } Imm;
98
99 struct {
100 unsigned Base;
101 unsigned OffReg;
102 const MCExpr *Off;
103 } Mem;
104
105 struct {
106 const MCExpr *Val;
107 } FslImm;
108 };
109
MBlazeOperand__anondaef85440111::MBlazeOperand110 MBlazeOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
111 public:
MBlazeOperand__anondaef85440111::MBlazeOperand112 MBlazeOperand(const MBlazeOperand &o) : MCParsedAsmOperand() {
113 Kind = o.Kind;
114 StartLoc = o.StartLoc;
115 EndLoc = o.EndLoc;
116 switch (Kind) {
117 case Register:
118 Reg = o.Reg;
119 break;
120 case Immediate:
121 Imm = o.Imm;
122 break;
123 case Token:
124 Tok = o.Tok;
125 break;
126 case Memory:
127 Mem = o.Mem;
128 break;
129 case Fsl:
130 FslImm = o.FslImm;
131 break;
132 }
133 }
134
135 /// getStartLoc - Get the location of the first token of this operand.
getStartLoc__anondaef85440111::MBlazeOperand136 SMLoc getStartLoc() const { return StartLoc; }
137
138 /// getEndLoc - Get the location of the last token of this operand.
getEndLoc__anondaef85440111::MBlazeOperand139 SMLoc getEndLoc() const { return EndLoc; }
140
getReg__anondaef85440111::MBlazeOperand141 unsigned getReg() const {
142 assert(Kind == Register && "Invalid access!");
143 return Reg.RegNum;
144 }
145
getImm__anondaef85440111::MBlazeOperand146 const MCExpr *getImm() const {
147 assert(Kind == Immediate && "Invalid access!");
148 return Imm.Val;
149 }
150
getFslImm__anondaef85440111::MBlazeOperand151 const MCExpr *getFslImm() const {
152 assert(Kind == Fsl && "Invalid access!");
153 return FslImm.Val;
154 }
155
getMemBase__anondaef85440111::MBlazeOperand156 unsigned getMemBase() const {
157 assert(Kind == Memory && "Invalid access!");
158 return Mem.Base;
159 }
160
getMemOff__anondaef85440111::MBlazeOperand161 const MCExpr* getMemOff() const {
162 assert(Kind == Memory && "Invalid access!");
163 return Mem.Off;
164 }
165
getMemOffReg__anondaef85440111::MBlazeOperand166 unsigned getMemOffReg() const {
167 assert(Kind == Memory && "Invalid access!");
168 return Mem.OffReg;
169 }
170
isToken__anondaef85440111::MBlazeOperand171 bool isToken() const { return Kind == Token; }
isImm__anondaef85440111::MBlazeOperand172 bool isImm() const { return Kind == Immediate; }
isMem__anondaef85440111::MBlazeOperand173 bool isMem() const { return Kind == Memory; }
isFsl__anondaef85440111::MBlazeOperand174 bool isFsl() const { return Kind == Fsl; }
isReg__anondaef85440111::MBlazeOperand175 bool isReg() const { return Kind == Register; }
176
addExpr__anondaef85440111::MBlazeOperand177 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
178 // Add as immediates when possible. Null MCExpr = 0.
179 if (Expr == 0)
180 Inst.addOperand(MCOperand::CreateImm(0));
181 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
182 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
183 else
184 Inst.addOperand(MCOperand::CreateExpr(Expr));
185 }
186
addRegOperands__anondaef85440111::MBlazeOperand187 void addRegOperands(MCInst &Inst, unsigned N) const {
188 assert(N == 1 && "Invalid number of operands!");
189 Inst.addOperand(MCOperand::CreateReg(getReg()));
190 }
191
addImmOperands__anondaef85440111::MBlazeOperand192 void addImmOperands(MCInst &Inst, unsigned N) const {
193 assert(N == 1 && "Invalid number of operands!");
194 addExpr(Inst, getImm());
195 }
196
addFslOperands__anondaef85440111::MBlazeOperand197 void addFslOperands(MCInst &Inst, unsigned N) const {
198 assert(N == 1 && "Invalid number of operands!");
199 addExpr(Inst, getFslImm());
200 }
201
addMemOperands__anondaef85440111::MBlazeOperand202 void addMemOperands(MCInst &Inst, unsigned N) const {
203 assert(N == 2 && "Invalid number of operands!");
204
205 Inst.addOperand(MCOperand::CreateReg(getMemBase()));
206
207 unsigned RegOff = getMemOffReg();
208 if (RegOff)
209 Inst.addOperand(MCOperand::CreateReg(RegOff));
210 else
211 addExpr(Inst, getMemOff());
212 }
213
getToken__anondaef85440111::MBlazeOperand214 StringRef getToken() const {
215 assert(Kind == Token && "Invalid access!");
216 return StringRef(Tok.Data, Tok.Length);
217 }
218
219 virtual void print(raw_ostream &OS) const;
220
CreateToken__anondaef85440111::MBlazeOperand221 static MBlazeOperand *CreateToken(StringRef Str, SMLoc S) {
222 MBlazeOperand *Op = new MBlazeOperand(Token);
223 Op->Tok.Data = Str.data();
224 Op->Tok.Length = Str.size();
225 Op->StartLoc = S;
226 Op->EndLoc = S;
227 return Op;
228 }
229
CreateReg__anondaef85440111::MBlazeOperand230 static MBlazeOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
231 MBlazeOperand *Op = new MBlazeOperand(Register);
232 Op->Reg.RegNum = RegNum;
233 Op->StartLoc = S;
234 Op->EndLoc = E;
235 return Op;
236 }
237
CreateImm__anondaef85440111::MBlazeOperand238 static MBlazeOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
239 MBlazeOperand *Op = new MBlazeOperand(Immediate);
240 Op->Imm.Val = Val;
241 Op->StartLoc = S;
242 Op->EndLoc = E;
243 return Op;
244 }
245
CreateFslImm__anondaef85440111::MBlazeOperand246 static MBlazeOperand *CreateFslImm(const MCExpr *Val, SMLoc S, SMLoc E) {
247 MBlazeOperand *Op = new MBlazeOperand(Fsl);
248 Op->Imm.Val = Val;
249 Op->StartLoc = S;
250 Op->EndLoc = E;
251 return Op;
252 }
253
CreateMem__anondaef85440111::MBlazeOperand254 static MBlazeOperand *CreateMem(unsigned Base, const MCExpr *Off, SMLoc S,
255 SMLoc E) {
256 MBlazeOperand *Op = new MBlazeOperand(Memory);
257 Op->Mem.Base = Base;
258 Op->Mem.Off = Off;
259 Op->Mem.OffReg = 0;
260 Op->StartLoc = S;
261 Op->EndLoc = E;
262 return Op;
263 }
264
CreateMem__anondaef85440111::MBlazeOperand265 static MBlazeOperand *CreateMem(unsigned Base, unsigned Off, SMLoc S,
266 SMLoc E) {
267 MBlazeOperand *Op = new MBlazeOperand(Memory);
268 Op->Mem.Base = Base;
269 Op->Mem.OffReg = Off;
270 Op->Mem.Off = 0;
271 Op->StartLoc = S;
272 Op->EndLoc = E;
273 return Op;
274 }
275 };
276
277 } // end anonymous namespace.
278
print(raw_ostream & OS) const279 void MBlazeOperand::print(raw_ostream &OS) const {
280 switch (Kind) {
281 case Immediate:
282 getImm()->print(OS);
283 break;
284 case Register:
285 OS << "<register R";
286 OS << getMBlazeRegisterNumbering(getReg()) << ">";
287 break;
288 case Token:
289 OS << "'" << getToken() << "'";
290 break;
291 case Memory: {
292 OS << "<memory R";
293 OS << getMBlazeRegisterNumbering(getMemBase());
294 OS << ", ";
295
296 unsigned RegOff = getMemOffReg();
297 if (RegOff)
298 OS << "R" << getMBlazeRegisterNumbering(RegOff);
299 else
300 OS << getMemOff();
301 OS << ">";
302 }
303 break;
304 case Fsl:
305 getFslImm()->print(OS);
306 break;
307 }
308 }
309
310 /// @name Auto-generated Match Functions
311 /// {
312
313 static unsigned MatchRegisterName(StringRef Name);
314
315 /// }
316 //
317 bool MBlazeAsmParser::
MatchAndEmitInstruction(SMLoc IDLoc,SmallVectorImpl<MCParsedAsmOperand * > & Operands,MCStreamer & Out)318 MatchAndEmitInstruction(SMLoc IDLoc,
319 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
320 MCStreamer &Out) {
321 MCInst Inst;
322 SMLoc ErrorLoc;
323 unsigned ErrorInfo;
324
325 switch (MatchInstructionImpl(Operands, Inst, ErrorInfo)) {
326 default: break;
327 case Match_Success:
328 Out.EmitInstruction(Inst);
329 return false;
330 case Match_MissingFeature:
331 return Error(IDLoc, "instruction use requires an option to be enabled");
332 case Match_MnemonicFail:
333 return Error(IDLoc, "unrecognized instruction mnemonic");
334 case Match_ConversionFail:
335 return Error(IDLoc, "unable to convert operands to instruction");
336 case Match_InvalidOperand:
337 ErrorLoc = IDLoc;
338 if (ErrorInfo != ~0U) {
339 if (ErrorInfo >= Operands.size())
340 return Error(IDLoc, "too few operands for instruction");
341
342 ErrorLoc = ((MBlazeOperand*)Operands[ErrorInfo])->getStartLoc();
343 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
344 }
345
346 return Error(ErrorLoc, "invalid operand for instruction");
347 }
348
349 llvm_unreachable("Implement any new match types added!");
350 return true;
351 }
352
353 MBlazeOperand *MBlazeAsmParser::
ParseMemory(SmallVectorImpl<MCParsedAsmOperand * > & Operands)354 ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
355 if (Operands.size() != 4)
356 return 0;
357
358 MBlazeOperand &Base = *(MBlazeOperand*)Operands[2];
359 MBlazeOperand &Offset = *(MBlazeOperand*)Operands[3];
360
361 SMLoc S = Base.getStartLoc();
362 SMLoc O = Offset.getStartLoc();
363 SMLoc E = Offset.getEndLoc();
364
365 if (!Base.isReg()) {
366 Error(S, "base address must be a register");
367 return 0;
368 }
369
370 if (!Offset.isReg() && !Offset.isImm()) {
371 Error(O, "offset must be a register or immediate");
372 return 0;
373 }
374
375 MBlazeOperand *Op;
376 if (Offset.isReg())
377 Op = MBlazeOperand::CreateMem(Base.getReg(), Offset.getReg(), S, E);
378 else
379 Op = MBlazeOperand::CreateMem(Base.getReg(), Offset.getImm(), S, E);
380
381 delete Operands.pop_back_val();
382 delete Operands.pop_back_val();
383 Operands.push_back(Op);
384
385 return Op;
386 }
387
ParseRegister(unsigned & RegNo,SMLoc & StartLoc,SMLoc & EndLoc)388 bool MBlazeAsmParser::ParseRegister(unsigned &RegNo,
389 SMLoc &StartLoc, SMLoc &EndLoc) {
390 return (ParseRegister(RegNo) == 0);
391 }
392
ParseRegister(unsigned & RegNo)393 MBlazeOperand *MBlazeAsmParser::ParseRegister(unsigned &RegNo) {
394 SMLoc S = Parser.getTok().getLoc();
395 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
396
397 switch (getLexer().getKind()) {
398 default: return 0;
399 case AsmToken::Identifier:
400 RegNo = MatchRegisterName(getLexer().getTok().getIdentifier());
401 if (RegNo == 0)
402 return 0;
403
404 getLexer().Lex();
405 return MBlazeOperand::CreateReg(RegNo, S, E);
406 }
407 }
408
MatchFslRegister(StringRef String)409 static unsigned MatchFslRegister(StringRef String) {
410 if (!String.startswith("rfsl"))
411 return -1;
412
413 unsigned regNum;
414 if (String.substr(4).getAsInteger(10,regNum))
415 return -1;
416
417 return regNum;
418 }
419
ParseFsl()420 MBlazeOperand *MBlazeAsmParser::ParseFsl() {
421 SMLoc S = Parser.getTok().getLoc();
422 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
423
424 switch (getLexer().getKind()) {
425 default: return 0;
426 case AsmToken::Identifier:
427 unsigned reg = MatchFslRegister(getLexer().getTok().getIdentifier());
428 if (reg >= 16)
429 return 0;
430
431 getLexer().Lex();
432 const MCExpr *EVal = MCConstantExpr::Create(reg,getContext());
433 return MBlazeOperand::CreateFslImm(EVal,S,E);
434 }
435 }
436
ParseImmediate()437 MBlazeOperand *MBlazeAsmParser::ParseImmediate() {
438 SMLoc S = Parser.getTok().getLoc();
439 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
440
441 const MCExpr *EVal;
442 switch (getLexer().getKind()) {
443 default: return 0;
444 case AsmToken::LParen:
445 case AsmToken::Plus:
446 case AsmToken::Minus:
447 case AsmToken::Integer:
448 case AsmToken::Identifier:
449 if (getParser().ParseExpression(EVal))
450 return 0;
451
452 return MBlazeOperand::CreateImm(EVal, S, E);
453 }
454 }
455
456 MBlazeOperand *MBlazeAsmParser::
ParseOperand(SmallVectorImpl<MCParsedAsmOperand * > & Operands)457 ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
458 MBlazeOperand *Op;
459
460 // Attempt to parse the next token as a register name
461 unsigned RegNo;
462 Op = ParseRegister(RegNo);
463
464 // Attempt to parse the next token as an FSL immediate
465 if (!Op)
466 Op = ParseFsl();
467
468 // Attempt to parse the next token as an immediate
469 if (!Op)
470 Op = ParseImmediate();
471
472 // If the token could not be parsed then fail
473 if (!Op) {
474 Error(Parser.getTok().getLoc(), "unknown operand");
475 return 0;
476 }
477
478 // Push the parsed operand into the list of operands
479 Operands.push_back(Op);
480 return Op;
481 }
482
483 /// Parse an mblaze instruction mnemonic followed by its operands.
484 bool MBlazeAsmParser::
ParseInstruction(StringRef Name,SMLoc NameLoc,SmallVectorImpl<MCParsedAsmOperand * > & Operands)485 ParseInstruction(StringRef Name, SMLoc NameLoc,
486 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
487 // The first operands is the token for the instruction name
488 size_t dotLoc = Name.find('.');
489 Operands.push_back(MBlazeOperand::CreateToken(Name.substr(0,dotLoc),NameLoc));
490 if (dotLoc < Name.size())
491 Operands.push_back(MBlazeOperand::CreateToken(Name.substr(dotLoc),NameLoc));
492
493 // If there are no more operands then finish
494 if (getLexer().is(AsmToken::EndOfStatement))
495 return false;
496
497 // Parse the first operand
498 if (!ParseOperand(Operands))
499 return true;
500
501 while (getLexer().isNot(AsmToken::EndOfStatement) &&
502 getLexer().is(AsmToken::Comma)) {
503 // Consume the comma token
504 getLexer().Lex();
505
506 // Parse the next operand
507 if (!ParseOperand(Operands))
508 return true;
509 }
510
511 // If the instruction requires a memory operand then we need to
512 // replace the last two operands (base+offset) with a single
513 // memory operand.
514 if (Name.startswith("lw") || Name.startswith("sw") ||
515 Name.startswith("lh") || Name.startswith("sh") ||
516 Name.startswith("lb") || Name.startswith("sb"))
517 return (ParseMemory(Operands) == NULL);
518
519 return false;
520 }
521
522 /// ParseDirective parses the MBlaze specific directives
ParseDirective(AsmToken DirectiveID)523 bool MBlazeAsmParser::ParseDirective(AsmToken DirectiveID) {
524 StringRef IDVal = DirectiveID.getIdentifier();
525 if (IDVal == ".word")
526 return ParseDirectiveWord(2, DirectiveID.getLoc());
527 return true;
528 }
529
530 /// ParseDirectiveWord
531 /// ::= .word [ expression (, expression)* ]
ParseDirectiveWord(unsigned Size,SMLoc L)532 bool MBlazeAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
533 if (getLexer().isNot(AsmToken::EndOfStatement)) {
534 for (;;) {
535 const MCExpr *Value;
536 if (getParser().ParseExpression(Value))
537 return true;
538
539 getParser().getStreamer().EmitValue(Value, Size, 0 /*addrspace*/);
540
541 if (getLexer().is(AsmToken::EndOfStatement))
542 break;
543
544 // FIXME: Improve diagnostic.
545 if (getLexer().isNot(AsmToken::Comma))
546 return Error(L, "unexpected token in directive");
547 Parser.Lex();
548 }
549 }
550
551 Parser.Lex();
552 return false;
553 }
554
555 extern "C" void LLVMInitializeMBlazeAsmLexer();
556
557 /// Force static initialization.
LLVMInitializeMBlazeAsmParser()558 extern "C" void LLVMInitializeMBlazeAsmParser() {
559 RegisterMCAsmParser<MBlazeAsmParser> X(TheMBlazeTarget);
560 LLVMInitializeMBlazeAsmLexer();
561 }
562
563 #define GET_REGISTER_MATCHER
564 #define GET_MATCHER_IMPLEMENTATION
565 #include "MBlazeGenAsmMatcher.inc"
566