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)
230 (inst bne temp zero-tn done
)
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)
256 (inst bne temp zero-tn done
)
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
)))
419 (inst beq y zero-tn zero
))
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
)))
435 (inst beq y zero-tn zero
))
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
)))
450 (inst beq y zero-tn zero
))
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 zero-tn target
)
535 (inst bne temp zero-tn 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 zero-tn target
)
550 (inst beq temp zero-tn target
))))
554 (inst sltu temp y x
))
556 (inst beq temp zero-tn target
)
557 (inst bne temp zero-tn 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 (merge-bits)
622 (:translate merge-bits
)
623 (:args
(shift :scs
(signed-reg unsigned-reg
))
624 (prev :scs
(unsigned-reg))
625 (next :scs
(unsigned-reg)))
626 (:arg-types tagged-num unsigned-num unsigned-num
)
627 (:temporary
(:scs
(unsigned-reg) :to
(:result
0)) temp
)
628 (:temporary
(:scs
(unsigned-reg) :to
(:result
0) :target result
) res
)
629 (:results
(result :scs
(unsigned-reg)))
630 (:result-types unsigned-num
)
633 (let ((done (gen-label)))
634 (inst beq shift done
)
635 (inst srl res next shift
)
636 (inst subu temp zero-tn shift
)
637 (inst sll temp prev temp
)
638 (inst or res res temp
)
642 (define-vop (shift-towards-someplace)
644 (:args
(num :scs
(unsigned-reg))
645 (amount :scs
(signed-reg)))
646 (:arg-types unsigned-num tagged-num
)
647 (:results
(r :scs
(unsigned-reg)))
648 (:result-types unsigned-num
))
650 (define-vop (shift-towards-start shift-towards-someplace
)
651 (:translate shift-towards-start
)
652 (:note
"SHIFT-TOWARDS-START")
654 (ecase *backend-byte-order
*
656 (inst sll r num amount
))
658 (inst srl r num amount
)))))
660 (define-vop (shift-towards-end shift-towards-someplace
)
661 (:translate shift-towards-end
)
662 (:note
"SHIFT-TOWARDS-END")
664 (ecase *backend-byte-order
*
666 (inst srl r num amount
))
668 (inst sll r num amount
)))))
670 ;;;; Modular arithmetic
671 (define-modular-fun +-mod32
(x y
) + :unsigned
32)
672 (define-vop (fast-+-mod32
/unsigned
=>unsigned fast-
+/unsigned
=>unsigned
)
673 (:translate
+-mod32
))
674 (define-vop (fast-+-mod32-c
/unsigned
=>unsigned fast-
+-c
/unsigned
=>unsigned
)
675 (:translate
+-mod32
))
676 (define-modular-fun --mod32
(x y
) -
:unsigned
32)
677 (define-vop (fast---mod32/unsigned
=>unsigned fast--
/unsigned
=>unsigned
)
678 (:translate --mod32
))
679 (define-vop (fast---mod32-c/unsigned
=>unsigned fast---c
/unsigned
=>unsigned
)
680 (:translate --mod32
))
682 (define-vop (fast-ash-left-mod32-c/unsigned
=>unsigned
683 fast-ash-c
/unsigned
=>unsigned
)
684 (:translate ash-left-mod32
))
686 (define-vop (fast-ash-left-mod32/unsigned
=>unsigned
687 fast-ash-left
/unsigned
=>unsigned
))
688 (deftransform ash-left-mod32
((integer count
)
689 ((unsigned-byte 32) (unsigned-byte 5)))
690 (when (sb!c
::constant-lvar-p count
)
691 (sb!c
::give-up-ir1-transform
))
692 '(%primitive fast-ash-left-mod32
/unsigned
=>unsigned integer count
))
694 ;;; logical operations
695 (define-modular-fun lognot-mod32
(x) lognot
:unsigned
32)
696 (define-vop (lognot-mod32/unsigned
=>unsigned
)
697 (:translate lognot-mod32
)
698 (:args
(x :scs
(unsigned-reg)))
699 (:arg-types unsigned-num
)
700 (:results
(r :scs
(unsigned-reg)))
701 (:result-types unsigned-num
)
704 (inst nor r x zero-tn
)))
706 (define-modular-fun logxor-mod32
(x y
) logxor
:unsigned
32)
707 (define-vop (fast-logxor-mod32/unsigned
=>unsigned
708 fast-logxor
/unsigned
=>unsigned
)
709 (:translate logxor-mod32
))
710 (define-vop (fast-logxor-mod32-c/unsigned
=>unsigned
711 fast-logxor-c
/unsigned
=>unsigned
)
712 (:translate logxor-mod32
))
714 (define-modular-fun lognor-mod32
(x y
) lognor
:unsigned
32)
715 (define-vop (fast-lognor-mod32/unsigned
=>unsigned
716 fast-lognor
/unsigned
=>unsigned
)
717 (:translate lognor-mod32
))
719 (define-source-transform logeqv
(&rest args
)
720 (if (oddp (length args
))
722 `(lognot (logxor ,@args
))))
723 (define-source-transform logandc1
(x y
)
724 `(logand (lognot ,x
) ,y
))
725 (define-source-transform logandc2
(x y
)
726 `(logand ,x
(lognot ,y
)))
727 (define-source-transform logorc1
(x y
)
728 `(logior (lognot ,x
) ,y
))
729 (define-source-transform logorc2
(x y
)
730 `(logior ,x
(lognot ,y
)))
731 (define-source-transform lognand
(x y
)
732 `(lognot (logand ,x
,y
)))
735 (define-vop (bignum-length get-header-data
)
736 (:translate sb
!bignum
:%bignum-length
)
737 (:policy
:fast-safe
))
739 (define-vop (bignum-set-length set-header-data
)
740 (:translate sb
!bignum
:%bignum-set-length
)
741 (:policy
:fast-safe
))
743 (define-full-reffer bignum-ref
* bignum-digits-offset other-pointer-lowtag
744 (unsigned-reg) unsigned-num sb
!bignum
:%bignum-ref
)
746 (define-full-setter bignum-set
* bignum-digits-offset other-pointer-lowtag
747 (unsigned-reg) unsigned-num sb
!bignum
:%bignum-set
)
749 (define-vop (digit-0-or-plus)
750 (:translate sb
!bignum
:%digit-0-or-plusp
)
752 (:args
(digit :scs
(unsigned-reg)))
753 (:arg-types unsigned-num
)
758 (inst bltz digit target
)
759 (inst bgez digit target
))
762 (define-vop (add-w/carry
)
763 (:translate sb
!bignum
:%add-with-carry
)
765 (:args
(a :scs
(unsigned-reg))
766 (b :scs
(unsigned-reg))
768 (:arg-types unsigned-num unsigned-num positive-fixnum
)
769 (:temporary
(:scs
(unsigned-reg) :to
(:result
0) :target result
) res
)
770 (:results
(result :scs
(unsigned-reg))
771 (carry :scs
(unsigned-reg) :from
:eval
))
772 (:result-types unsigned-num positive-fixnum
)
773 (:temporary
(:scs
(non-descriptor-reg)) temp
)
775 (let ((carry-in (gen-label))
777 (inst bne c carry-in
)
781 (inst sltu carry res b
)
783 (emit-label carry-in
)
785 (inst nor temp a zero-tn
)
786 (inst sltu carry b temp
)
792 (define-vop (sub-w/borrow
)
793 (:translate sb
!bignum
:%subtract-with-borrow
)
795 (:args
(a :scs
(unsigned-reg))
796 (b :scs
(unsigned-reg))
798 (:arg-types unsigned-num unsigned-num positive-fixnum
)
799 (:temporary
(:scs
(unsigned-reg) :to
(:result
0) :target result
) res
)
800 (:results
(result :scs
(unsigned-reg))
801 (borrow :scs
(unsigned-reg) :from
:eval
))
802 (:result-types unsigned-num positive-fixnum
)
804 (let ((no-borrow-in (gen-label))
807 (inst bne c no-borrow-in
)
812 (inst sltu borrow b a
)
814 (emit-label no-borrow-in
)
815 (inst sltu borrow a b
)
821 (define-vop (bignum-mult-and-add-3-arg)
822 (:translate sb
!bignum
:%multiply-and-add
)
824 (:args
(x :scs
(unsigned-reg))
825 (y :scs
(unsigned-reg))
826 (carry-in :scs
(unsigned-reg) :to
:save
))
827 (:arg-types unsigned-num unsigned-num unsigned-num
)
828 (:temporary
(:scs
(unsigned-reg) :from
(:argument
1)) temp
)
829 (:results
(hi :scs
(unsigned-reg))
830 (lo :scs
(unsigned-reg)))
831 (:result-types unsigned-num unsigned-num
)
835 (inst addu lo temp carry-in
)
836 (inst sltu temp lo carry-in
)
838 (inst addu hi temp
)))
840 (define-vop (bignum-mult-and-add-4-arg)
841 (:translate sb
!bignum
:%multiply-and-add
)
843 (:args
(x :scs
(unsigned-reg))
844 (y :scs
(unsigned-reg))
845 (prev :scs
(unsigned-reg))
846 (carry-in :scs
(unsigned-reg) :to
:save
))
847 (:arg-types unsigned-num unsigned-num unsigned-num unsigned-num
)
848 (:temporary
(:scs
(unsigned-reg) :from
(:argument
2)) temp
)
849 (:results
(hi :scs
(unsigned-reg))
850 (lo :scs
(unsigned-reg)))
851 (:result-types unsigned-num unsigned-num
)
854 (inst addu lo prev carry-in
)
855 (inst sltu temp lo carry-in
)
860 (inst sltu temp lo temp
)
861 (inst addu hi temp
)))
863 (define-vop (bignum-mult)
864 (:translate sb
!bignum
:%multiply
)
866 (:args
(x :scs
(unsigned-reg))
867 (y :scs
(unsigned-reg)))
868 (:arg-types unsigned-num unsigned-num
)
869 (:results
(hi :scs
(unsigned-reg))
870 (lo :scs
(unsigned-reg)))
871 (:result-types unsigned-num unsigned-num
)
877 (define-vop (bignum-lognot lognot-mod32
/unsigned
=>unsigned
)
878 (:translate sb
!bignum
:%lognot
))
880 (define-vop (fixnum-to-digit)
881 (:translate sb
!bignum
:%fixnum-to-digit
)
883 (:args
(fixnum :scs
(any-reg)))
884 (:arg-types tagged-num
)
885 (:results
(digit :scs
(unsigned-reg)))
886 (:result-types unsigned-num
)
888 (inst sra digit fixnum n-fixnum-tag-bits
)))
890 (define-vop (bignum-floor)
891 (:translate sb
!bignum
:%floor
)
893 (:args
(num-high :scs
(unsigned-reg) :target rem
)
894 (num-low :scs
(unsigned-reg) :target rem-low
)
895 (denom :scs
(unsigned-reg) :to
(:eval
1)))
896 (:arg-types unsigned-num unsigned-num unsigned-num
)
897 (:temporary
(:scs
(unsigned-reg) :from
(:argument
1)) rem-low
)
898 (:temporary
(:scs
(unsigned-reg) :from
(:eval
0)) temp
)
899 (:results
(quo :scs
(unsigned-reg) :from
(:eval
0))
900 (rem :scs
(unsigned-reg) :from
(:argument
0)))
901 (:result-types unsigned-num unsigned-num
)
902 (:generator
325 ; number of inst assuming targeting works.
904 (move rem-low num-low
)
905 (flet ((maybe-subtract (&optional
(guess temp
))
906 (inst subu temp guess
1)
907 (inst and temp denom
)
908 (inst subu rem temp
)))
909 (inst sltu quo rem denom
)
913 (inst srl temp rem-low
31)
916 (inst sltu temp rem denom
)
920 (inst nor quo zero-tn
)))
922 (define-vop (signify-digit)
923 (:translate sb
!bignum
:%fixnum-digit-with-correct-sign
)
925 (:args
(digit :scs
(unsigned-reg) :target res
))
926 (:arg-types unsigned-num
)
927 (:results
(res :scs
(any-reg signed-reg
)))
928 (:result-types signed-num
)
932 (inst sll res digit n-fixnum-tag-bits
))
937 (define-vop (digit-ashr)
938 (:translate sb
!bignum
:%ashr
)
940 (:args
(digit :scs
(unsigned-reg))
941 (count :scs
(unsigned-reg)))
942 (:arg-types unsigned-num positive-fixnum
)
943 (:results
(result :scs
(unsigned-reg)))
944 (:result-types unsigned-num
)
946 (inst sra result digit count
)))
948 (define-vop (digit-lshr digit-ashr
)
949 (:translate sb
!bignum
:%digit-logical-shift-right
)
951 (inst srl result digit count
)))
953 (define-vop (digit-ashl digit-ashr
)
954 (:translate sb
!bignum
:%ashl
)
956 (inst sll result digit count
)))
959 ;;;; Static functions.
961 (define-static-fun two-arg-gcd
(x y
) :translate gcd
)
962 (define-static-fun two-arg-lcm
(x y
) :translate lcm
)
964 (define-static-fun two-arg-
+ (x y
) :translate
+)
965 (define-static-fun two-arg--
(x y
) :translate -
)
966 (define-static-fun two-arg-
* (x y
) :translate
*)
967 (define-static-fun two-arg-
/ (x y
) :translate
/)
969 (define-static-fun two-arg-
< (x y
) :translate
<)
970 (define-static-fun two-arg-
<= (x y
) :translate
<=)
971 (define-static-fun two-arg-
> (x y
) :translate
>)
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
/=)
976 (define-static-fun %negate
(x) :translate %negate
)
978 (define-static-fun two-arg-and
(x y
) :translate logand
)
979 (define-static-fun two-arg-ior
(x y
) :translate logior
)
980 (define-static-fun two-arg-xor
(x y
) :translate logxor
)