0.9.15.22: check for error, do not aver, do not collect $200
[sbcl.git] / src / compiler / x86-64 / move.lisp
index a9a7ec5..4caf11f 100644 (file)
@@ -1,4 +1,4 @@
-;;;; the x86 VM definition of operand loading/saving and the MOVE vop
+;;;; the x86-64 VM definition of operand loading/saving and the MOVE vop
 
 ;;;; This software is part of the SBCL system. See the README file for
 ;;;; more information.
 
 (define-move-fun (load-number 1) (vop x y)
   ((immediate) (signed-reg unsigned-reg))
-  (inst mov y (tn-value x)))
+  (let ((val (tn-value x)))
+    (if (zerop val)
+        (inst xor y y)
+        (inst mov y val))))
 
 (define-move-fun (load-character 1) (vop x y)
   ((immediate) (character-reg))
      (aver (not (location= x y)))
      (let ((bignum (gen-label))
            (done (gen-label)))
-       (inst mov y x)
-       (inst shl y 1)
-       (inst jmp :o bignum)
-       (inst shl y 1)
-       (inst jmp :o bignum)
-       (inst shl y 1)
+       ;; We can't do the overflow check with SHL Y, 3, since the
+       ;; state of the overflow flag is only reliably set when
+       ;; shifting by 1. There used to be code here for doing "shift
+       ;; by one, check whether it overflowed" three times. But on all
+       ;; x86-64 processors IMUL is a reasonably fast instruction, so
+       ;; we can just do a straight multiply instead of trying to
+       ;; optimize it to a shift. This is both faster and smaller.
+       ;; -- JES, 2006-07-08
+       (inst imul y x (ash 1 n-fixnum-tag-bits))
        (inst jmp :o bignum)
        (emit-label done)