0.8.4.15:
[sbcl.git] / src / compiler / alpha / arith.lisp
1 ;;;; the VM definition arithmetic VOPs for the Alpha
2
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.
11
12 (in-package "SB!VM")
13 \f
14 ;;;; unary operations
15
16 (define-vop (fixnum-unop)
17   (:args (x :scs (any-reg)))
18   (:results (res :scs (any-reg)))
19   (:note "inline fixnum arithmetic")
20   (:arg-types tagged-num)
21   (:result-types tagged-num)
22   (:policy :fast-safe))
23
24 (define-vop (signed-unop)
25   (:args (x :scs (signed-reg)))
26   (:results (res :scs (signed-reg)))
27   (:note "inline (signed-byte 64) arithmetic")
28   (:arg-types signed-num)
29   (:result-types signed-num)
30   (:policy :fast-safe))
31
32 (define-vop (fast-negate/fixnum fixnum-unop)
33   (:translate %negate)
34   (:generator 1
35     (inst subq zero-tn x res)))
36
37 (define-vop (fast-negate/signed signed-unop)
38   (:translate %negate)
39   (:generator 2
40     (inst subq zero-tn x res)))
41
42 (define-vop (fast-lognot/fixnum fixnum-unop)
43   (:translate lognot)
44   (:generator 2
45     (inst eqv x zero-tn res)))
46
47 (define-vop (fast-lognot/signed signed-unop)
48   (:translate lognot)
49   (:generator 1
50     (inst not x res)))
51 \f
52 ;;;; binary fixnum operations
53
54 ;;; Assume that any constant operand is the second arg...
55
56 (define-vop (fast-fixnum-binop)
57   (:args (x :target r :scs (any-reg))
58          (y :target r :scs (any-reg)))
59   (:arg-types tagged-num tagged-num)
60   (:results (r :scs (any-reg)))
61   (:result-types tagged-num)
62   (:note "inline fixnum arithmetic")
63   (:effects)
64   (:affected)
65   (:policy :fast-safe))
66
67 (define-vop (fast-unsigned-binop)
68   (:args (x :target r :scs (unsigned-reg))
69          (y :target r :scs (unsigned-reg)))
70   (:arg-types unsigned-num unsigned-num)
71   (:results (r :scs (unsigned-reg)))
72   (:result-types unsigned-num)
73   (:note "inline (unsigned-byte 64) arithmetic")
74   (:effects)
75   (:affected)
76   (:policy :fast-safe))
77
78 (define-vop (fast-signed-binop)
79   (:args (x :target r :scs (signed-reg))
80          (y :target r :scs (signed-reg)))
81   (:arg-types signed-num signed-num)
82   (:results (r :scs (signed-reg)))
83   (:result-types signed-num)
84   (:note "inline (signed-byte 64) arithmetic")
85   (:effects)
86   (:affected)
87   (:policy :fast-safe))
88
89 (define-vop (fast-fixnum-c-binop fast-fixnum-binop)
90   (:args (x :target r :scs (any-reg)))
91   (:info y)
92   (:arg-types tagged-num (:constant integer)))
93
94 (define-vop (fast-signed-c-binop fast-signed-binop)
95   (:args (x :target r :scs (signed-reg)))
96   (:info y)
97   (:arg-types tagged-num (:constant integer)))
98
99 (define-vop (fast-unsigned-c-binop fast-unsigned-binop)
100   (:args (x :target r :scs (unsigned-reg)))
101   (:info y)
102   (:arg-types tagged-num (:constant integer)))
103
104 (defmacro define-binop (translate cost untagged-cost op 
105                         tagged-type untagged-type
106                         &optional arg-swap restore-fixnum-mask)
107   `(progn
108      (define-vop (,(symbolicate "FAST-" translate "/FIXNUM=>FIXNUM")
109                   fast-fixnum-binop)
110        ,@(when restore-fixnum-mask
111            `((:temporary (:sc non-descriptor-reg) temp)))
112        (:args (x ,@(unless restore-fixnum-mask `(:target r)) :scs (any-reg))
113               (y ,@(unless restore-fixnum-mask `(:target r)) :scs (any-reg)))
114        (:translate ,translate)
115        (:generator ,(1+ cost)
116          ,(if arg-swap
117               `(inst ,op y x ,(if restore-fixnum-mask 'temp 'r))
118               `(inst ,op x y ,(if restore-fixnum-mask 'temp 'r)))
119          ,@(when restore-fixnum-mask
120              `((inst bic temp #.(ash lowtag-mask -1) r)))))
121      (define-vop (,(symbolicate "FAST-" translate "/SIGNED=>SIGNED")
122                   fast-signed-binop)
123        (:args (x :target r :scs (signed-reg))
124               (y :target r :scs (signed-reg)))
125        (:translate ,translate)
126        (:generator ,(1+ untagged-cost)
127          ,(if arg-swap
128               `(inst ,op y x r)
129               `(inst ,op x y r))))
130      (define-vop (,(symbolicate "FAST-" translate "/UNSIGNED=>UNSIGNED")
131                   fast-unsigned-binop)
132        (:args (x :target r :scs (unsigned-reg))
133               (y :target r :scs (unsigned-reg)))
134        (:translate ,translate)
135        (:generator ,(1+ untagged-cost)
136          ,(if arg-swap
137               `(inst ,op y x r)
138               `(inst ,op x y r))))
139      ,@(when (and tagged-type (not arg-swap))
140          `((define-vop (,(symbolicate "FAST-" translate "-C/FIXNUM=>FIXNUM")
141                         fast-fixnum-c-binop)
142              (:arg-types tagged-num (:constant ,tagged-type))
143              ,@(when restore-fixnum-mask
144                  `((:temporary (:sc non-descriptor-reg) temp)))
145              (:translate ,translate)
146              (:generator ,cost
147                 (inst ,op x (fixnumize y) ,(if restore-fixnum-mask 'temp 'r))
148                 ,@(when restore-fixnum-mask
149                     `((inst bic temp #.(ash lowtag-mask -1) r)))))))
150      ,@(when (and untagged-type (not arg-swap))
151          `((define-vop (,(symbolicate "FAST-" translate "-C/SIGNED=>SIGNED")
152                         fast-signed-c-binop)
153              (:arg-types signed-num (:constant ,untagged-type))
154              (:translate ,translate)
155              (:generator ,untagged-cost
156                 (inst ,op x y r)))
157            (define-vop (,(symbolicate "FAST-" translate
158                                       "-C/UNSIGNED=>UNSIGNED")
159                         fast-unsigned-c-binop)
160              (:arg-types unsigned-num (:constant ,untagged-type))
161              (:translate ,translate)
162              (:generator ,untagged-cost
163                 (inst ,op x y r)))))))
164
165 (define-binop + 1 5 addq (unsigned-byte 6) (unsigned-byte 8))
166 (define-binop - 1 5 subq (unsigned-byte 6) (unsigned-byte 8))
167 (define-binop logand 1 3 and (unsigned-byte 6) (unsigned-byte 8))
168 (define-binop logandc1 1 3 bic (unsigned-byte 6) (unsigned-byte 8) t)
169 (define-binop logandc2 1 3 bic (unsigned-byte 6) (unsigned-byte 8))
170 (define-binop logior 1 3 bis (unsigned-byte 6) (unsigned-byte 8))
171 (define-binop logorc1 1 3 ornot (unsigned-byte 6) (unsigned-byte 8) t t)
172 (define-binop logorc2 1 3 ornot (unsigned-byte 6) (unsigned-byte 8) nil t)
173 (define-binop logxor 1 3 xor (unsigned-byte 6) (unsigned-byte 8))
174 (define-binop logeqv 1 3 eqv (unsigned-byte 6) (unsigned-byte 8) nil t)
175
176 ;;; special cases for LOGAND where we can use a mask operation
177 (define-vop (fast-logand-c-mask/unsigned=>unsigned fast-unsigned-c-binop)
178   (:translate logand)
179   (:arg-types unsigned-num
180               (:constant (or (integer #xffffffff #xffffffff)
181                              (integer #xffffffff00000000 #xffffffff00000000))))
182   (:generator 1
183     (ecase y
184       (#xffffffff (inst mskll x 4 r))
185       (#xffffffff00000000 (inst mskll x 0 r)))))
186 \f
187 ;;;; shifting
188
189 (define-vop (fast-ash/unsigned=>unsigned)
190   (:note "inline ASH")
191   (:args (number :scs (unsigned-reg) :to :save)
192          (amount :scs (signed-reg)))
193   (:arg-types unsigned-num signed-num)
194   (:results (result :scs (unsigned-reg)))
195   (:result-types unsigned-num)
196   (:translate ash)
197   (:policy :fast-safe)
198   (:temporary (:sc non-descriptor-reg) ndesc)
199   (:temporary (:sc non-descriptor-reg) temp)
200   (:generator 3
201     (inst bge amount positive)
202     (inst subq zero-tn amount ndesc)
203     (inst cmplt ndesc 64 temp)
204     (inst srl number ndesc result)
205     ;; FIXME: this looks like a candidate for a conditional move --
206     ;; CSR, 2003-09-10
207     (inst bne temp done)
208     (move zero-tn result)
209     (inst br zero-tn done)
210       
211     POSITIVE
212     (inst sll number amount result)
213       
214     DONE))
215
216 (define-vop (fast-ash/signed=>signed)
217   (:note "inline ASH")
218   (:args (number :scs (signed-reg) :to :save)
219          (amount :scs (signed-reg)))
220   (:arg-types signed-num signed-num)
221   (:results (result :scs (signed-reg)))
222   (:result-types signed-num)
223   (:translate ash)
224   (:policy :fast-safe)
225   (:temporary (:sc non-descriptor-reg) ndesc)
226   (:temporary (:sc non-descriptor-reg) temp)
227   (:generator 3
228     (inst bge amount positive)
229     (inst subq zero-tn amount ndesc)
230     (inst cmplt ndesc 63 temp)
231     (inst sra number ndesc result)
232     (inst bne temp done)
233     (inst sra number 63 result)
234     (inst br zero-tn done)
235       
236     POSITIVE
237     (inst sll number amount result)
238       
239     DONE))
240
241 (define-vop (fast-ash-c/signed=>signed)
242   (:policy :fast-safe)
243   (:translate ash)
244   (:note nil)
245   (:args (number :scs (signed-reg)))
246   (:info count)
247   (:arg-types signed-num (:constant integer))
248   (:results (result :scs (signed-reg)))
249   (:result-types signed-num)
250   (:generator 1
251     (cond
252       ((< count 0) (inst sra number (min 63 (- count)) result))
253       ((> count 0) (inst sll number (min 63 count) result))
254       (t (bug "identity ASH not transformed away")))))
255
256 (define-vop (fast-ash-c/unsigned=>unsigned)
257   (:policy :fast-safe)
258   (:translate ash)
259   (:note nil)
260   (:args (number :scs (unsigned-reg)))
261   (:info count)
262   (:arg-types unsigned-num (:constant integer))
263   (:results (result :scs (unsigned-reg)))
264   (:result-types unsigned-num)
265   (:generator 1
266     (cond
267       ((< count -63) (move zero-tn result))
268       ((< count 0) (inst sra number (- count) result))
269       ((> count 0) (inst sll number (min 63 count) result))
270       (t (bug "identity ASH not transformed away")))))
271
272 (define-vop (signed-byte-64-len)
273   (:translate integer-length)
274   (:note "inline (signed-byte 64) integer-length")
275   (:policy :fast-safe)
276   (:args (arg :scs (signed-reg) :to (:argument 1)))
277   (:arg-types signed-num)
278   (:results (res :scs (any-reg)))
279   (:result-types positive-fixnum)
280   (:temporary (:scs (non-descriptor-reg) :from (:argument 0)) shift)
281   (:generator 30
282     (inst not arg shift)
283     (inst cmovge arg arg shift)
284     (inst subq zero-tn (fixnumize 1) res)
285     (inst sll shift 1 shift)
286     LOOP
287     (inst addq res (fixnumize 1) res)
288     (inst srl shift 1 shift)
289     (inst bne shift loop)))
290
291 (define-vop (unsigned-byte-64-count)
292   (:translate logcount)
293   (:note "inline (unsigned-byte 64) logcount")
294   (:policy :fast-safe)
295   (:args (arg :scs (unsigned-reg) :target num))
296   (:arg-types unsigned-num)
297   (:results (res :scs (unsigned-reg)))
298   (:result-types positive-fixnum)
299   (:temporary (:scs (non-descriptor-reg) :from (:argument 0) :to (:result 0)
300                     :target res) num)
301   (:temporary (:scs (non-descriptor-reg)) mask temp)
302   (:generator 60
303     ;; FIXME: now this looks expensive, what with these 64bit loads.
304     ;; Maybe a loop and count would be faster?  -- CSR, 2003-09-10
305     (inst li #x5555555555555555 mask)
306     (inst srl arg 1 temp)
307     (inst and arg mask num)
308     (inst and temp mask temp)
309     (inst addq num temp num)
310     (inst li #x3333333333333333 mask)
311     (inst srl num 2 temp)
312     (inst and num mask num)
313     (inst and temp mask temp)
314     (inst addq num temp num)
315     (inst li #x0f0f0f0f0f0f0f0f mask)
316     (inst srl num 4 temp)
317     (inst and num mask num)
318     (inst and temp mask temp)
319     (inst addq num temp num)
320     (inst li #x00ff00ff00ff00ff mask)
321     (inst srl num 8 temp)
322     (inst and num mask num)
323     (inst and temp mask temp)
324     (inst addq num temp num)
325     (inst li #x0000ffff0000ffff mask)
326     (inst srl num 16 temp)
327     (inst and num mask num)
328     (inst and temp mask temp)
329     (inst addq num temp num)
330     (inst li #x00000000ffffffff mask)
331     (inst srl num 32 temp)
332     (inst and num mask num)
333     (inst and temp mask temp)
334     (inst addq num temp res)))
335 \f
336 ;;;; multiplying
337
338 (define-vop (fast-*/fixnum=>fixnum fast-fixnum-binop)
339   (:temporary (:scs (non-descriptor-reg)) temp)
340   (:translate *)
341   (:generator 4
342     (inst sra y 2 temp)
343     (inst mulq x temp r)))
344
345 (define-vop (fast-*/signed=>signed fast-signed-binop)
346   (:translate *)
347   (:generator 3
348     (inst mulq x y r)))
349
350 (define-vop (fast-*/unsigned=>unsigned fast-unsigned-binop)
351   (:translate *)
352   (:generator 3
353     (inst mulq x y r)))
354 \f
355 ;;;; Modular functions:
356 (define-modular-fun lognot-mod64 (x) lognot 64)
357 (define-vop (lognot-mod64/unsigned=>unsigned)
358   (:translate lognot-mod64)
359   (:args (x :scs (unsigned-reg)))
360   (:arg-types unsigned-num)
361   (:results (res :scs (unsigned-reg)))
362   (:result-types unsigned-num)
363   (:policy :fast-safe)
364   (:generator 1
365     (inst not x res)))
366
367 (define-vop (fast-ash-left-mod64-c/unsigned=>unsigned
368              fast-ash-c/unsigned=>unsigned)
369   (:translate ash-left-mod64))
370
371 (macrolet
372     ((define-modular-backend (fun &optional constantp)
373        (let ((mfun-name (symbolicate fun '-mod64))
374              (modvop (symbolicate 'fast- fun '-mod64/unsigned=>unsigned))
375              (modcvop (symbolicate 'fast- fun '-mod64-c/unsigned=>unsigned))
376              (vop (symbolicate 'fast- fun '/unsigned=>unsigned))
377              (cvop (symbolicate 'fast- fun '-c/unsigned=>unsigned)))
378          `(progn
379             (define-modular-fun ,mfun-name (x y) ,fun 64)
380             (define-vop (,modvop ,vop)
381               (:translate ,mfun-name))
382             ,@(when constantp
383                 `((define-vop (,modcvop ,cvop)
384                     (:translate ,mfun-name))))))))
385   (define-modular-backend + t)
386   (define-modular-backend - t)
387   (define-modular-backend logxor t)
388   (define-modular-backend logeqv t)
389   (define-modular-backend logandc1)
390   (define-modular-backend logandc2 t)
391   (define-modular-backend logorc1)
392   (define-modular-backend logorc2 t))
393
394 (define-source-transform lognand (x y)
395   `(lognot (logand ,x ,y)))
396 (define-source-transform lognor (x y)
397   `(lognot (logior ,x ,y)))
398 \f
399 ;;;; binary conditional VOPs
400
401 (define-vop (fast-conditional)
402   (:conditional)
403   (:info target not-p)
404   (:effects)
405   (:affected)
406   (:temporary (:scs (non-descriptor-reg)) temp)
407   (:policy :fast-safe))
408
409 (define-vop (fast-conditional/fixnum fast-conditional)
410   (:args (x :scs (any-reg))
411          (y :scs (any-reg)))
412   (:arg-types tagged-num tagged-num)
413   (:note "inline fixnum comparison"))
414
415 (define-vop (fast-conditional-c/fixnum fast-conditional/fixnum)
416   (:args (x :scs (any-reg)))
417   (:arg-types tagged-num (:constant (unsigned-byte-with-a-bite-out 6 4)))
418   (:info target not-p y))
419
420 (define-vop (fast-conditional/signed fast-conditional)
421   (:args (x :scs (signed-reg))
422          (y :scs (signed-reg)))
423   (:arg-types signed-num signed-num)
424   (:note "inline (signed-byte 64) comparison"))
425
426 (define-vop (fast-conditional-c/signed fast-conditional/signed)
427   (:args (x :scs (signed-reg)))
428   (:arg-types signed-num (:constant (unsigned-byte-with-a-bite-out 8 1)))
429   (:info target not-p y))
430
431 (define-vop (fast-conditional/unsigned fast-conditional)
432   (:args (x :scs (unsigned-reg))
433          (y :scs (unsigned-reg)))
434   (:arg-types unsigned-num unsigned-num)
435   (:note "inline (unsigned-byte 64) comparison"))
436
437 (define-vop (fast-conditional-c/unsigned fast-conditional/unsigned)
438   (:args (x :scs (unsigned-reg)))
439   (:arg-types unsigned-num (:constant (unsigned-byte-with-a-bite-out 8 1)))
440   (:info target not-p y))
441
442
443 (defmacro define-conditional-vop (translate &rest generator)
444   `(progn
445      ,@(mapcar (lambda (suffix cost signed)
446                  (unless (and (member suffix '(/fixnum -c/fixnum))
447                               (eq translate 'eql))
448                    `(define-vop (,(intern (format nil "~:@(FAST-IF-~A~A~)"
449                                                   translate suffix))
450                                  ,(intern
451                                    (format nil "~:@(FAST-CONDITIONAL~A~)"
452                                            suffix)))
453                       (:translate ,translate)
454                       (:generator ,cost
455                                   (let* ((signed ,signed)
456                                          (-c/fixnum ,(eq suffix '-c/fixnum))
457                                          (y (if -c/fixnum (fixnumize y) y)))
458                                     ,@generator)))))
459                '(/fixnum -c/fixnum /signed -c/signed /unsigned -c/unsigned)
460                '(3 2 5 4 5 4)
461                '(t t t t nil nil))))
462
463 (define-conditional-vop <
464   (cond ((and signed (eql y 0))
465          (if not-p
466              (inst bge x target)
467              (inst blt x target)))
468         (t
469          (if signed
470              (inst cmplt x y temp)
471              (inst cmpult x y temp))
472          (if not-p
473              (inst beq temp target)
474              (inst bne temp target)))))
475
476 (define-conditional-vop >
477   (cond ((and signed (eql y 0))
478          (if not-p
479              (inst ble x target)
480              (inst bgt x target)))
481         ((integerp y)
482          (let ((y (+ y (if -c/fixnum (fixnumize 1) 1))))
483            (if signed
484                (inst cmplt x y temp)
485                (inst cmpult x y temp))
486            (if not-p
487                (inst bne temp target)
488                (inst beq temp target))))
489         (t
490          (if signed
491              (inst cmplt y x temp)
492              (inst cmpult y x temp))
493          (if not-p
494              (inst beq temp target)
495              (inst bne temp target)))))
496
497 ;;; EQL/FIXNUM is funny because the first arg can be of any type, not
498 ;;; just a known fixnum.
499
500 (define-conditional-vop eql
501   (declare (ignore signed))
502   (when (integerp y)
503     (inst li y temp)
504     (setf y temp))
505   (inst cmpeq x y temp)
506   (if not-p
507       (inst beq temp target)
508       (inst bne temp target)))
509
510 ;;; These versions specify a fixnum restriction on their first arg. We
511 ;;; have also generic-eql/fixnum VOPs which are the same, but have no
512 ;;; restriction on the first arg and a higher cost. The reason for
513 ;;; doing this is to prevent fixnum specific operations from being
514 ;;; used on word integers, spuriously consing the argument.
515 (define-vop (fast-eql/fixnum fast-conditional)
516   (:args (x :scs (any-reg))
517          (y :scs (any-reg)))
518   (:arg-types tagged-num tagged-num)
519   (:note "inline fixnum comparison")
520   (:translate eql)
521   (:generator 3
522     (cond ((equal y zero-tn)
523            (if not-p
524                (inst bne x target)
525                (inst beq x target)))
526           (t
527            (inst cmpeq x y temp)
528            (if not-p
529                (inst beq temp target)
530                (inst bne temp target))))))
531
532 ;;;
533 (define-vop (generic-eql/fixnum fast-eql/fixnum)
534   (:args (x :scs (any-reg descriptor-reg))
535          (y :scs (any-reg)))
536   (:arg-types * tagged-num)
537   (:variant-cost 7))
538
539 (define-vop (fast-eql-c/fixnum fast-conditional/fixnum)
540   (:args (x :scs (any-reg)))
541   (:arg-types tagged-num (:constant (signed-byte 6)))
542   (:temporary (:scs (non-descriptor-reg)) temp)
543   (:info target not-p y)
544   (:translate eql)
545   (:generator 2
546     (let ((y (cond ((eql y 0) zero-tn)
547                    (t
548                     (inst li (fixnumize y) temp)
549                     temp))))
550       (inst cmpeq x y temp)
551       (if not-p
552           (inst beq temp target)
553           (inst bne temp target)))))
554 ;;;
555 (define-vop (generic-eql-c/fixnum fast-eql-c/fixnum)
556   (:args (x :scs (any-reg descriptor-reg)))
557   (:arg-types * (:constant (signed-byte 6)))
558   (:variant-cost 6))
559   
560 \f
561 ;;;; 32-bit logical operations
562
563 (define-vop (merge-bits)
564   (:translate merge-bits)
565   (:args (shift :scs (signed-reg unsigned-reg))
566          (prev :scs (unsigned-reg))
567          (next :scs (unsigned-reg)))
568   (:arg-types tagged-num unsigned-num unsigned-num)
569   (:temporary (:scs (unsigned-reg) :to (:result 0)) temp)
570   (:temporary (:scs (unsigned-reg) :to (:result 0) :target result) res)
571   (:results (result :scs (unsigned-reg)))
572   (:result-types unsigned-num)
573   (:policy :fast-safe)
574   (:generator 4
575     (let ((done (gen-label)))
576       (inst srl next shift res)
577       (inst beq shift done)
578       (inst subq zero-tn shift temp)
579       (inst sll prev temp temp)
580       (inst bis res temp res)
581       (emit-label done)
582       (move res result))))
583
584 (define-source-transform 32bit-logical-not (x)
585   `(logand (lognot (the (unsigned-byte 32) ,x)) #.(1- (ash 1 32))))
586
587 (deftransform 32bit-logical-and ((x y))
588   '(logand x y))
589
590 (define-source-transform 32bit-logical-nand (x y)
591   `(32bit-logical-not (32bit-logical-and ,x ,y)))
592
593 (deftransform 32bit-logical-or ((x y))
594   '(logior x y))
595
596 (define-source-transform 32bit-logical-nor (x y)
597   `(logand (lognor (the (unsigned-byte 32) ,x) (the (unsigned-byte 32) ,y))
598            #.(1- (ash 1 32))))
599
600 (deftransform 32bit-logical-xor ((x y))
601   '(logxor x y))
602
603 (define-source-transform 32bit-logical-eqv (x y)
604   `(logand (logeqv (the (unsigned-byte 32) ,x) (the (unsigned-byte 32) ,y))
605            #.(1- (ash 1 32))))
606
607 (define-source-transform 32bit-logical-orc1 (x y)
608   `(logand (logorc1 (the (unsigned-byte 32) ,x) (the (unsigned-byte 32) ,y))
609            #.(1- (ash 1 32))))
610
611 (define-source-transform 32bit-logical-orc2 (x y)
612   `(logand (logorc2 (the (unsigned-byte 32) ,x) (the (unsigned-byte 32) ,y))
613            #.(1- (ash 1 32))))
614
615 (define-source-transform 32bit-logical-andc1 (x y)
616   `(logandc1 (the (unsigned-byte 32) ,x) (the (unsigned-byte 32) ,y)))
617
618 (define-source-transform 32bit-logical-andc2 (x y)
619   `(logandc2 (the (unsigned-byte 32) ,x) (the (unsigned-byte 32) ,y)))
620
621 (define-vop (shift-towards-someplace)
622   (:policy :fast-safe)
623   (:args (num :scs (unsigned-reg))
624          (amount :scs (signed-reg)))
625   (:arg-types unsigned-num tagged-num)
626   (:results (r :scs (unsigned-reg)))
627   (:result-types unsigned-num))
628
629 (define-vop (shift-towards-start shift-towards-someplace)
630   (:translate shift-towards-start)
631   (:note "SHIFT-TOWARDS-START")
632   (:temporary (:sc non-descriptor-reg) temp)
633   (:generator 1
634     (inst and amount #x1f temp)
635     (inst srl num temp r)))
636
637 (define-vop (shift-towards-end shift-towards-someplace)
638   (:translate shift-towards-end)
639   (:note "SHIFT-TOWARDS-END")
640   (:temporary (:sc non-descriptor-reg) temp)
641   (:generator 1
642     (inst and amount #x1f temp)
643     (inst sll num temp r)))
644 \f
645 ;;;; bignum stuff
646
647 (define-vop (bignum-length get-header-data)
648   (:translate sb!bignum::%bignum-length)
649   (:policy :fast-safe))
650
651 (define-vop (bignum-set-length set-header-data)
652   (:translate sb!bignum::%bignum-set-length)
653   (:policy :fast-safe))
654
655 (define-full-reffer bignum-ref * bignum-digits-offset other-pointer-lowtag
656   (unsigned-reg) unsigned-num sb!bignum::%bignum-ref)
657
658 (define-full-setter bignum-set * bignum-digits-offset other-pointer-lowtag
659   (unsigned-reg) unsigned-num sb!bignum::%bignum-set #!+gengc nil)
660
661 (define-vop (digit-0-or-plus)
662   (:translate sb!bignum::%digit-0-or-plusp)
663   (:policy :fast-safe)
664   (:args (digit :scs (unsigned-reg)))
665   (:arg-types unsigned-num)
666   (:temporary (:sc non-descriptor-reg) temp)
667   (:conditional)
668   (:info target not-p)
669   (:generator 2
670     (inst sll digit 32 temp)
671     (if not-p
672         (inst blt temp target)
673         (inst bge temp target))))
674
675 (define-vop (add-w/carry)
676   (:translate sb!bignum::%add-with-carry)
677   (:policy :fast-safe)
678   (:args (a :scs (unsigned-reg))
679          (b :scs (unsigned-reg))
680          (c :scs (unsigned-reg)))
681   (:arg-types unsigned-num unsigned-num positive-fixnum)
682   (:results (result :scs (unsigned-reg) :from :load)
683             (carry :scs (unsigned-reg) :from :eval))
684   (:result-types unsigned-num positive-fixnum)
685   (:generator 5
686     (inst addq a b result)
687     (inst addq result c result)
688     (inst sra result 32 carry)
689     (inst mskll result 4 result)))
690
691 (define-vop (sub-w/borrow)
692   (:translate sb!bignum::%subtract-with-borrow)
693   (:policy :fast-safe)
694   (:args (a :scs (unsigned-reg))
695          (b :scs (unsigned-reg))
696          (c :scs (unsigned-reg)))
697   (:arg-types unsigned-num unsigned-num positive-fixnum)
698   (:results (result :scs (unsigned-reg) :from :load)
699             (borrow :scs (unsigned-reg) :from :eval))
700   (:result-types unsigned-num positive-fixnum)
701   (:generator 4
702     (inst xor c 1 result)
703     (inst subq a result result)
704     (inst subq result b result)
705     (inst srl result 63 borrow)
706     (inst xor borrow 1 borrow)
707     (inst mskll result 4 result)))
708
709 (define-vop (bignum-mult-and-add-3-arg)
710   (:translate sb!bignum::%multiply-and-add)
711   (:policy :fast-safe)
712   (:args (x :scs (unsigned-reg))
713          (y :scs (unsigned-reg))
714          (carry-in :scs (unsigned-reg) :to :save))
715   (:arg-types unsigned-num unsigned-num unsigned-num)
716   (:results (hi :scs (unsigned-reg))
717             (lo :scs (unsigned-reg)))
718   (:result-types unsigned-num unsigned-num)
719   (:generator 6
720     (inst mulq x y lo)
721     (inst addq lo carry-in lo)
722     (inst srl lo 32 hi)
723     (inst mskll lo 4 lo)))
724
725
726 (define-vop (bignum-mult-and-add-4-arg)
727   (:translate sb!bignum::%multiply-and-add)
728   (:policy :fast-safe)
729   (:args (x :scs (unsigned-reg))
730          (y :scs (unsigned-reg))
731          (prev :scs (unsigned-reg))
732          (carry-in :scs (unsigned-reg) :to :save))
733   (:arg-types unsigned-num unsigned-num unsigned-num unsigned-num)
734   (:results (hi :scs (unsigned-reg))
735             (lo :scs (unsigned-reg)))
736   (:result-types unsigned-num unsigned-num)
737   (:generator 9
738     (inst mulq x y lo)
739     (inst addq lo prev lo)
740     (inst addq lo carry-in lo)
741     (inst srl lo 32 hi)
742     (inst mskll lo 4 lo)))
743
744 (define-vop (bignum-mult)
745   (:translate sb!bignum::%multiply)
746   (:policy :fast-safe)
747   (:args (x :scs (unsigned-reg))
748          (y :scs (unsigned-reg)))
749   (:arg-types unsigned-num unsigned-num)
750   (:results (hi :scs (unsigned-reg))
751             (lo :scs (unsigned-reg)))
752   (:result-types unsigned-num unsigned-num)
753   (:generator 3
754     (inst mulq x y lo)
755     (inst srl lo 32 hi)
756     (inst mskll lo 4 lo)))
757
758 (define-vop (bignum-lognot)
759   (:translate sb!bignum::%lognot)
760   (:policy :fast-safe)
761   (:args (x :scs (unsigned-reg)))
762   (:arg-types unsigned-num)
763   (:results (r :scs (unsigned-reg)))
764   (:result-types unsigned-num)
765   (:generator 1
766     (inst not x r)
767     (inst mskll r 4 r)))
768
769 (define-vop (fixnum-to-digit)
770   (:translate sb!bignum::%fixnum-to-digit)
771   (:policy :fast-safe)
772   (:args (fixnum :scs (any-reg)))
773   (:arg-types tagged-num)
774   (:results (digit :scs (unsigned-reg)))
775   (:result-types unsigned-num)
776   (:generator 1
777     (inst sra fixnum 2 digit)))
778
779 (define-vop (bignum-floor)
780   (:translate sb!bignum::%floor)
781   (:policy :fast-safe)
782   (:args (num-high :scs (unsigned-reg))
783          (num-low :scs (unsigned-reg))
784          (denom-arg :scs (unsigned-reg) :target denom))
785   (:arg-types unsigned-num unsigned-num unsigned-num)
786   (:temporary (:scs (unsigned-reg) :from (:argument 2)) denom)
787   (:temporary (:scs (unsigned-reg) :from (:eval 0)) temp)
788   (:results (quo :scs (unsigned-reg) :from (:eval 0))
789             (rem :scs (unsigned-reg) :from (:argument 0)))
790   (:result-types unsigned-num unsigned-num)
791   (:generator 325 ; number of inst assuming targeting works.
792     (inst sll num-high 32 rem)
793     (inst bis rem num-low rem)
794     (inst sll denom-arg 32 denom)
795     (inst cmpule denom rem quo)
796     (inst beq quo shift1)
797     (inst subq rem denom rem)
798     SHIFT1
799     (dotimes (i 32)
800       (let ((shift2 (gen-label)))
801         (inst srl denom 1 denom)
802         (inst cmpule denom rem temp)
803         (inst sll quo 1 quo)
804         (inst beq temp shift2)
805         (inst subq rem denom rem)
806         (inst bis quo 1 quo)
807         (emit-label shift2)))))
808
809 (define-vop (signify-digit)
810   (:translate sb!bignum::%fixnum-digit-with-correct-sign)
811   (:policy :fast-safe)
812   (:args (digit :scs (unsigned-reg) :target res))
813   (:arg-types unsigned-num)
814   (:results (res :scs (any-reg signed-reg)))
815   (:result-types signed-num)
816   (:generator 2
817     (sc-case res
818       (any-reg
819        (inst sll digit 34 res)
820        (inst sra res 32 res))
821       (signed-reg
822        (inst sll digit 32 res)
823        (inst sra res 32 res)))))
824
825
826 (define-vop (digit-ashr)
827   (:translate sb!bignum::%ashr)
828   (:policy :fast-safe)
829   (:args (digit :scs (unsigned-reg))
830          (count :scs (unsigned-reg)))
831   (:arg-types unsigned-num positive-fixnum)
832   (:results (result :scs (unsigned-reg) :from (:argument 0)))
833   (:result-types unsigned-num)
834   (:generator 1
835     (inst sll digit 32 result)
836     (inst sra result count result)
837     (inst srl result 32 result)))
838
839 (define-vop (digit-lshr digit-ashr)
840   (:translate sb!bignum::%digit-logical-shift-right)
841   (:generator 1
842     (inst srl digit count result)))
843
844 (define-vop (digit-ashl digit-ashr)
845   (:translate sb!bignum::%ashl)
846   (:generator 1
847     (inst sll digit count result)))
848 \f
849 ;;;; static functions
850
851 (define-static-fun two-arg-gcd (x y) :translate gcd)
852 (define-static-fun two-arg-lcm (x y) :translate lcm)
853
854 (define-static-fun two-arg-+ (x y) :translate +)
855 (define-static-fun two-arg-- (x y) :translate -)
856 (define-static-fun two-arg-* (x y) :translate *)
857 (define-static-fun two-arg-/ (x y) :translate /)
858
859 (define-static-fun two-arg-< (x y) :translate <)
860 (define-static-fun two-arg-<= (x y) :translate <=)
861 (define-static-fun two-arg-> (x y) :translate >)
862 (define-static-fun two-arg->= (x y) :translate >=)
863 (define-static-fun two-arg-= (x y) :translate =)
864 (define-static-fun two-arg-/= (x y) :translate /=)
865
866 (define-static-fun %negate (x) :translate %negate)
867
868 (define-static-fun two-arg-and (x y) :translate logand)
869 (define-static-fun two-arg-ior (x y) :translate logior)
870 (define-static-fun two-arg-xor (x y) :translate logxor)
871 (define-static-fun two-arg-eqv (x y) :translate logeqv)