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 (fixnum-unop)
17 (:args (x :scs (any-reg)))
18 (:results (res :scs (any-reg)))
19 (:note "inline fixnum arithmetic")
20 (:arg-types tagged-num)
21 (:result-types tagged-num)
24 (define-vop (signed-unop)
25 (:args (x :scs (signed-reg)))
26 (:results (res :scs (signed-reg)))
27 (:note "inline (signed-byte 32) arithmetic")
28 (:arg-types signed-num)
29 (:result-types signed-num)
32 (define-vop (fast-negate/fixnum fixnum-unop)
35 (inst subu res zero-tn x)))
37 (define-vop (fast-negate/signed signed-unop)
40 (inst subu res zero-tn x)))
42 (define-vop (fast-lognot/fixnum fixnum-unop)
43 (:temporary (:scs (any-reg) :type fixnum :to (:result 0))
47 (inst li temp (fixnumize -1))
48 (inst xor res x temp)))
50 (define-vop (fast-lognot/signed signed-unop)
53 (inst nor res x zero-tn)))
57 ;;;; Binary fixnum operations.
59 ;;; Assume that any constant operand is the second arg...
61 (define-vop (fast-fixnum-binop)
62 (:args (x :target r :scs (any-reg))
63 (y :target r :scs (any-reg)))
64 (:arg-types tagged-num tagged-num)
65 (:results (r :scs (any-reg)))
66 (:result-types tagged-num)
67 (:note "inline fixnum arithmetic")
72 (define-vop (fast-unsigned-binop)
73 (:args (x :target r :scs (unsigned-reg))
74 (y :target r :scs (unsigned-reg)))
75 (:arg-types unsigned-num unsigned-num)
76 (:results (r :scs (unsigned-reg)))
77 (:result-types unsigned-num)
78 (:note "inline (unsigned-byte 32) arithmetic")
83 (define-vop (fast-signed-binop)
84 (:args (x :target r :scs (signed-reg))
85 (y :target r :scs (signed-reg)))
86 (:arg-types signed-num signed-num)
87 (:results (r :scs (signed-reg)))
88 (:result-types signed-num)
89 (:note "inline (signed-byte 32) arithmetic")
94 (define-vop (fast-fixnum-c-binop fast-fixnum-binop)
95 (:args (x :target r :scs (any-reg)))
97 (:arg-types tagged-num (:constant integer)))
99 (define-vop (fast-signed-c-binop fast-signed-binop)
100 (:args (x :target r :scs (signed-reg)))
102 (:arg-types tagged-num (:constant integer)))
104 (define-vop (fast-unsigned-c-binop fast-unsigned-binop)
105 (:args (x :target r :scs (unsigned-reg)))
107 (:arg-types tagged-num (:constant integer)))
109 (defmacro define-binop (translate cost untagged-cost op
110 tagged-type untagged-type)
112 (define-vop (,(symbolicate "FAST-" translate "/FIXNUM=>FIXNUM")
114 (:args (x :target r :scs (any-reg))
115 (y :target r :scs (any-reg)))
116 (:translate ,translate)
117 (:generator ,(1+ cost)
119 (define-vop (,(symbolicate "FAST-" translate "/SIGNED=>SIGNED")
121 (:args (x :target r :scs (signed-reg))
122 (y :target r :scs (signed-reg)))
123 (:translate ,translate)
124 (:generator ,(1+ untagged-cost)
126 (define-vop (,(symbolicate "FAST-" translate "/UNSIGNED=>UNSIGNED")
128 (:args (x :target r :scs (unsigned-reg))
129 (y :target r :scs (unsigned-reg)))
130 (:translate ,translate)
131 (:generator ,(1+ untagged-cost)
134 `((define-vop (,(symbolicate "FAST-" translate "-C/FIXNUM=>FIXNUM")
136 (:arg-types tagged-num (:constant ,tagged-type))
137 (:translate ,translate)
139 (inst ,op r x (fixnumize y))))))
140 ,@(when untagged-type
141 `((define-vop (,(symbolicate "FAST-" translate "-C/SIGNED=>SIGNED")
143 (:arg-types signed-num (:constant ,untagged-type))
144 (:translate ,translate)
145 (:generator ,untagged-cost
147 (define-vop (,(symbolicate "FAST-" translate
148 "-C/UNSIGNED=>UNSIGNED")
149 fast-unsigned-c-binop)
150 (:arg-types unsigned-num (:constant ,untagged-type))
151 (:translate ,translate)
152 (:generator ,untagged-cost
153 (inst ,op r x y)))))))
155 (define-binop + 1 5 addu (signed-byte 14) (signed-byte 16))
156 (define-binop - 1 5 subu
157 (integer #.(- 1 (ash 1 13)) #.(ash 1 13))
158 (integer #.(- 1 (ash 1 15)) #.(ash 1 15)))
159 (define-binop logior 1 3 or (unsigned-byte 14) (unsigned-byte 16))
160 (define-binop logand 1 3 and (unsigned-byte 14) (unsigned-byte 16))
161 (define-binop logxor 1 3 xor (unsigned-byte 14) (unsigned-byte 16))
163 ;;; No -C/ VOPs for LOGNOR because the NOR instruction doesn't take
164 ;;; immediate args. -- CSR, 2003-09-11
165 (define-vop (fast-lognor/fixnum=>fixnum fast-fixnum-binop)
167 (:args (x :target r :scs (any-reg))
168 (y :target r :scs (any-reg)))
169 (:temporary (:sc non-descriptor-reg) temp)
172 (inst addu r temp (- fixnum-tag-mask))))
174 (define-vop (fast-lognor/signed=>signed fast-signed-binop)
176 (:args (x :target r :scs (signed-reg))
177 (y :target r :scs (signed-reg)))
181 (define-vop (fast-lognor/unsigned=>unsigned fast-unsigned-binop)
183 (:args (x :target r :scs (unsigned-reg))
184 (y :target r :scs (unsigned-reg)))
188 ;;; Special case fixnum + and - that trap on overflow. Useful when we don't
189 ;;; know that the result is going to be a fixnum.
192 (define-vop (fast-+/fixnum fast-+/fixnum=>fixnum)
193 (:results (r :scs (any-reg descriptor-reg)))
194 (:result-types (:or signed-num unsigned-num))
199 (define-vop (fast-+-c/fixnum fast-+-c/fixnum=>fixnum)
200 (:results (r :scs (any-reg descriptor-reg)))
201 (:result-types (:or signed-num unsigned-num))
204 (inst add r x (fixnumize y))))
206 (define-vop (fast--/fixnum fast--/fixnum=>fixnum)
207 (:results (r :scs (any-reg descriptor-reg)))
208 (:result-types (:or signed-num unsigned-num))
213 (define-vop (fast---c/fixnum fast---c/fixnum=>fixnum)
214 (:results (r :scs (any-reg descriptor-reg)))
215 (:result-types (:or signed-num unsigned-num))
218 (inst sub r x (fixnumize y))))
219 ) ; bogus trap-to-c-land +/-
223 (define-vop (fast-ash/unsigned=>unsigned)
225 (:args (number :scs (unsigned-reg) :to :save)
226 (amount :scs (signed-reg) :to :save))
227 (:arg-types unsigned-num signed-num)
228 (:results (result :scs (unsigned-reg)))
229 (:result-types unsigned-num)
232 (:temporary (:sc non-descriptor-reg) ndesc)
233 (:temporary (:sc non-descriptor-reg :to :eval) temp)
235 (inst bgez amount positive)
236 (inst subu ndesc zero-tn amount)
237 (inst slt temp ndesc 32)
238 (inst bne temp zero-tn done)
239 (inst srl result number ndesc)
241 (move result zero-tn t)
244 ;; The result-type assures us that this shift will not overflow.
245 (inst sll result number amount)
249 (define-vop (fast-ash/signed=>signed)
251 (:args (number :scs (signed-reg) :to :save)
252 (amount :scs (signed-reg)))
253 (:arg-types signed-num signed-num)
254 (:results (result :scs (signed-reg)))
255 (:result-types signed-num)
258 (:temporary (:sc non-descriptor-reg) ndesc)
259 (:temporary (:sc non-descriptor-reg :to :eval) temp)
261 (inst bgez amount positive)
262 (inst subu ndesc zero-tn amount)
263 (inst slt temp ndesc 31)
264 (inst bne temp zero-tn done)
265 (inst sra result number ndesc)
267 (inst sra result number 31)
270 ;; The result-type assures us that this shift will not overflow.
271 (inst sll result number amount)
276 (define-vop (fast-ash-c/unsigned=>unsigned)
280 (:args (number :scs (unsigned-reg)))
282 (:arg-types unsigned-num (:constant integer))
283 (:results (result :scs (unsigned-reg)))
284 (:result-types unsigned-num)
287 ((< count -31) (move result zero-tn))
288 ((< count 0) (inst srl result number (min (- count) 31)))
289 ((> count 0) (inst sll result number (min count 31)))
290 (t (bug "identity ASH not transformed away")))))
292 (define-vop (fast-ash-c/signed=>signed)
296 (:args (number :scs (signed-reg)))
298 (:arg-types signed-num (:constant integer))
299 (:results (result :scs (signed-reg)))
300 (:result-types signed-num)
303 ((< count 0) (inst sra result number (min (- count) 31)))
304 ((> count 0) (inst sll result number (min count 31)))
305 (t (bug "identity ASH not transformed away")))))
307 (macrolet ((def (name sc-type type result-type cost)
311 (:args (number :scs (,sc-type))
312 (amount :scs (signed-reg unsigned-reg immediate)))
313 (:arg-types ,type positive-fixnum)
314 (:results (result :scs (,result-type)))
315 (:result-types ,type)
319 ((signed-reg unsigned-reg)
320 (inst sll result number amount))
322 (let ((amount (tn-value amount)))
324 (inst sll result number amount))))))))
325 (def fast-ash-left/fixnum=>fixnum any-reg tagged-num any-reg 2)
326 (def fast-ash-left/signed=>signed signed-reg signed-num signed-reg 3)
327 (def fast-ash-left/unsigned=>unsigned unsigned-reg unsigned-num unsigned-reg 3))
329 (define-vop (signed-byte-32-len)
330 (:translate integer-length)
331 (:note "inline (signed-byte 32) integer-length")
333 (:args (arg :scs (signed-reg) :target shift))
334 (:arg-types signed-num)
335 (:results (res :scs (any-reg)))
336 (:result-types positive-fixnum)
337 (:temporary (:scs (non-descriptor-reg) :from (:argument 0)) shift)
339 (let ((loop (gen-label))
342 (inst bgez shift test)
345 (inst nor shift shift)
348 (inst add res (fixnumize 1))
351 (inst bne shift loop)
352 (inst srl shift 1))))
354 (define-vop (unsigned-byte-32-count)
355 (:translate logcount)
356 (:note "inline (unsigned-byte 32) logcount")
358 (:args (arg :scs (unsigned-reg) :target num))
359 (:arg-types unsigned-num)
360 (:results (res :scs (unsigned-reg)))
361 (:result-types positive-fixnum)
362 (:temporary (:scs (non-descriptor-reg) :from (:argument 0) :to (:result 0)
364 (:temporary (:scs (non-descriptor-reg)) mask temp)
366 (inst li mask #x55555555)
367 (inst srl temp arg 1)
368 (inst and num arg mask)
371 (inst li mask #x33333333)
372 (inst srl temp num 2)
376 (inst li mask #x0f0f0f0f)
377 (inst srl temp num 4)
381 (inst li mask #x00ff00ff)
382 (inst srl temp num 8)
386 (inst li mask #x0000ffff)
387 (inst srl temp num 16)
390 (inst addu res num temp)))
393 ;;; Multiply and Divide.
395 (define-vop (fast-*/fixnum=>fixnum fast-fixnum-binop)
396 (:temporary (:scs (non-descriptor-reg)) temp)
399 (inst sra temp y n-fixnum-tag-bits)
403 (define-vop (fast-*/signed=>signed fast-signed-binop)
409 (define-vop (fast-*/unsigned=>unsigned fast-unsigned-binop)
417 (define-vop (fast-truncate/fixnum fast-fixnum-binop)
418 (:translate truncate)
419 (:results (q :scs (any-reg))
421 (:result-types tagged-num tagged-num)
422 (:temporary (:scs (non-descriptor-reg) :to :eval) temp)
424 (:save-p :compute-only)
426 (let ((zero (generate-error-code vop division-by-zero-error x y)))
427 (inst beq y zero-tn zero))
431 (inst sll q temp n-fixnum-tag-bits)
434 (define-vop (fast-truncate/unsigned fast-unsigned-binop)
435 (:translate truncate)
436 (:results (q :scs (unsigned-reg))
437 (r :scs (unsigned-reg)))
438 (:result-types unsigned-num unsigned-num)
440 (:save-p :compute-only)
442 (let ((zero (generate-error-code vop division-by-zero-error x y)))
443 (inst beq y zero-tn zero))
449 (define-vop (fast-truncate/signed fast-signed-binop)
450 (:translate truncate)
451 (:results (q :scs (signed-reg))
452 (r :scs (signed-reg)))
453 (:result-types signed-num signed-num)
455 (:save-p :compute-only)
457 (let ((zero (generate-error-code vop division-by-zero-error x y)))
458 (inst beq y zero-tn zero))
466 ;;;; Binary conditional VOPs:
468 (define-vop (fast-conditional)
473 (:temporary (:scs (non-descriptor-reg)) temp)
474 (:policy :fast-safe))
476 (define-vop (fast-conditional/fixnum fast-conditional)
477 (:args (x :scs (any-reg))
479 (:arg-types tagged-num tagged-num)
480 (:note "inline fixnum comparison"))
482 (define-vop (fast-conditional-c/fixnum fast-conditional/fixnum)
483 (:args (x :scs (any-reg)))
484 (:arg-types tagged-num (:constant (signed-byte-with-a-bite-out 14 4)))
485 (:info target not-p y))
487 (define-vop (fast-conditional/signed fast-conditional)
488 (:args (x :scs (signed-reg))
489 (y :scs (signed-reg)))
490 (:arg-types signed-num signed-num)
491 (:note "inline (signed-byte 32) comparison"))
493 (define-vop (fast-conditional-c/signed fast-conditional/signed)
494 (:args (x :scs (signed-reg)))
495 (:arg-types signed-num (:constant (signed-byte-with-a-bite-out 16 1)))
496 (:info target not-p y))
498 (define-vop (fast-conditional/unsigned fast-conditional)
499 (:args (x :scs (unsigned-reg))
500 (y :scs (unsigned-reg)))
501 (:arg-types unsigned-num unsigned-num)
502 (:note "inline (unsigned-byte 32) comparison"))
504 (define-vop (fast-conditional-c/unsigned fast-conditional/unsigned)
505 (:args (x :scs (unsigned-reg)))
506 (:arg-types unsigned-num (:constant (and (signed-byte-with-a-bite-out 16 1)
508 (:info target not-p y))
511 (defmacro define-conditional-vop (translate &rest generator)
513 ,@(mapcar #'(lambda (suffix cost signed)
514 (unless (and (member suffix '(/fixnum -c/fixnum))
516 `(define-vop (,(intern (format nil "~:@(FAST-IF-~A~A~)"
519 (format nil "~:@(FAST-CONDITIONAL~A~)"
521 (:translate ,translate)
523 (let* ((signed ,signed)
524 (-c/fixnum ,(eq suffix '-c/fixnum))
525 (y (if -c/fixnum (fixnumize y) y)))
526 (declare (ignorable signed -c/fixnum y))
528 '(/fixnum -c/fixnum /signed -c/signed /unsigned -c/unsigned)
530 '(t t t t nil nil))))
532 (define-conditional-vop <
533 (cond ((and signed (eql y 0))
536 (inst bltz x target)))
540 (inst sltu temp x y))
542 (inst beq temp zero-tn target)
543 (inst bne temp zero-tn target))))
546 (define-conditional-vop >
547 (cond ((and signed (eql y 0))
550 (inst bgtz x target)))
552 (let ((y (+ y (if -c/fixnum (fixnumize 1) 1))))
555 (inst sltu temp x y))
557 (inst bne temp zero-tn target)
558 (inst beq temp zero-tn target))))
562 (inst sltu temp y x))
564 (inst beq temp zero-tn target)
565 (inst bne temp zero-tn target))))
568 ;;; EQL/FIXNUM is funny because the first arg can be of any type, not just a
571 (define-conditional-vop eql
572 (declare (ignore signed))
577 (inst bne x y target)
578 (inst beq x y target))
581 ;;; These versions specify a fixnum restriction on their first arg. We have
582 ;;; also generic-eql/fixnum VOPs which are the same, but have no restriction on
583 ;;; the first arg and a higher cost. The reason for doing this is to prevent
584 ;;; fixnum specific operations from being used on word integers, spuriously
585 ;;; consing the argument.
587 (define-vop (fast-eql/fixnum fast-conditional)
588 (:args (x :scs (any-reg))
590 (:arg-types tagged-num tagged-num)
591 (:note "inline fixnum comparison")
596 (inst bne x y target)
597 (inst beq x y target))
600 (define-vop (generic-eql/fixnum fast-eql/fixnum)
601 (:args (x :scs (any-reg descriptor-reg))
603 (:arg-types * tagged-num)
606 (define-vop (fast-eql-c/fixnum fast-conditional/fixnum)
607 (:args (x :scs (any-reg)))
608 (:arg-types tagged-num (:constant (signed-byte 14)))
609 (:info target not-p y)
612 (let ((y (cond ((eql y 0) zero-tn)
614 (inst li temp (fixnumize y))
617 (inst bne x y target)
618 (inst beq x y target))
621 (define-vop (generic-eql-c/fixnum fast-eql-c/fixnum)
622 (:args (x :scs (any-reg descriptor-reg)))
623 (:arg-types * (:constant (signed-byte 14)))
627 ;;;; 32-bit logical operations
629 (define-vop (merge-bits)
630 (:translate merge-bits)
631 (:args (shift :scs (signed-reg unsigned-reg))
632 (prev :scs (unsigned-reg))
633 (next :scs (unsigned-reg)))
634 (:arg-types tagged-num unsigned-num unsigned-num)
635 (:temporary (:scs (unsigned-reg) :to (:result 0)) temp)
636 (:temporary (:scs (unsigned-reg) :to (:result 0) :target result) res)
637 (:results (result :scs (unsigned-reg)))
638 (:result-types unsigned-num)
641 (let ((done (gen-label)))
642 (inst beq shift done)
643 (inst srl res next shift)
644 (inst subu temp zero-tn shift)
645 (inst sll temp prev temp)
646 (inst or res res temp)
650 (define-vop (shift-towards-someplace)
652 (:args (num :scs (unsigned-reg))
653 (amount :scs (signed-reg)))
654 (:arg-types unsigned-num tagged-num)
655 (:results (r :scs (unsigned-reg)))
656 (:result-types unsigned-num))
658 (define-vop (shift-towards-start shift-towards-someplace)
659 (:translate shift-towards-start)
660 (:note "SHIFT-TOWARDS-START")
662 (ecase *backend-byte-order*
664 (inst sll r num amount))
666 (inst srl r num amount)))))
668 (define-vop (shift-towards-end shift-towards-someplace)
669 (:translate shift-towards-end)
670 (:note "SHIFT-TOWARDS-END")
672 (ecase *backend-byte-order*
674 (inst srl r num amount))
676 (inst sll r num amount)))))
678 ;;;; Modular arithmetic
679 (define-modular-fun +-mod32 (x y) + :unsigned 32)
680 (define-vop (fast-+-mod32/unsigned=>unsigned fast-+/unsigned=>unsigned)
681 (:translate +-mod32))
682 (define-vop (fast-+-mod32-c/unsigned=>unsigned fast-+-c/unsigned=>unsigned)
683 (:translate +-mod32))
684 (define-modular-fun --mod32 (x y) - :unsigned 32)
685 (define-vop (fast---mod32/unsigned=>unsigned fast--/unsigned=>unsigned)
686 (:translate --mod32))
687 (define-vop (fast---mod32-c/unsigned=>unsigned fast---c/unsigned=>unsigned)
688 (:translate --mod32))
690 (define-vop (fast-ash-left-mod32-c/unsigned=>unsigned
691 fast-ash-c/unsigned=>unsigned)
692 (:translate ash-left-mod32))
694 (define-vop (fast-ash-left-mod32/unsigned=>unsigned
695 fast-ash-left/unsigned=>unsigned))
696 (deftransform ash-left-mod32 ((integer count)
697 ((unsigned-byte 32) (unsigned-byte 5)))
698 (when (sb!c::constant-lvar-p count)
699 (sb!c::give-up-ir1-transform))
700 '(%primitive fast-ash-left-mod32/unsigned=>unsigned integer count))
702 ;;; logical operations
703 (define-modular-fun lognot-mod32 (x) lognot :unsigned 32)
704 (define-vop (lognot-mod32/unsigned=>unsigned)
705 (:translate lognot-mod32)
706 (:args (x :scs (unsigned-reg)))
707 (:arg-types unsigned-num)
708 (:results (r :scs (unsigned-reg)))
709 (:result-types unsigned-num)
712 (inst nor r x zero-tn)))
714 (define-modular-fun logxor-mod32 (x y) logxor :unsigned 32)
715 (define-vop (fast-logxor-mod32/unsigned=>unsigned
716 fast-logxor/unsigned=>unsigned)
717 (:translate logxor-mod32))
718 (define-vop (fast-logxor-mod32-c/unsigned=>unsigned
719 fast-logxor-c/unsigned=>unsigned)
720 (:translate logxor-mod32))
722 (define-modular-fun lognor-mod32 (x y) lognor :unsigned 32)
723 (define-vop (fast-lognor-mod32/unsigned=>unsigned
724 fast-lognor/unsigned=>unsigned)
725 (:translate lognor-mod32))
727 (define-source-transform logeqv (&rest args)
728 (if (oddp (length args))
730 `(lognot (logxor ,@args))))
731 (define-source-transform logandc1 (x y)
732 `(logand (lognot ,x) ,y))
733 (define-source-transform logandc2 (x y)
734 `(logand ,x (lognot ,y)))
735 (define-source-transform logorc1 (x y)
736 `(logior (lognot ,x) ,y))
737 (define-source-transform logorc2 (x y)
738 `(logior ,x (lognot ,y)))
739 (define-source-transform lognand (x y)
740 `(lognot (logand ,x ,y)))
743 (define-vop (bignum-length get-header-data)
744 (:translate sb!bignum:%bignum-length)
745 (:policy :fast-safe))
747 (define-vop (bignum-set-length set-header-data)
748 (:translate sb!bignum:%bignum-set-length)
749 (:policy :fast-safe))
751 (define-full-reffer bignum-ref * bignum-digits-offset other-pointer-lowtag
752 (unsigned-reg) unsigned-num sb!bignum:%bignum-ref)
754 (define-full-setter bignum-set * bignum-digits-offset other-pointer-lowtag
755 (unsigned-reg) unsigned-num sb!bignum:%bignum-set)
757 (define-vop (digit-0-or-plus)
758 (:translate sb!bignum:%digit-0-or-plusp)
760 (:args (digit :scs (unsigned-reg)))
761 (:arg-types unsigned-num)
766 (inst bltz digit target)
767 (inst bgez digit target))
770 (define-vop (add-w/carry)
771 (:translate sb!bignum:%add-with-carry)
773 (:args (a :scs (unsigned-reg))
774 (b :scs (unsigned-reg))
776 (:arg-types unsigned-num unsigned-num positive-fixnum)
777 (:temporary (:scs (unsigned-reg) :to (:result 0) :target result) res)
778 (:results (result :scs (unsigned-reg))
779 (carry :scs (unsigned-reg) :from :eval))
780 (:result-types unsigned-num positive-fixnum)
781 (:temporary (:scs (non-descriptor-reg)) temp)
783 (let ((carry-in (gen-label))
785 (inst bne c carry-in)
789 (inst sltu carry res b)
791 (emit-label carry-in)
793 (inst nor temp a zero-tn)
794 (inst sltu carry b temp)
800 (define-vop (sub-w/borrow)
801 (:translate sb!bignum:%subtract-with-borrow)
803 (:args (a :scs (unsigned-reg))
804 (b :scs (unsigned-reg))
806 (:arg-types unsigned-num unsigned-num positive-fixnum)
807 (:temporary (:scs (unsigned-reg) :to (:result 0) :target result) res)
808 (:results (result :scs (unsigned-reg))
809 (borrow :scs (unsigned-reg) :from :eval))
810 (:result-types unsigned-num positive-fixnum)
812 (let ((no-borrow-in (gen-label))
815 (inst bne c no-borrow-in)
820 (inst sltu borrow b a)
822 (emit-label no-borrow-in)
823 (inst sltu borrow a b)
829 (define-vop (bignum-mult-and-add-3-arg)
830 (:translate sb!bignum:%multiply-and-add)
832 (:args (x :scs (unsigned-reg))
833 (y :scs (unsigned-reg))
834 (carry-in :scs (unsigned-reg) :to :save))
835 (:arg-types unsigned-num unsigned-num unsigned-num)
836 (:temporary (:scs (unsigned-reg) :from (:argument 1)) temp)
837 (:results (hi :scs (unsigned-reg))
838 (lo :scs (unsigned-reg)))
839 (:result-types unsigned-num unsigned-num)
843 (inst addu lo temp carry-in)
844 (inst sltu temp lo carry-in)
846 (inst addu hi temp)))
848 (define-vop (bignum-mult-and-add-4-arg)
849 (:translate sb!bignum:%multiply-and-add)
851 (:args (x :scs (unsigned-reg))
852 (y :scs (unsigned-reg))
853 (prev :scs (unsigned-reg))
854 (carry-in :scs (unsigned-reg) :to :save))
855 (:arg-types unsigned-num unsigned-num unsigned-num unsigned-num)
856 (:temporary (:scs (unsigned-reg) :from (:argument 2)) temp)
857 (:results (hi :scs (unsigned-reg))
858 (lo :scs (unsigned-reg)))
859 (:result-types unsigned-num unsigned-num)
862 (inst addu lo prev carry-in)
863 (inst sltu temp lo carry-in)
868 (inst sltu temp lo temp)
869 (inst addu hi temp)))
871 (define-vop (bignum-mult)
872 (:translate sb!bignum:%multiply)
874 (:args (x :scs (unsigned-reg))
875 (y :scs (unsigned-reg)))
876 (:arg-types unsigned-num unsigned-num)
877 (:results (hi :scs (unsigned-reg))
878 (lo :scs (unsigned-reg)))
879 (:result-types unsigned-num unsigned-num)
885 (define-vop (bignum-lognot lognot-mod32/unsigned=>unsigned)
886 (:translate sb!bignum:%lognot))
888 (define-vop (fixnum-to-digit)
889 (:translate sb!bignum:%fixnum-to-digit)
891 (:args (fixnum :scs (any-reg)))
892 (:arg-types tagged-num)
893 (:results (digit :scs (unsigned-reg)))
894 (:result-types unsigned-num)
896 (inst sra digit fixnum n-fixnum-tag-bits)))
898 (define-vop (bignum-floor)
899 (:translate sb!bignum:%floor)
901 (:args (num-high :scs (unsigned-reg) :target rem)
902 (num-low :scs (unsigned-reg) :target rem-low)
903 (denom :scs (unsigned-reg) :to (:eval 1)))
904 (:arg-types unsigned-num unsigned-num unsigned-num)
905 (:temporary (:scs (unsigned-reg) :from (:argument 1)) rem-low)
906 (:temporary (:scs (unsigned-reg) :from (:eval 0)) temp)
907 (:results (quo :scs (unsigned-reg) :from (:eval 0))
908 (rem :scs (unsigned-reg) :from (:argument 0)))
909 (:result-types unsigned-num unsigned-num)
910 (:generator 325 ; number of inst assuming targeting works.
912 (move rem-low num-low)
913 (flet ((maybe-subtract (&optional (guess temp))
914 (inst subu temp guess 1)
915 (inst and temp denom)
916 (inst subu rem temp)))
917 (inst sltu quo rem denom)
921 (inst srl temp rem-low 31)
924 (inst sltu temp rem denom)
928 (inst nor quo zero-tn)))
930 (define-vop (signify-digit)
931 (:translate sb!bignum:%fixnum-digit-with-correct-sign)
933 (:args (digit :scs (unsigned-reg) :target res))
934 (:arg-types unsigned-num)
935 (:results (res :scs (any-reg signed-reg)))
936 (:result-types signed-num)
940 (inst sll res digit n-fixnum-tag-bits))
945 (define-vop (digit-ashr)
946 (:translate sb!bignum:%ashr)
948 (:args (digit :scs (unsigned-reg))
949 (count :scs (unsigned-reg)))
950 (:arg-types unsigned-num positive-fixnum)
951 (:results (result :scs (unsigned-reg)))
952 (:result-types unsigned-num)
954 (inst sra result digit count)))
956 (define-vop (digit-lshr digit-ashr)
957 (:translate sb!bignum:%digit-logical-shift-right)
959 (inst srl result digit count)))
961 (define-vop (digit-ashl digit-ashr)
962 (:translate sb!bignum:%ashl)
964 (inst sll result digit count)))
967 ;;;; Static functions.
969 (define-static-fun two-arg-gcd (x y) :translate gcd)
970 (define-static-fun two-arg-lcm (x y) :translate lcm)
972 (define-static-fun two-arg-+ (x y) :translate +)
973 (define-static-fun two-arg-- (x y) :translate -)
974 (define-static-fun two-arg-* (x y) :translate *)
975 (define-static-fun two-arg-/ (x y) :translate /)
977 (define-static-fun two-arg-< (x y) :translate <)
978 (define-static-fun two-arg-<= (x y) :translate <=)
979 (define-static-fun two-arg-> (x y) :translate >)
980 (define-static-fun two-arg->= (x y) :translate >=)
981 (define-static-fun two-arg-= (x y) :translate =)
982 (define-static-fun two-arg-/= (x y) :translate /=)
984 (define-static-fun %negate (x) :translate %negate)
986 (define-static-fun two-arg-and (x y) :translate logand)
987 (define-static-fun two-arg-ior (x y) :translate logior)
988 (define-static-fun two-arg-xor (x y) :translate logxor)