Update of /project/movitz/cvsroot/movitz/losp/muerte
In directory common-lisp.net:/tmp/cvs-serv19438
Modified Files:
integers.lisp
Log Message:
Extracted most compiler-macros from integers.lisp into arithmetic-macros.lisp.
Date: Sat Jul 17 05:16:12 2004
Author: ffjeld
Index: movitz/losp/muerte/integers.lisp
diff -u movitz/losp/muerte/integers.lisp:1.70 movitz/losp/muerte/integers.lisp:1.71
--- movitz/losp/muerte/integers.lisp:1.70 Sat Jul 17 04:27:58 2004
+++ movitz/losp/muerte/integers.lisp Sat Jul 17 05:16:12 2004
@@ -9,12 +9,13 @@
;;;; Created at: Wed Nov 8 18:44:57 2000
;;;; Distribution: See the accompanying file COPYING.
;;;;
-;;;; $Id: integers.lisp,v 1.70 2004/07/17 11:27:58 ffjeld Exp $
+;;;; $Id: integers.lisp,v 1.71 2004/07/17 12:16:12 ffjeld Exp $
;;;;
;;;;------------------------------------------------------------------
(require :muerte/basic-macros)
(require :muerte/typep)
+(require :muerte/arithmetic-macros)
(provide :muerte/integers)
(in-package muerte)
@@ -22,113 +23,404 @@
(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+) *))
-
-(deftype negative-fixnum ()
- `(integer ,movitz:+movitz-most-negative-fixnum+ -1))
-(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 fixnump (x)
- (typep x 'fixnum))
+;;; Comparison
-(define-compiler-macro evenp (x)
- `(with-inline-assembly (:returns :boolean-zf=1)
- (:compile-form (:result-mode :eax) ,x)
- (:call-global-pf unbox-u32)
- (:testb 1 :cl)))
+(define-primitive-function fast-compare-two-reals (n1 n2)
+ "Compare two numbers (i.e. set EFLAGS accordingly)."
+ (macrolet
+ ((do-it ()
+ `(with-inline-assembly (:returns :nothing) ; unspecified
+ (:testb ,movitz::+movitz-fixnum-zmask+ :al)
+ (:jnz 'n1-not-fixnum)
+ (:testb ,movitz::+movitz-fixnum-zmask+ :bl)
+ (:jnz 'n2-not-fixnum-but-n1-is)
+ (:cmpl :ebx :eax) ; both were fixnum
+ (:ret)
+ n1-not-fixnum ; but we don't know about n2
+ (:testb ,movitz::+movitz-fixnum-zmask+ :bl)
+ (:jnz 'neither-is-fixnum)
+ ;; n2 is fixnum
+ (:locally (:jmp (:edi (:edi-offset fast-compare-real-fixnum))))
+ n2-not-fixnum-but-n1-is
+ (:locally (:jmp (:edi (:edi-offset fast-compare-fixnum-real))))
+ neither-is-fixnum
+ ;; Check that both numbers are bignums, and compare them.
+ (:leal (:eax ,(- (movitz:tag :other))) :ecx)
+ (:testb 7 :cl)
+ (:jnz '(:sub-program (n1-not-bignum)
+ (:int 107)))
+ (:movl (:eax ,movitz:+other-type-offset+) :ecx)
+ (:cmpb ,(movitz:tag :bignum) :cl)
+ (:jne 'n1-not-bignum)
-(defun evenp (x)
- (evenp x))
+ (:cmpl :eax :ebx) ; If they are EQ, they are certainly =
+ (:je '(:sub-program (n1-and-n2-are-eq)
+ (:ret)))
-(define-compiler-macro oddp (x)
- `(with-inline-assembly (:returns :boolean-zf=0)
- (:compile-form (:result-mode :eax) ,x)
- (:call-global-pf unbox-u32)
- (:testb 1 :cl)))
+ (:leal (:ebx ,(- (movitz:tag :other))) :ecx)
+ (:testb 7 :cl)
+ (:jnz '(:sub-program (n2-not-bignum)
+ (:int 107)))
+ (:movl (:ebx ,movitz:+other-type-offset+) :ecx)
+ (:cmpb ,(movitz:tag :bignum) :cl)
+ (:jne 'n2-not-bignum)
-(defun oddp (x)
- (oddp x))
+ (:cmpb :ch (:eax ,(bt:slot-offset 'movitz:movitz-bignum 'movitz::sign)))
+ (:jne '(:sub-program (different-signs)
+ ;; Comparing the sign-bytes sets up EFLAGS correctly!
+ (:ret)))
+ (:testl #xff00 :ecx)
+ (:jnz 'compare-negatives)
+ ;; Both n1 and n2 are positive bignums.
-;;; Types
+ (:shrl 16 :ecx)
+ (:cmpw :cx (:eax ,(bt:slot-offset 'movitz:movitz-bignum 'movitz::length)))
+ (:jne '(:sub-program (positive-different-sizes)
+ (:ret)))
-(define-typep integer (x &optional (min '*) (max '*))
- (and (typep x 'integer)
- (or (eq min '*) (<= min x))
- (or (eq max '*) (<= x max))))
+ ;; Both n1 and n2 are positive bignums of the same size, namely ECX.
+ (:movl :ecx :edx) ; counter
+ positive-compare-loop
+ (:subl ,movitz:+movitz-fixnum-factor+ :edx)
+ (:jz 'positive-compare-lsb)
+ (:movl (:ebx :edx ,(bt:slot-offset 'movitz:movitz-bignum 'movitz::bigit0))
+ :ecx)
+ (:cmpl :ecx
+ (:eax :edx ,(bt:slot-offset 'movitz:movitz-bignum 'movitz::bigit0)))
+ (:je 'positive-compare-loop)
+ positive-compare-lsb
+ ;; Now we have to make the compare act as unsigned, which is why
+ ;; we compare zero-extended 16-bit quantities.
+ (:movzxw (:ebx :edx ,(+ 2 (bt:slot-offset 'movitz:movitz-bignum 'movitz::bigit0)))
+ :ecx) ; First compare upper 16 bits.
+ (:locally (:movl :ecx (:edi (:edi-offset scratch0))))
+ (:movzxw (:eax :edx ,(+ 2 (bt:slot-offset 'movitz:movitz-bignum 'movitz::bigit0)))
+ :ecx)
+ (:locally (:cmpl (:edi (:edi-offset scratch0)) :ecx))
+ (:jne 'upper-16-decisive)
+ (:movzxw (:ebx :edx ,(bt:slot-offset 'movitz:movitz-bignum 'movitz::bigit0))
+ :ecx) ; Then compare lower 16 bits.
+ (:locally (:movl :ecx (:edi (:edi-offset scratch0))))
+ (:movzxw (:eax :edx ,(bt:slot-offset 'movitz:movitz-bignum 'movitz::bigit0))
+ :ecx) ; Then compare lower 16 bits.
+ (:locally (:cmpl (:edi (:edi-offset scratch0)) :ecx))
+ upper-16-decisive
+ (:ret)
+
+ compare-negatives
+ ;; Moth n1 and n2 are negative bignums.
-(deftype signed-byte (&optional (size '*))
- (cond
- ((eq size '*)
- 'integer)
- ((typep size '(integer 1 *))
- (list 'integer
- (- (ash 1 (1- size)))
- (1- (ash 1 (1- size)))))
- (t (error "Illegal size for signed-byte."))))
+ (:shrl 16 :ecx)
+ (:cmpw (:eax ,(bt:slot-offset 'movitz:movitz-bignum 'movitz::length)) :cx)
+ (:jne '(:sub-program (negative-different-sizes)
+ (:ret)))
-(deftype unsigned-byte (&optional (size '*))
- (cond
- ((eq size '*)
- '(integer 0))
- ((typep size '(integer 1 *))
- (list 'integer 0 (1- (ash 1 size))))
- (t (error "Illegal size for unsigned-byte."))))
+ ;; Both n1 and n2 are negative bignums of the same size, namely ECX.
+ (:movl :ecx :edx) ; counter
+ negative-compare-loop
+ (:subl ,movitz:+movitz-fixnum-factor+ :edx)
+ (:jz 'negative-compare-lsb)
+ (:movl (:eax :edx ,(bt:slot-offset 'movitz:movitz-bignum 'movitz::bigit0))
+ :ecx)
+ (:cmpl :ecx
+ (:ebx :edx ,(bt:slot-offset 'movitz:movitz-bignum 'movitz::bigit0)))
+ (:je 'negative-compare-loop)
+ (:ret)
+ negative-compare-lsb ; it's down to the LSB bigits.
+ ;; Now we have to make the compare act as unsigned, which is why
+ ;; we compare zero-extended 16-bit quantities.
+ (:movzxw (:ebx :edx ,(+ 2 (bt:slot-offset 'movitz:movitz-bignum 'movitz::bigit0)))
+ :ecx) ; First compare upper 16 bits.
+ (:locally (:movl :ecx (:edi (:edi-offset scratch0))))
+ (:movzxw (:eax :edx ,(+ 2 (bt:slot-offset 'movitz:movitz-bignum 'movitz::bigit0)))
+ :ecx)
+ (:locally (:cmpl :ecx (:edi (:edi-offset scratch0))))
+ (:jne 'negative-upper-16-decisive)
+ (:movzxw (:ebx :edx ,(bt:slot-offset 'movitz:movitz-bignum 'movitz::bigit0))
+ :ecx) ; Then compare lower 16 bits.
+ (:locally (:movl :ecx (:edi (:edi-offset scratch0))))
+ (:movzxw (:eax :edx ,(bt:slot-offset 'movitz:movitz-bignum 'movitz::bigit0))
+ :ecx) ; Then compare lower 16 bits.
+ (:locally (:cmpl :ecx (:edi (:edi-offset scratch0))))
+ negative-upper-16-decisive
+ (:ret))))
+ (do-it)))
-(define-simple-typep (bit bitp) (x)
- (or (eq x 0) (eq x 1)))
+(define-primitive-function fast-eql (x y)
+ "Compare EAX and EBX under EQL, result in ZF.
+Preserve EAX and EBX."
+ (macrolet
+ ((do-it ()
+ `(with-inline-assembly (:returns :nothing) ; unspecified
+ (:cmpl :eax :ebx) ; EQ?
+ (:je 'done)
+ (:leal (:eax ,(- (movitz:tag :other))) :ecx)
+ (:testb 7 :cl)
+ (:jne 'done)
+ (:leal (:ebx ,(- (movitz:tag :other))) :ecx)
+ (:testb 7 :cl)
+ (:jne 'done)
+ (:movl (:eax ,movitz:+other-type-offset+) :ecx)
+ (:cmpb ,(movitz:tag :bignum) :cl)
+ (:jne 'done)
+ (:cmpl :ecx (:ebx ,movitz:+other-type-offset+))
+ (:jne 'done)
+ ;; Ok.. we have two bignums of identical sign and size.
+ (:shrl 16 :ecx)
+ (:movl :ecx :edx) ; counter
+ compare-loop
+ (:subl ,movitz:+movitz-fixnum-factor+ :edx)
+ (:jz 'done)
+ (:movl (:eax :edx ,(+ -4 (bt:slot-offset 'movitz:movitz-bignum 'movitz::bigit0)))
+ :ecx)
+ (:cmpl :ecx
+ (:ebx :edx ,(+ -4 (bt:slot-offset 'movitz:movitz-bignum 'movitz::bigit0))))
+ (:je 'compare-loop)
+ done
+ (:ret))))
+ (do-it)))
-;;;
+(define-primitive-function fast-compare-fixnum-real (n1 n2)
+ "Compare (known) fixnum <n1> with real <n2>."
+ (macrolet
+ ((do-it ()
+ `(with-inline-assembly (:returns :nothing) ; unspecified
+ (:testb ,movitz::+movitz-fixnum-zmask+ :bl)
+ (:jnz 'n2-not-fixnum)
+ (:cmpl :ebx :eax)
+ (:ret)
+ n2-not-fixnum
+ (:leal (:ebx ,(- (movitz:tag :other))) :ecx)
+ (:testb 7 :cl)
+ (:jnz '(:sub-program (not-integer)
+ (:int 107)
+ (:jmp 'not-integer)))
+ (:movl (:ebx ,movitz:+other-type-offset+) :ecx)
+ (:cmpw ,(movitz:tag :bignum 0) :cx)
+ (:jne 'not-plusbignum)
+ ;; compare eax with something bigger
+ (:cmpl #x10000000 :edi)
+ (:ret)
+ not-plusbignum
+ (:cmpw ,(movitz:tag :bignum #xff) :cx)
+ (:jne 'not-integer)
+ ;; compare ebx with something bigger
+ (:cmpl #x-10000000 :edi)
+ (:ret))))
+ (do-it)))
-(defun %negatef (x p0 p1)
- "Negate x. If x is not eq to p0 or p1, negate x destructively."
- (etypecase x
- (fixnum (- x))
- (bignum
- (if (or (eq x p0) (eq x p1))
- (- x)
- (with-inline-assembly (:returns :eax)
- (:compile-form (:result-mode :eax) x)
- (:xorl #xff00 (:eax #.movitz:+other-type-offset+)))))))
+(define-primitive-function fast-compare-real-fixnum (n1 n2)
+ "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)))
+ (: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)))
-;;; Addition
+;;;
-(define-compiler-macro + (&whole form &rest operands &environment env)
- (case (length operands)
- (0 0)
- (1 (first operands))
- #+ignore (2 `(+%2op ,(first operands) ,(second operands)))
- (2 `(let ((x ,(first operands))
- (y ,(second operands)))
- (++%2op x y)))
- (t (let ((operands
- (loop for operand in operands
- if (movitz:movitz-constantp operand env)
- sum (movitz:movitz-eval operand env)
- into constant-term
- else collect operand
- into non-constant-operands
- finally (return (if (zerop constant-term)
- non-constant-operands
- (cons constant-term non-constant-operands))))))
- `(+ (+ ,(first operands) ,(second operands)) ,@(cddr operands))))))
-(defun + (&rest terms)
- (declare (without-check-stack-limit))
- (numargs-case
- (1 (x) x)
- (2 (x y)
- (macrolet
- ((do-it ()
+(defmacro define-number-relational (name 2op-name condition &key (defun-p t) 3op-name)
+ `(progn
+ ,(when condition
+ `(define-compiler-macro ,2op-name (n1 n2)
+ (cond
+ ((movitz:movitz-constantp n1)
+ (let ((n1 (movitz::movitz-eval n1)))
+ (check-type n1 (signed-byte 30))
+ `(with-inline-assembly (:returns ,,condition :side-effects nil)
+ (:compile-two-forms (:eax :ebx) ,n1 ,n2)
+ (:call-global-pf fast-compare-fixnum-real))))
+ ((movitz:movitz-constantp n2)
+ (let ((n2 (movitz::movitz-eval n2)))
+ (check-type n2 (signed-byte 30))
+ `(with-inline-assembly (:returns ,,condition :side-effects nil)
+ (:compile-two-forms (:eax :ebx) ,n1 ,n2)
+ (:call-global-pf fast-compare-real-fixnum))))
+ (t `(with-inline-assembly (:returns ,,condition :side-effects nil)
+ (:compile-two-forms (:eax :ebx) ,n1 ,n2)
+ (:call-global-pf fast-compare-two-reals))))))
+
+ (defun ,2op-name (n1 n2)
+ (,2op-name n1 n2))
+
+ (define-compiler-macro ,name (&whole form number &rest more-numbers)
+ (case (length more-numbers)
+ (0 `(progn ,number t))
+ (1 `(,',2op-name ,number ,(first more-numbers)))
+ ,@(when 3op-name
+ `((2 `(,',3op-name ,number ,(first more-numbers) ,(second more-numbers)))))
+ (t #+ignore (when (= 2 (length more-numbers))
+ (warn "3op: ~S" form))
+ `(and (,',2op-name ,number ,(first more-numbers))
+ (,',name ,@more-numbers)))))
+
+ ,(when defun-p
+ `(defun ,name (number &rest more-numbers)
+ (declare (dynamic-extent more-numbers))
+ (cond
+ ((null more-numbers)
+ (check-type number fixnum)
+ t)
+ ((not (cdr more-numbers))
+ (,2op-name number (first more-numbers)))
+ (t (and (,2op-name number (first more-numbers))
+ (do ((p more-numbers (cdr p)))
+ ((not (cdr p)) t)
+ (unless (,2op-name (car p) (cadr p))
+ (return nil))))))))))
+
+(define-number-relational >= >=%2op :boolean-greater-equal)
+(define-number-relational > >%2op :boolean-greater)
+(define-number-relational < <%2op :boolean-less)
+(define-number-relational <= <=%2op :boolean-less-equal :3op-name <=%3op)
+
+;;; Unsigned
+
+(defun below (x max)
+ "Is x between 0 and max?"
+ (compiler-macro-call below x max))
+
+
+;;; Equality
+
+(define-compiler-macro =%2op (n1 n2 &environment env)
+ (cond
+ ((movitz:movitz-constantp n1 env)
+ (let ((n1 (movitz:movitz-eval n1 env)))
+ (etypecase n1
+ ((eql 0)
+ `(do-result-mode-case ()
+ (:booleans
+ (with-inline-assembly (:returns :boolean-zf=1 :side-effects nil)
+ (:compile-form (:result-mode :eax) ,n2)
+ (:testl :eax :eax)))
+ (t (with-inline-assembly (:returns :boolean-cf=1 :side-effects nil)
+ (:compile-form (:result-mode :eax) ,n2)
+ (:cmpl 1 :eax)))))
+ ((signed-byte 30)
+ `(with-inline-assembly (:returns :boolean-zf=1 :side-effects nil)
+ (:compile-two-forms (:eax :ebx) ,n1 ,n2)
+ (:call-global-pf fast-compare-fixnum-real)))
+ (integer
+ `(with-inline-assembly (:returns :boolean-zf=1 :side-effects nil)
+ (:compile-two-forms (:eax :ebx) ,n1 ,n2)
+ (:call-global-pf fast-compare-two-reals))))))
+ ((movitz:movitz-constantp n2 env)
+ `(=%2op ,n2 ,n1))
+ (t `(with-inline-assembly (:returns :boolean-zf=1 :side-effects nil)
+ (:compile-two-forms (:eax :ebx) ,n1 ,n2)
+ (:call-global-pf fast-compare-two-reals)))))
+
+(define-number-relational = =%2op nil :defun-p nil)
+
+(defun = (first-number &rest numbers)
+ (declare (dynamic-extent numbers))
+ (dolist (n numbers t)
+ (unless (= first-number n)
+ (return nil))))
+
+(define-number-relational /= /=%2op :boolean-zf=0 :defun-p nil)
+
+(defun /= (&rest numbers)
+ (declare (dynamic-extent numbers))
+ (do ((p (cdr numbers) (cdr p)))
+ ((null p) t)
+ (do ((v numbers (cdr v)))
+ ((eq p v))
+ (when (= (car p) (car v))
+ (return-from /= nil)))))
+
+
+;;;;
+
+(deftype positive-fixnum ()
+ `(integer 0 ,movitz:+movitz-most-positive-fixnum+))
+
+(deftype positive-bignum ()
+ `(integer ,(1+ movitz:+movitz-most-positive-fixnum+) *))
+
+(deftype negative-fixnum ()
+ `(integer ,movitz:+movitz-most-negative-fixnum+ -1))
+
+(defun fixnump (x)
+ (typep x 'fixnum))
+
+(defun evenp (x)
+ (compiler-macro-call evenp x))
+
+(defun oddp (x)
+ (compiler-macro-call oddp x))
+
+;;; Types
+
+(define-typep integer (x &optional (min '*) (max '*))
+ (and (typep x 'integer)
+ (or (eq min '*) (<= min x))
+ (or (eq max '*) (<= x max))))
+
+(deftype signed-byte (&optional (size '*))
+ (cond
+ ((eq size '*)
+ 'integer)
+ ((typep size '(integer 1 *))
+ (list 'integer
+ (- (ash 1 (1- size)))
+ (1- (ash 1 (1- size)))))
+ (t (error "Illegal size for signed-byte."))))
+
+(deftype unsigned-byte (&optional (size '*))
+ (cond
+ ((eq size '*)
+ '(integer 0))
+ ((typep size '(integer 1 *))
+ (list 'integer 0 (1- (ash 1 size))))
+ (t (error "Illegal size for unsigned-byte."))))
+
+(define-simple-typep (bit bitp) (x)
+ (or (eq x 0) (eq x 1)))
+
+;;;
+
+(defun %negatef (x p0 p1)
+ "Negate x. If x is not eq to p0 or p1, negate x destructively."
+ (etypecase x
+ (fixnum (- x))
+ (bignum
+ (if (or (eq x p0) (eq x p1))
+ (- x)
+ (with-inline-assembly (:returns :eax)
+ (:compile-form (:result-mode :eax) x)
+ (:xorl #xff00 (:eax #.movitz:+other-type-offset+)))))))
+
+;;; Addition
+
+(defun + (&rest terms)
+ (declare (without-check-stack-limit))
+ (numargs-case
+ (1 (x) x)
+ (2 (x y)
+ (macrolet
+ ((do-it ()
`(number-double-dispatch (x y)
((fixnum fixnum)
(with-inline-assembly (:returns :eax)
@@ -315,677 +607,214 @@
retry-not-size1
(:compile-form (:result-mode :eax) y)
(:movzxw (:eax ,(bt:slot-offset 'movitz::movitz-bignum 'movitz::length)) :ecx)
- not-size1
- (:declare-label-set retry-jumper (retry-not-size1))
- (:locally (:movl :esp (:edi (:edi-offset atomically-esp))))
- (:locally (:movl '(:funcall ,(movitz::atomically-status-jumper-fn t :esp)
- 'retry-jumper)
- (:edi (:edi-offset atomically-status))))
- (:leal ((:ecx 1) ,(* 2 movitz:+movitz-fixnum-factor+))
- :eax) ; Number of words
- (:call-local-pf get-cons-pointer)
- (:load-lexical (:lexical-binding y) :ebx) ; bignum
- (:movzxw (:ebx ,(bt:slot-offset 'movitz::movitz-bignum 'movitz::length)) :ecx)
- (:leal ((:ecx 1) ,movitz:+movitz-fixnum-factor+)
- :edx)
- (:movl 0 (:eax :edx ,movitz:+other-type-offset+)) ; MSB
- copy-bignum-loop
- (:subl ,movitz:+movitz-fixnum-factor+ :edx)
- (:movl (:ebx :edx ,movitz:+other-type-offset+) :ecx)
- (:movl :ecx (:eax :edx ,movitz:+other-type-offset+))
- (:jnz 'copy-bignum-loop)
-
- (:load-lexical (:lexical-binding x) :ebx)
- (:xorl :edx :edx) ; counter
- (:xorl :ecx :ecx) ; Carry
- add-bignum-loop
- (:cmpw :dx (:ebx ,(bt:slot-offset 'movitz::movitz-bignum 'movitz::length)))
- (:jbe '(:sub-program (zero-padding-loop)
- (:addl :ecx (:eax :edx ,(bt:slot-offset 'movitz::movitz-bignum
- 'movitz::bigit0)))
- (:sbbl :ecx :ecx)
- (:negl :ecx) ; ECX = Add's Carry.
- (:addl 4 :edx)
- (:cmpw :dx (:eax ,(bt:slot-offset 'movitz::movitz-bignum 'movitz::length)))
- (:jae 'zero-padding-loop)
- (:jmp 'add-bignum-done)))
- (:addl (:ebx :edx ,(bt:slot-offset 'movitz::movitz-bignum 'movitz::bigit0))
- :ecx)
- (:jc '(:sub-program (term1-carry)
- ;; The digit + carry carried over, ECX = 0
- (:addl 1 :ecx)
- (:addl 4 :edx)
- (:cmpw :dx (:eax ,(bt:slot-offset 'movitz::movitz-bignum 'movitz::length)))
- (:jae 'add-bignum-loop)
- (:jmp 'add-bignum-done)))
- (:addl :ecx (:eax :edx ,(bt:slot-offset 'movitz::movitz-bignum 'movitz::bigit0)))
- (:sbbl :ecx :ecx)
- (:negl :ecx) ; ECX = Add's Carry.
- (:addl 4 :edx)
- (:cmpw :dx (:eax ,(bt:slot-offset 'movitz::movitz-bignum 'movitz::length)))
- (:jae 'add-bignum-loop)
- add-bignum-done
- (:movzxw (:eax ,(bt:slot-offset 'movitz::movitz-bignum 'movitz::length))
- :ecx)
- (:leal ((:ecx 1) ,movitz:+movitz-fixnum-factor+)
- :ecx)
- (:cmpl 0 (:eax :ecx ,(+ -4 (bt:slot-offset 'movitz::movitz-bignum 'movitz::bigit0))))
- (:je 'no-expansion)
- (:addl #x40000 (:eax ,movitz:+other-type-offset+))
- (:addl ,movitz:+movitz-fixnum-factor+ :ecx)
- no-expansion
- (:call-local-pf cons-commit)
- (:locally (:movl ,(bt:enum-value 'movitz::atomically-status :inactive)
- (:edi (:edi-offset atomically-status))))
- pfix-pbig-done)
- ))
- (((integer * -1) (integer 0 *))
- (- y (- x)))
- (((integer 0 *) (integer * -1))
- (- x (- y)))
- (((integer * -1) (integer * -1))
- (%negatef (+ (- x) (- y)) x y))
- )))
- (do-it)))
- (t (&rest terms)
- (declare (dynamic-extent terms))
- (if (null terms)
- 0
- (reduce #'+ terms)))))
-
-(defun 1+ (number)
- (+ 1 number))
-
-(define-compiler-macro 1+ (number)
- `(+ 1 ,number))
-
-(defun 1- (number)
- (+ -1 number))
-
-(define-compiler-macro 1- (number)
- `(+ -1 ,number))
-
-(define-modify-macro incf (&optional (delta-form 1)) +)
-
-;;; Subtraction
-
-(define-compiler-macro - (&whole form &rest operands &environment env)
- (case (length operands)
- (0 0)
- (1 (let ((x (first operands)))
- (if (movitz:movitz-constantp x env)
- (- (movitz:movitz-eval x env))
- form)))
- (2 (let ((minuend (first operands))
- (subtrahend (second operands)))
- (cond
- ((movitz:movitz-constantp subtrahend env)
- `(+ ,minuend ,(- (movitz:movitz-eval subtrahend env))))
- (t form))))
- (t `(- ,(first operands) (+ ,@(rest operands))))))
-
-(defun - (minuend &rest subtrahends)
- (declare (dynamic-extent subtrahends))
- (numargs-case
- (1 (x)
- (macrolet
- ((do-it ()
- `(with-inline-assembly (:returns :eax)
- (:compile-form (:result-mode :eax) x)
- (:testb ,movitz:+movitz-fixnum-zmask+ :al)
- (:jnz '(:sub-program (not-fixnum)
- (:leal (:eax ,(- (movitz:tag :other))) :ecx)
- (:testb 7 :cl)
- (:jnz '(:sub-program (not-a-number)
- (:compile-form (:result-mode :ignore)
- (error 'type-error :expected-type 'number :datum x))))
- (:movl (:eax ,movitz:+other-type-offset+) :ecx)
- (:cmpb ,(movitz:tag :bignum) :cl)
- (:jne 'not-a-number)
- (:cmpl ,(dpb 4 (byte 16 16) (movitz:tag :bignum 0)) :ecx)
- (:jne 'not-most-negative-fixnum)
- (:cmpl ,(- most-negative-fixnum)
- (:eax ,(bt:slot-offset 'movitz::movitz-bignum 'movitz::bigit0)))
- (:jne 'not-most-negative-fixnum)
- (:movl ,(ldb (byte 32 0)
- (* most-negative-fixnum movitz::+movitz-fixnum-factor+))
- :eax)
- (:jmp 'fix-ok)
- not-most-negative-fixnum
- (:compile-form (:result-mode :eax)
- (copy-bignum x))
- (:notb (:eax ,(bt:slot-offset 'movitz::movitz-bignum 'movitz::sign)))
- (:jmp 'fix-ok)))
- (:negl :eax)
- (:jo '(:sub-program (fix-overflow)
- (:compile-form (:result-mode :eax)
- ,(1+ movitz:+movitz-most-positive-fixnum+))
- (:jmp 'fix-ok)))
- fix-ok
- )))
- (do-it)))
- (2 (minuend subtrahend)
- (macrolet
- ((do-it ()
- `(number-double-dispatch (minuend subtrahend)
- ((t (eql 0))
- minuend)
- (((eql 0) t)
- (- subtrahend))
- ((fixnum fixnum)
- (with-inline-assembly (:returns :eax :side-effects nil)
- (:compile-two-forms (:eax :ebx) minuend subtrahend)
- (:subl :ebx :eax)
- (:into)))
- ((positive-bignum fixnum)
- (+ (- subtrahend) minuend))
- ((fixnum positive-bignum)
- (- (+ (- minuend) subtrahend)))
- ((positive-bignum positive-bignum)
- (cond
- ((= minuend subtrahend)
- 0)
- ((< minuend subtrahend)
- (let ((x (- subtrahend minuend)))
- (%negatef x subtrahend minuend)))
- (t (%bignum-canonicalize
- (with-inline-assembly (:returns :eax)
- (:compile-two-forms (:eax :ebx) (copy-bignum minuend) subtrahend)
- (:xorl :edx :edx) ; counter
- (:xorl :ecx :ecx) ; carry
- sub-loop
- (:addl (:ebx :edx ,(bt:slot-offset 'movitz::movitz-bignum 'movitz::bigit0))
- :ecx)
- (:jc '(:sub-program (carry-overflow)
- ;; Just propagate carry
- (:addl 1 :ecx)
- (:addl 4 :edx)
- (:cmpw :dx (:ebx ,(bt:slot-offset 'movitz::movitz-bignum 'movitz::length)))
- (:jne 'sub-loop)
- (:jmp 'bignum-sub-done)))
- (:subl :ecx
- (:eax :edx ,(bt:slot-offset 'movitz::movitz-bignum 'movitz::bigit0)))
- (:sbbl :ecx :ecx)
- (:negl :ecx)
- (:addl 4 :edx)
- (:cmpw :dx (:ebx ,(bt:slot-offset 'movitz::movitz-bignum 'movitz::length)))
- (:jne 'sub-loop)
- (:subl :ecx
- (:eax :edx ,(bt:slot-offset 'movitz::movitz-bignum 'movitz::bigit0)))
- (:jnc 'bignum-sub-done)
- propagate-carry
- (:addl 4 :edx)
- (:subl 1 (:eax :edx ,(bt:slot-offset 'movitz::movitz-bignum 'movitz::bigit0)))
- (:jc 'propagate-carry)
- bignum-sub-done
- )))))
- (((integer 0 *) (integer * -1))
- (+ minuend (- subtrahend)))
- (((integer * -1) (integer 0 *))
- (%negatef (+ (- minuend) subtrahend) minuend subtrahend))
- (((integer * -1) (integer * -1))
- (+ minuend (- subtrahend)))
- )))
- (do-it)))
- (t (minuend &rest subtrahends)
- (declare (dynamic-extent subtrahends))
- (if subtrahends
- (reduce #'- subtrahends :initial-value minuend)
- (- minuend)))))
-
-(define-modify-macro decf (&optional (delta-form 1)) -)
-
-;;; Comparison
-
-(define-primitive-function fast-compare-two-reals (n1 n2)
- "Compare two numbers (i.e. set EFLAGS accordingly)."
- (macrolet
- ((do-it ()
- `(with-inline-assembly (:returns :nothing) ; unspecified
- (:testb ,movitz::+movitz-fixnum-zmask+ :al)
- (:jnz 'n1-not-fixnum)
- (:testb ,movitz::+movitz-fixnum-zmask+ :bl)
- (:jnz 'n2-not-fixnum-but-n1-is)
- (:cmpl :ebx :eax) ; both were fixnum
- (:ret)
- n1-not-fixnum ; but we don't know about n2
- (:testb ,movitz::+movitz-fixnum-zmask+ :bl)
- (:jnz 'neither-is-fixnum)
- ;; n2 is fixnum
- (:locally (:jmp (:edi (:edi-offset fast-compare-real-fixnum))))
- n2-not-fixnum-but-n1-is
- (:locally (:jmp (:edi (:edi-offset fast-compare-fixnum-real))))
- neither-is-fixnum
- ;; Check that both numbers are bignums, and compare them.
- (:leal (:eax ,(- (movitz:tag :other))) :ecx)
- (:testb 7 :cl)
- (:jnz '(:sub-program (n1-not-bignum)
- (:int 107)))
- (:movl (:eax ,movitz:+other-type-offset+) :ecx)
- (:cmpb ,(movitz:tag :bignum) :cl)
- (:jne 'n1-not-bignum)
-
- (:cmpl :eax :ebx) ; If they are EQ, they are certainly =
- (:je '(:sub-program (n1-and-n2-are-eq)
- (:ret)))
-
- (:leal (:ebx ,(- (movitz:tag :other))) :ecx)
- (:testb 7 :cl)
- (:jnz '(:sub-program (n2-not-bignum)
- (:int 107)))
- (:movl (:ebx ,movitz:+other-type-offset+) :ecx)
- (:cmpb ,(movitz:tag :bignum) :cl)
- (:jne 'n2-not-bignum)
-
- (:cmpb :ch (:eax ,(bt:slot-offset 'movitz:movitz-bignum 'movitz::sign)))
- (:jne '(:sub-program (different-signs)
- ;; Comparing the sign-bytes sets up EFLAGS correctly!
- (:ret)))
- (:testl #xff00 :ecx)
- (:jnz 'compare-negatives)
- ;; Both n1 and n2 are positive bignums.
-
- (:shrl 16 :ecx)
- (:cmpw :cx (:eax ,(bt:slot-offset 'movitz:movitz-bignum 'movitz::length)))
- (:jne '(:sub-program (positive-different-sizes)
- (:ret)))
-
- ;; Both n1 and n2 are positive bignums of the same size, namely ECX.
- (:movl :ecx :edx) ; counter
- positive-compare-loop
- (:subl ,movitz:+movitz-fixnum-factor+ :edx)
- (:jz 'positive-compare-lsb)
- (:movl (:ebx :edx ,(bt:slot-offset 'movitz:movitz-bignum 'movitz::bigit0))
- :ecx)
- (:cmpl :ecx
- (:eax :edx ,(bt:slot-offset 'movitz:movitz-bignum 'movitz::bigit0)))
- (:je 'positive-compare-loop)
- positive-compare-lsb
- ;; Now we have to make the compare act as unsigned, which is why
- ;; we compare zero-extended 16-bit quantities.
- (:movzxw (:ebx :edx ,(+ 2 (bt:slot-offset 'movitz:movitz-bignum 'movitz::bigit0)))
- :ecx) ; First compare upper 16 bits.
- (:locally (:movl :ecx (:edi (:edi-offset scratch0))))
- (:movzxw (:eax :edx ,(+ 2 (bt:slot-offset 'movitz:movitz-bignum 'movitz::bigit0)))
- :ecx)
- (:locally (:cmpl (:edi (:edi-offset scratch0)) :ecx))
- (:jne 'upper-16-decisive)
- (:movzxw (:ebx :edx ,(bt:slot-offset 'movitz:movitz-bignum 'movitz::bigit0))
- :ecx) ; Then compare lower 16 bits.
- (:locally (:movl :ecx (:edi (:edi-offset scratch0))))
- (:movzxw (:eax :edx ,(bt:slot-offset 'movitz:movitz-bignum 'movitz::bigit0))
- :ecx) ; Then compare lower 16 bits.
- (:locally (:cmpl (:edi (:edi-offset scratch0)) :ecx))
- upper-16-decisive
- (:ret)
-
- compare-negatives
- ;; Moth n1 and n2 are negative bignums.
-
- (:shrl 16 :ecx)
- (:cmpw (:eax ,(bt:slot-offset 'movitz:movitz-bignum 'movitz::length)) :cx)
- (:jne '(:sub-program (negative-different-sizes)
- (:ret)))
-
- ;; Both n1 and n2 are negative bignums of the same size, namely ECX.
- (:movl :ecx :edx) ; counter
- negative-compare-loop
- (:subl ,movitz:+movitz-fixnum-factor+ :edx)
- (:jz 'negative-compare-lsb)
- (:movl (:eax :edx ,(bt:slot-offset 'movitz:movitz-bignum 'movitz::bigit0))
- :ecx)
- (:cmpl :ecx
- (:ebx :edx ,(bt:slot-offset 'movitz:movitz-bignum 'movitz::bigit0)))
- (:je 'negative-compare-loop)
- (:ret)
- negative-compare-lsb ; it's down to the LSB bigits.
- ;; Now we have to make the compare act as unsigned, which is why
- ;; we compare zero-extended 16-bit quantities.
- (:movzxw (:ebx :edx ,(+ 2 (bt:slot-offset 'movitz:movitz-bignum 'movitz::bigit0)))
- :ecx) ; First compare upper 16 bits.
- (:locally (:movl :ecx (:edi (:edi-offset scratch0))))
- (:movzxw (:eax :edx ,(+ 2 (bt:slot-offset 'movitz:movitz-bignum 'movitz::bigit0)))
- :ecx)
- (:locally (:cmpl :ecx (:edi (:edi-offset scratch0))))
- (:jne 'negative-upper-16-decisive)
- (:movzxw (:ebx :edx ,(bt:slot-offset 'movitz:movitz-bignum 'movitz::bigit0))
- :ecx) ; Then compare lower 16 bits.
- (:locally (:movl :ecx (:edi (:edi-offset scratch0))))
- (:movzxw (:eax :edx ,(bt:slot-offset 'movitz:movitz-bignum 'movitz::bigit0))
- :ecx) ; Then compare lower 16 bits.
- (:locally (:cmpl :ecx (:edi (:edi-offset scratch0))))
- negative-upper-16-decisive
- (:ret))))
- (do-it)))
-
-(define-primitive-function fast-eql (x y)
- "Compare EAX and EBX under EQL, result in ZF.
-Preserve EAX and EBX."
- (macrolet
- ((do-it ()
- `(with-inline-assembly (:returns :nothing) ; unspecified
- (:cmpl :eax :ebx) ; EQ?
- (:je 'done)
- (:leal (:eax ,(- (movitz:tag :other))) :ecx)
- (:testb 7 :cl)
- (:jne 'done)
- (:leal (:ebx ,(- (movitz:tag :other))) :ecx)
- (:testb 7 :cl)
- (:jne 'done)
- (:movl (:eax ,movitz:+other-type-offset+) :ecx)
- (:cmpb ,(movitz:tag :bignum) :cl)
- (:jne 'done)
- (:cmpl :ecx (:ebx ,movitz:+other-type-offset+))
- (:jne 'done)
- ;; Ok.. we have two bignums of identical sign and size.
- (:shrl 16 :ecx)
- (:movl :ecx :edx) ; counter
- compare-loop
- (:subl ,movitz:+movitz-fixnum-factor+ :edx)
- (:jz 'done)
- (:movl (:eax :edx ,(+ -4 (bt:slot-offset 'movitz:movitz-bignum 'movitz::bigit0)))
- :ecx)
- (:cmpl :ecx
- (:ebx :edx ,(+ -4 (bt:slot-offset 'movitz:movitz-bignum 'movitz::bigit0))))
- (:je 'compare-loop)
- done
- (:ret))))
- (do-it)))
-
-(define-primitive-function fast-compare-fixnum-real (n1 n2)
- "Compare (known) fixnum <n1> with real <n2>."
- (macrolet
- ((do-it ()
- `(with-inline-assembly (:returns :nothing) ; unspecified
- (:testb ,movitz::+movitz-fixnum-zmask+ :bl)
- (:jnz 'n2-not-fixnum)
- (:cmpl :ebx :eax)
- (:ret)
- n2-not-fixnum
- (:leal (:ebx ,(- (movitz:tag :other))) :ecx)
- (:testb 7 :cl)
- (:jnz '(:sub-program (not-integer)
- (:int 107)
- (:jmp 'not-integer)))
- (:movl (:ebx ,movitz:+other-type-offset+) :ecx)
- (:cmpw ,(movitz:tag :bignum 0) :cx)
- (:jne 'not-plusbignum)
- ;; compare eax with something bigger
- (:cmpl #x10000000 :edi)
- (:ret)
- not-plusbignum
- (:cmpw ,(movitz:tag :bignum #xff) :cx)
- (:jne 'not-integer)
- ;; compare ebx with something bigger
- (:cmpl #x-10000000 :edi)
- (:ret))))
- (do-it)))
-
-(define-primitive-function fast-compare-real-fixnum (n1 n2)
- "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)))
- (: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)))
-
-;;;
-
-(define-compiler-macro <=%3op (min x max &environment env)
- (cond
- ((and (movitz:movitz-constantp min env)
- (movitz:movitz-constantp max env))
- (let ((min (movitz:movitz-eval min env))
- (max (movitz:movitz-eval max env)))
- (check-type min fixnum)
- (check-type max fixnum)
- ;; (warn "~D -- ~D" min max)
- (cond
- ((movitz:movitz-constantp x env)
- (<= min (movitz:movitz-eval x env) max))
- ((< max min)
- nil)
- ((= max min)
- `(= ,x ,min))
- ((minusp min)
- `(let ((x ,x))
- (and (<= ,min x) (<= x ,max))))
- ((= 0 min)
- `(with-inline-assembly (:returns :boolean-cf=1)
- (:compile-form (:result-mode :eax) ,x)
- (:testb ,movitz::+movitz-fixnum-zmask+ :al)
- (:jnz '(:sub-program () (:int 107)))
- (:cmpl ,(* (1+ max) movitz::+movitz-fixnum-factor+) :eax)))
- (t `(do-result-mode-case ()
- (:booleans
- (with-inline-assembly (:returns :boolean-zf=0)
- (:compile-form (:result-mode :eax) ,x)
- (:testb ,movitz::+movitz-fixnum-zmask+ :al)
- (:jnz '(:sub-program () (:int 107)))
- (:cmpl ,(* min movitz::+movitz-fixnum-factor+) :eax)
- (:sbbl :ecx :ecx)
- (:cmpl ,(* (1+ max) movitz::+movitz-fixnum-factor+) :eax)
- (:adcl 0 :ecx)))
- (t (with-inline-assembly (:returns (:boolean-ecx 1 0))
- (:compile-form (:result-mode :eax) ,x)
- (:testb ,movitz::+movitz-fixnum-zmask+ :al)
- (:jnz '(:sub-program () (:int 107)))
- (:cmpl ,(* min movitz::+movitz-fixnum-factor+) :eax)
- (:sbbl :ecx :ecx)
- (:cmpl ,(* (1+ max) movitz::+movitz-fixnum-factor+) :eax)
- (:adcl 0 :ecx))))))))
- #+ignore ; this is buggy.
- ((movitz:movitz-constantp min env)
- (let ((min (movitz:movitz-eval min env)))
- (check-type min fixnum)
- (cond
- ((minusp min)
- `(let ((x ,x))
- (and (<= ,min x) (<= x ,max))))
- (t `(do-result-mode-case ()
- (:booleans
- (with-inline-assembly (:returns :boolean-zf=1)
- (:compile-two-forms (:eax :ebx) ,x ,max)
- (:movl :eax :ecx)
- (:orl :ebx :ecx)
- (:testb ,movitz::+movitz-fixnum-zmask+ :cl)
- (:jne '(:sub-program () (:int 107)))
- (:cmpl :eax :ebx)
- (:sbbl :ecx :ecx)
- ,@(unless (= 0 min)
- `((:subl ,(* min movitz::+movitz-fixnum-factor+) :ebx)))
- (:addl :ebx :ebx)
- (:adcl 0 :ecx)))
- (t (with-inline-assembly (:returns (:boolean-ecx 0 1))
- (:compile-two-forms (:eax :ebx) ,x ,max)
- (:movl :eax :ecx)
- (:orl :ebx :ecx)
- (:testb ,movitz::+movitz-fixnum-zmask+ :cl)
- (:jne '(:sub-program () (:int 107)))
- (:cmpl :eax :ebx) ; if x>max, CF=1
- (:sbbl :ecx :ecx) ; ecx = x>max ? -1 : 0
- ,@(unless (= 0 min)
- `((:subl ,(* min movitz::+movitz-fixnum-factor+) :ebx)))
- (:addl :ebx :ebx) ; if x<min, CF=1
- (:adcl 0 :ecx) ;
- (:andl 1 :ecx))))))))
- (t `(let ((x ,x))
- (and (<= ,min x) (<= x ,max))))))
-
-
-(defmacro define-number-relational (name 2op-name condition &key (defun-p t) 3op-name)
- `(progn
- ,(when condition
- `(define-compiler-macro ,2op-name (n1 n2)
- (cond
- ((movitz:movitz-constantp n1)
- (let ((n1 (movitz::movitz-eval n1)))
- (check-type n1 (signed-byte 30))
- `(with-inline-assembly (:returns ,,condition :side-effects nil)
- (:compile-two-forms (:eax :ebx) ,n1 ,n2)
- (:call-global-pf fast-compare-fixnum-real))))
- ((movitz:movitz-constantp n2)
- (let ((n2 (movitz::movitz-eval n2)))
- (check-type n2 (signed-byte 30))
- `(with-inline-assembly (:returns ,,condition :side-effects nil)
- (:compile-two-forms (:eax :ebx) ,n1 ,n2)
- (:call-global-pf fast-compare-real-fixnum))))
- (t `(with-inline-assembly (:returns ,,condition :side-effects nil)
- (:compile-two-forms (:eax :ebx) ,n1 ,n2)
- (:call-global-pf fast-compare-two-reals))))))
-
- (defun ,2op-name (n1 n2)
- (,2op-name n1 n2))
-
- (define-compiler-macro ,name (&whole form number &rest more-numbers)
- (case (length more-numbers)
- (0 `(progn ,number t))
- (1 `(,',2op-name ,number ,(first more-numbers)))
- ,@(when 3op-name
- `((2 `(,',3op-name ,number ,(first more-numbers) ,(second more-numbers)))))
- (t #+ignore (when (= 2 (length more-numbers))
- (warn "3op: ~S" form))
- `(and (,',2op-name ,number ,(first more-numbers))
- (,',name ,@more-numbers)))))
-
- ,(when defun-p
- `(defun ,name (number &rest more-numbers)
- (declare (dynamic-extent more-numbers))
- (cond
- ((null more-numbers)
- (check-type number fixnum)
- t)
- ((not (cdr more-numbers))
- (,2op-name number (first more-numbers)))
- (t (and (,2op-name number (first more-numbers))
- (do ((p more-numbers (cdr p)))
- ((not (cdr p)) t)
- (unless (,2op-name (car p) (cadr p))
- (return nil))))))))))
-
-(define-number-relational >= >=%2op :boolean-greater-equal)
-(define-number-relational > >%2op :boolean-greater)
-(define-number-relational < <%2op :boolean-less)
-(define-number-relational <= <=%2op :boolean-less-equal :3op-name <=%3op)
-
-;;; Unsigned
-
-(define-compiler-macro below (&whole form x max &environment env)
- (let ((below-not-integer (gensym "below-not-integer-")))
- (if (movitz:movitz-constantp max env)
- `(with-inline-assembly (:returns :boolean-cf=1)
- (:compile-form (:result-mode :eax) ,x)
- (:testb ,movitz::+movitz-fixnum-zmask+ :al)
- (:jnz '(:sub-program (,below-not-integer) (:int 107)))
- (:cmpl ,(* (movitz:movitz-eval max env)
- movitz::+movitz-fixnum-factor+)
- :eax))
- `(with-inline-assembly (:returns :boolean-cf=1)
- (:compile-two-forms (:eax :ebx) ,x ,max)
- (:movl :eax :ecx)
- (:orl :ebx :ecx)
- (:testb ,movitz::+movitz-fixnum-zmask+ :cl)
- (:jnz '(:sub-program (,below-not-integer) (:int 107)))
- (:cmpl :ebx :eax)))))
-
-(defun below (x max)
- "Is x between 0 and max?"
- (below x max))
-
-
-;;; Equality
+ not-size1
+ (:declare-label-set retry-jumper (retry-not-size1))
+ (:locally (:movl :esp (:edi (:edi-offset atomically-esp))))
+ (:locally (:movl '(:funcall ,(movitz::atomically-status-jumper-fn t :esp)
+ 'retry-jumper)
+ (:edi (:edi-offset atomically-status))))
+ (:leal ((:ecx 1) ,(* 2 movitz:+movitz-fixnum-factor+))
+ :eax) ; Number of words
+ (:call-local-pf get-cons-pointer)
+ (:load-lexical (:lexical-binding y) :ebx) ; bignum
+ (:movzxw (:ebx ,(bt:slot-offset 'movitz::movitz-bignum 'movitz::length)) :ecx)
+ (:leal ((:ecx 1) ,movitz:+movitz-fixnum-factor+)
+ :edx)
+ (:movl 0 (:eax :edx ,movitz:+other-type-offset+)) ; MSB
+ copy-bignum-loop
+ (:subl ,movitz:+movitz-fixnum-factor+ :edx)
+ (:movl (:ebx :edx ,movitz:+other-type-offset+) :ecx)
+ (:movl :ecx (:eax :edx ,movitz:+other-type-offset+))
+ (:jnz 'copy-bignum-loop)
-(define-compiler-macro =%2op (n1 n2 &environment env)
- (cond
- ((movitz:movitz-constantp n1 env)
- (let ((n1 (movitz:movitz-eval n1 env)))
- (etypecase n1
- ((eql 0)
- `(do-result-mode-case ()
- (:booleans
- (with-inline-assembly (:returns :boolean-zf=1 :side-effects nil)
- (:compile-form (:result-mode :eax) ,n2)
- (:testl :eax :eax)))
- (t (with-inline-assembly (:returns :boolean-cf=1 :side-effects nil)
- (:compile-form (:result-mode :eax) ,n2)
- (:cmpl 1 :eax)))))
- ((signed-byte 30)
- `(with-inline-assembly (:returns :boolean-zf=1 :side-effects nil)
- (:compile-two-forms (:eax :ebx) ,n1 ,n2)
- (:call-global-pf fast-compare-fixnum-real)))
- (integer
- `(with-inline-assembly (:returns :boolean-zf=1 :side-effects nil)
- (:compile-two-forms (:eax :ebx) ,n1 ,n2)
- (:call-global-pf fast-compare-two-reals))))))
- ((movitz:movitz-constantp n2 env)
- `(=%2op ,n2 ,n1))
- (t `(with-inline-assembly (:returns :boolean-zf=1 :side-effects nil)
- (:compile-two-forms (:eax :ebx) ,n1 ,n2)
- (:call-global-pf fast-compare-two-reals)))))
+ (:load-lexical (:lexical-binding x) :ebx)
+ (:xorl :edx :edx) ; counter
+ (:xorl :ecx :ecx) ; Carry
+ add-bignum-loop
+ (:cmpw :dx (:ebx ,(bt:slot-offset 'movitz::movitz-bignum 'movitz::length)))
+ (:jbe '(:sub-program (zero-padding-loop)
+ (:addl :ecx (:eax :edx ,(bt:slot-offset 'movitz::movitz-bignum
+ 'movitz::bigit0)))
+ (:sbbl :ecx :ecx)
+ (:negl :ecx) ; ECX = Add's Carry.
+ (:addl 4 :edx)
+ (:cmpw :dx (:eax ,(bt:slot-offset 'movitz::movitz-bignum 'movitz::length)))
+ (:jae 'zero-padding-loop)
+ (:jmp 'add-bignum-done)))
+ (:addl (:ebx :edx ,(bt:slot-offset 'movitz::movitz-bignum 'movitz::bigit0))
+ :ecx)
+ (:jc '(:sub-program (term1-carry)
+ ;; The digit + carry carried over, ECX = 0
+ (:addl 1 :ecx)
+ (:addl 4 :edx)
+ (:cmpw :dx (:eax ,(bt:slot-offset 'movitz::movitz-bignum 'movitz::length)))
+ (:jae 'add-bignum-loop)
+ (:jmp 'add-bignum-done)))
+ (:addl :ecx (:eax :edx ,(bt:slot-offset 'movitz::movitz-bignum 'movitz::bigit0)))
+ (:sbbl :ecx :ecx)
+ (:negl :ecx) ; ECX = Add's Carry.
+ (:addl 4 :edx)
+ (:cmpw :dx (:eax ,(bt:slot-offset 'movitz::movitz-bignum 'movitz::length)))
+ (:jae 'add-bignum-loop)
+ add-bignum-done
+ (:movzxw (:eax ,(bt:slot-offset 'movitz::movitz-bignum 'movitz::length))
+ :ecx)
+ (:leal ((:ecx 1) ,movitz:+movitz-fixnum-factor+)
+ :ecx)
+ (:cmpl 0 (:eax :ecx ,(+ -4 (bt:slot-offset 'movitz::movitz-bignum 'movitz::bigit0))))
+ (:je 'no-expansion)
+ (:addl #x40000 (:eax ,movitz:+other-type-offset+))
+ (:addl ,movitz:+movitz-fixnum-factor+ :ecx)
+ no-expansion
+ (:call-local-pf cons-commit)
+ (:locally (:movl ,(bt:enum-value 'movitz::atomically-status :inactive)
+ (:edi (:edi-offset atomically-status))))
+ pfix-pbig-done)
+ ))
+ (((integer * -1) (integer 0 *))
+ (- y (- x)))
+ (((integer 0 *) (integer * -1))
+ (- x (- y)))
+ (((integer * -1) (integer * -1))
+ (%negatef (+ (- x) (- y)) x y))
+ )))
+ (do-it)))
+ (t (&rest terms)
+ (declare (dynamic-extent terms))
+ (if (null terms)
+ 0
+ (reduce #'+ terms)))))
-(define-number-relational = =%2op nil :defun-p nil)
+(defun 1+ (number)
+ (+ 1 number))
-(defun = (first-number &rest numbers)
- (declare (dynamic-extent numbers))
- (dolist (n numbers t)
- (unless (= first-number n)
- (return nil))))
+(defun 1- (number)
+ (+ -1 number))
-(define-number-relational /= /=%2op :boolean-zf=0 :defun-p nil)
+;;; Subtraction
-(defun /= (&rest numbers)
- (declare (dynamic-extent numbers))
- (do ((p (cdr numbers) (cdr p)))
- ((null p) t)
- (do ((v numbers (cdr v)))
- ((eq p v))
- (when (= (car p) (car v))
- (return-from /= nil)))))
+(defun - (minuend &rest subtrahends)
+ (declare (dynamic-extent subtrahends))
+ (numargs-case
+ (1 (x)
+ (macrolet
+ ((do-it ()
+ `(with-inline-assembly (:returns :eax)
+ (:compile-form (:result-mode :eax) x)
+ (:testb ,movitz:+movitz-fixnum-zmask+ :al)
+ (:jnz '(:sub-program (not-fixnum)
+ (:leal (:eax ,(- (movitz:tag :other))) :ecx)
+ (:testb 7 :cl)
+ (:jnz '(:sub-program (not-a-number)
+ (:compile-form (:result-mode :ignore)
+ (error 'type-error :expected-type 'number :datum x))))
+ (:movl (:eax ,movitz:+other-type-offset+) :ecx)
+ (:cmpb ,(movitz:tag :bignum) :cl)
+ (:jne 'not-a-number)
+ (:cmpl ,(dpb 4 (byte 16 16) (movitz:tag :bignum 0)) :ecx)
+ (:jne 'not-most-negative-fixnum)
+ (:cmpl ,(- most-negative-fixnum)
+ (:eax ,(bt:slot-offset 'movitz::movitz-bignum 'movitz::bigit0)))
+ (:jne 'not-most-negative-fixnum)
+ (:movl ,(ldb (byte 32 0)
+ (* most-negative-fixnum movitz::+movitz-fixnum-factor+))
+ :eax)
+ (:jmp 'fix-ok)
+ not-most-negative-fixnum
+ (:compile-form (:result-mode :eax)
+ (copy-bignum x))
+ (:notb (:eax ,(bt:slot-offset 'movitz::movitz-bignum 'movitz::sign)))
+ (:jmp 'fix-ok)))
+ (:negl :eax)
+ (:jo '(:sub-program (fix-overflow)
+ (:compile-form (:result-mode :eax)
+ ,(1+ movitz:+movitz-most-positive-fixnum+))
+ (:jmp 'fix-ok)))
+ fix-ok
+ )))
+ (do-it)))
+ (2 (minuend subtrahend)
+ (macrolet
+ ((do-it ()
+ `(number-double-dispatch (minuend subtrahend)
+ ((t (eql 0))
+ minuend)
+ (((eql 0) t)
+ (- subtrahend))
+ ((fixnum fixnum)
+ (with-inline-assembly (:returns :eax :side-effects nil)
+ (:compile-two-forms (:eax :ebx) minuend subtrahend)
+ (:subl :ebx :eax)
+ (:into)))
+ ((positive-bignum fixnum)
+ (+ (- subtrahend) minuend))
+ ((fixnum positive-bignum)
+ (- (+ (- minuend) subtrahend)))
+ ((positive-bignum positive-bignum)
+ (cond
+ ((= minuend subtrahend)
+ 0)
+ ((< minuend subtrahend)
+ (let ((x (- subtrahend minuend)))
+ (%negatef x subtrahend minuend)))
+ (t (%bignum-canonicalize
+ (with-inline-assembly (:returns :eax)
+ (:compile-two-forms (:eax :ebx) (copy-bignum minuend) subtrahend)
+ (:xorl :edx :edx) ; counter
+ (:xorl :ecx :ecx) ; carry
+ sub-loop
+ (:addl (:ebx :edx ,(bt:slot-offset 'movitz::movitz-bignum 'movitz::bigit0))
+ :ecx)
+ (:jc '(:sub-program (carry-overflow)
+ ;; Just propagate carry
+ (:addl 1 :ecx)
+ (:addl 4 :edx)
+ (:cmpw :dx (:ebx ,(bt:slot-offset 'movitz::movitz-bignum 'movitz::length)))
+ (:jne 'sub-loop)
+ (:jmp 'bignum-sub-done)))
+ (:subl :ecx
+ (:eax :edx ,(bt:slot-offset 'movitz::movitz-bignum 'movitz::bigit0)))
+ (:sbbl :ecx :ecx)
+ (:negl :ecx)
+ (:addl 4 :edx)
+ (:cmpw :dx (:ebx ,(bt:slot-offset 'movitz::movitz-bignum 'movitz::length)))
+ (:jne 'sub-loop)
+ (:subl :ecx
+ (:eax :edx ,(bt:slot-offset 'movitz::movitz-bignum 'movitz::bigit0)))
+ (:jnc 'bignum-sub-done)
+ propagate-carry
+ (:addl 4 :edx)
+ (:subl 1 (:eax :edx ,(bt:slot-offset 'movitz::movitz-bignum 'movitz::bigit0)))
+ (:jc 'propagate-carry)
+ bignum-sub-done
+ )))))
+ (((integer 0 *) (integer * -1))
+ (+ minuend (- subtrahend)))
+ (((integer * -1) (integer 0 *))
+ (%negatef (+ (- minuend) subtrahend) minuend subtrahend))
+ (((integer * -1) (integer * -1))
+ (+ minuend (- subtrahend)))
+ )))
+ (do-it)))
+ (t (minuend &rest subtrahends)
+ (declare (dynamic-extent subtrahends))
+ (if subtrahends
+ (reduce #'- subtrahends :initial-value minuend)
+ (- minuend)))))
;;;
(defun zerop (number)
(= 0 number))
-(define-compiler-macro zerop (number)
- `(= 0 ,number))
-
(defun plusp (number)
(> number 0))
-(define-compiler-macro plusp (number)
- `(> ,number 0))
-
(defun minusp (number)
(< number 0))
-(define-compiler-macro minusp (number)
- `(< ,number 0))
-
-(define-compiler-macro abs (x)
- `(let ((x ,x))
- (if (>= x 0) x (- x))))
-
(defun abs (x)
- (abs x))
+ (compiler-macro-call abs x))
(defun signum (x)
(cond
@@ -995,19 +824,10 @@
;;;
-(define-compiler-macro max (&whole form first-number &rest more-numbers)
- (case (length more-numbers)
- (0 first-number)
- (1 `(let ((x ,first-number)
- (y ,(car more-numbers)))
- (if (>= x y) x y)))
- ((2 3 4)
- `(max ,first-number (max ,@more-numbers)))
- (t form)))
-
(defun max (number1 &rest numbers)
(numargs-case
- (2 (x y) (max x y))
+ (2 (x y)
+ (compiler-macro-call max x y))
(t (number1 &rest numbers)
(declare (dynamic-extent numbers))
(let ((max number1))
@@ -1015,19 +835,10 @@
(when (> x max)
(setq max x)))))))
-(define-compiler-macro min (&whole form first-number &rest more-numbers)
- (case (length more-numbers)
- (0 first-number)
- (1 `(let ((x ,first-number)
- (y ,(car more-numbers)))
- (if (<= x y) x y)))
- ((2 3 4)
- `(min ,first-number (min ,@more-numbers)))
- (t form)))
-
(defun min (number1 &rest numbers)
(numargs-case
- (2 (x y) (min x y))
+ (2 (x y)
+ (compiler-macro-call min x y))
(t (number1 &rest numbers)
(declare (dynamic-extent numbers))
(let ((min number1))
@@ -1037,54 +848,6 @@
;; shift
-(define-compiler-macro ash (&whole form integer count &environment env)
- (if (not (movitz:movitz-constantp count env))
- form
- (let ((count (movitz:movitz-eval count env)))
- (cond
- ((movitz:movitz-constantp integer env)
- (ash (movitz::movitz-eval integer env) count))
- ((= 0 count)
- integer)
- (t form
- #+igore
- (let ((load-integer `((:compile-form (:result-mode :register) ,integer)
- (:testb ,movitz::+movitz-fixnum-zmask+ (:result-register-low8))
- (:jnz '(:sub-program () (:int 107) (:jmp (:pc+ -4)))))))
- (cond
- ((<= 1 count 4)
- `(with-inline-assembly (:returns :register :side-effects nil)
- ,@load-integer
- ,@(loop repeat count
- append `((:addl (:result-register) (:result-register))
- (:into)))))
- ((< 0 count #.(cl:1- movitz::+movitz-fixnum-bits+))
- `(with-inline-assembly (:returns :register :side-effects nil :type integer)
- ,@load-integer
- (:cmpl ,(ash 1 (- (- 31 0) count))
- (:result-register))
- (:jge '(:sub-program () (:int 4)))
- (:cmpl ,(- (ash 1 (- (- 31 0) count)))
- (:result-register))
- (:jl '(:sub-program () (:int 4)))
- (:shll ,count (:result-register))))
- ((= -1 count)
- `(with-inline-assembly (:returns :register :side-effects nil :type integer)
- ,@load-integer
- (:andb #.(cl:logxor #xfe (cl:* 2 movitz::+movitz-fixnum-zmask+)) (:result-register-low8))
- (:sarl 1 (:result-register))))
- ((> 0 count #.(cl:- (cl:1- movitz::+movitz-fixnum-bits+)))
- `(with-inline-assembly (:returns :register :side-effects nil :type integer)
- ,@load-integer
- (:andl ,(ldb (byte 32 0)
- (ash movitz:+movitz-most-positive-fixnum+
- (- movitz:+movitz-fixnum-shift+ count)))
- (:result-register))
- (:sarl ,(- count) (:result-register))))
- ((minusp count)
- `(if (minusp ,integer) -1 0))
- (t `(if (= 0 ,integer) 0 (with-inline-assembly (:returns :non-local-exit) (:int 4)))))))))))
-
(defun ash (integer count)
(cond
((= 0 count)
@@ -1202,30 +965,6 @@
;;; Multiplication
-(define-compiler-macro * (&whole form &rest operands &environment env)
- (case (length operands)
- (0 0)
- (1 (first operands))
- (2 (let ((factor1 (first operands))
- (factor2 (second operands)))
- (cond
- ((and (movitz:movitz-constantp factor1 env)
- (movitz:movitz-constantp factor2 env))
- (* (movitz:movitz-eval factor1 env)
- (movitz:movitz-eval factor2 env)))
- ((movitz:movitz-constantp factor2 env)
- `(* ,(movitz:movitz-eval factor2 env) ,factor1))
- ((movitz:movitz-constantp factor1 env)
- (let ((f1 (movitz:movitz-eval factor1 env)))
- (check-type f1 integer)
- (case f1
- (0 `(progn ,factor2 0))
- (1 factor2)
- (2 `(let ((x ,factor2)) (+ x x)))
- (t `(no-macro-call * ,factor1 ,factor2)))))
- (t `(no-macro-call * ,factor1 ,factor2)))))
- (t `(* (* ,(first operands) ,(second operands)) ,@(cddr operands)))))
-
(defun * (&rest factors)
(numargs-case
(1 (x) x)
@@ -1637,16 +1376,6 @@
(defun byte (size position)
(+ (* size #x400) position))
-(define-compiler-macro byte (&whole form size position)
- (cond
- ((and (integerp size)
- (integerp position))
- (+ (* size #x400) position))
- #+ignore
- ((integerp size)
- `(+ ,position ,(* size #x400)))
- (t form)))
-
(defun byte-size (bytespec)
(truncate bytespec #x400))
@@ -1671,24 +1400,6 @@
(:btl :ecx (:ebx ,(bt:slot-offset 'movitz::movitz-bignum 'movitz::bigit0))))))))
(do-it)))
-(define-compiler-macro logand (&whole form &rest integers &environment env)
- (let ((constant-folded-integers (loop for x in integers
- with folded-constant = -1
- if (and (movitz:movitz-constantp x env)
- (not (= -1 (movitz:movitz-eval x env))))
- do (setf folded-constant
- (logand folded-constant (movitz:movitz-eval x env)))
- else collect x into non-constants
- finally (return (if (= -1 folded-constant)
- non-constants
- (cons folded-constant non-constants))))))
- (case (length constant-folded-integers)
- (0 0)
- (1 (first constant-folded-integers))
- (2 `(no-macro-call logand ,(first constant-folded-integers) ,(second constant-folded-integers)))
- (t `(logand (logand ,(first constant-folded-integers) ,(second constant-folded-integers))
- ,@(cddr constant-folded-integers))))))
-
(defun logand (&rest integers)
(numargs-case
(1 (x) x)
@@ -1834,24 +1545,6 @@
0
(reduce #'logior integers)))))
-(define-compiler-macro logior (&whole form &rest integers &environment env)
- (let ((constant-folded-integers (loop for x in integers
- with folded-constant = 0
- if (and (movitz:movitz-constantp x env)
- (not (zerop (movitz:movitz-eval x env))))
- do (setf folded-constant
- (logior folded-constant (movitz:movitz-eval x env)))
- else collect x into non-constants
- finally (return (if (= 0 folded-constant)
- non-constants
- (cons folded-constant non-constants))))))
- (case (length constant-folded-integers)
- (0 0)
- (1 (first constant-folded-integers))
- (2 `(no-macro-call logior ,(first constant-folded-integers) ,(second constant-folded-integers)))
- (t `(logior (logior ,(first constant-folded-integers) ,(second constant-folded-integers))
- ,@(cddr constant-folded-integers))))))
-
(defun logxor (&rest integers)
(numargs-case
(1 (x) x)
@@ -2271,104 +1964,10 @@
(:edi (:edi-offset atomically-status))))
ldb-done))))
(do-it)))))))
-
-
-(define-compiler-macro ldb%byte (&whole form &environment env size position integer)
- "This is LDB with explicit byte-size and position parameters."
- (cond
- ((and (movitz:movitz-constantp size env)
- (movitz:movitz-constantp position env)
- (movitz:movitz-constantp integer env))
- (ldb (byte (movitz:movitz-eval size env)
- (movitz:movitz-eval position env))
- (movitz:movitz-eval integer env))) ; constant folding
- ((and (movitz:movitz-constantp size env)
- (movitz:movitz-constantp position env))
- (let* ((size (movitz:movitz-eval size env))
- (position (movitz:movitz-eval position env))
- (result-type `(unsigned-byte ,size)))
- (cond
- ((or (minusp size) (minusp position))
- (error "Negative byte-spec for ldb."))
- ((= 0 size)
- `(progn ,integer 0))
- ((<= (+ size position) (- 31 movitz:+movitz-fixnum-shift+))
- `(with-inline-assembly (:returns :register
- :type ,result-type)
- (:compile-form (:result-mode :eax) ,integer)
- (:call-global-pf unbox-u32)
- (:andl ,(mask-field (byte size position) -1) :ecx)
- ,@(unless (zerop position)
- `((:shrl ,position :ecx)))
- (:leal ((:ecx ,movitz:+movitz-fixnum-factor+)) (:result-register))))
- ((<= (+ size position) 32)
- `(with-inline-assembly-case (:type ,result-type)
- (do-case (t :eax :labels (nix done))
- (:compile-form (:result-mode :eax) ,integer)
- ,@(cond
- ((and (= 0 position) (= 32 size))
- ;; If integer is a positive bignum with one bigit, return it.
- `((:leal (:eax ,(- (movitz:tag :other))) :ecx)
- (:testb 7 :cl)
- (:jnz 'nix)
- (:cmpl ,(dpb 4 (byte 16 16) (movitz:tag :bignum 0))
- (:eax ,movitz:+other-type-offset+))
- (:je 'done)))
- ((and (= 0 position) (<= (- 32 movitz:+movitz-fixnum-shift+) size ))
- `((:leal (:eax ,(- (movitz:tag :other))) :ecx)
- (:testb 7 :cl)
- (:jnz 'nix)
- (:cmpl ,(dpb 4 (byte 16 16) (movitz:tag :bignum 0))
- (:eax ,movitz:+other-type-offset+))
- (:jne 'nix)
- (:movl (:eax ,(bt:slot-offset 'movitz::movitz-bignum 'movitz::bigit0))
- :ecx)
- (:testl ,(logxor #xffffffff (mask-field (byte size 0) -1))
- :ecx)
- (:jz 'done)
- (:andl ,(mask-field (byte size 0) -1)
- :ecx)
- (:call-local-pf box-u32-ecx)
- (:jmp 'done))))
- nix
- (:call-global-pf unbox-u32)
- ,@(unless (= 32 (- size position))
- `((:andl ,(mask-field (byte size position) -1) :ecx)))
- ,@(unless (zerop position)
- `((:shrl ,position :ecx)))
- (:call-local-pf box-u32-ecx)
- done)))
- (t form))))
- (t form)))
(defun ldb (bytespec integer)
(ldb%byte (byte-size bytespec) (byte-position bytespec) integer))
-(define-compiler-macro ldb (&whole form &environment env bytespec integer)
- (let ((bytespec (movitz::movitz-macroexpand bytespec env)))
- (if (not (and (consp bytespec) (eq 'byte (car bytespec))))
- form
- `(ldb%byte ,(second bytespec) ,(third bytespec) ,integer))))
-
-(define-setf-expander ldb (bytespec int &environment env)
- "Stolen from the Hyperspec example in the define-setf-expander entry."
- (multiple-value-bind (temps vals stores store-form access-form)
- (get-setf-expansion int env) ;Get setf expansion for int.
- (let ((btemp (gensym)) ;Temp var for byte specifier.
- (store (gensym)) ;Temp var for byte to store.
- (stemp (first stores))) ;Temp var for int to store.
- (if (cdr stores) (error "Can't expand this."))
- ;; Return the setf expansion for LDB as five values.
- (values (cons btemp temps) ;Temporary variables.
- (cons bytespec vals) ;Value forms.
- (list store) ;Store variables.
- `(let ((,stemp (dpb ,store ,btemp ,access-form)))
- ,store-form
- ,store) ;Storing form.
- `(ldb ,btemp ,access-form) ;Accessing form.
- ))))
-
-
(defun ldb-test (bytespec integer)
(case (byte-size bytespec)
(0 nil)
@@ -2456,14 +2055,6 @@
r+1
r)))
(setf r next-r))))))
-
-(define-compiler-macro expt (&whole form base-number power-number &environment env)
- (if (not (and (movitz:movitz-constantp base-number env)
- (movitz:movitz-constantp power-number env)))
- form
- (expt (movitz:movitz-eval base-number env)
- (movitz:movitz-eval power-number env))))
-
(defun expt (base-number power-number)
"Take base-number to the power-number."