Path: blob/main/contrib/llvm-project/llvm/lib/Target/VE/AsmParser/VEAsmParser.cpp
35294 views
//===-- VEAsmParser.cpp - Parse VE 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 "MCTargetDesc/VEMCExpr.h"9#include "MCTargetDesc/VEMCTargetDesc.h"10#include "TargetInfo/VETargetInfo.h"11#include "VE.h"12#include "llvm/ADT/STLExtras.h"13#include "llvm/ADT/SmallVector.h"14#include "llvm/ADT/StringRef.h"15#include "llvm/ADT/Twine.h"16#include "llvm/MC/MCContext.h"17#include "llvm/MC/MCExpr.h"18#include "llvm/MC/MCInst.h"19#include "llvm/MC/MCInstrInfo.h"20#include "llvm/MC/MCParser/MCAsmLexer.h"21#include "llvm/MC/MCParser/MCAsmParser.h"22#include "llvm/MC/MCParser/MCParsedAsmOperand.h"23#include "llvm/MC/MCParser/MCTargetAsmParser.h"24#include "llvm/MC/MCRegisterInfo.h"25#include "llvm/MC/MCStreamer.h"26#include "llvm/MC/MCSubtargetInfo.h"27#include "llvm/MC/MCSymbol.h"28#include "llvm/MC/TargetRegistry.h"29#include "llvm/Support/raw_ostream.h"30#include <algorithm>31#include <memory>3233using namespace llvm;3435#define DEBUG_TYPE "ve-asmparser"3637namespace {3839class VEOperand;4041class VEAsmParser : public MCTargetAsmParser {42MCAsmParser &Parser;4344/// @name Auto-generated Match Functions45/// {4647#define GET_ASSEMBLER_HEADER48#include "VEGenAsmMatcher.inc"4950/// }5152// public interface of the MCTargetAsmParser.53bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,54OperandVector &Operands, MCStreamer &Out,55uint64_t &ErrorInfo,56bool MatchingInlineAsm) override;57bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;58int parseRegisterName(MCRegister (*matchFn)(StringRef));59ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,60SMLoc &EndLoc) override;61bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,62SMLoc NameLoc, OperandVector &Operands) override;63ParseStatus parseDirective(AsmToken DirectiveID) override;6465unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,66unsigned Kind) override;6768// Custom parse functions for VE specific operands.69ParseStatus parseMEMOperand(OperandVector &Operands);70ParseStatus parseMEMAsOperand(OperandVector &Operands);71ParseStatus parseCCOpOperand(OperandVector &Operands);72ParseStatus parseRDOpOperand(OperandVector &Operands);73ParseStatus parseMImmOperand(OperandVector &Operands);74ParseStatus parseOperand(OperandVector &Operands, StringRef Name);75ParseStatus parseVEAsmOperand(std::unique_ptr<VEOperand> &Operand);7677// Helper function to parse expression with a symbol.78const MCExpr *extractModifierFromExpr(const MCExpr *E,79VEMCExpr::VariantKind &Variant);80const MCExpr *fixupVariantKind(const MCExpr *E);81bool parseExpression(const MCExpr *&EVal);8283// Split the mnemonic stripping conditional code and quantifiers84StringRef splitMnemonic(StringRef Name, SMLoc NameLoc,85OperandVector *Operands);8687bool parseLiteralValues(unsigned Size, SMLoc L);8889public:90VEAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,91const MCInstrInfo &MII, const MCTargetOptions &Options)92: MCTargetAsmParser(Options, sti, MII), Parser(parser) {93// Initialize the set of available features.94setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));95}96};9798} // end anonymous namespace99100static const MCPhysReg I32Regs[64] = {101VE::SW0, VE::SW1, VE::SW2, VE::SW3, VE::SW4, VE::SW5, VE::SW6,102VE::SW7, VE::SW8, VE::SW9, VE::SW10, VE::SW11, VE::SW12, VE::SW13,103VE::SW14, VE::SW15, VE::SW16, VE::SW17, VE::SW18, VE::SW19, VE::SW20,104VE::SW21, VE::SW22, VE::SW23, VE::SW24, VE::SW25, VE::SW26, VE::SW27,105VE::SW28, VE::SW29, VE::SW30, VE::SW31, VE::SW32, VE::SW33, VE::SW34,106VE::SW35, VE::SW36, VE::SW37, VE::SW38, VE::SW39, VE::SW40, VE::SW41,107VE::SW42, VE::SW43, VE::SW44, VE::SW45, VE::SW46, VE::SW47, VE::SW48,108VE::SW49, VE::SW50, VE::SW51, VE::SW52, VE::SW53, VE::SW54, VE::SW55,109VE::SW56, VE::SW57, VE::SW58, VE::SW59, VE::SW60, VE::SW61, VE::SW62,110VE::SW63};111112static const MCPhysReg F32Regs[64] = {113VE::SF0, VE::SF1, VE::SF2, VE::SF3, VE::SF4, VE::SF5, VE::SF6,114VE::SF7, VE::SF8, VE::SF9, VE::SF10, VE::SF11, VE::SF12, VE::SF13,115VE::SF14, VE::SF15, VE::SF16, VE::SF17, VE::SF18, VE::SF19, VE::SF20,116VE::SF21, VE::SF22, VE::SF23, VE::SF24, VE::SF25, VE::SF26, VE::SF27,117VE::SF28, VE::SF29, VE::SF30, VE::SF31, VE::SF32, VE::SF33, VE::SF34,118VE::SF35, VE::SF36, VE::SF37, VE::SF38, VE::SF39, VE::SF40, VE::SF41,119VE::SF42, VE::SF43, VE::SF44, VE::SF45, VE::SF46, VE::SF47, VE::SF48,120VE::SF49, VE::SF50, VE::SF51, VE::SF52, VE::SF53, VE::SF54, VE::SF55,121VE::SF56, VE::SF57, VE::SF58, VE::SF59, VE::SF60, VE::SF61, VE::SF62,122VE::SF63};123124static const MCPhysReg F128Regs[32] = {125VE::Q0, VE::Q1, VE::Q2, VE::Q3, VE::Q4, VE::Q5, VE::Q6, VE::Q7,126VE::Q8, VE::Q9, VE::Q10, VE::Q11, VE::Q12, VE::Q13, VE::Q14, VE::Q15,127VE::Q16, VE::Q17, VE::Q18, VE::Q19, VE::Q20, VE::Q21, VE::Q22, VE::Q23,128VE::Q24, VE::Q25, VE::Q26, VE::Q27, VE::Q28, VE::Q29, VE::Q30, VE::Q31};129130static const MCPhysReg VM512Regs[8] = {VE::VMP0, VE::VMP1, VE::VMP2, VE::VMP3,131VE::VMP4, VE::VMP5, VE::VMP6, VE::VMP7};132133static const MCPhysReg MISCRegs[31] = {134VE::USRCC, VE::PSW, VE::SAR, VE::NoRegister,135VE::NoRegister, VE::NoRegister, VE::NoRegister, VE::PMMR,136VE::PMCR0, VE::PMCR1, VE::PMCR2, VE::PMCR3,137VE::NoRegister, VE::NoRegister, VE::NoRegister, VE::NoRegister,138VE::PMC0, VE::PMC1, VE::PMC2, VE::PMC3,139VE::PMC4, VE::PMC5, VE::PMC6, VE::PMC7,140VE::PMC8, VE::PMC9, VE::PMC10, VE::PMC11,141VE::PMC12, VE::PMC13, VE::PMC14};142143namespace {144145/// VEOperand - Instances of this class represent a parsed VE machine146/// instruction.147class VEOperand : public MCParsedAsmOperand {148private:149enum KindTy {150k_Token,151k_Register,152k_Immediate,153// SX-Aurora ASX form is disp(index, base).154k_MemoryRegRegImm, // base=reg, index=reg, disp=imm155k_MemoryRegImmImm, // base=reg, index=imm, disp=imm156k_MemoryZeroRegImm, // base=0, index=reg, disp=imm157k_MemoryZeroImmImm, // base=0, index=imm, disp=imm158// SX-Aurora AS form is disp(base).159k_MemoryRegImm, // base=reg, disp=imm160k_MemoryZeroImm, // base=0, disp=imm161// Other special cases for Aurora VE162k_CCOp, // condition code163k_RDOp, // rounding mode164k_MImmOp, // Special immediate value of sequential bit stream of 0 or 1.165} Kind;166167SMLoc StartLoc, EndLoc;168169struct Token {170const char *Data;171unsigned Length;172};173174struct RegOp {175unsigned RegNum;176};177178struct ImmOp {179const MCExpr *Val;180};181182struct MemOp {183unsigned Base;184unsigned IndexReg;185const MCExpr *Index;186const MCExpr *Offset;187};188189struct CCOp {190unsigned CCVal;191};192193struct RDOp {194unsigned RDVal;195};196197struct MImmOp {198const MCExpr *Val;199bool M0Flag;200};201202union {203struct Token Tok;204struct RegOp Reg;205struct ImmOp Imm;206struct MemOp Mem;207struct CCOp CC;208struct RDOp RD;209struct MImmOp MImm;210};211212public:213VEOperand(KindTy K) : Kind(K) {}214215bool isToken() const override { return Kind == k_Token; }216bool isReg() const override { return Kind == k_Register; }217bool isImm() const override { return Kind == k_Immediate; }218bool isMem() const override {219return isMEMrri() || isMEMrii() || isMEMzri() || isMEMzii() || isMEMri() ||220isMEMzi();221}222bool isMEMrri() const { return Kind == k_MemoryRegRegImm; }223bool isMEMrii() const { return Kind == k_MemoryRegImmImm; }224bool isMEMzri() const { return Kind == k_MemoryZeroRegImm; }225bool isMEMzii() const { return Kind == k_MemoryZeroImmImm; }226bool isMEMri() const { return Kind == k_MemoryRegImm; }227bool isMEMzi() const { return Kind == k_MemoryZeroImm; }228bool isCCOp() const { return Kind == k_CCOp; }229bool isRDOp() const { return Kind == k_RDOp; }230bool isZero() {231if (!isImm())232return false;233234// Constant case235if (const auto *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Val)) {236int64_t Value = ConstExpr->getValue();237return Value == 0;238}239return false;240}241bool isUImm0to2() {242if (!isImm())243return false;244245// Constant case246if (const auto *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Val)) {247int64_t Value = ConstExpr->getValue();248return Value >= 0 && Value < 3;249}250return false;251}252bool isUImm1() {253if (!isImm())254return false;255256// Constant case257if (const auto *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Val)) {258int64_t Value = ConstExpr->getValue();259return isUInt<1>(Value);260}261return false;262}263bool isUImm2() {264if (!isImm())265return false;266267// Constant case268if (const auto *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Val)) {269int64_t Value = ConstExpr->getValue();270return isUInt<2>(Value);271}272return false;273}274bool isUImm3() {275if (!isImm())276return false;277278// Constant case279if (const auto *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Val)) {280int64_t Value = ConstExpr->getValue();281return isUInt<3>(Value);282}283return false;284}285bool isUImm4() {286if (!isImm())287return false;288289// Constant case290if (const auto *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Val)) {291int64_t Value = ConstExpr->getValue();292return isUInt<4>(Value);293}294return false;295}296bool isUImm6() {297if (!isImm())298return false;299300// Constant case301if (const auto *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Val)) {302int64_t Value = ConstExpr->getValue();303return isUInt<6>(Value);304}305return false;306}307bool isUImm7() {308if (!isImm())309return false;310311// Constant case312if (const auto *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Val)) {313int64_t Value = ConstExpr->getValue();314return isUInt<7>(Value);315}316return false;317}318bool isSImm7() {319if (!isImm())320return false;321322// Constant case323if (const auto *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Val)) {324int64_t Value = ConstExpr->getValue();325return isInt<7>(Value);326}327return false;328}329bool isMImm() const {330if (Kind != k_MImmOp)331return false;332333// Constant case334if (const auto *ConstExpr = dyn_cast<MCConstantExpr>(MImm.Val)) {335int64_t Value = ConstExpr->getValue();336return isUInt<6>(Value);337}338return false;339}340341StringRef getToken() const {342assert(Kind == k_Token && "Invalid access!");343return StringRef(Tok.Data, Tok.Length);344}345346MCRegister getReg() const override {347assert((Kind == k_Register) && "Invalid access!");348return Reg.RegNum;349}350351const MCExpr *getImm() const {352assert((Kind == k_Immediate) && "Invalid access!");353return Imm.Val;354}355356unsigned getMemBase() const {357assert((Kind == k_MemoryRegRegImm || Kind == k_MemoryRegImmImm ||358Kind == k_MemoryRegImm) &&359"Invalid access!");360return Mem.Base;361}362363unsigned getMemIndexReg() const {364assert((Kind == k_MemoryRegRegImm || Kind == k_MemoryZeroRegImm) &&365"Invalid access!");366return Mem.IndexReg;367}368369const MCExpr *getMemIndex() const {370assert((Kind == k_MemoryRegImmImm || Kind == k_MemoryZeroImmImm) &&371"Invalid access!");372return Mem.Index;373}374375const MCExpr *getMemOffset() const {376assert((Kind == k_MemoryRegRegImm || Kind == k_MemoryRegImmImm ||377Kind == k_MemoryZeroImmImm || Kind == k_MemoryZeroRegImm ||378Kind == k_MemoryRegImm || Kind == k_MemoryZeroImm) &&379"Invalid access!");380return Mem.Offset;381}382383void setMemOffset(const MCExpr *off) {384assert((Kind == k_MemoryRegRegImm || Kind == k_MemoryRegImmImm ||385Kind == k_MemoryZeroImmImm || Kind == k_MemoryZeroRegImm ||386Kind == k_MemoryRegImm || Kind == k_MemoryZeroImm) &&387"Invalid access!");388Mem.Offset = off;389}390391unsigned getCCVal() const {392assert((Kind == k_CCOp) && "Invalid access!");393return CC.CCVal;394}395396unsigned getRDVal() const {397assert((Kind == k_RDOp) && "Invalid access!");398return RD.RDVal;399}400401const MCExpr *getMImmVal() const {402assert((Kind == k_MImmOp) && "Invalid access!");403return MImm.Val;404}405bool getM0Flag() const {406assert((Kind == k_MImmOp) && "Invalid access!");407return MImm.M0Flag;408}409410/// getStartLoc - Get the location of the first token of this operand.411SMLoc getStartLoc() const override { return StartLoc; }412/// getEndLoc - Get the location of the last token of this operand.413SMLoc getEndLoc() const override { return EndLoc; }414415void print(raw_ostream &OS) const override {416switch (Kind) {417case k_Token:418OS << "Token: " << getToken() << "\n";419break;420case k_Register:421OS << "Reg: #" << getReg() << "\n";422break;423case k_Immediate:424OS << "Imm: " << getImm() << "\n";425break;426case k_MemoryRegRegImm:427assert(getMemOffset() != nullptr);428OS << "Mem: #" << getMemBase() << "+#" << getMemIndexReg() << "+"429<< *getMemOffset() << "\n";430break;431case k_MemoryRegImmImm:432assert(getMemIndex() != nullptr && getMemOffset() != nullptr);433OS << "Mem: #" << getMemBase() << "+" << *getMemIndex() << "+"434<< *getMemOffset() << "\n";435break;436case k_MemoryZeroRegImm:437assert(getMemOffset() != nullptr);438OS << "Mem: 0+#" << getMemIndexReg() << "+" << *getMemOffset() << "\n";439break;440case k_MemoryZeroImmImm:441assert(getMemIndex() != nullptr && getMemOffset() != nullptr);442OS << "Mem: 0+" << *getMemIndex() << "+" << *getMemOffset() << "\n";443break;444case k_MemoryRegImm:445assert(getMemOffset() != nullptr);446OS << "Mem: #" << getMemBase() << "+" << *getMemOffset() << "\n";447break;448case k_MemoryZeroImm:449assert(getMemOffset() != nullptr);450OS << "Mem: 0+" << *getMemOffset() << "\n";451break;452case k_CCOp:453OS << "CCOp: " << getCCVal() << "\n";454break;455case k_RDOp:456OS << "RDOp: " << getRDVal() << "\n";457break;458case k_MImmOp:459OS << "MImm: (" << getMImmVal() << (getM0Flag() ? ")0" : ")1") << "\n";460break;461}462}463464void addRegOperands(MCInst &Inst, unsigned N) const {465assert(N == 1 && "Invalid number of operands!");466Inst.addOperand(MCOperand::createReg(getReg()));467}468469void addImmOperands(MCInst &Inst, unsigned N) const {470assert(N == 1 && "Invalid number of operands!");471const MCExpr *Expr = getImm();472addExpr(Inst, Expr);473}474475void addZeroOperands(MCInst &Inst, unsigned N) const {476addImmOperands(Inst, N);477}478479void addUImm0to2Operands(MCInst &Inst, unsigned N) const {480addImmOperands(Inst, N);481}482483void addUImm1Operands(MCInst &Inst, unsigned N) const {484addImmOperands(Inst, N);485}486487void addUImm2Operands(MCInst &Inst, unsigned N) const {488addImmOperands(Inst, N);489}490491void addUImm3Operands(MCInst &Inst, unsigned N) const {492addImmOperands(Inst, N);493}494495void addUImm4Operands(MCInst &Inst, unsigned N) const {496addImmOperands(Inst, N);497}498499void addUImm6Operands(MCInst &Inst, unsigned N) const {500addImmOperands(Inst, N);501}502503void addUImm7Operands(MCInst &Inst, unsigned N) const {504addImmOperands(Inst, N);505}506507void addSImm7Operands(MCInst &Inst, unsigned N) const {508addImmOperands(Inst, N);509}510511void addExpr(MCInst &Inst, const MCExpr *Expr) const {512// Add as immediate when possible. Null MCExpr = 0.513if (!Expr)514Inst.addOperand(MCOperand::createImm(0));515else if (const auto *CE = dyn_cast<MCConstantExpr>(Expr))516Inst.addOperand(MCOperand::createImm(CE->getValue()));517else518Inst.addOperand(MCOperand::createExpr(Expr));519}520521void addMEMrriOperands(MCInst &Inst, unsigned N) const {522assert(N == 3 && "Invalid number of operands!");523524Inst.addOperand(MCOperand::createReg(getMemBase()));525Inst.addOperand(MCOperand::createReg(getMemIndexReg()));526addExpr(Inst, getMemOffset());527}528529void addMEMriiOperands(MCInst &Inst, unsigned N) const {530assert(N == 3 && "Invalid number of operands!");531532Inst.addOperand(MCOperand::createReg(getMemBase()));533addExpr(Inst, getMemIndex());534addExpr(Inst, getMemOffset());535}536537void addMEMzriOperands(MCInst &Inst, unsigned N) const {538assert(N == 3 && "Invalid number of operands!");539540Inst.addOperand(MCOperand::createImm(0));541Inst.addOperand(MCOperand::createReg(getMemIndexReg()));542addExpr(Inst, getMemOffset());543}544545void addMEMziiOperands(MCInst &Inst, unsigned N) const {546assert(N == 3 && "Invalid number of operands!");547548Inst.addOperand(MCOperand::createImm(0));549addExpr(Inst, getMemIndex());550addExpr(Inst, getMemOffset());551}552553void addMEMriOperands(MCInst &Inst, unsigned N) const {554assert(N == 2 && "Invalid number of operands!");555556Inst.addOperand(MCOperand::createReg(getMemBase()));557addExpr(Inst, getMemOffset());558}559560void addMEMziOperands(MCInst &Inst, unsigned N) const {561assert(N == 2 && "Invalid number of operands!");562563Inst.addOperand(MCOperand::createImm(0));564addExpr(Inst, getMemOffset());565}566567void addCCOpOperands(MCInst &Inst, unsigned N) const {568assert(N == 1 && "Invalid number of operands!");569570Inst.addOperand(MCOperand::createImm(getCCVal()));571}572573void addRDOpOperands(MCInst &Inst, unsigned N) const {574assert(N == 1 && "Invalid number of operands!");575576Inst.addOperand(MCOperand::createImm(getRDVal()));577}578579void addMImmOperands(MCInst &Inst, unsigned N) const {580assert(N == 1 && "Invalid number of operands!");581const auto *ConstExpr = dyn_cast<MCConstantExpr>(getMImmVal());582assert(ConstExpr && "Null operands!");583int64_t Value = ConstExpr->getValue();584if (getM0Flag())585Value += 64;586Inst.addOperand(MCOperand::createImm(Value));587}588589static std::unique_ptr<VEOperand> CreateToken(StringRef Str, SMLoc S) {590auto Op = std::make_unique<VEOperand>(k_Token);591Op->Tok.Data = Str.data();592Op->Tok.Length = Str.size();593Op->StartLoc = S;594Op->EndLoc = S;595return Op;596}597598static std::unique_ptr<VEOperand> CreateReg(unsigned RegNum, SMLoc S,599SMLoc E) {600auto Op = std::make_unique<VEOperand>(k_Register);601Op->Reg.RegNum = RegNum;602Op->StartLoc = S;603Op->EndLoc = E;604return Op;605}606607static std::unique_ptr<VEOperand> CreateImm(const MCExpr *Val, SMLoc S,608SMLoc E) {609auto Op = std::make_unique<VEOperand>(k_Immediate);610Op->Imm.Val = Val;611Op->StartLoc = S;612Op->EndLoc = E;613return Op;614}615616static std::unique_ptr<VEOperand> CreateCCOp(unsigned CCVal, SMLoc S,617SMLoc E) {618auto Op = std::make_unique<VEOperand>(k_CCOp);619Op->CC.CCVal = CCVal;620Op->StartLoc = S;621Op->EndLoc = E;622return Op;623}624625static std::unique_ptr<VEOperand> CreateRDOp(unsigned RDVal, SMLoc S,626SMLoc E) {627auto Op = std::make_unique<VEOperand>(k_RDOp);628Op->RD.RDVal = RDVal;629Op->StartLoc = S;630Op->EndLoc = E;631return Op;632}633634static std::unique_ptr<VEOperand> CreateMImm(const MCExpr *Val, bool Flag,635SMLoc S, SMLoc E) {636auto Op = std::make_unique<VEOperand>(k_MImmOp);637Op->MImm.Val = Val;638Op->MImm.M0Flag = Flag;639Op->StartLoc = S;640Op->EndLoc = E;641return Op;642}643644static bool MorphToI32Reg(VEOperand &Op) {645unsigned Reg = Op.getReg();646unsigned regIdx = Reg - VE::SX0;647if (regIdx > 63)648return false;649Op.Reg.RegNum = I32Regs[regIdx];650return true;651}652653static bool MorphToF32Reg(VEOperand &Op) {654unsigned Reg = Op.getReg();655unsigned regIdx = Reg - VE::SX0;656if (regIdx > 63)657return false;658Op.Reg.RegNum = F32Regs[regIdx];659return true;660}661662static bool MorphToF128Reg(VEOperand &Op) {663unsigned Reg = Op.getReg();664unsigned regIdx = Reg - VE::SX0;665if (regIdx % 2 || regIdx > 63)666return false;667Op.Reg.RegNum = F128Regs[regIdx / 2];668return true;669}670671static bool MorphToVM512Reg(VEOperand &Op) {672unsigned Reg = Op.getReg();673unsigned regIdx = Reg - VE::VM0;674if (regIdx % 2 || regIdx > 15)675return false;676Op.Reg.RegNum = VM512Regs[regIdx / 2];677return true;678}679680static bool MorphToMISCReg(VEOperand &Op) {681const auto *ConstExpr = dyn_cast<MCConstantExpr>(Op.getImm());682if (!ConstExpr)683return false;684unsigned regIdx = ConstExpr->getValue();685if (regIdx > 31 || MISCRegs[regIdx] == VE::NoRegister)686return false;687Op.Kind = k_Register;688Op.Reg.RegNum = MISCRegs[regIdx];689return true;690}691692static std::unique_ptr<VEOperand>693MorphToMEMri(unsigned Base, std::unique_ptr<VEOperand> Op) {694const MCExpr *Imm = Op->getImm();695Op->Kind = k_MemoryRegImm;696Op->Mem.Base = Base;697Op->Mem.IndexReg = 0;698Op->Mem.Index = nullptr;699Op->Mem.Offset = Imm;700return Op;701}702703static std::unique_ptr<VEOperand>704MorphToMEMzi(std::unique_ptr<VEOperand> Op) {705const MCExpr *Imm = Op->getImm();706Op->Kind = k_MemoryZeroImm;707Op->Mem.Base = 0;708Op->Mem.IndexReg = 0;709Op->Mem.Index = nullptr;710Op->Mem.Offset = Imm;711return Op;712}713714static std::unique_ptr<VEOperand>715MorphToMEMrri(unsigned Base, unsigned Index, std::unique_ptr<VEOperand> Op) {716const MCExpr *Imm = Op->getImm();717Op->Kind = k_MemoryRegRegImm;718Op->Mem.Base = Base;719Op->Mem.IndexReg = Index;720Op->Mem.Index = nullptr;721Op->Mem.Offset = Imm;722return Op;723}724725static std::unique_ptr<VEOperand>726MorphToMEMrii(unsigned Base, const MCExpr *Index,727std::unique_ptr<VEOperand> Op) {728const MCExpr *Imm = Op->getImm();729Op->Kind = k_MemoryRegImmImm;730Op->Mem.Base = Base;731Op->Mem.IndexReg = 0;732Op->Mem.Index = Index;733Op->Mem.Offset = Imm;734return Op;735}736737static std::unique_ptr<VEOperand>738MorphToMEMzri(unsigned Index, std::unique_ptr<VEOperand> Op) {739const MCExpr *Imm = Op->getImm();740Op->Kind = k_MemoryZeroRegImm;741Op->Mem.Base = 0;742Op->Mem.IndexReg = Index;743Op->Mem.Index = nullptr;744Op->Mem.Offset = Imm;745return Op;746}747748static std::unique_ptr<VEOperand>749MorphToMEMzii(const MCExpr *Index, std::unique_ptr<VEOperand> Op) {750const MCExpr *Imm = Op->getImm();751Op->Kind = k_MemoryZeroImmImm;752Op->Mem.Base = 0;753Op->Mem.IndexReg = 0;754Op->Mem.Index = Index;755Op->Mem.Offset = Imm;756return Op;757}758};759760} // end anonymous namespace761762bool VEAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,763OperandVector &Operands,764MCStreamer &Out, uint64_t &ErrorInfo,765bool MatchingInlineAsm) {766MCInst Inst;767unsigned MatchResult =768MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);769switch (MatchResult) {770case Match_Success:771Inst.setLoc(IDLoc);772Out.emitInstruction(Inst, getSTI());773return false;774775case Match_MissingFeature:776return Error(IDLoc,777"instruction requires a CPU feature not currently enabled");778779case Match_InvalidOperand: {780SMLoc ErrorLoc = IDLoc;781if (ErrorInfo != ~0ULL) {782if (ErrorInfo >= Operands.size())783return Error(IDLoc, "too few operands for instruction");784785ErrorLoc = ((VEOperand &)*Operands[ErrorInfo]).getStartLoc();786if (ErrorLoc == SMLoc())787ErrorLoc = IDLoc;788}789790return Error(ErrorLoc, "invalid operand for instruction");791}792case Match_MnemonicFail:793return Error(IDLoc, "invalid instruction mnemonic");794}795llvm_unreachable("Implement any new match types added!");796}797798bool VEAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,799SMLoc &EndLoc) {800if (!tryParseRegister(Reg, StartLoc, EndLoc).isSuccess())801return Error(StartLoc, "invalid register name");802return false;803}804805/// Parses a register name using a given matching function.806/// Checks for lowercase or uppercase if necessary.807int VEAsmParser::parseRegisterName(MCRegister (*matchFn)(StringRef)) {808StringRef Name = Parser.getTok().getString();809810int RegNum = matchFn(Name);811812// GCC supports case insensitive register names. All of the VE registers813// are all lower case.814if (RegNum == VE::NoRegister) {815RegNum = matchFn(Name.lower());816}817818return RegNum;819}820821/// Maps from the set of all register names to a register number.822/// \note Generated by TableGen.823static MCRegister MatchRegisterName(StringRef Name);824825/// Maps from the set of all alternative registernames to a register number.826/// \note Generated by TableGen.827static MCRegister MatchRegisterAltName(StringRef Name);828829ParseStatus VEAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,830SMLoc &EndLoc) {831const AsmToken Tok = Parser.getTok();832StartLoc = Tok.getLoc();833EndLoc = Tok.getEndLoc();834Reg = VE::NoRegister;835if (getLexer().getKind() != AsmToken::Percent)836return ParseStatus::NoMatch;837Parser.Lex();838839Reg = parseRegisterName(&MatchRegisterName);840if (Reg == VE::NoRegister)841Reg = parseRegisterName(&MatchRegisterAltName);842843if (Reg != VE::NoRegister) {844Parser.Lex();845return ParseStatus::Success;846}847848getLexer().UnLex(Tok);849return ParseStatus::NoMatch;850}851852static StringRef parseCC(StringRef Name, unsigned Prefix, unsigned Suffix,853bool IntegerCC, bool OmitCC, SMLoc NameLoc,854OperandVector *Operands) {855// Parse instructions with a conditional code. For example, 'bne' is856// converted into two operands 'b' and 'ne'.857StringRef Cond = Name.slice(Prefix, Suffix);858VECC::CondCode CondCode =859IntegerCC ? stringToVEICondCode(Cond) : stringToVEFCondCode(Cond);860861// If OmitCC is enabled, CC_AT and CC_AF is treated as a part of mnemonic.862if (CondCode != VECC::UNKNOWN &&863(!OmitCC || (CondCode != VECC::CC_AT && CondCode != VECC::CC_AF))) {864StringRef SuffixStr = Name.substr(Suffix);865// Push "b".866Name = Name.slice(0, Prefix);867Operands->push_back(VEOperand::CreateToken(Name, NameLoc));868// Push $cond part.869SMLoc CondLoc = SMLoc::getFromPointer(NameLoc.getPointer() + Prefix);870SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() + Suffix);871Operands->push_back(VEOperand::CreateCCOp(CondCode, CondLoc, SuffixLoc));872// push suffix like ".l.t"873if (!SuffixStr.empty())874Operands->push_back(VEOperand::CreateToken(SuffixStr, SuffixLoc));875} else {876Operands->push_back(VEOperand::CreateToken(Name, NameLoc));877}878return Name;879}880881static StringRef parseRD(StringRef Name, unsigned Prefix, SMLoc NameLoc,882OperandVector *Operands) {883// Parse instructions with a conditional code. For example, 'cvt.w.d.sx.rz'884// is converted into two operands 'cvt.w.d.sx' and '.rz'.885StringRef RD = Name.substr(Prefix);886VERD::RoundingMode RoundingMode = stringToVERD(RD);887888if (RoundingMode != VERD::UNKNOWN) {889Name = Name.slice(0, Prefix);890// push 1st like `cvt.w.d.sx`891Operands->push_back(VEOperand::CreateToken(Name, NameLoc));892SMLoc SuffixLoc =893SMLoc::getFromPointer(NameLoc.getPointer() + (RD.data() - Name.data()));894SMLoc SuffixEnd =895SMLoc::getFromPointer(NameLoc.getPointer() + (RD.end() - Name.data()));896// push $round if it has rounding mode897Operands->push_back(898VEOperand::CreateRDOp(RoundingMode, SuffixLoc, SuffixEnd));899} else {900Operands->push_back(VEOperand::CreateToken(Name, NameLoc));901}902return Name;903}904905// Split the mnemonic into ASM operand, conditional code and instruction906// qualifier (half-word, byte).907StringRef VEAsmParser::splitMnemonic(StringRef Name, SMLoc NameLoc,908OperandVector *Operands) {909// Create the leading tokens for the mnemonic910StringRef Mnemonic = Name;911912if (Name[0] == 'b') {913// Match b?? or br??.914size_t Start = 1;915size_t Next = Name.find('.');916// Adjust position of CondCode.917if (Name.size() > 1 && Name[1] == 'r')918Start = 2;919// Check suffix.920bool ICC = true;921if (Next + 1 < Name.size() &&922(Name[Next + 1] == 'd' || Name[Next + 1] == 's'))923ICC = false;924Mnemonic = parseCC(Name, Start, Next, ICC, true, NameLoc, Operands);925} else if (Name.starts_with("cmov.l.") || Name.starts_with("cmov.w.") ||926Name.starts_with("cmov.d.") || Name.starts_with("cmov.s.")) {927bool ICC = Name[5] == 'l' || Name[5] == 'w';928Mnemonic = parseCC(Name, 7, Name.size(), ICC, false, NameLoc, Operands);929} else if (Name.starts_with("cvt.w.d.sx") || Name.starts_with("cvt.w.d.zx") ||930Name.starts_with("cvt.w.s.sx") || Name.starts_with("cvt.w.s.zx")) {931Mnemonic = parseRD(Name, 10, NameLoc, Operands);932} else if (Name.starts_with("cvt.l.d")) {933Mnemonic = parseRD(Name, 7, NameLoc, Operands);934} else if (Name.starts_with("vcvt.w.d.sx") ||935Name.starts_with("vcvt.w.d.zx") ||936Name.starts_with("vcvt.w.s.sx") ||937Name.starts_with("vcvt.w.s.zx")) {938Mnemonic = parseRD(Name, 11, NameLoc, Operands);939} else if (Name.starts_with("vcvt.l.d")) {940Mnemonic = parseRD(Name, 8, NameLoc, Operands);941} else if (Name.starts_with("pvcvt.w.s.lo") ||942Name.starts_with("pvcvt.w.s.up")) {943Mnemonic = parseRD(Name, 12, NameLoc, Operands);944} else if (Name.starts_with("pvcvt.w.s")) {945Mnemonic = parseRD(Name, 9, NameLoc, Operands);946} else if (Name.starts_with("vfmk.l.") || Name.starts_with("vfmk.w.") ||947Name.starts_with("vfmk.d.") || Name.starts_with("vfmk.s.")) {948bool ICC = Name[5] == 'l' || Name[5] == 'w' ? true : false;949Mnemonic = parseCC(Name, 7, Name.size(), ICC, true, NameLoc, Operands);950} else if (Name.starts_with("pvfmk.w.lo.") ||951Name.starts_with("pvfmk.w.up.") ||952Name.starts_with("pvfmk.s.lo.") ||953Name.starts_with("pvfmk.s.up.")) {954bool ICC = Name[6] == 'l' || Name[6] == 'w' ? true : false;955Mnemonic = parseCC(Name, 11, Name.size(), ICC, true, NameLoc, Operands);956} else {957Operands->push_back(VEOperand::CreateToken(Mnemonic, NameLoc));958}959960return Mnemonic;961}962963static void applyMnemonicAliases(StringRef &Mnemonic,964const FeatureBitset &Features,965unsigned VariantID);966967bool VEAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,968SMLoc NameLoc, OperandVector &Operands) {969// If the target architecture uses MnemonicAlias, call it here to parse970// operands correctly.971applyMnemonicAliases(Name, getAvailableFeatures(), 0);972973// Split name to first token and the rest, e.g. "bgt.l.t" to "b", "gt", and974// ".l.t". We treat "b" as a mnemonic, "gt" as first operand, and ".l.t"975// as second operand.976StringRef Mnemonic = splitMnemonic(Name, NameLoc, &Operands);977978if (getLexer().isNot(AsmToken::EndOfStatement)) {979// Read the first operand.980if (!parseOperand(Operands, Mnemonic).isSuccess()) {981SMLoc Loc = getLexer().getLoc();982return Error(Loc, "unexpected token");983}984985while (getLexer().is(AsmToken::Comma)) {986Parser.Lex(); // Eat the comma.987// Parse and remember the operand.988if (!parseOperand(Operands, Mnemonic).isSuccess()) {989SMLoc Loc = getLexer().getLoc();990return Error(Loc, "unexpected token");991}992}993}994if (getLexer().isNot(AsmToken::EndOfStatement)) {995SMLoc Loc = getLexer().getLoc();996return Error(Loc, "unexpected token");997}998Parser.Lex(); // Consume the EndOfStatement.999return false;1000}10011002ParseStatus VEAsmParser::parseDirective(AsmToken DirectiveID) {1003std::string IDVal = DirectiveID.getIdentifier().lower();10041005// Defines VE specific directives. Reference is "Vector Engine Assembly1006// Language Reference Manual":1007// https://www.hpc.nec/documents/sdk/pdfs/VectorEngine-as-manual-v1.3.pdf10081009// The .word is 4 bytes long on VE.1010if (IDVal == ".word")1011return parseLiteralValues(4, DirectiveID.getLoc());10121013// The .long is 8 bytes long on VE.1014if (IDVal == ".long")1015return parseLiteralValues(8, DirectiveID.getLoc());10161017// The .llong is 8 bytes long on VE.1018if (IDVal == ".llong")1019return parseLiteralValues(8, DirectiveID.getLoc());10201021// Let the MC layer to handle other directives.1022return ParseStatus::NoMatch;1023}10241025/// parseLiteralValues1026/// ::= .word expression [, expression]*1027/// ::= .long expression [, expression]*1028/// ::= .llong expression [, expression]*1029bool VEAsmParser::parseLiteralValues(unsigned Size, SMLoc L) {1030auto parseOne = [&]() -> bool {1031const MCExpr *Value;1032if (getParser().parseExpression(Value))1033return true;1034getParser().getStreamer().emitValue(Value, Size, L);1035return false;1036};1037return (parseMany(parseOne));1038}10391040/// Extract \code @lo32/@hi32/etc \endcode modifier from expression.1041/// Recursively scan the expression and check for VK_VE_HI32/LO32/etc1042/// symbol variants. If all symbols with modifier use the same1043/// variant, return the corresponding VEMCExpr::VariantKind,1044/// and a modified expression using the default symbol variant.1045/// Otherwise, return NULL.1046const MCExpr *1047VEAsmParser::extractModifierFromExpr(const MCExpr *E,1048VEMCExpr::VariantKind &Variant) {1049MCContext &Context = getParser().getContext();1050Variant = VEMCExpr::VK_VE_None;10511052switch (E->getKind()) {1053case MCExpr::Target:1054case MCExpr::Constant:1055return nullptr;10561057case MCExpr::SymbolRef: {1058const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(E);10591060switch (SRE->getKind()) {1061case MCSymbolRefExpr::VK_None:1062// Use VK_VE_REFLONG to a symbol without modifiers.1063Variant = VEMCExpr::VK_VE_REFLONG;1064break;1065case MCSymbolRefExpr::VK_VE_HI32:1066Variant = VEMCExpr::VK_VE_HI32;1067break;1068case MCSymbolRefExpr::VK_VE_LO32:1069Variant = VEMCExpr::VK_VE_LO32;1070break;1071case MCSymbolRefExpr::VK_VE_PC_HI32:1072Variant = VEMCExpr::VK_VE_PC_HI32;1073break;1074case MCSymbolRefExpr::VK_VE_PC_LO32:1075Variant = VEMCExpr::VK_VE_PC_LO32;1076break;1077case MCSymbolRefExpr::VK_VE_GOT_HI32:1078Variant = VEMCExpr::VK_VE_GOT_HI32;1079break;1080case MCSymbolRefExpr::VK_VE_GOT_LO32:1081Variant = VEMCExpr::VK_VE_GOT_LO32;1082break;1083case MCSymbolRefExpr::VK_VE_GOTOFF_HI32:1084Variant = VEMCExpr::VK_VE_GOTOFF_HI32;1085break;1086case MCSymbolRefExpr::VK_VE_GOTOFF_LO32:1087Variant = VEMCExpr::VK_VE_GOTOFF_LO32;1088break;1089case MCSymbolRefExpr::VK_VE_PLT_HI32:1090Variant = VEMCExpr::VK_VE_PLT_HI32;1091break;1092case MCSymbolRefExpr::VK_VE_PLT_LO32:1093Variant = VEMCExpr::VK_VE_PLT_LO32;1094break;1095case MCSymbolRefExpr::VK_VE_TLS_GD_HI32:1096Variant = VEMCExpr::VK_VE_TLS_GD_HI32;1097break;1098case MCSymbolRefExpr::VK_VE_TLS_GD_LO32:1099Variant = VEMCExpr::VK_VE_TLS_GD_LO32;1100break;1101case MCSymbolRefExpr::VK_VE_TPOFF_HI32:1102Variant = VEMCExpr::VK_VE_TPOFF_HI32;1103break;1104case MCSymbolRefExpr::VK_VE_TPOFF_LO32:1105Variant = VEMCExpr::VK_VE_TPOFF_LO32;1106break;1107default:1108return nullptr;1109}11101111return MCSymbolRefExpr::create(&SRE->getSymbol(), Context);1112}11131114case MCExpr::Unary: {1115const MCUnaryExpr *UE = cast<MCUnaryExpr>(E);1116const MCExpr *Sub = extractModifierFromExpr(UE->getSubExpr(), Variant);1117if (!Sub)1118return nullptr;1119return MCUnaryExpr::create(UE->getOpcode(), Sub, Context);1120}11211122case MCExpr::Binary: {1123const MCBinaryExpr *BE = cast<MCBinaryExpr>(E);1124VEMCExpr::VariantKind LHSVariant, RHSVariant;1125const MCExpr *LHS = extractModifierFromExpr(BE->getLHS(), LHSVariant);1126const MCExpr *RHS = extractModifierFromExpr(BE->getRHS(), RHSVariant);11271128if (!LHS && !RHS)1129return nullptr;11301131if (!LHS)1132LHS = BE->getLHS();1133if (!RHS)1134RHS = BE->getRHS();11351136if (LHSVariant == VEMCExpr::VK_VE_None)1137Variant = RHSVariant;1138else if (RHSVariant == VEMCExpr::VK_VE_None)1139Variant = LHSVariant;1140else if (LHSVariant == RHSVariant)1141Variant = LHSVariant;1142else1143return nullptr;11441145return MCBinaryExpr::create(BE->getOpcode(), LHS, RHS, Context);1146}1147}11481149llvm_unreachable("Invalid expression kind!");1150}11511152const MCExpr *VEAsmParser::fixupVariantKind(const MCExpr *E) {1153MCContext &Context = getParser().getContext();11541155switch (E->getKind()) {1156case MCExpr::Target:1157case MCExpr::Constant:1158case MCExpr::SymbolRef:1159return E;11601161case MCExpr::Unary: {1162const MCUnaryExpr *UE = cast<MCUnaryExpr>(E);1163const MCExpr *Sub = fixupVariantKind(UE->getSubExpr());1164if (Sub == UE->getSubExpr())1165return E;1166return MCUnaryExpr::create(UE->getOpcode(), Sub, Context);1167}11681169case MCExpr::Binary: {1170const MCBinaryExpr *BE = cast<MCBinaryExpr>(E);1171const MCExpr *LHS = fixupVariantKind(BE->getLHS());1172const MCExpr *RHS = fixupVariantKind(BE->getRHS());1173if (LHS == BE->getLHS() && RHS == BE->getRHS())1174return E;1175return MCBinaryExpr::create(BE->getOpcode(), LHS, RHS, Context);1176}1177}11781179llvm_unreachable("Invalid expression kind!");1180}11811182/// ParseExpression. This differs from the default "parseExpression" in that1183/// it handles modifiers.1184bool VEAsmParser::parseExpression(const MCExpr *&EVal) {1185// Handle \code symbol @lo32/@hi32/etc \endcode.1186if (getParser().parseExpression(EVal))1187return true;11881189// Convert MCSymbolRefExpr with VK_* to MCExpr with VK_*.1190EVal = fixupVariantKind(EVal);1191VEMCExpr::VariantKind Variant;1192const MCExpr *E = extractModifierFromExpr(EVal, Variant);1193if (E)1194EVal = VEMCExpr::create(Variant, E, getParser().getContext());11951196return false;1197}11981199ParseStatus VEAsmParser::parseMEMOperand(OperandVector &Operands) {1200LLVM_DEBUG(dbgs() << "parseMEMOperand\n");1201const AsmToken &Tok = Parser.getTok();1202SMLoc S = Tok.getLoc();1203SMLoc E = Tok.getEndLoc();1204// Parse ASX format1205// disp1206// disp(, base)1207// disp(index)1208// disp(index, base)1209// (, base)1210// (index)1211// (index, base)12121213std::unique_ptr<VEOperand> Offset;1214switch (getLexer().getKind()) {1215default:1216return ParseStatus::NoMatch;12171218case AsmToken::Minus:1219case AsmToken::Integer:1220case AsmToken::Dot:1221case AsmToken::Identifier: {1222const MCExpr *EVal;1223if (!parseExpression(EVal))1224Offset = VEOperand::CreateImm(EVal, S, E);1225else1226return ParseStatus::NoMatch;1227break;1228}12291230case AsmToken::LParen:1231// empty disp (= 0)1232Offset =1233VEOperand::CreateImm(MCConstantExpr::create(0, getContext()), S, E);1234break;1235}12361237switch (getLexer().getKind()) {1238default:1239return ParseStatus::Failure;12401241case AsmToken::EndOfStatement:1242Operands.push_back(VEOperand::MorphToMEMzii(1243MCConstantExpr::create(0, getContext()), std::move(Offset)));1244return ParseStatus::Success;12451246case AsmToken::LParen:1247Parser.Lex(); // Eat the (1248break;1249}12501251const MCExpr *IndexValue = nullptr;1252MCRegister IndexReg;12531254switch (getLexer().getKind()) {1255default:1256if (parseRegister(IndexReg, S, E))1257return ParseStatus::Failure;1258break;12591260case AsmToken::Minus:1261case AsmToken::Integer:1262case AsmToken::Dot:1263if (getParser().parseExpression(IndexValue, E))1264return ParseStatus::Failure;1265break;12661267case AsmToken::Comma:1268// empty index1269IndexValue = MCConstantExpr::create(0, getContext());1270break;1271}12721273switch (getLexer().getKind()) {1274default:1275return ParseStatus::Failure;12761277case AsmToken::RParen:1278Parser.Lex(); // Eat the )1279Operands.push_back(1280IndexValue ? VEOperand::MorphToMEMzii(IndexValue, std::move(Offset))1281: VEOperand::MorphToMEMzri(IndexReg, std::move(Offset)));1282return ParseStatus::Success;12831284case AsmToken::Comma:1285Parser.Lex(); // Eat the ,1286break;1287}12881289MCRegister BaseReg;1290if (parseRegister(BaseReg, S, E))1291return ParseStatus::Failure;12921293if (!Parser.getTok().is(AsmToken::RParen))1294return ParseStatus::Failure;12951296Parser.Lex(); // Eat the )1297Operands.push_back(1298IndexValue1299? VEOperand::MorphToMEMrii(BaseReg, IndexValue, std::move(Offset))1300: VEOperand::MorphToMEMrri(BaseReg, IndexReg, std::move(Offset)));13011302return ParseStatus::Success;1303}13041305ParseStatus VEAsmParser::parseMEMAsOperand(OperandVector &Operands) {1306LLVM_DEBUG(dbgs() << "parseMEMAsOperand\n");1307const AsmToken &Tok = Parser.getTok();1308SMLoc S = Tok.getLoc();1309SMLoc E = Tok.getEndLoc();1310// Parse AS format1311// disp1312// disp(, base)1313// disp(base)1314// disp()1315// (, base)1316// (base)1317// base13181319MCRegister BaseReg;1320std::unique_ptr<VEOperand> Offset;1321switch (getLexer().getKind()) {1322default:1323return ParseStatus::NoMatch;13241325case AsmToken::Minus:1326case AsmToken::Integer:1327case AsmToken::Dot:1328case AsmToken::Identifier: {1329const MCExpr *EVal;1330if (!parseExpression(EVal))1331Offset = VEOperand::CreateImm(EVal, S, E);1332else1333return ParseStatus::NoMatch;1334break;1335}13361337case AsmToken::Percent:1338if (parseRegister(BaseReg, S, E))1339return ParseStatus::NoMatch;1340Offset =1341VEOperand::CreateImm(MCConstantExpr::create(0, getContext()), S, E);1342break;13431344case AsmToken::LParen:1345// empty disp (= 0)1346Offset =1347VEOperand::CreateImm(MCConstantExpr::create(0, getContext()), S, E);1348break;1349}13501351switch (getLexer().getKind()) {1352default:1353return ParseStatus::Failure;13541355case AsmToken::EndOfStatement:1356case AsmToken::Comma:1357Operands.push_back(BaseReg != VE::NoRegister1358? VEOperand::MorphToMEMri(BaseReg, std::move(Offset))1359: VEOperand::MorphToMEMzi(std::move(Offset)));1360return ParseStatus::Success;13611362case AsmToken::LParen:1363if (BaseReg != VE::NoRegister)1364return ParseStatus::Failure;1365Parser.Lex(); // Eat the (1366break;1367}13681369switch (getLexer().getKind()) {1370default:1371if (parseRegister(BaseReg, S, E))1372return ParseStatus::Failure;1373break;13741375case AsmToken::Comma:1376Parser.Lex(); // Eat the ,1377if (parseRegister(BaseReg, S, E))1378return ParseStatus::Failure;1379break;13801381case AsmToken::RParen:1382break;1383}13841385if (!Parser.getTok().is(AsmToken::RParen))1386return ParseStatus::Failure;13871388Parser.Lex(); // Eat the )1389Operands.push_back(BaseReg != VE::NoRegister1390? VEOperand::MorphToMEMri(BaseReg, std::move(Offset))1391: VEOperand::MorphToMEMzi(std::move(Offset)));13921393return ParseStatus::Success;1394}13951396ParseStatus VEAsmParser::parseMImmOperand(OperandVector &Operands) {1397LLVM_DEBUG(dbgs() << "parseMImmOperand\n");13981399// Parsing "(" + number + ")0/1"1400const AsmToken Tok1 = Parser.getTok();1401if (!Tok1.is(AsmToken::LParen))1402return ParseStatus::NoMatch;14031404Parser.Lex(); // Eat the '('.14051406const AsmToken Tok2 = Parser.getTok();1407SMLoc E;1408const MCExpr *EVal;1409if (!Tok2.is(AsmToken::Integer) || getParser().parseExpression(EVal, E)) {1410getLexer().UnLex(Tok1);1411return ParseStatus::NoMatch;1412}14131414const AsmToken Tok3 = Parser.getTok();1415if (!Tok3.is(AsmToken::RParen)) {1416getLexer().UnLex(Tok2);1417getLexer().UnLex(Tok1);1418return ParseStatus::NoMatch;1419}1420Parser.Lex(); // Eat the ')'.14211422const AsmToken &Tok4 = Parser.getTok();1423StringRef Suffix = Tok4.getString();1424if (Suffix != "1" && Suffix != "0") {1425getLexer().UnLex(Tok3);1426getLexer().UnLex(Tok2);1427getLexer().UnLex(Tok1);1428return ParseStatus::NoMatch;1429}1430Parser.Lex(); // Eat the value.1431SMLoc EndLoc = SMLoc::getFromPointer(Suffix.end());1432Operands.push_back(1433VEOperand::CreateMImm(EVal, Suffix == "0", Tok1.getLoc(), EndLoc));1434return ParseStatus::Success;1435}14361437ParseStatus VEAsmParser::parseOperand(OperandVector &Operands,1438StringRef Mnemonic) {1439LLVM_DEBUG(dbgs() << "parseOperand\n");1440ParseStatus Res = MatchOperandParserImpl(Operands, Mnemonic);14411442// If there wasn't a custom match, try the generic matcher below. Otherwise,1443// there was a match, but an error occurred, in which case, just return that1444// the operand parsing failed.1445if (Res.isSuccess() || Res.isFailure())1446return Res;14471448switch (getLexer().getKind()) {1449case AsmToken::LParen: {1450// Parsing "(" + %vreg + ", " + %vreg + ")"1451const AsmToken Tok1 = Parser.getTok();1452Parser.Lex(); // Eat the '('.14531454MCRegister Reg1;1455SMLoc S1, E1;1456if (!tryParseRegister(Reg1, S1, E1).isSuccess()) {1457getLexer().UnLex(Tok1);1458return ParseStatus::NoMatch;1459}14601461if (!Parser.getTok().is(AsmToken::Comma))1462return ParseStatus::Failure;1463Parser.Lex(); // Eat the ','.14641465MCRegister Reg2;1466SMLoc S2, E2;1467if (!tryParseRegister(Reg2, S2, E2).isSuccess())1468return ParseStatus::Failure;14691470if (!Parser.getTok().is(AsmToken::RParen))1471return ParseStatus::Failure;14721473Operands.push_back(VEOperand::CreateToken(Tok1.getString(), Tok1.getLoc()));1474Operands.push_back(VEOperand::CreateReg(Reg1, S1, E1));1475Operands.push_back(VEOperand::CreateReg(Reg2, S2, E2));1476Operands.push_back(VEOperand::CreateToken(Parser.getTok().getString(),1477Parser.getTok().getLoc()));1478Parser.Lex(); // Eat the ')'.1479break;1480}1481default: {1482std::unique_ptr<VEOperand> Op;1483Res = parseVEAsmOperand(Op);1484if (!Res.isSuccess() || !Op)1485return ParseStatus::Failure;14861487// Push the parsed operand into the list of operands1488Operands.push_back(std::move(Op));14891490if (!Parser.getTok().is(AsmToken::LParen))1491break;14921493// Parsing %vec-reg + "(" + %sclar-reg/number + ")"1494std::unique_ptr<VEOperand> Op1 = VEOperand::CreateToken(1495Parser.getTok().getString(), Parser.getTok().getLoc());1496Parser.Lex(); // Eat the '('.14971498std::unique_ptr<VEOperand> Op2;1499Res = parseVEAsmOperand(Op2);1500if (!Res.isSuccess() || !Op2)1501return ParseStatus::Failure;15021503if (!Parser.getTok().is(AsmToken::RParen))1504return ParseStatus::Failure;15051506Operands.push_back(std::move(Op1));1507Operands.push_back(std::move(Op2));1508Operands.push_back(VEOperand::CreateToken(Parser.getTok().getString(),1509Parser.getTok().getLoc()));1510Parser.Lex(); // Eat the ')'.1511break;1512}1513}15141515return ParseStatus::Success;1516}15171518ParseStatus VEAsmParser::parseVEAsmOperand(std::unique_ptr<VEOperand> &Op) {1519LLVM_DEBUG(dbgs() << "parseVEAsmOperand\n");1520SMLoc S = Parser.getTok().getLoc();1521SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);1522const MCExpr *EVal;15231524Op = nullptr;1525switch (getLexer().getKind()) {1526default:1527break;15281529case AsmToken::Percent: {1530MCRegister Reg;1531if (tryParseRegister(Reg, S, E).isSuccess())1532Op = VEOperand::CreateReg(Reg, S, E);1533break;1534}1535case AsmToken::Minus:1536case AsmToken::Integer:1537case AsmToken::Dot:1538case AsmToken::Identifier:1539if (!parseExpression(EVal))1540Op = VEOperand::CreateImm(EVal, S, E);1541break;1542}1543return Op ? ParseStatus::Success : ParseStatus::Failure;1544}15451546// Force static initialization.1547extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeVEAsmParser() {1548RegisterMCAsmParser<VEAsmParser> A(getTheVETarget());1549}15501551#define GET_REGISTER_MATCHER1552#define GET_MATCHER_IMPLEMENTATION1553#include "VEGenAsmMatcher.inc"15541555unsigned VEAsmParser::validateTargetOperandClass(MCParsedAsmOperand &GOp,1556unsigned Kind) {1557VEOperand &Op = (VEOperand &)GOp;15581559// VE uses identical register name for all registers like both1560// F32 and I32 uses "%s23". Need to convert the name of them1561// for validation.1562switch (Kind) {1563default:1564break;1565case MCK_F32:1566if (Op.isReg() && VEOperand::MorphToF32Reg(Op))1567return MCTargetAsmParser::Match_Success;1568break;1569case MCK_I32:1570if (Op.isReg() && VEOperand::MorphToI32Reg(Op))1571return MCTargetAsmParser::Match_Success;1572break;1573case MCK_F128:1574if (Op.isReg() && VEOperand::MorphToF128Reg(Op))1575return MCTargetAsmParser::Match_Success;1576break;1577case MCK_VM512:1578if (Op.isReg() && VEOperand::MorphToVM512Reg(Op))1579return MCTargetAsmParser::Match_Success;1580break;1581case MCK_MISC:1582if (Op.isImm() && VEOperand::MorphToMISCReg(Op))1583return MCTargetAsmParser::Match_Success;1584break;1585}1586return Match_InvalidOperand;1587}158815891590