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