1 ;;;; the VM definition arithmetic VOPs for the PPC
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
)
40 (define-vop (fast-negate/signed signed-unop
)
45 (define-vop (fast-lognot/fixnum fixnum-unop
)
48 (inst xori res x
(fixnumize -
1))))
50 (define-vop (fast-lognot/signed signed-unop
)
55 ;;;; Binary fixnum operations.
57 ;;; Assume that any constant operand is the second arg...
59 (define-vop (fast-fixnum-binop fast-safe-arith-op
)
60 (:args
(x :target r
:scs
(any-reg zero
))
61 (y :target r
:scs
(any-reg zero
)))
62 (:arg-types tagged-num tagged-num
)
63 (:results
(r :scs
(any-reg)))
64 (:result-types tagged-num
)
65 (:note
"inline fixnum arithmetic"))
67 (define-vop (fast-unsigned-binop fast-safe-arith-op
)
68 (:args
(x :target r
:scs
(unsigned-reg zero
))
69 (y :target r
:scs
(unsigned-reg zero
)))
70 (:arg-types unsigned-num unsigned-num
)
71 (:results
(r :scs
(unsigned-reg)))
72 (:result-types unsigned-num
)
73 (:note
"inline (unsigned-byte 32) arithmetic"))
75 (define-vop (fast-signed-binop fast-safe-arith-op
)
76 (:args
(x :target r
:scs
(signed-reg zero
))
77 (y :target r
:scs
(signed-reg zero
)))
78 (:arg-types signed-num signed-num
)
79 (:results
(r :scs
(signed-reg)))
80 (:result-types signed-num
)
81 (:note
"inline (signed-byte 32) arithmetic"))
83 (define-vop (fast-fixnum-binop-c fast-safe-arith-op
)
84 (:args
(x :target r
:scs
(any-reg zero
)))
86 (:arg-types tagged-num
87 (:constant
(and (signed-byte 14) (not (integer 0 0)))))
88 (:results
(r :scs
(any-reg)))
89 (:result-types tagged-num
)
90 (:note
"inline fixnum arithmetic"))
92 (define-vop (fast-fixnum-logop-c fast-safe-arith-op
)
93 (:args
(x :target r
:scs
(any-reg zero
)))
95 (:arg-types tagged-num
96 (:constant
(and (unsigned-byte 14) (not (integer 0 0)))))
97 (:results
(r :scs
(any-reg)))
98 (:result-types tagged-num
)
99 (:note
"inline fixnum logical op"))
101 (define-vop (fast-unsigned-binop-c fast-safe-arith-op
)
102 (:args
(x :target r
:scs
(unsigned-reg zero
)))
104 (:arg-types unsigned-num
105 (:constant
(and (signed-byte 16) (not (integer 0 0)))))
106 (:results
(r :scs
(unsigned-reg)))
107 (:result-types unsigned-num
)
108 (:note
"inline (unsigned-byte 32) arithmetic"))
110 (define-vop (fast-unsigned-logop-c fast-safe-arith-op
)
111 (:args
(x :target r
:scs
(unsigned-reg zero
)))
113 (:arg-types unsigned-num
114 (:constant
(and (unsigned-byte 16) (not (integer 0 0)))))
115 (:results
(r :scs
(unsigned-reg)))
116 (:result-types unsigned-num
)
117 (:note
"inline (unsigned-byte 32) logical op"))
119 (define-vop (fast-signed-binop-c fast-safe-arith-op
)
120 (:args
(x :target r
:scs
(signed-reg zero
)))
122 (:arg-types signed-num
123 (:constant
(and (signed-byte 16) (not (integer 0 0)))))
124 (:results
(r :scs
(signed-reg)))
125 (:result-types signed-num
)
126 (:note
"inline (signed-byte 32) arithmetic"))
128 (define-vop (fast-signed-logop-c fast-safe-arith-op
)
129 (:args
(x :target r
:scs
(signed-reg zero
)))
131 (:arg-types signed-num
132 (:constant
(and (unsigned-byte 16) (not (integer 0 0)))))
133 (:results
(r :scs
(signed-reg)))
134 (:result-types signed-num
)
135 (:note
"inline (signed-byte 32) arithmetic"))
138 (eval-when (:compile-toplevel
:load-toplevel
:execute
)
140 (defmacro define-var-binop
(translate untagged-penalty op
141 &optional arg-swap restore-fixnum-mask
)
143 (define-vop (,(symbolicate "FAST-" translate
"/FIXNUM=>FIXNUM")
145 ,@(when restore-fixnum-mask
146 `((:temporary
(:sc non-descriptor-reg
) temp
)))
147 (:translate
,translate
)
150 `(inst ,op
,(if restore-fixnum-mask
'temp
'r
) y x
)
151 `(inst ,op
,(if restore-fixnum-mask
'temp
'r
) x y
))
152 ;; FIXME: remind me what convention we used for 64bitizing
153 ;; stuff? -- CSR, 2003-08-27
154 ,@(when restore-fixnum-mask
155 `((inst clrrwi r temp
(1- n-lowtag-bits
))))))
156 (define-vop (,(symbolicate "FAST-" translate
"/SIGNED=>SIGNED")
158 (:translate
,translate
)
159 (:generator
,(1+ untagged-penalty
)
163 (define-vop (,(symbolicate "FAST-" translate
"/UNSIGNED=>UNSIGNED")
165 (:translate
,translate
)
166 (:generator
,(1+ untagged-penalty
)
169 `(inst ,op r x y
))))))
172 (defmacro define-const-binop
(translate untagged-penalty op
)
175 (define-vop (,(symbolicate 'fast- translate
'-c
/fixnum
=>fixnum
)
177 (:translate
,translate
)
179 (inst ,op r x
(fixnumize y
))))
180 (define-vop (,(symbolicate 'fast- translate
'-c
/signed
=>signed
)
182 (:translate
,translate
)
183 (:generator
,untagged-penalty
185 (define-vop (,(symbolicate 'fast- translate
'-c
/unsigned
=>unsigned
)
186 fast-unsigned-binop-c
)
187 (:translate
,translate
)
188 (:generator
,untagged-penalty
191 (defmacro define-const-logop
(translate untagged-penalty op
)
194 (define-vop (,(symbolicate 'fast- translate
'-c
/fixnum
=>fixnum
)
196 (:translate
,translate
)
198 (inst ,op r x
(fixnumize y
))))
199 (define-vop (,(symbolicate 'fast- translate
'-c
/signed
=>signed
)
201 (:translate
,translate
)
202 (:generator
,untagged-penalty
204 (define-vop (,(symbolicate 'fast- translate
'-c
/unsigned
=>unsigned
)
205 fast-unsigned-logop-c
)
206 (:translate
,translate
)
207 (:generator
,untagged-penalty
212 (define-var-binop + 4 add
)
213 (define-var-binop -
4 sub
)
214 (define-var-binop logand
2 and
)
215 (define-var-binop logandc1
2 andc t
)
216 (define-var-binop logandc2
2 andc
)
217 (define-var-binop logior
2 or
)
218 (define-var-binop logorc1
2 orc t t
)
219 (define-var-binop logorc2
2 orc nil t
)
220 (define-var-binop logxor
2 xor
)
221 (define-var-binop logeqv
2 eqv nil t
)
222 (define-var-binop lognand
2 nand nil t
)
223 (define-var-binop lognor
2 nor nil t
)
225 (define-const-binop + 4 addi
)
226 (define-const-binop -
4 subi
)
227 (define-const-logop logand
2 andi.
)
228 (define-const-logop logior
2 ori
)
229 (define-const-logop logxor
2 xori
)
232 ;;; Special case fixnum + and - that trap on overflow. Useful when we
233 ;;; don't know that the output type is a fixnum.
235 (define-vop (+/fixnum fast-
+/fixnum
=>fixnum
)
237 (:results
(r :scs
(any-reg descriptor-reg
)))
238 (:result-types tagged-num
)
239 (:note
"safe inline fixnum arithmetic")
241 (let* ((no-overflow (gen-label)))
244 (inst bns no-overflow
)
245 (inst unimp
(logior (ash (reg-tn-encoding r
) 5)
246 fixnum-additive-overflow-trap
))
247 (emit-label no-overflow
))))
250 (define-vop (-/fixnum fast--
/fixnum
=>fixnum
)
252 (:results
(r :scs
(any-reg descriptor-reg
)))
253 (:result-types tagged-num
)
254 (:note
"safe inline fixnum arithmetic")
256 (let* ((no-overflow (gen-label)))
259 (inst bns no-overflow
)
260 (inst unimp
(logior (ash (reg-tn-encoding r
) 5)
261 fixnum-additive-overflow-trap
))
262 (emit-label no-overflow
))))
264 (define-vop (fast-*/fixnum
=>fixnum fast-fixnum-binop
)
265 (:temporary
(:scs
(non-descriptor-reg)) temp
)
268 (inst srawi temp y
2)
269 (inst mullw r x temp
)))
271 (define-vop (fast-*-c
/fixnum
=>fixnum fast-fixnum-binop-c
)
273 (:arg-types tagged-num
274 (:constant
(and (signed-byte 16) (not (integer 0 0)))))
278 (define-vop (fast-*-bigc
/fixnum
=>fixnum fast-fixnum-binop-c
)
280 (:arg-types tagged-num
281 (:constant
(and fixnum
(not (signed-byte 16)))))
282 (:temporary
(:scs
(non-descriptor-reg)) temp
)
285 (inst mullw r x temp
)))
287 (define-vop (fast-*/signed
=>signed fast-signed-binop
)
292 (define-vop (fast-*-c
/signed
=>signed fast-signed-binop-c
)
297 (define-vop (fast-*/unsigned
=>unsigned fast-unsigned-binop
)
302 (define-vop (fast-*-c
/unsigned
=>unsigned fast-unsigned-binop-c
)
309 (macrolet ((def (name sc-type type result-type cost
)
313 (:args
(number :scs
(,sc-type
))
314 (amount :scs
(signed-reg unsigned-reg immediate
)))
315 (:arg-types
,type positive-fixnum
)
316 (:results
(result :scs
(,result-type
)))
317 (:result-types
,type
)
321 ((signed-reg unsigned-reg
)
322 (inst slw result number amount
))
324 (let ((amount (tn-value amount
)))
326 (inst slwi result number amount
))))))))
327 ;; FIXME: There's the opportunity for a sneaky optimization here, I
328 ;; think: a FAST-ASH-LEFT-C/FIXNUM=>SIGNED vop. -- CSR, 2003-09-03
329 (def fast-ash-left
/fixnum
=>fixnum any-reg tagged-num any-reg
2)
330 (def fast-ash-left
/signed
=>signed signed-reg signed-num signed-reg
3)
331 (def fast-ash-left
/unsigned
=>unsigned unsigned-reg unsigned-num unsigned-reg
3))
333 (define-vop (fast-ash/unsigned
=>unsigned
)
335 (:args
(number :scs
(unsigned-reg) :to
:save
)
336 (amount :scs
(signed-reg)))
337 (:arg-types
(:or unsigned-num
) signed-num
)
338 (:results
(result :scs
(unsigned-reg)))
339 (:result-types unsigned-num
)
342 (:temporary
(:sc non-descriptor-reg
) ndesc
)
344 (let ((positive (gen-label))
346 (inst cmpwi amount
0)
347 (inst neg ndesc amount
)
349 (inst cmpwi ndesc
31)
350 (inst srw result number ndesc
)
352 (move result zero-tn
)
355 (emit-label positive
)
356 ;; The result-type assures us that this shift will not overflow.
357 (inst slw result number amount
)
361 (define-vop (fast-ash-c/unsigned
=>unsigned
)
362 (:note
"inline constant ASH")
363 (:args
(number :scs
(unsigned-reg)))
365 (:arg-types unsigned-num
(:constant integer
))
366 (:results
(result :scs
(unsigned-reg)))
367 (:result-types unsigned-num
)
372 ((and (minusp amount
) (< amount -
31)) (move result zero-tn
))
373 ((minusp amount
) (inst srwi result number
(- amount
)))
374 ;; possible because this is used in the modular version too
375 ((> amount
31) (move result zero-tn
))
376 (t (inst slwi result number amount
)))))
378 (define-vop (fast-ash/signed
=>signed
)
380 (:args
(number :scs
(signed-reg) :to
:save
)
381 (amount :scs
(signed-reg immediate
)))
382 (:arg-types
(:or signed-num
) signed-num
)
383 (:results
(result :scs
(signed-reg)))
384 (:result-types
(:or signed-num
))
387 (:temporary
(:sc non-descriptor-reg
) ndesc
)
391 (let ((positive (gen-label))
393 (inst cmpwi amount
0)
394 (inst neg ndesc amount
)
396 (inst cmpwi ndesc
31)
397 (inst sraw result number ndesc
)
399 (inst srawi result number
31)
402 (emit-label positive
)
403 ;; The result-type assures us that this shift will not overflow.
404 (inst slw result number amount
)
409 (let ((amount (tn-value amount
)))
411 (let ((amount (min 31 (- amount
))))
412 (inst srawi result number amount
))
413 (inst slwi result number amount
)))))))
417 (define-vop (signed-byte-32-len)
418 (:translate integer-length
)
419 (:note
"inline (signed-byte 32) integer-length")
421 (:args
(arg :scs
(signed-reg)))
422 (:arg-types signed-num
)
423 (:results
(res :scs
(any-reg)))
424 (:result-types positive-fixnum
)
425 (:temporary
(:scs
(non-descriptor-reg) :to
(:argument
0)) shift
)
427 ; (integer-length arg) = (- 32 (cntlz (if (>= arg 0) arg (lognot arg))))
428 (let ((nonneg (gen-label)))
429 (inst cntlzw. shift arg
)
432 (inst cntlzw shift shift
)
434 (inst slwi shift shift
2)
435 (inst subfic res shift
(fixnumize 32)))))
437 (define-vop (unsigned-byte-32-count)
438 (:translate logcount
)
439 (:note
"inline (unsigned-byte 32) logcount")
441 (:args
(arg :scs
(unsigned-reg) :target shift
))
442 (:arg-types unsigned-num
)
443 (:results
(res :scs
(any-reg)))
444 (:result-types positive-fixnum
)
445 (:temporary
(:scs
(non-descriptor-reg) :from
(:argument
0)) shift temp
)
447 (let ((loop (gen-label))
449 (inst add. shift zero-tn arg
)
454 (inst subi temp shift
1)
455 (inst and. shift shift temp
)
456 (inst addi res res
(fixnumize 1))
462 ;;;; Modular functions:
463 (define-modular-fun lognot-mod32
(x) lognot
32)
464 (define-vop (lognot-mod32/unsigned
=>unsigned
)
465 (:translate lognot-mod32
)
466 (:args
(x :scs
(unsigned-reg)))
467 (:arg-types unsigned-num
)
468 (:results
(res :scs
(unsigned-reg)))
469 (:result-types unsigned-num
)
474 (define-vop (fast-ash-left-mod32-c/unsigned
=>unsigned
475 fast-ash-c
/unsigned
=>unsigned
)
476 (:translate ash-left-mod32
))
478 (define-vop (fast-ash-left-mod32/unsigned
=>unsigned
479 fast-ash-left
/unsigned
=>unsigned
))
480 (deftransform ash-left-mod32
((integer count
)
481 ((unsigned-byte 32) (unsigned-byte 5)))
482 (when (sb!c
::constant-lvar-p count
)
483 (sb!c
::give-up-ir1-transform
))
484 '(%primitive fast-ash-left-mod32
/unsigned
=>unsigned integer count
))
487 ((define-modular-backend (fun &optional constantp
)
488 (let ((mfun-name (symbolicate fun
'-mod32
))
489 (modvop (symbolicate 'fast- fun
'-mod32
/unsigned
=>unsigned
))
490 (modcvop (symbolicate 'fast- fun
'mod32-c
/unsigned
=>unsigned
))
491 (vop (symbolicate 'fast- fun
'/unsigned
=>unsigned
))
492 (cvop (symbolicate 'fast- fun
'-c
/unsigned
=>unsigned
)))
494 (define-modular-fun ,mfun-name
(x y
) ,fun
32)
495 (define-vop (,modvop
,vop
)
496 (:translate
,mfun-name
))
498 `((define-vop (,modcvop
,cvop
)
499 (:translate
,mfun-name
))))))))
500 (define-modular-backend + t
)
501 (define-modular-backend - t
)
502 (define-modular-backend * t
)
503 (define-modular-backend logxor t
)
504 (define-modular-backend logeqv
)
505 (define-modular-backend lognand
)
506 (define-modular-backend lognor
)
507 (define-modular-backend logandc1
)
508 (define-modular-backend logandc2
)
509 (define-modular-backend logorc1
)
510 (define-modular-backend logorc2
))
512 ;;;; Binary conditional VOPs:
514 (define-vop (fast-conditional)
519 (:policy
:fast-safe
))
521 (define-vop (fast-conditional/fixnum fast-conditional
)
522 (:args
(x :scs
(any-reg zero
))
523 (y :scs
(any-reg zero
)))
524 (:arg-types tagged-num tagged-num
)
525 (:note
"inline fixnum comparison"))
527 (define-vop (fast-conditional-c/fixnum fast-conditional
/fixnum
)
528 (:args
(x :scs
(any-reg zero
)))
529 (:arg-types tagged-num
(:constant
(signed-byte 14)))
530 (:info target not-p y
))
532 (define-vop (fast-conditional/signed fast-conditional
)
533 (:args
(x :scs
(signed-reg zero
))
534 (y :scs
(signed-reg zero
)))
535 (:arg-types signed-num signed-num
)
536 (:note
"inline (signed-byte 32) comparison"))
538 (define-vop (fast-conditional-c/signed fast-conditional
/signed
)
539 (:args
(x :scs
(signed-reg zero
)))
540 (:arg-types signed-num
(:constant
(signed-byte 16)))
541 (:info target not-p y
))
543 (define-vop (fast-conditional/unsigned fast-conditional
)
544 (:args
(x :scs
(unsigned-reg zero
))
545 (y :scs
(unsigned-reg zero
)))
546 (:arg-types unsigned-num unsigned-num
)
547 (:note
"inline (unsigned-byte 32) comparison"))
549 (define-vop (fast-conditional-c/unsigned fast-conditional
/unsigned
)
550 (:args
(x :scs
(unsigned-reg zero
)))
551 (:arg-types unsigned-num
(:constant
(unsigned-byte 16)))
552 (:info target not-p y
))
555 (define-vop (fast-if-</fixnum fast-conditional
/fixnum
)
559 (inst b?
(if not-p
:ge
:lt
) target
)))
561 (define-vop (fast-if-<-c
/fixnum fast-conditional-c
/fixnum
)
564 (inst cmpwi x
(fixnumize y
))
565 (inst b?
(if not-p
:ge
:lt
) target
)))
567 (define-vop (fast-if-</signed fast-conditional
/signed
)
571 (inst b?
(if not-p
:ge
:lt
) target
)))
573 (define-vop (fast-if-<-c
/signed fast-conditional-c
/signed
)
577 (inst b?
(if not-p
:ge
:lt
) target
)))
579 (define-vop (fast-if-</unsigned fast-conditional
/unsigned
)
583 (inst b?
(if not-p
:ge
:lt
) target
)))
585 (define-vop (fast-if-<-c
/unsigned fast-conditional-c
/unsigned
)
589 (inst b?
(if not-p
:ge
:lt
) target
)))
591 (define-vop (fast-if->/fixnum fast-conditional
/fixnum
)
595 (inst b?
(if not-p
:le
:gt
) target
)))
597 (define-vop (fast-if->-c
/fixnum fast-conditional-c
/fixnum
)
600 (inst cmpwi x
(fixnumize y
))
601 (inst b?
(if not-p
:le
:gt
) target
)))
603 (define-vop (fast-if->/signed fast-conditional
/signed
)
607 (inst b?
(if not-p
:le
:gt
) target
)))
609 (define-vop (fast-if->-c
/signed fast-conditional-c
/signed
)
613 (inst b?
(if not-p
:le
:gt
) target
)))
615 (define-vop (fast-if->/unsigned fast-conditional
/unsigned
)
619 (inst b?
(if not-p
:le
:gt
) target
)))
621 (define-vop (fast-if->-c
/unsigned fast-conditional-c
/unsigned
)
625 (inst b?
(if not-p
:le
:gt
) target
)))
627 (define-vop (fast-if-eql/signed fast-conditional
/signed
)
631 (inst b?
(if not-p
:ne
:eq
) target
)))
633 (define-vop (fast-if-eql-c/signed fast-conditional-c
/signed
)
637 (inst b?
(if not-p
:ne
:eq
) target
)))
639 (define-vop (fast-if-eql/unsigned fast-conditional
/unsigned
)
643 (inst b?
(if not-p
:ne
:eq
) target
)))
645 (define-vop (fast-if-eql-c/unsigned fast-conditional-c
/unsigned
)
649 (inst b?
(if not-p
:ne
:eq
) target
)))
652 ;;; EQL/FIXNUM is funny because the first arg can be of any type, not just a
655 ;;; These versions specify a fixnum restriction on their first arg. We have
656 ;;; also generic-eql/fixnum VOPs which are the same, but have no restriction on
657 ;;; the first arg and a higher cost. The reason for doing this is to prevent
658 ;;; fixnum specific operations from being used on word integers, spuriously
659 ;;; consing the argument.
662 (define-vop (fast-eql/fixnum fast-conditional
)
663 (:args
(x :scs
(any-reg descriptor-reg zero
))
664 (y :scs
(any-reg zero
)))
665 (:arg-types tagged-num tagged-num
)
666 (:note
"inline fixnum comparison")
670 (inst b?
(if not-p
:ne
:eq
) target
)))
672 (define-vop (generic-eql/fixnum fast-eql
/fixnum
)
673 (:arg-types
* tagged-num
)
676 (define-vop (fast-eql-c/fixnum fast-conditional
/fixnum
)
677 (:args
(x :scs
(any-reg descriptor-reg zero
)))
678 (:arg-types tagged-num
(:constant
(signed-byte 14)))
679 (:info target not-p y
)
682 (inst cmpwi x
(fixnumize y
))
683 (inst b?
(if not-p
:ne
:eq
) target
)))
685 (define-vop (generic-eql-c/fixnum fast-eql-c
/fixnum
)
686 (:arg-types
* (:constant
(signed-byte 11)))
690 ;;;; 32-bit logical operations
692 (define-vop (merge-bits)
693 (:translate merge-bits
)
694 (:args
(shift :scs
(signed-reg unsigned-reg
))
695 (prev :scs
(unsigned-reg))
696 (next :scs
(unsigned-reg)))
697 (:arg-types tagged-num unsigned-num unsigned-num
)
698 (:temporary
(:scs
(unsigned-reg) :to
(:result
0)) temp
)
699 (:temporary
(:scs
(unsigned-reg) :to
(:result
0) :target result
) res
)
700 (:results
(result :scs
(unsigned-reg)))
701 (:result-types unsigned-num
)
704 (let ((done (gen-label)))
707 (inst srw res next shift
)
708 (inst sub temp zero-tn shift
)
709 (inst slw temp prev temp
)
710 (inst or res res temp
)
714 (define-vop (shift-towards-someplace)
716 (:args
(num :scs
(unsigned-reg))
717 (amount :scs
(signed-reg)))
718 (:arg-types unsigned-num tagged-num
)
719 (:results
(r :scs
(unsigned-reg)))
720 (:result-types unsigned-num
))
722 (define-vop (shift-towards-start shift-towards-someplace
)
723 (:translate shift-towards-start
)
724 (:note
"shift-towards-start")
726 (inst rlwinm amount amount
0 27 31)
727 (inst slw r num amount
)))
729 (define-vop (shift-towards-end shift-towards-someplace
)
730 (:translate shift-towards-end
)
731 (:note
"shift-towards-end")
733 (inst rlwinm amount amount
0 27 31)
734 (inst srw r num amount
)))
738 (define-vop (bignum-length get-header-data
)
739 (:translate sb
!bignum
:%bignum-length
)
740 (:policy
:fast-safe
))
742 (define-vop (bignum-set-length set-header-data
)
743 (:translate sb
!bignum
:%bignum-set-length
)
744 (:policy
:fast-safe
))
746 (define-vop (bignum-ref word-index-ref
)
747 (:variant bignum-digits-offset other-pointer-lowtag
)
748 (:translate sb
!bignum
:%bignum-ref
)
749 (:results
(value :scs
(unsigned-reg)))
750 (:result-types unsigned-num
))
752 (define-vop (bignum-set word-index-set
)
753 (:variant bignum-digits-offset other-pointer-lowtag
)
754 (:translate sb
!bignum
:%bignum-set
)
755 (:args
(object :scs
(descriptor-reg))
756 (index :scs
(any-reg immediate zero
))
757 (value :scs
(unsigned-reg)))
758 (:arg-types t positive-fixnum unsigned-num
)
759 (:results
(result :scs
(unsigned-reg)))
760 (:result-types unsigned-num
))
762 (define-vop (digit-0-or-plus)
763 (:translate sb
!bignum
:%digit-0-or-plusp
)
765 (:args
(digit :scs
(unsigned-reg)))
766 (:arg-types unsigned-num
)
767 (:results
(result :scs
(descriptor-reg)))
769 (let ((done (gen-label)))
771 (move result null-tn
)
773 (load-symbol result t
)
776 (define-vop (add-w/carry
)
777 (:translate sb
!bignum
:%add-with-carry
)
779 (:args
(a :scs
(unsigned-reg))
780 (b :scs
(unsigned-reg))
782 (:arg-types unsigned-num unsigned-num positive-fixnum
)
783 (:temporary
(:scs
(unsigned-reg)) temp
)
784 (:results
(result :scs
(unsigned-reg))
785 (carry :scs
(unsigned-reg)))
786 (:result-types unsigned-num positive-fixnum
)
788 (inst addic temp c -
1)
789 (inst adde result a b
)
790 (inst addze carry zero-tn
)))
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)) temp
)
800 (:results
(result :scs
(unsigned-reg))
801 (borrow :scs
(unsigned-reg)))
802 (:result-types unsigned-num positive-fixnum
)
804 (inst addic temp c -
1)
805 (inst sube result a b
)
806 (inst addze borrow zero-tn
)))
808 (define-vop (bignum-mult-and-add-3-arg)
809 (:translate sb
!bignum
:%multiply-and-add
)
811 (:args
(x :scs
(unsigned-reg))
812 (y :scs
(unsigned-reg))
813 (carry-in :scs
(unsigned-reg) :to
(:eval
1)))
814 (:arg-types unsigned-num unsigned-num unsigned-num
)
815 (:temporary
(:scs
(unsigned-reg) :to
(:result
0) :target hi
) hi-temp
)
816 (:temporary
(:scs
(unsigned-reg) :from
(:eval
0) :to
(:result
1)
818 (:results
(hi :scs
(unsigned-reg))
819 (lo :scs
(unsigned-reg)))
820 (:result-types unsigned-num unsigned-num
)
822 (inst mulhwu hi-temp x y
)
823 (inst mullw lo-temp x y
)
824 (inst addc lo lo-temp carry-in
)
825 (inst addze hi hi-temp
)))
827 (define-vop (bignum-mult-and-add-4-arg)
828 (:translate sb
!bignum
:%multiply-and-add
)
830 (:args
(x :scs
(unsigned-reg))
831 (y :scs
(unsigned-reg))
832 (prev :scs
(unsigned-reg) :to
(:eval
1))
833 (carry-in :scs
(unsigned-reg) :to
(:eval
1)))
834 (:arg-types unsigned-num unsigned-num unsigned-num unsigned-num
)
835 (:temporary
(:scs
(unsigned-reg) :to
(:result
0) :target hi
) hi-temp
)
836 (:temporary
(:scs
(unsigned-reg) :from
(:eval
0) :to
(:result
1)
838 (:results
(hi :scs
(unsigned-reg))
839 (lo :scs
(unsigned-reg)))
840 (:result-types unsigned-num unsigned-num
)
842 (inst mulhwu hi-temp x y
)
843 (inst mullw lo-temp x y
)
844 (inst addc lo-temp lo-temp carry-in
)
845 (inst addze hi-temp hi-temp
)
846 (inst addc lo lo-temp prev
)
847 (inst addze hi hi-temp
)))
849 (define-vop (bignum-mult)
850 (:translate sb
!bignum
:%multiply
)
852 (:args
(x :scs
(unsigned-reg) :to
(:eval
1))
853 (y :scs
(unsigned-reg) :to
(:eval
1)))
854 (:arg-types unsigned-num unsigned-num
)
855 (:results
(hi :scs
(unsigned-reg) :from
(:eval
1))
856 (lo :scs
(unsigned-reg) :from
(:eval
0)))
857 (:result-types unsigned-num unsigned-num
)
860 (inst mulhwu hi x y
)))
862 (define-vop (bignum-lognot lognot-mod32
/unsigned
=>unsigned
)
863 (:translate sb
!bignum
:%lognot
))
865 (define-vop (fixnum-to-digit)
866 (:translate sb
!bignum
:%fixnum-to-digit
)
868 (:args
(fixnum :scs
(any-reg)))
869 (:arg-types tagged-num
)
870 (:results
(digit :scs
(unsigned-reg)))
871 (:result-types unsigned-num
)
873 (inst srawi digit fixnum
2)))
876 (define-vop (bignum-floor)
877 (:translate sb
!bignum
:%floor
)
879 (:args
(num-high :scs
(unsigned-reg) :target rem
)
880 (num-low :scs
(unsigned-reg) :target rem-low
)
881 (denom :scs
(unsigned-reg) :to
(:eval
1)))
882 (:arg-types unsigned-num unsigned-num unsigned-num
)
883 (:temporary
(:scs
(unsigned-reg) :from
(:argument
1)) rem-low
)
884 (:temporary
(:scs
(unsigned-reg) :from
(:eval
0)) temp
)
885 (:results
(quo :scs
(unsigned-reg) :from
(:eval
0))
886 (rem :scs
(unsigned-reg) :from
(:argument
0)))
887 (:result-types unsigned-num unsigned-num
)
888 (:generator
325 ; number of inst assuming targeting works.
890 (move rem-low num-low
)
891 (flet ((maybe-subtract (&optional
(guess temp
))
892 (inst subi temp guess
1)
893 (inst and temp temp denom
)
894 (inst sub rem rem temp
))
897 (inst subfe res res res
)
902 (inst slwi rem rem
1)
903 (inst srwi temp rem-low
31)
904 (inst or rem rem temp
)
905 (inst slwi rem-low rem-low
1)
906 (sltu temp rem denom
)
907 (inst slwi quo quo
1)
908 (inst or quo quo temp
)
914 (define-vop (bignum-floor)
915 (:translate sb
!bignum
:%floor
)
917 (:args
(div-high :scs
(unsigned-reg) :target rem
)
918 (div-low :scs
(unsigned-reg) :target quo
)
919 (divisor :scs
(unsigned-reg)))
920 (:arg-types unsigned-num unsigned-num unsigned-num
)
921 (:results
(quo :scs
(unsigned-reg) :from
(:argument
1))
922 (rem :scs
(unsigned-reg) :from
(:argument
0)))
923 (:result-types unsigned-num unsigned-num
)
926 (inst div quo div-high divisor
)
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 slwi res digit
2))
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 sraw result digit count
)))
956 (define-vop (digit-lshr digit-ashr
)
957 (:translate sb
!bignum
:%digit-logical-shift-right
)
959 (inst srw result digit count
)))
961 (define-vop (digit-ashl digit-ashr
)
962 (:translate sb
!bignum
:%ashl
)
964 (inst slw result digit count
)))
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
)
989 (define-static-fun two-arg-eqv
(x y
) :translate logeqv
)
993 (deftransform * ((x y
)
994 ((unsigned-byte 32) (constant-arg (unsigned-byte 32)))
996 "recode as shifts and adds"
997 (let ((y (lvar-value y
)))
998 (multiple-value-bind (result adds shifts
)
999 (ub32-strength-reduce-constant-multiply 'x y
)
1001 ((typep y
'(signed-byte 16))
1002 ;; a mulli instruction has a latency of 5.
1003 (when (> (+ adds shifts
) 4)
1004 (give-up-ir1-transform)))
1006 ;; a mullw instruction also has a latency of 5, plus two
1007 ;; instructions (in general) to load the immediate into a
1009 (when (> (+ adds shifts
) 6)
1010 (give-up-ir1-transform))))