diff --git a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp --- a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp +++ b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp @@ -290,6 +290,11 @@ return (unsigned) Imm.Val; } + unsigned getVSRpEvenReg() const { + assert(isVSRpEvenRegNumber() && "Invalid access!"); + return (unsigned) Imm.Val >> 1; + } + unsigned getCCReg() const { assert(isCCRegNumber() && "Invalid access!"); return (unsigned) (Kind == Immediate ? Imm.Val : Expr.CRVal); @@ -402,6 +407,9 @@ (getImm() & 3) == 0); } bool isImmZero() const { return Kind == Immediate && getImm() == 0; } bool isRegNumber() const { return Kind == Immediate && isUInt<5>(getImm()); } + bool isVSRpEvenRegNumber() const { + return Kind == Immediate && isUInt<6>(getImm()) && ((getImm() & 1) == 0); + } bool isVSRegNumber() const { return Kind == Immediate && isUInt<6>(getImm()); } @@ -502,6 +510,11 @@ Inst.addOperand(MCOperand::createReg(SPERegs[getReg()])); } + void addRegVSRpRCOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::createReg(VSRpRegs[getVSRpEvenReg()])); + } + void addRegCRBITRCOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); Inst.addOperand(MCOperand::createReg(CRBITRegs[getCRBit()])); diff --git a/llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp b/llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp --- a/llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp +++ b/llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp @@ -173,6 +173,12 @@ return decodeRegisterClass(Inst, RegNo, SPERegs); } +static DecodeStatus DecodeVSRpRCRegisterClass(MCInst &Inst, uint64_t RegNo, + uint64_t Address, + const void *Decoder) { + return decodeRegisterClass(Inst, RegNo, VSRpRegs); +} + #define DecodeQSRCRegisterClass DecodeQFRCRegisterClass #define DecodeQBRCRegisterClass DecodeQFRCRegisterClass diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h --- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h +++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h @@ -156,6 +156,7 @@ static const MCPhysReg RRegs[32] = PPC_REGS0_31(PPC::R); \ static const MCPhysReg XRegs[32] = PPC_REGS0_31(PPC::X); \ static const MCPhysReg FRegs[32] = PPC_REGS0_31(PPC::F); \ + static const MCPhysReg VSRpRegs[32] = PPC_REGS0_31(PPC::VSRp); \ static const MCPhysReg SPERegs[32] = PPC_REGS0_31(PPC::S); \ static const MCPhysReg VFRegs[32] = PPC_REGS0_31(PPC::VF); \ static const MCPhysReg VRegs[32] = PPC_REGS0_31(PPC::V); \ diff --git a/llvm/lib/Target/PowerPC/PPCInstrPrefix.td b/llvm/lib/Target/PowerPC/PPCInstrPrefix.td --- a/llvm/lib/Target/PowerPC/PPCInstrPrefix.td +++ b/llvm/lib/Target/PowerPC/PPCInstrPrefix.td @@ -517,10 +517,79 @@ isPCRel; } +def PPCRegVSRpRCAsmOperand : AsmOperandClass { + let Name = "RegVSRpRC"; let PredicateMethod = "isVSRpEvenRegNumber"; +} + +def vsrprc : RegisterOperand { + let ParserMatchClass = PPCRegVSRpRCAsmOperand; +} + +class DQForm_XTp5_RA17_MEM opcode, bits<4> xo, dag OOL, dag IOL, + string asmstr, InstrItinClass itin, list pattern> + : I { + bits<5> XTp; + bits<17> DQ_RA; + let Pattern = pattern; + + let Inst{6-9} = XTp{3-0}; + let Inst{10} = XTp{4}; + let Inst{11-15} = DQ_RA{16-12}; // Register # + let Inst{16-27} = DQ_RA{11-0}; // Displacement. + let Inst{28-31} = xo; +} + +class XForm_XTp5_XAB5 opcode, bits<10> xo, dag OOL, dag IOL, + string asmstr, InstrItinClass itin, list pattern> + : I, XFormMemOp { + bits<5> XTp; + bits<5> A; + bits<5> B; + + let Pattern = pattern; + let Inst{6-9} = XTp{3-0}; + let Inst{10} = XTp{4}; + let Inst{11-15} = A; + let Inst{16-20} = B; + let Inst{21-30} = xo; + let Inst{31} = 0; +} + +class 8LS_DForm_R_XTp5_SI34_MEM opcode, dag OOL, dag IOL, string asmstr, + InstrItinClass itin, list pattern> + : PI<1, opcode, OOL, IOL, asmstr, itin> { + bits<5> XTp; + bits<39> D_RA; + + let Pattern = pattern; + + // The prefix. + let Inst{6-10} = 0; + let Inst{11} = PCRel; + let Inst{12-13} = 0; + let Inst{14-31} = D_RA{33-16}; // Imm18 + + // The instruction. + let Inst{38-41} = XTp{3-0}; + let Inst{42} = XTp{4}; + let Inst{43-47} = D_RA{38-34}; // Register # + let Inst{48-63} = D_RA{15-0}; // D +} + +multiclass 8LS_DForm_R_XTp5_SI34_MEM_p pref, bits<6> opcode, dag OOL, + dag IOL, dag PCRel_IOL, + string asmstr, InstrItinClass itin> { + def NAME : 8LS_DForm_R_XTp5_SI34_MEM; + def pc : 8LS_DForm_R_XTp5_SI34_MEM, + isPCRel; +} + def PrefixInstrs : Predicate<"Subtarget->hasPrefixInstrs()">; def IsISA3_1 : Predicate<"Subtarget->isISA3_1()">; -def PairedVectorMemops : Predicate<"PPCSubTarget->pairedVectorMemops()">; -def MMA : Predicate<"PPCSubTarget->hasMMA()">; +def PairedVectorMemops : Predicate<"Subtarget->pairedVectorMemops()">; +def MMA : Predicate<"Subtarget->hasMMA()">; def RCCp { dag AToVSRC = (COPY_TO_REGCLASS $XA, VSRC); @@ -672,6 +741,36 @@ } } +let mayLoad = 1, mayStore = 0, Predicates = [PairedVectorMemops] in { + def LXVP : DQForm_XTp5_RA17_MEM<6, 0, (outs vsrprc:$XTp), + (ins memrix16:$DQ_RA), "lxvp $XTp, $DQ_RA", + IIC_LdStLFD, []>; + def LXVPX : XForm_XTp5_XAB5<31, 333, (outs vsrprc:$XTp), (ins memrr:$src), + "lxvpx $XTp, $src", IIC_LdStLFD, + [(set v4i64:$XTp, (load xaddr:$src))]>; + let Predicates = [PrefixInstrs] in { + defm PLXVP : + 8LS_DForm_R_XTp5_SI34_MEM_p<1, 58, (outs vsrprc:$XTp), (ins memri34:$D_RA), + (ins memri34_pcrel:$D_RA), "plxvp $XTp, $D_RA", + IIC_LdStLFD>; + } +} + +let mayLoad = 0, mayStore = 1, Predicates = [PairedVectorMemops] in { + def STXVP : DQForm_XTp5_RA17_MEM<6, 1, (outs), (ins vsrprc:$XTp, + memrix16:$DQ_RA), "stxvp $XTp, $DQ_RA", + IIC_LdStLFD, []>; + def STXVPX : XForm_XTp5_XAB5<31, 461, (outs), (ins vsrprc:$XTp, memrr:$dst), + "stxvpx $XTp, $dst", IIC_LdStLFD, + [(store v4i64:$XTp, xaddr:$dst)]>; + let Predicates = [PrefixInstrs] in { + defm PSTXVP : + 8LS_DForm_R_XTp5_SI34_MEM_p<1, 62, (outs), (ins vsrprc:$XTp, memri34:$D_RA), + (ins vsrprc:$XTp, memri34_pcrel:$D_RA), + "pstxvp $XTp, $D_RA", IIC_LdStLFD>; + } +} + // TODO: We have an added complexity of 500 here. This is only a temporary // solution to have tablegen consider these patterns first. The way we do // addressing for PowerPC is complex depending on available D form, X form, or diff --git a/llvm/lib/Target/PowerPC/PPCRegisterInfo.h b/llvm/lib/Target/PowerPC/PPCRegisterInfo.h --- a/llvm/lib/Target/PowerPC/PPCRegisterInfo.h +++ b/llvm/lib/Target/PowerPC/PPCRegisterInfo.h @@ -154,8 +154,11 @@ case 'r': case 'f': case 'v': - if (RegName[1] == 's') + if (RegName[1] == 's') { + if (RegName[2] == 'p') + return RegName + 3; return RegName + 2; + } return RegName + 1; case 'c': if (RegName[1] == 'r') return RegName + 2; } diff --git a/llvm/lib/Target/PowerPC/PPCRegisterInfo.td b/llvm/lib/Target/PowerPC/PPCRegisterInfo.td --- a/llvm/lib/Target/PowerPC/PPCRegisterInfo.td +++ b/llvm/lib/Target/PowerPC/PPCRegisterInfo.td @@ -16,6 +16,8 @@ def sub_un : SubRegIndex<1, 3>; def sub_32 : SubRegIndex<32>; def sub_64 : SubRegIndex<64>; +def sub_vsx0 : SubRegIndex<128>; +def sub_vsx1 : SubRegIndex<128>; } @@ -94,6 +96,12 @@ let HWEncoding{4-0} = num; } +// VSR Pairs - One of the 32 paired even-odd consecutive VSRs. +class VSRPair num, string n, list subregs> : PPCReg { + let HWEncoding{4-0} = num; + let SubRegs = subregs; +} + // General-purpose registers foreach Index = 0-31 in { def R#Index : GPR, DwarfRegNum<[-2, Index]>; @@ -143,6 +151,23 @@ def VSX#Index : VSXReg; } +let SubRegIndices = [sub_vsx0, sub_vsx1] in { + // VSR pairs 0 - 15 (corresponding to VSRs 0 - 30 paired with 1 - 31). + foreach Index = { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30 } in { + def VSRp#!srl(Index, 1) : VSRPair("VSL"#Index), !cast("VSL"#!add(Index, 1))]>, + DwarfRegNum<[0, 0]>; + } + + // VSR pairs 16 - 31 (corresponding to VSRs 32 - 62 paired with 33 - 63). + foreach Index = { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30 } in { + def VSRp#!add(!srl(Index, 1), 16) : + VSRPair("V"#Index), !cast("V"#!add(Index, 1))]>, + DwarfRegNum<[0, 0]>; + } +} + // The representation of r0 when treated as the constant 0. def ZERO : GPR<0, "0">, DwarfRegAlias; def ZERO8 : GP8, DwarfRegAlias; @@ -372,3 +397,13 @@ let CopyCost = -1; } +// Allocate in the same order as the underlying VSX registers. +def VSRpRC : + RegisterClass<"PPC", [v4i64,v4f64,v8i32,v8f32,v16i16,v32i8,v256i1], 128, + (add (sequence "VSRp%u", 0, 6), + (sequence "VSRp%u", 15, 7), VSRp17, VSRp18, + VSRp16, VSRp19, VSRp20, VSRp21, VSRp22, VSRp23, + VSRp24, VSRp25, VSRp31, VSRp30, VSRp29, VSRp28, + VSRp27, VSRp26)> { + let Size = 256; +} diff --git a/llvm/test/MC/Disassembler/PowerPC/ppc64-encoding-ISA31.txt b/llvm/test/MC/Disassembler/PowerPC/ppc64-encoding-ISA31.txt --- a/llvm/test/MC/Disassembler/PowerPC/ppc64-encoding-ISA31.txt +++ b/llvm/test/MC/Disassembler/PowerPC/ppc64-encoding-ISA31.txt @@ -25,6 +25,30 @@ # CHECK: pstxv 33, 8589934591(0), 1 0x04 0x11 0xff 0xff 0xdc 0x20 0xff 0xff +# CHECK: lxvp 2, 32(4) +0x18 0x44 0x00 0x20 + +# CHECK: plxvp 2, -8589934592(0), 1 +0x04 0x12 0x00 0x00 0xe8 0x40 0x00 0x00 + +# CHECK: plxvp 34, 8589934591(3), 0 +0x04 0x01 0xff 0xff 0xe8 0x63 0xff 0xff + +# CHECK: stxvp 2, 32(4) +0x18 0x44 0x00 0x21 + +# CHECK: pstxvp 2, -8589934592(0), 1 +0x04 0x12 0x00 0x00 0xf8 0x40 0x00 0x00 + +# CHECK: pstxvp 34, 8589934591(3), 0 +0x04 0x01 0xff 0xff 0xf8 0x63 0xff 0xff + +# CHECK: lxvpx 2, 3, 4 +0x7c 0x43 0x22 0x9a + +# CHECK: stxvpx 34, 6, 4 +0x7c 0x66 0x23 0x9a + # CHECK: pstfs 1, -134217728(3), 0 0x06 0x03 0xf8 0x00 0xd0 0x23 0x00 0x00 diff --git a/llvm/test/MC/PowerPC/ppc64-encoding-ISA31.s b/llvm/test/MC/PowerPC/ppc64-encoding-ISA31.s --- a/llvm/test/MC/PowerPC/ppc64-encoding-ISA31.s +++ b/llvm/test/MC/PowerPC/ppc64-encoding-ISA31.s @@ -23,6 +23,44 @@ # CHECK-LE: pstxv 33, -8589934592(31), 0 # encoding: [0x00,0x00,0x02,0x04 # CHECK-LE-SAME: 0x00,0x00,0x3f,0xdc] pstxv 33, -8589934592(31), 0 +# CHECK-BE: lxvp 2, 32(4) # encoding: [0x18,0x44,0x00,0x20] +# CHECK-LE: lxvp 2, 32(4) # encoding: [0x20,0x00,0x44,0x18] + lxvp 2, 32(4) +# CHECK-BE: lxvp 34, 64(4) # encoding: [0x18,0x64,0x00,0x40] +# CHECK-LE: lxvp 34, 64(4) # encoding: [0x40,0x00,0x64,0x18] + lxvp 34, 64(4) +# CHECK-BE: plxvp 2, -8589934592(0), 1 # encoding: [0x04,0x12,0x00,0x00, +# CHECK-BE-SAME: 0xe8,0x40,0x00,0x00] +# CHECK-LE: plxvp 2, -8589934592(0), 1 # encoding: [0x00,0x00,0x12,0x04, +# CHECK-LE-SAME: 0x00,0x00,0x40,0xe8] + plxvp 2, -8589934592(0), 1 +# CHECK-BE: plxvp 34, 8589934591(3), 0 # encoding: [0x04,0x01,0xff,0xff, +# CHECK-BE-SAME: 0xe8,0x63,0xff,0xff] +# CHECK-LE: plxvp 34, 8589934591(3), 0 # encoding: [0xff,0xff,0x01,0x04, +# CHECK-LE-SAME: 0xff,0xff,0x63,0xe8] + plxvp 34, 8589934591(3), 0 +# CHECK-BE: stxvp 2, 32(4) # encoding: [0x18,0x44,0x00,0x21] +# CHECK-LE: stxvp 2, 32(4) # encoding: [0x21,0x00,0x44,0x18] + stxvp 2, 32(4) +# CHECK-BE: stxvp 34, 64(4) # encoding: [0x18,0x64,0x00,0x41] +# CHECK-LE: stxvp 34, 64(4) # encoding: [0x41,0x00,0x64,0x18] + stxvp 34, 64(4) +# CHECK-BE: pstxvp 2, -8589934592(0), 1 # encoding: [0x04,0x12,0x00,0x00, +# CHECK-BE-SAME: 0xf8,0x40,0x00,0x00] +# CHECK-LE: pstxvp 2, -8589934592(0), 1 # encoding: [0x00,0x00,0x12,0x04 +# CHECK-LE-SAME: 0x00,0x00,0x40,0xf8] + pstxvp 2, -8589934592(0), 1 +# CHECK-BE: pstxvp 34, 8589934591(3), 0 # encoding: [0x04,0x01,0xff,0xff +# CHECK-BE-SAME: 0xf8,0x63,0xff,0xff] +# CHECK-LE: pstxvp 34, 8589934591(3), 0 # encoding: [0xff,0xff,0x01,0x04 +# CHECK-LE-SAME: 0xff,0xff,0x63,0xf8] + pstxvp 34, 8589934591(3), 0 +# CHECK-BE: lxvpx 2, 3, 4 # encoding: [0x7c,0x43,0x22,0x9a] +# CHECK-LE: lxvpx 2, 3, 4 # encoding: [0x9a,0x22,0x43,0x7c] + lxvpx 2, 3, 4 +# CHECK-BE: stxvpx 34, 6, 4 # encoding: [0x7c,0x66,0x23,0x9a] +# CHECK-LE: stxvpx 34, 6, 4 # encoding: [0x9a,0x23,0x66,0x7c] + stxvpx 34, 6, 4 # CHECK-BE: paddi 1, 2, 8589934591, 0 # encoding: [0x06,0x01,0xff,0xff # CHECK-BE-SAME: 0x38,0x22,0xff,0xff] # CHECK-LE: paddi 1, 2, 8589934591, 0 # encoding: [0xff,0xff,0x01,0x06 diff --git a/llvm/utils/TableGen/CodeGenTarget.cpp b/llvm/utils/TableGen/CodeGenTarget.cpp --- a/llvm/utils/TableGen/CodeGenTarget.cpp +++ b/llvm/utils/TableGen/CodeGenTarget.cpp @@ -86,6 +86,7 @@ case MVT::v32i1: return "MVT::v32i1"; case MVT::v64i1: return "MVT::v64i1"; case MVT::v128i1: return "MVT::v128i1"; + case MVT::v256i1: return "MVT::v256i1"; case MVT::v512i1: return "MVT::v512i1"; case MVT::v1024i1: return "MVT::v1024i1"; case MVT::v1i8: return "MVT::v1i8";