18870902f14baaf3f7a719743c8d296d4af67290
[sbcl.git] / src / compiler / sparc / arith.lisp
1 ;;;; the VM definition arithmetic VOPs for the SPARC
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 (fast-safe-arith-op)
17   (:policy :fast-safe)
18   (:effects)
19   (:affected))
20
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))
27
28 (define-vop (signed-unop fast-safe-arith-op)
29   (:args (x :scs (signed-reg)))
30   (:results (res :scs (signed-reg)))
31   (:note "inline (signed-byte 32) arithmetic")
32   (:arg-types signed-num)
33   (:result-types signed-num))
34
35 (define-vop (fast-negate/fixnum fixnum-unop)
36   (:translate %negate)
37   (:generator 1
38     (inst neg res x)))
39
40 (define-vop (fast-negate/signed signed-unop)
41   (:translate %negate)
42   (:generator 2
43     (inst neg res x)))
44
45 (define-vop (fast-lognot/fixnum fixnum-unop)
46   (:translate lognot)
47   (:generator 2
48     (inst xor res x (fixnumize -1))))
49
50 (define-vop (fast-lognot/signed signed-unop)
51   (:translate lognot)
52   (:generator 1
53     (inst not res x)))
54 \f
55 ;;;; Binary fixnum operations.
56
57 ;;; Assume that any constant operand is the second arg...
58
59 (define-vop (fast-fixnum-binop fast-safe-arith-op)
60   (:args (x :target r :scs (any-reg zero))
61          (y :target r :scs (any-reg zero)))
62   (:arg-types tagged-num tagged-num)
63   (:results (r :scs (any-reg)))
64   (:result-types tagged-num)
65   (:note "inline fixnum arithmetic"))
66
67 (define-vop (fast-unsigned-binop fast-safe-arith-op)
68   (:args (x :target r :scs (unsigned-reg zero))
69          (y :target r :scs (unsigned-reg zero)))
70   (:arg-types unsigned-num unsigned-num)
71   (:results (r :scs (unsigned-reg)))
72   (:result-types unsigned-num)
73   (:note "inline (unsigned-byte 32) arithmetic"))
74
75 (define-vop (fast-signed-binop fast-safe-arith-op)
76   (:args (x :target r :scs (signed-reg zero))
77          (y :target r :scs (signed-reg zero)))
78   (:arg-types signed-num signed-num)
79   (:results (r :scs (signed-reg)))
80   (:result-types signed-num)
81   (:note "inline (signed-byte 32) arithmetic"))
82
83
84 (define-vop (fast-fixnum-binop-c fast-safe-arith-op)
85   (:args (x :target r :scs (any-reg zero)))
86   (:info y)
87   (:arg-types tagged-num
88               (:constant (and (signed-byte 11) (not (integer 0 0)))))
89   (:results (r :scs (any-reg)))
90   (:result-types tagged-num)
91   (:note "inline fixnum arithmetic"))
92
93 (define-vop (fast-unsigned-binop-c fast-safe-arith-op)
94   (:args (x :target r :scs (unsigned-reg zero)))
95   (:info y)
96   (:arg-types unsigned-num
97               (:constant (and (signed-byte 13) (not (integer 0 0)))))
98   (:results (r :scs (unsigned-reg)))
99   (:result-types unsigned-num)
100   (:note "inline (unsigned-byte 32) arithmetic"))
101
102 (define-vop (fast-signed-binop-c fast-safe-arith-op)
103   (:args (x :target r :scs (signed-reg zero)))
104   (:info y)
105   (:arg-types signed-num
106               (:constant (and (signed-byte 13) (not (integer 0 0)))))
107   (:results (r :scs (signed-reg)))
108   (:result-types signed-num)
109   (:note "inline (signed-byte 32) arithmetic"))
110
111
112 (eval-when (:compile-toplevel :load-toplevel :execute)
113
114 (defmacro define-binop (translate untagged-penalty op
115                         &optional arg-swap restore-fixnum-mask)
116   `(progn
117      (define-vop (,(symbolicate 'fast translate '/fixnum=>fixnum)
118                   fast-fixnum-binop)
119        ,@(when restore-fixnum-mask
120            `((:temporary (:sc non-descriptor-reg) temp)))
121        (:translate ,translate)
122        (:generator 2
123          ,(if arg-swap
124               `(inst ,op ,(if restore-fixnum-mask 'temp 'r) y x)
125               `(inst ,op ,(if restore-fixnum-mask 'temp 'r) x y))
126          ,@(when restore-fixnum-mask
127              `((inst andn r temp fixnum-tag-mask)))))
128      ,@(unless arg-swap
129          `((define-vop (,(symbolicate 'fast- translate '-c/fixnum=>fixnum)
130                         fast-fixnum-binop-c)
131              ,@(when restore-fixnum-mask
132                  `((:temporary (:sc non-descriptor-reg) temp)))
133              (:translate ,translate)
134              (:generator 1
135                (inst ,op ,(if restore-fixnum-mask 'temp 'r) x (fixnumize y))
136                ,@(when restore-fixnum-mask
137                    `((inst andn r temp fixnum-tag-mask)))))))
138      (define-vop (,(symbolicate 'fast- translate '/signed=>signed)
139                   fast-signed-binop)
140        (:translate ,translate)
141        (:generator ,(1+ untagged-penalty)
142          ,(if arg-swap
143               `(inst ,op r y x)
144               `(inst ,op r x y))))
145      ,@(unless arg-swap
146          `((define-vop (,(symbolicate 'fast- translate '-c/signed=>signed)
147                         fast-signed-binop-c)
148              (:translate ,translate)
149              (:generator ,untagged-penalty
150                (inst ,op r x y)))))
151      (define-vop (,(symbolicate 'fast- translate '/unsigned=>unsigned)
152                   fast-unsigned-binop)
153        (:translate ,translate)
154        (:generator ,(1+ untagged-penalty)
155          ,(if arg-swap
156               `(inst ,op r y x)
157               `(inst ,op r x y))))
158      ,@(unless arg-swap
159          `((define-vop (,(symbolicate 'fast- translate '-c/unsigned=>unsigned)
160                         fast-unsigned-binop-c)
161              (:translate ,translate)
162              (:generator ,untagged-penalty
163                (inst ,op r x y)))))))
164
165 ); eval-when
166
167 (define-binop + 4 add)
168 (define-binop - 4 sub)
169 (define-binop logand 2 and)
170 (define-binop logandc1 2 andn t)
171 (define-binop logandc2 2 andn)
172 (define-binop logior 2 or)
173 (define-binop logorc1 2 orn t t)
174 (define-binop logorc2 2 orn nil t)
175 (define-binop logxor 2 xor)
176 (define-binop logeqv 2 xnor nil t)
177
178 ;;; Special case fixnum + and - that trap on overflow.  Useful when we
179 ;;; don't know that the output type is a fixnum.
180
181 ;;; I (Raymond Toy) took these out. They don't seem to be used
182 ;;; anywhere at all.
183 #+nil
184 (progn
185 (define-vop (+/fixnum fast-+/fixnum=>fixnum)
186   (:policy :safe)
187   (:results (r :scs (any-reg descriptor-reg)))
188   (:result-types tagged-num)
189   (:note "safe inline fixnum arithmetic")
190   (:generator 4
191     (inst taddcctv r x y)))
192
193 (define-vop (+-c/fixnum fast-+-c/fixnum=>fixnum)
194   (:policy :safe)
195   (:results (r :scs (any-reg descriptor-reg)))
196   (:result-types tagged-num)
197   (:note "safe inline fixnum arithmetic")
198   (:generator 3
199     (inst taddcctv r x (fixnumize y))))
200
201 (define-vop (-/fixnum fast--/fixnum=>fixnum)
202   (:policy :safe)
203   (:results (r :scs (any-reg descriptor-reg)))
204   (:result-types tagged-num)
205   (:note "safe inline fixnum arithmetic")
206   (:generator 4
207     (inst tsubcctv r x y)))
208
209 (define-vop (--c/fixnum fast---c/fixnum=>fixnum)
210   (:policy :safe)
211   (:results (r :scs (any-reg descriptor-reg)))
212   (:result-types tagged-num)
213   (:note "safe inline fixnum arithmetic")
214   (:generator 3
215     (inst tsubcctv r x (fixnumize y))))
216
217 )
218
219 ;;; Truncate
220
221 ;; This doesn't work for some reason.
222 #+nil
223 (define-vop (fast-v8-truncate/fixnum=>fixnum fast-safe-arith-op)
224   (:translate truncate)
225   (:args (x :scs (any-reg))
226          (y :scs (any-reg)))
227   (:arg-types tagged-num tagged-num)
228   (:results (quo :scs (any-reg))
229             (rem :scs (any-reg)))
230   (:result-types tagged-num tagged-num)
231   (:note "inline fixnum arithmetic")
232   (:temporary (:scs (any-reg) :target quo) q)
233   (:temporary (:scs (any-reg)) r)
234   (:temporary (:scs (signed-reg)) y-int)
235   (:vop-var vop)
236   (:save-p :compute-only)
237   (:guard (or (member :sparc-v8 *backend-subfeatures*)
238               (and (member :sparc-v9 *backend-subfeatures*)
239                    (not (member :sparc-64 *backend-subfeatures*)))))
240   (:generator 12
241     (let ((zero (generate-error-code vop division-by-zero-error x y)))
242       (inst cmp y zero-tn)
243       (inst b :eq zero)
244       ;; Extend the sign of X into the Y register
245         (inst sra r x 31)
246       (inst wry r)
247       ;; Remove tag bits so Q and R will be tagged correctly.
248       (inst sra y-int y n-fixnum-tag-bits)
249       (inst nop)
250       (inst nop)
251
252       (inst sdiv q x y-int)             ; Q is tagged.
253       ;; We have the quotient so we need to compute the remainder
254       (inst smul r q y-int)             ; R is tagged
255       (inst sub rem x r)
256       (unless (location= quo q)
257         (move quo q)))))
258
259 (define-vop (fast-v8-truncate/signed=>signed fast-safe-arith-op)
260   (:translate truncate)
261   (:args (x :scs (signed-reg))
262          (y :scs (signed-reg)))
263   (:arg-types signed-num signed-num)
264   (:results (quo :scs (signed-reg))
265             (rem :scs (signed-reg)))
266   (:result-types signed-num signed-num)
267   (:note "inline (signed-byte 32) arithmetic")
268   (:temporary (:scs (signed-reg) :target quo) q)
269   (:temporary (:scs (signed-reg)) r)
270   (:vop-var vop)
271   (:save-p :compute-only)
272   (:guard (or (member :sparc-v8 *backend-subfeatures*)
273               (and (member :sparc-v9 *backend-subfeatures*)
274                    (not (member :sparc-64 *backend-subfeatures*)))))
275   (:generator 12
276     (let ((zero (generate-error-code vop division-by-zero-error x y)))
277       (inst cmp y zero-tn)
278       (if (member :sparc-v9 *backend-subfeatures*)
279           (inst b :eq zero :pn)
280           (inst b :eq zero))
281       ;; Extend the sign of X into the Y register
282       (inst sra r x 31)
283       (inst wry r)
284       (inst nop)
285       (inst nop)
286       (inst nop)
287
288       (inst sdiv q x y)
289       ;; We have the quotient so we need to compue the remainder
290       (inst smul r q y)         ; rem
291       (inst sub rem x r)
292       (unless (location= quo q)
293         (move quo q)))))
294
295 (define-vop (fast-v8-truncate/unsigned=>unsigned fast-safe-arith-op)
296   (:translate truncate)
297   (:args (x :scs (unsigned-reg))
298          (y :scs (unsigned-reg)))
299   (:arg-types unsigned-num unsigned-num)
300   (:results (quo :scs (unsigned-reg))
301             (rem :scs (unsigned-reg)))
302   (:result-types unsigned-num unsigned-num)
303   (:note "inline (unsigned-byte 32) arithmetic")
304   (:temporary (:scs (unsigned-reg) :target quo) q)
305   (:temporary (:scs (unsigned-reg)) r)
306   (:vop-var vop)
307   (:save-p :compute-only)
308   (:guard (or (member :sparc-v8 *backend-subfeatures*)
309               (and (member :sparc-v9 *backend-subfeatures*)
310                    (not (member :sparc-64 *backend-subfeatures*)))))
311   (:generator 8
312     (let ((zero (generate-error-code vop division-by-zero-error x y)))
313       (inst cmp y zero-tn)
314       (if (member :sparc-v9 *backend-subfeatures*)
315           (inst b :eq zero :pn)
316           (inst b :eq zero))
317       (inst wry zero-tn)                ; Clear out high part
318       (inst nop)
319       (inst nop)
320       (inst nop)
321       
322       (inst udiv q x y)
323       ;; Compute remainder
324       (inst umul r q y)
325       (inst sub rem x r)
326       (unless (location= quo q)
327         (inst move quo q)))))
328
329 (define-vop (fast-v9-truncate/signed=>signed fast-safe-arith-op)
330   (:translate truncate)
331   (:args (x :scs (signed-reg))
332          (y :scs (signed-reg)))
333   (:arg-types signed-num signed-num)
334   (:results (quo :scs (signed-reg))
335             (rem :scs (signed-reg)))
336   (:result-types signed-num signed-num)
337   (:note "inline (signed-byte 32) arithmetic")
338   (:temporary (:scs (signed-reg) :target quo) q)
339   (:temporary (:scs (signed-reg)) r)
340   (:vop-var vop)
341   (:save-p :compute-only)
342   (:guard (member :sparc-64 *backend-subfeatures*))
343   (:generator 8
344     (let ((zero (generate-error-code vop division-by-zero-error x y)))
345       (inst cmp y zero-tn)
346       (inst b :eq zero :pn)
347       ;; Sign extend the numbers, just in case.
348       (inst sra x 0)
349       (inst sra y 0)
350       (inst sdivx q x y)
351       ;; Compute remainder
352       (inst mulx r q y)
353       (inst sub rem x r)
354       (unless (location= quo q)
355         (inst move quo q)))))
356
357 (define-vop (fast-v9-truncate/unsigned=>unsigned fast-safe-arith-op)
358   (:translate truncate)
359   (:args (x :scs (unsigned-reg))
360          (y :scs (unsigned-reg)))
361   (:arg-types unsigned-num unsigned-num)
362   (:results (quo :scs (unsigned-reg))
363             (rem :scs (unsigned-reg)))
364   (:result-types unsigned-num unsigned-num)
365   (:note "inline (unsigned-byte 32) arithmetic")
366   (:temporary (:scs (unsigned-reg) :target quo) q)
367   (:temporary (:scs (unsigned-reg)) r)
368   (:vop-var vop)
369   (:save-p :compute-only)
370   (:guard (member :sparc-64 *backend-subfeatures*))
371   (:generator 8
372     (let ((zero (generate-error-code vop division-by-zero-error x y)))
373       (inst cmp y zero-tn)
374       (inst b :eq zero :pn)
375       ;; Zap the higher 32 bits, just in case
376       (inst srl x 0)
377       (inst srl y 0)
378       (inst udivx q x y)
379       ;; Compute remainder
380       (inst mulx r q y)
381       (inst sub rem x r)
382       (unless (location= quo q)
383         (inst move quo q)))))
384
385 ;;; Shifting
386
387 (define-vop (fast-ash/signed=>signed)
388   (:note "inline ASH")
389   (:args (number :scs (signed-reg) :to :save)
390          (amount :scs (signed-reg immediate) :to :save))
391   (:arg-types signed-num signed-num)
392   (:results (result :scs (signed-reg)))
393   (:result-types signed-num)
394   (:translate ash)
395   (:policy :fast-safe)
396   (:temporary (:sc non-descriptor-reg) ndesc)
397   (:generator 5
398     (sc-case amount
399       (signed-reg
400        (let ((done (gen-label)))
401          (inst cmp amount)
402          (inst b :ge done)
403          ;; The result-type assures us that this shift will not
404          ;; overflow.
405          (inst sll result number amount)
406          (inst neg ndesc amount)
407          (inst cmp ndesc 31)
408          (if (member :sparc-v9 *backend-subfeatures*)
409              (progn
410                (inst cmove :ge ndesc 31)
411                (inst sra result number ndesc))
412              (progn
413                (inst b :le done)
414                (inst sra result number ndesc)
415                (inst sra result number 31)))
416          (emit-label done)))
417       (immediate
418        (bug "IMMEDIATE case in ASH VOP; should have been transformed")))))
419
420 (define-vop (fast-ash/unsigned=>unsigned)
421   (:note "inline ASH")
422   (:args (number :scs (unsigned-reg) :to :save)
423          (amount :scs (signed-reg immediate) :to :save))
424   (:arg-types unsigned-num signed-num)
425   (:results (result :scs (unsigned-reg)))
426   (:result-types unsigned-num)
427   (:translate ash)
428   (:policy :fast-safe)
429   (:temporary (:sc non-descriptor-reg) ndesc)
430   (:generator 5
431     (sc-case amount
432       (signed-reg
433        (let ((done (gen-label)))
434          (inst cmp amount)
435          (inst b :ge done)
436          ;; The result-type assures us that this shift will not
437          ;; overflow.
438          (inst sll result number amount)
439          (inst neg ndesc amount)
440          (inst cmp ndesc 32)
441          (if (member :sparc-v9 *backend-subfeatures*)
442              (progn
443                (inst srl result number ndesc)
444                (inst cmove :ge result zero-tn))
445              (progn
446                (inst b :lt done)
447                (inst srl result number ndesc)
448                (move result zero-tn)))
449          (emit-label done)))
450       (immediate
451        (bug "IMMEDIATE case in ASH VOP; should have been transformed")))))
452
453 ;; Some special cases where we know we want a left shift.  Just do the
454 ;; shift, instead of checking for the sign of the shift.
455 (macrolet
456     ((frob (name sc-type type result-type cost)
457        `(define-vop (,name)
458          (:note "inline ASH")
459          (:translate ash)
460          (:args (number :scs (,sc-type))
461                 (amount :scs (signed-reg unsigned-reg immediate)))
462          (:arg-types ,type positive-fixnum)
463          (:results (result :scs (,result-type)))
464          (:result-types ,type)
465          (:policy :fast-safe)
466          (:generator ,cost
467           ;; The result-type assures us that this shift will not
468           ;; overflow. And for fixnums, the zero bits that get
469           ;; shifted in are just fine for the fixnum tag.
470           (sc-case amount
471            ((signed-reg unsigned-reg)
472             (inst sll result number amount))
473            (immediate
474             (let ((amount (tn-value amount)))
475               (assert (>= amount 0))
476               (inst sll result number amount))))))))
477   (frob fast-ash-left/signed=>signed signed-reg signed-num signed-reg 3)
478   (frob fast-ash-left/fixnum=>fixnum any-reg tagged-num any-reg 2)
479   (frob fast-ash-left/unsigned=>unsigned unsigned-reg unsigned-num unsigned-reg 3))
480
481 (defknown ash-right-signed ((signed-byte #.sb!vm:n-word-bits)
482                             (and fixnum unsigned-byte))
483   (signed-byte #.sb!vm:n-word-bits)
484   (movable foldable flushable))
485
486 (defknown ash-right-unsigned ((unsigned-byte #.sb!vm:n-word-bits)
487                               (and fixnum unsigned-byte))
488   (unsigned-byte #.sb!vm:n-word-bits)
489   (movable foldable flushable))
490
491 ;; Some special cases where we want a right shift.  Just do the shift.
492 ;; (Needs appropriate deftransforms to call these, though.)
493
494 (macrolet
495     ((frob (trans name sc-type type shift-inst cost)
496        `(define-vop (,name)
497          (:note "inline right ASH")
498          (:translate ,trans)
499          (:args (number :scs (,sc-type))
500                 (amount :scs (signed-reg unsigned-reg immediate)))
501          (:arg-types ,type positive-fixnum)
502          (:results (result :scs (,sc-type)))
503          (:result-types ,type)
504          (:policy :fast-safe)
505          (:generator ,cost
506             (sc-case amount
507              ((signed-reg unsigned-reg)
508                 (inst ,shift-inst result number amount))
509              (immediate
510               (let ((amt (tn-value amount)))
511                 (inst ,shift-inst result number amt))))))))
512   (frob ash-right-signed fast-ash-right/signed=>signed
513         signed-reg signed-num sra 3)
514   (frob ash-right-unsigned fast-ash-right/unsigned=>unsigned
515         unsigned-reg unsigned-num srl 3))
516
517 (define-vop (fast-ash-right/fixnum=>fixnum)
518     (:note "inline right ASH")
519   (:translate ash-right-signed)
520   (:args (number :scs (any-reg))
521          (amount :scs (signed-reg unsigned-reg immediate)))
522   (:arg-types tagged-num positive-fixnum)
523   (:results (result :scs (any-reg)))
524   (:result-types tagged-num)
525   (:temporary (:sc non-descriptor-reg :target result) temp)
526   (:policy :fast-safe)
527   (:generator 2
528     ;; Shift the fixnum right by the desired amount.  Then zap out the
529     ;; 2 LSBs to make it a fixnum again.  (Those bits are junk.)
530     (sc-case amount
531       ((signed-reg unsigned-reg)
532        (inst sra temp number amount))
533       (immediate
534        (inst sra temp number (tn-value amount))))
535     (inst andn result temp fixnum-tag-mask)))
536     
537
538
539 \f
540 (define-vop (signed-byte-32-len)
541   (:translate integer-length)
542   (:note "inline (signed-byte 32) integer-length")
543   (:policy :fast-safe)
544   (:args (arg :scs (signed-reg) :target shift))
545   (:arg-types signed-num)
546   (:results (res :scs (any-reg)))
547   (:result-types positive-fixnum)
548   (:temporary (:scs (non-descriptor-reg) :from (:argument 0)) shift)
549   (:generator 30
550     (let ((loop (gen-label))
551           (test (gen-label)))
552       (inst addcc shift zero-tn arg)
553       (inst b :ge test)
554       (move res zero-tn)
555       (inst b test)
556       (inst not shift)
557
558       (emit-label loop)
559       (inst add res (fixnumize 1))
560       
561       (emit-label test)
562       (inst cmp shift)
563       (inst b :ne loop)
564       (inst srl shift 1))))
565
566 (define-vop (unsigned-byte-32-count)
567   (:translate logcount)
568   (:note "inline (unsigned-byte 32) logcount")
569   (:policy :fast-safe)
570   (:args (arg :scs (unsigned-reg)))
571   (:arg-types unsigned-num)
572   (:results (res :scs (unsigned-reg)))
573   (:result-types positive-fixnum)
574   (:temporary (:scs (non-descriptor-reg) :from (:argument 0)) mask temp)
575   (:generator 35
576       (move res arg)
577
578       (dolist (stuff '((1 #x55555555) (2 #x33333333) (4 #x0f0f0f0f)
579                        (8 #x00ff00ff) (16 #x0000ffff)))
580         (destructuring-bind (shift bit-mask)
581             stuff
582           ;; Set mask
583           (inst sethi mask (ldb (byte 22 10) bit-mask))
584           (inst add mask (ldb (byte 10 0) bit-mask))
585
586           (inst and temp res mask)
587           (inst srl res shift)
588           (inst and res mask)
589           (inst add res temp)))))
590
591
592 ;;; Multiply and Divide.
593
594 (define-vop (fast-v8-*/fixnum=>fixnum fast-fixnum-binop)
595   (:temporary (:scs (non-descriptor-reg)) temp)
596   (:translate *)
597   (:guard (or (member :sparc-v8 *backend-subfeatures*)
598               (and (member :sparc-v9 *backend-subfeatures*)
599                    (not (member :sparc-64 *backend-subfeatures*)))))
600   (:generator 2
601     ;; The cost here should be less than the cost for
602     ;; */signed=>signed.  Why?  A fixnum product using signed=>signed
603     ;; has to convert both args to signed-nums.  But using this, we
604     ;; don't have to and that saves an instruction.
605     (inst sra temp y n-fixnum-tag-bits)
606     (inst smul r x temp)))
607
608 (define-vop (fast-v8-*-c/fixnum=>fixnum fast-safe-arith-op)
609   (:args (x :target r :scs (any-reg zero)))
610   (:info y)
611   (:arg-types tagged-num
612               (:constant (and (signed-byte 13) (not (integer 0 0)))))
613   (:results (r :scs (any-reg)))
614   (:result-types tagged-num)
615   (:note "inline fixnum arithmetic")
616   (:translate *)
617   (:guard (or (member :sparc-v8 *backend-subfeatures*)
618               (and (member :sparc-v9 *backend-subfeatures*)
619                    (not (member :sparc-64 *backend-subfeatures*)))))
620   (:generator 1
621     (inst smul r x y)))
622
623 (define-vop (fast-v8-*/signed=>signed fast-signed-binop)
624   (:translate *)
625   (:guard (or (member :sparc-v8 *backend-subfeatures*)
626               (and (member :sparc-v9 *backend-subfeatures*)
627                    (not (member :sparc-64 *backend-subfeatures*)))))
628   (:generator 3
629     (inst smul r x y)))
630
631 (define-vop (fast-v8-*-c/signed=>signed fast-signed-binop-c)
632   (:translate *)
633   (:guard (or (member :sparc-v8 *backend-subfeatures*)
634               (and (member :sparc-v9 *backend-subfeatures*)
635                    (not (member :sparc-64 *backend-subfeatures*)))))
636   (:generator 2
637     (inst smul r x y)))
638           
639 (define-vop (fast-v8-*/unsigned=>unsigned fast-unsigned-binop)
640   (:translate *)
641   (:guard (or (member :sparc-v8 *backend-subfeatures*)
642               (and (member :sparc-v9 *backend-subfeatures*)
643                    (not (member :sparc-64 *backend-subfeatures*)))))
644   (:generator 3
645     (inst umul r x y)))
646
647 (define-vop (fast-v8-*-c/unsigned=>unsigned fast-unsigned-binop-c)
648   (:translate *)
649   (:guard (or (member :sparc-v8 *backend-subfeatures*)
650               (and (member :sparc-v9 *backend-subfeatures*)
651                    (not (member :sparc-64 *backend-subfeatures*)))))
652   (:generator 2
653     (inst umul r x y)))
654
655 ;; The smul and umul instructions are deprecated on the Sparc V9.  Use
656 ;; mulx instead.
657 (define-vop (fast-v9-*/fixnum=>fixnum fast-fixnum-binop)
658   (:temporary (:scs (non-descriptor-reg)) temp)
659   (:translate *)
660   (:guard (member :sparc-64 *backend-subfeatures*))
661   (:generator 4
662     (inst sra temp y n-fixnum-tag-bits)
663     (inst mulx r x temp)))
664
665 (define-vop (fast-v9-*/signed=>signed fast-signed-binop)
666   (:translate *)
667   (:guard (member :sparc-64 *backend-subfeatures*))
668   (:generator 3
669     (inst mulx r x y)))
670
671 (define-vop (fast-v9-*/unsigned=>unsigned fast-unsigned-binop)
672   (:translate *)
673   (:guard (member :sparc-64 *backend-subfeatures*))
674   (:generator 3
675     (inst mulx r x y)))
676
677 \f
678 ;;;; Modular functions:
679 (define-modular-fun lognot-mod32 (x) lognot 32)
680 (define-vop (lognot-mod32/unsigned=>unsigned)
681   (:translate lognot-mod32)
682   (:args (x :scs (unsigned-reg)))
683   (:arg-types unsigned-num)
684   (:results (res :scs (unsigned-reg)))
685   (:result-types unsigned-num)
686   (:policy :fast-safe)
687   (:generator 1
688     (inst not res x)))
689
690 (macrolet
691     ((define-modular-backend (fun &optional constantp)
692        (let ((mfun-name (symbolicate fun '-mod32))
693              (modvop (symbolicate 'fast- fun '-mod32/unsigned=>unsigned))
694              (modcvop (symbolicate 'fast- fun 'mod32-c/unsigned=>unsigned))
695              (vop (symbolicate 'fast- fun '/unsigned=>unsigned))
696              (cvop (symbolicate 'fast- fun '-c/unsigned=>unsigned)))
697          `(progn
698             (define-modular-fun ,mfun-name (x y) ,fun 32)
699             (define-vop (,modvop ,vop)
700               (:translate ,mfun-name))
701             ,@(when constantp
702                 `((define-vop (,modcvop ,cvop)
703                     (:translate ,mfun-name))))))))
704   (define-modular-backend + t)
705   (define-modular-backend logxor t)
706   (define-modular-backend logeqv t)
707   (define-modular-backend logandc1)
708   (define-modular-backend logandc2 t)
709   (define-modular-backend logorc1)
710   (define-modular-backend logorc2 t))
711
712 (define-source-transform lognand (x y)
713   `(lognot (logand ,x ,y)))
714 (define-source-transform lognor (x y)
715   `(lognot (logior ,x ,y)))
716 \f
717 ;;;; Binary conditional VOPs:
718
719 (define-vop (fast-conditional)
720   (:conditional)
721   (:info target not-p)
722   (:effects)
723   (:affected)
724   (:policy :fast-safe))
725
726 (define-vop (fast-conditional/fixnum fast-conditional)
727   (:args (x :scs (any-reg zero))
728          (y :scs (any-reg zero)))
729   (:arg-types tagged-num tagged-num)
730   (:note "inline fixnum comparison"))
731
732 (define-vop (fast-conditional-c/fixnum fast-conditional/fixnum)
733   (:args (x :scs (any-reg zero)))
734   (:arg-types tagged-num (:constant (signed-byte 11)))
735   (:info target not-p y))
736
737 (define-vop (fast-conditional/signed fast-conditional)
738   (:args (x :scs (signed-reg zero))
739          (y :scs (signed-reg zero)))
740   (:arg-types signed-num signed-num)
741   (:note "inline (signed-byte 32) comparison"))
742
743 (define-vop (fast-conditional-c/signed fast-conditional/signed)
744   (:args (x :scs (signed-reg zero)))
745   (:arg-types signed-num (:constant (signed-byte 13)))
746   (:info target not-p y))
747
748 (define-vop (fast-conditional/unsigned fast-conditional)
749   (:args (x :scs (unsigned-reg zero))
750          (y :scs (unsigned-reg zero)))
751   (:arg-types unsigned-num unsigned-num)
752   (:note "inline (unsigned-byte 32) comparison"))
753
754 (define-vop (fast-conditional-c/unsigned fast-conditional/unsigned)
755   (:args (x :scs (unsigned-reg zero)))
756   (:arg-types unsigned-num (:constant (unsigned-byte 12)))
757   (:info target not-p y))
758
759
760 (defmacro define-conditional-vop (tran cond unsigned not-cond not-unsigned)
761   `(progn
762      ,@(mapcar (lambda (suffix cost signed)
763                  (unless (and (member suffix '(/fixnum -c/fixnum))
764                               (eq tran 'eql))
765                    `(define-vop (,(intern (format nil "~:@(FAST-IF-~A~A~)"
766                                                   tran suffix))
767                                  ,(intern
768                                    (format nil "~:@(FAST-CONDITIONAL~A~)"
769                                            suffix)))
770                      (:translate ,tran)
771                      (:generator ,cost
772                       (inst cmp x
773                        ,(if (eq suffix '-c/fixnum) '(fixnumize y) 'y))
774                       (inst b (if not-p
775                                   ,(if signed not-cond not-unsigned)
776                                   ,(if signed cond unsigned))
777                        target)
778                       (inst nop)))))
779                '(/fixnum -c/fixnum /signed -c/signed /unsigned -c/unsigned)
780                '(4 3 6 5 6 5)
781                '(t t t t nil nil))))
782
783 (define-conditional-vop < :lt :ltu :ge :geu)
784
785 (define-conditional-vop > :gt :gtu :le :leu)
786
787 (define-conditional-vop eql :eq :eq :ne :ne)
788
789 ;;; EQL/FIXNUM is funny because the first arg can be of any type, not just a
790 ;;; known fixnum.
791
792 ;;; These versions specify a fixnum restriction on their first arg.  We have
793 ;;; also generic-eql/fixnum VOPs which are the same, but have no restriction on
794 ;;; the first arg and a higher cost.  The reason for doing this is to prevent
795 ;;; fixnum specific operations from being used on word integers, spuriously
796 ;;; consing the argument.
797 ;;;
798
799 (define-vop (fast-eql/fixnum fast-conditional)
800   (:args (x :scs (any-reg descriptor-reg zero))
801          (y :scs (any-reg zero)))
802   (:arg-types tagged-num tagged-num)
803   (:note "inline fixnum comparison")
804   (:translate eql)
805   (:generator 4
806     (inst cmp x y)
807     (inst b (if not-p :ne :eq) target)
808     (inst nop)))
809 ;;;
810 (define-vop (generic-eql/fixnum fast-eql/fixnum)
811   (:arg-types * tagged-num)
812   (:variant-cost 7))
813
814 (define-vop (fast-eql-c/fixnum fast-conditional/fixnum)
815   (:args (x :scs (any-reg descriptor-reg zero)))
816   (:arg-types tagged-num (:constant (signed-byte 11)))
817   (:info target not-p y)
818   (:translate eql)
819   (:generator 2
820     (inst cmp x (fixnumize y))
821     (inst b (if not-p :ne :eq) target)
822     (inst nop)))
823 ;;;
824 (define-vop (generic-eql-c/fixnum fast-eql-c/fixnum)
825   (:arg-types * (:constant (signed-byte 11)))
826   (:variant-cost 6))
827
828 \f
829 ;;;; 32-bit logical operations
830
831 (define-vop (merge-bits)
832   (:translate merge-bits)
833   (:args (shift :scs (signed-reg unsigned-reg))
834          (prev :scs (unsigned-reg))
835          (next :scs (unsigned-reg)))
836   (:arg-types tagged-num unsigned-num unsigned-num)
837   (:temporary (:scs (unsigned-reg) :to (:result 0)) temp)
838   (:temporary (:scs (unsigned-reg) :to (:result 0) :target result) res)
839   (:results (result :scs (unsigned-reg)))
840   (:result-types unsigned-num)
841   (:policy :fast-safe)
842   (:generator 4
843     (let ((done (gen-label)))
844       (inst cmp shift)
845       (inst b :eq done)
846       (inst srl res next shift)
847       (inst sub temp zero-tn shift)
848       (inst sll temp prev temp)
849       (inst or res temp)
850       (emit-label done)
851       (move result res))))
852
853 (define-source-transform 32bit-logical-not (x)
854   `(logand (lognot (the (unsigned-byte 32) ,x)) #.(1- (ash 1 32))))
855
856 (deftransform 32bit-logical-and ((x y))
857   '(logand x y))
858
859 (deftransform 32bit-logical-nand ((x y))
860   '(logand (lognand x y) #.(1- (ash 1 32))))
861
862 (deftransform 32bit-logical-or ((x y))
863   '(logior x y))
864
865 (deftransform 32bit-logical-nor ((x y))
866   '(logand (lognor x y) #.(1- (ash 1 32))))
867
868 (deftransform 32bit-logical-xor ((x y))
869   '(logxor x y))
870
871 (deftransform 32bit-logical-eqv ((x y))
872   '(logand (logeqv x y) #.(1- (ash 1 32))))
873
874 (deftransform 32bit-logical-orc1 ((x y))
875   '(logand (logorc1 x y) #.(1- (ash 1 32))))
876
877 (deftransform 32bit-logical-orc2 ((x y))
878   '(logand (logorc2 x y) #.(1- (ash 1 32))))
879
880 (deftransform 32bit-logical-andc1 ((x y))
881   '(logand (logandc1 x y) #.(1- (ash 1 32))))
882
883 (deftransform 32bit-logical-andc2 ((x y))
884   '(logand (logandc2 x y) #.(1- (ash 1 32))))
885
886 (define-vop (shift-towards-someplace)
887   (:policy :fast-safe)
888   (:args (num :scs (unsigned-reg))
889          (amount :scs (signed-reg)))
890   (:arg-types unsigned-num tagged-num)
891   (:results (r :scs (unsigned-reg)))
892   (:result-types unsigned-num))
893
894 (define-vop (shift-towards-start shift-towards-someplace)
895   (:translate shift-towards-start)
896   (:note "shift-towards-start")
897   (:generator 1
898     (inst sll r num amount)))
899
900 (define-vop (shift-towards-end shift-towards-someplace)
901   (:translate shift-towards-end)
902   (:note "shift-towards-end")
903   (:generator 1
904     (inst srl r num amount)))
905 \f
906 ;;;; Bignum stuff.
907
908 (define-vop (bignum-length get-header-data)
909   (:translate sb!bignum::%bignum-length)
910   (:policy :fast-safe))
911
912 (define-vop (bignum-set-length set-header-data)
913   (:translate sb!bignum::%bignum-set-length)
914   (:policy :fast-safe))
915
916 (define-vop (bignum-ref word-index-ref)
917   (:variant bignum-digits-offset other-pointer-lowtag)
918   (:translate sb!bignum::%bignum-ref)
919   (:results (value :scs (unsigned-reg)))
920   (:result-types unsigned-num))
921
922 (define-vop (bignum-set word-index-set)
923   (:variant bignum-digits-offset other-pointer-lowtag)
924   (:translate sb!bignum::%bignum-set)
925   (:args (object :scs (descriptor-reg))
926          (index :scs (any-reg immediate zero))
927          (value :scs (unsigned-reg)))
928   (:arg-types t positive-fixnum unsigned-num)
929   (:results (result :scs (unsigned-reg)))
930   (:result-types unsigned-num))
931
932 (define-vop (digit-0-or-plus)
933   (:translate sb!bignum::%digit-0-or-plusp)
934   (:policy :fast-safe)
935   (:args (digit :scs (unsigned-reg)))
936   (:arg-types unsigned-num)
937   (:results (result :scs (descriptor-reg)))
938   (:guard (not (member :sparc-v9 *backend-subfeatures*)))
939   (:generator 3
940     (let ((done (gen-label)))
941       (inst cmp digit)
942       (inst b :lt done)
943       (move result null-tn)
944       (load-symbol result t)
945       (emit-label done))))
946
947 (define-vop (v9-digit-0-or-plus-cmove)
948   (:translate sb!bignum::%digit-0-or-plusp)
949   (:policy :fast-safe)
950   (:args (digit :scs (unsigned-reg)))
951   (:arg-types unsigned-num)
952   (:results (result :scs (descriptor-reg)))
953   (:guard (member :sparc-v9 *backend-subfeatures*))
954   (:generator 3
955     (inst cmp digit)
956     (load-symbol result t)
957     (inst cmove :lt result null-tn)))
958
959 ;; This doesn't work?
960 #+nil
961 (define-vop (v9-digit-0-or-plus-movr)
962   (:translate sb!bignum::%digit-0-or-plusp)
963   (:policy :fast-safe)
964   (:args (digit :scs (unsigned-reg)))
965   (:arg-types unsigned-num)
966   (:results (result :scs (descriptor-reg)))
967   (:temporary (:scs (descriptor-reg)) temp)
968   (:guard #!+:sparc-v9 t #!-:sparc-v9 nil)
969   (:generator 2
970     (load-symbol temp t)
971     (inst movr result null-tn digit :lz)
972     (inst movr result temp digit :gez)))
973
974
975 (define-vop (add-w/carry)
976   (:translate sb!bignum::%add-with-carry)
977   (:policy :fast-safe)
978   (:args (a :scs (unsigned-reg))
979          (b :scs (unsigned-reg))
980          (c :scs (any-reg)))
981   (:arg-types unsigned-num unsigned-num positive-fixnum)
982   (:results (result :scs (unsigned-reg))
983             (carry :scs (unsigned-reg)))
984   (:result-types unsigned-num positive-fixnum)
985   (:generator 3
986     (inst addcc zero-tn c -1)
987     (inst addxcc result a b)
988     (inst addx carry zero-tn zero-tn)))
989
990 (define-vop (sub-w/borrow)
991   (:translate sb!bignum::%subtract-with-borrow)
992   (:policy :fast-safe)
993   (:args (a :scs (unsigned-reg))
994          (b :scs (unsigned-reg))
995          (c :scs (any-reg)))
996   (:arg-types unsigned-num unsigned-num positive-fixnum)
997   (:results (result :scs (unsigned-reg))
998             (borrow :scs (unsigned-reg)))
999   (:result-types unsigned-num positive-fixnum)
1000   (:generator 4
1001     (inst subcc zero-tn c 1)
1002     (inst subxcc result a b)
1003     (inst addx borrow zero-tn zero-tn)
1004     (inst xor borrow 1)))
1005
1006 ;;; EMIT-MULTIPLY -- This is used both for bignum stuff and in assembly
1007 ;;; routines.
1008 ;;; 
1009 (defun emit-multiply (multiplier multiplicand result-high result-low)
1010   "Emit code to multiply MULTIPLIER with MULTIPLICAND, putting the result
1011   in RESULT-HIGH and RESULT-LOW.  KIND is either :signed or :unsigned.
1012   Note: the lifetimes of MULTIPLICAND and RESULT-HIGH overlap."
1013   (declare (type tn multiplier result-high result-low)
1014            (type (or tn (signed-byte 13)) multiplicand))
1015   ;; It seems that emit-multiply is only used to do an unsigned
1016   ;; multiply, so the code only does an unsigned multiply.
1017   (cond
1018     ((member :sparc-64 *backend-subfeatures*)
1019      ;; Take advantage of V9's 64-bit multiplier.
1020      ;;
1021      ;; Make sure the multiplier and multiplicand are really
1022      ;; unsigned 64-bit numbers.
1023      (inst srl multiplier 0)
1024      (inst srl multiplicand 0)
1025   
1026      ;; Multiply the two numbers and put the result in
1027      ;; result-high.  Copy the low 32-bits to result-low.  Then
1028      ;; shift result-high so the high 32-bits end up in the low
1029      ;; 32-bits.
1030      (inst mulx result-high multiplier multiplicand)
1031      (inst move result-low result-high)
1032      (inst srax result-high 32))
1033     ((or (member :sparc-v8 *backend-subfeatures*)
1034          (member :sparc-v9 *backend-subfeatures*))
1035      ;; V8 has a multiply instruction.  This should also work for
1036      ;; the V9, but umul and the Y register is deprecated on the
1037      ;; V9.
1038      (inst umul result-low multiplier multiplicand)
1039      (inst rdy result-high))
1040     (t
1041      (let ((label (gen-label)))
1042        (inst wry multiplier)
1043        (inst andcc result-high zero-tn)
1044        ;; Note: we can't use the Y register until three insts
1045        ;; after it's written.
1046        (inst nop)
1047        (inst nop)
1048        (dotimes (i 32)
1049          (inst mulscc result-high multiplicand))
1050        (inst mulscc result-high zero-tn)
1051        (inst cmp multiplicand)
1052        (inst b :ge label)
1053        (inst nop)
1054        (inst add result-high multiplier)
1055        (emit-label label)
1056        (inst rdy result-low)))))
1057
1058 (define-vop (bignum-mult-and-add-3-arg)
1059   (:translate sb!bignum::%multiply-and-add)
1060   (:policy :fast-safe)
1061   (:args (x :scs (unsigned-reg) :to (:eval 1))
1062          (y :scs (unsigned-reg) :to (:eval 1))
1063          (carry-in :scs (unsigned-reg) :to (:eval 2)))
1064   (:arg-types unsigned-num unsigned-num unsigned-num)
1065   (:results (hi :scs (unsigned-reg) :from (:eval 0))
1066             (lo :scs (unsigned-reg) :from (:eval 1)))
1067   (:result-types unsigned-num unsigned-num)
1068   (:generator 40
1069     (emit-multiply x y hi lo)
1070     (inst addcc lo carry-in)
1071     (inst addx hi zero-tn)))
1072
1073 (define-vop (bignum-mult-and-add-4-arg)
1074   (:translate sb!bignum::%multiply-and-add)
1075   (:policy :fast-safe)
1076   (:args (x :scs (unsigned-reg) :to (:eval 1))
1077          (y :scs (unsigned-reg) :to (:eval 1))
1078          (prev :scs (unsigned-reg) :to (:eval 2))
1079          (carry-in :scs (unsigned-reg) :to (:eval 2)))
1080   (:arg-types unsigned-num unsigned-num unsigned-num unsigned-num)
1081   (:results (hi :scs (unsigned-reg) :from (:eval 0))
1082             (lo :scs (unsigned-reg) :from (:eval 1)))
1083   (:result-types unsigned-num unsigned-num)
1084   (:generator 40
1085     (emit-multiply x y hi lo)
1086     (inst addcc lo carry-in)
1087     (inst addx hi zero-tn)
1088     (inst addcc lo prev)
1089     (inst addx hi zero-tn)))
1090
1091 (define-vop (bignum-mult)
1092   (:translate sb!bignum::%multiply)
1093   (:policy :fast-safe)
1094   (:args (x :scs (unsigned-reg) :to (:result 1))
1095          (y :scs (unsigned-reg) :to (:result 1)))
1096   (:arg-types unsigned-num unsigned-num)
1097   (:results (hi :scs (unsigned-reg))
1098             (lo :scs (unsigned-reg)))
1099   (:result-types unsigned-num unsigned-num)
1100   (:generator 40
1101     (emit-multiply x y hi lo)))
1102
1103 (define-vop (bignum-lognot lognot-mod32/unsigned=>unsigned)
1104   (:translate sb!bignum::%lognot))
1105
1106 (define-vop (fixnum-to-digit)
1107   (:translate sb!bignum::%fixnum-to-digit)
1108   (:policy :fast-safe)
1109   (:args (fixnum :scs (any-reg)))
1110   (:arg-types tagged-num)
1111   (:results (digit :scs (unsigned-reg)))
1112   (:result-types unsigned-num)
1113   (:generator 1
1114     (inst sra digit fixnum n-fixnum-tag-bits)))
1115
1116 (define-vop (bignum-floor)
1117   (:translate sb!bignum::%floor)
1118   (:policy :fast-safe)
1119   (:args (div-high :scs (unsigned-reg) :target rem)
1120          (div-low :scs (unsigned-reg) :target quo)
1121          (divisor :scs (unsigned-reg)))
1122   (:arg-types unsigned-num unsigned-num unsigned-num)
1123   (:results (quo :scs (unsigned-reg) :from (:argument 1))
1124             (rem :scs (unsigned-reg) :from (:argument 0)))
1125   (:result-types unsigned-num unsigned-num)
1126   (:generator 300
1127     (move rem div-high)
1128     (move quo div-low)
1129     (dotimes (i 33)
1130       (let ((label (gen-label)))
1131         (inst cmp rem divisor)
1132         (inst b :ltu label)
1133         (inst addxcc quo quo)
1134         (inst sub rem divisor)
1135         (emit-label label)
1136         (unless (= i 32)
1137           (inst addx rem rem))))
1138     (inst not quo)))
1139
1140 (define-vop (bignum-floor-v8)
1141   (:translate sb!bignum::%floor)
1142   (:policy :fast-safe)
1143   (:args (div-high :scs (unsigned-reg) :target rem)
1144          (div-low :scs (unsigned-reg) :target quo)
1145          (divisor :scs (unsigned-reg)))
1146   (:arg-types unsigned-num unsigned-num unsigned-num)
1147   (:results (quo :scs (unsigned-reg) :from (:argument 1))
1148             (rem :scs (unsigned-reg) :from (:argument 0)))
1149   (:result-types unsigned-num unsigned-num)
1150   (:temporary (:scs (unsigned-reg) :target quo) q)
1151   ;; This vop is for a v8 or v9, provided we're also not using
1152   ;; sparc-64, for which there a special sparc-64 vop.
1153   (:guard (or (member :sparc-v8 *backend-subfeatures*)
1154               (member :sparc-v9 *backend-subfeatures*)))
1155   (:generator 15
1156     (inst wry div-high)
1157     (inst nop)
1158     (inst nop)
1159     (inst nop)
1160     ;; Compute the quotient [Y, div-low] / divisor
1161     (inst udiv q div-low divisor)
1162     ;; Compute the remainder.  The high part of the result is in the Y
1163     ;; register.
1164     (inst umul rem q divisor)
1165     (inst sub rem div-low rem)
1166     (unless (location= quo q)
1167       (move quo q))))
1168
1169 (define-vop (bignum-floor-v9)
1170   (:translate sb!bignum::%floor)
1171   (:policy :fast-safe)
1172   (:args (div-high :scs (unsigned-reg))
1173          (div-low :scs (unsigned-reg))
1174          (divisor :scs (unsigned-reg) :to (:result 1)))
1175   (:arg-types unsigned-num unsigned-num unsigned-num)
1176   (:temporary (:sc unsigned-reg :from (:argument 0)) dividend)
1177   (:results (quo :scs (unsigned-reg))
1178             (rem :scs (unsigned-reg)))
1179   (:result-types unsigned-num unsigned-num)
1180   (:guard (member :sparc-64 *backend-subfeatures*))
1181   (:generator 5
1182     ;; Set dividend to be div-high and div-low        
1183     (inst sllx dividend div-high 32)
1184     (inst add dividend div-low)
1185     ;; Compute quotient
1186     (inst udivx quo dividend divisor)
1187     ;; Compute the remainder
1188     (inst mulx rem quo divisor)
1189     (inst sub rem dividend rem)))
1190
1191 (define-vop (signify-digit)
1192   (:translate sb!bignum::%fixnum-digit-with-correct-sign)
1193   (:policy :fast-safe)
1194   (:args (digit :scs (unsigned-reg) :target res))
1195   (:arg-types unsigned-num)
1196   (:results (res :scs (any-reg signed-reg)))
1197   (:result-types signed-num)
1198   (:generator 1
1199     (sc-case res
1200       (any-reg
1201        (inst sll res digit n-fixnum-tag-bits))
1202       (signed-reg
1203        (move res digit)))))
1204
1205
1206 (define-vop (digit-ashr)
1207   (:translate sb!bignum::%ashr)
1208   (:policy :fast-safe)
1209   (:args (digit :scs (unsigned-reg))
1210          (count :scs (unsigned-reg)))
1211   (:arg-types unsigned-num positive-fixnum)
1212   (:results (result :scs (unsigned-reg)))
1213   (:result-types unsigned-num)
1214   (:generator 1
1215     (inst sra result digit count)))
1216
1217 (define-vop (digit-lshr digit-ashr)
1218   (:translate sb!bignum::%digit-logical-shift-right)
1219   (:generator 1
1220     (inst srl result digit count)))
1221
1222 (define-vop (digit-ashl digit-ashr)
1223   (:translate sb!bignum::%ashl)
1224   (:generator 1
1225     (inst sll result digit count)))
1226
1227 \f
1228 ;;;; Static functions.
1229
1230 (define-static-fun two-arg-gcd (x y) :translate gcd)
1231 (define-static-fun two-arg-lcm (x y) :translate lcm)
1232
1233 (define-static-fun two-arg-+ (x y) :translate +)
1234 (define-static-fun two-arg-- (x y) :translate -)
1235 (define-static-fun two-arg-* (x y) :translate *)
1236 (define-static-fun two-arg-/ (x y) :translate /)
1237
1238 (define-static-fun two-arg-< (x y) :translate <)
1239 (define-static-fun two-arg-<= (x y) :translate <=)
1240 (define-static-fun two-arg-> (x y) :translate >)
1241 (define-static-fun two-arg->= (x y) :translate >=)
1242 (define-static-fun two-arg-= (x y) :translate =)
1243 (define-static-fun two-arg-/= (x y) :translate /=)
1244
1245 (define-static-fun %negate (x) :translate %negate)
1246
1247 (define-static-fun two-arg-and (x y) :translate logand)
1248 (define-static-fun two-arg-ior (x y) :translate logior)
1249 (define-static-fun two-arg-xor (x y) :translate logxor)
1250 (define-static-fun two-arg-eqv (x y) :translate logeqv)
1251
1252 \f
1253 ;; Need these so constant folding works with the deftransform.
1254
1255 ;; FIXME KLUDGE ew yuk.
1256 #-sb-xc-host
1257 (progn
1258   (defun ash-right-signed (num shift)
1259     (ash-right-signed num shift))
1260
1261   (defun ash-right-unsigned (num shuft)
1262     (ash-right-unsigned num shift)))
1263
1264 (in-package "SB!C")
1265
1266 (deftransform * ((x y)
1267                  ((unsigned-byte 32) (constant-arg (unsigned-byte 32)))
1268                  (unsigned-byte 32))
1269   "recode as shifts and adds"
1270   (let ((y (lvar-value y)))
1271     (multiple-value-bind (result adds shifts)
1272         (ub32-strength-reduce-constant-multiply 'x y)
1273       (cond
1274         ;; we assume, perhaps foolishly, that good SPARCs don't have an
1275         ;; issue with multiplications.  (Remember that there's a
1276         ;; different transform for converting x*2^k to a shift).
1277         ((member :sparc-64 *backend-subfeatures*) (give-up-ir1-transform))
1278         ((or (member :sparc-v9 *backend-subfeatures*)
1279              (member :sparc-v8 *backend-subfeatures*))
1280          ;; breakeven point as measured by Raymond Toy
1281          (when (> (+ adds shifts) 9)
1282            (give-up-ir1-transform))))
1283       (or result 0))))
1284
1285 ;; If we can prove that we have a right shift, just do the right shift
1286 ;; instead of calling the inline ASH which has to check for the
1287 ;; direction of the shift at run-time.
1288 (deftransform ash ((num shift) (integer integer))
1289   (let ((num-type (lvar-type num))
1290         (shift-type (lvar-type shift)))
1291     ;; Can only handle right shifts
1292     (unless (csubtypep shift-type (specifier-type '(integer * 0)))
1293       (give-up-ir1-transform))
1294
1295     ;; If we can prove the shift is so large that all bits are shifted
1296     ;; out, return the appropriate constant.  If the shift is small
1297     ;; enough, call the VOP.  Otherwise, check for the shift size and
1298     ;; do the appropriate thing.  (Hmm, could we just leave the IF
1299     ;; s-expr and depend on other parts of the compiler to delete the
1300     ;; unreachable parts, if any?)
1301     (cond ((csubtypep num-type (specifier-type '(signed-byte #.sb!vm:n-word-bits)))
1302            ;; A right shift by 31 is the same as a right shift by
1303            ;; larger amount.  We get just the sign.
1304            (if (csubtypep shift-type (specifier-type '(integer #.(- 1 sb!vm:n-word-bits) 0)))
1305                ;; FIXME: ash-right-{un,}signed package problems
1306                `(sb!vm::ash-right-signed num (- shift))
1307                `(sb!vm::ash-right-signed num (min (- shift) #.(1- sb!vm:n-word-bits)))))
1308           ((csubtypep num-type (specifier-type '(unsigned-byte #.sb!vm:n-word-bits)))
1309            (if (csubtypep shift-type (specifier-type '(integer #.(- 1 sb!vm:n-word-bits) 0)))
1310                `(sb!vm::ash-right-unsigned num (- shift))
1311                `(if (<= shift #.(- sb!vm:n-word-bits))
1312                  0
1313                  (sb!vm::ash-right-unsigned num (- shift)))))
1314           (t
1315            (give-up-ir1-transform)))))
1316