Skip to content

Commit

Permalink
[vm/compiler] general rbit utilities
Browse files Browse the repository at this point in the history
Rationale:
Useful to implement the simulator, but also useful
in the future when compiler wants to constant fold
operations related to bit reversal.

#38346

Change-Id: I2f09ba6b1897202b5c07a2cff771afd7bbc99495
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/119703
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Aart Bik <ajcbik@google.com>
  • Loading branch information
aartbik authored and commit-bot@chromium.org committed Oct 2, 2019
1 parent 9e738b9 commit 7e99f49
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 38 deletions.
20 changes: 20 additions & 0 deletions runtime/platform/utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,26 @@ int Utils::HighestBit(int64_t v) {
return r;
}

uint64_t Utils::ReverseBits64(uint64_t x) {
const uint64_t one = static_cast<uint64_t>(1);
uint64_t result = 0;
for (uint64_t rbit = one << 63; x != 0; x >>= 1) {
if ((x & one) != 0) result |= rbit;
rbit >>= 1;
}
return result;
}

uint32_t Utils::ReverseBits32(uint32_t x) {
const uint32_t one = static_cast<uint32_t>(1);
uint32_t result = 0;
for (uint32_t rbit = one << 31; x != 0; x >>= 1) {
if ((x & one) != 0) result |= rbit;
rbit >>= 1;
}
return result;
}

// Implementation according to H.S.Warren's "Hacker's Delight"
// (Addison Wesley, 2002) Chapter 10 and T.Grablund, P.L.Montogomery's
// "Division by Invariant Integers Using Multiplication" (PLDI 1994).
Expand Down
11 changes: 11 additions & 0 deletions runtime/platform/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,17 @@ class Utils {
static int CountLeadingZeros(uword x);
static int CountTrailingZeros(uword x);

static uint64_t ReverseBits64(uint64_t x);
static uint32_t ReverseBits32(uint32_t x);

static uword ReverseBitsWord(uword x) {
#ifdef ARCH_IS_64_BIT
return ReverseBits64(x);
#else
return ReverseBits32(x);
#endif
}

// Computes magic numbers to implement DIV or MOD operator.
static void CalculateMagicAndShiftForDivRem(int64_t divisor,
int64_t* magic,
Expand Down
22 changes: 4 additions & 18 deletions runtime/vm/simulator_arm.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2230,29 +2230,15 @@ void Simulator::DoDivision(Instr* instr) {
}
}

void Simulator::DoRbit(Instr* instr) {
// Format(instr, "rbit'cond 'rd, 'rm");
Register rm = instr->RmField();
Register rd = instr->RdField();
uint32_t bval = static_cast<uint32_t>(get_register(rm));
uint32_t rbit = static_cast<uint32_t>(1) << 31;
int32_t rd_val = 0;
while (bval != 0) {
if (bval & 0x1) {
rd_val |= rbit;
}
bval >>= 1;
rbit >>= 1;
}
set_register(rd, rd_val);
}

void Simulator::DecodeType3(Instr* instr) {
if (instr->IsDivision()) {
DoDivision(instr);
return;
} else if (instr->IsRbit()) {
DoRbit(instr);
// Format(instr, "rbit'cond 'rd, 'rm");
Register rm = instr->RmField();
Register rd = instr->RdField();
set_register(rd, Utils::ReverseBits32(get_register(rm)));
return;
}
Register rd = instr->RdField();
Expand Down
3 changes: 0 additions & 3 deletions runtime/vm/simulator_arm.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,9 +195,6 @@ class Simulator {
// Perform a division.
void DoDivision(Instr* instr);

// Perform bit reversal.
void DoRbit(Instr* instr);

inline uint8_t ReadBU(uword addr);
inline int8_t ReadB(uword addr);
inline void WriteB(uword addr, uint8_t value);
Expand Down
19 changes: 2 additions & 17 deletions runtime/vm/simulator_arm64.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2439,26 +2439,11 @@ void Simulator::DecodeMiscDP1Source(Instr* instr) {
}
case 0: {
// Format(instr, "rbit'sf 'rd, 'rn");
int64_t rd_val = 0;
uint64_t bval;
uint64_t rbit;
if (instr->SFField() == 1) {
bval = static_cast<uint64_t>(rn_val64);
rbit = static_cast<uint64_t>(1) << 63;
} else {
bval = static_cast<uint64_t>(rn_val32);
rbit = static_cast<uint64_t>(1) << 31;
}
while (bval != 0) {
if (bval & 0x1) {
rd_val |= rbit;
}
bval >>= 1;
rbit >>= 1;
}
if (instr->SFField() == 1) {
const uint64_t rd_val = Utils::ReverseBits64(rn_val64);
set_register(instr, rd, rd_val, R31IsZR);
} else {
const uint32_t rd_val = Utils::ReverseBits32(rn_val32);
set_wregister(rd, rd_val, R31IsZR);
}
break;
Expand Down
16 changes: 16 additions & 0 deletions runtime/vm/utils_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,22 @@ VM_UNIT_TEST_CASE(CountZeros) {
EXPECT_EQ(0, Utils::CountLeadingZeros(kTopBit));
}

VM_UNIT_TEST_CASE(ReverseBits32) {
EXPECT_EQ(0xffffffffU, Utils::ReverseBits32(0xffffffffU));
EXPECT_EQ(0xf0000000U, Utils::ReverseBits32(0x0000000fU));
EXPECT_EQ(0x00000001U, Utils::ReverseBits32(0x80000000U));
EXPECT_EQ(0x22222222U, Utils::ReverseBits32(0x44444444U));
EXPECT_EQ(0x1E6A2C48U, Utils::ReverseBits32(0x12345678U));
}

VM_UNIT_TEST_CASE(ReverseBits64) {
EXPECT_EQ(0xffffffffffffffffLLU, Utils::ReverseBits64(0xffffffffffffffffLLU));
EXPECT_EQ(0xf000000000000000LLU, Utils::ReverseBits64(0x000000000000000fLLU));
EXPECT_EQ(0x0000000000000001LLU, Utils::ReverseBits64(0x8000000000000000LLU));
EXPECT_EQ(0x2222222222222222LLU, Utils::ReverseBits64(0x4444444444444444LLU));
EXPECT_EQ(0x8f7b3d591e6a2c48LLU, Utils::ReverseBits64(0x123456789abcdef1LLU));
}

VM_UNIT_TEST_CASE(IsInt) {
EXPECT(Utils::IsInt(8, 16));
EXPECT(Utils::IsInt(8, 127));
Expand Down

0 comments on commit 7e99f49

Please sign in to comment.