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