1 ;;;; the VM definition arithmetic VOPs for MIPS
3 ;;;; This software is part of the SBCL system. See the README file for
6 ;;;; This software is derived from the CMU CL system, which was
7 ;;;; written at Carnegie Mellon University and released into the
8 ;;;; public domain. The software is in the public domain and is
9 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
10 ;;;; files for more information.
14 ;;;; Unary operations.
16 (define-vop (fast-safe-arith-op)
21 (define-vop (fixnum-unop fast-safe-arith-op)
22 (:args (x :scs (any-reg)))
23 (:results (res :scs (any-reg)))
24 (:note "inline fixnum arithmetic")
25 (:arg-types tagged-num)
26 (:result-types tagged-num))
28 (define-vop (signed-unop fast-safe-arith-op)
29 (:args (x :scs (signed-reg)))
30 (:results (res :scs (signed-reg)))
31 (:note "inline (signed-byte 32) arithmetic")
32 (:arg-types signed-num)
33 (:result-types signed-num))
35 (define-vop (fast-negate/fixnum fixnum-unop)
38 (inst subu res zero-tn x)))
40 (define-vop (fast-negate/signed signed-unop)
43 (inst subu res zero-tn x)))
45 (define-vop (fast-lognot/fixnum fixnum-unop)
46 (:temporary (:scs (any-reg) :type fixnum :to (:result 0))
50 (inst li temp (fixnumize -1))
51 (inst xor res x temp)))
53 (define-vop (fast-lognot/signed signed-unop)
56 (inst nor res x zero-tn)))
58 ;;;; Binary fixnum operations.
60 ;;; Assume that any constant operand is the second arg...
62 (define-vop (fast-fixnum-binop fast-safe-arith-op)
63 (:args (x :target r :scs (any-reg zero))
64 (y :target r :scs (any-reg zero)))
65 (:arg-types tagged-num tagged-num)
66 (:results (r :scs (any-reg)))
67 (:result-types tagged-num)
68 (:note "inline fixnum arithmetic"))
70 (define-vop (fast-unsigned-binop fast-safe-arith-op)
71 (:args (x :target r :scs (unsigned-reg zero))
72 (y :target r :scs (unsigned-reg zero)))
73 (:arg-types unsigned-num unsigned-num)
74 (:results (r :scs (unsigned-reg)))
75 (:result-types unsigned-num)
76 (:note "inline (unsigned-byte 32) arithmetic"))
78 (define-vop (fast-signed-binop fast-safe-arith-op)
79 (:args (x :target r :scs (signed-reg zero))
80 (y :target r :scs (signed-reg zero)))
81 (:arg-types signed-num signed-num)
82 (:results (r :scs (signed-reg)))
83 (:result-types signed-num)
84 (:note "inline (signed-byte 32) arithmetic"))
86 (define-vop (fast-fixnum-c-binop fast-fixnum-binop)
87 (:args (x :target r :scs (any-reg)))
89 (:arg-types tagged-num (:constant integer)))
91 (define-vop (fast-signed-c-binop fast-signed-binop)
92 (:args (x :target r :scs (signed-reg)))
94 (:arg-types tagged-num (:constant integer)))
96 (define-vop (fast-unsigned-c-binop fast-unsigned-binop)
97 (:args (x :target r :scs (unsigned-reg)))
99 (:arg-types tagged-num (:constant integer)))
101 (defmacro define-binop (translate cost untagged-cost op
102 tagged-type untagged-type)
104 (define-vop (,(symbolicate "FAST-" translate "/FIXNUM=>FIXNUM")
106 (:args (x :target r :scs (any-reg))
107 (y :target r :scs (any-reg)))
108 (:translate ,translate)
109 (:generator ,(1+ cost)
111 (define-vop (,(symbolicate "FAST-" translate "/SIGNED=>SIGNED")
113 (:args (x :target r :scs (signed-reg))
114 (y :target r :scs (signed-reg)))
115 (:translate ,translate)
116 (:generator ,(1+ untagged-cost)
118 (define-vop (,(symbolicate "FAST-" translate "/UNSIGNED=>UNSIGNED")
120 (:args (x :target r :scs (unsigned-reg))
121 (y :target r :scs (unsigned-reg)))
122 (:translate ,translate)
123 (:generator ,(1+ untagged-cost)
126 `((define-vop (,(symbolicate "FAST-" translate "-C/FIXNUM=>FIXNUM")
128 (:arg-types tagged-num (:constant ,tagged-type))
129 (:translate ,translate)
131 (inst ,op r x (fixnumize y))))))
132 ,@(when untagged-type
133 `((define-vop (,(symbolicate "FAST-" translate "-C/SIGNED=>SIGNED")
135 (:arg-types signed-num (:constant ,untagged-type))
136 (:translate ,translate)
137 (:generator ,untagged-cost
139 (define-vop (,(symbolicate "FAST-" translate
140 "-C/UNSIGNED=>UNSIGNED")
141 fast-unsigned-c-binop)
142 (:arg-types unsigned-num (:constant ,untagged-type))
143 (:translate ,translate)
144 (:generator ,untagged-cost
145 (inst ,op r x y)))))))
147 (define-binop + 1 5 addu (signed-byte 14) (signed-byte 16))
148 (define-binop - 1 5 subu
149 (integer #.(- 1 (ash 1 13)) #.(ash 1 13))
150 (integer #.(- 1 (ash 1 15)) #.(ash 1 15)))
151 (define-binop logior 1 3 or (unsigned-byte 14) (unsigned-byte 16))
152 (define-binop logand 1 3 and (unsigned-byte 14) (unsigned-byte 16))
153 (define-binop logxor 1 3 xor (unsigned-byte 14) (unsigned-byte 16))
155 ;;; No -C/ VOPs for LOGNOR because the NOR instruction doesn't take
156 ;;; immediate args. -- CSR, 2003-09-11
157 (define-vop (fast-lognor/fixnum=>fixnum fast-fixnum-binop)
159 (:args (x :target r :scs (any-reg))
160 (y :target r :scs (any-reg)))
161 (:temporary (:sc non-descriptor-reg) temp)
164 (inst addu r temp (- fixnum-tag-mask))))
166 (define-vop (fast-lognor/signed=>signed fast-signed-binop)
168 (:args (x :target r :scs (signed-reg))
169 (y :target r :scs (signed-reg)))
173 (define-vop (fast-lognor/unsigned=>unsigned fast-unsigned-binop)
175 (:args (x :target r :scs (unsigned-reg))
176 (y :target r :scs (unsigned-reg)))
180 ;;; Special case fixnum + and - that trap on overflow. Useful when we don't
181 ;;; know that the result is going to be a fixnum.
184 (define-vop (fast-+/fixnum fast-+/fixnum=>fixnum)
185 (:results (r :scs (any-reg descriptor-reg)))
186 (:result-types (:or signed-num unsigned-num))
191 (define-vop (fast-+-c/fixnum fast-+-c/fixnum=>fixnum)
192 (:results (r :scs (any-reg descriptor-reg)))
193 (:result-types (:or signed-num unsigned-num))
196 (inst add r x (fixnumize y))))
198 (define-vop (fast--/fixnum fast--/fixnum=>fixnum)
199 (:results (r :scs (any-reg descriptor-reg)))
200 (:result-types (:or signed-num unsigned-num))
205 (define-vop (fast---c/fixnum fast---c/fixnum=>fixnum)
206 (:results (r :scs (any-reg descriptor-reg)))
207 (:result-types (:or signed-num unsigned-num))
210 (inst sub r x (fixnumize y))))
211 ) ; bogus trap-to-c-land +/-
215 (define-vop (fast-ash/unsigned=>unsigned)
217 (:args (number :scs (unsigned-reg) :to :save)
218 (amount :scs (signed-reg) :to :save))
219 (:arg-types unsigned-num signed-num)
220 (:results (result :scs (unsigned-reg)))
221 (:result-types unsigned-num)
224 (:temporary (:sc non-descriptor-reg) ndesc)
225 (:temporary (:sc non-descriptor-reg :to :eval) temp)
227 (inst bgez amount positive)
228 (inst subu ndesc zero-tn amount)
229 (inst slt temp ndesc 32)
231 (inst srl result number ndesc)
233 (move result zero-tn t)
236 ;; The result-type assures us that this shift will not overflow.
237 (inst sll result number amount)
241 (define-vop (fast-ash/signed=>signed)
243 (:args (number :scs (signed-reg) :to :save)
244 (amount :scs (signed-reg)))
245 (:arg-types signed-num signed-num)
246 (:results (result :scs (signed-reg)))
247 (:result-types signed-num)
250 (:temporary (:sc non-descriptor-reg) ndesc)
251 (:temporary (:sc non-descriptor-reg :to :eval) temp)
253 (inst bgez amount positive)
254 (inst subu ndesc zero-tn amount)
255 (inst slt temp ndesc 31)
257 (inst sra result number ndesc)
259 (inst sra result number 31)
262 ;; The result-type assures us that this shift will not overflow.
263 (inst sll result number amount)
268 (define-vop (fast-ash-c/unsigned=>unsigned)
272 (:args (number :scs (unsigned-reg)))
274 (:arg-types unsigned-num (:constant integer))
275 (:results (result :scs (unsigned-reg)))
276 (:result-types unsigned-num)
279 ((< count -31) (move result zero-tn))
280 ((< count 0) (inst srl result number (min (- count) 31)))
281 ((> count 0) (inst sll result number (min count 31)))
282 (t (bug "identity ASH not transformed away")))))
284 (define-vop (fast-ash-c/signed=>signed)
288 (:args (number :scs (signed-reg)))
290 (:arg-types signed-num (:constant integer))
291 (:results (result :scs (signed-reg)))
292 (:result-types signed-num)
295 ((< count 0) (inst sra result number (min (- count) 31)))
296 ((> count 0) (inst sll result number (min count 31)))
297 (t (bug "identity ASH not transformed away")))))
299 (macrolet ((def (name sc-type type result-type cost)
303 (:args (number :scs (,sc-type))
304 (amount :scs (signed-reg unsigned-reg immediate)))
305 (:arg-types ,type positive-fixnum)
306 (:results (result :scs (,result-type)))
307 (:result-types ,type)
311 ((signed-reg unsigned-reg)
312 (inst sll result number amount))
314 (let ((amount (tn-value amount)))
316 (inst sll result number amount))))))))
317 (def fast-ash-left/fixnum=>fixnum any-reg tagged-num any-reg 2)
318 (def fast-ash-left/signed=>signed signed-reg signed-num signed-reg 3)
319 (def fast-ash-left/unsigned=>unsigned unsigned-reg unsigned-num unsigned-reg 3))
321 (define-vop (signed-byte-32-len)
322 (:translate integer-length)
323 (:note "inline (signed-byte 32) integer-length")
325 (:args (arg :scs (signed-reg) :target shift))
326 (:arg-types signed-num)
327 (:results (res :scs (any-reg)))
328 (:result-types positive-fixnum)
329 (:temporary (:scs (non-descriptor-reg) :from (:argument 0)) shift)
331 (let ((loop (gen-label))
334 (inst bgez shift test)
337 (inst nor shift shift)
340 (inst add res (fixnumize 1))
343 (inst bne shift loop)
344 (inst srl shift 1))))
346 (define-vop (unsigned-byte-32-count)
347 (:translate logcount)
348 (:note "inline (unsigned-byte 32) logcount")
350 (:args (arg :scs (unsigned-reg) :target num))
351 (:arg-types unsigned-num)
352 (:results (res :scs (unsigned-reg)))
353 (:result-types positive-fixnum)
354 (:temporary (:scs (non-descriptor-reg) :from (:argument 0) :to (:result 0)
356 (:temporary (:scs (non-descriptor-reg)) mask temp)
358 (inst li mask #x55555555)
359 (inst srl temp arg 1)
360 (inst and num arg mask)
363 (inst li mask #x33333333)
364 (inst srl temp num 2)
368 (inst li mask #x0f0f0f0f)
369 (inst srl temp num 4)
373 (inst li mask #x00ff00ff)
374 (inst srl temp num 8)
378 (inst li mask #x0000ffff)
379 (inst srl temp num 16)
382 (inst addu res num temp)))
385 ;;; Multiply and Divide.
387 (define-vop (fast-*/fixnum=>fixnum fast-fixnum-binop)
388 (:temporary (:scs (non-descriptor-reg)) temp)
391 (inst sra temp y n-fixnum-tag-bits)
395 (define-vop (fast-*/signed=>signed fast-signed-binop)
401 (define-vop (fast-*/unsigned=>unsigned fast-unsigned-binop)
409 (define-vop (fast-truncate/fixnum fast-fixnum-binop)
410 (:translate truncate)
411 (:results (q :scs (any-reg))
413 (:result-types tagged-num tagged-num)
414 (:temporary (:scs (non-descriptor-reg) :to :eval) temp)
416 (:save-p :compute-only)
418 (let ((zero (generate-error-code vop division-by-zero-error x y)))
423 (inst sll q temp n-fixnum-tag-bits)
426 (define-vop (fast-truncate/unsigned fast-unsigned-binop)
427 (:translate truncate)
428 (:results (q :scs (unsigned-reg))
429 (r :scs (unsigned-reg)))
430 (:result-types unsigned-num unsigned-num)
432 (:save-p :compute-only)
434 (let ((zero (generate-error-code vop division-by-zero-error x y)))
441 (define-vop (fast-truncate/signed fast-signed-binop)
442 (:translate truncate)
443 (:results (q :scs (signed-reg))
444 (r :scs (signed-reg)))
445 (:result-types signed-num signed-num)
447 (:save-p :compute-only)
449 (let ((zero (generate-error-code vop division-by-zero-error x y)))
458 ;;;; Binary conditional VOPs:
460 (define-vop (fast-conditional)
465 (:temporary (:scs (non-descriptor-reg)) temp)
466 (:policy :fast-safe))
468 (define-vop (fast-conditional/fixnum fast-conditional)
469 (:args (x :scs (any-reg))
471 (:arg-types tagged-num tagged-num)
472 (:note "inline fixnum comparison"))
474 (define-vop (fast-conditional-c/fixnum fast-conditional/fixnum)
475 (:args (x :scs (any-reg)))
476 (:arg-types tagged-num (:constant (signed-byte-with-a-bite-out 14 4)))
477 (:info target not-p y))
479 (define-vop (fast-conditional/signed fast-conditional)
480 (:args (x :scs (signed-reg))
481 (y :scs (signed-reg)))
482 (:arg-types signed-num signed-num)
483 (:note "inline (signed-byte 32) comparison"))
485 (define-vop (fast-conditional-c/signed fast-conditional/signed)
486 (:args (x :scs (signed-reg)))
487 (:arg-types signed-num (:constant (signed-byte-with-a-bite-out 16 1)))
488 (:info target not-p y))
490 (define-vop (fast-conditional/unsigned fast-conditional)
491 (:args (x :scs (unsigned-reg))
492 (y :scs (unsigned-reg)))
493 (:arg-types unsigned-num unsigned-num)
494 (:note "inline (unsigned-byte 32) comparison"))
496 (define-vop (fast-conditional-c/unsigned fast-conditional/unsigned)
497 (:args (x :scs (unsigned-reg)))
498 (:arg-types unsigned-num (:constant (and (signed-byte-with-a-bite-out 16 1)
500 (:info target not-p y))
503 (defmacro define-conditional-vop (translate &rest generator)
505 ,@(mapcar #'(lambda (suffix cost signed)
506 (unless (and (member suffix '(/fixnum -c/fixnum))
508 `(define-vop (,(intern (format nil "~:@(FAST-IF-~A~A~)"
511 (format nil "~:@(FAST-CONDITIONAL~A~)"
513 (:translate ,translate)
515 (let* ((signed ,signed)
516 (-c/fixnum ,(eq suffix '-c/fixnum))
517 (y (if -c/fixnum (fixnumize y) y)))
518 (declare (ignorable signed -c/fixnum y))
520 '(/fixnum -c/fixnum /signed -c/signed /unsigned -c/unsigned)
522 '(t t t t nil nil))))
524 (define-conditional-vop <
525 (cond ((and signed (eql y 0))
528 (inst bltz x target)))
532 (inst sltu temp x y))
534 (inst beq temp target)
535 (inst bne temp target))))
538 (define-conditional-vop >
539 (cond ((and signed (eql y 0))
542 (inst bgtz x target)))
544 (let ((y (+ y (if -c/fixnum (fixnumize 1) 1))))
547 (inst sltu temp x y))
549 (inst bne temp target)
550 (inst beq temp target))))
554 (inst sltu temp y x))
556 (inst beq temp target)
557 (inst bne temp target))))
560 ;;; EQL/FIXNUM is funny because the first arg can be of any type, not just a
563 (define-conditional-vop eql
564 (declare (ignore signed))
569 (inst bne x y target)
570 (inst beq x y target))
573 ;;; These versions specify a fixnum restriction on their first arg. We have
574 ;;; also generic-eql/fixnum VOPs which are the same, but have no restriction on
575 ;;; the first arg and a higher cost. The reason for doing this is to prevent
576 ;;; fixnum specific operations from being used on word integers, spuriously
577 ;;; consing the argument.
579 (define-vop (fast-eql/fixnum fast-conditional)
580 (:args (x :scs (any-reg))
582 (:arg-types tagged-num tagged-num)
583 (:note "inline fixnum comparison")
588 (inst bne x y target)
589 (inst beq x y target))
592 (define-vop (generic-eql/fixnum fast-eql/fixnum)
593 (:args (x :scs (any-reg descriptor-reg))
595 (:arg-types * tagged-num)
598 (define-vop (fast-eql-c/fixnum fast-conditional/fixnum)
599 (:args (x :scs (any-reg)))
600 (:arg-types tagged-num (:constant (signed-byte 14)))
601 (:info target not-p y)
604 (let ((y (cond ((eql y 0) zero-tn)
606 (inst li temp (fixnumize y))
609 (inst bne x y target)
610 (inst beq x y target))
613 (define-vop (generic-eql-c/fixnum fast-eql-c/fixnum)
614 (:args (x :scs (any-reg descriptor-reg)))
615 (:arg-types * (:constant (signed-byte 14)))
619 ;;;; 32-bit logical operations
621 (define-vop (shift-towards-someplace)
623 (:args (num :scs (unsigned-reg))
624 (amount :scs (signed-reg)))
625 (:arg-types unsigned-num tagged-num)
626 (:results (r :scs (unsigned-reg)))
627 (:result-types unsigned-num))
629 (define-vop (shift-towards-start shift-towards-someplace)
630 (:translate shift-towards-start)
631 (:note "SHIFT-TOWARDS-START")
633 (ecase *backend-byte-order*
635 (inst sll r num amount))
637 (inst srl r num amount)))))
639 (define-vop (shift-towards-end shift-towards-someplace)
640 (:translate shift-towards-end)
641 (:note "SHIFT-TOWARDS-END")
643 (ecase *backend-byte-order*
645 (inst srl r num amount))
647 (inst sll r num amount)))))
649 ;;;; Modular arithmetic
650 (define-modular-fun +-mod32 (x y) + :untagged nil 32)
651 (define-vop (fast-+-mod32/unsigned=>unsigned fast-+/unsigned=>unsigned)
652 (:translate +-mod32))
653 (define-vop (fast-+-mod32-c/unsigned=>unsigned fast-+-c/unsigned=>unsigned)
654 (:translate +-mod32))
655 (define-modular-fun --mod32 (x y) - :untagged nil 32)
656 (define-vop (fast---mod32/unsigned=>unsigned fast--/unsigned=>unsigned)
657 (:translate --mod32))
658 (define-vop (fast---mod32-c/unsigned=>unsigned fast---c/unsigned=>unsigned)
659 (:translate --mod32))
661 (define-vop (fast-ash-left-mod32-c/unsigned=>unsigned
662 fast-ash-c/unsigned=>unsigned)
663 (:translate ash-left-mod32))
665 (define-vop (fast-ash-left-mod32/unsigned=>unsigned
666 fast-ash-left/unsigned=>unsigned))
667 (deftransform ash-left-mod32 ((integer count)
668 ((unsigned-byte 32) (unsigned-byte 5)))
669 (when (sb!c::constant-lvar-p count)
670 (sb!c::give-up-ir1-transform))
671 '(%primitive fast-ash-left-mod32/unsigned=>unsigned integer count))
673 ;;; logical operations
674 (define-modular-fun lognot-mod32 (x) lognot :untagged nil 32)
675 (define-vop (lognot-mod32/unsigned=>unsigned)
676 (:translate lognot-mod32)
677 (:args (x :scs (unsigned-reg)))
678 (:arg-types unsigned-num)
679 (:results (r :scs (unsigned-reg)))
680 (:result-types unsigned-num)
683 (inst nor r x zero-tn)))
685 (define-modular-fun lognor-mod32 (x y) lognor :untagged nil 32)
686 (define-vop (fast-lognor-mod32/unsigned=>unsigned
687 fast-lognor/unsigned=>unsigned)
688 (:translate lognor-mod32))
690 (define-source-transform logeqv (&rest args)
691 (if (oddp (length args))
693 `(lognot (logxor ,@args))))
694 (define-source-transform logandc1 (x y)
695 `(logand (lognot ,x) ,y))
696 (define-source-transform logandc2 (x y)
697 `(logand ,x (lognot ,y)))
698 (define-source-transform logorc1 (x y)
699 `(logior (lognot ,x) ,y))
700 (define-source-transform logorc2 (x y)
701 `(logior ,x (lognot ,y)))
702 (define-source-transform lognand (x y)
703 `(lognot (logand ,x ,y)))
706 (define-vop (bignum-length get-header-data)
707 (:translate sb!bignum:%bignum-length)
708 (:policy :fast-safe))
710 (define-vop (bignum-set-length set-header-data)
711 (:translate sb!bignum:%bignum-set-length)
712 (:policy :fast-safe))
714 (define-full-reffer bignum-ref * bignum-digits-offset other-pointer-lowtag
715 (unsigned-reg) unsigned-num sb!bignum:%bignum-ref)
717 (define-full-setter bignum-set * bignum-digits-offset other-pointer-lowtag
718 (unsigned-reg) unsigned-num sb!bignum:%bignum-set)
720 (define-vop (digit-0-or-plus)
721 (:translate sb!bignum:%digit-0-or-plusp)
723 (:args (digit :scs (unsigned-reg)))
724 (:arg-types unsigned-num)
729 (inst bltz digit target)
730 (inst bgez digit target))
733 (define-vop (add-w/carry)
734 (:translate sb!bignum:%add-with-carry)
736 (:args (a :scs (unsigned-reg))
737 (b :scs (unsigned-reg))
739 (:arg-types unsigned-num unsigned-num positive-fixnum)
740 (:temporary (:scs (unsigned-reg) :to (:result 0) :target result) res)
741 (:results (result :scs (unsigned-reg))
742 (carry :scs (unsigned-reg) :from :eval))
743 (:result-types unsigned-num positive-fixnum)
744 (:temporary (:scs (non-descriptor-reg)) temp)
746 (let ((carry-in (gen-label))
748 (inst bne c carry-in)
752 (inst sltu carry res b)
754 (emit-label carry-in)
756 (inst nor temp a zero-tn)
757 (inst sltu carry b temp)
763 (define-vop (sub-w/borrow)
764 (:translate sb!bignum:%subtract-with-borrow)
766 (:args (a :scs (unsigned-reg))
767 (b :scs (unsigned-reg))
769 (:arg-types unsigned-num unsigned-num positive-fixnum)
770 (:temporary (:scs (unsigned-reg) :to (:result 0) :target result) res)
771 (:results (result :scs (unsigned-reg))
772 (borrow :scs (unsigned-reg) :from :eval))
773 (:result-types unsigned-num positive-fixnum)
775 (let ((no-borrow-in (gen-label))
778 (inst bne c no-borrow-in)
783 (inst sltu borrow b a)
785 (emit-label no-borrow-in)
786 (inst sltu borrow a b)
792 (define-vop (bignum-mult-and-add-3-arg)
793 (:translate sb!bignum:%multiply-and-add)
795 (:args (x :scs (unsigned-reg))
796 (y :scs (unsigned-reg))
797 (carry-in :scs (unsigned-reg) :to :save))
798 (:arg-types unsigned-num unsigned-num unsigned-num)
799 (:temporary (:scs (unsigned-reg) :from (:argument 1)) temp)
800 (:results (hi :scs (unsigned-reg))
801 (lo :scs (unsigned-reg)))
802 (:result-types unsigned-num unsigned-num)
806 (inst addu lo temp carry-in)
807 (inst sltu temp lo carry-in)
809 (inst addu hi temp)))
811 (define-vop (bignum-mult-and-add-4-arg)
812 (:translate sb!bignum:%multiply-and-add)
814 (:args (x :scs (unsigned-reg))
815 (y :scs (unsigned-reg))
816 (prev :scs (unsigned-reg))
817 (carry-in :scs (unsigned-reg) :to :save))
818 (:arg-types unsigned-num unsigned-num unsigned-num unsigned-num)
819 (:temporary (:scs (unsigned-reg) :from (:argument 2)) temp)
820 (:results (hi :scs (unsigned-reg))
821 (lo :scs (unsigned-reg)))
822 (:result-types unsigned-num unsigned-num)
825 (inst addu lo prev carry-in)
826 (inst sltu temp lo carry-in)
831 (inst sltu temp lo temp)
832 (inst addu hi temp)))
834 (define-vop (bignum-mult)
835 (:translate sb!bignum:%multiply)
837 (:args (x :scs (unsigned-reg))
838 (y :scs (unsigned-reg)))
839 (:arg-types unsigned-num unsigned-num)
840 (:results (hi :scs (unsigned-reg))
841 (lo :scs (unsigned-reg)))
842 (:result-types unsigned-num unsigned-num)
848 (define-vop (bignum-lognot lognot-mod32/unsigned=>unsigned)
849 (:translate sb!bignum:%lognot))
851 (define-vop (fixnum-to-digit)
852 (:translate sb!bignum:%fixnum-to-digit)
854 (:args (fixnum :scs (any-reg)))
855 (:arg-types tagged-num)
856 (:results (digit :scs (unsigned-reg)))
857 (:result-types unsigned-num)
859 (inst sra digit fixnum n-fixnum-tag-bits)))
861 (define-vop (bignum-floor)
862 (:translate sb!bignum:%floor)
864 (:args (num-high :scs (unsigned-reg) :target rem)
865 (num-low :scs (unsigned-reg) :target rem-low)
866 (denom :scs (unsigned-reg) :to (:eval 1)))
867 (:arg-types unsigned-num unsigned-num unsigned-num)
868 (:temporary (:scs (unsigned-reg) :from (:argument 1)) rem-low)
869 (:temporary (:scs (unsigned-reg) :from (:eval 0)) temp)
870 (:results (quo :scs (unsigned-reg) :from (:eval 0))
871 (rem :scs (unsigned-reg) :from (:argument 0)))
872 (:result-types unsigned-num unsigned-num)
873 (:generator 325 ; number of inst assuming targeting works.
875 (move rem-low num-low)
876 (flet ((maybe-subtract (&optional (guess temp))
877 (inst subu temp guess 1)
878 (inst and temp denom)
879 (inst subu rem temp)))
880 (inst sltu quo rem denom)
884 (inst srl temp rem-low 31)
887 (inst sltu temp rem denom)
891 (inst nor quo zero-tn)))
893 (define-vop (signify-digit)
894 (:translate sb!bignum:%fixnum-digit-with-correct-sign)
896 (:args (digit :scs (unsigned-reg) :target res))
897 (:arg-types unsigned-num)
898 (:results (res :scs (any-reg signed-reg)))
899 (:result-types signed-num)
903 (inst sll res digit n-fixnum-tag-bits))
908 (define-vop (digit-ashr)
909 (:translate sb!bignum:%ashr)
911 (:args (digit :scs (unsigned-reg))
912 (count :scs (unsigned-reg)))
913 (:arg-types unsigned-num positive-fixnum)
914 (:results (result :scs (unsigned-reg)))
915 (:result-types unsigned-num)
917 (inst sra result digit count)))
919 (define-vop (digit-lshr digit-ashr)
920 (:translate sb!bignum:%digit-logical-shift-right)
922 (inst srl result digit count)))
924 (define-vop (digit-ashl digit-ashr)
925 (:translate sb!bignum:%ashl)
927 (inst sll result digit count)))
930 ;;;; Static functions.
932 (define-static-fun two-arg-gcd (x y) :translate gcd)
933 (define-static-fun two-arg-lcm (x y) :translate lcm)
935 (define-static-fun two-arg-+ (x y) :translate +)
936 (define-static-fun two-arg-- (x y) :translate -)
937 (define-static-fun two-arg-* (x y) :translate *)
938 (define-static-fun two-arg-/ (x y) :translate /)
940 (define-static-fun two-arg-< (x y) :translate <)
941 (define-static-fun two-arg-<= (x y) :translate <=)
942 (define-static-fun two-arg-> (x y) :translate >)
943 (define-static-fun two-arg->= (x y) :translate >=)
944 (define-static-fun two-arg-= (x y) :translate =)
945 (define-static-fun two-arg-/= (x y) :translate /=)
947 (define-static-fun %negate (x) :translate %negate)
949 (define-static-fun two-arg-and (x y) :translate logand)
950 (define-static-fun two-arg-ior (x y) :translate logior)
951 (define-static-fun two-arg-xor (x y) :translate logxor)