1 //===---- AVRAsmParser.cpp - Parse AVR assembly to MCInst instructions ----===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
10 #include "AVRRegisterInfo.h"
11 #include "MCTargetDesc/AVRMCELFStreamer.h"
12 #include "MCTargetDesc/AVRMCExpr.h"
13 #include "MCTargetDesc/AVRMCTargetDesc.h"
14 #include "TargetInfo/AVRTargetInfo.h"
16 #include "llvm/ADT/APInt.h"
17 #include "llvm/ADT/StringSwitch.h"
18 #include "llvm/MC/MCContext.h"
19 #include "llvm/MC/MCExpr.h"
20 #include "llvm/MC/MCInst.h"
21 #include "llvm/MC/MCInstBuilder.h"
22 #include "llvm/MC/MCParser/MCAsmLexer.h"
23 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
24 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
25 #include "llvm/MC/MCStreamer.h"
26 #include "llvm/MC/MCSubtargetInfo.h"
27 #include "llvm/MC/MCSymbol.h"
28 #include "llvm/MC/MCValue.h"
29 #include "llvm/Support/Debug.h"
30 #include "llvm/Support/MathExtras.h"
31 #include "llvm/Support/TargetRegistry.h"
35 #define DEBUG_TYPE "avr-asm-parser"
40 /// Parses AVR assembly from a stream.
41 class AVRAsmParser
: public MCTargetAsmParser
{
42 const MCSubtargetInfo
&STI
;
44 const MCRegisterInfo
*MRI
;
45 const std::string GENERATE_STUBS
= "gs";
47 #define GET_ASSEMBLER_HEADER
48 #include "AVRGenAsmMatcher.inc"
50 bool MatchAndEmitInstruction(SMLoc IDLoc
, unsigned &Opcode
,
51 OperandVector
&Operands
, MCStreamer
&Out
,
53 bool MatchingInlineAsm
) override
;
55 bool ParseRegister(unsigned &RegNo
, SMLoc
&StartLoc
, SMLoc
&EndLoc
) override
;
57 bool ParseInstruction(ParseInstructionInfo
&Info
, StringRef Name
,
58 SMLoc NameLoc
, OperandVector
&Operands
) override
;
60 bool ParseDirective(AsmToken DirectiveID
) override
;
62 OperandMatchResultTy
parseMemriOperand(OperandVector
&Operands
);
64 bool parseOperand(OperandVector
&Operands
);
65 int parseRegisterName(unsigned (*matchFn
)(StringRef
));
66 int parseRegisterName();
68 bool tryParseRegisterOperand(OperandVector
&Operands
);
69 bool tryParseExpression(OperandVector
&Operands
);
70 bool tryParseRelocExpression(OperandVector
&Operands
);
73 unsigned validateTargetOperandClass(MCParsedAsmOperand
&Op
,
74 unsigned Kind
) override
;
76 unsigned toDREG(unsigned Reg
, unsigned From
= AVR::sub_lo
) {
77 MCRegisterClass
const *Class
= &AVRMCRegisterClasses
[AVR::DREGSRegClassID
];
78 return MRI
->getMatchingSuperReg(Reg
, From
, Class
);
81 bool emit(MCInst
&Instruction
, SMLoc
const &Loc
, MCStreamer
&Out
) const;
82 bool invalidOperand(SMLoc
const &Loc
, OperandVector
const &Operands
,
83 uint64_t const &ErrorInfo
);
84 bool missingFeature(SMLoc
const &Loc
, uint64_t const &ErrorInfo
);
86 bool parseLiteralValues(unsigned SizeInBytes
, SMLoc L
);
89 AVRAsmParser(const MCSubtargetInfo
&STI
, MCAsmParser
&Parser
,
90 const MCInstrInfo
&MII
, const MCTargetOptions
&Options
)
91 : MCTargetAsmParser(Options
, STI
, MII
), STI(STI
), Parser(Parser
) {
92 MCAsmParserExtension::Initialize(Parser
);
93 MRI
= getContext().getRegisterInfo();
95 setAvailableFeatures(ComputeAvailableFeatures(STI
.getFeatureBits()));
98 MCAsmParser
&getParser() const { return Parser
; }
99 MCAsmLexer
&getLexer() const { return Parser
.getLexer(); }
102 /// An parsed AVR assembly operand.
103 class AVROperand
: public MCParsedAsmOperand
{
104 typedef MCParsedAsmOperand Base
;
105 enum KindTy
{ k_Immediate
, k_Register
, k_Token
, k_Memri
} Kind
;
108 AVROperand(StringRef Tok
, SMLoc
const &S
)
109 : Base(), Kind(k_Token
), Tok(Tok
), Start(S
), End(S
) {}
110 AVROperand(unsigned Reg
, SMLoc
const &S
, SMLoc
const &E
)
111 : Base(), Kind(k_Register
), RegImm({Reg
, nullptr}), Start(S
), End(E
) {}
112 AVROperand(MCExpr
const *Imm
, SMLoc
const &S
, SMLoc
const &E
)
113 : Base(), Kind(k_Immediate
), RegImm({0, Imm
}), Start(S
), End(E
) {}
114 AVROperand(unsigned Reg
, MCExpr
const *Imm
, SMLoc
const &S
, SMLoc
const &E
)
115 : Base(), Kind(k_Memri
), RegImm({Reg
, Imm
}), Start(S
), End(E
) {}
117 struct RegisterImmediate
{
123 RegisterImmediate RegImm
;
129 void addRegOperands(MCInst
&Inst
, unsigned N
) const {
130 assert(Kind
== k_Register
&& "Unexpected operand kind");
131 assert(N
== 1 && "Invalid number of operands!");
133 Inst
.addOperand(MCOperand::createReg(getReg()));
136 void addExpr(MCInst
&Inst
, const MCExpr
*Expr
) const {
137 // Add as immediate when possible
139 Inst
.addOperand(MCOperand::createImm(0));
140 else if (const MCConstantExpr
*CE
= dyn_cast
<MCConstantExpr
>(Expr
))
141 Inst
.addOperand(MCOperand::createImm(CE
->getValue()));
143 Inst
.addOperand(MCOperand::createExpr(Expr
));
146 void addImmOperands(MCInst
&Inst
, unsigned N
) const {
147 assert(Kind
== k_Immediate
&& "Unexpected operand kind");
148 assert(N
== 1 && "Invalid number of operands!");
150 const MCExpr
*Expr
= getImm();
154 /// Adds the contained reg+imm operand to an instruction.
155 void addMemriOperands(MCInst
&Inst
, unsigned N
) const {
156 assert(Kind
== k_Memri
&& "Unexpected operand kind");
157 assert(N
== 2 && "Invalid number of operands");
159 Inst
.addOperand(MCOperand::createReg(getReg()));
160 addExpr(Inst
, getImm());
163 void addImmCom8Operands(MCInst
&Inst
, unsigned N
) const {
164 assert(N
== 1 && "Invalid number of operands!");
165 // The operand is actually a imm8, but we have its bitwise
166 // negation in the assembly source, so twiddle it here.
167 const MCConstantExpr
*CE
= dyn_cast
<MCConstantExpr
>(getImm());
168 Inst
.addOperand(MCOperand::createImm(~(uint8_t)CE
->getValue()));
171 bool isImmCom8() const {
172 if (!isImm()) return false;
173 const MCConstantExpr
*CE
= dyn_cast
<MCConstantExpr
>(getImm());
174 if (!CE
) return false;
175 int64_t Value
= CE
->getValue();
176 return isUInt
<8>(Value
);
179 bool isReg() const { return Kind
== k_Register
; }
180 bool isImm() const { return Kind
== k_Immediate
; }
181 bool isToken() const { return Kind
== k_Token
; }
182 bool isMem() const { return Kind
== k_Memri
; }
183 bool isMemri() const { return Kind
== k_Memri
; }
185 StringRef
getToken() const {
186 assert(Kind
== k_Token
&& "Invalid access!");
190 unsigned getReg() const {
191 assert((Kind
== k_Register
|| Kind
== k_Memri
) && "Invalid access!");
196 const MCExpr
*getImm() const {
197 assert((Kind
== k_Immediate
|| Kind
== k_Memri
) && "Invalid access!");
201 static std::unique_ptr
<AVROperand
> CreateToken(StringRef Str
, SMLoc S
) {
202 return std::make_unique
<AVROperand
>(Str
, S
);
205 static std::unique_ptr
<AVROperand
> CreateReg(unsigned RegNum
, SMLoc S
,
207 return std::make_unique
<AVROperand
>(RegNum
, S
, E
);
210 static std::unique_ptr
<AVROperand
> CreateImm(const MCExpr
*Val
, SMLoc S
,
212 return std::make_unique
<AVROperand
>(Val
, S
, E
);
215 static std::unique_ptr
<AVROperand
>
216 CreateMemri(unsigned RegNum
, const MCExpr
*Val
, SMLoc S
, SMLoc E
) {
217 return std::make_unique
<AVROperand
>(RegNum
, Val
, S
, E
);
220 void makeToken(StringRef Token
) {
225 void makeReg(unsigned RegNo
) {
227 RegImm
= {RegNo
, nullptr};
230 void makeImm(MCExpr
const *Ex
) {
235 void makeMemri(unsigned RegNo
, MCExpr
const *Imm
) {
237 RegImm
= {RegNo
, Imm
};
240 SMLoc
getStartLoc() const { return Start
; }
241 SMLoc
getEndLoc() const { return End
; }
243 virtual void print(raw_ostream
&O
) const {
246 O
<< "Token: \"" << getToken() << "\"";
249 O
<< "Register: " << getReg();
252 O
<< "Immediate: \"" << *getImm() << "\"";
255 // only manually print the size for non-negative values,
256 // as the sign is inserted automatically.
257 O
<< "Memri: \"" << getReg() << '+' << *getImm() << "\"";
265 } // end anonymous namespace.
267 // Auto-generated Match Functions
269 /// Maps from the set of all register names to a register number.
270 /// \note Generated by TableGen.
271 static unsigned MatchRegisterName(StringRef Name
);
273 /// Maps from the set of all alternative registernames to a register number.
274 /// \note Generated by TableGen.
275 static unsigned MatchRegisterAltName(StringRef Name
);
277 bool AVRAsmParser::invalidOperand(SMLoc
const &Loc
,
278 OperandVector
const &Operands
,
279 uint64_t const &ErrorInfo
) {
280 SMLoc ErrorLoc
= Loc
;
281 char const *Diag
= 0;
283 if (ErrorInfo
!= ~0U) {
284 if (ErrorInfo
>= Operands
.size()) {
285 Diag
= "too few operands for instruction.";
287 AVROperand
const &Op
= (AVROperand
const &)*Operands
[ErrorInfo
];
289 // TODO: See if we can do a better error than just "invalid ...".
290 if (Op
.getStartLoc() != SMLoc()) {
291 ErrorLoc
= Op
.getStartLoc();
297 Diag
= "invalid operand for instruction";
300 return Error(ErrorLoc
, Diag
);
303 bool AVRAsmParser::missingFeature(llvm::SMLoc
const &Loc
,
304 uint64_t const &ErrorInfo
) {
305 return Error(Loc
, "instruction requires a CPU feature not currently enabled");
308 bool AVRAsmParser::emit(MCInst
&Inst
, SMLoc
const &Loc
, MCStreamer
&Out
) const {
310 Out
.EmitInstruction(Inst
, STI
);
315 bool AVRAsmParser::MatchAndEmitInstruction(SMLoc Loc
, unsigned &Opcode
,
316 OperandVector
&Operands
,
317 MCStreamer
&Out
, uint64_t &ErrorInfo
,
318 bool MatchingInlineAsm
) {
320 unsigned MatchResult
=
321 MatchInstructionImpl(Operands
, Inst
, ErrorInfo
, MatchingInlineAsm
);
323 switch (MatchResult
) {
324 case Match_Success
: return emit(Inst
, Loc
, Out
);
325 case Match_MissingFeature
: return missingFeature(Loc
, ErrorInfo
);
326 case Match_InvalidOperand
: return invalidOperand(Loc
, Operands
, ErrorInfo
);
327 case Match_MnemonicFail
: return Error(Loc
, "invalid instruction");
328 default: return true;
332 /// Parses a register name using a given matching function.
333 /// Checks for lowercase or uppercase if necessary.
334 int AVRAsmParser::parseRegisterName(unsigned (*matchFn
)(StringRef
)) {
335 StringRef Name
= Parser
.getTok().getString();
337 int RegNum
= matchFn(Name
);
339 // GCC supports case insensitive register names. Some of the AVR registers
340 // are all lower case, some are all upper case but non are mixed. We prefer
341 // to use the original names in the register definitions. That is why we
342 // have to test both upper and lower case here.
343 if (RegNum
== AVR::NoRegister
) {
344 RegNum
= matchFn(Name
.lower());
346 if (RegNum
== AVR::NoRegister
) {
347 RegNum
= matchFn(Name
.upper());
353 int AVRAsmParser::parseRegisterName() {
354 int RegNum
= parseRegisterName(&MatchRegisterName
);
356 if (RegNum
== AVR::NoRegister
)
357 RegNum
= parseRegisterName(&MatchRegisterAltName
);
362 int AVRAsmParser::parseRegister() {
363 int RegNum
= AVR::NoRegister
;
365 if (Parser
.getTok().is(AsmToken::Identifier
)) {
366 // Check for register pair syntax
367 if (Parser
.getLexer().peekTok().is(AsmToken::Colon
)) {
369 Parser
.Lex(); // Eat high (odd) register and colon
371 if (Parser
.getTok().is(AsmToken::Identifier
)) {
372 // Convert lower (even) register to DREG
373 RegNum
= toDREG(parseRegisterName());
376 RegNum
= parseRegisterName();
382 bool AVRAsmParser::tryParseRegisterOperand(OperandVector
&Operands
) {
383 int RegNo
= parseRegister();
385 if (RegNo
== AVR::NoRegister
)
388 AsmToken
const &T
= Parser
.getTok();
389 Operands
.push_back(AVROperand::CreateReg(RegNo
, T
.getLoc(), T
.getEndLoc()));
390 Parser
.Lex(); // Eat register token.
395 bool AVRAsmParser::tryParseExpression(OperandVector
&Operands
) {
396 SMLoc S
= Parser
.getTok().getLoc();
398 if (!tryParseRelocExpression(Operands
))
401 if ((Parser
.getTok().getKind() == AsmToken::Plus
||
402 Parser
.getTok().getKind() == AsmToken::Minus
) &&
403 Parser
.getLexer().peekTok().getKind() == AsmToken::Identifier
) {
404 // Don't handle this case - it should be split into two
409 // Parse (potentially inner) expression
410 MCExpr
const *Expression
;
411 if (getParser().parseExpression(Expression
))
414 SMLoc E
= SMLoc::getFromPointer(Parser
.getTok().getLoc().getPointer() - 1);
415 Operands
.push_back(AVROperand::CreateImm(Expression
, S
, E
));
419 bool AVRAsmParser::tryParseRelocExpression(OperandVector
&Operands
) {
420 bool isNegated
= false;
421 AVRMCExpr::VariantKind ModifierKind
= AVRMCExpr::VK_AVR_None
;
423 SMLoc S
= Parser
.getTok().getLoc();
427 size_t ReadCount
= Parser
.getLexer().peekTokens(tokens
);
429 if (ReadCount
== 2) {
430 if ((tokens
[0].getKind() == AsmToken::Identifier
&&
431 tokens
[1].getKind() == AsmToken::LParen
) ||
432 (tokens
[0].getKind() == AsmToken::LParen
&&
433 tokens
[1].getKind() == AsmToken::Minus
)) {
435 AsmToken::TokenKind CurTok
= Parser
.getLexer().getKind();
436 if (CurTok
== AsmToken::Minus
||
437 tokens
[1].getKind() == AsmToken::Minus
) {
440 assert(CurTok
== AsmToken::Plus
);
445 if (CurTok
== AsmToken::Minus
|| CurTok
== AsmToken::Plus
)
450 // Check if we have a target specific modifier (lo8, hi8, &c)
451 if (Parser
.getTok().getKind() != AsmToken::Identifier
||
452 Parser
.getLexer().peekTok().getKind() != AsmToken::LParen
) {
456 StringRef ModifierName
= Parser
.getTok().getString();
457 ModifierKind
= AVRMCExpr::getKindByName(ModifierName
.str().c_str());
459 if (ModifierKind
!= AVRMCExpr::VK_AVR_None
) {
461 Parser
.Lex(); // Eat modifier name and parenthesis
462 if (Parser
.getTok().getString() == GENERATE_STUBS
&&
463 Parser
.getTok().getKind() == AsmToken::Identifier
) {
464 std::string GSModName
= ModifierName
.str() + "_" + GENERATE_STUBS
;
465 ModifierKind
= AVRMCExpr::getKindByName(GSModName
.c_str());
466 if (ModifierKind
!= AVRMCExpr::VK_AVR_None
)
467 Parser
.Lex(); // Eat gs modifier name
470 return Error(Parser
.getTok().getLoc(), "unknown modifier");
473 if (tokens
[1].getKind() == AsmToken::Minus
||
474 tokens
[1].getKind() == AsmToken::Plus
) {
476 assert(Parser
.getTok().getKind() == AsmToken::LParen
);
477 Parser
.Lex(); // Eat the sign and parenthesis
480 MCExpr
const *InnerExpression
;
481 if (getParser().parseExpression(InnerExpression
))
484 if (tokens
[1].getKind() == AsmToken::Minus
||
485 tokens
[1].getKind() == AsmToken::Plus
) {
486 assert(Parser
.getTok().getKind() == AsmToken::RParen
);
487 Parser
.Lex(); // Eat closing parenthesis
490 // If we have a modifier wrap the inner expression
491 assert(Parser
.getTok().getKind() == AsmToken::RParen
);
492 Parser
.Lex(); // Eat closing parenthesis
494 MCExpr
const *Expression
= AVRMCExpr::create(ModifierKind
, InnerExpression
,
495 isNegated
, getContext());
497 SMLoc E
= SMLoc::getFromPointer(Parser
.getTok().getLoc().getPointer() - 1);
498 Operands
.push_back(AVROperand::CreateImm(Expression
, S
, E
));
503 bool AVRAsmParser::parseOperand(OperandVector
&Operands
) {
504 LLVM_DEBUG(dbgs() << "parseOperand\n");
506 switch (getLexer().getKind()) {
508 return Error(Parser
.getTok().getLoc(), "unexpected token in operand");
510 case AsmToken::Identifier
:
511 // Try to parse a register, if it fails,
512 // fall through to the next case.
513 if (!tryParseRegisterOperand(Operands
)) {
517 case AsmToken::LParen
:
518 case AsmToken::Integer
:
520 return tryParseExpression(Operands
);
522 case AsmToken::Minus
: {
523 // If the sign preceeds a number, parse the number,
524 // otherwise treat the sign a an independent token.
525 switch (getLexer().peekTok().getKind()) {
526 case AsmToken::Integer
:
527 case AsmToken::BigNum
:
528 case AsmToken::Identifier
:
530 if (!tryParseExpression(Operands
))
536 // Treat the token as an independent token.
537 Operands
.push_back(AVROperand::CreateToken(Parser
.getTok().getString(),
538 Parser
.getTok().getLoc()));
539 Parser
.Lex(); // Eat the token.
544 // Could not parse operand
549 AVRAsmParser::parseMemriOperand(OperandVector
&Operands
) {
550 LLVM_DEBUG(dbgs() << "parseMemriOperand()\n");
553 MCExpr
const *Expression
;
558 RegNo
= parseRegister();
560 if (RegNo
== AVR::NoRegister
)
561 return MatchOperand_ParseFail
;
563 S
= SMLoc::getFromPointer(Parser
.getTok().getLoc().getPointer() - 1);
564 Parser
.Lex(); // Eat register token.
569 if (getParser().parseExpression(Expression
))
570 return MatchOperand_ParseFail
;
572 E
= SMLoc::getFromPointer(Parser
.getTok().getLoc().getPointer() - 1);
575 Operands
.push_back(AVROperand::CreateMemri(RegNo
, Expression
, S
, E
));
577 return MatchOperand_Success
;
580 bool AVRAsmParser::ParseRegister(unsigned &RegNo
, SMLoc
&StartLoc
,
582 StartLoc
= Parser
.getTok().getLoc();
583 RegNo
= parseRegister();
584 EndLoc
= Parser
.getTok().getLoc();
586 return (RegNo
== AVR::NoRegister
);
589 void AVRAsmParser::eatComma() {
590 if (getLexer().is(AsmToken::Comma
)) {
593 // GCC allows commas to be omitted.
597 bool AVRAsmParser::ParseInstruction(ParseInstructionInfo
&Info
,
598 StringRef Mnemonic
, SMLoc NameLoc
,
599 OperandVector
&Operands
) {
600 Operands
.push_back(AVROperand::CreateToken(Mnemonic
, NameLoc
));
603 while (getLexer().isNot(AsmToken::EndOfStatement
)) {
604 if (!first
) eatComma();
608 auto MatchResult
= MatchOperandParserImpl(Operands
, Mnemonic
);
610 if (MatchResult
== MatchOperand_Success
) {
614 if (MatchResult
== MatchOperand_ParseFail
) {
615 SMLoc Loc
= getLexer().getLoc();
616 Parser
.eatToEndOfStatement();
618 return Error(Loc
, "failed to parse register and immediate pair");
621 if (parseOperand(Operands
)) {
622 SMLoc Loc
= getLexer().getLoc();
623 Parser
.eatToEndOfStatement();
624 return Error(Loc
, "unexpected token in argument list");
627 Parser
.Lex(); // Consume the EndOfStatement
631 bool AVRAsmParser::ParseDirective(llvm::AsmToken DirectiveID
) {
632 StringRef IDVal
= DirectiveID
.getIdentifier();
633 if (IDVal
.lower() == ".long") {
634 parseLiteralValues(SIZE_LONG
, DirectiveID
.getLoc());
635 } else if (IDVal
.lower() == ".word" || IDVal
.lower() == ".short") {
636 parseLiteralValues(SIZE_WORD
, DirectiveID
.getLoc());
637 } else if (IDVal
.lower() == ".byte") {
638 parseLiteralValues(1, DirectiveID
.getLoc());
643 bool AVRAsmParser::parseLiteralValues(unsigned SizeInBytes
, SMLoc L
) {
644 MCAsmParser
&Parser
= getParser();
645 AVRMCELFStreamer
&AVRStreamer
=
646 static_cast<AVRMCELFStreamer
&>(Parser
.getStreamer());
648 size_t ReadCount
= Parser
.getLexer().peekTokens(Tokens
);
649 if (ReadCount
== 2 && Parser
.getTok().getKind() == AsmToken::Identifier
&&
650 Tokens
[0].getKind() == AsmToken::Minus
&&
651 Tokens
[1].getKind() == AsmToken::Identifier
) {
652 MCSymbol
*Symbol
= getContext().getOrCreateSymbol(".text");
653 AVRStreamer
.EmitValueForModiferKind(Symbol
, SizeInBytes
, L
,
654 AVRMCExpr::VK_AVR_None
);
658 if (Parser
.getTok().getKind() == AsmToken::Identifier
&&
659 Parser
.getLexer().peekTok().getKind() == AsmToken::LParen
) {
660 StringRef ModifierName
= Parser
.getTok().getString();
661 AVRMCExpr::VariantKind ModifierKind
=
662 AVRMCExpr::getKindByName(ModifierName
.str().c_str());
663 if (ModifierKind
!= AVRMCExpr::VK_AVR_None
) {
665 Parser
.Lex(); // Eat the modifier and parenthesis
667 return Error(Parser
.getTok().getLoc(), "unknown modifier");
670 getContext().getOrCreateSymbol(Parser
.getTok().getString());
671 AVRStreamer
.EmitValueForModiferKind(Symbol
, SizeInBytes
, L
, ModifierKind
);
675 auto parseOne
= [&]() -> bool {
677 if (Parser
.parseExpression(Value
))
679 Parser
.getStreamer().EmitValue(Value
, SizeInBytes
, L
);
682 return (parseMany(parseOne
));
685 extern "C" void LLVMInitializeAVRAsmParser() {
686 RegisterMCAsmParser
<AVRAsmParser
> X(getTheAVRTarget());
689 #define GET_REGISTER_MATCHER
690 #define GET_MATCHER_IMPLEMENTATION
691 #include "AVRGenAsmMatcher.inc"
693 // Uses enums defined in AVRGenAsmMatcher.inc
694 unsigned AVRAsmParser::validateTargetOperandClass(MCParsedAsmOperand
&AsmOp
,
695 unsigned ExpectedKind
) {
696 AVROperand
&Op
= static_cast<AVROperand
&>(AsmOp
);
697 MatchClassKind Expected
= static_cast<MatchClassKind
>(ExpectedKind
);
699 // If need be, GCC converts bare numbers to register names
700 // It's ugly, but GCC supports it.
702 if (MCConstantExpr
const *Const
= dyn_cast
<MCConstantExpr
>(Op
.getImm())) {
703 int64_t RegNum
= Const
->getValue();
704 std::ostringstream RegName
;
705 RegName
<< "r" << RegNum
;
706 RegNum
= MatchRegisterName(RegName
.str().c_str());
707 if (RegNum
!= AVR::NoRegister
) {
709 if (validateOperandClass(Op
, Expected
) == Match_Success
) {
710 return Match_Success
;
713 // Let the other quirks try their magic.
718 // If the instruction uses a register pair but we got a single, lower
719 // register we perform a "class cast".
720 if (isSubclass(Expected
, MCK_DREGS
)) {
721 unsigned correspondingDREG
= toDREG(Op
.getReg());
723 if (correspondingDREG
!= AVR::NoRegister
) {
724 Op
.makeReg(correspondingDREG
);
725 return validateOperandClass(Op
, Expected
);
729 return Match_InvalidOperand
;