From caaffa861c46a50834678621ab39f5be9aa2accc Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 6 Mar 2021 23:25:15 -0800 Subject: [PATCH] base: Add a szext function for true sign extension. The existing sext function is a bit of a misnomer since it doesn't actually sign extend its input, it just extends the sign if the sign bit was zero. This change adds a new szext function which truly sign extends the value, although with a tiny amount of additional overhead. Change-Id: I562ce479b771be8a3319934aeff55e797126a146 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/42384 Reviewed-by: Daniel Carvalho Maintainer: Gabe Black Tested-by: kokoro --- src/base/bitfield.hh | 22 +++++++++++++++++++++- src/base/bitfield.test.cc | 33 ++++++++++++++++++++++++++++++++- 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/src/base/bitfield.hh b/src/base/bitfield.hh index 9dc7722998..d47ab8c594 100644 --- a/src/base/bitfield.hh +++ b/src/base/bitfield.hh @@ -112,7 +112,9 @@ mask(unsigned first, unsigned last) } /** - * Sign-extend an N-bit value to 64 bits. + * Sign-extend an N-bit value to 64 bits. Assumes all bits past the sign are + * currently zero. For true sign extension regardless of the value of the sign + * bit, see szext. * * @ingroup api_bitfield */ @@ -126,6 +128,24 @@ sext(uint64_t val) return val; } +/** + * Sign-extend an N-bit value to 64 bits. Zero any bits past the sign if + * necessary. + * + * @ingroup api_bitfield + */ +template +constexpr inline uint64_t +szext(uint64_t val) +{ + bool sign_bit = bits(val, N - 1); + if (sign_bit) + val |= ~mask(N); + else + val &= mask(N); + return val; +} + /** * Returns val with bits first to last set to the LSBs of bit_val * diff --git a/src/base/bitfield.test.cc b/src/base/bitfield.test.cc index 8097415217..c2ef8d2b6f 100644 --- a/src/base/bitfield.test.cc +++ b/src/base/bitfield.test.cc @@ -164,7 +164,8 @@ TEST(BitfieldTest, MbitsEntireRange) /* * The following tests the "sext(X)" function. sext carries out a sign - * extention from N bits to 64 bits on value X. + * extention from N bits to 64 bits on value X. It does not zero bits past the + * sign bit if it was zero. */ TEST(BitfieldTest, SignExtendPositiveInput) { @@ -191,6 +192,36 @@ TEST(BitfieldTest, SignExtendNegativeInputOutsideRange) uint64_t output = 0xF800000010000008; EXPECT_EQ(output, sext<60>(val)); } +/* + * The following tests the "szext(X)" function. szext carries out a sign + * extention from N bits to 64 bits on value X. Will zero bits past the sign + * bit if it was zero. + */ +TEST(BitfieldTest, SignZeroExtendPositiveInput) +{ + int8_t val = 14; + int64_t output = 14; + EXPECT_EQ(output, szext<8>(val)); +} + +TEST(BitfieldTest, SignZeroExtendNegativeInput) +{ + int8_t val = -14; + uint64_t output = -14; + EXPECT_EQ(output, szext<8>(val)); +} + +TEST(BitfieldTest, SignZeroExtendPositiveInputOutsideRange) +{ + EXPECT_EQ(0, szext<8>(1 << 10)); +} + +TEST(BitfieldTest, SignZeroExtendNegativeInputOutsideRange) +{ + uint64_t val = 0x4800000010000008; + uint64_t output = 0xF800000010000008; + EXPECT_EQ(output, szext<60>(val)); +} /* The following tests "insertBits(A, B, C, D)". insertBits returns A * with bits B to C set to D's (B - C) LSBs. "insertBits(A, B, D)" overrides