mirror of
git://git.code.sf.net/p/sbcl/sbcl
synced 2026-09-10 07:26:40 -04:00
Better bignum multiplication
Some checks are pending
CL-host / ecl (push) Waiting to run
CL-host / clisp (push) Waiting to run
CL-host / ccl (push) Waiting to run
CL-host / cmucl (push) Waiting to run
CL-host / sbcl (push) Waiting to run
CL-host / compare-xc-host-fasls (ccl, false) (push) Blocked by required conditions
CL-host / compare-xc-host-fasls (clisp, false) (push) Blocked by required conditions
CL-host / compare-xc-host-fasls (cmucl, false) (push) Blocked by required conditions
CL-host / compare-xc-host-fasls (self, false) (push) Blocked by required conditions
Linux arm / build (push) Waiting to run
Linux arm64 / build () (push) Waiting to run
Linux qemu / build (ppc64le) (push) Waiting to run
Linux qemu / build (riscv64) (push) Waiting to run
Linux / build (x86, --with-sb-thread, ) (push) Waiting to run
Linux / build (x86, --without-sb-thread, ) (push) Waiting to run
Linux / build (x86, --without-sb-unicode, ) (push) Waiting to run
Linux / build (x86-64, --with-mark-region-gc --with-nonstop-foreign-call) (push) Waiting to run
Linux / build (x86-64, --with-sb-fasteval --without-sb-eval --with-nonstop-foreign-call, fasteval) (push) Waiting to run
Linux / build (x86-64, --with-sb-thread --with-nonstop-foreign-call --with-tls-based-mv-return, sse4) (push) Waiting to run
Linux / build (x86-64, --with-sb-thread, ) (push) Waiting to run
Linux / build (x86-64, --without-sb-thread, ) (push) Waiting to run
Linux / build (x86-64, --without-sb-unicode, ) (push) Waiting to run
Mac / build (arm64, --with-mark-region-gc --with-nonstop-foreign-call --with-tls-based-mv-return) (push) Waiting to run
Mac / build (arm64, --with-sb-thread --with-nonstop-foreign-call --with-tls-based-mv-return) (push) Waiting to run
Mac / build (x86-64, --with-mark-region-gc --with-nonstop-foreign-call --with-tls-based-mv-return) (push) Waiting to run
Mac / build (x86-64, --with-sb-thread --with-nonstop-foreign-call --with-tls-based-mv-return) (push) Waiting to run
Windows arm64 / build (arm64, clang-aarch64, clangarm64) (push) Waiting to run
Windows / build (x86-64, ucrt-x86_64, ucrt64) (push) Waiting to run
Some checks are pending
CL-host / ecl (push) Waiting to run
CL-host / clisp (push) Waiting to run
CL-host / ccl (push) Waiting to run
CL-host / cmucl (push) Waiting to run
CL-host / sbcl (push) Waiting to run
CL-host / compare-xc-host-fasls (ccl, false) (push) Blocked by required conditions
CL-host / compare-xc-host-fasls (clisp, false) (push) Blocked by required conditions
CL-host / compare-xc-host-fasls (cmucl, false) (push) Blocked by required conditions
CL-host / compare-xc-host-fasls (self, false) (push) Blocked by required conditions
Linux arm / build (push) Waiting to run
Linux arm64 / build () (push) Waiting to run
Linux qemu / build (ppc64le) (push) Waiting to run
Linux qemu / build (riscv64) (push) Waiting to run
Linux / build (x86, --with-sb-thread, ) (push) Waiting to run
Linux / build (x86, --without-sb-thread, ) (push) Waiting to run
Linux / build (x86, --without-sb-unicode, ) (push) Waiting to run
Linux / build (x86-64, --with-mark-region-gc --with-nonstop-foreign-call) (push) Waiting to run
Linux / build (x86-64, --with-sb-fasteval --without-sb-eval --with-nonstop-foreign-call, fasteval) (push) Waiting to run
Linux / build (x86-64, --with-sb-thread --with-nonstop-foreign-call --with-tls-based-mv-return, sse4) (push) Waiting to run
Linux / build (x86-64, --with-sb-thread, ) (push) Waiting to run
Linux / build (x86-64, --without-sb-thread, ) (push) Waiting to run
Linux / build (x86-64, --without-sb-unicode, ) (push) Waiting to run
Mac / build (arm64, --with-mark-region-gc --with-nonstop-foreign-call --with-tls-based-mv-return) (push) Waiting to run
Mac / build (arm64, --with-sb-thread --with-nonstop-foreign-call --with-tls-based-mv-return) (push) Waiting to run
Mac / build (x86-64, --with-mark-region-gc --with-nonstop-foreign-call --with-tls-based-mv-return) (push) Waiting to run
Mac / build (x86-64, --with-sb-thread --with-nonstop-foreign-call --with-tls-based-mv-return) (push) Waiting to run
Windows arm64 / build (arm64, clang-aarch64, clangarm64) (push) Waiting to run
Windows / build (x86-64, ucrt-x86_64, ucrt64) (push) Waiting to run
Do not cons positive bignums at the start of the loop, the result can be adjusted in place by subtraction at the end. On arm64 and x86-64, write the whole loop in assembly, not just the first iteration.
This commit is contained in:
parent
3d4fe67e29
commit
0077dde930
|
|
@ -485,53 +485,65 @@
|
||||||
%normalize-bignum-buffer))
|
%normalize-bignum-buffer))
|
||||||
|
|
||||||
;;;; multiplication
|
;;;; multiplication
|
||||||
|
(declaim (inline %subtract-bignum-in-place))
|
||||||
|
(defun %subtract-bignum-in-place (a b offset len)
|
||||||
|
(declare (type bignum a b)
|
||||||
|
(type bignum-length offset len)
|
||||||
|
(optimize speed (safety 0)))
|
||||||
|
(let ((borrow 1))
|
||||||
|
(declare (type (integer 0 1) borrow))
|
||||||
|
(dotimes (i len)
|
||||||
|
(declare (type bignum-index i))
|
||||||
|
(let ((a-idx (the bignum-index (+ offset i))))
|
||||||
|
(multiple-value-bind (diff new-borrow)
|
||||||
|
(%subtract-with-borrow (%bignum-ref a a-idx)
|
||||||
|
(%bignum-ref b i)
|
||||||
|
borrow)
|
||||||
|
(setf (%bignum-ref a a-idx) diff)
|
||||||
|
(setf borrow new-borrow))))))
|
||||||
|
|
||||||
|
;;; See x86-64-vm.lisp for variants with mulx
|
||||||
(defun multiply-bignums (a b)
|
(defun multiply-bignums (a b)
|
||||||
(declare (type bignum a b)
|
(declare (type bignum a b)
|
||||||
(optimize speed (safety 0)))
|
(optimize speed (safety 0)))
|
||||||
(let* ((a-plusp (bignum-plus-p a))
|
(let* ((len-a (%bignum-length a))
|
||||||
(b-plusp (bignum-plus-p b))
|
|
||||||
(a (if a-plusp a (negate-bignum-not-fully-normalized a)))
|
|
||||||
(b (if b-plusp b (negate-bignum-not-fully-normalized b)))
|
|
||||||
(len-a (%bignum-length a))
|
|
||||||
(len-b (%bignum-length b))
|
(len-b (%bignum-length b))
|
||||||
(len-res (+ len-a len-b))
|
(len-res (+ len-a len-b))
|
||||||
(res (%allocate-bignum len-res))
|
(res (%allocate-bignum len-res)))
|
||||||
(negate-res (not (eq a-plusp b-plusp))))
|
|
||||||
(declare (type bignum-length len-a len-b len-res))
|
|
||||||
(when (> len-a len-b)
|
(when (> len-a len-b)
|
||||||
(rotatef a b)
|
(rotatef a b)
|
||||||
(rotatef len-a len-b))
|
(rotatef len-a len-b))
|
||||||
|
(sb-c::if-vop-existsp (:named sb-vm::bignum-multiply-loop)
|
||||||
|
(sb-sys:%primitive sb-vm::bignum-multiply-loop a len-a b len-b res)
|
||||||
|
|
||||||
;; The partial result is zero on the first iteration,
|
;; The partial result is zero on the first iteration,
|
||||||
;; so don't include it. And no need to zero when allocating it.
|
;; so don't include it. And no need to zero when allocating it.
|
||||||
(let ((x (%bignum-ref a 0)))
|
(let ((x (%bignum-ref a 0)))
|
||||||
(sb-c::if-vop-existsp (:named sb-vm::bignum-mult-and-add-word-loop)
|
|
||||||
(sb-sys:%primitive sb-vm::bignum-mult-and-add-word-loop b x len-b res)
|
|
||||||
(let ((carry-digit 0))
|
(let ((carry-digit 0))
|
||||||
(declare (fixnum carry-digit))
|
(declare (fixnum carry-digit))
|
||||||
(dotimes (index len-b)
|
(dotimes (index len-b)
|
||||||
(declare (type bignum-index index))
|
(declare (type bignum-index index))
|
||||||
(setf (values carry-digit
|
(setf (values carry-digit (%bignum-ref res index))
|
||||||
(%bignum-ref res index))
|
|
||||||
(%multiply-and-add (%bignum-ref b index) x carry-digit)))
|
(%multiply-and-add (%bignum-ref b index) x carry-digit)))
|
||||||
(setf (%bignum-ref res len-b) carry-digit))))
|
(setf (%bignum-ref res len-b) carry-digit))
|
||||||
|
(loop for i of-type bignum-index from 1 below len-a
|
||||||
(loop for i of-type bignum-index from 1 below len-a
|
do
|
||||||
do
|
(let ((x (%bignum-ref a i)))
|
||||||
(let ((x (%bignum-ref a i))
|
(let ((k i)
|
||||||
(k i)
|
(carry-digit 0))
|
||||||
(carry-digit 0))
|
(declare (type bignum-index k))
|
||||||
(declare (type bignum-index k))
|
(dotimes (j len-b)
|
||||||
(dotimes (j len-b)
|
(setf (values carry-digit (%bignum-ref res k))
|
||||||
(setf (values carry-digit (%bignum-ref res k))
|
(%multiply-and-add x
|
||||||
(%multiply-and-add x
|
(%bignum-ref b j)
|
||||||
(%bignum-ref b j)
|
(%bignum-ref res k)
|
||||||
(%bignum-ref res k)
|
carry-digit))
|
||||||
carry-digit))
|
(incf k))
|
||||||
(incf k))
|
(setf (%bignum-ref res k) carry-digit))))))
|
||||||
(setf (%bignum-ref res k) carry-digit)))
|
(unless (bignum-plus-p a)
|
||||||
(when negate-res (negate-bignum-in-place res))
|
(%subtract-bignum-in-place res b len-a len-b))
|
||||||
|
(unless (bignum-plus-p b)
|
||||||
|
(%subtract-bignum-in-place res a len-b len-a))
|
||||||
(%normalize-bignum res len-res)))
|
(%normalize-bignum res len-res)))
|
||||||
|
|
||||||
(defun multiply-bignum-and-fixnum (bignum fixnum)
|
(defun multiply-bignum-and-fixnum (bignum fixnum)
|
||||||
|
|
@ -542,25 +554,26 @@
|
||||||
((eql fixnum -1)
|
((eql fixnum -1)
|
||||||
(- bignum))
|
(- bignum))
|
||||||
(t
|
(t
|
||||||
(let* ((bignum-plus-p (bignum-plus-p bignum))
|
(let* ((bignum-len (%bignum-length bignum))
|
||||||
(fixnum-plus-p (not (minusp fixnum)))
|
(abs-fixnum (abs fixnum))
|
||||||
(bignum (if bignum-plus-p bignum (negate-bignum-not-fully-normalized bignum)))
|
|
||||||
(bignum-len (%bignum-length bignum))
|
|
||||||
(fixnum (if fixnum-plus-p fixnum (- fixnum)))
|
|
||||||
(result (%allocate-bignum (1+ bignum-len))))
|
(result (%allocate-bignum (1+ bignum-len))))
|
||||||
(declare (type bignum bignum result)
|
(declare (type bignum bignum result)
|
||||||
(type bignum-element-type fixnum))
|
(type bignum-element-type abs-fixnum))
|
||||||
(sb-c::if-vop-existsp (:named sb-vm::bignum-mult-and-add-word-loop)
|
(sb-c::if-vop-existsp (:named sb-vm::bignum-mult-and-add-word-loop)
|
||||||
(sb-sys:%primitive sb-vm::bignum-mult-and-add-word-loop bignum fixnum bignum-len result)
|
(sb-sys:%primitive sb-vm::bignum-mult-and-add-word-loop bignum abs-fixnum bignum-len result)
|
||||||
(let ((carry-digit 0))
|
(let ((carry-digit 0))
|
||||||
(declare (fixnum carry-digit))
|
(declare (fixnum carry-digit))
|
||||||
(dotimes (index bignum-len)
|
(dotimes (index bignum-len)
|
||||||
(declare (type bignum-index index))
|
(declare (type bignum-index index))
|
||||||
(setf (values carry-digit
|
(setf (values carry-digit
|
||||||
(%bignum-ref result index))
|
(%bignum-ref result index))
|
||||||
(%multiply-and-add (%bignum-ref bignum index) fixnum carry-digit)))
|
(%multiply-and-add (%bignum-ref bignum index) abs-fixnum carry-digit)))
|
||||||
(setf (%bignum-ref result bignum-len) carry-digit)))
|
(setf (%bignum-ref result bignum-len) carry-digit)))
|
||||||
(unless (eq bignum-plus-p fixnum-plus-p)
|
(unless (bignum-plus-p bignum)
|
||||||
|
(setf (%bignum-ref result bignum-len)
|
||||||
|
(logand (- (%bignum-ref result bignum-len) abs-fixnum)
|
||||||
|
most-positive-word)))
|
||||||
|
(when (minusp fixnum)
|
||||||
(negate-bignum-in-place result))
|
(negate-bignum-in-place result))
|
||||||
(%normalize-bignum result (1+ bignum-len))))))
|
(%normalize-bignum result (1+ bignum-len))))))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -352,6 +352,7 @@
|
||||||
|
|
||||||
(in-package :sb-bignum)
|
(in-package :sb-bignum)
|
||||||
|
|
||||||
|
#+x86-64
|
||||||
(sb-vm::def-variant multiply-bignum-and-fixnum :bmi2 (bignum fixnum)
|
(sb-vm::def-variant multiply-bignum-and-fixnum :bmi2 (bignum fixnum)
|
||||||
(declare (type bignum bignum) (type fixnum fixnum)
|
(declare (type bignum bignum) (type fixnum fixnum)
|
||||||
(optimize speed (safety 0)))
|
(optimize speed (safety 0)))
|
||||||
|
|
@ -360,17 +361,35 @@
|
||||||
((eql fixnum -1)
|
((eql fixnum -1)
|
||||||
(- bignum))
|
(- bignum))
|
||||||
(t
|
(t
|
||||||
(let* ((bignum-plus-p (bignum-plus-p bignum))
|
(let* ((bignum-len (%bignum-length bignum))
|
||||||
(fixnum-plus-p (not (minusp fixnum)))
|
(abs-fixnum (abs fixnum))
|
||||||
(bignum (if bignum-plus-p bignum (negate-bignum-not-fully-normalized bignum)))
|
|
||||||
(bignum-len (%bignum-length bignum))
|
|
||||||
(fixnum (if fixnum-plus-p fixnum (- fixnum)))
|
|
||||||
(result (%allocate-bignum (1+ bignum-len))))
|
(result (%allocate-bignum (1+ bignum-len))))
|
||||||
(declare (type bignum bignum result)
|
(declare (type bignum bignum result)
|
||||||
(type bignum-element-type fixnum))
|
(type bignum-element-type abs-fixnum))
|
||||||
(sb-sys:%primitive sb-vm::bignum-mulx-and-add-word-loop bignum fixnum bignum-len result)
|
(sb-sys:%primitive sb-vm::bignum-mulx-and-add-word-loop bignum abs-fixnum bignum-len result)
|
||||||
(unless (eq bignum-plus-p fixnum-plus-p)
|
(unless (bignum-plus-p bignum)
|
||||||
|
(setf (%bignum-ref result bignum-len)
|
||||||
|
(logand (- (%bignum-ref result bignum-len) abs-fixnum)
|
||||||
|
most-positive-word)))
|
||||||
|
(when (minusp fixnum)
|
||||||
(negate-bignum-in-place result))
|
(negate-bignum-in-place result))
|
||||||
(%normalize-bignum result (1+ bignum-len))))))
|
(%normalize-bignum result (1+ bignum-len))))))
|
||||||
|
|
||||||
|
(sb-vm::def-variant multiply-bignums :bmi2 (a b)
|
||||||
|
(declare (type bignum a b)
|
||||||
|
(optimize speed (safety 0)))
|
||||||
|
(let* ((len-a (%bignum-length a))
|
||||||
|
(len-b (%bignum-length b))
|
||||||
|
(res (%allocate-bignum (+ len-a len-b))))
|
||||||
|
(when (> len-a len-b)
|
||||||
|
(rotatef a b)
|
||||||
|
(rotatef len-a len-b))
|
||||||
|
|
||||||
|
(sb-sys:%primitive sb-vm::bignum-mulx-multiply-loop a len-a b len-b res)
|
||||||
|
(unless (bignum-plus-p a)
|
||||||
|
(%subtract-bignum-in-place res b len-a len-b))
|
||||||
|
(unless (bignum-plus-p b)
|
||||||
|
(%subtract-bignum-in-place res a len-b len-a))
|
||||||
|
(%normalize-bignum res (+ len-a len-b))))
|
||||||
|
|
||||||
(in-package :sb-vm)
|
(in-package :sb-vm)
|
||||||
|
|
|
||||||
|
|
@ -2036,6 +2036,77 @@
|
||||||
(inst adc hi hi zr-tn)
|
(inst adc hi hi zr-tn)
|
||||||
(inst str hi (@ r (extend index :lsl 3)))))
|
(inst str hi (@ r (extend index :lsl 3)))))
|
||||||
|
|
||||||
|
(define-vop (bignum-multiply-loop)
|
||||||
|
(:args (a* :scs (descriptor-reg))
|
||||||
|
(la :scs (unsigned-reg))
|
||||||
|
(b* :scs (descriptor-reg))
|
||||||
|
(lb :scs (unsigned-reg))
|
||||||
|
(r* :scs (descriptor-reg)))
|
||||||
|
(:arg-types bignum unsigned-num bignum unsigned-num bignum)
|
||||||
|
(:temporary (:sc descriptor-reg) a b-base b r-row-base r)
|
||||||
|
(:temporary (:sc unsigned-reg) outer-len inner-len
|
||||||
|
x b-digit r-digit lo hi carry)
|
||||||
|
(:generator 40
|
||||||
|
(inst add-sub a a* (- (* bignum-digits-offset n-word-bytes) other-pointer-lowtag))
|
||||||
|
(inst add-sub b-base b* (- (* bignum-digits-offset n-word-bytes) other-pointer-lowtag))
|
||||||
|
(inst add-sub r-row-base r* (- (* bignum-digits-offset n-word-bytes) other-pointer-lowtag))
|
||||||
|
|
||||||
|
|
||||||
|
(inst ldr x (@ a n-word-bytes :post-index))
|
||||||
|
(inst mov b b-base)
|
||||||
|
(inst mov r r-row-base)
|
||||||
|
(inst mov inner-len lb)
|
||||||
|
(inst adds hi zr-tn zr-tn) ;; clear carry
|
||||||
|
|
||||||
|
ROW0-LOOP
|
||||||
|
(inst ldr b-digit (@ b n-word-bytes :post-index))
|
||||||
|
(inst mul lo b-digit x)
|
||||||
|
(inst adcs lo lo hi)
|
||||||
|
(inst umulh hi b-digit x)
|
||||||
|
(inst str lo (@ r n-word-bytes :post-index))
|
||||||
|
(inst sub inner-len inner-len 1)
|
||||||
|
(inst cbnz inner-len ROW0-LOOP)
|
||||||
|
|
||||||
|
(inst adc hi hi zr-tn)
|
||||||
|
(inst str hi (@ r))
|
||||||
|
|
||||||
|
(inst subs outer-len la 1)
|
||||||
|
(inst b :eq DONE)
|
||||||
|
|
||||||
|
(inst add r-row-base r-row-base n-word-bytes)
|
||||||
|
|
||||||
|
OUTER-LOOP
|
||||||
|
(inst ldr x (@ a n-word-bytes :post-index))
|
||||||
|
(inst mov b b-base)
|
||||||
|
(inst mov r r-row-base)
|
||||||
|
(inst mov inner-len lb)
|
||||||
|
(inst adds carry zr-tn zr-tn) ;; clear carry
|
||||||
|
|
||||||
|
INNER-LOOP
|
||||||
|
(inst ldr b-digit (@ b n-word-bytes :post-index))
|
||||||
|
(inst ldr r-digit (@ r))
|
||||||
|
|
||||||
|
(inst mul lo b-digit x)
|
||||||
|
(inst umulh hi b-digit x)
|
||||||
|
|
||||||
|
(inst adcs lo lo carry)
|
||||||
|
(inst adc carry hi zr-tn)
|
||||||
|
|
||||||
|
(inst adds lo lo r-digit)
|
||||||
|
|
||||||
|
(inst str lo (@ r n-word-bytes :post-index))
|
||||||
|
(inst sub inner-len inner-len 1)
|
||||||
|
(inst cbnz inner-len INNER-LOOP)
|
||||||
|
|
||||||
|
(inst adc carry carry zr-tn)
|
||||||
|
(inst str carry (@ r))
|
||||||
|
|
||||||
|
(inst add r-row-base r-row-base n-word-bytes)
|
||||||
|
(inst subs outer-len outer-len 1)
|
||||||
|
(inst b :ne OUTER-LOOP)
|
||||||
|
|
||||||
|
DONE))
|
||||||
|
|
||||||
(define-vop (bignum-mult-and-add-3-arg)
|
(define-vop (bignum-mult-and-add-3-arg)
|
||||||
(:translate sb-bignum:%multiply-and-add)
|
(:translate sb-bignum:%multiply-and-add)
|
||||||
(:policy :fast-safe)
|
(:policy :fast-safe)
|
||||||
|
|
|
||||||
|
|
@ -4158,6 +4158,74 @@
|
||||||
(inst adc hi 0)
|
(inst adc hi 0)
|
||||||
(inst mov (ea #1# r index 8) hi)))
|
(inst mov (ea #1# r index 8) hi)))
|
||||||
|
|
||||||
|
(define-vop (bignum-mulx-multiply-loop)
|
||||||
|
(:args (a* :scs (descriptor-reg))
|
||||||
|
(la :scs (unsigned-reg unsigned-stack))
|
||||||
|
(b* :scs (descriptor-reg))
|
||||||
|
(lb :scs (unsigned-reg unsigned-stack))
|
||||||
|
(r* :scs (descriptor-reg)))
|
||||||
|
(:arg-types bignum unsigned-num bignum unsigned-num bignum)
|
||||||
|
(:temporary (:sc unsigned-reg :offset rdx-offset) rdx)
|
||||||
|
(:temporary (:sc unsigned-reg) a b-end r-end index carry lo hi outer-len)
|
||||||
|
(:generator 40
|
||||||
|
(inst mov :dword index lb)
|
||||||
|
(inst lea b-end (ea #1=(- (* bignum-digits-offset n-word-bytes) other-pointer-lowtag) b* index 8))
|
||||||
|
(inst lea r-end (ea #1# r* index 8))
|
||||||
|
|
||||||
|
(inst mov rdx (ea #1# a*))
|
||||||
|
|
||||||
|
(inst neg index)
|
||||||
|
(zeroize carry) ;; clears cf
|
||||||
|
|
||||||
|
ROW0-LOOP
|
||||||
|
(inst mulx hi lo (ea 0 b-end index 8))
|
||||||
|
(inst adc lo carry)
|
||||||
|
(inst mov carry hi)
|
||||||
|
(inst mov (ea 0 r-end index 8) lo)
|
||||||
|
|
||||||
|
(inst inc index)
|
||||||
|
(inst jmp :nz ROW0-LOOP)
|
||||||
|
|
||||||
|
(inst adc carry 0)
|
||||||
|
(inst mov (ea r-end) carry)
|
||||||
|
|
||||||
|
(inst mov :dword index la)
|
||||||
|
(inst dec :dword index)
|
||||||
|
(inst jmp :z DONE)
|
||||||
|
(inst mov :dword outer-len index)
|
||||||
|
|
||||||
|
(inst lea a (ea (+ #1# n-word-bytes) a*))
|
||||||
|
(inst add r-end n-word-bytes)
|
||||||
|
|
||||||
|
OUTER-LOOP
|
||||||
|
(inst mov rdx (ea a))
|
||||||
|
(inst add a n-word-bytes)
|
||||||
|
|
||||||
|
(inst mov :dword index lb)
|
||||||
|
(inst neg index)
|
||||||
|
(zeroize carry) ;; clears cf
|
||||||
|
|
||||||
|
INNER-LOOP
|
||||||
|
(inst mulx hi lo (ea 0 b-end index 8))
|
||||||
|
|
||||||
|
(inst adc lo carry)
|
||||||
|
(inst adc hi 0)
|
||||||
|
|
||||||
|
(inst add (ea 0 r-end index 8) lo)
|
||||||
|
(inst mov carry hi)
|
||||||
|
|
||||||
|
(inst inc index)
|
||||||
|
(inst jmp :nz INNER-LOOP)
|
||||||
|
|
||||||
|
(inst adc carry 0)
|
||||||
|
(inst mov (ea r-end) carry)
|
||||||
|
|
||||||
|
(inst add r-end n-word-bytes)
|
||||||
|
(inst dec :dword outer-len)
|
||||||
|
(inst jmp :nz OUTER-LOOP)
|
||||||
|
|
||||||
|
DONE))
|
||||||
|
|
||||||
(define-vop (bignum-mult-and-add-3-arg)
|
(define-vop (bignum-mult-and-add-3-arg)
|
||||||
(:translate sb-bignum:%multiply-and-add)
|
(:translate sb-bignum:%multiply-and-add)
|
||||||
(:policy :fast-safe)
|
(:policy :fast-safe)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue