Dear sbcl developers,
first many thanks for providing the x8664 port of SBCL!
I could build it (versions 0.8.18.18 upto 0.8.18.23) without
problems using SBCL 0.8.12 on SuSE Linux 9.0 64Bit (kernel 2.4.21).
Curiously looking through the sources I spotted questionable code
in "src/compiler/x8664/arith.lisp" in the definition of the vop
"fastashc/fixnum=>fixnum", and indeed:
* (defun f (x)
(declare (type fixnum x))
(ash x 61))
F
* (f 1)
8 ; 0 expected
* (defun g (x)
(declare (type fixnum x))
(ash x 100))
G
* (g 1)
0 ; 1 expected
Disassembling f you see that a "sar reg, 64" is generated which doesn't
make much sense. The problem g shows is that negative fixnums are not
considered for shift amounts less than 63.
May I suggest the following fix?
Replace the final part of the vop in question
(cond ((plusp amount)
;; We don't have to worry about overflow because of the
;; result type restriction.
(inst shl result amount))
((zerop amount) )
((< amount 63)
(inst xor result result))
(t
;; shift too far then back again, to zero tag bits
(inst sar result ( 3 amount))
(inst shl result 3)))))))
with
(cond ((plusp amount)
;; We don't have to worry about overflow because of the
;; result type restriction.
(inst shl result amount))
(t
;; Since the shift instructions take the shift amount
;; modulo 64 we must special case amounts of 64 and more.
;; Because fixnums have only 61 bits, the result is 0 or
;; 1 for all amounts of 60 or more, so use this as the
;; limit instead.
(inst sar result (min ( nwordbits nfixnumtagbits 1)
( amount)))
(inst and result (lognot fixnumtagmask))))))))
Yours
Lutz Euler
