xref: /freebsd/contrib/llvm-project/llvm/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- MSP430AsmParser.cpp - Parse MSP430 assembly to MCInst instructions -===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "MSP430.h"
100b57cec5SDimitry Andric #include "MSP430RegisterInfo.h"
110b57cec5SDimitry Andric #include "MCTargetDesc/MSP430MCTargetDesc.h"
120b57cec5SDimitry Andric #include "TargetInfo/MSP430TargetInfo.h"
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "llvm/ADT/APInt.h"
150b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
160b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h"
170b57cec5SDimitry Andric #include "llvm/MC/MCInst.h"
180b57cec5SDimitry Andric #include "llvm/MC/MCInstBuilder.h"
1981ad6265SDimitry Andric #include "llvm/MC/MCInstrInfo.h"
200b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCAsmLexer.h"
210b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
220b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCTargetAsmParser.h"
230b57cec5SDimitry Andric #include "llvm/MC/MCStreamer.h"
240b57cec5SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
250b57cec5SDimitry Andric #include "llvm/MC/MCSymbol.h"
260b57cec5SDimitry Andric #include "llvm/MC/MCValue.h"
27349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h"
280b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
290b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h"
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric #define DEBUG_TYPE "msp430-asm-parser"
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric using namespace llvm;
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric namespace {
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric /// Parses MSP430 assembly from a stream.
380b57cec5SDimitry Andric class MSP430AsmParser : public MCTargetAsmParser {
390b57cec5SDimitry Andric   const MCSubtargetInfo &STI;
400b57cec5SDimitry Andric   MCAsmParser &Parser;
410b57cec5SDimitry Andric   const MCRegisterInfo *MRI;
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric   bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
440b57cec5SDimitry Andric                                OperandVector &Operands, MCStreamer &Out,
450b57cec5SDimitry Andric                                uint64_t &ErrorInfo,
460b57cec5SDimitry Andric                                bool MatchingInlineAsm) override;
470b57cec5SDimitry Andric 
485f757f3fSDimitry Andric   bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
495f757f3fSDimitry Andric   ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
505ffd83dbSDimitry Andric                                SMLoc &EndLoc) override;
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric   bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
530b57cec5SDimitry Andric                         SMLoc NameLoc, OperandVector &Operands) override;
540b57cec5SDimitry Andric 
5506c3fb27SDimitry Andric   ParseStatus parseDirective(AsmToken DirectiveID) override;
560b57cec5SDimitry Andric   bool ParseDirectiveRefSym(AsmToken DirectiveID);
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric   unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
590b57cec5SDimitry Andric                                       unsigned Kind) override;
600b57cec5SDimitry Andric 
610b57cec5SDimitry Andric   bool parseJccInstruction(ParseInstructionInfo &Info, StringRef Name,
620b57cec5SDimitry Andric                            SMLoc NameLoc, OperandVector &Operands);
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric   bool ParseOperand(OperandVector &Operands);
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric   bool ParseLiteralValues(unsigned Size, SMLoc L);
670b57cec5SDimitry Andric 
getParser() const680b57cec5SDimitry Andric   MCAsmParser &getParser() const { return Parser; }
getLexer() const690b57cec5SDimitry Andric   MCAsmLexer &getLexer() const { return Parser.getLexer(); }
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric   /// @name Auto-generated Matcher Functions
720b57cec5SDimitry Andric   /// {
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric #define GET_ASSEMBLER_HEADER
750b57cec5SDimitry Andric #include "MSP430GenAsmMatcher.inc"
760b57cec5SDimitry Andric 
770b57cec5SDimitry Andric   /// }
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric public:
MSP430AsmParser(const MCSubtargetInfo & STI,MCAsmParser & Parser,const MCInstrInfo & MII,const MCTargetOptions & Options)800b57cec5SDimitry Andric   MSP430AsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
810b57cec5SDimitry Andric                   const MCInstrInfo &MII, const MCTargetOptions &Options)
820b57cec5SDimitry Andric       : MCTargetAsmParser(Options, STI, MII), STI(STI), Parser(Parser) {
830b57cec5SDimitry Andric     MCAsmParserExtension::Initialize(Parser);
840b57cec5SDimitry Andric     MRI = getContext().getRegisterInfo();
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric     setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
870b57cec5SDimitry Andric   }
880b57cec5SDimitry Andric };
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric /// A parsed MSP430 assembly operand.
910b57cec5SDimitry Andric class MSP430Operand : public MCParsedAsmOperand {
920b57cec5SDimitry Andric   typedef MCParsedAsmOperand Base;
930b57cec5SDimitry Andric 
940b57cec5SDimitry Andric   enum KindTy {
950b57cec5SDimitry Andric     k_Imm,
960b57cec5SDimitry Andric     k_Reg,
970b57cec5SDimitry Andric     k_Tok,
980b57cec5SDimitry Andric     k_Mem,
990b57cec5SDimitry Andric     k_IndReg,
1000b57cec5SDimitry Andric     k_PostIndReg
1010b57cec5SDimitry Andric   } Kind;
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric   struct Memory {
1040b57cec5SDimitry Andric     unsigned Reg;
1050b57cec5SDimitry Andric     const MCExpr *Offset;
1060b57cec5SDimitry Andric   };
1070b57cec5SDimitry Andric   union {
1080b57cec5SDimitry Andric     const MCExpr *Imm;
1090b57cec5SDimitry Andric     unsigned      Reg;
1100b57cec5SDimitry Andric     StringRef     Tok;
1110b57cec5SDimitry Andric     Memory        Mem;
1120b57cec5SDimitry Andric   };
1130b57cec5SDimitry Andric 
1140b57cec5SDimitry Andric   SMLoc Start, End;
1150b57cec5SDimitry Andric 
1160b57cec5SDimitry Andric public:
MSP430Operand(StringRef Tok,SMLoc const & S)1170b57cec5SDimitry Andric   MSP430Operand(StringRef Tok, SMLoc const &S)
11804eeddc0SDimitry Andric       : Kind(k_Tok), Tok(Tok), Start(S), End(S) {}
MSP430Operand(KindTy Kind,unsigned Reg,SMLoc const & S,SMLoc const & E)1190b57cec5SDimitry Andric   MSP430Operand(KindTy Kind, unsigned Reg, SMLoc const &S, SMLoc const &E)
12004eeddc0SDimitry Andric       : Kind(Kind), Reg(Reg), Start(S), End(E) {}
MSP430Operand(MCExpr const * Imm,SMLoc const & S,SMLoc const & E)1210b57cec5SDimitry Andric   MSP430Operand(MCExpr const *Imm, SMLoc const &S, SMLoc const &E)
12204eeddc0SDimitry Andric       : Kind(k_Imm), Imm(Imm), Start(S), End(E) {}
MSP430Operand(unsigned Reg,MCExpr const * Expr,SMLoc const & S,SMLoc const & E)12304eeddc0SDimitry Andric   MSP430Operand(unsigned Reg, MCExpr const *Expr, SMLoc const &S,
12404eeddc0SDimitry Andric                 SMLoc const &E)
12504eeddc0SDimitry Andric       : Kind(k_Mem), Mem({Reg, Expr}), Start(S), End(E) {}
1260b57cec5SDimitry Andric 
addRegOperands(MCInst & Inst,unsigned N) const1270b57cec5SDimitry Andric   void addRegOperands(MCInst &Inst, unsigned N) const {
1280b57cec5SDimitry Andric     assert((Kind == k_Reg || Kind == k_IndReg || Kind == k_PostIndReg) &&
1290b57cec5SDimitry Andric         "Unexpected operand kind");
1300b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(Reg));
1330b57cec5SDimitry Andric   }
1340b57cec5SDimitry Andric 
addExprOperand(MCInst & Inst,const MCExpr * Expr) const1350b57cec5SDimitry Andric   void addExprOperand(MCInst &Inst, const MCExpr *Expr) const {
1360b57cec5SDimitry Andric     // Add as immediate when possible
1370b57cec5SDimitry Andric     if (!Expr)
1380b57cec5SDimitry Andric       Inst.addOperand(MCOperand::createImm(0));
1390b57cec5SDimitry Andric     else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
1400b57cec5SDimitry Andric       Inst.addOperand(MCOperand::createImm(CE->getValue()));
1410b57cec5SDimitry Andric     else
1420b57cec5SDimitry Andric       Inst.addOperand(MCOperand::createExpr(Expr));
1430b57cec5SDimitry Andric   }
1440b57cec5SDimitry Andric 
addImmOperands(MCInst & Inst,unsigned N) const1450b57cec5SDimitry Andric   void addImmOperands(MCInst &Inst, unsigned N) const {
1460b57cec5SDimitry Andric     assert(Kind == k_Imm && "Unexpected operand kind");
1470b57cec5SDimitry Andric     assert(N == 1 && "Invalid number of operands!");
1480b57cec5SDimitry Andric 
1490b57cec5SDimitry Andric     addExprOperand(Inst, Imm);
1500b57cec5SDimitry Andric   }
1510b57cec5SDimitry Andric 
addMemOperands(MCInst & Inst,unsigned N) const1520b57cec5SDimitry Andric   void addMemOperands(MCInst &Inst, unsigned N) const {
1530b57cec5SDimitry Andric     assert(Kind == k_Mem && "Unexpected operand kind");
1540b57cec5SDimitry Andric     assert(N == 2 && "Invalid number of operands");
1550b57cec5SDimitry Andric 
1560b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createReg(Mem.Reg));
1570b57cec5SDimitry Andric     addExprOperand(Inst, Mem.Offset);
1580b57cec5SDimitry Andric   }
1590b57cec5SDimitry Andric 
isReg() const1605ffd83dbSDimitry Andric   bool isReg()   const override { return Kind == k_Reg; }
isImm() const1615ffd83dbSDimitry Andric   bool isImm()   const override { return Kind == k_Imm; }
isToken() const1625ffd83dbSDimitry Andric   bool isToken() const override { return Kind == k_Tok; }
isMem() const1635ffd83dbSDimitry Andric   bool isMem()   const override { return Kind == k_Mem; }
isIndReg() const1640b57cec5SDimitry Andric   bool isIndReg()         const { return Kind == k_IndReg; }
isPostIndReg() const1650b57cec5SDimitry Andric   bool isPostIndReg()     const { return Kind == k_PostIndReg; }
1660b57cec5SDimitry Andric 
isCGImm() const1670b57cec5SDimitry Andric   bool isCGImm() const {
1680b57cec5SDimitry Andric     if (Kind != k_Imm)
1690b57cec5SDimitry Andric       return false;
1700b57cec5SDimitry Andric 
1710b57cec5SDimitry Andric     int64_t Val;
1720b57cec5SDimitry Andric     if (!Imm->evaluateAsAbsolute(Val))
1730b57cec5SDimitry Andric       return false;
1740b57cec5SDimitry Andric 
1750b57cec5SDimitry Andric     if (Val == 0 || Val == 1 || Val == 2 || Val == 4 || Val == 8 || Val == -1)
1760b57cec5SDimitry Andric       return true;
1770b57cec5SDimitry Andric 
1780b57cec5SDimitry Andric     return false;
1790b57cec5SDimitry Andric   }
1800b57cec5SDimitry Andric 
getToken() const1810b57cec5SDimitry Andric   StringRef getToken() const {
1820b57cec5SDimitry Andric     assert(Kind == k_Tok && "Invalid access!");
1830b57cec5SDimitry Andric     return Tok;
1840b57cec5SDimitry Andric   }
1850b57cec5SDimitry Andric 
getReg() const186*0fca6ea1SDimitry Andric   MCRegister getReg() const override {
1870b57cec5SDimitry Andric     assert(Kind == k_Reg && "Invalid access!");
1880b57cec5SDimitry Andric     return Reg;
1890b57cec5SDimitry Andric   }
1900b57cec5SDimitry Andric 
setReg(unsigned RegNo)1910b57cec5SDimitry Andric   void setReg(unsigned RegNo) {
1920b57cec5SDimitry Andric     assert(Kind == k_Reg && "Invalid access!");
1930b57cec5SDimitry Andric     Reg = RegNo;
1940b57cec5SDimitry Andric   }
1950b57cec5SDimitry Andric 
CreateToken(StringRef Str,SMLoc S)1960b57cec5SDimitry Andric   static std::unique_ptr<MSP430Operand> CreateToken(StringRef Str, SMLoc S) {
1978bcb0991SDimitry Andric     return std::make_unique<MSP430Operand>(Str, S);
1980b57cec5SDimitry Andric   }
1990b57cec5SDimitry Andric 
CreateReg(unsigned RegNum,SMLoc S,SMLoc E)2000b57cec5SDimitry Andric   static std::unique_ptr<MSP430Operand> CreateReg(unsigned RegNum, SMLoc S,
2010b57cec5SDimitry Andric                                                   SMLoc E) {
2028bcb0991SDimitry Andric     return std::make_unique<MSP430Operand>(k_Reg, RegNum, S, E);
2030b57cec5SDimitry Andric   }
2040b57cec5SDimitry Andric 
CreateImm(const MCExpr * Val,SMLoc S,SMLoc E)2050b57cec5SDimitry Andric   static std::unique_ptr<MSP430Operand> CreateImm(const MCExpr *Val, SMLoc S,
2060b57cec5SDimitry Andric                                                   SMLoc E) {
2078bcb0991SDimitry Andric     return std::make_unique<MSP430Operand>(Val, S, E);
2080b57cec5SDimitry Andric   }
2090b57cec5SDimitry Andric 
CreateMem(unsigned RegNum,const MCExpr * Val,SMLoc S,SMLoc E)2100b57cec5SDimitry Andric   static std::unique_ptr<MSP430Operand> CreateMem(unsigned RegNum,
2110b57cec5SDimitry Andric                                                   const MCExpr *Val,
2120b57cec5SDimitry Andric                                                   SMLoc S, SMLoc E) {
2138bcb0991SDimitry Andric     return std::make_unique<MSP430Operand>(RegNum, Val, S, E);
2140b57cec5SDimitry Andric   }
2150b57cec5SDimitry Andric 
CreateIndReg(unsigned RegNum,SMLoc S,SMLoc E)2160b57cec5SDimitry Andric   static std::unique_ptr<MSP430Operand> CreateIndReg(unsigned RegNum, SMLoc S,
2170b57cec5SDimitry Andric                                                   SMLoc E) {
2188bcb0991SDimitry Andric     return std::make_unique<MSP430Operand>(k_IndReg, RegNum, S, E);
2190b57cec5SDimitry Andric   }
2200b57cec5SDimitry Andric 
CreatePostIndReg(unsigned RegNum,SMLoc S,SMLoc E)2210b57cec5SDimitry Andric   static std::unique_ptr<MSP430Operand> CreatePostIndReg(unsigned RegNum, SMLoc S,
2220b57cec5SDimitry Andric                                                   SMLoc E) {
2238bcb0991SDimitry Andric     return std::make_unique<MSP430Operand>(k_PostIndReg, RegNum, S, E);
2240b57cec5SDimitry Andric   }
2250b57cec5SDimitry Andric 
getStartLoc() const2265ffd83dbSDimitry Andric   SMLoc getStartLoc() const override { return Start; }
getEndLoc() const2275ffd83dbSDimitry Andric   SMLoc getEndLoc() const override { return End; }
2280b57cec5SDimitry Andric 
print(raw_ostream & O) const2295ffd83dbSDimitry Andric   void print(raw_ostream &O) const override {
2300b57cec5SDimitry Andric     switch (Kind) {
2310b57cec5SDimitry Andric     case k_Tok:
2320b57cec5SDimitry Andric       O << "Token " << Tok;
2330b57cec5SDimitry Andric       break;
2340b57cec5SDimitry Andric     case k_Reg:
2350b57cec5SDimitry Andric       O << "Register " << Reg;
2360b57cec5SDimitry Andric       break;
2370b57cec5SDimitry Andric     case k_Imm:
2380b57cec5SDimitry Andric       O << "Immediate " << *Imm;
2390b57cec5SDimitry Andric       break;
2400b57cec5SDimitry Andric     case k_Mem:
2410b57cec5SDimitry Andric       O << "Memory ";
2420b57cec5SDimitry Andric       O << *Mem.Offset << "(" << Reg << ")";
2430b57cec5SDimitry Andric       break;
2440b57cec5SDimitry Andric     case k_IndReg:
2450b57cec5SDimitry Andric       O << "RegInd " << Reg;
2460b57cec5SDimitry Andric       break;
2470b57cec5SDimitry Andric     case k_PostIndReg:
2480b57cec5SDimitry Andric       O << "PostInc " << Reg;
2490b57cec5SDimitry Andric       break;
2500b57cec5SDimitry Andric     }
2510b57cec5SDimitry Andric   }
2520b57cec5SDimitry Andric };
2530b57cec5SDimitry Andric } // end anonymous namespace
2540b57cec5SDimitry Andric 
MatchAndEmitInstruction(SMLoc Loc,unsigned & Opcode,OperandVector & Operands,MCStreamer & Out,uint64_t & ErrorInfo,bool MatchingInlineAsm)2550b57cec5SDimitry Andric bool MSP430AsmParser::MatchAndEmitInstruction(SMLoc Loc, unsigned &Opcode,
2560b57cec5SDimitry Andric                                               OperandVector &Operands,
2570b57cec5SDimitry Andric                                               MCStreamer &Out,
2580b57cec5SDimitry Andric                                               uint64_t &ErrorInfo,
2590b57cec5SDimitry Andric                                               bool MatchingInlineAsm) {
2600b57cec5SDimitry Andric   MCInst Inst;
2610b57cec5SDimitry Andric   unsigned MatchResult =
2620b57cec5SDimitry Andric       MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
2630b57cec5SDimitry Andric 
2640b57cec5SDimitry Andric   switch (MatchResult) {
2650b57cec5SDimitry Andric   case Match_Success:
2660b57cec5SDimitry Andric     Inst.setLoc(Loc);
2675ffd83dbSDimitry Andric     Out.emitInstruction(Inst, STI);
2680b57cec5SDimitry Andric     return false;
2690b57cec5SDimitry Andric   case Match_MnemonicFail:
2700b57cec5SDimitry Andric     return Error(Loc, "invalid instruction mnemonic");
2710b57cec5SDimitry Andric   case Match_InvalidOperand: {
2720b57cec5SDimitry Andric     SMLoc ErrorLoc = Loc;
2730b57cec5SDimitry Andric     if (ErrorInfo != ~0U) {
2740b57cec5SDimitry Andric       if (ErrorInfo >= Operands.size())
2750b57cec5SDimitry Andric         return Error(ErrorLoc, "too few operands for instruction");
2760b57cec5SDimitry Andric 
2770b57cec5SDimitry Andric       ErrorLoc = ((MSP430Operand &)*Operands[ErrorInfo]).getStartLoc();
2780b57cec5SDimitry Andric       if (ErrorLoc == SMLoc())
2790b57cec5SDimitry Andric         ErrorLoc = Loc;
2800b57cec5SDimitry Andric     }
2810b57cec5SDimitry Andric     return Error(ErrorLoc, "invalid operand for instruction");
2820b57cec5SDimitry Andric   }
2830b57cec5SDimitry Andric   default:
2840b57cec5SDimitry Andric     return true;
2850b57cec5SDimitry Andric   }
2860b57cec5SDimitry Andric }
2870b57cec5SDimitry Andric 
2880b57cec5SDimitry Andric // Auto-generated by TableGen
289*0fca6ea1SDimitry Andric static MCRegister MatchRegisterName(StringRef Name);
290*0fca6ea1SDimitry Andric static MCRegister MatchRegisterAltName(StringRef Name);
2910b57cec5SDimitry Andric 
parseRegister(MCRegister & Reg,SMLoc & StartLoc,SMLoc & EndLoc)2925f757f3fSDimitry Andric bool MSP430AsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
2930b57cec5SDimitry Andric                                     SMLoc &EndLoc) {
2945f757f3fSDimitry Andric   ParseStatus Res = tryParseRegister(Reg, StartLoc, EndLoc);
2955f757f3fSDimitry Andric   if (Res.isFailure())
2965ffd83dbSDimitry Andric     return Error(StartLoc, "invalid register name");
2975f757f3fSDimitry Andric   if (Res.isSuccess())
2985ffd83dbSDimitry Andric     return false;
2995f757f3fSDimitry Andric   if (Res.isNoMatch())
3005ffd83dbSDimitry Andric     return true;
3015f757f3fSDimitry Andric 
3025f757f3fSDimitry Andric   llvm_unreachable("unknown parse status");
3035ffd83dbSDimitry Andric }
3045ffd83dbSDimitry Andric 
tryParseRegister(MCRegister & Reg,SMLoc & StartLoc,SMLoc & EndLoc)3055f757f3fSDimitry Andric ParseStatus MSP430AsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
3065ffd83dbSDimitry Andric                                               SMLoc &EndLoc) {
3070b57cec5SDimitry Andric   if (getLexer().getKind() == AsmToken::Identifier) {
3080b57cec5SDimitry Andric     auto Name = getLexer().getTok().getIdentifier().lower();
3095f757f3fSDimitry Andric     Reg = MatchRegisterName(Name);
3105f757f3fSDimitry Andric     if (Reg == MSP430::NoRegister) {
3115f757f3fSDimitry Andric       Reg = MatchRegisterAltName(Name);
3125f757f3fSDimitry Andric       if (Reg == MSP430::NoRegister)
3135f757f3fSDimitry Andric         return ParseStatus::NoMatch;
3140b57cec5SDimitry Andric     }
3150b57cec5SDimitry Andric 
3160b57cec5SDimitry Andric     AsmToken const &T = getParser().getTok();
3170b57cec5SDimitry Andric     StartLoc = T.getLoc();
3180b57cec5SDimitry Andric     EndLoc = T.getEndLoc();
3190b57cec5SDimitry Andric     getLexer().Lex(); // eat register token
3200b57cec5SDimitry Andric 
3215f757f3fSDimitry Andric     return ParseStatus::Success;
3220b57cec5SDimitry Andric   }
3230b57cec5SDimitry Andric 
3245f757f3fSDimitry Andric   return ParseStatus::Failure;
3250b57cec5SDimitry Andric }
3260b57cec5SDimitry Andric 
parseJccInstruction(ParseInstructionInfo & Info,StringRef Name,SMLoc NameLoc,OperandVector & Operands)3270b57cec5SDimitry Andric bool MSP430AsmParser::parseJccInstruction(ParseInstructionInfo &Info,
3280b57cec5SDimitry Andric                                           StringRef Name, SMLoc NameLoc,
3290b57cec5SDimitry Andric                                           OperandVector &Operands) {
33006c3fb27SDimitry Andric   if (!Name.starts_with_insensitive("j"))
3310b57cec5SDimitry Andric     return true;
3320b57cec5SDimitry Andric 
3330b57cec5SDimitry Andric   auto CC = Name.drop_front().lower();
3340b57cec5SDimitry Andric   unsigned CondCode;
3350b57cec5SDimitry Andric   if (CC == "ne" || CC == "nz")
3360b57cec5SDimitry Andric     CondCode = MSP430CC::COND_NE;
3370b57cec5SDimitry Andric   else if (CC == "eq" || CC == "z")
3380b57cec5SDimitry Andric     CondCode = MSP430CC::COND_E;
3390b57cec5SDimitry Andric   else if (CC == "lo" || CC == "nc")
3400b57cec5SDimitry Andric     CondCode = MSP430CC::COND_LO;
3410b57cec5SDimitry Andric   else if (CC == "hs" || CC == "c")
3420b57cec5SDimitry Andric     CondCode = MSP430CC::COND_HS;
3430b57cec5SDimitry Andric   else if (CC == "n")
3440b57cec5SDimitry Andric     CondCode = MSP430CC::COND_N;
3450b57cec5SDimitry Andric   else if (CC == "ge")
3460b57cec5SDimitry Andric     CondCode = MSP430CC::COND_GE;
3470b57cec5SDimitry Andric   else if (CC == "l")
3480b57cec5SDimitry Andric     CondCode = MSP430CC::COND_L;
3490b57cec5SDimitry Andric   else if (CC == "mp")
3500b57cec5SDimitry Andric     CondCode = MSP430CC::COND_NONE;
3510b57cec5SDimitry Andric   else
3520b57cec5SDimitry Andric     return Error(NameLoc, "unknown instruction");
3530b57cec5SDimitry Andric 
3540b57cec5SDimitry Andric   if (CondCode == (unsigned)MSP430CC::COND_NONE)
3550b57cec5SDimitry Andric     Operands.push_back(MSP430Operand::CreateToken("jmp", NameLoc));
3560b57cec5SDimitry Andric   else {
3570b57cec5SDimitry Andric     Operands.push_back(MSP430Operand::CreateToken("j", NameLoc));
3580b57cec5SDimitry Andric     const MCExpr *CCode = MCConstantExpr::create(CondCode, getContext());
3590b57cec5SDimitry Andric     Operands.push_back(MSP430Operand::CreateImm(CCode, SMLoc(), SMLoc()));
3600b57cec5SDimitry Andric   }
3610b57cec5SDimitry Andric 
3620b57cec5SDimitry Andric   // Skip optional '$' sign.
36306c3fb27SDimitry Andric   (void)parseOptionalToken(AsmToken::Dollar);
3640b57cec5SDimitry Andric 
3650b57cec5SDimitry Andric   const MCExpr *Val;
3660b57cec5SDimitry Andric   SMLoc ExprLoc = getLexer().getLoc();
3670b57cec5SDimitry Andric   if (getParser().parseExpression(Val))
3680b57cec5SDimitry Andric     return Error(ExprLoc, "expected expression operand");
3690b57cec5SDimitry Andric 
3700b57cec5SDimitry Andric   int64_t Res;
3710b57cec5SDimitry Andric   if (Val->evaluateAsAbsolute(Res))
3720b57cec5SDimitry Andric     if (Res < -512 || Res > 511)
3730b57cec5SDimitry Andric       return Error(ExprLoc, "invalid jump offset");
3740b57cec5SDimitry Andric 
3750b57cec5SDimitry Andric   Operands.push_back(MSP430Operand::CreateImm(Val, ExprLoc,
3760b57cec5SDimitry Andric     getLexer().getLoc()));
3770b57cec5SDimitry Andric 
3780b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement)) {
3790b57cec5SDimitry Andric     SMLoc Loc = getLexer().getLoc();
3800b57cec5SDimitry Andric     getParser().eatToEndOfStatement();
3810b57cec5SDimitry Andric     return Error(Loc, "unexpected token");
3820b57cec5SDimitry Andric   }
3830b57cec5SDimitry Andric 
3840b57cec5SDimitry Andric   getParser().Lex(); // Consume the EndOfStatement.
3850b57cec5SDimitry Andric   return false;
3860b57cec5SDimitry Andric }
3870b57cec5SDimitry Andric 
ParseInstruction(ParseInstructionInfo & Info,StringRef Name,SMLoc NameLoc,OperandVector & Operands)3880b57cec5SDimitry Andric bool MSP430AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3890b57cec5SDimitry Andric                                        StringRef Name, SMLoc NameLoc,
3900b57cec5SDimitry Andric                                        OperandVector &Operands) {
3910b57cec5SDimitry Andric   // Drop .w suffix
39206c3fb27SDimitry Andric   if (Name.ends_with_insensitive(".w"))
3930b57cec5SDimitry Andric     Name = Name.drop_back(2);
3940b57cec5SDimitry Andric 
3950b57cec5SDimitry Andric   if (!parseJccInstruction(Info, Name, NameLoc, Operands))
3960b57cec5SDimitry Andric     return false;
3970b57cec5SDimitry Andric 
3980b57cec5SDimitry Andric   // First operand is instruction mnemonic
3990b57cec5SDimitry Andric   Operands.push_back(MSP430Operand::CreateToken(Name, NameLoc));
4000b57cec5SDimitry Andric 
4010b57cec5SDimitry Andric   // If there are no more operands, then finish
4020b57cec5SDimitry Andric   if (getLexer().is(AsmToken::EndOfStatement))
4030b57cec5SDimitry Andric     return false;
4040b57cec5SDimitry Andric 
4050b57cec5SDimitry Andric   // Parse first operand
4060b57cec5SDimitry Andric   if (ParseOperand(Operands))
4070b57cec5SDimitry Andric     return true;
4080b57cec5SDimitry Andric 
4090b57cec5SDimitry Andric   // Parse second operand if any
41006c3fb27SDimitry Andric   if (parseOptionalToken(AsmToken::Comma) && ParseOperand(Operands))
4110b57cec5SDimitry Andric     return true;
4120b57cec5SDimitry Andric 
4130b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement)) {
4140b57cec5SDimitry Andric     SMLoc Loc = getLexer().getLoc();
4150b57cec5SDimitry Andric     getParser().eatToEndOfStatement();
4160b57cec5SDimitry Andric     return Error(Loc, "unexpected token");
4170b57cec5SDimitry Andric   }
4180b57cec5SDimitry Andric 
4190b57cec5SDimitry Andric   getParser().Lex(); // Consume the EndOfStatement.
4200b57cec5SDimitry Andric   return false;
4210b57cec5SDimitry Andric }
4220b57cec5SDimitry Andric 
ParseDirectiveRefSym(AsmToken DirectiveID)4230b57cec5SDimitry Andric bool MSP430AsmParser::ParseDirectiveRefSym(AsmToken DirectiveID) {
4240b57cec5SDimitry Andric   StringRef Name;
4250b57cec5SDimitry Andric   if (getParser().parseIdentifier(Name))
4260b57cec5SDimitry Andric     return TokError("expected identifier in directive");
4270b57cec5SDimitry Andric 
4280b57cec5SDimitry Andric   MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
4295ffd83dbSDimitry Andric   getStreamer().emitSymbolAttribute(Sym, MCSA_Global);
43006c3fb27SDimitry Andric   return parseEOL();
4310b57cec5SDimitry Andric }
4320b57cec5SDimitry Andric 
parseDirective(AsmToken DirectiveID)43306c3fb27SDimitry Andric ParseStatus MSP430AsmParser::parseDirective(AsmToken DirectiveID) {
4340b57cec5SDimitry Andric   StringRef IDVal = DirectiveID.getIdentifier();
43506c3fb27SDimitry Andric   if (IDVal.lower() == ".long")
43606c3fb27SDimitry Andric     return ParseLiteralValues(4, DirectiveID.getLoc());
43706c3fb27SDimitry Andric   if (IDVal.lower() == ".word" || IDVal.lower() == ".short")
43806c3fb27SDimitry Andric     return ParseLiteralValues(2, DirectiveID.getLoc());
43906c3fb27SDimitry Andric   if (IDVal.lower() == ".byte")
44006c3fb27SDimitry Andric     return ParseLiteralValues(1, DirectiveID.getLoc());
44106c3fb27SDimitry Andric   if (IDVal.lower() == ".refsym")
4420b57cec5SDimitry Andric     return ParseDirectiveRefSym(DirectiveID);
44306c3fb27SDimitry Andric   return ParseStatus::NoMatch;
4440b57cec5SDimitry Andric }
4450b57cec5SDimitry Andric 
ParseOperand(OperandVector & Operands)4460b57cec5SDimitry Andric bool MSP430AsmParser::ParseOperand(OperandVector &Operands) {
4470b57cec5SDimitry Andric   switch (getLexer().getKind()) {
4480b57cec5SDimitry Andric     default: return true;
4490b57cec5SDimitry Andric     case AsmToken::Identifier: {
4500b57cec5SDimitry Andric       // try rN
451bdd1243dSDimitry Andric       MCRegister RegNo;
4520b57cec5SDimitry Andric       SMLoc StartLoc, EndLoc;
453bdd1243dSDimitry Andric       if (!parseRegister(RegNo, StartLoc, EndLoc)) {
4540b57cec5SDimitry Andric         Operands.push_back(MSP430Operand::CreateReg(RegNo, StartLoc, EndLoc));
4550b57cec5SDimitry Andric         return false;
4560b57cec5SDimitry Andric       }
457bdd1243dSDimitry Andric       [[fallthrough]];
4580b57cec5SDimitry Andric     }
4590b57cec5SDimitry Andric     case AsmToken::Integer:
4600b57cec5SDimitry Andric     case AsmToken::Plus:
4610b57cec5SDimitry Andric     case AsmToken::Minus: {
4620b57cec5SDimitry Andric       SMLoc StartLoc = getParser().getTok().getLoc();
4630b57cec5SDimitry Andric       const MCExpr *Val;
4640b57cec5SDimitry Andric       // Try constexpr[(rN)]
4650b57cec5SDimitry Andric       if (!getParser().parseExpression(Val)) {
466bdd1243dSDimitry Andric         MCRegister RegNo = MSP430::PC;
4670b57cec5SDimitry Andric         SMLoc EndLoc = getParser().getTok().getLoc();
4680b57cec5SDimitry Andric         // Try (rN)
46906c3fb27SDimitry Andric         if (parseOptionalToken(AsmToken::LParen)) {
4700b57cec5SDimitry Andric           SMLoc RegStartLoc;
471bdd1243dSDimitry Andric           if (parseRegister(RegNo, RegStartLoc, EndLoc))
4720b57cec5SDimitry Andric             return true;
4730b57cec5SDimitry Andric           EndLoc = getParser().getTok().getEndLoc();
47406c3fb27SDimitry Andric           if (!parseOptionalToken(AsmToken::RParen))
47506c3fb27SDimitry Andric             return true;
4760b57cec5SDimitry Andric         }
4770b57cec5SDimitry Andric         Operands.push_back(MSP430Operand::CreateMem(RegNo, Val, StartLoc,
4780b57cec5SDimitry Andric           EndLoc));
4790b57cec5SDimitry Andric         return false;
4800b57cec5SDimitry Andric       }
4810b57cec5SDimitry Andric       return true;
4820b57cec5SDimitry Andric     }
4830b57cec5SDimitry Andric     case AsmToken::Amp: {
4840b57cec5SDimitry Andric       // Try &constexpr
4850b57cec5SDimitry Andric       SMLoc StartLoc = getParser().getTok().getLoc();
4860b57cec5SDimitry Andric       getLexer().Lex(); // Eat '&'
4870b57cec5SDimitry Andric       const MCExpr *Val;
4880b57cec5SDimitry Andric       if (!getParser().parseExpression(Val)) {
4890b57cec5SDimitry Andric         SMLoc EndLoc = getParser().getTok().getLoc();
4900b57cec5SDimitry Andric         Operands.push_back(MSP430Operand::CreateMem(MSP430::SR, Val, StartLoc,
4910b57cec5SDimitry Andric           EndLoc));
4920b57cec5SDimitry Andric         return false;
4930b57cec5SDimitry Andric       }
4940b57cec5SDimitry Andric       return true;
4950b57cec5SDimitry Andric     }
4960b57cec5SDimitry Andric     case AsmToken::At: {
4970b57cec5SDimitry Andric       // Try @rN[+]
4980b57cec5SDimitry Andric       SMLoc StartLoc = getParser().getTok().getLoc();
4990b57cec5SDimitry Andric       getLexer().Lex(); // Eat '@'
500bdd1243dSDimitry Andric       MCRegister RegNo;
5010b57cec5SDimitry Andric       SMLoc RegStartLoc, EndLoc;
502bdd1243dSDimitry Andric       if (parseRegister(RegNo, RegStartLoc, EndLoc))
5030b57cec5SDimitry Andric         return true;
50406c3fb27SDimitry Andric       if (parseOptionalToken(AsmToken::Plus)) {
5050b57cec5SDimitry Andric         Operands.push_back(MSP430Operand::CreatePostIndReg(RegNo, StartLoc, EndLoc));
5060b57cec5SDimitry Andric         return false;
5070b57cec5SDimitry Andric       }
5080b57cec5SDimitry Andric       if (Operands.size() > 1) // Emulate @rd in destination position as 0(rd)
5090b57cec5SDimitry Andric         Operands.push_back(MSP430Operand::CreateMem(RegNo,
5100b57cec5SDimitry Andric             MCConstantExpr::create(0, getContext()), StartLoc, EndLoc));
5110b57cec5SDimitry Andric       else
5120b57cec5SDimitry Andric         Operands.push_back(MSP430Operand::CreateIndReg(RegNo, StartLoc, EndLoc));
5130b57cec5SDimitry Andric       return false;
5140b57cec5SDimitry Andric     }
5150b57cec5SDimitry Andric     case AsmToken::Hash:
5160b57cec5SDimitry Andric       // Try #constexpr
5170b57cec5SDimitry Andric       SMLoc StartLoc = getParser().getTok().getLoc();
5180b57cec5SDimitry Andric       getLexer().Lex(); // Eat '#'
5190b57cec5SDimitry Andric       const MCExpr *Val;
5200b57cec5SDimitry Andric       if (!getParser().parseExpression(Val)) {
5210b57cec5SDimitry Andric         SMLoc EndLoc = getParser().getTok().getLoc();
5220b57cec5SDimitry Andric         Operands.push_back(MSP430Operand::CreateImm(Val, StartLoc, EndLoc));
5230b57cec5SDimitry Andric         return false;
5240b57cec5SDimitry Andric       }
5250b57cec5SDimitry Andric       return true;
5260b57cec5SDimitry Andric   }
5270b57cec5SDimitry Andric }
5280b57cec5SDimitry Andric 
ParseLiteralValues(unsigned Size,SMLoc L)5290b57cec5SDimitry Andric bool MSP430AsmParser::ParseLiteralValues(unsigned Size, SMLoc L) {
5300b57cec5SDimitry Andric   auto parseOne = [&]() -> bool {
5310b57cec5SDimitry Andric     const MCExpr *Value;
5320b57cec5SDimitry Andric     if (getParser().parseExpression(Value))
5330b57cec5SDimitry Andric       return true;
5345ffd83dbSDimitry Andric     getParser().getStreamer().emitValue(Value, Size, L);
5350b57cec5SDimitry Andric     return false;
5360b57cec5SDimitry Andric   };
5370b57cec5SDimitry Andric   return (parseMany(parseOne));
5380b57cec5SDimitry Andric }
5390b57cec5SDimitry Andric 
LLVMInitializeMSP430AsmParser()540480093f4SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeMSP430AsmParser() {
5410b57cec5SDimitry Andric   RegisterMCAsmParser<MSP430AsmParser> X(getTheMSP430Target());
5420b57cec5SDimitry Andric }
5430b57cec5SDimitry Andric 
5440b57cec5SDimitry Andric #define GET_REGISTER_MATCHER
5450b57cec5SDimitry Andric #define GET_MATCHER_IMPLEMENTATION
5460b57cec5SDimitry Andric #include "MSP430GenAsmMatcher.inc"
5470b57cec5SDimitry Andric 
convertGR16ToGR8(unsigned Reg)5480b57cec5SDimitry Andric static unsigned convertGR16ToGR8(unsigned Reg) {
5490b57cec5SDimitry Andric   switch (Reg) {
5500b57cec5SDimitry Andric   default:
5510b57cec5SDimitry Andric     llvm_unreachable("Unknown GR16 register");
5520b57cec5SDimitry Andric   case MSP430::PC:  return MSP430::PCB;
5530b57cec5SDimitry Andric   case MSP430::SP:  return MSP430::SPB;
5540b57cec5SDimitry Andric   case MSP430::SR:  return MSP430::SRB;
5550b57cec5SDimitry Andric   case MSP430::CG:  return MSP430::CGB;
5565ffd83dbSDimitry Andric   case MSP430::R4:  return MSP430::R4B;
5570b57cec5SDimitry Andric   case MSP430::R5:  return MSP430::R5B;
5580b57cec5SDimitry Andric   case MSP430::R6:  return MSP430::R6B;
5590b57cec5SDimitry Andric   case MSP430::R7:  return MSP430::R7B;
5600b57cec5SDimitry Andric   case MSP430::R8:  return MSP430::R8B;
5610b57cec5SDimitry Andric   case MSP430::R9:  return MSP430::R9B;
5620b57cec5SDimitry Andric   case MSP430::R10: return MSP430::R10B;
5630b57cec5SDimitry Andric   case MSP430::R11: return MSP430::R11B;
5640b57cec5SDimitry Andric   case MSP430::R12: return MSP430::R12B;
5650b57cec5SDimitry Andric   case MSP430::R13: return MSP430::R13B;
5660b57cec5SDimitry Andric   case MSP430::R14: return MSP430::R14B;
5670b57cec5SDimitry Andric   case MSP430::R15: return MSP430::R15B;
5680b57cec5SDimitry Andric   }
5690b57cec5SDimitry Andric }
5700b57cec5SDimitry Andric 
validateTargetOperandClass(MCParsedAsmOperand & AsmOp,unsigned Kind)5710b57cec5SDimitry Andric unsigned MSP430AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
5720b57cec5SDimitry Andric                                                      unsigned Kind) {
5730b57cec5SDimitry Andric   MSP430Operand &Op = static_cast<MSP430Operand &>(AsmOp);
5740b57cec5SDimitry Andric 
5750b57cec5SDimitry Andric   if (!Op.isReg())
5760b57cec5SDimitry Andric     return Match_InvalidOperand;
5770b57cec5SDimitry Andric 
5780b57cec5SDimitry Andric   unsigned Reg = Op.getReg();
5790b57cec5SDimitry Andric   bool isGR16 =
5800b57cec5SDimitry Andric       MSP430MCRegisterClasses[MSP430::GR16RegClassID].contains(Reg);
5810b57cec5SDimitry Andric 
5820b57cec5SDimitry Andric   if (isGR16 && (Kind == MCK_GR8)) {
5830b57cec5SDimitry Andric     Op.setReg(convertGR16ToGR8(Reg));
5840b57cec5SDimitry Andric     return Match_Success;
5850b57cec5SDimitry Andric   }
5860b57cec5SDimitry Andric 
5870b57cec5SDimitry Andric   return Match_InvalidOperand;
5880b57cec5SDimitry Andric }
589