]>
git.proxmox.com Git - rustc.git/blob - src/llvm/lib/Target/MBlaze/AsmParser/MBlazeAsmParser.cpp
1 //===-- MBlazeAsmParser.cpp - Parse MBlaze asm to MCInst instructions -----===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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"
28 class MBlazeAsmParser
: public MCTargetAsmParser
{
31 MCAsmParser
&getParser() const { return Parser
; }
32 MCAsmLexer
&getLexer() const { return Parser
.getLexer(); }
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
); }
37 MBlazeOperand
*ParseMemory(SmallVectorImpl
<MCParsedAsmOperand
*> &Operands
);
38 MBlazeOperand
*ParseRegister(unsigned &RegNo
);
39 MBlazeOperand
*ParseImmediate();
40 MBlazeOperand
*ParseFsl();
41 MBlazeOperand
* ParseOperand(SmallVectorImpl
<MCParsedAsmOperand
*> &Operands
);
43 virtual bool ParseRegister(unsigned &RegNo
, SMLoc
&StartLoc
, SMLoc
&EndLoc
);
45 bool ParseDirectiveWord(unsigned Size
, SMLoc L
);
47 bool MatchAndEmitInstruction(SMLoc IDLoc
,
48 SmallVectorImpl
<MCParsedAsmOperand
*> &Operands
,
51 /// @name Auto-generated Match Functions
54 #define GET_ASSEMBLER_HEADER
55 #include "MBlazeGenAsmMatcher.inc"
60 MBlazeAsmParser(MCSubtargetInfo
&_STI
, MCAsmParser
&_Parser
)
61 : MCTargetAsmParser(), Parser(_Parser
) {}
63 virtual bool ParseInstruction(StringRef Name
, SMLoc NameLoc
,
64 SmallVectorImpl
<MCParsedAsmOperand
*> &Operands
);
66 virtual bool ParseDirective(AsmToken DirectiveID
);
69 /// MBlazeOperand - Instances of this class represent a parsed MBlaze machine
71 struct MBlazeOperand
: public MCParsedAsmOperand
{
80 SMLoc StartLoc
, EndLoc
;
107 MBlazeOperand(KindTy K
) : MCParsedAsmOperand(), Kind(K
) {}
109 MBlazeOperand(const MBlazeOperand
&o
) : MCParsedAsmOperand() {
111 StartLoc
= o
.StartLoc
;
132 /// getStartLoc - Get the location of the first token of this operand.
133 SMLoc
getStartLoc() const { return StartLoc
; }
135 /// getEndLoc - Get the location of the last token of this operand.
136 SMLoc
getEndLoc() const { return EndLoc
; }
138 unsigned getReg() const {
139 assert(Kind
== Register
&& "Invalid access!");
143 const MCExpr
*getImm() const {
144 assert(Kind
== Immediate
&& "Invalid access!");
148 const MCExpr
*getFslImm() const {
149 assert(Kind
== Fsl
&& "Invalid access!");
153 unsigned getMemBase() const {
154 assert(Kind
== Memory
&& "Invalid access!");
158 const MCExpr
* getMemOff() const {
159 assert(Kind
== Memory
&& "Invalid access!");
163 unsigned getMemOffReg() const {
164 assert(Kind
== Memory
&& "Invalid access!");
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
; }
174 void addExpr(MCInst
&Inst
, const MCExpr
*Expr
) const {
175 // Add as immediates when possible. Null MCExpr = 0.
177 Inst
.addOperand(MCOperand::CreateImm(0));
178 else if (const MCConstantExpr
*CE
= dyn_cast
<MCConstantExpr
>(Expr
))
179 Inst
.addOperand(MCOperand::CreateImm(CE
->getValue()));
181 Inst
.addOperand(MCOperand::CreateExpr(Expr
));
184 void addRegOperands(MCInst
&Inst
, unsigned N
) const {
185 assert(N
== 1 && "Invalid number of operands!");
186 Inst
.addOperand(MCOperand::CreateReg(getReg()));
189 void addImmOperands(MCInst
&Inst
, unsigned N
) const {
190 assert(N
== 1 && "Invalid number of operands!");
191 addExpr(Inst
, getImm());
194 void addFslOperands(MCInst
&Inst
, unsigned N
) const {
195 assert(N
== 1 && "Invalid number of operands!");
196 addExpr(Inst
, getFslImm());
199 void addMemOperands(MCInst
&Inst
, unsigned N
) const {
200 assert(N
== 2 && "Invalid number of operands!");
202 Inst
.addOperand(MCOperand::CreateReg(getMemBase()));
204 unsigned RegOff
= getMemOffReg();
206 Inst
.addOperand(MCOperand::CreateReg(RegOff
));
208 addExpr(Inst
, getMemOff());
211 StringRef
getToken() const {
212 assert(Kind
== Token
&& "Invalid access!");
213 return StringRef(Tok
.Data
, Tok
.Length
);
216 virtual void print(raw_ostream
&OS
) const;
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();
227 static MBlazeOperand
*CreateReg(unsigned RegNum
, SMLoc S
, SMLoc E
) {
228 MBlazeOperand
*Op
= new MBlazeOperand(Register
);
229 Op
->Reg
.RegNum
= RegNum
;
235 static MBlazeOperand
*CreateImm(const MCExpr
*Val
, SMLoc S
, SMLoc E
) {
236 MBlazeOperand
*Op
= new MBlazeOperand(Immediate
);
243 static MBlazeOperand
*CreateFslImm(const MCExpr
*Val
, SMLoc S
, SMLoc E
) {
244 MBlazeOperand
*Op
= new MBlazeOperand(Fsl
);
251 static MBlazeOperand
*CreateMem(unsigned Base
, const MCExpr
*Off
, SMLoc S
,
253 MBlazeOperand
*Op
= new MBlazeOperand(Memory
);
262 static MBlazeOperand
*CreateMem(unsigned Base
, unsigned Off
, SMLoc S
,
264 MBlazeOperand
*Op
= new MBlazeOperand(Memory
);
266 Op
->Mem
.OffReg
= Off
;
274 } // end anonymous namespace.
276 void MBlazeOperand::print(raw_ostream
&OS
) const {
283 OS
<< getMBlazeRegisterNumbering(getReg()) << ">";
286 OS
<< "'" << getToken() << "'";
290 OS
<< getMBlazeRegisterNumbering(getMemBase());
293 unsigned RegOff
= getMemOffReg();
295 OS
<< "R" << getMBlazeRegisterNumbering(RegOff
);
302 getFslImm()->print(OS
);
307 /// @name Auto-generated Match Functions
310 static unsigned MatchRegisterName(StringRef Name
);
314 bool MBlazeAsmParser::
315 MatchAndEmitInstruction(SMLoc IDLoc
,
316 SmallVectorImpl
<MCParsedAsmOperand
*> &Operands
,
322 switch (MatchInstructionImpl(Operands
, Kind
, Inst
, ErrorInfo
)) {
325 Out
.EmitInstruction(Inst
);
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");
337 ErrorLoc
= ((MBlazeOperand
*)Operands
[ErrorInfo
])->getStartLoc();
338 if (ErrorLoc
== SMLoc()) ErrorLoc
= IDLoc
;
341 return Error(ErrorLoc
, "invalid operand for instruction");
345 llvm_unreachable("Implement any new match types added!");
348 MBlazeOperand
*MBlazeAsmParser::
349 ParseMemory(SmallVectorImpl
<MCParsedAsmOperand
*> &Operands
) {
350 if (Operands
.size() != 4)
353 MBlazeOperand
&Base
= *(MBlazeOperand
*)Operands
[2];
354 MBlazeOperand
&Offset
= *(MBlazeOperand
*)Operands
[3];
356 SMLoc S
= Base
.getStartLoc();
357 SMLoc O
= Offset
.getStartLoc();
358 SMLoc E
= Offset
.getEndLoc();
361 Error(S
, "base address must be a register");
365 if (!Offset
.isReg() && !Offset
.isImm()) {
366 Error(O
, "offset must be a register or immediate");
372 Op
= MBlazeOperand::CreateMem(Base
.getReg(), Offset
.getReg(), S
, E
);
374 Op
= MBlazeOperand::CreateMem(Base
.getReg(), Offset
.getImm(), S
, E
);
376 delete Operands
.pop_back_val();
377 delete Operands
.pop_back_val();
378 Operands
.push_back(Op
);
383 bool MBlazeAsmParser::ParseRegister(unsigned &RegNo
,
384 SMLoc
&StartLoc
, SMLoc
&EndLoc
) {
385 return (ParseRegister(RegNo
) == 0);
388 MBlazeOperand
*MBlazeAsmParser::ParseRegister(unsigned &RegNo
) {
389 SMLoc S
= Parser
.getTok().getLoc();
390 SMLoc E
= SMLoc::getFromPointer(Parser
.getTok().getLoc().getPointer() - 1);
392 switch (getLexer().getKind()) {
394 case AsmToken::Identifier
:
395 RegNo
= MatchRegisterName(getLexer().getTok().getIdentifier());
400 return MBlazeOperand::CreateReg(RegNo
, S
, E
);
404 static unsigned MatchFslRegister(StringRef String
) {
405 if (!String
.startswith("rfsl"))
409 if (String
.substr(4).getAsInteger(10,regNum
))
415 MBlazeOperand
*MBlazeAsmParser::ParseFsl() {
416 SMLoc S
= Parser
.getTok().getLoc();
417 SMLoc E
= SMLoc::getFromPointer(Parser
.getTok().getLoc().getPointer() - 1);
419 switch (getLexer().getKind()) {
421 case AsmToken::Identifier
:
422 unsigned reg
= MatchFslRegister(getLexer().getTok().getIdentifier());
427 const MCExpr
*EVal
= MCConstantExpr::Create(reg
,getContext());
428 return MBlazeOperand::CreateFslImm(EVal
,S
,E
);
432 MBlazeOperand
*MBlazeAsmParser::ParseImmediate() {
433 SMLoc S
= Parser
.getTok().getLoc();
434 SMLoc E
= SMLoc::getFromPointer(Parser
.getTok().getLoc().getPointer() - 1);
437 switch (getLexer().getKind()) {
439 case AsmToken::LParen
:
441 case AsmToken::Minus
:
442 case AsmToken::Integer
:
443 case AsmToken::Identifier
:
444 if (getParser().ParseExpression(EVal
))
447 return MBlazeOperand::CreateImm(EVal
, S
, E
);
451 MBlazeOperand
*MBlazeAsmParser::
452 ParseOperand(SmallVectorImpl
<MCParsedAsmOperand
*> &Operands
) {
455 // Attempt to parse the next token as a register name
457 Op
= ParseRegister(RegNo
);
459 // Attempt to parse the next token as an FSL immediate
463 // Attempt to parse the next token as an immediate
465 Op
= ParseImmediate();
467 // If the token could not be parsed then fail
469 Error(Parser
.getTok().getLoc(), "unknown operand");
473 // Push the parsed operand into the list of operands
474 Operands
.push_back(Op
);
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
));
488 // If there are no more operands then finish
489 if (getLexer().is(AsmToken::EndOfStatement
))
492 // Parse the first operand
493 if (!ParseOperand(Operands
))
496 while (getLexer().isNot(AsmToken::EndOfStatement
) &&
497 getLexer().is(AsmToken::Comma
)) {
498 // Consume the comma token
501 // Parse the next operand
502 if (!ParseOperand(Operands
))
506 // If the instruction requires a memory operand then we need to
507 // replace the last two operands (base+offset) with a single
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
);
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());
525 /// ParseDirectiveWord
526 /// ::= .word [ expression (, expression)* ]
527 bool MBlazeAsmParser::ParseDirectiveWord(unsigned Size
, SMLoc L
) {
528 if (getLexer().isNot(AsmToken::EndOfStatement
)) {
531 if (getParser().ParseExpression(Value
))
534 getParser().getStreamer().EmitValue(Value
, Size
, 0 /*addrspace*/);
536 if (getLexer().is(AsmToken::EndOfStatement
))
539 // FIXME: Improve diagnostic.
540 if (getLexer().isNot(AsmToken::Comma
))
541 return Error(L
, "unexpected token in directive");
550 extern "C" void LLVMInitializeMBlazeAsmLexer();
552 /// Force static initialization.
553 extern "C" void LLVMInitializeMBlazeAsmParser() {
554 RegisterMCAsmParser
<MBlazeAsmParser
> X(TheMBlazeTarget
);
555 LLVMInitializeMBlazeAsmLexer();
558 #define GET_REGISTER_MATCHER
559 #define GET_MATCHER_IMPLEMENTATION
560 #include "MBlazeGenAsmMatcher.inc"