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