Path: blob/main/contrib/llvm-project/llvm/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp
35294 views
//===- MSP430AsmParser.cpp - Parse MSP430 assembly to MCInst instructions -===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "MSP430.h"9#include "MSP430RegisterInfo.h"10#include "MCTargetDesc/MSP430MCTargetDesc.h"11#include "TargetInfo/MSP430TargetInfo.h"1213#include "llvm/ADT/APInt.h"14#include "llvm/MC/MCContext.h"15#include "llvm/MC/MCExpr.h"16#include "llvm/MC/MCInst.h"17#include "llvm/MC/MCInstBuilder.h"18#include "llvm/MC/MCInstrInfo.h"19#include "llvm/MC/MCParser/MCAsmLexer.h"20#include "llvm/MC/MCParser/MCParsedAsmOperand.h"21#include "llvm/MC/MCParser/MCTargetAsmParser.h"22#include "llvm/MC/MCStreamer.h"23#include "llvm/MC/MCSubtargetInfo.h"24#include "llvm/MC/MCSymbol.h"25#include "llvm/MC/MCValue.h"26#include "llvm/MC/TargetRegistry.h"27#include "llvm/Support/Debug.h"28#include "llvm/Support/MathExtras.h"2930#define DEBUG_TYPE "msp430-asm-parser"3132using namespace llvm;3334namespace {3536/// Parses MSP430 assembly from a stream.37class MSP430AsmParser : public MCTargetAsmParser {38const MCSubtargetInfo &STI;39MCAsmParser &Parser;40const MCRegisterInfo *MRI;4142bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,43OperandVector &Operands, MCStreamer &Out,44uint64_t &ErrorInfo,45bool MatchingInlineAsm) override;4647bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;48ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,49SMLoc &EndLoc) override;5051bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,52SMLoc NameLoc, OperandVector &Operands) override;5354ParseStatus parseDirective(AsmToken DirectiveID) override;55bool ParseDirectiveRefSym(AsmToken DirectiveID);5657unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,58unsigned Kind) override;5960bool parseJccInstruction(ParseInstructionInfo &Info, StringRef Name,61SMLoc NameLoc, OperandVector &Operands);6263bool ParseOperand(OperandVector &Operands);6465bool ParseLiteralValues(unsigned Size, SMLoc L);6667MCAsmParser &getParser() const { return Parser; }68MCAsmLexer &getLexer() const { return Parser.getLexer(); }6970/// @name Auto-generated Matcher Functions71/// {7273#define GET_ASSEMBLER_HEADER74#include "MSP430GenAsmMatcher.inc"7576/// }7778public:79MSP430AsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,80const MCInstrInfo &MII, const MCTargetOptions &Options)81: MCTargetAsmParser(Options, STI, MII), STI(STI), Parser(Parser) {82MCAsmParserExtension::Initialize(Parser);83MRI = getContext().getRegisterInfo();8485setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));86}87};8889/// A parsed MSP430 assembly operand.90class MSP430Operand : public MCParsedAsmOperand {91typedef MCParsedAsmOperand Base;9293enum KindTy {94k_Imm,95k_Reg,96k_Tok,97k_Mem,98k_IndReg,99k_PostIndReg100} Kind;101102struct Memory {103unsigned Reg;104const MCExpr *Offset;105};106union {107const MCExpr *Imm;108unsigned Reg;109StringRef Tok;110Memory Mem;111};112113SMLoc Start, End;114115public:116MSP430Operand(StringRef Tok, SMLoc const &S)117: Kind(k_Tok), Tok(Tok), Start(S), End(S) {}118MSP430Operand(KindTy Kind, unsigned Reg, SMLoc const &S, SMLoc const &E)119: Kind(Kind), Reg(Reg), Start(S), End(E) {}120MSP430Operand(MCExpr const *Imm, SMLoc const &S, SMLoc const &E)121: Kind(k_Imm), Imm(Imm), Start(S), End(E) {}122MSP430Operand(unsigned Reg, MCExpr const *Expr, SMLoc const &S,123SMLoc const &E)124: Kind(k_Mem), Mem({Reg, Expr}), Start(S), End(E) {}125126void addRegOperands(MCInst &Inst, unsigned N) const {127assert((Kind == k_Reg || Kind == k_IndReg || Kind == k_PostIndReg) &&128"Unexpected operand kind");129assert(N == 1 && "Invalid number of operands!");130131Inst.addOperand(MCOperand::createReg(Reg));132}133134void addExprOperand(MCInst &Inst, const MCExpr *Expr) const {135// Add as immediate when possible136if (!Expr)137Inst.addOperand(MCOperand::createImm(0));138else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))139Inst.addOperand(MCOperand::createImm(CE->getValue()));140else141Inst.addOperand(MCOperand::createExpr(Expr));142}143144void addImmOperands(MCInst &Inst, unsigned N) const {145assert(Kind == k_Imm && "Unexpected operand kind");146assert(N == 1 && "Invalid number of operands!");147148addExprOperand(Inst, Imm);149}150151void addMemOperands(MCInst &Inst, unsigned N) const {152assert(Kind == k_Mem && "Unexpected operand kind");153assert(N == 2 && "Invalid number of operands");154155Inst.addOperand(MCOperand::createReg(Mem.Reg));156addExprOperand(Inst, Mem.Offset);157}158159bool isReg() const override { return Kind == k_Reg; }160bool isImm() const override { return Kind == k_Imm; }161bool isToken() const override { return Kind == k_Tok; }162bool isMem() const override { return Kind == k_Mem; }163bool isIndReg() const { return Kind == k_IndReg; }164bool isPostIndReg() const { return Kind == k_PostIndReg; }165166bool isCGImm() const {167if (Kind != k_Imm)168return false;169170int64_t Val;171if (!Imm->evaluateAsAbsolute(Val))172return false;173174if (Val == 0 || Val == 1 || Val == 2 || Val == 4 || Val == 8 || Val == -1)175return true;176177return false;178}179180StringRef getToken() const {181assert(Kind == k_Tok && "Invalid access!");182return Tok;183}184185MCRegister getReg() const override {186assert(Kind == k_Reg && "Invalid access!");187return Reg;188}189190void setReg(unsigned RegNo) {191assert(Kind == k_Reg && "Invalid access!");192Reg = RegNo;193}194195static std::unique_ptr<MSP430Operand> CreateToken(StringRef Str, SMLoc S) {196return std::make_unique<MSP430Operand>(Str, S);197}198199static std::unique_ptr<MSP430Operand> CreateReg(unsigned RegNum, SMLoc S,200SMLoc E) {201return std::make_unique<MSP430Operand>(k_Reg, RegNum, S, E);202}203204static std::unique_ptr<MSP430Operand> CreateImm(const MCExpr *Val, SMLoc S,205SMLoc E) {206return std::make_unique<MSP430Operand>(Val, S, E);207}208209static std::unique_ptr<MSP430Operand> CreateMem(unsigned RegNum,210const MCExpr *Val,211SMLoc S, SMLoc E) {212return std::make_unique<MSP430Operand>(RegNum, Val, S, E);213}214215static std::unique_ptr<MSP430Operand> CreateIndReg(unsigned RegNum, SMLoc S,216SMLoc E) {217return std::make_unique<MSP430Operand>(k_IndReg, RegNum, S, E);218}219220static std::unique_ptr<MSP430Operand> CreatePostIndReg(unsigned RegNum, SMLoc S,221SMLoc E) {222return std::make_unique<MSP430Operand>(k_PostIndReg, RegNum, S, E);223}224225SMLoc getStartLoc() const override { return Start; }226SMLoc getEndLoc() const override { return End; }227228void print(raw_ostream &O) const override {229switch (Kind) {230case k_Tok:231O << "Token " << Tok;232break;233case k_Reg:234O << "Register " << Reg;235break;236case k_Imm:237O << "Immediate " << *Imm;238break;239case k_Mem:240O << "Memory ";241O << *Mem.Offset << "(" << Reg << ")";242break;243case k_IndReg:244O << "RegInd " << Reg;245break;246case k_PostIndReg:247O << "PostInc " << Reg;248break;249}250}251};252} // end anonymous namespace253254bool MSP430AsmParser::MatchAndEmitInstruction(SMLoc Loc, unsigned &Opcode,255OperandVector &Operands,256MCStreamer &Out,257uint64_t &ErrorInfo,258bool MatchingInlineAsm) {259MCInst Inst;260unsigned MatchResult =261MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);262263switch (MatchResult) {264case Match_Success:265Inst.setLoc(Loc);266Out.emitInstruction(Inst, STI);267return false;268case Match_MnemonicFail:269return Error(Loc, "invalid instruction mnemonic");270case Match_InvalidOperand: {271SMLoc ErrorLoc = Loc;272if (ErrorInfo != ~0U) {273if (ErrorInfo >= Operands.size())274return Error(ErrorLoc, "too few operands for instruction");275276ErrorLoc = ((MSP430Operand &)*Operands[ErrorInfo]).getStartLoc();277if (ErrorLoc == SMLoc())278ErrorLoc = Loc;279}280return Error(ErrorLoc, "invalid operand for instruction");281}282default:283return true;284}285}286287// Auto-generated by TableGen288static MCRegister MatchRegisterName(StringRef Name);289static MCRegister MatchRegisterAltName(StringRef Name);290291bool MSP430AsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,292SMLoc &EndLoc) {293ParseStatus Res = tryParseRegister(Reg, StartLoc, EndLoc);294if (Res.isFailure())295return Error(StartLoc, "invalid register name");296if (Res.isSuccess())297return false;298if (Res.isNoMatch())299return true;300301llvm_unreachable("unknown parse status");302}303304ParseStatus MSP430AsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,305SMLoc &EndLoc) {306if (getLexer().getKind() == AsmToken::Identifier) {307auto Name = getLexer().getTok().getIdentifier().lower();308Reg = MatchRegisterName(Name);309if (Reg == MSP430::NoRegister) {310Reg = MatchRegisterAltName(Name);311if (Reg == MSP430::NoRegister)312return ParseStatus::NoMatch;313}314315AsmToken const &T = getParser().getTok();316StartLoc = T.getLoc();317EndLoc = T.getEndLoc();318getLexer().Lex(); // eat register token319320return ParseStatus::Success;321}322323return ParseStatus::Failure;324}325326bool MSP430AsmParser::parseJccInstruction(ParseInstructionInfo &Info,327StringRef Name, SMLoc NameLoc,328OperandVector &Operands) {329if (!Name.starts_with_insensitive("j"))330return true;331332auto CC = Name.drop_front().lower();333unsigned CondCode;334if (CC == "ne" || CC == "nz")335CondCode = MSP430CC::COND_NE;336else if (CC == "eq" || CC == "z")337CondCode = MSP430CC::COND_E;338else if (CC == "lo" || CC == "nc")339CondCode = MSP430CC::COND_LO;340else if (CC == "hs" || CC == "c")341CondCode = MSP430CC::COND_HS;342else if (CC == "n")343CondCode = MSP430CC::COND_N;344else if (CC == "ge")345CondCode = MSP430CC::COND_GE;346else if (CC == "l")347CondCode = MSP430CC::COND_L;348else if (CC == "mp")349CondCode = MSP430CC::COND_NONE;350else351return Error(NameLoc, "unknown instruction");352353if (CondCode == (unsigned)MSP430CC::COND_NONE)354Operands.push_back(MSP430Operand::CreateToken("jmp", NameLoc));355else {356Operands.push_back(MSP430Operand::CreateToken("j", NameLoc));357const MCExpr *CCode = MCConstantExpr::create(CondCode, getContext());358Operands.push_back(MSP430Operand::CreateImm(CCode, SMLoc(), SMLoc()));359}360361// Skip optional '$' sign.362(void)parseOptionalToken(AsmToken::Dollar);363364const MCExpr *Val;365SMLoc ExprLoc = getLexer().getLoc();366if (getParser().parseExpression(Val))367return Error(ExprLoc, "expected expression operand");368369int64_t Res;370if (Val->evaluateAsAbsolute(Res))371if (Res < -512 || Res > 511)372return Error(ExprLoc, "invalid jump offset");373374Operands.push_back(MSP430Operand::CreateImm(Val, ExprLoc,375getLexer().getLoc()));376377if (getLexer().isNot(AsmToken::EndOfStatement)) {378SMLoc Loc = getLexer().getLoc();379getParser().eatToEndOfStatement();380return Error(Loc, "unexpected token");381}382383getParser().Lex(); // Consume the EndOfStatement.384return false;385}386387bool MSP430AsmParser::ParseInstruction(ParseInstructionInfo &Info,388StringRef Name, SMLoc NameLoc,389OperandVector &Operands) {390// Drop .w suffix391if (Name.ends_with_insensitive(".w"))392Name = Name.drop_back(2);393394if (!parseJccInstruction(Info, Name, NameLoc, Operands))395return false;396397// First operand is instruction mnemonic398Operands.push_back(MSP430Operand::CreateToken(Name, NameLoc));399400// If there are no more operands, then finish401if (getLexer().is(AsmToken::EndOfStatement))402return false;403404// Parse first operand405if (ParseOperand(Operands))406return true;407408// Parse second operand if any409if (parseOptionalToken(AsmToken::Comma) && ParseOperand(Operands))410return true;411412if (getLexer().isNot(AsmToken::EndOfStatement)) {413SMLoc Loc = getLexer().getLoc();414getParser().eatToEndOfStatement();415return Error(Loc, "unexpected token");416}417418getParser().Lex(); // Consume the EndOfStatement.419return false;420}421422bool MSP430AsmParser::ParseDirectiveRefSym(AsmToken DirectiveID) {423StringRef Name;424if (getParser().parseIdentifier(Name))425return TokError("expected identifier in directive");426427MCSymbol *Sym = getContext().getOrCreateSymbol(Name);428getStreamer().emitSymbolAttribute(Sym, MCSA_Global);429return parseEOL();430}431432ParseStatus MSP430AsmParser::parseDirective(AsmToken DirectiveID) {433StringRef IDVal = DirectiveID.getIdentifier();434if (IDVal.lower() == ".long")435return ParseLiteralValues(4, DirectiveID.getLoc());436if (IDVal.lower() == ".word" || IDVal.lower() == ".short")437return ParseLiteralValues(2, DirectiveID.getLoc());438if (IDVal.lower() == ".byte")439return ParseLiteralValues(1, DirectiveID.getLoc());440if (IDVal.lower() == ".refsym")441return ParseDirectiveRefSym(DirectiveID);442return ParseStatus::NoMatch;443}444445bool MSP430AsmParser::ParseOperand(OperandVector &Operands) {446switch (getLexer().getKind()) {447default: return true;448case AsmToken::Identifier: {449// try rN450MCRegister RegNo;451SMLoc StartLoc, EndLoc;452if (!parseRegister(RegNo, StartLoc, EndLoc)) {453Operands.push_back(MSP430Operand::CreateReg(RegNo, StartLoc, EndLoc));454return false;455}456[[fallthrough]];457}458case AsmToken::Integer:459case AsmToken::Plus:460case AsmToken::Minus: {461SMLoc StartLoc = getParser().getTok().getLoc();462const MCExpr *Val;463// Try constexpr[(rN)]464if (!getParser().parseExpression(Val)) {465MCRegister RegNo = MSP430::PC;466SMLoc EndLoc = getParser().getTok().getLoc();467// Try (rN)468if (parseOptionalToken(AsmToken::LParen)) {469SMLoc RegStartLoc;470if (parseRegister(RegNo, RegStartLoc, EndLoc))471return true;472EndLoc = getParser().getTok().getEndLoc();473if (!parseOptionalToken(AsmToken::RParen))474return true;475}476Operands.push_back(MSP430Operand::CreateMem(RegNo, Val, StartLoc,477EndLoc));478return false;479}480return true;481}482case AsmToken::Amp: {483// Try &constexpr484SMLoc StartLoc = getParser().getTok().getLoc();485getLexer().Lex(); // Eat '&'486const MCExpr *Val;487if (!getParser().parseExpression(Val)) {488SMLoc EndLoc = getParser().getTok().getLoc();489Operands.push_back(MSP430Operand::CreateMem(MSP430::SR, Val, StartLoc,490EndLoc));491return false;492}493return true;494}495case AsmToken::At: {496// Try @rN[+]497SMLoc StartLoc = getParser().getTok().getLoc();498getLexer().Lex(); // Eat '@'499MCRegister RegNo;500SMLoc RegStartLoc, EndLoc;501if (parseRegister(RegNo, RegStartLoc, EndLoc))502return true;503if (parseOptionalToken(AsmToken::Plus)) {504Operands.push_back(MSP430Operand::CreatePostIndReg(RegNo, StartLoc, EndLoc));505return false;506}507if (Operands.size() > 1) // Emulate @rd in destination position as 0(rd)508Operands.push_back(MSP430Operand::CreateMem(RegNo,509MCConstantExpr::create(0, getContext()), StartLoc, EndLoc));510else511Operands.push_back(MSP430Operand::CreateIndReg(RegNo, StartLoc, EndLoc));512return false;513}514case AsmToken::Hash:515// Try #constexpr516SMLoc StartLoc = getParser().getTok().getLoc();517getLexer().Lex(); // Eat '#'518const MCExpr *Val;519if (!getParser().parseExpression(Val)) {520SMLoc EndLoc = getParser().getTok().getLoc();521Operands.push_back(MSP430Operand::CreateImm(Val, StartLoc, EndLoc));522return false;523}524return true;525}526}527528bool MSP430AsmParser::ParseLiteralValues(unsigned Size, SMLoc L) {529auto parseOne = [&]() -> bool {530const MCExpr *Value;531if (getParser().parseExpression(Value))532return true;533getParser().getStreamer().emitValue(Value, Size, L);534return false;535};536return (parseMany(parseOne));537}538539extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeMSP430AsmParser() {540RegisterMCAsmParser<MSP430AsmParser> X(getTheMSP430Target());541}542543#define GET_REGISTER_MATCHER544#define GET_MATCHER_IMPLEMENTATION545#include "MSP430GenAsmMatcher.inc"546547static unsigned convertGR16ToGR8(unsigned Reg) {548switch (Reg) {549default:550llvm_unreachable("Unknown GR16 register");551case MSP430::PC: return MSP430::PCB;552case MSP430::SP: return MSP430::SPB;553case MSP430::SR: return MSP430::SRB;554case MSP430::CG: return MSP430::CGB;555case MSP430::R4: return MSP430::R4B;556case MSP430::R5: return MSP430::R5B;557case MSP430::R6: return MSP430::R6B;558case MSP430::R7: return MSP430::R7B;559case MSP430::R8: return MSP430::R8B;560case MSP430::R9: return MSP430::R9B;561case MSP430::R10: return MSP430::R10B;562case MSP430::R11: return MSP430::R11B;563case MSP430::R12: return MSP430::R12B;564case MSP430::R13: return MSP430::R13B;565case MSP430::R14: return MSP430::R14B;566case MSP430::R15: return MSP430::R15B;567}568}569570unsigned MSP430AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,571unsigned Kind) {572MSP430Operand &Op = static_cast<MSP430Operand &>(AsmOp);573574if (!Op.isReg())575return Match_InvalidOperand;576577unsigned Reg = Op.getReg();578bool isGR16 =579MSP430MCRegisterClasses[MSP430::GR16RegClassID].contains(Reg);580581if (isGR16 && (Kind == MCK_GR8)) {582Op.setReg(convertGR16ToGR8(Reg));583return Match_Success;584}585586return Match_InvalidOperand;587}588589590