Update of /project/movitz/cvsroot/movitz/losp/muerte
In directory common-lisp.net:/tmp/cvs-serv23968
Modified Files:
integers.lisp
Log Message:
Starting to add some bignum support.
Date: Mon May 24 10:58:51 2004
Author: ffjeld
Index: movitz/losp/muerte/integers.lisp
diff -u movitz/losp/muerte/integers.lisp:1.10 movitz/losp/muerte/integers.lisp:1.11
--- movitz/losp/muerte/integers.lisp:1.10 Wed May 19 11:42:08 2004
+++ movitz/losp/muerte/integers.lisp Mon May 24 10:58:51 2004
@@ -9,7 +9,7 @@
;;;; Created at: Wed Nov 8 18:44:57 2000
;;;; Distribution: See the accompanying file COPYING.
;;;;
-;;;; $Id: integers.lisp,v 1.10 2004/05/19 15:42:08 ffjeld Exp $
+;;;; $Id: integers.lisp,v 1.11 2004/05/24 14:58:51 ffjeld Exp $
;;;;
;;;;------------------------------------------------------------------
@@ -22,6 +22,12 @@
(defconstant most-positive-fixnum #.movitz::+movitz-most-positive-fixnum+)
(defconstant most-negative-fixnum #.movitz::+movitz-most-negative-fixnum+)
+(deftype positive-fixnum ()
+ `(integer 0 ,movitz:+movitz-most-positive-fixnum+))
+
+(deftype positive-bignum ()
+ `(integer ,(1+ movitz:+movitz-most-positive-fixnum+) *))
+
(defun fixnump (x)
(typep x 'fixnum))
@@ -242,10 +248,26 @@
"Compare real <n1> with fixnum <n2>."
(with-inline-assembly (:returns :nothing) ; unspecified
(:testb #.movitz::+movitz-fixnum-zmask+ :al)
+ (:jnz 'not-fixnum)
+ (:cmpl :ebx :eax)
+ (:ret)
+ not-fixnum
+ (:leal (:eax #.(cl:- (movitz:tag :other))) :ecx)
+ (:testb 7 :cl)
(:jnz '(:sub-program (not-integer)
(:int 107)
(:jmp 'not-integer)))
- (:cmpl :ebx :eax)
+ (:movl (:eax #.movitz:+other-type-offset+) :ecx)
+ (:cmpw #.(movitz:tag :bignum 0) :cx)
+ (:jne 'not-plusbignum)
+ ;; compare ebx with something bigger
+ (:cmpl #x-10000000 :edi)
+ (:ret)
+ not-plusbignum
+ (:cmpw #.(movitz:tag :bignum #xff) :cx)
+ (:jne 'not-integer)
+ ;; compare ebx with something bigger
+ (:cmpl #x10000000 :edi)
(:ret)))
;;;
@@ -256,8 +278,8 @@
(movitz:movitz-constantp max env))
(let ((min (movitz:movitz-eval min env))
(max (movitz:movitz-eval max env)))
- (check-type min integer)
- (check-type max integer)
+ (check-type min fixnum)
+ (check-type max fixnum)
;; (warn "~D -- ~D" min max)
(cond
((movitz:movitz-constantp x env)
@@ -296,7 +318,7 @@
#+ignore ; this is buggy.
((movitz:movitz-constantp min env)
(let ((min (movitz:movitz-eval min env)))
- (check-type min integer)
+ (check-type min fixnum)
(cond
((minusp min)
`(let ((x ,x))
@@ -372,7 +394,7 @@
(declare (dynamic-extent more-numbers))
(cond
((null more-numbers)
- (check-type number integer)
+ (check-type number fixnum)
t)
((not (cdr more-numbers))
(,2op-name number (first more-numbers)))
@@ -514,7 +536,7 @@
(if (< number1 number2)
number2 number1))
(let ((label (gensym)))
- `(with-inline-assembly (:returns :eax :type integer)
+ `(with-inline-assembly (:returns :eax :type fixnum)
(:compile-two-forms (:eax :ebx) ,number1 ,number2)
(:movl :ebx :ecx)
(:orl :eax :ecx)
@@ -650,7 +672,7 @@
`(*%2op ,(movitz:movitz-eval factor2 env) ,factor1))
((movitz:movitz-constantp factor1 env)
(let ((f1 (movitz:movitz-eval factor1 env)))
- (check-type f1 integer)
+ (check-type f1 fixnum)
(case f1
(0 `(progn ,factor2 0))
(1 factor2)
@@ -708,9 +730,9 @@
`(do-result-mode-case ()
(:plural
(no-macro-call ,@form))
- (t (truncate%2ops%1ret ,number ,divisor))))
+ (t (truncate%1ret ,number ,divisor))))
-(defun truncate%2ops%1ret (number divisor)
+(defun truncate%1ret (number divisor)
(with-inline-assembly (:returns :multiple-values)
(:compile-form (:result-mode :eax) number)
(:compile-form (:result-mode :ebx) divisor)
@@ -723,7 +745,7 @@
(:shll #.movitz::+movitz-fixnum-shift+ :eax)
(:clc)))
-(define-compiler-macro truncate%2ops%1ret (&whole form &environment env number divisor)
+(define-compiler-macro truncate%1ret (&whole form &environment env number divisor)
(cond
((movitz:movitz-constantp divisor env)
(let ((d (movitz:movitz-eval divisor env)))
@@ -731,7 +753,7 @@
(case d
(0 (error "Truncate by zero."))
(1 number)
- (t `(with-inline-assembly (:returns :eax :type integer)
+ (t `(with-inline-assembly (:returns :eax :type fixnum)
(:compile-form (:result-mode :eax) ,number)
(:compile-form (:result-mode :ebx) ,divisor)
(:testb #.movitz::+movitz-fixnum-zmask+ :al)
@@ -741,26 +763,116 @@
(:shll #.movitz::+movitz-fixnum-shift+ :eax))))))
(t form)))
+(defmacro number-double-dispatch ((x y) &rest clauses)
+ `(let ((x ,x) (y ,y))
+ (cond ,@(loop for ((x-type y-type) . then-body) in clauses
+ collect `((and (typep x ',x-type) (typep y ',y-type))
+ ,@then-body))
+ (t (error "Not numbers: ~S or ~S." x y)))))
+
(defun truncate (number &optional (divisor 1))
(numargs-case
(1 (number)
(values number 0))
(t (number divisor)
- (with-inline-assembly (:returns :multiple-values)
- (:compile-form (:result-mode :eax) number)
- (:compile-form (:result-mode :ebx) divisor)
- (:movl :eax :ecx)
- (:orl :ebx :ecx)
- (:testb #.movitz::+movitz-fixnum-zmask+ :cl)
- (:jnz '(:sub-program (not-integer) (:int 107)))
- (:cdq :eax :edx)
- (:idivl :ebx :eax :edx)
- (:shll #.movitz::+movitz-fixnum-shift+ :eax)
- (:movl :edx :ebx)
- (:xorl :ecx :ecx)
- (:movb 2 :cl) ; return values: qutient, remainder.
- (:stc)))))
-
+ (number-double-dispatch (number divisor)
+ ((fixnum fixnum)
+ (with-inline-assembly (:returns :multiple-values)
+ (:compile-form (:result-mode :eax) number)
+ (:compile-form (:result-mode :ebx) divisor)
+ (:std)
+ (:cdq :eax :edx)
+ (:idivl :ebx :eax :edx)
+ (:shll #.movitz::+movitz-fixnum-shift+ :eax)
+ (:cld)
+ (:movl :edx :ebx)
+ (:xorl :ecx :ecx)
+ (:movb 2 :cl) ; return values: qutient, remainder.
+ (:stc)))
+ ((positive-bignum positive-fixnum)
+ (let (r n)
+ (with-inline-assembly (:returns :multiple-values)
+ (:compile-form (:result-mode :ebx) number)
+ (:movzxw (:ebx #.(bt:slot-offset 'movitz::movitz-bignum 'movitz::length)) :ecx)
+ (:cmpl 1 :ecx)
+ (:jne 'not-size1)
+ (:compile-form (:result-mode :ecx) divisor)
+ (:shrl #.movitz:+movitz-fixnum-shift+ :ecx)
+ (:std)
+ (:movl (:ebx #.(bt:slot-offset 'movitz::movitz-bignum 'movitz::bigit0)) :eax)
+ (:xorl :edx :edx)
+ (:divl :ecx :eax :edx)
+ (:movl :eax :ecx)
+ (:shll #.movitz:+movitz-fixnum-shift+ :edx)
+ (:movl :edi :eax)
+ (:cld)
+ (:pushl :edx)
+ (:call-global-constant normalize-u32-ecx)
+ (:popl :ebx)
+ (:jmp 'done)
+ not-size1
+ (:cmpl 2 :ecx)
+ (:jne 'not-size2)
+ (:compile-form (:result-mode :ecx) divisor)
+ (:shrl #.movitz:+movitz-fixnum-shift+ :ecx)
+ (:std)
+ (:movl (:ebx #.(cl:+ 4 (bt:slot-offset 'movitz::movitz-bignum 'movitz::bigit0)))
+ :edx)
+ (:cmpl :ecx :edx)
+ (:jae 'not-size2)
+ (:movl (:ebx #.(bt:slot-offset 'movitz::movitz-bignum 'movitz::bigit0)) :eax)
+ (:divl :ecx :eax :edx)
+ (:movl :eax :ecx)
+ (:shll #.movitz:+movitz-fixnum-shift+ :edx)
+ (:movl :edi :eax)
+ (:cld)
+ (:pushl :edx)
+ (:call-global-constant normalize-u32-ecx)
+ (:popl :ebx)
+ (:jmp 'done)
+ not-size2
+ (:cmpl :ecx (:ebx #.(bt:slot-offset 'movitz::movitz-bignum 'movitz::bigit0)
+ -4 (:ecx 4)))
+ (:jc 'shrink-not-size2)
+ not-shrink
+ (:leal ((:ecx #.movitz:+movitz-fixnum-factor+)) :eax)
+ (:compile-form (:result-mode :eax)
+ (malloc-words (with-inline-assembly (:returns :eax))))
+ (:store-lexical (:lexical-binding r) :eax :type t)
+ (:compile-form (:result-mode :ebx) number)
+ (:movl (:ebx #.movitz:+other-type-offset+) :ecx)
+ (:movl :ecx (:eax #.movitz:+other-type-offset+))
+ (:shrl 16 :ecx)
+
+ (:xorl :edx :edx) ; edx=hi-digit=0
+ ; eax=lo-digit=msd(number)
+ (:std)
+ (:compile-form (:result-mode :esi) divisor)
+ (:shrl #.movitz:+movitz-fixnum-shift+ :esi)
+
+ divide-loop
+ (:load-lexical (:lexical-binding number) :ebx)
+ (:movl (:ebx #.(bt:slot-offset 'movitz::movitz-bignum 'movitz::bigit0)
+ -4 (:ecx 4))
+ :eax)
+ (:divl :esi :eax :edx)
+ (:load-lexical (:lexical-binding r) :ebx)
+ (:movl :eax (:ebx #.(bt:slot-offset 'movitz::movitz-bignum 'movitz::bigit0)
+ -4 (:ecx 4)))
+ (:subl 1 :ecx)
+ (:jnz 'divide-loop)
+ (:movl :ebx :eax)
+ (:leal ((:edx #.movitz:+movitz-fixnum-factor+)) :ebx)
+ (:movl :edi :edx)
+ (:movl (:ebp -4) :esi)
+ (:cld)
+ (:jmp 'done)
+ shrink-not-size2
+ (:int 107)
+ done
+ (:movl 2 :ecx)
+ (:stc))))
+ ))))
(defun round (number &optional (divisor 1))
"Mathematical rounding."
@@ -1147,4 +1259,4 @@
(values q 0))
(t (values (1- q) (+ r divisor))))))
(t (n &optional (divisor 1))
- (floor n divisor))))
\ No newline at end of file
+ (floor n divisor))))