1f0001f41SAnton Korobeynikov //===- MSP430AsmParser.cpp - Parse MSP430 assembly to MCInst instructions -===//
2f0001f41SAnton Korobeynikov //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f0001f41SAnton Korobeynikov //
7f0001f41SAnton Korobeynikov //===----------------------------------------------------------------------===//
8f0001f41SAnton Korobeynikov 
9f0001f41SAnton Korobeynikov #include "MSP430.h"
10f0001f41SAnton Korobeynikov #include "MSP430RegisterInfo.h"
11f0001f41SAnton Korobeynikov #include "MCTargetDesc/MSP430MCTargetDesc.h"
12a57ce32eSRichard Trieu #include "TargetInfo/MSP430TargetInfo.h"
13f0001f41SAnton Korobeynikov 
14f0001f41SAnton Korobeynikov #include "llvm/ADT/APInt.h"
15f0001f41SAnton Korobeynikov #include "llvm/MC/MCContext.h"
16f0001f41SAnton Korobeynikov #include "llvm/MC/MCExpr.h"
17f0001f41SAnton Korobeynikov #include "llvm/MC/MCInst.h"
18f0001f41SAnton Korobeynikov #include "llvm/MC/MCInstBuilder.h"
19*06943537Sserge-sans-paille #include "llvm/MC/MCInstrInfo.h"
20f0001f41SAnton Korobeynikov #include "llvm/MC/MCParser/MCAsmLexer.h"
21f0001f41SAnton Korobeynikov #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
22f0001f41SAnton Korobeynikov #include "llvm/MC/MCParser/MCTargetAsmParser.h"
23f0001f41SAnton Korobeynikov #include "llvm/MC/MCStreamer.h"
24f0001f41SAnton Korobeynikov #include "llvm/MC/MCSubtargetInfo.h"
25f0001f41SAnton Korobeynikov #include "llvm/MC/MCSymbol.h"
26f0001f41SAnton Korobeynikov #include "llvm/MC/MCValue.h"
2789b57061SReid Kleckner #include "llvm/MC/TargetRegistry.h"
28f0001f41SAnton Korobeynikov #include "llvm/Support/Debug.h"
29f0001f41SAnton Korobeynikov #include "llvm/Support/MathExtras.h"
30f0001f41SAnton Korobeynikov 
31f0001f41SAnton Korobeynikov #define DEBUG_TYPE "msp430-asm-parser"
32f0001f41SAnton Korobeynikov 
33f0001f41SAnton Korobeynikov using namespace llvm;
34f0001f41SAnton Korobeynikov 
35f0001f41SAnton Korobeynikov namespace {
36f0001f41SAnton Korobeynikov 
37f0001f41SAnton Korobeynikov /// Parses MSP430 assembly from a stream.
38f0001f41SAnton Korobeynikov class MSP430AsmParser : public MCTargetAsmParser {
39f0001f41SAnton Korobeynikov   const MCSubtargetInfo &STI;
40f0001f41SAnton Korobeynikov   MCAsmParser &Parser;
41f0001f41SAnton Korobeynikov   const MCRegisterInfo *MRI;
42f0001f41SAnton Korobeynikov 
43f0001f41SAnton Korobeynikov   bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
44f0001f41SAnton Korobeynikov                                OperandVector &Operands, MCStreamer &Out,
45f0001f41SAnton Korobeynikov                                uint64_t &ErrorInfo,
46f0001f41SAnton Korobeynikov                                bool MatchingInlineAsm) override;
47f0001f41SAnton Korobeynikov 
48f0001f41SAnton Korobeynikov   bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
498d5bf042SEric Astor   OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc,
508d5bf042SEric Astor                                         SMLoc &EndLoc) override;
51f0001f41SAnton Korobeynikov 
52f0001f41SAnton Korobeynikov   bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
53f0001f41SAnton Korobeynikov                         SMLoc NameLoc, OperandVector &Operands) override;
54f0001f41SAnton Korobeynikov 
55f0001f41SAnton Korobeynikov   bool ParseDirective(AsmToken DirectiveID) override;
56411773d2SAnton Korobeynikov   bool ParseDirectiveRefSym(AsmToken DirectiveID);
57f0001f41SAnton Korobeynikov 
58f0001f41SAnton Korobeynikov   unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
59f0001f41SAnton Korobeynikov                                       unsigned Kind) override;
60f0001f41SAnton Korobeynikov 
61f0001f41SAnton Korobeynikov   bool parseJccInstruction(ParseInstructionInfo &Info, StringRef Name,
62f0001f41SAnton Korobeynikov                            SMLoc NameLoc, OperandVector &Operands);
63f0001f41SAnton Korobeynikov 
64f0001f41SAnton Korobeynikov   bool ParseOperand(OperandVector &Operands);
65f0001f41SAnton Korobeynikov 
66f0001f41SAnton Korobeynikov   bool ParseLiteralValues(unsigned Size, SMLoc L);
67f0001f41SAnton Korobeynikov 
getParser() const68f0001f41SAnton Korobeynikov   MCAsmParser &getParser() const { return Parser; }
getLexer() const69f0001f41SAnton Korobeynikov   MCAsmLexer &getLexer() const { return Parser.getLexer(); }
70f0001f41SAnton Korobeynikov 
71f0001f41SAnton Korobeynikov   /// @name Auto-generated Matcher Functions
72f0001f41SAnton Korobeynikov   /// {
73f0001f41SAnton Korobeynikov 
74f0001f41SAnton Korobeynikov #define GET_ASSEMBLER_HEADER
75f0001f41SAnton Korobeynikov #include "MSP430GenAsmMatcher.inc"
76f0001f41SAnton Korobeynikov 
77f0001f41SAnton Korobeynikov   /// }
78f0001f41SAnton Korobeynikov 
79f0001f41SAnton Korobeynikov public:
MSP430AsmParser(const MCSubtargetInfo & STI,MCAsmParser & Parser,const MCInstrInfo & MII,const MCTargetOptions & Options)80f0001f41SAnton Korobeynikov   MSP430AsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
81f0001f41SAnton Korobeynikov                   const MCInstrInfo &MII, const MCTargetOptions &Options)
82f0001f41SAnton Korobeynikov       : MCTargetAsmParser(Options, STI, MII), STI(STI), Parser(Parser) {
83f0001f41SAnton Korobeynikov     MCAsmParserExtension::Initialize(Parser);
84f0001f41SAnton Korobeynikov     MRI = getContext().getRegisterInfo();
85f0001f41SAnton Korobeynikov 
86f0001f41SAnton Korobeynikov     setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
87f0001f41SAnton Korobeynikov   }
88f0001f41SAnton Korobeynikov };
89f0001f41SAnton Korobeynikov 
90f0001f41SAnton Korobeynikov /// A parsed MSP430 assembly operand.
91f0001f41SAnton Korobeynikov class MSP430Operand : public MCParsedAsmOperand {
92f0001f41SAnton Korobeynikov   typedef MCParsedAsmOperand Base;
93f0001f41SAnton Korobeynikov 
94f0001f41SAnton Korobeynikov   enum KindTy {
95f0001f41SAnton Korobeynikov     k_Imm,
96f0001f41SAnton Korobeynikov     k_Reg,
97f0001f41SAnton Korobeynikov     k_Tok,
98f0001f41SAnton Korobeynikov     k_Mem,
99f0001f41SAnton Korobeynikov     k_IndReg,
100f0001f41SAnton Korobeynikov     k_PostIndReg
101f0001f41SAnton Korobeynikov   } Kind;
102f0001f41SAnton Korobeynikov 
103f0001f41SAnton Korobeynikov   struct Memory {
104f0001f41SAnton Korobeynikov     unsigned Reg;
105f0001f41SAnton Korobeynikov     const MCExpr *Offset;
106f0001f41SAnton Korobeynikov   };
107f0001f41SAnton Korobeynikov   union {
108f0001f41SAnton Korobeynikov     const MCExpr *Imm;
109f0001f41SAnton Korobeynikov     unsigned      Reg;
110f0001f41SAnton Korobeynikov     StringRef     Tok;
111f0001f41SAnton Korobeynikov     Memory        Mem;
112f0001f41SAnton Korobeynikov   };
113f0001f41SAnton Korobeynikov 
114f0001f41SAnton Korobeynikov   SMLoc Start, End;
115f0001f41SAnton Korobeynikov 
116f0001f41SAnton Korobeynikov public:
MSP430Operand(StringRef Tok,SMLoc const & S)117f0001f41SAnton Korobeynikov   MSP430Operand(StringRef Tok, SMLoc const &S)
118f3a344d2SKazu Hirata       : Kind(k_Tok), Tok(Tok), Start(S), End(S) {}
MSP430Operand(KindTy Kind,unsigned Reg,SMLoc const & S,SMLoc const & E)119f0001f41SAnton Korobeynikov   MSP430Operand(KindTy Kind, unsigned Reg, SMLoc const &S, SMLoc const &E)
120f3a344d2SKazu Hirata       : Kind(Kind), Reg(Reg), Start(S), End(E) {}
MSP430Operand(MCExpr const * Imm,SMLoc const & S,SMLoc const & E)121f0001f41SAnton Korobeynikov   MSP430Operand(MCExpr const *Imm, SMLoc const &S, SMLoc const &E)
122f3a344d2SKazu Hirata       : Kind(k_Imm), Imm(Imm), Start(S), End(E) {}
MSP430Operand(unsigned Reg,MCExpr const * Expr,SMLoc const & S,SMLoc const & E)123f3a344d2SKazu Hirata   MSP430Operand(unsigned Reg, MCExpr const *Expr, SMLoc const &S,
124f3a344d2SKazu Hirata                 SMLoc const &E)
125f3a344d2SKazu Hirata       : Kind(k_Mem), Mem({Reg, Expr}), Start(S), End(E) {}
126f0001f41SAnton Korobeynikov 
addRegOperands(MCInst & Inst,unsigned N) const127f0001f41SAnton Korobeynikov   void addRegOperands(MCInst &Inst, unsigned N) const {
128f0001f41SAnton Korobeynikov     assert((Kind == k_Reg || Kind == k_IndReg || Kind == k_PostIndReg) &&
129f0001f41SAnton Korobeynikov         "Unexpected operand kind");
130f0001f41SAnton Korobeynikov     assert(N == 1 && "Invalid number of operands!");
131f0001f41SAnton Korobeynikov 
132f0001f41SAnton Korobeynikov     Inst.addOperand(MCOperand::createReg(Reg));
133f0001f41SAnton Korobeynikov   }
134f0001f41SAnton Korobeynikov 
addExprOperand(MCInst & Inst,const MCExpr * Expr) const135f0001f41SAnton Korobeynikov   void addExprOperand(MCInst &Inst, const MCExpr *Expr) const {
136f0001f41SAnton Korobeynikov     // Add as immediate when possible
137f0001f41SAnton Korobeynikov     if (!Expr)
138f0001f41SAnton Korobeynikov       Inst.addOperand(MCOperand::createImm(0));
139f0001f41SAnton Korobeynikov     else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
140f0001f41SAnton Korobeynikov       Inst.addOperand(MCOperand::createImm(CE->getValue()));
141f0001f41SAnton Korobeynikov     else
142f0001f41SAnton Korobeynikov       Inst.addOperand(MCOperand::createExpr(Expr));
143f0001f41SAnton Korobeynikov   }
144f0001f41SAnton Korobeynikov 
addImmOperands(MCInst & Inst,unsigned N) const145f0001f41SAnton Korobeynikov   void addImmOperands(MCInst &Inst, unsigned N) const {
146f0001f41SAnton Korobeynikov     assert(Kind == k_Imm && "Unexpected operand kind");
147f0001f41SAnton Korobeynikov     assert(N == 1 && "Invalid number of operands!");
148f0001f41SAnton Korobeynikov 
149f0001f41SAnton Korobeynikov     addExprOperand(Inst, Imm);
150f0001f41SAnton Korobeynikov   }
151f0001f41SAnton Korobeynikov 
addMemOperands(MCInst & Inst,unsigned N) const152f0001f41SAnton Korobeynikov   void addMemOperands(MCInst &Inst, unsigned N) const {
153f0001f41SAnton Korobeynikov     assert(Kind == k_Mem && "Unexpected operand kind");
154f0001f41SAnton Korobeynikov     assert(N == 2 && "Invalid number of operands");
155f0001f41SAnton Korobeynikov 
156f0001f41SAnton Korobeynikov     Inst.addOperand(MCOperand::createReg(Mem.Reg));
157f0001f41SAnton Korobeynikov     addExprOperand(Inst, Mem.Offset);
158f0001f41SAnton Korobeynikov   }
159f0001f41SAnton Korobeynikov 
isReg() const160a19461d9SLogan Smith   bool isReg()   const override { return Kind == k_Reg; }
isImm() const161a19461d9SLogan Smith   bool isImm()   const override { return Kind == k_Imm; }
isToken() const162a19461d9SLogan Smith   bool isToken() const override { return Kind == k_Tok; }
isMem() const163a19461d9SLogan Smith   bool isMem()   const override { return Kind == k_Mem; }
isIndReg() const164f0001f41SAnton Korobeynikov   bool isIndReg()         const { return Kind == k_IndReg; }
isPostIndReg() const165f0001f41SAnton Korobeynikov   bool isPostIndReg()     const { return Kind == k_PostIndReg; }
166f0001f41SAnton Korobeynikov 
isCGImm() const167f0001f41SAnton Korobeynikov   bool isCGImm() const {
168f0001f41SAnton Korobeynikov     if (Kind != k_Imm)
169f0001f41SAnton Korobeynikov       return false;
170f0001f41SAnton Korobeynikov 
171f0001f41SAnton Korobeynikov     int64_t Val;
172f0001f41SAnton Korobeynikov     if (!Imm->evaluateAsAbsolute(Val))
173f0001f41SAnton Korobeynikov       return false;
174f0001f41SAnton Korobeynikov 
175f0001f41SAnton Korobeynikov     if (Val == 0 || Val == 1 || Val == 2 || Val == 4 || Val == 8 || Val == -1)
176f0001f41SAnton Korobeynikov       return true;
177f0001f41SAnton Korobeynikov 
178f0001f41SAnton Korobeynikov     return false;
179f0001f41SAnton Korobeynikov   }
180f0001f41SAnton Korobeynikov 
getToken() const181f0001f41SAnton Korobeynikov   StringRef getToken() const {
182f0001f41SAnton Korobeynikov     assert(Kind == k_Tok && "Invalid access!");
183f0001f41SAnton Korobeynikov     return Tok;
184f0001f41SAnton Korobeynikov   }
185f0001f41SAnton Korobeynikov 
getReg() const186a19461d9SLogan Smith   unsigned getReg() const override {
187f0001f41SAnton Korobeynikov     assert(Kind == k_Reg && "Invalid access!");
188f0001f41SAnton Korobeynikov     return Reg;
189f0001f41SAnton Korobeynikov   }
190f0001f41SAnton Korobeynikov 
setReg(unsigned RegNo)191f0001f41SAnton Korobeynikov   void setReg(unsigned RegNo) {
192f0001f41SAnton Korobeynikov     assert(Kind == k_Reg && "Invalid access!");
193f0001f41SAnton Korobeynikov     Reg = RegNo;
194f0001f41SAnton Korobeynikov   }
195f0001f41SAnton Korobeynikov 
CreateToken(StringRef Str,SMLoc S)196f0001f41SAnton Korobeynikov   static std::unique_ptr<MSP430Operand> CreateToken(StringRef Str, SMLoc S) {
1970eaee545SJonas Devlieghere     return std::make_unique<MSP430Operand>(Str, S);
198f0001f41SAnton Korobeynikov   }
199f0001f41SAnton Korobeynikov 
CreateReg(unsigned RegNum,SMLoc S,SMLoc E)200f0001f41SAnton Korobeynikov   static std::unique_ptr<MSP430Operand> CreateReg(unsigned RegNum, SMLoc S,
201f0001f41SAnton Korobeynikov                                                   SMLoc E) {
2020eaee545SJonas Devlieghere     return std::make_unique<MSP430Operand>(k_Reg, RegNum, S, E);
203f0001f41SAnton Korobeynikov   }
204f0001f41SAnton Korobeynikov 
CreateImm(const MCExpr * Val,SMLoc S,SMLoc E)205f0001f41SAnton Korobeynikov   static std::unique_ptr<MSP430Operand> CreateImm(const MCExpr *Val, SMLoc S,
206f0001f41SAnton Korobeynikov                                                   SMLoc E) {
2070eaee545SJonas Devlieghere     return std::make_unique<MSP430Operand>(Val, S, E);
208f0001f41SAnton Korobeynikov   }
209f0001f41SAnton Korobeynikov 
CreateMem(unsigned RegNum,const MCExpr * Val,SMLoc S,SMLoc E)210f0001f41SAnton Korobeynikov   static std::unique_ptr<MSP430Operand> CreateMem(unsigned RegNum,
211f0001f41SAnton Korobeynikov                                                   const MCExpr *Val,
212f0001f41SAnton Korobeynikov                                                   SMLoc S, SMLoc E) {
2130eaee545SJonas Devlieghere     return std::make_unique<MSP430Operand>(RegNum, Val, S, E);
214f0001f41SAnton Korobeynikov   }
215f0001f41SAnton Korobeynikov 
CreateIndReg(unsigned RegNum,SMLoc S,SMLoc E)216f0001f41SAnton Korobeynikov   static std::unique_ptr<MSP430Operand> CreateIndReg(unsigned RegNum, SMLoc S,
217f0001f41SAnton Korobeynikov                                                   SMLoc E) {
2180eaee545SJonas Devlieghere     return std::make_unique<MSP430Operand>(k_IndReg, RegNum, S, E);
219f0001f41SAnton Korobeynikov   }
220f0001f41SAnton Korobeynikov 
CreatePostIndReg(unsigned RegNum,SMLoc S,SMLoc E)221f0001f41SAnton Korobeynikov   static std::unique_ptr<MSP430Operand> CreatePostIndReg(unsigned RegNum, SMLoc S,
222f0001f41SAnton Korobeynikov                                                   SMLoc E) {
2230eaee545SJonas Devlieghere     return std::make_unique<MSP430Operand>(k_PostIndReg, RegNum, S, E);
224f0001f41SAnton Korobeynikov   }
225f0001f41SAnton Korobeynikov 
getStartLoc() const226a19461d9SLogan Smith   SMLoc getStartLoc() const override { return Start; }
getEndLoc() const227a19461d9SLogan Smith   SMLoc getEndLoc() const override { return End; }
228f0001f41SAnton Korobeynikov 
print(raw_ostream & O) const229a19461d9SLogan Smith   void print(raw_ostream &O) const override {
230f0001f41SAnton Korobeynikov     switch (Kind) {
231f0001f41SAnton Korobeynikov     case k_Tok:
232f0001f41SAnton Korobeynikov       O << "Token " << Tok;
233f0001f41SAnton Korobeynikov       break;
234f0001f41SAnton Korobeynikov     case k_Reg:
235f0001f41SAnton Korobeynikov       O << "Register " << Reg;
236f0001f41SAnton Korobeynikov       break;
237f0001f41SAnton Korobeynikov     case k_Imm:
238f0001f41SAnton Korobeynikov       O << "Immediate " << *Imm;
239f0001f41SAnton Korobeynikov       break;
240f0001f41SAnton Korobeynikov     case k_Mem:
241f0001f41SAnton Korobeynikov       O << "Memory ";
242f0001f41SAnton Korobeynikov       O << *Mem.Offset << "(" << Reg << ")";
243f0001f41SAnton Korobeynikov       break;
244f0001f41SAnton Korobeynikov     case k_IndReg:
245f0001f41SAnton Korobeynikov       O << "RegInd " << Reg;
246f0001f41SAnton Korobeynikov       break;
247f0001f41SAnton Korobeynikov     case k_PostIndReg:
248f0001f41SAnton Korobeynikov       O << "PostInc " << Reg;
249f0001f41SAnton Korobeynikov       break;
250f0001f41SAnton Korobeynikov     }
251f0001f41SAnton Korobeynikov   }
252f0001f41SAnton Korobeynikov };
253f0001f41SAnton Korobeynikov } // end anonymous namespace
254f0001f41SAnton Korobeynikov 
MatchAndEmitInstruction(SMLoc Loc,unsigned & Opcode,OperandVector & Operands,MCStreamer & Out,uint64_t & ErrorInfo,bool MatchingInlineAsm)255f0001f41SAnton Korobeynikov bool MSP430AsmParser::MatchAndEmitInstruction(SMLoc Loc, unsigned &Opcode,
256f0001f41SAnton Korobeynikov                                               OperandVector &Operands,
257f0001f41SAnton Korobeynikov                                               MCStreamer &Out,
258f0001f41SAnton Korobeynikov                                               uint64_t &ErrorInfo,
259f0001f41SAnton Korobeynikov                                               bool MatchingInlineAsm) {
260f0001f41SAnton Korobeynikov   MCInst Inst;
261f0001f41SAnton Korobeynikov   unsigned MatchResult =
262f0001f41SAnton Korobeynikov       MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
263f0001f41SAnton Korobeynikov 
264f0001f41SAnton Korobeynikov   switch (MatchResult) {
265f0001f41SAnton Korobeynikov   case Match_Success:
266f0001f41SAnton Korobeynikov     Inst.setLoc(Loc);
267bcd24b2dSFangrui Song     Out.emitInstruction(Inst, STI);
268f0001f41SAnton Korobeynikov     return false;
269f0001f41SAnton Korobeynikov   case Match_MnemonicFail:
270f0001f41SAnton Korobeynikov     return Error(Loc, "invalid instruction mnemonic");
271f0001f41SAnton Korobeynikov   case Match_InvalidOperand: {
272f0001f41SAnton Korobeynikov     SMLoc ErrorLoc = Loc;
273f0001f41SAnton Korobeynikov     if (ErrorInfo != ~0U) {
274f0001f41SAnton Korobeynikov       if (ErrorInfo >= Operands.size())
275f0001f41SAnton Korobeynikov         return Error(ErrorLoc, "too few operands for instruction");
276f0001f41SAnton Korobeynikov 
277f0001f41SAnton Korobeynikov       ErrorLoc = ((MSP430Operand &)*Operands[ErrorInfo]).getStartLoc();
278f0001f41SAnton Korobeynikov       if (ErrorLoc == SMLoc())
279f0001f41SAnton Korobeynikov         ErrorLoc = Loc;
280f0001f41SAnton Korobeynikov     }
281f0001f41SAnton Korobeynikov     return Error(ErrorLoc, "invalid operand for instruction");
282f0001f41SAnton Korobeynikov   }
283f0001f41SAnton Korobeynikov   default:
284f0001f41SAnton Korobeynikov     return true;
285f0001f41SAnton Korobeynikov   }
286f0001f41SAnton Korobeynikov }
287f0001f41SAnton Korobeynikov 
288f0001f41SAnton Korobeynikov // Auto-generated by TableGen
289f0001f41SAnton Korobeynikov static unsigned MatchRegisterName(StringRef Name);
290f0001f41SAnton Korobeynikov static unsigned MatchRegisterAltName(StringRef Name);
291f0001f41SAnton Korobeynikov 
ParseRegister(unsigned & RegNo,SMLoc & StartLoc,SMLoc & EndLoc)292f0001f41SAnton Korobeynikov bool MSP430AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
293f0001f41SAnton Korobeynikov                                     SMLoc &EndLoc) {
2948d5bf042SEric Astor   switch (tryParseRegister(RegNo, StartLoc, EndLoc)) {
2958d5bf042SEric Astor   case MatchOperand_ParseFail:
2968d5bf042SEric Astor     return Error(StartLoc, "invalid register name");
2978d5bf042SEric Astor   case MatchOperand_Success:
2988d5bf042SEric Astor     return false;
2998d5bf042SEric Astor   case MatchOperand_NoMatch:
3008d5bf042SEric Astor     return true;
3018d5bf042SEric Astor   }
3028d5bf042SEric Astor 
3038d5bf042SEric Astor   llvm_unreachable("unknown match result type");
3048d5bf042SEric Astor }
3058d5bf042SEric Astor 
tryParseRegister(unsigned & RegNo,SMLoc & StartLoc,SMLoc & EndLoc)3068d5bf042SEric Astor OperandMatchResultTy MSP430AsmParser::tryParseRegister(unsigned &RegNo,
3078d5bf042SEric Astor                                                        SMLoc &StartLoc,
3088d5bf042SEric Astor                                                        SMLoc &EndLoc) {
309f0001f41SAnton Korobeynikov   if (getLexer().getKind() == AsmToken::Identifier) {
310f0001f41SAnton Korobeynikov     auto Name = getLexer().getTok().getIdentifier().lower();
311f0001f41SAnton Korobeynikov     RegNo = MatchRegisterName(Name);
312f0001f41SAnton Korobeynikov     if (RegNo == MSP430::NoRegister) {
313f0001f41SAnton Korobeynikov       RegNo = MatchRegisterAltName(Name);
314f0001f41SAnton Korobeynikov       if (RegNo == MSP430::NoRegister)
3158d5bf042SEric Astor         return MatchOperand_NoMatch;
316f0001f41SAnton Korobeynikov     }
317f0001f41SAnton Korobeynikov 
318f0001f41SAnton Korobeynikov     AsmToken const &T = getParser().getTok();
319f0001f41SAnton Korobeynikov     StartLoc = T.getLoc();
320f0001f41SAnton Korobeynikov     EndLoc = T.getEndLoc();
321f0001f41SAnton Korobeynikov     getLexer().Lex(); // eat register token
322f0001f41SAnton Korobeynikov 
3238d5bf042SEric Astor     return MatchOperand_Success;
324f0001f41SAnton Korobeynikov   }
325f0001f41SAnton Korobeynikov 
3268d5bf042SEric Astor   return MatchOperand_ParseFail;
327f0001f41SAnton Korobeynikov }
328f0001f41SAnton Korobeynikov 
parseJccInstruction(ParseInstructionInfo & Info,StringRef Name,SMLoc NameLoc,OperandVector & Operands)329f0001f41SAnton Korobeynikov bool MSP430AsmParser::parseJccInstruction(ParseInstructionInfo &Info,
330f0001f41SAnton Korobeynikov                                           StringRef Name, SMLoc NameLoc,
331f0001f41SAnton Korobeynikov                                           OperandVector &Operands) {
33242f74e82SMartin Storsjö   if (!Name.startswith_insensitive("j"))
333f0001f41SAnton Korobeynikov     return true;
334f0001f41SAnton Korobeynikov 
335f0001f41SAnton Korobeynikov   auto CC = Name.drop_front().lower();
336f0001f41SAnton Korobeynikov   unsigned CondCode;
337f0001f41SAnton Korobeynikov   if (CC == "ne" || CC == "nz")
338f0001f41SAnton Korobeynikov     CondCode = MSP430CC::COND_NE;
339f0001f41SAnton Korobeynikov   else if (CC == "eq" || CC == "z")
340f0001f41SAnton Korobeynikov     CondCode = MSP430CC::COND_E;
341f0001f41SAnton Korobeynikov   else if (CC == "lo" || CC == "nc")
342f0001f41SAnton Korobeynikov     CondCode = MSP430CC::COND_LO;
343f0001f41SAnton Korobeynikov   else if (CC == "hs" || CC == "c")
344f0001f41SAnton Korobeynikov     CondCode = MSP430CC::COND_HS;
345f0001f41SAnton Korobeynikov   else if (CC == "n")
346f0001f41SAnton Korobeynikov     CondCode = MSP430CC::COND_N;
347f0001f41SAnton Korobeynikov   else if (CC == "ge")
348f0001f41SAnton Korobeynikov     CondCode = MSP430CC::COND_GE;
349f0001f41SAnton Korobeynikov   else if (CC == "l")
350f0001f41SAnton Korobeynikov     CondCode = MSP430CC::COND_L;
351f0001f41SAnton Korobeynikov   else if (CC == "mp")
352f0001f41SAnton Korobeynikov     CondCode = MSP430CC::COND_NONE;
353f0001f41SAnton Korobeynikov   else
354f0001f41SAnton Korobeynikov     return Error(NameLoc, "unknown instruction");
355f0001f41SAnton Korobeynikov 
356f0001f41SAnton Korobeynikov   if (CondCode == (unsigned)MSP430CC::COND_NONE)
357f0001f41SAnton Korobeynikov     Operands.push_back(MSP430Operand::CreateToken("jmp", NameLoc));
358f0001f41SAnton Korobeynikov   else {
359f0001f41SAnton Korobeynikov     Operands.push_back(MSP430Operand::CreateToken("j", NameLoc));
360f0001f41SAnton Korobeynikov     const MCExpr *CCode = MCConstantExpr::create(CondCode, getContext());
361f0001f41SAnton Korobeynikov     Operands.push_back(MSP430Operand::CreateImm(CCode, SMLoc(), SMLoc()));
362f0001f41SAnton Korobeynikov   }
363f0001f41SAnton Korobeynikov 
364f0001f41SAnton Korobeynikov   // Skip optional '$' sign.
365f0001f41SAnton Korobeynikov   if (getLexer().getKind() == AsmToken::Dollar)
366f0001f41SAnton Korobeynikov     getLexer().Lex(); // Eat '$'
367f0001f41SAnton Korobeynikov 
368f0001f41SAnton Korobeynikov   const MCExpr *Val;
369f0001f41SAnton Korobeynikov   SMLoc ExprLoc = getLexer().getLoc();
370f0001f41SAnton Korobeynikov   if (getParser().parseExpression(Val))
371f0001f41SAnton Korobeynikov     return Error(ExprLoc, "expected expression operand");
372f0001f41SAnton Korobeynikov 
373f0001f41SAnton Korobeynikov   int64_t Res;
374f0001f41SAnton Korobeynikov   if (Val->evaluateAsAbsolute(Res))
375f0001f41SAnton Korobeynikov     if (Res < -512 || Res > 511)
376f0001f41SAnton Korobeynikov       return Error(ExprLoc, "invalid jump offset");
377f0001f41SAnton Korobeynikov 
378f0001f41SAnton Korobeynikov   Operands.push_back(MSP430Operand::CreateImm(Val, ExprLoc,
379f0001f41SAnton Korobeynikov     getLexer().getLoc()));
380f0001f41SAnton Korobeynikov 
381f0001f41SAnton Korobeynikov   if (getLexer().isNot(AsmToken::EndOfStatement)) {
382f0001f41SAnton Korobeynikov     SMLoc Loc = getLexer().getLoc();
383f0001f41SAnton Korobeynikov     getParser().eatToEndOfStatement();
384f0001f41SAnton Korobeynikov     return Error(Loc, "unexpected token");
385f0001f41SAnton Korobeynikov   }
386f0001f41SAnton Korobeynikov 
387f0001f41SAnton Korobeynikov   getParser().Lex(); // Consume the EndOfStatement.
388f0001f41SAnton Korobeynikov   return false;
389f0001f41SAnton Korobeynikov }
390f0001f41SAnton Korobeynikov 
ParseInstruction(ParseInstructionInfo & Info,StringRef Name,SMLoc NameLoc,OperandVector & Operands)391f0001f41SAnton Korobeynikov bool MSP430AsmParser::ParseInstruction(ParseInstructionInfo &Info,
392f0001f41SAnton Korobeynikov                                        StringRef Name, SMLoc NameLoc,
393f0001f41SAnton Korobeynikov                                        OperandVector &Operands) {
394f0001f41SAnton Korobeynikov   // Drop .w suffix
39542f74e82SMartin Storsjö   if (Name.endswith_insensitive(".w"))
396f0001f41SAnton Korobeynikov     Name = Name.drop_back(2);
397f0001f41SAnton Korobeynikov 
398f0001f41SAnton Korobeynikov   if (!parseJccInstruction(Info, Name, NameLoc, Operands))
399f0001f41SAnton Korobeynikov     return false;
400f0001f41SAnton Korobeynikov 
401f0001f41SAnton Korobeynikov   // First operand is instruction mnemonic
402f0001f41SAnton Korobeynikov   Operands.push_back(MSP430Operand::CreateToken(Name, NameLoc));
403f0001f41SAnton Korobeynikov 
404f0001f41SAnton Korobeynikov   // If there are no more operands, then finish
405f0001f41SAnton Korobeynikov   if (getLexer().is(AsmToken::EndOfStatement))
406f0001f41SAnton Korobeynikov     return false;
407f0001f41SAnton Korobeynikov 
408f0001f41SAnton Korobeynikov   // Parse first operand
409f0001f41SAnton Korobeynikov   if (ParseOperand(Operands))
410f0001f41SAnton Korobeynikov     return true;
411f0001f41SAnton Korobeynikov 
412f0001f41SAnton Korobeynikov   // Parse second operand if any
413f0001f41SAnton Korobeynikov   if (getLexer().is(AsmToken::Comma)) {
414f0001f41SAnton Korobeynikov     getLexer().Lex(); // Eat ','
415f0001f41SAnton Korobeynikov     if (ParseOperand(Operands))
416f0001f41SAnton Korobeynikov       return true;
417f0001f41SAnton Korobeynikov   }
418f0001f41SAnton Korobeynikov 
419f0001f41SAnton Korobeynikov   if (getLexer().isNot(AsmToken::EndOfStatement)) {
420f0001f41SAnton Korobeynikov     SMLoc Loc = getLexer().getLoc();
421f0001f41SAnton Korobeynikov     getParser().eatToEndOfStatement();
422f0001f41SAnton Korobeynikov     return Error(Loc, "unexpected token");
423f0001f41SAnton Korobeynikov   }
424f0001f41SAnton Korobeynikov 
425f0001f41SAnton Korobeynikov   getParser().Lex(); // Consume the EndOfStatement.
426f0001f41SAnton Korobeynikov   return false;
427f0001f41SAnton Korobeynikov }
428f0001f41SAnton Korobeynikov 
ParseDirectiveRefSym(AsmToken DirectiveID)429411773d2SAnton Korobeynikov bool MSP430AsmParser::ParseDirectiveRefSym(AsmToken DirectiveID) {
430411773d2SAnton Korobeynikov     StringRef Name;
431411773d2SAnton Korobeynikov     if (getParser().parseIdentifier(Name))
432411773d2SAnton Korobeynikov       return TokError("expected identifier in directive");
433411773d2SAnton Korobeynikov 
434411773d2SAnton Korobeynikov     MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
435a55daa14SFangrui Song     getStreamer().emitSymbolAttribute(Sym, MCSA_Global);
436411773d2SAnton Korobeynikov     return false;
437411773d2SAnton Korobeynikov }
438411773d2SAnton Korobeynikov 
ParseDirective(AsmToken DirectiveID)439f0001f41SAnton Korobeynikov bool MSP430AsmParser::ParseDirective(AsmToken DirectiveID) {
440f0001f41SAnton Korobeynikov   StringRef IDVal = DirectiveID.getIdentifier();
441f0001f41SAnton Korobeynikov   if (IDVal.lower() == ".long") {
442f0001f41SAnton Korobeynikov     ParseLiteralValues(4, DirectiveID.getLoc());
443f0001f41SAnton Korobeynikov   } else if (IDVal.lower() == ".word" || IDVal.lower() == ".short") {
444f0001f41SAnton Korobeynikov     ParseLiteralValues(2, DirectiveID.getLoc());
445f0001f41SAnton Korobeynikov   } else if (IDVal.lower() == ".byte") {
446f0001f41SAnton Korobeynikov     ParseLiteralValues(1, DirectiveID.getLoc());
447411773d2SAnton Korobeynikov   } else if (IDVal.lower() == ".refsym") {
448411773d2SAnton Korobeynikov     return ParseDirectiveRefSym(DirectiveID);
449f0001f41SAnton Korobeynikov   }
450f0001f41SAnton Korobeynikov   return true;
451f0001f41SAnton Korobeynikov }
452f0001f41SAnton Korobeynikov 
ParseOperand(OperandVector & Operands)453f0001f41SAnton Korobeynikov bool MSP430AsmParser::ParseOperand(OperandVector &Operands) {
454f0001f41SAnton Korobeynikov   switch (getLexer().getKind()) {
455f0001f41SAnton Korobeynikov     default: return true;
456f0001f41SAnton Korobeynikov     case AsmToken::Identifier: {
457f0001f41SAnton Korobeynikov       // try rN
458f0001f41SAnton Korobeynikov       unsigned RegNo;
459f0001f41SAnton Korobeynikov       SMLoc StartLoc, EndLoc;
460f0001f41SAnton Korobeynikov       if (!ParseRegister(RegNo, StartLoc, EndLoc)) {
461f0001f41SAnton Korobeynikov         Operands.push_back(MSP430Operand::CreateReg(RegNo, StartLoc, EndLoc));
462f0001f41SAnton Korobeynikov         return false;
463f0001f41SAnton Korobeynikov       }
464f0001f41SAnton Korobeynikov       LLVM_FALLTHROUGH;
465f0001f41SAnton Korobeynikov     }
466f0001f41SAnton Korobeynikov     case AsmToken::Integer:
467f0001f41SAnton Korobeynikov     case AsmToken::Plus:
468f0001f41SAnton Korobeynikov     case AsmToken::Minus: {
469f0001f41SAnton Korobeynikov       SMLoc StartLoc = getParser().getTok().getLoc();
470f0001f41SAnton Korobeynikov       const MCExpr *Val;
471f0001f41SAnton Korobeynikov       // Try constexpr[(rN)]
472f0001f41SAnton Korobeynikov       if (!getParser().parseExpression(Val)) {
473f0001f41SAnton Korobeynikov         unsigned RegNo = MSP430::PC;
474f0001f41SAnton Korobeynikov         SMLoc EndLoc = getParser().getTok().getLoc();
475f0001f41SAnton Korobeynikov         // Try (rN)
476f0001f41SAnton Korobeynikov         if (getLexer().getKind() == AsmToken::LParen) {
477f0001f41SAnton Korobeynikov           getLexer().Lex(); // Eat '('
478f0001f41SAnton Korobeynikov           SMLoc RegStartLoc;
479f0001f41SAnton Korobeynikov           if (ParseRegister(RegNo, RegStartLoc, EndLoc))
480f0001f41SAnton Korobeynikov             return true;
481f0001f41SAnton Korobeynikov           if (getLexer().getKind() != AsmToken::RParen)
482f0001f41SAnton Korobeynikov             return true;
483f0001f41SAnton Korobeynikov           EndLoc = getParser().getTok().getEndLoc();
484f0001f41SAnton Korobeynikov           getLexer().Lex(); // Eat ')'
485f0001f41SAnton Korobeynikov         }
486f0001f41SAnton Korobeynikov         Operands.push_back(MSP430Operand::CreateMem(RegNo, Val, StartLoc,
487f0001f41SAnton Korobeynikov           EndLoc));
488f0001f41SAnton Korobeynikov         return false;
489f0001f41SAnton Korobeynikov       }
490f0001f41SAnton Korobeynikov       return true;
491f0001f41SAnton Korobeynikov     }
492f0001f41SAnton Korobeynikov     case AsmToken::Amp: {
493f0001f41SAnton Korobeynikov       // Try &constexpr
494f0001f41SAnton Korobeynikov       SMLoc StartLoc = getParser().getTok().getLoc();
495f0001f41SAnton Korobeynikov       getLexer().Lex(); // Eat '&'
496f0001f41SAnton Korobeynikov       const MCExpr *Val;
497f0001f41SAnton Korobeynikov       if (!getParser().parseExpression(Val)) {
498f0001f41SAnton Korobeynikov         SMLoc EndLoc = getParser().getTok().getLoc();
499f0001f41SAnton Korobeynikov         Operands.push_back(MSP430Operand::CreateMem(MSP430::SR, Val, StartLoc,
500f0001f41SAnton Korobeynikov           EndLoc));
501f0001f41SAnton Korobeynikov         return false;
502f0001f41SAnton Korobeynikov       }
503f0001f41SAnton Korobeynikov       return true;
504f0001f41SAnton Korobeynikov     }
505f0001f41SAnton Korobeynikov     case AsmToken::At: {
506f0001f41SAnton Korobeynikov       // Try @rN[+]
507f0001f41SAnton Korobeynikov       SMLoc StartLoc = getParser().getTok().getLoc();
508f0001f41SAnton Korobeynikov       getLexer().Lex(); // Eat '@'
509f0001f41SAnton Korobeynikov       unsigned RegNo;
510f0001f41SAnton Korobeynikov       SMLoc RegStartLoc, EndLoc;
511f0001f41SAnton Korobeynikov       if (ParseRegister(RegNo, RegStartLoc, EndLoc))
512f0001f41SAnton Korobeynikov         return true;
513f0001f41SAnton Korobeynikov       if (getLexer().getKind() == AsmToken::Plus) {
514f0001f41SAnton Korobeynikov         Operands.push_back(MSP430Operand::CreatePostIndReg(RegNo, StartLoc, EndLoc));
515f0001f41SAnton Korobeynikov         getLexer().Lex(); // Eat '+'
516f0001f41SAnton Korobeynikov         return false;
517f0001f41SAnton Korobeynikov       }
5180681d6bcSAnton Korobeynikov       if (Operands.size() > 1) // Emulate @rd in destination position as 0(rd)
5190681d6bcSAnton Korobeynikov         Operands.push_back(MSP430Operand::CreateMem(RegNo,
5200681d6bcSAnton Korobeynikov             MCConstantExpr::create(0, getContext()), StartLoc, EndLoc));
5210681d6bcSAnton Korobeynikov       else
522f0001f41SAnton Korobeynikov         Operands.push_back(MSP430Operand::CreateIndReg(RegNo, StartLoc, EndLoc));
523f0001f41SAnton Korobeynikov       return false;
524f0001f41SAnton Korobeynikov     }
525f0001f41SAnton Korobeynikov     case AsmToken::Hash:
526f0001f41SAnton Korobeynikov       // Try #constexpr
527f0001f41SAnton Korobeynikov       SMLoc StartLoc = getParser().getTok().getLoc();
528f0001f41SAnton Korobeynikov       getLexer().Lex(); // Eat '#'
529f0001f41SAnton Korobeynikov       const MCExpr *Val;
530f0001f41SAnton Korobeynikov       if (!getParser().parseExpression(Val)) {
531f0001f41SAnton Korobeynikov         SMLoc EndLoc = getParser().getTok().getLoc();
532f0001f41SAnton Korobeynikov         Operands.push_back(MSP430Operand::CreateImm(Val, StartLoc, EndLoc));
533f0001f41SAnton Korobeynikov         return false;
534f0001f41SAnton Korobeynikov       }
535f0001f41SAnton Korobeynikov       return true;
536f0001f41SAnton Korobeynikov   }
537f0001f41SAnton Korobeynikov }
538f0001f41SAnton Korobeynikov 
ParseLiteralValues(unsigned Size,SMLoc L)539f0001f41SAnton Korobeynikov bool MSP430AsmParser::ParseLiteralValues(unsigned Size, SMLoc L) {
540f0001f41SAnton Korobeynikov   auto parseOne = [&]() -> bool {
541f0001f41SAnton Korobeynikov     const MCExpr *Value;
542f0001f41SAnton Korobeynikov     if (getParser().parseExpression(Value))
543f0001f41SAnton Korobeynikov       return true;
54477497103SFangrui Song     getParser().getStreamer().emitValue(Value, Size, L);
545f0001f41SAnton Korobeynikov     return false;
546f0001f41SAnton Korobeynikov   };
547f0001f41SAnton Korobeynikov   return (parseMany(parseOne));
548f0001f41SAnton Korobeynikov }
549f0001f41SAnton Korobeynikov 
LLVMInitializeMSP430AsmParser()5500dbcb363STom Stellard extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeMSP430AsmParser() {
551f0001f41SAnton Korobeynikov   RegisterMCAsmParser<MSP430AsmParser> X(getTheMSP430Target());
552f0001f41SAnton Korobeynikov }
553f0001f41SAnton Korobeynikov 
554f0001f41SAnton Korobeynikov #define GET_REGISTER_MATCHER
555f0001f41SAnton Korobeynikov #define GET_MATCHER_IMPLEMENTATION
556f0001f41SAnton Korobeynikov #include "MSP430GenAsmMatcher.inc"
557f0001f41SAnton Korobeynikov 
convertGR16ToGR8(unsigned Reg)558f0001f41SAnton Korobeynikov static unsigned convertGR16ToGR8(unsigned Reg) {
559f0001f41SAnton Korobeynikov   switch (Reg) {
560f0001f41SAnton Korobeynikov   default:
561f0001f41SAnton Korobeynikov     llvm_unreachable("Unknown GR16 register");
562f0001f41SAnton Korobeynikov   case MSP430::PC:  return MSP430::PCB;
563f0001f41SAnton Korobeynikov   case MSP430::SP:  return MSP430::SPB;
564f0001f41SAnton Korobeynikov   case MSP430::SR:  return MSP430::SRB;
565f0001f41SAnton Korobeynikov   case MSP430::CG:  return MSP430::CGB;
566cb56fa21SAnatoly Trosinenko   case MSP430::R4:  return MSP430::R4B;
567f0001f41SAnton Korobeynikov   case MSP430::R5:  return MSP430::R5B;
568f0001f41SAnton Korobeynikov   case MSP430::R6:  return MSP430::R6B;
569f0001f41SAnton Korobeynikov   case MSP430::R7:  return MSP430::R7B;
570f0001f41SAnton Korobeynikov   case MSP430::R8:  return MSP430::R8B;
571f0001f41SAnton Korobeynikov   case MSP430::R9:  return MSP430::R9B;
572f0001f41SAnton Korobeynikov   case MSP430::R10: return MSP430::R10B;
573f0001f41SAnton Korobeynikov   case MSP430::R11: return MSP430::R11B;
574f0001f41SAnton Korobeynikov   case MSP430::R12: return MSP430::R12B;
575f0001f41SAnton Korobeynikov   case MSP430::R13: return MSP430::R13B;
576f0001f41SAnton Korobeynikov   case MSP430::R14: return MSP430::R14B;
577f0001f41SAnton Korobeynikov   case MSP430::R15: return MSP430::R15B;
578f0001f41SAnton Korobeynikov   }
579f0001f41SAnton Korobeynikov }
580f0001f41SAnton Korobeynikov 
validateTargetOperandClass(MCParsedAsmOperand & AsmOp,unsigned Kind)581f0001f41SAnton Korobeynikov unsigned MSP430AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
582f0001f41SAnton Korobeynikov                                                      unsigned Kind) {
583f0001f41SAnton Korobeynikov   MSP430Operand &Op = static_cast<MSP430Operand &>(AsmOp);
584f0001f41SAnton Korobeynikov 
585f0001f41SAnton Korobeynikov   if (!Op.isReg())
586f0001f41SAnton Korobeynikov     return Match_InvalidOperand;
587f0001f41SAnton Korobeynikov 
588f0001f41SAnton Korobeynikov   unsigned Reg = Op.getReg();
589f0001f41SAnton Korobeynikov   bool isGR16 =
590f0001f41SAnton Korobeynikov       MSP430MCRegisterClasses[MSP430::GR16RegClassID].contains(Reg);
591f0001f41SAnton Korobeynikov 
592f0001f41SAnton Korobeynikov   if (isGR16 && (Kind == MCK_GR8)) {
593f0001f41SAnton Korobeynikov     Op.setReg(convertGR16ToGR8(Reg));
594f0001f41SAnton Korobeynikov     return Match_Success;
595f0001f41SAnton Korobeynikov   }
596f0001f41SAnton Korobeynikov 
597f0001f41SAnton Korobeynikov   return Match_InvalidOperand;
598f0001f41SAnton Korobeynikov }
599