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