On 2004-08-10, Joe Wright <jo********@comcast.net> wrote:
How many years is several? Can you imagine any association between
Shift and Rotate?
I can, but what we're witnessing is definitely *not* a rotate.
Clearly (not?) 'r = (uint32_t)1 << 31' is the
widest shift you can expect to work in C.
I understand that this is how left-shift is *defined*. But it could
easily be defined having shifts larger than the type-width result to
zero. Come to think of it, this is what happens with
constants. Actually your example is *wrong*:
r = (uint32_t)1 << 31
yields:
00000000 00000000 00000000 00000001
while, all of the following:
r = (uint32_t)1 << 32
r = (uint32_t)1 << 33
r = (uint32_t)1 << 34
yield
00000000 00000000 00000000 00000000
The 'problem' appears *only* when the code is written like this:
s = 32;
r = (uint32_t)1 << s;
And what really happens, is that the compiler simply emits the
architecture's left-shift instruction (*not* the rotate instruction),
regardless of the value of "k". The problem is that for *some* 32bit
architectures the left-shift instruction only considers bits bit 4:0
of the register-operand, and *this* explains the behavior
observed. For other architectures the shifter ORs the remaining
operand-register bits together, and if the OR's result is non-zero, it
zeroes the shift's result (guaranteeing this way a more "consistent"
behavior).
The compiler is allowed to *simply* emit the architectural shift
instruction, because the standard explicitly makes shifts more than
the type-width undefined.
In the examples above (with the literals), the compiler has to emit no
shift instructions whatsoever; it simply performs the shift
*internally*. And it this case it does it using the "consistent" way.
/npat