I see the following:
ELISP> (= (lsh -1 (lognot 0)) (lsh -2 (lognot 0)))
t
ELISP> (= (lsh -1 (lognot 0)) (lsh -3 (lognot 0)))
nil
The first seems odd to me. Is it really what's expected?
Yes, it's what is expected. The docstring of lsh says:
"(lsh VALUE COUNT) ... If COUNT is negative, shifting is actually to
the right. In this case, if VALUE is a negative fixnum treat it as
unsigned ..."
-1 (decimal) = 111...111 (binary)
-2 (decimal) = 111...110 (binary)
If you shift these two numbers to the right, you get the exact same
result: 011...111, that is, `most-positive-fixnum'.