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];
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 <<
")";
301void M68kOperand::addExpr(
MCInst &Inst,
const MCExpr *Expr) {
302 if (
auto Const = dyn_cast<MCConstantExpr>(Expr)) {
311bool M68kOperand::isReg()
const {
312 return Kind == KindTy::MemOp &&
MemOp.Op == M68kMemOp::Kind::Reg;
317 return MemOp.OuterReg;
320void M68kOperand::addRegOperands(
MCInst &Inst,
unsigned N)
const {
322 assert((
N == 1) &&
"can only handle one register operand");
327std::unique_ptr<M68kOperand> M68kOperand::createMemOp(M68kMemOp
MemOp,
329 auto Op = std::make_unique<M68kOperand>(KindTy::MemOp, Start,
End);
335bool M68kOperand::isToken()
const {
return Kind == KindTy::Token; }
341std::unique_ptr<M68kOperand> M68kOperand::createToken(
StringRef Token,
343 auto Op = std::make_unique<M68kOperand>(KindTy::Token, Start,
End);
349bool M68kOperand::isImm()
const {
return Kind == KindTy::Imm; }
350void M68kOperand::addImmOperands(
MCInst &Inst,
unsigned N)
const {
352 assert((
N == 1) &&
"can only handle one register operand");
354 M68kOperand::addExpr(Inst, Expr);
357std::unique_ptr<M68kOperand> M68kOperand::createImm(
const MCExpr *Expr,
359 auto Op = std::make_unique<M68kOperand>(KindTy::Imm, Start,
End);
364bool M68kOperand::isTrapImm()
const {
366 if (!
isImm() || !Expr->evaluateAsAbsolute(
Value))
369 return isUInt<4>(
Value);
372bool M68kOperand::isBkptImm()
const {
374 if (!
isImm() || !Expr->evaluateAsAbsolute(
Value))
377 return isUInt<3>(
Value);
381bool M68kOperand::isMoveMask()
const {
385 if (
MemOp.Op == M68kMemOp::Kind::RegMask)
388 if (
MemOp.Op != M68kMemOp::Kind::Reg)
396void M68kOperand::addMoveMaskOperands(
MCInst &Inst,
unsigned N)
const {
397 assert(isMoveMask() &&
"wrong operand kind");
398 assert((
N == 1) &&
"can only handle one immediate operand");
401 if (
MemOp.Op == M68kMemOp::Kind::Reg)
408bool M68kOperand::isAddr()
const {
409 return isMemOp() &&
MemOp.Op == M68kMemOp::Kind::Addr;
413template <
unsigned N>
bool M68kOperand::isAddrN()
const {
416 if (
MemOp.OuterDisp->evaluateAsAbsolute(Res))
417 return isInt<N>(Res);
422void M68kOperand::addAddrOperands(
MCInst &Inst,
unsigned N)
const {
423 M68kOperand::addExpr(Inst,
MemOp.OuterDisp);
427bool M68kOperand::isARI()
const {
428 return isMemOp() &&
MemOp.Op == M68kMemOp::Kind::RegIndirect &&
429 M68k::AR32RegClass.contains(
MemOp.OuterReg);
431void M68kOperand::addARIOperands(
MCInst &Inst,
unsigned N)
const {
436bool M68kOperand::isARID()
const {
437 return isMemOp() &&
MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacement &&
438 M68k::AR32RegClass.contains(
MemOp.OuterReg);
440void M68kOperand::addARIDOperands(
MCInst &Inst,
unsigned N)
const {
441 M68kOperand::addExpr(Inst,
MemOp.OuterDisp);
446bool M68kOperand::isARII()
const {
448 MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacementIndex &&
449 M68k::AR32RegClass.contains(
MemOp.OuterReg);
451void M68kOperand::addARIIOperands(
MCInst &Inst,
unsigned N)
const {
452 M68kOperand::addExpr(Inst,
MemOp.OuterDisp);
458bool M68kOperand::isARIPD()
const {
459 return isMemOp() &&
MemOp.Op == M68kMemOp::Kind::RegPreDecrement &&
460 M68k::AR32RegClass.contains(
MemOp.OuterReg);
462void M68kOperand::addARIPDOperands(
MCInst &Inst,
unsigned N)
const {
467bool M68kOperand::isARIPI()
const {
468 return isMemOp() &&
MemOp.Op == M68kMemOp::Kind::RegPostIncrement &&
469 M68k::AR32RegClass.contains(
MemOp.OuterReg);
471void M68kOperand::addARIPIOperands(
MCInst &Inst,
unsigned N)
const {
476bool M68kOperand::isPCD()
const {
477 return isMemOp() &&
MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacement &&
478 MemOp.OuterReg == M68k::PC;
480void M68kOperand::addPCDOperands(
MCInst &Inst,
unsigned N)
const {
481 M68kOperand::addExpr(Inst,
MemOp.OuterDisp);
485bool M68kOperand::isPCI()
const {
487 MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacementIndex &&
488 MemOp.OuterReg == M68k::PC;
490void M68kOperand::addPCIOperands(
MCInst &Inst,
unsigned N)
const {
491 M68kOperand::addExpr(Inst,
MemOp.OuterDisp);
496 bool SP,
bool FPDR =
false,
546bool M68kOperand::isAReg()
const {
552bool M68kOperand::isDReg()
const {
558bool M68kOperand::isFPDReg()
const {
565bool M68kOperand::isFPCReg()
const {
574 M68kOperand &Operand = (M68kOperand &)
Op;
579 if (Operand.isReg() &&
581 return Match_Success;
587 if (Operand.isReg() &&
589 return Match_Success;
594 if (Operand.isReg() &&
596 return Match_Success;
603 if (Operand.isReg() &&
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;
637 auto RegisterNameLower = RegisterName.
lower();
640 if (RegisterNameLower ==
"ccr") {
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');
663 if (RegisterNameLower[1] ==
'p') {
666 }
else if (RegisterNameLower[1] ==
'r') {
673 if (RegisterNameLower[1] ==
'c') {
680 RegisterNameLower.size() > 2) {
681 auto RegIndex =
unsigned(RegisterNameLower[2] -
'0');
682 if (RegIndex < 8 && RegisterNameLower.size() == 3) {
689 .
Cases(
"fpc",
"fpcr", M68k::FPC)
690 .
Cases(
"fps",
"fpsr", M68k::FPS)
691 .
Cases(
"fpi",
"fpiar", M68k::FPIAR)
693 assert(RegNo != M68k::NoRegister &&
694 "Unrecognized FP control register name");
703 bool HasPercent =
false;
710 PercentToken = Lex();
717 getLexer().UnLex(PercentToken);
723 if (!parseRegisterName(RegNo, Parser.
getLexer().
getLoc(), RegisterName)) {
725 getLexer().UnLex(PercentToken);
738 return Error(StartLoc,
"expected register");
745 StartLoc = getLexer().getLoc();
747 EndLoc = getLexer().getLoc();
751bool M68kAsmParser::isExpr() {
767 SMLoc Start = getLexer().getLoc();
773 if (getParser().parseExpression(Expr,
End))
776 Operands.push_back(M68kOperand::createImm(Expr, Start,
End));
781 SMLoc Start = getLexer().getLoc();
791 bool HasDisplacement =
false;
795 }
else if (isExpr()) {
798 HasDisplacement =
true;
802 if (HasDisplacement) {
803 MemOp.Op = M68kMemOp::Kind::Addr;
805 M68kOperand::createMemOp(
MemOp, Start, getLexer().getLoc()));
809 return Error(getLexer().getLoc(),
"expected (");
816 if (!HasDisplacement && isExpr()) {
819 HasDisplacement =
true;
823 MemOp.Op = M68kMemOp::Kind::Addr;
825 M68kOperand::createMemOp(
MemOp, Start, getLexer().getLoc()));
837 return Error(getLexer().getLoc(),
"expected register");
849 return Error(getLexer().getLoc(),
"expected register");
859 return Error(getLexer().getLoc(),
"expected )");
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;
892 SMLoc Start = getLexer().getLoc();
893 M68kMemOp
MemOp(M68kMemOp::Kind::RegMask);
897 bool IsFirstRegister =
898 (
MemOp.Op == M68kMemOp::Kind::RegMask) && (
MemOp.RegMask == 0);
902 if (IsFirstRegister &&
Result.isNoMatch())
905 return Error(getLexer().getLoc(),
"expected start register");
909 Result = parseRegister(LastRegister);
911 return Error(getLexer().getLoc(),
"expected end register");
917 uint16_t NumNewBits = LastRegisterIndex - FirstRegisterIndex + 1;
918 uint16_t NewMaskBits = ((1 << NumNewBits) - 1) << FirstRegisterIndex;
920 if (IsFirstRegister && (FirstRegister == LastRegister)) {
923 MemOp.Op = M68kMemOp::Kind::Reg;
924 MemOp.OuterReg = FirstRegister;
926 if (
MemOp.Op == M68kMemOp::Kind::Reg) {
929 MemOp.Op = M68kMemOp::Kind::RegMask;
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;
952 M68kOperand::createMemOp(
MemOp, Start, getLexer().getLoc()));
956void M68kAsmParser::eatComma() {
964 SMLoc Start = getLexer().getLoc();
965 Operands.push_back(M68kOperand::createToken(
Name, Start, Start));
980 SMLoc Loc = getLexer().getLoc();
982 return Error(Loc,
"unexpected token parsing operands");
990bool M68kAsmParser::invalidOperand(
SMLoc const &Loc,
993 SMLoc ErrorLoc = Loc;
994 char const *Diag = 0;
998 Diag =
"too few operands for instruction.";
1001 if (
Op.getStartLoc() !=
SMLoc()) {
1002 ErrorLoc =
Op.getStartLoc();
1008 Diag =
"invalid operand for instruction";
1011 return Error(ErrorLoc, Diag);
1014bool M68kAsmParser::missingFeature(
llvm::SMLoc const &Loc,
1016 return Error(Loc,
"instruction requires a CPU feature not currently enabled");
1019bool M68kAsmParser::emit(
MCInst &Inst,
SMLoc const &Loc,
1027bool M68kAsmParser::matchAndEmitInstruction(
SMLoc Loc,
unsigned &Opcode,
1031 bool MatchingInlineAsm) {
1033 unsigned MatchResult =
1036 switch (MatchResult) {
1038 return emit(Inst, Loc, Out);
1039 case Match_MissingFeature:
1041 case Match_InvalidOperand:
1043 case Match_MnemonicFail:
1044 return Error(Loc,
"invalid instruction");
1052 case KindTy::Invalid:
1057 OS <<
"token '" << Token <<
"'";
1062 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,...