LLVM  15.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"
17 #include "llvm/MC/MCStreamer.h"
18 #include "llvm/MC/TargetRegistry.h"
19 
20 #include <sstream>
21 
22 #define DEBUG_TYPE "m68k-asm-parser"
23 
24 using namespace llvm;
25 
27  "m68k-register-prefix-optional", cl::Hidden,
28  cl::desc("Enable specifying registers without the % prefix"),
29  cl::init(false));
30 
31 namespace {
32 /// Parses M68k assembly from a stream.
33 class M68kAsmParser : public MCTargetAsmParser {
34  const MCSubtargetInfo &STI;
35  MCAsmParser &Parser;
36  const MCRegisterInfo *MRI;
37 
38 #define GET_ASSEMBLER_HEADER
39 #include "M68kGenAsmMatcher.inc"
40 
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(unsigned int &RegNo, SMLoc Loc,
47  StringRef RegisterName);
48  OperandMatchResultTy parseRegister(unsigned int &RegNo);
49 
50  // Parser functions.
51  void eatComma();
52 
53  bool isExpr();
56  OperandMatchResultTy parseRegOrMoveMask(OperandVector &Operands);
57 
58 public:
59  M68kAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
60  const MCInstrInfo &MII, const MCTargetOptions &Options)
61  : MCTargetAsmParser(Options, STI, MII), STI(STI), Parser(Parser) {
63  MRI = getContext().getRegisterInfo();
64 
65  setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
66  }
67 
68  unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
69  unsigned Kind) override;
70  bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
71  OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc,
72  SMLoc &EndLoc) override;
73  bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
74  SMLoc NameLoc, OperandVector &Operands) override;
75  bool ParseDirective(AsmToken DirectiveID) override;
76  bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
79  bool MatchingInlineAsm) override;
80 };
81 
82 struct M68kMemOp {
83  enum class Kind {
84  Addr,
85  RegMask,
86  Reg,
87  RegIndirect,
88  RegPostIncrement,
89  RegPreDecrement,
90  RegIndirectDisplacement,
91  RegIndirectDisplacementIndex,
92  };
93 
94  // These variables are used for the following forms:
95  // Addr: (OuterDisp)
96  // RegMask: RegMask (as register mask)
97  // Reg: %OuterReg
98  // RegIndirect: (%OuterReg)
99  // RegPostIncrement: (%OuterReg)+
100  // RegPreDecrement: -(%OuterReg)
101  // RegIndirectDisplacement: OuterDisp(%OuterReg)
102  // RegIndirectDisplacementIndex:
103  // OuterDisp(%OuterReg, %InnerReg.Size * Scale, InnerDisp)
104 
105  Kind Op;
106  unsigned OuterReg;
107  unsigned InnerReg;
108  const MCExpr *OuterDisp;
109  const MCExpr *InnerDisp;
110  uint8_t Size : 4;
111  uint8_t Scale : 4;
112  const MCExpr *Expr;
113  uint16_t RegMask;
114 
115  M68kMemOp() {}
116  M68kMemOp(Kind Op) : Op(Op) {}
117 
118  void print(raw_ostream &OS) const;
119 };
120 
121 /// An parsed M68k assembly operand.
122 class M68kOperand : public MCParsedAsmOperand {
123  typedef MCParsedAsmOperand Base;
124 
125  enum class KindTy {
126  Invalid,
127  Token,
128  Imm,
129  MemOp,
130  };
131 
132  KindTy Kind;
133  SMLoc Start, End;
134  union {
135  StringRef Token;
136  int64_t Imm;
137  const MCExpr *Expr;
138  M68kMemOp MemOp;
139  };
140 
141  template <unsigned N> bool isAddrN() const;
142 
143 public:
144  M68kOperand(KindTy Kind, SMLoc Start, SMLoc End)
145  : Base(), Kind(Kind), Start(Start), End(End) {}
146 
147  SMLoc getStartLoc() const override { return Start; }
148  SMLoc getEndLoc() const override { return End; }
149 
150  void print(raw_ostream &OS) const override;
151 
152  bool isMem() const override { return false; }
153  bool isMemOp() const { return Kind == KindTy::MemOp; }
154 
155  static void addExpr(MCInst &Inst, const MCExpr *Expr);
156 
157  // Reg
158  bool isReg() const override;
159  bool isAReg() const;
160  bool isDReg() const;
161  unsigned getReg() const override;
162  void addRegOperands(MCInst &Inst, unsigned N) const;
163 
164  static std::unique_ptr<M68kOperand> createMemOp(M68kMemOp MemOp, SMLoc Start,
165  SMLoc End);
166 
167  // Token
168  bool isToken() const override;
169  StringRef getToken() const;
170  static std::unique_ptr<M68kOperand> createToken(StringRef Token, SMLoc Start,
171  SMLoc End);
172 
173  // Imm
174  bool isImm() const override;
175  void addImmOperands(MCInst &Inst, unsigned N) const;
176 
177  static std::unique_ptr<M68kOperand> createImm(const MCExpr *Expr, SMLoc Start,
178  SMLoc End);
179 
180  // MoveMask
181  bool isMoveMask() const;
182  void addMoveMaskOperands(MCInst &Inst, unsigned N) const;
183 
184  // Addr
185  bool isAddr() const;
186  bool isAddr8() const { return isAddrN<8>(); }
187  bool isAddr16() const { return isAddrN<16>(); }
188  bool isAddr32() const { return isAddrN<32>(); }
189  void addAddrOperands(MCInst &Inst, unsigned N) const;
190 
191  // ARI
192  bool isARI() const;
193  void addARIOperands(MCInst &Inst, unsigned N) const;
194 
195  // ARID
196  bool isARID() const;
197  void addARIDOperands(MCInst &Inst, unsigned N) const;
198 
199  // ARII
200  bool isARII() const;
201  void addARIIOperands(MCInst &Inst, unsigned N) const;
202 
203  // ARIPD
204  bool isARIPD() const;
205  void addARIPDOperands(MCInst &Inst, unsigned N) const;
206 
207  // ARIPI
208  bool isARIPI() const;
209  void addARIPIOperands(MCInst &Inst, unsigned N) const;
210 
211  // PCD
212  bool isPCD() const;
213  void addPCDOperands(MCInst &Inst, unsigned N) const;
214 
215  // PCI
216  bool isPCI() const;
217  void addPCIOperands(MCInst &Inst, unsigned N) const;
218 };
219 
220 } // end anonymous namespace.
221 
224 }
225 
226 #define GET_MATCHER_IMPLEMENTATION
227 #include "M68kGenAsmMatcher.inc"
228 
229 static inline unsigned getRegisterByIndex(unsigned RegisterIndex) {
230  static unsigned RegistersByIndex[] = {
231  M68k::D0, M68k::D1, M68k::D2, M68k::D3, M68k::D4, M68k::D5,
232  M68k::D6, M68k::D7, M68k::A0, M68k::A1, M68k::A2, M68k::A3,
233  M68k::A4, M68k::A5, M68k::A6, M68k::SP,
234  };
235  assert(RegisterIndex <=
236  sizeof(RegistersByIndex) / sizeof(RegistersByIndex[0]));
237  return RegistersByIndex[RegisterIndex];
238 }
239 
240 static inline unsigned getRegisterIndex(unsigned Register) {
241  if (Register >= M68k::D0 && Register <= M68k::D7)
242  return Register - M68k::D0;
243  if (Register >= M68k::A0 && Register <= M68k::A6)
244  return Register - M68k::A0 + 8;
245 
246  switch (Register) {
247  case M68k::SP:
248  // SP is sadly not contiguous with the rest of the An registers
249  return 15;
250 
251  case M68k::PC:
252  case M68k::CCR:
253  return 16;
254 
255  default:
256  llvm_unreachable("unexpected register number");
257  }
258 }
259 
260 void M68kMemOp::print(raw_ostream &OS) const {
261  switch (Op) {
262  case Kind::Addr:
263  OS << OuterDisp;
264  break;
265  case Kind::RegMask:
266  OS << "RegMask(" << format("%04x", RegMask) << ")";
267  break;
268  case Kind::Reg:
269  OS << '%' << OuterReg;
270  break;
271  case Kind::RegIndirect:
272  OS << "(%" << OuterReg << ')';
273  break;
274  case Kind::RegPostIncrement:
275  OS << "(%" << OuterReg << ")+";
276  break;
277  case Kind::RegPreDecrement:
278  OS << "-(%" << OuterReg << ")";
279  break;
280  case Kind::RegIndirectDisplacement:
281  OS << OuterDisp << "(%" << OuterReg << ")";
282  break;
283  case Kind::RegIndirectDisplacementIndex:
284  OS << OuterDisp << "(%" << OuterReg << ", " << InnerReg << "." << Size
285  << ", " << InnerDisp << ")";
286  break;
287  }
288 }
289 
290 void M68kOperand::addExpr(MCInst &Inst, const MCExpr *Expr) {
291  if (auto Const = dyn_cast<MCConstantExpr>(Expr)) {
292  Inst.addOperand(MCOperand::createImm(Const->getValue()));
293  return;
294  }
295 
296  Inst.addOperand(MCOperand::createExpr(Expr));
297 }
298 
299 // Reg
300 bool M68kOperand::isReg() const {
301  return Kind == KindTy::MemOp && MemOp.Op == M68kMemOp::Kind::Reg;
302 }
303 
304 unsigned M68kOperand::getReg() const {
305  assert(isReg());
306  return MemOp.OuterReg;
307 }
308 
309 void M68kOperand::addRegOperands(MCInst &Inst, unsigned N) const {
310  assert(isReg() && "wrong operand kind");
311  assert((N == 1) && "can only handle one register operand");
312 
314 }
315 
316 std::unique_ptr<M68kOperand> M68kOperand::createMemOp(M68kMemOp MemOp,
317  SMLoc Start, SMLoc End) {
318  auto Op = std::make_unique<M68kOperand>(KindTy::MemOp, Start, End);
319  Op->MemOp = MemOp;
320  return Op;
321 }
322 
323 // Token
324 bool M68kOperand::isToken() const { return Kind == KindTy::Token; }
325 StringRef M68kOperand::getToken() const {
326  assert(isToken());
327  return Token;
328 }
329 
330 std::unique_ptr<M68kOperand> M68kOperand::createToken(StringRef Token,
331  SMLoc Start, SMLoc End) {
332  auto Op = std::make_unique<M68kOperand>(KindTy::Token, Start, End);
333  Op->Token = Token;
334  return Op;
335 }
336 
337 // Imm
338 bool M68kOperand::isImm() const { return Kind == KindTy::Imm; }
339 void M68kOperand::addImmOperands(MCInst &Inst, unsigned N) const {
340  assert(isImm() && "wrong operand kind");
341  assert((N == 1) && "can only handle one register operand");
342 
343  M68kOperand::addExpr(Inst, Expr);
344 }
345 
346 std::unique_ptr<M68kOperand> M68kOperand::createImm(const MCExpr *Expr,
347  SMLoc Start, SMLoc End) {
348  auto Op = std::make_unique<M68kOperand>(KindTy::Imm, Start, End);
349  Op->Expr = Expr;
350  return Op;
351 }
352 
353 // MoveMask
354 bool M68kOperand::isMoveMask() const {
355  if (!isMemOp())
356  return false;
357 
358  if (MemOp.Op == M68kMemOp::Kind::RegMask)
359  return true;
360 
361  if (MemOp.Op != M68kMemOp::Kind::Reg)
362  return false;
363 
364  // Only regular address / data registers are allowed to be used
365  // in register masks.
366  return getRegisterIndex(MemOp.OuterReg) < 16;
367 }
368 
369 void M68kOperand::addMoveMaskOperands(MCInst &Inst, unsigned N) const {
370  assert(isMoveMask() && "wrong operand kind");
371  assert((N == 1) && "can only handle one immediate operand");
372 
373  uint16_t MoveMask = MemOp.RegMask;
374  if (MemOp.Op == M68kMemOp::Kind::Reg)
375  MoveMask = 1 << getRegisterIndex(MemOp.OuterReg);
376 
377  Inst.addOperand(MCOperand::createImm(MoveMask));
378 }
379 
380 // Addr
381 bool M68kOperand::isAddr() const {
382  return isMemOp() && MemOp.Op == M68kMemOp::Kind::Addr;
383 }
384 // TODO: Maybe we can also store the size of OuterDisp
385 // in Size?
386 template <unsigned N> bool M68kOperand::isAddrN() const {
387  if (isAddr()) {
388  int64_t Res;
389  if (MemOp.OuterDisp->evaluateAsAbsolute(Res))
390  return isInt<N>(Res);
391  return true;
392  }
393  return false;
394 }
395 void M68kOperand::addAddrOperands(MCInst &Inst, unsigned N) const {
396  M68kOperand::addExpr(Inst, MemOp.OuterDisp);
397 }
398 
399 // ARI
400 bool M68kOperand::isARI() const {
401  return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegIndirect &&
402  M68k::AR32RegClass.contains(MemOp.OuterReg);
403 }
404 void M68kOperand::addARIOperands(MCInst &Inst, unsigned N) const {
405  Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));
406 }
407 
408 // ARID
409 bool M68kOperand::isARID() const {
410  return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacement &&
411  M68k::AR32RegClass.contains(MemOp.OuterReg);
412 }
413 void M68kOperand::addARIDOperands(MCInst &Inst, unsigned N) const {
414  M68kOperand::addExpr(Inst, MemOp.OuterDisp);
415  Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));
416 }
417 
418 // ARII
419 bool M68kOperand::isARII() const {
420  return isMemOp() &&
421  MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacementIndex &&
422  M68k::AR32RegClass.contains(MemOp.OuterReg);
423 }
424 void M68kOperand::addARIIOperands(MCInst &Inst, unsigned N) const {
425  M68kOperand::addExpr(Inst, MemOp.OuterDisp);
426  Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));
427  Inst.addOperand(MCOperand::createReg(MemOp.InnerReg));
428 }
429 
430 // ARIPD
431 bool M68kOperand::isARIPD() const {
432  return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegPreDecrement &&
433  M68k::AR32RegClass.contains(MemOp.OuterReg);
434 }
435 void M68kOperand::addARIPDOperands(MCInst &Inst, unsigned N) const {
436  Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));
437 }
438 
439 // ARIPI
440 bool M68kOperand::isARIPI() const {
441  return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegPostIncrement &&
442  M68k::AR32RegClass.contains(MemOp.OuterReg);
443 }
444 void M68kOperand::addARIPIOperands(MCInst &Inst, unsigned N) const {
445  Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));
446 }
447 
448 // PCD
449 bool M68kOperand::isPCD() const {
450  return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacement &&
451  MemOp.OuterReg == M68k::PC;
452 }
453 void M68kOperand::addPCDOperands(MCInst &Inst, unsigned N) const {
454  M68kOperand::addExpr(Inst, MemOp.OuterDisp);
455 }
456 
457 // PCI
458 bool M68kOperand::isPCI() const {
459  return isMemOp() &&
460  MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacementIndex &&
461  MemOp.OuterReg == M68k::PC;
462 }
463 void M68kOperand::addPCIOperands(MCInst &Inst, unsigned N) const {
464  M68kOperand::addExpr(Inst, MemOp.OuterDisp);
465  Inst.addOperand(MCOperand::createReg(MemOp.InnerReg));
466 }
467 
468 static inline bool checkRegisterClass(unsigned RegNo, bool Data, bool Address,
469  bool SP) {
470  switch (RegNo) {
471  case M68k::A0:
472  case M68k::A1:
473  case M68k::A2:
474  case M68k::A3:
475  case M68k::A4:
476  case M68k::A5:
477  case M68k::A6:
478  return Address;
479 
480  case M68k::SP:
481  return SP;
482 
483  case M68k::D0:
484  case M68k::D1:
485  case M68k::D2:
486  case M68k::D3:
487  case M68k::D4:
488  case M68k::D5:
489  case M68k::D6:
490  case M68k::D7:
491  return Data;
492 
493  case M68k::SR:
494  case M68k::CCR:
495  return false;
496 
497  default:
498  llvm_unreachable("unexpected register type");
499  return false;
500  }
501 }
502 
503 bool M68kOperand::isAReg() const {
504  return isReg() && checkRegisterClass(getReg(),
505  /*Data=*/false,
506  /*Address=*/true, /*SP=*/true);
507 }
508 
509 bool M68kOperand::isDReg() const {
510  return isReg() && checkRegisterClass(getReg(),
511  /*Data=*/true,
512  /*Address=*/false, /*SP=*/false);
513 }
514 
515 unsigned M68kAsmParser::validateTargetOperandClass(MCParsedAsmOperand &Op,
516  unsigned Kind) {
517  M68kOperand &Operand = (M68kOperand &)Op;
518 
519  switch (Kind) {
520  case MCK_XR16:
521  case MCK_SPILL:
522  if (Operand.isReg() &&
523  checkRegisterClass(Operand.getReg(), true, true, true)) {
524  return Match_Success;
525  }
526  break;
527 
528  case MCK_AR16:
529  case MCK_AR32:
530  if (Operand.isReg() &&
531  checkRegisterClass(Operand.getReg(), false, true, true)) {
532  return Match_Success;
533  }
534  break;
535 
536  case MCK_AR32_NOSP:
537  if (Operand.isReg() &&
538  checkRegisterClass(Operand.getReg(), false, true, false)) {
539  return Match_Success;
540  }
541  break;
542 
543  case MCK_DR8:
544  case MCK_DR16:
545  case MCK_DR32:
546  if (Operand.isReg() &&
547  checkRegisterClass(Operand.getReg(), true, false, false)) {
548  return Match_Success;
549  }
550  break;
551 
552  case MCK_AR16_TC:
553  if (Operand.isReg() &&
554  ((Operand.getReg() == M68k::A0) || (Operand.getReg() == M68k::A1))) {
555  return Match_Success;
556  }
557  break;
558 
559  case MCK_DR16_TC:
560  if (Operand.isReg() &&
561  ((Operand.getReg() == M68k::D0) || (Operand.getReg() == M68k::D1))) {
562  return Match_Success;
563  }
564  break;
565 
566  case MCK_XR16_TC:
567  if (Operand.isReg() &&
568  ((Operand.getReg() == M68k::D0) || (Operand.getReg() == M68k::D1) ||
569  (Operand.getReg() == M68k::A0) || (Operand.getReg() == M68k::A1))) {
570  return Match_Success;
571  }
572  break;
573  }
574 
575  return Match_InvalidOperand;
576 }
577 
578 bool M68kAsmParser::parseRegisterName(unsigned &RegNo, SMLoc Loc,
579  StringRef RegisterName) {
580  auto RegisterNameLower = RegisterName.lower();
581 
582  // CCR register
583  if (RegisterNameLower == "ccr") {
584  RegNo = M68k::CCR;
585  return true;
586  }
587 
588  // Parse simple general-purpose registers.
589  if (RegisterNameLower.size() == 2) {
590 
591  switch (RegisterNameLower[0]) {
592  case 'd':
593  case 'a': {
594  if (isdigit(RegisterNameLower[1])) {
595  unsigned IndexOffset = (RegisterNameLower[0] == 'a') ? 8 : 0;
596  unsigned RegIndex = (unsigned)(RegisterNameLower[1] - '0');
597  if (RegIndex < 8) {
598  RegNo = getRegisterByIndex(IndexOffset + RegIndex);
599  return true;
600  }
601  }
602  break;
603  }
604 
605  case 's':
606  if (RegisterNameLower[1] == 'p') {
607  RegNo = M68k::SP;
608  return true;
609  } else if (RegisterNameLower[1] == 'r') {
610  RegNo = M68k::SR;
611  return true;
612  }
613  break;
614 
615  case 'p':
616  if (RegisterNameLower[1] == 'c') {
617  RegNo = M68k::PC;
618  return true;
619  }
620  break;
621  }
622  }
623 
624  return false;
625 }
626 
627 OperandMatchResultTy M68kAsmParser::parseRegister(unsigned &RegNo) {
628  bool HasPercent = false;
629  AsmToken PercentToken;
630 
631  LLVM_DEBUG(dbgs() << "parseRegister "; getTok().dump(dbgs()); dbgs() << "\n");
632 
633  if (getTok().is(AsmToken::Percent)) {
634  HasPercent = true;
635  PercentToken = Lex();
636  } else if (!RegisterPrefixOptional.getValue()) {
637  return MatchOperand_NoMatch;
638  }
639 
640  if (!Parser.getTok().is(AsmToken::Identifier)) {
641  if (HasPercent) {
642  getLexer().UnLex(PercentToken);
643  }
644  return MatchOperand_NoMatch;
645  }
646 
647  auto RegisterName = Parser.getTok().getString();
648  if (!parseRegisterName(RegNo, Parser.getLexer().getLoc(), RegisterName)) {
649  if (HasPercent) {
650  getLexer().UnLex(PercentToken);
651  }
652  return MatchOperand_NoMatch;
653  }
654 
655  Parser.Lex();
656  return MatchOperand_Success;
657 }
658 
659 bool M68kAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
660  SMLoc &EndLoc) {
661  auto Result = tryParseRegister(RegNo, StartLoc, EndLoc);
662  if (Result != MatchOperand_Success) {
663  return Error(StartLoc, "expected register");
664  }
665 
666  return false;
667 }
668 
669 OperandMatchResultTy M68kAsmParser::tryParseRegister(unsigned &RegNo,
670  SMLoc &StartLoc,
671  SMLoc &EndLoc) {
672  StartLoc = getLexer().getLoc();
673  auto Result = parseRegister(RegNo);
674  EndLoc = getLexer().getLoc();
675  return Result;
676 }
677 
678 bool M68kAsmParser::isExpr() {
679  switch (Parser.getTok().getKind()) {
681  case AsmToken::Integer:
682  return true;
683  case AsmToken::Minus:
684  return getLexer().peekTok().getKind() == AsmToken::Integer;
685 
686  default:
687  return false;
688  }
689 }
690 
691 OperandMatchResultTy M68kAsmParser::parseImm(OperandVector &Operands) {
692  if (getLexer().isNot(AsmToken::Hash)) {
693  return MatchOperand_NoMatch;
694  }
695  SMLoc Start = getLexer().getLoc();
696  Parser.Lex();
697 
698  SMLoc End;
699  const MCExpr *Expr;
700 
701  if (getParser().parseExpression(Expr, End)) {
702  return MatchOperand_ParseFail;
703  }
704 
705  Operands.push_back(M68kOperand::createImm(Expr, Start, End));
706  return MatchOperand_Success;
707 }
708 
709 OperandMatchResultTy M68kAsmParser::parseMemOp(OperandVector &Operands) {
710  SMLoc Start = getLexer().getLoc();
711  bool IsPD = false;
712  M68kMemOp MemOp;
713 
714  // Check for a plain register or register mask.
715  auto Result = parseRegOrMoveMask(Operands);
716  if (Result != llvm::MatchOperand_NoMatch) {
717  return Result;
718  }
719 
720  // Check for pre-decrement & outer displacement.
721  bool HasDisplacement = false;
722  if (getLexer().is(AsmToken::Minus)) {
723  IsPD = true;
724  Parser.Lex();
725  } else if (isExpr()) {
726  if (Parser.parseExpression(MemOp.OuterDisp)) {
727  return MatchOperand_ParseFail;
728  }
729  HasDisplacement = true;
730  }
731 
732  if (getLexer().isNot(AsmToken::LParen)) {
733  if (HasDisplacement) {
735  Operands.push_back(
736  M68kOperand::createMemOp(MemOp, Start, getLexer().getLoc()));
737  return MatchOperand_Success;
738  } else if (IsPD) {
739  Error(getLexer().getLoc(), "expected (");
740  return MatchOperand_ParseFail;
741  }
742 
743  return MatchOperand_NoMatch;
744  }
745  Parser.Lex();
746 
747  // Check for constant dereference & MIT-style displacement
748  if (!HasDisplacement && isExpr()) {
749  if (Parser.parseExpression(MemOp.OuterDisp)) {
750  return MatchOperand_ParseFail;
751  }
752  HasDisplacement = true;
753 
754  // If we're not followed by a comma, we're a constant dereference.
755  if (getLexer().isNot(AsmToken::Comma)) {
757  Operands.push_back(
758  M68kOperand::createMemOp(MemOp, Start, getLexer().getLoc()));
759  return MatchOperand_Success;
760  }
761 
762  Parser.Lex();
763  }
764 
765  Result = parseRegister(MemOp.OuterReg);
766  if (Result == MatchOperand_ParseFail) {
767  return MatchOperand_ParseFail;
768  }
769 
770  if (Result != MatchOperand_Success) {
771  Error(getLexer().getLoc(), "expected register");
772  return MatchOperand_ParseFail;
773  }
774 
775  // Check for Index.
776  bool HasIndex = false;
777  if (Parser.getTok().is(AsmToken::Comma)) {
778  Parser.Lex();
779 
780  Result = parseRegister(MemOp.InnerReg);
781  if (Result == MatchOperand_ParseFail) {
782  return Result;
783  }
784 
785  if (Result == MatchOperand_NoMatch) {
786  Error(getLexer().getLoc(), "expected register");
787  return MatchOperand_ParseFail;
788  }
789 
790  // TODO: parse size, scale and inner displacement.
791  MemOp.Size = 4;
792  MemOp.Scale = 1;
793  MemOp.InnerDisp = MCConstantExpr::create(0, Parser.getContext(), true, 4);
794  HasIndex = true;
795  }
796 
797  if (Parser.getTok().isNot(AsmToken::RParen)) {
798  Error(getLexer().getLoc(), "expected )");
799  return MatchOperand_ParseFail;
800  }
801  Parser.Lex();
802 
803  bool IsPI = false;
804  if (!IsPD && Parser.getTok().is(AsmToken::Plus)) {
805  Parser.Lex();
806  IsPI = true;
807  }
808 
809  SMLoc End = getLexer().getLoc();
810 
811  unsigned OpCount = IsPD + IsPI + (HasIndex || HasDisplacement);
812  if (OpCount > 1) {
813  Error(Start, "only one of post-increment, pre-decrement or displacement "
814  "can be used");
815  return MatchOperand_ParseFail;
816  }
817 
818  if (IsPD) {
819  MemOp.Op = M68kMemOp::Kind::RegPreDecrement;
820  } else if (IsPI) {
821  MemOp.Op = M68kMemOp::Kind::RegPostIncrement;
822  } else if (HasIndex) {
823  MemOp.Op = M68kMemOp::Kind::RegIndirectDisplacementIndex;
824  } else if (HasDisplacement) {
825  MemOp.Op = M68kMemOp::Kind::RegIndirectDisplacement;
826  } else {
827  MemOp.Op = M68kMemOp::Kind::RegIndirect;
828  }
829 
830  Operands.push_back(M68kOperand::createMemOp(MemOp, Start, End));
831  return MatchOperand_Success;
832 }
833 
835 M68kAsmParser::parseRegOrMoveMask(OperandVector &Operands) {
836  SMLoc Start = getLexer().getLoc();
837  M68kMemOp MemOp(M68kMemOp::Kind::RegMask);
838  MemOp.RegMask = 0;
839 
840  for (;;) {
841  bool IsFirstRegister =
842  (MemOp.Op == M68kMemOp::Kind::RegMask) && (MemOp.RegMask == 0);
843 
844  unsigned FirstRegister;
845  auto Result = parseRegister(FirstRegister);
846  if (IsFirstRegister && (Result == llvm::MatchOperand_NoMatch)) {
847  return MatchOperand_NoMatch;
848  }
849  if (Result != llvm::MatchOperand_Success) {
850  Error(getLexer().getLoc(), "expected start register");
851  return MatchOperand_ParseFail;
852  }
853 
854  unsigned LastRegister = FirstRegister;
855  if (getLexer().is(AsmToken::Minus)) {
856  getLexer().Lex();
857  Result = parseRegister(LastRegister);
858  if (Result != llvm::MatchOperand_Success) {
859  Error(getLexer().getLoc(), "expected end register");
860  return MatchOperand_ParseFail;
861  }
862  }
863 
864  unsigned FirstRegisterIndex = getRegisterIndex(FirstRegister);
865  unsigned LastRegisterIndex = getRegisterIndex(LastRegister);
866 
867  uint16_t NumNewBits = LastRegisterIndex - FirstRegisterIndex + 1;
868  uint16_t NewMaskBits = ((1 << NumNewBits) - 1) << FirstRegisterIndex;
869 
870  if (IsFirstRegister && (FirstRegister == LastRegister)) {
871  // First register range is a single register, simplify to just Reg
872  // so that it matches more operands.
874  MemOp.OuterReg = FirstRegister;
875  } else {
876  if (MemOp.Op == M68kMemOp::Kind::Reg) {
877  // This is the second register being specified - expand the Reg operand
878  // into a mask first.
879  MemOp.Op = M68kMemOp::Kind::RegMask;
880  MemOp.RegMask = 1 << getRegisterIndex(MemOp.OuterReg);
881 
882  if (MemOp.RegMask == 0) {
883  Error(getLexer().getLoc(),
884  "special registers cannot be used in register masks");
885  return MatchOperand_ParseFail;
886  }
887  }
888 
889  if ((FirstRegisterIndex >= 16) || (LastRegisterIndex >= 16)) {
890  Error(getLexer().getLoc(),
891  "special registers cannot be used in register masks");
892  return MatchOperand_ParseFail;
893  }
894 
895  if (NewMaskBits & MemOp.RegMask) {
896  Error(getLexer().getLoc(), "conflicting masked registers");
897  return MatchOperand_ParseFail;
898  }
899 
900  MemOp.RegMask |= NewMaskBits;
901  }
902 
903  if (getLexer().isNot(AsmToken::Slash)) {
904  break;
905  }
906 
907  getLexer().Lex();
908  }
909 
910  Operands.push_back(
911  M68kOperand::createMemOp(MemOp, Start, getLexer().getLoc()));
912  return MatchOperand_Success;
913 }
914 
915 void M68kAsmParser::eatComma() {
916  if (Parser.getTok().is(AsmToken::Comma)) {
917  Parser.Lex();
918  }
919 }
920 
921 bool M68kAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
922  SMLoc NameLoc, OperandVector &Operands) {
923  SMLoc Start = getLexer().getLoc();
924  Operands.push_back(M68kOperand::createToken(Name, Start, Start));
925 
926  bool First = true;
927  while (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
928  if (!First) {
929  eatComma();
930  } else {
931  First = false;
932  }
933 
934  auto MatchResult = MatchOperandParserImpl(Operands, Name);
935  if (MatchResult == MatchOperand_Success) {
936  continue;
937  }
938 
939  // Add custom operand formats here...
940  SMLoc Loc = getLexer().getLoc();
941  Parser.eatToEndOfStatement();
942  return Error(Loc, "unexpected token parsing operands");
943  }
944 
945  // Eat EndOfStatement.
946  Parser.Lex();
947  return false;
948 }
949 
950 bool M68kAsmParser::ParseDirective(AsmToken DirectiveID) { return true; }
951 
952 bool M68kAsmParser::invalidOperand(SMLoc const &Loc,
953  OperandVector const &Operands,
954  uint64_t const &ErrorInfo) {
955  SMLoc ErrorLoc = Loc;
956  char const *Diag = 0;
957 
958  if (ErrorInfo != ~0U) {
959  if (ErrorInfo >= Operands.size()) {
960  Diag = "too few operands for instruction.";
961  } else {
962  auto const &Op = (M68kOperand const &)*Operands[ErrorInfo];
963  if (Op.getStartLoc() != SMLoc()) {
964  ErrorLoc = Op.getStartLoc();
965  }
966  }
967  }
968 
969  if (!Diag) {
970  Diag = "invalid operand for instruction";
971  }
972 
973  return Error(ErrorLoc, Diag);
974 }
975 
976 bool M68kAsmParser::missingFeature(llvm::SMLoc const &Loc,
977  uint64_t const &ErrorInfo) {
978  return Error(Loc, "instruction requires a CPU feature not currently enabled");
979 }
980 
981 bool M68kAsmParser::emit(MCInst &Inst, SMLoc const &Loc,
982  MCStreamer &Out) const {
983  Inst.setLoc(Loc);
984  Out.emitInstruction(Inst, STI);
985 
986  return false;
987 }
988 
989 bool M68kAsmParser::MatchAndEmitInstruction(SMLoc Loc, unsigned &Opcode,
991  MCStreamer &Out,
993  bool MatchingInlineAsm) {
994  MCInst Inst;
995  unsigned MatchResult =
996  MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
997 
998  switch (MatchResult) {
999  case Match_Success:
1000  return emit(Inst, Loc, Out);
1001  case Match_MissingFeature:
1002  return missingFeature(Loc, ErrorInfo);
1003  case Match_InvalidOperand:
1004  return invalidOperand(Loc, Operands, ErrorInfo);
1005  case Match_MnemonicFail:
1006  return Error(Loc, "invalid instruction");
1007  default:
1008  return true;
1009  }
1010 }
1011 
1012 void M68kOperand::print(raw_ostream &OS) const {
1013  switch (Kind) {
1014  case KindTy::Invalid:
1015  OS << "invalid";
1016  break;
1017 
1018  case KindTy::Token:
1019  OS << "token '" << Token << "'";
1020  break;
1021 
1022  case KindTy::Imm:
1023  OS << "immediate " << Imm;
1024  break;
1025 
1026  case KindTy::MemOp:
1027  MemOp.print(OS);
1028  break;
1029  }
1030 }
llvm::Check::Size
@ Size
Definition: FileCheck.h:77
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
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:17
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:189
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::X86Disassembler::Reg
Reg
All possible values of the reg field in the ModR/M byte.
Definition: X86DisassemblerDecoder.h:462
llvm::MachO::Invalid
@ Invalid
Invalid file type.
Definition: InterfaceFile.h:55
llvm::cl::Hidden
@ Hidden
Definition: CommandLine.h:139
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:55
LLVM_DEBUG
#define LLVM_DEBUG(X)
Definition: Debug.h:101
llvm::AsmToken
Target independent representation for an assembler token.
Definition: MCAsmMacro.h:21
isImm
static bool isImm(const MachineOperand &MO, MachineRegisterInfo *MRI)
Definition: SPIRVInstructionSelector.cpp:982
llvm::SystemZII::HasIndex
@ HasIndex
Definition: SystemZInstrInfo.h:39
getRegisterByIndex
static unsigned getRegisterByIndex(unsigned RegisterIndex)
Definition: M68kAsmParser.cpp:229
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:212
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:1360
llvm::MatchOperand_Success
@ MatchOperand_Success
Definition: MCTargetAsmParser.h:127
llvm::SMLoc
Represents a location in source code.
Definition: SMLoc.h:23
getReg
static unsigned getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
Definition: MipsDisassembler.cpp:517
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:112
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:54
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:3219
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:468
Operands
mir Rename Register Operands
Definition: MIRNamerPass.cpp:74
llvm::cl::opt< bool >
MCAsmLexer.h
llvm::ParseInstructionInfo
Definition: MCTargetAsmParser.h:118
uint64_t
LLVM_EXTERNAL_VISIBILITY
#define LLVM_EXTERNAL_VISIBILITY
Definition: Compiler.h:126
llvm::MCAsmLexer::getLoc
SMLoc getLoc() const
Get the current source location.
Definition: MCAsmLexer.cpp:22
Addr
uint64_t Addr
Definition: ELFObjHandler.cpp:78
llvm::MCAsmParserExtension::Initialize
virtual void Initialize(MCAsmParser &Parser)
Initialize the extension for parsing using the given Parser.
Definition: MCAsmParserExtension.cpp:21
llvm::MCStreamer::emitInstruction
virtual void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI)
Emit the given Instruction into the current section.
Definition: MCStreamer.cpp:1096
llvm::MatchOperand_ParseFail
@ MatchOperand_ParseFail
Definition: MCTargetAsmParser.h:129
LLVMInitializeM68kAsmParser
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeM68kAsmParser()
Definition: M68kAsmParser.cpp:222
llvm::cl::init
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:432
llvm::StringRef::lower
LLVM_NODISCARD std::string lower() const
Definition: StringRef.cpp:112
llvm::AsmToken::Slash
@ Slash
Definition: MCAsmMacro.h:46
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::ErrorInfo
Base class for user error types.
Definition: Error.h:347
llvm::MCTargetOptions
Definition: MCTargetOptions.h:42
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:128
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:143
llvm::MCOperand::createReg
static MCOperand createReg(unsigned Reg)
Definition: MCInst.h:134
llvm::AsmToken::RParen
@ RParen
Definition: MCAsmMacro.h:48
llvm::format
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:124
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::Register
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
llvm::OperandMatchResultTy
OperandMatchResultTy
Definition: MCTargetAsmParser.h:126
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:26
llvm::GraphProgram::Name
Name
Definition: GraphWriter.h:50
llvm::MCInst::setLoc
void setLoc(SMLoc loc)
Definition: MCInst.h:203
llvm::AsmToken::Identifier
@ Identifier
Definition: MCAsmMacro.h:28
uint16_t
getRegisterIndex
static unsigned getRegisterIndex(unsigned Register)
Definition: M68kAsmParser.cpp:240
llvm::AsmToken::isNot
bool isNot(TokenKind K) const
Definition: MCAsmMacro.h:83
llvm::AMDGPU::SendMsg::Op
Op
Definition: SIDefines.h:348
M68kTargetInfo.h
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:155
llvm::MCTargetAsmParser
MCTargetAsmParser - Generic interface to target specific assembly parsers.
Definition: MCTargetAsmParser.h:314
llvm::codeview::ModifierOptions::Const
@ Const
llvm::RISCVMatInt::Imm
@ Imm
Definition: RISCVMatInt.h:23
Invalid
@ Invalid
Definition: AArch64ISelLowering.cpp:8909
llvm::MCAsmParser::getLexer
virtual MCAsmLexer & getLexer()=0
N
#define N
MCStreamer.h
llvm::cl::opt_storage::getValue
DataType & getValue()
Definition: CommandLine.h:1323
llvm::isMem
static bool isMem(const MachineInstr &MI, unsigned Op)
Definition: X86InstrInfo.h:131
M68kRegisterInfo.h
llvm::SmallVectorImpl
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: APFloat.h:42
llvm::cl::desc
Definition: CommandLine.h:405
llvm::AsmToken::Hash
@ Hash
Definition: MCAsmMacro.h:52
TargetRegistry.h
llvm::MCSubtargetInfo
Generic base class for all target subtargets.
Definition: MCSubtargetInfo.h:76
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