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