1 //===---- M68kAsmParser.cpp - Parse M68k 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 //===----------------------------------------------------------------------===//
9 #include "M68kInstrInfo.h"
10 #include "M68kRegisterInfo.h"
11 #include "TargetInfo/M68kTargetInfo.h"
13 #include "llvm/MC/MCContext.h"
14 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
15 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
16 #include "llvm/MC/MCStreamer.h"
17 #include "llvm/Support/TargetRegistry.h"
21 #define DEBUG_TYPE "m68k-asm-parser"
25 static cl::opt
<bool> RegisterPrefixOptional(
26 "m68k-register-prefix-optional", cl::Hidden
,
27 cl::desc("Enable specifying registers without the % prefix"),
31 /// Parses M68k assembly from a stream.
32 class M68kAsmParser
: public MCTargetAsmParser
{
33 const MCSubtargetInfo
&STI
;
35 const MCRegisterInfo
*MRI
;
37 #define GET_ASSEMBLER_HEADER
38 #include "M68kGenAsmMatcher.inc"
40 // Helpers for Match&Emit.
41 bool invalidOperand(const SMLoc
&Loc
, const OperandVector
&Operands
,
42 const uint64_t &ErrorInfo
);
43 bool missingFeature(const SMLoc
&Loc
, const uint64_t &ErrorInfo
);
44 bool emit(MCInst
&Inst
, SMLoc
const &Loc
, MCStreamer
&Out
) const;
45 bool parseRegisterName(unsigned int &RegNo
, SMLoc Loc
,
46 StringRef RegisterName
);
47 OperandMatchResultTy
parseRegister(unsigned int &RegNo
);
53 OperandMatchResultTy
parseImm(OperandVector
&Operands
);
54 OperandMatchResultTy
parseMemOp(OperandVector
&Operands
);
57 M68kAsmParser(const MCSubtargetInfo
&STI
, MCAsmParser
&Parser
,
58 const MCInstrInfo
&MII
, const MCTargetOptions
&Options
)
59 : MCTargetAsmParser(Options
, STI
, MII
), STI(STI
), Parser(Parser
) {
60 MCAsmParserExtension::Initialize(Parser
);
61 MRI
= getContext().getRegisterInfo();
63 setAvailableFeatures(ComputeAvailableFeatures(STI
.getFeatureBits()));
66 unsigned validateTargetOperandClass(MCParsedAsmOperand
&Op
,
67 unsigned Kind
) override
;
68 bool ParseRegister(unsigned &RegNo
, SMLoc
&StartLoc
, SMLoc
&EndLoc
) override
;
69 OperandMatchResultTy
tryParseRegister(unsigned &RegNo
, SMLoc
&StartLoc
,
70 SMLoc
&EndLoc
) override
;
71 bool ParseInstruction(ParseInstructionInfo
&Info
, StringRef Name
,
72 SMLoc NameLoc
, OperandVector
&Operands
) override
;
73 bool ParseDirective(AsmToken DirectiveID
) override
;
74 bool MatchAndEmitInstruction(SMLoc IDLoc
, unsigned &Opcode
,
75 OperandVector
&Operands
, MCStreamer
&Out
,
77 bool MatchingInlineAsm
) override
;
87 RegIndirectDisplacement
,
88 RegIndirectDisplacementIndex
,
91 // These variables are used for the following forms:
94 // RegIndirect: (%OuterReg)
95 // RegPostIncrement: (%OuterReg)+
96 // RegPreDecrement: -(%OuterReg)
97 // RegIndirectDisplacement: OuterDisp(%OuterReg)
98 // RegIndirectDisplacementIndex:
99 // OuterDisp(%OuterReg, %InnerReg.Size * Scale, InnerDisp)
104 const MCExpr
*OuterDisp
;
105 const MCExpr
*InnerDisp
;
111 M68kMemOp(Kind Op
) : Op(Op
) {}
113 void print(raw_ostream
&OS
) const;
116 /// An parsed M68k assembly operand.
117 class M68kOperand
: public MCParsedAsmOperand
{
118 typedef MCParsedAsmOperand Base
;
136 template <unsigned N
> bool isAddrN() const;
139 M68kOperand(enum Kind Kind
, SMLoc Start
, SMLoc End
)
140 : Base(), Kind(Kind
), Start(Start
), End(End
) {}
142 SMLoc
getStartLoc() const override
{ return Start
; }
143 SMLoc
getEndLoc() const override
{ return End
; }
145 void print(raw_ostream
&OS
) const override
;
147 bool isMem() const override
{ return false; }
148 bool isMemOp() const { return Kind
== Kind::MemOp
; }
150 static void addExpr(MCInst
&Inst
, const MCExpr
*Expr
);
153 bool isReg() const override
;
156 unsigned getReg() const override
;
157 void addRegOperands(MCInst
&Inst
, unsigned N
) const;
159 static std::unique_ptr
<M68kOperand
> createMemOp(M68kMemOp MemOp
, SMLoc Start
,
163 bool isToken() const override
;
164 StringRef
getToken() const;
165 static std::unique_ptr
<M68kOperand
> createToken(StringRef Token
, SMLoc Start
,
169 bool isImm() const override
;
170 void addImmOperands(MCInst
&Inst
, unsigned N
) const;
172 static std::unique_ptr
<M68kOperand
> createImm(const MCExpr
*Expr
, SMLoc Start
,
177 bool isAddr8() const { return isAddrN
<8>(); }
178 bool isAddr16() const { return isAddrN
<16>(); }
179 bool isAddr32() const { return isAddrN
<32>(); }
180 void addAddrOperands(MCInst
&Inst
, unsigned N
) const;
184 void addARIOperands(MCInst
&Inst
, unsigned N
) const;
188 void addARIDOperands(MCInst
&Inst
, unsigned N
) const;
192 void addARIIOperands(MCInst
&Inst
, unsigned N
) const;
195 bool isARIPD() const;
196 void addARIPDOperands(MCInst
&Inst
, unsigned N
) const;
199 bool isARIPI() const;
200 void addARIPIOperands(MCInst
&Inst
, unsigned N
) const;
204 void addPCDOperands(MCInst
&Inst
, unsigned N
) const;
208 void addPCIOperands(MCInst
&Inst
, unsigned N
) const;
211 } // end anonymous namespace.
213 extern "C" LLVM_EXTERNAL_VISIBILITY
void LLVMInitializeM68kAsmParser() {
214 RegisterMCAsmParser
<M68kAsmParser
> X(getTheM68kTarget());
217 #define GET_MATCHER_IMPLEMENTATION
218 #include "M68kGenAsmMatcher.inc"
220 void M68kMemOp::print(raw_ostream
&OS
) const {
226 OS
<< '%' << OuterReg
;
228 case Kind::RegIndirect
:
229 OS
<< "(%" << OuterReg
<< ')';
231 case Kind::RegPostIncrement
:
232 OS
<< "(%" << OuterReg
<< ")+";
234 case Kind::RegPreDecrement
:
235 OS
<< "-(%" << OuterReg
<< ")";
237 case Kind::RegIndirectDisplacement
:
238 OS
<< OuterDisp
<< "(%" << OuterReg
<< ")";
240 case Kind::RegIndirectDisplacementIndex
:
241 OS
<< OuterDisp
<< "(%" << OuterReg
<< ", " << InnerReg
<< "." << Size
242 << ", " << InnerDisp
<< ")";
247 void M68kOperand::addExpr(MCInst
&Inst
, const MCExpr
*Expr
) {
248 if (auto Const
= dyn_cast
<MCConstantExpr
>(Expr
)) {
249 Inst
.addOperand(MCOperand::createImm(Const
->getValue()));
253 Inst
.addOperand(MCOperand::createExpr(Expr
));
257 bool M68kOperand::isReg() const {
258 return Kind
== Kind::MemOp
&& MemOp
.Op
== M68kMemOp::Kind::Reg
;
261 unsigned M68kOperand::getReg() const {
263 return MemOp
.OuterReg
;
266 void M68kOperand::addRegOperands(MCInst
&Inst
, unsigned N
) const {
267 assert(isReg() && "wrong operand kind");
268 assert((N
== 1) && "can only handle one register operand");
270 Inst
.addOperand(MCOperand::createReg(getReg()));
273 std::unique_ptr
<M68kOperand
> M68kOperand::createMemOp(M68kMemOp MemOp
,
274 SMLoc Start
, SMLoc End
) {
275 auto Op
= std::make_unique
<M68kOperand
>(Kind::MemOp
, Start
, End
);
281 bool M68kOperand::isToken() const { return Kind
== Kind::Token
; }
282 StringRef
M68kOperand::getToken() const {
287 std::unique_ptr
<M68kOperand
> M68kOperand::createToken(StringRef Token
,
288 SMLoc Start
, SMLoc End
) {
289 auto Op
= std::make_unique
<M68kOperand
>(Kind::Token
, Start
, End
);
295 bool M68kOperand::isImm() const { return Kind
== Kind::Imm
; }
296 void M68kOperand::addImmOperands(MCInst
&Inst
, unsigned N
) const {
297 assert(isImm() && "wrong oeprand kind");
298 assert((N
== 1) && "can only handle one register operand");
300 M68kOperand::addExpr(Inst
, Expr
);
303 std::unique_ptr
<M68kOperand
> M68kOperand::createImm(const MCExpr
*Expr
,
304 SMLoc Start
, SMLoc End
) {
305 auto Op
= std::make_unique
<M68kOperand
>(Kind::Imm
, Start
, End
);
311 bool M68kOperand::isAddr() const {
312 return isMemOp() && MemOp
.Op
== M68kMemOp::Kind::Addr
;
314 // TODO: Maybe we can also store the size of OuterDisp
316 template <unsigned N
> bool M68kOperand::isAddrN() const {
319 if (MemOp
.OuterDisp
->evaluateAsAbsolute(Res
))
320 return isInt
<N
>(Res
);
325 void M68kOperand::addAddrOperands(MCInst
&Inst
, unsigned N
) const {
326 M68kOperand::addExpr(Inst
, MemOp
.OuterDisp
);
330 bool M68kOperand::isARI() const {
331 return isMemOp() && MemOp
.Op
== M68kMemOp::Kind::RegIndirect
&&
332 M68k::AR32RegClass
.contains(MemOp
.OuterReg
);
334 void M68kOperand::addARIOperands(MCInst
&Inst
, unsigned N
) const {
335 Inst
.addOperand(MCOperand::createReg(MemOp
.OuterReg
));
339 bool M68kOperand::isARID() const {
340 return isMemOp() && MemOp
.Op
== M68kMemOp::Kind::RegIndirectDisplacement
&&
341 M68k::AR32RegClass
.contains(MemOp
.OuterReg
);
343 void M68kOperand::addARIDOperands(MCInst
&Inst
, unsigned N
) const {
344 M68kOperand::addExpr(Inst
, MemOp
.OuterDisp
);
345 Inst
.addOperand(MCOperand::createReg(MemOp
.OuterReg
));
349 bool M68kOperand::isARII() const {
351 MemOp
.Op
== M68kMemOp::Kind::RegIndirectDisplacementIndex
&&
352 M68k::AR32RegClass
.contains(MemOp
.OuterReg
);
354 void M68kOperand::addARIIOperands(MCInst
&Inst
, unsigned N
) const {
355 M68kOperand::addExpr(Inst
, MemOp
.OuterDisp
);
356 Inst
.addOperand(MCOperand::createReg(MemOp
.OuterReg
));
357 Inst
.addOperand(MCOperand::createReg(MemOp
.InnerReg
));
361 bool M68kOperand::isARIPD() const {
362 return isMemOp() && MemOp
.Op
== M68kMemOp::Kind::RegPreDecrement
&&
363 M68k::AR32RegClass
.contains(MemOp
.OuterReg
);
365 void M68kOperand::addARIPDOperands(MCInst
&Inst
, unsigned N
) const {
366 Inst
.addOperand(MCOperand::createReg(MemOp
.OuterReg
));
370 bool M68kOperand::isARIPI() const {
371 return isMemOp() && MemOp
.Op
== M68kMemOp::Kind::RegPostIncrement
&&
372 M68k::AR32RegClass
.contains(MemOp
.OuterReg
);
374 void M68kOperand::addARIPIOperands(MCInst
&Inst
, unsigned N
) const {
375 Inst
.addOperand(MCOperand::createReg(MemOp
.OuterReg
));
379 bool M68kOperand::isPCD() const {
380 return isMemOp() && MemOp
.Op
== M68kMemOp::Kind::RegIndirectDisplacement
&&
381 MemOp
.OuterReg
== M68k::PC
;
383 void M68kOperand::addPCDOperands(MCInst
&Inst
, unsigned N
) const {
384 M68kOperand::addExpr(Inst
, MemOp
.OuterDisp
);
388 bool M68kOperand::isPCI() const {
390 MemOp
.Op
== M68kMemOp::Kind::RegIndirectDisplacementIndex
&&
391 MemOp
.OuterReg
== M68k::PC
;
393 void M68kOperand::addPCIOperands(MCInst
&Inst
, unsigned N
) const {
394 M68kOperand::addExpr(Inst
, MemOp
.OuterDisp
);
395 Inst
.addOperand(MCOperand::createReg(MemOp
.InnerReg
));
398 static inline bool checkRegisterClass(unsigned RegNo
, bool Data
, bool Address
,
428 llvm_unreachable("unexpected register type");
433 bool M68kOperand::isAReg() const {
434 return isReg() && checkRegisterClass(getReg(),
436 /*Address=*/true, /*SP=*/true);
439 bool M68kOperand::isDReg() const {
440 return isReg() && checkRegisterClass(getReg(),
442 /*Address=*/false, /*SP=*/false);
445 unsigned M68kAsmParser::validateTargetOperandClass(MCParsedAsmOperand
&Op
,
447 M68kOperand
&Operand
= (M68kOperand
&)Op
;
452 if (Operand
.isReg() &&
453 checkRegisterClass(Operand
.getReg(), true, true, true)) {
454 return Match_Success
;
460 if (Operand
.isReg() &&
461 checkRegisterClass(Operand
.getReg(), false, true, true)) {
462 return Match_Success
;
467 if (Operand
.isReg() &&
468 checkRegisterClass(Operand
.getReg(), false, true, false)) {
469 return Match_Success
;
476 if (Operand
.isReg() &&
477 checkRegisterClass(Operand
.getReg(), true, false, false)) {
478 return Match_Success
;
483 if (Operand
.isReg() &&
484 ((Operand
.getReg() == M68k::A0
) || (Operand
.getReg() == M68k::A1
))) {
485 return Match_Success
;
490 if (Operand
.isReg() &&
491 ((Operand
.getReg() == M68k::D0
) || (Operand
.getReg() == M68k::D1
))) {
492 return Match_Success
;
497 if (Operand
.isReg() &&
498 ((Operand
.getReg() == M68k::D0
) || (Operand
.getReg() == M68k::D1
) ||
499 (Operand
.getReg() == M68k::A0
) || (Operand
.getReg() == M68k::A1
))) {
500 return Match_Success
;
505 return Match_InvalidOperand
;
508 bool M68kAsmParser::parseRegisterName(unsigned &RegNo
, SMLoc Loc
,
509 StringRef RegisterName
) {
510 auto RegisterNameLower
= RegisterName
.lower();
513 if (RegisterNameLower
== "ccr") {
518 // Parse simple general-purpose registers.
519 if (RegisterNameLower
.size() == 2) {
520 static unsigned RegistersByIndex
[] = {
521 M68k::D0
, M68k::D1
, M68k::D2
, M68k::D3
, M68k::D4
, M68k::D5
,
522 M68k::D6
, M68k::D7
, M68k::A0
, M68k::A1
, M68k::A2
, M68k::A3
,
523 M68k::A4
, M68k::A5
, M68k::A6
, M68k::SP
,
526 switch (RegisterNameLower
[0]) {
529 if (isdigit(RegisterNameLower
[1])) {
530 unsigned IndexOffset
= (RegisterNameLower
[0] == 'a') ? 8 : 0;
531 unsigned RegIndex
= (unsigned)(RegisterNameLower
[1] - '0');
533 RegNo
= RegistersByIndex
[IndexOffset
+ RegIndex
];
541 if (RegisterNameLower
[1] == 'p') {
544 } else if (RegisterNameLower
[1] == 'r') {
551 if (RegisterNameLower
[1] == 'c') {
562 OperandMatchResultTy
M68kAsmParser::parseRegister(unsigned &RegNo
) {
563 bool HasPercent
= false;
564 AsmToken PercentToken
;
566 LLVM_DEBUG(dbgs() << "parseRegister "; getTok().dump(dbgs()); dbgs() << "\n");
568 if (getTok().is(AsmToken::Percent
)) {
570 PercentToken
= Lex();
571 } else if (!RegisterPrefixOptional
.getValue()) {
572 return MatchOperand_NoMatch
;
575 if (!Parser
.getTok().is(AsmToken::Identifier
)) {
577 getLexer().UnLex(PercentToken
);
579 return MatchOperand_NoMatch
;
582 auto RegisterName
= Parser
.getTok().getString();
583 if (!parseRegisterName(RegNo
, Parser
.getLexer().getLoc(), RegisterName
)) {
585 getLexer().UnLex(PercentToken
);
587 return MatchOperand_NoMatch
;
591 return MatchOperand_Success
;
594 bool M68kAsmParser::ParseRegister(unsigned &RegNo
, SMLoc
&StartLoc
,
596 auto Result
= tryParseRegister(RegNo
, StartLoc
, EndLoc
);
597 if (Result
!= MatchOperand_Success
) {
598 return Error(StartLoc
, "expected register");
604 OperandMatchResultTy
M68kAsmParser::tryParseRegister(unsigned &RegNo
,
607 StartLoc
= getLexer().getLoc();
608 auto Result
= parseRegister(RegNo
);
609 EndLoc
= getLexer().getLoc();
613 bool M68kAsmParser::isExpr() {
614 switch (Parser
.getTok().getKind()) {
615 case AsmToken::Identifier
:
616 case AsmToken::Integer
:
618 case AsmToken::Minus
:
619 return getLexer().peekTok().getKind() == AsmToken::Integer
;
626 OperandMatchResultTy
M68kAsmParser::parseImm(OperandVector
&Operands
) {
627 if (getLexer().isNot(AsmToken::Hash
)) {
628 return MatchOperand_NoMatch
;
630 SMLoc Start
= getLexer().getLoc();
636 if (getParser().parseExpression(Expr
, End
)) {
637 return MatchOperand_ParseFail
;
640 Operands
.push_back(M68kOperand::createImm(Expr
, Start
, End
));
641 return MatchOperand_Success
;
644 OperandMatchResultTy
M68kAsmParser::parseMemOp(OperandVector
&Operands
) {
645 SMLoc Start
= getLexer().getLoc();
649 // Check for a plain register.
650 auto Result
= parseRegister(MemOp
.OuterReg
);
651 if (Result
== MatchOperand_Success
) {
652 MemOp
.Op
= M68kMemOp::Kind::Reg
;
654 M68kOperand::createMemOp(MemOp
, Start
, getLexer().getLoc()));
655 return MatchOperand_Success
;
658 if (Result
== MatchOperand_ParseFail
) {
662 // Check for pre-decrement & outer displacement.
663 bool HasDisplacement
= false;
664 if (getLexer().is(AsmToken::Minus
)) {
667 } else if (isExpr()) {
668 if (Parser
.parseExpression(MemOp
.OuterDisp
)) {
669 return MatchOperand_ParseFail
;
671 HasDisplacement
= true;
674 if (getLexer().isNot(AsmToken::LParen
)) {
675 if (HasDisplacement
) {
676 MemOp
.Op
= M68kMemOp::Kind::Addr
;
678 M68kOperand::createMemOp(MemOp
, Start
, getLexer().getLoc()));
679 return MatchOperand_Success
;
681 Error(getLexer().getLoc(), "expected (");
682 return MatchOperand_ParseFail
;
685 return MatchOperand_NoMatch
;
689 // Check for constant dereference & MIT-style displacement
690 if (!HasDisplacement
&& isExpr()) {
691 if (Parser
.parseExpression(MemOp
.OuterDisp
)) {
692 return MatchOperand_ParseFail
;
694 HasDisplacement
= true;
696 // If we're not followed by a comma, we're a constant dereference.
697 if (getLexer().isNot(AsmToken::Comma
)) {
698 MemOp
.Op
= M68kMemOp::Kind::Addr
;
700 M68kOperand::createMemOp(MemOp
, Start
, getLexer().getLoc()));
701 return MatchOperand_Success
;
707 Result
= parseRegister(MemOp
.OuterReg
);
708 if (Result
== MatchOperand_ParseFail
) {
709 return MatchOperand_ParseFail
;
712 if (Result
!= MatchOperand_Success
) {
713 Error(getLexer().getLoc(), "expected register");
714 return MatchOperand_ParseFail
;
718 bool HasIndex
= false;
719 if (Parser
.getTok().is(AsmToken::Comma
)) {
722 Result
= parseRegister(MemOp
.InnerReg
);
723 if (Result
== MatchOperand_ParseFail
) {
727 if (Result
== MatchOperand_NoMatch
) {
728 Error(getLexer().getLoc(), "expected register");
729 return MatchOperand_ParseFail
;
732 // TODO: parse size, scale and inner displacement.
735 MemOp
.InnerDisp
= MCConstantExpr::create(0, Parser
.getContext(), true, 4);
739 if (Parser
.getTok().isNot(AsmToken::RParen
)) {
740 Error(getLexer().getLoc(), "expected )");
741 return MatchOperand_ParseFail
;
746 if (!IsPD
&& Parser
.getTok().is(AsmToken::Plus
)) {
751 SMLoc End
= getLexer().getLoc();
753 unsigned OpCount
= IsPD
+ IsPI
+ (HasIndex
|| HasDisplacement
);
755 Error(Start
, "only one of post-increment, pre-decrement or displacement "
757 return MatchOperand_ParseFail
;
761 MemOp
.Op
= M68kMemOp::Kind::RegPreDecrement
;
763 MemOp
.Op
= M68kMemOp::Kind::RegPostIncrement
;
764 } else if (HasIndex
) {
765 MemOp
.Op
= M68kMemOp::Kind::RegIndirectDisplacementIndex
;
766 } else if (HasDisplacement
) {
767 MemOp
.Op
= M68kMemOp::Kind::RegIndirectDisplacement
;
769 MemOp
.Op
= M68kMemOp::Kind::RegIndirect
;
772 Operands
.push_back(M68kOperand::createMemOp(MemOp
, Start
, End
));
773 return MatchOperand_Success
;
776 void M68kAsmParser::eatComma() {
777 if (Parser
.getTok().is(AsmToken::Comma
)) {
782 bool M68kAsmParser::ParseInstruction(ParseInstructionInfo
&Info
, StringRef Name
,
783 SMLoc NameLoc
, OperandVector
&Operands
) {
784 SMLoc Start
= getLexer().getLoc();
785 Operands
.push_back(M68kOperand::createToken(Name
, Start
, Start
));
788 while (Parser
.getTok().isNot(AsmToken::EndOfStatement
)) {
795 auto MatchResult
= MatchOperandParserImpl(Operands
, Name
);
796 if (MatchResult
== MatchOperand_Success
) {
800 // Add custom operand formats here...
801 SMLoc Loc
= getLexer().getLoc();
802 Parser
.eatToEndOfStatement();
803 return Error(Loc
, "unexpected token parsing operands");
806 // Eat EndOfStatement.
811 bool M68kAsmParser::ParseDirective(AsmToken DirectiveID
) { return true; }
813 bool M68kAsmParser::invalidOperand(SMLoc
const &Loc
,
814 OperandVector
const &Operands
,
815 uint64_t const &ErrorInfo
) {
816 SMLoc ErrorLoc
= Loc
;
817 char const *Diag
= 0;
819 if (ErrorInfo
!= ~0U) {
820 if (ErrorInfo
>= Operands
.size()) {
821 Diag
= "too few operands for instruction.";
823 auto const &Op
= (M68kOperand
const &)*Operands
[ErrorInfo
];
824 if (Op
.getStartLoc() != SMLoc()) {
825 ErrorLoc
= Op
.getStartLoc();
831 Diag
= "invalid operand for instruction";
834 return Error(ErrorLoc
, Diag
);
837 bool M68kAsmParser::missingFeature(llvm::SMLoc
const &Loc
,
838 uint64_t const &ErrorInfo
) {
839 return Error(Loc
, "instruction requires a CPU feature not currently enabled");
842 bool M68kAsmParser::emit(MCInst
&Inst
, SMLoc
const &Loc
,
843 MCStreamer
&Out
) const {
845 Out
.emitInstruction(Inst
, STI
);
850 bool M68kAsmParser::MatchAndEmitInstruction(SMLoc Loc
, unsigned &Opcode
,
851 OperandVector
&Operands
,
854 bool MatchingInlineAsm
) {
856 unsigned MatchResult
=
857 MatchInstructionImpl(Operands
, Inst
, ErrorInfo
, MatchingInlineAsm
);
859 switch (MatchResult
) {
861 return emit(Inst
, Loc
, Out
);
862 case Match_MissingFeature
:
863 return missingFeature(Loc
, ErrorInfo
);
864 case Match_InvalidOperand
:
865 return invalidOperand(Loc
, Operands
, ErrorInfo
);
866 case Match_MnemonicFail
:
867 return Error(Loc
, "invalid instruction");
873 void M68kOperand::print(raw_ostream
&OS
) const {
880 OS
<< "token '" << Token
<< "'";
884 OS
<< "immediate " << Imm
;