From 1b8b84be82ebb9fb86ddd5159c7a36067ee27257 Mon Sep 17 00:00:00 2001
From: Raymond Toy <toy.raymond@gmail.com>
Date: Tue, 1 Dec 2015 21:41:49 -0800
Subject: [PATCH] Handle large (fixed) shift amounts for the digit shifters.

Make the vops handle the case when the known constant shift amount is
so large that the result is a known value.  Plus, the instructions
have a fixed immediate argument size and the amount is taken mod 32
which would produce the wrong result if the actual shift amount were
used.
---
 src/compiler/x86/arith.lisp | 29 ++++++++++++++++++++++++-----
 1 file changed, 24 insertions(+), 5 deletions(-)

diff --git a/src/compiler/x86/arith.lisp b/src/compiler/x86/arith.lisp
index c01faf07f..13c04250a 100644
--- a/src/compiler/x86/arith.lisp
+++ b/src/compiler/x86/arith.lisp
@@ -1459,29 +1459,48 @@
        (move ecx count)
        (inst sar result :cl))
       (immediate
-       (inst sar result (tn-value count))))))
+       (let ((amount (tn-value count)))
+	 ;; If the amount is greater than 31, it's the same as
+	 ;; shifting by 31, leaving just the sign bit.
+	 (inst sar result (if (>= amount vm:word-bits)
+			      (1- vm:word-bits)
+			      amount)))))))
 
 (define-vop (digit-lshr digit-ashr)
   (:translate bignum::%digit-logical-shift-right)
   (:generator 2
-    (move result digit)
     (sc-case count
       (unsigned-reg
+       (move result digit)
        (move ecx count)
        (inst shr result :cl))
       (immediate
-       (inst shr result (tn-value count))))))
+       (let ((amount (tn-value count)))
+	 ;; If the amount is greater than 31, the result is 0 because
+	 ;; all the bits get shifted right and out.
+	 (cond ((>= amount vm:word-bits)
+		(inst mov result 0))
+	       (t
+		(move result digit)
+		(inst shr result count))))))))
 
 (define-vop (digit-ashl digit-ashr)
   (:translate bignum::%ashl)
   (:generator 2
-    (move result digit)
     (sc-case count
       (unsigned-reg
+       (move result digit)
        (move ecx count)
        (inst shl result :cl))
       (immediate
-       (inst shl result (tn-value count))))))
+       (let ((amount (tn-value count)))
+	 ;; If the amount is greater than 31, the result is 0 because
+	 ;; all the bits get shifted left and out.
+	 (cond ((>= amount vm:word-bits)
+		(inst mov result 0))
+	       (t
+		(move result digit)
+		(inst shl result amount))))))))
 
 
 ;;;; Static functions.
-- 
GitLab