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