LLVM  14.0.0git
M68kAsmParser.cpp
Go to the documentation of this file.
1 //===---- M68kAsmParser.cpp - Parse M68k assembly to MCInst instructions --===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "M68kInstrInfo.h"
10 #include "M68kRegisterInfo.h"
12 
13 #include "llvm/MC/MCContext.h"
16 #include "llvm/MC/MCStreamer.h"
18 
19 #include <sstream>
20 
21 #define DEBUG_TYPE "m68k-asm-parser"
22 
23 using namespace llvm;
24 
26  "m68k-register-prefix-optional", cl::Hidden,
27  cl::desc("Enable specifying registers without the % prefix"),
28  cl::init(false));
29 
30 namespace {
31 /// Parses M68k assembly from a stream.
32 class M68kAsmParser : public MCTargetAsmParser {
33  const MCSubtargetInfo &STI;
34  MCAsmParser &Parser;
35  const MCRegisterInfo *MRI;
36 
37 #define GET_ASSEMBLER_HEADER
38 #include "M68kGenAsmMatcher.inc"
39 
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);
48 
49  // Parser functions.
50  void eatComma();
51 
52  bool isExpr();
55 
56 public:
57  M68kAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
58  const MCInstrInfo &MII, const MCTargetOptions &Options)
59  : MCTargetAsmParser(Options, STI, MII), STI(STI), Parser(Parser) {
61  MRI = getContext().getRegisterInfo();
62 
63  setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
64  }
65 
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,
76  uint64_t &ErrorInfo,
77  bool MatchingInlineAsm) override;
78 };
79 
80 struct M68kMemOp {
81  enum class Kind {
82  Addr,
83  Reg,
84  RegIndirect,
85  RegPostIncrement,
86  RegPreDecrement,
87  RegIndirectDisplacement,
88  RegIndirectDisplacementIndex,
89  };
90 
91  // These variables are used for the following forms:
92  // Addr: (OuterDisp)
93  // Reg: %OuterReg
94  // RegIndirect: (%OuterReg)
95  // RegPostIncrement: (%OuterReg)+
96  // RegPreDecrement: -(%OuterReg)
97  // RegIndirectDisplacement: OuterDisp(%OuterReg)
98  // RegIndirectDisplacementIndex:
99  // OuterDisp(%OuterReg, %InnerReg.Size * Scale, InnerDisp)
100 
101  Kind Op;
102  unsigned OuterReg;
103  unsigned InnerReg;
104  const MCExpr *OuterDisp;
105  const MCExpr *InnerDisp;
106  uint8_t Size : 4;
107  uint8_t Scale : 4;
108  const MCExpr *Expr;
109 
110  M68kMemOp() {}
111  M68kMemOp(Kind Op) : Op(Op) {}
112 
113  void print(raw_ostream &OS) const;
114 };
115 
116 /// An parsed M68k assembly operand.
117 class M68kOperand : public MCParsedAsmOperand {
118  typedef MCParsedAsmOperand Base;
119 
120  enum class Kind {
121  Invalid,
122  Token,
123  Imm,
124  MemOp,
125  };
126 
127  Kind Kind;
128  SMLoc Start, End;
129  union {
130  StringRef Token;
131  int64_t Imm;
132  const MCExpr *Expr;
133  M68kMemOp MemOp;
134  };
135 
136 public:
137  M68kOperand(enum Kind Kind, SMLoc Start, SMLoc End)
138  : Base(), Kind(Kind), Start(Start), End(End) {}
139 
140  SMLoc getStartLoc() const override { return Start; }
141  SMLoc getEndLoc() const override { return End; }
142 
143  void print(raw_ostream &OS) const override;
144 
145  bool isMem() const override { return false; }
146  bool isMemOp() const { return Kind == Kind::MemOp; }
147 
148  static void addExpr(MCInst &Inst, const MCExpr *Expr);
149 
150  // Reg
151  bool isReg() const override;
152  unsigned getReg() const override;
153  void addRegOperands(MCInst &Inst, unsigned N) const;
154 
155  static std::unique_ptr<M68kOperand> createMemOp(M68kMemOp MemOp, SMLoc Start,
156  SMLoc End);
157 
158  // Token
159  bool isToken() const override;
160  StringRef getToken() const;
161  static std::unique_ptr<M68kOperand> createToken(StringRef Token, SMLoc Start,
162  SMLoc End);
163 
164  // Imm
165  bool isImm() const override;
166  void addImmOperands(MCInst &Inst, unsigned N) const;
167 
168  static std::unique_ptr<M68kOperand> createImm(const MCExpr *Expr, SMLoc Start,
169  SMLoc End);
170 
171  // Addr
172  bool isAddr() const;
173  void addAddrOperands(MCInst &Inst, unsigned N) const;
174 
175  // ARI
176  bool isARI() const;
177  void addARIOperands(MCInst &Inst, unsigned N) const;
178 
179  // ARID
180  bool isARID() const;
181  void addARIDOperands(MCInst &Inst, unsigned N) const;
182 
183  // ARII
184  bool isARII() const;
185  void addARIIOperands(MCInst &Inst, unsigned N) const;
186 
187  // ARIPD
188  bool isARIPD() const;
189  void addARIPDOperands(MCInst &Inst, unsigned N) const;
190 
191  // ARIPI
192  bool isARIPI() const;
193  void addARIPIOperands(MCInst &Inst, unsigned N) const;
194 
195  // PCD
196  bool isPCD() const;
197  void addPCDOperands(MCInst &Inst, unsigned N) const;
198 
199  // PCI
200  bool isPCI() const;
201  void addPCIOperands(MCInst &Inst, unsigned N) const;
202 };
203 
204 } // end anonymous namespace.
205 
208 }
209 
210 #define GET_MATCHER_IMPLEMENTATION
211 #include "M68kGenAsmMatcher.inc"
212 
213 void M68kMemOp::print(raw_ostream &OS) const {
214  switch (Op) {
215  case Kind::Addr:
216  OS << OuterDisp;
217  break;
218  case Kind::Reg:
219  OS << '%' << OuterReg;
220  break;
221  case Kind::RegIndirect:
222  OS << "(%" << OuterReg << ')';
223  break;
224  case Kind::RegPostIncrement:
225  OS << "(%" << OuterReg << ")+";
226  break;
227  case Kind::RegPreDecrement:
228  OS << "-(%" << OuterReg << ")";
229  break;
230  case Kind::RegIndirectDisplacement:
231  OS << OuterDisp << "(%" << OuterReg << ")";
232  break;
233  case Kind::RegIndirectDisplacementIndex:
234  OS << OuterDisp << "(%" << OuterReg << ", " << InnerReg << "." << Size
235  << ", " << InnerDisp << ")";
236  break;
237  }
238 }
239 
240 void M68kOperand::addExpr(MCInst &Inst, const MCExpr *Expr) {
241  if (auto Const = dyn_cast<MCConstantExpr>(Expr)) {
242  Inst.addOperand(MCOperand::createImm(Const->getValue()));
243  return;
244  }
245 
246  Inst.addOperand(MCOperand::createExpr(Expr));
247 }
248 
249 // Reg
250 bool M68kOperand::isReg() const {
251  return Kind == Kind::MemOp && MemOp.Op == M68kMemOp::Kind::Reg;
252 }
253 
254 unsigned M68kOperand::getReg() const {
255  assert(isReg());
256  return MemOp.OuterReg;
257 }
258 
259 void M68kOperand::addRegOperands(MCInst &Inst, unsigned N) const {
260  assert(isReg() && "wrong operand kind");
261  assert((N == 1) && "can only handle one register operand");
262 
264 }
265 
266 std::unique_ptr<M68kOperand> M68kOperand::createMemOp(M68kMemOp MemOp,
267  SMLoc Start, SMLoc End) {
268  auto Op = std::make_unique<M68kOperand>(Kind::MemOp, Start, End);
269  Op->MemOp = MemOp;
270  return Op;
271 }
272 
273 // Token
274 bool M68kOperand::isToken() const { return Kind == Kind::Token; }
275 StringRef M68kOperand::getToken() const {
276  assert(isToken());
277  return Token;
278 }
279 
280 std::unique_ptr<M68kOperand> M68kOperand::createToken(StringRef Token,
281  SMLoc Start, SMLoc End) {
282  auto Op = std::make_unique<M68kOperand>(Kind::Token, Start, End);
283  Op->Token = Token;
284  return Op;
285 }
286 
287 // Imm
288 bool M68kOperand::isImm() const { return Kind == Kind::Imm; }
289 void M68kOperand::addImmOperands(MCInst &Inst, unsigned N) const {
290  assert(isImm() && "wrong oeprand kind");
291  assert((N == 1) && "can only handle one register operand");
292 
293  M68kOperand::addExpr(Inst, Expr);
294 }
295 
296 std::unique_ptr<M68kOperand> M68kOperand::createImm(const MCExpr *Expr,
297  SMLoc Start, SMLoc End) {
298  auto Op = std::make_unique<M68kOperand>(Kind::Imm, Start, End);
299  Op->Expr = Expr;
300  return Op;
301 }
302 
303 // Addr
304 bool M68kOperand::isAddr() const {
305  return isMemOp() && MemOp.Op == M68kMemOp::Kind::Addr;
306 }
307 void M68kOperand::addAddrOperands(MCInst &Inst, unsigned N) const {
308  M68kOperand::addExpr(Inst, MemOp.OuterDisp);
309 }
310 
311 // ARI
312 bool M68kOperand::isARI() const {
313  return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegIndirect &&
314  M68k::AR32RegClass.contains(MemOp.OuterReg);
315 }
316 void M68kOperand::addARIOperands(MCInst &Inst, unsigned N) const {
317  Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));
318 }
319 
320 // ARID
321 bool M68kOperand::isARID() const {
322  return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacement &&
323  M68k::AR32RegClass.contains(MemOp.OuterReg);
324 }
325 void M68kOperand::addARIDOperands(MCInst &Inst, unsigned N) const {
326  M68kOperand::addExpr(Inst, MemOp.OuterDisp);
327  Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));
328 }
329 
330 // ARII
331 bool M68kOperand::isARII() const {
332  return isMemOp() &&
333  MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacementIndex &&
334  M68k::AR32RegClass.contains(MemOp.OuterReg);
335 }
336 void M68kOperand::addARIIOperands(MCInst &Inst, unsigned N) const {
337  M68kOperand::addExpr(Inst, MemOp.OuterDisp);
338  Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));
339  Inst.addOperand(MCOperand::createReg(MemOp.InnerReg));
340 }
341 
342 // ARIPD
343 bool M68kOperand::isARIPD() const {
344  return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegPreDecrement &&
345  M68k::AR32RegClass.contains(MemOp.OuterReg);
346 }
347 void M68kOperand::addARIPDOperands(MCInst &Inst, unsigned N) const {
348  Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));
349 }
350 
351 // ARIPI
352 bool M68kOperand::isARIPI() const {
353  return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegPostIncrement &&
354  M68k::AR32RegClass.contains(MemOp.OuterReg);
355 }
356 void M68kOperand::addARIPIOperands(MCInst &Inst, unsigned N) const {
357  Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));
358 }
359 
360 // PCD
361 bool M68kOperand::isPCD() const {
362  return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacement &&
363  MemOp.OuterReg == M68k::PC;
364 }
365 void M68kOperand::addPCDOperands(MCInst &Inst, unsigned N) const {
366  M68kOperand::addExpr(Inst, MemOp.OuterDisp);
367 }
368 
369 // PCI
370 bool M68kOperand::isPCI() const {
371  return isMemOp() &&
372  MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacementIndex &&
373  MemOp.OuterReg == M68k::PC;
374 }
375 void M68kOperand::addPCIOperands(MCInst &Inst, unsigned N) const {
376  M68kOperand::addExpr(Inst, MemOp.OuterDisp);
377  Inst.addOperand(MCOperand::createReg(MemOp.InnerReg));
378 }
379 
380 static inline bool checkRegisterClass(unsigned RegNo, bool Data, bool Address,
381  bool SP) {
382  switch (RegNo) {
383  case M68k::A0:
384  case M68k::A1:
385  case M68k::A2:
386  case M68k::A3:
387  case M68k::A4:
388  case M68k::A5:
389  case M68k::A6:
390  return Address;
391 
392  case M68k::SP:
393  return SP;
394 
395  case M68k::D0:
396  case M68k::D1:
397  case M68k::D2:
398  case M68k::D3:
399  case M68k::D4:
400  case M68k::D5:
401  case M68k::D6:
402  case M68k::D7:
403  return Data;
404 
405  case M68k::SR:
406  case M68k::CCR:
407  return false;
408 
409  default:
410  llvm_unreachable("unexpected register type");
411  return false;
412  }
413 }
414 
415 unsigned M68kAsmParser::validateTargetOperandClass(MCParsedAsmOperand &Op,
416  unsigned Kind) {
417  M68kOperand &Operand = (M68kOperand &)Op;
418 
419  switch (Kind) {
420  case MCK_XR16:
421  case MCK_SPILL:
422  if (Operand.isReg() &&
423  checkRegisterClass(Operand.getReg(), true, true, true)) {
424  return Match_Success;
425  }
426  break;
427 
428  case MCK_AR16:
429  case MCK_AR32:
430  if (Operand.isReg() &&
431  checkRegisterClass(Operand.getReg(), false, true, true)) {
432  return Match_Success;
433  }
434  break;
435 
436  case MCK_AR32_NOSP:
437  if (Operand.isReg() &&
438  checkRegisterClass(Operand.getReg(), false, true, false)) {
439  return Match_Success;
440  }
441  break;
442 
443  case MCK_DR8:
444  case MCK_DR16:
445  case MCK_DR32:
446  if (Operand.isReg() &&
447  checkRegisterClass(Operand.getReg(), true, false, false)) {
448  return Match_Success;
449  }
450  break;
451 
452  case MCK_AR16_TC:
453  if (Operand.isReg() &&
454  ((Operand.getReg() == M68k::A0) || (Operand.getReg() == M68k::A1))) {
455  return Match_Success;
456  }
457  break;
458 
459  case MCK_DR16_TC:
460  if (Operand.isReg() &&
461  ((Operand.getReg() == M68k::D0) || (Operand.getReg() == M68k::D1))) {
462  return Match_Success;
463  }
464  break;
465 
466  case MCK_XR16_TC:
467  if (Operand.isReg() &&
468  ((Operand.getReg() == M68k::D0) || (Operand.getReg() == M68k::D1) ||
469  (Operand.getReg() == M68k::A0) || (Operand.getReg() == M68k::A1))) {
470  return Match_Success;
471  }
472  break;
473  }
474 
475  return Match_InvalidOperand;
476 }
477 
478 bool M68kAsmParser::parseRegisterName(unsigned &RegNo, SMLoc Loc,
479  StringRef RegisterName) {
480  auto RegisterNameLower = RegisterName.lower();
481 
482  // CCR register
483  if (RegisterNameLower == "ccr") {
484  RegNo = M68k::CCR;
485  return true;
486  }
487 
488  // Parse simple general-purpose registers.
489  if (RegisterNameLower.size() == 2) {
490  static unsigned RegistersByIndex[] = {
491  M68k::D0, M68k::D1, M68k::D2, M68k::D3, M68k::D4, M68k::D5,
492  M68k::D6, M68k::D7, M68k::A0, M68k::A1, M68k::A2, M68k::A3,
493  M68k::A4, M68k::A5, M68k::A6, M68k::SP,
494  };
495 
496  switch (RegisterNameLower[0]) {
497  case 'd':
498  case 'a': {
499  if (isdigit(RegisterNameLower[1])) {
500  unsigned IndexOffset = (RegisterNameLower[0] == 'a') ? 8 : 0;
501  unsigned RegIndex = (unsigned)(RegisterNameLower[1] - '0');
502  if (RegIndex < 8) {
503  RegNo = RegistersByIndex[IndexOffset + RegIndex];
504  return true;
505  }
506  }
507  break;
508  }
509 
510  case 's':
511  if (RegisterNameLower[1] == 'p') {
512  RegNo = M68k::SP;
513  return true;
514  } else if (RegisterNameLower[1] == 'r') {
515  RegNo = M68k::SR;
516  return true;
517  }
518  break;
519 
520  case 'p':
521  if (RegisterNameLower[1] == 'c') {
522  RegNo = M68k::PC;
523  return true;
524  }
525  break;
526  }
527  }
528 
529  return false;
530 }
531 
532 OperandMatchResultTy M68kAsmParser::parseRegister(unsigned &RegNo) {
533  bool HasPercent = false;
534  AsmToken PercentToken;
535 
536  LLVM_DEBUG(dbgs() << "parseRegister "; getTok().dump(dbgs()); dbgs() << "\n");
537 
538  if (getTok().is(AsmToken::Percent)) {
539  HasPercent = true;
540  PercentToken = Lex();
541  } else if (!RegisterPrefixOptional.getValue()) {
542  return MatchOperand_NoMatch;
543  }
544 
545  if (!Parser.getTok().is(AsmToken::Identifier)) {
546  if (HasPercent) {
547  getLexer().UnLex(PercentToken);
548  }
549  return MatchOperand_NoMatch;
550  }
551 
552  auto RegisterName = Parser.getTok().getString();
553  if (!parseRegisterName(RegNo, Parser.getLexer().getLoc(), RegisterName)) {
554  if (HasPercent) {
555  getLexer().UnLex(PercentToken);
556  }
557  return MatchOperand_NoMatch;
558  }
559 
560  Parser.Lex();
561  return MatchOperand_Success;
562 }
563 
564 bool M68kAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
565  SMLoc &EndLoc) {
566  auto Result = tryParseRegister(RegNo, StartLoc, EndLoc);
567  if (Result != MatchOperand_Success) {
568  return Error(StartLoc, "expected register");
569  }
570 
571  return false;
572 }
573 
574 OperandMatchResultTy M68kAsmParser::tryParseRegister(unsigned &RegNo,
575  SMLoc &StartLoc,
576  SMLoc &EndLoc) {
577  StartLoc = getLexer().getLoc();
578  auto Result = parseRegister(RegNo);
579  EndLoc = getLexer().getLoc();
580  return Result;
581 }
582 
583 bool M68kAsmParser::isExpr() {
584  switch (Parser.getTok().getKind()) {
586  case AsmToken::Integer:
587  return true;
588  case AsmToken::Minus:
589  return getLexer().peekTok().getKind() == AsmToken::Integer;
590 
591  default:
592  return false;
593  }
594 }
595 
596 OperandMatchResultTy M68kAsmParser::parseImm(OperandVector &Operands) {
597  if (getLexer().isNot(AsmToken::Hash)) {
598  return MatchOperand_NoMatch;
599  }
600  SMLoc Start = getLexer().getLoc();
601  Parser.Lex();
602 
603  SMLoc End;
604  const MCExpr *Expr;
605 
606  if (getParser().parseExpression(Expr, End)) {
607  return MatchOperand_ParseFail;
608  }
609 
610  Operands.push_back(M68kOperand::createImm(Expr, Start, End));
611  return MatchOperand_Success;
612 }
613 
614 OperandMatchResultTy M68kAsmParser::parseMemOp(OperandVector &Operands) {
615  SMLoc Start = getLexer().getLoc();
616  bool IsPD = false;
617  M68kMemOp MemOp;
618 
619  // Check for a plain register.
620  auto Result = parseRegister(MemOp.OuterReg);
621  if (Result == MatchOperand_Success) {
623  Operands.push_back(
624  M68kOperand::createMemOp(MemOp, Start, getLexer().getLoc()));
625  return MatchOperand_Success;
626  }
627 
628  if (Result == MatchOperand_ParseFail) {
629  return Result;
630  }
631 
632  // Check for pre-decrement & outer displacement.
633  bool HasDisplacement = false;
634  if (getLexer().is(AsmToken::Minus)) {
635  IsPD = true;
636  Parser.Lex();
637  } else if (isExpr()) {
638  if (Parser.parseExpression(MemOp.OuterDisp)) {
639  return MatchOperand_ParseFail;
640  }
641  HasDisplacement = true;
642  }
643 
644  if (getLexer().isNot(AsmToken::LParen)) {
645  if (HasDisplacement) {
647  Operands.push_back(
648  M68kOperand::createMemOp(MemOp, Start, getLexer().getLoc()));
649  return MatchOperand_Success;
650  } else if (IsPD) {
651  Error(getLexer().getLoc(), "expected (");
652  return MatchOperand_ParseFail;
653  }
654 
655  return MatchOperand_NoMatch;
656  }
657  Parser.Lex();
658 
659  // Check for constant dereference & MIT-style displacement
660  if (!HasDisplacement && isExpr()) {
661  if (Parser.parseExpression(MemOp.OuterDisp)) {
662  return MatchOperand_ParseFail;
663  }
664  HasDisplacement = true;
665 
666  // If we're not followed by a comma, we're a constant dereference.
667  if (getLexer().isNot(AsmToken::Comma)) {
669  Operands.push_back(
670  M68kOperand::createMemOp(MemOp, Start, getLexer().getLoc()));
671  return MatchOperand_Success;
672  }
673 
674  Parser.Lex();
675  }
676 
677  Result = parseRegister(MemOp.OuterReg);
678  if (Result == MatchOperand_ParseFail) {
679  return MatchOperand_ParseFail;
680  }
681 
682  if (Result != MatchOperand_Success) {
683  Error(getLexer().getLoc(), "expected register");
684  return MatchOperand_ParseFail;
685  }
686 
687  // Check for Index.
688  bool HasIndex = false;
689  if (Parser.getTok().is(AsmToken::Comma)) {
690  Parser.Lex();
691 
692  Result = parseRegister(MemOp.InnerReg);
693  if (Result == MatchOperand_ParseFail) {
694  return Result;
695  }
696 
697  if (Result == MatchOperand_NoMatch) {
698  Error(getLexer().getLoc(), "expected register");
699  return MatchOperand_ParseFail;
700  }
701 
702  // TODO: parse size, scale and inner displacement.
703  MemOp.Size = 4;
704  MemOp.Scale = 1;
705  MemOp.InnerDisp = MCConstantExpr::create(0, Parser.getContext(), true, 4);
706  HasIndex = true;
707  }
708 
709  if (Parser.getTok().isNot(AsmToken::RParen)) {
710  Error(getLexer().getLoc(), "expected )");
711  return MatchOperand_ParseFail;
712  }
713  Parser.Lex();
714 
715  bool IsPI = false;
716  if (!IsPD && Parser.getTok().is(AsmToken::Plus)) {
717  Parser.Lex();
718  IsPI = true;
719  }
720 
721  SMLoc End = getLexer().getLoc();
722 
723  unsigned OpCount = IsPD + IsPI + (HasIndex || HasDisplacement);
724  if (OpCount > 1) {
725  Error(Start, "only one of post-increment, pre-decrement or displacement "
726  "can be used");
727  return MatchOperand_ParseFail;
728  }
729 
730  if (IsPD) {
731  MemOp.Op = M68kMemOp::Kind::RegPreDecrement;
732  } else if (IsPI) {
733  MemOp.Op = M68kMemOp::Kind::RegPostIncrement;
734  } else if (HasIndex) {
735  MemOp.Op = M68kMemOp::Kind::RegIndirectDisplacementIndex;
736  } else if (HasDisplacement) {
737  MemOp.Op = M68kMemOp::Kind::RegIndirectDisplacement;
738  } else {
739  MemOp.Op = M68kMemOp::Kind::RegIndirect;
740  }
741 
742  Operands.push_back(M68kOperand::createMemOp(MemOp, Start, End));
743  return MatchOperand_Success;
744 }
745 
746 void M68kAsmParser::eatComma() {
747  if (Parser.getTok().is(AsmToken::Comma)) {
748  Parser.Lex();
749  }
750 }
751 
752 bool M68kAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
753  SMLoc NameLoc, OperandVector &Operands) {
754  SMLoc Start = getLexer().getLoc();
755  Operands.push_back(M68kOperand::createToken(Name, Start, Start));
756 
757  bool First = true;
758  while (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
759  if (!First) {
760  eatComma();
761  } else {
762  First = false;
763  }
764 
765  auto MatchResult = MatchOperandParserImpl(Operands, Name);
766  if (MatchResult == MatchOperand_Success) {
767  continue;
768  }
769 
770  // Add custom operand formats here...
771  SMLoc Loc = getLexer().getLoc();
772  Parser.eatToEndOfStatement();
773  return Error(Loc, "unexpected token parsing operands");
774  }
775 
776  // Eat EndOfStatement.
777  Parser.Lex();
778  return false;
779 }
780 
781 bool M68kAsmParser::ParseDirective(AsmToken DirectiveID) { return true; }
782 
783 bool M68kAsmParser::invalidOperand(SMLoc const &Loc,
784  OperandVector const &Operands,
785  uint64_t const &ErrorInfo) {
786  SMLoc ErrorLoc = Loc;
787  char const *Diag = 0;
788 
789  if (ErrorInfo != ~0U) {
790  if (ErrorInfo >= Operands.size()) {
791  Diag = "too few operands for instruction.";
792  } else {
793  auto const &Op = (M68kOperand const &)*Operands[ErrorInfo];
794  if (Op.getStartLoc() != SMLoc()) {
795  ErrorLoc = Op.getStartLoc();
796  }
797  }
798  }
799 
800  if (!Diag) {
801  Diag = "invalid operand for instruction";
802  }
803 
804  return Error(ErrorLoc, Diag);
805 }
806 
807 bool M68kAsmParser::missingFeature(llvm::SMLoc const &Loc,
808  uint64_t const &ErrorInfo) {
809  return Error(Loc, "instruction requires a CPU feature not currently enabled");
810 }
811 
812 bool M68kAsmParser::emit(MCInst &Inst, SMLoc const &Loc,
813  MCStreamer &Out) const {
814  Inst.setLoc(Loc);
815  Out.emitInstruction(Inst, STI);
816 
817  return false;
818 }
819 
820 bool M68kAsmParser::MatchAndEmitInstruction(SMLoc Loc, unsigned &Opcode,
822  MCStreamer &Out,
823  uint64_t &ErrorInfo,
824  bool MatchingInlineAsm) {
825  MCInst Inst;
826  unsigned MatchResult =
827  MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
828 
829  switch (MatchResult) {
830  case Match_Success:
831  return emit(Inst, Loc, Out);
832  case Match_MissingFeature:
833  return missingFeature(Loc, ErrorInfo);
834  case Match_InvalidOperand:
835  return invalidOperand(Loc, Operands, ErrorInfo);
836  case Match_MnemonicFail:
837  return Error(Loc, "invalid instruction");
838  default:
839  return true;
840  }
841 }
842 
843 void M68kOperand::print(raw_ostream &OS) const {
844  switch (Kind) {
845  case Kind::Invalid:
846  OS << "invalid";
847  break;
848 
849  case Kind::Token:
850  OS << "token '" << Token << "'";
851  break;
852 
853  case Kind::Imm:
854  OS << "immediate " << Imm;
855  break;
856 
857  case Kind::MemOp:
858  MemOp.print(OS);
859  break;
860  }
861 }
llvm::Check::Size
@ Size
Definition: FileCheck.h:73
llvm::MCAsmParser
Generic assembler parser interface, for use by target specific assembly parsers.
Definition: MCAsmParser.h:124
is
should just be implemented with a CLZ instruction Since there are other e that share this it would be best to implement this in a target independent as zero is the default value for the binary encoder e add r0 add r5 Register operands should be distinct That is
Definition: README.txt:725
llvm
---------------------— PointerInfo ------------------------------------—
Definition: AllocatorList.h:23
Reg
unsigned Reg
Definition: MachineSink.cpp:1566
llvm::AsmToken::is
bool is(TokenKind K) const
Definition: MCAsmMacro.h:82
llvm::MCOperand::createExpr
static MCOperand createExpr(const MCExpr *Val)
Definition: MCInst.h:162
print
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
Definition: ArchiveWriter.cpp:147
llvm::MCParsedAsmOperand
MCParsedAsmOperand - This abstract class represents a source-level assembly instruction operand.
Definition: MCParsedAsmOperand.h:24
llvm::MCOperand::createImm
static MCOperand createImm(int64_t Val)
Definition: MCInst.h:141
llvm::AsmToken::EndOfStatement
@ EndOfStatement
Definition: MCAsmMacro.h:42
llvm::MCConstantExpr::create
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition: MCExpr.cpp:194
MCParsedAsmOperand.h
llvm::MachO::Invalid
@ Invalid
Invalid file type.
Definition: InterfaceFile.h:59
llvm::cl::Hidden
@ Hidden
Definition: CommandLine.h:143
llvm::MemOp
Definition: TargetLowering.h:111
llvm::getTheM68kTarget
Target & getTheM68kTarget()
Definition: M68kTargetInfo.cpp:18
llvm::AsmToken::Integer
@ Integer
Definition: MCAsmMacro.h:32
llvm::MCInst
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:184
MCTargetAsmParser.h
llvm::Data
@ Data
Definition: SIMachineScheduler.h:56
LLVM_DEBUG
#define LLVM_DEBUG(X)
Definition: Debug.h:122
llvm::AsmToken
Target independent representation for an assembler token.
Definition: MCAsmMacro.h:21
M68kInstrInfo.h
llvm::AsmToken::Minus
@ Minus
Definition: MCAsmMacro.h:45
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
llvm::AsmToken::LParen
@ LParen
Definition: MCAsmMacro.h:48
llvm::MCAsmParser::Lex
virtual const AsmToken & Lex()=0
Get the next AsmToken in the stream, possibly handling file inclusion first.
llvm::MCStreamer
Streaming machine code generation interface.
Definition: MCStreamer.h:197
llvm::MCAsmParser::parseExpression
virtual bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc)=0
Parse an arbitrary expression.
RegisterPrefixOptional
static cl::opt< bool > RegisterPrefixOptional("m68k-register-prefix-optional", cl::Hidden, cl::desc("Enable specifying registers without the % prefix"), cl::init(false))
llvm::RegisterMCAsmParser
RegisterMCAsmParser - Helper template for registering a target specific assembly parser,...
Definition: TargetRegistry.h:1317
llvm::MatchOperand_Success
@ MatchOperand_Success
Definition: MCTargetAsmParser.h:122
llvm::SMLoc
Represents a location in source code.
Definition: SMLoc.h:23
MCContext.h
llvm::ms_demangle::QualifierMangleMode::Result
@ Result
First
into llvm powi allowing the code generator to produce balanced multiplication trees First
Definition: README.txt:54
llvm::MCSubtargetInfo::getFeatureBits
const FeatureBitset & getFeatureBits() const
Definition: MCSubtargetInfo.h:111
llvm::MCAsmParser::getContext
virtual MCContext & getContext()=0
Options
const char LLVMTargetMachineRef LLVMPassBuilderOptionsRef Options
Definition: PassBuilderBindings.cpp:48
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:53
llvm::AsmToken::getKind
TokenKind getKind() const
Definition: MCAsmMacro.h:81
Info
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
isNot
static bool isNot(const MachineRegisterInfo &MRI, const MachineInstr &MI)
Definition: AMDGPULegalizerInfo.cpp:2748
llvm::AsmToken::Percent
@ Percent
Definition: MCAsmMacro.h:52
llvm::lltok::Kind
Kind
Definition: LLToken.h:18
X
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
llvm::MCInst::addOperand
void addOperand(const MCOperand Op)
Definition: MCInst.h:210
checkRegisterClass
static bool checkRegisterClass(unsigned RegNo, bool Data, bool Address, bool SP)
Definition: M68kAsmParser.cpp:380
Operands
mir Rename Register Operands
Definition: MIRNamerPass.cpp:78
llvm::cl::opt< bool >
llvm::ParseInstructionInfo
Definition: MCTargetAsmParser.h:113
LLVM_EXTERNAL_VISIBILITY
#define LLVM_EXTERNAL_VISIBILITY
Definition: Compiler.h:132
llvm::MCAsmLexer::getLoc
SMLoc getLoc() const
Get the current source location.
Definition: MCAsmLexer.cpp:23
Addr
uint64_t Addr
Definition: ELFObjHandler.cpp:80
llvm::MCAsmParserExtension::Initialize
virtual void Initialize(MCAsmParser &Parser)
Initialize the extension for parsing using the given Parser.
Definition: MCAsmParserExtension.cpp:19
llvm::MCStreamer::emitInstruction
virtual void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI)
Emit the given Instruction into the current section.
Definition: MCStreamer.cpp:1085
llvm::MatchOperand_ParseFail
@ MatchOperand_ParseFail
Definition: MCTargetAsmParser.h:124
LLVMInitializeM68kAsmParser
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeM68kAsmParser()
Definition: M68kAsmParser.cpp:206
llvm::cl::init
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:443
llvm::StringRef::lower
LLVM_NODISCARD std::string lower() const
Definition: StringRef.cpp:105
llvm::HighlightColor::Address
@ Address
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::ErrorInfo
Base class for user error types.
Definition: Error.h:349
llvm::MCTargetOptions
Definition: MCTargetOptions.h:36
isReg
static bool isReg(const MCInst &MI, unsigned OpNo)
Definition: MipsInstPrinter.cpp:31
llvm::AsmToken::Comma
@ Comma
Definition: MCAsmMacro.h:49
llvm::MatchOperand_NoMatch
@ MatchOperand_NoMatch
Definition: MCTargetAsmParser.h:123
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
llvm::MCAsmParser::getTok
const AsmToken & getTok() const
Get the current AsmToken from the stream.
Definition: MCAsmParser.cpp:38
llvm::AsmToken::Plus
@ Plus
Definition: MCAsmMacro.h:45
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:136
llvm::MCOperand::createReg
static MCOperand createReg(unsigned Reg)
Definition: MCInst.h:134
llvm::SystemZII::HasIndex
@ HasIndex
Definition: SystemZInstrInfo.h:39
llvm::AsmToken::RParen
@ RParen
Definition: MCAsmMacro.h:48
llvm::MCRegisterInfo
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
Definition: MCRegisterInfo.h:135
llvm::AsmToken::getString
StringRef getString() const
Get the string for the current token, this includes all characters (for example, the quotes on string...
Definition: MCAsmMacro.h:110
MRI
unsigned const MachineRegisterInfo * MRI
Definition: AArch64AdvSIMDScalarPass.cpp:105
llvm::OperandMatchResultTy
OperandMatchResultTy
Definition: MCTargetAsmParser.h:121
llvm::MCAsmParser::eatToEndOfStatement
virtual void eatToEndOfStatement()=0
Skip to the end of the current statement, for error recovery.
llvm::MCInstrInfo
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:25
llvm::GraphProgram::Name
Name
Definition: GraphWriter.h:52
llvm::MCInst::setLoc
void setLoc(SMLoc loc)
Definition: MCInst.h:203
llvm::AsmToken::Identifier
@ Identifier
Definition: MCAsmMacro.h:28
llvm::AsmToken::isNot
bool isNot(TokenKind K) const
Definition: MCAsmMacro.h:83
llvm::AMDGPU::SendMsg::Op
Op
Definition: SIDefines.h:314
M68kTargetInfo.h
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
llvm::MCTargetAsmParser
MCTargetAsmParser - Generic interface to target specific assembly parsers.
Definition: MCTargetAsmParser.h:309
llvm::codeview::ModifierOptions::Const
@ Const
Invalid
@ Invalid
Definition: AArch64ISelLowering.cpp:8134
llvm::MCAsmParser::getLexer
virtual MCAsmLexer & getLexer()=0
N
#define N
MCStreamer.h
llvm::cl::opt_storage::getValue
DataType & getValue()
Definition: CommandLine.h:1353
llvm::isMem
static bool isMem(const MachineInstr &MI, unsigned Op)
Definition: X86InstrInfo.h:123
M68kRegisterInfo.h
llvm::SmallVectorImpl
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: APFloat.h:43
llvm::cl::desc
Definition: CommandLine.h:414
llvm::AsmToken::Hash
@ Hash
Definition: MCAsmMacro.h:52
TargetRegistry.h
llvm::MCSubtargetInfo
Generic base class for all target subtargets.
Definition: MCSubtargetInfo.h:75
llvm::MCExpr
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:35
llvm::sampleprof::Base
@ Base
Definition: Discriminator.h:58
getReg
static unsigned getReg(const void *D, unsigned RC, unsigned RegNo)
Definition: MipsDisassembler.cpp:580