Skip to content

Commit

Permalink
[PowerPC] Implement DFP add and sub instructions.
Browse files Browse the repository at this point in the history
Add the following Decimal Floating Point (DFP) instructions for PowerPC.
dadd, daddq, dsub, dsubq

In order to add these instructions a new register class for a pair
of floating point registers is added.

This patch is only to allow the user to specify the instructions in
assembly. There is no scheduling or patterns for the instructions.

Reviewed By: amyk

Differential Revision: https://reviews.llvm.org/D148597
  • Loading branch information
stefanp-ibm committed May 2, 2023
1 parent 7dc5635 commit c74aec9
Show file tree
Hide file tree
Showing 10 changed files with 177 additions and 38 deletions.
10 changes: 10 additions & 0 deletions llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,11 @@ struct PPCOperand : public MCParsedAsmOperand {
return (unsigned) Imm.Val;
}

unsigned getFpReg() const {
assert(isEvenRegNumber() && "Invalid access!");
return (unsigned)(Imm.Val >> 1);
}

unsigned getVSReg() const {
assert(isVSRegNumber() && "Invalid access!");
return (unsigned) Imm.Val;
Expand Down Expand Up @@ -502,6 +507,11 @@ struct PPCOperand : public MCParsedAsmOperand {
Inst.addOperand(MCOperand::createReg(FRegs[getReg()]));
}

void addRegFpRCOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
Inst.addOperand(MCOperand::createReg(FpRegs[getFpReg()]));
}

void addRegVFRCOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
Inst.addOperand(MCOperand::createReg(VFRegs[getReg()]));
Expand Down
8 changes: 8 additions & 0 deletions llvm/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,14 @@ static DecodeStatus DecodeF8RCRegisterClass(MCInst &Inst, uint64_t RegNo,
return decodeRegisterClass(Inst, RegNo, FRegs);
}

static DecodeStatus DecodeFpRCRegisterClass(MCInst &Inst, uint64_t RegNo,
uint64_t Address,
const MCDisassembler *Decoder) {
assert(RegNo <= 30 && "Expecting a register number no more than 30.");
assert((RegNo & 1) == 0 && "Expecting an even register number.");
return decodeRegisterClass(Inst, RegNo >> 1, FpRegs);
}

static DecodeStatus DecodeVFRCRegisterClass(MCInst &Inst, uint64_t RegNo,
uint64_t Address,
const MCDisassembler *Decoder) {
Expand Down
69 changes: 34 additions & 35 deletions llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,12 @@ static inline bool isRunOfOnes64(uint64_t Val, unsigned &MB, unsigned &ME) {
X##22, X##23, X##24, X##25, X##26, X##27, X##28, X##29, X##30, X##31 \
}

#define PPC_REGS_EVEN0_30(X) \
{ \
X##0, X##2, X##4, X##6, X##8, X##10, X##12, X##14, X##16, X##18, X##20, \
X##22, X##24, X##26, X##28, X##30 \
}

#define PPC_REGS0_63(X) \
{ \
X##0, X##1, X##2, X##3, X##4, X##5, X##6, X##7, X##8, X##9, X##10, X##11, \
Expand Down Expand Up @@ -178,41 +184,34 @@ static inline bool isRunOfOnes64(uint64_t Val, unsigned &MB, unsigned &ME) {

using llvm::MCPhysReg;

#define DEFINE_PPC_REGCLASSES \
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); \
static const MCPhysReg RRegsNoR0[32] = \
PPC_REGS_NO0_31(PPC::ZERO, PPC::R); \
static const MCPhysReg XRegsNoX0[32] = \
PPC_REGS_NO0_31(PPC::ZERO8, PPC::X); \
static const MCPhysReg VSRegs[64] = \
PPC_REGS_LO_HI(PPC::VSL, PPC::V); \
static const MCPhysReg VSFRegs[64] = \
PPC_REGS_LO_HI(PPC::F, PPC::VF); \
static const MCPhysReg VSSRegs[64] = \
PPC_REGS_LO_HI(PPC::F, PPC::VF); \
static const MCPhysReg CRBITRegs[32] = { \
PPC::CR0LT, PPC::CR0GT, PPC::CR0EQ, PPC::CR0UN, \
PPC::CR1LT, PPC::CR1GT, PPC::CR1EQ, PPC::CR1UN, \
PPC::CR2LT, PPC::CR2GT, PPC::CR2EQ, PPC::CR2UN, \
PPC::CR3LT, PPC::CR3GT, PPC::CR3EQ, PPC::CR3UN, \
PPC::CR4LT, PPC::CR4GT, PPC::CR4EQ, PPC::CR4UN, \
PPC::CR5LT, PPC::CR5GT, PPC::CR5EQ, PPC::CR5UN, \
PPC::CR6LT, PPC::CR6GT, PPC::CR6EQ, PPC::CR6UN, \
PPC::CR7LT, PPC::CR7GT, PPC::CR7EQ, PPC::CR7UN}; \
static const MCPhysReg CRRegs[8] = PPC_REGS0_7(PPC::CR); \
static const MCPhysReg ACCRegs[8] = PPC_REGS0_7(PPC::ACC); \
static const MCPhysReg WACCRegs[8] = PPC_REGS0_7(PPC::WACC); \
static const MCPhysReg WACC_HIRegs[8] = PPC_REGS0_7(PPC::WACC_HI); \
static const MCPhysReg DMRROWpRegs[32] = PPC_REGS0_31(PPC::DMRROWp); \
static const MCPhysReg DMRROWRegs[64] = PPC_REGS0_63(PPC::DMRROW); \
static const MCPhysReg DMRRegs[8] = PPC_REGS0_7(PPC::DMR); \
#define DEFINE_PPC_REGCLASSES \
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 FpRegs[16] = PPC_REGS_EVEN0_30(PPC::Fpair); \
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); \
static const MCPhysReg RRegsNoR0[32] = PPC_REGS_NO0_31(PPC::ZERO, PPC::R); \
static const MCPhysReg XRegsNoX0[32] = PPC_REGS_NO0_31(PPC::ZERO8, PPC::X); \
static const MCPhysReg VSRegs[64] = PPC_REGS_LO_HI(PPC::VSL, PPC::V); \
static const MCPhysReg VSFRegs[64] = PPC_REGS_LO_HI(PPC::F, PPC::VF); \
static const MCPhysReg VSSRegs[64] = PPC_REGS_LO_HI(PPC::F, PPC::VF); \
static const MCPhysReg CRBITRegs[32] = { \
PPC::CR0LT, PPC::CR0GT, PPC::CR0EQ, PPC::CR0UN, PPC::CR1LT, PPC::CR1GT, \
PPC::CR1EQ, PPC::CR1UN, PPC::CR2LT, PPC::CR2GT, PPC::CR2EQ, PPC::CR2UN, \
PPC::CR3LT, PPC::CR3GT, PPC::CR3EQ, PPC::CR3UN, PPC::CR4LT, PPC::CR4GT, \
PPC::CR4EQ, PPC::CR4UN, PPC::CR5LT, PPC::CR5GT, PPC::CR5EQ, PPC::CR5UN, \
PPC::CR6LT, PPC::CR6GT, PPC::CR6EQ, PPC::CR6UN, PPC::CR7LT, PPC::CR7GT, \
PPC::CR7EQ, PPC::CR7UN}; \
static const MCPhysReg CRRegs[8] = PPC_REGS0_7(PPC::CR); \
static const MCPhysReg ACCRegs[8] = PPC_REGS0_7(PPC::ACC); \
static const MCPhysReg WACCRegs[8] = PPC_REGS0_7(PPC::WACC); \
static const MCPhysReg WACC_HIRegs[8] = PPC_REGS0_7(PPC::WACC_HI); \
static const MCPhysReg DMRROWpRegs[32] = PPC_REGS0_31(PPC::DMRROWp); \
static const MCPhysReg DMRROWRegs[64] = PPC_REGS0_63(PPC::DMRROW); \
static const MCPhysReg DMRRegs[8] = PPC_REGS0_7(PPC::DMR); \
static const MCPhysReg DMRpRegs[4] = PPC_REGS0_3(PPC::DMRp);


#endif // LLVM_LIB_TARGET_POWERPC_MCTARGETDESC_PPCMCTARGETDESC_H
28 changes: 28 additions & 0 deletions llvm/lib/Target/PowerPC/PPCInstrDFP.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//===-- PPCInstrDFP.td - PowerPC Decimal Floating Point ----*- tablegen -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file describes the PowerPC Decimal Floating Point (DFP) instructions.
//
//===----------------------------------------------------------------------===//

// We provide no scheduling info for the DFP instructions.
// While they are not pseudo instructions we don't intend on scheduling them.
let hasNoSchedulingInfo = 1 in {
defm DADD : XForm_28r<59, 2, (outs f8rc:$RST), (ins f8rc:$RA, f8rc:$RB),
"dadd", "$RST, $RA, $RB", IIC_FPGeneral, []>;

defm DADDQ : XForm_28r<63, 2, (outs fpairrc:$RST), (ins fpairrc:$RA, fpairrc:$RB),
"daddq", "$RST, $RA, $RB", IIC_FPGeneral, []>;

defm DSUB : XForm_28r<59, 514, (outs f8rc:$RST), (ins f8rc:$RA, f8rc:$RB),
"dsub", "$RST, $RA, $RB", IIC_FPGeneral, []>;

defm DSUBQ : XForm_28r<63, 514, (outs fpairrc:$RST), (ins fpairrc:$RA, fpairrc:$RB),
"dsubq", "$RST, $RA, $RB", IIC_FPGeneral, []>;
}

1 change: 1 addition & 0 deletions llvm/lib/Target/PowerPC/PPCInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -3321,6 +3321,7 @@ include "PPCInstrP10.td"
include "PPCInstrFutureMMA.td"
include "PPCInstrFuture.td"
include "PPCInstrMMA.td"
include "PPCInstrDFP.td"

// Patterns for arithmetic i1 operations.
def : Pat<(add i1:$a, i1:$b),
Expand Down
7 changes: 5 additions & 2 deletions llvm/lib/Target/PowerPC/PPCRegisterInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,9 +179,12 @@ class PPCRegisterInfo : public PPCGenRegisterInfo {
case 'a':
if (RegName[1] == 'c' && RegName[2] == 'c')
return RegName + 3;
break;
case 'r':
break;
case 'f':
if (RegName[1] == 'p')
return RegName + 2;
LLVM_FALLTHROUGH;
case 'r':
case 'v':
if (RegName[1] == 's') {
if (RegName[2] == 'p')
Expand Down
37 changes: 37 additions & 0 deletions llvm/lib/Target/PowerPC/PPCRegisterInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ def sub_vsx0 : SubRegIndex<128>;
def sub_vsx1 : SubRegIndex<128, 128>;
def sub_gp8_x0 : SubRegIndex<64>;
def sub_gp8_x1 : SubRegIndex<64, 64>;
def sub_fp0 : SubRegIndex<64>;
def sub_fp1 : SubRegIndex<64, 64>;
}


Expand Down Expand Up @@ -58,6 +60,15 @@ class FPR<bits<5> num, string n> : PPCReg<n> {
let HWEncoding{4-0} = num;
}

// FPPair - A pair of 64-bit floating-point registers.
class FPPair<string n, bits<5> EvenIndex> : PPCReg<n> {
assert !eq(EvenIndex{0}, 0), "Index should be even.";
let HWEncoding{4-0} = EvenIndex;
let SubRegs = [!cast<FPR>("F"#EvenIndex), !cast<FPR>("F"#!add(EvenIndex, 1))];
let DwarfNumbers = [-1, -1];
let SubRegIndices = [sub_fp0, sub_fp1];
}

// VF - One of the 32 64-bit floating-point subregisters of the vector
// registers (used by VSX).
class VF<bits<5> num, string n> : PPCReg<n> {
Expand Down Expand Up @@ -136,6 +147,11 @@ foreach Index = 0-31 in {
DwarfRegNum<[!add(Index, 32), !add(Index, 32)]>;
}

// Floating-point pair registers
foreach Index = { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30 } in {
def Fpair#Index : FPPair<"fp"#Index, Index>;
}

// 64-bit Floating-point subregisters of Altivec registers
// Note: the register names are v0-v31 or vs32-vs63 depending on the use.
// Custom C++ code is used to produce the correct name and encoding.
Expand Down Expand Up @@ -349,6 +365,21 @@ def F8RC : RegisterClass<"PPC", [f64], 64, (add (sequence "F%u", 0, 13),
(sequence "F%u", 31, 14))>;
def F4RC : RegisterClass<"PPC", [f32], 32, (add F8RC)>;

// Floating point pair registers.
// Note that the type used for this register class is ppcf128. This is not
// completely correct. However, since we are not pattern matching any
// instructions for these registers and we are not register allocating or
// scheduling any of these instructions it should be safe to do this.
// The reason we didn't use the correct type (Decimal Floating Point) is that
// at the time of this implementation the correct type was not available.
def FpRC :
RegisterClass<"PPC", [ppcf128], 128,
(add Fpair0, Fpair2, Fpair4, Fpair6, Fpair8, Fpair10, Fpair12,
Fpair14, Fpair16, Fpair18, Fpair20, Fpair22, Fpair24,
Fpair26, Fpair28, Fpair30)> {
let Size = 128;
}

def VRRC : RegisterClass<"PPC",
[v16i8,v8i16,v4i32,v2i64,v1i128,v4f32,v2f64, f128],
128,
Expand Down Expand Up @@ -504,6 +535,12 @@ def PPCRegF4RCAsmOperand : AsmOperandClass {
def f4rc : RegisterOperand<F4RC> {
let ParserMatchClass = PPCRegF4RCAsmOperand;
}
def PPCRegFpRCAsmOperand : AsmOperandClass {
let Name = "RegFpRC"; let PredicateMethod = "isEvenRegNumber";
}
def fpairrc : RegisterOperand<FpRC> {
let ParserMatchClass = PPCRegFpRCAsmOperand;
}
def PPCRegVRRCAsmOperand : AsmOperandClass {
let Name = "RegVRRC"; let PredicateMethod = "isRegNumber";
}
Expand Down
25 changes: 25 additions & 0 deletions llvm/test/MC/Disassembler/PowerPC/ppc64-encoding-dfp.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# RUN: llvm-mc --disassemble %s -triple powerpc64-unknown-unknown -mcpu=pwr7 | FileCheck %s

# CHECK: dadd 2, 3, 4
0xec 0x43 0x20 0x04

# CHECK: dadd. 2, 3, 4
0xec 0x43 0x20 0x05

# CHECK: daddq 2, 6, 4
0xfc 0x46 0x20 0x04

# CHECK: daddq. 2, 6, 4
0xfc 0x46 0x20 0x05

# CHECK: dsub 2, 3, 4
0xec 0x43 0x24 0x04

# CHECK: dsub. 2, 3, 4
0xec 0x43 0x24 0x05

# CHECK: dsubq 2, 6, 4
0xfc 0x46 0x24 0x04

# CHECK: dsubq. 2, 6, 4
0xfc 0x46 0x24 0x05
2 changes: 1 addition & 1 deletion llvm/test/MC/PowerPC/invalid-instructions-spellcheck.s
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,6 @@ xsnmsubad %r1, %r2

adXd %r1, %r2, %r3

# CHECK: error: invalid instruction, did you mean: add, addc, adde, addi, addo, fadd?
# CHECK: error: invalid instruction, did you mean: add, addc, adde, addi, addo, dadd, fadd?
# CHECK-NEXT: adXd %r1, %r2, %r3
# CHECK-NEXT: ^
28 changes: 28 additions & 0 deletions llvm/test/MC/PowerPC/ppc64-encoding-dfp.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# RUN: llvm-mc -triple powerpc64-unknown-unknown --show-encoding %s | FileCheck -check-prefix=CHECK-BE %s
# RUN: llvm-mc -triple powerpc64le-unknown-unknown --show-encoding %s | FileCheck -check-prefix=CHECK-LE %s


# CHECK-BE: dadd 2, 3, 4 # encoding: [0xec,0x43,0x20,0x04]
# CHECK-LE: dadd 2, 3, 4 # encoding: [0x04,0x20,0x43,0xec]
dadd 2, 3, 4
# CHECK-BE: dadd. 2, 3, 4 # encoding: [0xec,0x43,0x20,0x05]
# CHECK-LE: dadd. 2, 3, 4 # encoding: [0x05,0x20,0x43,0xec]
dadd. 2, 3, 4
# CHECK-BE: daddq 2, 6, 4 # encoding: [0xfc,0x46,0x20,0x04]
# CHECK-LE: daddq 2, 6, 4 # encoding: [0x04,0x20,0x46,0xfc]
daddq 2, 6, 4
# CHECK-BE: daddq. 2, 6, 4 # encoding: [0xfc,0x46,0x20,0x05]
# CHECK-LE: daddq. 2, 6, 4 # encoding: [0x05,0x20,0x46,0xfc]
daddq. 2, 6, 4
# CHECK-BE: dsub 2, 3, 4 # encoding: [0xec,0x43,0x24,0x04]
# CHECK-LE: dsub 2, 3, 4 # encoding: [0x04,0x24,0x43,0xec]
dsub 2, 3, 4
# CHECK-BE: dsub. 2, 3, 4 # encoding: [0xec,0x43,0x24,0x05]
# CHECK-LE: dsub. 2, 3, 4 # encoding: [0x05,0x24,0x43,0xec]
dsub. 2, 3, 4
# CHECK-BE: dsubq 2, 6, 4 # encoding: [0xfc,0x46,0x24,0x04]
# CHECK-LE: dsubq 2, 6, 4 # encoding: [0x04,0x24,0x46,0xfc]
dsubq 2, 6, 4
# CHECK-BE: dsubq. 2, 6, 4 # encoding: [0xfc,0x46,0x24,0x05]
# CHECK-LE: dsubq. 2, 6, 4 # encoding: [0x05,0x24,0x46,0xfc]
dsubq. 2, 6, 4

0 comments on commit c74aec9

Please sign in to comment.