I have a homework problem (MIPS simulator) which requires for example that we take a 16-bit "immediate" value and sign and/or zero extend it to 32-bits. I was under the impression that this could be easily accomplished just by casting, such as:
uint32_t imm = (uint16_t)IMM_FIELD(instruction); # Zero extend to 32-bits
and
uint32_t imm = (int16_t)IMM_FIELD(instruction); # Sign extend to 32-bits
But then I came across a piece of code online where someone who worked on the same project had written their own "sign_extension8to16", "sign_extension16to32" functions, and these functions worked by shifting the 8 bit number right by 7 and evaluating whether or not the most significant bit (now in the one's place) was 1, then returning a number that is casted to (uint16_t) which masks the upper 8 bits to 0 or 1 accordingly.
Is such an approach really necessary? I thought that surely casting took care of this already. The reason I ask is that I'm having very strange error messages and I can't pinpoint the problem, so I figure the reason might be that I'm incorrectly zero and sign extending...
IMO: your method will work.
Let's simplify the problem.
The promotion of uint16_t
to uint32_t
and the promotion of int16_t
to int32_t
is easy to understand and the expected results occur. Zero fill unsigned integers and sign extend signed integers.
int main() {
uint16_t u = 65535;
int16_t i = -1;
printf("%" PRIu32 "\n", (uint32_t) u);
printf("%" PRId32 "\n", (int32_t) i);
return 0;
}
65535
-1
The promotion of int16_t
to uint32_t
will first promote the int16_t
to a int32_t
and then to a uint32_t
. (Actually I think it promote first to int16_t
to int
to int32_t
and then to a uint32_t
if sizeof int <= sizeof int32_t
.) Thus code does a sign-extension before making the result an unsigned integer.
The promotion of uint16_t
to int32_t
will promote the uint16_t
directly to a int32_t
. A simple zero extension.
Note: I could be using "promote", when I should say "convert".
int main() {
uint16_t u = 65535;
int16_t i = -1;
printf("%" PRIu32 "\n", (uint32_t) i);
printf("%" PRId32 "\n", (int32_t) u);
return 0;
}
4294967295
65535
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With