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