arch-power: Add doubleword multiply instructions
This introduces 128-bit multiplication helpers and adds the following instructions. * Multiply Low Doubleword (mulld[o][.]) * Multiply High Doubleword (mulhd[.]) * Multiply High Doubleword Unsigned (mulhdu[.]) Change-Id: Id579c95468ffe5fe7b5164579ec1dfb18f0b3ab3 Signed-off-by: Sandipan Das <sandipan@linux.ibm.com> Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/40903 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
e2f275dce9
commit
930419bcb2
@@ -134,6 +134,49 @@ class IntArithOp : public IntOp
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute 128-bit product of 64-bit unsigned integer multiplication
|
||||
* based on https://stackoverflow.com/a/28904636
|
||||
*/
|
||||
inline std::tuple<uint64_t, uint64_t>
|
||||
multiply(uint64_t ra, uint64_t rb) const
|
||||
{
|
||||
uint64_t plo, phi;
|
||||
#if defined(__SIZEOF_INT128__)
|
||||
__uint128_t prod = (__uint128_t)ra * rb;
|
||||
plo = prod;
|
||||
phi = prod >> 64;
|
||||
#else
|
||||
uint64_t ralo = (uint32_t)ra, rahi = ra >> 32;
|
||||
uint64_t rblo = (uint32_t)rb, rbhi = rb >> 32;
|
||||
uint64_t pp0 = ralo * rblo;
|
||||
uint64_t pp1 = rahi * rblo;
|
||||
uint64_t pp2 = ralo * rbhi;
|
||||
uint64_t pp3 = rahi * rbhi;
|
||||
uint64_t c = ((uint32_t)pp1) + ((uint32_t)pp2) + (pp0 >> 32);
|
||||
phi = pp3 + (pp2 >> 32) + (pp1 >> 32) + (c >> 32);
|
||||
plo = (c << 32) | ((uint32_t)pp0);
|
||||
#endif
|
||||
return std::make_tuple(plo, phi);
|
||||
}
|
||||
|
||||
/* Compute 128-bit product of 64-bit signed integer multiplication */
|
||||
inline std::tuple<uint64_t, int64_t>
|
||||
multiply(int64_t ra, int64_t rb) const
|
||||
{
|
||||
uint64_t plo, phi;
|
||||
#if defined(__SIZEOF_INT128__)
|
||||
__int128_t prod = (__int128_t)ra * rb;
|
||||
plo = prod;
|
||||
phi = prod >> 64;
|
||||
#else
|
||||
std::tie(plo, phi) = multiply((uint64_t)ra, (uint64_t)rb);
|
||||
if (rb < 0) phi -= (uint64_t)ra;
|
||||
if (ra < 0) phi -= (uint64_t)rb;
|
||||
#endif
|
||||
return std::make_tuple(plo, (int64_t)phi);
|
||||
}
|
||||
|
||||
std::string generateDisassembly(
|
||||
Addr pc, const Loader::SymbolTable *symtab) const override;
|
||||
};
|
||||
|
||||
@@ -483,10 +483,15 @@ decode PO default Unknown::unknown() {
|
||||
|
||||
// These instructions are of XO form with bit 21 as the OE bit.
|
||||
default: decode XO_XO {
|
||||
format IntSumOp {
|
||||
8: subfc({{ ~Ra }}, {{ Rb }}, {{ 1 }}, true);
|
||||
10: addc({{ Ra }}, {{ Rb }}, computeCA = true);
|
||||
}
|
||||
8: IntSumOp::subfc({{ ~Ra }}, {{ Rb }}, {{ 1 }}, true);
|
||||
|
||||
9: IntArithCheckRcOp::mulhdu({{
|
||||
uint64_t res;
|
||||
std::tie(std::ignore, res) = multiply(Ra, Rb);
|
||||
Rt = res;
|
||||
}});
|
||||
|
||||
10: IntSumOp::addc({{ Ra }}, {{ Rb }}, computeCA = true);
|
||||
|
||||
11: IntArithCheckRcOp::mulhwu({{
|
||||
uint64_t res = (uint64_t)Ra_uw * Rb_uw;
|
||||
@@ -496,11 +501,19 @@ decode PO default Unknown::unknown() {
|
||||
|
||||
40: IntSumOp::subf({{ ~Ra }}, {{ Rb }}, {{ 1 }});
|
||||
|
||||
75: IntArithCheckRcOp::mulhw({{
|
||||
uint64_t res = (int64_t)Ra_sw * Rb_sw;
|
||||
res = res >> 32;
|
||||
Rt = res;
|
||||
}});
|
||||
format IntArithCheckRcOp {
|
||||
73: mulhd({{
|
||||
int64_t res;
|
||||
std::tie(std::ignore, res) = multiply(Ra_sd, Rb_sd);
|
||||
Rt = res;
|
||||
}});
|
||||
|
||||
75: mulhw({{
|
||||
uint64_t res = (int64_t)Ra_sw * Rb_sw;
|
||||
res = res >> 32;
|
||||
Rt = res;
|
||||
}});
|
||||
}
|
||||
|
||||
format IntSumOp {
|
||||
104: neg({{ ~Ra }}, {{ 1 }});
|
||||
@@ -512,13 +525,26 @@ decode PO default Unknown::unknown() {
|
||||
234: addme({{ Ra }}, {{ -1ULL }}, {{ xer.ca }}, true);
|
||||
}
|
||||
|
||||
235: IntArithCheckRcOp::mullw({{
|
||||
int64_t res = (int64_t)Ra_sw * Rb_sw;
|
||||
if (res != (int32_t)res) {
|
||||
setOV = true;
|
||||
}
|
||||
Rt = res;
|
||||
}}, true);
|
||||
format IntArithCheckRcOp {
|
||||
233: mulld({{
|
||||
int64_t src1 = Ra_sd;
|
||||
int64_t src2 = Rb_sd;
|
||||
uint64_t res = src1 * src2;
|
||||
std::tie(res, std::ignore) = multiply(src1, src2);
|
||||
if (src1 != 0 && (int64_t)res / src1 != src2) {
|
||||
setOV = true;
|
||||
}
|
||||
Rt = res;
|
||||
}}, true);
|
||||
|
||||
235: mullw({{
|
||||
int64_t res = (int64_t)Ra_sw * Rb_sw;
|
||||
if (res != (int32_t)res) {
|
||||
setOV = true;
|
||||
}
|
||||
Rt = res;
|
||||
}}, true);
|
||||
}
|
||||
|
||||
266: IntSumOp::add({{ Ra }}, {{ Rb }});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user