Remove unnecessary package prefixes.
[sbcl.git] / src / compiler / arm64 / arith.lisp
blob15443d42528d0c171369f1ff5a52999ec42b46b6
1 ;;;; the VM definition arithmetic VOPs for the ARM
3 ;;;; This software is part of the SBCL system. See the README file for
4 ;;;; more information.
5 ;;;;
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.
12 (in-package "SB!VM")
14 ;;;; unary operations.
16 (define-vop (fast-safe-arith-op)
17 (:policy :fast-safe)
18 (:effects)
19 (:affected))
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)
43 (:translate %negate)
44 (:generator 1
45 (inst neg res x)))
47 (define-vop (fast-negate/signed signed-unop)
48 (:translate %negate)
49 (:generator 2
50 (inst neg res x)))
52 (define-vop (fast-negate/unsigned signed-unop)
53 (:args (x :scs (unsigned-reg) :target res))
54 (:arg-types unsigned-num)
55 (:translate %negate)
56 (:generator 3
57 (inst neg res x)))
59 (define-vop (fast-lognot/fixnum fixnum-unop)
60 (:args (x :scs (any-reg)))
61 (:arg-types tagged-num)
62 (:translate lognot)
63 (:generator 1
64 (inst eor res x (lognot n-fixnum-tag-bits))))
66 (define-vop (fast-lognot/signed signed-unop)
67 (:translate lognot)
68 (:generator 2
69 (inst mvn res x)))
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)))
102 (:info y)
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)))
109 (:info y)
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)))
116 (:info y)
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)
125 (and (fixnump x)
126 (encode-logical-immediate (bic-mask (fixnumize x)))))
128 (defmacro define-binop (translate untagged-penalty op
129 &key
130 (constant-test 'encode-logical-immediate)
131 (constant-fixnum-test 'fixnum-encode-logical-immediate)
132 swap
133 (constant-op op)
134 (constant-transform 'identity))
135 `(progn
136 (define-vop (,(symbolicate 'fast- translate '/fixnum=>fixnum)
137 fast-fixnum-binop)
138 (:translate ,translate)
139 (:generator 2
140 ,(if swap
141 `(inst ,op r y x)
142 `(inst ,op r x y))))
143 (define-vop (,(symbolicate 'fast- translate '-c/fixnum=>fixnum)
144 fast-fixnum-binop-c)
145 ,(if swap
146 `(:arg-types (:constant (satisfies ,constant-fixnum-test))
147 tagged-num)
148 `(:arg-types tagged-num
149 (:constant (satisfies ,constant-fixnum-test))))
150 (:translate ,translate)
151 (:generator 1
152 (inst ,constant-op r x (,constant-transform (fixnumize y)))))
153 (define-vop (,(symbolicate 'fast- translate '/signed=>signed)
154 fast-signed-binop)
155 (:translate ,translate)
156 (:generator ,(1+ untagged-penalty)
157 ,(if swap
158 `(inst ,op r y x)
159 `(inst ,op r x y))))
160 (define-vop (,(symbolicate 'fast- translate '-c/signed=>signed)
161 fast-signed-binop-c)
162 (:translate ,translate)
163 ,(if swap
164 `(:arg-types (:constant (satisfies ,constant-test))
165 signed-num)
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)
171 fast-unsigned-binop)
172 (:translate ,translate)
173 (:generator ,(1+ untagged-penalty)
174 ,(if swap
175 `(inst ,op r y x)
176 `(inst ,op r x y))))
177 (define-vop (,(symbolicate 'fast- translate '-c/unsigned=>unsigned)
178 fast-unsigned-binop-c)
179 (:translate ,translate)
180 ,(if swap
181 `(:arg-types (:constant (satisfies ,constant-test))
182 unsigned-num)
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
197 :constant-op and
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
202 :constant-op and
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
208 ;; :constant-op orr
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
213 ;; :constant-op orr
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")
223 (:translate logior)
224 (:generator 3
225 (inst orr r x y)))
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")
234 (:translate logior)
235 (:generator 3
236 (inst orr r x y)))
238 ;;; Multiplication
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)))
243 (:translate *)
244 (:generator 2
245 (inst mul r x y)))
247 (define-vop (fast-*/signed=>signed fast-signed-binop)
248 (:translate *)
249 (:generator 3
250 (inst mul r x y)))
252 (define-vop (fast-*/unsigned=>unsigned fast-unsigned-binop)
253 (:translate *)
254 (:generator 3
255 (inst mul r x y)))
257 ;;; Division
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")
267 (:vop-var vop)
268 (:save-p :compute-only)
269 (:generator 33
270 (let ((zero (generate-error-code vop 'division-by-zero-error x y)))
271 (inst cbz y zero))
272 (inst sdiv quo 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")
284 (:vop-var vop)
285 (:save-p :compute-only)
286 (:generator 33
287 (let ((zero (generate-error-code vop 'division-by-zero-error x y)))
288 (inst cbz y zero))
289 (inst udiv quo x y)
290 (inst msub rem quo y x)))
293 (define-vop (fast-lognor/fixnum=>fixnum fast-fixnum-binop)
294 (:translate lognor)
295 (:args (x :scs (any-reg))
296 (y :scs (any-reg)))
297 (:generator 3
298 (inst orr r x y)
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)
305 (:translate logand))
307 (define-source-transform logeqv (&rest args)
308 (if (oddp (length args))
309 `(logxor ,@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)))
316 ;;; Shifting
318 (define-vop (fast-ash-left-c/fixnum=>fixnum)
319 (:translate ash)
320 (:policy :fast-safe)
321 (:args (number :scs (any-reg) :target result))
322 (:info amount)
323 (:arg-types tagged-num (:constant unsigned-byte))
324 (:results (result :scs (any-reg)))
325 (:result-types tagged-num)
326 (:note "inline ASH")
327 (:generator 1
328 (if (< amount 64)
329 (inst lsl result number amount)
330 (inst mov result 0))))
332 (define-vop (fast-ash-right-c/fixnum=>fixnum)
333 (:translate ash)
334 (:policy :fast-safe)
335 (:args (number :scs (any-reg) :target result))
336 (:info amount)
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)
341 (:note "inline ASH")
342 (:generator 1
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)
347 (:translate ash)
348 (:policy :fast-safe)
349 (:args (number :scs (unsigned-reg) :target result))
350 (:info amount)
351 (:arg-types unsigned-num (:constant integer))
352 (:results (result :scs (unsigned-reg)))
353 (:result-types unsigned-num)
354 (:note "inline ASH")
355 (:generator 3
356 (cond ((< -64 amount 64)
357 (if (plusp amount)
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)
364 (:translate ash)
365 (:policy :fast-safe)
366 (:args (number :scs (signed-reg) :target result))
367 (:info amount)
368 (:arg-types signed-num (:constant integer))
369 (:results (result :scs (signed-reg)))
370 (:result-types signed-num)
371 (:note "inline ASH")
372 (:generator 3
373 (cond ((< -64 amount 64)
374 (if (plusp amount)
375 (inst lsl result number amount)
376 (inst asr result number (- amount))))
378 (inst mov result 0)))))
380 (define-vop (fast-ash/signed/unsigned)
381 (:note "inline ASH")
382 (:args (number)
383 (amount))
384 (:results (result))
385 (:policy :fast-safe)
386 (:temporary (:sc non-descriptor-reg) temp)
387 (:variant-vars variant)
388 (:generator 5
389 (move temp amount)
390 (inst cmp temp 0)
391 (inst b :ge LEFT)
392 (inst neg temp temp)
393 (inst cmp temp n-word-bits)
394 (inst b :lt DO)
395 (inst mov temp (1- n-word-bits))
397 (ecase variant
398 (:signed (inst asr result number temp))
399 (:unsigned (inst lsr result number temp)))
400 (inst b END)
401 LEFT
402 (inst cmp temp n-word-bits)
403 (inst b :lt DO2)
404 (inst mov temp (1- n-word-bits))
406 (inst lsl result number temp)
407 END))
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)
415 (:translate ash)
416 (:variant :signed))
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)
424 (:translate ash)
425 (:variant :unsigned))
427 (macrolet ((def (name sc-type type result-type cost)
428 `(define-vop (,name)
429 (:note "inline ASH")
430 (:translate ash)
431 (:args (number :scs (,sc-type))
432 (amount :scs (signed-reg unsigned-reg)))
433 ;; For modular variants
434 (:variant-vars cut)
435 (:arg-types ,type positive-fixnum)
436 (:results (result :scs (,result-type)))
437 (:result-types ,type)
438 (:policy :fast-safe)
439 (:generator ,cost
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)
446 tmp-tn)
448 amount))))
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))
456 #!+ash-right-vops
457 (define-vop (fast-%ash/right/unsigned)
458 (:translate %ash/right)
459 (:policy :fast-safe)
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)
465 (:generator 4
466 (inst lsr result number amount)))
468 #!+ash-right-vops
469 (define-vop (fast-%ash/right/signed)
470 (:translate %ash/right)
471 (:policy :fast-safe)
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)
477 (:generator 4
478 (inst asr result number amount)))
480 #!+ash-right-vops
481 (define-vop (fast-%ash/right/fixnum)
482 (:translate %ash/right)
483 (:policy :fast-safe)
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)
490 (:generator 3
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)
496 (:variant t)
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)
509 (:variant t)
510 (:translate ash-left-mod64))
512 (define-vop (fast-ash-left-mod64/unsigned=>unsigned
513 fast-ash-left/unsigned=>unsigned)
514 (:variant t)
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)
523 (:policy :fast-safe)
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")
534 (:generator 1
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")
541 (:generator 1
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")
548 (:policy :fast-safe)
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)
554 (:generator 30
555 (move temp arg)
556 (inst cmp temp 0)
557 (inst csinv temp temp temp :ge)
558 (inst clz temp temp)
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")
565 (:policy :fast-safe)
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)
571 :target res) num)
572 (:temporary (:scs (non-descriptor-reg)) mask temp)
573 (:generator 30
574 (move num arg)
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))
598 ;;; Constant folding
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)
606 (:translate %%ldb)
607 (:args (x :scs (any-reg)))
608 (:arg-types tagged-num
609 (:constant integer) (:constant integer))
610 (:info size posn)
611 (:results (res :scs (unsigned-reg)))
612 (:result-types unsigned-num)
613 (:policy :fast-safe)
614 (:generator 2
615 (inst ubfm res x (1+ posn) (+ posn size))))
617 (define-vop (ldb-c)
618 (:translate %%ldb)
619 (:args (x :scs (unsigned-reg signed-reg)))
620 (:arg-types (:or unsigned-num signed-num)
621 (:constant integer) (:constant integer))
622 (:info size posn)
623 (:results (res :scs (unsigned-reg)))
624 (:result-types unsigned-num)
625 (:policy :fast-safe)
626 (:generator 3
627 (inst ubfm res x posn (+ posn size -1))))
629 (define-vop (dpb-c/fixnum)
630 (:translate %%dpb)
631 (:args (x :scs (signed-reg) :to :save)
632 (y :scs (any-reg)))
633 (:arg-types signed-num
634 (:constant integer) (:constant integer)
635 tagged-num)
636 (:info size posn)
637 (:results (res :scs (any-reg)))
638 (:result-types tagged-num)
639 (:policy :fast-safe)
640 (:generator 2
641 (move res y)
642 (inst bfm res x (- (1- n-word-bits) posn) (1- size))))
644 (define-vop (dpb-c/signed)
645 (:translate %%dpb)
646 (:args (x :scs (signed-reg) :to :save)
647 (y :scs (signed-reg)))
648 (:arg-types signed-num
649 (:constant integer) (:constant integer)
650 signed-num)
651 (:info size posn)
652 (:results (res :scs (signed-reg)))
653 (:result-types signed-num)
654 (:policy :fast-safe)
655 (:generator 3
656 (move res y)
657 (inst bfm res x (- n-word-bits posn) (1- size))))
659 (define-vop (dpb-c/unsigned)
660 (:translate %%dpb)
661 (:args (x :scs (unsigned-reg) :to :save)
662 (y :scs (unsigned-reg)))
663 (:arg-types unsigned-num
664 (:constant integer) (:constant integer)
665 unsigned-num)
666 (:info size posn)
667 (:results (res :scs (unsigned-reg)))
668 (:result-types unsigned-num)
669 (:policy :fast-safe)
670 (:generator 3
671 (move res y)
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)
682 (:policy :fast-safe)
683 (:generator 1
684 (inst mvn res x)))
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)))
698 (:info y)
699 (:arg-types untagged-num (:constant (or word
700 signed-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))))
717 `(progn
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))
724 ,@(when -c-p
725 `((define-mod-binop-c (,vop64cu ,vopcu) ,fun64)
726 (define-vop (,vopfxcf ,vopcf) (:translate ,funfx))))))))
727 (def + t)
728 (def - t)
729 (def * nil))
731 ;;;; Binary conditional VOPs:
733 (define-vop (fast-conditional)
734 (:conditional :eq)
735 (:effects)
736 (:affected)
737 (:policy :fast-safe))
739 (define-vop (fast-conditional/fixnum fast-conditional)
740 (:args (x :scs (any-reg))
741 (y :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)))
748 (:info y))
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)))
759 (:info y))
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)))
770 (:info y))
772 (defmacro define-conditional-vop (tran cond unsigned)
773 `(progn
774 ,@(mapcar (lambda (suffix cost signed)
775 (unless (and (member suffix '(/fixnum -c/fixnum))
776 (eq tran 'eql))
777 `(define-vop (,(intern (format nil "~:@(FAST-IF-~A~A~)"
778 tran suffix))
779 ,(intern
780 (format nil "~:@(FAST-CONDITIONAL~A~)"
781 suffix)))
782 (:translate ,tran)
783 (:conditional ,(if signed cond unsigned))
784 (:generator ,cost
785 (inst cmp x
786 ,(if (eq suffix '-c/fixnum) '(fixnumize y) 'y))))))
787 '(/fixnum -c/fixnum /signed -c/signed /unsigned -c/unsigned)
788 '(4 3 6 5 6 5)
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))
806 (y :scs (any-reg)))
807 (:arg-types tagged-num tagged-num)
808 (:note "inline fixnum comparison")
809 (:translate eql)
810 (:conditional :eq)
811 (:policy :fast-safe)
812 (:generator 4
813 (inst cmp x y)))
815 (define-vop (generic-eql/fixnum fast-eql/fixnum)
816 (:args (x :scs (any-reg descriptor-reg))
817 (y :scs (any-reg)))
818 (:arg-types * tagged-num)
819 (:variant-cost 7))
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)))
824 (:info y)
825 (:translate eql)
826 (:policy :fast-safe)
827 (:conditional :eq)
828 (:generator 3
829 (if (minusp y)
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)))
836 (:variant-cost 6))
838 ;; (macrolet ((define-logtest-vops ()
839 ;; `(progn
840 ;; ,@(loop for suffix in '(/fixnum -c/fixnum
841 ;; /signed -c/signed
842 ;; /unsigned -c/unsigned)
843 ;; for cost in '(4 3 6 5 6 5)
844 ;; collect
845 ;; `(define-vop (,(symbolicate "FAST-LOGTEST" suffix)
846 ;; ,(symbolicate "FAST-CONDITIONAL" suffix))
847 ;; (:translate logtest)
848 ;; (:conditional :ne)
849 ;; (:generator ,cost
850 ;; (inst tst x
851 ;; ,(case suffix
852 ;; (-c/fixnum
853 ;; `(fixnumize y))
854 ;; ((-c/signed -c/unsigned)
855 ;; `y)
856 ;; (t
857 ;; 'y)))))))))
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)
872 (:conditional :ne)
873 (:arg-types tagged-num (:constant (integer 0 63)))
874 (:generator 4
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)
879 (:conditional :ne)
880 (:arg-types signed-num (:constant (integer 0 63)))
881 (:generator 5
882 (inst tst x (ash 1 y))))
884 (define-vop (fast-logbitp-c/unsigned fast-conditional-c/unsigned)
885 (:translate %logbitp)
886 (:conditional :ne)
887 (:arg-types unsigned-num (:constant (integer 0 63)))
888 (:generator 5
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)
894 (:policy :fast-safe)
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)
899 (:info width)
900 (:generator 3
901 (cond ((zerop width)
902 (inst mov r 0))
903 ((= width 64)
904 (move r x))
906 (let ((delta (- n-word-bits width)))
907 (inst lsl r x delta)
908 (inst asr r r delta))))))
910 (define-vop (mask-signed-field-bignum/c)
911 (:translate sb!c::mask-signed-field)
912 (:policy :fast-safe)
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)
917 (:info width)
918 (:generator 4
919 (cond ((zerop width)
920 (inst mov r 0))
922 (loadw r x bignum-digits-offset other-pointer-lowtag)
923 (let ((delta (- n-word-bits width)))
924 (inst lsl r r delta)
925 (inst asr r r delta))))))
926 ;;;; Bignum stuff.
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)
944 (:policy :fast-safe)
945 (:args (digit :scs (unsigned-reg)))
946 (:arg-types unsigned-num)
947 (:conditional)
948 (:info target not-p)
949 (:generator 2
950 (inst cmp digit 0)
951 (inst b (if not-p :lt :ge) target)))
953 (define-vop (add-w/carry)
954 (:translate sb!bignum:%add-with-carry)
955 (:policy :fast-safe)
956 (:args (a :scs (unsigned-reg))
957 (b :scs (unsigned-reg))
958 (c :scs (any-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)
963 (:generator 3
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)
970 (:policy :fast-safe)
971 (:args (a :scs (unsigned-reg))
972 (b :scs (unsigned-reg))
973 (c :scs (any-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)
978 (:generator 4
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)
985 (:policy :fast-safe)
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)
993 (:generator 2
994 (inst mul lo x y)
995 (inst adds lo lo carry-in)
996 (inst umulh hi x y)
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)
1010 (:generator 9
1011 (inst umulh hi x y)
1012 (inst mul lo x y)
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)
1027 (:generator 1
1028 (inst umulh hi x y)
1029 (inst mul lo x y)))
1031 #!+multiply-high-vops
1032 (define-vop (mulhi)
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)
1040 (:generator 20
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)
1053 (:generator 15
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)
1070 (:generator 300
1071 (move rem div-high)
1072 (move quo div-low)
1073 (dotimes (i 65)
1074 (assemble ()
1075 (inst cmp rem divisor)
1076 (inst b :cc CC)
1077 (inst sub rem rem divisor)
1079 (inst adcs quo quo quo)
1080 (unless (= i 64)
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)
1090 (:generator 1
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)
1103 (:generator 1
1104 (inst asr result digit count)))
1106 (define-vop (digit-lshr digit-ashr)
1107 (:translate sb!bignum:%digit-logical-shift-right)
1108 (:generator 1
1109 (inst lsr result digit count)))
1111 (define-vop (digit-ashl digit-ashr)
1112 (:translate sb!bignum:%ashl)
1113 (:generator 1
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)