xref: /freebsd/contrib/llvm-project/llvm/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp (revision 734e82fe33aa764367791a7d603b383996c6b40b)
1 //===- MSP430AsmParser.cpp - Parse MSP430 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 "MSP430.h"
10 #include "MSP430RegisterInfo.h"
11 #include "MCTargetDesc/MSP430MCTargetDesc.h"
12 #include "TargetInfo/MSP430TargetInfo.h"
13 
14 #include "llvm/ADT/APInt.h"
15 #include "llvm/MC/MCContext.h"
16 #include "llvm/MC/MCExpr.h"
17 #include "llvm/MC/MCInst.h"
18 #include "llvm/MC/MCInstBuilder.h"
19 #include "llvm/MC/MCInstrInfo.h"
20 #include "llvm/MC/MCParser/MCAsmLexer.h"
21 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
22 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
23 #include "llvm/MC/MCStreamer.h"
24 #include "llvm/MC/MCSubtargetInfo.h"
25 #include "llvm/MC/MCSymbol.h"
26 #include "llvm/MC/MCValue.h"
27 #include "llvm/MC/TargetRegistry.h"
28 #include "llvm/Support/Debug.h"
29 #include "llvm/Support/MathExtras.h"
30 
31 #define DEBUG_TYPE "msp430-asm-parser"
32 
33 using namespace llvm;
34 
35 namespace {
36 
37 /// Parses MSP430 assembly from a stream.
38 class MSP430AsmParser : public MCTargetAsmParser {
39   const MCSubtargetInfo &STI;
40   MCAsmParser &Parser;
41   const MCRegisterInfo *MRI;
42 
43   bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
44                                OperandVector &Operands, MCStreamer &Out,
45                                uint64_t &ErrorInfo,
46                                bool MatchingInlineAsm) override;
47 
48   bool parseRegister(MCRegister &RegNo, SMLoc &StartLoc,
49                      SMLoc &EndLoc) override;
50   OperandMatchResultTy tryParseRegister(MCRegister &RegNo, SMLoc &StartLoc,
51                                         SMLoc &EndLoc) override;
52 
53   bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
54                         SMLoc NameLoc, OperandVector &Operands) override;
55 
56   bool ParseDirective(AsmToken DirectiveID) override;
57   bool ParseDirectiveRefSym(AsmToken DirectiveID);
58 
59   unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
60                                       unsigned Kind) override;
61 
62   bool parseJccInstruction(ParseInstructionInfo &Info, StringRef Name,
63                            SMLoc NameLoc, OperandVector &Operands);
64 
65   bool ParseOperand(OperandVector &Operands);
66 
67   bool ParseLiteralValues(unsigned Size, SMLoc L);
68 
69   MCAsmParser &getParser() const { return Parser; }
70   MCAsmLexer &getLexer() const { return Parser.getLexer(); }
71 
72   /// @name Auto-generated Matcher Functions
73   /// {
74 
75 #define GET_ASSEMBLER_HEADER
76 #include "MSP430GenAsmMatcher.inc"
77 
78   /// }
79 
80 public:
81   MSP430AsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
82                   const MCInstrInfo &MII, const MCTargetOptions &Options)
83       : MCTargetAsmParser(Options, STI, MII), STI(STI), Parser(Parser) {
84     MCAsmParserExtension::Initialize(Parser);
85     MRI = getContext().getRegisterInfo();
86 
87     setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
88   }
89 };
90 
91 /// A parsed MSP430 assembly operand.
92 class MSP430Operand : public MCParsedAsmOperand {
93   typedef MCParsedAsmOperand Base;
94 
95   enum KindTy {
96     k_Imm,
97     k_Reg,
98     k_Tok,
99     k_Mem,
100     k_IndReg,
101     k_PostIndReg
102   } Kind;
103 
104   struct Memory {
105     unsigned Reg;
106     const MCExpr *Offset;
107   };
108   union {
109     const MCExpr *Imm;
110     unsigned      Reg;
111     StringRef     Tok;
112     Memory        Mem;
113   };
114 
115   SMLoc Start, End;
116 
117 public:
118   MSP430Operand(StringRef Tok, SMLoc const &S)
119       : Kind(k_Tok), Tok(Tok), Start(S), End(S) {}
120   MSP430Operand(KindTy Kind, unsigned Reg, SMLoc const &S, SMLoc const &E)
121       : Kind(Kind), Reg(Reg), Start(S), End(E) {}
122   MSP430Operand(MCExpr const *Imm, SMLoc const &S, SMLoc const &E)
123       : Kind(k_Imm), Imm(Imm), Start(S), End(E) {}
124   MSP430Operand(unsigned Reg, MCExpr const *Expr, SMLoc const &S,
125                 SMLoc const &E)
126       : Kind(k_Mem), Mem({Reg, Expr}), Start(S), End(E) {}
127 
128   void addRegOperands(MCInst &Inst, unsigned N) const {
129     assert((Kind == k_Reg || Kind == k_IndReg || Kind == k_PostIndReg) &&
130         "Unexpected operand kind");
131     assert(N == 1 && "Invalid number of operands!");
132 
133     Inst.addOperand(MCOperand::createReg(Reg));
134   }
135 
136   void addExprOperand(MCInst &Inst, const MCExpr *Expr) const {
137     // Add as immediate when possible
138     if (!Expr)
139       Inst.addOperand(MCOperand::createImm(0));
140     else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
141       Inst.addOperand(MCOperand::createImm(CE->getValue()));
142     else
143       Inst.addOperand(MCOperand::createExpr(Expr));
144   }
145 
146   void addImmOperands(MCInst &Inst, unsigned N) const {
147     assert(Kind == k_Imm && "Unexpected operand kind");
148     assert(N == 1 && "Invalid number of operands!");
149 
150     addExprOperand(Inst, Imm);
151   }
152 
153   void addMemOperands(MCInst &Inst, unsigned N) const {
154     assert(Kind == k_Mem && "Unexpected operand kind");
155     assert(N == 2 && "Invalid number of operands");
156 
157     Inst.addOperand(MCOperand::createReg(Mem.Reg));
158     addExprOperand(Inst, Mem.Offset);
159   }
160 
161   bool isReg()   const override { return Kind == k_Reg; }
162   bool isImm()   const override { return Kind == k_Imm; }
163   bool isToken() const override { return Kind == k_Tok; }
164   bool isMem()   const override { return Kind == k_Mem; }
165   bool isIndReg()         const { return Kind == k_IndReg; }
166   bool isPostIndReg()     const { return Kind == k_PostIndReg; }
167 
168   bool isCGImm() const {
169     if (Kind != k_Imm)
170       return false;
171 
172     int64_t Val;
173     if (!Imm->evaluateAsAbsolute(Val))
174       return false;
175 
176     if (Val == 0 || Val == 1 || Val == 2 || Val == 4 || Val == 8 || Val == -1)
177       return true;
178 
179     return false;
180   }
181 
182   StringRef getToken() const {
183     assert(Kind == k_Tok && "Invalid access!");
184     return Tok;
185   }
186 
187   unsigned getReg() const override {
188     assert(Kind == k_Reg && "Invalid access!");
189     return Reg;
190   }
191 
192   void setReg(unsigned RegNo) {
193     assert(Kind == k_Reg && "Invalid access!");
194     Reg = RegNo;
195   }
196 
197   static std::unique_ptr<MSP430Operand> CreateToken(StringRef Str, SMLoc S) {
198     return std::make_unique<MSP430Operand>(Str, S);
199   }
200 
201   static std::unique_ptr<MSP430Operand> CreateReg(unsigned RegNum, SMLoc S,
202                                                   SMLoc E) {
203     return std::make_unique<MSP430Operand>(k_Reg, RegNum, S, E);
204   }
205 
206   static std::unique_ptr<MSP430Operand> CreateImm(const MCExpr *Val, SMLoc S,
207                                                   SMLoc E) {
208     return std::make_unique<MSP430Operand>(Val, S, E);
209   }
210 
211   static std::unique_ptr<MSP430Operand> CreateMem(unsigned RegNum,
212                                                   const MCExpr *Val,
213                                                   SMLoc S, SMLoc E) {
214     return std::make_unique<MSP430Operand>(RegNum, Val, S, E);
215   }
216 
217   static std::unique_ptr<MSP430Operand> CreateIndReg(unsigned RegNum, SMLoc S,
218                                                   SMLoc E) {
219     return std::make_unique<MSP430Operand>(k_IndReg, RegNum, S, E);
220   }
221 
222   static std::unique_ptr<MSP430Operand> CreatePostIndReg(unsigned RegNum, SMLoc S,
223                                                   SMLoc E) {
224     return std::make_unique<MSP430Operand>(k_PostIndReg, RegNum, S, E);
225   }
226 
227   SMLoc getStartLoc() const override { return Start; }
228   SMLoc getEndLoc() const override { return End; }
229 
230   void print(raw_ostream &O) const override {
231     switch (Kind) {
232     case k_Tok:
233       O << "Token " << Tok;
234       break;
235     case k_Reg:
236       O << "Register " << Reg;
237       break;
238     case k_Imm:
239       O << "Immediate " << *Imm;
240       break;
241     case k_Mem:
242       O << "Memory ";
243       O << *Mem.Offset << "(" << Reg << ")";
244       break;
245     case k_IndReg:
246       O << "RegInd " << Reg;
247       break;
248     case k_PostIndReg:
249       O << "PostInc " << Reg;
250       break;
251     }
252   }
253 };
254 } // end anonymous namespace
255 
256 bool MSP430AsmParser::MatchAndEmitInstruction(SMLoc Loc, unsigned &Opcode,
257                                               OperandVector &Operands,
258                                               MCStreamer &Out,
259                                               uint64_t &ErrorInfo,
260                                               bool MatchingInlineAsm) {
261   MCInst Inst;
262   unsigned MatchResult =
263       MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
264 
265   switch (MatchResult) {
266   case Match_Success:
267     Inst.setLoc(Loc);
268     Out.emitInstruction(Inst, STI);
269     return false;
270   case Match_MnemonicFail:
271     return Error(Loc, "invalid instruction mnemonic");
272   case Match_InvalidOperand: {
273     SMLoc ErrorLoc = Loc;
274     if (ErrorInfo != ~0U) {
275       if (ErrorInfo >= Operands.size())
276         return Error(ErrorLoc, "too few operands for instruction");
277 
278       ErrorLoc = ((MSP430Operand &)*Operands[ErrorInfo]).getStartLoc();
279       if (ErrorLoc == SMLoc())
280         ErrorLoc = Loc;
281     }
282     return Error(ErrorLoc, "invalid operand for instruction");
283   }
284   default:
285     return true;
286   }
287 }
288 
289 // Auto-generated by TableGen
290 static unsigned MatchRegisterName(StringRef Name);
291 static unsigned MatchRegisterAltName(StringRef Name);
292 
293 bool MSP430AsmParser::parseRegister(MCRegister &RegNo, SMLoc &StartLoc,
294                                     SMLoc &EndLoc) {
295   switch (tryParseRegister(RegNo, StartLoc, EndLoc)) {
296   case MatchOperand_ParseFail:
297     return Error(StartLoc, "invalid register name");
298   case MatchOperand_Success:
299     return false;
300   case MatchOperand_NoMatch:
301     return true;
302   }
303 
304   llvm_unreachable("unknown match result type");
305 }
306 
307 OperandMatchResultTy MSP430AsmParser::tryParseRegister(MCRegister &RegNo,
308                                                        SMLoc &StartLoc,
309                                                        SMLoc &EndLoc) {
310   if (getLexer().getKind() == AsmToken::Identifier) {
311     auto Name = getLexer().getTok().getIdentifier().lower();
312     RegNo = MatchRegisterName(Name);
313     if (RegNo == MSP430::NoRegister) {
314       RegNo = MatchRegisterAltName(Name);
315       if (RegNo == MSP430::NoRegister)
316         return MatchOperand_NoMatch;
317     }
318 
319     AsmToken const &T = getParser().getTok();
320     StartLoc = T.getLoc();
321     EndLoc = T.getEndLoc();
322     getLexer().Lex(); // eat register token
323 
324     return MatchOperand_Success;
325   }
326 
327   return MatchOperand_ParseFail;
328 }
329 
330 bool MSP430AsmParser::parseJccInstruction(ParseInstructionInfo &Info,
331                                           StringRef Name, SMLoc NameLoc,
332                                           OperandVector &Operands) {
333   if (!Name.startswith_insensitive("j"))
334     return true;
335 
336   auto CC = Name.drop_front().lower();
337   unsigned CondCode;
338   if (CC == "ne" || CC == "nz")
339     CondCode = MSP430CC::COND_NE;
340   else if (CC == "eq" || CC == "z")
341     CondCode = MSP430CC::COND_E;
342   else if (CC == "lo" || CC == "nc")
343     CondCode = MSP430CC::COND_LO;
344   else if (CC == "hs" || CC == "c")
345     CondCode = MSP430CC::COND_HS;
346   else if (CC == "n")
347     CondCode = MSP430CC::COND_N;
348   else if (CC == "ge")
349     CondCode = MSP430CC::COND_GE;
350   else if (CC == "l")
351     CondCode = MSP430CC::COND_L;
352   else if (CC == "mp")
353     CondCode = MSP430CC::COND_NONE;
354   else
355     return Error(NameLoc, "unknown instruction");
356 
357   if (CondCode == (unsigned)MSP430CC::COND_NONE)
358     Operands.push_back(MSP430Operand::CreateToken("jmp", NameLoc));
359   else {
360     Operands.push_back(MSP430Operand::CreateToken("j", NameLoc));
361     const MCExpr *CCode = MCConstantExpr::create(CondCode, getContext());
362     Operands.push_back(MSP430Operand::CreateImm(CCode, SMLoc(), SMLoc()));
363   }
364 
365   // Skip optional '$' sign.
366   if (getLexer().getKind() == AsmToken::Dollar)
367     getLexer().Lex(); // Eat '$'
368 
369   const MCExpr *Val;
370   SMLoc ExprLoc = getLexer().getLoc();
371   if (getParser().parseExpression(Val))
372     return Error(ExprLoc, "expected expression operand");
373 
374   int64_t Res;
375   if (Val->evaluateAsAbsolute(Res))
376     if (Res < -512 || Res > 511)
377       return Error(ExprLoc, "invalid jump offset");
378 
379   Operands.push_back(MSP430Operand::CreateImm(Val, ExprLoc,
380     getLexer().getLoc()));
381 
382   if (getLexer().isNot(AsmToken::EndOfStatement)) {
383     SMLoc Loc = getLexer().getLoc();
384     getParser().eatToEndOfStatement();
385     return Error(Loc, "unexpected token");
386   }
387 
388   getParser().Lex(); // Consume the EndOfStatement.
389   return false;
390 }
391 
392 bool MSP430AsmParser::ParseInstruction(ParseInstructionInfo &Info,
393                                        StringRef Name, SMLoc NameLoc,
394                                        OperandVector &Operands) {
395   // Drop .w suffix
396   if (Name.endswith_insensitive(".w"))
397     Name = Name.drop_back(2);
398 
399   if (!parseJccInstruction(Info, Name, NameLoc, Operands))
400     return false;
401 
402   // First operand is instruction mnemonic
403   Operands.push_back(MSP430Operand::CreateToken(Name, NameLoc));
404 
405   // If there are no more operands, then finish
406   if (getLexer().is(AsmToken::EndOfStatement))
407     return false;
408 
409   // Parse first operand
410   if (ParseOperand(Operands))
411     return true;
412 
413   // Parse second operand if any
414   if (getLexer().is(AsmToken::Comma)) {
415     getLexer().Lex(); // Eat ','
416     if (ParseOperand(Operands))
417       return true;
418   }
419 
420   if (getLexer().isNot(AsmToken::EndOfStatement)) {
421     SMLoc Loc = getLexer().getLoc();
422     getParser().eatToEndOfStatement();
423     return Error(Loc, "unexpected token");
424   }
425 
426   getParser().Lex(); // Consume the EndOfStatement.
427   return false;
428 }
429 
430 bool MSP430AsmParser::ParseDirectiveRefSym(AsmToken DirectiveID) {
431     StringRef Name;
432     if (getParser().parseIdentifier(Name))
433       return TokError("expected identifier in directive");
434 
435     MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
436     getStreamer().emitSymbolAttribute(Sym, MCSA_Global);
437     return false;
438 }
439 
440 bool MSP430AsmParser::ParseDirective(AsmToken DirectiveID) {
441   StringRef IDVal = DirectiveID.getIdentifier();
442   if (IDVal.lower() == ".long") {
443     ParseLiteralValues(4, DirectiveID.getLoc());
444   } else if (IDVal.lower() == ".word" || IDVal.lower() == ".short") {
445     ParseLiteralValues(2, DirectiveID.getLoc());
446   } else if (IDVal.lower() == ".byte") {
447     ParseLiteralValues(1, DirectiveID.getLoc());
448   } else if (IDVal.lower() == ".refsym") {
449     return ParseDirectiveRefSym(DirectiveID);
450   }
451   return true;
452 }
453 
454 bool MSP430AsmParser::ParseOperand(OperandVector &Operands) {
455   switch (getLexer().getKind()) {
456     default: return true;
457     case AsmToken::Identifier: {
458       // try rN
459       MCRegister RegNo;
460       SMLoc StartLoc, EndLoc;
461       if (!parseRegister(RegNo, StartLoc, EndLoc)) {
462         Operands.push_back(MSP430Operand::CreateReg(RegNo, StartLoc, EndLoc));
463         return false;
464       }
465       [[fallthrough]];
466     }
467     case AsmToken::Integer:
468     case AsmToken::Plus:
469     case AsmToken::Minus: {
470       SMLoc StartLoc = getParser().getTok().getLoc();
471       const MCExpr *Val;
472       // Try constexpr[(rN)]
473       if (!getParser().parseExpression(Val)) {
474         MCRegister RegNo = MSP430::PC;
475         SMLoc EndLoc = getParser().getTok().getLoc();
476         // Try (rN)
477         if (getLexer().getKind() == AsmToken::LParen) {
478           getLexer().Lex(); // Eat '('
479           SMLoc RegStartLoc;
480           if (parseRegister(RegNo, RegStartLoc, EndLoc))
481             return true;
482           if (getLexer().getKind() != AsmToken::RParen)
483             return true;
484           EndLoc = getParser().getTok().getEndLoc();
485           getLexer().Lex(); // Eat ')'
486         }
487         Operands.push_back(MSP430Operand::CreateMem(RegNo, Val, StartLoc,
488           EndLoc));
489         return false;
490       }
491       return true;
492     }
493     case AsmToken::Amp: {
494       // Try &constexpr
495       SMLoc StartLoc = getParser().getTok().getLoc();
496       getLexer().Lex(); // Eat '&'
497       const MCExpr *Val;
498       if (!getParser().parseExpression(Val)) {
499         SMLoc EndLoc = getParser().getTok().getLoc();
500         Operands.push_back(MSP430Operand::CreateMem(MSP430::SR, Val, StartLoc,
501           EndLoc));
502         return false;
503       }
504       return true;
505     }
506     case AsmToken::At: {
507       // Try @rN[+]
508       SMLoc StartLoc = getParser().getTok().getLoc();
509       getLexer().Lex(); // Eat '@'
510       MCRegister RegNo;
511       SMLoc RegStartLoc, EndLoc;
512       if (parseRegister(RegNo, RegStartLoc, EndLoc))
513         return true;
514       if (getLexer().getKind() == AsmToken::Plus) {
515         Operands.push_back(MSP430Operand::CreatePostIndReg(RegNo, StartLoc, EndLoc));
516         getLexer().Lex(); // Eat '+'
517         return false;
518       }
519       if (Operands.size() > 1) // Emulate @rd in destination position as 0(rd)
520         Operands.push_back(MSP430Operand::CreateMem(RegNo,
521             MCConstantExpr::create(0, getContext()), StartLoc, EndLoc));
522       else
523         Operands.push_back(MSP430Operand::CreateIndReg(RegNo, StartLoc, EndLoc));
524       return false;
525     }
526     case AsmToken::Hash:
527       // Try #constexpr
528       SMLoc StartLoc = getParser().getTok().getLoc();
529       getLexer().Lex(); // Eat '#'
530       const MCExpr *Val;
531       if (!getParser().parseExpression(Val)) {
532         SMLoc EndLoc = getParser().getTok().getLoc();
533         Operands.push_back(MSP430Operand::CreateImm(Val, StartLoc, EndLoc));
534         return false;
535       }
536       return true;
537   }
538 }
539 
540 bool MSP430AsmParser::ParseLiteralValues(unsigned Size, SMLoc L) {
541   auto parseOne = [&]() -> bool {
542     const MCExpr *Value;
543     if (getParser().parseExpression(Value))
544       return true;
545     getParser().getStreamer().emitValue(Value, Size, L);
546     return false;
547   };
548   return (parseMany(parseOne));
549 }
550 
551 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeMSP430AsmParser() {
552   RegisterMCAsmParser<MSP430AsmParser> X(getTheMSP430Target());
553 }
554 
555 #define GET_REGISTER_MATCHER
556 #define GET_MATCHER_IMPLEMENTATION
557 #include "MSP430GenAsmMatcher.inc"
558 
559 static unsigned convertGR16ToGR8(unsigned Reg) {
560   switch (Reg) {
561   default:
562     llvm_unreachable("Unknown GR16 register");
563   case MSP430::PC:  return MSP430::PCB;
564   case MSP430::SP:  return MSP430::SPB;
565   case MSP430::SR:  return MSP430::SRB;
566   case MSP430::CG:  return MSP430::CGB;
567   case MSP430::R4:  return MSP430::R4B;
568   case MSP430::R5:  return MSP430::R5B;
569   case MSP430::R6:  return MSP430::R6B;
570   case MSP430::R7:  return MSP430::R7B;
571   case MSP430::R8:  return MSP430::R8B;
572   case MSP430::R9:  return MSP430::R9B;
573   case MSP430::R10: return MSP430::R10B;
574   case MSP430::R11: return MSP430::R11B;
575   case MSP430::R12: return MSP430::R12B;
576   case MSP430::R13: return MSP430::R13B;
577   case MSP430::R14: return MSP430::R14B;
578   case MSP430::R15: return MSP430::R15B;
579   }
580 }
581 
582 unsigned MSP430AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
583                                                      unsigned Kind) {
584   MSP430Operand &Op = static_cast<MSP430Operand &>(AsmOp);
585 
586   if (!Op.isReg())
587     return Match_InvalidOperand;
588 
589   unsigned Reg = Op.getReg();
590   bool isGR16 =
591       MSP430MCRegisterClasses[MSP430::GR16RegClassID].contains(Reg);
592 
593   if (isGR16 && (Kind == MCK_GR8)) {
594     Op.setReg(convertGR16ToGR8(Reg));
595     return Match_Success;
596   }
597 
598   return Match_InvalidOperand;
599 }
600