Index: /branches/ia32/level-0/X86/X8632/x8632-bignum.lisp
===================================================================
--- /branches/ia32/level-0/X86/X8632/x8632-bignum.lisp	(revision 7913)
+++ /branches/ia32/level-0/X86/X8632/x8632-bignum.lisp	(revision 7914)
@@ -6,21 +6,15 @@
 ;;; The easiest thing to do is to store the 32 raw bits in two fixnums
 ;;; and return multiple values.
+;;; XXX -- figure out how we're going to handle multiple-values...
 (defx8632lapfunction %bignum-ref ((bignum arg_y) (i arg_z))
+  (movl (% esp) (% temp0))
+  (movzwl (@ (+ 2 x8632::misc-data-offset) (% bignum) (% i)) (% imm0))
+  (box-fixnum imm0 temp1)
+  (push (% temp1))			;high
   (movzwl (@ x8632::misc-data-offset (% bignum) (% i)) (% imm0))
-  (box-fixnum imm0 temp1)		;low
-  (movzwl (@ (+ 2 x8632::misc-data-offset) (% bignum) (% i)) (% imm0))
-  (box-fixnum imm0 temp0)		;high
-  (push (% temp0))
-  (push (% temp1))
+  (box-fixnum imm0 temp1)
+  (push (% temp1))			;low
   (set-nargs 2)
   (jmp-subprim .SPvalues))
-
-;;; Set the 0th element of DEST (a bignum or some other 32-bit ivector)
-;;; to the Ith element of the bignum SRC.
-(defx8632lapfunction %ref-digit ((bignum 4) #|(ra 0)|# (i arg_y) (dest arg_z))
-  (movl (@ bignum (% esp)) (% temp0))
-  (movl (@ x8632::misc-data-offset (% temp0) (% i)) (% imm0))
-  (svset dest 0 imm0)
-  (single-value-return 3))
 
 ;;; BIGNUM[I] := DIGIT[0]
@@ -31,25 +25,9 @@
   (single-value-return 3))
 
-;;; Return 0 if the 0th digit in X is 0.
-(defx8632lapfunction %digit-zerop ((x arg_z))
-  (svref x 0 imm0)
-  (movl ($ x8632::nil-value) (% arg_z))
-  (testl (% imm0) (% imm0))
-  (cmovzl (% imm0) (% arg_z))
-  (single-value-return))
-
-;;; store the sign of bignum (0 or -1) in the one-word bignum "digit".
-(defx8632lapfunction %bignum-sign-digit ((bignum arg_y) (digit arg_z))
-  (vector-length bignum imm0)
-  (movl (@ (- 4 x8632::misc-data-offset) (% bignum) (% imm0)) (% imm0))
-  (shr ($ 31) (% imm0))			       ;propagate sign bit
-  (svset digit 0 imm0)
-  (single-value-return))
-
 ;;; Return the sign of bignum (0 or -1) as a fixnum
 (defx8632lapfunction %bignum-sign ((bignum arg_z))
   (vector-length bignum imm0)
-  (movl (@ (- 4 x8632::misc-data-offset) (% bignum) (% imm0)) (% imm0))
-  (shr ($ 31) (% imm0))			       ;propagate sign bit
+  (movl (@ (- x8632::misc-data-offset 4) (% bignum) (% imm0)) (% imm0))
+  (sarl ($ 31) (% imm0))		;propagate sign bit
   (box-fixnum imm0 arg_z)
   (single-value-return))
@@ -58,6 +36,6 @@
 ;;; return fixnum count.
 (defx8632lapfunction %bignum-sign-bits ((bignum arg_z))
-  (vector-size bignum imm0 imm0)
-  (movl (@ (- x8632::misc-data-offset 4) (% bignum) (% imm0) 4) (% imm0))
+  (vector-length bignum imm0)
+  (movl (@ (- x8632::misc-data-offset 4) (% bignum) (% imm0)) (% imm0))
   (mark-as-imm temp0)
   (movl (% imm0) (% temp0))
@@ -78,6 +56,7 @@
   (movl (@ x8632::misc-data-offset (% bignum) (% idx)) (% imm0))
   (movl ($ x8632::nil-value) (% temp0))
+  (leal (@ x8632::t-offset (% temp0)) (% arg_z))
   (testl (% imm0) (% imm0))
-  (cmovsl (% temp0) (% arg_z))
+  (cmovll (% temp0) (% arg_z))
   (single-value-return))
 
@@ -86,32 +65,30 @@
   (movl (@ x8632::misc-data-offset (% bignum)) (% imm0))
   (movl ($ x8632::nil-value) (% temp0))
-  (btl ($ 0) (% imm0))			;copy bit 0 to carry flag
-  (cmovncl (% temp0) (% arg_z))
+  (leal (@ x8632::t-offset (% temp0)) (% arg_z))
+  (testb ($ 1) (% imm0.b))
+  (cmovzl (% temp0) (% arg_z))
   (single-value-return))
 
 (defx8632lapfunction bignum-plusp ((bignum arg_z))
   (vector-length bignum imm0)
-  (movl (@ (- 4 x8632::misc-data-offset) (% bignum)) (% imm0))
-  (movl ($ x8632::nil-value) (% temp0))
-  (cmpl ($ 1) (% imm0))
-  (cmovbl (% temp0) (% arg_z))
-  (single-value-return))
-
-(defx8632lapfunction %fixnum-to-bignum-set ((bignum arg_y) (fixnum arg_z))
-  (unbox-fixnum fixnum imm0)
-  (movl (% imm0) (@ x8632::misc-data-offset (% bignum)))
+  (movl (@ (- x8632::misc-data-offset 4) (% bignum) (% imm0)) (% imm0))
+  (movl ($ x8632::nil-value) (% temp0))
+  (lea (@ x8632::t-offset (% temp0)) (% arg_z))
+  (testl (% imm0) (% imm0))
+  (cmovlel (% temp0) (% arg_z))
   (single-value-return))
 
 (defx8632lapfunction bignum-minusp ((bignum arg_z))
   (vector-length bignum imm0)
-  (movl (@ (- 4 x8632::misc-data-offset) (% bignum) (% imm0)) (% imm0))
-  (movl ($ x8632::nil-value) (% temp0))
+  (movl (@ (- x8632::misc-data-offset 4) (% bignum) (% imm0)) (% imm0))
+  (movl ($ x8632::nil-value) (% temp0))
+  (lea (@ x8632::t-offset (% temp0)) (% arg_z))
   (testl (% imm0) (% imm0))
-  (cmovnsl (% temp0) (% arg_z))
-  (single-value-return))
-
-;;; Add the digits A[I] and B[J], and the incoming carry C (a fixnum).
-;;; Store the result in R[K], and return the outgoing carry.
-;;; If I is NIL, A is a fixnum.  If J is NIL, B is a fixnum.
+  (cmovgl (% temp0) (% arg_z))
+  (single-value-return))
+
+;;; Add the digits A[I] and B[J], and the incoming carry C (a fixnum,
+;;; either 0 or 1).  Store the result in R[K], and return the outgoing
+;;; carry.  If I is NIL, A is a fixnum.  If J is NIL, B is a fixnum.
 (defx8632lapfunction %add-with-carry ((r 20) (k 16) (c 12) (a 8) (i 4) #|(ra 0)|# (b arg_y) (j arg_z))
   (mark-as-imm temp0)
@@ -130,5 +107,5 @@
   ;; unboxed a or a[i] now in temp0
   ;; unboxed b or b[j] now in imm0
-  (movl ($ x8632::fixnumone) (% arg_z))	;for outgoing carry
+  (movl ($ '1) (% arg_z))		;for outgoing carry
   (movl (@ c (% esp)) (% arg_y))
   (testl (% arg_y) (% arg_y))		;clears carry flag
@@ -142,5 +119,5 @@
   (movl (@ k (% esp)) (% temp1))
   (movl (% imm0) (@ x8632::misc-data-offset (% temp0) (% temp1)))
-  (cmovnc (% arg_y) (% arg_z))		;outgoing carry
+  (cmovnc (% arg_y) (% arg_z))		;zero outgoing carry if no carry
   (mark-as-node temp0)
   (single-value-return 7))
@@ -164,5 +141,5 @@
   ;; unboxed a or a[i] now in temp0
   ;; unboxed b or b[j] now in imm0
-  (movl ($ x8632::fixnumone) (% arg_z))	;for outgoing carry
+  (movl ($ '1) (% arg_z))		;for outgoing carry
   (movl (@ borrow (% esp)) (% arg_y))
   (testl (% arg_y) (% arg_y))		;clears carry flag
@@ -176,5 +153,55 @@
   (movl (@ k (% esp)) (% temp1))
   (movl (% imm0) (@ x8632::misc-data-offset (% temp0) (% temp1)))
-  (cmovnc (% arg_y) (% arg_z))		;outgoing carry
+  (cmovnc (% arg_y) (% arg_z))		;zero outgoing carry if no carry
   (mark-as-node temp0)
   (single-value-return 7))
+
+;;; To normalize a bignum is to drop "trailing" digits which are
+;;; redundant sign information.  When return-fixum-p is t, make
+;;; the resultant bignum into a fixnum if it fits.
+(defx8632lapfunction %normalize-bignum-2 ((return-fixnum-p arg_y) (bignum arg_z))
+  (push (% return-fixnum-p))
+  (mark-as-imm temp0)
+  (mark-as-imm temp1)
+  ;; %zero-trailing-sign-digits
+  (let ((len arg_y)
+	(sign temp0)
+	(next temp1))
+    (vector-length bignum len)
+    (cmpl ($ '1) (% len))
+    (jle @maybe-fixnumize)
+    ;; next-to-last digit
+    (movl (@ (- x8632::misc-data-offset 8) (% bignum) (% len)) (% next))
+    ;; last digit
+    (movl (@ (- x8632::misc-data-offset 4) (% bignum) (% len)) (% sign))
+    (jmp @test)
+    @loop
+    (subl ($ '1) (% len))
+    (movl ($ 0) (@ x8632::misc-data-offset (% bignum) (% len)))
+    (cmpl ($ '1) (% len))		;any more digits?
+    (je @maybe-fixnumize)
+    (movl (% next) (% sign))
+    ;; (bignum-ref bignum (- len 2)), i.e., next-to-last digit
+    (movl (@ (- x8632::misc-data-offset 8) (% bignum) (% imm0)) (% next))
+    @test
+    (movl (% next) (% imm0))
+    (sarl ($ 31) (% imm0))		;propagate sign bit
+    (xorl (% sign) (% imm0))
+    (testl (% imm0) (% imm0))		;whole digit only sign?
+    (jz @loop)
+    @maybe-fixnumize
+    (pop (% return-fixnum-p))
+    (cmpl ($ x8632::nil-value) (% return-fixnum-p))
+    (je @done)
+    (vector-length bignum len)
+    (cmpl ($ '1) (% len))
+    (jg @done)
+    ;; Bignum has one digit.  If it fits in a fixnum, return a fixnum.
+    (movl (@ x8632::misc-data-offset (% bignum)) (% imm0))
+    (box-fixnum imm0 arg_y)
+    (cmpl ($ #x3fffffff) (% imm0))
+    (cmovbel (% arg_y) (% arg_z))
+    @done
+    (mark-as-node temp0)
+    (mark-as-node temp1)
+    (single-value-return)))
