[SystemZ] Add z13 vector facility and MC support

This patch adds support for the z13 processor type and its vector facility,
and adds MC support for all new instructions provided by that facilily.

Apart from defining the new instructions, the main changes are:

- Adding VR128, VR64 and VR32 register classes.
- Making FP64 a subclass of VR64 and FP32 a subclass of VR32.
- Adding a D(V,B) addressing mode for scatter/gather operations
- Adding 1-, 2-, and 3-bit immediate operands for some 4-bit fields.
  Until now all immediate operands have been the same width as the
  underlying field (hence the assert->return change in decode[SU]ImmOperand).

In addition, sys::getHostCPUName is extended to detect running natively
on a z13 machine.

Based on a patch by Richard Sandiford.



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@236520 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Ulrich Weigand 2015-05-05 19:23:40 +00:00
parent 2c04d158ce
commit 1a21909e98
22 changed files with 13182 additions and 117 deletions

View File

@ -682,6 +682,28 @@ StringRef sys::getHostCPUName() {
StringRef Str(buffer, CPUInfoSize);
SmallVector<StringRef, 32> Lines;
Str.split(Lines, "\n");
// Look for the CPU features.
SmallVector<StringRef, 32> CPUFeatures;
for (unsigned I = 0, E = Lines.size(); I != E; ++I)
if (Lines[I].startswith("features")) {
size_t Pos = Lines[I].find(":");
if (Pos != StringRef::npos) {
Lines[I].drop_front(Pos + 1).split(CPUFeatures, " ");
break;
}
}
// We need to check for the presence of vector support independently of
// the machine type, since we may only use the vector register set when
// supported by the kernel (and hypervisor).
bool HaveVectorSupport = false;
for (unsigned I = 0, E = CPUFeatures.size(); I != E; ++I) {
if (CPUFeatures[I] == "vx")
HaveVectorSupport = true;
}
// Now check the processor machine type.
for (unsigned I = 0, E = Lines.size(); I != E; ++I) {
if (Lines[I].startswith("processor ")) {
size_t Pos = Lines[I].find("machine = ");
@ -689,6 +711,8 @@ StringRef sys::getHostCPUName() {
Pos += sizeof("machine = ") - 1;
unsigned int Id;
if (!Lines[I].drop_front(Pos).getAsInteger(10, Id)) {
if (Id >= 2964 && HaveVectorSupport)
return "z13";
if (Id >= 2827)
return "zEC12";
if (Id >= 2817)

View File

@ -39,13 +39,17 @@ enum RegisterKind {
ADDR64Reg,
FP32Reg,
FP64Reg,
FP128Reg
FP128Reg,
VR32Reg,
VR64Reg,
VR128Reg
};
enum MemoryKind {
BDMem,
BDXMem,
BDLMem
BDLMem,
BDVMem
};
class SystemZOperand : public MCParsedAsmOperand {
@ -89,10 +93,10 @@ private:
// the base register has (ADDR32Reg or ADDR64Reg). Length is the operand
// length for D(L,B)-style operands, otherwise it is null.
struct MemOp {
unsigned Base : 8;
unsigned Index : 8;
unsigned MemKind : 8;
unsigned RegKind : 8;
unsigned Base : 12;
unsigned Index : 12;
unsigned MemKind : 4;
unsigned RegKind : 4;
const MCExpr *Disp;
const MCExpr *Length;
};
@ -246,6 +250,13 @@ public:
bool isMemDisp12Len8(RegisterKind RegKind) const {
return isMemDisp12(BDLMem, RegKind) && inRange(Mem.Length, 1, 0x100);
}
void addBDVAddrOperands(MCInst &Inst, unsigned N) const {
assert(N == 3 && "Invalid number of operands");
assert(isMem(BDVMem) && "Invalid operand type");
Inst.addOperand(MCOperand::CreateReg(Mem.Base));
addExpr(Inst, Mem.Disp);
Inst.addOperand(MCOperand::CreateReg(Mem.Index));
}
// Override MCParsedAsmOperand.
SMLoc getStartLoc() const override { return StartLoc; }
@ -307,6 +318,10 @@ public:
bool isFP32() const { return isReg(FP32Reg); }
bool isFP64() const { return isReg(FP64Reg); }
bool isFP128() const { return isReg(FP128Reg); }
bool isVR32() const { return isReg(VR32Reg); }
bool isVR64() const { return isReg(VR64Reg); }
bool isVF128() const { return false; }
bool isVR128() const { return isReg(VR128Reg); }
bool isBDAddr32Disp12() const { return isMemDisp12(BDMem, ADDR32Reg); }
bool isBDAddr32Disp20() const { return isMemDisp20(BDMem, ADDR32Reg); }
bool isBDAddr64Disp12() const { return isMemDisp12(BDMem, ADDR64Reg); }
@ -314,10 +329,15 @@ public:
bool isBDXAddr64Disp12() const { return isMemDisp12(BDXMem, ADDR64Reg); }
bool isBDXAddr64Disp20() const { return isMemDisp20(BDXMem, ADDR64Reg); }
bool isBDLAddr64Disp12Len8() const { return isMemDisp12Len8(ADDR64Reg); }
bool isBDVAddr64Disp12() const { return isMemDisp12(BDVMem, ADDR64Reg); }
bool isU1Imm() const { return isImm(0, 1); }
bool isU2Imm() const { return isImm(0, 3); }
bool isU3Imm() const { return isImm(0, 7); }
bool isU4Imm() const { return isImm(0, 15); }
bool isU6Imm() const { return isImm(0, 63); }
bool isU8Imm() const { return isImm(0, 255); }
bool isS8Imm() const { return isImm(-128, 127); }
bool isU12Imm() const { return isImm(0, 4095); }
bool isU16Imm() const { return isImm(0, 65535); }
bool isS16Imm() const { return isImm(-32768, 32767); }
bool isU32Imm() const { return isImm(0, (1LL << 32) - 1); }
@ -334,6 +354,7 @@ private:
enum RegisterGroup {
RegGR,
RegFP,
RegV,
RegAccess
};
struct Register {
@ -352,7 +373,7 @@ private:
RegisterKind Kind);
bool parseAddress(unsigned &Base, const MCExpr *&Disp,
unsigned &Index, const MCExpr *&Length,
unsigned &Index, bool &IsVector, const MCExpr *&Length,
const unsigned *Regs, RegisterKind RegKind);
OperandMatchResultTy parseAddress(OperandVector &Operands,
@ -419,6 +440,18 @@ public:
OperandMatchResultTy parseFP128(OperandVector &Operands) {
return parseRegister(Operands, RegFP, SystemZMC::FP128Regs, FP128Reg);
}
OperandMatchResultTy parseVR32(OperandVector &Operands) {
return parseRegister(Operands, RegV, SystemZMC::VR32Regs, VR32Reg);
}
OperandMatchResultTy parseVR64(OperandVector &Operands) {
return parseRegister(Operands, RegV, SystemZMC::VR64Regs, VR64Reg);
}
OperandMatchResultTy parseVF128(OperandVector &Operands) {
llvm_unreachable("Shouldn't be used as an operand");
}
OperandMatchResultTy parseVR128(OperandVector &Operands) {
return parseRegister(Operands, RegV, SystemZMC::VR128Regs, VR128Reg);
}
OperandMatchResultTy parseBDAddr32(OperandVector &Operands) {
return parseAddress(Operands, BDMem, SystemZMC::GR32Regs, ADDR32Reg);
}
@ -431,6 +464,9 @@ public:
OperandMatchResultTy parseBDLAddr64(OperandVector &Operands) {
return parseAddress(Operands, BDLMem, SystemZMC::GR64Regs, ADDR64Reg);
}
OperandMatchResultTy parseBDVAddr64(OperandVector &Operands) {
return parseAddress(Operands, BDVMem, SystemZMC::GR64Regs, ADDR64Reg);
}
OperandMatchResultTy parseAccessReg(OperandVector &Operands);
OperandMatchResultTy parsePCRel16(OperandVector &Operands) {
return parsePCRel(Operands, -(1LL << 16), (1LL << 16) - 1, false);
@ -484,6 +520,8 @@ bool SystemZAsmParser::parseRegister(Register &Reg) {
Reg.Group = RegGR;
else if (Prefix == 'f' && Reg.Num < 16)
Reg.Group = RegFP;
else if (Prefix == 'v' && Reg.Num < 32)
Reg.Group = RegV;
else if (Prefix == 'a' && Reg.Num < 16)
Reg.Group = RegAccess;
else
@ -534,8 +572,8 @@ SystemZAsmParser::parseRegister(OperandVector &Operands, RegisterGroup Group,
// Regs maps asm register numbers to LLVM register numbers and RegKind
// says what kind of address register we're using (ADDR32Reg or ADDR64Reg).
bool SystemZAsmParser::parseAddress(unsigned &Base, const MCExpr *&Disp,
unsigned &Index, const MCExpr *&Length,
const unsigned *Regs,
unsigned &Index, bool &IsVector,
const MCExpr *&Length, const unsigned *Regs,
RegisterKind RegKind) {
// Parse the displacement, which must always be present.
if (getParser().parseExpression(Disp))
@ -544,6 +582,7 @@ bool SystemZAsmParser::parseAddress(unsigned &Base, const MCExpr *&Disp,
// Parse the optional base and index.
Index = 0;
Base = 0;
IsVector = false;
Length = nullptr;
if (getLexer().is(AsmToken::LParen)) {
Parser.Lex();
@ -551,12 +590,23 @@ bool SystemZAsmParser::parseAddress(unsigned &Base, const MCExpr *&Disp,
if (getLexer().is(AsmToken::Percent)) {
// Parse the first register and decide whether it's a base or an index.
Register Reg;
if (parseRegister(Reg, RegGR, Regs, RegKind))
if (parseRegister(Reg))
return true;
if (getLexer().is(AsmToken::Comma))
Index = Reg.Num;
else
Base = Reg.Num;
if (Reg.Group == RegV) {
// A vector index register. The base register is optional.
IsVector = true;
Index = SystemZMC::VR128Regs[Reg.Num];
} else if (Reg.Group == RegGR) {
if (Reg.Num == 0)
return Error(Reg.StartLoc, "%r0 used in an address");
// If the are two registers, the first one is the index and the
// second is the base.
if (getLexer().is(AsmToken::Comma))
Index = Regs[Reg.Num];
else
Base = Regs[Reg.Num];
} else
return Error(Reg.StartLoc, "invalid address register");
} else {
// Parse the length.
if (getParser().parseExpression(Length))
@ -587,28 +637,36 @@ SystemZAsmParser::parseAddress(OperandVector &Operands, MemoryKind MemKind,
const unsigned *Regs, RegisterKind RegKind) {
SMLoc StartLoc = Parser.getTok().getLoc();
unsigned Base, Index;
bool IsVector;
const MCExpr *Disp;
const MCExpr *Length;
if (parseAddress(Base, Disp, Index, Length, Regs, RegKind))
if (parseAddress(Base, Disp, Index, IsVector, Length, Regs, RegKind))
return MatchOperand_ParseFail;
if (Index && MemKind != BDXMem)
{
Error(StartLoc, "invalid use of indexed addressing");
return MatchOperand_ParseFail;
}
if (IsVector && MemKind != BDVMem) {
Error(StartLoc, "invalid use of vector addressing");
return MatchOperand_ParseFail;
}
if (Length && MemKind != BDLMem)
{
Error(StartLoc, "invalid use of length addressing");
return MatchOperand_ParseFail;
}
if (!IsVector && MemKind == BDVMem) {
Error(StartLoc, "vector index required in address");
return MatchOperand_ParseFail;
}
if (!Length && MemKind == BDLMem)
{
Error(StartLoc, "missing length in address");
return MatchOperand_ParseFail;
}
if (Index && MemKind != BDXMem && MemKind != BDVMem) {
Error(StartLoc, "invalid use of indexed addressing");
return MatchOperand_ParseFail;
}
if (Length && MemKind != BDLMem) {
Error(StartLoc, "invalid use of length addressing");
return MatchOperand_ParseFail;
}
if (!Length && MemKind == BDLMem) {
Error(StartLoc, "missing length in address");
return MatchOperand_ParseFail;
}
SMLoc EndLoc =
SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
@ -631,6 +689,8 @@ bool SystemZAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
RegNo = SystemZMC::GR64Regs[Reg.Num];
else if (Reg.Group == RegFP)
RegNo = SystemZMC::FP64Regs[Reg.Num];
else if (Reg.Group == RegV)
RegNo = SystemZMC::VR128Regs[Reg.Num];
else
// FIXME: Access registers aren't modelled as LLVM registers yet.
return Error(Reg.StartLoc, "invalid operand for instruction");
@ -703,8 +763,10 @@ bool SystemZAsmParser::parseOperand(OperandVector &Operands,
// so we treat any plain expression as an immediate.
SMLoc StartLoc = Parser.getTok().getLoc();
unsigned Base, Index;
bool IsVector;
const MCExpr *Expr, *Length;
if (parseAddress(Base, Expr, Index, Length, SystemZMC::GR64Regs, ADDR64Reg))
if (parseAddress(Base, Expr, Index, IsVector, Length, SystemZMC::GR64Regs,
ADDR64Reg))
return true;
SMLoc EndLoc =

View File

@ -47,8 +47,8 @@ extern "C" void LLVMInitializeSystemZDisassembler() {
}
static DecodeStatus decodeRegisterClass(MCInst &Inst, uint64_t RegNo,
const unsigned *Regs) {
assert(RegNo < 16 && "Invalid register");
const unsigned *Regs, unsigned Size) {
assert(RegNo < Size && "Invalid register");
RegNo = Regs[RegNo];
if (RegNo == 0)
return MCDisassembler::Fail;
@ -59,61 +59,81 @@ static DecodeStatus decodeRegisterClass(MCInst &Inst, uint64_t RegNo,
static DecodeStatus DecodeGR32BitRegisterClass(MCInst &Inst, uint64_t RegNo,
uint64_t Address,
const void *Decoder) {
return decodeRegisterClass(Inst, RegNo, SystemZMC::GR32Regs);
return decodeRegisterClass(Inst, RegNo, SystemZMC::GR32Regs, 16);
}
static DecodeStatus DecodeGRH32BitRegisterClass(MCInst &Inst, uint64_t RegNo,
uint64_t Address,
const void *Decoder) {
return decodeRegisterClass(Inst, RegNo, SystemZMC::GRH32Regs);
return decodeRegisterClass(Inst, RegNo, SystemZMC::GRH32Regs, 16);
}
static DecodeStatus DecodeGR64BitRegisterClass(MCInst &Inst, uint64_t RegNo,
uint64_t Address,
const void *Decoder) {
return decodeRegisterClass(Inst, RegNo, SystemZMC::GR64Regs);
return decodeRegisterClass(Inst, RegNo, SystemZMC::GR64Regs, 16);
}
static DecodeStatus DecodeGR128BitRegisterClass(MCInst &Inst, uint64_t RegNo,
uint64_t Address,
const void *Decoder) {
return decodeRegisterClass(Inst, RegNo, SystemZMC::GR128Regs);
return decodeRegisterClass(Inst, RegNo, SystemZMC::GR128Regs, 16);
}
static DecodeStatus DecodeADDR64BitRegisterClass(MCInst &Inst, uint64_t RegNo,
uint64_t Address,
const void *Decoder) {
return decodeRegisterClass(Inst, RegNo, SystemZMC::GR64Regs);
return decodeRegisterClass(Inst, RegNo, SystemZMC::GR64Regs, 16);
}
static DecodeStatus DecodeFP32BitRegisterClass(MCInst &Inst, uint64_t RegNo,
uint64_t Address,
const void *Decoder) {
return decodeRegisterClass(Inst, RegNo, SystemZMC::FP32Regs);
return decodeRegisterClass(Inst, RegNo, SystemZMC::FP32Regs, 16);
}
static DecodeStatus DecodeFP64BitRegisterClass(MCInst &Inst, uint64_t RegNo,
uint64_t Address,
const void *Decoder) {
return decodeRegisterClass(Inst, RegNo, SystemZMC::FP64Regs);
return decodeRegisterClass(Inst, RegNo, SystemZMC::FP64Regs, 16);
}
static DecodeStatus DecodeFP128BitRegisterClass(MCInst &Inst, uint64_t RegNo,
uint64_t Address,
const void *Decoder) {
return decodeRegisterClass(Inst, RegNo, SystemZMC::FP128Regs);
return decodeRegisterClass(Inst, RegNo, SystemZMC::FP128Regs, 16);
}
static DecodeStatus DecodeVR32BitRegisterClass(MCInst &Inst, uint64_t RegNo,
uint64_t Address,
const void *Decoder) {
return decodeRegisterClass(Inst, RegNo, SystemZMC::VR32Regs, 32);
}
static DecodeStatus DecodeVR64BitRegisterClass(MCInst &Inst, uint64_t RegNo,
uint64_t Address,
const void *Decoder) {
return decodeRegisterClass(Inst, RegNo, SystemZMC::VR64Regs, 32);
}
static DecodeStatus DecodeVR128BitRegisterClass(MCInst &Inst, uint64_t RegNo,
uint64_t Address,
const void *Decoder) {
return decodeRegisterClass(Inst, RegNo, SystemZMC::VR128Regs, 32);
}
template<unsigned N>
static DecodeStatus decodeUImmOperand(MCInst &Inst, uint64_t Imm) {
assert(isUInt<N>(Imm) && "Invalid immediate");
if (!isUInt<N>(Imm))
return MCDisassembler::Fail;
Inst.addOperand(MCOperand::CreateImm(Imm));
return MCDisassembler::Success;
}
template<unsigned N>
static DecodeStatus decodeSImmOperand(MCInst &Inst, uint64_t Imm) {
assert(isUInt<N>(Imm) && "Invalid immediate");
if (!isUInt<N>(Imm))
return MCDisassembler::Fail;
Inst.addOperand(MCOperand::CreateImm(SignExtend64<N>(Imm)));
return MCDisassembler::Success;
}
@ -124,6 +144,21 @@ static DecodeStatus decodeAccessRegOperand(MCInst &Inst, uint64_t Imm,
return decodeUImmOperand<4>(Inst, Imm);
}
static DecodeStatus decodeU1ImmOperand(MCInst &Inst, uint64_t Imm,
uint64_t Address, const void *Decoder) {
return decodeUImmOperand<1>(Inst, Imm);
}
static DecodeStatus decodeU2ImmOperand(MCInst &Inst, uint64_t Imm,
uint64_t Address, const void *Decoder) {
return decodeUImmOperand<2>(Inst, Imm);
}
static DecodeStatus decodeU3ImmOperand(MCInst &Inst, uint64_t Imm,
uint64_t Address, const void *Decoder) {
return decodeUImmOperand<3>(Inst, Imm);
}
static DecodeStatus decodeU4ImmOperand(MCInst &Inst, uint64_t Imm,
uint64_t Address, const void *Decoder) {
return decodeUImmOperand<4>(Inst, Imm);
@ -139,6 +174,11 @@ static DecodeStatus decodeU8ImmOperand(MCInst &Inst, uint64_t Imm,
return decodeUImmOperand<8>(Inst, Imm);
}
static DecodeStatus decodeU12ImmOperand(MCInst &Inst, uint64_t Imm,
uint64_t Address, const void *Decoder) {
return decodeUImmOperand<12>(Inst, Imm);
}
static DecodeStatus decodeU16ImmOperand(MCInst &Inst, uint64_t Imm,
uint64_t Address, const void *Decoder) {
return decodeUImmOperand<16>(Inst, Imm);
@ -240,6 +280,18 @@ static DecodeStatus decodeBDLAddr12Len8Operand(MCInst &Inst, uint64_t Field,
return MCDisassembler::Success;
}
static DecodeStatus decodeBDVAddr12Operand(MCInst &Inst, uint64_t Field,
const unsigned *Regs) {
uint64_t Index = Field >> 16;
uint64_t Base = (Field >> 12) & 0xf;
uint64_t Disp = Field & 0xfff;
assert(Index < 32 && "Invalid BDVAddr12");
Inst.addOperand(MCOperand::CreateReg(Base == 0 ? 0 : Regs[Base]));
Inst.addOperand(MCOperand::CreateImm(Disp));
Inst.addOperand(MCOperand::CreateReg(SystemZMC::VR128Regs[Index]));
return MCDisassembler::Success;
}
static DecodeStatus decodeBDAddr32Disp12Operand(MCInst &Inst, uint64_t Field,
uint64_t Address,
const void *Decoder) {
@ -283,6 +335,12 @@ static DecodeStatus decodeBDLAddr64Disp12Len8Operand(MCInst &Inst,
return decodeBDLAddr12Len8Operand(Inst, Field, SystemZMC::GR64Regs);
}
static DecodeStatus decodeBDVAddr64Disp12Operand(MCInst &Inst, uint64_t Field,
uint64_t Address,
const void *Decoder) {
return decodeBDVAddr12Operand(Inst, Field, SystemZMC::GR64Regs);
}
#include "SystemZGenDisassemblerTables.inc"
DecodeStatus SystemZDisassembler::getInstruction(MCInst &MI, uint64_t &Size,

View File

@ -22,13 +22,17 @@ using namespace llvm;
void SystemZInstPrinter::printAddress(unsigned Base, int64_t Disp,
unsigned Index, raw_ostream &O) {
O << Disp;
if (Base) {
if (Base || Index) {
O << '(';
if (Index)
O << '%' << getRegisterName(Index) << ',';
O << '%' << getRegisterName(Base) << ')';
} else
assert(!Index && "Shouldn't have an index without a base");
if (Index) {
O << '%' << getRegisterName(Index);
if (Base)
O << ',';
}
if (Base)
O << '%' << getRegisterName(Base);
O << ')';
}
}
void SystemZInstPrinter::printOperand(const MCOperand &MO, raw_ostream &O) {
@ -53,60 +57,78 @@ void SystemZInstPrinter::printRegName(raw_ostream &O, unsigned RegNo) const {
O << '%' << getRegisterName(RegNo);
}
template<unsigned N>
void printUImmOperand(const MCInst *MI, int OpNum, raw_ostream &O) {
int64_t Value = MI->getOperand(OpNum).getImm();
assert(isUInt<N>(Value) && "Invalid uimm argument");
O << Value;
}
template<unsigned N>
void printSImmOperand(const MCInst *MI, int OpNum, raw_ostream &O) {
int64_t Value = MI->getOperand(OpNum).getImm();
assert(isInt<N>(Value) && "Invalid simm argument");
O << Value;
}
void SystemZInstPrinter::printU1ImmOperand(const MCInst *MI, int OpNum,
raw_ostream &O) {
printUImmOperand<1>(MI, OpNum, O);
}
void SystemZInstPrinter::printU2ImmOperand(const MCInst *MI, int OpNum,
raw_ostream &O) {
printUImmOperand<2>(MI, OpNum, O);
}
void SystemZInstPrinter::printU3ImmOperand(const MCInst *MI, int OpNum,
raw_ostream &O) {
printUImmOperand<3>(MI, OpNum, O);
}
void SystemZInstPrinter::printU4ImmOperand(const MCInst *MI, int OpNum,
raw_ostream &O) {
int64_t Value = MI->getOperand(OpNum).getImm();
assert(isUInt<4>(Value) && "Invalid u4imm argument");
O << Value;
printUImmOperand<4>(MI, OpNum, O);
}
void SystemZInstPrinter::printU6ImmOperand(const MCInst *MI, int OpNum,
raw_ostream &O) {
int64_t Value = MI->getOperand(OpNum).getImm();
assert(isUInt<6>(Value) && "Invalid u6imm argument");
O << Value;
printUImmOperand<6>(MI, OpNum, O);
}
void SystemZInstPrinter::printS8ImmOperand(const MCInst *MI, int OpNum,
raw_ostream &O) {
int64_t Value = MI->getOperand(OpNum).getImm();
assert(isInt<8>(Value) && "Invalid s8imm argument");
O << Value;
printSImmOperand<8>(MI, OpNum, O);
}
void SystemZInstPrinter::printU8ImmOperand(const MCInst *MI, int OpNum,
raw_ostream &O) {
int64_t Value = MI->getOperand(OpNum).getImm();
assert(isUInt<8>(Value) && "Invalid u8imm argument");
O << Value;
printUImmOperand<8>(MI, OpNum, O);
}
void SystemZInstPrinter::printU12ImmOperand(const MCInst *MI, int OpNum,
raw_ostream &O) {
printUImmOperand<12>(MI, OpNum, O);
}
void SystemZInstPrinter::printS16ImmOperand(const MCInst *MI, int OpNum,
raw_ostream &O) {
int64_t Value = MI->getOperand(OpNum).getImm();
assert(isInt<16>(Value) && "Invalid s16imm argument");
O << Value;
printSImmOperand<16>(MI, OpNum, O);
}
void SystemZInstPrinter::printU16ImmOperand(const MCInst *MI, int OpNum,
raw_ostream &O) {
int64_t Value = MI->getOperand(OpNum).getImm();
assert(isUInt<16>(Value) && "Invalid u16imm argument");
O << Value;
printUImmOperand<16>(MI, OpNum, O);
}
void SystemZInstPrinter::printS32ImmOperand(const MCInst *MI, int OpNum,
raw_ostream &O) {
int64_t Value = MI->getOperand(OpNum).getImm();
assert(isInt<32>(Value) && "Invalid s32imm argument");
O << Value;
printSImmOperand<32>(MI, OpNum, O);
}
void SystemZInstPrinter::printU32ImmOperand(const MCInst *MI, int OpNum,
raw_ostream &O) {
int64_t Value = MI->getOperand(OpNum).getImm();
assert(isUInt<32>(Value) && "Invalid u32imm argument");
O << Value;
printUImmOperand<32>(MI, OpNum, O);
}
void SystemZInstPrinter::printAccessRegOperand(const MCInst *MI, int OpNum,
@ -178,6 +200,13 @@ void SystemZInstPrinter::printBDLAddrOperand(const MCInst *MI, int OpNum,
O << ')';
}
void SystemZInstPrinter::printBDVAddrOperand(const MCInst *MI, int OpNum,
raw_ostream &O) {
printAddress(MI->getOperand(OpNum).getReg(),
MI->getOperand(OpNum + 1).getImm(),
MI->getOperand(OpNum + 2).getReg(), O);
}
void SystemZInstPrinter::printCond4Operand(const MCInst *MI, int OpNum,
raw_ostream &O) {
static const char *const CondNames[] = {

View File

@ -48,10 +48,15 @@ private:
void printBDAddrOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printBDXAddrOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printBDLAddrOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printBDVAddrOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printU1ImmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printU2ImmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printU3ImmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printU4ImmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printU6ImmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printS8ImmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printU8ImmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printU12ImmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printS16ImmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printU16ImmOperand(const MCInst *MI, int OpNum, raw_ostream &O);
void printS32ImmOperand(const MCInst *MI, int OpNum, raw_ostream &O);

View File

@ -70,6 +70,9 @@ private:
uint64_t getBDLAddr12Len8Encoding(const MCInst &MI, unsigned OpNum,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
uint64_t getBDVAddr12Encoding(const MCInst &MI, unsigned OpNum,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
// Operand OpNum of MI needs a PC-relative fixup of kind Kind at
// Offset bytes from the start of MI. Add the fixup to Fixups
@ -193,6 +196,17 @@ getBDLAddr12Len8Encoding(const MCInst &MI, unsigned OpNum,
return (Len << 16) | (Base << 12) | Disp;
}
uint64_t SystemZMCCodeEmitter::
getBDVAddr12Encoding(const MCInst &MI, unsigned OpNum,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI);
assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<5>(Index));
return (Index << 16) | (Base << 12) | Disp;
}
uint64_t
SystemZMCCodeEmitter::getPCRelEncoding(const MCInst &MI, unsigned OpNum,
SmallVectorImpl<MCFixup> &Fixups,

View File

@ -76,6 +76,39 @@ const unsigned SystemZMC::FP128Regs[16] = {
SystemZ::F12Q, SystemZ::F13Q, 0, 0
};
const unsigned SystemZMC::VR32Regs[32] = {
SystemZ::F0S, SystemZ::F1S, SystemZ::F2S, SystemZ::F3S,
SystemZ::F4S, SystemZ::F5S, SystemZ::F6S, SystemZ::F7S,
SystemZ::F8S, SystemZ::F9S, SystemZ::F10S, SystemZ::F11S,
SystemZ::F12S, SystemZ::F13S, SystemZ::F14S, SystemZ::F15S,
SystemZ::F16S, SystemZ::F17S, SystemZ::F18S, SystemZ::F19S,
SystemZ::F20S, SystemZ::F21S, SystemZ::F22S, SystemZ::F23S,
SystemZ::F24S, SystemZ::F25S, SystemZ::F26S, SystemZ::F27S,
SystemZ::F28S, SystemZ::F29S, SystemZ::F30S, SystemZ::F31S
};
const unsigned SystemZMC::VR64Regs[32] = {
SystemZ::F0D, SystemZ::F1D, SystemZ::F2D, SystemZ::F3D,
SystemZ::F4D, SystemZ::F5D, SystemZ::F6D, SystemZ::F7D,
SystemZ::F8D, SystemZ::F9D, SystemZ::F10D, SystemZ::F11D,
SystemZ::F12D, SystemZ::F13D, SystemZ::F14D, SystemZ::F15D,
SystemZ::F16D, SystemZ::F17D, SystemZ::F18D, SystemZ::F19D,
SystemZ::F20D, SystemZ::F21D, SystemZ::F22D, SystemZ::F23D,
SystemZ::F24D, SystemZ::F25D, SystemZ::F26D, SystemZ::F27D,
SystemZ::F28D, SystemZ::F29D, SystemZ::F30D, SystemZ::F31D
};
const unsigned SystemZMC::VR128Regs[32] = {
SystemZ::V0, SystemZ::V1, SystemZ::V2, SystemZ::V3,
SystemZ::V4, SystemZ::V5, SystemZ::V6, SystemZ::V7,
SystemZ::V8, SystemZ::V9, SystemZ::V10, SystemZ::V11,
SystemZ::V12, SystemZ::V13, SystemZ::V14, SystemZ::V15,
SystemZ::V16, SystemZ::V17, SystemZ::V18, SystemZ::V19,
SystemZ::V20, SystemZ::V21, SystemZ::V22, SystemZ::V23,
SystemZ::V24, SystemZ::V25, SystemZ::V26, SystemZ::V27,
SystemZ::V28, SystemZ::V29, SystemZ::V30, SystemZ::V31
};
unsigned SystemZMC::getFirstReg(unsigned Reg) {
static unsigned Map[SystemZ::NUM_TARGET_REGS];
static bool Initialized = false;
@ -85,10 +118,13 @@ unsigned SystemZMC::getFirstReg(unsigned Reg) {
Map[GRH32Regs[I]] = I;
Map[GR64Regs[I]] = I;
Map[GR128Regs[I]] = I;
Map[FP32Regs[I]] = I;
Map[FP64Regs[I]] = I;
Map[FP128Regs[I]] = I;
}
for (unsigned I = 0; I < 32; ++I) {
Map[VR32Regs[I]] = I;
Map[VR64Regs[I]] = I;
Map[VR128Regs[I]] = I;
}
}
assert(Reg < SystemZ::NUM_TARGET_REGS);
return Map[Reg];

View File

@ -49,6 +49,9 @@ extern const unsigned GR128Regs[16];
extern const unsigned FP32Regs[16];
extern const unsigned FP64Regs[16];
extern const unsigned FP128Regs[16];
extern const unsigned VR32Regs[32];
extern const unsigned VR64Regs[32];
extern const unsigned VR128Regs[32];
// Return the 0-based number of the first architectural register that
// contains the given LLVM register. E.g. R1D -> 1.

View File

@ -41,6 +41,7 @@ include "SystemZPatterns.td"
include "SystemZInstrFormats.td"
include "SystemZInstrInfo.td"
include "SystemZInstrFP.td"
include "SystemZInstrVector.td"
def SystemZInstrInfo : InstrInfo {}

View File

@ -142,10 +142,13 @@ def getThreeOperandOpcode : InstrMapping {
// Formats are specified using operand field declarations of the form:
//
// bits<4> Rn : register input or output for operand n
// bits<5> Vn : vector register input or output for operand n
// bits<m> In : immediate value of width m for operand n
// bits<4> BDn : address operand n, which has a base and a displacement
// bits<m> XBDn : address operand n, which has an index, a base and a
// displacement
// bits<m> VBDn : address operand n, which has a vector index, a base and a
// displacement
// bits<4> Xn : index register for address operand n
// bits<4> Mn : mode value for operand n
//
@ -339,11 +342,13 @@ class InstRXE<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern>
bits<4> R1;
bits<20> XBD2;
bits<4> M3;
let Inst{47-40} = op{15-8};
let Inst{39-36} = R1;
let Inst{35-16} = XBD2;
let Inst{15-8} = 0;
let Inst{15-12} = M3;
let Inst{11-8} = 0;
let Inst{7-0} = op{7-0};
let HasIndex = 1;
@ -484,6 +489,382 @@ class InstS<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern>
let Inst{15-0} = BD2;
}
class InstVRIa<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern>
: InstSystemZ<6, outs, ins, asmstr, pattern> {
field bits<48> Inst;
field bits<48> SoftFail = 0;
bits<5> V1;
bits<16> I2;
bits<4> M3;
let Inst{47-40} = op{15-8};
let Inst{39-36} = V1{3-0};
let Inst{35-32} = 0;
let Inst{31-16} = I2;
let Inst{15-12} = M3;
let Inst{11} = V1{4};
let Inst{10-8} = 0;
let Inst{7-0} = op{7-0};
}
class InstVRIb<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern>
: InstSystemZ<6, outs, ins, asmstr, pattern> {
field bits<48> Inst;
field bits<48> SoftFail = 0;
bits<5> V1;
bits<8> I2;
bits<8> I3;
bits<4> M4;
let Inst{47-40} = op{15-8};
let Inst{39-36} = V1{3-0};
let Inst{35-32} = 0;
let Inst{31-24} = I2;
let Inst{23-16} = I3;
let Inst{15-12} = M4;
let Inst{11} = V1{4};
let Inst{10-8} = 0;
let Inst{7-0} = op{7-0};
}
class InstVRIc<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern>
: InstSystemZ<6, outs, ins, asmstr, pattern> {
field bits<48> Inst;
field bits<48> SoftFail = 0;
bits<5> V1;
bits<5> V3;
bits<16> I2;
bits<4> M4;
let Inst{47-40} = op{15-8};
let Inst{39-36} = V1{3-0};
let Inst{35-32} = V3{3-0};
let Inst{31-16} = I2;
let Inst{15-12} = M4;
let Inst{11} = V1{4};
let Inst{10} = V3{4};
let Inst{9-8} = 0;
let Inst{7-0} = op{7-0};
}
class InstVRId<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern>
: InstSystemZ<6, outs, ins, asmstr, pattern> {
field bits<48> Inst;
field bits<48> SoftFail = 0;
bits<5> V1;
bits<5> V2;
bits<5> V3;
bits<8> I4;
bits<4> M5;
let Inst{47-40} = op{15-8};
let Inst{39-36} = V1{3-0};
let Inst{35-32} = V2{3-0};
let Inst{31-28} = V3{3-0};
let Inst{27-24} = 0;
let Inst{23-16} = I4;
let Inst{15-12} = M5;
let Inst{11} = V1{4};
let Inst{10} = V2{4};
let Inst{9} = V3{4};
let Inst{8} = 0;
let Inst{7-0} = op{7-0};
}
class InstVRIe<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern>
: InstSystemZ<6, outs, ins, asmstr, pattern> {
field bits<48> Inst;
field bits<48> SoftFail = 0;
bits<5> V1;
bits<5> V2;
bits<12> I3;
bits<4> M4;
bits<4> M5;
let Inst{47-40} = op{15-8};
let Inst{39-36} = V1{3-0};
let Inst{35-32} = V2{3-0};
let Inst{31-20} = I3;
let Inst{19-16} = M5;
let Inst{15-12} = M4;
let Inst{11} = V1{4};
let Inst{10} = V2{4};
let Inst{9-8} = 0;
let Inst{7-0} = op{7-0};
}
// Depending on the instruction mnemonic, certain bits may be or-ed into
// the M4 value provided as explicit operand. These are passed as m4or.
class InstVRRa<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern,
bits<4> m4or = 0>
: InstSystemZ<6, outs, ins, asmstr, pattern> {
field bits<48> Inst;
field bits<48> SoftFail = 0;
bits<5> V1;
bits<5> V2;
bits<4> M3;
bits<4> M4;
bits<4> M5;
let Inst{47-40} = op{15-8};
let Inst{39-36} = V1{3-0};
let Inst{35-32} = V2{3-0};
let Inst{31-24} = 0;
let Inst{23-20} = M5;
let Inst{19} = !if (!eq (m4or{3}, 1), 1, M4{3});
let Inst{18} = !if (!eq (m4or{2}, 1), 1, M4{2});
let Inst{17} = !if (!eq (m4or{1}, 1), 1, M4{1});
let Inst{16} = !if (!eq (m4or{0}, 1), 1, M4{0});
let Inst{15-12} = M3;
let Inst{11} = V1{4};
let Inst{10} = V2{4};
let Inst{9-8} = 0;
let Inst{7-0} = op{7-0};
}
// Depending on the instruction mnemonic, certain bits may be or-ed into
// the M5 value provided as explicit operand. These are passed as m5or.
class InstVRRb<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern,
bits<4> m5or = 0>
: InstSystemZ<6, outs, ins, asmstr, pattern> {
field bits<48> Inst;
field bits<48> SoftFail = 0;
bits<5> V1;
bits<5> V2;
bits<5> V3;
bits<4> M4;
bits<4> M5;
let Inst{47-40} = op{15-8};
let Inst{39-36} = V1{3-0};
let Inst{35-32} = V2{3-0};
let Inst{31-28} = V3{3-0};
let Inst{27-24} = 0;
let Inst{23} = !if (!eq (m5or{3}, 1), 1, M5{3});
let Inst{22} = !if (!eq (m5or{2}, 1), 1, M5{2});
let Inst{21} = !if (!eq (m5or{1}, 1), 1, M5{1});
let Inst{20} = !if (!eq (m5or{0}, 1), 1, M5{0});
let Inst{19-16} = 0;
let Inst{15-12} = M4;
let Inst{11} = V1{4};
let Inst{10} = V2{4};
let Inst{9} = V3{4};
let Inst{8} = 0;
let Inst{7-0} = op{7-0};
}
class InstVRRc<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern>
: InstSystemZ<6, outs, ins, asmstr, pattern> {
field bits<48> Inst;
field bits<48> SoftFail = 0;
bits<5> V1;
bits<5> V2;
bits<5> V3;
bits<4> M4;
bits<4> M5;
bits<4> M6;
let Inst{47-40} = op{15-8};
let Inst{39-36} = V1{3-0};
let Inst{35-32} = V2{3-0};
let Inst{31-28} = V3{3-0};
let Inst{27-24} = 0;
let Inst{23-20} = M6;
let Inst{19-16} = M5;
let Inst{15-12} = M4;
let Inst{11} = V1{4};
let Inst{10} = V2{4};
let Inst{9} = V3{4};
let Inst{8} = 0;
let Inst{7-0} = op{7-0};
}
// Depending on the instruction mnemonic, certain bits may be or-ed into
// the M6 value provided as explicit operand. These are passed as m6or.
class InstVRRd<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern,
bits<4> m6or = 0>
: InstSystemZ<6, outs, ins, asmstr, pattern> {
field bits<48> Inst;
field bits<48> SoftFail = 0;
bits<5> V1;
bits<5> V2;
bits<5> V3;
bits<5> V4;
bits<4> M5;
bits<4> M6;
let Inst{47-40} = op{15-8};
let Inst{39-36} = V1{3-0};
let Inst{35-32} = V2{3-0};
let Inst{31-28} = V3{3-0};
let Inst{27-24} = M5;
let Inst{23} = !if (!eq (m6or{3}, 1), 1, M6{3});
let Inst{22} = !if (!eq (m6or{2}, 1), 1, M6{2});
let Inst{21} = !if (!eq (m6or{1}, 1), 1, M6{1});
let Inst{20} = !if (!eq (m6or{0}, 1), 1, M6{0});
let Inst{19-16} = 0;
let Inst{15-12} = V4{3-0};
let Inst{11} = V1{4};
let Inst{10} = V2{4};
let Inst{9} = V3{4};
let Inst{8} = V4{4};
let Inst{7-0} = op{7-0};
}
class InstVRRe<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern>
: InstSystemZ<6, outs, ins, asmstr, pattern> {
field bits<48> Inst;
field bits<48> SoftFail = 0;
bits<5> V1;
bits<5> V2;
bits<5> V3;
bits<5> V4;
bits<4> M5;
bits<4> M6;
let Inst{47-40} = op{15-8};
let Inst{39-36} = V1{3-0};
let Inst{35-32} = V2{3-0};
let Inst{31-28} = V3{3-0};
let Inst{27-24} = M6;
let Inst{23-20} = 0;
let Inst{19-16} = M5;
let Inst{15-12} = V4{3-0};
let Inst{11} = V1{4};
let Inst{10} = V2{4};
let Inst{9} = V3{4};
let Inst{8} = V4{4};
let Inst{7-0} = op{7-0};
}
class InstVRRf<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern>
: InstSystemZ<6, outs, ins, asmstr, pattern> {
field bits<48> Inst;
field bits<48> SoftFail = 0;
bits<5> V1;
bits<4> R2;
bits<4> R3;
let Inst{47-40} = op{15-8};
let Inst{39-36} = V1{3-0};
let Inst{35-32} = R2;
let Inst{31-28} = R3;
let Inst{27-12} = 0;
let Inst{11} = V1{4};
let Inst{10-8} = 0;
let Inst{7-0} = op{7-0};
}
class InstVRSa<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern>
: InstSystemZ<6, outs, ins, asmstr, pattern> {
field bits<48> Inst;
field bits<48> SoftFail = 0;
bits<5> V1;
bits<16> BD2;
bits<5> V3;
bits<4> M4;
let Inst{47-40} = op{15-8};
let Inst{39-36} = V1{3-0};
let Inst{35-32} = V3{3-0};
let Inst{31-16} = BD2;
let Inst{15-12} = M4;
let Inst{11} = V1{4};
let Inst{10} = V3{4};
let Inst{9-8} = 0;
let Inst{7-0} = op{7-0};
}
class InstVRSb<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern>
: InstSystemZ<6, outs, ins, asmstr, pattern> {
field bits<48> Inst;
field bits<48> SoftFail = 0;
bits<5> V1;
bits<16> BD2;
bits<4> R3;
bits<4> M4;
let Inst{47-40} = op{15-8};
let Inst{39-36} = V1{3-0};
let Inst{35-32} = R3;
let Inst{31-16} = BD2;
let Inst{15-12} = M4;
let Inst{11} = V1{4};
let Inst{10-8} = 0;
let Inst{7-0} = op{7-0};
}
class InstVRSc<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern>
: InstSystemZ<6, outs, ins, asmstr, pattern> {
field bits<48> Inst;
field bits<48> SoftFail = 0;
bits<4> R1;
bits<16> BD2;
bits<5> V3;
bits<4> M4;
let Inst{47-40} = op{15-8};
let Inst{39-36} = R1;
let Inst{35-32} = V3{3-0};
let Inst{31-16} = BD2;
let Inst{15-12} = M4;
let Inst{11} = 0;
let Inst{10} = V3{4};
let Inst{9-8} = 0;
let Inst{7-0} = op{7-0};
}
class InstVRV<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern>
: InstSystemZ<6, outs, ins, asmstr, pattern> {
field bits<48> Inst;
field bits<48> SoftFail = 0;
bits<5> V1;
bits<21> VBD2;
bits<4> M3;
let Inst{47-40} = op{15-8};
let Inst{39-36} = V1{3-0};
let Inst{35-16} = VBD2{19-0};
let Inst{15-12} = M3;
let Inst{11} = V1{4};
let Inst{10} = VBD2{20};
let Inst{9-8} = 0;
let Inst{7-0} = op{7-0};
}
class InstVRX<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern>
: InstSystemZ<6, outs, ins, asmstr, pattern> {
field bits<48> Inst;
field bits<48> SoftFail = 0;
bits<5> V1;
bits<20> XBD2;
bits<4> M3;
let Inst{47-40} = op{15-8};
let Inst{39-36} = V1{3-0};
let Inst{35-16} = XBD2;
let Inst{15-12} = M3;
let Inst{11} = V1{4};
let Inst{10-8} = 0;
let Inst{7-0} = op{7-0};
}
//===----------------------------------------------------------------------===//
// Instruction definitions with semantics
//===----------------------------------------------------------------------===//
@ -503,12 +884,6 @@ class InstS<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern>
// form of the source register in the destination register and
// branches on the result.
//
// Store:
// One register or immediate input operand and one address input operand.
// The instruction stores the first operand to the address.
//
// This category is used for both pure and truncating stores.
//
// LoadMultiple:
// One address input operand and two explicit output operands.
// The instruction loads a range of registers from the address,
@ -521,18 +896,35 @@ class InstS<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern>
// with the explicit operands giving the first and last register
// to store. Other stored registers are added as implicit uses.
//
// StoreLength:
// One value operand, one length operand and one address operand.
// The instruction stores the value operand to the address but
// doesn't write more than the number of bytes specified by the
// length operand.
//
// Unary:
// One register output operand and one input operand.
//
// Store:
// One address operand and one other input operand. The instruction
// stores to the address.
//
// Binary:
// One register output operand and two input operands.
//
// StoreBinary:
// One address operand and two other input operands. The instruction
// stores to the address.
//
// Compare:
// Two input operands and an implicit CC output operand.
//
// Ternary:
// One register output operand and three input operands.
//
// Quaternary:
// One register output operand and four input operands.
//
// LoadAndOp:
// One output operand and two input operands, one of which is an address.
// The instruction both reads from and writes to the address.
@ -567,6 +959,12 @@ class InherentRRE<string mnemonic, bits<16> opcode, RegisterOperand cls,
let R2 = 0;
}
class InherentVRIa<string mnemonic, bits<16> opcode, bits<16> value>
: InstVRIa<opcode, (outs VR128:$V1), (ins), mnemonic#"\t$V1", []> {
let I2 = value;
let M3 = 0;
}
class BranchUnaryRI<string mnemonic, bits<12> opcode, RegisterOperand cls>
: InstRI<opcode, (outs cls:$R1), (ins cls:$R1src, brtarget16:$I2),
mnemonic##"\t$R1, $I2", []> {
@ -582,6 +980,13 @@ class LoadMultipleRSY<string mnemonic, bits<16> opcode, RegisterOperand cls>
let mayLoad = 1;
}
class LoadMultipleVRSa<string mnemonic, bits<16> opcode>
: InstVRSa<opcode, (outs VR128:$V1, VR128:$V3), (ins bdaddr12only:$BD2),
mnemonic#"\t$V1, $V3, $BD2", []> {
let M4 = 0;
let mayLoad = 1;
}
class StoreRILPC<string mnemonic, bits<12> opcode, SDPatternOperator operator,
RegisterOperand cls>
: InstRIL<opcode, (outs), (ins cls:$R1, pcrel32:$I2),
@ -630,12 +1035,39 @@ multiclass StoreRXPair<string mnemonic, bits<8> rxOpcode, bits<16> rxyOpcode,
}
}
class StoreVRX<string mnemonic, bits<16> opcode, SDPatternOperator operator,
TypedReg tr, bits<5> bytes, bits<4> type = 0>
: InstVRX<opcode, (outs), (ins tr.op:$V1, bdxaddr12only:$XBD2),
mnemonic#"\t$V1, $XBD2",
[(set tr.op:$V1, (tr.vt (operator bdxaddr12only:$XBD2)))]> {
let M3 = type;
let mayStore = 1;
let AccessBytes = bytes;
}
class StoreLengthVRSb<string mnemonic, bits<16> opcode,
SDPatternOperator operator, bits<5> bytes>
: InstVRSb<opcode, (outs), (ins VR128:$V1, GR32:$R3, bdaddr12only:$BD2),
mnemonic#"\t$V1, $R3, $BD2",
[(operator VR128:$V1, GR32:$R3, bdaddr12only:$BD2)]> {
let M4 = 0;
let mayStore = 1;
let AccessBytes = bytes;
}
class StoreMultipleRSY<string mnemonic, bits<16> opcode, RegisterOperand cls>
: InstRSY<opcode, (outs), (ins cls:$R1, cls:$R3, bdaddr20only:$BD2),
mnemonic#"\t$R1, $R3, $BD2", []> {
let mayStore = 1;
}
class StoreMultipleVRSa<string mnemonic, bits<16> opcode>
: InstVRSa<opcode, (outs), (ins VR128:$V1, VR128:$V3, bdaddr12only:$BD2),
mnemonic#"\t$V1, $V3, $BD2", []> {
let M4 = 0;
let mayStore = 1;
}
// StoreSI* instructions are used to store an integer to memory, but the
// addresses are more restricted than for normal stores. If we are in the
// situation of having to force either the address into a register or the
@ -868,6 +1300,7 @@ class UnaryRXE<string mnemonic, bits<16> opcode, SDPatternOperator operator,
let OpType = "mem";
let mayLoad = 1;
let AccessBytes = bytes;
let M3 = 0;
}
class UnaryRXY<string mnemonic, bits<16> opcode, SDPatternOperator operator,
@ -894,6 +1327,46 @@ multiclass UnaryRXPair<string mnemonic, bits<8> rxOpcode, bits<16> rxyOpcode,
}
}
class UnaryVRIa<string mnemonic, bits<16> opcode, SDPatternOperator operator,
TypedReg tr, Immediate imm, bits<4> type = 0>
: InstVRIa<opcode, (outs tr.op:$V1), (ins imm:$I2),
mnemonic#"\t$V1, $I2",
[(set tr.op:$V1, (tr.vt (operator imm:$I2)))]> {
let M3 = type;
}
class UnaryVRRa<string mnemonic, bits<16> opcode, SDPatternOperator operator,
TypedReg tr1, TypedReg tr2, bits<4> type = 0, bits<4> m4 = 0,
bits<4> m5 = 0>
: InstVRRa<opcode, (outs tr1.op:$V1), (ins tr2.op:$V2),
mnemonic#"\t$V1, $V2",
[(set tr1.op:$V1, (tr1.vt (operator (tr2.vt tr2.op:$V2))))]> {
let M3 = type;
let M4 = m4;
let M5 = m5;
}
multiclass UnaryVRRaSPair<string mnemonic, bits<16> opcode,
SDPatternOperator operator,
SDPatternOperator operator_cc, TypedReg tr1,
TypedReg tr2, bits<4> type, bits<4> modifier = 0,
bits<4> modifier_cc = 1> {
def "" : UnaryVRRa<mnemonic, opcode, operator, tr1, tr2, type, 0, modifier>;
let Defs = [CC] in
def S : UnaryVRRa<mnemonic##"s", opcode, operator_cc, tr1, tr2, type, 0,
modifier_cc>;
}
class UnaryVRX<string mnemonic, bits<16> opcode, SDPatternOperator operator,
TypedReg tr, bits<5> bytes, bits<4> type = 0>
: InstVRX<opcode, (outs tr.op:$V1), (ins bdxaddr12only:$XBD2),
mnemonic#"\t$V1, $XBD2",
[(set tr.op:$V1, (tr.vt (operator bdxaddr12only:$XBD2)))]> {
let M3 = type;
let mayLoad = 1;
let AccessBytes = bytes;
}
class BinaryRR<string mnemonic, bits<8> opcode, SDPatternOperator operator,
RegisterOperand cls1, RegisterOperand cls2>
: InstRR<opcode, (outs cls1:$R1), (ins cls1:$R1src, cls2:$R2),
@ -1047,6 +1520,7 @@ class BinaryRXE<string mnemonic, bits<16> opcode, SDPatternOperator operator,
let DisableEncoding = "$R1src";
let mayLoad = 1;
let AccessBytes = bytes;
let M3 = 0;
}
class BinaryRXY<string mnemonic, bits<16> opcode, SDPatternOperator operator,
@ -1105,6 +1579,148 @@ multiclass BinarySIPair<string mnemonic, bits<8> siOpcode,
}
}
class BinaryVRIb<string mnemonic, bits<16> opcode, SDPatternOperator operator,
TypedReg tr, bits<4> type>
: InstVRIb<opcode, (outs tr.op:$V1), (ins imm32zx8:$I2, imm32zx8:$I3),
mnemonic#"\t$V1, $I2, $I3",
[(set tr.op:$V1, (tr.vt (operator imm32zx8:$I2, imm32zx8:$I3)))]> {
let M4 = type;
}
class BinaryVRIc<string mnemonic, bits<16> opcode, SDPatternOperator operator,
TypedReg tr1, TypedReg tr2, bits<4> type>
: InstVRIc<opcode, (outs tr1.op:$V1), (ins tr2.op:$V3, imm32zx16:$I2),
mnemonic#"\t$V1, $V3, $I2",
[(set tr1.op:$V1, (tr1.vt (operator (tr2.vt tr2.op:$V3),
imm32zx16:$I2)))]> {
let M4 = type;
}
class BinaryVRIe<string mnemonic, bits<16> opcode, SDPatternOperator operator,
TypedReg tr1, TypedReg tr2, bits<4> type, bits<4> m5>
: InstVRIe<opcode, (outs tr1.op:$V1), (ins tr2.op:$V2, imm32zx12:$I3),
mnemonic#"\t$V1, $V2, $I3",
[(set tr1.op:$V1, (tr1.vt (operator (tr2.vt tr2.op:$V2),
imm32zx12:$I3)))]> {
let M4 = type;
let M5 = m5;
}
class BinaryVRRa<string mnemonic, bits<16> opcode>
: InstVRRa<opcode, (outs VR128:$V1), (ins VR128:$V2, imm32zx4:$M3),
mnemonic#"\t$V1, $V2, $M3", []> {
let M4 = 0;
let M5 = 0;
}
class BinaryVRRb<string mnemonic, bits<16> opcode, SDPatternOperator operator,
TypedReg tr1, TypedReg tr2, bits<4> type = 0,
bits<4> modifier = 0>
: InstVRRb<opcode, (outs tr1.op:$V1), (ins tr2.op:$V2, tr2.op:$V3),
mnemonic#"\t$V1, $V2, $V3",
[(set tr1.op:$V1, (tr1.vt (operator (tr2.vt tr2.op:$V2),
(tr2.vt tr2.op:$V3))))]> {
let M4 = type;
let M5 = modifier;
}
// Declare a pair of instructions, one which sets CC and one which doesn't.
// The CC-setting form ends with "S" and sets the low bit of M5.
multiclass BinaryVRRbSPair<string mnemonic, bits<16> opcode,
SDPatternOperator operator,
SDPatternOperator operator_cc, TypedReg tr1,
TypedReg tr2, bits<4> type,
bits<4> modifier = 0, bits<4> modifier_cc = 1> {
def "" : BinaryVRRb<mnemonic, opcode, operator, tr1, tr2, type, modifier>;
let Defs = [CC] in
def S : BinaryVRRb<mnemonic##"s", opcode, operator_cc, tr1, tr2, type,
modifier_cc>;
}
class BinaryVRRc<string mnemonic, bits<16> opcode, SDPatternOperator operator,
TypedReg tr1, TypedReg tr2, bits<4> type = 0, bits<4> m5 = 0,
bits<4> m6 = 0>
: InstVRRc<opcode, (outs tr1.op:$V1), (ins tr2.op:$V2, tr2.op:$V3),
mnemonic#"\t$V1, $V2, $V3",
[(set tr1.op:$V1, (tr1.vt (operator (tr2.vt tr2.op:$V2),
(tr2.vt tr2.op:$V3))))]> {
let M4 = type;
let M5 = m5;
let M6 = m6;
}
multiclass BinaryVRRcSPair<string mnemonic, bits<16> opcode,
SDPatternOperator operator,
SDPatternOperator operator_cc, TypedReg tr1,
TypedReg tr2, bits<4> type, bits<4> m5,
bits<4> modifier = 0, bits<4> modifier_cc = 1> {
def "" : BinaryVRRc<mnemonic, opcode, operator, tr1, tr2, type, m5, modifier>;
let Defs = [CC] in
def S : BinaryVRRc<mnemonic##"s", opcode, operator_cc, tr1, tr2, type,
m5, modifier_cc>;
}
class BinaryVRRf<string mnemonic, bits<16> opcode, SDPatternOperator operator,
TypedReg tr>
: InstVRRf<opcode, (outs tr.op:$V1), (ins GR64:$R2, GR64:$R3),
mnemonic#"\t$V1, $R2, $R3",
[(set tr.op:$V1, (tr.vt (operator GR64:$R2, GR64:$R3)))]>;
class BinaryVRSa<string mnemonic, bits<16> opcode, SDPatternOperator operator,
TypedReg tr1, TypedReg tr2, bits<4> type>
: InstVRSa<opcode, (outs tr1.op:$V1), (ins tr2.op:$V3, shift12only:$BD2),
mnemonic#"\t$V1, $V3, $BD2",
[(set tr1.op:$V1, (tr1.vt (operator (tr2.vt tr2.op:$V3),
shift12only:$BD2)))]> {
let M4 = type;
}
class BinaryVRSb<string mnemonic, bits<16> opcode, SDPatternOperator operator,
bits<5> bytes>
: InstVRSb<opcode, (outs VR128:$V1), (ins GR32:$R3, bdaddr12only:$BD2),
mnemonic#"\t$V1, $R3, $BD2",
[(set VR128:$V1, (operator GR32:$R3, bdaddr12only:$BD2))]> {
let M4 = 0;
let mayLoad = 1;
let AccessBytes = bytes;
}
class BinaryVRSc<string mnemonic, bits<16> opcode, SDPatternOperator operator,
TypedReg tr, bits<4> type>
: InstVRSc<opcode, (outs GR64:$R1), (ins tr.op:$V3, shift12only:$BD2),
mnemonic#"\t$R1, $V3, $BD2",
[(set GR64:$R1, (operator (tr.vt tr.op:$V3), shift12only:$BD2))]> {
let M4 = type;
}
class BinaryVRX<string mnemonic, bits<16> opcode, SDPatternOperator operator,
TypedReg tr, bits<5> bytes>
: InstVRX<opcode, (outs VR128:$V1), (ins bdxaddr12only:$XBD2, imm32zx4:$M3),
mnemonic#"\t$V1, $XBD2, $M3",
[(set tr.op:$V1, (tr.vt (operator bdxaddr12only:$XBD2,
imm32zx4:$M3)))]> {
let mayLoad = 1;
let AccessBytes = bytes;
}
class StoreBinaryVRV<string mnemonic, bits<16> opcode, bits<5> bytes,
Immediate index>
: InstVRV<opcode, (outs), (ins VR128:$V1, bdvaddr12only:$VBD2, index:$M3),
mnemonic#"\t$V1, $VBD2, $M3", []> {
let mayStore = 1;
let AccessBytes = bytes;
}
class StoreBinaryVRX<string mnemonic, bits<16> opcode,
SDPatternOperator operator, TypedReg tr, bits<5> bytes,
Immediate index>
: InstVRX<opcode, (outs), (ins tr.op:$V1, bdxaddr12only:$XBD2, index:$M3),
mnemonic#"\t$V1, $XBD2, $M3",
[(operator (tr.vt tr.op:$V1), bdxaddr12only:$XBD2, index:$M3)]> {
let mayStore = 1;
let AccessBytes = bytes;
}
class CompareRR<string mnemonic, bits<8> opcode, SDPatternOperator operator,
RegisterOperand cls1, RegisterOperand cls2>
: InstRR<opcode, (outs), (ins cls1:$R1, cls2:$R2),
@ -1177,6 +1793,7 @@ class CompareRXE<string mnemonic, bits<16> opcode, SDPatternOperator operator,
let isCompare = 1;
let mayLoad = 1;
let AccessBytes = bytes;
let M3 = 0;
}
class CompareRXY<string mnemonic, bits<16> opcode, SDPatternOperator operator,
@ -1246,6 +1863,17 @@ multiclass CompareSIPair<string mnemonic, bits<8> siOpcode, bits<16> siyOpcode,
}
}
class CompareVRRa<string mnemonic, bits<16> opcode, SDPatternOperator operator,
TypedReg tr, bits<4> type>
: InstVRRa<opcode, (outs), (ins tr.op:$V1, tr.op:$V2),
mnemonic#"\t$V1, $V2",
[(operator (tr.vt tr.op:$V1), (tr.vt tr.op:$V2))]> {
let isCompare = 1;
let M3 = type;
let M4 = 0;
let M5 = 0;
}
class TernaryRRD<string mnemonic, bits<16> opcode,
SDPatternOperator operator, RegisterOperand cls>
: InstRRD<opcode, (outs cls:$R1), (ins cls:$R1src, cls:$R3, cls:$R2),
@ -1272,6 +1900,188 @@ class TernaryRXF<string mnemonic, bits<16> opcode, SDPatternOperator operator,
let AccessBytes = bytes;
}
class TernaryVRIa<string mnemonic, bits<16> opcode, SDPatternOperator operator,
TypedReg tr1, TypedReg tr2, Immediate imm, Immediate index>
: InstVRIa<opcode, (outs tr1.op:$V1), (ins tr2.op:$V1src, imm:$I2, index:$M3),
mnemonic#"\t$V1, $I2, $M3",
[(set tr1.op:$V1, (tr1.vt (operator (tr2.vt tr2.op:$V1src),
imm:$I2, index:$M3)))]> {
let Constraints = "$V1 = $V1src";
let DisableEncoding = "$V1src";
}
class TernaryVRId<string mnemonic, bits<16> opcode, SDPatternOperator operator,
TypedReg tr1, TypedReg tr2, bits<4> type>
: InstVRId<opcode, (outs tr1.op:$V1),
(ins tr2.op:$V2, tr2.op:$V3, imm32zx8:$I4),
mnemonic#"\t$V1, $V2, $V3, $I4",
[(set tr1.op:$V1, (tr1.vt (operator (tr2.vt tr2.op:$V2),
(tr2.vt tr2.op:$V3),
imm32zx8:$I4)))]> {
let M5 = type;
}
class TernaryVRRa<string mnemonic, bits<16> opcode, SDPatternOperator operator,
TypedReg tr1, TypedReg tr2, bits<4> type, bits<4> m4or>
: InstVRRa<opcode, (outs tr1.op:$V1),
(ins tr2.op:$V2, imm32zx4:$M4, imm32zx4:$M5),
mnemonic#"\t$V1, $V2, $M4, $M5",
[(set tr1.op:$V1, (tr1.vt (operator (tr2.vt tr2.op:$V2),
imm32zx4:$M4,
imm32zx4:$M5)))],
m4or> {
let M3 = type;
}
class TernaryVRRb<string mnemonic, bits<16> opcode, SDPatternOperator operator,
TypedReg tr1, TypedReg tr2, bits<4> type,
SDPatternOperator m5mask, bits<4> m5or>
: InstVRRb<opcode, (outs tr1.op:$V1),
(ins tr2.op:$V2, tr2.op:$V3, m5mask:$M5),
mnemonic#"\t$V1, $V2, $V3, $M5",
[(set tr1.op:$V1, (tr1.vt (operator (tr2.vt tr2.op:$V2),
(tr2.vt tr2.op:$V3),
m5mask:$M5)))],
m5or> {
let M4 = type;
}
multiclass TernaryVRRbSPair<string mnemonic, bits<16> opcode,
SDPatternOperator operator,
SDPatternOperator operator_cc, TypedReg tr1,
TypedReg tr2, bits<4> type, bits<4> m5or> {
def "" : TernaryVRRb<mnemonic, opcode, operator, tr1, tr2, type,
imm32zx4even, !and (m5or, 14)>;
def : InstAlias<mnemonic#"\t$V1, $V2, $V3",
(!cast<Instruction>(NAME) tr1.op:$V1, tr2.op:$V2,
tr2.op:$V3, 0)>;
let Defs = [CC] in
def S : TernaryVRRb<mnemonic##"s", opcode, operator_cc, tr1, tr2, type,
imm32zx4even, !add(!and (m5or, 14), 1)>;
def : InstAlias<mnemonic#"s\t$V1, $V2, $V3",
(!cast<Instruction>(NAME#"S") tr1.op:$V1, tr2.op:$V2,
tr2.op:$V3, 0)>;
}
class TernaryVRRc<string mnemonic, bits<16> opcode, SDPatternOperator operator,
TypedReg tr1, TypedReg tr2>
: InstVRRc<opcode, (outs tr1.op:$V1),
(ins tr2.op:$V2, tr2.op:$V3, imm32zx4:$M4),
mnemonic#"\t$V1, $V2, $V3, $M4",
[(set tr1.op:$V1, (tr1.vt (operator (tr2.vt tr2.op:$V2),
(tr2.vt tr2.op:$V3),
imm32zx4:$M4)))]> {
let M5 = 0;
let M6 = 0;
}
class TernaryVRRd<string mnemonic, bits<16> opcode, SDPatternOperator operator,
TypedReg tr1, TypedReg tr2, bits<4> type = 0>
: InstVRRd<opcode, (outs tr1.op:$V1),
(ins tr2.op:$V2, tr2.op:$V3, tr1.op:$V4),
mnemonic#"\t$V1, $V2, $V3, $V4",
[(set tr1.op:$V1, (tr1.vt (operator (tr2.vt tr2.op:$V2),
(tr2.vt tr2.op:$V3),
(tr1.vt tr1.op:$V4))))]> {
let M5 = type;
let M6 = 0;
}
class TernaryVRRe<string mnemonic, bits<16> opcode, SDPatternOperator operator,
TypedReg tr1, TypedReg tr2, bits<4> m5 = 0, bits<4> type = 0>
: InstVRRe<opcode, (outs tr1.op:$V1),
(ins tr2.op:$V2, tr2.op:$V3, tr1.op:$V4),
mnemonic#"\t$V1, $V2, $V3, $V4",
[(set tr1.op:$V1, (tr1.vt (operator (tr2.vt tr2.op:$V2),
(tr2.vt tr2.op:$V3),
(tr1.vt tr1.op:$V4))))]> {
let M5 = m5;
let M6 = type;
}
class TernaryVRSb<string mnemonic, bits<16> opcode, SDPatternOperator operator,
TypedReg tr1, TypedReg tr2, RegisterOperand cls, bits<4> type>
: InstVRSb<opcode, (outs tr1.op:$V1),
(ins tr2.op:$V1src, cls:$R3, shift12only:$BD2),
mnemonic#"\t$V1, $R3, $BD2",
[(set tr1.op:$V1, (tr1.vt (operator (tr2.vt tr2.op:$V1src),
cls:$R3,
shift12only:$BD2)))]> {
let Constraints = "$V1 = $V1src";
let DisableEncoding = "$V1src";
let M4 = type;
}
class TernaryVRV<string mnemonic, bits<16> opcode, bits<5> bytes,
Immediate index>
: InstVRV<opcode, (outs VR128:$V1),
(ins VR128:$V1src, bdvaddr12only:$VBD2, index:$M3),
mnemonic#"\t$V1, $VBD2, $M3", []> {
let Constraints = "$V1 = $V1src";
let DisableEncoding = "$V1src";
let mayLoad = 1;
let AccessBytes = bytes;
}
class TernaryVRX<string mnemonic, bits<16> opcode, SDPatternOperator operator,
TypedReg tr1, TypedReg tr2, bits<5> bytes, Immediate index>
: InstVRX<opcode, (outs tr1.op:$V1),
(ins tr2.op:$V1src, bdxaddr12only:$XBD2, index:$M3),
mnemonic#"\t$V1, $XBD2, $M3",
[(set tr1.op:$V1, (tr1.vt (operator (tr2.vt tr2.op:$V1src),
bdxaddr12only:$XBD2,
index:$M3)))]> {
let Constraints = "$V1 = $V1src";
let DisableEncoding = "$V1src";
let mayLoad = 1;
let AccessBytes = bytes;
}
class QuaternaryVRId<string mnemonic, bits<16> opcode, SDPatternOperator operator,
TypedReg tr1, TypedReg tr2, bits<4> type>
: InstVRId<opcode, (outs tr1.op:$V1),
(ins tr2.op:$V1src, tr2.op:$V2, tr2.op:$V3, imm32zx8:$I4),
mnemonic#"\t$V1, $V2, $V3, $I4",
[(set tr1.op:$V1, (tr1.vt (operator (tr2.vt tr2.op:$V1src),
(tr2.vt tr2.op:$V2),
(tr2.vt tr2.op:$V3),
imm32zx8:$I4)))]> {
let Constraints = "$V1 = $V1src";
let DisableEncoding = "$V1src";
let M5 = type;
}
class QuaternaryVRRd<string mnemonic, bits<16> opcode,
SDPatternOperator operator, TypedReg tr1, TypedReg tr2,
bits<4> type, SDPatternOperator m6mask, bits<4> m6or>
: InstVRRd<opcode, (outs tr1.op:$V1),
(ins tr2.op:$V2, tr2.op:$V3, tr2.op:$V4, m6mask:$M6),
mnemonic#"\t$V1, $V2, $V3, $V4, $M6",
[(set tr1.op:$V1, (tr1.vt (operator (tr2.vt tr2.op:$V2),
(tr2.vt tr2.op:$V3),
(tr2.vt tr2.op:$V4),
m6mask:$M6)))],
m6or> {
let M5 = type;
}
multiclass QuaternaryVRRdSPair<string mnemonic, bits<16> opcode,
SDPatternOperator operator,
SDPatternOperator operator_cc, TypedReg tr1,
TypedReg tr2, bits<4> type, bits<4> m6or> {
def "" : QuaternaryVRRd<mnemonic, opcode, operator, tr1, tr2, type,
imm32zx4even, !and (m6or, 14)>;
def : InstAlias<mnemonic#"\t$V1, $V2, $V3, $V4",
(!cast<Instruction>(NAME) tr1.op:$V1, tr2.op:$V2,
tr2.op:$V3, tr2.op:$V4, 0)>;
let Defs = [CC] in
def S : QuaternaryVRRd<mnemonic##"s", opcode, operator_cc, tr1, tr2, type,
imm32zx4even, !add (!and (m6or, 14), 1)>;
def : InstAlias<mnemonic#"s\t$V1, $V2, $V3, $V4",
(!cast<Instruction>(NAME#"S") tr1.op:$V1, tr2.op:$V2,
tr2.op:$V3, tr2.op:$V4, 0)>;
}
class LoadAndOpRSY<string mnemonic, bits<16> opcode, SDPatternOperator operator,
RegisterOperand cls, AddressingMode mode = bdaddr20only>
: InstRSY<opcode, (outs cls:$R1), (ins cls:$R3, mode:$BD2),

View File

@ -0,0 +1,751 @@
//==- SystemZInstrVector.td - SystemZ Vector instructions ------*- tblgen-*-==//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// Move instructions
//===----------------------------------------------------------------------===//
let Predicates = [FeatureVector] in {
// Register move.
def VLR : UnaryVRRa<"vlr", 0xE756, null_frag, v128any, v128any>;
// Load GR from VR element.
def VLGVB : BinaryVRSc<"vlgvb", 0xE721, null_frag, v128b, 0>;
def VLGVH : BinaryVRSc<"vlgvh", 0xE721, null_frag, v128h, 1>;
def VLGVF : BinaryVRSc<"vlgvf", 0xE721, null_frag, v128f, 2>;
def VLGVG : BinaryVRSc<"vlgvg", 0xE721, null_frag, v128g, 3>;
// Load VR element from GR.
def VLVGB : TernaryVRSb<"vlvgb", 0xE722, null_frag, v128b, v128b, GR32, 0>;
def VLVGH : TernaryVRSb<"vlvgh", 0xE722, null_frag, v128h, v128h, GR32, 1>;
def VLVGF : TernaryVRSb<"vlvgf", 0xE722, null_frag, v128f, v128f, GR32, 2>;
def VLVGG : TernaryVRSb<"vlvgg", 0xE722, null_frag, v128g, v128g, GR64, 3>;
// Load VR from GRs disjoint.
def VLVGP : BinaryVRRf<"vlvgp", 0xE762, null_frag, v128g>;
}
//===----------------------------------------------------------------------===//
// Immediate instructions
//===----------------------------------------------------------------------===//
let Predicates = [FeatureVector] in {
// Generate byte mask.
def VZERO : InherentVRIa<"vzero", 0xE744, 0>;
def VONE : InherentVRIa<"vone", 0xE744, 0xffff>;
def VGBM : UnaryVRIa<"vgbm", 0xE744, null_frag, v128b, imm32zx16>;
// Generate mask.
def VGMB : BinaryVRIb<"vgmb", 0xE746, null_frag, v128b, 0>;
def VGMH : BinaryVRIb<"vgmh", 0xE746, null_frag, v128h, 1>;
def VGMF : BinaryVRIb<"vgmf", 0xE746, null_frag, v128f, 2>;
def VGMG : BinaryVRIb<"vgmg", 0xE746, null_frag, v128g, 3>;
// Load element immediate.
def VLEIB : TernaryVRIa<"vleib", 0xE740, null_frag,
v128b, v128b, imm32sx16trunc, imm32zx4>;
def VLEIH : TernaryVRIa<"vleih", 0xE741, null_frag,
v128h, v128h, imm32sx16trunc, imm32zx3>;
def VLEIF : TernaryVRIa<"vleif", 0xE743, null_frag,
v128f, v128f, imm32sx16, imm32zx2>;
def VLEIG : TernaryVRIa<"vleig", 0xE742, null_frag,
v128g, v128g, imm64sx16, imm32zx1>;
// Replicate immediate.
def VREPIB : UnaryVRIa<"vrepib", 0xE745, null_frag, v128b, imm32sx16, 0>;
def VREPIH : UnaryVRIa<"vrepih", 0xE745, null_frag, v128h, imm32sx16, 1>;
def VREPIF : UnaryVRIa<"vrepif", 0xE745, null_frag, v128f, imm32sx16, 2>;
def VREPIG : UnaryVRIa<"vrepig", 0xE745, null_frag, v128g, imm32sx16, 3>;
}
//===----------------------------------------------------------------------===//
// Loads
//===----------------------------------------------------------------------===//
let Predicates = [FeatureVector] in {
// Load.
def VL : UnaryVRX<"vl", 0xE706, null_frag, v128any, 16>;
// Load to block boundary. The number of loaded bytes is only known
// at run time.
def VLBB : BinaryVRX<"vlbb", 0xE707, null_frag, v128any, 0>;
// Load count to block boundary.
let Defs = [CC] in
def LCBB : InstRXE<0xE727, (outs GR32:$R1),
(ins bdxaddr12only:$XBD2, imm32zx4:$M3),
"lcbb\t$R1, $XBD2, $M3", []>;
// Load with length. The number of loaded bytes is only known at run time.
def VLL : BinaryVRSb<"vll", 0xE737, null_frag, 0>;
// Load multiple.
def VLM : LoadMultipleVRSa<"vlm", 0xE736>;
// Load and replicate
def VLREPB : UnaryVRX<"vlrepb", 0xE705, null_frag, v128b, 1, 0>;
def VLREPH : UnaryVRX<"vlreph", 0xE705, null_frag, v128h, 2, 1>;
def VLREPF : UnaryVRX<"vlrepf", 0xE705, null_frag, v128f, 4, 2>;
def VLREPG : UnaryVRX<"vlrepg", 0xE705, null_frag, v128g, 8, 3>;
// Load logical element and zero.
def VLLEZB : UnaryVRX<"vllezb", 0xE704, null_frag, v128b, 1, 0>;
def VLLEZH : UnaryVRX<"vllezh", 0xE704, null_frag, v128h, 2, 1>;
def VLLEZF : UnaryVRX<"vllezf", 0xE704, null_frag, v128f, 4, 2>;
def VLLEZG : UnaryVRX<"vllezg", 0xE704, null_frag, v128g, 8, 3>;
// Load element.
def VLEB : TernaryVRX<"vleb", 0xE700, null_frag, v128b, v128b, 1, imm32zx4>;
def VLEH : TernaryVRX<"vleh", 0xE701, null_frag, v128h, v128h, 2, imm32zx3>;
def VLEF : TernaryVRX<"vlef", 0xE703, null_frag, v128f, v128f, 4, imm32zx2>;
def VLEG : TernaryVRX<"vleg", 0xE702, null_frag, v128g, v128g, 8, imm32zx1>;
// Gather element.
def VGEF : TernaryVRV<"vgef", 0xE713, 4, imm32zx2>;
def VGEG : TernaryVRV<"vgeg", 0xE712, 8, imm32zx1>;
}
//===----------------------------------------------------------------------===//
// Stores
//===----------------------------------------------------------------------===//
let Predicates = [FeatureVector] in {
// Store.
def VST : StoreVRX<"vst", 0xE70E, null_frag, v128any, 16>;
// Store with length. The number of stored bytes is only known at run time.
def VSTL : StoreLengthVRSb<"vstl", 0xE73F, null_frag, 0>;
// Store multiple.
def VSTM : StoreMultipleVRSa<"vstm", 0xE73E>;
// Store element.
def VSTEB : StoreBinaryVRX<"vsteb", 0xE708, null_frag, v128b, 1, imm32zx4>;
def VSTEH : StoreBinaryVRX<"vsteh", 0xE709, null_frag, v128h, 2, imm32zx3>;
def VSTEF : StoreBinaryVRX<"vstef", 0xE70B, null_frag, v128f, 4, imm32zx2>;
def VSTEG : StoreBinaryVRX<"vsteg", 0xE70A, null_frag, v128g, 8, imm32zx1>;
// Scatter element.
def VSCEF : StoreBinaryVRV<"vscef", 0xE71B, 4, imm32zx2>;
def VSCEG : StoreBinaryVRV<"vsceg", 0xE71A, 8, imm32zx1>;
}
//===----------------------------------------------------------------------===//
// Selects and permutes
//===----------------------------------------------------------------------===//
let Predicates = [FeatureVector] in {
// Merge high.
def VMRHB : BinaryVRRc<"vmrhb", 0xE761, null_frag, v128b, v128b, 0>;
def VMRHH : BinaryVRRc<"vmrhh", 0xE761, null_frag, v128h, v128h, 1>;
def VMRHF : BinaryVRRc<"vmrhf", 0xE761, null_frag, v128f, v128f, 2>;
def VMRHG : BinaryVRRc<"vmrhg", 0xE761, null_frag, v128g, v128g, 3>;
// Merge low.
def VMRLB : BinaryVRRc<"vmrlb", 0xE760, null_frag, v128b, v128b, 0>;
def VMRLH : BinaryVRRc<"vmrlh", 0xE760, null_frag, v128h, v128h, 1>;
def VMRLF : BinaryVRRc<"vmrlf", 0xE760, null_frag, v128f, v128f, 2>;
def VMRLG : BinaryVRRc<"vmrlg", 0xE760, null_frag, v128g, v128g, 3>;
// Permute.
def VPERM : TernaryVRRe<"vperm", 0xE78C, null_frag, v128b, v128b>;
// Permute doubleword immediate.
def VPDI : TernaryVRRc<"vpdi", 0xE784, null_frag, v128b, v128b>;
// Replicate.
def VREPB : BinaryVRIc<"vrepb", 0xE74D, null_frag, v128b, v128b, 0>;
def VREPH : BinaryVRIc<"vreph", 0xE74D, null_frag, v128h, v128h, 1>;
def VREPF : BinaryVRIc<"vrepf", 0xE74D, null_frag, v128f, v128f, 2>;
def VREPG : BinaryVRIc<"vrepg", 0xE74D, null_frag, v128g, v128g, 3>;
// Select.
def VSEL : TernaryVRRe<"vsel", 0xE78D, null_frag, v128any, v128any>;
}
//===----------------------------------------------------------------------===//
// Widening and narrowing
//===----------------------------------------------------------------------===//
let Predicates = [FeatureVector] in {
// Pack
def VPKH : BinaryVRRc<"vpkh", 0xE794, null_frag, v128b, v128h, 1>;
def VPKF : BinaryVRRc<"vpkf", 0xE794, null_frag, v128h, v128f, 2>;
def VPKG : BinaryVRRc<"vpkg", 0xE794, null_frag, v128f, v128g, 3>;
// Pack saturate.
defm VPKSH : BinaryVRRbSPair<"vpksh", 0xE797, null_frag, null_frag,
v128b, v128h, 1>;
defm VPKSF : BinaryVRRbSPair<"vpksf", 0xE797, null_frag, null_frag,
v128h, v128f, 2>;
defm VPKSG : BinaryVRRbSPair<"vpksg", 0xE797, null_frag, null_frag,
v128f, v128g, 3>;
// Pack saturate logical.
defm VPKLSH : BinaryVRRbSPair<"vpklsh", 0xE795, null_frag, null_frag,
v128b, v128h, 1>;
defm VPKLSF : BinaryVRRbSPair<"vpklsf", 0xE795, null_frag, null_frag,
v128h, v128f, 2>;
defm VPKLSG : BinaryVRRbSPair<"vpklsg", 0xE795, null_frag, null_frag,
v128f, v128g, 3>;
// Sign-extend to doubleword.
def VSEGB : UnaryVRRa<"vsegb", 0xE75F, null_frag, v128g, v128b, 0>;
def VSEGH : UnaryVRRa<"vsegh", 0xE75F, null_frag, v128g, v128h, 1>;
def VSEGF : UnaryVRRa<"vsegf", 0xE75F, null_frag, v128g, v128f, 2>;
// Unpack high.
def VUPHB : UnaryVRRa<"vuphb", 0xE7D7, null_frag, v128h, v128b, 0>;
def VUPHH : UnaryVRRa<"vuphh", 0xE7D7, null_frag, v128f, v128h, 1>;
def VUPHF : UnaryVRRa<"vuphf", 0xE7D7, null_frag, v128g, v128f, 2>;
// Unpack logical high.
def VUPLHB : UnaryVRRa<"vuplhb", 0xE7D5, null_frag, v128h, v128b, 0>;
def VUPLHH : UnaryVRRa<"vuplhh", 0xE7D5, null_frag, v128f, v128h, 1>;
def VUPLHF : UnaryVRRa<"vuplhf", 0xE7D5, null_frag, v128g, v128f, 2>;
// Unpack low.
def VUPLB : UnaryVRRa<"vuplb", 0xE7D6, null_frag, v128h, v128b, 0>;
def VUPLHW : UnaryVRRa<"vuplhw", 0xE7D6, null_frag, v128f, v128h, 1>;
def VUPLF : UnaryVRRa<"vuplf", 0xE7D6, null_frag, v128g, v128f, 2>;
// Unpack logical low.
def VUPLLB : UnaryVRRa<"vupllb", 0xE7D4, null_frag, v128h, v128b, 0>;
def VUPLLH : UnaryVRRa<"vupllh", 0xE7D4, null_frag, v128f, v128h, 1>;
def VUPLLF : UnaryVRRa<"vupllf", 0xE7D4, null_frag, v128g, v128f, 2>;
}
//===----------------------------------------------------------------------===//
// Integer arithmetic
//===----------------------------------------------------------------------===//
let Predicates = [FeatureVector] in {
// Add.
def VAB : BinaryVRRc<"vab", 0xE7F3, null_frag, v128b, v128b, 0>;
def VAH : BinaryVRRc<"vah", 0xE7F3, null_frag, v128h, v128h, 1>;
def VAF : BinaryVRRc<"vaf", 0xE7F3, null_frag, v128f, v128f, 2>;
def VAG : BinaryVRRc<"vag", 0xE7F3, null_frag, v128g, v128g, 3>;
def VAQ : BinaryVRRc<"vaq", 0xE7F3, null_frag, v128q, v128q, 4>;
// Add compute carry.
def VACCB : BinaryVRRc<"vaccb", 0xE7F1, null_frag, v128b, v128b, 0>;
def VACCH : BinaryVRRc<"vacch", 0xE7F1, null_frag, v128h, v128h, 1>;
def VACCF : BinaryVRRc<"vaccf", 0xE7F1, null_frag, v128f, v128f, 2>;
def VACCG : BinaryVRRc<"vaccg", 0xE7F1, null_frag, v128g, v128g, 3>;
def VACCQ : BinaryVRRc<"vaccq", 0xE7F1, null_frag, v128q, v128q, 4>;
// Add with carry.
def VACQ : TernaryVRRd<"vacq", 0xE7BB, null_frag, v128q, v128q, 4>;
// Add with carry compute carry.
def VACCCQ : TernaryVRRd<"vacccq", 0xE7B9, null_frag, v128q, v128q, 4>;
// And.
def VN : BinaryVRRc<"vn", 0xE768, null_frag, v128any, v128any>;
// And with complement.
def VNC : BinaryVRRc<"vnc", 0xE769, null_frag, v128any, v128any>;
// Average.
def VAVGB : BinaryVRRc<"vavgb", 0xE7F2, null_frag, v128b, v128b, 0>;
def VAVGH : BinaryVRRc<"vavgh", 0xE7F2, null_frag, v128h, v128h, 1>;
def VAVGF : BinaryVRRc<"vavgf", 0xE7F2, null_frag, v128f, v128f, 2>;
def VAVGG : BinaryVRRc<"vavgg", 0xE7F2, null_frag, v128g, v128g, 3>;
// Average logical.
def VAVGLB : BinaryVRRc<"vavglb", 0xE7F0, null_frag, v128b, v128b, 0>;
def VAVGLH : BinaryVRRc<"vavglh", 0xE7F0, null_frag, v128h, v128h, 1>;
def VAVGLF : BinaryVRRc<"vavglf", 0xE7F0, null_frag, v128f, v128f, 2>;
def VAVGLG : BinaryVRRc<"vavglg", 0xE7F0, null_frag, v128g, v128g, 3>;
// Checksum.
def VCKSM : BinaryVRRc<"vcksm", 0xE766, null_frag, v128any, v128any>;
// Count leading zeros.
def VCLZB : UnaryVRRa<"vclzb", 0xE753, null_frag, v128b, v128b, 0>;
def VCLZH : UnaryVRRa<"vclzh", 0xE753, null_frag, v128h, v128h, 1>;
def VCLZF : UnaryVRRa<"vclzf", 0xE753, null_frag, v128f, v128f, 2>;
def VCLZG : UnaryVRRa<"vclzg", 0xE753, null_frag, v128g, v128g, 3>;
// Count trailing zeros.
def VCTZB : UnaryVRRa<"vctzb", 0xE752, null_frag, v128b, v128b, 0>;
def VCTZH : UnaryVRRa<"vctzh", 0xE752, null_frag, v128h, v128h, 1>;
def VCTZF : UnaryVRRa<"vctzf", 0xE752, null_frag, v128f, v128f, 2>;
def VCTZG : UnaryVRRa<"vctzg", 0xE752, null_frag, v128g, v128g, 3>;
// Exclusive or.
def VX : BinaryVRRc<"vx", 0xE76D, null_frag, v128any, v128any>;
// Galois field multiply sum.
def VGFMB : BinaryVRRc<"vgfmb", 0xE7B4, null_frag, v128b, v128b, 0>;
def VGFMH : BinaryVRRc<"vgfmh", 0xE7B4, null_frag, v128h, v128h, 1>;
def VGFMF : BinaryVRRc<"vgfmf", 0xE7B4, null_frag, v128f, v128f, 2>;
def VGFMG : BinaryVRRc<"vgfmg", 0xE7B4, null_frag, v128g, v128g, 3>;
// Galois field multiply sum and accumulate.
def VGFMAB : TernaryVRRd<"vgfmab", 0xE7BC, null_frag, v128b, v128b, 0>;
def VGFMAH : TernaryVRRd<"vgfmah", 0xE7BC, null_frag, v128h, v128h, 1>;
def VGFMAF : TernaryVRRd<"vgfmaf", 0xE7BC, null_frag, v128f, v128f, 2>;
def VGFMAG : TernaryVRRd<"vgfmag", 0xE7BC, null_frag, v128g, v128g, 3>;
// Load complement.
def VLCB : UnaryVRRa<"vlcb", 0xE7DE, null_frag, v128b, v128b, 0>;
def VLCH : UnaryVRRa<"vlch", 0xE7DE, null_frag, v128h, v128h, 1>;
def VLCF : UnaryVRRa<"vlcf", 0xE7DE, null_frag, v128f, v128f, 2>;
def VLCG : UnaryVRRa<"vlcg", 0xE7DE, null_frag, v128g, v128g, 3>;
// Load positive.
def VLPB : UnaryVRRa<"vlpb", 0xE7DF, null_frag, v128b, v128b, 0>;
def VLPH : UnaryVRRa<"vlph", 0xE7DF, null_frag, v128h, v128h, 1>;
def VLPF : UnaryVRRa<"vlpf", 0xE7DF, null_frag, v128f, v128f, 2>;
def VLPG : UnaryVRRa<"vlpg", 0xE7DF, null_frag, v128g, v128g, 3>;
// Maximum.
def VMXB : BinaryVRRc<"vmxb", 0xE7FF, null_frag, v128b, v128b, 0>;
def VMXH : BinaryVRRc<"vmxh", 0xE7FF, null_frag, v128h, v128h, 1>;
def VMXF : BinaryVRRc<"vmxf", 0xE7FF, null_frag, v128f, v128f, 2>;
def VMXG : BinaryVRRc<"vmxg", 0xE7FF, null_frag, v128g, v128g, 3>;
// Maximum logical.
def VMXLB : BinaryVRRc<"vmxlb", 0xE7FD, null_frag, v128b, v128b, 0>;
def VMXLH : BinaryVRRc<"vmxlh", 0xE7FD, null_frag, v128h, v128h, 1>;
def VMXLF : BinaryVRRc<"vmxlf", 0xE7FD, null_frag, v128f, v128f, 2>;
def VMXLG : BinaryVRRc<"vmxlg", 0xE7FD, null_frag, v128g, v128g, 3>;
// Minimum.
def VMNB : BinaryVRRc<"vmnb", 0xE7FE, null_frag, v128b, v128b, 0>;
def VMNH : BinaryVRRc<"vmnh", 0xE7FE, null_frag, v128h, v128h, 1>;
def VMNF : BinaryVRRc<"vmnf", 0xE7FE, null_frag, v128f, v128f, 2>;
def VMNG : BinaryVRRc<"vmng", 0xE7FE, null_frag, v128g, v128g, 3>;
// Minimum logical.
def VMNLB : BinaryVRRc<"vmnlb", 0xE7FC, null_frag, v128b, v128b, 0>;
def VMNLH : BinaryVRRc<"vmnlh", 0xE7FC, null_frag, v128h, v128h, 1>;
def VMNLF : BinaryVRRc<"vmnlf", 0xE7FC, null_frag, v128f, v128f, 2>;
def VMNLG : BinaryVRRc<"vmnlg", 0xE7FC, null_frag, v128g, v128g, 3>;
// Multiply and add low.
def VMALB : TernaryVRRd<"vmalb", 0xE7AA, null_frag, v128b, v128b, 0>;
def VMALHW : TernaryVRRd<"vmalhw", 0xE7AA, null_frag, v128h, v128h, 1>;
def VMALF : TernaryVRRd<"vmalf", 0xE7AA, null_frag, v128f, v128f, 2>;
// Multiply and add high.
def VMAHB : TernaryVRRd<"vmahb", 0xE7AB, null_frag, v128b, v128b, 0>;
def VMAHH : TernaryVRRd<"vmahh", 0xE7AB, null_frag, v128h, v128h, 1>;
def VMAHF : TernaryVRRd<"vmahf", 0xE7AB, null_frag, v128f, v128f, 2>;
// Multiply and add logical high.
def VMALHB : TernaryVRRd<"vmalhb", 0xE7A9, null_frag, v128b, v128b, 0>;
def VMALHH : TernaryVRRd<"vmalhh", 0xE7A9, null_frag, v128h, v128h, 1>;
def VMALHF : TernaryVRRd<"vmalhf", 0xE7A9, null_frag, v128f, v128f, 2>;
// Multiply and add even.
def VMAEB : TernaryVRRd<"vmaeb", 0xE7AE, null_frag, v128h, v128b, 0>;
def VMAEH : TernaryVRRd<"vmaeh", 0xE7AE, null_frag, v128f, v128h, 1>;
def VMAEF : TernaryVRRd<"vmaef", 0xE7AE, null_frag, v128g, v128f, 2>;
// Multiply and add logical even.
def VMALEB : TernaryVRRd<"vmaleb", 0xE7AC, null_frag, v128h, v128b, 0>;
def VMALEH : TernaryVRRd<"vmaleh", 0xE7AC, null_frag, v128f, v128h, 1>;
def VMALEF : TernaryVRRd<"vmalef", 0xE7AC, null_frag, v128g, v128f, 2>;
// Multiply and add odd.
def VMAOB : TernaryVRRd<"vmaob", 0xE7AF, null_frag, v128h, v128b, 0>;
def VMAOH : TernaryVRRd<"vmaoh", 0xE7AF, null_frag, v128f, v128h, 1>;
def VMAOF : TernaryVRRd<"vmaof", 0xE7AF, null_frag, v128g, v128f, 2>;
// Multiply and add logical odd.
def VMALOB : TernaryVRRd<"vmalob", 0xE7AD, null_frag, v128h, v128b, 0>;
def VMALOH : TernaryVRRd<"vmaloh", 0xE7AD, null_frag, v128f, v128h, 1>;
def VMALOF : TernaryVRRd<"vmalof", 0xE7AD, null_frag, v128g, v128f, 2>;
// Multiply high.
def VMHB : BinaryVRRc<"vmhb", 0xE7A3, null_frag, v128b, v128b, 0>;
def VMHH : BinaryVRRc<"vmhh", 0xE7A3, null_frag, v128h, v128h, 1>;
def VMHF : BinaryVRRc<"vmhf", 0xE7A3, null_frag, v128f, v128f, 2>;
// Multiply logical high.
def VMLHB : BinaryVRRc<"vmlhb", 0xE7A1, null_frag, v128b, v128b, 0>;
def VMLHH : BinaryVRRc<"vmlhh", 0xE7A1, null_frag, v128h, v128h, 1>;
def VMLHF : BinaryVRRc<"vmlhf", 0xE7A1, null_frag, v128f, v128f, 2>;
// Multiply low.
def VMLB : BinaryVRRc<"vmlb", 0xE7A2, null_frag, v128b, v128b, 0>;
def VMLHW : BinaryVRRc<"vmlhw", 0xE7A2, null_frag, v128h, v128h, 1>;
def VMLF : BinaryVRRc<"vmlf", 0xE7A2, null_frag, v128f, v128f, 2>;
// Multiply even.
def VMEB : BinaryVRRc<"vmeb", 0xE7A6, null_frag, v128h, v128b, 0>;
def VMEH : BinaryVRRc<"vmeh", 0xE7A6, null_frag, v128f, v128h, 1>;
def VMEF : BinaryVRRc<"vmef", 0xE7A6, null_frag, v128g, v128f, 2>;
// Multiply logical even.
def VMLEB : BinaryVRRc<"vmleb", 0xE7A4, null_frag, v128h, v128b, 0>;
def VMLEH : BinaryVRRc<"vmleh", 0xE7A4, null_frag, v128f, v128h, 1>;
def VMLEF : BinaryVRRc<"vmlef", 0xE7A4, null_frag, v128g, v128f, 2>;
// Multiply odd.
def VMOB : BinaryVRRc<"vmob", 0xE7A7, null_frag, v128h, v128b, 0>;
def VMOH : BinaryVRRc<"vmoh", 0xE7A7, null_frag, v128f, v128h, 1>;
def VMOF : BinaryVRRc<"vmof", 0xE7A7, null_frag, v128g, v128f, 2>;
// Multiply logical odd.
def VMLOB : BinaryVRRc<"vmlob", 0xE7A5, null_frag, v128h, v128b, 0>;
def VMLOH : BinaryVRRc<"vmloh", 0xE7A5, null_frag, v128f, v128h, 1>;
def VMLOF : BinaryVRRc<"vmlof", 0xE7A5, null_frag, v128g, v128f, 2>;
// Nor.
def VNO : BinaryVRRc<"vno", 0xE76B, null_frag, v128any, v128any>;
// Or.
def VO : BinaryVRRc<"vo", 0xE76A, null_frag, v128any, v128any>;
// Population count.
def VPOPCT : BinaryVRRa<"vpopct", 0xE750>;
// Element rotate left logical (with vector shift amount).
def VERLLVB : BinaryVRRc<"verllvb", 0xE773, null_frag, v128b, v128b, 0>;
def VERLLVH : BinaryVRRc<"verllvh", 0xE773, null_frag, v128h, v128h, 1>;
def VERLLVF : BinaryVRRc<"verllvf", 0xE773, null_frag, v128f, v128f, 2>;
def VERLLVG : BinaryVRRc<"verllvg", 0xE773, null_frag, v128g, v128g, 3>;
// Element rotate left logical (with scalar shift amount).
def VERLLB : BinaryVRSa<"verllb", 0xE733, null_frag, v128b, v128b, 0>;
def VERLLH : BinaryVRSa<"verllh", 0xE733, null_frag, v128h, v128h, 1>;
def VERLLF : BinaryVRSa<"verllf", 0xE733, null_frag, v128f, v128f, 2>;
def VERLLG : BinaryVRSa<"verllg", 0xE733, null_frag, v128g, v128g, 3>;
// Element rotate and insert under mask.
def VERIMB : QuaternaryVRId<"verimb", 0xE772, null_frag, v128b, v128b, 0>;
def VERIMH : QuaternaryVRId<"verimh", 0xE772, null_frag, v128h, v128h, 1>;
def VERIMF : QuaternaryVRId<"verimf", 0xE772, null_frag, v128f, v128f, 2>;
def VERIMG : QuaternaryVRId<"verimg", 0xE772, null_frag, v128g, v128g, 3>;
// Element shift left (with vector shift amount).
def VESLVB : BinaryVRRc<"veslvb", 0xE770, null_frag, v128b, v128b, 0>;
def VESLVH : BinaryVRRc<"veslvh", 0xE770, null_frag, v128h, v128h, 1>;
def VESLVF : BinaryVRRc<"veslvf", 0xE770, null_frag, v128f, v128f, 2>;
def VESLVG : BinaryVRRc<"veslvg", 0xE770, null_frag, v128g, v128g, 3>;
// Element shift left (with scalar shift amount).
def VESLB : BinaryVRSa<"veslb", 0xE730, null_frag, v128b, v128b, 0>;
def VESLH : BinaryVRSa<"veslh", 0xE730, null_frag, v128h, v128h, 1>;
def VESLF : BinaryVRSa<"veslf", 0xE730, null_frag, v128f, v128f, 2>;
def VESLG : BinaryVRSa<"veslg", 0xE730, null_frag, v128g, v128g, 3>;
// Element shift right arithmetic (with vector shift amount).
def VESRAVB : BinaryVRRc<"vesravb", 0xE77A, null_frag, v128b, v128b, 0>;
def VESRAVH : BinaryVRRc<"vesravh", 0xE77A, null_frag, v128h, v128h, 1>;
def VESRAVF : BinaryVRRc<"vesravf", 0xE77A, null_frag, v128f, v128f, 2>;
def VESRAVG : BinaryVRRc<"vesravg", 0xE77A, null_frag, v128g, v128g, 3>;
// Element shift right arithmetic (with scalar shift amount).
def VESRAB : BinaryVRSa<"vesrab", 0xE73A, null_frag, v128b, v128b, 0>;
def VESRAH : BinaryVRSa<"vesrah", 0xE73A, null_frag, v128h, v128h, 1>;
def VESRAF : BinaryVRSa<"vesraf", 0xE73A, null_frag, v128f, v128f, 2>;
def VESRAG : BinaryVRSa<"vesrag", 0xE73A, null_frag, v128g, v128g, 3>;
// Element shift right logical (with vector shift amount).
def VESRLVB : BinaryVRRc<"vesrlvb", 0xE778, null_frag, v128b, v128b, 0>;
def VESRLVH : BinaryVRRc<"vesrlvh", 0xE778, null_frag, v128h, v128h, 1>;
def VESRLVF : BinaryVRRc<"vesrlvf", 0xE778, null_frag, v128f, v128f, 2>;
def VESRLVG : BinaryVRRc<"vesrlvg", 0xE778, null_frag, v128g, v128g, 3>;
// Element shift right logical (with scalar shift amount).
def VESRLB : BinaryVRSa<"vesrlb", 0xE738, null_frag, v128b, v128b, 0>;
def VESRLH : BinaryVRSa<"vesrlh", 0xE738, null_frag, v128h, v128h, 1>;
def VESRLF : BinaryVRSa<"vesrlf", 0xE738, null_frag, v128f, v128f, 2>;
def VESRLG : BinaryVRSa<"vesrlg", 0xE738, null_frag, v128g, v128g, 3>;
// Shift left.
def VSL : BinaryVRRc<"vsl", 0xE774, null_frag, v128b, v128b>;
// Shift left by byte.
def VSLB : BinaryVRRc<"vslb", 0xE775, null_frag, v128b, v128b>;
// Shift left double by byte.
def VSLDB : TernaryVRId<"vsldb", 0xE777, null_frag, v128b, v128b, 0>;
// Shift right arithmetic.
def VSRA : BinaryVRRc<"vsra", 0xE77E, null_frag, v128b, v128b>;
// Shift right arithmetic by byte.
def VSRAB : BinaryVRRc<"vsrab", 0xE77F, null_frag, v128b, v128b>;
// Shift right logical.
def VSRL : BinaryVRRc<"vsrl", 0xE77C, null_frag, v128b, v128b>;
// Shift right logical by byte.
def VSRLB : BinaryVRRc<"vsrlb", 0xE77D, null_frag, v128b, v128b>;
// Subtract.
def VSB : BinaryVRRc<"vsb", 0xE7F7, null_frag, v128b, v128b, 0>;
def VSH : BinaryVRRc<"vsh", 0xE7F7, null_frag, v128h, v128h, 1>;
def VSF : BinaryVRRc<"vsf", 0xE7F7, null_frag, v128f, v128f, 2>;
def VSG : BinaryVRRc<"vsg", 0xE7F7, null_frag, v128g, v128g, 3>;
def VSQ : BinaryVRRc<"vsq", 0xE7F7, null_frag, v128q, v128q, 4>;
// Subtract compute borrow indication.
def VSCBIB : BinaryVRRc<"vscbib", 0xE7F5, null_frag, v128b, v128b, 0>;
def VSCBIH : BinaryVRRc<"vscbih", 0xE7F5, null_frag, v128h, v128h, 1>;
def VSCBIF : BinaryVRRc<"vscbif", 0xE7F5, null_frag, v128f, v128f, 2>;
def VSCBIG : BinaryVRRc<"vscbig", 0xE7F5, null_frag, v128g, v128g, 3>;
def VSCBIQ : BinaryVRRc<"vscbiq", 0xE7F5, null_frag, v128q, v128q, 4>;
// Subtract with borrow indication.
def VSBIQ : TernaryVRRd<"vsbiq", 0xE7BF, null_frag, v128q, v128q, 4>;
// Subtract with borrow compute borrow indication.
def VSBCBIQ : TernaryVRRd<"vsbcbiq", 0xE7BD, null_frag, v128q, v128q, 4>;
// Sum across doubleword.
def VSUMGH : BinaryVRRc<"vsumgh", 0xE765, null_frag, v128g, v128h, 1>;
def VSUMGF : BinaryVRRc<"vsumgf", 0xE765, null_frag, v128g, v128f, 2>;
// Sum across quadword.
def VSUMQF : BinaryVRRc<"vsumqf", 0xE767, null_frag, v128q, v128f, 2>;
def VSUMQG : BinaryVRRc<"vsumqg", 0xE767, null_frag, v128q, v128g, 3>;
// Sum across word.
def VSUMB : BinaryVRRc<"vsumb", 0xE764, null_frag, v128f, v128b, 0>;
def VSUMH : BinaryVRRc<"vsumh", 0xE764, null_frag, v128f, v128h, 1>;
}
//===----------------------------------------------------------------------===//
// Integer comparison
//===----------------------------------------------------------------------===//
let Predicates = [FeatureVector] in {
// Element compare.
let Defs = [CC] in {
def VECB : CompareVRRa<"vecb", 0xE7DB, null_frag, v128b, 0>;
def VECH : CompareVRRa<"vech", 0xE7DB, null_frag, v128h, 1>;
def VECF : CompareVRRa<"vecf", 0xE7DB, null_frag, v128f, 2>;
def VECG : CompareVRRa<"vecg", 0xE7DB, null_frag, v128g, 3>;
}
// Element compare logical.
let Defs = [CC] in {
def VECLB : CompareVRRa<"veclb", 0xE7D9, null_frag, v128b, 0>;
def VECLH : CompareVRRa<"veclh", 0xE7D9, null_frag, v128h, 1>;
def VECLF : CompareVRRa<"veclf", 0xE7D9, null_frag, v128f, 2>;
def VECLG : CompareVRRa<"veclg", 0xE7D9, null_frag, v128g, 3>;
}
// Compare equal.
defm VCEQB : BinaryVRRbSPair<"vceqb", 0xE7F8, null_frag, null_frag,
v128b, v128b, 0>;
defm VCEQH : BinaryVRRbSPair<"vceqh", 0xE7F8, null_frag, null_frag,
v128h, v128h, 1>;
defm VCEQF : BinaryVRRbSPair<"vceqf", 0xE7F8, null_frag, null_frag,
v128f, v128f, 2>;
defm VCEQG : BinaryVRRbSPair<"vceqg", 0xE7F8, null_frag, null_frag,
v128g, v128g, 3>;
// Compare high.
defm VCHB : BinaryVRRbSPair<"vchb", 0xE7FB, null_frag, null_frag,
v128b, v128b, 0>;
defm VCHH : BinaryVRRbSPair<"vchh", 0xE7FB, null_frag, null_frag,
v128h, v128h, 1>;
defm VCHF : BinaryVRRbSPair<"vchf", 0xE7FB, null_frag, null_frag,
v128f, v128f, 2>;
defm VCHG : BinaryVRRbSPair<"vchg", 0xE7FB, null_frag, null_frag,
v128g, v128g, 3>;
// Compare high logical.
defm VCHLB : BinaryVRRbSPair<"vchlb", 0xE7F9, null_frag, null_frag,
v128b, v128b, 0>;
defm VCHLH : BinaryVRRbSPair<"vchlh", 0xE7F9, null_frag, null_frag,
v128h, v128h, 1>;
defm VCHLF : BinaryVRRbSPair<"vchlf", 0xE7F9, null_frag, null_frag,
v128f, v128f, 2>;
defm VCHLG : BinaryVRRbSPair<"vchlg", 0xE7F9, null_frag, null_frag,
v128g, v128g, 3>;
// Test under mask.
let Defs = [CC] in
def VTM : CompareVRRa<"vtm", 0xE7D8, null_frag, v128any, 0>;
}
//===----------------------------------------------------------------------===//
// Floating-point arithmetic
//===----------------------------------------------------------------------===//
let Predicates = [FeatureVector] in {
// Add.
def VFADB : BinaryVRRc<"vfadb", 0xE7E3, null_frag, v128db, v128db, 3, 0>;
def WFADB : BinaryVRRc<"wfadb", 0xE7E3, null_frag, v64db, v64db, 3, 8>;
// Convert from fixed 64-bit.
def VCDGB : TernaryVRRa<"vcdgb", 0xE7C3, null_frag, v128db, v128g, 3, 0>;
def WCDGB : TernaryVRRa<"wcdgb", 0xE7C3, null_frag, v64db, v64g, 3, 8>;
// Convert from logical 64-bit.
def VCDLGB : TernaryVRRa<"vcdlgb", 0xE7C1, null_frag, v128db, v128g, 3, 0>;
def WCDLGB : TernaryVRRa<"wcdlgb", 0xE7C1, null_frag, v64db, v64g, 3, 8>;
// Convert to fixed 64-bit.
def VCGDB : TernaryVRRa<"vcgdb", 0xE7C2, null_frag, v128g, v128db, 3, 0>;
def WCGDB : TernaryVRRa<"wcgdb", 0xE7C2, null_frag, v64g, v64db, 3, 8>;
// Convert to logical 64-bit.
def VCLGDB : TernaryVRRa<"vclgdb", 0xE7C0, null_frag, v128g, v128db, 3, 0>;
def WCLGDB : TernaryVRRa<"wclgdb", 0xE7C0, null_frag, v64g, v64db, 3, 8>;
// Divide.
def VFDDB : BinaryVRRc<"vfddb", 0xE7E5, null_frag, v128db, v128db, 3, 0>;
def WFDDB : BinaryVRRc<"wfddb", 0xE7E5, null_frag, v64db, v64db, 3, 8>;
// Load FP integer.
def VFIDB : TernaryVRRa<"vfidb", 0xE7C7, null_frag, v128db, v128db, 3, 0>;
def WFIDB : TernaryVRRa<"wfidb", 0xE7C7, null_frag, v64db, v64db, 3, 8>;
// Load lengthened.
def VLDEB : UnaryVRRa<"vldeb", 0xE7C4, null_frag, v128db, v128eb, 2, 0>;
def WLDEB : UnaryVRRa<"wldeb", 0xE7C4, null_frag, v64db, v32eb, 2, 8>;
// Load rounded,
def VLEDB : TernaryVRRa<"vledb", 0xE7C5, null_frag, v128eb, v128db, 3, 0>;
def WLEDB : TernaryVRRa<"wledb", 0xE7C5, null_frag, v32eb, v64db, 3, 8>;
// Multiply.
def VFMDB : BinaryVRRc<"vfmdb", 0xE7E7, null_frag, v128db, v128db, 3, 0>;
def WFMDB : BinaryVRRc<"wfmdb", 0xE7E7, null_frag, v64db, v64db, 3, 8>;
// Multiply and add.
def VFMADB : TernaryVRRe<"vfmadb", 0xE78F, null_frag, v128db, v128db, 0, 3>;
def WFMADB : TernaryVRRe<"wfmadb", 0xE78F, null_frag, v64db, v64db, 8, 3>;
// Multiply and subtract.
def VFMSDB : TernaryVRRe<"vfmsdb", 0xE78E, null_frag, v128db, v128db, 0, 3>;
def WFMSDB : TernaryVRRe<"wfmsdb", 0xE78E, null_frag, v64db, v64db, 8, 3>;
// Load complement,
def VFLCDB : UnaryVRRa<"vflcdb", 0xE7CC, null_frag, v128db, v128db, 3, 0, 0>;
def WFLCDB : UnaryVRRa<"wflcdb", 0xE7CC, null_frag, v64db, v64db, 3, 8, 0>;
// Load negative.
def VFLNDB : UnaryVRRa<"vflndb", 0xE7CC, null_frag, v128db, v128db, 3, 0, 1>;
def WFLNDB : UnaryVRRa<"wflndb", 0xE7CC, null_frag, v64db, v64db, 3, 8, 1>;
// Load positive.
def VFLPDB : UnaryVRRa<"vflpdb", 0xE7CC, null_frag, v128db, v128db, 3, 0, 2>;
def WFLPDB : UnaryVRRa<"wflpdb", 0xE7CC, null_frag, v64db, v64db, 3, 8, 2>;
// Square root.
def VFSQDB : UnaryVRRa<"vfsqdb", 0xE7CE, null_frag, v128db, v128db, 3, 0>;
def WFSQDB : UnaryVRRa<"wfsqdb", 0xE7CE, null_frag, v64db, v64db, 3, 8>;
// Subtract.
def VFSDB : BinaryVRRc<"vfsdb", 0xE7E2, null_frag, v128db, v128db, 3, 0>;
def WFSDB : BinaryVRRc<"wfsdb", 0xE7E2, null_frag, v64db, v64db, 3, 8>;
// Test data class immediate.
let Defs = [CC] in {
def VFTCIDB : BinaryVRIe<"vftcidb", 0xE74A, null_frag, v128g, v128db, 3, 0>;
def WFTCIDB : BinaryVRIe<"wftcidb", 0xE74A, null_frag, v64g, v64db, 3, 8>;
}
}
//===----------------------------------------------------------------------===//
// Floating-point comparison
//===----------------------------------------------------------------------===//
let Predicates = [FeatureVector] in {
// Compare scalar.
let Defs = [CC] in
def WFCDB : CompareVRRa<"wfcdb", 0xE7CB, null_frag, v64db, 3>;
// Compare and signal scalar.
let Defs = [CC] in
def WFKDB : CompareVRRa<"wfkdb", 0xE7CA, null_frag, v64db, 3>;
// Compare equal.
defm VFCEDB : BinaryVRRcSPair<"vfcedb", 0xE7E8, null_frag, null_frag,
v128g, v128db, 3, 0>;
defm WFCEDB : BinaryVRRcSPair<"wfcedb", 0xE7E8, null_frag, null_frag,
v64g, v64db, 3, 8>;
// Compare high.
defm VFCHDB : BinaryVRRcSPair<"vfchdb", 0xE7EB, null_frag, null_frag,
v128g, v128db, 3, 0>;
defm WFCHDB : BinaryVRRcSPair<"wfchdb", 0xE7EB, null_frag, null_frag,
v64g, v64db, 3, 8>;
// Compare high or equal.
defm VFCHEDB : BinaryVRRcSPair<"vfchedb", 0xE7EA, null_frag, null_frag,
v128g, v128db, 3, 0>;
defm WFCHEDB : BinaryVRRcSPair<"wfchedb", 0xE7EA, null_frag, null_frag,
v64g, v64db, 3, 8>;
}
//===----------------------------------------------------------------------===//
// String instructions
//===----------------------------------------------------------------------===//
let Predicates = [FeatureVector] in {
defm VFAEB : TernaryVRRbSPair<"vfaeb", 0xE782, null_frag, null_frag,
v128b, v128b, 0, 0>;
defm VFAEH : TernaryVRRbSPair<"vfaeh", 0xE782, null_frag, null_frag,
v128h, v128h, 1, 0>;
defm VFAEF : TernaryVRRbSPair<"vfaef", 0xE782, null_frag, null_frag,
v128f, v128f, 2, 0>;
defm VFAEZB : TernaryVRRbSPair<"vfaezb", 0xE782, null_frag, null_frag,
v128b, v128b, 0, 2>;
defm VFAEZH : TernaryVRRbSPair<"vfaezh", 0xE782, null_frag, null_frag,
v128h, v128h, 1, 2>;
defm VFAEZF : TernaryVRRbSPair<"vfaezf", 0xE782, null_frag, null_frag,
v128f, v128f, 2, 2>;
defm VFEEB : BinaryVRRbSPair<"vfeeb", 0xE780, null_frag, null_frag,
v128b, v128b, 0, 0, 1>;
defm VFEEH : BinaryVRRbSPair<"vfeeh", 0xE780, null_frag, null_frag,
v128h, v128h, 1, 0, 1>;
defm VFEEF : BinaryVRRbSPair<"vfeef", 0xE780, null_frag, null_frag,
v128f, v128f, 2, 0, 1>;
defm VFEEZB : BinaryVRRbSPair<"vfeezb", 0xE780, null_frag, null_frag,
v128b, v128b, 0, 2, 3>;
defm VFEEZH : BinaryVRRbSPair<"vfeezh", 0xE780, null_frag, null_frag,
v128h, v128h, 1, 2, 3>;
defm VFEEZF : BinaryVRRbSPair<"vfeezf", 0xE780, null_frag, null_frag,
v128f, v128f, 2, 2, 3>;
defm VFENEB : BinaryVRRbSPair<"vfeneb", 0xE781, null_frag, null_frag,
v128b, v128b, 0, 0, 1>;
defm VFENEH : BinaryVRRbSPair<"vfeneh", 0xE781, null_frag, null_frag,
v128h, v128h, 1, 0, 1>;
defm VFENEF : BinaryVRRbSPair<"vfenef", 0xE781, null_frag, null_frag,
v128f, v128f, 2, 0, 1>;
defm VFENEZB : BinaryVRRbSPair<"vfenezb", 0xE781, null_frag, null_frag,
v128b, v128b, 0, 2, 3>;
defm VFENEZH : BinaryVRRbSPair<"vfenezh", 0xE781, null_frag, null_frag,
v128h, v128h, 1, 2, 3>;
defm VFENEZF : BinaryVRRbSPair<"vfenezf", 0xE781, null_frag, null_frag,
v128f, v128f, 2, 2, 3>;
defm VISTRB : UnaryVRRaSPair<"vistrb", 0xE75C, null_frag, null_frag,
v128b, v128b, 0>;
defm VISTRH : UnaryVRRaSPair<"vistrh", 0xE75C, null_frag, null_frag,
v128h, v128h, 1>;
defm VISTRF : UnaryVRRaSPair<"vistrf", 0xE75C, null_frag, null_frag,
v128f, v128f, 2>;
defm VSTRCB : QuaternaryVRRdSPair<"vstrcb", 0xE78A, null_frag, null_frag,
v128b, v128b, 0, 0>;
defm VSTRCH : QuaternaryVRRdSPair<"vstrch", 0xE78A, null_frag, null_frag,
v128h, v128h, 1, 0>;
defm VSTRCF : QuaternaryVRRdSPair<"vstrcf", 0xE78A, null_frag, null_frag,
v128f, v128f, 2, 0>;
defm VSTRCZB : QuaternaryVRRdSPair<"vstrczb", 0xE78A, null_frag, null_frag,
v128b, v128b, 0, 2>;
defm VSTRCZH : QuaternaryVRRdSPair<"vstrczh", 0xE78A, null_frag, null_frag,
v128h, v128h, 1, 2>;
defm VSTRCZF : QuaternaryVRRdSPair<"vstrczf", 0xE78A, null_frag, null_frag,
v128f, v128f, 2, 2>;
}

View File

@ -78,6 +78,22 @@ class AddressAsmOperand<string format, string bitsize, string dispsize,
let RenderMethod = "add"##format##"Operands";
}
// Constructs an instruction operand for an addressing mode. FORMAT,
// BITSIZE, DISPSIZE and LENGTH are the parameters to an associated
// AddressAsmOperand. OPERANDS is a list of individual operands
// (base register, displacement, etc.).
class AddressOperand<string bitsize, string dispsize, string length,
string format, dag operands>
: Operand<!cast<ValueType>("i"##bitsize)> {
let PrintMethod = "print"##format##"Operand";
let EncoderMethod = "get"##format##dispsize##length##"Encoding";
let DecoderMethod =
"decode"##format##bitsize##"Disp"##dispsize##length##"Operand";
let MIOperandInfo = operands;
let ParserMatchClass =
!cast<AddressAsmOperand>(format##bitsize##"Disp"##dispsize##length);
}
// Constructs both a DAG pattern and instruction operand for an addressing mode.
// FORMAT, BITSIZE, DISPSIZE and LENGTH are the parameters to an associated
// AddressAsmOperand. OPERANDS is a list of NUMOPS individual operands
@ -93,15 +109,7 @@ class AddressingMode<string seltype, string bitsize, string dispsize,
: ComplexPattern<!cast<ValueType>("i"##bitsize), numops,
"select"##seltype##dispsize##suffix##length,
[add, sub, or, frameindex, z_adjdynalloc]>,
Operand<!cast<ValueType>("i"##bitsize)> {
let PrintMethod = "print"##format##"Operand";
let EncoderMethod = "get"##format##dispsize##length##"Encoding";
let DecoderMethod =
"decode"##format##bitsize##"Disp"##dispsize##length##"Operand";
let MIOperandInfo = operands;
let ParserMatchClass =
!cast<AddressAsmOperand>(format##bitsize##"Disp"##dispsize##length);
}
AddressOperand<bitsize, dispsize, length, format, operands>;
// An addressing mode with a base and displacement but no index.
class BDMode<string type, string bitsize, string dispsize, string suffix>
@ -125,6 +133,13 @@ class BDLMode<string type, string bitsize, string dispsize, string suffix,
!cast<Immediate>("disp"##dispsize##"imm"##bitsize),
!cast<Immediate>("imm"##bitsize))>;
// An addressing mode with a base, displacement and a vector index.
class BDVMode<string bitsize, string dispsize>
: AddressOperand<bitsize, dispsize, "", "BDVAddr",
(ops !cast<RegisterOperand>("ADDR"##bitsize),
!cast<Immediate>("disp"##dispsize##"imm"##bitsize),
!cast<RegisterOperand>("VR128"))>;
//===----------------------------------------------------------------------===//
// Extracting immediate operands from nodes
// These all create MVT::i64 nodes to ensure the value is not sign-extended
@ -179,6 +194,18 @@ def UIMM8 : SDNodeXForm<imm, [{
MVT::i64);
}]>;
// Truncate an immediate to a 8-bit unsigned quantity and mask off low bit.
def UIMM8EVEN : SDNodeXForm<imm, [{
return CurDAG->getTargetConstant(N->getZExtValue() & 0xfe, SDLoc(N),
MVT::i64);
}]>;
// Truncate an immediate to a 12-bit unsigned quantity.
def UIMM12 : SDNodeXForm<imm, [{
return CurDAG->getTargetConstant(N->getZExtValue() & 0xfff, SDLoc(N),
MVT::i64);
}]>;
// Truncate an immediate to a 16-bit signed quantity.
def SIMM16 : SDNodeXForm<imm, [{
return CurDAG->getTargetConstant(int16_t(N->getZExtValue()), SDLoc(N),
@ -213,10 +240,14 @@ def NEGIMM32 : SDNodeXForm<imm, [{
// Immediate asm operands.
//===----------------------------------------------------------------------===//
def U1Imm : ImmediateAsmOperand<"U1Imm">;
def U2Imm : ImmediateAsmOperand<"U2Imm">;
def U3Imm : ImmediateAsmOperand<"U3Imm">;
def U4Imm : ImmediateAsmOperand<"U4Imm">;
def U6Imm : ImmediateAsmOperand<"U6Imm">;
def S8Imm : ImmediateAsmOperand<"S8Imm">;
def U8Imm : ImmediateAsmOperand<"U8Imm">;
def U12Imm : ImmediateAsmOperand<"U12Imm">;
def S16Imm : ImmediateAsmOperand<"S16Imm">;
def U16Imm : ImmediateAsmOperand<"U16Imm">;
def S32Imm : ImmediateAsmOperand<"S32Imm">;
@ -247,10 +278,28 @@ def imm32lh16c : Immediate<i32, [{
}], LH16, "U16Imm">;
// Short immediates
def imm32zx1 : Immediate<i32, [{
return isUInt<1>(N->getZExtValue());
}], NOOP_SDNodeXForm, "U1Imm">;
def imm32zx2 : Immediate<i32, [{
return isUInt<2>(N->getZExtValue());
}], NOOP_SDNodeXForm, "U2Imm">;
def imm32zx3 : Immediate<i32, [{
return isUInt<3>(N->getZExtValue());
}], NOOP_SDNodeXForm, "U3Imm">;
def imm32zx4 : Immediate<i32, [{
return isUInt<4>(N->getZExtValue());
}], NOOP_SDNodeXForm, "U4Imm">;
// Note: this enforces an even value during code generation only.
// When used from the assembler, any 4-bit value is allowed.
def imm32zx4even : Immediate<i32, [{
return isUInt<4>(N->getZExtValue());
}], UIMM8EVEN, "U4Imm">;
def imm32zx6 : Immediate<i32, [{
return isUInt<6>(N->getZExtValue());
}], NOOP_SDNodeXForm, "U6Imm">;
@ -265,6 +314,10 @@ def imm32zx8 : Immediate<i32, [{
def imm32zx8trunc : Immediate<i32, [{}], UIMM8, "U8Imm">;
def imm32zx12 : Immediate<i32, [{
return isUInt<12>(N->getZExtValue());
}], UIMM12, "U12Imm">;
def imm32sx16 : Immediate<i32, [{
return isInt<16>(N->getSExtValue());
}], SIMM16, "S16Imm">;
@ -445,6 +498,7 @@ def BDAddr64Disp20 : AddressAsmOperand<"BDAddr", "64", "20">;
def BDXAddr64Disp12 : AddressAsmOperand<"BDXAddr", "64", "12">;
def BDXAddr64Disp20 : AddressAsmOperand<"BDXAddr", "64", "20">;
def BDLAddr64Disp12Len8 : AddressAsmOperand<"BDLAddr", "64", "12", "Len8">;
def BDVAddr64Disp12 : AddressAsmOperand<"BDVAddr", "64", "12">;
// DAG patterns and operands for addressing modes. Each mode has
// the form <type><range><group>[<len>] where:
@ -457,6 +511,7 @@ def BDLAddr64Disp12Len8 : AddressAsmOperand<"BDLAddr", "64", "12", "Len8">;
// laaddr : like bdxaddr, but used for Load Address operations
// dynalloc : base + displacement + index + ADJDYNALLOC
// bdladdr : base + displacement with a length field
// bdvaddr : base + displacement with a vector index
//
// <range> is one of:
// 12 : the displacement is an unsigned 12-bit value
@ -489,6 +544,7 @@ def dynalloc12only : BDXMode<"DynAlloc", "64", "12", "Only">;
def laaddr12pair : BDXMode<"LAAddr", "64", "12", "Pair">;
def laaddr20pair : BDXMode<"LAAddr", "64", "20", "Pair">;
def bdladdr12onlylen8 : BDLMode<"BDLAddr", "64", "12", "Only", "8">;
def bdvaddr12only : BDVMode< "64", "12">;
//===----------------------------------------------------------------------===//
// Miscellaneous

View File

@ -70,6 +70,12 @@ def FeatureProcessorAssist : SystemZFeature<
"Assume that the processor-assist facility is installed"
>;
def FeatureVector : SystemZFeature<
"vector", "Vector",
"Assume that the vectory facility is installed"
>;
def FeatureNoVector : SystemZMissingFeature<"Vector">;
def : Processor<"generic", NoItineraries, []>;
def : Processor<"z10", NoItineraries, []>;
def : Processor<"z196", NoItineraries,
@ -82,3 +88,9 @@ def : Processor<"zEC12", NoItineraries,
FeatureFastSerialization, FeatureInterlockedAccess1,
FeatureMiscellaneousExtensions,
FeatureTransactionalExecution, FeatureProcessorAssist]>;
def : Processor<"z13", NoItineraries,
[FeatureDistinctOps, FeatureLoadStoreOnCond, FeatureHighWord,
FeatureFPExtension, FeaturePopulationCount,
FeatureFastSerialization, FeatureInterlockedAccess1,
FeatureTransactionalExecution, FeatureProcessorAssist,
FeatureVector]>;

View File

@ -26,21 +26,23 @@ def subreg_h32 : SubRegIndex<32, 32>; // Also acts as subreg_lh32.
def subreg_l64 : SubRegIndex<64, 0>;
def subreg_h64 : SubRegIndex<64, 64>;
def subreg_r32 : SubRegIndex<32, 32>; // Reinterpret a wider reg as 32 bits.
def subreg_r64 : SubRegIndex<64, 64>; // Reinterpret a wider reg as 64 bits.
def subreg_hh32 : ComposedSubRegIndex<subreg_h64, subreg_h32>;
def subreg_hl32 : ComposedSubRegIndex<subreg_h64, subreg_l32>;
def subreg_hr32 : ComposedSubRegIndex<subreg_h64, subreg_r32>;
}
// Define a register class that contains values of type TYPE and an
// Define a register class that contains values of types TYPES and an
// associated operand called NAME. SIZE is the size and alignment
// of the registers and REGLIST is the list of individual registers.
multiclass SystemZRegClass<string name, ValueType type, int size, dag regList> {
multiclass SystemZRegClass<string name, list<ValueType> types, int size,
dag regList> {
def AsmOperand : AsmOperandClass {
let Name = name;
let ParserMethod = "parse"##name;
let RenderMethod = "addRegOperands";
}
def Bit : RegisterClass<"SystemZ", [type], size, regList> {
def Bit : RegisterClass<"SystemZ", types, size, regList> {
let Size = size;
}
def "" : RegisterOperand<!cast<RegisterClass>(name##"Bit")> {
@ -86,16 +88,19 @@ foreach I = [0, 2, 4, 6, 8, 10, 12, 14] in {
/// Allocate the callee-saved R6-R13 backwards. That way they can be saved
/// together with R14 and R15 in one prolog instruction.
defm GR32 : SystemZRegClass<"GR32", i32, 32, (add (sequence "R%uL", 0, 5),
(sequence "R%uL", 15, 6))>;
defm GRH32 : SystemZRegClass<"GRH32", i32, 32, (add (sequence "R%uH", 0, 5),
(sequence "R%uH", 15, 6))>;
defm GR64 : SystemZRegClass<"GR64", i64, 64, (add (sequence "R%uD", 0, 5),
(sequence "R%uD", 15, 6))>;
defm GR32 : SystemZRegClass<"GR32", [i32], 32,
(add (sequence "R%uL", 0, 5),
(sequence "R%uL", 15, 6))>;
defm GRH32 : SystemZRegClass<"GRH32", [i32], 32,
(add (sequence "R%uH", 0, 5),
(sequence "R%uH", 15, 6))>;
defm GR64 : SystemZRegClass<"GR64", [i64], 64,
(add (sequence "R%uD", 0, 5),
(sequence "R%uD", 15, 6))>;
// Combine the low and high GR32s into a single class. This can only be
// used for virtual registers if the high-word facility is available.
defm GRX32 : SystemZRegClass<"GRX32", i32, 32,
defm GRX32 : SystemZRegClass<"GRX32", [i32], 32,
(add (sequence "R%uL", 0, 5),
(sequence "R%uH", 0, 5),
R15L, R15H, R14L, R14H, R13L, R13H,
@ -104,18 +109,17 @@ defm GRX32 : SystemZRegClass<"GRX32", i32, 32,
// The architecture doesn't really have any i128 support, so model the
// register pairs as untyped instead.
defm GR128 : SystemZRegClass<"GR128", untyped, 128, (add R0Q, R2Q, R4Q,
R12Q, R10Q, R8Q, R6Q,
R14Q)>;
defm GR128 : SystemZRegClass<"GR128", [untyped], 128,
(add R0Q, R2Q, R4Q, R12Q, R10Q, R8Q, R6Q, R14Q)>;
// Base and index registers. Everything except R0, which in an address
// context evaluates as 0.
defm ADDR32 : SystemZRegClass<"ADDR32", i32, 32, (sub GR32Bit, R0L)>;
defm ADDR64 : SystemZRegClass<"ADDR64", i64, 64, (sub GR64Bit, R0D)>;
defm ADDR32 : SystemZRegClass<"ADDR32", [i32], 32, (sub GR32Bit, R0L)>;
defm ADDR64 : SystemZRegClass<"ADDR64", [i64], 64, (sub GR64Bit, R0D)>;
// Not used directly, but needs to exist for ADDR32 and ADDR64 subregs
// of a GR128.
defm ADDR128 : SystemZRegClass<"ADDR128", untyped, 128, (sub GR128Bit, R0Q)>;
defm ADDR128 : SystemZRegClass<"ADDR128", [untyped], 128, (sub GR128Bit, R0Q)>;
//===----------------------------------------------------------------------===//
// Floating-point registers
@ -144,14 +148,34 @@ def F11Dwarf : DwarfMapping<29>;
def F13Dwarf : DwarfMapping<30>;
def F15Dwarf : DwarfMapping<31>;
// Lower 32 bits of one of the 16 64-bit floating-point registers
def F16Dwarf : DwarfMapping<68>;
def F18Dwarf : DwarfMapping<69>;
def F20Dwarf : DwarfMapping<70>;
def F22Dwarf : DwarfMapping<71>;
def F17Dwarf : DwarfMapping<72>;
def F19Dwarf : DwarfMapping<73>;
def F21Dwarf : DwarfMapping<74>;
def F23Dwarf : DwarfMapping<75>;
def F24Dwarf : DwarfMapping<76>;
def F26Dwarf : DwarfMapping<77>;
def F28Dwarf : DwarfMapping<78>;
def F30Dwarf : DwarfMapping<79>;
def F25Dwarf : DwarfMapping<80>;
def F27Dwarf : DwarfMapping<81>;
def F29Dwarf : DwarfMapping<82>;
def F31Dwarf : DwarfMapping<83>;
// Upper 32 bits of one of the floating-point registers
class FPR32<bits<16> num, string n> : SystemZReg<n> {
let HWEncoding = num;
}
// One of the 16 64-bit floating-point registers
class FPR64<bits<16> num, string n, FPR32 low>
: SystemZRegWithSubregs<n, [low]> {
// One of the floating-point registers.
class FPR64<bits<16> num, string n, FPR32 high>
: SystemZRegWithSubregs<n, [high]> {
let HWEncoding = num;
let SubRegIndices = [subreg_r32];
}
@ -163,12 +187,17 @@ class FPR128<bits<16> num, string n, FPR64 low, FPR64 high>
let SubRegIndices = [subreg_l64, subreg_h64];
}
// Floating-point registers
// Floating-point registers. Registers 16-31 require the vector facility.
foreach I = 0-15 in {
def F#I#S : FPR32<I, "f"#I>;
def F#I#D : FPR64<I, "f"#I, !cast<FPR32>("F"#I#"S")>,
DwarfRegNum<[!cast<DwarfMapping>("F"#I#"Dwarf").Id]>;
}
foreach I = 16-31 in {
def F#I#S : FPR32<I, "v"#I>;
def F#I#D : FPR64<I, "v"#I, !cast<FPR32>("F"#I#"S")>,
DwarfRegNum<[!cast<DwarfMapping>("F"#I#"Dwarf").Id]>;
}
foreach I = [0, 1, 4, 5, 8, 9, 12, 13] in {
def F#I#Q : FPR128<I, "f"#I, !cast<FPR64>("F"#!add(I, 2)#"D"),
@ -177,10 +206,74 @@ foreach I = [0, 1, 4, 5, 8, 9, 12, 13] in {
// There's no store-multiple instruction for FPRs, so we're not fussy
// about the order in which call-saved registers are allocated.
defm FP32 : SystemZRegClass<"FP32", f32, 32, (sequence "F%uS", 0, 15)>;
defm FP64 : SystemZRegClass<"FP64", f64, 64, (sequence "F%uD", 0, 15)>;
defm FP128 : SystemZRegClass<"FP128", f128, 128, (add F0Q, F1Q, F4Q, F5Q,
F8Q, F9Q, F12Q, F13Q)>;
defm FP32 : SystemZRegClass<"FP32", [f32], 32, (sequence "F%uS", 0, 15)>;
defm FP64 : SystemZRegClass<"FP64", [f64], 64, (sequence "F%uD", 0, 15)>;
defm FP128 : SystemZRegClass<"FP128", [f128], 128,
(add F0Q, F1Q, F4Q, F5Q, F8Q, F9Q, F12Q, F13Q)>;
//===----------------------------------------------------------------------===//
// Vector registers
//===----------------------------------------------------------------------===//
// A full 128-bit vector register, with an FPR64 as its high part.
class VR128<bits<16> num, string n, FPR64 high>
: SystemZRegWithSubregs<n, [high]> {
let HWEncoding = num;
let SubRegIndices = [subreg_r64];
}
// Full vector registers.
foreach I = 0-31 in {
def V#I : VR128<I, "v"#I, !cast<FPR64>("F"#I#"D")>,
DwarfRegNum<[!cast<DwarfMapping>("F"#I#"Dwarf").Id]>;
}
// Class used to store 32-bit values in the first element of a vector
// register. f32 scalars are used for the WLEDB and WLDEB instructions.
defm VR32 : SystemZRegClass<"VR32", [f32, v4i8, v2i16], 32,
(add (sequence "F%uS", 0, 7),
(sequence "F%uS", 16, 31),
(sequence "F%uS", 8, 15))>;
// Class used to store 64-bit values in the upper half of a vector register.
// The vector facility also includes scalar f64 instructions that operate
// on the full vector register set.
defm VR64 : SystemZRegClass<"VR64", [f64, v8i8, v4i16, v2i32, v2f32], 64,
(add (sequence "F%uD", 0, 7),
(sequence "F%uD", 16, 31),
(sequence "F%uD", 8, 15))>;
// The subset of vector registers that can be used for floating-point
// operations too.
defm VF128 : SystemZRegClass<"VF128",
[v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], 128,
(sequence "V%u", 0, 15)>;
// All vector registers.
defm VR128 : SystemZRegClass<"VR128",
[v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], 128,
(add (sequence "V%u", 0, 7),
(sequence "V%u", 16, 31),
(sequence "V%u", 8, 15))>;
// Attaches a ValueType to a register operand, to make the instruction
// definitions easier.
class TypedReg<ValueType vtin, RegisterOperand opin> {
ValueType vt = vtin;
RegisterOperand op = opin;
}
def v32eb : TypedReg<f32, VR32>;
def v64g : TypedReg<i64, VR64>;
def v64db : TypedReg<f64, VR64>;
def v128b : TypedReg<v16i8, VR128>;
def v128h : TypedReg<v8i16, VR128>;
def v128f : TypedReg<v4i32, VR128>;
def v128g : TypedReg<v2i64, VR128>;
def v128q : TypedReg<v16i8, VR128>;
def v128eb : TypedReg<v4f32, VR128>;
def v128db : TypedReg<v2f64, VR128>;
def v128any : TypedReg<untyped, VR128>;
//===----------------------------------------------------------------------===//
// Other registers

View File

@ -41,6 +41,7 @@ SystemZSubtarget::SystemZSubtarget(const std::string &TT,
HasPopulationCount(false), HasFastSerialization(false),
HasInterlockedAccess1(false), HasMiscellaneousExtensions(false),
HasTransactionalExecution(false), HasProcessorAssist(false),
HasVector(false),
TargetTriple(TT), InstrInfo(initializeSubtargetDependencies(CPU, FS)),
TLInfo(TM, *this), TSInfo(*TM.getDataLayout()), FrameLowering() {}

View File

@ -44,6 +44,7 @@ protected:
bool HasMiscellaneousExtensions;
bool HasTransactionalExecution;
bool HasProcessorAssist;
bool HasVector;
private:
Triple TargetTriple;
@ -110,6 +111,9 @@ public:
// Return true if the target has the processor-assist facility.
bool hasProcessorAssist() const { return HasProcessorAssist; }
// Return true if the target has the vector facility.
bool hasVector() const { return HasVector; }
// Return true if GV can be accessed using LARL for reloc model RM
// and code model CM.
bool isPC32DBLSymbol(const GlobalValue *GV, Reloc::Model RM,

View File

@ -0,0 +1,39 @@
# Test z13 instructions that don't have PC-relative operands.
# RUN: llvm-mc --disassemble %s -triple=s390x-linux-gnu -mcpu=z13 2>&1 \
# RUN: | FileCheck %s
# This would be "vlef %v0, 0, 4", but element 4 is invalid.
#
#CHECK: warning: invalid instruction encoding
#CHECK-NEXT: 0xe7 0x00 0x00 0x00 0x40 0x03
0xe7 0x00 0x00 0x00 0x40 0x03
# ...and again with element 15
#
#CHECK: warning: invalid instruction encoding
#CHECK-NEXT: 0xe7 0x00 0x00 0x00 0xf0 0x03
0xe7 0x00 0x00 0x00 0xf0 0x03
# This would be "vleg %v0, 0, 2", but element 2 is invalid.
#
#CHECK: warning: invalid instruction encoding
#CHECK-NEXT: 0xe7 0x00 0x00 0x00 0x20 0x02
0xe7 0x00 0x00 0x00 0x20 0x02
# ...and again with element 15
#
#CHECK: warning: invalid instruction encoding
#CHECK-NEXT: 0xe7 0x00 0x00 0x00 0xf0 0x02
0xe7 0x00 0x00 0x00 0xf0 0x02
# This would be "vleh %v0, 0, 8", but element 8 is invalid.
#
#CHECK: warning: invalid instruction encoding
#CHECK-NEXT: 0xe7 0x00 0x00 0x00 0x80 0x01
0xe7 0x00 0x00 0x00 0x80 0x01
# ...and again with element 15
#
#CHECK: warning: invalid instruction encoding
#CHECK-NEXT: 0xe7 0x00 0x00 0x00 0xf0 0x01
0xe7 0x00 0x00 0x00 0xf0 0x01

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -13,10 +13,16 @@
#CHECK: foo 100(200,%r0), 300
#CHECK: error: invalid instruction
#CHECK: foo 100(200,%r1), 300
#CHECK: error: invalid operand
#CHECK: error: invalid address register
#CHECK: foo 100(%a0), 200
#CHECK: error: %r0 used in an address
#CHECK: foo 100(%r0), 200
#CHECK: error: %r0 used in an address
#CHECK: foo 100(%v1,%r0), 200
#CHECK: error: invalid instruction
#CHECK: foo 100(%v0,%r1), 200
#CHECK: error: invalid instruction
#CHECK: foo 100(%v31), 200
#CHECK: error: invalid operand
#CHECK: foo 100(%r1,%a0), 200
#CHECK: error: %r0 used in an address
@ -45,6 +51,12 @@
#CHECK: foo %a15, 200
#CHECK: error: invalid register
#CHECK: foo %a16, 200
#CHECK: error: invalid instruction
#CHECK: foo %v0, 200
#CHECK: error: invalid instruction
#CHECK: foo %v31, 200
#CHECK: error: invalid register
#CHECK: foo %v32, 200
#CHECK: error: invalid register
#CHECK: foo %c, 200
#CHECK: error: invalid register
@ -60,6 +72,9 @@
foo 100(200,%r1), 300
foo 100(%a0), 200
foo 100(%r0), 200
foo 100(%v1,%r0), 200
foo 100(%v0,%r1), 200
foo 100(%v31), 200
foo 100(%r1,%a0), 200
foo 100(%r1,%r0), 200
foo 100(%r1,%r2, 200
@ -74,6 +89,9 @@
foo %a0, 200
foo %a15, 200
foo %a16, 200
foo %v0, 200
foo %v31, 200
foo %v32, 200
foo %c, 200
foo %, 200
foo {, 200