[llvm] 0e0907f - [VE] Implements minimum MC layer for VE (4/4)
Simon Moll via llvm-commits
llvm-commits at lists.llvm.org
Fri May 29 01:51:29 PDT 2020
Author: Kazushi (Jam) Marukawa
Date: 2020-05-29T10:50:16+02:00
New Revision: 0e0907fa0e257ba63d6f820eafbf2079502153ed
URL: https://github.com/llvm/llvm-project/commit/0e0907fa0e257ba63d6f820eafbf2079502153ed
DIFF: https://github.com/llvm/llvm-project/commit/0e0907fa0e257ba63d6f820eafbf2079502153ed.diff
LOG: [VE] Implements minimum MC layer for VE (4/4)
Summary:
This patch includes following items.
- Adds AsmParser and minimum AsmBackend/ELFObjectWriter/MCCodeEmitter to
support only LEA instruction in order to reduce the size of this patch.
- Adds regression test of MC layer for a LEA instruction.
- Relocations are not supported this time to reduce the size of this patch.
Differential Revision: https://reviews.llvm.org/D79546
Added:
llvm/lib/Target/VE/AsmParser/CMakeLists.txt
llvm/lib/Target/VE/AsmParser/LLVMBuild.txt
llvm/lib/Target/VE/AsmParser/VEAsmParser.cpp
llvm/lib/Target/VE/MCTargetDesc/VEAsmBackend.cpp
llvm/lib/Target/VE/MCTargetDesc/VEELFObjectWriter.cpp
llvm/lib/Target/VE/MCTargetDesc/VEMCCodeEmitter.cpp
llvm/test/MC/VE/LEA.s
llvm/test/MC/VE/lit.local.cfg
Modified:
llvm/lib/Target/VE/CMakeLists.txt
llvm/lib/Target/VE/LLVMBuild.txt
llvm/lib/Target/VE/MCTargetDesc/CMakeLists.txt
llvm/lib/Target/VE/MCTargetDesc/VEMCTargetDesc.cpp
llvm/lib/Target/VE/MCTargetDesc/VEMCTargetDesc.h
llvm/lib/Target/VE/VE.td
llvm/lib/Target/VE/VEInstrInfo.td
Removed:
################################################################################
diff --git a/llvm/lib/Target/VE/AsmParser/CMakeLists.txt b/llvm/lib/Target/VE/AsmParser/CMakeLists.txt
new file mode 100644
index 000000000000..1dc76426de67
--- /dev/null
+++ b/llvm/lib/Target/VE/AsmParser/CMakeLists.txt
@@ -0,0 +1,3 @@
+add_llvm_component_library(LLVMVEAsmParser
+ VEAsmParser.cpp
+ )
diff --git a/llvm/lib/Target/VE/AsmParser/LLVMBuild.txt b/llvm/lib/Target/VE/AsmParser/LLVMBuild.txt
new file mode 100644
index 000000000000..b55015219bf3
--- /dev/null
+++ b/llvm/lib/Target/VE/AsmParser/LLVMBuild.txt
@@ -0,0 +1,22 @@
+;===- ./lib/Target/VE/AsmParser/LLVMBuild.txt ------------------*- Conf -*--===;
+;
+; Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+; See https://llvm.org/LICENSE.txt for license information.
+; SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+;
+;===------------------------------------------------------------------------===;
+;
+; This is an LLVMBuild description file for the components in this subdirectory.
+;
+; For more information on the LLVMBuild system, please see:
+;
+; http://llvm.org/docs/LLVMBuild.html
+;
+;===------------------------------------------------------------------------===;
+
+[component_0]
+type = Library
+name = VEAsmParser
+parent = VE
+required_libraries = MC MCParser VEDesc VEInfo Support
+add_to_library_groups = VE
diff --git a/llvm/lib/Target/VE/AsmParser/VEAsmParser.cpp b/llvm/lib/Target/VE/AsmParser/VEAsmParser.cpp
new file mode 100644
index 000000000000..24147d0cd8c0
--- /dev/null
+++ b/llvm/lib/Target/VE/AsmParser/VEAsmParser.cpp
@@ -0,0 +1,692 @@
+//===-- VEAsmParser.cpp - Parse VE assembly to MCInst instructions --------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "MCTargetDesc/VEMCExpr.h"
+#include "MCTargetDesc/VEMCTargetDesc.h"
+#include "TargetInfo/VETargetInfo.h"
+#include "VE.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCParser/MCAsmLexer.h"
+#include "llvm/MC/MCParser/MCAsmParser.h"
+#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
+#include "llvm/MC/MCParser/MCTargetAsmParser.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/Support/TargetRegistry.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <memory>
+
+using namespace llvm;
+
+#define DEBUG_TYPE "ve-asmparser"
+
+namespace {
+
+class VEOperand;
+
+class VEAsmParser : public MCTargetAsmParser {
+ MCAsmParser &Parser;
+
+ /// @name Auto-generated Match Functions
+ /// {
+
+#define GET_ASSEMBLER_HEADER
+#include "VEGenAsmMatcher.inc"
+
+ /// }
+
+ // public interface of the MCTargetAsmParser.
+ bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
+ OperandVector &Operands, MCStreamer &Out,
+ uint64_t &ErrorInfo,
+ bool MatchingInlineAsm) override;
+ bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
+ int parseRegisterName(unsigned (*matchFn)(StringRef));
+ OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc,
+ SMLoc &EndLoc) override;
+ bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
+ SMLoc NameLoc, OperandVector &Operands) override;
+ bool ParseDirective(AsmToken DirectiveID) override;
+
+ // Custom parse functions for VE specific operands.
+ OperandMatchResultTy parseMEMOperand(OperandVector &Operands);
+ OperandMatchResultTy parseOperand(OperandVector &Operands, StringRef Name);
+ OperandMatchResultTy parseVEAsmOperand(std::unique_ptr<VEOperand> &Operand);
+
+public:
+ VEAsmParser(const MCSubtargetInfo &sti, MCAsmParser &parser,
+ const MCInstrInfo &MII, const MCTargetOptions &Options)
+ : MCTargetAsmParser(Options, sti, MII), Parser(parser) {
+ // Initialize the set of available features.
+ setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
+ }
+};
+
+} // end anonymous namespace
+
+namespace {
+
+/// VEOperand - Instances of this class represent a parsed VE machine
+/// instruction.
+class VEOperand : public MCParsedAsmOperand {
+private:
+ enum KindTy {
+ k_Token,
+ k_Register,
+ k_Immediate,
+ // SX-Aurora ASX form is disp(index, base).
+ k_MemoryRegRegImm, // base=reg, index=reg, disp=imm
+ k_MemoryRegImmImm, // base=reg, index=imm, disp=imm
+ k_MemoryZeroRegImm, // base=0, index=reg, disp=imm
+ k_MemoryZeroImmImm, // base=0, index=imm, disp=imm
+ } Kind;
+
+ SMLoc StartLoc, EndLoc;
+
+ struct Token {
+ const char *Data;
+ unsigned Length;
+ };
+
+ struct RegOp {
+ unsigned RegNum;
+ };
+
+ struct ImmOp {
+ const MCExpr *Val;
+ };
+
+ struct MemOp {
+ unsigned Base;
+ unsigned IndexReg;
+ const MCExpr *Index;
+ const MCExpr *Offset;
+ };
+
+ union {
+ struct Token Tok;
+ struct RegOp Reg;
+ struct ImmOp Imm;
+ struct MemOp Mem;
+ };
+
+public:
+ VEOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
+
+ bool isToken() const override { return Kind == k_Token; }
+ bool isReg() const override { return Kind == k_Register; }
+ bool isImm() const override { return Kind == k_Immediate; }
+ bool isMem() const override {
+ return isMEMrri() || isMEMrii() || isMEMzri() || isMEMzii() || isMEMri() ||
+ isMEMzi();
+ }
+ bool isMEMrri() const { return Kind == k_MemoryRegRegImm; }
+ bool isMEMrii() const { return Kind == k_MemoryRegImmImm; }
+ bool isMEMzri() const { return Kind == k_MemoryZeroRegImm; }
+ bool isMEMzii() const { return Kind == k_MemoryZeroImmImm; }
+ // isMEMri and isMEMzi will be implemented later.
+ bool isMEMri() const { return false; }
+ bool isMEMzi() const { return false; }
+ bool isSImm7() {
+ if (!isImm())
+ return false;
+
+ // Constant case
+ if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Val)) {
+ int64_t Value = ConstExpr->getValue();
+ return isInt<7>(Value);
+ }
+ return false;
+ }
+
+ StringRef getToken() const {
+ assert(Kind == k_Token && "Invalid access!");
+ return StringRef(Tok.Data, Tok.Length);
+ }
+
+ unsigned getReg() const override {
+ assert((Kind == k_Register) && "Invalid access!");
+ return Reg.RegNum;
+ }
+
+ const MCExpr *getImm() const {
+ assert((Kind == k_Immediate) && "Invalid access!");
+ return Imm.Val;
+ }
+
+ unsigned getMemBase() const {
+ assert((Kind == k_MemoryRegRegImm || Kind == k_MemoryRegImmImm) &&
+ "Invalid access!");
+ return Mem.Base;
+ }
+
+ unsigned getMemIndexReg() const {
+ assert((Kind == k_MemoryRegRegImm || Kind == k_MemoryZeroRegImm) &&
+ "Invalid access!");
+ return Mem.IndexReg;
+ }
+
+ const MCExpr *getMemIndex() const {
+ assert((Kind == k_MemoryRegImmImm || Kind == k_MemoryZeroImmImm) &&
+ "Invalid access!");
+ return Mem.Index;
+ }
+
+ const MCExpr *getMemOffset() const {
+ assert((Kind == k_MemoryRegRegImm || Kind == k_MemoryRegImmImm ||
+ Kind == k_MemoryZeroImmImm || Kind == k_MemoryZeroRegImm) &&
+ "Invalid access!");
+ return Mem.Offset;
+ }
+
+ void setMemOffset(const MCExpr *off) {
+ assert((Kind == k_MemoryRegRegImm || Kind == k_MemoryRegImmImm ||
+ Kind == k_MemoryZeroImmImm || Kind == k_MemoryZeroRegImm) &&
+ "Invalid access!");
+ Mem.Offset = off;
+ }
+
+ /// getStartLoc - Get the location of the first token of this operand.
+ SMLoc getStartLoc() const override { return StartLoc; }
+ /// getEndLoc - Get the location of the last token of this operand.
+ SMLoc getEndLoc() const override { return EndLoc; }
+
+ void print(raw_ostream &OS) const override {
+ switch (Kind) {
+ case k_Token:
+ OS << "Token: " << getToken() << "\n";
+ break;
+ case k_Register:
+ OS << "Reg: #" << getReg() << "\n";
+ break;
+ case k_Immediate:
+ OS << "Imm: " << getImm() << "\n";
+ break;
+ case k_MemoryRegRegImm:
+ assert(getMemOffset() != nullptr);
+ OS << "Mem: #" << getMemBase() << "+#" << getMemIndexReg() << "+"
+ << *getMemOffset() << "\n";
+ break;
+ case k_MemoryRegImmImm:
+ assert(getMemIndex() != nullptr && getMemOffset() != nullptr);
+ OS << "Mem: #" << getMemBase() << "+" << *getMemIndex() << "+"
+ << *getMemOffset() << "\n";
+ break;
+ case k_MemoryZeroRegImm:
+ assert(getMemOffset() != nullptr);
+ OS << "Mem: 0+#" << getMemIndexReg() << "+" << *getMemOffset() << "\n";
+ break;
+ case k_MemoryZeroImmImm:
+ assert(getMemIndex() != nullptr && getMemOffset() != nullptr);
+ OS << "Mem: 0+" << *getMemIndex() << "+" << *getMemOffset() << "\n";
+ break;
+ }
+ }
+
+ void addRegOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::createReg(getReg()));
+ }
+
+ void addImmOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ const MCExpr *Expr = getImm();
+ addExpr(Inst, Expr);
+ }
+
+ void addSImm7Operands(MCInst &Inst, unsigned N) const {
+ addImmOperands(Inst, N);
+ }
+
+ void addExpr(MCInst &Inst, const MCExpr *Expr) const {
+ // Add as immediate when possible. Null MCExpr = 0.
+ if (!Expr)
+ Inst.addOperand(MCOperand::createImm(0));
+ else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
+ Inst.addOperand(MCOperand::createImm(CE->getValue()));
+ else
+ Inst.addOperand(MCOperand::createExpr(Expr));
+ }
+
+ void addMEMrriOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 3 && "Invalid number of operands!");
+
+ Inst.addOperand(MCOperand::createReg(getMemBase()));
+ Inst.addOperand(MCOperand::createReg(getMemIndexReg()));
+ addExpr(Inst, getMemOffset());
+ }
+
+ void addMEMriiOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 3 && "Invalid number of operands!");
+
+ Inst.addOperand(MCOperand::createReg(getMemBase()));
+ addExpr(Inst, getMemIndex());
+ addExpr(Inst, getMemOffset());
+ }
+
+ void addMEMzriOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 3 && "Invalid number of operands!");
+
+ Inst.addOperand(MCOperand::createImm(0));
+ Inst.addOperand(MCOperand::createReg(getMemIndexReg()));
+ addExpr(Inst, getMemOffset());
+ }
+
+ void addMEMziiOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 3 && "Invalid number of operands!");
+
+ Inst.addOperand(MCOperand::createImm(0));
+ addExpr(Inst, getMemIndex());
+ addExpr(Inst, getMemOffset());
+ }
+
+ void addMEMriOperands(MCInst &Inst, unsigned N) const {
+ // FIXME: implement
+ }
+
+ void addMEMziOperands(MCInst &Inst, unsigned N) const {
+ // FIXME: implement
+ }
+
+ static std::unique_ptr<VEOperand> CreateToken(StringRef Str, SMLoc S) {
+ auto Op = std::make_unique<VEOperand>(k_Token);
+ Op->Tok.Data = Str.data();
+ Op->Tok.Length = Str.size();
+ Op->StartLoc = S;
+ Op->EndLoc = S;
+ return Op;
+ }
+
+ static std::unique_ptr<VEOperand> CreateReg(unsigned RegNum, SMLoc S,
+ SMLoc E) {
+ auto Op = std::make_unique<VEOperand>(k_Register);
+ Op->Reg.RegNum = RegNum;
+ Op->StartLoc = S;
+ Op->EndLoc = E;
+ return Op;
+ }
+
+ static std::unique_ptr<VEOperand> CreateImm(const MCExpr *Val, SMLoc S,
+ SMLoc E) {
+ auto Op = std::make_unique<VEOperand>(k_Immediate);
+ Op->Imm.Val = Val;
+ Op->StartLoc = S;
+ Op->EndLoc = E;
+ return Op;
+ }
+
+ static std::unique_ptr<VEOperand>
+ MorphToMEMrri(unsigned Base, unsigned Index, std::unique_ptr<VEOperand> Op) {
+ const MCExpr *Imm = Op->getImm();
+ Op->Kind = k_MemoryRegRegImm;
+ Op->Mem.Base = Base;
+ Op->Mem.IndexReg = Index;
+ Op->Mem.Index = nullptr;
+ Op->Mem.Offset = Imm;
+ return Op;
+ }
+
+ static std::unique_ptr<VEOperand>
+ MorphToMEMrii(unsigned Base, const MCExpr *Index,
+ std::unique_ptr<VEOperand> Op) {
+ const MCExpr *Imm = Op->getImm();
+ Op->Kind = k_MemoryRegImmImm;
+ Op->Mem.Base = Base;
+ Op->Mem.IndexReg = 0;
+ Op->Mem.Index = Index;
+ Op->Mem.Offset = Imm;
+ return Op;
+ }
+
+ static std::unique_ptr<VEOperand>
+ MorphToMEMzri(unsigned Index, std::unique_ptr<VEOperand> Op) {
+ const MCExpr *Imm = Op->getImm();
+ Op->Kind = k_MemoryZeroRegImm;
+ Op->Mem.Base = 0;
+ Op->Mem.IndexReg = Index;
+ Op->Mem.Index = nullptr;
+ Op->Mem.Offset = Imm;
+ return Op;
+ }
+
+ static std::unique_ptr<VEOperand>
+ MorphToMEMzii(const MCExpr *Index, std::unique_ptr<VEOperand> Op) {
+ const MCExpr *Imm = Op->getImm();
+ Op->Kind = k_MemoryZeroImmImm;
+ Op->Mem.Base = 0;
+ Op->Mem.IndexReg = 0;
+ Op->Mem.Index = Index;
+ Op->Mem.Offset = Imm;
+ return Op;
+ }
+};
+
+} // end anonymous namespace
+
+bool VEAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
+ OperandVector &Operands,
+ MCStreamer &Out, uint64_t &ErrorInfo,
+ bool MatchingInlineAsm) {
+ MCInst Inst;
+ unsigned MatchResult =
+ MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
+ switch (MatchResult) {
+ case Match_Success:
+ Inst.setLoc(IDLoc);
+ Out.emitInstruction(Inst, getSTI());
+ return false;
+
+ case Match_MissingFeature:
+ return Error(IDLoc,
+ "instruction requires a CPU feature not currently enabled");
+
+ case Match_InvalidOperand: {
+ SMLoc ErrorLoc = IDLoc;
+ if (ErrorInfo != ~0ULL) {
+ if (ErrorInfo >= Operands.size())
+ return Error(IDLoc, "too few operands for instruction");
+
+ ErrorLoc = ((VEOperand &)*Operands[ErrorInfo]).getStartLoc();
+ if (ErrorLoc == SMLoc())
+ ErrorLoc = IDLoc;
+ }
+
+ return Error(ErrorLoc, "invalid operand for instruction");
+ }
+ case Match_MnemonicFail:
+ return Error(IDLoc, "invalid instruction mnemonic");
+ }
+ llvm_unreachable("Implement any new match types added!");
+}
+
+bool VEAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
+ SMLoc &EndLoc) {
+ if (tryParseRegister(RegNo, StartLoc, EndLoc) != MatchOperand_Success)
+ return Error(StartLoc, "invalid register name");
+ return false;
+}
+
+/// Parses a register name using a given matching function.
+/// Checks for lowercase or uppercase if necessary.
+int VEAsmParser::parseRegisterName(unsigned (*matchFn)(StringRef)) {
+ StringRef Name = Parser.getTok().getString();
+
+ int RegNum = matchFn(Name);
+
+ // GCC supports case insensitive register names. All of the VE registers
+ // are all lower case.
+ if (RegNum == VE::NoRegister) {
+ RegNum = matchFn(Name.lower());
+ }
+
+ return RegNum;
+}
+
+/// Maps from the set of all register names to a register number.
+/// \note Generated by TableGen.
+static unsigned MatchRegisterName(StringRef Name);
+
+/// Maps from the set of all alternative registernames to a register number.
+/// \note Generated by TableGen.
+static unsigned MatchRegisterAltName(StringRef Name);
+
+OperandMatchResultTy
+VEAsmParser::tryParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) {
+ const AsmToken Tok = Parser.getTok();
+ StartLoc = Tok.getLoc();
+ EndLoc = Tok.getEndLoc();
+ RegNo = 0;
+ if (getLexer().getKind() != AsmToken::Percent)
+ return MatchOperand_NoMatch;
+ Parser.Lex();
+
+ RegNo = parseRegisterName(&MatchRegisterName);
+ if (RegNo == VE::NoRegister)
+ RegNo = parseRegisterName(&MatchRegisterAltName);
+
+ if (RegNo != VE::NoRegister) {
+ Parser.Lex();
+ return MatchOperand_Success;
+ }
+
+ getLexer().UnLex(Tok);
+ return MatchOperand_NoMatch;
+}
+
+bool VEAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
+ SMLoc NameLoc, OperandVector &Operands) {
+
+ // First operand in MCInst is instruction mnemonic.
+ Operands.push_back(VEOperand::CreateToken(Name, NameLoc));
+
+ if (getLexer().isNot(AsmToken::EndOfStatement)) {
+ // Read the first operand.
+ if (parseOperand(Operands, Name) != MatchOperand_Success) {
+ SMLoc Loc = getLexer().getLoc();
+ return Error(Loc, "unexpected token");
+ }
+
+ while (getLexer().is(AsmToken::Comma)) {
+ Parser.Lex(); // Eat the comma.
+ // Parse and remember the operand.
+ if (parseOperand(Operands, Name) != MatchOperand_Success) {
+ SMLoc Loc = getLexer().getLoc();
+ return Error(Loc, "unexpected token");
+ }
+ }
+ }
+ if (getLexer().isNot(AsmToken::EndOfStatement)) {
+ SMLoc Loc = getLexer().getLoc();
+ return Error(Loc, "unexpected token");
+ }
+ Parser.Lex(); // Consume the EndOfStatement.
+ return false;
+}
+
+bool VEAsmParser::ParseDirective(AsmToken DirectiveID) {
+ // Let the MC layer to handle other directives.
+ return true;
+}
+
+OperandMatchResultTy VEAsmParser::parseMEMOperand(OperandVector &Operands) {
+ LLVM_DEBUG(dbgs() << "parseMEMOperand\n");
+ const AsmToken &Tok = Parser.getTok();
+ SMLoc S = Tok.getLoc();
+ SMLoc E = Tok.getEndLoc();
+ // Parse ASX format
+ // disp
+ // disp(, base)
+ // disp(index)
+ // disp(index, base)
+ // (, base)
+ // (index)
+ // (index, base)
+
+ std::unique_ptr<VEOperand> Offset;
+ switch (getLexer().getKind()) {
+ default:
+ return MatchOperand_NoMatch;
+
+ case AsmToken::Minus:
+ case AsmToken::Integer:
+ case AsmToken::Dot: {
+ const MCExpr *EVal;
+ if (!getParser().parseExpression(EVal, E))
+ Offset = VEOperand::CreateImm(EVal, S, E);
+ else
+ return MatchOperand_NoMatch;
+ break;
+ }
+ case AsmToken::LParen:
+ // empty disp (= 0)
+ Offset =
+ VEOperand::CreateImm(MCConstantExpr::create(0, getContext()), S, E);
+ break;
+ }
+
+ switch (getLexer().getKind()) {
+ default:
+ return MatchOperand_ParseFail;
+
+ case AsmToken::EndOfStatement:
+ Operands.push_back(VEOperand::MorphToMEMzii(
+ MCConstantExpr::create(0, getContext()), std::move(Offset)));
+ return MatchOperand_Success;
+
+ case AsmToken::LParen:
+ Parser.Lex(); // Eat the (
+ break;
+ }
+
+ const MCExpr *IndexValue = nullptr;
+ unsigned IndexReg = 0;
+
+ switch (getLexer().getKind()) {
+ default:
+ if (ParseRegister(IndexReg, S, E))
+ return MatchOperand_ParseFail;
+ break;
+
+ case AsmToken::Minus:
+ case AsmToken::Integer:
+ case AsmToken::Dot:
+ if (getParser().parseExpression(IndexValue, E))
+ return MatchOperand_ParseFail;
+ break;
+
+ case AsmToken::Comma:
+ // empty index
+ IndexValue = MCConstantExpr::create(0, getContext());
+ break;
+ }
+
+ switch (getLexer().getKind()) {
+ default:
+ return MatchOperand_ParseFail;
+
+ case AsmToken::RParen:
+ Parser.Lex(); // Eat the )
+ Operands.push_back(
+ IndexValue ? VEOperand::MorphToMEMzii(IndexValue, std::move(Offset))
+ : VEOperand::MorphToMEMzri(IndexReg, std::move(Offset)));
+ return MatchOperand_Success;
+
+ case AsmToken::Comma:
+ Parser.Lex(); // Eat the ,
+ break;
+ }
+
+ unsigned BaseReg = 0;
+ if (ParseRegister(BaseReg, S, E))
+ return MatchOperand_ParseFail;
+
+ if (!Parser.getTok().is(AsmToken::RParen))
+ return MatchOperand_ParseFail;
+
+ Parser.Lex(); // Eat the )
+ Operands.push_back(
+ IndexValue
+ ? VEOperand::MorphToMEMrii(BaseReg, IndexValue, std::move(Offset))
+ : VEOperand::MorphToMEMrri(BaseReg, IndexReg, std::move(Offset)));
+
+ return MatchOperand_Success;
+}
+
+OperandMatchResultTy VEAsmParser::parseOperand(OperandVector &Operands,
+ StringRef Mnemonic) {
+ LLVM_DEBUG(dbgs() << "parseOperand\n");
+ OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
+
+ // If there wasn't a custom match, try the generic matcher below. Otherwise,
+ // there was a match, but an error occurred, in which case, just return that
+ // the operand parsing failed.
+ if (ResTy == MatchOperand_Success || ResTy == MatchOperand_ParseFail)
+ return ResTy;
+
+ switch (getLexer().getKind()) {
+ case AsmToken::LParen:
+ // FIXME: Parsing "(" + %vreg + ", " + %vreg + ")"
+ // FALLTHROUGH
+ default: {
+ std::unique_ptr<VEOperand> Op;
+ ResTy = parseVEAsmOperand(Op);
+ if (ResTy != MatchOperand_Success || !Op)
+ return MatchOperand_ParseFail;
+
+ // Push the parsed operand into the list of operands
+ Operands.push_back(std::move(Op));
+
+ if (!Parser.getTok().is(AsmToken::LParen))
+ break;
+
+ // FIXME: Parsing %vec-reg + "(" + %sclar-reg/number + ")"
+ break;
+ }
+ }
+
+ return MatchOperand_Success;
+}
+
+OperandMatchResultTy
+VEAsmParser::parseVEAsmOperand(std::unique_ptr<VEOperand> &Op) {
+ LLVM_DEBUG(dbgs() << "parseVEAsmOperand\n");
+ SMLoc S = Parser.getTok().getLoc();
+ SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
+ const MCExpr *EVal;
+
+ Op = nullptr;
+ switch (getLexer().getKind()) {
+ default:
+ break;
+
+ case AsmToken::Percent:
+ unsigned RegNo;
+ if (tryParseRegister(RegNo, S, E) == MatchOperand_Success)
+ Op = VEOperand::CreateReg(RegNo, S, E);
+ break;
+
+ case AsmToken::Minus:
+ case AsmToken::Integer:
+ case AsmToken::Dot:
+ if (!getParser().parseExpression(EVal, E))
+ Op = VEOperand::CreateImm(EVal, S, E);
+ break;
+
+ case AsmToken::Identifier: {
+ StringRef Identifier;
+ if (!getParser().parseIdentifier(Identifier)) {
+ E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
+ MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
+
+ const MCExpr *Res =
+ MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
+ Op = VEOperand::CreateImm(Res, S, E);
+ }
+ break;
+ }
+ }
+ return (Op) ? MatchOperand_Success : MatchOperand_ParseFail;
+}
+
+// Force static initialization.
+extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeVEAsmParser() {
+ RegisterMCAsmParser<VEAsmParser> A(getTheVETarget());
+}
+
+#define GET_REGISTER_MATCHER
+#define GET_MATCHER_IMPLEMENTATION
+#include "VEGenAsmMatcher.inc"
diff --git a/llvm/lib/Target/VE/CMakeLists.txt b/llvm/lib/Target/VE/CMakeLists.txt
index 89c946d87e19..4b9169da63c0 100644
--- a/llvm/lib/Target/VE/CMakeLists.txt
+++ b/llvm/lib/Target/VE/CMakeLists.txt
@@ -2,7 +2,9 @@ set(LLVM_TARGET_DEFINITIONS VE.td)
tablegen(LLVM VEGenRegisterInfo.inc -gen-register-info)
tablegen(LLVM VEGenInstrInfo.inc -gen-instr-info)
+tablegen(LLVM VEGenMCCodeEmitter.inc -gen-emitter)
tablegen(LLVM VEGenAsmWriter.inc -gen-asm-writer)
+tablegen(LLVM VEGenAsmMatcher.inc -gen-asm-matcher)
tablegen(LLVM VEGenDAGISel.inc -gen-dag-isel)
tablegen(LLVM VEGenSubtargetInfo.inc -gen-subtarget)
tablegen(LLVM VEGenCallingConv.inc -gen-callingconv)
@@ -21,5 +23,6 @@ add_llvm_target(VECodeGen
VETargetMachine.cpp
)
+add_subdirectory(AsmParser)
add_subdirectory(TargetInfo)
add_subdirectory(MCTargetDesc)
diff --git a/llvm/lib/Target/VE/LLVMBuild.txt b/llvm/lib/Target/VE/LLVMBuild.txt
index eb74a9a387b0..f3169930771c 100644
--- a/llvm/lib/Target/VE/LLVMBuild.txt
+++ b/llvm/lib/Target/VE/LLVMBuild.txt
@@ -15,13 +15,13 @@
;===------------------------------------------------------------------------===;
[common]
-subdirectories = MCTargetDesc TargetInfo
+subdirectories = AsmParser MCTargetDesc TargetInfo
[component_0]
type = TargetGroup
name = VE
parent = Target
-has_asmparser = 0
+has_asmparser = 1
has_asmprinter = 1
[component_1]
diff --git a/llvm/lib/Target/VE/MCTargetDesc/CMakeLists.txt b/llvm/lib/Target/VE/MCTargetDesc/CMakeLists.txt
index 9bca0ceeb69b..4d8787ff8609 100644
--- a/llvm/lib/Target/VE/MCTargetDesc/CMakeLists.txt
+++ b/llvm/lib/Target/VE/MCTargetDesc/CMakeLists.txt
@@ -1,6 +1,9 @@
add_llvm_component_library(LLVMVEDesc
+ VEAsmBackend.cpp
+ VEELFObjectWriter.cpp
VEInstPrinter.cpp
VEMCAsmInfo.cpp
+ VEMCCodeEmitter.cpp
VEMCExpr.cpp
VEMCTargetDesc.cpp
VETargetStreamer.cpp
diff --git a/llvm/lib/Target/VE/MCTargetDesc/VEAsmBackend.cpp b/llvm/lib/Target/VE/MCTargetDesc/VEAsmBackend.cpp
new file mode 100644
index 000000000000..dcc9fe8f7e4a
--- /dev/null
+++ b/llvm/lib/Target/VE/MCTargetDesc/VEAsmBackend.cpp
@@ -0,0 +1,120 @@
+//===-- VEAsmBackend.cpp - VE Assembler Backend ---------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "MCTargetDesc/VEFixupKinds.h"
+#include "MCTargetDesc/VEMCTargetDesc.h"
+#include "llvm/MC/MCAsmBackend.h"
+#include "llvm/MC/MCELFObjectWriter.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCFixupKindInfo.h"
+#include "llvm/MC/MCObjectWriter.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCValue.h"
+#include "llvm/Support/EndianStream.h"
+#include "llvm/Support/TargetRegistry.h"
+
+using namespace llvm;
+
+static uint64_t adjustFixupValue(unsigned Kind, uint64_t Value) {
+ switch (Kind) {
+ default:
+ llvm_unreachable("Unknown fixup kind!");
+ }
+}
+
+namespace {
+class VEAsmBackend : public MCAsmBackend {
+protected:
+ const Target &TheTarget;
+
+public:
+ VEAsmBackend(const Target &T) : MCAsmBackend(support::little), TheTarget(T) {}
+
+ unsigned getNumFixupKinds() const override { return VE::NumTargetFixupKinds; }
+
+ const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override {
+ if (Kind < FirstTargetFixupKind)
+ return MCAsmBackend::getFixupKindInfo(Kind);
+
+ // FIXME.
+ llvm_unreachable("getFixupKindInfo() unimplemented");
+ }
+
+ bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup,
+ const MCValue &Target) override {
+ // FIXME.
+ return false;
+ }
+
+ bool mayNeedRelaxation(const MCInst &Inst,
+ const MCSubtargetInfo &STI) const override {
+ // FIXME.
+ return false;
+ }
+
+ /// fixupNeedsRelaxation - Target specific predicate for whether a given
+ /// fixup requires the associated instruction to be relaxed.
+ bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
+ const MCRelaxableFragment *DF,
+ const MCAsmLayout &Layout) const override {
+ // FIXME.
+ llvm_unreachable("fixupNeedsRelaxation() unimplemented");
+ return false;
+ }
+ void relaxInstruction(MCInst &Inst,
+ const MCSubtargetInfo &STI) const override {
+ // FIXME.
+ llvm_unreachable("relaxInstruction() unimplemented");
+ }
+
+ bool writeNopData(raw_ostream &OS, uint64_t Count) const override {
+ if ((Count % 8) != 0)
+ return false;
+
+ for (uint64_t i = 0; i < Count; i += 8)
+ support::endian::write<uint64_t>(OS, 0x7900000000000000ULL,
+ support::little);
+
+ return true;
+ }
+};
+
+class ELFVEAsmBackend : public VEAsmBackend {
+ Triple::OSType OSType;
+
+public:
+ ELFVEAsmBackend(const Target &T, Triple::OSType OSType)
+ : VEAsmBackend(T), OSType(OSType) {}
+
+ void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
+ const MCValue &Target, MutableArrayRef<char> Data,
+ uint64_t Value, bool IsResolved,
+ const MCSubtargetInfo *STI) const override {
+ Value = adjustFixupValue(Fixup.getKind(), Value);
+ if (!Value)
+ return; // Doesn't change encoding.
+
+ // FIXME.
+ llvm_unreachable("applyFixup() unimplemented");
+ }
+
+ std::unique_ptr<MCObjectTargetWriter>
+ createObjectTargetWriter() const override {
+ uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(OSType);
+ return createVEELFObjectWriter(OSABI);
+ }
+};
+
+} // end anonymous namespace
+
+MCAsmBackend *llvm::createVEAsmBackend(const Target &T,
+ const MCSubtargetInfo &STI,
+ const MCRegisterInfo &MRI,
+ const MCTargetOptions &Options) {
+ return new ELFVEAsmBackend(T, STI.getTargetTriple().getOS());
+}
diff --git a/llvm/lib/Target/VE/MCTargetDesc/VEELFObjectWriter.cpp b/llvm/lib/Target/VE/MCTargetDesc/VEELFObjectWriter.cpp
new file mode 100644
index 000000000000..77ac97979cef
--- /dev/null
+++ b/llvm/lib/Target/VE/MCTargetDesc/VEELFObjectWriter.cpp
@@ -0,0 +1,53 @@
+//===-- VEELFObjectWriter.cpp - VE ELF Writer -----------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "VEFixupKinds.h"
+#include "VEMCTargetDesc.h"
+#include "llvm/MC/MCELFObjectWriter.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCObjectWriter.h"
+#include "llvm/MC/MCValue.h"
+#include "llvm/Support/ErrorHandling.h"
+
+using namespace llvm;
+
+namespace {
+class VEELFObjectWriter : public MCELFObjectTargetWriter {
+public:
+ VEELFObjectWriter(uint8_t OSABI)
+ : MCELFObjectTargetWriter(/* Is64Bit */ true, OSABI, ELF::EM_VE,
+ /* HasRelocationAddend */ true) {}
+
+ ~VEELFObjectWriter() override {}
+
+protected:
+ unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
+ const MCFixup &Fixup, bool IsPCRel) const override;
+
+ bool needsRelocateWithSymbol(const MCSymbol &Sym,
+ unsigned Type) const override;
+};
+} // namespace
+
+unsigned VEELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target,
+ const MCFixup &Fixup,
+ bool IsPCRel) const {
+ // FIXME: implements.
+ return ELF::R_VE_NONE;
+}
+
+bool VEELFObjectWriter::needsRelocateWithSymbol(const MCSymbol &Sym,
+ unsigned Type) const {
+ // FIXME: implements.
+ return false;
+}
+
+std::unique_ptr<MCObjectTargetWriter>
+llvm::createVEELFObjectWriter(uint8_t OSABI) {
+ return std::make_unique<VEELFObjectWriter>(OSABI);
+}
diff --git a/llvm/lib/Target/VE/MCTargetDesc/VEMCCodeEmitter.cpp b/llvm/lib/Target/VE/MCTargetDesc/VEMCCodeEmitter.cpp
new file mode 100644
index 000000000000..b8328c6cb58d
--- /dev/null
+++ b/llvm/lib/Target/VE/MCTargetDesc/VEMCCodeEmitter.cpp
@@ -0,0 +1,122 @@
+//===-- VEMCCodeEmitter.cpp - Convert VE code to machine code -------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the VEMCCodeEmitter class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MCTargetDesc/VEFixupKinds.h"
+#include "VE.h"
+#include "VEMCExpr.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/MC/MCCodeEmitter.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCFixup.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/Support/EndianStream.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <cstdint>
+
+using namespace llvm;
+
+#define DEBUG_TYPE "mccodeemitter"
+
+STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
+
+namespace {
+
+class VEMCCodeEmitter : public MCCodeEmitter {
+ const MCInstrInfo &MCII;
+ MCContext &Ctx;
+
+public:
+ VEMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx)
+ : MCII(mcii), Ctx(ctx) {}
+ VEMCCodeEmitter(const VEMCCodeEmitter &) = delete;
+ VEMCCodeEmitter &operator=(const VEMCCodeEmitter &) = delete;
+ ~VEMCCodeEmitter() override = default;
+
+ void encodeInstruction(const MCInst &MI, raw_ostream &OS,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const override;
+
+ // getBinaryCodeForInstr - TableGen'erated function for getting the
+ // binary encoding for an instruction.
+ uint64_t getBinaryCodeForInstr(const MCInst &MI,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const;
+
+ /// getMachineOpValue - Return binary encoding of operand. If the machine
+ /// operand requires relocation, record the relocation and return zero.
+ unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const;
+
+private:
+ FeatureBitset computeAvailableFeatures(const FeatureBitset &FB) const;
+ void
+ verifyInstructionPredicates(const MCInst &MI,
+ const FeatureBitset &AvailableFeatures) const;
+};
+
+} // end anonymous namespace
+
+void VEMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
+ verifyInstructionPredicates(MI,
+ computeAvailableFeatures(STI.getFeatureBits()));
+
+ uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
+ support::endian::write<uint64_t>(OS, Bits, support::little);
+
+ ++MCNumEmitted; // Keep track of the # of mi's emitted.
+}
+
+unsigned VEMCCodeEmitter::getMachineOpValue(const MCInst &MI,
+ const MCOperand &MO,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
+ if (MO.isReg())
+ return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
+
+ if (MO.isImm())
+ return MO.getImm();
+
+ assert(MO.isExpr());
+ const MCExpr *Expr = MO.getExpr();
+ if (const VEMCExpr *SExpr = dyn_cast<VEMCExpr>(Expr)) {
+ MCFixupKind Kind = (MCFixupKind)SExpr->getFixupKind();
+ Fixups.push_back(MCFixup::create(0, Expr, Kind));
+ return 0;
+ }
+
+ int64_t Res;
+ if (Expr->evaluateAsAbsolute(Res))
+ return Res;
+
+ llvm_unreachable("Unhandled expression!");
+ return 0;
+}
+
+#define ENABLE_INSTR_PREDICATE_VERIFIER
+#include "VEGenMCCodeEmitter.inc"
+
+MCCodeEmitter *llvm::createVEMCCodeEmitter(const MCInstrInfo &MCII,
+ const MCRegisterInfo &MRI,
+ MCContext &Ctx) {
+ return new VEMCCodeEmitter(MCII, Ctx);
+}
diff --git a/llvm/lib/Target/VE/MCTargetDesc/VEMCTargetDesc.cpp b/llvm/lib/Target/VE/MCTargetDesc/VEMCTargetDesc.cpp
index bf964782515c..a39cffc8f4a6 100644
--- a/llvm/lib/Target/VE/MCTargetDesc/VEMCTargetDesc.cpp
+++ b/llvm/lib/Target/VE/MCTargetDesc/VEMCTargetDesc.cpp
@@ -94,6 +94,12 @@ extern "C" void LLVMInitializeVETargetMC() {
// Register the MC subtarget info.
TargetRegistry::RegisterMCSubtargetInfo(*T, createVEMCSubtargetInfo);
+ // Register the MC Code Emitter.
+ TargetRegistry::RegisterMCCodeEmitter(*T, createVEMCCodeEmitter);
+
+ // Register the asm backend.
+ TargetRegistry::RegisterMCAsmBackend(*T, createVEAsmBackend);
+
// Register the object target streamer.
TargetRegistry::RegisterObjectTargetStreamer(*T,
createObjectTargetStreamer);
diff --git a/llvm/lib/Target/VE/MCTargetDesc/VEMCTargetDesc.h b/llvm/lib/Target/VE/MCTargetDesc/VEMCTargetDesc.h
index 79acc509b3c8..7fb8a556aa74 100644
--- a/llvm/lib/Target/VE/MCTargetDesc/VEMCTargetDesc.h
+++ b/llvm/lib/Target/VE/MCTargetDesc/VEMCTargetDesc.h
@@ -22,7 +22,7 @@ class MCAsmBackend;
class MCCodeEmitter;
class MCContext;
class MCInstrInfo;
-class MCObjectWriter;
+class MCObjectTargetWriter;
class MCRegisterInfo;
class MCSubtargetInfo;
class MCTargetOptions;
@@ -31,6 +31,13 @@ class Triple;
class StringRef;
class raw_pwrite_stream;
class raw_ostream;
+
+MCCodeEmitter *createVEMCCodeEmitter(const MCInstrInfo &MCII,
+ const MCRegisterInfo &MRI, MCContext &Ctx);
+MCAsmBackend *createVEAsmBackend(const Target &T, const MCSubtargetInfo &STI,
+ const MCRegisterInfo &MRI,
+ const MCTargetOptions &Options);
+std::unique_ptr<MCObjectTargetWriter> createVEELFObjectWriter(uint8_t OSABI);
} // namespace llvm
// Defines symbolic names for VE registers. This defines a mapping from
diff --git a/llvm/lib/Target/VE/VE.td b/llvm/lib/Target/VE/VE.td
index 7404321b1a06..617a6ea458b6 100644
--- a/llvm/lib/Target/VE/VE.td
+++ b/llvm/lib/Target/VE/VE.td
@@ -29,6 +29,13 @@ include "VEInstrInfo.td"
def VEInstrInfo : InstrInfo;
+def VEAsmParser : AsmParser {
+ // Use both VE register name matcher to accept "S0~S63" register names
+ // and default register matcher to accept other registeres.
+ let AllowDuplicateRegisterNames = 1;
+ let ShouldEmitMatchRegisterAltName = 1;
+}
+
//===----------------------------------------------------------------------===//
// VE processors supported.
//===----------------------------------------------------------------------===//
@@ -51,6 +58,7 @@ def VEAsmWriter : AsmWriter {
def VE : Target {
// Pull in Instruction Info:
let InstructionSet = VEInstrInfo;
+ let AssemblyParsers = [VEAsmParser];
let AssemblyWriters = [VEAsmWriter];
let AllowRegisterRenaming = 1;
}
diff --git a/llvm/lib/Target/VE/VEInstrInfo.td b/llvm/lib/Target/VE/VEInstrInfo.td
index c7815efb8c71..0a37e52e0240 100644
--- a/llvm/lib/Target/VE/VEInstrInfo.td
+++ b/llvm/lib/Target/VE/VEInstrInfo.td
@@ -263,20 +263,6 @@ def fcond2ccSwap : SDNodeXForm<cond, [{
return CurDAG->getTargetConstant(cc, SDLoc(N), MVT::i32);
}]>;
-// Addressing modes.
-def ADDRri : ComplexPattern<iPTR, 2, "selectADDRri", [frameindex], []>;
-
-def MEMri : Operand<iPTR> {
- let PrintMethod = "printMemASOperandASX";
- let MIOperandInfo = (ops ptr_rc, i64imm);
-}
-
-// AS format of memory address
-def MEMASri : Operand<iPTR> {
- let PrintMethod = "printMemASOperand";
- let MIOperandInfo = (ops ptr_rc, i64imm);
-}
-
// Addressing modes.
// SX-Aurora has following fields.
// sz: register or 0
@@ -307,8 +293,10 @@ def ADDRrri : ComplexPattern<iPTR, 3, "selectADDRrri", [frameindex], []>;
def ADDRrii : ComplexPattern<iPTR, 3, "selectADDRrii", [frameindex], []>;
def ADDRzri : ComplexPattern<iPTR, 3, "selectADDRzri", [], []>;
def ADDRzii : ComplexPattern<iPTR, 3, "selectADDRzii", [], []>;
+// AS format:
+def ADDRri : ComplexPattern<iPTR, 2, "selectADDRri", [frameindex], []>;
//
-// ASX assembly instrcution format:
+// ASX assembly instruction format:
def VEMEMrriAsmOperand : AsmOperandClass {
let Name = "MEMrri";
let ParserMethod = "parseMEMOperand";
@@ -345,14 +333,12 @@ def MEMzii : Operand<iPTR> {
let MIOperandInfo = (ops i32imm /* = 0 */, i32imm, i32imm);
let ParserMatchClass = VEMEMziiAsmOperand;
}
-// AS assembly instrcution format:
+// AS assembly instruction format:
def VEMEMriAsmOperand : AsmOperandClass {
let Name = "MEMri";
- let ParserMethod = "parseMEMAsOperand";
}
def VEMEMziAsmOperand : AsmOperandClass {
let Name = "MEMzi";
- let ParserMethod = "parseMEMAsOperand";
}
// AS generic assembly instruction format:
def MEMriASX : Operand<iPTR> {
@@ -365,6 +351,11 @@ def MEMziASX : Operand<iPTR> {
let MIOperandInfo = (ops i32imm /* = 0 */, i32imm);
let ParserMatchClass = VEMEMziAsmOperand;
}
+def MEMASri : Operand<iPTR> {
+ let PrintMethod = "printMemASOperand";
+ let MIOperandInfo = (ops ptr_rc, i32imm);
+ let ParserMatchClass = VEMEMriAsmOperand;
+}
// Branch targets have OtherVT type.
def brtarget32 : Operand<OtherVT> {
diff --git a/llvm/test/MC/VE/LEA.s b/llvm/test/MC/VE/LEA.s
new file mode 100644
index 000000000000..fca99d59f57c
--- /dev/null
+++ b/llvm/test/MC/VE/LEA.s
@@ -0,0 +1,29 @@
+# RUN: llvm-mc -triple ve-unknown-unknown --show-encoding %s | FileCheck %s
+
+# CHECK: lea %s11, 23
+# CHECK: encoding: [0x17,0x00,0x00,0x00,0x00,0x00,0x0b,0x06]
+lea %s11, 23
+
+# CHECK: lea %s63, 324(, %s11)
+# CHECK: encoding: [0x44,0x01,0x00,0x00,0x8b,0x00,0x3f,0x06]
+lea %s63, 324(,%s11)
+
+# CHECK: lea %s11, 324(%s10)
+# CHECK: encoding: [0x44,0x01,0x00,0x00,0x00,0x8a,0x0b,0x06]
+lea %s11, 324(%s10 )
+
+# CHECK: lea %s11, 324(%s13, %s11)
+# CHECK: encoding: [0x44,0x01,0x00,0x00,0x8b,0x8d,0x0b,0x06]
+lea %s11, 324 (%s13,%s11)
+
+# CHECK: lea %s11, (%s10)
+# CHECK: encoding: [0x00,0x00,0x00,0x00,0x00,0x8a,0x0b,0x06]
+lea %s11, (%s10)
+
+# CHECK: lea %s11, (, %s12)
+# CHECK: encoding: [0x00,0x00,0x00,0x00,0x8c,0x00,0x0b,0x06]
+lea %s11, (,%s12)
+
+# CHECK: lea.sl %s11, -1(%s13, %s11)
+# CHECK: encoding: [0xff,0xff,0xff,0xff,0x8b,0x8d,0x8b,0x06]
+lea.sl %s11, -1(%s13, %s11)
diff --git a/llvm/test/MC/VE/lit.local.cfg b/llvm/test/MC/VE/lit.local.cfg
new file mode 100644
index 000000000000..b6366779272d
--- /dev/null
+++ b/llvm/test/MC/VE/lit.local.cfg
@@ -0,0 +1,2 @@
+if not 'VE' in config.root.targets:
+ config.unsupported = True
More information about the llvm-commits
mailing list