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 680b57cec5SDimitry Andric MCAsmParser &getParser() const { return Parser; } 690b57cec5SDimitry 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: 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: 1170b57cec5SDimitry Andric MSP430Operand(StringRef Tok, SMLoc const &S) 11804eeddc0SDimitry Andric : Kind(k_Tok), Tok(Tok), Start(S), End(S) {} 1190b57cec5SDimitry Andric MSP430Operand(KindTy Kind, unsigned Reg, SMLoc const &S, SMLoc const &E) 12004eeddc0SDimitry Andric : Kind(Kind), Reg(Reg), Start(S), End(E) {} 1210b57cec5SDimitry Andric MSP430Operand(MCExpr const *Imm, SMLoc const &S, SMLoc const &E) 12204eeddc0SDimitry Andric : Kind(k_Imm), Imm(Imm), Start(S), End(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 1270b57cec5SDimitry 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 1350b57cec5SDimitry 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 1450b57cec5SDimitry 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 1520b57cec5SDimitry 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 1605ffd83dbSDimitry Andric bool isReg() const override { return Kind == k_Reg; } 1615ffd83dbSDimitry Andric bool isImm() const override { return Kind == k_Imm; } 1625ffd83dbSDimitry Andric bool isToken() const override { return Kind == k_Tok; } 1635ffd83dbSDimitry Andric bool isMem() const override { return Kind == k_Mem; } 1640b57cec5SDimitry Andric bool isIndReg() const { return Kind == k_IndReg; } 1650b57cec5SDimitry Andric bool isPostIndReg() const { return Kind == k_PostIndReg; } 1660b57cec5SDimitry Andric 1670b57cec5SDimitry 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 1810b57cec5SDimitry Andric StringRef getToken() const { 1820b57cec5SDimitry Andric assert(Kind == k_Tok && "Invalid access!"); 1830b57cec5SDimitry Andric return Tok; 1840b57cec5SDimitry Andric } 1850b57cec5SDimitry Andric 186*0fca6ea1SDimitry Andric MCRegister getReg() const override { 1870b57cec5SDimitry Andric assert(Kind == k_Reg && "Invalid access!"); 1880b57cec5SDimitry Andric return Reg; 1890b57cec5SDimitry Andric } 1900b57cec5SDimitry Andric 1910b57cec5SDimitry Andric void setReg(unsigned RegNo) { 1920b57cec5SDimitry Andric assert(Kind == k_Reg && "Invalid access!"); 1930b57cec5SDimitry Andric Reg = RegNo; 1940b57cec5SDimitry Andric } 1950b57cec5SDimitry Andric 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 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 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 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 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 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 2265ffd83dbSDimitry Andric SMLoc getStartLoc() const override { return Start; } 2275ffd83dbSDimitry Andric SMLoc getEndLoc() const override { return End; } 2280b57cec5SDimitry Andric 2295ffd83dbSDimitry 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 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 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 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 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 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 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 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 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 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 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 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 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