1 ;;;; the VM definition arithmetic VOPs for the ARM
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 64) arithmetic")
32 (:arg-types signed-num
)
33 (:result-types signed-num
))
35 (define-vop (unsigned-unop fast-safe-arith-op
)
36 (:args
(x :scs
(unsigned-reg)))
37 (:results
(res :scs
(unsigned-reg)))
38 (:note
"inline (unsigned-byte 64) arithmetic")
39 (:arg-types unsigned-num
)
40 (:result-types unsigned-num
))
42 (define-vop (fast-negate/fixnum fixnum-unop
)
47 (define-vop (fast-negate/signed signed-unop
)
52 (define-vop (fast-negate/unsigned signed-unop
)
53 (:args
(x :scs
(unsigned-reg) :target res
))
54 (:arg-types unsigned-num
)
59 (define-vop (fast-lognot/fixnum fixnum-unop
)
60 (:args
(x :scs
(any-reg)))
61 (:arg-types tagged-num
)
64 (inst eor res x
(lognot n-fixnum-tag-bits
))))
66 (define-vop (fast-lognot/signed signed-unop
)
72 ;;;; Binary fixnum operations.
74 ;;; Assume that any constant operand is the second arg...
76 (define-vop (fast-fixnum-binop fast-safe-arith-op
)
77 (:args
(x :target r
:scs
(any-reg))
78 (y :target r
:scs
(any-reg)))
79 (:arg-types tagged-num tagged-num
)
80 (:results
(r :scs
(any-reg)))
81 (:result-types tagged-num
)
82 (:note
"inline fixnum arithmetic"))
84 (define-vop (fast-unsigned-binop fast-safe-arith-op
)
85 (:args
(x :target r
:scs
(unsigned-reg))
86 (y :target r
:scs
(unsigned-reg)))
87 (:arg-types unsigned-num unsigned-num
)
88 (:results
(r :scs
(unsigned-reg)))
89 (:result-types unsigned-num
)
90 (:note
"inline (unsigned-byte 64) arithmetic"))
92 (define-vop (fast-signed-binop fast-safe-arith-op
)
93 (:args
(x :target r
:scs
(signed-reg))
94 (y :target r
:scs
(signed-reg)))
95 (:arg-types signed-num signed-num
)
96 (:results
(r :scs
(signed-reg)))
97 (:result-types signed-num
)
98 (:note
"inline (signed-byte 64) arithmetic"))
100 (define-vop (fast-fixnum-binop-c fast-safe-arith-op
)
101 (:args
(x :target r
:scs
(any-reg)))
103 (:results
(r :scs
(any-reg)))
104 (:result-types tagged-num
)
105 (:note
"inline fixnum arithmetic"))
107 (define-vop (fast-unsigned-binop-c fast-safe-arith-op
)
108 (:args
(x :target r
:scs
(unsigned-reg)))
110 (:results
(r :scs
(unsigned-reg)))
111 (:result-types unsigned-num
)
112 (:note
"inline (unsigned-byte 64) arithmetic"))
114 (define-vop (fast-signed-binop-c fast-safe-arith-op
)
115 (:args
(x :target r
:scs
(signed-reg)))
117 (:results
(r :scs
(signed-reg)))
118 (:result-types signed-num
)
119 (:note
"inline (signed-byte 64) arithmetic"))
121 (defun bic-encode-immediate (x)
122 (encode-logical-immediate (bic-mask x
)))
124 (defun bic-fixnum-encode-immediate (x)
126 (encode-logical-immediate (bic-mask (fixnumize x
)))))
128 (defmacro define-binop
(translate untagged-penalty op
130 (constant-test 'encode-logical-immediate
)
131 (constant-fixnum-test 'fixnum-encode-logical-immediate
)
134 (constant-transform 'identity
))
136 (define-vop (,(symbolicate 'fast- translate
'/fixnum
=>fixnum
)
138 (:translate
,translate
)
143 (define-vop (,(symbolicate 'fast- translate
'-c
/fixnum
=>fixnum
)
146 `(:arg-types
(:constant
(satisfies ,constant-fixnum-test
))
148 `(:arg-types tagged-num
149 (:constant
(satisfies ,constant-fixnum-test
))))
150 (:translate
,translate
)
152 (inst ,constant-op r x
(,constant-transform
(fixnumize y
)))))
153 (define-vop (,(symbolicate 'fast- translate
'/signed
=>signed
)
155 (:translate
,translate
)
156 (:generator
,(1+ untagged-penalty
)
160 (define-vop (,(symbolicate 'fast- translate
'-c
/signed
=>signed
)
162 (:translate
,translate
)
164 `(:arg-types
(:constant
(satisfies ,constant-test
))
166 `(:arg-types signed-num
167 (:constant
(satisfies ,constant-test
))))
168 (:generator
,untagged-penalty
169 (inst ,constant-op r x
(,constant-transform y
))))
170 (define-vop (,(symbolicate 'fast- translate
'/unsigned
=>unsigned
)
172 (:translate
,translate
)
173 (:generator
,(1+ untagged-penalty
)
177 (define-vop (,(symbolicate 'fast- translate
'-c
/unsigned
=>unsigned
)
178 fast-unsigned-binop-c
)
179 (:translate
,translate
)
181 `(:arg-types
(:constant
(satisfies ,constant-test
))
183 `(:arg-types unsigned-num
184 (:constant
(satisfies ,constant-test
))))
185 (:generator
,untagged-penalty
186 (inst ,constant-op r x
(,constant-transform y
))))))
188 (define-binop + 4 add
:constant-test add-sub-immediate-p
:constant-fixnum-test fixnum-add-sub-immediate-p
)
189 (define-binop -
4 sub
:constant-test add-sub-immediate-p
:constant-fixnum-test fixnum-add-sub-immediate-p
)
190 (define-binop logand
2 and
)
191 (define-binop logior
2 orr
)
192 (define-binop logxor
2 eor
)
194 (define-binop logandc1
2 bic
:swap t
195 :constant-test bic-encode-immediate
196 :constant-fixnum-test bic-fixnum-encode-immediate
198 :constant-transform bic-mask
)
199 (define-binop logandc2
2 bic
200 :constant-test bic-encode-immediate
201 :constant-fixnum-test bic-fixnum-encode-immediate
203 :constant-transform bic-mask
)
205 ;; (define-binop logorc1 2 orn :swap t
206 ;; :constant-test bic-encode-immediate
207 ;; :constant-fixnum-test bic-fixnum-encode-immediate
209 ;; :constant-transform bic-mask)
210 ;; (define-binop logorc2 2 orn
211 ;; :constant-test bic-encode-immediate
212 ;; :constant-fixnum-test bic-fixnum-encode-immediate
214 ;; :constant-transform bic-mask)
216 (define-vop (fast-logior-unsigned-signed=>signed fast-safe-arith-op
)
217 (:args
(x :scs
(unsigned-reg))
218 (y :target r
:scs
(signed-reg)))
219 (:arg-types unsigned-num signed-num
)
220 (:results
(r :scs
(signed-reg) :from
(:argument
1)))
221 (:result-types signed-num
)
222 (:note
"inline (unsigned-byte 64) arithmetic")
227 (define-vop (fast-logior-signed-unsigned=>signed fast-safe-arith-op
)
228 (:args
(x :target r
:scs
(signed-reg))
229 (y :scs
(unsigned-reg)))
230 (:arg-types signed-num unsigned-num
)
231 (:results
(r :scs
(signed-reg) :from
(:argument
0)))
232 (:result-types signed-num
)
233 (:note
"inline (unsigned-byte 64) arithmetic")
240 (define-vop (fast-*/fixnum
=>fixnum fast-fixnum-binop
)
241 (:args
(x :scs
(signed-reg)) ;; one operand needs to be untagged
242 (y :target r
:scs
(any-reg)))
247 (define-vop (fast-*/signed
=>signed fast-signed-binop
)
252 (define-vop (fast-*/unsigned
=>unsigned fast-unsigned-binop
)
258 (define-vop (fast-truncate/signed
=>signed fast-safe-arith-op
)
259 (:translate truncate
)
260 (:args
(x :scs
(signed-reg) :to
:result
)
261 (y :scs
(signed-reg) :to
:result
))
262 (:arg-types signed-num signed-num
)
263 (:results
(quo :scs
(signed-reg) :from
:eval
)
264 (rem :scs
(signed-reg) :from
:eval
))
265 (:result-types signed-num signed-num
)
266 (:note
"inline (signed-byte 64) arithmetic")
268 (:save-p
:compute-only
)
270 (let ((zero (generate-error-code vop
'division-by-zero-error x y
)))
273 (inst msub rem quo y x
)))
275 (define-vop (fast-truncate/unsigned
=>unsigned fast-safe-arith-op
)
276 (:translate truncate
)
277 (:args
(x :scs
(unsigned-reg) :to
:result
)
278 (y :scs
(unsigned-reg) :to
:result
))
279 (:arg-types unsigned-num unsigned-num
)
280 (:results
(quo :scs
(unsigned-reg) :from
:eval
)
281 (rem :scs
(unsigned-reg) :from
:eval
))
282 (:result-types unsigned-num unsigned-num
)
283 (:note
"inline (unsigned-byte 64) arithmetic")
285 (:save-p
:compute-only
)
287 (let ((zero (generate-error-code vop
'division-by-zero-error x y
)))
290 (inst msub rem quo y x
)))
293 (define-vop (fast-lognor/fixnum
=>fixnum fast-fixnum-binop
)
295 (:args
(x :scs
(any-reg))
299 (inst eor r r
(lognot fixnum-tag-mask
))))
301 (define-vop (fast-logand/signed-unsigned
=>unsigned fast-logand
/unsigned
=>unsigned
)
302 (:args
(x :scs
(signed-reg) :target r
)
303 (y :scs
(unsigned-reg) :target r
))
304 (:arg-types signed-num unsigned-num
)
307 (define-source-transform logeqv
(&rest args
)
308 (if (oddp (length args
))
310 `(lognot (logxor ,@args
))))
311 (define-source-transform logorc1
(x y
)
312 `(logior (lognot ,x
) ,y
))
313 (define-source-transform logorc2
(x y
)
314 `(logior ,x
(lognot ,y
)))
318 (define-vop (fast-ash-left-c/fixnum
=>fixnum
)
321 (:args
(number :scs
(any-reg) :target result
))
323 (:arg-types tagged-num
(:constant unsigned-byte
))
324 (:results
(result :scs
(any-reg)))
325 (:result-types tagged-num
)
329 (inst lsl result number amount
)
330 (inst mov result
0))))
332 (define-vop (fast-ash-right-c/fixnum
=>fixnum
)
335 (:args
(number :scs
(any-reg) :target result
))
337 (:arg-types tagged-num
(:constant
(integer * -
1)))
338 (:results
(result :scs
(any-reg)))
339 (:result-types tagged-num
)
340 (:temporary
(:sc unsigned-reg
:target result
) temp
)
343 (inst asr temp number
(min (- amount
) 63))
344 (inst and result temp
(bic-mask fixnum-tag-mask
))))
346 (define-vop (fast-ash-c/unsigned
=>unsigned
)
349 (:args
(number :scs
(unsigned-reg) :target result
))
351 (:arg-types unsigned-num
(:constant integer
))
352 (:results
(result :scs
(unsigned-reg)))
353 (:result-types unsigned-num
)
356 (cond ((< -
64 amount
64)
358 (inst lsl result number amount
)
359 (inst lsr result number
(- amount
))))
361 (inst mov result
0)))))
363 (define-vop (fast-ash-c/signed
=>signed
)
366 (:args
(number :scs
(signed-reg) :target result
))
368 (:arg-types signed-num
(:constant integer
))
369 (:results
(result :scs
(signed-reg)))
370 (:result-types signed-num
)
373 (cond ((< -
64 amount
64)
375 (inst lsl result number amount
)
376 (inst asr result number
(- amount
))))
378 (inst mov result
0)))))
380 (define-vop (fast-ash/signed
/unsigned
)
386 (:temporary
(:sc non-descriptor-reg
) temp
)
387 (:variant-vars variant
)
393 (inst cmp temp n-word-bits
)
395 (inst mov temp
(1- n-word-bits
))
398 (:signed
(inst asr result number temp
))
399 (:unsigned
(inst lsr result number temp
)))
402 (inst cmp temp n-word-bits
)
404 (inst mov temp
(1- n-word-bits
))
406 (inst lsl result number temp
)
409 (define-vop (fast-ash/signed
=>signed fast-ash
/signed
/unsigned
)
410 (:args
(number :scs
(signed-reg) :to
:save
)
411 (amount :scs
(signed-reg) :to
:save
:target temp
))
412 (:arg-types signed-num signed-num
)
413 (:results
(result :scs
(signed-reg)))
414 (:result-types signed-num
)
418 (define-vop (fast-ash/unsigned
=>unsigned fast-ash
/signed
/unsigned
)
419 (:args
(number :scs
(unsigned-reg) :to
:save
)
420 (amount :scs
(signed-reg) :to
:save
))
421 (:arg-types unsigned-num signed-num
)
422 (:results
(result :scs
(unsigned-reg)))
423 (:result-types unsigned-num
)
425 (:variant
:unsigned
))
427 (macrolet ((def (name sc-type type result-type cost
)
431 (:args
(number :scs
(,sc-type
))
432 (amount :scs
(signed-reg unsigned-reg
)))
433 ;; For modular variants
435 (:arg-types
,type positive-fixnum
)
436 (:results
(result :scs
(,result-type
)))
437 (:result-types
,type
)
440 (let ((amount (cond (cut
441 (inst cmp amount n-word-bits
)
442 ;; Only the first 6 bits count for shifts.
443 ;; This sets all bits to 1 if AMOUNT is larger than 63,
444 ;; cutting the amount to 63.
445 (inst csinv tmp-tn amount zr-tn
:lt
)
449 (inst lsl result number amount
))))))
450 ;; FIXME: There's the opportunity for a sneaky optimization here, I
451 ;; think: a FAST-ASH-LEFT-C/FIXNUM=>SIGNED vop. -- CSR, 2003-09-03
452 (def fast-ash-left
/fixnum
=>fixnum any-reg tagged-num any-reg
2)
453 (def fast-ash-left
/signed
=>signed signed-reg signed-num signed-reg
3)
454 (def fast-ash-left
/unsigned
=>unsigned unsigned-reg unsigned-num unsigned-reg
3))
457 (define-vop (fast-%ash
/right
/unsigned
)
458 (:translate %ash
/right
)
460 (:args
(number :scs
(unsigned-reg) :target result
)
461 (amount :scs
(unsigned-reg)))
462 (:arg-types unsigned-num unsigned-num
)
463 (:results
(result :scs
(unsigned-reg) :from
(:argument
0)))
464 (:result-types unsigned-num
)
466 (inst lsr result number amount
)))
469 (define-vop (fast-%ash
/right
/signed
)
470 (:translate %ash
/right
)
472 (:args
(number :scs
(signed-reg) :target result
)
473 (amount :scs
(unsigned-reg)))
474 (:arg-types signed-num unsigned-num
)
475 (:results
(result :scs
(signed-reg) :from
(:argument
0)))
476 (:result-types signed-num
)
478 (inst asr result number amount
)))
481 (define-vop (fast-%ash
/right
/fixnum
)
482 (:translate %ash
/right
)
484 (:args
(number :scs
(any-reg) :target result
)
485 (amount :scs
(unsigned-reg) :target temp
))
486 (:arg-types tagged-num unsigned-num
)
487 (:results
(result :scs
(any-reg) :from
(:argument
0)))
488 (:result-types tagged-num
)
489 (:temporary
(:sc unsigned-reg
:target result
) temp
)
491 (inst asr temp number amount
)
492 (inst and result temp
(bic-mask fixnum-tag-mask
))))
494 (define-vop (fast-ash-left-modfx/fixnum
=>fixnum
495 fast-ash-left
/fixnum
=>fixnum
)
497 (:translate ash-left-modfx
))
499 (define-vop (fast-ash-left-modfx-c/fixnum
=>fixnum
500 fast-ash-left-c
/fixnum
=>fixnum
)
501 (:translate ash-left-modfx
))
503 (define-vop (fast-ash-left-mod64-c/fixnum
=>fixnum
504 fast-ash-left-c
/fixnum
=>fixnum
)
505 (:translate ash-left-mod64
))
507 (define-vop (fast-ash-left-mod64/fixnum
=>fixnum
508 fast-ash-left
/fixnum
=>fixnum
)
510 (:translate ash-left-mod64
))
512 (define-vop (fast-ash-left-mod64/unsigned
=>unsigned
513 fast-ash-left
/unsigned
=>unsigned
)
515 (:translate ash-left-mod64
))
517 (define-vop (fast-ash-left-mod64-c/unsigned
=>unsigned
518 fast-ash-c
/unsigned
=>unsigned
)
519 (:translate ash-left-mod64
))
521 ;;; Only the lower 6 bits of the shift amount are significant.
522 (define-vop (shift-towards-someplace)
524 (:args
(num :scs
(unsigned-reg))
525 (amount :scs
(signed-reg)))
526 (:arg-types unsigned-num tagged-num
)
527 (:temporary
(:sc signed-reg
) temp
)
528 (:results
(r :scs
(unsigned-reg)))
529 (:result-types unsigned-num
))
531 (define-vop (shift-towards-start shift-towards-someplace
)
532 (:translate shift-towards-start
)
533 (:note
"SHIFT-TOWARDS-START")
535 (inst and temp amount
#b111111
)
536 (inst lsr r num temp
)))
538 (define-vop (shift-towards-end shift-towards-someplace
)
539 (:translate shift-towards-end
)
540 (:note
"SHIFT-TOWARDS-END")
542 (inst and temp amount
#b111111
)
543 (inst lsl r num temp
)))
545 (define-vop (signed-byte-64-len)
546 (:translate integer-length
)
547 (:note
"inline (signed-byte 64) integer-length")
549 (:args
(arg :scs
(signed-reg) :target temp
))
550 (:arg-types signed-num
)
551 (:results
(res :scs
(any-reg)))
552 (:result-types positive-fixnum
)
553 (:temporary
(:scs
(non-descriptor-reg) :from
(:argument
0)) temp
)
557 (inst csinv temp temp temp
:ge
)
559 (inst mov res
(fixnumize 64))
560 (inst sub res res
(lsl temp n-fixnum-tag-bits
))))
562 (define-vop (unsigned-byte-64-count)
563 (:translate logcount
)
564 (:note
"inline (unsigned-byte 64) logcount")
566 (:args
(arg :scs
(unsigned-reg) :target num
))
567 (:arg-types unsigned-num
)
568 (:results
(res :scs
(unsigned-reg)))
569 (:result-types positive-fixnum
)
570 (:temporary
(:scs
(non-descriptor-reg) :from
(:argument
0) :to
(:result
0)
572 (:temporary
(:scs
(non-descriptor-reg)) mask temp
)
575 (load-immediate-word mask
#x5555555555555555
)
576 (inst and temp mask
(lsr num
1))
577 (inst and num num mask
)
578 (inst add num num temp
)
579 (load-immediate-word mask
#x3333333333333333
)
580 (inst and temp mask
(lsr num
2))
581 (inst and num num mask
)
582 (inst add num num temp
)
583 (load-immediate-word mask
#x0f0f0f0f0f0f0f0f
)
584 (inst and temp mask
(lsr num
4))
585 (inst and num num mask
)
586 (inst add num num temp
)
587 (inst add num num
(lsr num
8))
588 (inst add num num
(lsr num
16))
589 (inst add num num
(lsr num
32))
590 (inst and res num
#xff
)))
592 (defknown %%ldb
(integer unsigned-byte unsigned-byte
) unsigned-byte
593 (movable foldable flushable always-translatable
))
595 (defknown %%dpb
(integer unsigned-byte unsigned-byte integer
) integer
596 (movable foldable flushable always-translatable
))
599 (defun %%ldb
(integer size posn
)
600 (%ldb size posn integer
))
602 (defun %%dpb
(newbyte integer size posn
)
603 (%dpb newbyte size posn integer
))
605 (define-vop (ldb-c/fixnum
)
607 (:args
(x :scs
(any-reg)))
608 (:arg-types tagged-num
609 (:constant integer
) (:constant integer
))
611 (:results
(res :scs
(unsigned-reg)))
612 (:result-types unsigned-num
)
615 (inst ubfm res x
(1+ posn
) (+ posn size
))))
619 (:args
(x :scs
(unsigned-reg signed-reg
)))
620 (:arg-types
(:or unsigned-num signed-num
)
621 (:constant integer
) (:constant integer
))
623 (:results
(res :scs
(unsigned-reg)))
624 (:result-types unsigned-num
)
627 (inst ubfm res x posn
(+ posn size -
1))))
629 (define-vop (dpb-c/fixnum
)
631 (:args
(x :scs
(signed-reg) :to
:save
)
633 (:arg-types signed-num
634 (:constant integer
) (:constant integer
)
637 (:results
(res :scs
(any-reg)))
638 (:result-types tagged-num
)
642 (inst bfm res x
(- (1- n-word-bits
) posn
) (1- size
))))
644 (define-vop (dpb-c/signed
)
646 (:args
(x :scs
(signed-reg) :to
:save
)
647 (y :scs
(signed-reg)))
648 (:arg-types signed-num
649 (:constant integer
) (:constant integer
)
652 (:results
(res :scs
(signed-reg)))
653 (:result-types signed-num
)
657 (inst bfm res x
(- n-word-bits posn
) (1- size
))))
659 (define-vop (dpb-c/unsigned
)
661 (:args
(x :scs
(unsigned-reg) :to
:save
)
662 (y :scs
(unsigned-reg)))
663 (:arg-types unsigned-num
664 (:constant integer
) (:constant integer
)
667 (:results
(res :scs
(unsigned-reg)))
668 (:result-types unsigned-num
)
672 (inst bfm res x
(- n-word-bits posn
) (1- size
))))
674 ;;; Modular functions
675 (define-modular-fun lognot-mod64
(x) lognot
:untagged nil
64)
676 (define-vop (lognot-mod64/unsigned
=>unsigned
)
677 (:translate lognot-mod64
)
678 (:args
(x :scs
(unsigned-reg)))
679 (:arg-types unsigned-num
)
680 (:results
(res :scs
(unsigned-reg)))
681 (:result-types unsigned-num
)
686 (defmacro define-mod-binop
((name prototype
) function
)
687 `(define-vop (,name
,prototype
)
688 (:args
(x :target r
:scs
(unsigned-reg signed-reg
))
689 (y :scs
(unsigned-reg signed-reg
)))
690 (:arg-types untagged-num untagged-num
)
691 (:results
(r :scs
(unsigned-reg signed-reg
) :from
(:argument
0)))
692 (:result-types unsigned-num
)
693 (:translate
,function
)))
695 (defmacro define-mod-binop-c
((name prototype
) function
)
696 `(define-vop (,name
,prototype
)
697 (:args
(x :target r
:scs
(unsigned-reg signed-reg
)))
699 (:arg-types untagged-num
(:constant
(or word
701 (:results
(r :scs
(unsigned-reg signed-reg
) :from
(:argument
0)))
702 (:result-types unsigned-num
)
703 (:translate
,function
)))
705 (macrolet ((def (name -c-p
)
706 (let ((fun64 (intern (format nil
"~S-MOD64" name
)))
707 (vopu (intern (format nil
"FAST-~S/UNSIGNED=>UNSIGNED" name
)))
708 (vopcu (intern (format nil
"FAST-~S-C/UNSIGNED=>UNSIGNED" name
)))
709 (vopf (intern (format nil
"FAST-~S/FIXNUM=>FIXNUM" name
)))
710 (vopcf (intern (format nil
"FAST-~S-C/FIXNUM=>FIXNUM" name
)))
711 (vop64u (intern (format nil
"FAST-~S-MOD64/WORD=>UNSIGNED" name
)))
712 (vop64f (intern (format nil
"FAST-~S-MOD64/FIXNUM=>FIXNUM" name
)))
713 (vop64cu (intern (format nil
"FAST-~S-MOD64-C/WORD=>UNSIGNED" name
)))
714 (funfx (intern (format nil
"~S-MODFX" name
)))
715 (vopfxf (intern (format nil
"FAST-~S-MODFX/FIXNUM=>FIXNUM" name
)))
716 (vopfxcf (intern (format nil
"FAST-~S-MODFX-C/FIXNUM=>FIXNUM" name
))))
718 (define-modular-fun ,fun64
(x y
) ,name
:untagged nil
64)
719 (define-modular-fun ,funfx
(x y
) ,name
:tagged t
720 #.
(- n-word-bits n-fixnum-tag-bits
))
721 (define-mod-binop (,vop64u
,vopu
) ,fun64
)
722 (define-vop (,vop64f
,vopf
) (:translate
,fun64
))
723 (define-vop (,vopfxf
,vopf
) (:translate
,funfx
))
725 `((define-mod-binop-c (,vop64cu
,vopcu
) ,fun64
)
726 (define-vop (,vopfxcf
,vopcf
) (:translate
,funfx
))))))))
731 ;;;; Binary conditional VOPs:
733 (define-vop (fast-conditional)
737 (:policy
:fast-safe
))
739 (define-vop (fast-conditional/fixnum fast-conditional
)
740 (:args
(x :scs
(any-reg))
742 (:arg-types tagged-num tagged-num
)
743 (:note
"inline fixnum comparison"))
745 (define-vop (fast-conditional-c/fixnum fast-conditional
/fixnum
)
746 (:args
(x :scs
(any-reg)))
747 (:arg-types tagged-num
(:constant
(satisfies fixnum-add-sub-immediate-p
)))
750 (define-vop (fast-conditional/signed fast-conditional
)
751 (:args
(x :scs
(signed-reg))
752 (y :scs
(signed-reg)))
753 (:arg-types signed-num signed-num
)
754 (:note
"inline (signed-byte 64) comparison"))
756 (define-vop (fast-conditional-c/signed fast-conditional
/signed
)
757 (:args
(x :scs
(signed-reg)))
758 (:arg-types signed-num
(:constant
(satisfies add-sub-immediate-p
)))
761 (define-vop (fast-conditional/unsigned fast-conditional
)
762 (:args
(x :scs
(unsigned-reg))
763 (y :scs
(unsigned-reg)))
764 (:arg-types unsigned-num unsigned-num
)
765 (:note
"inline (unsigned-byte 64) comparison"))
767 (define-vop (fast-conditional-c/unsigned fast-conditional
/unsigned
)
768 (:args
(x :scs
(unsigned-reg)))
769 (:arg-types unsigned-num
(:constant
(satisfies add-sub-immediate-p
)))
772 (defmacro define-conditional-vop
(tran cond unsigned
)
774 ,@(mapcar (lambda (suffix cost signed
)
775 (unless (and (member suffix
'(/fixnum -c
/fixnum
))
777 `(define-vop (,(intern (format nil
"~:@(FAST-IF-~A~A~)"
780 (format nil
"~:@(FAST-CONDITIONAL~A~)"
783 (:conditional
,(if signed cond unsigned
))
786 ,(if (eq suffix
'-c
/fixnum
) '(fixnumize y
) 'y
))))))
787 '(/fixnum -c
/fixnum
/signed -c
/signed
/unsigned -c
/unsigned
)
789 '(t t t t nil nil
))))
791 (define-conditional-vop < :lt
:lo
)
792 (define-conditional-vop > :gt
:hi
)
793 (define-conditional-vop eql
:eq
:eq
)
795 ;;; EQL/FIXNUM is funny because the first arg can be of any type, not
796 ;;; just a known fixnum.
798 ;;; These versions specify a fixnum restriction on their first arg.
799 ;;; We have also generic-eql/fixnum VOPs which are the same, but have
800 ;;; no restriction on the first arg and a higher cost. The reason for
801 ;;; doing this is to prevent fixnum specific operations from being
802 ;;; used on word integers, spuriously consing the argument.
804 (define-vop (fast-eql/fixnum
)
805 (:args
(x :scs
(any-reg))
807 (:arg-types tagged-num tagged-num
)
808 (:note
"inline fixnum comparison")
815 (define-vop (generic-eql/fixnum fast-eql
/fixnum
)
816 (:args
(x :scs
(any-reg descriptor-reg
))
818 (:arg-types
* tagged-num
)
821 (define-vop (fast-eql-c/fixnum
)
822 (:args
(x :scs
(any-reg)))
823 (:arg-types tagged-num
(:constant
(satisfies fixnum-add-sub-immediate-p
)))
830 (inst cmn x
(fixnumize (abs y
)))
831 (inst cmp x
(fixnumize y
)))))
833 (define-vop (generic-eql-c/fixnum fast-eql-c
/fixnum
)
834 (:args
(x :scs
(any-reg descriptor-reg
)))
835 (:arg-types
* (:constant
(satisfies fixnum-add-sub-immediate-p
)))
838 ;; (macrolet ((define-logtest-vops ()
840 ;; ,@(loop for suffix in '(/fixnum -c/fixnum
842 ;; /unsigned -c/unsigned)
843 ;; for cost in '(4 3 6 5 6 5)
845 ;; `(define-vop (,(symbolicate "FAST-LOGTEST" suffix)
846 ;; ,(symbolicate "FAST-CONDITIONAL" suffix))
847 ;; (:translate logtest)
848 ;; (:conditional :ne)
854 ;; ((-c/signed -c/unsigned)
858 ;; (define-logtest-vops))
860 (define-source-transform lognand
(x y
)
861 `(lognot (logand ,x
,y
)))
863 (defknown %logbitp
(integer unsigned-byte
) boolean
864 (movable foldable flushable always-translatable
))
866 ;;; For constant folding
867 (defun %logbitp
(integer index
)
868 (logbitp index integer
))
870 (define-vop (fast-logbitp-c/fixnum fast-conditional-c
/fixnum
)
871 (:translate %logbitp
)
873 (:arg-types tagged-num
(:constant
(integer 0 63)))
875 (inst tst x
(ash 1 (+ y n-fixnum-tag-bits
)))))
877 (define-vop (fast-logbitp-c/signed fast-conditional-c
/signed
)
878 (:translate %logbitp
)
880 (:arg-types signed-num
(:constant
(integer 0 63)))
882 (inst tst x
(ash 1 y
))))
884 (define-vop (fast-logbitp-c/unsigned fast-conditional-c
/unsigned
)
885 (:translate %logbitp
)
887 (:arg-types unsigned-num
(:constant
(integer 0 63)))
889 (inst tst x
(ash 1 y
))))
891 ;; Specialised mask-signed-field VOPs.
892 (define-vop (mask-signed-field-word/c
)
893 (:translate sb
!c
::mask-signed-field
)
895 (:args
(x :scs
(signed-reg unsigned-reg
) :target r
))
896 (:arg-types
(:constant
(integer 0 64)) untagged-num
)
897 (:results
(r :scs
(signed-reg)))
898 (:result-types signed-num
)
906 (let ((delta (- n-word-bits width
)))
908 (inst asr r r delta
))))))
910 (define-vop (mask-signed-field-bignum/c
)
911 (:translate sb
!c
::mask-signed-field
)
913 (:args
(x :scs
(descriptor-reg) :target r
))
914 (:arg-types
(:constant
(integer 0 64)) bignum
)
915 (:results
(r :scs
(signed-reg)))
916 (:result-types signed-num
)
922 (loadw r x bignum-digits-offset other-pointer-lowtag
)
923 (let ((delta (- n-word-bits width
)))
925 (inst asr r r delta
))))))
928 (define-vop (bignum-length get-header-data
)
929 (:translate sb
!bignum
:%bignum-length
)
930 (:policy
:fast-safe
))
932 (define-vop (bignum-set-length set-header-data
)
933 (:translate sb
!bignum
:%bignum-set-length
)
934 (:policy
:fast-safe
))
936 (define-full-reffer bignum-ref
* bignum-digits-offset other-pointer-lowtag
937 (unsigned-reg) unsigned-num sb
!bignum
:%bignum-ref
)
939 (define-full-setter bignum-set
* bignum-digits-offset other-pointer-lowtag
940 (unsigned-reg) unsigned-num sb
!bignum
:%bignum-set
)
942 (define-vop (digit-0-or-plus)
943 (:translate sb
!bignum
:%digit-0-or-plusp
)
945 (:args
(digit :scs
(unsigned-reg)))
946 (:arg-types unsigned-num
)
951 (inst b
(if not-p
:lt
:ge
) target
)))
953 (define-vop (add-w/carry
)
954 (:translate sb
!bignum
:%add-with-carry
)
956 (:args
(a :scs
(unsigned-reg))
957 (b :scs
(unsigned-reg))
959 (:arg-types unsigned-num unsigned-num positive-fixnum
)
960 (:results
(result :scs
(unsigned-reg))
961 (carry :scs
(unsigned-reg) :from
:eval
))
962 (:result-types unsigned-num positive-fixnum
)
964 (inst cmp c
1) ;; Set carry if (fixnum 0 or 1) c=0, else clear.
965 (inst adcs result a b
)
966 (inst cset carry
:cs
)))
968 (define-vop (sub-w/borrow
)
969 (:translate sb
!bignum
:%subtract-with-borrow
)
971 (:args
(a :scs
(unsigned-reg))
972 (b :scs
(unsigned-reg))
974 (:arg-types unsigned-num unsigned-num positive-fixnum
)
975 (:results
(result :scs
(unsigned-reg))
976 (borrow :scs
(unsigned-reg) :from
:eval
))
977 (:result-types unsigned-num positive-fixnum
)
979 (inst cmp c
1) ;; Set carry if (fixnum 0 or 1) c=0, else clear.
980 (inst sbcs result a b
)
981 (inst cset borrow
:cs
)))
983 (define-vop (bignum-mult-and-add-3-arg)
984 (:translate sb
!bignum
:%multiply-and-add
)
986 (:args
(x :scs
(unsigned-reg) :to
:result
)
987 (y :scs
(unsigned-reg) :to
:result
)
988 (carry-in :scs
(unsigned-reg)))
989 (:arg-types unsigned-num unsigned-num unsigned-num
)
990 (:results
(hi :scs
(unsigned-reg) :from
(:argument
2))
991 (lo :scs
(unsigned-reg) :from
:load
))
992 (:result-types unsigned-num unsigned-num
)
995 (inst adds lo lo carry-in
)
997 (inst adc hi hi zr-tn
)))
999 (define-vop (bignum-mult-and-add-4-arg)
1000 (:translate sb
!bignum
:%multiply-and-add
)
1001 (:policy
:fast-safe
)
1002 (:args
(x :scs
(unsigned-reg) :to
:result
)
1003 (y :scs
(unsigned-reg) :target lo
)
1004 (prev :scs
(unsigned-reg) :to
:result
)
1005 (carry-in :scs
(unsigned-reg) :to
:result
))
1006 (:arg-types unsigned-num unsigned-num unsigned-num unsigned-num
)
1007 (:results
(hi :scs
(unsigned-reg) :from
:eval
)
1008 (lo :scs
(unsigned-reg)))
1009 (:result-types unsigned-num unsigned-num
)
1013 (inst adds lo lo prev
)
1014 (inst adc hi hi zr-tn
)
1015 (inst adds lo lo carry-in
)
1016 (inst adc hi hi zr-tn
)))
1018 (define-vop (bignum-mult)
1019 (:translate sb
!bignum
:%multiply
)
1020 (:policy
:fast-safe
)
1021 (:args
(x :scs
(unsigned-reg) :to
:result
)
1022 (y :scs
(unsigned-reg) :to
:result
))
1023 (:arg-types unsigned-num unsigned-num
)
1024 (:results
(hi :scs
(unsigned-reg) :from
:eval
)
1025 (lo :scs
(unsigned-reg) :from
:eval
))
1026 (:result-types unsigned-num unsigned-num
)
1031 #!+multiply-high-vops
1033 (:translate %multiply-high
)
1034 (:policy
:fast-safe
)
1035 (:args
(x :scs
(unsigned-reg) :target hi
)
1036 (y :scs
(unsigned-reg)))
1037 (:arg-types unsigned-num unsigned-num
)
1038 (:results
(hi :scs
(unsigned-reg)))
1039 (:result-types unsigned-num
)
1041 (inst umulh hi x y
)))
1043 #!+multiply-high-vops
1044 (define-vop (mulhi/fx
)
1045 (:translate %multiply-high
)
1046 (:policy
:fast-safe
)
1047 (:args
(x :scs
(any-reg) :target hi
)
1048 (y :scs
(unsigned-reg)))
1049 (:arg-types positive-fixnum unsigned-num
)
1050 (:temporary
(:sc unsigned-reg
) temp
)
1051 (:results
(hi :scs
(any-reg)))
1052 (:result-types positive-fixnum
)
1054 (inst umulh temp x y
)
1055 (inst and hi temp
(bic-mask fixnum-tag-mask
))))
1057 (define-vop (bignum-lognot lognot-mod64
/unsigned
=>unsigned
)
1058 (:translate sb
!bignum
:%lognot
))
1060 (define-vop (bignum-floor)
1061 (:translate sb
!bignum
:%bigfloor
)
1062 (:policy
:fast-safe
)
1063 (:args
(div-high :scs
(unsigned-reg) :target rem
)
1064 (div-low :scs
(unsigned-reg) :target quo
)
1065 (divisor :scs
(unsigned-reg)))
1066 (:arg-types unsigned-num unsigned-num unsigned-num
)
1067 (:results
(quo :scs
(unsigned-reg) :from
(:argument
1))
1068 (rem :scs
(unsigned-reg) :from
(:argument
0)))
1069 (:result-types unsigned-num unsigned-num
)
1075 (inst cmp rem divisor
)
1077 (inst sub rem rem divisor
)
1079 (inst adcs quo quo quo
)
1081 (inst adc rem rem rem
))))))
1083 (define-vop (signify-digit)
1084 (:translate sb
!bignum
:%fixnum-digit-with-correct-sign
)
1085 (:policy
:fast-safe
)
1086 (:args
(digit :scs
(unsigned-reg) :target res
))
1087 (:arg-types unsigned-num
)
1088 (:results
(res :scs
(any-reg signed-reg
)))
1089 (:result-types signed-num
)
1091 (if (sc-is res any-reg
)
1092 (inst lsl res digit n-fixnum-tag-bits
)
1093 (inst mov res digit
))))
1095 (define-vop (digit-ashr)
1096 (:translate sb
!bignum
:%ashr
)
1097 (:policy
:fast-safe
)
1098 (:args
(digit :scs
(unsigned-reg))
1099 (count :scs
(unsigned-reg)))
1100 (:arg-types unsigned-num positive-fixnum
)
1101 (:results
(result :scs
(unsigned-reg)))
1102 (:result-types unsigned-num
)
1104 (inst asr result digit count
)))
1106 (define-vop (digit-lshr digit-ashr
)
1107 (:translate sb
!bignum
:%digit-logical-shift-right
)
1109 (inst lsr result digit count
)))
1111 (define-vop (digit-ashl digit-ashr
)
1112 (:translate sb
!bignum
:%ashl
)
1114 (inst lsl result digit count
)))
1116 ;;;; Static functions.
1118 (define-static-fun two-arg-gcd
(x y
) :translate gcd
)
1119 (define-static-fun two-arg-lcm
(x y
) :translate lcm
)
1121 (define-static-fun two-arg-
+ (x y
) :translate
+)
1122 (define-static-fun two-arg--
(x y
) :translate -
)
1123 (define-static-fun two-arg-
* (x y
) :translate
*)
1124 (define-static-fun two-arg-
/ (x y
) :translate
/)
1126 (define-static-fun two-arg-
< (x y
) :translate
<)
1127 (define-static-fun two-arg-
> (x y
) :translate
>)
1128 (define-static-fun two-arg-
= (x y
) :translate
=)
1130 (define-static-fun two-arg-and
(x y
) :translate logand
)
1131 (define-static-fun two-arg-ior
(x y
) :translate logior
)
1132 (define-static-fun two-arg-xor
(x y
) :translate logxor
)
1133 (define-static-fun two-arg-eqv
(x y
) :translate logeqv
)
1135 (define-static-fun eql
(x y
) :translate eql
)
1137 (define-static-fun %negate
(x) :translate %negate
)