Replace Bit Field in a 32-bit Register

Code

#include <stdio.h>
#include <stdint.h>
#include <limits.h>

#define MASK(pos, len)   (((1ULL << (pos + len)) - 1) >> pos) << pos

uint32_t replace_field(uint32_t reg, uint32_t val, uint8_t pos, uint8_t len) 
{
    uint32_t rpl_val = (val & ((1 << len) - 1)) << pos;
    reg &= ~((uint32_t)MASK(pos, len));
    reg |= rpl_val;
    return reg;
}

int main() 
{
    uint32_t reg, val;
    uint8_t pos, len;
    scanf("%u %u %hhu %hhu", &reg, &val, &pos, &len);
    printf("%u", replace_field(reg, val, pos, len));
    return 0;
}

Solving Approach

This code is a high-level utility for Read-Modify-Write operations. It allows you to take a specific "slice" or "field" inside a 32-bit register and replace it with a new value without disturbing any of the surrounding bits.

The Three-Step Logic

To replace a bit-field safely, the program follows a "Clear then Insert" strategy:

1. Prepare the New Value (rpl_val)

uint32_t rpl_val = (val & ((1 << len) - 1)) << pos;

  • Sanitize: It first masks the input val to ensure it isn't larger than the allowed len. This prevents the new value from "bleeding" into neighboring fields.

  • Align: It shifts the sanitized value to the left by pos so it sits exactly where it needs to go in the register.

2. Clear the Target Area

reg &= ~((uint32_t)MASK(pos, len));

  • Before inserting the new bits, the code must "clean" the destination. It uses an inverted mask to force the bits in the target range to 0.

  • Think of this as erasing a whiteboard before writing a new message.

3. Insert the Value

reg |= rpl_val;

  • Finally, it uses the Bitwise OR (|) to merge the new aligned value into the now-empty slot in the register.

Step-by-Step Example

Imagine a register controlling a motor's speed in bits 4 to 6 (length 3).

  • Current Register: 242 (Binary: 1111 0010). Note that speed bits [6:4] are 111 (7).

  • New Speed Value: 2 (Binary: 010).

  • Goal: Change speed from 7 to 2 at position 4.

Step

Operation

Result (Binary)

Initial

reg

1111 0010

Clear

reg &= ~(Mask)

1000 0010 (Target bits [6:4] are now 0)

Align

val << 4

0010 0000

Merge

reg | aligned_val

1010 0010

Final

Result: 162

Speed is now 2, other bits are untouched.

Why This Matters for Others

  • Atomic-like Updates: In embedded systems (like controlling an ECU or a GPIO pin), you often need to change one setting (like "Baud Rate") without accidentally changing another (like "Enable Pin"). This code ensures that "surgical" precision.

  • Input Protection: The (val & ((1 << len) - 1)) part is a critical safety feature. If a user tries to put a 4-bit value into a 2-bit field, the code clips the extra bits instead of corrupting the rest of the register.

  • Efficiency: This avoids slow if-else logic or loops. It uses pure bitwise math, which the CPU can execute in a fraction of a nanosecond.

Summary of Constants Used

  • pos: The starting bit index (0–31).

  • len: How many bits the field occupies.

  • val: The new data you want to put into that field.

Upvote
Downvote
Loading...

Input

255 0 4 4

Expected Output

15