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/MCAsmLexer.h"
15 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
16 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
17 #include "llvm/MC/MCStreamer.h"
18 #include "llvm/MC/TargetRegistry.h"
22 #define DEBUG_TYPE "m68k-asm-parser"
26 static cl::opt
<bool> RegisterPrefixOptional(
27 "m68k-register-prefix-optional", cl::Hidden
,
28 cl::desc("Enable specifying registers without the % prefix"),
32 /// Parses M68k assembly from a stream.
33 class M68kAsmParser
: public MCTargetAsmParser
{
34 const MCSubtargetInfo
&STI
;
36 const MCRegisterInfo
*MRI
;
38 #define GET_ASSEMBLER_HEADER
39 #include "M68kGenAsmMatcher.inc"
41 // Helpers for Match&Emit.
42 bool invalidOperand(const SMLoc
&Loc
, const OperandVector
&Operands
,
43 const uint64_t &ErrorInfo
);
44 bool missingFeature(const SMLoc
&Loc
, const uint64_t &ErrorInfo
);
45 bool emit(MCInst
&Inst
, SMLoc
const &Loc
, MCStreamer
&Out
) const;
46 bool parseRegisterName(MCRegister
&RegNo
, SMLoc Loc
, StringRef RegisterName
);
47 ParseStatus
parseRegister(MCRegister
&RegNo
);
53 ParseStatus
parseImm(OperandVector
&Operands
);
54 ParseStatus
parseMemOp(OperandVector
&Operands
);
55 ParseStatus
parseRegOrMoveMask(OperandVector
&Operands
);
58 M68kAsmParser(const MCSubtargetInfo
&STI
, MCAsmParser
&Parser
,
59 const MCInstrInfo
&MII
, const MCTargetOptions
&Options
)
60 : MCTargetAsmParser(Options
, STI
, MII
), STI(STI
), Parser(Parser
) {
61 MCAsmParserExtension::Initialize(Parser
);
62 MRI
= getContext().getRegisterInfo();
64 setAvailableFeatures(ComputeAvailableFeatures(STI
.getFeatureBits()));
67 unsigned validateTargetOperandClass(MCParsedAsmOperand
&Op
,
68 unsigned Kind
) override
;
69 bool parseRegister(MCRegister
&Reg
, SMLoc
&StartLoc
, SMLoc
&EndLoc
) override
;
70 ParseStatus
tryParseRegister(MCRegister
&Reg
, SMLoc
&StartLoc
,
71 SMLoc
&EndLoc
) override
;
72 bool parseInstruction(ParseInstructionInfo
&Info
, StringRef Name
,
73 SMLoc NameLoc
, OperandVector
&Operands
) override
;
74 bool matchAndEmitInstruction(SMLoc IDLoc
, unsigned &Opcode
,
75 OperandVector
&Operands
, MCStreamer
&Out
,
77 bool MatchingInlineAsm
) override
;
88 RegIndirectDisplacement
,
89 RegIndirectDisplacementIndex
,
92 // These variables are used for the following forms:
94 // RegMask: RegMask (as register mask)
96 // RegIndirect: (%OuterReg)
97 // RegPostIncrement: (%OuterReg)+
98 // RegPreDecrement: -(%OuterReg)
99 // RegIndirectDisplacement: OuterDisp(%OuterReg)
100 // RegIndirectDisplacementIndex:
101 // OuterDisp(%OuterReg, %InnerReg.Size * Scale, InnerDisp)
106 const MCExpr
*OuterDisp
;
107 const MCExpr
*InnerDisp
;
114 M68kMemOp(Kind Op
) : Op(Op
) {}
116 void print(raw_ostream
&OS
) const;
119 /// An parsed M68k assembly operand.
120 class M68kOperand
: public MCParsedAsmOperand
{
121 typedef MCParsedAsmOperand Base
;
138 template <unsigned N
> bool isAddrN() const;
141 M68kOperand(KindTy Kind
, SMLoc Start
, SMLoc End
)
142 : Base(), Kind(Kind
), Start(Start
), End(End
) {}
144 SMLoc
getStartLoc() const override
{ return Start
; }
145 SMLoc
getEndLoc() const override
{ return End
; }
147 void print(raw_ostream
&OS
) const override
;
149 bool isMem() const override
{ return false; }
150 bool isMemOp() const { return Kind
== KindTy::MemOp
; }
152 static void addExpr(MCInst
&Inst
, const MCExpr
*Expr
);
155 bool isReg() const override
;
158 bool isFPDReg() const;
159 bool isFPCReg() const;
160 MCRegister
getReg() const override
;
161 void addRegOperands(MCInst
&Inst
, unsigned N
) const;
163 static std::unique_ptr
<M68kOperand
> createMemOp(M68kMemOp MemOp
, SMLoc Start
,
167 bool isToken() const override
;
168 StringRef
getToken() const;
169 static std::unique_ptr
<M68kOperand
> createToken(StringRef Token
, SMLoc Start
,
173 bool isImm() const override
;
174 void addImmOperands(MCInst
&Inst
, unsigned N
) const;
176 static std::unique_ptr
<M68kOperand
> createImm(const MCExpr
*Expr
, SMLoc Start
,
179 // Imm for TRAP instruction
180 bool isTrapImm() const;
181 // Imm for BKPT instruction
182 bool isBkptImm() const;
185 bool isMoveMask() const;
186 void addMoveMaskOperands(MCInst
&Inst
, unsigned N
) const;
190 bool isAddr8() const { return isAddrN
<8>(); }
191 bool isAddr16() const { return isAddrN
<16>(); }
192 bool isAddr32() const { return isAddrN
<32>(); }
193 void addAddrOperands(MCInst
&Inst
, unsigned N
) const;
197 void addARIOperands(MCInst
&Inst
, unsigned N
) const;
201 void addARIDOperands(MCInst
&Inst
, unsigned N
) const;
205 void addARIIOperands(MCInst
&Inst
, unsigned N
) const;
208 bool isARIPD() const;
209 void addARIPDOperands(MCInst
&Inst
, unsigned N
) const;
212 bool isARIPI() const;
213 void addARIPIOperands(MCInst
&Inst
, unsigned N
) const;
217 void addPCDOperands(MCInst
&Inst
, unsigned N
) const;
221 void addPCIOperands(MCInst
&Inst
, unsigned N
) const;
224 } // end anonymous namespace.
226 extern "C" LLVM_EXTERNAL_VISIBILITY
void LLVMInitializeM68kAsmParser() {
227 RegisterMCAsmParser
<M68kAsmParser
> X(getTheM68kTarget());
230 #define GET_REGISTER_MATCHER
231 #define GET_MATCHER_IMPLEMENTATION
232 #include "M68kGenAsmMatcher.inc"
234 static inline unsigned getRegisterByIndex(unsigned RegisterIndex
) {
235 static unsigned RegistersByIndex
[] = {
236 M68k::D0
, M68k::D1
, M68k::D2
, M68k::D3
, M68k::D4
, M68k::D5
,
237 M68k::D6
, M68k::D7
, M68k::A0
, M68k::A1
, M68k::A2
, M68k::A3
,
238 M68k::A4
, M68k::A5
, M68k::A6
, M68k::SP
, M68k::FP0
, M68k::FP1
,
239 M68k::FP2
, M68k::FP3
, M68k::FP4
, M68k::FP5
, M68k::FP6
, M68k::FP7
};
240 assert(RegisterIndex
<=
241 sizeof(RegistersByIndex
) / sizeof(RegistersByIndex
[0]));
242 return RegistersByIndex
[RegisterIndex
];
245 static inline unsigned getRegisterIndex(unsigned Register
) {
246 if (Register
>= M68k::D0
&& Register
<= M68k::D7
)
247 return Register
- M68k::D0
;
248 if (Register
>= M68k::A0
&& Register
<= M68k::A6
)
249 return Register
- M68k::A0
+ 8;
250 if (Register
>= M68k::FP0
&& Register
<= M68k::FP7
)
251 return Register
- M68k::FP0
+ 16;
255 // SP is sadly not contiguous with the rest of the An registers
258 // We don't care about the indices of these registers.
267 llvm_unreachable("unexpected register number");
271 void M68kMemOp::print(raw_ostream
&OS
) const {
277 OS
<< "RegMask(" << format("%04x", RegMask
) << ")";
280 OS
<< '%' << OuterReg
;
282 case Kind::RegIndirect
:
283 OS
<< "(%" << OuterReg
<< ')';
285 case Kind::RegPostIncrement
:
286 OS
<< "(%" << OuterReg
<< ")+";
288 case Kind::RegPreDecrement
:
289 OS
<< "-(%" << OuterReg
<< ")";
291 case Kind::RegIndirectDisplacement
:
292 OS
<< OuterDisp
<< "(%" << OuterReg
<< ")";
294 case Kind::RegIndirectDisplacementIndex
:
295 OS
<< OuterDisp
<< "(%" << OuterReg
<< ", " << InnerReg
<< "." << Size
296 << ", " << InnerDisp
<< ")";
301 void M68kOperand::addExpr(MCInst
&Inst
, const MCExpr
*Expr
) {
302 if (auto Const
= dyn_cast
<MCConstantExpr
>(Expr
)) {
303 Inst
.addOperand(MCOperand::createImm(Const
->getValue()));
307 Inst
.addOperand(MCOperand::createExpr(Expr
));
311 bool M68kOperand::isReg() const {
312 return Kind
== KindTy::MemOp
&& MemOp
.Op
== M68kMemOp::Kind::Reg
;
315 MCRegister
M68kOperand::getReg() const {
317 return MemOp
.OuterReg
;
320 void M68kOperand::addRegOperands(MCInst
&Inst
, unsigned N
) const {
321 assert(isReg() && "wrong operand kind");
322 assert((N
== 1) && "can only handle one register operand");
324 Inst
.addOperand(MCOperand::createReg(getReg()));
327 std::unique_ptr
<M68kOperand
> M68kOperand::createMemOp(M68kMemOp MemOp
,
328 SMLoc Start
, SMLoc End
) {
329 auto Op
= std::make_unique
<M68kOperand
>(KindTy::MemOp
, Start
, End
);
335 bool M68kOperand::isToken() const { return Kind
== KindTy::Token
; }
336 StringRef
M68kOperand::getToken() const {
341 std::unique_ptr
<M68kOperand
> M68kOperand::createToken(StringRef Token
,
342 SMLoc Start
, SMLoc End
) {
343 auto Op
= std::make_unique
<M68kOperand
>(KindTy::Token
, Start
, End
);
349 bool M68kOperand::isImm() const { return Kind
== KindTy::Imm
; }
350 void M68kOperand::addImmOperands(MCInst
&Inst
, unsigned N
) const {
351 assert(isImm() && "wrong operand kind");
352 assert((N
== 1) && "can only handle one register operand");
354 M68kOperand::addExpr(Inst
, Expr
);
357 std::unique_ptr
<M68kOperand
> M68kOperand::createImm(const MCExpr
*Expr
,
358 SMLoc Start
, SMLoc End
) {
359 auto Op
= std::make_unique
<M68kOperand
>(KindTy::Imm
, Start
, End
);
364 bool M68kOperand::isTrapImm() const {
366 if (!isImm() || !Expr
->evaluateAsAbsolute(Value
))
369 return isUInt
<4>(Value
);
372 bool M68kOperand::isBkptImm() const {
374 if (!isImm() || !Expr
->evaluateAsAbsolute(Value
))
377 return isUInt
<3>(Value
);
381 bool M68kOperand::isMoveMask() const {
385 if (MemOp
.Op
== M68kMemOp::Kind::RegMask
)
388 if (MemOp
.Op
!= M68kMemOp::Kind::Reg
)
391 // Only regular address / data registers are allowed to be used
392 // in register masks.
393 return getRegisterIndex(MemOp
.OuterReg
) < 16;
396 void M68kOperand::addMoveMaskOperands(MCInst
&Inst
, unsigned N
) const {
397 assert(isMoveMask() && "wrong operand kind");
398 assert((N
== 1) && "can only handle one immediate operand");
400 uint16_t MoveMask
= MemOp
.RegMask
;
401 if (MemOp
.Op
== M68kMemOp::Kind::Reg
)
402 MoveMask
= 1 << getRegisterIndex(MemOp
.OuterReg
);
404 Inst
.addOperand(MCOperand::createImm(MoveMask
));
408 bool M68kOperand::isAddr() const {
409 return isMemOp() && MemOp
.Op
== M68kMemOp::Kind::Addr
;
411 // TODO: Maybe we can also store the size of OuterDisp
413 template <unsigned N
> bool M68kOperand::isAddrN() const {
416 if (MemOp
.OuterDisp
->evaluateAsAbsolute(Res
))
417 return isInt
<N
>(Res
);
422 void M68kOperand::addAddrOperands(MCInst
&Inst
, unsigned N
) const {
423 M68kOperand::addExpr(Inst
, MemOp
.OuterDisp
);
427 bool M68kOperand::isARI() const {
428 return isMemOp() && MemOp
.Op
== M68kMemOp::Kind::RegIndirect
&&
429 M68k::AR32RegClass
.contains(MemOp
.OuterReg
);
431 void M68kOperand::addARIOperands(MCInst
&Inst
, unsigned N
) const {
432 Inst
.addOperand(MCOperand::createReg(MemOp
.OuterReg
));
436 bool M68kOperand::isARID() const {
437 return isMemOp() && MemOp
.Op
== M68kMemOp::Kind::RegIndirectDisplacement
&&
438 M68k::AR32RegClass
.contains(MemOp
.OuterReg
);
440 void M68kOperand::addARIDOperands(MCInst
&Inst
, unsigned N
) const {
441 M68kOperand::addExpr(Inst
, MemOp
.OuterDisp
);
442 Inst
.addOperand(MCOperand::createReg(MemOp
.OuterReg
));
446 bool M68kOperand::isARII() const {
448 MemOp
.Op
== M68kMemOp::Kind::RegIndirectDisplacementIndex
&&
449 M68k::AR32RegClass
.contains(MemOp
.OuterReg
);
451 void M68kOperand::addARIIOperands(MCInst
&Inst
, unsigned N
) const {
452 M68kOperand::addExpr(Inst
, MemOp
.OuterDisp
);
453 Inst
.addOperand(MCOperand::createReg(MemOp
.OuterReg
));
454 Inst
.addOperand(MCOperand::createReg(MemOp
.InnerReg
));
458 bool M68kOperand::isARIPD() const {
459 return isMemOp() && MemOp
.Op
== M68kMemOp::Kind::RegPreDecrement
&&
460 M68k::AR32RegClass
.contains(MemOp
.OuterReg
);
462 void M68kOperand::addARIPDOperands(MCInst
&Inst
, unsigned N
) const {
463 Inst
.addOperand(MCOperand::createReg(MemOp
.OuterReg
));
467 bool M68kOperand::isARIPI() const {
468 return isMemOp() && MemOp
.Op
== M68kMemOp::Kind::RegPostIncrement
&&
469 M68k::AR32RegClass
.contains(MemOp
.OuterReg
);
471 void M68kOperand::addARIPIOperands(MCInst
&Inst
, unsigned N
) const {
472 Inst
.addOperand(MCOperand::createReg(MemOp
.OuterReg
));
476 bool M68kOperand::isPCD() const {
477 return isMemOp() && MemOp
.Op
== M68kMemOp::Kind::RegIndirectDisplacement
&&
478 MemOp
.OuterReg
== M68k::PC
;
480 void M68kOperand::addPCDOperands(MCInst
&Inst
, unsigned N
) const {
481 M68kOperand::addExpr(Inst
, MemOp
.OuterDisp
);
485 bool M68kOperand::isPCI() const {
487 MemOp
.Op
== M68kMemOp::Kind::RegIndirectDisplacementIndex
&&
488 MemOp
.OuterReg
== M68k::PC
;
490 void M68kOperand::addPCIOperands(MCInst
&Inst
, unsigned N
) const {
491 M68kOperand::addExpr(Inst
, MemOp
.OuterDisp
);
492 Inst
.addOperand(MCOperand::createReg(MemOp
.InnerReg
));
495 static inline bool checkRegisterClass(unsigned RegNo
, bool Data
, bool Address
,
496 bool SP
, bool FPDR
= false,
541 llvm_unreachable("unexpected register type");
546 bool M68kOperand::isAReg() const {
547 return isReg() && checkRegisterClass(getReg(),
549 /*Address=*/true, /*SP=*/true);
552 bool M68kOperand::isDReg() const {
553 return isReg() && checkRegisterClass(getReg(),
555 /*Address=*/false, /*SP=*/false);
558 bool M68kOperand::isFPDReg() const {
559 return isReg() && checkRegisterClass(getReg(),
561 /*Address=*/false, /*SP=*/false,
565 bool M68kOperand::isFPCReg() const {
566 return isReg() && checkRegisterClass(getReg(),
568 /*Address=*/false, /*SP=*/false,
569 /*FPDR=*/false, /*FPCR=*/true);
572 unsigned M68kAsmParser::validateTargetOperandClass(MCParsedAsmOperand
&Op
,
574 M68kOperand
&Operand
= (M68kOperand
&)Op
;
579 if (Operand
.isReg() &&
580 checkRegisterClass(Operand
.getReg(), true, true, true)) {
581 return Match_Success
;
587 if (Operand
.isReg() &&
588 checkRegisterClass(Operand
.getReg(), false, true, true)) {
589 return Match_Success
;
594 if (Operand
.isReg() &&
595 checkRegisterClass(Operand
.getReg(), false, true, false)) {
596 return Match_Success
;
603 if (Operand
.isReg() &&
604 checkRegisterClass(Operand
.getReg(), true, false, false)) {
605 return Match_Success
;
610 if (Operand
.isReg() &&
611 ((Operand
.getReg() == M68k::A0
) || (Operand
.getReg() == M68k::A1
))) {
612 return Match_Success
;
617 if (Operand
.isReg() &&
618 ((Operand
.getReg() == M68k::D0
) || (Operand
.getReg() == M68k::D1
))) {
619 return Match_Success
;
624 if (Operand
.isReg() &&
625 ((Operand
.getReg() == M68k::D0
) || (Operand
.getReg() == M68k::D1
) ||
626 (Operand
.getReg() == M68k::A0
) || (Operand
.getReg() == M68k::A1
))) {
627 return Match_Success
;
632 return Match_InvalidOperand
;
635 bool M68kAsmParser::parseRegisterName(MCRegister
&RegNo
, SMLoc Loc
,
636 StringRef RegisterName
) {
637 auto RegisterNameLower
= RegisterName
.lower();
640 if (RegisterNameLower
== "ccr") {
645 // Parse simple general-purpose registers.
646 if (RegisterNameLower
.size() == 2) {
648 switch (RegisterNameLower
[0]) {
651 if (isdigit(RegisterNameLower
[1])) {
652 unsigned IndexOffset
= (RegisterNameLower
[0] == 'a') ? 8 : 0;
653 unsigned RegIndex
= (unsigned)(RegisterNameLower
[1] - '0');
655 RegNo
= getRegisterByIndex(IndexOffset
+ RegIndex
);
663 if (RegisterNameLower
[1] == 'p') {
666 } else if (RegisterNameLower
[1] == 'r') {
673 if (RegisterNameLower
[1] == 'c') {
679 } else if (StringRef(RegisterNameLower
).starts_with("fp") &&
680 RegisterNameLower
.size() > 2) {
681 auto RegIndex
= unsigned(RegisterNameLower
[2] - '0');
682 if (RegIndex
< 8 && RegisterNameLower
.size() == 3) {
683 // Floating point data register.
684 RegNo
= getRegisterByIndex(16 + RegIndex
);
687 // Floating point control register.
688 RegNo
= StringSwitch
<unsigned>(RegisterNameLower
)
689 .Cases("fpc", "fpcr", M68k::FPC
)
690 .Cases("fps", "fpsr", M68k::FPS
)
691 .Cases("fpi", "fpiar", M68k::FPIAR
)
692 .Default(M68k::NoRegister
);
693 assert(RegNo
!= M68k::NoRegister
&&
694 "Unrecognized FP control register name");
702 ParseStatus
M68kAsmParser::parseRegister(MCRegister
&RegNo
) {
703 bool HasPercent
= false;
704 AsmToken PercentToken
;
706 LLVM_DEBUG(dbgs() << "parseRegister "; getTok().dump(dbgs()); dbgs() << "\n");
708 if (getTok().is(AsmToken::Percent
)) {
710 PercentToken
= Lex();
711 } else if (!RegisterPrefixOptional
.getValue()) {
712 return ParseStatus::NoMatch
;
715 if (!Parser
.getTok().is(AsmToken::Identifier
)) {
717 getLexer().UnLex(PercentToken
);
719 return ParseStatus::NoMatch
;
722 auto RegisterName
= Parser
.getTok().getString();
723 if (!parseRegisterName(RegNo
, Parser
.getLexer().getLoc(), RegisterName
)) {
725 getLexer().UnLex(PercentToken
);
727 return ParseStatus::NoMatch
;
731 return ParseStatus::Success
;
734 bool M68kAsmParser::parseRegister(MCRegister
&Reg
, SMLoc
&StartLoc
,
736 ParseStatus Result
= tryParseRegister(Reg
, StartLoc
, EndLoc
);
737 if (!Result
.isSuccess())
738 return Error(StartLoc
, "expected register");
743 ParseStatus
M68kAsmParser::tryParseRegister(MCRegister
&Reg
, SMLoc
&StartLoc
,
745 StartLoc
= getLexer().getLoc();
746 ParseStatus Result
= parseRegister(Reg
);
747 EndLoc
= getLexer().getLoc();
751 bool M68kAsmParser::isExpr() {
752 switch (Parser
.getTok().getKind()) {
753 case AsmToken::Identifier
:
754 case AsmToken::Integer
:
756 case AsmToken::Minus
:
757 return getLexer().peekTok().getKind() == AsmToken::Integer
;
764 ParseStatus
M68kAsmParser::parseImm(OperandVector
&Operands
) {
765 if (getLexer().isNot(AsmToken::Hash
))
766 return ParseStatus::NoMatch
;
767 SMLoc Start
= getLexer().getLoc();
773 if (getParser().parseExpression(Expr
, End
))
774 return ParseStatus::Failure
;
776 Operands
.push_back(M68kOperand::createImm(Expr
, Start
, End
));
777 return ParseStatus::Success
;
780 ParseStatus
M68kAsmParser::parseMemOp(OperandVector
&Operands
) {
781 SMLoc Start
= getLexer().getLoc();
785 // Check for a plain register or register mask.
786 ParseStatus Result
= parseRegOrMoveMask(Operands
);
787 if (!Result
.isNoMatch())
790 // Check for pre-decrement & outer displacement.
791 bool HasDisplacement
= false;
792 if (getLexer().is(AsmToken::Minus
)) {
795 } else if (isExpr()) {
796 if (Parser
.parseExpression(MemOp
.OuterDisp
))
797 return ParseStatus::Failure
;
798 HasDisplacement
= true;
801 if (getLexer().isNot(AsmToken::LParen
)) {
802 if (HasDisplacement
) {
803 MemOp
.Op
= M68kMemOp::Kind::Addr
;
805 M68kOperand::createMemOp(MemOp
, Start
, getLexer().getLoc()));
806 return ParseStatus::Success
;
809 return Error(getLexer().getLoc(), "expected (");
811 return ParseStatus::NoMatch
;
815 // Check for constant dereference & MIT-style displacement
816 if (!HasDisplacement
&& isExpr()) {
817 if (Parser
.parseExpression(MemOp
.OuterDisp
))
818 return ParseStatus::Failure
;
819 HasDisplacement
= true;
821 // If we're not followed by a comma, we're a constant dereference.
822 if (getLexer().isNot(AsmToken::Comma
)) {
823 MemOp
.Op
= M68kMemOp::Kind::Addr
;
825 M68kOperand::createMemOp(MemOp
, Start
, getLexer().getLoc()));
826 return ParseStatus::Success
;
832 Result
= parseRegister(MemOp
.OuterReg
);
833 if (Result
.isFailure())
834 return ParseStatus::Failure
;
836 if (!Result
.isSuccess())
837 return Error(getLexer().getLoc(), "expected register");
840 bool HasIndex
= false;
841 if (Parser
.getTok().is(AsmToken::Comma
)) {
844 Result
= parseRegister(MemOp
.InnerReg
);
845 if (Result
.isFailure())
848 if (Result
.isNoMatch())
849 return Error(getLexer().getLoc(), "expected register");
851 // TODO: parse size, scale and inner displacement.
854 MemOp
.InnerDisp
= MCConstantExpr::create(0, Parser
.getContext(), true, 4);
858 if (Parser
.getTok().isNot(AsmToken::RParen
))
859 return Error(getLexer().getLoc(), "expected )");
863 if (!IsPD
&& Parser
.getTok().is(AsmToken::Plus
)) {
868 SMLoc End
= getLexer().getLoc();
870 unsigned OpCount
= IsPD
+ IsPI
+ (HasIndex
|| HasDisplacement
);
872 return Error(Start
, "only one of post-increment, pre-decrement or "
873 "displacement can be used");
876 MemOp
.Op
= M68kMemOp::Kind::RegPreDecrement
;
878 MemOp
.Op
= M68kMemOp::Kind::RegPostIncrement
;
879 } else if (HasIndex
) {
880 MemOp
.Op
= M68kMemOp::Kind::RegIndirectDisplacementIndex
;
881 } else if (HasDisplacement
) {
882 MemOp
.Op
= M68kMemOp::Kind::RegIndirectDisplacement
;
884 MemOp
.Op
= M68kMemOp::Kind::RegIndirect
;
887 Operands
.push_back(M68kOperand::createMemOp(MemOp
, Start
, End
));
888 return ParseStatus::Success
;
891 ParseStatus
M68kAsmParser::parseRegOrMoveMask(OperandVector
&Operands
) {
892 SMLoc Start
= getLexer().getLoc();
893 M68kMemOp
MemOp(M68kMemOp::Kind::RegMask
);
897 bool IsFirstRegister
=
898 (MemOp
.Op
== M68kMemOp::Kind::RegMask
) && (MemOp
.RegMask
== 0);
900 MCRegister FirstRegister
;
901 ParseStatus Result
= parseRegister(FirstRegister
);
902 if (IsFirstRegister
&& Result
.isNoMatch())
903 return ParseStatus::NoMatch
;
904 if (!Result
.isSuccess())
905 return Error(getLexer().getLoc(), "expected start register");
907 MCRegister LastRegister
= FirstRegister
;
908 if (parseOptionalToken(AsmToken::Minus
)) {
909 Result
= parseRegister(LastRegister
);
910 if (!Result
.isSuccess())
911 return Error(getLexer().getLoc(), "expected end register");
914 unsigned FirstRegisterIndex
= getRegisterIndex(FirstRegister
);
915 unsigned LastRegisterIndex
= getRegisterIndex(LastRegister
);
917 uint16_t NumNewBits
= LastRegisterIndex
- FirstRegisterIndex
+ 1;
918 uint16_t NewMaskBits
= ((1 << NumNewBits
) - 1) << FirstRegisterIndex
;
920 if (IsFirstRegister
&& (FirstRegister
== LastRegister
)) {
921 // First register range is a single register, simplify to just Reg
922 // so that it matches more operands.
923 MemOp
.Op
= M68kMemOp::Kind::Reg
;
924 MemOp
.OuterReg
= FirstRegister
;
926 if (MemOp
.Op
== M68kMemOp::Kind::Reg
) {
927 // This is the second register being specified - expand the Reg operand
928 // into a mask first.
929 MemOp
.Op
= M68kMemOp::Kind::RegMask
;
930 MemOp
.RegMask
= 1 << getRegisterIndex(MemOp
.OuterReg
);
932 if (MemOp
.RegMask
== 0)
933 return Error(getLexer().getLoc(),
934 "special registers cannot be used in register masks");
937 if ((FirstRegisterIndex
>= 16) || (LastRegisterIndex
>= 16))
938 return Error(getLexer().getLoc(),
939 "special registers cannot be used in register masks");
941 if (NewMaskBits
& MemOp
.RegMask
)
942 return Error(getLexer().getLoc(), "conflicting masked registers");
944 MemOp
.RegMask
|= NewMaskBits
;
947 if (!parseOptionalToken(AsmToken::Slash
))
952 M68kOperand::createMemOp(MemOp
, Start
, getLexer().getLoc()));
953 return ParseStatus::Success
;
956 void M68kAsmParser::eatComma() {
957 if (Parser
.getTok().is(AsmToken::Comma
)) {
962 bool M68kAsmParser::parseInstruction(ParseInstructionInfo
&Info
, StringRef Name
,
963 SMLoc NameLoc
, OperandVector
&Operands
) {
964 SMLoc Start
= getLexer().getLoc();
965 Operands
.push_back(M68kOperand::createToken(Name
, Start
, Start
));
968 while (Parser
.getTok().isNot(AsmToken::EndOfStatement
)) {
975 ParseStatus MatchResult
= MatchOperandParserImpl(Operands
, Name
);
976 if (MatchResult
.isSuccess())
979 // Add custom operand formats here...
980 SMLoc Loc
= getLexer().getLoc();
981 Parser
.eatToEndOfStatement();
982 return Error(Loc
, "unexpected token parsing operands");
985 // Eat EndOfStatement.
990 bool M68kAsmParser::invalidOperand(SMLoc
const &Loc
,
991 OperandVector
const &Operands
,
992 uint64_t const &ErrorInfo
) {
993 SMLoc ErrorLoc
= Loc
;
994 char const *Diag
= 0;
996 if (ErrorInfo
!= ~0U) {
997 if (ErrorInfo
>= Operands
.size()) {
998 Diag
= "too few operands for instruction.";
1000 auto const &Op
= (M68kOperand
const &)*Operands
[ErrorInfo
];
1001 if (Op
.getStartLoc() != SMLoc()) {
1002 ErrorLoc
= Op
.getStartLoc();
1008 Diag
= "invalid operand for instruction";
1011 return Error(ErrorLoc
, Diag
);
1014 bool M68kAsmParser::missingFeature(llvm::SMLoc
const &Loc
,
1015 uint64_t const &ErrorInfo
) {
1016 return Error(Loc
, "instruction requires a CPU feature not currently enabled");
1019 bool M68kAsmParser::emit(MCInst
&Inst
, SMLoc
const &Loc
,
1020 MCStreamer
&Out
) const {
1022 Out
.emitInstruction(Inst
, STI
);
1027 bool M68kAsmParser::matchAndEmitInstruction(SMLoc Loc
, unsigned &Opcode
,
1028 OperandVector
&Operands
,
1030 uint64_t &ErrorInfo
,
1031 bool MatchingInlineAsm
) {
1033 unsigned MatchResult
=
1034 MatchInstructionImpl(Operands
, Inst
, ErrorInfo
, MatchingInlineAsm
);
1036 switch (MatchResult
) {
1038 return emit(Inst
, Loc
, Out
);
1039 case Match_MissingFeature
:
1040 return missingFeature(Loc
, ErrorInfo
);
1041 case Match_InvalidOperand
:
1042 return invalidOperand(Loc
, Operands
, ErrorInfo
);
1043 case Match_MnemonicFail
:
1044 return Error(Loc
, "invalid instruction");
1050 void M68kOperand::print(raw_ostream
&OS
) const {
1052 case KindTy::Invalid
:
1057 OS
<< "token '" << Token
<< "'";
1062 Expr
->evaluateAsAbsolute(Value
);
1063 OS
<< "immediate " << Value
;