10b57cec5SDimitry Andric //===---- AVRAsmParser.cpp - Parse AVR 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 "AVR.h"
100b57cec5SDimitry Andric #include "AVRRegisterInfo.h"
110b57cec5SDimitry Andric #include "MCTargetDesc/AVRMCELFStreamer.h"
120b57cec5SDimitry Andric #include "MCTargetDesc/AVRMCExpr.h"
130b57cec5SDimitry Andric #include "MCTargetDesc/AVRMCTargetDesc.h"
140b57cec5SDimitry Andric #include "TargetInfo/AVRTargetInfo.h"
150b57cec5SDimitry Andric
160b57cec5SDimitry Andric #include "llvm/ADT/APInt.h"
170b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
180b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h"
190b57cec5SDimitry Andric #include "llvm/MC/MCInst.h"
200b57cec5SDimitry Andric #include "llvm/MC/MCInstBuilder.h"
210b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCAsmLexer.h"
220b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
230b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCTargetAsmParser.h"
240b57cec5SDimitry Andric #include "llvm/MC/MCStreamer.h"
250b57cec5SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
260b57cec5SDimitry Andric #include "llvm/MC/MCSymbol.h"
270b57cec5SDimitry Andric #include "llvm/MC/MCValue.h"
28349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h"
290b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
300b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h"
310b57cec5SDimitry Andric
32bdd1243dSDimitry Andric #include <array>
330b57cec5SDimitry Andric #include <sstream>
340b57cec5SDimitry Andric
350b57cec5SDimitry Andric #define DEBUG_TYPE "avr-asm-parser"
360b57cec5SDimitry Andric
370b57cec5SDimitry Andric using namespace llvm;
380b57cec5SDimitry Andric
390b57cec5SDimitry Andric namespace {
400b57cec5SDimitry Andric /// Parses AVR assembly from a stream.
410b57cec5SDimitry Andric class AVRAsmParser : public MCTargetAsmParser {
420b57cec5SDimitry Andric const MCSubtargetInfo &STI;
430b57cec5SDimitry Andric MCAsmParser &Parser;
440b57cec5SDimitry Andric const MCRegisterInfo *MRI;
450b57cec5SDimitry Andric const std::string GENERATE_STUBS = "gs";
460b57cec5SDimitry Andric
4781ad6265SDimitry Andric enum AVRMatchResultTy {
4881ad6265SDimitry Andric Match_InvalidRegisterOnTiny = FIRST_TARGET_MATCH_RESULT_TY + 1,
4981ad6265SDimitry Andric };
5081ad6265SDimitry Andric
510b57cec5SDimitry Andric #define GET_ASSEMBLER_HEADER
520b57cec5SDimitry Andric #include "AVRGenAsmMatcher.inc"
530b57cec5SDimitry Andric
540b57cec5SDimitry Andric bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
550b57cec5SDimitry Andric OperandVector &Operands, MCStreamer &Out,
560b57cec5SDimitry Andric uint64_t &ErrorInfo,
570b57cec5SDimitry Andric bool MatchingInlineAsm) override;
580b57cec5SDimitry Andric
595f757f3fSDimitry Andric bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
605f757f3fSDimitry Andric ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
615ffd83dbSDimitry Andric SMLoc &EndLoc) override;
620b57cec5SDimitry Andric
630b57cec5SDimitry Andric bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
640b57cec5SDimitry Andric SMLoc NameLoc, OperandVector &Operands) override;
650b57cec5SDimitry Andric
6606c3fb27SDimitry Andric ParseStatus parseDirective(AsmToken DirectiveID) override;
670b57cec5SDimitry Andric
685f757f3fSDimitry Andric ParseStatus parseMemriOperand(OperandVector &Operands);
690b57cec5SDimitry Andric
70bdd1243dSDimitry Andric bool parseOperand(OperandVector &Operands, bool maybeReg);
710fca6ea1SDimitry Andric int parseRegisterName(MCRegister (*matchFn)(StringRef));
720b57cec5SDimitry Andric int parseRegisterName();
735ffd83dbSDimitry Andric int parseRegister(bool RestoreOnFailure = false);
740b57cec5SDimitry Andric bool tryParseRegisterOperand(OperandVector &Operands);
75*6c4b055cSDimitry Andric bool tryParseExpression(OperandVector &Operands, int64_t offset);
760b57cec5SDimitry Andric bool tryParseRelocExpression(OperandVector &Operands);
770b57cec5SDimitry Andric void eatComma();
780b57cec5SDimitry Andric
790b57cec5SDimitry Andric unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
800b57cec5SDimitry Andric unsigned Kind) override;
810b57cec5SDimitry Andric
toDREG(unsigned Reg,unsigned From=AVR::sub_lo)820b57cec5SDimitry Andric unsigned toDREG(unsigned Reg, unsigned From = AVR::sub_lo) {
830b57cec5SDimitry Andric MCRegisterClass const *Class = &AVRMCRegisterClasses[AVR::DREGSRegClassID];
840b57cec5SDimitry Andric return MRI->getMatchingSuperReg(Reg, From, Class);
850b57cec5SDimitry Andric }
860b57cec5SDimitry Andric
870b57cec5SDimitry Andric bool emit(MCInst &Instruction, SMLoc const &Loc, MCStreamer &Out) const;
880b57cec5SDimitry Andric bool invalidOperand(SMLoc const &Loc, OperandVector const &Operands,
890b57cec5SDimitry Andric uint64_t const &ErrorInfo);
900b57cec5SDimitry Andric bool missingFeature(SMLoc const &Loc, uint64_t const &ErrorInfo);
910b57cec5SDimitry Andric
9206c3fb27SDimitry Andric ParseStatus parseLiteralValues(unsigned SizeInBytes, SMLoc L);
930b57cec5SDimitry Andric
940b57cec5SDimitry Andric public:
AVRAsmParser(const MCSubtargetInfo & STI,MCAsmParser & Parser,const MCInstrInfo & MII,const MCTargetOptions & Options)950b57cec5SDimitry Andric AVRAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
960b57cec5SDimitry Andric const MCInstrInfo &MII, const MCTargetOptions &Options)
970b57cec5SDimitry Andric : MCTargetAsmParser(Options, STI, MII), STI(STI), Parser(Parser) {
980b57cec5SDimitry Andric MCAsmParserExtension::Initialize(Parser);
990b57cec5SDimitry Andric MRI = getContext().getRegisterInfo();
1000b57cec5SDimitry Andric
1010b57cec5SDimitry Andric setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
1020b57cec5SDimitry Andric }
1030b57cec5SDimitry Andric
getParser() const1040b57cec5SDimitry Andric MCAsmParser &getParser() const { return Parser; }
getLexer() const1050b57cec5SDimitry Andric MCAsmLexer &getLexer() const { return Parser.getLexer(); }
1060b57cec5SDimitry Andric };
1070b57cec5SDimitry Andric
1080b57cec5SDimitry Andric /// An parsed AVR assembly operand.
1090b57cec5SDimitry Andric class AVROperand : public MCParsedAsmOperand {
1100b57cec5SDimitry Andric typedef MCParsedAsmOperand Base;
1110b57cec5SDimitry Andric enum KindTy { k_Immediate, k_Register, k_Token, k_Memri } Kind;
1120b57cec5SDimitry Andric
1130b57cec5SDimitry Andric public:
AVROperand(StringRef Tok,SMLoc const & S)1140b57cec5SDimitry Andric AVROperand(StringRef Tok, SMLoc const &S)
11504eeddc0SDimitry Andric : Kind(k_Token), Tok(Tok), Start(S), End(S) {}
AVROperand(unsigned Reg,SMLoc const & S,SMLoc const & E)1160b57cec5SDimitry Andric AVROperand(unsigned Reg, SMLoc const &S, SMLoc const &E)
11704eeddc0SDimitry Andric : Kind(k_Register), RegImm({Reg, nullptr}), Start(S), End(E) {}
AVROperand(MCExpr const * Imm,SMLoc const & S,SMLoc const & E)1180b57cec5SDimitry Andric AVROperand(MCExpr const *Imm, SMLoc const &S, SMLoc const &E)
11904eeddc0SDimitry Andric : Kind(k_Immediate), RegImm({0, Imm}), Start(S), End(E) {}
AVROperand(unsigned Reg,MCExpr const * Imm,SMLoc const & S,SMLoc const & E)1200b57cec5SDimitry Andric AVROperand(unsigned Reg, MCExpr const *Imm, SMLoc const &S, SMLoc const &E)
12104eeddc0SDimitry Andric : Kind(k_Memri), RegImm({Reg, Imm}), Start(S), End(E) {}
1220b57cec5SDimitry Andric
1230b57cec5SDimitry Andric struct RegisterImmediate {
1240b57cec5SDimitry Andric unsigned Reg;
1250b57cec5SDimitry Andric MCExpr const *Imm;
1260b57cec5SDimitry Andric };
1270b57cec5SDimitry Andric union {
1280b57cec5SDimitry Andric StringRef Tok;
1290b57cec5SDimitry Andric RegisterImmediate RegImm;
1300b57cec5SDimitry Andric };
1310b57cec5SDimitry Andric
1320b57cec5SDimitry Andric SMLoc Start, End;
1330b57cec5SDimitry Andric
1340b57cec5SDimitry Andric public:
addRegOperands(MCInst & Inst,unsigned N) const1350b57cec5SDimitry Andric void addRegOperands(MCInst &Inst, unsigned N) const {
1360b57cec5SDimitry Andric assert(Kind == k_Register && "Unexpected operand kind");
1370b57cec5SDimitry Andric assert(N == 1 && "Invalid number of operands!");
1380b57cec5SDimitry Andric
1390b57cec5SDimitry Andric Inst.addOperand(MCOperand::createReg(getReg()));
1400b57cec5SDimitry Andric }
1410b57cec5SDimitry Andric
addExpr(MCInst & Inst,const MCExpr * Expr) const1420b57cec5SDimitry Andric void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1430b57cec5SDimitry Andric // Add as immediate when possible
1440b57cec5SDimitry Andric if (!Expr)
1450b57cec5SDimitry Andric Inst.addOperand(MCOperand::createImm(0));
1460b57cec5SDimitry Andric else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
1470b57cec5SDimitry Andric Inst.addOperand(MCOperand::createImm(CE->getValue()));
1480b57cec5SDimitry Andric else
1490b57cec5SDimitry Andric Inst.addOperand(MCOperand::createExpr(Expr));
1500b57cec5SDimitry Andric }
1510b57cec5SDimitry Andric
addImmOperands(MCInst & Inst,unsigned N) const1520b57cec5SDimitry Andric void addImmOperands(MCInst &Inst, unsigned N) const {
1530b57cec5SDimitry Andric assert(Kind == k_Immediate && "Unexpected operand kind");
1540b57cec5SDimitry Andric assert(N == 1 && "Invalid number of operands!");
1550b57cec5SDimitry Andric
1560b57cec5SDimitry Andric const MCExpr *Expr = getImm();
1570b57cec5SDimitry Andric addExpr(Inst, Expr);
1580b57cec5SDimitry Andric }
1590b57cec5SDimitry Andric
1600b57cec5SDimitry Andric /// Adds the contained reg+imm operand to an instruction.
addMemriOperands(MCInst & Inst,unsigned N) const1610b57cec5SDimitry Andric void addMemriOperands(MCInst &Inst, unsigned N) const {
1620b57cec5SDimitry Andric assert(Kind == k_Memri && "Unexpected operand kind");
1630b57cec5SDimitry Andric assert(N == 2 && "Invalid number of operands");
1640b57cec5SDimitry Andric
1650b57cec5SDimitry Andric Inst.addOperand(MCOperand::createReg(getReg()));
1660b57cec5SDimitry Andric addExpr(Inst, getImm());
1670b57cec5SDimitry Andric }
1680b57cec5SDimitry Andric
addImmCom8Operands(MCInst & Inst,unsigned N) const1690b57cec5SDimitry Andric void addImmCom8Operands(MCInst &Inst, unsigned N) const {
1700b57cec5SDimitry Andric assert(N == 1 && "Invalid number of operands!");
1710b57cec5SDimitry Andric // The operand is actually a imm8, but we have its bitwise
1720b57cec5SDimitry Andric // negation in the assembly source, so twiddle it here.
173e8d8bef9SDimitry Andric const auto *CE = cast<MCConstantExpr>(getImm());
1740b57cec5SDimitry Andric Inst.addOperand(MCOperand::createImm(~(uint8_t)CE->getValue()));
1750b57cec5SDimitry Andric }
1760b57cec5SDimitry Andric
isImmCom8() const1770b57cec5SDimitry Andric bool isImmCom8() const {
178349cc55cSDimitry Andric if (!isImm())
179349cc55cSDimitry Andric return false;
180e8d8bef9SDimitry Andric const auto *CE = dyn_cast<MCConstantExpr>(getImm());
181349cc55cSDimitry Andric if (!CE)
182349cc55cSDimitry Andric return false;
1830b57cec5SDimitry Andric int64_t Value = CE->getValue();
1840b57cec5SDimitry Andric return isUInt<8>(Value);
1850b57cec5SDimitry Andric }
1860b57cec5SDimitry Andric
isReg() const1875ffd83dbSDimitry Andric bool isReg() const override { return Kind == k_Register; }
isImm() const1885ffd83dbSDimitry Andric bool isImm() const override { return Kind == k_Immediate; }
isToken() const1895ffd83dbSDimitry Andric bool isToken() const override { return Kind == k_Token; }
isMem() const1905ffd83dbSDimitry Andric bool isMem() const override { return Kind == k_Memri; }
isMemri() const1910b57cec5SDimitry Andric bool isMemri() const { return Kind == k_Memri; }
1920b57cec5SDimitry Andric
getToken() const1930b57cec5SDimitry Andric StringRef getToken() const {
1940b57cec5SDimitry Andric assert(Kind == k_Token && "Invalid access!");
1950b57cec5SDimitry Andric return Tok;
1960b57cec5SDimitry Andric }
1970b57cec5SDimitry Andric
getReg() const1980fca6ea1SDimitry Andric MCRegister getReg() const override {
1990b57cec5SDimitry Andric assert((Kind == k_Register || Kind == k_Memri) && "Invalid access!");
2000b57cec5SDimitry Andric
2010b57cec5SDimitry Andric return RegImm.Reg;
2020b57cec5SDimitry Andric }
2030b57cec5SDimitry Andric
getImm() const2040b57cec5SDimitry Andric const MCExpr *getImm() const {
2050b57cec5SDimitry Andric assert((Kind == k_Immediate || Kind == k_Memri) && "Invalid access!");
2060b57cec5SDimitry Andric return RegImm.Imm;
2070b57cec5SDimitry Andric }
2080b57cec5SDimitry Andric
CreateToken(StringRef Str,SMLoc S)2090b57cec5SDimitry Andric static std::unique_ptr<AVROperand> CreateToken(StringRef Str, SMLoc S) {
2108bcb0991SDimitry Andric return std::make_unique<AVROperand>(Str, S);
2110b57cec5SDimitry Andric }
2120b57cec5SDimitry Andric
CreateReg(unsigned RegNum,SMLoc S,SMLoc E)2130b57cec5SDimitry Andric static std::unique_ptr<AVROperand> CreateReg(unsigned RegNum, SMLoc S,
2140b57cec5SDimitry Andric SMLoc E) {
2158bcb0991SDimitry Andric return std::make_unique<AVROperand>(RegNum, S, E);
2160b57cec5SDimitry Andric }
2170b57cec5SDimitry Andric
CreateImm(const MCExpr * Val,SMLoc S,SMLoc E)2180b57cec5SDimitry Andric static std::unique_ptr<AVROperand> CreateImm(const MCExpr *Val, SMLoc S,
2190b57cec5SDimitry Andric SMLoc E) {
2208bcb0991SDimitry Andric return std::make_unique<AVROperand>(Val, S, E);
2210b57cec5SDimitry Andric }
2220b57cec5SDimitry Andric
2230b57cec5SDimitry Andric static std::unique_ptr<AVROperand>
CreateMemri(unsigned RegNum,const MCExpr * Val,SMLoc S,SMLoc E)2240b57cec5SDimitry Andric CreateMemri(unsigned RegNum, const MCExpr *Val, SMLoc S, SMLoc E) {
2258bcb0991SDimitry Andric return std::make_unique<AVROperand>(RegNum, Val, S, E);
2260b57cec5SDimitry Andric }
2270b57cec5SDimitry Andric
makeToken(StringRef Token)2280b57cec5SDimitry Andric void makeToken(StringRef Token) {
2290b57cec5SDimitry Andric Kind = k_Token;
2300b57cec5SDimitry Andric Tok = Token;
2310b57cec5SDimitry Andric }
2320b57cec5SDimitry Andric
makeReg(unsigned RegNo)2330b57cec5SDimitry Andric void makeReg(unsigned RegNo) {
2340b57cec5SDimitry Andric Kind = k_Register;
2350b57cec5SDimitry Andric RegImm = {RegNo, nullptr};
2360b57cec5SDimitry Andric }
2370b57cec5SDimitry Andric
makeImm(MCExpr const * Ex)2380b57cec5SDimitry Andric void makeImm(MCExpr const *Ex) {
2390b57cec5SDimitry Andric Kind = k_Immediate;
2400b57cec5SDimitry Andric RegImm = {0, Ex};
2410b57cec5SDimitry Andric }
2420b57cec5SDimitry Andric
makeMemri(unsigned RegNo,MCExpr const * Imm)2430b57cec5SDimitry Andric void makeMemri(unsigned RegNo, MCExpr const *Imm) {
2440b57cec5SDimitry Andric Kind = k_Memri;
2450b57cec5SDimitry Andric RegImm = {RegNo, Imm};
2460b57cec5SDimitry Andric }
2470b57cec5SDimitry Andric
getStartLoc() const2485ffd83dbSDimitry Andric SMLoc getStartLoc() const override { return Start; }
getEndLoc() const2495ffd83dbSDimitry Andric SMLoc getEndLoc() const override { return End; }
2500b57cec5SDimitry Andric
print(raw_ostream & O) const2515ffd83dbSDimitry Andric void print(raw_ostream &O) const override {
2520b57cec5SDimitry Andric switch (Kind) {
2530b57cec5SDimitry Andric case k_Token:
2540b57cec5SDimitry Andric O << "Token: \"" << getToken() << "\"";
2550b57cec5SDimitry Andric break;
2560b57cec5SDimitry Andric case k_Register:
2570b57cec5SDimitry Andric O << "Register: " << getReg();
2580b57cec5SDimitry Andric break;
2590b57cec5SDimitry Andric case k_Immediate:
2600b57cec5SDimitry Andric O << "Immediate: \"" << *getImm() << "\"";
2610b57cec5SDimitry Andric break;
2620b57cec5SDimitry Andric case k_Memri: {
2630b57cec5SDimitry Andric // only manually print the size for non-negative values,
2640b57cec5SDimitry Andric // as the sign is inserted automatically.
2650b57cec5SDimitry Andric O << "Memri: \"" << getReg() << '+' << *getImm() << "\"";
2660b57cec5SDimitry Andric break;
2670b57cec5SDimitry Andric }
2680b57cec5SDimitry Andric }
2690b57cec5SDimitry Andric O << "\n";
2700b57cec5SDimitry Andric }
2710b57cec5SDimitry Andric };
2720b57cec5SDimitry Andric
2730b57cec5SDimitry Andric } // end anonymous namespace.
2740b57cec5SDimitry Andric
2750b57cec5SDimitry Andric // Auto-generated Match Functions
2760b57cec5SDimitry Andric
2770b57cec5SDimitry Andric /// Maps from the set of all register names to a register number.
2780b57cec5SDimitry Andric /// \note Generated by TableGen.
2790fca6ea1SDimitry Andric static MCRegister MatchRegisterName(StringRef Name);
2800b57cec5SDimitry Andric
2810b57cec5SDimitry Andric /// Maps from the set of all alternative registernames to a register number.
2820b57cec5SDimitry Andric /// \note Generated by TableGen.
2830fca6ea1SDimitry Andric static MCRegister MatchRegisterAltName(StringRef Name);
2840b57cec5SDimitry Andric
invalidOperand(SMLoc const & Loc,OperandVector const & Operands,uint64_t const & ErrorInfo)2850b57cec5SDimitry Andric bool AVRAsmParser::invalidOperand(SMLoc const &Loc,
2860b57cec5SDimitry Andric OperandVector const &Operands,
2870b57cec5SDimitry Andric uint64_t const &ErrorInfo) {
2880b57cec5SDimitry Andric SMLoc ErrorLoc = Loc;
28904eeddc0SDimitry Andric char const *Diag = nullptr;
2900b57cec5SDimitry Andric
2910b57cec5SDimitry Andric if (ErrorInfo != ~0U) {
2920b57cec5SDimitry Andric if (ErrorInfo >= Operands.size()) {
2930b57cec5SDimitry Andric Diag = "too few operands for instruction.";
2940b57cec5SDimitry Andric } else {
2950b57cec5SDimitry Andric AVROperand const &Op = (AVROperand const &)*Operands[ErrorInfo];
2960b57cec5SDimitry Andric
2970b57cec5SDimitry Andric // TODO: See if we can do a better error than just "invalid ...".
2980b57cec5SDimitry Andric if (Op.getStartLoc() != SMLoc()) {
2990b57cec5SDimitry Andric ErrorLoc = Op.getStartLoc();
3000b57cec5SDimitry Andric }
3010b57cec5SDimitry Andric }
3020b57cec5SDimitry Andric }
3030b57cec5SDimitry Andric
3040b57cec5SDimitry Andric if (!Diag) {
3050b57cec5SDimitry Andric Diag = "invalid operand for instruction";
3060b57cec5SDimitry Andric }
3070b57cec5SDimitry Andric
3080b57cec5SDimitry Andric return Error(ErrorLoc, Diag);
3090b57cec5SDimitry Andric }
3100b57cec5SDimitry Andric
missingFeature(llvm::SMLoc const & Loc,uint64_t const & ErrorInfo)3110b57cec5SDimitry Andric bool AVRAsmParser::missingFeature(llvm::SMLoc const &Loc,
3120b57cec5SDimitry Andric uint64_t const &ErrorInfo) {
3130b57cec5SDimitry Andric return Error(Loc, "instruction requires a CPU feature not currently enabled");
3140b57cec5SDimitry Andric }
3150b57cec5SDimitry Andric
emit(MCInst & Inst,SMLoc const & Loc,MCStreamer & Out) const3160b57cec5SDimitry Andric bool AVRAsmParser::emit(MCInst &Inst, SMLoc const &Loc, MCStreamer &Out) const {
3170b57cec5SDimitry Andric Inst.setLoc(Loc);
3185ffd83dbSDimitry Andric Out.emitInstruction(Inst, STI);
3190b57cec5SDimitry Andric
3200b57cec5SDimitry Andric return false;
3210b57cec5SDimitry Andric }
3220b57cec5SDimitry Andric
MatchAndEmitInstruction(SMLoc Loc,unsigned & Opcode,OperandVector & Operands,MCStreamer & Out,uint64_t & ErrorInfo,bool MatchingInlineAsm)3230b57cec5SDimitry Andric bool AVRAsmParser::MatchAndEmitInstruction(SMLoc Loc, unsigned &Opcode,
3240b57cec5SDimitry Andric OperandVector &Operands,
3250b57cec5SDimitry Andric MCStreamer &Out, uint64_t &ErrorInfo,
3260b57cec5SDimitry Andric bool MatchingInlineAsm) {
3270b57cec5SDimitry Andric MCInst Inst;
3280b57cec5SDimitry Andric unsigned MatchResult =
3290b57cec5SDimitry Andric MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
3300b57cec5SDimitry Andric
3310b57cec5SDimitry Andric switch (MatchResult) {
332349cc55cSDimitry Andric case Match_Success:
333349cc55cSDimitry Andric return emit(Inst, Loc, Out);
334349cc55cSDimitry Andric case Match_MissingFeature:
335349cc55cSDimitry Andric return missingFeature(Loc, ErrorInfo);
336349cc55cSDimitry Andric case Match_InvalidOperand:
337349cc55cSDimitry Andric return invalidOperand(Loc, Operands, ErrorInfo);
338349cc55cSDimitry Andric case Match_MnemonicFail:
339349cc55cSDimitry Andric return Error(Loc, "invalid instruction");
34081ad6265SDimitry Andric case Match_InvalidRegisterOnTiny:
34181ad6265SDimitry Andric return Error(Loc, "invalid register on avrtiny");
342349cc55cSDimitry Andric default:
343349cc55cSDimitry Andric return true;
3440b57cec5SDimitry Andric }
3450b57cec5SDimitry Andric }
3460b57cec5SDimitry Andric
3470b57cec5SDimitry Andric /// Parses a register name using a given matching function.
3480b57cec5SDimitry Andric /// Checks for lowercase or uppercase if necessary.
parseRegisterName(MCRegister (* matchFn)(StringRef))3490fca6ea1SDimitry Andric int AVRAsmParser::parseRegisterName(MCRegister (*matchFn)(StringRef)) {
3500b57cec5SDimitry Andric StringRef Name = Parser.getTok().getString();
3510b57cec5SDimitry Andric
3520b57cec5SDimitry Andric int RegNum = matchFn(Name);
3530b57cec5SDimitry Andric
3540b57cec5SDimitry Andric // GCC supports case insensitive register names. Some of the AVR registers
3550b57cec5SDimitry Andric // are all lower case, some are all upper case but non are mixed. We prefer
3560b57cec5SDimitry Andric // to use the original names in the register definitions. That is why we
3570b57cec5SDimitry Andric // have to test both upper and lower case here.
3580b57cec5SDimitry Andric if (RegNum == AVR::NoRegister) {
3590b57cec5SDimitry Andric RegNum = matchFn(Name.lower());
3600b57cec5SDimitry Andric }
3610b57cec5SDimitry Andric if (RegNum == AVR::NoRegister) {
3620b57cec5SDimitry Andric RegNum = matchFn(Name.upper());
3630b57cec5SDimitry Andric }
3640b57cec5SDimitry Andric
3650b57cec5SDimitry Andric return RegNum;
3660b57cec5SDimitry Andric }
3670b57cec5SDimitry Andric
parseRegisterName()3680b57cec5SDimitry Andric int AVRAsmParser::parseRegisterName() {
3690b57cec5SDimitry Andric int RegNum = parseRegisterName(&MatchRegisterName);
3700b57cec5SDimitry Andric
3710b57cec5SDimitry Andric if (RegNum == AVR::NoRegister)
3720b57cec5SDimitry Andric RegNum = parseRegisterName(&MatchRegisterAltName);
3730b57cec5SDimitry Andric
3740b57cec5SDimitry Andric return RegNum;
3750b57cec5SDimitry Andric }
3760b57cec5SDimitry Andric
parseRegister(bool RestoreOnFailure)3775ffd83dbSDimitry Andric int AVRAsmParser::parseRegister(bool RestoreOnFailure) {
3780b57cec5SDimitry Andric int RegNum = AVR::NoRegister;
3790b57cec5SDimitry Andric
3800b57cec5SDimitry Andric if (Parser.getTok().is(AsmToken::Identifier)) {
3810b57cec5SDimitry Andric // Check for register pair syntax
3820b57cec5SDimitry Andric if (Parser.getLexer().peekTok().is(AsmToken::Colon)) {
3835ffd83dbSDimitry Andric AsmToken HighTok = Parser.getTok();
3840b57cec5SDimitry Andric Parser.Lex();
3855ffd83dbSDimitry Andric AsmToken ColonTok = Parser.getTok();
3860b57cec5SDimitry Andric Parser.Lex(); // Eat high (odd) register and colon
3870b57cec5SDimitry Andric
3880b57cec5SDimitry Andric if (Parser.getTok().is(AsmToken::Identifier)) {
3890b57cec5SDimitry Andric // Convert lower (even) register to DREG
3900b57cec5SDimitry Andric RegNum = toDREG(parseRegisterName());
3910b57cec5SDimitry Andric }
3925ffd83dbSDimitry Andric if (RegNum == AVR::NoRegister && RestoreOnFailure) {
3935ffd83dbSDimitry Andric getLexer().UnLex(std::move(ColonTok));
3945ffd83dbSDimitry Andric getLexer().UnLex(std::move(HighTok));
3955ffd83dbSDimitry Andric }
3960b57cec5SDimitry Andric } else {
3970b57cec5SDimitry Andric RegNum = parseRegisterName();
3980b57cec5SDimitry Andric }
3990b57cec5SDimitry Andric }
4000b57cec5SDimitry Andric return RegNum;
4010b57cec5SDimitry Andric }
4020b57cec5SDimitry Andric
tryParseRegisterOperand(OperandVector & Operands)4030b57cec5SDimitry Andric bool AVRAsmParser::tryParseRegisterOperand(OperandVector &Operands) {
4040b57cec5SDimitry Andric int RegNo = parseRegister();
4050b57cec5SDimitry Andric
4060b57cec5SDimitry Andric if (RegNo == AVR::NoRegister)
4070b57cec5SDimitry Andric return true;
4080b57cec5SDimitry Andric
40981ad6265SDimitry Andric // Reject R0~R15 on avrtiny.
41081ad6265SDimitry Andric if (AVR::R0 <= RegNo && RegNo <= AVR::R15 &&
41181ad6265SDimitry Andric STI.hasFeature(AVR::FeatureTinyEncoding))
41281ad6265SDimitry Andric return Error(Parser.getTok().getLoc(), "invalid register on avrtiny");
41381ad6265SDimitry Andric
4140b57cec5SDimitry Andric AsmToken const &T = Parser.getTok();
4150b57cec5SDimitry Andric Operands.push_back(AVROperand::CreateReg(RegNo, T.getLoc(), T.getEndLoc()));
4160b57cec5SDimitry Andric Parser.Lex(); // Eat register token.
4170b57cec5SDimitry Andric
4180b57cec5SDimitry Andric return false;
4190b57cec5SDimitry Andric }
4200b57cec5SDimitry Andric
tryParseExpression(OperandVector & Operands,int64_t offset)421*6c4b055cSDimitry Andric bool AVRAsmParser::tryParseExpression(OperandVector &Operands, int64_t offset) {
4220b57cec5SDimitry Andric SMLoc S = Parser.getTok().getLoc();
4230b57cec5SDimitry Andric
4240b57cec5SDimitry Andric if (!tryParseRelocExpression(Operands))
4250b57cec5SDimitry Andric return false;
4260b57cec5SDimitry Andric
4270b57cec5SDimitry Andric if ((Parser.getTok().getKind() == AsmToken::Plus ||
4280b57cec5SDimitry Andric Parser.getTok().getKind() == AsmToken::Minus) &&
4290b57cec5SDimitry Andric Parser.getLexer().peekTok().getKind() == AsmToken::Identifier) {
4300b57cec5SDimitry Andric // Don't handle this case - it should be split into two
4310b57cec5SDimitry Andric // separate tokens.
4320b57cec5SDimitry Andric return true;
4330b57cec5SDimitry Andric }
4340b57cec5SDimitry Andric
4350b57cec5SDimitry Andric // Parse (potentially inner) expression
4360b57cec5SDimitry Andric MCExpr const *Expression;
4370b57cec5SDimitry Andric if (getParser().parseExpression(Expression))
4380b57cec5SDimitry Andric return true;
4390b57cec5SDimitry Andric
440*6c4b055cSDimitry Andric if (offset) {
441*6c4b055cSDimitry Andric Expression = MCBinaryExpr::createAdd(
442*6c4b055cSDimitry Andric Expression, MCConstantExpr::create(offset, getContext()), getContext());
443*6c4b055cSDimitry Andric }
444*6c4b055cSDimitry Andric
4450b57cec5SDimitry Andric SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4460b57cec5SDimitry Andric Operands.push_back(AVROperand::CreateImm(Expression, S, E));
4470b57cec5SDimitry Andric return false;
4480b57cec5SDimitry Andric }
4490b57cec5SDimitry Andric
tryParseRelocExpression(OperandVector & Operands)4500b57cec5SDimitry Andric bool AVRAsmParser::tryParseRelocExpression(OperandVector &Operands) {
4510b57cec5SDimitry Andric bool isNegated = false;
4520b57cec5SDimitry Andric AVRMCExpr::VariantKind ModifierKind = AVRMCExpr::VK_AVR_None;
4530b57cec5SDimitry Andric
4540b57cec5SDimitry Andric SMLoc S = Parser.getTok().getLoc();
4550b57cec5SDimitry Andric
456bdd1243dSDimitry Andric // Reject the form in which sign comes first. This behaviour is
457bdd1243dSDimitry Andric // in accordance with avr-gcc.
4580b57cec5SDimitry Andric AsmToken::TokenKind CurTok = Parser.getLexer().getKind();
4590b57cec5SDimitry Andric if (CurTok == AsmToken::Minus || CurTok == AsmToken::Plus)
460bdd1243dSDimitry Andric return true;
461bdd1243dSDimitry Andric
462bdd1243dSDimitry Andric // Check for sign.
463bdd1243dSDimitry Andric AsmToken tokens[2];
464bdd1243dSDimitry Andric if (Parser.getLexer().peekTokens(tokens) == 2)
465bdd1243dSDimitry Andric if (tokens[0].getKind() == AsmToken::LParen &&
466bdd1243dSDimitry Andric tokens[1].getKind() == AsmToken::Minus)
467bdd1243dSDimitry Andric isNegated = true;
4680b57cec5SDimitry Andric
4690b57cec5SDimitry Andric // Check if we have a target specific modifier (lo8, hi8, &c)
470bdd1243dSDimitry Andric if (CurTok != AsmToken::Identifier ||
4710b57cec5SDimitry Andric Parser.getLexer().peekTok().getKind() != AsmToken::LParen) {
4720b57cec5SDimitry Andric // Not a reloc expr
4730b57cec5SDimitry Andric return true;
4740b57cec5SDimitry Andric }
4750b57cec5SDimitry Andric StringRef ModifierName = Parser.getTok().getString();
476349cc55cSDimitry Andric ModifierKind = AVRMCExpr::getKindByName(ModifierName);
4770b57cec5SDimitry Andric
4780b57cec5SDimitry Andric if (ModifierKind != AVRMCExpr::VK_AVR_None) {
4790b57cec5SDimitry Andric Parser.Lex();
4800b57cec5SDimitry Andric Parser.Lex(); // Eat modifier name and parenthesis
4810b57cec5SDimitry Andric if (Parser.getTok().getString() == GENERATE_STUBS &&
4820b57cec5SDimitry Andric Parser.getTok().getKind() == AsmToken::Identifier) {
4830b57cec5SDimitry Andric std::string GSModName = ModifierName.str() + "_" + GENERATE_STUBS;
484349cc55cSDimitry Andric ModifierKind = AVRMCExpr::getKindByName(GSModName);
4850b57cec5SDimitry Andric if (ModifierKind != AVRMCExpr::VK_AVR_None)
4860b57cec5SDimitry Andric Parser.Lex(); // Eat gs modifier name
4870b57cec5SDimitry Andric }
4880b57cec5SDimitry Andric } else {
4890b57cec5SDimitry Andric return Error(Parser.getTok().getLoc(), "unknown modifier");
4900b57cec5SDimitry Andric }
4910b57cec5SDimitry Andric
4920b57cec5SDimitry Andric if (tokens[1].getKind() == AsmToken::Minus ||
4930b57cec5SDimitry Andric tokens[1].getKind() == AsmToken::Plus) {
4940b57cec5SDimitry Andric Parser.Lex();
4950b57cec5SDimitry Andric assert(Parser.getTok().getKind() == AsmToken::LParen);
4960b57cec5SDimitry Andric Parser.Lex(); // Eat the sign and parenthesis
4970b57cec5SDimitry Andric }
4980b57cec5SDimitry Andric
4990b57cec5SDimitry Andric MCExpr const *InnerExpression;
5000b57cec5SDimitry Andric if (getParser().parseExpression(InnerExpression))
5010b57cec5SDimitry Andric return true;
5020b57cec5SDimitry Andric
5030b57cec5SDimitry Andric if (tokens[1].getKind() == AsmToken::Minus ||
5040b57cec5SDimitry Andric tokens[1].getKind() == AsmToken::Plus) {
5050b57cec5SDimitry Andric assert(Parser.getTok().getKind() == AsmToken::RParen);
5060b57cec5SDimitry Andric Parser.Lex(); // Eat closing parenthesis
5070b57cec5SDimitry Andric }
5080b57cec5SDimitry Andric
5090b57cec5SDimitry Andric // If we have a modifier wrap the inner expression
5100b57cec5SDimitry Andric assert(Parser.getTok().getKind() == AsmToken::RParen);
5110b57cec5SDimitry Andric Parser.Lex(); // Eat closing parenthesis
5120b57cec5SDimitry Andric
513349cc55cSDimitry Andric MCExpr const *Expression =
514349cc55cSDimitry Andric AVRMCExpr::create(ModifierKind, InnerExpression, isNegated, getContext());
5150b57cec5SDimitry Andric
5160b57cec5SDimitry Andric SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5170b57cec5SDimitry Andric Operands.push_back(AVROperand::CreateImm(Expression, S, E));
5180b57cec5SDimitry Andric
5190b57cec5SDimitry Andric return false;
5200b57cec5SDimitry Andric }
5210b57cec5SDimitry Andric
parseOperand(OperandVector & Operands,bool maybeReg)522bdd1243dSDimitry Andric bool AVRAsmParser::parseOperand(OperandVector &Operands, bool maybeReg) {
5230b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "parseOperand\n");
5240b57cec5SDimitry Andric
5250b57cec5SDimitry Andric switch (getLexer().getKind()) {
5260b57cec5SDimitry Andric default:
5270b57cec5SDimitry Andric return Error(Parser.getTok().getLoc(), "unexpected token in operand");
5280b57cec5SDimitry Andric
5290b57cec5SDimitry Andric case AsmToken::Identifier:
530bdd1243dSDimitry Andric // Try to parse a register, fall through to the next case if it fails.
531bdd1243dSDimitry Andric if (maybeReg && !tryParseRegisterOperand(Operands)) {
5320b57cec5SDimitry Andric return false;
5330b57cec5SDimitry Andric }
534bdd1243dSDimitry Andric [[fallthrough]];
5350b57cec5SDimitry Andric case AsmToken::LParen:
5360b57cec5SDimitry Andric case AsmToken::Integer:
537*6c4b055cSDimitry Andric return tryParseExpression(Operands, 0);
5380b57cec5SDimitry Andric case AsmToken::Dot:
539*6c4b055cSDimitry Andric return tryParseExpression(Operands, 2);
5400b57cec5SDimitry Andric case AsmToken::Plus:
5410b57cec5SDimitry Andric case AsmToken::Minus: {
5420b57cec5SDimitry Andric // If the sign preceeds a number, parse the number,
5430b57cec5SDimitry Andric // otherwise treat the sign a an independent token.
5440b57cec5SDimitry Andric switch (getLexer().peekTok().getKind()) {
5450b57cec5SDimitry Andric case AsmToken::Integer:
5460b57cec5SDimitry Andric case AsmToken::BigNum:
5470b57cec5SDimitry Andric case AsmToken::Identifier:
5480b57cec5SDimitry Andric case AsmToken::Real:
549*6c4b055cSDimitry Andric if (!tryParseExpression(Operands, 0))
5500b57cec5SDimitry Andric return false;
5510b57cec5SDimitry Andric break;
5520b57cec5SDimitry Andric default:
5530b57cec5SDimitry Andric break;
5540b57cec5SDimitry Andric }
5550b57cec5SDimitry Andric // Treat the token as an independent token.
5560b57cec5SDimitry Andric Operands.push_back(AVROperand::CreateToken(Parser.getTok().getString(),
5570b57cec5SDimitry Andric Parser.getTok().getLoc()));
5580b57cec5SDimitry Andric Parser.Lex(); // Eat the token.
5590b57cec5SDimitry Andric return false;
5600b57cec5SDimitry Andric }
5610b57cec5SDimitry Andric }
5620b57cec5SDimitry Andric
5630b57cec5SDimitry Andric // Could not parse operand
5640b57cec5SDimitry Andric return true;
5650b57cec5SDimitry Andric }
5660b57cec5SDimitry Andric
parseMemriOperand(OperandVector & Operands)5675f757f3fSDimitry Andric ParseStatus AVRAsmParser::parseMemriOperand(OperandVector &Operands) {
5680b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "parseMemriOperand()\n");
5690b57cec5SDimitry Andric
5700b57cec5SDimitry Andric SMLoc E, S;
5710b57cec5SDimitry Andric MCExpr const *Expression;
5720b57cec5SDimitry Andric int RegNo;
5730b57cec5SDimitry Andric
5740b57cec5SDimitry Andric // Parse register.
5750b57cec5SDimitry Andric {
5760b57cec5SDimitry Andric RegNo = parseRegister();
5770b57cec5SDimitry Andric
5780b57cec5SDimitry Andric if (RegNo == AVR::NoRegister)
5795f757f3fSDimitry Andric return ParseStatus::Failure;
5800b57cec5SDimitry Andric
5810b57cec5SDimitry Andric S = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5820b57cec5SDimitry Andric Parser.Lex(); // Eat register token.
5830b57cec5SDimitry Andric }
5840b57cec5SDimitry Andric
5850b57cec5SDimitry Andric // Parse immediate;
5860b57cec5SDimitry Andric {
5870b57cec5SDimitry Andric if (getParser().parseExpression(Expression))
5885f757f3fSDimitry Andric return ParseStatus::Failure;
5890b57cec5SDimitry Andric
5900b57cec5SDimitry Andric E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5910b57cec5SDimitry Andric }
5920b57cec5SDimitry Andric
5930b57cec5SDimitry Andric Operands.push_back(AVROperand::CreateMemri(RegNo, Expression, S, E));
5940b57cec5SDimitry Andric
5955f757f3fSDimitry Andric return ParseStatus::Success;
5960b57cec5SDimitry Andric }
5970b57cec5SDimitry Andric
parseRegister(MCRegister & Reg,SMLoc & StartLoc,SMLoc & EndLoc)5985f757f3fSDimitry Andric bool AVRAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
5990b57cec5SDimitry Andric SMLoc &EndLoc) {
6000b57cec5SDimitry Andric StartLoc = Parser.getTok().getLoc();
6015f757f3fSDimitry Andric Reg = parseRegister(/*RestoreOnFailure=*/false);
6020b57cec5SDimitry Andric EndLoc = Parser.getTok().getLoc();
6030b57cec5SDimitry Andric
6045f757f3fSDimitry Andric return Reg == AVR::NoRegister;
6050b57cec5SDimitry Andric }
6060b57cec5SDimitry Andric
tryParseRegister(MCRegister & Reg,SMLoc & StartLoc,SMLoc & EndLoc)6075f757f3fSDimitry Andric ParseStatus AVRAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
6085ffd83dbSDimitry Andric SMLoc &EndLoc) {
6095ffd83dbSDimitry Andric StartLoc = Parser.getTok().getLoc();
6105f757f3fSDimitry Andric Reg = parseRegister(/*RestoreOnFailure=*/true);
6115ffd83dbSDimitry Andric EndLoc = Parser.getTok().getLoc();
6125ffd83dbSDimitry Andric
6135f757f3fSDimitry Andric if (Reg == AVR::NoRegister)
6145f757f3fSDimitry Andric return ParseStatus::NoMatch;
6155f757f3fSDimitry Andric return ParseStatus::Success;
6165ffd83dbSDimitry Andric }
6175ffd83dbSDimitry Andric
eatComma()6180b57cec5SDimitry Andric void AVRAsmParser::eatComma() {
6190b57cec5SDimitry Andric if (getLexer().is(AsmToken::Comma)) {
6200b57cec5SDimitry Andric Parser.Lex();
6210b57cec5SDimitry Andric } else {
6220b57cec5SDimitry Andric // GCC allows commas to be omitted.
6230b57cec5SDimitry Andric }
6240b57cec5SDimitry Andric }
6250b57cec5SDimitry Andric
ParseInstruction(ParseInstructionInfo & Info,StringRef Mnemonic,SMLoc NameLoc,OperandVector & Operands)6260b57cec5SDimitry Andric bool AVRAsmParser::ParseInstruction(ParseInstructionInfo &Info,
6270b57cec5SDimitry Andric StringRef Mnemonic, SMLoc NameLoc,
6280b57cec5SDimitry Andric OperandVector &Operands) {
6290b57cec5SDimitry Andric Operands.push_back(AVROperand::CreateToken(Mnemonic, NameLoc));
6300b57cec5SDimitry Andric
631bdd1243dSDimitry Andric int OperandNum = -1;
6320b57cec5SDimitry Andric while (getLexer().isNot(AsmToken::EndOfStatement)) {
633bdd1243dSDimitry Andric OperandNum++;
634bdd1243dSDimitry Andric if (OperandNum > 0)
635349cc55cSDimitry Andric eatComma();
6360b57cec5SDimitry Andric
6375f757f3fSDimitry Andric ParseStatus ParseRes = MatchOperandParserImpl(Operands, Mnemonic);
6380b57cec5SDimitry Andric
6395f757f3fSDimitry Andric if (ParseRes.isSuccess())
6400b57cec5SDimitry Andric continue;
6410b57cec5SDimitry Andric
6425f757f3fSDimitry Andric if (ParseRes.isFailure()) {
6430b57cec5SDimitry Andric SMLoc Loc = getLexer().getLoc();
6440b57cec5SDimitry Andric Parser.eatToEndOfStatement();
6450b57cec5SDimitry Andric
6460b57cec5SDimitry Andric return Error(Loc, "failed to parse register and immediate pair");
6470b57cec5SDimitry Andric }
6480b57cec5SDimitry Andric
649bdd1243dSDimitry Andric // These specific operands should be treated as addresses/symbols/labels,
650bdd1243dSDimitry Andric // other than registers.
651bdd1243dSDimitry Andric bool maybeReg = true;
652*6c4b055cSDimitry Andric
653bdd1243dSDimitry Andric if (OperandNum == 1) {
654bdd1243dSDimitry Andric std::array<StringRef, 8> Insts = {"lds", "adiw", "sbiw", "ldi"};
655bdd1243dSDimitry Andric for (auto Inst : Insts) {
656bdd1243dSDimitry Andric if (Inst == Mnemonic) {
657bdd1243dSDimitry Andric maybeReg = false;
658bdd1243dSDimitry Andric break;
659bdd1243dSDimitry Andric }
660bdd1243dSDimitry Andric }
661bdd1243dSDimitry Andric } else if (OperandNum == 0) {
662bdd1243dSDimitry Andric std::array<StringRef, 8> Insts = {"sts", "call", "rcall", "rjmp", "jmp"};
663bdd1243dSDimitry Andric for (auto Inst : Insts) {
664bdd1243dSDimitry Andric if (Inst == Mnemonic) {
665bdd1243dSDimitry Andric maybeReg = false;
666bdd1243dSDimitry Andric break;
667bdd1243dSDimitry Andric }
668bdd1243dSDimitry Andric }
669bdd1243dSDimitry Andric }
670bdd1243dSDimitry Andric
671bdd1243dSDimitry Andric if (parseOperand(Operands, maybeReg)) {
6720b57cec5SDimitry Andric SMLoc Loc = getLexer().getLoc();
6730b57cec5SDimitry Andric Parser.eatToEndOfStatement();
6740b57cec5SDimitry Andric return Error(Loc, "unexpected token in argument list");
6750b57cec5SDimitry Andric }
6760b57cec5SDimitry Andric }
6770b57cec5SDimitry Andric Parser.Lex(); // Consume the EndOfStatement
6780b57cec5SDimitry Andric return false;
6790b57cec5SDimitry Andric }
6800b57cec5SDimitry Andric
parseDirective(llvm::AsmToken DirectiveID)68106c3fb27SDimitry Andric ParseStatus AVRAsmParser::parseDirective(llvm::AsmToken DirectiveID) {
6820b57cec5SDimitry Andric StringRef IDVal = DirectiveID.getIdentifier();
68306c3fb27SDimitry Andric if (IDVal.lower() == ".long")
68406c3fb27SDimitry Andric return parseLiteralValues(SIZE_LONG, DirectiveID.getLoc());
68506c3fb27SDimitry Andric if (IDVal.lower() == ".word" || IDVal.lower() == ".short")
68606c3fb27SDimitry Andric return parseLiteralValues(SIZE_WORD, DirectiveID.getLoc());
68706c3fb27SDimitry Andric if (IDVal.lower() == ".byte")
68806c3fb27SDimitry Andric return parseLiteralValues(1, DirectiveID.getLoc());
68906c3fb27SDimitry Andric return ParseStatus::NoMatch;
6900b57cec5SDimitry Andric }
6910b57cec5SDimitry Andric
parseLiteralValues(unsigned SizeInBytes,SMLoc L)69206c3fb27SDimitry Andric ParseStatus AVRAsmParser::parseLiteralValues(unsigned SizeInBytes, SMLoc L) {
6930b57cec5SDimitry Andric MCAsmParser &Parser = getParser();
6940b57cec5SDimitry Andric AVRMCELFStreamer &AVRStreamer =
6950b57cec5SDimitry Andric static_cast<AVRMCELFStreamer &>(Parser.getStreamer());
6960b57cec5SDimitry Andric AsmToken Tokens[2];
6970b57cec5SDimitry Andric size_t ReadCount = Parser.getLexer().peekTokens(Tokens);
6980b57cec5SDimitry Andric if (ReadCount == 2 && Parser.getTok().getKind() == AsmToken::Identifier &&
6990b57cec5SDimitry Andric Tokens[0].getKind() == AsmToken::Minus &&
7000b57cec5SDimitry Andric Tokens[1].getKind() == AsmToken::Identifier) {
7010b57cec5SDimitry Andric MCSymbol *Symbol = getContext().getOrCreateSymbol(".text");
7025ffd83dbSDimitry Andric AVRStreamer.emitValueForModiferKind(Symbol, SizeInBytes, L,
7030b57cec5SDimitry Andric AVRMCExpr::VK_AVR_None);
70406c3fb27SDimitry Andric return ParseStatus::NoMatch;
7050b57cec5SDimitry Andric }
7060b57cec5SDimitry Andric
7070b57cec5SDimitry Andric if (Parser.getTok().getKind() == AsmToken::Identifier &&
7080b57cec5SDimitry Andric Parser.getLexer().peekTok().getKind() == AsmToken::LParen) {
7090b57cec5SDimitry Andric StringRef ModifierName = Parser.getTok().getString();
7100b57cec5SDimitry Andric AVRMCExpr::VariantKind ModifierKind =
711349cc55cSDimitry Andric AVRMCExpr::getKindByName(ModifierName);
7120b57cec5SDimitry Andric if (ModifierKind != AVRMCExpr::VK_AVR_None) {
7130b57cec5SDimitry Andric Parser.Lex();
7140b57cec5SDimitry Andric Parser.Lex(); // Eat the modifier and parenthesis
7150b57cec5SDimitry Andric } else {
7160b57cec5SDimitry Andric return Error(Parser.getTok().getLoc(), "unknown modifier");
7170b57cec5SDimitry Andric }
7180b57cec5SDimitry Andric MCSymbol *Symbol =
7190b57cec5SDimitry Andric getContext().getOrCreateSymbol(Parser.getTok().getString());
7205ffd83dbSDimitry Andric AVRStreamer.emitValueForModiferKind(Symbol, SizeInBytes, L, ModifierKind);
72106c3fb27SDimitry Andric Lex(); // Eat the symbol name.
72206c3fb27SDimitry Andric if (parseToken(AsmToken::RParen))
72306c3fb27SDimitry Andric return ParseStatus::Failure;
72406c3fb27SDimitry Andric return parseEOL();
7250b57cec5SDimitry Andric }
7260b57cec5SDimitry Andric
7270b57cec5SDimitry Andric auto parseOne = [&]() -> bool {
7280b57cec5SDimitry Andric const MCExpr *Value;
7290b57cec5SDimitry Andric if (Parser.parseExpression(Value))
7300b57cec5SDimitry Andric return true;
7315ffd83dbSDimitry Andric Parser.getStreamer().emitValue(Value, SizeInBytes, L);
7320b57cec5SDimitry Andric return false;
7330b57cec5SDimitry Andric };
7340b57cec5SDimitry Andric return (parseMany(parseOne));
7350b57cec5SDimitry Andric }
7360b57cec5SDimitry Andric
LLVMInitializeAVRAsmParser()737480093f4SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAVRAsmParser() {
7380b57cec5SDimitry Andric RegisterMCAsmParser<AVRAsmParser> X(getTheAVRTarget());
7390b57cec5SDimitry Andric }
7400b57cec5SDimitry Andric
7410b57cec5SDimitry Andric #define GET_REGISTER_MATCHER
7420b57cec5SDimitry Andric #define GET_MATCHER_IMPLEMENTATION
7430b57cec5SDimitry Andric #include "AVRGenAsmMatcher.inc"
7440b57cec5SDimitry Andric
7450b57cec5SDimitry Andric // Uses enums defined in AVRGenAsmMatcher.inc
validateTargetOperandClass(MCParsedAsmOperand & AsmOp,unsigned ExpectedKind)7460b57cec5SDimitry Andric unsigned AVRAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
7470b57cec5SDimitry Andric unsigned ExpectedKind) {
7480b57cec5SDimitry Andric AVROperand &Op = static_cast<AVROperand &>(AsmOp);
7490b57cec5SDimitry Andric MatchClassKind Expected = static_cast<MatchClassKind>(ExpectedKind);
7500b57cec5SDimitry Andric
7510b57cec5SDimitry Andric // If need be, GCC converts bare numbers to register names
7520b57cec5SDimitry Andric // It's ugly, but GCC supports it.
7530b57cec5SDimitry Andric if (Op.isImm()) {
7540b57cec5SDimitry Andric if (MCConstantExpr const *Const = dyn_cast<MCConstantExpr>(Op.getImm())) {
7550b57cec5SDimitry Andric int64_t RegNum = Const->getValue();
75681ad6265SDimitry Andric
75781ad6265SDimitry Andric // Reject R0~R15 on avrtiny.
75881ad6265SDimitry Andric if (0 <= RegNum && RegNum <= 15 &&
75981ad6265SDimitry Andric STI.hasFeature(AVR::FeatureTinyEncoding))
76081ad6265SDimitry Andric return Match_InvalidRegisterOnTiny;
76181ad6265SDimitry Andric
7620b57cec5SDimitry Andric std::ostringstream RegName;
7630b57cec5SDimitry Andric RegName << "r" << RegNum;
764349cc55cSDimitry Andric RegNum = MatchRegisterName(RegName.str());
7650b57cec5SDimitry Andric if (RegNum != AVR::NoRegister) {
7660b57cec5SDimitry Andric Op.makeReg(RegNum);
7670b57cec5SDimitry Andric if (validateOperandClass(Op, Expected) == Match_Success) {
7680b57cec5SDimitry Andric return Match_Success;
7690b57cec5SDimitry Andric }
7700b57cec5SDimitry Andric }
7710b57cec5SDimitry Andric // Let the other quirks try their magic.
7720b57cec5SDimitry Andric }
7730b57cec5SDimitry Andric }
7740b57cec5SDimitry Andric
7750b57cec5SDimitry Andric if (Op.isReg()) {
7760b57cec5SDimitry Andric // If the instruction uses a register pair but we got a single, lower
7770b57cec5SDimitry Andric // register we perform a "class cast".
7780b57cec5SDimitry Andric if (isSubclass(Expected, MCK_DREGS)) {
7790b57cec5SDimitry Andric unsigned correspondingDREG = toDREG(Op.getReg());
7800b57cec5SDimitry Andric
7810b57cec5SDimitry Andric if (correspondingDREG != AVR::NoRegister) {
7820b57cec5SDimitry Andric Op.makeReg(correspondingDREG);
7830b57cec5SDimitry Andric return validateOperandClass(Op, Expected);
7840b57cec5SDimitry Andric }
7850b57cec5SDimitry Andric }
7860b57cec5SDimitry Andric }
7870b57cec5SDimitry Andric return Match_InvalidOperand;
7880b57cec5SDimitry Andric }
789