From dc08c52552a48b68c811baea929a70d40a723a4c Mon Sep 17 00:00:00 2001 From: Sandipan Das Date: Sat, 6 Feb 2021 17:17:45 +0530 Subject: [PATCH] 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 --- src/arch/power/insts/integer.hh | 43 +++++++++++++++++++++++++++++++++ src/arch/power/isa/decoder.isa | 24 ++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/src/arch/power/insts/integer.hh b/src/arch/power/insts/integer.hh index a75f38b0c..12ad8fc99 100644 --- a/src/arch/power/insts/integer.hh +++ b/src/arch/power/insts/integer.hh @@ -154,6 +154,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 + 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 Loader::SymbolTable *symtab) const override; }; diff --git a/src/arch/power/isa/decoder.isa b/src/arch/power/isa/decoder.isa index ff4fecea9..13bbe87c7 100644 --- a/src/arch/power/isa/decoder.isa +++ b/src/arch/power/isa/decoder.isa @@ -557,6 +557,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; -- 2.30.2