From: Sandipan Das Date: Thu, 7 Jun 2018 06:23:03 +0000 (+0530) Subject: arch-power: Add fixed-point doubleword multiply instructions X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=74b12c754cbf01733d17823c0837dc5b59782d15;p=gem5.git arch-power: Add fixed-point doubleword multiply instructions This adds the following arithmetic instructions: * Multiply Low Doubleword (mulld[o][.]) * Multiply High Doubleword (mulhd[.]) * Multiply High Doubleword Unsigned (mulhdu[.]) Change-Id: I505d94dc8e9711c575c94f75e10f7e05e1d05fdf Signed-off-by: Sandipan Das --- diff --git a/src/arch/power/insts/integer.hh b/src/arch/power/insts/integer.hh index 4ffd4691f..6a34184a2 100644 --- a/src/arch/power/insts/integer.hh +++ b/src/arch/power/insts/integer.hh @@ -156,6 +156,46 @@ class IntArithOp : public IntOp { } + /* Compute 128-bit product of 64-bit unsigned integer multiplication */ + inline std::tuple + 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 + 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 SymbolTable *symtab) const override; }; diff --git a/src/arch/power/isa/decoder.isa b/src/arch/power/isa/decoder.isa index cc90f8537..f7ae7ffb2 100644 --- a/src/arch/power/isa/decoder.isa +++ b/src/arch/power/isa/decoder.isa @@ -611,6 +611,30 @@ decode PO default Unknown::unknown() { }}, true); + 73: mulhd({{ + int64_t res; + std::tie(std::ignore, res) = multiply(Ra_sd, Rb_sd); + Rt = res; + }}); + + 9: mulhdu({{ + uint64_t res; + std::tie(std::ignore, res) = multiply(Ra, Rb); + Rt = res; + }}); + + 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); + 491: divw({{ int32_t src1 = Ra_sw; int32_t src2 = Rb_sw;