This code:
unsigned long f(unsigned long x)
{
return ~0UL >> (32 - x);
}
generates this:
.file "right-shift-bug.c"
.version "01.01"
gcc2_compiled.:
__gnu_compiled_c:
.text
.align 1
.globl f
.type f,@function
f:
.word 0x0
subl3 4(%ap),$32,%r0
mcoml $0,%r1
subb3 %r0,$32,%r2
extzv %r0,%r2,%r1,%r1
movl %r1,%r0
ret
ret
.Lfe1:
.size f,.Lfe1-f
.ident "GCC: (GNU) 2.95.2-linuxvax-20030615"
Note carefully the use of subb3 and extzv to implement
the >> operator. When x is greater than 32, r2 ends up
with a negative value, which extzv interprets as a large
positive value.
If extzv's second argument (bit field size) is > 32 and
the source is a register, it throws a reserved operand
fault.
While the operation of (x >> -6) might not be defined by
the C standard (I don't have a reference handy right now),
I don't think our compiler should be generating code
that throws reserved operand faults.
(This bug was triggered by lib/radix-tree.c:__maxindex()
that appeared in 2.5.62. Workaround is to avoid doing the
right shift if the shift count will be negative.)