22#define DEBUG_TYPE "m68k-asm-parser"
28 cl::desc(
"Enable specifying registers without the % prefix"),
38#define GET_ASSEMBLER_HEADER
39#include "M68kGenAsmMatcher.inc"
68 unsigned Kind)
override;
71 SMLoc &EndLoc)
override;
77 bool MatchingInlineAsm)
override;
88 RegIndirectDisplacement,
89 RegIndirectDisplacementIndex,
114 M68kMemOp(Kind
Op) :
Op(
Op) {}
138 template <
unsigned N>
bool isAddrN()
const;
141 M68kOperand(KindTy Kind,
SMLoc Start,
SMLoc End)
149 bool isMem()
const override {
return false; }
150 bool isMemOp()
const {
return Kind == KindTy::MemOp; }
155 bool isReg()
const override;
158 bool isFPDReg()
const;
159 bool isFPCReg()
const;
161 void addRegOperands(
MCInst &Inst,
unsigned N)
const;
163 static std::unique_ptr<M68kOperand> createMemOp(M68kMemOp
MemOp,
SMLoc Start,
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,
180 bool isTrapImm()
const;
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;
230#define GET_REGISTER_MATCHER
231#define GET_MATCHER_IMPLEMENTATION
232#include "M68kGenAsmMatcher.inc"
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};
241 sizeof(RegistersByIndex) /
sizeof(RegistersByIndex[0]));
242 return RegistersByIndex[RegisterIndex];
278 OS <<
"RegMask(" <<
format(
"%04x", RegMask) <<
")";
281 OS <<
'%' << OuterReg;
283 case Kind::RegIndirect:
284 OS <<
"(%" << OuterReg <<
')';
286 case Kind::RegPostIncrement:
287 OS <<
"(%" << OuterReg <<
")+";
289 case Kind::RegPreDecrement:
290 OS <<
"-(%" << OuterReg <<
")";
292 case Kind::RegIndirectDisplacement:
293 OS << OuterDisp <<
"(%" << OuterReg <<
")";
295 case Kind::RegIndirectDisplacementIndex:
296 OS << OuterDisp <<
"(%" << OuterReg <<
", " << InnerReg <<
"." <<
Size
297 <<
", " << InnerDisp <<
")";
302void M68kOperand::addExpr(
MCInst &Inst,
const MCExpr *Expr) {
303 if (
auto Const = dyn_cast<MCConstantExpr>(Expr)) {
312bool M68kOperand::isReg()
const {
313 return Kind == KindTy::MemOp &&
MemOp.Op == M68kMemOp::Kind::Reg;
318 return MemOp.OuterReg;
321void M68kOperand::addRegOperands(
MCInst &Inst,
unsigned N)
const {
323 assert((
N == 1) &&
"can only handle one register operand");
328std::unique_ptr<M68kOperand> M68kOperand::createMemOp(M68kMemOp
MemOp,
330 auto Op = std::make_unique<M68kOperand>(KindTy::MemOp, Start,
End);
336bool M68kOperand::isToken()
const {
return Kind == KindTy::Token; }
342std::unique_ptr<M68kOperand> M68kOperand::createToken(
StringRef Token,
344 auto Op = std::make_unique<M68kOperand>(KindTy::Token, Start,
End);
350bool M68kOperand::isImm()
const {
return Kind == KindTy::Imm; }
351void M68kOperand::addImmOperands(
MCInst &Inst,
unsigned N)
const {
353 assert((
N == 1) &&
"can only handle one register operand");
355 M68kOperand::addExpr(Inst, Expr);
358std::unique_ptr<M68kOperand> M68kOperand::createImm(
const MCExpr *Expr,
360 auto Op = std::make_unique<M68kOperand>(KindTy::Imm, Start,
End);
365bool M68kOperand::isTrapImm()
const {
367 if (!
isImm() || !Expr->evaluateAsAbsolute(
Value))
370 return isUInt<4>(
Value);
373bool M68kOperand::isBkptImm()
const {
375 if (!
isImm() || !Expr->evaluateAsAbsolute(
Value))
378 return isUInt<3>(
Value);
382bool M68kOperand::isMoveMask()
const {
386 if (
MemOp.Op == M68kMemOp::Kind::RegMask)
389 if (
MemOp.Op != M68kMemOp::Kind::Reg)
397void M68kOperand::addMoveMaskOperands(
MCInst &Inst,
unsigned N)
const {
398 assert(isMoveMask() &&
"wrong operand kind");
399 assert((
N == 1) &&
"can only handle one immediate operand");
402 if (
MemOp.Op == M68kMemOp::Kind::Reg)
409bool M68kOperand::isAddr()
const {
410 return isMemOp() &&
MemOp.Op == M68kMemOp::Kind::Addr;
414template <
unsigned N>
bool M68kOperand::isAddrN()
const {
417 if (
MemOp.OuterDisp->evaluateAsAbsolute(Res))
418 return isInt<N>(Res);
423void M68kOperand::addAddrOperands(
MCInst &Inst,
unsigned N)
const {
424 M68kOperand::addExpr(Inst,
MemOp.OuterDisp);
428bool M68kOperand::isARI()
const {
429 return isMemOp() &&
MemOp.Op == M68kMemOp::Kind::RegIndirect &&
430 M68k::AR32RegClass.contains(
MemOp.OuterReg);
432void M68kOperand::addARIOperands(
MCInst &Inst,
unsigned N)
const {
437bool M68kOperand::isARID()
const {
438 return isMemOp() &&
MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacement &&
439 M68k::AR32RegClass.contains(
MemOp.OuterReg);
441void M68kOperand::addARIDOperands(
MCInst &Inst,
unsigned N)
const {
442 M68kOperand::addExpr(Inst,
MemOp.OuterDisp);
447bool M68kOperand::isARII()
const {
449 MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacementIndex &&
450 M68k::AR32RegClass.contains(
MemOp.OuterReg);
452void M68kOperand::addARIIOperands(
MCInst &Inst,
unsigned N)
const {
453 M68kOperand::addExpr(Inst,
MemOp.OuterDisp);
459bool M68kOperand::isARIPD()
const {
460 return isMemOp() &&
MemOp.Op == M68kMemOp::Kind::RegPreDecrement &&
461 M68k::AR32RegClass.contains(
MemOp.OuterReg);
463void M68kOperand::addARIPDOperands(
MCInst &Inst,
unsigned N)
const {
468bool M68kOperand::isARIPI()
const {
469 return isMemOp() &&
MemOp.Op == M68kMemOp::Kind::RegPostIncrement &&
470 M68k::AR32RegClass.contains(
MemOp.OuterReg);
472void M68kOperand::addARIPIOperands(
MCInst &Inst,
unsigned N)
const {
477bool M68kOperand::isPCD()
const {
478 return isMemOp() &&
MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacement &&
479 MemOp.OuterReg == M68k::PC;
481void M68kOperand::addPCDOperands(
MCInst &Inst,
unsigned N)
const {
482 M68kOperand::addExpr(Inst,
MemOp.OuterDisp);
486bool M68kOperand::isPCI()
const {
488 MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacementIndex &&
489 MemOp.OuterReg == M68k::PC;
491void M68kOperand::addPCIOperands(
MCInst &Inst,
unsigned N)
const {
492 M68kOperand::addExpr(Inst,
MemOp.OuterDisp);
497 bool SP,
bool FPDR =
false,
547bool M68kOperand::isAReg()
const {
553bool M68kOperand::isDReg()
const {
559bool M68kOperand::isFPDReg()
const {
566bool M68kOperand::isFPCReg()
const {
575 M68kOperand &Operand = (M68kOperand &)
Op;
580 if (Operand.isReg() &&
582 return Match_Success;
588 if (Operand.isReg() &&
590 return Match_Success;
595 if (Operand.isReg() &&
597 return Match_Success;
604 if (Operand.isReg() &&
606 return Match_Success;
611 if (Operand.isReg() &&
612 ((Operand.getReg() == M68k::A0) || (Operand.getReg() == M68k::A1))) {
613 return Match_Success;
618 if (Operand.isReg() &&
619 ((Operand.getReg() == M68k::D0) || (Operand.getReg() == M68k::D1))) {
620 return Match_Success;
625 if (Operand.isReg() &&
626 ((Operand.getReg() == M68k::D0) || (Operand.getReg() == M68k::D1) ||
627 (Operand.getReg() == M68k::A0) || (Operand.getReg() == M68k::A1))) {
628 return Match_Success;
633 return Match_InvalidOperand;
638 auto RegisterNameLower = RegisterName.
lower();
641 if (RegisterNameLower ==
"ccr") {
644 }
else if (RegisterNameLower ==
"sr") {
650 if (RegisterNameLower.size() == 2) {
652 switch (RegisterNameLower[0]) {
655 if (isdigit(RegisterNameLower[1])) {
656 unsigned IndexOffset = (RegisterNameLower[0] ==
'a') ? 8 : 0;
657 unsigned RegIndex = (
unsigned)(RegisterNameLower[1] -
'0');
667 if (RegisterNameLower[1] ==
'p') {
670 }
else if (RegisterNameLower[1] ==
'r') {
677 if (RegisterNameLower[1] ==
'c') {
684 RegisterNameLower.size() > 2) {
685 auto RegIndex =
unsigned(RegisterNameLower[2] -
'0');
686 if (RegIndex < 8 && RegisterNameLower.size() == 3) {
693 .
Cases(
"fpc",
"fpcr", M68k::FPC)
694 .
Cases(
"fps",
"fpsr", M68k::FPS)
695 .
Cases(
"fpi",
"fpiar", M68k::FPIAR)
697 assert(RegNo != M68k::NoRegister &&
698 "Unrecognized FP control register name");
707 bool HasPercent =
false;
714 PercentToken = Lex();
721 getLexer().UnLex(PercentToken);
727 if (!parseRegisterName(RegNo, Parser.
getLexer().
getLoc(), RegisterName)) {
729 getLexer().UnLex(PercentToken);
742 return Error(StartLoc,
"expected register");
749 StartLoc = getLexer().getLoc();
751 EndLoc = getLexer().getLoc();
755bool M68kAsmParser::isExpr() {
771 SMLoc Start = getLexer().getLoc();
777 if (getParser().parseExpression(Expr,
End))
780 Operands.push_back(M68kOperand::createImm(Expr, Start,
End));
785 SMLoc Start = getLexer().getLoc();
795 bool HasDisplacement =
false;
799 }
else if (isExpr()) {
802 HasDisplacement =
true;
806 if (HasDisplacement) {
807 MemOp.Op = M68kMemOp::Kind::Addr;
809 M68kOperand::createMemOp(
MemOp, Start, getLexer().getLoc()));
813 return Error(getLexer().getLoc(),
"expected (");
820 if (!HasDisplacement && isExpr()) {
823 HasDisplacement =
true;
827 MemOp.Op = M68kMemOp::Kind::Addr;
829 M68kOperand::createMemOp(
MemOp, Start, getLexer().getLoc()));
841 return Error(getLexer().getLoc(),
"expected register");
853 return Error(getLexer().getLoc(),
"expected register");
863 return Error(getLexer().getLoc(),
"expected )");
874 unsigned OpCount = IsPD + IsPI + (
HasIndex || HasDisplacement);
876 return Error(Start,
"only one of post-increment, pre-decrement or "
877 "displacement can be used");
880 MemOp.Op = M68kMemOp::Kind::RegPreDecrement;
882 MemOp.Op = M68kMemOp::Kind::RegPostIncrement;
883 }
else if (HasIndex) {
884 MemOp.Op = M68kMemOp::Kind::RegIndirectDisplacementIndex;
885 }
else if (HasDisplacement) {
886 MemOp.Op = M68kMemOp::Kind::RegIndirectDisplacement;
888 MemOp.Op = M68kMemOp::Kind::RegIndirect;
896 SMLoc Start = getLexer().getLoc();
897 M68kMemOp
MemOp(M68kMemOp::Kind::RegMask);
901 bool IsFirstRegister =
902 (
MemOp.Op == M68kMemOp::Kind::RegMask) && (
MemOp.RegMask == 0);
906 if (IsFirstRegister &&
Result.isNoMatch())
909 return Error(getLexer().getLoc(),
"expected start register");
913 Result = parseRegister(LastRegister);
915 return Error(getLexer().getLoc(),
"expected end register");
921 uint16_t NumNewBits = LastRegisterIndex - FirstRegisterIndex + 1;
922 uint16_t NewMaskBits = ((1 << NumNewBits) - 1) << FirstRegisterIndex;
924 if (IsFirstRegister && (FirstRegister == LastRegister)) {
927 MemOp.Op = M68kMemOp::Kind::Reg;
928 MemOp.OuterReg = FirstRegister;
930 if (
MemOp.Op == M68kMemOp::Kind::Reg) {
933 MemOp.Op = M68kMemOp::Kind::RegMask;
936 if (
MemOp.RegMask == 0)
937 return Error(getLexer().getLoc(),
938 "special registers cannot be used in register masks");
941 if ((FirstRegisterIndex >= 16) || (LastRegisterIndex >= 16))
942 return Error(getLexer().getLoc(),
943 "special registers cannot be used in register masks");
945 if (NewMaskBits &
MemOp.RegMask)
946 return Error(getLexer().getLoc(),
"conflicting masked registers");
948 MemOp.RegMask |= NewMaskBits;
956 M68kOperand::createMemOp(
MemOp, Start, getLexer().getLoc()));
960void M68kAsmParser::eatComma() {
968 SMLoc Start = getLexer().getLoc();
969 Operands.push_back(M68kOperand::createToken(
Name, Start, Start));
984 SMLoc Loc = getLexer().getLoc();
986 return Error(Loc,
"unexpected token parsing operands");
994bool M68kAsmParser::invalidOperand(
SMLoc const &Loc,
997 SMLoc ErrorLoc = Loc;
998 char const *Diag = 0;
1002 Diag =
"too few operands for instruction.";
1005 if (
Op.getStartLoc() !=
SMLoc()) {
1006 ErrorLoc =
Op.getStartLoc();
1012 Diag =
"invalid operand for instruction";
1015 return Error(ErrorLoc, Diag);
1018bool M68kAsmParser::missingFeature(
llvm::SMLoc const &Loc,
1020 return Error(Loc,
"instruction requires a CPU feature not currently enabled");
1023bool M68kAsmParser::emit(
MCInst &Inst,
SMLoc const &Loc,
1031bool M68kAsmParser::matchAndEmitInstruction(
SMLoc Loc,
unsigned &Opcode,
1035 bool MatchingInlineAsm) {
1037 unsigned MatchResult =
1040 switch (MatchResult) {
1042 return emit(Inst, Loc, Out);
1043 case Match_MissingFeature:
1045 case Match_InvalidOperand:
1047 case Match_MnemonicFail:
1048 return Error(Loc,
"invalid instruction");
1056 case KindTy::Invalid:
1061 OS <<
"token '" << Token <<
"'";
1066 Expr->evaluateAsAbsolute(
Value);
unsigned const MachineRegisterInfo * MRI
static bool isNot(const MachineRegisterInfo &MRI, const MachineInstr &MI)
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
#define LLVM_EXTERNAL_VISIBILITY
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
static bool checkRegisterClass(unsigned RegNo, bool Data, bool Address, bool SP, bool FPDR=false, bool FPCR=false)
static cl::opt< bool > RegisterPrefixOptional("m68k-register-prefix-optional", cl::Hidden, cl::desc("Enable specifying registers without the % prefix"), cl::init(false))
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeM68kAsmParser()
static unsigned getRegisterByIndex(unsigned RegisterIndex)
static unsigned getRegisterIndex(unsigned Register)
This file contains the M68k implementation of the TargetInstrInfo class.
This file contains the M68k implementation of the TargetRegisterInfo class.
mir Rename Register Operands
static unsigned getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
static bool isReg(const MCInst &MI, unsigned OpNo)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static bool isImm(const MachineOperand &MO, MachineRegisterInfo *MRI)
Target independent representation for an assembler token.
bool isNot(TokenKind K) const
StringRef getString() const
Get the string for the current token, this includes all characters (for example, the quotes on string...
bool is(TokenKind K) const
TokenKind getKind() const
This class represents an Operation in the Expression.
Base class for user error types.
Lightweight error class with error context and mandatory checking.
SMLoc getLoc() const
Get the current source location.
virtual void Initialize(MCAsmParser &Parser)
Initialize the extension for parsing using the given Parser.
Generic assembler parser interface, for use by target specific assembly parsers.
virtual void eatToEndOfStatement()=0
Skip to the end of the current statement, for error recovery.
virtual bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc)=0
Parse an arbitrary expression.
const AsmToken & getTok() const
Get the current AsmToken from the stream.
virtual const AsmToken & Lex()=0
Get the next AsmToken in the stream, possibly handling file inclusion first.
virtual MCAsmLexer & getLexer()=0
virtual MCContext & getContext()=0
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
const MCRegisterInfo * getRegisterInfo() const
Base class for the full range of assembler expressions which are needed for parsing.
Instances of this class represent a single low-level machine instruction.
void addOperand(const MCOperand Op)
Interface to description of machine instruction set.
static MCOperand createExpr(const MCExpr *Val)
static MCOperand createReg(MCRegister Reg)
static MCOperand createImm(int64_t Val)
MCParsedAsmOperand - This abstract class represents a source-level assembly instruction operand.
virtual SMLoc getStartLoc() const =0
getStartLoc - Get the location of the first token of this operand.
virtual bool isReg() const =0
isReg - Is this a register operand?
virtual bool isMem() const =0
isMem - Is this a memory operand?
virtual MCRegister getReg() const =0
virtual void print(raw_ostream &OS) const =0
print - Print a debug representation of the operand to the given stream.
virtual bool isToken() const =0
isToken - Is this a token operand?
virtual bool isImm() const =0
isImm - Is this an immediate operand?
virtual SMLoc getEndLoc() const =0
getEndLoc - Get the location of the last token of this operand.
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
Wrapper class representing physical registers. Should be passed by value.
Streaming machine code generation interface.
virtual void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI)
Emit the given Instruction into the current section.
Generic base class for all target subtargets.
const FeatureBitset & getFeatureBits() const
MCTargetAsmParser - Generic interface to target specific assembly parsers.
virtual bool parseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands)=0
Parse one assembly instruction.
virtual bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc)=0
virtual ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc)=0
tryParseRegister - parse one register if possible
virtual bool matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, OperandVector &Operands, MCStreamer &Out, uint64_t &ErrorInfo, bool MatchingInlineAsm)=0
Recognize a series of operands of a parsed instruction as an actual MCInst and emit it to the specifi...
void setAvailableFeatures(const FeatureBitset &Value)
virtual unsigned validateTargetOperandClass(MCParsedAsmOperand &Op, unsigned Kind)
Allow a target to add special case operand matching for things that tblgen doesn't/can't handle effec...
const MCSubtargetInfo * STI
Current STI.
Ternary parse status returned by various parse* methods.
static constexpr StatusTy Failure
constexpr bool isSuccess() const
static constexpr StatusTy Success
static constexpr StatusTy NoMatch
Wrapper class representing virtual and physical registers.
Represents a location in source code.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
StringRef - Represent a constant reference to a string, i.e.
std::string lower() const
A switch()-like statement whose cases are string literals.
StringSwitch & Cases(StringLiteral S0, StringLiteral S1, T Value)
LLVM Value Representation.
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Reg
All possible values of the reg field in the ModR/M byte.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
DWARFExpression::Operation Op
Target & getTheM68kTarget()
RegisterMCAsmParser - Helper template for registering a target specific assembly parser,...