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"
11 #include "TargetInfo/M68kTargetInfo.h"
12
13 #include "llvm/MC/MCContext.h"
14 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
15 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
16 #include "llvm/MC/MCStreamer.h"
17 #include "llvm/Support/TargetRegistry.h"
18
19 #include <sstream>
20
21 #define DEBUG_TYPE "m68k-asm-parser"
22
23 using namespace llvm;
24
25 static cl::opt<bool> RegisterPrefixOptional(
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();
53 OperandMatchResultTy parseImm(OperandVector &Operands);
54 OperandMatchResultTy parseMemOp(OperandVector &Operands);
55
56 public:
M68kAsmParser(const MCSubtargetInfo & STI,MCAsmParser & Parser,const MCInstrInfo & MII,const MCTargetOptions & Options)57 M68kAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
58 const MCInstrInfo &MII, const MCTargetOptions &Options)
59 : MCTargetAsmParser(Options, STI, MII), STI(STI), Parser(Parser) {
60 MCAsmParserExtension::Initialize(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,
75 OperandVector &Operands, MCStreamer &Out,
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
M68kMemOp__anoned645c470111::M68kMemOp110 M68kMemOp() {}
M68kMemOp__anoned645c470111::M68kMemOp111 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 KindTy {
121 Invalid,
122 Token,
123 Imm,
124 MemOp,
125 };
126
127 KindTy 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:
M68kOperand(KindTy Kind,SMLoc Start,SMLoc End)137 M68kOperand(KindTy Kind, SMLoc Start, SMLoc End)
138 : Base(), Kind(Kind), Start(Start), End(End) {}
139
getStartLoc() const140 SMLoc getStartLoc() const override { return Start; }
getEndLoc() const141 SMLoc getEndLoc() const override { return End; }
142
143 void print(raw_ostream &OS) const override;
144
isMem() const145 bool isMem() const override { return false; }
isMemOp() const146 bool isMemOp() const { return Kind == KindTy::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
LLVMInitializeM68kAsmParser()206 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeM68kAsmParser() {
207 RegisterMCAsmParser<M68kAsmParser> X(getTheM68kTarget());
208 }
209
210 #define GET_MATCHER_IMPLEMENTATION
211 #include "M68kGenAsmMatcher.inc"
212
print(raw_ostream & OS) const213 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
addExpr(MCInst & Inst,const MCExpr * Expr)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
isReg() const250 bool M68kOperand::isReg() const {
251 return Kind == KindTy::MemOp && MemOp.Op == M68kMemOp::Kind::Reg;
252 }
253
getReg() const254 unsigned M68kOperand::getReg() const {
255 assert(isReg());
256 return MemOp.OuterReg;
257 }
258
addRegOperands(MCInst & Inst,unsigned N) const259 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
263 Inst.addOperand(MCOperand::createReg(getReg()));
264 }
265
createMemOp(M68kMemOp MemOp,SMLoc Start,SMLoc End)266 std::unique_ptr<M68kOperand> M68kOperand::createMemOp(M68kMemOp MemOp,
267 SMLoc Start, SMLoc End) {
268 auto Op = std::make_unique<M68kOperand>(KindTy::MemOp, Start, End);
269 Op->MemOp = MemOp;
270 return Op;
271 }
272
273 // Token
isToken() const274 bool M68kOperand::isToken() const { return Kind == KindTy::Token; }
getToken() const275 StringRef M68kOperand::getToken() const {
276 assert(isToken());
277 return Token;
278 }
279
createToken(StringRef Token,SMLoc Start,SMLoc End)280 std::unique_ptr<M68kOperand> M68kOperand::createToken(StringRef Token,
281 SMLoc Start, SMLoc End) {
282 auto Op = std::make_unique<M68kOperand>(KindTy::Token, Start, End);
283 Op->Token = Token;
284 return Op;
285 }
286
287 // Imm
isImm() const288 bool M68kOperand::isImm() const { return Kind == KindTy::Imm; }
addImmOperands(MCInst & Inst,unsigned N) const289 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
createImm(const MCExpr * Expr,SMLoc Start,SMLoc End)296 std::unique_ptr<M68kOperand> M68kOperand::createImm(const MCExpr *Expr,
297 SMLoc Start, SMLoc End) {
298 auto Op = std::make_unique<M68kOperand>(KindTy::Imm, Start, End);
299 Op->Expr = Expr;
300 return Op;
301 }
302
303 // Addr
isAddr() const304 bool M68kOperand::isAddr() const {
305 return isMemOp() && MemOp.Op == M68kMemOp::Kind::Addr;
306 }
addAddrOperands(MCInst & Inst,unsigned N) const307 void M68kOperand::addAddrOperands(MCInst &Inst, unsigned N) const {
308 M68kOperand::addExpr(Inst, MemOp.OuterDisp);
309 }
310
311 // ARI
isARI() const312 bool M68kOperand::isARI() const {
313 return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegIndirect &&
314 M68k::AR32RegClass.contains(MemOp.OuterReg);
315 }
addARIOperands(MCInst & Inst,unsigned N) const316 void M68kOperand::addARIOperands(MCInst &Inst, unsigned N) const {
317 Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));
318 }
319
320 // ARID
isARID() const321 bool M68kOperand::isARID() const {
322 return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacement &&
323 M68k::AR32RegClass.contains(MemOp.OuterReg);
324 }
addARIDOperands(MCInst & Inst,unsigned N) const325 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
isARII() const331 bool M68kOperand::isARII() const {
332 return isMemOp() &&
333 MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacementIndex &&
334 M68k::AR32RegClass.contains(MemOp.OuterReg);
335 }
addARIIOperands(MCInst & Inst,unsigned N) const336 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
isARIPD() const343 bool M68kOperand::isARIPD() const {
344 return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegPreDecrement &&
345 M68k::AR32RegClass.contains(MemOp.OuterReg);
346 }
addARIPDOperands(MCInst & Inst,unsigned N) const347 void M68kOperand::addARIPDOperands(MCInst &Inst, unsigned N) const {
348 Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));
349 }
350
351 // ARIPI
isARIPI() const352 bool M68kOperand::isARIPI() const {
353 return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegPostIncrement &&
354 M68k::AR32RegClass.contains(MemOp.OuterReg);
355 }
addARIPIOperands(MCInst & Inst,unsigned N) const356 void M68kOperand::addARIPIOperands(MCInst &Inst, unsigned N) const {
357 Inst.addOperand(MCOperand::createReg(MemOp.OuterReg));
358 }
359
360 // PCD
isPCD() const361 bool M68kOperand::isPCD() const {
362 return isMemOp() && MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacement &&
363 MemOp.OuterReg == M68k::PC;
364 }
addPCDOperands(MCInst & Inst,unsigned N) const365 void M68kOperand::addPCDOperands(MCInst &Inst, unsigned N) const {
366 M68kOperand::addExpr(Inst, MemOp.OuterDisp);
367 }
368
369 // PCI
isPCI() const370 bool M68kOperand::isPCI() const {
371 return isMemOp() &&
372 MemOp.Op == M68kMemOp::Kind::RegIndirectDisplacementIndex &&
373 MemOp.OuterReg == M68k::PC;
374 }
addPCIOperands(MCInst & Inst,unsigned N) const375 void M68kOperand::addPCIOperands(MCInst &Inst, unsigned N) const {
376 M68kOperand::addExpr(Inst, MemOp.OuterDisp);
377 Inst.addOperand(MCOperand::createReg(MemOp.InnerReg));
378 }
379
checkRegisterClass(unsigned RegNo,bool Data,bool Address,bool SP)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
validateTargetOperandClass(MCParsedAsmOperand & Op,unsigned Kind)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
parseRegisterName(unsigned & RegNo,SMLoc Loc,StringRef RegisterName)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
parseRegister(unsigned & RegNo)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
ParseRegister(unsigned & RegNo,SMLoc & StartLoc,SMLoc & EndLoc)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
tryParseRegister(unsigned & RegNo,SMLoc & StartLoc,SMLoc & EndLoc)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
isExpr()583 bool M68kAsmParser::isExpr() {
584 switch (Parser.getTok().getKind()) {
585 case AsmToken::Identifier:
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
parseImm(OperandVector & Operands)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
parseMemOp(OperandVector & Operands)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) {
622 MemOp.Op = M68kMemOp::Kind::Reg;
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) {
646 MemOp.Op = M68kMemOp::Kind::Addr;
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)) {
668 MemOp.Op = M68kMemOp::Kind::Addr;
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
eatComma()746 void M68kAsmParser::eatComma() {
747 if (Parser.getTok().is(AsmToken::Comma)) {
748 Parser.Lex();
749 }
750 }
751
ParseInstruction(ParseInstructionInfo & Info,StringRef Name,SMLoc NameLoc,OperandVector & Operands)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
ParseDirective(AsmToken DirectiveID)781 bool M68kAsmParser::ParseDirective(AsmToken DirectiveID) { return true; }
782
invalidOperand(SMLoc const & Loc,OperandVector const & Operands,uint64_t const & ErrorInfo)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
missingFeature(llvm::SMLoc const & Loc,uint64_t const & ErrorInfo)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
emit(MCInst & Inst,SMLoc const & Loc,MCStreamer & Out) const812 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
MatchAndEmitInstruction(SMLoc Loc,unsigned & Opcode,OperandVector & Operands,MCStreamer & Out,uint64_t & ErrorInfo,bool MatchingInlineAsm)820 bool M68kAsmParser::MatchAndEmitInstruction(SMLoc Loc, unsigned &Opcode,
821 OperandVector &Operands,
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
print(raw_ostream & OS) const843 void M68kOperand::print(raw_ostream &OS) const {
844 switch (Kind) {
845 case KindTy::Invalid:
846 OS << "invalid";
847 break;
848
849 case KindTy::Token:
850 OS << "token '" << Token << "'";
851 break;
852
853 case KindTy::Imm:
854 OS << "immediate " << Imm;
855 break;
856
857 case KindTy::MemOp:
858 MemOp.print(OS);
859 break;
860 }
861 }
862