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