9
\$\begingroup\$

For homework, I had to parse CPUID instruction output in C, which required a lot of specific bit-manipulation like:

(eax & CACHE_LEVEL) >> 5

I calculated the mask CACHE_LEVEL and the amount that was needed to be right-shifted by hand. It was a pain, so I decided to write a couple Python functions to help with this.

For example:

>>> eax = 0x4004121  # Taken from a register after executing a CPUID instruction with leaf-4 indicated
>>> parse_out_bits(eax, 5, 7)  # Return the value at bits 5 to 7 (inclusive)
1  # This is an L1 cache

Indices are 0-based and inclusive.

Where eax is the following, and I want the value of the bits from S to E:

                        E S
100 0000 0000 0100 0001 0010 0001‬

I'd like notes on anything here, but specifically how this could be done better in terms of bit manipulation.

from typing import Generator

def bit_place_values(start_index: int, end_index: int) -> Generator[int, None, None]:
    acc = 1 << start_index
    for _ in range(start_index, end_index + 1):
        yield acc
        acc <<= 1

def parse_out_bits(bit_field: int, start_index: int, end_index: int) -> int:
    mask = sum(bit_place_values(start_index, end_index))
    return (mask & bit_field) >> start_index
\$\endgroup\$
0

1 Answer 1

10
\$\begingroup\$

This is not the kind of thing you should loop for. Just calculate a mask:

def parse_out_bits(bit_field: int, start_index: int, end_index: int) -> int:
    mask = (1 << (end_index - start_index + 1)) - 1
    return (bit_field >> start_index) & mask

In English:

  • If you're getting bits 5-7, that's 3 bits
  • 2³ == 8, - 1 = 7 (or 111 in binary - that is your mask)
  • Shift the field right by 5 to put the bits of interest in the least-significant position
  • And-mask them to get the result.
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Nice. But gosh, bit arithmetic is hard for me to read. (you've got it quite nice tho) \$\endgroup\$ Commented Jun 3, 2020 at 0:23

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.