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