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 <odanrc@yahoo.com.br> Maintainer: Gabe Black <gabe.black@gmail.com> Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
@@ -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 <int N>
|
||||
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
|
||||
*
|
||||
|
||||
@@ -164,7 +164,8 @@ TEST(BitfieldTest, MbitsEntireRange)
|
||||
|
||||
/*
|
||||
* The following tests the "sext<N>(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<N>(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
|
||||
|
||||
Reference in New Issue
Block a user