From: Sandipan Das Date: Thu, 7 Jun 2018 06:30:28 +0000 (+0530) Subject: arch-power: Add fixed-point doubleword multipy-add instructions X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=b966944f38b1ef304a2eeab22342e7b32c403109;p=gem5.git arch-power: Add fixed-point doubleword multipy-add instructions This adds the following arithmetic instructions: * Multiply-Add Low Doubleword (maddld) * Multiply-Add High Doubleword (maddhd) * Multiply-Add High Doubleword Unsigned (maddhdu) Change-Id: I09ecca9f3eb0abaf6b5a82a6d33d7f3e54b9837b Signed-off-by: Sandipan Das --- diff --git a/src/arch/power/insts/integer.cc b/src/arch/power/insts/integer.cc index 638634972..e5692bb22 100644 --- a/src/arch/power/insts/integer.cc +++ b/src/arch/power/insts/integer.cc @@ -110,6 +110,7 @@ IntArithOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const { stringstream ss; bool printSecondSrc = true; + bool printThirdSrc = false; // Generate the correct mnemonic string myMnemonic(mnemonic); @@ -121,6 +122,10 @@ IntArithOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const !myMnemonic.compare("subfze") || !myMnemonic.compare("neg")){ printSecondSrc = false; + } else if (!myMnemonic.compare("maddhd") || + !myMnemonic.compare("maddhdu") || + !myMnemonic.compare("maddld")) { + printThirdSrc = true; } // Additional characters depending on isa bits being set @@ -144,6 +149,12 @@ IntArithOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const if (_numSrcRegs > 1 && printSecondSrc) { ss << ", "; printReg(ss, _srcRegIdx[1]); + + // Print the third source register + if (_numSrcRegs > 2 && printThirdSrc) { + ss << ", "; + printReg(ss, _srcRegIdx[2]); + } } } diff --git a/src/arch/power/insts/integer.hh b/src/arch/power/insts/integer.hh index 63e9501e8..538750215 100644 --- a/src/arch/power/insts/integer.hh +++ b/src/arch/power/insts/integer.hh @@ -154,6 +154,52 @@ class IntArithOp : public IntOp { } + /* Compute 128-bit sum of 128-bit to 64-bit unsigned integer addition */ + inline std::tuple + 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 + 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 */ inline std::tuple multiply(uint64_t ra, uint64_t rb) const @@ -194,6 +240,44 @@ 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 + 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 + 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 SymbolTable *symtab) const override; }; diff --git a/src/arch/power/isa/decoder.isa b/src/arch/power/isa/decoder.isa index baabc41f6..83e3efca2 100644 --- a/src/arch/power/isa/decoder.isa +++ b/src/arch/power/isa/decoder.isa @@ -225,6 +225,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 IntImmOp { 10: cmpli({{ Xer xer = XER;