Extraction of directory and page bits off a linear address - c

As many sources say that using ((1 << x) -1) << y isolates x bits
starting from y to y + x, and a linear address is built like this: 0:11 is the offset, 12:21 is the page and 22:31is the directory.
However, when I use the bit mask above and try to extract the directory for example, it doesn't seem to work at all.
/* unsigned address */
#define MASK_DIR ((1u << 9) - 1) << 22
int main(void)
{
unsigned int dir;
uint32_t addr = 0x12345678;
dir = MASK_DIR & addr;
printf("%#x", dir); // 0x12000000
}
Extracting the offset works well when using (1u << 11) - 1 with the same process as above.

As #Gerhardh corrected my false calculation in which I thought 0-11 is 11 bits even though it's 12. With that said I was able to isolate all the required bits from the 32-bit address, with the following macros
#define ADDR_PAGE(addr) ((((1u << 10) - 1) << 12) & addr)
#define ADDR_DIR(addr) ((((1u << 10) - 1) << 22) & addr)
#define ADDR_OFF(addr) (((1u << 12) - 1) & addr)
Output
0x678 - 0x345000 - 0x12000000 (offset, page, dir)

Related

Most correct way for bit checking in C

I reading a book "Linux Kernel. Development. Third Edition." by Robert Love.
And in softirq section it's comment next piece of code:
u32 pending;
pending = local_softirq_pending();
if (pending) {
struct softirq_action *h;
/* reset the pending bitmask */
set_softirq_pending(0);
h = softirq_vec;
do {
if (pending & 1) /* STEP 4 */
h->action(h);
h++;
pending >>= 1;
} while (pending);
}
He discribe step by step what happens and most unclear step for me is 4:
If the first bit in pending is set, h->action(h) is called
I have following code to check if bit set like in book:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define BIT_SET(n) ((1) << (n))
#define BIT_CLEAR(n) ~((1) << (n))
int main(void)
{
unsigned char bits = 0x0;
bits |= BIT_SET(1);
if (bits & (1 << 1))
printf("TEST CHECK SET 1\n");
if (bits & 1)
printf("TEST CHECK SET 2\n");
bits &= BIT_CLEAR(1);
if (!(bits >> 1) & 1UL)
printf("BITS UNSET\n");
return 0;
}
compiled with:
gcc main.c -O0 -Wall -Wextra -Werror.
I always check if bit set with this one:
if (bits & (1 << n))
And my code make output like this:
TEST CHECK SET 1
BITS UNSET
Why if (bits & 1) statment is not work?:
So from several option which should I use and what exactly last one check?
if (bit & (1 << n))
if ((bit >> n) & 1)
if (bit & n)
I always check if bit set with this one: if (bits & (1 << n))
This checks n-th bit in place; the code from the book, however, shifts the bit into the least-significant-bit position prior to making the check with bits & 1. In other words, by the time the code reaches the if (bits & 1) the value of bits has already been shifted such that the bit of interest is in 1-s position.
This is similar to your other check
if ((bit >> n) & 1)
except (bit >> n) part is done by performing bit >>= 1 operation n times in a loop.
Note that in order for this code to work correctly bit must be unsigned.
So from several option which should I use and what exactly last one check?
You misinterpreted the last check: it's not checking bit n, it's checking bit against the entire bit pattern of n's binary representation.

What is doing this bitwise operation in order to emulate a RRC instruction

I'm working on a personal project to improve my knowledge on how a CPU works. So I'm doing a Intel 8080 emulator, which is a 8 bits microprocessor.
In the implementation of a RRC instruction, which example is this:
case 0x0f: {
uint8_t x = state->a;
state->a = ((x & 1) << 7) | (x >> 1);
state->cc.cy = (1 == (x&1));
}
I can't understand how this line is working.
state->a = ((x & 1) << 7) | (x >> 1);
I know it's supposed to move all the bits to the right by 1 position, but I can't figure out how.
I would appreciate if someone could provide me an example of what it's actually doing step by step.
state->a is a uint8_t which emulate the intel 8080 register named
A.
0x0f is the HEX value for RRC.
The example has been provided by this page.
Lets study the steps in order:
uint8_t x = state->a; Use a temporary variable for the current value of the A register;
(x & 1) << 7 shift the low order bit to the high order bit; (x & 1) is the value of the low order bit as all other bits of x are masked off.
(x >> 1) shift the other bits one place to the right (towards the lower bits).
state->a = ((x & 1) << 7) | (x >> 1); combine the bits from the previous 2 steps and store as the new value of the A register;
state->cc.cy = (1 == (x&1)); store the low order bit from the original value into the carry bit (this is the bit that was rotated into the high order bit).
The effect of these steps is a rotation of the 8 bits one step to the right, with the low order bit landing into the carry flag. The 8080 reference card describes this as Rotate Accumulator Right thru Carry.
Note that the steps can be simplified:
state->a = ((x & 1) << 7) | (x >> 1); is the same as state->a = (x << 7) | (x >> 1); because state->a is a uint8_t.
state->cc.cy = (1 == (x&1)) is the same as state->cc.cy = x & 1;

Find the base 2 logarithm of the next power of 2 of an integer

I've run into this a bunch, and it seems like there should be a better way to do this. I'd like to use bit twiddling to accomplish something equivalent to the following:
uint8_t nextlog(uint32_t n) {
return (uint8_t) ceil(log2(n)) + 1;
}
Example usage:
nextlog(0) -> undefined
nextlog(1) == 1
nextlog(3) == 3 // 0b11 -{next power 2}-> 0b100 -{log2+1}-> 3
nextlog(32) == 6 // 0b00100000 -{log2+1}-> 6
nextlog(71) == 8 // 0b01000111 --> 0b10000000 -> 8
The best I've come up with is to combine the "Round up to the next highest power of 2" and "Finding integer log base 2 of an integer" from the well-known bit twiddling hacks reference. I suppose it's also worth noting that __builtin_clz could help accomplish the latter part of the question.
You want 32 - clz(x), despite your claim to the contrary.
You claim that log2 0b100 is 3, this is the error in your math. The correct answer is 2.
It's not in the "bit twiddling hacks" page, but I found this:
int clz(uint32_t x) {
x |= x >> 1;
x |= x >> 2;
x |= x >> 4;
x |= x >> 8;
x |= x >> 16;
return 32 - popcount(x);
}
int popcount(uint32_t x) {
x = x - ((x >> 1) & 0x55555555);
x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
return (((x + (x >> 4)) & 0x0f0f0f0f) * 0x01010101) >> 24;
}
Note that I'm sure that the performance is somewhat terrible, compared to what should be little more than ffs on x86.
See: http://aggregate.org/MAGIC/#Leading%20Zero%20Count
Per #Mark Dickinson's comment, the obvious solution with a single branch is as follows:
uint8_t nextlog(uint32_t n) {
if (n == 1) return 1;
return 33 - __builtin_clz(n - 1);
}

Switching bits in each nibble of an int

How can I switch the 0th and 3rd bits of each nibble in an integer using only bit operations (no control structures)? What kind of masks do I need to create in order to solve this problem? Any help would be appreciated. For example, 8(1000) become 1(0001).
/*
* SwitchBits(0) = 0
* SwitchBits(8) = 1
* SwitchBits(0x812) = 0x182
* SwitchBits(0x12345678) = 0x82a4c6e1
* Legal Operations: ! ~ & ^ | + << >>
*/
int SwitchBits(int n) {
}
Code:
#include <stdio.h>
#include <inttypes.h>
static uint32_t SwitchBits(uint32_t n)
{
uint32_t bit0_mask = 0x11111111;
uint32_t bit3_mask = 0x88888888;
uint32_t v_bit0 = n & bit0_mask;
uint32_t v_bit3 = n & bit3_mask;
n &= ~(bit0_mask | bit3_mask);
n |= (v_bit0 << 3) | (v_bit3 >> 3);
return n;
}
int main(void)
{
uint32_t i_values[] = { 0, 8, 0x812, 0x12345678, 0x9ABCDEF0 };
uint32_t o_values[] = { 0, 1, 0x182, 0x82A4C6E1, 0x93B5D7F0 };
enum { N_VALUES = sizeof(o_values) / sizeof(o_values[0]) };
for (int i = 0; i < N_VALUES; i++)
{
printf("0x%.8" PRIX32 " => 0x%.8" PRIX32 " (vs 0x%.8" PRIX32 ")\n",
i_values[i], SwitchBits(i_values[i]), o_values[i]);
}
return 0;
}
Output:
0x00000000 => 0x00000000 (vs 0x00000000)
0x00000008 => 0x00000001 (vs 0x00000001)
0x00000812 => 0x00000182 (vs 0x00000182)
0x12345678 => 0x82A4C6E1 (vs 0x82A4C6E1)
0x9ABCDEF0 => 0x93B5D7F0 (vs 0x93B5D7F0)
Note the use of uint32_t to avoid undefined behaviour with sign bits in signed integers.
To obtain a bit, you can mask it out using AND. To get the lowest bit, for example:
x & 0x01
Think about how AND works: both bits must be set. Since we're ANDing with 1, all bits except the first must be 0, because they're 0 in 0x01. The lowest bit will be either 0 or 1, depending on what's in x; said differently, the lowest bit will be the lowest bit in x, which is what we want. Visually:
x = abcd
AND 1 = 0001
--------
000d
(where abcd represent the bits in those slots; we don't know what they are)
To move it to bit 3's position, just shift it:
(x & 0x01) << 3
Visually, again:
x & 0x01 = 000d
<< 3
-----------
d000
To add it in, first, we need to clear out that spot in x for our bit. We use AND again:
x & ~0x08
Here, we invert 0x08 (which is 1000 in binary): this means all bits except bit 3 are set, and when we AND that with x, we get x except for that bit.
Visually,
0x08 = 1000
(invert)
-----------
0111
AND x = abcd
------------
0bcd
Combine with OR:
(x & ~0x08) | ((x & 0x01) << 3)
Visually,
x & ~0x08 = 0bcd
| ((x & 0x01) << 3) = d000
--------------------------
dbcd
Now, this only moves bit 0 to bit 3, and just overwrites bit 3. We still need to do bit 3 → 0. That's simply another:
x & 0x08 >> 3
And we need to clear out its spot:
x & ~0x01
We can combine the two clearing pieces:
x & ~0x09
And then:
(x & ~0x09) | ((x & 0x01) << 3) | ((x & 0x08) >> 3)
That of course handles only the lowest nibble. I'll leave the others as an exercise.
Try below code . Here you should know bitwise operator to implement and correct position to place.Also needs to aware of maintenance ,shifting and toggling basic properties.
#include<stdio.h>
#define BITS_SWAP(x) x=(((x & 0x88888888)>>3) | ((x & 0x11111111)<<3)) | ((x & ~ (0x88888888 | 0x11111111)))
int main()
{
int data=0;
printf("enter the data in hex=0x");
scanf("%x",&data);
printf("bits=%x",BITS_SWAP(data));
return 0;
}
OP
vinay#vinay-VirtualBox:~/c_skill$ ./a.out
enter the data in hex=0x1
bits=8
vinay#vinay-VirtualBox:~/c_skill$ ./a.out
enter the data in hex=0x812
bits=182
vinay#vinay-VirtualBox:~/c_skill$ ./a.out
enter the data in hex=0x12345678
bits=82a4c6e1
vinay#vinay-VirtualBox:~/c_skill$
Try this variant of the xor swap:
uint32_t switch_bits(uint32_t a){
static const mask = 0x11111111;
a ^= (a & mask) << 3;
a ^= (a >> 3) & mask;
a ^= (a & mask) << 3;
return a;
}
Move the low bits to the high bits and mask out the resulting bits.
Move the high bits to the low bits and mask out the resulting bits.
Mask out all bits that have not been moved.
Combine the results with ORs.
Code:
unsigned SwitchBits(unsigned n) {
return ((n << 3) & 0x88888888) | ((n >> 3) & 0x11111111) | (n & 0x66666666);
}
Alternativly, if you would like to be very clever. It can be done with two fewer operations, though this may not actually be faster due to some of the dependicies between instrutions.
Move the high bits to align with the low bits
XOR recording a 0 in the low bit if high an low bits are the same, and a 1 if they are different.
From this, mask out only the low bit of each nibble.
From this, multiply by 9, this will keep the low bit as is, and also copy it to the high bit.
From this, XOR with the original value. in the case that the high and low bit are the same, no change will correctly occure. In the case they are different, they will be effectivly exchanged.
Code:
unsigned SwitchBits(unsigned n) {
return ((((n >> 3) ^ n) & 0x11111111) * 0x9) ^ n;
}

How to break 32 bit value and assign it to three different data types.?

I have a
#define PROT_EN_DAT 0x140
//(320 in decimal)
Its loaded into 64 bit value register(ex setup_data[39:8]=PROT_EN_DATA)
Now i want to put this value(0x140)into
uint8_t bRequest
uint16_t wValue
uint16_t wIndex
How can load the value so that i don't have to manually do it for other values again.
I think we can do with shift operators but don know how.
EDIT:Ya its related to USB. bRequest(8:15),wValue(16:31),wIndex(32:47) but setup_data is 64 bit value.I want to know how can i load proper values into the these fields.
For example say next time i am using #define PROT_EN2_REG 0x1D8.
and say setup_data[39:8]=PROT_EN2_DATA
General read form:
aField = (aRegister >> kBitFieldLSBIndex) & ((1 << kBitFieldWidth) - 1)
General write form:
mask = ((1 << kBitFieldWidth) - 1) << kBitFieldLSBIndex;
aRegister = (aRegister & ~mask) | ((aField << kBitFieldLSBIndex) & mask);
where:
aRegister is the value you read from the bit-field-packed register,
kBitFieldLSBIndex is the index of the least significant bit of the bit field, and
kBitFieldWidth is the width of the bit field, and
aField is the value of the bit field
These are generalized, and some operations (such as bit-masking) may be unnecessary in your case. Replace the 1 with 1L if the register is larger than 32 bits.
EDIT: In your example case (setup_data[39:8]=PROT_EN_DATA):
Read:
aField = (setup_data >> 8) & ((1L << 32) - 1L)
Write:
#define PROT_EN_MASK = (((1L << 32) - 1L) << 8) // 0x0000000FFFFFFFF0
setup_data = (setup_data & ~PROT_EN_MASK) | ((PROT_EN_DATA << 8) & PROT_EN_MASK);

Resources