mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 12:12:47 +01:00
[Hexagon] Adding vector load with post-increment instructions. Adding decoder function for 64bit control register class.
llvm-svn: 228708
This commit is contained in:
parent
7f0e9478f6
commit
350f7188f4
@ -51,6 +51,8 @@ static DecodeStatus DecodeModRegsRegisterClass(MCInst &Inst, unsigned RegNo,
|
|||||||
uint64_t Address, const void *Decoder);
|
uint64_t Address, const void *Decoder);
|
||||||
static DecodeStatus DecodeCtrRegsRegisterClass(MCInst &Inst, unsigned RegNo,
|
static DecodeStatus DecodeCtrRegsRegisterClass(MCInst &Inst, unsigned RegNo,
|
||||||
uint64_t Address, const void *Decoder);
|
uint64_t Address, const void *Decoder);
|
||||||
|
static DecodeStatus DecodeCtrRegs64RegisterClass(MCInst &Inst, unsigned RegNo,
|
||||||
|
uint64_t Address, void const *Decoder);
|
||||||
|
|
||||||
static const uint16_t IntRegDecoderTable[] = {
|
static const uint16_t IntRegDecoderTable[] = {
|
||||||
Hexagon::R0, Hexagon::R1, Hexagon::R2, Hexagon::R3, Hexagon::R4,
|
Hexagon::R0, Hexagon::R1, Hexagon::R2, Hexagon::R3, Hexagon::R4,
|
||||||
@ -105,6 +107,30 @@ static DecodeStatus DecodeCtrRegsRegisterClass(MCInst &Inst, unsigned RegNo,
|
|||||||
return MCDisassembler::Success;
|
return MCDisassembler::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static DecodeStatus DecodeCtrRegs64RegisterClass(MCInst &Inst, unsigned RegNo,
|
||||||
|
uint64_t /*Address*/, void const *Decoder) {
|
||||||
|
static const uint16_t CtrlReg64DecoderTable[] = {
|
||||||
|
Hexagon::C1_0, Hexagon::NoRegister,
|
||||||
|
Hexagon::C3_2, Hexagon::NoRegister,
|
||||||
|
Hexagon::NoRegister, Hexagon::NoRegister,
|
||||||
|
Hexagon::C7_6, Hexagon::NoRegister,
|
||||||
|
Hexagon::C9_8, Hexagon::NoRegister,
|
||||||
|
Hexagon::C11_10, Hexagon::NoRegister,
|
||||||
|
Hexagon::CS, Hexagon::NoRegister,
|
||||||
|
Hexagon::UPC, Hexagon::NoRegister
|
||||||
|
};
|
||||||
|
|
||||||
|
if (RegNo >= sizeof(CtrlReg64DecoderTable) / sizeof(CtrlReg64DecoderTable[0]))
|
||||||
|
return MCDisassembler::Fail;
|
||||||
|
|
||||||
|
if (CtrlReg64DecoderTable[RegNo] == Hexagon::NoRegister)
|
||||||
|
return MCDisassembler::Fail;
|
||||||
|
|
||||||
|
unsigned Register = CtrlReg64DecoderTable[RegNo];
|
||||||
|
Inst.addOperand(MCOperand::CreateReg(Register));
|
||||||
|
return MCDisassembler::Success;
|
||||||
|
}
|
||||||
|
|
||||||
static DecodeStatus DecodeModRegsRegisterClass(MCInst &Inst, unsigned RegNo,
|
static DecodeStatus DecodeModRegsRegisterClass(MCInst &Inst, unsigned RegNo,
|
||||||
uint64_t /*Address*/, const void *Decoder) {
|
uint64_t /*Address*/, const void *Decoder) {
|
||||||
unsigned Register = 0;
|
unsigned Register = 0;
|
||||||
|
@ -1707,6 +1707,37 @@ let accessSize = WordAccess, opExtentAlign = 2 in {
|
|||||||
def L2_loadbsw4_io: T_load_io<"membh", DoubleRegs, 0b0111, s11_2Ext>;
|
def L2_loadbsw4_io: T_load_io<"membh", DoubleRegs, 0b0111, s11_2Ext>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let addrMode = BaseImmOffset, isExtendable = 1, hasSideEffects = 0,
|
||||||
|
opExtendable = 3, isExtentSigned = 1 in
|
||||||
|
class T_loadalign_io <string str, bits<4> MajOp, Operand ImmOp>
|
||||||
|
: LDInst<(outs DoubleRegs:$dst),
|
||||||
|
(ins DoubleRegs:$src1, IntRegs:$src2, ImmOp:$offset),
|
||||||
|
"$dst = "#str#"($src2 + #$offset)", [],
|
||||||
|
"$src1 = $dst">, AddrModeRel {
|
||||||
|
bits<4> name;
|
||||||
|
bits<5> dst;
|
||||||
|
bits<5> src2;
|
||||||
|
bits<12> offset;
|
||||||
|
bits<11> offsetBits;
|
||||||
|
|
||||||
|
let offsetBits = !if (!eq(!cast<string>(ImmOp), "s11_1Ext"), offset{11-1},
|
||||||
|
/* s11_0Ext */ offset{10-0});
|
||||||
|
let IClass = 0b1001;
|
||||||
|
|
||||||
|
let Inst{27} = 0b0;
|
||||||
|
let Inst{26-25} = offsetBits{10-9};
|
||||||
|
let Inst{24-21} = MajOp;
|
||||||
|
let Inst{20-16} = src2;
|
||||||
|
let Inst{13-5} = offsetBits{8-0};
|
||||||
|
let Inst{4-0} = dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
let accessSize = HalfWordAccess, opExtentBits = 12, opExtentAlign = 1 in
|
||||||
|
def L2_loadalignh_io: T_loadalign_io <"memh_fifo", 0b0010, s11_1Ext>;
|
||||||
|
|
||||||
|
let accessSize = ByteAccess, opExtentBits = 11 in
|
||||||
|
def L2_loadalignb_io: T_loadalign_io <"memb_fifo", 0b0100, s11_0Ext>;
|
||||||
|
|
||||||
// Patterns to select load-indexed (i.e. load from base+offset).
|
// Patterns to select load-indexed (i.e. load from base+offset).
|
||||||
multiclass Loadx_pat<PatFrag Load, ValueType VT, PatLeaf ImmPred,
|
multiclass Loadx_pat<PatFrag Load, ValueType VT, PatLeaf ImmPred,
|
||||||
InstHexagon MI> {
|
InstHexagon MI> {
|
||||||
@ -1872,6 +1903,41 @@ let accessSize = WordAccess, opExtentAlign = 2, hasNewValue = 0 in {
|
|||||||
def L2_loadbzw4_pi : T_load_pi <"memubh", DoubleRegs, s4_2Imm, 0b0101>;
|
def L2_loadbzw4_pi : T_load_pi <"memubh", DoubleRegs, s4_2Imm, 0b0101>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Template class for post increment fifo loads with immediate offset.
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
let hasSideEffects = 0, addrMode = PostInc in
|
||||||
|
class T_loadalign_pi <string mnemonic, Operand ImmOp, bits<4> MajOp >
|
||||||
|
: LDInstPI <(outs DoubleRegs:$dst, IntRegs:$dst2),
|
||||||
|
(ins DoubleRegs:$src1, IntRegs:$src2, ImmOp:$offset),
|
||||||
|
"$dst = "#mnemonic#"($src2++#$offset)" ,
|
||||||
|
[], "$src2 = $dst2, $src1 = $dst" > ,
|
||||||
|
PredNewRel {
|
||||||
|
bits<5> dst;
|
||||||
|
bits<5> src2;
|
||||||
|
bits<5> offset;
|
||||||
|
bits<4> offsetBits;
|
||||||
|
|
||||||
|
let offsetBits = !if (!eq(!cast<string>(ImmOp), "s4_1Imm"), offset{4-1},
|
||||||
|
/* s4_0Imm */ offset{3-0});
|
||||||
|
let IClass = 0b1001;
|
||||||
|
|
||||||
|
let Inst{27-25} = 0b101;
|
||||||
|
let Inst{24-21} = MajOp;
|
||||||
|
let Inst{20-16} = src2;
|
||||||
|
let Inst{13-12} = 0b00;
|
||||||
|
let Inst{8-5} = offsetBits;
|
||||||
|
let Inst{4-0} = dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ryy=memh_fifo(Rx++#s4:1)
|
||||||
|
// Ryy=memb_fifo(Rx++#s4:0)
|
||||||
|
let accessSize = ByteAccess in
|
||||||
|
def L2_loadalignb_pi : T_loadalign_pi <"memb_fifo", s4_0Imm, 0b0100>;
|
||||||
|
|
||||||
|
let accessSize = HalfWordAccess, opExtentAlign = 1 in
|
||||||
|
def L2_loadalignh_pi : T_loadalign_pi <"memh_fifo", s4_1Imm, 0b0010>;
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Template class for post increment loads with register offset.
|
// Template class for post increment loads with register offset.
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
@ -1976,6 +2042,33 @@ let accessSize = WordAccess in {
|
|||||||
let accessSize = DoubleWordAccess in
|
let accessSize = DoubleWordAccess in
|
||||||
def L2_loadrd_pcr : T_load_pcr <"memd", DoubleRegs, 0b1110>;
|
def L2_loadrd_pcr : T_load_pcr <"memd", DoubleRegs, 0b1110>;
|
||||||
|
|
||||||
|
// Load / Post increment circular addressing mode.
|
||||||
|
let Uses = [CS], hasSideEffects = 0 in
|
||||||
|
class T_loadalign_pcr<string mnemonic, bits<4> MajOp, MemAccessSize AccessSz >
|
||||||
|
: LDInst <(outs DoubleRegs:$dst, IntRegs:$_dst_),
|
||||||
|
(ins DoubleRegs:$_src_, IntRegs:$Rz, ModRegs:$Mu),
|
||||||
|
"$dst = "#mnemonic#"($Rz ++ I:circ($Mu))", [],
|
||||||
|
"$Rz = $_dst_, $dst = $_src_" > {
|
||||||
|
bits<5> dst;
|
||||||
|
bits<5> Rz;
|
||||||
|
bit Mu;
|
||||||
|
|
||||||
|
let accessSize = AccessSz;
|
||||||
|
let IClass = 0b1001;
|
||||||
|
|
||||||
|
let Inst{27-25} = 0b100;
|
||||||
|
let Inst{24-21} = MajOp;
|
||||||
|
let Inst{20-16} = Rz;
|
||||||
|
let Inst{13} = Mu;
|
||||||
|
let Inst{12} = 0b0;
|
||||||
|
let Inst{9} = 0b1;
|
||||||
|
let Inst{7} = 0b0;
|
||||||
|
let Inst{4-0} = dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
def L2_loadalignb_pcr : T_loadalign_pcr <"memb_fifo", 0b0100, ByteAccess>;
|
||||||
|
def L2_loadalignh_pcr : T_loadalign_pcr <"memh_fifo", 0b0010, HalfWordAccess>;
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Circular loads with immediate offset.
|
// Circular loads with immediate offset.
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
@ -2035,6 +2128,37 @@ let accessSize = WordAccess, hasNewValue = 0 in {
|
|||||||
let accessSize = DoubleWordAccess, hasNewValue = 0 in
|
let accessSize = DoubleWordAccess, hasNewValue = 0 in
|
||||||
def L2_loadrd_pci : T_load_pci <"memd", DoubleRegs, s4_3Imm, 0b1110>;
|
def L2_loadrd_pci : T_load_pci <"memd", DoubleRegs, s4_3Imm, 0b1110>;
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Circular loads - Pseudo
|
||||||
|
//
|
||||||
|
// Please note that the input operand order in the pseudo instructions
|
||||||
|
// doesn't match with the real instructions. Pseudo instructions operand
|
||||||
|
// order should mimics the ordering in the intrinsics. Also, 'src2' doesn't
|
||||||
|
// appear in the AsmString because it's same as 'dst'.
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
let isCodeGenOnly = 1, mayLoad = 1, hasSideEffects = 0, isPseudo = 1 in
|
||||||
|
class T_load_pci_pseudo <string opc, RegisterClass RC>
|
||||||
|
: LDInstPI<(outs IntRegs:$_dst_, RC:$dst),
|
||||||
|
(ins IntRegs:$src1, IntRegs:$src2, IntRegs:$src3, s4Imm:$src4),
|
||||||
|
".error \"$dst = "#opc#"($src1++#$src4:circ($src3))\"",
|
||||||
|
[], "$src1 = $_dst_">;
|
||||||
|
|
||||||
|
def L2_loadrb_pci_pseudo : T_load_pci_pseudo <"memb", IntRegs>;
|
||||||
|
def L2_loadrub_pci_pseudo : T_load_pci_pseudo <"memub", IntRegs>;
|
||||||
|
def L2_loadrh_pci_pseudo : T_load_pci_pseudo <"memh", IntRegs>;
|
||||||
|
def L2_loadruh_pci_pseudo : T_load_pci_pseudo <"memuh", IntRegs>;
|
||||||
|
def L2_loadri_pci_pseudo : T_load_pci_pseudo <"memw", IntRegs>;
|
||||||
|
def L2_loadrd_pci_pseudo : T_load_pci_pseudo <"memd", DoubleRegs>;
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: memb_fifo and memh_fifo must take destination register as input.
|
||||||
|
// One-off circ loads - not enough in common to break into a class.
|
||||||
|
let accessSize = ByteAccess in
|
||||||
|
def L2_loadalignb_pci : T_load_pci <"memb_fifo", DoubleRegs, s4_0Imm, 0b0100>;
|
||||||
|
|
||||||
|
let accessSize = HalfWordAccess, opExtentAlign = 1 in
|
||||||
|
def L2_loadalignh_pci : T_load_pci <"memh_fifo", DoubleRegs, s4_1Imm, 0b0010>;
|
||||||
|
|
||||||
// L[24]_load[wd]_locked: Load word/double with lock.
|
// L[24]_load[wd]_locked: Load word/double with lock.
|
||||||
let isSoloAX = 1 in
|
let isSoloAX = 1 in
|
||||||
class T_load_locked <string mnemonic, RegisterClass RC>
|
class T_load_locked <string mnemonic, RegisterClass RC>
|
||||||
@ -2122,6 +2246,30 @@ def L2_loadbzw4_pbr : T_load_pbr <"memubh", DoubleRegs, WordAccess, 0b0101>;
|
|||||||
def L2_loadbsw4_pbr : T_load_pbr <"membh", DoubleRegs, WordAccess, 0b0111>;
|
def L2_loadbsw4_pbr : T_load_pbr <"membh", DoubleRegs, WordAccess, 0b0111>;
|
||||||
def L2_loadrd_pbr : T_load_pbr <"memd", DoubleRegs, DoubleWordAccess, 0b1110>;
|
def L2_loadrd_pbr : T_load_pbr <"memd", DoubleRegs, DoubleWordAccess, 0b1110>;
|
||||||
|
|
||||||
|
def L2_loadalignb_pbr :T_load_pbr <"memb_fifo", DoubleRegs, ByteAccess, 0b0100>;
|
||||||
|
def L2_loadalignh_pbr :T_load_pbr <"memh_fifo", DoubleRegs,
|
||||||
|
HalfWordAccess, 0b0010>;
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Bit-reversed loads - Pseudo
|
||||||
|
//
|
||||||
|
// Please note that 'src2' doesn't appear in the AsmString because
|
||||||
|
// it's same as 'dst'.
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
let isCodeGenOnly = 1, mayLoad = 1, hasSideEffects = 0, isPseudo = 1 in
|
||||||
|
class T_load_pbr_pseudo <string opc, RegisterClass RC>
|
||||||
|
: LDInstPI<(outs IntRegs:$_dst_, RC:$dst),
|
||||||
|
(ins IntRegs:$src1, IntRegs:$src2, IntRegs:$src3),
|
||||||
|
".error \"$dst = "#opc#"($src1++$src3:brev)\"",
|
||||||
|
[], "$src1 = $_dst_">;
|
||||||
|
|
||||||
|
def L2_loadrb_pbr_pseudo : T_load_pbr_pseudo <"memb", IntRegs>;
|
||||||
|
def L2_loadrub_pbr_pseudo : T_load_pbr_pseudo <"memub", IntRegs>;
|
||||||
|
def L2_loadrh_pbr_pseudo : T_load_pbr_pseudo <"memh", IntRegs>;
|
||||||
|
def L2_loadruh_pbr_pseudo : T_load_pbr_pseudo <"memuh", IntRegs>;
|
||||||
|
def L2_loadri_pbr_pseudo : T_load_pbr_pseudo <"memw", IntRegs>;
|
||||||
|
def L2_loadrd_pbr_pseudo : T_load_pbr_pseudo <"memd", DoubleRegs>;
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// LD -
|
// LD -
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
@ -3548,6 +3696,26 @@ def S2_storerbnew_pci : T_storenew_pci <"memb", s4_0Imm, 0b00, ByteAccess>;
|
|||||||
def S2_storerhnew_pci : T_storenew_pci <"memh", s4_1Imm, 0b01, HalfWordAccess>;
|
def S2_storerhnew_pci : T_storenew_pci <"memh", s4_1Imm, 0b01, HalfWordAccess>;
|
||||||
def S2_storerinew_pci : T_storenew_pci <"memw", s4_2Imm, 0b10, WordAccess>;
|
def S2_storerinew_pci : T_storenew_pci <"memw", s4_2Imm, 0b10, WordAccess>;
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Circular stores - Pseudo
|
||||||
|
//
|
||||||
|
// Please note that the input operand order in the pseudo instructions
|
||||||
|
// doesn't match with the real instructions. Pseudo instructions operand
|
||||||
|
// order should mimics the ordering in the intrinsics.
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
let isCodeGenOnly = 1, mayStore = 1, hasSideEffects = 0, isPseudo = 1 in
|
||||||
|
class T_store_pci_pseudo <string opc, RegisterClass RC>
|
||||||
|
: STInstPI<(outs IntRegs:$_dst_),
|
||||||
|
(ins IntRegs:$src1, RC:$src2, IntRegs:$src3, s4Imm:$src4),
|
||||||
|
".error \""#opc#"($src1++#$src4:circ($src3)) = $src2\"",
|
||||||
|
[], "$_dst_ = $src1">;
|
||||||
|
|
||||||
|
def S2_storerb_pci_pseudo : T_store_pci_pseudo <"memb", IntRegs>;
|
||||||
|
def S2_storerh_pci_pseudo : T_store_pci_pseudo <"memh", IntRegs>;
|
||||||
|
def S2_storerf_pci_pseudo : T_store_pci_pseudo <"memh", IntRegs>;
|
||||||
|
def S2_storeri_pci_pseudo : T_store_pci_pseudo <"memw", IntRegs>;
|
||||||
|
def S2_storerd_pci_pseudo : T_store_pci_pseudo <"memd", DoubleRegs>;
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Circular stores with auto-increment register
|
// Circular stores with auto-increment register
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
@ -3691,6 +3859,26 @@ def S2_storerhnew_pbr : T_storenew_pbr<"memh", HalfWordAccess, 0b01>;
|
|||||||
let BaseOpcode = "S2_storeri_pbr" in
|
let BaseOpcode = "S2_storeri_pbr" in
|
||||||
def S2_storerinew_pbr : T_storenew_pbr<"memw", WordAccess, 0b10>;
|
def S2_storerinew_pbr : T_storenew_pbr<"memw", WordAccess, 0b10>;
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Bit-reversed stores - Pseudo
|
||||||
|
//
|
||||||
|
// Please note that the input operand order in the pseudo instructions
|
||||||
|
// doesn't match with the real instructions. Pseudo instructions operand
|
||||||
|
// order should mimics the ordering in the intrinsics.
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
let isCodeGenOnly = 1, mayStore = 1, hasSideEffects = 0, isPseudo = 1 in
|
||||||
|
class T_store_pbr_pseudo <string opc, RegisterClass RC>
|
||||||
|
: STInstPI<(outs IntRegs:$_dst_),
|
||||||
|
(ins IntRegs:$src1, RC:$src2, IntRegs:$src3),
|
||||||
|
".error \""#opc#"($src1++$src3:brev) = $src2\"",
|
||||||
|
[], "$_dst_ = $src1">;
|
||||||
|
|
||||||
|
def S2_storerb_pbr_pseudo : T_store_pbr_pseudo <"memb", IntRegs>;
|
||||||
|
def S2_storerh_pbr_pseudo : T_store_pbr_pseudo <"memh", IntRegs>;
|
||||||
|
def S2_storeri_pbr_pseudo : T_store_pbr_pseudo <"memw", IntRegs>;
|
||||||
|
def S2_storerf_pbr_pseudo : T_store_pbr_pseudo <"memh", IntRegs>;
|
||||||
|
def S2_storerd_pbr_pseudo : T_store_pbr_pseudo <"memd", DoubleRegs>;
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// ST -
|
// ST -
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
@ -3870,6 +4058,10 @@ def S2_asr_i_r_rnd_goodsyntax
|
|||||||
"$dst = asrrnd($src, #$u5)",
|
"$dst = asrrnd($src, #$u5)",
|
||||||
[], "", S_2op_tc_1_SLOT23>;
|
[], "", S_2op_tc_1_SLOT23>;
|
||||||
|
|
||||||
|
let isAsmParserOnly = 1 in
|
||||||
|
def A2_not: ALU32_rr<(outs IntRegs:$dst),(ins IntRegs:$src),
|
||||||
|
"$dst = not($src)">;
|
||||||
|
|
||||||
def: Pat<(i32 (sra (i32 (add (i32 (sra I32:$src1, u5ImmPred:$src2)),
|
def: Pat<(i32 (sra (i32 (add (i32 (sra I32:$src1, u5ImmPred:$src2)),
|
||||||
(i32 1))),
|
(i32 1))),
|
||||||
(i32 1))),
|
(i32 1))),
|
||||||
@ -3914,6 +4106,9 @@ def A2_vabshsat : T_S2op_3 <"vabsh", 0b01, 0b101, 1>;
|
|||||||
def A2_vabsw : T_S2op_3 <"vabsw", 0b01, 0b110>;
|
def A2_vabsw : T_S2op_3 <"vabsw", 0b01, 0b110>;
|
||||||
def A2_vabswsat : T_S2op_3 <"vabsw", 0b01, 0b111, 1>;
|
def A2_vabswsat : T_S2op_3 <"vabsw", 0b01, 0b111, 1>;
|
||||||
|
|
||||||
|
def : Pat<(not (i64 DoubleRegs:$src1)),
|
||||||
|
(A2_notp DoubleRegs:$src1)>;
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// STYPE/BIT +
|
// STYPE/BIT +
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
@ -4161,6 +4356,27 @@ def C2_tfrrp: SInst<(outs PredRegs:$Pd), (ins IntRegs:$Rs),
|
|||||||
let Inst{1-0} = Pd;
|
let Inst{1-0} = Pd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let hasSideEffects = 0, isCodeGenOnly = 1 in
|
||||||
|
def C2_pxfer_map: SInst<(outs PredRegs:$dst), (ins PredRegs:$src),
|
||||||
|
"$dst = $src">;
|
||||||
|
|
||||||
|
|
||||||
|
// Patterns for loads of i1:
|
||||||
|
def: Pat<(i1 (load AddrFI:$fi)),
|
||||||
|
(C2_tfrrp (L2_loadrub_io AddrFI:$fi, 0))>;
|
||||||
|
def: Pat<(i1 (load (add (i32 IntRegs:$Rs), s11_0ExtPred:$Off))),
|
||||||
|
(C2_tfrrp (L2_loadrub_io IntRegs:$Rs, imm:$Off))>;
|
||||||
|
def: Pat<(i1 (load (i32 IntRegs:$Rs))),
|
||||||
|
(C2_tfrrp (L2_loadrub_io IntRegs:$Rs, 0))>;
|
||||||
|
|
||||||
|
def I1toI32: OutPatFrag<(ops node:$Rs),
|
||||||
|
(C2_muxii (i1 $Rs), 1, 0)>;
|
||||||
|
|
||||||
|
def I32toI1: OutPatFrag<(ops node:$Rs),
|
||||||
|
(i1 (C2_tfrrp (i32 $Rs)))>;
|
||||||
|
|
||||||
|
defm: Storexm_pat<store, I1, s11_0ExtPred, I1toI32, S2_storerb_io>;
|
||||||
|
def: Storexm_simple_pat<store, I1, I1toI32, S2_storerb_io>;
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// STYPE/PRED -
|
// STYPE/PRED -
|
||||||
@ -4423,6 +4639,7 @@ class TFR_CR_RS_base<RegisterClass CTRC, RegisterClass RC, bit isDouble>
|
|||||||
}
|
}
|
||||||
|
|
||||||
def A2_tfrrcr : TFR_CR_RS_base<CtrRegs, IntRegs, 0b0>;
|
def A2_tfrrcr : TFR_CR_RS_base<CtrRegs, IntRegs, 0b0>;
|
||||||
|
def A4_tfrpcp : TFR_CR_RS_base<CtrRegs64, DoubleRegs, 0b1>;
|
||||||
def : InstAlias<"m0 = $Rs", (A2_tfrrcr C6, IntRegs:$Rs)>;
|
def : InstAlias<"m0 = $Rs", (A2_tfrrcr C6, IntRegs:$Rs)>;
|
||||||
def : InstAlias<"m1 = $Rs", (A2_tfrrcr C7, IntRegs:$Rs)>;
|
def : InstAlias<"m1 = $Rs", (A2_tfrrcr C7, IntRegs:$Rs)>;
|
||||||
|
|
||||||
@ -4444,6 +4661,7 @@ class TFR_RD_CR_base<RegisterClass RC, RegisterClass CTRC, bit isSingle>
|
|||||||
|
|
||||||
let hasNewValue = 1, opNewValue = 0 in
|
let hasNewValue = 1, opNewValue = 0 in
|
||||||
def A2_tfrcrr : TFR_RD_CR_base<IntRegs, CtrRegs, 1>;
|
def A2_tfrcrr : TFR_RD_CR_base<IntRegs, CtrRegs, 1>;
|
||||||
|
def A4_tfrcpp : TFR_RD_CR_base<DoubleRegs, CtrRegs64, 0>;
|
||||||
def : InstAlias<"$Rd = m0", (A2_tfrcrr IntRegs:$Rd, C6)>;
|
def : InstAlias<"$Rd = m0", (A2_tfrcrr IntRegs:$Rd, C6)>;
|
||||||
def : InstAlias<"$Rd = m1", (A2_tfrcrr IntRegs:$Rd, C7)>;
|
def : InstAlias<"$Rd = m1", (A2_tfrcrr IntRegs:$Rd, C7)>;
|
||||||
|
|
||||||
@ -4603,9 +4821,14 @@ def CONST64_Int_Real : CONSTLDInst<(outs DoubleRegs:$dst), (ins i64imm:$global),
|
|||||||
"$dst = CONST64(#$global)",
|
"$dst = CONST64(#$global)",
|
||||||
[(set (i64 DoubleRegs:$dst), imm:$global)]>;
|
[(set (i64 DoubleRegs:$dst), imm:$global)]>;
|
||||||
|
|
||||||
let isCodeGenOnly = 1 in
|
let hasSideEffects = 0, isReMaterializable = 1, isPseudo = 1,
|
||||||
def TFR_PdFalse : SInst<(outs PredRegs:$dst), (ins),
|
isCodeGenOnly = 1 in
|
||||||
"$dst = xor($dst, $dst)",
|
def TFR_PdTrue : SInst<(outs PredRegs:$dst), (ins), "",
|
||||||
|
[(set (i1 PredRegs:$dst), 1)]>;
|
||||||
|
|
||||||
|
let hasSideEffects = 0, isReMaterializable = 1, isPseudo = 1,
|
||||||
|
isCodeGenOnly = 1 in
|
||||||
|
def TFR_PdFalse : SInst<(outs PredRegs:$dst), (ins), "$dst = xor($dst, $dst)",
|
||||||
[(set (i1 PredRegs:$dst), 0)]>;
|
[(set (i1 PredRegs:$dst), 0)]>;
|
||||||
|
|
||||||
// Pseudo instructions.
|
// Pseudo instructions.
|
||||||
|
@ -3863,6 +3863,13 @@ def: Loada_pat<atomic_load_16, i32, addrgp, L2_loadruhgp>;
|
|||||||
def: Loada_pat<atomic_load_32, i32, addrgp, L2_loadrigp>;
|
def: Loada_pat<atomic_load_32, i32, addrgp, L2_loadrigp>;
|
||||||
def: Loada_pat<atomic_load_64, i64, addrgp, L2_loadrdgp>;
|
def: Loada_pat<atomic_load_64, i64, addrgp, L2_loadrdgp>;
|
||||||
|
|
||||||
|
// Map from Pd = load(globaladdress) -> Rd = memb(globaladdress), Pd = Rd
|
||||||
|
def: Loadam_pat<load, i1, addrga, I32toI1, L4_loadrub_abs>;
|
||||||
|
def: Loadam_pat<load, i1, addrgp, I32toI1, L2_loadrubgp>;
|
||||||
|
|
||||||
|
def: Stoream_pat<store, I1, addrga, I1toI32, S2_storerbabs>;
|
||||||
|
def: Stoream_pat<store, I1, addrgp, I1toI32, S2_storerbgp>;
|
||||||
|
|
||||||
// Map from load(globaladdress) -> mem[u][bhwd](#foo)
|
// Map from load(globaladdress) -> mem[u][bhwd](#foo)
|
||||||
class LoadGP_pats <PatFrag ldOp, InstHexagon MI, ValueType VT = i32>
|
class LoadGP_pats <PatFrag ldOp, InstHexagon MI, ValueType VT = i32>
|
||||||
: Pat <(VT (ldOp (HexagonCONST32_GP tglobaladdr:$global))),
|
: Pat <(VT (ldOp (HexagonCONST32_GP tglobaladdr:$global))),
|
||||||
@ -3887,6 +3894,11 @@ let AddedComplexity = 100 in {
|
|||||||
def: LoadGP_pats <zextloadi1, L2_loadrubgp>;
|
def: LoadGP_pats <zextloadi1, L2_loadrubgp>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Transfer global address into a register
|
||||||
|
def: Pat<(HexagonCONST32 tglobaladdr:$Rs), (A2_tfrsi s16Ext:$Rs)>;
|
||||||
|
def: Pat<(HexagonCONST32_GP tblockaddress:$Rs), (A2_tfrsi s16Ext:$Rs)>;
|
||||||
|
def: Pat<(HexagonCONST32_GP tglobaladdr:$Rs), (A2_tfrsi s16Ext:$Rs)>;
|
||||||
|
|
||||||
def: Pat<(i64 (ctlz I64:$src1)), (Zext64 (S2_cl0p I64:$src1))>;
|
def: Pat<(i64 (ctlz I64:$src1)), (Zext64 (S2_cl0p I64:$src1))>;
|
||||||
def: Pat<(i64 (cttz I64:$src1)), (Zext64 (S2_ct0p I64:$src1))>;
|
def: Pat<(i64 (cttz I64:$src1)), (Zext64 (S2_ct0p I64:$src1))>;
|
||||||
|
|
||||||
|
@ -144,6 +144,8 @@ defm: Loadx_pat<load, f64, s11_3ExtPred, L2_loadrd_io>;
|
|||||||
|
|
||||||
defm: Storex_pat<store, F32, s11_2ExtPred, S2_storeri_io>;
|
defm: Storex_pat<store, F32, s11_2ExtPred, S2_storeri_io>;
|
||||||
defm: Storex_pat<store, F64, s11_3ExtPred, S2_storerd_io>;
|
defm: Storex_pat<store, F64, s11_3ExtPred, S2_storerd_io>;
|
||||||
|
def: Storex_simple_pat<store, F32, S2_storeri_io>;
|
||||||
|
def: Storex_simple_pat<store, F64, S2_storerd_io>;
|
||||||
|
|
||||||
let isFP = 1, hasNewValue = 1, opNewValue = 0 in
|
let isFP = 1, hasNewValue = 1, opNewValue = 0 in
|
||||||
class T_MInstFloat <string mnemonic, bits<3> MajOp, bits<3> MinOp>
|
class T_MInstFloat <string mnemonic, bits<3> MajOp, bits<3> MinOp>
|
||||||
@ -188,6 +190,24 @@ let Itinerary = M_tc_3x_SLOT23 in {
|
|||||||
def F2_sfmin : T_MInstFloat < "sfmin", 0b100, 0b001>;
|
def F2_sfmin : T_MInstFloat < "sfmin", 0b100, 0b001>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let AddedComplexity = 100, Predicates = [HasV5T] in {
|
||||||
|
def: Pat<(f32 (select (i1 (setolt F32:$src1, F32:$src2)),
|
||||||
|
F32:$src1, F32:$src2)),
|
||||||
|
(F2_sfmin F32:$src1, F32:$src2)>;
|
||||||
|
|
||||||
|
def: Pat<(f32 (select (i1 (setogt F32:$src1, F32:$src2)),
|
||||||
|
F32:$src2, F32:$src1)),
|
||||||
|
(F2_sfmin F32:$src1, F32:$src2)>;
|
||||||
|
|
||||||
|
def: Pat<(f32 (select (i1 (setogt F32:$src1, F32:$src2)),
|
||||||
|
F32:$src1, F32:$src2)),
|
||||||
|
(F2_sfmax F32:$src1, F32:$src2)>;
|
||||||
|
|
||||||
|
def: Pat<(f32 (select (i1 (setolt F32:$src1, F32:$src2)),
|
||||||
|
F32:$src2, F32:$src1)),
|
||||||
|
(F2_sfmax F32:$src1, F32:$src2)>;
|
||||||
|
}
|
||||||
|
|
||||||
def F2_sffixupn : T_MInstFloat < "sffixupn", 0b110, 0b000>;
|
def F2_sffixupn : T_MInstFloat < "sffixupn", 0b110, 0b000>;
|
||||||
def F2_sffixupd : T_MInstFloat < "sffixupd", 0b110, 0b001>;
|
def F2_sffixupd : T_MInstFloat < "sffixupd", 0b110, 0b001>;
|
||||||
|
|
||||||
@ -699,6 +719,9 @@ def F2_sffms: T_sfmpy_acc <1, 0>;
|
|||||||
def F2_sffma_lib: T_sfmpy_acc <0, 1>;
|
def F2_sffma_lib: T_sfmpy_acc <0, 1>;
|
||||||
def F2_sffms_lib: T_sfmpy_acc <1, 1>;
|
def F2_sffms_lib: T_sfmpy_acc <1, 1>;
|
||||||
|
|
||||||
|
def : Pat <(f32 (fma F32:$src2, F32:$src3, F32:$src1)),
|
||||||
|
(F2_sffma F32:$src1, F32:$src2, F32:$src3)>;
|
||||||
|
|
||||||
// Floating-point fused multiply add w/ additional scaling (2**pu).
|
// Floating-point fused multiply add w/ additional scaling (2**pu).
|
||||||
let isFP = 1, hasNewValue = 1 in
|
let isFP = 1, hasNewValue = 1 in
|
||||||
def F2_sffma_sc: MInst <
|
def F2_sffma_sc: MInst <
|
||||||
@ -739,6 +762,38 @@ def MUX_ri_f : ALU32_rr<(outs IntRegs:$dst),
|
|||||||
[(set F32:$dst, (f32 (select I1:$src1, fpimm:$src2, F32:$src3)))]>,
|
[(set F32:$dst, (f32 (select I1:$src1, fpimm:$src2, F32:$src3)))]>,
|
||||||
Requires<[HasV5T]>;
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def: Pat<(select I1:$src1, F32:$src2, F32:$src3),
|
||||||
|
(C2_mux I1:$src1, F32:$src2, F32:$src3)>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def: Pat<(select (i1 (setult F32:$src1, F32:$src2)), F32:$src3, F32:$src4),
|
||||||
|
(C2_mux (F2_sfcmpgt F32:$src2, F32:$src1), F32:$src4, F32:$src3)>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def: Pat<(select I1:$src1, F64:$src2, F64:$src3),
|
||||||
|
(C2_vmux I1:$src1, F64:$src2, F64:$src3)>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def: Pat<(select (i1 (setult F64:$src1, F64:$src2)), F64:$src3, F64:$src4),
|
||||||
|
(C2_vmux (F2_dfcmpgt F64:$src2, F64:$src1), F64:$src3, F64:$src4)>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
// Map from p0 = pnot(p0); r0 = select(p0, #i, r1)
|
||||||
|
// => r0 = MUX_ir_f(p0, #i, r1)
|
||||||
|
def: Pat<(select (not I1:$src1), fpimm:$src2, F32:$src3),
|
||||||
|
(MUX_ir_f I1:$src1, F32:$src3, fpimm:$src2)>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
// Map from p0 = pnot(p0); r0 = mux(p0, r1, #i)
|
||||||
|
// => r0 = MUX_ri_f(p0, r1, #i)
|
||||||
|
def: Pat<(select (not I1:$src1), F32:$src2, fpimm:$src3),
|
||||||
|
(MUX_ri_f I1:$src1, fpimm:$src3, F32:$src2)>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def: Pat<(i32 (fp_to_sint F64:$src1)),
|
||||||
|
(LoReg (F2_conv_df2d_chop F64:$src1))>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// :natural forms of vasrh and vasrhub insns
|
// :natural forms of vasrh and vasrhub insns
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
@ -849,7 +904,6 @@ def F2_dfclass: ALU64Inst<(outs PredRegs:$Pd), (ins DoubleRegs:$Rss, u5Imm:$u5),
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Instructions to create floating point constant
|
// Instructions to create floating point constant
|
||||||
let hasNewValue = 1, opNewValue = 0 in
|
|
||||||
class T_fimm <string mnemonic, RegisterClass RC, bits<4> RegType, bit isNeg>
|
class T_fimm <string mnemonic, RegisterClass RC, bits<4> RegType, bit isNeg>
|
||||||
: ALU64Inst<(outs RC:$dst), (ins u10Imm:$src),
|
: ALU64Inst<(outs RC:$dst), (ins u10Imm:$src),
|
||||||
"$dst = "#mnemonic#"(#$src)"#!if(isNeg, ":neg", ":pos"),
|
"$dst = "#mnemonic#"(#$src)"#!if(isNeg, ":neg", ":pos"),
|
||||||
|
Loading…
Reference in New Issue
Block a user