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:
-
I added
and shamtto skip the mask logic ifshamtis zero. This is becuase, in C, shifting a 32-bit integer by 32 produces an unspecified result. -
For the Python version only, the mask value needs to be and-ed with
0xffffffffto 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).