arch-power: Add doubleword multiply-add instructions
This introduces 128-bit addition helpers and adds the following instructions. * Multiply-Add Low Doubleword (maddld) * Multiply-Add High Doubleword (maddhd) * Multiply-Add High Doubleword Unsigned (maddhdu) Change-Id: I04e6ea5fb4978b341a6e648424de2930ad41f449 Signed-off-by: Sandipan Das <sandipan@linux.ibm.com> Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/40905 Reviewed-by: Boris Shingarov <shingarov@labware.com> Maintainer: Jason Lowe-Power <power.jg@gmail.com> Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
committed by
Boris Shingarov
parent
a74a9633f2
commit
52fb5e42ec
@@ -117,6 +117,7 @@ IntArithOp::generateDisassembly(
|
||||
{
|
||||
std::stringstream ss;
|
||||
bool printSecondSrc = true;
|
||||
bool printThirdSrc = false;
|
||||
|
||||
// Generate the correct mnemonic
|
||||
std::string myMnemonic(mnemonic);
|
||||
@@ -128,6 +129,10 @@ IntArithOp::generateDisassembly(
|
||||
myMnemonic == "subfze" ||
|
||||
myMnemonic == "neg") {
|
||||
printSecondSrc = false;
|
||||
} else if (myMnemonic == "maddhd" ||
|
||||
myMnemonic == "maddhdu" ||
|
||||
myMnemonic == "maddld") {
|
||||
printThirdSrc = true;
|
||||
}
|
||||
|
||||
// Additional characters depending on isa bits being set
|
||||
@@ -151,6 +156,12 @@ IntArithOp::generateDisassembly(
|
||||
if (_numSrcRegs > 1 && printSecondSrc) {
|
||||
ss << ", ";
|
||||
printReg(ss, srcRegIdx(1));
|
||||
|
||||
// Print the third source register
|
||||
if (_numSrcRegs > 2 && printThirdSrc) {
|
||||
ss << ", ";
|
||||
printReg(ss, srcRegIdx(2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -134,6 +134,52 @@ class IntArithOp : public IntOp
|
||||
{
|
||||
}
|
||||
|
||||
/* Compute 128-bit sum of 128-bit to 64-bit unsigned integer addition */
|
||||
inline std::tuple<uint64_t, uint64_t>
|
||||
add(uint64_t ralo, uint64_t rahi, uint64_t rb) const
|
||||
{
|
||||
uint64_t slo, shi;
|
||||
#if defined(__SIZEOF_INT128__)
|
||||
__uint128_t ra = ((__uint128_t)rahi << 64) | ralo;
|
||||
__uint128_t sum = ra + rb;
|
||||
slo = sum;
|
||||
shi = sum >> 64;
|
||||
#else
|
||||
shi = rahi + ((ralo + rb) < ralo);
|
||||
slo = ralo + rb;
|
||||
#endif
|
||||
return std::make_tuple(slo, shi);
|
||||
}
|
||||
|
||||
/* Compute 128-bit sum of 128-bit to 64-bit signed integer addition */
|
||||
inline std::tuple<uint64_t, int64_t>
|
||||
add(uint64_t ralo, int64_t rahi, int64_t rb) const
|
||||
{
|
||||
uint64_t slo;
|
||||
int64_t shi;
|
||||
#if defined(__SIZEOF_INT128__)
|
||||
__int128_t ra = ((__int128_t)rahi << 64) | ralo;
|
||||
__int128_t sum = (__int128_t)ra + rb;
|
||||
slo = sum;
|
||||
shi = sum >> 64;
|
||||
#else
|
||||
if (rb < 0) {
|
||||
shi = rahi - 1;
|
||||
slo = ralo + rb;
|
||||
if (slo < rb) {
|
||||
shi++;
|
||||
}
|
||||
} else {
|
||||
shi = rahi;
|
||||
slo = ralo + rb;
|
||||
if (slo < rb) {
|
||||
shi++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return std::make_tuple(slo, shi);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute 128-bit product of 64-bit unsigned integer multiplication
|
||||
* based on https://stackoverflow.com/a/28904636
|
||||
@@ -177,6 +223,48 @@ class IntArithOp : public IntOp
|
||||
return std::make_tuple(plo, (int64_t)phi);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute 128-bit result of 64-bit unsigned integer multiplication
|
||||
* followed by addition
|
||||
*/
|
||||
inline std::tuple<uint64_t, uint64_t>
|
||||
multiplyAdd(uint64_t ra, uint64_t rb, uint64_t rc) const
|
||||
{
|
||||
uint64_t rlo, rhi;
|
||||
#if defined(__SIZEOF_INT128__)
|
||||
__uint128_t res = ((__uint128_t)ra * rb) + rc;
|
||||
rlo = res;
|
||||
rhi = res >> 64;
|
||||
#else
|
||||
uint64_t plo, phi;
|
||||
std::tie(plo, phi) = multiply(ra, rb);
|
||||
std::tie(rlo, rhi) = add(plo, phi, rc);
|
||||
#endif
|
||||
return std::make_tuple(rlo, rhi);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute 128-bit result of 64-bit signed integer multiplication
|
||||
* followed by addition
|
||||
*/
|
||||
inline std::tuple<uint64_t, int64_t>
|
||||
multiplyAdd(int64_t ra, int64_t rb, int64_t rc) const
|
||||
{
|
||||
uint64_t rlo;
|
||||
int64_t rhi;
|
||||
#if defined(__SIZEOF_INT128__)
|
||||
__int128_t res = (__int128_t)ra * rb + rc;
|
||||
rlo = res;
|
||||
rhi = res >> 64;
|
||||
#else
|
||||
uint64_t plo;
|
||||
int64_t phi;
|
||||
std::tie(plo, phi) = multiply(ra, rb);
|
||||
std::tie(rlo, rhi) = add(plo, phi, rc);
|
||||
#endif
|
||||
return std::make_tuple(rlo, rhi);
|
||||
}
|
||||
|
||||
std::string generateDisassembly(
|
||||
Addr pc, const Loader::SymbolTable *symtab) const override;
|
||||
};
|
||||
|
||||
@@ -36,6 +36,31 @@
|
||||
//
|
||||
decode PO default Unknown::unknown() {
|
||||
|
||||
4: decode VA_XO {
|
||||
|
||||
// Arithmetic instructions that use source registers Ra, Rb and Rc,
|
||||
// with destination register Rt.
|
||||
format IntArithOp {
|
||||
48: maddhd({{
|
||||
int64_t res;
|
||||
std::tie(std::ignore, res) = multiplyAdd(Ra_sd, Rb_sd, Rc_sd);
|
||||
Rt = res;
|
||||
}});
|
||||
|
||||
49: maddhdu({{
|
||||
uint64_t res;
|
||||
std::tie(std::ignore, res) = multiplyAdd(Ra, Rb, Rc);
|
||||
Rt = res;
|
||||
}});
|
||||
|
||||
51: maddld({{
|
||||
uint64_t res;
|
||||
std::tie(res, std::ignore) = multiplyAdd(Ra_sd, Rb_sd, Rc_sd);
|
||||
Rt = res;
|
||||
}});
|
||||
}
|
||||
}
|
||||
|
||||
format IntImmArithOp {
|
||||
7: mulli({{
|
||||
int64_t res = Ra_sd * si;
|
||||
|
||||
@@ -290,6 +290,16 @@ def format IntSumOp(src1, src2, ca = {{ 0 }}, computeCA = 0,
|
||||
|
||||
}};
|
||||
|
||||
// Instructions that use source registers Ra and Rb, with the result
|
||||
// placed into Rt but do not check for carry, overflow or the Rc bit.
|
||||
def format IntArithOp(code, inst_flags = []) {{
|
||||
|
||||
# Generate the class
|
||||
(header_output, decoder_output, decode_block, exec_output) = \
|
||||
GenAluOp(name, Name, 'IntArithOp', code, inst_flags, BasicDecode,
|
||||
BasicConstructor)
|
||||
}};
|
||||
|
||||
|
||||
// Instructions that use source registers Ra and Rb, with the result
|
||||
// placed into Rt. Basically multiply and divide instructions. The
|
||||
|
||||
Reference in New Issue
Block a user