arithmetic right shift with sign extension

I am trying to write a function (in C) the does an arithmetic right shift with sign extension.

The result will be held in R[rd].
the source is R[rs]
the shift amount is R[rt]

In order to simplify my task, I’m trying to write this function in python.

dest functions as R[rd]
source functions as R[rs]
shamt functions as shamt

my try:

dest = 0
source = 0xF5042352
print("source = ", hex(source))

shamt = 1
print(f"shifting {shamt}")

sign_bit = source & 0x80000000
shifted = source >> shamt
if(sign_bit):
    mask = (1 << (32 - shamt)) - 1 # create a mask with 1s from the 32 bit to the 32 - shamt bit
    print("mask = ", hex(mask))
    shifted |= (mask << shamt) # sign extend the number

dest = shifted
print("dest =   ", hex(dest))

I added some prints just to view the variable contents mid.

The way I went about solving my problem is keeping note on the sign of the number source.

if the number was negative before the shift, then I should create a mask with 1’s from the rightmost 1 to the 32′ bit.

However this doesn’t work.
When I shift the number 0xf5042352 by just 1, the resulting dest is:

0xffffffff

My algorithm is wrong, I couldn’t figure out how to fix my implementation, tips would be appreciated

>Solution :

This should work:

dest = 0
source = 0xF5042352
print("source = ", hex(source))

shamt = 1
print(f"shifting {shamt}")

sign_bit = source & 0x80000000
shifted = source >> shamt
if sign_bit and shamt:
    mask = 0xffffffff << (32 - shamt)
    mask &= 0xffffffff  # only needed in python, to force back to 32 bits
    print("mask =   ", hex(mask))
    shifted |= mask     # sign extend the number

dest = shifted
print("dest =   ", hex(dest))

This computes the shifted mask value, which can then be used directly without shifting. Note that:

  1. I added and shamt to skip the mask logic if shamt is zero. This is becuase, in C, shifting a 32-bit integer by 32 produces an unspecified result.

  2. For the Python version only, the mask value needs to be and-ed with 0xffffffff to force it back to a 32-bit value. In C, this won’t be necessary with 32-bit integers (but you should use an unsigned integer for the value being shifted).

Leave a Reply