arch-x86: Use the new multiplication helpers in the mul uops.

Change-Id: Ib12b2e357fae19455a1a11dd890dda6602a6dc41
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/42361
Reviewed-by: Daniel Carvalho <odanrc@yahoo.com.br>
Maintainer: Gabe Black <gabe.black@gmail.com>
Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
Gabe Black
2021-03-05 23:32:47 -08:00
parent da649727f7
commit e25201b58d
2 changed files with 37 additions and 60 deletions

View File

@@ -102,6 +102,7 @@ using namespace X86ISA;
output exec {{
#include <cmath>
#include <limits>
#include <tuple>
#include "arch/generic/debugfaults.hh"
#include "arch/x86/cpuid.hh"
@@ -112,6 +113,7 @@ output exec {{
#include "arch/x86/tlb.hh"
#include "base/compiler.hh"
#include "base/condcodes.hh"
#include "base/logging.hh"
#include "cpu/base.hh"
#include "cpu/exetrace.hh"
#include "debug/X86.hh"

View File

@@ -584,43 +584,26 @@ let {{
class Mul1s(WrRegOp):
op_class = 'IntMultOp'
# Multiply two values Aa and Bb where Aa = A << p + a, then correct for
# negative operands.
# Aa * Bb
# = (A << p + a) * (B << p + b)
# = (A * B) << 2p + (A * b + a * B) << p + a * b
code = '''
ProdLow = psrc1 * op2;
int p = (dataSize * 8) / 2;
uint64_t A = bits(psrc1, 2 * p - 1, p);
uint64_t a = bits(psrc1, p - 1, 0);
uint64_t B = bits<uint64_t>(op2, 2 * p - 1, p);
uint64_t b = bits<uint64_t>(op2, p - 1, 0);
uint64_t c1, c2; // Carry between place values.
uint64_t ab = a * b, Ab = A * b, aB = a * B, AB = A * B;
c1 = ab >> p;
// Be careful to avoid overflow if p is large.
if (p == 32) {
c2 = (c1 >> 1) + (Ab >> 1) + (aB >> 1);
c2 += ((c1 & 0x1) + (Ab & 0x1) + (aB & 0x1)) >> 1;
c2 >>= (p - 1);
} else {
c2 = (c1 + Ab + aB) >> p;
int64_t hi, low;
switch (dataSize) {
case 8:
std::tie(hi, low) = mulSigned<int64_t>(psrc1, op2);
break;
case 4:
std::tie(hi, low) = mulSigned<int32_t>(psrc1, op2);
break;
case 2:
std::tie(hi, low) = mulSigned<int16_t>(psrc1, op2);
break;
case 1:
std::tie(hi, low) = mulSigned<int8_t>(psrc1, op2);
break;
default:
panic("Unrecognized data size %d.", dataSize);
}
uint64_t hi = AB + c2;
if (bits(psrc1, dataSize * 8 - 1))
hi -= op2;
if (bits(op2, dataSize * 8 - 1))
hi -= psrc1;
ProdHi = hi;
ProdLow = low;
'''
flag_code = '''
if ((-ProdHi & mask(dataSize * 8)) !=
@@ -636,34 +619,26 @@ let {{
class Mul1u(WrRegOp):
op_class = 'IntMultOp'
# Multiply two values Aa and Bb where Aa = A << p + a.
# Aa * Bb
# = (A << p + a) * (B << p + b)
# = (A * B) << 2p + (A * b + a * B) << p + a * b
code = '''
ProdLow = psrc1 * op2;
int p = (dataSize * 8) / 2;
uint64_t A = bits(psrc1, 2 * p - 1, p);
uint64_t a = bits(psrc1, p - 1, 0);
uint64_t B = bits<uint64_t>(op2, 2 * p - 1, p);
uint64_t b = bits<uint64_t>(op2, p - 1, 0);
uint64_t c1, c2; // Carry between place values.
uint64_t ab = a * b, Ab = A * b, aB = a * B, AB = A * B;
c1 = ab >> p;
// Be careful to avoid overflow if p is large.
if (p == 32) {
c2 = (c1 >> 1) + (Ab >> 1) + (aB >> 1);
c2 += ((c1 & 0x1) + (Ab & 0x1) + (aB & 0x1)) >> 1;
c2 >>= (p - 1);
} else {
c2 = (c1 + Ab + aB) >> p;
uint64_t hi, low;
switch (dataSize) {
case 8:
std::tie(hi, low) = mulUnsigned<uint64_t>(psrc1, op2);
break;
case 4:
std::tie(hi, low) = mulUnsigned<uint32_t>(psrc1, op2);
break;
case 2:
std::tie(hi, low) = mulUnsigned<uint16_t>(psrc1, op2);
break;
case 1:
std::tie(hi, low) = mulUnsigned<uint8_t>(psrc1, op2);
break;
default:
panic("Unrecognized data size %d.", dataSize);
}
ProdHi = AB + c2;
ProdHi = hi;
ProdLow = low;
'''
flag_code = '''
if (ProdHi) {