1 ;;;; floating point support for the x86
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 (macrolet ((ea-for-xf-desc (tn slot)
17 :disp (- (* ,slot n-word-bytes)
18 other-pointer-lowtag))))
19 (defun ea-for-df-desc (tn)
20 (ea-for-xf-desc tn double-float-value-slot))
22 (defun ea-for-csf-data-desc (tn)
23 (ea-for-xf-desc tn complex-single-float-data-slot))
24 (defun ea-for-csf-real-desc (tn)
25 (ea-for-xf-desc tn complex-single-float-data-slot))
26 (defun ea-for-csf-imag-desc (tn)
27 (ea-for-xf-desc tn (+ complex-single-float-data-slot 1/2)))
29 (defun ea-for-cdf-data-desc (tn)
30 (ea-for-xf-desc tn complex-double-float-real-slot))
31 (defun ea-for-cdf-real-desc (tn)
32 (ea-for-xf-desc tn complex-double-float-real-slot))
33 (defun ea-for-cdf-imag-desc (tn)
34 (ea-for-xf-desc tn complex-double-float-imag-slot)))
36 (macrolet ((ea-for-xf-stack (tn kind)
37 (declare (ignore kind))
40 :disp (frame-byte-offset (tn-offset ,tn)))))
41 (defun ea-for-sf-stack (tn)
42 (ea-for-xf-stack tn :single))
43 (defun ea-for-df-stack (tn)
44 (ea-for-xf-stack tn :double)))
46 ;;; complex float stack EAs
47 (macrolet ((ea-for-cxf-stack (tn kind slot &optional base)
50 :disp (frame-byte-offset
52 (cond ((= (tn-offset ,base) rsp-offset)
54 ((= (tn-offset ,base) rbp-offset)
56 (t (error "Unexpected offset.")))
66 (defun ea-for-csf-data-stack (tn &optional (base rbp-tn))
67 (ea-for-cxf-stack tn :single :real base))
68 (defun ea-for-csf-real-stack (tn &optional (base rbp-tn))
69 (ea-for-cxf-stack tn :single :real base))
70 (defun ea-for-csf-imag-stack (tn &optional (base rbp-tn))
71 (ea-for-cxf-stack tn :single :imag base))
73 (defun ea-for-cdf-data-stack (tn &optional (base rbp-tn))
74 (ea-for-cxf-stack tn :double :real base))
75 (defun ea-for-cdf-real-stack (tn &optional (base rbp-tn))
76 (ea-for-cxf-stack tn :double :real base))
77 (defun ea-for-cdf-imag-stack (tn &optional (base rbp-tn))
78 (ea-for-cxf-stack tn :double :imag base)))
82 ;;; X is source, Y is destination.
84 (define-move-fun (load-fp-zero 1) (vop x y)
85 ((fp-single-zero) (single-reg)
86 (fp-double-zero) (double-reg)
87 (fp-complex-single-zero) (complex-single-reg)
88 (fp-complex-double-zero) (complex-double-reg))
91 ((single-reg complex-single-reg) (inst xorps y y))
92 ((double-reg complex-double-reg) (inst xorpd y y))))
94 (define-move-fun (load-single 2) (vop x y)
95 ((single-stack) (single-reg))
96 (inst movss y (ea-for-sf-stack x)))
98 (define-move-fun (store-single 2) (vop x y)
99 ((single-reg) (single-stack))
100 (inst movss (ea-for-sf-stack y) x))
102 (define-move-fun (load-double 2) (vop x y)
103 ((double-stack) (double-reg))
104 (inst movsd y (ea-for-df-stack x)))
106 (define-move-fun (store-double 2) (vop x y)
107 ((double-reg) (double-stack))
108 (inst movsd (ea-for-df-stack y) x))
110 (eval-when (:compile-toplevel :execute)
111 (setf *read-default-float-format* 'single-float))
113 ;;;; complex float move functions
115 ;;; X is source, Y is destination.
116 (define-move-fun (load-complex-single 2) (vop x y)
117 ((complex-single-stack) (complex-single-reg))
118 (inst movq y (ea-for-csf-data-stack x)))
120 (define-move-fun (store-complex-single 2) (vop x y)
121 ((complex-single-reg) (complex-single-stack))
122 (inst movq (ea-for-csf-data-stack y) x))
124 (define-move-fun (load-complex-double 2) (vop x y)
125 ((complex-double-stack) (complex-double-reg))
126 (inst movupd y (ea-for-cdf-data-stack x)))
128 (define-move-fun (store-complex-double 2) (vop x y)
129 ((complex-double-reg) (complex-double-stack))
130 (inst movupd (ea-for-cdf-data-stack y) x))
134 ;;; float register to register moves
135 (macrolet ((frob (vop sc)
140 :load-if (not (location= x y))))
141 (:results (y :scs (,sc)
142 :load-if (not (location= x y))))
146 (define-move-vop ,vop :move (,sc) (,sc)))))
147 (frob single-move single-reg)
148 (frob double-move double-reg)
149 (frob complex-single-move complex-single-reg)
150 (frob complex-double-move complex-double-reg))
153 ;;; Move from float to a descriptor reg. allocating a new float
154 ;;; object in the process.
155 (define-vop (move-from-single)
156 (:args (x :scs (single-reg) :to :save))
157 (:results (y :scs (descriptor-reg)))
158 (:note "float to pointer coercion")
162 (inst or y single-float-widetag)))
164 (define-move-vop move-from-single :move
165 (single-reg) (descriptor-reg))
167 (define-vop (move-from-double)
168 (:args (x :scs (double-reg) :to :save))
169 (:results (y :scs (descriptor-reg)))
171 (:note "float to pointer coercion")
173 (with-fixed-allocation (y
177 (inst movsd (ea-for-df-desc y) x))))
178 (define-move-vop move-from-double :move
179 (double-reg) (descriptor-reg))
181 ;;; Move from a descriptor to a float register.
182 (define-vop (move-to-single)
183 (:args (x :scs (descriptor-reg) :target tmp))
184 (:temporary (:sc unsigned-reg) tmp)
185 (:results (y :scs (single-reg)))
186 (:note "pointer to float coercion")
192 (define-move-vop move-to-single :move (descriptor-reg) (single-reg))
194 (define-vop (move-to-double)
195 (:args (x :scs (descriptor-reg)))
196 (:results (y :scs (double-reg)))
197 (:note "pointer to float coercion")
199 (inst movsd y (ea-for-df-desc x))))
200 (define-move-vop move-to-double :move (descriptor-reg) (double-reg))
203 ;;; Move from complex float to a descriptor reg. allocating a new
204 ;;; complex float object in the process.
205 (define-vop (move-from-complex-single)
206 (:args (x :scs (complex-single-reg) :to :save))
207 (:results (y :scs (descriptor-reg)))
209 (:note "complex float to pointer coercion")
211 (with-fixed-allocation (y
212 complex-single-float-widetag
213 complex-single-float-size
215 (inst movq (ea-for-csf-data-desc y) x))))
216 (define-move-vop move-from-complex-single :move
217 (complex-single-reg) (descriptor-reg))
219 (define-vop (move-from-complex-double)
220 (:args (x :scs (complex-double-reg) :to :save))
221 (:results (y :scs (descriptor-reg)))
223 (:note "complex float to pointer coercion")
225 (with-fixed-allocation (y
226 complex-double-float-widetag
227 complex-double-float-size
229 (inst movapd (ea-for-cdf-data-desc y) x))))
230 (define-move-vop move-from-complex-double :move
231 (complex-double-reg) (descriptor-reg))
233 ;;; Move from a descriptor to a complex float register.
234 (macrolet ((frob (name sc format)
237 (:args (x :scs (descriptor-reg)))
238 (:results (y :scs (,sc)))
239 (:note "pointer to complex float coercion")
243 '(inst movq y (ea-for-csf-data-desc x)))
245 '(inst movapd y (ea-for-cdf-data-desc x))))))
246 (define-move-vop ,name :move (descriptor-reg) (,sc)))))
247 (frob move-to-complex-single complex-single-reg :single)
248 (frob move-to-complex-double complex-double-reg :double))
250 ;;;; the move argument vops
252 ;;;; Note these are also used to stuff fp numbers onto the c-call
253 ;;;; stack so the order is different than the lisp-stack.
255 ;;; the general MOVE-ARG VOP
256 (macrolet ((frob (name sc stack-sc format)
259 (:args (x :scs (,sc) :target y)
261 :load-if (not (sc-is y ,sc))))
263 (:note "float argument move")
264 (:generator ,(case format (:single 2) (:double 3) )
269 (if (= (tn-offset fp) esp-offset)
270 (let* ((offset (* (tn-offset y) n-word-bytes))
271 (ea (make-ea :dword :base fp :disp offset)))
273 (:single '((inst movss ea x)))
274 (:double '((inst movsd ea x)))))
277 :disp (frame-byte-offset (tn-offset y)))))
279 (:single '((inst movss ea x)))
280 (:double '((inst movsd ea x))))))))))
281 (define-move-vop ,name :move-arg
282 (,sc descriptor-reg) (,sc)))))
283 (frob move-single-float-arg single-reg single-stack :single)
284 (frob move-double-float-arg double-reg double-stack :double))
286 ;;;; complex float MOVE-ARG VOP
287 (macrolet ((frob (name sc stack-sc format)
290 (:args (x :scs (,sc) :target y)
292 :load-if (not (sc-is y ,sc))))
294 (:note "complex float argument move")
295 (:generator ,(ecase format (:single 2) (:double 3))
302 '(inst movq (ea-for-csf-data-stack y fp) x))
304 '(inst movupd (ea-for-cdf-data-stack y fp) x)))))))
305 (define-move-vop ,name :move-arg
306 (,sc descriptor-reg) (,sc)))))
307 (frob move-complex-single-float-arg
308 complex-single-reg complex-single-stack :single)
309 (frob move-complex-double-float-arg
310 complex-double-reg complex-double-stack :double))
312 (define-move-vop move-arg :move-arg
313 (single-reg double-reg
314 complex-single-reg complex-double-reg)
320 (define-vop (float-op)
324 (:note "inline float arithmetic")
326 (:save-p :compute-only))
328 (macrolet ((frob (name sc ptype)
329 `(define-vop (,name float-op)
330 (:args (x :scs (,sc) :target r)
332 (:results (r :scs (,sc)))
333 (:arg-types ,ptype ,ptype)
334 (:result-types ,ptype))))
335 (frob single-float-op single-reg single-float)
336 (frob double-float-op double-reg double-float)
337 (frob complex-single-float-op complex-single-reg complex-single-float)
338 (frob complex-double-float-op complex-double-reg complex-double-float))
340 (macrolet ((generate (opinst commutative)
345 ((and ,commutative (location= y r))
347 ((not (location= r y))
354 (frob (op sinst sname scost dinst dname dcost commutative
355 &optional csinst csname cscost cdinst cdname cdcost)
357 (define-vop (,sname single-float-op)
359 (:temporary (:sc single-reg) tmp)
361 (generate ,sinst ,commutative)))
362 (define-vop (,dname double-float-op)
364 (:temporary (:sc double-reg) tmp)
366 (generate ,dinst ,commutative)))
368 `(define-vop (,csname complex-single-float-op)
370 (:temporary (:sc complex-single-reg) tmp)
372 (generate ,csinst ,commutative))))
374 `(define-vop (,cdname complex-double-float-op)
376 (:temporary (:sc complex-double-reg) tmp)
378 (generate ,cdinst ,commutative)))))))
379 (frob + addss +/single-float 2 addsd +/double-float 2 t
380 addps +/complex-single-float 3 addpd +/complex-double-float 3)
381 (frob - subss -/single-float 2 subsd -/double-float 2 nil
382 subps -/complex-single-float 3 subpd -/complex-double-float 3)
383 (frob * mulss */single-float 4 mulsd */double-float 5 t)
384 (frob / divss //single-float 12 divsd //double-float 19 nil))
386 (macrolet ((frob (op cost commutativep
387 duplicate-inst op-inst
388 real-sc real-type complex-sc complex-type
389 real-complex-name complex-real-name)
390 (cond ((not duplicate-inst) ; simple case
392 ,(when real-complex-name
393 `(define-vop (,real-complex-name float-op)
395 (:args (x :scs (,real-sc) :target r)
396 (y :scs (,complex-sc)
397 ,@(when commutativep '(:target r))))
398 (:arg-types ,real-type ,complex-type)
399 (:results (r :scs (,complex-sc)
400 ,@(unless commutativep '(:from (:argument 0)))))
401 (:result-types ,complex-type)
404 `(when (location= y r)
407 (inst ,op-inst r y))))
409 ,(when complex-real-name
410 `(define-vop (,complex-real-name float-op)
412 (:args (x :scs (,complex-sc) :target r)
414 ,@(when commutativep '(:target r))))
415 (:arg-types ,complex-type ,real-type)
416 (:results (r :scs (,complex-sc)
417 ,@(unless commutativep '(:from (:argument 0)))))
418 (:result-types ,complex-type)
421 `(when (location= y r)
424 (inst ,op-inst r y))))))
425 (commutativep ; must duplicate, but commutative
427 ,(when real-complex-name
428 `(define-vop (,real-complex-name float-op)
430 (:args (x :scs (,real-sc) :target dup)
431 (y :scs (,complex-sc) :target r
433 (:arg-types ,real-type ,complex-type)
434 (:temporary (:sc ,complex-sc :target r
438 (:results (r :scs (,complex-sc)))
439 (:result-types ,complex-type)
444 (when (location= dup r)
447 (inst ,op-inst r dup))))
449 ,(when complex-real-name
450 `(define-vop (,complex-real-name float-op)
452 (:args (x :scs (,complex-sc) :target r
454 (y :scs (,real-sc) :target dup))
455 (:arg-types ,complex-type ,real-type)
456 (:temporary (:sc ,complex-sc :target r
460 (:results (r :scs (,complex-sc)))
461 (:result-types ,complex-type)
465 (when (location= dup r)
468 (inst ,op-inst r dup))))))
469 (t ; duplicate, not commutative
471 ,(when real-complex-name
472 `(define-vop (,real-complex-name float-op)
474 (:args (x :scs (,real-sc)
476 (y :scs (,complex-sc) :to :result))
477 (:arg-types ,real-type ,complex-type)
478 (:results (r :scs (,complex-sc) :from (:argument 0)))
479 (:result-types ,complex-type)
484 (inst ,op-inst r y))))
486 ,(when complex-real-name
487 `(define-vop (,complex-real-name float-op)
489 (:args (x :scs (,complex-sc) :target r
491 (y :scs (,real-sc) :target dup))
492 (:arg-types ,complex-type ,real-type)
493 (:temporary (:sc ,complex-sc :from (:argument 1))
495 (:results (r :scs (,complex-sc) :from :eval))
496 (:result-types ,complex-type)
501 (inst ,op-inst r dup))))))))
502 (def-real-complex-op (op commutativep duplicatep
503 single-inst single-real-complex-name single-complex-real-name single-cost
504 double-inst double-real-complex-name double-complex-real-name double-cost)
506 (frob ,op ,single-cost ,commutativep
510 (inst unpcklps dup dup)))
512 single-reg single-float complex-single-reg complex-single-float
513 ,single-real-complex-name ,single-complex-real-name)
514 (frob ,op ,double-cost ,commutativep
518 (inst unpcklpd dup dup)))
520 double-reg double-float complex-double-reg complex-double-float
521 ,double-real-complex-name ,double-complex-real-name))))
522 (def-real-complex-op + t nil
523 addps +/real-complex-single-float +/complex-real-single-float 3
524 addpd +/real-complex-double-float +/complex-real-double-float 4)
525 (def-real-complex-op - nil nil
526 subps -/real-complex-single-float -/complex-real-single-float 3
527 subpd -/real-complex-double-float -/complex-real-double-float 4)
528 (def-real-complex-op * t t
529 mulps */real-complex-single-float */complex-real-single-float 4
530 mulpd */real-complex-double-float */complex-real-double-float 5)
531 (def-real-complex-op / nil t
533 divpd nil //complex-real-double-float 19))
535 (define-vop (//complex-real-single-float float-op)
537 (:args (x :scs (complex-single-reg)
540 (y :scs (single-reg) :target dup))
541 (:arg-types complex-single-float single-float)
542 (:temporary (:sc complex-single-reg :from (:argument 1)) dup)
543 (:results (r :scs (complex-single-reg)))
544 (:result-types complex-single-float)
547 (inst shufps dup dup #b00000000)
553 ;; Complex multiplication
554 ;; r := rx * ry - ix * iy
555 ;; i := rx * iy + ix * ry
557 ;; Transpose for SIMDness
562 ;;+ [ix ix] * [-iy ry]
565 (macrolet ((define-complex-* (name cost type sc &body body)
566 `(define-vop (,name float-op)
568 (:args (x :scs (,sc) :target r)
569 (y :scs (,sc) :target copy-y))
570 (:arg-types ,type ,type)
571 (:temporary (:sc any-reg) hex8)
572 (:temporary (:sc ,sc) imag)
573 (:temporary (:sc ,sc :from :eval) copy-y)
574 (:temporary (:sc ,sc) xmm)
575 (:results (r :scs (,sc) :from :eval))
576 (:result-types ,type)
578 (when (or (location= x copy-y)
582 (define-complex-* */complex-single-float 20 complex-single-float complex-single-reg
587 (inst unpckhpd imag xmm)
588 (inst unpcklpd r xmm)
589 (move copy-y y) ; y == r only if y == x == r
592 (inst lea hex8 (make-ea :qword :disp 1))
598 (inst shufps y y #b11110001)
603 (define-complex-* */complex-double-float 25 complex-double-float complex-double-reg
609 (inst unpckhpd imag imag)
610 (inst lea hex8 (make-ea :qword :disp 1))
611 (inst ror hex8 1) ; #x8000000000000000
616 (inst shufpd y y #b01)
620 (inst addpd r imag)))
623 (:args (x :scs (double-reg)))
624 (:results (y :scs (double-reg)))
627 (:arg-types double-float)
628 (:result-types double-float)
629 (:note "inline float arithmetic")
631 (:save-p :compute-only)
633 (note-this-location vop :internal-error)
636 (macrolet ((frob ((name translate sc type) &body body)
638 (:args (x :scs (,sc)))
639 (:results (y :scs (,sc)))
640 (:translate ,translate)
643 (:result-types ,type)
644 (:temporary (:sc any-reg) hex8)
647 (:note "inline float arithmetic")
649 (:save-p :compute-only)
651 (note-this-location vop :internal-error)
652 ;; we should be able to do this better. what we
653 ;; really would like to do is use the target as the
654 ;; temp whenever it's not also the source
657 (frob (%negate/double-float %negate double-reg double-float)
658 (inst lea hex8 (make-ea :qword :disp 1))
659 (inst ror hex8 1) ; #x8000000000000000
662 (frob (%negate/complex-double-float %negate complex-double-reg complex-double-float)
663 (inst lea hex8 (make-ea :qword :disp 1))
664 (inst ror hex8 1) ; #x8000000000000000
666 (inst unpcklpd xmm xmm)
668 (frob (conjugate/complex-double-float conjugate complex-double-reg complex-double-float)
669 (inst lea hex8 (make-ea :qword :disp 1))
670 (inst ror hex8 1) ; #x8000000000000000
672 (inst shufpd xmm xmm #b01)
674 (frob (%negate/single-float %negate single-reg single-float)
675 (inst lea hex8 (make-ea :qword :disp 1))
679 (frob (%negate/complex-single-float %negate complex-single-reg complex-single-float)
680 (inst lea hex8 (make-ea :qword :disp 1))
683 (inst unpcklps xmm xmm)
685 (frob (conjugate/complex-single-float conjugate complex-single-reg complex-single-float)
686 (inst lea hex8 (make-ea :qword :disp 1))
687 (inst ror hex8 1) ; #x8000000000000000
690 (frob (abs/double-float abs double-reg double-float)
695 (frob (abs/single-float abs single-reg single-float)
704 (define-vop (float-compare)
707 (:save-p :compute-only)
708 (:note "inline float comparison"))
711 (macrolet ((define-float-eql (name cost sc type)
712 `(define-vop (,name float-compare)
714 (:args (x :scs (,sc) :target mask)
715 (y :scs (,sc) :target mask))
716 (:arg-types ,type ,type)
717 (:temporary (:sc ,sc :from :eval) mask)
718 (:temporary (:sc any-reg) bits)
721 (when (location= y mask)
724 (inst pcmpeqd mask y)
725 (inst movmskps bits mask)
726 (inst cmp bits #b1111)))))
727 (define-float-eql eql/single-float 4
728 single-reg single-float)
729 (define-float-eql eql/double-float 4
730 double-reg double-float)
731 (define-float-eql eql/complex-double-float 5
732 complex-double-reg complex-double-float)
733 (define-float-eql eql/complex-single-float 5
734 complex-single-reg complex-single-float))
736 ;;; comiss and comisd can cope with one or other arg in memory: we
737 ;;; could (should, indeed) extend these to cope with descriptor args
740 (define-vop (single-float-compare float-compare)
741 (:args (x :scs (single-reg)) (y :scs (single-reg)))
742 (:arg-types single-float single-float))
743 (define-vop (double-float-compare float-compare)
744 (:args (x :scs (double-reg)) (y :scs (double-reg)))
745 (:arg-types double-float double-float))
747 (define-vop (=/single-float single-float-compare)
750 (:conditional not :p :ne)
753 (note-this-location vop :internal-error)
755 ;; if PF&CF, there was a NaN involved => not equal
756 ;; otherwise, ZF => equal
759 (define-vop (=/double-float double-float-compare)
762 (:conditional not :p :ne)
765 (note-this-location vop :internal-error)
768 (macrolet ((define-complex-float-= (complex-complex-name complex-real-name real-complex-name
769 real-sc real-type complex-sc complex-type
770 cmp-inst mask-inst mask)
772 (define-vop (,complex-complex-name float-compare)
774 (:args (x :scs (,complex-sc) :target cmp)
775 (y :scs (,complex-sc) :target cmp))
776 (:arg-types ,complex-type ,complex-type)
777 (:temporary (:sc ,complex-sc :from :eval) cmp)
778 (:temporary (:sc unsigned-reg) bits)
782 (when (location= y cmp)
785 (note-this-location vop :internal-error)
786 (inst ,cmp-inst :eq cmp y)
787 (inst ,mask-inst bits cmp)
788 (inst cmp bits ,mask)))
789 (define-vop (,complex-real-name ,complex-complex-name)
790 (:args (x :scs (,complex-sc) :target cmp)
791 (y :scs (,real-sc) :target cmp))
792 (:arg-types ,complex-type ,real-type))
793 (define-vop (,real-complex-name ,complex-complex-name)
794 (:args (x :scs (,real-sc) :target cmp)
795 (y :scs (,complex-sc) :target cmp))
796 (:arg-types ,real-type ,complex-type)))))
797 (define-complex-float-= =/complex-single-float =/complex-real-single-float =/real-complex-single-float
798 single-reg single-float complex-single-reg complex-single-float
799 cmpps movmskps #b1111)
800 (define-complex-float-= =/complex-double-float =/complex-real-double-float =/real-complex-double-float
801 double-reg double-float complex-double-reg complex-double-float
802 cmppd movmskpd #b11))
804 (define-vop (<double-float double-float-compare)
807 (:conditional not :p :nc)
811 (define-vop (<single-float single-float-compare)
814 (:conditional not :p :nc)
818 (define-vop (>double-float double-float-compare)
821 (:conditional not :p :na)
825 (define-vop (>single-float single-float-compare)
828 (:conditional not :p :na)
836 (macrolet ((frob (name translate inst to-sc to-type)
838 (:args (x :scs (signed-stack signed-reg) :target temp))
839 (:temporary (:sc signed-stack) temp)
840 (:results (y :scs (,to-sc)))
841 (:arg-types signed-num)
842 (:result-types ,to-type)
844 (:note "inline float coercion")
845 (:translate ,translate)
847 (:save-p :compute-only)
852 (note-this-location vop :internal-error)
855 (note-this-location vop :internal-error)
856 (inst ,inst y x)))))))
857 (frob %single-float/signed %single-float cvtsi2ss single-reg single-float)
858 (frob %double-float/signed %double-float cvtsi2sd double-reg double-float))
860 (macrolet ((frob (name translate inst from-sc from-type to-sc to-type)
862 (:args (x :scs (,from-sc) :target y))
863 (:results (y :scs (,to-sc)))
864 (:arg-types ,from-type)
865 (:result-types ,to-type)
867 (:note "inline float coercion")
868 (:translate ,translate)
870 (:save-p :compute-only)
872 (note-this-location vop :internal-error)
874 (frob %single-float/double-float %single-float cvtsd2ss double-reg
875 double-float single-reg single-float)
877 (frob %double-float/single-float %double-float cvtss2sd
878 single-reg single-float double-reg double-float))
880 (macrolet ((frob (trans inst from-sc from-type round-p)
881 (declare (ignore round-p))
882 `(define-vop (,(symbolicate trans "/" from-type))
883 (:args (x :scs (,from-sc)))
884 (:temporary (:sc any-reg) temp-reg)
885 (:results (y :scs (signed-reg)))
886 (:arg-types ,from-type)
887 (:result-types signed-num)
890 (:note "inline float truncate")
892 (:save-p :compute-only)
896 (inst ,inst temp-reg x)
901 (frob %unary-truncate cvttss2si single-reg single-float nil)
902 (frob %unary-truncate cvttsd2si double-reg double-float nil)
904 (frob %unary-round cvtss2si single-reg single-float t)
905 (frob %unary-round cvtsd2si double-reg double-float t))
907 (define-vop (make-single-float)
908 (:args (bits :scs (signed-reg) :target res
909 :load-if (not (or (and (sc-is bits signed-stack)
910 (sc-is res single-reg))
911 (and (sc-is bits signed-stack)
912 (sc-is res single-stack)
913 (location= bits res))))))
914 (:results (res :scs (single-reg single-stack)))
915 (:arg-types signed-num)
916 (:result-types single-float)
917 (:translate make-single-float)
927 (aver (location= bits res)))))
931 (inst movd res bits))
933 (inst movd res bits)))))))
935 (define-vop (make-double-float)
936 (:args (hi-bits :scs (signed-reg))
937 (lo-bits :scs (unsigned-reg)))
938 (:results (res :scs (double-reg)))
939 (:temporary (:sc unsigned-reg) temp)
940 (:arg-types signed-num unsigned-num)
941 (:result-types double-float)
942 (:translate make-double-float)
948 (inst or temp lo-bits)
949 (inst movd res temp)))
951 (define-vop (single-float-bits)
952 (:args (float :scs (single-reg descriptor-reg)
953 :load-if (not (sc-is float single-stack))))
954 (:results (bits :scs (signed-reg)))
955 (:temporary (:sc signed-stack :from :argument :to :result) stack-temp)
956 (:arg-types single-float)
957 (:result-types signed-num)
958 (:translate single-float-bits)
966 (inst movss stack-temp float)
967 (move bits stack-temp))
972 (inst shr bits 32))))
976 (inst movss bits float)))))
981 (define-vop (double-float-high-bits)
982 (:args (float :scs (double-reg descriptor-reg)
983 :load-if (not (sc-is float double-stack))))
984 (:results (hi-bits :scs (signed-reg)))
985 (:temporary (:sc signed-stack :from :argument :to :result) temp)
986 (:arg-types double-float)
987 (:result-types signed-num)
988 (:translate double-float-high-bits)
994 (inst movsd temp float)
997 (loadw hi-bits ebp-tn (frame-word-offset (tn-offset float))))
999 (loadw hi-bits float double-float-value-slot
1000 other-pointer-lowtag)))
1001 (inst sar hi-bits 32)))
1003 (define-vop (double-float-low-bits)
1004 (:args (float :scs (double-reg descriptor-reg)
1005 :load-if (not (sc-is float double-stack))))
1006 (:results (lo-bits :scs (unsigned-reg)))
1007 (:temporary (:sc signed-stack :from :argument :to :result) temp)
1008 (:arg-types double-float)
1009 (:result-types unsigned-num)
1010 (:translate double-float-low-bits)
1011 (:policy :fast-safe)
1016 (inst movsd temp float)
1017 (move lo-bits temp))
1019 (loadw lo-bits ebp-tn (frame-word-offset (tn-offset float))))
1021 (loadw lo-bits float double-float-value-slot
1022 other-pointer-lowtag)))
1023 (inst shl lo-bits 32)
1024 (inst shr lo-bits 32)))
1028 ;;;; complex float VOPs
1030 (define-vop (make-complex-single-float)
1031 (:translate complex)
1032 (:args (real :scs (single-reg fp-single-zero)
1034 :load-if (not (sc-is real fp-single-zero)))
1035 (imag :scs (single-reg fp-single-zero)
1036 :load-if (not (sc-is imag fp-single-zero))))
1037 (:arg-types single-float single-float)
1038 (:results (r :scs (complex-single-reg) :from (:argument 0)))
1039 (:result-types complex-single-float)
1040 (:note "inline complex single-float creation")
1041 (:policy :fast-safe)
1043 (cond ((sc-is real fp-single-zero)
1045 (unless (sc-is imag fp-single-zero)
1046 (inst unpcklps r imag)))
1047 ((location= real imag)
1049 (inst unpcklps r r))
1052 (unless (sc-is imag fp-single-zero)
1053 (inst unpcklps r imag))))))
1055 (define-vop (make-complex-double-float)
1056 (:translate complex)
1057 (:args (real :scs (double-reg fp-double-zero)
1059 :load-if (not (sc-is real fp-double-zero)))
1060 (imag :scs (double-reg fp-double-zero)
1061 :load-if (not (sc-is imag fp-double-zero))))
1062 (:arg-types double-float double-float)
1063 (:results (r :scs (complex-double-reg) :from (:argument 0)))
1064 (:result-types complex-double-float)
1065 (:note "inline complex double-float creation")
1066 (:policy :fast-safe)
1068 (cond ((sc-is real fp-double-zero)
1070 (unless (sc-is imag fp-double-zero)
1071 (inst unpcklpd r imag)))
1072 ((location= real imag)
1074 (inst unpcklpd r r))
1077 (unless (sc-is imag fp-double-zero)
1078 (inst unpcklpd r imag))))))
1080 (define-vop (complex-float-value)
1081 (:args (x :target r))
1082 (:temporary (:sc complex-double-reg) zero)
1084 (:variant-vars offset)
1085 (:policy :fast-safe)
1087 (cond ((sc-is x complex-double-reg)
1089 (inst xorpd zero zero)
1091 (0 (inst unpcklpd r zero))
1092 (1 (inst unpckhpd r zero))))
1093 ((sc-is x complex-single-reg)
1096 (0 (inst shufps r r #b11111100))
1097 (1 (inst shufps r r #b11111101))))
1098 ((sc-is r single-reg)
1099 (let ((ea (sc-case x
1100 (complex-single-stack
1102 (0 (ea-for-csf-real-stack x))
1103 (1 (ea-for-csf-imag-stack x))))
1106 (0 (ea-for-csf-real-desc x))
1107 (1 (ea-for-csf-imag-desc x)))))))
1109 ((sc-is r double-reg)
1110 (let ((ea (sc-case x
1111 (complex-double-stack
1113 (0 (ea-for-cdf-real-stack x))
1114 (1 (ea-for-cdf-imag-stack x))))
1117 (0 (ea-for-cdf-real-desc x))
1118 (1 (ea-for-cdf-imag-desc x)))))))
1120 (t (error "COMPLEX-FLOAT-VALUE VOP failure")))))
1122 (define-vop (realpart/complex-single-float complex-float-value)
1123 (:translate realpart)
1124 (:args (x :scs (complex-single-reg complex-single-stack descriptor-reg)
1126 (:arg-types complex-single-float)
1127 (:results (r :scs (single-reg)))
1128 (:result-types single-float)
1129 (:note "complex float realpart")
1132 (define-vop (realpart/complex-double-float complex-float-value)
1133 (:translate realpart)
1134 (:args (x :scs (complex-double-reg complex-double-stack descriptor-reg)
1136 (:arg-types complex-double-float)
1137 (:results (r :scs (double-reg)))
1138 (:result-types double-float)
1139 (:note "complex float realpart")
1142 (define-vop (imagpart/complex-single-float complex-float-value)
1143 (:translate imagpart)
1144 (:args (x :scs (complex-single-reg complex-single-stack descriptor-reg)
1146 (:arg-types complex-single-float)
1147 (:results (r :scs (single-reg)))
1148 (:result-types single-float)
1149 (:note "complex float imagpart")
1152 (define-vop (imagpart/complex-double-float complex-float-value)
1153 (:translate imagpart)
1154 (:args (x :scs (complex-double-reg complex-double-stack descriptor-reg)
1156 (:arg-types complex-double-float)
1157 (:results (r :scs (double-reg)))
1158 (:result-types double-float)
1159 (:note "complex float imagpart")
1163 ;;; hack dummy VOPs to bias the representation selection of their
1164 ;;; arguments towards a FP register, which can help avoid consing at
1165 ;;; inappropriate locations
1166 (defknown double-float-reg-bias (double-float) (values))
1167 (define-vop (double-float-reg-bias)
1168 (:translate double-float-reg-bias)
1169 (:args (x :scs (double-reg double-stack) :load-if nil))
1170 (:arg-types double-float)
1171 (:policy :fast-safe)
1172 (:note "inline dummy FP register bias")
1175 (defknown single-float-reg-bias (single-float) (values))
1176 (define-vop (single-float-reg-bias)
1177 (:translate single-float-reg-bias)
1178 (:args (x :scs (single-reg single-stack) :load-if nil))
1179 (:arg-types single-float)
1180 (:policy :fast-safe)
1181 (:note "inline dummy FP register bias")
1185 (defknown swap-complex ((complex float)) (complex float)
1186 (foldable flushable movable always-translatable))
1187 (defoptimizer (swap-complex derive-type) ((x))
1188 (sb!c::lvar-type x))
1189 (defun swap-complex (x)
1190 (complex (imagpart x) (realpart x)))
1191 (define-vop (swap-complex-single-float)
1192 (:translate swap-complex)
1193 (:policy :fast-safe)
1194 (:args (x :scs (complex-single-reg) :target r))
1195 (:arg-types complex-single-float)
1196 (:results (r :scs (complex-single-reg)))
1197 (:result-types complex-single-float)
1200 (inst shufps r r #b11110001)))
1201 (define-vop (swap-complex-double-float)
1202 (:translate swap-complex)
1203 (:policy :fast-safe)
1204 (:args (x :scs (complex-double-reg) :target r))
1205 (:arg-types complex-double-float)
1206 (:results (r :scs (complex-double-reg)))
1207 (:result-types complex-double-float)
1210 (inst shufpd r r #b01)))