1 ;;;; floating point support for the Sparc
3 ;;;; This software is part of the SBCL system. See the README file for
6 ;;;; This software is derived from the CMU CL system, which was
7 ;;;; written at Carnegie Mellon University and released into the
8 ;;;; public domain. The software is in the public domain and is
9 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
10 ;;;; files for more information.
14 ;;;; float move functions
16 (define-move-fun (load-single 1) (vop x y
)
17 ((single-stack) (single-reg))
18 (inst ldf y
(current-nfp-tn vop
) (* (tn-offset x
) n-word-bytes
)))
20 (define-move-fun (store-single 1) (vop x y
)
21 ((single-reg) (single-stack))
22 (inst stf x
(current-nfp-tn vop
) (* (tn-offset y
) n-word-bytes
)))
25 (define-move-fun (load-double 2) (vop x y
)
26 ((double-stack) (double-reg))
27 (let ((nfp (current-nfp-tn vop
))
28 (offset (* (tn-offset x
) n-word-bytes
)))
29 (inst lddf y nfp offset
)))
31 (define-move-fun (store-double 2) (vop x y
)
32 ((double-reg) (double-stack))
33 (let ((nfp (current-nfp-tn vop
))
34 (offset (* (tn-offset y
) n-word-bytes
)))
35 (inst stdf x nfp offset
)))
37 ;;; The offset may be an integer or a TN in which case it will be
38 ;;; temporarily modified but is restored if restore-offset is true.
39 (defun load-long-reg (reg base offset
&optional
(restore-offset t
))
41 ((member :sparc-v9
*backend-subfeatures
*)
42 (inst ldqf reg base offset
))
44 (let ((reg0 (make-random-tn :kind
:normal
45 :sc
(sc-or-lose 'double-reg
)
46 :offset
(tn-offset reg
)))
47 (reg2 (make-random-tn :kind
:normal
48 :sc
(sc-or-lose 'double-reg
)
49 :offset
(+ 2 (tn-offset reg
)))))
50 (cond ((integerp offset
)
51 (inst lddf reg0 base offset
)
52 (inst lddf reg2 base
(+ offset
(* 2 n-word-bytes
))))
54 (inst lddf reg0 base offset
)
55 (inst add offset
(* 2 n-word-bytes
))
56 (inst lddf reg2 base offset
)
58 (inst sub offset
(* 2 n-word-bytes
)))))))))
61 (define-move-fun (load-long 2) (vop x y
)
62 ((long-stack) (long-reg))
63 (let ((nfp (current-nfp-tn vop
))
64 (offset (* (tn-offset x
) n-word-bytes
)))
65 (load-long-reg y nfp offset
)))
67 ;;; The offset may be an integer or a TN in which case it will be
68 ;;; temporarily modified but is restored if restore-offset is true.
69 (defun store-long-reg (reg base offset
&optional
(restore-offset t
))
71 ((member :sparc-v9
*backend-subfeatures
*)
72 (inst stqf reg base offset
))
74 (let ((reg0 (make-random-tn :kind
:normal
75 :sc
(sc-or-lose 'double-reg
)
76 :offset
(tn-offset reg
)))
77 (reg2 (make-random-tn :kind
:normal
78 :sc
(sc-or-lose 'double-reg
)
79 :offset
(+ 2 (tn-offset reg
)))))
80 (cond ((integerp offset
)
81 (inst stdf reg0 base offset
)
82 (inst stdf reg2 base
(+ offset
(* 2 n-word-bytes
))))
84 (inst stdf reg0 base offset
)
85 (inst add offset
(* 2 n-word-bytes
))
86 (inst stdf reg2 base offset
)
88 (inst sub offset
(* 2 n-word-bytes
)))))))))
91 (define-move-fun (store-long 2) (vop x y
)
92 ((long-reg) (long-stack))
93 (let ((nfp (current-nfp-tn vop
))
94 (offset (* (tn-offset y
) n-word-bytes
)))
95 (store-long-reg x nfp offset
)))
100 ;;; Exploit the V9 double-float move instruction. This is conditional
101 ;;; on the :sparc-v9 feature.
102 (defun move-double-reg (dst src
)
104 ((member :sparc-v9
*backend-subfeatures
*)
105 (inst fmovd dst src
))
108 (let ((dst (make-random-tn :kind
:normal
109 :sc
(sc-or-lose 'single-reg
)
110 :offset
(+ i
(tn-offset dst
))))
111 (src (make-random-tn :kind
:normal
112 :sc
(sc-or-lose 'single-reg
)
113 :offset
(+ i
(tn-offset src
)))))
114 (inst fmovs dst src
))))))
116 ;;; Exploit the V9 long-float move instruction. This is conditional
117 ;;; on the :sparc-v9 feature.
118 (defun move-long-reg (dst src
)
120 ((member :sparc-v9
*backend-subfeatures
*)
121 (inst fmovq dst src
))
124 (let ((dst (make-random-tn :kind
:normal
125 :sc
(sc-or-lose 'single-reg
)
126 :offset
(+ i
(tn-offset dst
))))
127 (src (make-random-tn :kind
:normal
128 :sc
(sc-or-lose 'single-reg
)
129 :offset
(+ i
(tn-offset src
)))))
130 (inst fmovs dst src
))))))
132 (macrolet ((frob (vop sc format
)
137 :load-if
(not (location= x y
))))
138 (:results
(y :scs
(,sc
)
139 :load-if
(not (location= x y
))))
142 (unless (location= y x
)
144 (:single
`((inst fmovs y x
)))
145 (:double
`((move-double-reg y x
)))
146 (:long
`((move-long-reg y x
)))))))
147 (define-move-vop ,vop
:move
(,sc
) (,sc
)))))
148 (frob single-move single-reg
:single
)
149 (frob double-move double-reg
:double
)
151 (frob long-move long-reg
:long
))
154 (define-vop (move-from-float)
155 (:args
(x :to
:save
))
157 (:note
"float to pointer coercion")
158 (:temporary
(:scs
(non-descriptor-reg)) ndescr
)
159 (:variant-vars format size type data
)
161 (with-fixed-allocation (y ndescr type size
))
164 (inst stf x y
(- (* data n-word-bytes
) other-pointer-lowtag
)))
166 (inst stdf x y
(- (* data n-word-bytes
) other-pointer-lowtag
)))
168 (store-long-reg x y
(- (* data n-word-bytes
)
169 other-pointer-lowtag
))))))
171 (macrolet ((frob (name sc
&rest args
)
173 (define-vop (,name move-from-float
)
174 (:args
(x :scs
(,sc
) :to
:save
))
175 (:results
(y :scs
(descriptor-reg)))
177 (define-move-vop ,name
:move
(,sc
) (descriptor-reg)))))
178 (frob move-from-single single-reg
:single
179 single-float-size single-float-widetag single-float-value-slot
)
180 (frob move-from-double double-reg
:double
181 double-float-size double-float-widetag double-float-value-slot
)
183 (frob move-from-long long-reg
:long
184 long-float-size long-float-widetag long-float-value-slot
))
186 (macrolet ((frob (name sc format value
)
189 (:args
(x :scs
(descriptor-reg)))
190 (:results
(y :scs
(,sc
)))
191 (:note
"pointer to float coercion")
197 (- (* ,value n-word-bytes
) other-pointer-lowtag
))))
198 (define-move-vop ,name
:move
(descriptor-reg) (,sc
)))))
199 (frob move-to-single single-reg
:single single-float-value-slot
)
200 (frob move-to-double double-reg
:double double-float-value-slot
))
203 (define-vop (move-to-long)
204 (:args
(x :scs
(descriptor-reg)))
205 (:results
(y :scs
(long-reg)))
206 (:note
"pointer to float coercion")
208 (load-long-reg y x
(- (* long-float-value-slot n-word-bytes
)
209 other-pointer-lowtag
))))
211 (define-move-vop move-to-long
:move
(descriptor-reg) (long-reg))
213 (macrolet ((frob (name sc stack-sc format
)
216 (:args
(x :scs
(,sc
) :target y
)
218 :load-if
(not (sc-is y
,sc
))))
220 (:note
"float argument move")
221 (:generator
,(ecase format
(:single
1) (:double
2))
224 (unless (location= x y
)
226 (:single
'((inst fmovs y x
)))
227 (:double
'((move-double-reg y x
))))))
229 (let ((offset (* (tn-offset y
) n-word-bytes
)))
234 (define-move-vop ,name
:move-arg
235 (,sc descriptor-reg
) (,sc
)))))
236 (frob move-single-float-arg single-reg single-stack
:single
)
237 (frob move-double-float-arg double-reg double-stack
:double
))
240 (define-vop (move-long-float-arg)
241 (:args
(x :scs
(long-reg) :target y
)
242 (nfp :scs
(any-reg) :load-if
(not (sc-is y long-reg
))))
244 (:note
"float argument move")
248 (unless (location= x y
)
249 (move-long-reg y x
)))
251 (let ((offset (* (tn-offset y
) n-word-bytes
)))
252 (store-long-reg x nfp offset
))))))
255 (define-move-vop move-long-float-arg
:move-arg
256 (long-reg descriptor-reg
) (long-reg))
259 ;;;; Complex float move functions
261 (defun complex-single-reg-real-tn (x)
262 (make-random-tn :kind
:normal
:sc
(sc-or-lose 'single-reg
)
263 :offset
(tn-offset x
)))
264 (defun complex-single-reg-imag-tn (x)
265 (make-random-tn :kind
:normal
:sc
(sc-or-lose 'single-reg
)
266 :offset
(1+ (tn-offset x
))))
268 (defun complex-double-reg-real-tn (x)
269 (make-random-tn :kind
:normal
:sc
(sc-or-lose 'double-reg
)
270 :offset
(tn-offset x
)))
271 (defun complex-double-reg-imag-tn (x)
272 (make-random-tn :kind
:normal
:sc
(sc-or-lose 'double-reg
)
273 :offset
(+ (tn-offset x
) 2)))
276 (defun complex-long-reg-real-tn (x)
277 (make-random-tn :kind
:normal
:sc
(sc-or-lose 'long-reg
)
278 :offset
(tn-offset x
)))
280 (defun complex-long-reg-imag-tn (x)
281 (make-random-tn :kind
:normal
:sc
(sc-or-lose 'long-reg
)
282 :offset
(+ (tn-offset x
) 4)))
285 (define-move-fun (load-complex-single 2) (vop x y
)
286 ((complex-single-stack) (complex-single-reg))
287 (let ((nfp (current-nfp-tn vop
))
288 (offset (* (tn-offset x
) n-word-bytes
)))
289 (let ((real-tn (complex-single-reg-real-tn y
)))
290 (inst ldf real-tn nfp offset
))
291 (let ((imag-tn (complex-single-reg-imag-tn y
)))
292 (inst ldf imag-tn nfp
(+ offset n-word-bytes
)))))
294 (define-move-fun (store-complex-single 2) (vop x y
)
295 ((complex-single-reg) (complex-single-stack))
296 (let ((nfp (current-nfp-tn vop
))
297 (offset (* (tn-offset y
) n-word-bytes
)))
298 (let ((real-tn (complex-single-reg-real-tn x
)))
299 (inst stf real-tn nfp offset
))
300 (let ((imag-tn (complex-single-reg-imag-tn x
)))
301 (inst stf imag-tn nfp
(+ offset n-word-bytes
)))))
304 (define-move-fun (load-complex-double 4) (vop x y
)
305 ((complex-double-stack) (complex-double-reg))
306 (let ((nfp (current-nfp-tn vop
))
307 (offset (* (tn-offset x
) n-word-bytes
)))
308 (let ((real-tn (complex-double-reg-real-tn y
)))
309 (inst lddf real-tn nfp offset
))
310 (let ((imag-tn (complex-double-reg-imag-tn y
)))
311 (inst lddf imag-tn nfp
(+ offset
(* 2 n-word-bytes
))))))
313 (define-move-fun (store-complex-double 4) (vop x y
)
314 ((complex-double-reg) (complex-double-stack))
315 (let ((nfp (current-nfp-tn vop
))
316 (offset (* (tn-offset y
) n-word-bytes
)))
317 (let ((real-tn (complex-double-reg-real-tn x
)))
318 (inst stdf real-tn nfp offset
))
319 (let ((imag-tn (complex-double-reg-imag-tn x
)))
320 (inst stdf imag-tn nfp
(+ offset
(* 2 n-word-bytes
))))))
324 (define-move-fun (load-complex-long 5) (vop x y
)
325 ((complex-long-stack) (complex-long-reg))
326 (let ((nfp (current-nfp-tn vop
))
327 (offset (* (tn-offset x
) n-word-bytes
)))
328 (let ((real-tn (complex-long-reg-real-tn y
)))
329 (load-long-reg real-tn nfp offset
))
330 (let ((imag-tn (complex-long-reg-imag-tn y
)))
331 (load-long-reg imag-tn nfp
(+ offset
(* 4 n-word-bytes
))))))
334 (define-move-fun (store-complex-long 5) (vop x y
)
335 ((complex-long-reg) (complex-long-stack))
336 (let ((nfp (current-nfp-tn vop
))
337 (offset (* (tn-offset y
) n-word-bytes
)))
338 (let ((real-tn (complex-long-reg-real-tn x
)))
339 (store-long-reg real-tn nfp offset
))
340 (let ((imag-tn (complex-long-reg-imag-tn x
)))
341 (store-long-reg imag-tn nfp
(+ offset
(* 4 n-word-bytes
))))))
344 ;;; Complex float register to register moves.
346 (define-vop (complex-single-move)
347 (:args
(x :scs
(complex-single-reg) :target y
348 :load-if
(not (location= x y
))))
349 (:results
(y :scs
(complex-single-reg) :load-if
(not (location= x y
))))
350 (:note
"complex single float move")
352 (unless (location= x y
)
353 ;; Note the complex-float-regs are aligned to every second
354 ;; float register so there is not need to worry about overlap.
355 (let ((x-real (complex-single-reg-real-tn x
))
356 (y-real (complex-single-reg-real-tn y
)))
357 (inst fmovs y-real x-real
))
358 (let ((x-imag (complex-single-reg-imag-tn x
))
359 (y-imag (complex-single-reg-imag-tn y
)))
360 (inst fmovs y-imag x-imag
)))))
362 (define-move-vop complex-single-move
:move
363 (complex-single-reg) (complex-single-reg))
365 (define-vop (complex-double-move)
366 (:args
(x :scs
(complex-double-reg)
367 :target y
:load-if
(not (location= x y
))))
368 (:results
(y :scs
(complex-double-reg) :load-if
(not (location= x y
))))
369 (:note
"complex double float move")
371 (unless (location= x y
)
372 ;; Note the complex-float-regs are aligned to every second
373 ;; float register so there is not need to worry about overlap.
374 (let ((x-real (complex-double-reg-real-tn x
))
375 (y-real (complex-double-reg-real-tn y
)))
376 (move-double-reg y-real x-real
))
377 (let ((x-imag (complex-double-reg-imag-tn x
))
378 (y-imag (complex-double-reg-imag-tn y
)))
379 (move-double-reg y-imag x-imag
)))))
381 (define-move-vop complex-double-move
:move
382 (complex-double-reg) (complex-double-reg))
385 (define-vop (complex-long-move)
386 (:args
(x :scs
(complex-long-reg)
387 :target y
:load-if
(not (location= x y
))))
388 (:results
(y :scs
(complex-long-reg) :load-if
(not (location= x y
))))
389 (:note
"complex long float move")
391 (unless (location= x y
)
392 ;; Note the complex-float-regs are aligned to every second
393 ;; float register so there is not need to worry about overlap.
394 (let ((x-real (complex-long-reg-real-tn x
))
395 (y-real (complex-long-reg-real-tn y
)))
396 (move-long-reg y-real x-real
))
397 (let ((x-imag (complex-long-reg-imag-tn x
))
398 (y-imag (complex-long-reg-imag-tn y
)))
399 (move-long-reg y-imag x-imag
)))))
402 (define-move-vop complex-long-move
:move
403 (complex-long-reg) (complex-long-reg))
406 ;;; Move from a complex float to a descriptor register allocating a
407 ;;; new complex float object in the process.
409 (define-vop (move-from-complex-single)
410 (:args
(x :scs
(complex-single-reg) :to
:save
))
411 (:results
(y :scs
(descriptor-reg)))
412 (:temporary
(:scs
(non-descriptor-reg)) ndescr
)
413 (:note
"complex single float to pointer coercion")
415 (with-fixed-allocation (y ndescr complex-single-float-widetag
416 complex-single-float-size
))
417 (let ((real-tn (complex-single-reg-real-tn x
)))
418 (inst stf real-tn y
(- (* complex-single-float-real-slot
420 other-pointer-lowtag
)))
421 (let ((imag-tn (complex-single-reg-imag-tn x
)))
422 (inst stf imag-tn y
(- (* complex-single-float-imag-slot
424 other-pointer-lowtag
)))))
426 (define-move-vop move-from-complex-single
:move
427 (complex-single-reg) (descriptor-reg))
429 (define-vop (move-from-complex-double)
430 (:args
(x :scs
(complex-double-reg) :to
:save
))
431 (:results
(y :scs
(descriptor-reg)))
432 (:temporary
(:scs
(non-descriptor-reg)) ndescr
)
433 (:note
"complex double float to pointer coercion")
435 (with-fixed-allocation (y ndescr complex-double-float-widetag
436 complex-double-float-size
))
437 (let ((real-tn (complex-double-reg-real-tn x
)))
438 (inst stdf real-tn y
(- (* complex-double-float-real-slot
440 other-pointer-lowtag
)))
441 (let ((imag-tn (complex-double-reg-imag-tn x
)))
442 (inst stdf imag-tn y
(- (* complex-double-float-imag-slot
444 other-pointer-lowtag
)))))
446 (define-move-vop move-from-complex-double
:move
447 (complex-double-reg) (descriptor-reg))
450 (define-vop (move-from-complex-long)
451 (:args
(x :scs
(complex-long-reg) :to
:save
))
452 (:results
(y :scs
(descriptor-reg)))
453 (:temporary
(:scs
(non-descriptor-reg)) ndescr
)
454 (:note
"complex long float to pointer coercion")
456 (with-fixed-allocation (y ndescr complex-long-float-widetag
457 complex-long-float-size
))
458 (let ((real-tn (complex-long-reg-real-tn x
)))
459 (store-long-reg real-tn y
(- (* complex-long-float-real-slot
461 other-pointer-lowtag
)))
462 (let ((imag-tn (complex-long-reg-imag-tn x
)))
463 (store-long-reg imag-tn y
(- (* complex-long-float-imag-slot
465 other-pointer-lowtag
)))))
468 (define-move-vop move-from-complex-long
:move
469 (complex-long-reg) (descriptor-reg))
472 ;;; Move from a descriptor to a complex float register
474 (define-vop (move-to-complex-single)
475 (:args
(x :scs
(descriptor-reg)))
476 (:results
(y :scs
(complex-single-reg)))
477 (:note
"pointer to complex float coercion")
479 (let ((real-tn (complex-single-reg-real-tn y
)))
480 (inst ldf real-tn x
(- (* complex-single-float-real-slot n-word-bytes
)
481 other-pointer-lowtag
)))
482 (let ((imag-tn (complex-single-reg-imag-tn y
)))
483 (inst ldf imag-tn x
(- (* complex-single-float-imag-slot n-word-bytes
)
484 other-pointer-lowtag
)))))
485 (define-move-vop move-to-complex-single
:move
486 (descriptor-reg) (complex-single-reg))
488 (define-vop (move-to-complex-double)
489 (:args
(x :scs
(descriptor-reg)))
490 (:results
(y :scs
(complex-double-reg)))
491 (:note
"pointer to complex float coercion")
493 (let ((real-tn (complex-double-reg-real-tn y
)))
494 (inst lddf real-tn x
(- (* complex-double-float-real-slot n-word-bytes
)
495 other-pointer-lowtag
)))
496 (let ((imag-tn (complex-double-reg-imag-tn y
)))
497 (inst lddf imag-tn x
(- (* complex-double-float-imag-slot n-word-bytes
)
498 other-pointer-lowtag
)))))
499 (define-move-vop move-to-complex-double
:move
500 (descriptor-reg) (complex-double-reg))
503 (define-vop (move-to-complex-long)
504 (:args
(x :scs
(descriptor-reg)))
505 (:results
(y :scs
(complex-long-reg)))
506 (:note
"pointer to complex float coercion")
508 (let ((real-tn (complex-long-reg-real-tn y
)))
509 (load-long-reg real-tn x
(- (* complex-long-float-real-slot n-word-bytes
)
510 other-pointer-lowtag
)))
511 (let ((imag-tn (complex-long-reg-imag-tn y
)))
512 (load-long-reg imag-tn x
(- (* complex-long-float-imag-slot n-word-bytes
)
513 other-pointer-lowtag
)))))
515 (define-move-vop move-to-complex-long
:move
516 (descriptor-reg) (complex-long-reg))
519 ;;; Complex float move-arg vop
521 (define-vop (move-complex-single-float-arg)
522 (:args
(x :scs
(complex-single-reg) :target y
)
523 (nfp :scs
(any-reg) :load-if
(not (sc-is y complex-single-reg
))))
525 (:note
"complex single-float argument move")
529 (unless (location= x y
)
530 (let ((x-real (complex-single-reg-real-tn x
))
531 (y-real (complex-single-reg-real-tn y
)))
532 (inst fmovs y-real x-real
))
533 (let ((x-imag (complex-single-reg-imag-tn x
))
534 (y-imag (complex-single-reg-imag-tn y
)))
535 (inst fmovs y-imag x-imag
))))
536 (complex-single-stack
537 (let ((offset (* (tn-offset y
) n-word-bytes
)))
538 (let ((real-tn (complex-single-reg-real-tn x
)))
539 (inst stf real-tn nfp offset
))
540 (let ((imag-tn (complex-single-reg-imag-tn x
)))
541 (inst stf imag-tn nfp
(+ offset n-word-bytes
))))))))
542 (define-move-vop move-complex-single-float-arg
:move-arg
543 (complex-single-reg descriptor-reg
) (complex-single-reg))
545 (define-vop (move-complex-double-float-arg)
546 (:args
(x :scs
(complex-double-reg) :target y
)
547 (nfp :scs
(any-reg) :load-if
(not (sc-is y complex-double-reg
))))
549 (:note
"complex double-float argument move")
553 (unless (location= x y
)
554 (let ((x-real (complex-double-reg-real-tn x
))
555 (y-real (complex-double-reg-real-tn y
)))
556 (move-double-reg y-real x-real
))
557 (let ((x-imag (complex-double-reg-imag-tn x
))
558 (y-imag (complex-double-reg-imag-tn y
)))
559 (move-double-reg y-imag x-imag
))))
560 (complex-double-stack
561 (let ((offset (* (tn-offset y
) n-word-bytes
)))
562 (let ((real-tn (complex-double-reg-real-tn x
)))
563 (inst stdf real-tn nfp offset
))
564 (let ((imag-tn (complex-double-reg-imag-tn x
)))
565 (inst stdf imag-tn nfp
(+ offset
(* 2 n-word-bytes
)))))))))
566 (define-move-vop move-complex-double-float-arg
:move-arg
567 (complex-double-reg descriptor-reg
) (complex-double-reg))
570 (define-vop (move-complex-long-float-arg)
571 (:args
(x :scs
(complex-long-reg) :target y
)
572 (nfp :scs
(any-reg) :load-if
(not (sc-is y complex-long-reg
))))
574 (:note
"complex long-float argument move")
578 (unless (location= x y
)
579 (let ((x-real (complex-long-reg-real-tn x
))
580 (y-real (complex-long-reg-real-tn y
)))
581 (move-long-reg y-real x-real
))
582 (let ((x-imag (complex-long-reg-imag-tn x
))
583 (y-imag (complex-long-reg-imag-tn y
)))
584 (move-long-reg y-imag x-imag
))))
586 (let ((offset (* (tn-offset y
) n-word-bytes
)))
587 (let ((real-tn (complex-long-reg-real-tn x
)))
588 (store-long-reg real-tn nfp offset
))
589 (let ((imag-tn (complex-long-reg-imag-tn x
)))
590 (store-long-reg imag-tn nfp
(+ offset
(* 4 n-word-bytes
)))))))))
592 (define-move-vop move-complex-long-float-arg
:move-arg
593 (complex-long-reg descriptor-reg
) (complex-long-reg))
596 (define-move-vop move-arg
:move-arg
597 (single-reg double-reg
#!+long-float long-reg
598 complex-single-reg complex-double-reg
#!+long-float complex-long-reg
)
602 ;;;; Arithmetic VOPs:
604 (define-vop (float-op)
608 (:note
"inline float arithmetic")
610 (:save-p
:compute-only
))
612 (macrolet ((frob (name sc ptype
)
613 `(define-vop (,name float-op
)
614 (:args
(x :scs
(,sc
))
616 (:results
(r :scs
(,sc
)))
617 (:arg-types
,ptype
,ptype
)
618 (:result-types
,ptype
))))
619 (frob single-float-op single-reg single-float
)
620 (frob double-float-op double-reg double-float
)
622 (frob long-float-op long-reg long-float
))
624 (macrolet ((frob (op sinst sname scost dinst dname dcost
)
626 (define-vop (,sname single-float-op
)
629 (inst ,sinst r x y
)))
630 (define-vop (,dname double-float-op
)
633 (inst ,dinst r x y
))))))
634 (frob + fadds
+/single-float
2 faddd
+/double-float
2)
635 (frob - fsubs -
/single-float
2 fsubd -
/double-float
2)
636 (frob * fmuls
*/single-float
4 fmuld
*/double-float
5)
637 (frob / fdivs
//single-float
12 fdivd
//double-float
19))
640 (macrolet ((frob (op linst lname lcost
)
641 `(define-vop (,lname long-float-op
)
644 (inst ,linst r x y
)))))
645 (frob + faddq
+/long-float
2)
646 (frob - fsubq -
/long-float
2)
647 (frob * fmulq
*/long-float
6)
648 (frob / fdivq
//long-float
20))
651 (macrolet ((frob (name inst translate sc type
)
653 (:args
(x :scs
(,sc
)))
654 (:results
(y :scs
(,sc
)))
655 (:translate
,translate
)
658 (:result-types
,type
)
659 (:note
"inline float arithmetic")
661 (:save-p
:compute-only
)
663 (note-this-location vop
:internal-error
)
665 (frob abs
/single-float fabss abs single-reg single-float
)
666 (frob %negate
/single-float fnegs %negate single-reg single-float
))
668 (defun negate-double-reg (dst src
)
670 ((member :sparc-v9
*backend-subfeatures
*)
671 (inst fnegd dst src
))
673 ;; Negate the MS part of the numbers, then copy over the rest
676 (let ((dst-odd (make-random-tn :kind
:normal
677 :sc
(sc-or-lose 'single-reg
)
678 :offset
(+ 1 (tn-offset dst
))))
679 (src-odd (make-random-tn :kind
:normal
680 :sc
(sc-or-lose 'single-reg
)
681 :offset
(+ 1 (tn-offset src
)))))
682 (inst fmovs dst-odd src-odd
)))))
684 (defun abs-double-reg (dst src
)
686 ((member :sparc-v9
*backend-subfeatures
*)
687 (inst fabsd dst src
))
689 ;; Abs the MS part of the numbers, then copy over the rest
692 (let ((dst-2 (make-random-tn :kind
:normal
693 :sc
(sc-or-lose 'single-reg
)
694 :offset
(+ 1 (tn-offset dst
))))
695 (src-2 (make-random-tn :kind
:normal
696 :sc
(sc-or-lose 'single-reg
)
697 :offset
(+ 1 (tn-offset src
)))))
698 (inst fmovs dst-2 src-2
)))))
700 (define-vop (abs/double-float
)
701 (:args
(x :scs
(double-reg)))
702 (:results
(y :scs
(double-reg)))
705 (:arg-types double-float
)
706 (:result-types double-float
)
707 (:note
"inline float arithmetic")
709 (:save-p
:compute-only
)
711 (note-this-location vop
:internal-error
)
712 (abs-double-reg y x
)))
714 (define-vop (%negate
/double-float
)
715 (:args
(x :scs
(double-reg)))
716 (:results
(y :scs
(double-reg)))
719 (:arg-types double-float
)
720 (:result-types double-float
)
721 (:note
"inline float arithmetic")
723 (:save-p
:compute-only
)
725 (note-this-location vop
:internal-error
)
726 (negate-double-reg y x
)))
729 (define-vop (abs/long-float
)
730 (:args
(x :scs
(long-reg)))
731 (:results
(y :scs
(long-reg)))
734 (:arg-types long-float
)
735 (:result-types long-float
)
736 (:note
"inline float arithmetic")
738 (:save-p
:compute-only
)
740 (note-this-location vop
:internal-error
)
742 ((member :sparc-v9
*backend-subfeatures
*)
747 (let ((y-odd (make-random-tn
749 :sc
(sc-or-lose 'single-reg
)
750 :offset
(+ i
1 (tn-offset y
))))
751 (x-odd (make-random-tn
753 :sc
(sc-or-lose 'single-reg
)
754 :offset
(+ i
1 (tn-offset x
)))))
755 (inst fmovs y-odd x-odd
)))))))
758 (define-vop (%negate
/long-float
)
759 (:args
(x :scs
(long-reg)))
760 (:results
(y :scs
(long-reg)))
763 (:arg-types long-float
)
764 (:result-types long-float
)
765 (:note
"inline float arithmetic")
767 (:save-p
:compute-only
)
769 (note-this-location vop
:internal-error
)
771 ((member :sparc-v9
*backend-subfeatures
*)
776 (let ((y-odd (make-random-tn
778 :sc
(sc-or-lose 'single-reg
)
779 :offset
(+ i
1 (tn-offset y
))))
780 (x-odd (make-random-tn
782 :sc
(sc-or-lose 'single-reg
)
783 :offset
(+ i
1 (tn-offset x
)))))
784 (inst fmovs y-odd x-odd
)))))))
789 (define-vop (float-compare)
793 (:variant-vars format yep nope
)
795 (:note
"inline float comparison")
797 (:save-p
:compute-only
)
799 (note-this-location vop
:internal-error
)
801 (:single
(inst fcmps x y
))
802 (:double
(inst fcmpd x y
))
803 (:long
(inst fcmpq x y
)))
804 ;; The SPARC V9 doesn't need an instruction between a
805 ;; floating-point compare and a floating-point branch.
806 (unless (member :sparc-v9
*backend-subfeatures
*)
808 (inst fb
(if not-p nope yep
) target
)
811 (macrolet ((frob (name sc ptype
)
812 `(define-vop (,name float-compare
)
813 (:args
(x :scs
(,sc
))
815 (:arg-types
,ptype
,ptype
))))
816 (frob single-float-compare single-reg single-float
)
817 (frob double-float-compare double-reg double-float
)
819 (frob long-float-compare long-reg long-float
))
821 (macrolet ((frob (translate yep nope sname dname
#!+long-float lname
)
823 (define-vop (,sname single-float-compare
)
824 (:translate
,translate
)
825 (:variant
:single
,yep
,nope
))
826 (define-vop (,dname double-float-compare
)
827 (:translate
,translate
)
828 (:variant
:double
,yep
,nope
))
830 (define-vop (,lname long-float-compare
)
831 (:translate
,translate
)
832 (:variant
:long
,yep
,nope
)))))
833 (frob < :l
:ge
</single-float
</double-float
#!+long-float
</long-float
)
834 (frob > :g
:le
>/single-float
>/double-float
#!+long-float
>/long-float
)
835 (frob = :eq
:ne eql
/single-float eql
/double-float
#!+long-float eql
/long-float
))
838 (deftransform eql
((x y
) (long-float long-float
))
839 '(and (= (long-float-low-bits x
) (long-float-low-bits y
))
840 (= (long-float-mid-bits x
) (long-float-mid-bits y
))
841 (= (long-float-high-bits x
) (long-float-high-bits y
))
842 (= (long-float-exp-bits x
) (long-float-exp-bits y
))))
847 (macrolet ((frob (name translate inst to-sc to-type
)
849 (:args
(x :scs
(signed-reg) :target stack-temp
850 :load-if
(not (sc-is x signed-stack
))))
851 (:temporary
(:scs
(single-stack) :from
:argument
) stack-temp
)
852 (:temporary
(:scs
(single-reg) :to
:result
:target y
) temp
)
853 (:results
(y :scs
(,to-sc
)))
854 (:arg-types signed-num
)
855 (:result-types
,to-type
)
857 (:note
"inline float coercion")
858 (:translate
,translate
)
860 (:save-p
:compute-only
)
867 (* (tn-offset temp
) n-word-bytes
))
873 (* (tn-offset stack-tn
) n-word-bytes
))
874 (note-this-location vop
:internal-error
)
875 (inst ,inst y temp
))))))
876 (frob %single-float
/signed %single-float fitos single-reg single-float
)
877 (frob %double-float
/signed %double-float fitod double-reg double-float
)
879 (frob %long-float
/signed %long-float fitoq long-reg long-float
))
881 (macrolet ((frob (name translate inst from-sc from-type to-sc to-type
)
883 (:args
(x :scs
(,from-sc
)))
884 (:results
(y :scs
(,to-sc
)))
885 (:arg-types
,from-type
)
886 (:result-types
,to-type
)
888 (:note
"inline float coercion")
889 (:translate
,translate
)
891 (:save-p
:compute-only
)
893 (note-this-location vop
:internal-error
)
895 (frob %single-float
/double-float %single-float fdtos
896 double-reg double-float single-reg single-float
)
898 (frob %single-float
/long-float %single-float fqtos
899 long-reg long-float single-reg single-float
)
900 (frob %double-float
/single-float %double-float fstod
901 single-reg single-float double-reg double-float
)
903 (frob %double-float
/long-float %double-float fqtod
904 long-reg long-float double-reg double-float
)
906 (frob %long-float
/single-float %long-float fstoq
907 single-reg single-float long-reg long-float
)
909 (frob %long-float
/double-float %long-float fdtoq
910 double-reg double-float long-reg long-float
))
912 (macrolet ((frob (trans from-sc from-type inst
)
913 `(define-vop (,(symbolicate trans
"/" from-type
))
914 (:args
(x :scs
(,from-sc
) :target temp
))
915 (:temporary
(:from
(:argument
0) :sc single-reg
) temp
)
916 (:temporary
(:scs
(signed-stack)) stack-temp
)
917 (:results
(y :scs
(signed-reg)
918 :load-if
(not (sc-is y signed-stack
))))
919 (:arg-types
,from-type
)
920 (:result-types signed-num
)
923 (:note
"inline float truncate")
925 (:save-p
:compute-only
)
927 (note-this-location vop
:internal-error
)
931 (inst stf temp
(current-nfp-tn vop
)
932 (* (tn-offset y
) n-word-bytes
)))
934 (inst stf temp
(current-nfp-tn vop
)
935 (* (tn-offset stack-temp
) n-word-bytes
))
936 (inst ld y
(current-nfp-tn vop
)
937 (* (tn-offset stack-temp
) n-word-bytes
))))))))
938 (frob %unary-truncate single-reg single-float fstoi
)
939 (frob %unary-truncate double-reg double-float fdtoi
)
941 (frob %unary-truncate long-reg long-float fqtoi
)
942 ;; KLUDGE -- these two forms were protected by #-sun4.
943 ;; (frob %unary-round single-reg single-float fstoir)
944 ;; (frob %unary-round double-reg double-float fdtoir)
947 (deftransform %unary-round
((x) (float) (signed-byte 32))
948 '(let* ((trunc (truly-the (signed-byte 32) (%unary-truncate x
)))
951 (one-half (float 1/2 x
)))
955 (truly-the (signed-byte 32) (%unary-truncate
(+ x extra
)))
958 (define-vop (make-single-float)
959 (:args
(bits :scs
(signed-reg) :target res
960 :load-if
(not (sc-is bits signed-stack
))))
961 (:results
(res :scs
(single-reg)
962 :load-if
(not (sc-is res single-stack
))))
963 (:temporary
(:scs
(signed-reg) :from
(:argument
0) :to
(:result
0)) temp
)
964 (:temporary
(:scs
(signed-stack)) stack-temp
)
965 (:arg-types signed-num
)
966 (:result-types single-float
)
967 (:translate make-single-float
)
975 (inst st bits
(current-nfp-tn vop
)
976 (* (tn-offset stack-temp
) n-word-bytes
))
977 (inst ldf res
(current-nfp-tn vop
)
978 (* (tn-offset stack-temp
) n-word-bytes
)))
980 (inst st bits
(current-nfp-tn vop
)
981 (* (tn-offset res
) n-word-bytes
)))))
985 (inst ldf res
(current-nfp-tn vop
)
986 (* (tn-offset bits
) n-word-bytes
)))
988 (unless (location= bits res
)
989 (inst ld temp
(current-nfp-tn vop
)
990 (* (tn-offset bits
) n-word-bytes
))
991 (inst st temp
(current-nfp-tn vop
)
992 (* (tn-offset res
) n-word-bytes
)))))))))
994 (define-vop (make-double-float)
995 (:args
(hi-bits :scs
(signed-reg))
996 (lo-bits :scs
(unsigned-reg)))
997 (:results
(res :scs
(double-reg)
998 :load-if
(not (sc-is res double-stack
))))
999 (:temporary
(:scs
(double-stack)) temp
)
1000 (:arg-types signed-num unsigned-num
)
1001 (:result-types double-float
)
1002 (:translate make-double-float
)
1003 (:policy
:fast-safe
)
1006 (let ((stack-tn (sc-case res
1008 (double-reg temp
))))
1009 (inst st hi-bits
(current-nfp-tn vop
)
1010 (* (tn-offset stack-tn
) n-word-bytes
))
1011 (inst st lo-bits
(current-nfp-tn vop
)
1012 (* (1+ (tn-offset stack-tn
)) n-word-bytes
)))
1013 (when (sc-is res double-reg
)
1014 (inst lddf res
(current-nfp-tn vop
)
1015 (* (tn-offset temp
) n-word-bytes
)))))
1018 (define-vop (make-long-float)
1019 (:args
(hi-bits :scs
(signed-reg))
1020 (lo1-bits :scs
(unsigned-reg))
1021 (lo2-bits :scs
(unsigned-reg))
1022 (lo3-bits :scs
(unsigned-reg)))
1023 (:results
(res :scs
(long-reg)
1024 :load-if
(not (sc-is res long-stack
))))
1025 (:temporary
(:scs
(long-stack)) temp
)
1026 (:arg-types signed-num unsigned-num unsigned-num unsigned-num
)
1027 (:result-types long-float
)
1028 (:translate make-long-float
)
1029 (:policy
:fast-safe
)
1032 (let ((stack-tn (sc-case res
1035 (inst st hi-bits
(current-nfp-tn vop
)
1036 (* (tn-offset stack-tn
) n-word-bytes
))
1037 (inst st lo1-bits
(current-nfp-tn vop
)
1038 (* (1+ (tn-offset stack-tn
)) n-word-bytes
))
1039 (inst st lo2-bits
(current-nfp-tn vop
)
1040 (* (+ 2 (tn-offset stack-tn
)) n-word-bytes
))
1041 (inst st lo3-bits
(current-nfp-tn vop
)
1042 (* (+ 3 (tn-offset stack-tn
)) n-word-bytes
)))
1043 (when (sc-is res long-reg
)
1044 (load-long-reg res
(current-nfp-tn vop
)
1045 (* (tn-offset temp
) n-word-bytes
)))))
1047 (define-vop (single-float-bits)
1048 (:args
(float :scs
(single-reg descriptor-reg
)
1049 :load-if
(not (sc-is float single-stack
))))
1050 (:results
(bits :scs
(signed-reg)
1051 :load-if
(or (sc-is float descriptor-reg single-stack
)
1052 (not (sc-is bits signed-stack
)))))
1053 (:temporary
(:scs
(signed-stack)) stack-temp
)
1054 (:arg-types single-float
)
1055 (:result-types signed-num
)
1056 (:translate single-float-bits
)
1057 (:policy
:fast-safe
)
1064 (inst stf float
(current-nfp-tn vop
)
1065 (* (tn-offset stack-temp
) n-word-bytes
))
1066 (inst ld bits
(current-nfp-tn vop
)
1067 (* (tn-offset stack-temp
) n-word-bytes
)))
1069 (inst ld bits
(current-nfp-tn vop
)
1070 (* (tn-offset float
) n-word-bytes
)))
1072 (loadw bits float single-float-value-slot
1073 other-pointer-lowtag
))))
1077 (inst stf float
(current-nfp-tn vop
)
1078 (* (tn-offset bits
) n-word-bytes
))))))))
1080 (define-vop (double-float-high-bits)
1081 (:args
(float :scs
(double-reg descriptor-reg
)
1082 :load-if
(not (sc-is float double-stack
))))
1083 (:results
(hi-bits :scs
(signed-reg)))
1084 (:temporary
(:scs
(double-stack)) stack-temp
)
1085 (:arg-types double-float
)
1086 (:result-types signed-num
)
1087 (:translate double-float-high-bits
)
1088 (:policy
:fast-safe
)
1093 (inst stdf float
(current-nfp-tn vop
)
1094 (* (tn-offset stack-temp
) n-word-bytes
))
1095 (inst ld hi-bits
(current-nfp-tn vop
)
1096 (* (tn-offset stack-temp
) n-word-bytes
)))
1098 (inst ld hi-bits
(current-nfp-tn vop
)
1099 (* (tn-offset float
) n-word-bytes
)))
1101 (loadw hi-bits float double-float-value-slot
1102 other-pointer-lowtag
)))))
1104 (define-vop (double-float-low-bits)
1105 (:args
(float :scs
(double-reg descriptor-reg
)
1106 :load-if
(not (sc-is float double-stack
))))
1107 (:results
(lo-bits :scs
(unsigned-reg)))
1108 (:temporary
(:scs
(double-stack)) stack-temp
)
1109 (:arg-types double-float
)
1110 (:result-types unsigned-num
)
1111 (:translate double-float-low-bits
)
1112 (:policy
:fast-safe
)
1117 (inst stdf float
(current-nfp-tn vop
)
1118 (* (tn-offset stack-temp
) n-word-bytes
))
1119 (inst ld lo-bits
(current-nfp-tn vop
)
1120 (* (1+ (tn-offset stack-temp
)) n-word-bytes
)))
1122 (inst ld lo-bits
(current-nfp-tn vop
)
1123 (* (1+ (tn-offset float
)) n-word-bytes
)))
1125 (loadw lo-bits float
(1+ double-float-value-slot
)
1126 other-pointer-lowtag
)))))
1129 (define-vop (long-float-exp-bits)
1130 (:args
(float :scs
(long-reg descriptor-reg
)
1131 :load-if
(not (sc-is float long-stack
))))
1132 (:results
(exp-bits :scs
(signed-reg)))
1133 (:temporary
(:scs
(double-stack)) stack-temp
)
1134 (:arg-types long-float
)
1135 (:result-types signed-num
)
1136 (:translate long-float-exp-bits
)
1137 (:policy
:fast-safe
)
1142 (let ((float (make-random-tn :kind
:normal
1143 :sc
(sc-or-lose 'double-reg
)
1144 :offset
(tn-offset float
))))
1145 (inst stdf float
(current-nfp-tn vop
)
1146 (* (tn-offset stack-temp
) n-word-bytes
)))
1147 (inst ld exp-bits
(current-nfp-tn vop
)
1148 (* (tn-offset stack-temp
) n-word-bytes
)))
1150 (inst ld exp-bits
(current-nfp-tn vop
)
1151 (* (tn-offset float
) n-word-bytes
)))
1153 (loadw exp-bits float long-float-value-slot
1154 other-pointer-lowtag
)))))
1157 (define-vop (long-float-high-bits)
1158 (:args
(float :scs
(long-reg descriptor-reg
)
1159 :load-if
(not (sc-is float long-stack
))))
1160 (:results
(high-bits :scs
(unsigned-reg)))
1161 (:temporary
(:scs
(double-stack)) stack-temp
)
1162 (:arg-types long-float
)
1163 (:result-types unsigned-num
)
1164 (:translate long-float-high-bits
)
1165 (:policy
:fast-safe
)
1170 (let ((float (make-random-tn :kind
:normal
1171 :sc
(sc-or-lose 'double-reg
)
1172 :offset
(tn-offset float
))))
1173 (inst stdf float
(current-nfp-tn vop
)
1174 (* (tn-offset stack-temp
) n-word-bytes
)))
1175 (inst ld high-bits
(current-nfp-tn vop
)
1176 (* (1+ (tn-offset stack-temp
)) n-word-bytes
)))
1178 (inst ld high-bits
(current-nfp-tn vop
)
1179 (* (1+ (tn-offset float
)) n-word-bytes
)))
1181 (loadw high-bits float
(1+ long-float-value-slot
)
1182 other-pointer-lowtag
)))))
1185 (define-vop (long-float-mid-bits)
1186 (:args
(float :scs
(long-reg descriptor-reg
)
1187 :load-if
(not (sc-is float long-stack
))))
1188 (:results
(mid-bits :scs
(unsigned-reg)))
1189 (:temporary
(:scs
(double-stack)) stack-temp
)
1190 (:arg-types long-float
)
1191 (:result-types unsigned-num
)
1192 (:translate long-float-mid-bits
)
1193 (:policy
:fast-safe
)
1198 (let ((float (make-random-tn :kind
:normal
1199 :sc
(sc-or-lose 'double-reg
)
1200 :offset
(+ 2 (tn-offset float
)))))
1201 (inst stdf float
(current-nfp-tn vop
)
1202 (* (tn-offset stack-temp
) n-word-bytes
)))
1203 (inst ld mid-bits
(current-nfp-tn vop
)
1204 (* (tn-offset stack-temp
) n-word-bytes
)))
1206 (inst ld mid-bits
(current-nfp-tn vop
)
1207 (* (+ 2 (tn-offset float
)) n-word-bytes
)))
1209 (loadw mid-bits float
(+ 2 long-float-value-slot
)
1210 other-pointer-lowtag
)))))
1213 (define-vop (long-float-low-bits)
1214 (:args
(float :scs
(long-reg descriptor-reg
)
1215 :load-if
(not (sc-is float long-stack
))))
1216 (:results
(lo-bits :scs
(unsigned-reg)))
1217 (:temporary
(:scs
(double-stack)) stack-temp
)
1218 (:arg-types long-float
)
1219 (:result-types unsigned-num
)
1220 (:translate long-float-low-bits
)
1221 (:policy
:fast-safe
)
1226 (let ((float (make-random-tn :kind
:normal
1227 :sc
(sc-or-lose 'double-reg
)
1228 :offset
(+ 2 (tn-offset float
)))))
1229 (inst stdf float
(current-nfp-tn vop
)
1230 (* (tn-offset stack-temp
) n-word-bytes
)))
1231 (inst ld lo-bits
(current-nfp-tn vop
)
1232 (* (1+ (tn-offset stack-temp
)) n-word-bytes
)))
1234 (inst ld lo-bits
(current-nfp-tn vop
)
1235 (* (+ 3 (tn-offset float
)) n-word-bytes
)))
1237 (loadw lo-bits float
(+ 3 long-float-value-slot
)
1238 other-pointer-lowtag
)))))
1241 ;;;; Float mode hackery:
1243 (sb!xc
:deftype float-modes
() '(unsigned-byte 32))
1244 (defknown floating-point-modes
() float-modes
(flushable))
1245 (defknown ((setf floating-point-modes
)) (float-modes)
1248 (define-vop (floating-point-modes)
1249 (:results
(res :scs
(unsigned-reg)))
1250 (:result-types unsigned-num
)
1251 (:translate floating-point-modes
)
1252 (:policy
:fast-safe
)
1254 (:temporary
(:sc unsigned-stack
) temp
)
1256 (let ((nfp (current-nfp-tn vop
)))
1257 (inst stfsr nfp
(* n-word-bytes
(tn-offset temp
)))
1258 (loadw res nfp
(tn-offset temp
))
1262 (define-vop (floating-point-modes)
1263 (:results
(res :scs
(unsigned-reg)))
1264 (:result-types unsigned-num
)
1265 (:translate floating-point-modes
)
1266 (:policy
:fast-safe
)
1268 (:temporary
(:sc double-stack
) temp
)
1270 (let* ((nfp (current-nfp-tn vop
))
1271 (offset (* 4 (tn-offset temp
))))
1272 (inst stxfsr nfp offset
)
1273 ;; The desired FP mode data is in the least significant 32
1274 ;; bits, which is stored at the next higher word in memory.
1275 (loadw res nfp
(+ offset
4))
1276 ;; Is this nop needed? -- rtoy
1279 (define-vop (set-floating-point-modes)
1280 (:args
(new :scs
(unsigned-reg) :target res
))
1281 (:results
(res :scs
(unsigned-reg)))
1282 (:arg-types unsigned-num
)
1283 (:result-types unsigned-num
)
1284 (:translate
(setf floating-point-modes
))
1285 (:policy
:fast-safe
)
1286 (:temporary
(:sc unsigned-stack
) temp
)
1289 (let ((nfp (current-nfp-tn vop
)))
1290 (storew new nfp
(tn-offset temp
))
1291 (inst ldfsr nfp
(* n-word-bytes
(tn-offset temp
)))
1295 (define-vop (set-floating-point-modes)
1296 (:args
(new :scs
(unsigned-reg) :target res
))
1297 (:results
(res :scs
(unsigned-reg)))
1298 (:arg-types unsigned-num
)
1299 (:result-types unsigned-num
)
1300 (:translate
(setf floating-point-modes
))
1301 (:policy
:fast-safe
)
1302 (:temporary
(:sc double-stack
) temp
)
1303 (:temporary
(:sc unsigned-reg
) my-fsr
)
1306 (let ((nfp (current-nfp-tn vop
))
1307 (offset (* n-word-bytes
(tn-offset temp
))))
1309 ;; Get the current FSR, so we can get the new %fcc's
1310 (inst stxfsr nfp offset
)
1311 (inst ldx my-fsr nfp offset
)
1312 ;; Carefully merge in the new mode bits with the rest of the
1313 ;; FSR. This is only needed if we care about preserving the
1314 ;; high 32 bits of the FSR, which contain the additional
1315 ;; %fcc's on the sparc V9. If not, we don't need this, but we
1316 ;; do need to make sure that the unused bits are written as
1317 ;; zeroes, according the V9 architecture manual.
1319 (inst srlx my-fsr
32)
1320 (inst sllx my-fsr
32)
1321 (inst or my-fsr new
)
1322 ;; Save it back and load it into the fsr register
1323 (inst stx my-fsr nfp offset
)
1324 (inst ldxfsr nfp offset
)
1328 (define-vop (set-floating-point-modes)
1329 (:args
(new :scs
(unsigned-reg) :target res
))
1330 (:results
(res :scs
(unsigned-reg)))
1331 (:arg-types unsigned-num
)
1332 (:result-types unsigned-num
)
1333 (:translate
(setf floating-point-modes
))
1334 (:policy
:fast-safe
)
1335 (:temporary
(:sc double-stack
) temp
)
1336 (:temporary
(:sc unsigned-reg
) my-fsr
)
1339 (let ((nfp (current-nfp-tn vop
))
1340 (offset (* n-word-bytes
(tn-offset temp
))))
1341 (inst stx new nfp offset
)
1342 (inst ldxfsr nfp offset
)
1346 ;;;; Special functions.
1350 (:args
(x :scs
(double-reg)))
1351 (:results
(y :scs
(double-reg)))
1353 (:policy
:fast-safe
)
1354 (:guard
(or (member :sparc-v7
*backend-subfeatures
*)
1355 (member :sparc-v8
*backend-subfeatures
*)
1356 (member :sparc-v9
*backend-subfeatures
*)))
1357 (:arg-types double-float
)
1358 (:result-types double-float
)
1359 (:note
"inline float arithmetic")
1361 (:save-p
:compute-only
)
1363 (note-this-location vop
:internal-error
)
1367 (define-vop (fsqrt-long)
1368 (:args
(x :scs
(long-reg)))
1369 (:results
(y :scs
(long-reg)))
1371 (:policy
:fast-safe
)
1372 (:arg-types long-float
)
1373 (:result-types long-float
)
1374 (:note
"inline float arithmetic")
1376 (:save-p
:compute-only
)
1378 (note-this-location vop
:internal-error
)
1382 ;;;; Complex float VOPs
1384 (define-vop (make-complex-single-float)
1385 (:translate complex
)
1386 (:args
(real :scs
(single-reg) :target r
1387 :load-if
(not (location= real r
)))
1388 (imag :scs
(single-reg) :to
:save
))
1389 (:arg-types single-float single-float
)
1390 (:results
(r :scs
(complex-single-reg) :from
(:argument
0)
1391 :load-if
(not (sc-is r complex-single-stack
))))
1392 (:result-types complex-single-float
)
1393 (:note
"inline complex single-float creation")
1394 (:policy
:fast-safe
)
1399 (let ((r-real (complex-single-reg-real-tn r
)))
1400 (unless (location= real r-real
)
1401 (inst fmovs r-real real
)))
1402 (let ((r-imag (complex-single-reg-imag-tn r
)))
1403 (unless (location= imag r-imag
)
1404 (inst fmovs r-imag imag
))))
1405 (complex-single-stack
1406 (let ((nfp (current-nfp-tn vop
))
1407 (offset (* (tn-offset r
) n-word-bytes
)))
1408 (unless (location= real r
)
1409 (inst stf real nfp offset
))
1410 (inst stf imag nfp
(+ offset n-word-bytes
)))))))
1412 (define-vop (make-complex-double-float)
1413 (:translate complex
)
1414 (:args
(real :scs
(double-reg) :target r
1415 :load-if
(not (location= real r
)))
1416 (imag :scs
(double-reg) :to
:save
))
1417 (:arg-types double-float double-float
)
1418 (:results
(r :scs
(complex-double-reg) :from
(:argument
0)
1419 :load-if
(not (sc-is r complex-double-stack
))))
1420 (:result-types complex-double-float
)
1421 (:note
"inline complex double-float creation")
1422 (:policy
:fast-safe
)
1427 (let ((r-real (complex-double-reg-real-tn r
)))
1428 (unless (location= real r-real
)
1429 (move-double-reg r-real real
)))
1430 (let ((r-imag (complex-double-reg-imag-tn r
)))
1431 (unless (location= imag r-imag
)
1432 (move-double-reg r-imag imag
))))
1433 (complex-double-stack
1434 (let ((nfp (current-nfp-tn vop
))
1435 (offset (* (tn-offset r
) n-word-bytes
)))
1436 (unless (location= real r
)
1437 (inst stdf real nfp offset
))
1438 (inst stdf imag nfp
(+ offset
(* 2 n-word-bytes
))))))))
1441 (define-vop (make-complex-long-float)
1442 (:translate complex
)
1443 (:args
(real :scs
(long-reg) :target r
1444 :load-if
(not (location= real r
)))
1445 (imag :scs
(long-reg) :to
:save
))
1446 (:arg-types long-float long-float
)
1447 (:results
(r :scs
(complex-long-reg) :from
(:argument
0)
1448 :load-if
(not (sc-is r complex-long-stack
))))
1449 (:result-types complex-long-float
)
1450 (:note
"inline complex long-float creation")
1451 (:policy
:fast-safe
)
1456 (let ((r-real (complex-long-reg-real-tn r
)))
1457 (unless (location= real r-real
)
1458 (move-long-reg r-real real
)))
1459 (let ((r-imag (complex-long-reg-imag-tn r
)))
1460 (unless (location= imag r-imag
)
1461 (move-long-reg r-imag imag
))))
1463 (let ((nfp (current-nfp-tn vop
))
1464 (offset (* (tn-offset r
) n-word-bytes
)))
1465 (unless (location= real r
)
1466 (store-long-reg real nfp offset
))
1467 (store-long-reg imag nfp
(+ offset
(* 4 n-word-bytes
))))))))
1469 (define-vop (complex-single-float-value)
1470 (:args
(x :scs
(complex-single-reg) :target r
1471 :load-if
(not (sc-is x complex-single-stack
))))
1472 (:arg-types complex-single-float
)
1473 (:results
(r :scs
(single-reg)))
1474 (:result-types single-float
)
1475 (:variant-vars slot
)
1476 (:policy
:fast-safe
)
1481 (let ((value-tn (ecase slot
1482 (:real
(complex-single-reg-real-tn x
))
1483 (:imag
(complex-single-reg-imag-tn x
)))))
1484 (unless (location= value-tn r
)
1485 (inst fmovs r value-tn
))))
1486 (complex-single-stack
1487 (inst ldf r
(current-nfp-tn vop
) (* (+ (ecase slot
(:real
0) (:imag
1))
1491 (define-vop (realpart/complex-single-float complex-single-float-value
)
1492 (:translate realpart
)
1493 (:note
"complex single float realpart")
1496 (define-vop (imagpart/complex-single-float complex-single-float-value
)
1497 (:translate imagpart
)
1498 (:note
"complex single float imagpart")
1501 (define-vop (complex-double-float-value)
1502 (:args
(x :scs
(complex-double-reg) :target r
1503 :load-if
(not (sc-is x complex-double-stack
))))
1504 (:arg-types complex-double-float
)
1505 (:results
(r :scs
(double-reg)))
1506 (:result-types double-float
)
1507 (:variant-vars slot
)
1508 (:policy
:fast-safe
)
1513 (let ((value-tn (ecase slot
1514 (:real
(complex-double-reg-real-tn x
))
1515 (:imag
(complex-double-reg-imag-tn x
)))))
1516 (unless (location= value-tn r
)
1517 (move-double-reg r value-tn
))))
1518 (complex-double-stack
1519 (inst lddf r
(current-nfp-tn vop
) (* (+ (ecase slot
(:real
0) (:imag
2))
1523 (define-vop (realpart/complex-double-float complex-double-float-value
)
1524 (:translate realpart
)
1525 (:note
"complex double float realpart")
1528 (define-vop (imagpart/complex-double-float complex-double-float-value
)
1529 (:translate imagpart
)
1530 (:note
"complex double float imagpart")
1534 (define-vop (complex-long-float-value)
1535 (:args
(x :scs
(complex-long-reg) :target r
1536 :load-if
(not (sc-is x complex-long-stack
))))
1537 (:arg-types complex-long-float
)
1538 (:results
(r :scs
(long-reg)))
1539 (:result-types long-float
)
1540 (:variant-vars slot
)
1541 (:policy
:fast-safe
)
1546 (let ((value-tn (ecase slot
1547 (:real
(complex-long-reg-real-tn x
))
1548 (:imag
(complex-long-reg-imag-tn x
)))))
1549 (unless (location= value-tn r
)
1550 (move-long-reg r value-tn
))))
1552 (load-long-reg r
(current-nfp-tn vop
)
1553 (* (+ (ecase slot
(:real
0) (:imag
4)) (tn-offset x
))
1557 (define-vop (realpart/complex-long-float complex-long-float-value
)
1558 (:translate realpart
)
1559 (:note
"complex long float realpart")
1563 (define-vop (imagpart/complex-long-float complex-long-float-value
)
1564 (:translate imagpart
)
1565 (:note
"complex long float imagpart")
1570 ;;;; Complex float arithmetic
1577 ((frob (float-type fneg cost
)
1578 (let* ((vop-name (symbolicate "%NEGATE/COMPLEX-" float-type
))
1579 (c-type (symbolicate "COMPLEX-" float-type
"-FLOAT"))
1580 (complex-reg (symbolicate "COMPLEX-" float-type
"-REG"))
1581 (real-tn (symbolicate "COMPLEX-" float-type
"-REG-REAL-TN"))
1582 (imag-tn (symbolicate "COMPLEX-" float-type
"-REG-IMAG-TN")))
1583 `(define-vop (,vop-name
)
1584 (:args
(x :scs
(,complex-reg
)))
1585 (:arg-types
,c-type
)
1586 (:results
(r :scs
(,complex-reg
)))
1587 (:result-types
,c-type
)
1588 (:policy
:fast-safe
)
1589 (:note
"inline complex float arithmetic")
1590 (:translate %negate
)
1592 (let ((xr (,real-tn x
))
1597 (,@fneg ri xi
)))))))
1598 (frob single
(inst fnegs
) 4)
1599 (frob double
(negate-double-reg) 4))
1601 ;; Add and subtract for two complex arguments
1603 ((frob (op inst float-type cost
)
1604 (let* ((vop-name (symbolicate (symbol-name op
) "/COMPLEX-" float-type
"-FLOAT"))
1605 (c-type (symbolicate "COMPLEX-" float-type
"-FLOAT"))
1606 (complex-reg (symbolicate "COMPLEX-" float-type
"-REG"))
1607 (real-part (symbolicate "COMPLEX-" float-type
"-REG-REAL-TN"))
1608 (imag-part (symbolicate "COMPLEX-" float-type
"-REG-IMAG-TN")))
1609 `(define-vop (,vop-name
)
1610 (:args
(x :scs
(,complex-reg
)) (y :scs
(,complex-reg
)))
1611 (:results
(r :scs
(,complex-reg
)))
1612 (:arg-types
,c-type
,c-type
)
1613 (:result-types
,c-type
)
1614 (:policy
:fast-safe
)
1615 (:note
"inline complex float arithmetic")
1618 (let ((xr (,real-part x
))
1623 (ri (,imag-part r
)))
1624 (inst ,inst rr xr yr
)
1625 (inst ,inst ri xi yi
)))))))
1626 (frob + fadds single
4)
1627 (frob + faddd double
4)
1628 (frob - fsubs single
4)
1629 (frob - fsubd double
4))
1631 ;; Add and subtract a complex and a float
1634 ((frob (size op fop fmov cost
)
1635 (let ((vop-name (symbolicate "COMPLEX-" size
"-FLOAT-"
1638 (complex-reg (symbolicate "COMPLEX-" size
"-REG"))
1639 (real-reg (symbolicate size
"-REG"))
1640 (c-type (symbolicate "COMPLEX-" size
"-FLOAT"))
1641 (r-type (symbolicate size
"-FLOAT"))
1642 (real-part (symbolicate "COMPLEX-" size
"-REG-REAL-TN"))
1643 (imag-part (symbolicate "COMPLEX-" size
"-REG-IMAG-TN")))
1644 `(define-vop (,vop-name
)
1645 (:args
(x :scs
(,complex-reg
))
1646 (y :scs
(,real-reg
)))
1647 (:results
(r :scs
(,complex-reg
)))
1648 (:arg-types
,c-type
,r-type
)
1649 (:result-types
,c-type
)
1650 (:policy
:fast-safe
)
1651 (:note
"inline complex float/float arithmetic")
1654 (let ((xr (,real-part x
))
1657 (ri (,imag-part r
)))
1659 (unless (location= ri xi
)
1660 (,@fmov ri xi
))))))))
1662 (frob single
+ fadds
(inst fmovs
) 2)
1663 (frob single - fsubs
(inst fmovs
) 2)
1664 (frob double
+ faddd
(move-double-reg) 4)
1665 (frob double - fsubd
(move-double-reg) 4))
1667 ;; Add a float and a complex
1669 ((frob (size fop fmov cost
)
1671 (symbolicate size
"-FLOAT-+-COMPLEX-" size
"-FLOAT"))
1672 (complex-reg (symbolicate "COMPLEX-" size
"-REG"))
1673 (real-reg (symbolicate size
"-REG"))
1674 (c-type (symbolicate "COMPLEX-" size
"-FLOAT"))
1675 (r-type (symbolicate size
"-FLOAT"))
1676 (real-part (symbolicate "COMPLEX-" size
"-REG-REAL-TN"))
1677 (imag-part (symbolicate "COMPLEX-" size
"-REG-IMAG-TN")))
1678 `(define-vop (,vop-name
)
1679 (:args
(y :scs
(,real-reg
))
1680 (x :scs
(,complex-reg
)))
1681 (:results
(r :scs
(,complex-reg
)))
1682 (:arg-types
,r-type
,c-type
)
1683 (:result-types
,c-type
)
1684 (:policy
:fast-safe
)
1685 (:note
"inline complex float/float arithmetic")
1688 (let ((xr (,real-part x
))
1691 (ri (,imag-part r
)))
1693 (unless (location= ri xi
)
1694 (,@fmov ri xi
))))))))
1695 (frob single fadds
(inst fmovs
) 1)
1696 (frob double faddd
(move-double-reg) 2))
1698 ;; Subtract a complex from a float
1701 ((frob (size fop fneg cost
)
1702 (let ((vop-name (symbolicate size
"-FLOAT---COMPLEX-" size
"-FLOAT"))
1703 (complex-reg (symbolicate "COMPLEX-" size
"-REG"))
1704 (real-reg (symbolicate size
"-REG"))
1705 (c-type (symbolicate "COMPLEX-" size
"-FLOAT"))
1706 (r-type (symbolicate size
"-FLOAT"))
1707 (real-part (symbolicate "COMPLEX-" size
"-REG-REAL-TN"))
1708 (imag-part (symbolicate "COMPLEX-" size
"-REG-IMAG-TN")))
1709 `(define-vop (single-float---complex-single-float)
1710 (:args
(x :scs
(,real-reg
)) (y :scs
(,complex-reg
)))
1711 (:results
(r :scs
(,complex-reg
)))
1712 (:arg-types
,r-type
,c-type
)
1713 (:result-types
,c-type
)
1714 (:policy
:fast-safe
)
1715 (:note
"inline complex float/float arithmetic")
1718 (let ((yr (,real-part y
))
1721 (ri (,imag-part r
)))
1726 (frob single fsubs
(inst fnegs
) 2)
1727 (frob double fsubd
(negate-double-reg) 2)))
1729 ;; Multiply two complex numbers
1733 ((frob (size fmul fadd fsub cost
)
1734 (let ((vop-name (symbolicate "*/COMPLEX-" size
"-FLOAT"))
1735 (complex-reg (symbolicate "COMPLEX-" size
"-REG"))
1736 (real-reg (symbolicate size
"-REG"))
1737 (c-type (symbolicate "COMPLEX-" size
"-FLOAT"))
1738 (real-part (symbolicate "COMPLEX-" size
"-REG-REAL-TN"))
1739 (imag-part (symbolicate "COMPLEX-" size
"-REG-IMAG-TN")))
1740 `(define-vop (,vop-name
)
1741 (:args
(x :scs
(,complex-reg
))
1742 (y :scs
(,complex-reg
)))
1743 (:results
(r :scs
(,complex-reg
)))
1744 (:arg-types
,c-type
,c-type
)
1745 (:result-types
,c-type
)
1746 (:policy
:fast-safe
)
1747 (:note
"inline complex float multiplication")
1749 (:temporary
(:scs
(,real-reg
)) prod-1 prod-2 prod-3 prod-4
)
1751 (let ((xr (,real-part x
))
1756 (ri (,imag-part r
)))
1757 ;; All of the temps are needed in case the result TN happens to
1758 ;; be the same as one of the arg TN's
1759 (inst ,fmul prod-1 xr yr
)
1760 (inst ,fmul prod-2 xi yi
)
1761 (inst ,fmul prod-3 xr yi
)
1762 (inst ,fmul prod-4 xi yr
)
1763 (inst ,fsub rr prod-1 prod-2
)
1764 (inst ,fadd ri prod-3 prod-4
)))))))
1766 (frob single fmuls fadds fsubs
6)
1767 (frob double fmuld faddd fsubd
6))
1770 ((frob (size fmul fadd fsub cost
)
1771 (let ((vop-name (symbolicate "*/COMPLEX-" size
"-FLOAT"))
1772 (complex-reg (symbolicate "COMPLEX-" size
"-REG"))
1773 (real-reg (symbolicate size
"-REG"))
1774 (c-type (symbolicate "COMPLEX-" size
"-FLOAT"))
1775 (real-part (symbolicate "COMPLEX-" size
"-REG-REAL-TN"))
1776 (imag-part (symbolicate "COMPLEX-" size
"-REG-IMAG-TN")))
1777 `(define-vop (,vop-name
)
1778 (:args
(x :scs
(,complex-reg
))
1779 (y :scs
(,complex-reg
)))
1780 (:results
(r :scs
(,complex-reg
)))
1781 (:arg-types
,c-type
,c-type
)
1782 (:result-types
,c-type
)
1783 (:policy
:fast-safe
)
1784 (:note
"inline complex float multiplication")
1786 (:temporary
(:scs
(,real-reg
)) p1 p2
)
1788 (let ((xr (,real-part x
))
1793 (ri (,imag-part r
)))
1794 (cond ((location= r x
)
1795 (inst ,fmul p1 xr yr
)
1796 (inst ,fmul p2 xr yi
)
1797 (inst ,fmul rr xi yi
)
1798 (inst ,fsub rr p1 xr
)
1799 (inst ,fmul p1 xi yr
)
1800 (inst ,fadd ri p2 p1
))
1802 (inst ,fmul p1 yr xr
)
1803 (inst ,fmul p2 yr xi
)
1804 (inst ,fmul rr yi xi
)
1805 (inst ,fsub rr p1 rr
)
1806 (inst ,fmul p1 yi xr
)
1807 (inst ,fadd ri p2 p1
))
1809 (inst ,fmul rr yr xr
)
1810 (inst ,fmul ri xi yi
)
1811 (inst ,fsub rr rr ri
)
1812 (inst ,fmul p1 xr yi
)
1813 (inst ,fmul ri xi yr
)
1814 (inst ,fadd ri ri p1
)))))))))
1816 (frob single fmuls fadds fsubs
6)
1817 (frob double fmuld faddd fsubd
6))
1819 ;; Multiply a complex by a float. The case of float * complex is
1820 ;; handled by a deftransform to convert it to the complex*float case.
1822 ((frob (float-type fmul mov cost
)
1823 (let* ((vop-name (symbolicate "COMPLEX-"
1828 (vop-name-r (symbolicate float-type
1832 (complex-sc-type (symbolicate "COMPLEX-" float-type
"-REG"))
1833 (real-sc-type (symbolicate float-type
"-REG"))
1834 (c-type (symbolicate "COMPLEX-" float-type
"-FLOAT"))
1835 (r-type (symbolicate float-type
"-FLOAT"))
1836 (real-part (symbolicate "COMPLEX-" float-type
"-REG-REAL-TN"))
1837 (imag-part (symbolicate "COMPLEX-" float-type
"-REG-IMAG-TN")))
1840 (define-vop (,vop-name
)
1841 (:args
(x :scs
(,complex-sc-type
))
1842 (y :scs
(,real-sc-type
)))
1843 (:results
(r :scs
(,complex-sc-type
)))
1844 (:arg-types
,c-type
,r-type
)
1845 (:result-types
,c-type
)
1846 (:policy
:fast-safe
)
1847 (:note
"inline complex float arithmetic")
1849 (:temporary
(:scs
(,real-sc-type
)) temp
)
1851 (let ((xr (,real-part x
))
1854 (ri (,imag-part r
)))
1855 (cond ((location= y rr
)
1856 (inst ,fmul temp xr y
) ; xr * y
1857 (inst ,fmul ri xi y
) ; xi * yi
1860 (inst ,fmul rr xr y
)
1861 (inst ,fmul ri xi y
))))))
1863 (define-vop (,vop-name-r
)
1864 (:args
(y :scs
(,real-sc-type
))
1865 (x :scs
(,complex-sc-type
)))
1866 (:results
(r :scs
(,complex-sc-type
)))
1867 (:arg-types
,r-type
,c-type
)
1868 (:result-types
,c-type
)
1869 (:policy
:fast-safe
)
1870 (:note
"inline complex float arithmetic")
1872 (:temporary
(:scs
(,real-sc-type
)) temp
)
1874 (let ((xr (,real-part x
))
1877 (ri (,imag-part r
)))
1878 (cond ((location= y rr
)
1879 (inst ,fmul temp xr y
) ; xr * y
1880 (inst ,fmul ri xi y
) ; xi * yi
1883 (inst ,fmul rr xr y
)
1884 (inst ,fmul ri xi y
))))))))))
1885 (frob single fmuls
(inst fmovs
) 4)
1886 (frob double fmuld
(move-double-reg) 4))
1889 ;; Divide a complex by a complex
1891 ;; Here's how we do a complex division
1893 ;; Compute (xr + i*xi)/(yr + i*yi)
1895 ;; Assume |yi| < |yr|. Then
1897 ;; (xr + i*xi) (xr + i*xi)
1898 ;; ----------- = -----------------
1899 ;; (yr + i*yi) yr*(1 + i*(yi/yr))
1901 ;; (xr + i*xi)*(1 - i*(yi/yr))
1902 ;; = ---------------------------
1903 ;; yr*(1 + (yi/yr)^2)
1905 ;; (xr + (yi/yr)*xi) + i*(xi - (yi/yr)*xr)
1906 ;; = --------------------------------------
1910 ;; We do the similar thing when |yi| > |yr|. The result is
1913 ;; (xr + i*xi) (xr + i*xi)
1914 ;; ----------- = -----------------
1915 ;; (yr + i*yi) yi*((yr/yi) + i)
1917 ;; (xr + i*xi)*((yr/yi) - i)
1918 ;; = -------------------------
1919 ;; yi*((yr/yi)^2 + 1)
1921 ;; (xr*(yr/yi) + xi) + i*(xi*(yr/yi) - xr)
1922 ;; = ---------------------------------------
1928 ((frob (float-type fcmp fadd fsub fmul fdiv fabs fmov cost
)
1929 (let ((vop-name (symbolicate "//COMPLEX-" float-type
"-FLOAT"))
1930 (complex-reg (symbolicate "COMPLEX-" float-type
"-REG"))
1931 (real-reg (symbolicate float-type
"-REG"))
1932 (c-type (symbolicate "COMPLEX-" float-type
"-FLOAT"))
1933 (real-part (symbolicate "COMPLEX-" float-type
"-REG-REAL-TN"))
1934 (imag-part (symbolicate "COMPLEX-" float-type
"-REG-IMAG-TN")))
1935 `(define-vop (,vop-name
)
1936 (:args
(x :scs
(,complex-reg
))
1937 (y :scs
(,complex-reg
)))
1938 (:results
(r :scs
(,complex-reg
)))
1939 (:arg-types
,c-type
,c-type
)
1940 (:result-types
,c-type
)
1941 (:policy
:fast-safe
)
1942 (:note
"inline complex float division")
1944 (:temporary
(:sc
,real-reg
) ratio
)
1945 (:temporary
(:sc
,real-reg
) den
)
1946 (:temporary
(:sc
,real-reg
) temp-r
)
1947 (:temporary
(:sc
,real-reg
) temp-i
)
1949 (let ((xr (,real-part x
))
1955 (bigger (gen-label))
1959 (inst ,fcmp ratio den
)
1960 (unless (member :sparc-v9
*backend-subfeatures
*)
1962 (inst fb
:ge bigger
)
1964 ;; The case of |yi| <= |yr|
1965 (inst ,fdiv ratio yi yr
) ; ratio = yi/yr
1966 (inst ,fmul den ratio yi
)
1967 (inst ,fadd den den yr
) ; den = yr + (yi/yr)*yi
1969 (inst ,fmul temp-r ratio xi
)
1970 (inst ,fadd temp-r temp-r xr
) ; temp-r = xr + (yi/yr)*xi
1971 (inst ,fdiv temp-r temp-r den
)
1973 (inst ,fmul temp-i ratio xr
)
1974 (inst ,fsub temp-i xi temp-i
) ; temp-i = xi - (yi/yr)*xr
1976 (inst ,fdiv temp-i temp-i den
)
1979 ;; The case of |yi| > |yr|
1980 (inst ,fdiv ratio yr yi
) ; ratio = yr/yi
1981 (inst ,fmul den ratio yr
)
1982 (inst ,fadd den den yi
) ; den = yi + (yr/yi)*yr
1984 (inst ,fmul temp-r ratio xr
)
1985 (inst ,fadd temp-r temp-r xi
) ; temp-r = xi + xr*(yr/yi)
1986 (inst ,fdiv temp-r temp-r den
)
1988 (inst ,fmul temp-i ratio xi
)
1989 (inst ,fsub temp-i temp-i xr
) ; temp-i = xi*(yr/yi) - xr
1990 (inst ,fdiv temp-i temp-i den
)
1993 (unless (location= temp-r rr
)
1995 (unless (location= temp-i ri
)
1999 (frob single fcmps fadds fsubs fmuls fdivs
(inst fabss
) (inst fmovs
) 15)
2000 (frob double fcmpd faddd fsubd fmuld fdivd
(abs-double-reg) (move-double-reg) 15))
2003 ((frob (float-type fcmp fadd fsub fmul fdiv fabs cost
)
2004 (let ((vop-name (symbolicate "//COMPLEX-" float-type
"-FLOAT"))
2005 (complex-reg (symbolicate "COMPLEX-" float-type
"-REG"))
2006 (real-reg (symbolicate float-type
"-REG"))
2007 (c-type (symbolicate "COMPLEX-" float-type
"-FLOAT"))
2008 (real-part (symbolicate "COMPLEX-" float-type
"-REG-REAL-TN"))
2009 (imag-part (symbolicate "COMPLEX-" float-type
"-REG-IMAG-TN")))
2010 `(define-vop (,vop-name
)
2011 (:args
(x :scs
(,complex-reg
))
2012 (y :scs
(,complex-reg
)))
2013 (:results
(r :scs
(,complex-reg
)))
2014 (:arg-types
,c-type
,c-type
)
2015 (:result-types
,c-type
)
2016 (:policy
:fast-safe
)
2017 (:note
"inline complex float division")
2019 (:temporary
(:sc
,real-reg
) ratio
)
2020 (:temporary
(:sc
,real-reg
) den
)
2021 (:temporary
(:sc
,real-reg
) temp-r
)
2022 (:temporary
(:sc
,real-reg
) temp-i
)
2024 (let ((xr (,real-part x
))
2030 (bigger (gen-label))
2034 (inst ,fcmp ratio den
)
2035 (unless (member :sparc-v9
*backend-subfeatures
*)
2037 (inst fb
:ge bigger
)
2039 ;; The case of |yi| <= |yr|
2040 (inst ,fdiv ratio yi yr
) ; ratio = yi/yr
2041 (inst ,fmul den ratio yi
)
2042 (inst ,fmul temp-r ratio xi
)
2043 (inst ,fmul temp-i ratio xr
)
2045 (inst ,fadd den den yr
) ; den = yr + (yi/yr)*yi
2046 (inst ,fadd temp-r temp-r xr
) ; temp-r = xr + (yi/yr)*xi
2048 (inst ,fsub temp-i xi temp-i
) ; temp-i = xi - (yi/yr)*xr
2052 ;; The case of |yi| > |yr|
2053 (inst ,fdiv ratio yr yi
) ; ratio = yr/yi
2054 (inst ,fmul den ratio yr
)
2055 (inst ,fmul temp-r ratio xr
)
2056 (inst ,fmul temp-i ratio xi
)
2058 (inst ,fadd den den yi
) ; den = yi + (yr/yi)*yr
2059 (inst ,fadd temp-r temp-r xi
) ; temp-r = xi + xr*(yr/yi)
2061 (inst ,fsub temp-i temp-i xr
) ; temp-i = xi*(yr/yi) - xr
2065 (inst ,fdiv rr temp-r den
)
2066 (inst ,fdiv ri temp-i den
)
2069 (frob single fcmps fadds fsubs fmuls fdivs
(inst fabss
) 15)
2070 (frob double fcmpd faddd fsubd fmuld fdivd
(abs-double-reg) 15))
2073 ;; Divide a complex by a real
2075 ((frob (float-type fdiv cost
)
2076 (let* ((vop-name (symbolicate "COMPLEX-" float-type
"-FLOAT-/-" float-type
"-FLOAT"))
2077 (complex-sc-type (symbolicate "COMPLEX-" float-type
"-REG"))
2078 (real-sc-type (symbolicate float-type
"-REG"))
2079 (c-type (symbolicate "COMPLEX-" float-type
"-FLOAT"))
2080 (r-type (symbolicate float-type
"-FLOAT"))
2081 (real-part (symbolicate "COMPLEX-" float-type
"-REG-REAL-TN"))
2082 (imag-part (symbolicate "COMPLEX-" float-type
"-REG-IMAG-TN")))
2083 `(define-vop (,vop-name
)
2084 (:args
(x :scs
(,complex-sc-type
)) (y :scs
(,real-sc-type
)))
2085 (:results
(r :scs
(,complex-sc-type
)))
2086 (:arg-types
,c-type
,r-type
)
2087 (:result-types
,c-type
)
2088 (:policy
:fast-safe
)
2089 (:note
"inline complex float arithmetic")
2092 (let ((xr (,real-part x
))
2095 (ri (,imag-part r
)))
2096 (inst ,fdiv rr xr y
) ; xr * y
2097 (inst ,fdiv ri xi y
) ; xi * yi
2099 (frob single fdivs
2)
2100 (frob double fdivd
2))
2102 ;; Divide a real by a complex
2105 ((frob (float-type fcmp fadd fmul fdiv fneg fabs cost
)
2106 (let ((vop-name (symbolicate float-type
"-FLOAT-/-COMPLEX-" float-type
"-FLOAT"))
2107 (complex-reg (symbolicate "COMPLEX-" float-type
"-REG"))
2108 (real-reg (symbolicate float-type
"-REG"))
2109 (r-type (symbolicate float-type
"-FLOAT"))
2110 (c-type (symbolicate "COMPLEX-" float-type
"-FLOAT"))
2111 (real-tn (symbolicate "COMPLEX-" float-type
"-REG-REAL-TN"))
2112 (imag-tn (symbolicate "COMPLEX-" float-type
"-REG-IMAG-TN")))
2113 `(define-vop (,vop-name
)
2114 (:args
(x :scs
(,real-reg
))
2115 (y :scs
(,complex-reg
)))
2116 (:results
(r :scs
(,complex-reg
)))
2117 (:arg-types
,r-type
,c-type
)
2118 (:result-types
,c-type
)
2119 (:policy
:fast-safe
)
2120 (:note
"inline complex float division")
2122 (:temporary
(:sc
,real-reg
) ratio
)
2123 (:temporary
(:sc
,real-reg
) den
)
2124 (:temporary
(:sc
,real-reg
) temp
)
2126 (let ((yr (,real-tn y
))
2130 (bigger (gen-label))
2134 (inst ,fcmp ratio den
)
2135 (unless (member :sparc-v9
*backend-subfeatures
*)
2137 (inst fb
:ge bigger
)
2139 ;; The case of |yi| <= |yr|
2140 (inst ,fdiv ratio yi yr
) ; ratio = yi/yr
2141 (inst ,fmul den ratio yi
)
2142 (inst ,fadd den den yr
) ; den = yr + (yi/yr)*yi
2144 (inst ,fmul temp ratio x
) ; temp = (yi/yr)*x
2145 (inst ,fdiv rr x den
) ; rr = x/den
2147 (inst ,fdiv temp temp den
) ; temp = (yi/yr)*x/den
2150 ;; The case of |yi| > |yr|
2151 (inst ,fdiv ratio yr yi
) ; ratio = yr/yi
2152 (inst ,fmul den ratio yr
)
2153 (inst ,fadd den den yi
) ; den = yi + (yr/yi)*yr
2155 (inst ,fmul temp ratio x
) ; temp = (yr/yi)*x
2156 (inst ,fdiv rr temp den
) ; rr = (yr/yi)*x/den
2157 (inst ,fdiv temp x den
) ; temp = x/den
2160 (,@fneg ri temp
)))))))
2162 (frob single fcmps fadds fmuls fdivs
(inst fnegs
) (inst fabss
) 10)
2163 (frob double fcmpd faddd fmuld fdivd
(negate-double-reg) (abs-double-reg) 10))
2165 ;; Conjugate of a complex number
2168 ((frob (float-type fneg fmov cost
)
2169 (let ((vop-name (symbolicate "CONJUGATE/COMPLEX-" float-type
"-FLOAT"))
2170 (complex-reg (symbolicate "COMPLEX-" float-type
"-REG"))
2171 (c-type (symbolicate "COMPLEX-" float-type
"-FLOAT"))
2172 (real-part (symbolicate "COMPLEX-" float-type
"-REG-REAL-TN"))
2173 (imag-part (symbolicate "COMPLEX-" float-type
"-REG-IMAG-TN")))
2174 `(define-vop (,vop-name
)
2175 (:args
(x :scs
(,complex-reg
)))
2176 (:results
(r :scs
(,complex-reg
)))
2177 (:arg-types
,c-type
)
2178 (:result-types
,c-type
)
2179 (:policy
:fast-safe
)
2180 (:note
"inline complex conjugate")
2181 (:translate conjugate
)
2183 (let ((xr (,real-part x
))
2186 (ri (,imag-part r
)))
2188 (unless (location= rr xr
)
2189 (,@fmov rr xr
))))))))
2191 (frob single
(inst fnegs
) (inst fmovs
) 4)
2192 (frob double
(negate-double-reg) (move-double-reg) 4))
2194 ;; Compare a float with a complex or a complex with a float
2197 ((frob (name name-r f-type c-type
)
2199 (defknown ,name
(,f-type
,c-type
) t
)
2200 (defknown ,name-r
(,c-type
,f-type
) t
)
2202 (declare (type ,f-type x
)
2205 (defun ,name-r
(x y
)
2206 (declare (type ,c-type x
)
2210 (frob %compare-complex-single-single %compare-single-complex-single
2211 single-float
(complex single-float
))
2212 (frob %compare-complex-double-double %compare-double-complex-double
2213 double-float
(complex double-float
)))
2217 ((frob (trans-1 trans-2 float-type fcmp fsub
)
2219 (symbolicate "COMPLEX-" float-type
"-FLOAT-"
2220 float-type
"-FLOAT-COMPARE"))
2222 (symbolicate float-type
"-FLOAT-COMPLEX-"
2223 float-type
"-FLOAT-COMPARE"))
2224 (complex-reg (symbolicate "COMPLEX-" float-type
"-REG"))
2225 (real-reg (symbolicate float-type
"-REG"))
2226 (c-type (symbolicate "COMPLEX-" float-type
"-FLOAT"))
2227 (r-type (symbolicate float-type
"-FLOAT"))
2228 (real-part (symbolicate "COMPLEX-" float-type
"-REG-REAL-TN"))
2229 (imag-part (symbolicate "COMPLEX-" float-type
"-REG-IMAG-TN")))
2231 ;; (= float complex)
2232 (define-vop (,vop-name
)
2233 (:args
(x :scs
(,real-reg
))
2234 (y :scs
(,complex-reg
)))
2235 (:arg-types
,r-type
,c-type
)
2236 (:translate
,trans-1
)
2238 (:info target not-p
)
2239 (:policy
:fast-safe
)
2240 (:note
"inline complex float/float comparison")
2242 (:save-p
:compute-only
)
2243 (:temporary
(:sc
,real-reg
) fp-zero
)
2244 (:guard
#!-
:sparc-v9 nil
#!+:sparc-v9 t
)
2246 (note-this-location vop
:internal-error
)
2247 (let ((yr (,real-part y
))
2248 (yi (,imag-part y
)))
2249 ;; Set fp-zero to zero
2250 (inst ,fsub fp-zero fp-zero fp-zero
)
2253 (inst fb
(if not-p
:ne
:eq
) target
#!+sparc-v9
:fcc0
#!+sparc-v9
:pn
)
2254 (inst ,fcmp yi fp-zero
)
2256 (inst fb
(if not-p
:ne
:eq
) target
#!+sparc-v9
:fcc0
#!+sparc-v9
:pn
)
2258 ;; (= complex float)
2259 (define-vop (,vop-name-r
)
2260 (:args
(y :scs
(,complex-reg
))
2261 (x :scs
(,real-reg
)))
2262 (:arg-types
,c-type
,r-type
)
2263 (:translate
,trans-2
)
2265 (:info target not-p
)
2266 (:policy
:fast-safe
)
2267 (:note
"inline complex float/float comparison")
2269 (:save-p
:compute-only
)
2270 (:temporary
(:sc
,real-reg
) fp-zero
)
2271 (:guard
#!-
:sparc-v9 t
#!+:sparc-v9 nil
)
2273 (note-this-location vop
:internal-error
)
2274 (let ((yr (,real-part y
))
2275 (yi (,imag-part y
)))
2276 ;; Set fp-zero to zero
2277 (inst ,fsub fp-zero fp-zero fp-zero
)
2280 (inst fb
(if not-p
:ne
:eq
) target
#!+sparc-v9
:fcc0
#!+sparc-v9
:pn
)
2281 (inst ,fcmp yi fp-zero
)
2283 (inst fb
(if not-p
:ne
:eq
) target
#!+sparc-v9
:fcc0
#!+sparc-v9
:pn
)
2285 (frob %compare-complex-single-single %compare-single-complex-single
2287 (frob %compare-complex-double-double %compare-double-complex-double
2288 double fcmpd fsubd
))
2290 ;; Compare two complex numbers for equality
2292 ((frob (float-type fcmp
)
2294 (symbolicate "COMPLEX-" float-type
"-FLOAT-COMPARE"))
2295 (complex-reg (symbolicate "COMPLEX-" float-type
"-REG"))
2296 (c-type (symbolicate "COMPLEX-" float-type
"-FLOAT"))
2297 (real-part (symbolicate "COMPLEX-" float-type
"-REG-REAL-TN"))
2298 (imag-part (symbolicate "COMPLEX-" float-type
"-REG-IMAG-TN")))
2299 `(define-vop (,vop-name
)
2300 (:args
(x :scs
(,complex-reg
))
2301 (y :scs
(,complex-reg
)))
2302 (:arg-types
,c-type
,c-type
)
2305 (:info target not-p
)
2306 (:policy
:fast-safe
)
2307 (:note
"inline complex float comparison")
2309 (:save-p
:compute-only
)
2311 (note-this-location vop
:internal-error
)
2312 (let ((xr (,real-part x
))
2315 (yi (,imag-part y
)))
2318 (inst fb
(if not-p
:ne
:eq
) target
#!+sparc-v9
:fcc0
#!+sparc-v9
:pn
)
2321 (inst fb
(if not-p
:ne
:eq
) target
#!+sparc-v9
:fcc0
#!+sparc-v9
:pn
)
2324 (frob double fcmpd
))
2326 ;; Compare a complex with a complex, for V9
2328 ((frob (float-type fcmp
)
2330 (symbolicate "V9-COMPLEX-" float-type
"-FLOAT-COMPARE"))
2331 (complex-reg (symbolicate "COMPLEX-" float-type
"-REG"))
2332 (c-type (symbolicate "COMPLEX-" float-type
"-FLOAT"))
2333 (real-part (symbolicate "COMPLEX-" float-type
"-REG-REAL-TN"))
2334 (imag-part (symbolicate "COMPLEX-" float-type
"-REG-IMAG-TN")))
2335 `(define-vop (,vop-name
)
2336 (:args
(x :scs
(,complex-reg
))
2337 (y :scs
(,complex-reg
)))
2338 (:arg-types
,c-type
,c-type
)
2341 (:info target not-p
)
2342 (:policy
:fast-safe
)
2343 (:note
"inline complex float comparison")
2345 (:save-p
:compute-only
)
2346 (:temporary
(:sc descriptor-reg
) true
)
2347 (:guard
(member :sparc-v9
*backend-subfeatures
*))
2349 (note-this-location vop
:internal-error
)
2350 (let ((xr (,real-part x
))
2353 (yi (,imag-part y
)))
2354 ;; Assume comparison is true
2355 (load-symbol true t
)
2357 (inst cmove
(if not-p
:eq
:ne
) true null-tn
:fcc0
)
2359 (inst cmove
(if not-p
:eq
:ne
) true null-tn
:fcc0
)
2360 (inst cmp true null-tn
)
2361 (inst b
(if not-p
:eq
:ne
) target
:pt
)
2364 (frob double fcmpd
))
2366 ) ; end progn complex-fp-vops
2371 ;;; The stuff below looks good, but we already have transforms for max
2372 ;;; and min. How should we arrange that?
2376 ;; Vops to take advantage of the conditional move instruction
2377 ;; available on the Sparc V9
2379 (defknown (%%max %%min
) ((or (unsigned-byte #.n-word-bits
)
2380 (signed-byte #.n-word-bits
)
2381 single-float double-float
)
2382 (or (unsigned-byte #.n-word-bits
)
2383 (signed-byte #.n-word-bits
)
2384 single-float double-float
))
2385 (or (unsigned-byte #.n-word-bits
)
2386 (signed-byte #.n-word-bits
)
2387 single-float double-float
)
2388 (movable foldable flushable
))
2390 ;; We need these definitions for byte-compiled code
2392 ;; Well, we (SBCL) probably don't, having deleted the byte
2393 ;; compiler. Let's see what happens if we comment out these
2397 (declare (type (or (unsigned-byte 32) (signed-byte 32)
2398 single-float double-float
) x y
))
2404 (declare (type (or (unsigned-byte 32) (signed-byte 32)
2405 single-float double-float
) x y
))
2410 ((frob (name sc-type type compare cmov cost cc max min note
)
2411 (let ((vop-name (symbolicate name
"-" type
"=>" type
))
2412 (trans-name (symbolicate "%%" name
)))
2413 `(define-vop (,vop-name
)
2414 (:args
(x :scs
(,sc-type
))
2415 (y :scs
(,sc-type
)))
2416 (:results
(r :scs
(,sc-type
)))
2417 (:arg-types
,type
,type
)
2418 (:result-types
,type
)
2419 (:policy
:fast-safe
)
2421 (:translate
,trans-name
)
2422 (:guard
(member :sparc-v9
*backend-subfeatures
*))
2425 (cond ((location= r x
)
2426 ;; If x < y, need to move y to r, otherwise r already has
2428 (inst ,cmov
,min r y
,cc
))
2430 ;; If x > y, need to move x to r, otherwise r already has
2432 (inst ,cmov
,max r x
,cc
))
2434 ;; It doesn't matter what R is, just copy the min to R.
2435 (inst ,cmov
,max r x
,cc
)
2436 (inst ,cmov
,min r y
,cc
))))))))
2437 (frob max single-reg single-float fcmps cfmovs
3
2438 :fcc0
:ge
:l
"inline float max")
2439 (frob max double-reg double-float fcmpd cfmovd
3
2440 :fcc0
:ge
:l
"inline float max")
2441 (frob min single-reg single-float fcmps cfmovs
3
2442 :fcc0
:l
:ge
"inline float min")
2443 (frob min double-reg double-float fcmpd cfmovd
3
2444 :fcc0
:l
:ge
"inline float min")
2445 ;; Strictly speaking these aren't float ops, but it's convenient to
2448 ;; The cost is here is the worst case number of instructions. For
2449 ;; 32-bit integer operands, we add 2 more to account for the
2450 ;; untagging of fixnums, if necessary.
2451 (frob max signed-reg signed-num cmp cmove
5
2452 :icc
:ge
:lt
"inline (signed-byte 32) max")
2453 (frob max unsigned-reg unsigned-num cmp cmove
5
2454 :icc
:ge
:lt
"inline (unsigned-byte 32) max")
2455 ;; For fixnums, make the cost lower so we don't have to untag the
2457 (frob max any-reg tagged-num cmp cmove
3
2458 :icc
:ge
:lt
"inline fixnum max")
2459 (frob min signed-reg signed-num cmp cmove
5
2460 :icc
:lt
:ge
"inline (signed-byte 32) min")
2461 (frob min unsigned-reg unsigned-num cmp cmove
5
2462 :icc
:lt
:ge
"inline (unsigned-byte 32) min")
2463 ;; For fixnums, make the cost lower so we don't have to untag the
2465 (frob min any-reg tagged-num cmp cmove
3
2466 :icc
:lt
:ge
"inline fixnum min"))
2469 (define-vop (max-boxed-double-float=>boxed-double-float
)
2470 (:args
(x :scs
(descriptor-reg))
2471 (y :scs
(descriptor-reg)))
2472 (:results
(r :scs
(descriptor-reg)))
2473 (:arg-types double-float double-float
)
2474 (:result-types double-float
)
2475 (:policy
:fast-safe
)
2476 (:note
"inline float max/min")
2477 (:translate %max-double-float
)
2478 (:temporary
(:scs
(double-reg)) xval
)
2479 (:temporary
(:scs
(double-reg)) yval
)
2480 (:guard
#!+:sparc-v9 t
#!-
:sparc-v9 nil
)
2483 (let ((offset (- (* double-float-value-slot n-word-bytes
)
2484 other-pointer-lowtag
)))
2485 (inst lddf xval x offset
)
2486 (inst lddf yval y offset
)
2487 (inst fcmpd xval yval
)
2488 (cond ((location= r x
)
2489 ;; If x < y, need to move y to r, otherwise r already has
2491 (inst cmove
:l r y
:fcc0
))
2493 ;; If x > y, need to move x to r, otherwise r already has
2495 (inst cmove
:ge r x
:fcc0
))
2497 ;; It doesn't matter what R is, just copy the min to R.
2498 (inst cmove
:ge r x
:fcc0
)
2499 (inst cmove
:l r y
:fcc0
))))))
2508 ;;; The sparc-v9 architecture has conditional move instructions that
2509 ;;; can be used. This should be faster than using the obvious if
2510 ;;; expression since we don't have to do branches.
2512 (define-source-transform min
(&rest args
)
2513 (if (member :sparc-v9
*backend-subfeatures
*)
2515 ((0 2) (values nil t
))
2516 (1 `(values ,(first args
)))
2517 (t (sb!c
::associate-arguments
'min
(first args
) (rest args
))))
2520 (define-source-transform max
(&rest args
)
2521 (if (member :sparc-v9
*backend-subfeatures
*)
2523 ((0 2) (values nil t
))
2524 (1 `(values ,(first args
)))
2525 (t (sb!c
::associate-arguments
'max
(first args
) (rest args
))))
2528 ;; Derive the types of max and min
2529 (defoptimizer (max derive-type
) ((x y
))
2530 (multiple-value-bind (definitely-< definitely-
>=)
2531 (ir1-transform-<-helper x y
)
2537 (make-canonical-union-type (list (lvar-type x
)
2540 (defoptimizer (min derive-type
) ((x y
))
2541 (multiple-value-bind (definitely-> definitely-
<=)
2542 (ir1-transform-<-helper y x
)
2543 (cond (definitely-<=
2548 (make-canonical-union-type (list (lvar-type x
)
2551 (deftransform max
((x y
) (number number
) *)
2552 (let ((x-type (lvar-type x
))
2553 (y-type (lvar-type y
))
2554 (signed (specifier-type '(signed-byte #.n-word-bits
)))
2555 (unsigned (specifier-type '(unsigned-byte #.n-word-bits
)))
2556 (d-float (specifier-type 'double-float
))
2557 (s-float (specifier-type 'single-float
)))
2558 ;; Use %%max if both args are good types of the same type. As a
2559 ;; last resort, use the obvious comparison to select the desired
2561 (cond ((and (csubtypep x-type signed
)
2562 (csubtypep y-type signed
))
2564 ((and (csubtypep x-type unsigned
)
2565 (csubtypep y-type unsigned
))
2567 ((and (csubtypep x-type d-float
)
2568 (csubtypep y-type d-float
))
2570 ((and (csubtypep x-type s-float
)
2571 (csubtypep y-type s-float
))
2574 (let ((arg1 (gensym))
2578 (if (>= ,arg1
,arg2
)
2581 (deftransform min
((x y
) (real real
) *)
2582 (let ((x-type (lvar-type x
))
2583 (y-type (lvar-type y
))
2584 (signed (specifier-type '(signed-byte #.n-word-bits
)))
2585 (unsigned (specifier-type '(unsigned-byte #.n-word-bits
)))
2586 (d-float (specifier-type 'double-float
))
2587 (s-float (specifier-type 'single-float
)))
2588 (cond ((and (csubtypep x-type signed
)
2589 (csubtypep y-type signed
))
2591 ((and (csubtypep x-type unsigned
)
2592 (csubtypep y-type unsigned
))
2594 ((and (csubtypep x-type d-float
)
2595 (csubtypep y-type d-float
))
2597 ((and (csubtypep x-type s-float
)
2598 (csubtypep y-type s-float
))
2601 (let ((arg1 (gensym))
2605 (if (<= ,arg1
,arg2
)