7 (define-vop (fixnum-unop)
8 (:args (x :scs (any-reg)))
9 (:results (res :scs (any-reg)))
10 (:note "inline fixnum arithmetic")
11 (:arg-types tagged-num)
12 (:result-types tagged-num)
15 (define-vop (signed-unop)
16 (:args (x :scs (signed-reg)))
17 (:results (res :scs (signed-reg)))
18 (:note "inline (signed-byte 32) arithmetic")
19 (:arg-types signed-num)
20 (:result-types signed-num)
23 (define-vop (fast-negate/fixnum fixnum-unop)
26 (inst sub zero-tn x res)))
28 (define-vop (fast-negate/signed signed-unop)
31 (inst sub zero-tn x res)))
33 (define-vop (fast-lognot/fixnum fixnum-unop)
34 (:temporary (:scs (any-reg) :type fixnum :to (:result 0))
38 (inst li (fixnumize -1) temp)
39 (inst xor x temp res)))
41 (define-vop (fast-lognot/signed signed-unop)
44 (inst uaddcm zero-tn x res)))
48 ;;;; Binary fixnum operations.
50 ;;; Assume that any constant operand is the second arg...
52 (define-vop (fast-fixnum-binop)
53 (:args (x :target r :scs (any-reg))
54 (y :target r :scs (any-reg)))
55 (:arg-types tagged-num tagged-num)
56 (:results (r :scs (any-reg)))
57 (:result-types tagged-num)
58 (:note "inline fixnum arithmetic")
63 (define-vop (fast-unsigned-binop)
64 (:args (x :target r :scs (unsigned-reg))
65 (y :target r :scs (unsigned-reg)))
66 (:arg-types unsigned-num unsigned-num)
67 (:results (r :scs (unsigned-reg)))
68 (:result-types unsigned-num)
69 (:note "inline (unsigned-byte 32) arithmetic")
74 (define-vop (fast-signed-binop)
75 (:args (x :target r :scs (signed-reg))
76 (y :target r :scs (signed-reg)))
77 (:arg-types signed-num signed-num)
78 (:results (r :scs (signed-reg)))
79 (:result-types signed-num)
80 (:note "inline (signed-byte 32) arithmetic")
85 (defmacro define-binop (translate cost untagged-cost op)
87 (define-vop (,(symbolicate "FAST-" translate "/FIXNUM=>FIXNUM")
89 (:args (x :target r :scs (any-reg))
90 (y :target r :scs (any-reg)))
91 (:translate ,translate)
94 (define-vop (,(symbolicate "FAST-" translate "/SIGNED=>SIGNED")
96 (:args (x :target r :scs (signed-reg))
97 (y :target r :scs (signed-reg)))
98 (:translate ,translate)
99 (:generator ,untagged-cost
101 (define-vop (,(symbolicate "FAST-" translate "/UNSIGNED=>UNSIGNED")
103 (:args (x :target r :scs (unsigned-reg))
104 (y :target r :scs (unsigned-reg)))
105 (:translate ,translate)
106 (:generator ,untagged-cost
109 (define-binop + 2 6 add)
110 (define-binop - 2 6 sub)
111 (define-binop logior 1 2 or)
112 (define-binop logand 1 2 and)
113 (define-binop logandc2 1 2 andcm)
114 (define-binop logxor 1 2 xor)
116 (define-vop (fast-fixnum-c-binop fast-fixnum-binop)
117 (:args (x :target r :scs (any-reg)))
119 (:arg-types tagged-num (:constant integer)))
121 (define-vop (fast-signed-c-binop fast-signed-binop)
122 (:args (x :target r :scs (signed-reg)))
124 (:arg-types tagged-num (:constant integer)))
126 (define-vop (fast-unsigned-c-binop fast-unsigned-binop)
127 (:args (x :target r :scs (unsigned-reg)))
129 (:arg-types tagged-num (:constant integer)))
131 (defmacro define-c-binop (translate cost untagged-cost tagged-type
134 (define-vop (,(symbolicate "FAST-" translate "-C/FIXNUM=>FIXNUM")
136 (:arg-types tagged-num (:constant ,tagged-type))
137 (:translate ,translate)
139 (let ((y (fixnumize y)))
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 "-C/UNSIGNED=>UNSIGNED")
148 fast-unsigned-c-binop)
149 (:arg-types unsigned-num (:constant ,untagged-type))
150 (:translate ,translate)
151 (:generator ,untagged-cost
154 (define-c-binop + 1 3 (signed-byte 9) (signed-byte 11)
156 (define-c-binop - 1 3
157 (integer #.(- (1- (ash 1 9))) #.(ash 1 9))
158 (integer #.(- (1- (ash 1 11))) #.(ash 1 11))
159 (inst addi (- y) x r))
161 ;;; Special case fixnum + and - that trap on overflow. Useful when we don't
162 ;;; know that the result is going to be a fixnum.
164 (define-vop (fast-+/fixnum fast-+/fixnum=>fixnum)
165 (:results (r :scs (any-reg descriptor-reg)))
166 (:result-types (:or signed-num unsigned-num))
171 (define-vop (fast-+-c/fixnum fast-+-c/fixnum=>fixnum)
172 (:results (r :scs (any-reg descriptor-reg)))
173 (:result-types (:or signed-num unsigned-num))
176 (inst addio (fixnumize y) x r)))
178 (define-vop (fast--/fixnum fast--/fixnum=>fixnum)
179 (:results (r :scs (any-reg descriptor-reg)))
180 (:result-types (:or signed-num unsigned-num))
185 (define-vop (fast---c/fixnum fast---c/fixnum=>fixnum)
186 (:results (r :scs (any-reg descriptor-reg)))
187 (:result-types (:or signed-num unsigned-num))
190 (inst addio (- (fixnumize y)) x r)))
194 (define-vop (fast-ash/unsigned=>unsigned)
197 (:note "inline word ASH")
198 (:args (number :scs (unsigned-reg))
199 (count :scs (signed-reg)))
200 (:arg-types unsigned-num tagged-num)
201 (:temporary (:scs (unsigned-reg) :to (:result 0)) temp)
202 (:results (result :scs (unsigned-reg)))
203 (:result-types unsigned-num)
205 (inst comb :>= count zero-tn positive :nullify t)
206 (inst sub zero-tn count temp)
207 (inst comiclr 31 temp zero-tn :>=)
209 (inst mtctl temp :sar)
210 (inst extrs number 0 1 temp)
212 (inst shd temp number :variable result)
214 (inst subi 31 count temp)
215 (inst mtctl temp :sar)
216 (inst zdep number :variable 32 result)
219 (define-vop (fast-ash/signed=>signed)
222 (:note "inline word ASH")
223 (:args (number :scs (signed-reg))
224 (count :scs (signed-reg)))
225 (:arg-types signed-num tagged-num)
226 (:temporary (:scs (unsigned-reg) :to (:result 0)) temp)
227 (:results (result :scs (signed-reg)))
228 (:result-types signed-num)
230 (inst comb :>= count zero-tn positive :nullify t)
231 (inst sub zero-tn count temp)
232 (inst comiclr 31 temp zero-tn :>=)
234 (inst mtctl temp :sar)
235 (inst extrs number 0 1 temp)
237 (inst shd temp number :variable result)
239 (inst subi 31 count temp)
240 (inst mtctl temp :sar)
241 (inst zdep number :variable 32 result)
244 (define-vop (fast-ash-c/unsigned=>unsigned)
248 (:args (number :scs (unsigned-reg)))
250 (:arg-types unsigned-num (:constant integer))
251 (:results (result :scs (unsigned-reg)))
252 (:result-types unsigned-num)
255 ;; It is a right shift.
256 (inst srl number (min (- count) 31) result))
258 ;; It is a left shift.
259 (inst sll number (min count 31) result))
261 ;; Count=0? Shouldn't happen, but it's easy:
262 (move number result)))))
264 (define-vop (fast-ash-c/signed=>signed)
268 (:args (number :scs (signed-reg)))
270 (:arg-types signed-num (:constant integer))
271 (:results (result :scs (signed-reg)))
272 (:result-types signed-num)
275 ;; It is a right shift.
276 (inst sra number (min (- count) 31) result))
278 ;; It is a left shift.
279 (inst sll number (min count 31) result))
281 ;; Count=0? Shouldn't happen, but it's easy:
282 (move number result)))))
285 (define-vop (signed-byte-32-len)
286 (:translate integer-length)
287 (:note "inline (signed-byte 32) integer-length")
289 (:args (arg :scs (signed-reg) :target shift))
290 (:arg-types signed-num)
291 (:results (res :scs (any-reg)))
292 (:result-types positive-fixnum)
293 (:temporary (:scs (non-descriptor-reg) :from (:argument 0)) shift)
295 (inst move arg shift :>=)
296 (inst uaddcm zero-tn shift shift)
297 (inst comb := shift zero-tn done)
300 (inst srl shift 1 shift)
301 (inst comb :<> shift zero-tn loop)
302 (inst addi (fixnumize 1) res res)
305 (define-vop (unsigned-byte-32-count)
306 (:translate logcount)
307 (:note "inline (unsigned-byte 32) logcount")
309 (:args (arg :scs (unsigned-reg) :target num))
310 (:arg-types unsigned-num)
311 (:results (res :scs (unsigned-reg)))
312 (:result-types positive-fixnum)
313 (:temporary (:scs (non-descriptor-reg) :from (:argument 0) :to (:result 0)
315 (:temporary (:scs (non-descriptor-reg)) mask temp)
317 (inst li #x55555555 mask)
318 (inst srl arg 1 temp)
319 (inst and arg mask num)
320 (inst and temp mask temp)
321 (inst add num temp num)
322 (inst li #x33333333 mask)
323 (inst srl num 2 temp)
324 (inst and num mask num)
325 (inst and temp mask temp)
326 (inst add num temp num)
327 (inst li #x0f0f0f0f mask)
328 (inst srl num 4 temp)
329 (inst and num mask num)
330 (inst and temp mask temp)
331 (inst add num temp num)
332 (inst li #x00ff00ff mask)
333 (inst srl num 8 temp)
334 (inst and num mask num)
335 (inst and temp mask temp)
336 (inst add num temp num)
337 (inst li #x0000ffff mask)
338 (inst srl num 16 temp)
339 (inst and num mask num)
340 (inst and temp mask temp)
341 (inst add num temp res)))
343 ;;; Multiply and Divide.
345 (define-vop (fast-*/fixnum=>fixnum fast-fixnum-binop)
346 (:args (x :scs (any-reg) :target x-pass)
347 (y :scs (any-reg) :target y-pass))
348 (:temporary (:sc signed-reg :offset nl0-offset
349 :from (:argument 0) :to (:result 0)) x-pass)
350 (:temporary (:sc signed-reg :offset nl1-offset
351 :from (:argument 1) :to (:result 0)) y-pass)
352 (:temporary (:sc signed-reg :offset nl2-offset :target r
353 :from (:argument 1) :to (:result 0)) res-pass)
354 (:temporary (:sc signed-reg :offset nl3-offset :to (:result 0)) tmp)
355 (:temporary (:sc signed-reg :offset nl4-offset
356 :from (:argument 1) :to (:result 0)) sign)
357 (:temporary (:sc interior-reg :offset lip-offset) lip)
361 (unless (location= y y-pass)
362 (inst sra x 2 x-pass))
363 (let ((fixup (make-fixup 'multiply :assembly-routine)))
364 (inst ldil fixup tmp)
365 (inst ble fixup lisp-heap-space tmp))
366 (if (location= y y-pass)
367 (inst sra x 2 x-pass)
368 (inst move y y-pass))
371 (define-vop (fast-*/signed=>signed fast-signed-binop)
373 (:args (x :scs (signed-reg) :target x-pass)
374 (y :scs (signed-reg) :target y-pass))
375 (:temporary (:sc signed-reg :offset nl0-offset
376 :from (:argument 0) :to (:result 0)) x-pass)
377 (:temporary (:sc signed-reg :offset nl1-offset
378 :from (:argument 1) :to (:result 0)) y-pass)
379 (:temporary (:sc signed-reg :offset nl2-offset :target r
380 :from (:argument 1) :to (:result 0)) res-pass)
381 (:temporary (:sc signed-reg :offset nl3-offset :to (:result 0)) tmp)
382 (:temporary (:sc signed-reg :offset nl4-offset
383 :from (:argument 1) :to (:result 0)) sign)
384 (:temporary (:sc interior-reg :offset lip-offset) lip)
388 (let ((fixup (make-fixup 'multiply :assembly-routine)))
391 (inst ldil fixup tmp)
392 (inst ble fixup lisp-heap-space tmp :nullify t)
396 (define-vop (fast-truncate/fixnum fast-fixnum-binop)
397 (:translate truncate)
398 (:args (x :scs (any-reg) :target x-pass)
399 (y :scs (any-reg) :target y-pass))
400 (:temporary (:sc signed-reg :offset nl0-offset
401 :from (:argument 0) :to (:result 0)) x-pass)
402 (:temporary (:sc signed-reg :offset nl1-offset
403 :from (:argument 1) :to (:result 0)) y-pass)
404 (:temporary (:sc signed-reg :offset nl2-offset :target q
405 :from (:argument 1) :to (:result 0)) q-pass)
406 (:temporary (:sc signed-reg :offset nl3-offset :target r
407 :from (:argument 1) :to (:result 1)) r-pass)
408 (:results (q :scs (signed-reg))
410 (:result-types tagged-num tagged-num)
412 (:save-p :compute-only)
414 (let ((zero (generate-error-code vop division-by-zero-error x y)))
415 (inst bc := nil y zero-tn zero))
418 (let ((fixup (make-fixup 'truncate :assembly-routine)))
419 (inst ldil fixup q-pass)
420 (inst ble fixup lisp-heap-space q-pass :nullify t))
425 (define-vop (fast-truncate/signed fast-signed-binop)
426 (:translate truncate)
427 (:args (x :scs (signed-reg) :target x-pass)
428 (y :scs (signed-reg) :target y-pass))
429 (:temporary (:sc signed-reg :offset nl0-offset
430 :from (:argument 0) :to (:result 0)) x-pass)
431 (:temporary (:sc signed-reg :offset nl1-offset
432 :from (:argument 1) :to (:result 0)) y-pass)
433 (:temporary (:sc signed-reg :offset nl2-offset :target q
434 :from (:argument 1) :to (:result 0)) q-pass)
435 (:temporary (:sc signed-reg :offset nl3-offset :target r
436 :from (:argument 1) :to (:result 1)) r-pass)
437 (:results (q :scs (signed-reg))
438 (r :scs (signed-reg)))
439 (:result-types signed-num signed-num)
441 (:save-p :compute-only)
443 (let ((zero (generate-error-code vop division-by-zero-error x y)))
444 (inst bc := nil y zero-tn zero))
447 (let ((fixup (make-fixup 'truncate :assembly-routine)))
448 (inst ldil fixup q-pass)
449 (inst ble fixup lisp-heap-space q-pass :nullify t))
455 ;;;; Binary conditional VOPs:
457 (define-vop (fast-conditional)
462 (:policy :fast-safe))
464 (define-vop (fast-conditional/fixnum fast-conditional)
465 (:args (x :scs (any-reg))
467 (:arg-types tagged-num tagged-num)
468 (:note "inline fixnum comparison"))
470 (define-vop (fast-conditional-c/fixnum fast-conditional/fixnum)
471 (:args (x :scs (any-reg)))
472 (:arg-types tagged-num (:constant (signed-byte 9)))
473 (:info target not-p y))
475 (define-vop (fast-conditional/signed fast-conditional)
476 (:args (x :scs (signed-reg))
477 (y :scs (signed-reg)))
478 (:arg-types signed-num signed-num)
479 (:note "inline (signed-byte 32) comparison"))
481 (define-vop (fast-conditional-c/signed fast-conditional/signed)
482 (:args (x :scs (signed-reg)))
483 (:arg-types signed-num (:constant (signed-byte 11)))
484 (:info target not-p y))
486 (define-vop (fast-conditional/unsigned fast-conditional)
487 (:args (x :scs (unsigned-reg))
488 (y :scs (unsigned-reg)))
489 (:arg-types unsigned-num unsigned-num)
490 (:note "inline (unsigned-byte 32) comparison"))
492 (define-vop (fast-conditional-c/unsigned fast-conditional/unsigned)
493 (:args (x :scs (unsigned-reg)))
494 (:arg-types unsigned-num (:constant (signed-byte 11)))
495 (:info target not-p y))
498 (defmacro define-conditional-vop (translate signed-cond unsigned-cond)
500 ,@(mapcar #'(lambda (suffix cost signed imm)
501 (unless (and (member suffix '(/fixnum -c/fixnum))
503 `(define-vop (,(intern (format nil "~:@(FAST-IF-~A~A~)"
506 (format nil "~:@(FAST-CONDITIONAL~A~)"
508 (:translate ,translate)
510 (inst ,(if imm 'bci 'bc)
511 ,(if signed signed-cond unsigned-cond)
513 ,(if (eq suffix '-c/fixnum)
518 '(/fixnum -c/fixnum /signed -c/signed /unsigned -c/unsigned)
521 '(nil t nil t nil t))))
523 ;; We switch < and > because the immediate has to come first.
525 (define-conditional-vop < :> :>>)
526 (define-conditional-vop > :< :<<)
528 ;;; EQL/FIXNUM is funny because the first arg can be of any type, not just a
531 (define-conditional-vop eql := :=)
533 ;;; These versions specify a fixnum restriction on their first arg. We have
534 ;;; also generic-eql/fixnum VOPs which are the same, but have no restriction on
535 ;;; the first arg and a higher cost. The reason for doing this is to prevent
536 ;;; fixnum specific operations from being used on word integers, spuriously
537 ;;; consing the argument.
539 (define-vop (fast-eql/fixnum fast-conditional)
540 (:args (x :scs (any-reg descriptor-reg))
542 (:arg-types tagged-num tagged-num)
543 (:note "inline fixnum comparison")
546 (inst bc := not-p x y target)))
548 (define-vop (generic-eql/fixnum fast-eql/fixnum)
549 (:arg-types * tagged-num)
552 (define-vop (fast-eql-c/fixnum fast-conditional/fixnum)
553 (:args (x :scs (any-reg descriptor-reg)))
554 (:arg-types tagged-num (:constant (signed-byte 9)))
555 (:info target not-p y)
558 (inst bci := not-p (fixnumize y) x target)))
560 (define-vop (generic-eql-c/fixnum fast-eql-c/fixnum)
561 (:arg-types * (:constant (signed-byte 9)))
565 ;;;; 32-bit logical operations
567 (define-vop (32bit-logical)
568 (:args (x :scs (unsigned-reg))
569 (y :scs (unsigned-reg)))
570 (:arg-types unsigned-num unsigned-num)
571 (:results (r :scs (unsigned-reg)))
572 (:result-types unsigned-num)
573 (:policy :fast-safe))
575 (define-vop (32bit-logical-not 32bit-logical)
576 (:translate 32bit-logical-not)
577 (:args (x :scs (unsigned-reg)))
578 (:arg-types unsigned-num)
580 (inst uaddcm zero-tn x r)))
582 (define-vop (32bit-logical-and 32bit-logical)
583 (:translate 32bit-logical-and)
587 (deftransform 32bit-logical-nand ((x y) (* *))
588 '(32bit-logical-not (32bit-logical-and x y)))
590 (define-vop (32bit-logical-or 32bit-logical)
591 (:translate 32bit-logical-or)
595 (deftransform 32bit-logical-nor ((x y) (* *))
596 '(32bit-logical-not (32bit-logical-or x y)))
598 (define-vop (32bit-logical-xor 32bit-logical)
599 (:translate 32bit-logical-xor)
603 (deftransform 32bit-logical-eqv ((x y) (* *))
604 '(32bit-logical-not (32bit-logical-xor x y)))
606 (deftransform 32bit-logical-andc1 ((x y) (* *))
607 '(32bit-logical-and (32bit-logical-not x) y))
609 (define-vop (32bit-logical-andc2 32bit-logical)
610 (:translate 32bit-logical-andc2)
614 (deftransform 32bit-logical-orc1 ((x y) (* *))
615 '(32bit-logical-or (32bit-logical-not x) y))
617 (deftransform 32bit-logical-orc2 ((x y) (* *))
618 '(32bit-logical-or x (32bit-logical-not y)))
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 (:temporary (:scs (unsigned-reg) :to (:result 0)) temp)
632 (:note "SHIFT-TOWARDS-START")
634 (inst subi 31 amount temp)
635 (inst mtctl temp :sar)
636 (inst zdep num :variable 32 r)))
638 (define-vop (shift-towards-end shift-towards-someplace)
639 (:translate shift-towards-end)
640 (:note "SHIFT-TOWARDS-END")
642 (inst mtctl amount :sar)
643 (inst shd zero-tn num :variable r)))
649 (define-vop (bignum-length get-header-data)
650 (:translate sb!bignum::%bignum-length)
651 (:policy :fast-safe))
653 (define-vop (bignum-set-length set-header-data)
654 (:translate sb!bignum::%bignum-set-length)
655 (:policy :fast-safe))
657 (define-full-reffer bignum-ref * bignum-digits-offset other-pointer-lowtag
658 (unsigned-reg) unsigned-num sb!bignum::%bignum-ref)
660 (define-full-setter bignum-set * bignum-digits-offset other-pointer-lowtag
661 (unsigned-reg) unsigned-num sb!bignum::%bignum-set)
663 (define-vop (digit-0-or-plus)
664 (:translate sb!bignum::%digit-0-or-plusp)
666 (:args (digit :scs (unsigned-reg)))
667 (:arg-types unsigned-num)
673 (inst bc :>= not-p digit zero-tn target)))
675 (define-vop (add-w/carry)
676 (:translate sb!bignum::%add-with-carry)
678 (:args (a :scs (unsigned-reg))
679 (b :scs (unsigned-reg))
680 (c :scs (unsigned-reg)))
681 (:arg-types unsigned-num unsigned-num positive-fixnum)
682 (:results (result :scs (unsigned-reg))
683 (carry :scs (unsigned-reg)))
684 (:result-types unsigned-num positive-fixnum)
686 (inst addi -1 c zero-tn)
687 (inst addc a b result)
688 (inst addc zero-tn zero-tn carry)))
690 (define-vop (sub-w/borrow)
691 (:translate sb!bignum::%subtract-with-borrow)
693 (:args (a :scs (unsigned-reg))
694 (b :scs (unsigned-reg))
695 (c :scs (unsigned-reg)))
696 (:arg-types unsigned-num unsigned-num positive-fixnum)
697 (:results (result :scs (unsigned-reg))
698 (borrow :scs (unsigned-reg)))
699 (:result-types unsigned-num positive-fixnum)
701 (inst addi -1 c zero-tn)
702 (inst subb a b result)
703 (inst addc zero-tn zero-tn borrow)))
705 (define-vop (bignum-mult)
706 (:translate sb!bignum::%multiply)
708 (:args (x-arg :scs (unsigned-reg) :target x)
709 (y-arg :scs (unsigned-reg) :target y))
710 (:arg-types unsigned-num unsigned-num)
711 (:temporary (:scs (signed-reg) :from (:argument 0)) x)
712 (:temporary (:scs (signed-reg) :from (:argument 1)) y)
713 (:temporary (:scs (signed-reg)) tmp)
714 (:results (hi :scs (unsigned-reg))
715 (lo :scs (unsigned-reg)))
716 (:result-types unsigned-num unsigned-num)
718 ;; Make sure X is less then Y.
719 (inst comclr x-arg y-arg tmp :<<)
720 (inst xor x-arg y-arg tmp)
721 (inst xor x-arg tmp x)
722 (inst xor y-arg tmp y)
724 ;; Blow out of here if the result is zero.
726 (inst comb := x zero-tn done)
731 (inst comb :ev x zero-tn next-bit)
734 (inst addc hi tmp hi)
737 (inst comb :<> x zero-tn loop)
738 (inst addc tmp tmp tmp)
742 (define-source-transform sb!bignum:%multiply-and-add (x y carry &optional (extra 0))
743 #+nil ;; This would be greate if it worked, but it doesn't.
745 `(multiple-value-call #'sb!bignum::%dual-word-add
746 (sb!bignum:%multiply ,x ,y)
748 `(multiple-value-call #'sb!bignum::%dual-word-add
749 (multiple-value-call #'sb!bignum::%dual-word-add
750 (sb!bignum:%multiply ,x ,y)
753 (with-unique-names (hi lo)
755 `(multiple-value-bind (,hi ,lo) (sb!bignum:%multiply ,x ,y)
756 (sb!bignum::%dual-word-add ,hi ,lo ,carry))
757 `(multiple-value-bind (,hi ,lo) (sb!bignum:%multiply ,x ,y)
760 (sb!bignum::%dual-word-add ,hi ,lo ,carry)
761 (sb!bignum::%dual-word-add ,hi ,lo ,extra))))))
763 (defknown sb!bignum::%dual-word-add
764 (sb!bignum:bignum-element-type sb!bignum:bignum-element-type sb!bignum:bignum-element-type)
765 (values sb!bignum:bignum-element-type sb!bignum:bignum-element-type)
768 (define-vop (dual-word-add)
770 (:translate sb!bignum::%dual-word-add)
771 (:args (hi :scs (unsigned-reg) :to (:result 1))
772 (lo :scs (unsigned-reg))
773 (extra :scs (unsigned-reg)))
774 (:arg-types unsigned-num unsigned-num unsigned-num)
775 (:results (hi-res :scs (unsigned-reg) :from (:result 1))
776 (lo-res :scs (unsigned-reg) :from (:result 0)))
777 (:result-types unsigned-num unsigned-num)
781 (inst add lo extra lo-res)
782 (inst addc hi zero-tn hi-res)))
784 (define-vop (bignum-lognot)
785 (:translate sb!bignum::%lognot)
787 (:args (x :scs (unsigned-reg)))
788 (:arg-types unsigned-num)
789 (:results (r :scs (unsigned-reg)))
790 (:result-types unsigned-num)
792 (inst uaddcm zero-tn x r)))
794 (define-vop (fixnum-to-digit)
795 (:translate sb!bignum::%fixnum-to-digit)
797 (:args (fixnum :scs (signed-reg)))
798 (:arg-types tagged-num)
799 (:results (digit :scs (unsigned-reg)))
800 (:result-types unsigned-num)
802 (move fixnum digit)))
804 (define-vop (bignum-floor)
805 (:translate sb!bignum::%floor)
807 (:args (hi :scs (unsigned-reg) :to (:argument 1))
808 (lo :scs (unsigned-reg) :to (:argument 0))
809 (divisor :scs (unsigned-reg)))
810 (:arg-types unsigned-num unsigned-num unsigned-num)
811 (:temporary (:scs (unsigned-reg) :to (:argument 1)) temp)
812 (:results (quo :scs (unsigned-reg) :from (:argument 0))
813 (rem :scs (unsigned-reg) :from (:argument 1)))
814 (:result-types unsigned-num unsigned-num)
816 (inst sub zero-tn divisor temp)
817 (inst ds zero-tn temp zero-tn)
819 (inst ds hi divisor rem)
820 (inst addc quo quo quo)
822 (inst ds rem divisor rem)
823 (inst addc quo quo quo))
824 (inst comclr rem zero-tn zero-tn :>=)
825 (inst add divisor rem rem)))
827 (define-vop (signify-digit)
828 (:translate sb!bignum::%fixnum-digit-with-correct-sign)
830 (:args (digit :scs (unsigned-reg) :target res))
831 (:arg-types unsigned-num)
832 (:results (res :scs (signed-reg)))
833 (:result-types signed-num)
837 (define-vop (digit-lshr)
838 (:translate sb!bignum::%digit-logical-shift-right)
840 (:args (digit :scs (unsigned-reg))
841 (count :scs (unsigned-reg)))
842 (:arg-types unsigned-num positive-fixnum)
843 (:results (result :scs (unsigned-reg)))
844 (:result-types unsigned-num)
846 (inst mtctl count :sar)
847 (inst shd zero-tn digit :variable result)))
849 (define-vop (digit-ashr digit-lshr)
850 (:translate sb!bignum::%ashr)
851 (:temporary (:scs (unsigned-reg) :to (:result 0)) temp)
853 (inst extrs digit 0 1 temp)
854 (inst mtctl count :sar)
855 (inst shd temp digit :variable result)))
857 (define-vop (digit-ashl digit-ashr)
858 (:translate sb!bignum::%ashl)
860 (inst subi 31 count temp)
861 (inst mtctl temp :sar)
862 (inst zdep digit :variable 32 result)))
865 ;;;; Static functions.
867 (define-static-fun two-arg-gcd (x y) :translate gcd)
868 (define-static-fun two-arg-lcm (x y) :translate lcm)
870 (define-static-fun two-arg-* (x y) :translate *)
871 (define-static-fun two-arg-/ (x y) :translate /)
873 (define-static-fun %negate (x) :translate %negate)
875 (define-static-fun two-arg-and (x y) :translate logand)
876 (define-static-fun two-arg-ior (x y) :translate logior)
877 (define-static-fun two-arg-xor (x y) :translate logxor)