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-real-desc (tn)
23 (ea-for-xf-desc tn complex-single-float-real-slot))
24 (defun ea-for-csf-imag-desc (tn)
25 (ea-for-xf-desc tn complex-single-float-imag-slot))
26 (defun ea-for-cdf-real-desc (tn)
27 (ea-for-xf-desc tn complex-double-float-real-slot))
28 (defun ea-for-cdf-imag-desc (tn)
29 (ea-for-xf-desc tn complex-double-float-imag-slot)))
31 (macrolet ((ea-for-xf-stack (tn kind)
32 (declare (ignore kind))
35 :disp (- (* (+ (tn-offset ,tn) 1)
37 (defun ea-for-sf-stack (tn)
38 (ea-for-xf-stack tn :single))
39 (defun ea-for-df-stack (tn)
40 (ea-for-xf-stack tn :double)))
42 ;;; complex float stack EAs
43 (macrolet ((ea-for-cxf-stack (tn kind slot &optional base)
44 (declare (ignore kind))
47 :disp (- (* (+ (tn-offset ,tn)
48 (* 1 (ecase ,slot (:real 1) (:imag 2))))
50 (defun ea-for-csf-real-stack (tn &optional (base rbp-tn))
51 (ea-for-cxf-stack tn :single :real base))
52 (defun ea-for-csf-imag-stack (tn &optional (base rbp-tn))
53 (ea-for-cxf-stack tn :single :imag base))
54 (defun ea-for-cdf-real-stack (tn &optional (base rbp-tn))
55 (ea-for-cxf-stack tn :double :real base))
56 (defun ea-for-cdf-imag-stack (tn &optional (base rbp-tn))
57 (ea-for-cxf-stack tn :double :imag base)))
62 ;;; X is source, Y is destination.
64 (define-move-fun (load-fp-zero 1) (vop x y)
65 ((fp-single-zero) (single-reg)
66 (fp-double-zero) (double-reg))
67 (identity x) ; KLUDGE: IDENTITY as IGNORABLE...
68 (inst movq y fp-double-zero-tn))
70 (define-move-fun (load-single 2) (vop x y)
71 ((single-stack) (single-reg))
72 (inst movss y (ea-for-sf-stack x)))
74 (define-move-fun (store-single 2) (vop x y)
75 ((single-reg) (single-stack))
76 (inst movss (ea-for-sf-stack y) x))
78 (define-move-fun (load-double 2) (vop x y)
79 ((double-stack) (double-reg))
80 (inst movsd y (ea-for-df-stack x)))
82 (define-move-fun (store-double 2) (vop x y)
83 ((double-reg) (double-stack))
84 (inst movsd (ea-for-df-stack y) x))
86 (eval-when (:compile-toplevel :execute)
87 (setf *read-default-float-format* 'single-float))
89 ;;;; complex float move functions
91 (defun complex-single-reg-real-tn (x)
92 (make-random-tn :kind :normal :sc (sc-or-lose 'single-reg)
93 :offset (tn-offset x)))
94 (defun complex-single-reg-imag-tn (x)
95 (make-random-tn :kind :normal :sc (sc-or-lose 'single-reg)
96 :offset (1+ (tn-offset x))))
98 (defun complex-double-reg-real-tn (x)
99 (make-random-tn :kind :normal :sc (sc-or-lose 'double-reg)
100 :offset (tn-offset x)))
101 (defun complex-double-reg-imag-tn (x)
102 (make-random-tn :kind :normal :sc (sc-or-lose 'double-reg)
103 :offset (1+ (tn-offset x))))
105 ;;; X is source, Y is destination.
106 (define-move-fun (load-complex-single 2) (vop x y)
107 ((complex-single-stack) (complex-single-reg))
108 (let ((real-tn (complex-single-reg-real-tn y)))
109 (inst movss real-tn (ea-for-csf-real-stack x)))
110 (let ((imag-tn (complex-single-reg-imag-tn y)))
111 (inst movss imag-tn (ea-for-csf-imag-stack x))))
113 (define-move-fun (store-complex-single 2) (vop x y)
114 ((complex-single-reg) (complex-single-stack))
115 (let ((real-tn (complex-single-reg-real-tn x))
116 (imag-tn (complex-single-reg-imag-tn x)))
117 (inst movss (ea-for-csf-real-stack y) real-tn)
118 (inst movss (ea-for-csf-imag-stack y) imag-tn)))
120 (define-move-fun (load-complex-double 2) (vop x y)
121 ((complex-double-stack) (complex-double-reg))
122 (let ((real-tn (complex-double-reg-real-tn y)))
123 (inst movsd real-tn (ea-for-cdf-real-stack x)))
124 (let ((imag-tn (complex-double-reg-imag-tn y)))
125 (inst movsd imag-tn (ea-for-cdf-imag-stack x))))
127 (define-move-fun (store-complex-double 2) (vop x y)
128 ((complex-double-reg) (complex-double-stack))
129 (let ((real-tn (complex-double-reg-real-tn x))
130 (imag-tn (complex-double-reg-imag-tn x)))
131 (inst movsd (ea-for-cdf-real-stack y) real-tn)
132 (inst movsd (ea-for-cdf-imag-stack y) imag-tn)))
137 ;;; float register to register moves
138 (macrolet ((frob (vop sc)
143 :load-if (not (location= x y))))
144 (:results (y :scs (,sc)
145 :load-if (not (location= x y))))
148 (unless (location= y x)
150 (define-move-vop ,vop :move (,sc) (,sc)))))
151 (frob single-move single-reg)
152 (frob double-move double-reg))
154 ;;; complex float register to register moves
155 (define-vop (complex-float-move)
156 (:args (x :target y :load-if (not (location= x y))))
157 (:results (y :load-if (not (location= x y))))
158 (:note "complex float move")
160 (unless (location= x y)
161 ;; Note the complex-float-regs are aligned to every second
162 ;; float register so there is not need to worry about overlap.
163 ;; (It would be better to put the imagpart in the top half of the
164 ;; register, or something, but let's worry about that later)
165 (let ((x-real (complex-single-reg-real-tn x))
166 (y-real (complex-single-reg-real-tn y)))
167 (inst movq y-real x-real))
168 (let ((x-imag (complex-single-reg-imag-tn x))
169 (y-imag (complex-single-reg-imag-tn y)))
170 (inst movq y-imag x-imag)))))
172 (define-vop (complex-single-move complex-float-move)
173 (:args (x :scs (complex-single-reg) :target y
174 :load-if (not (location= x y))))
175 (:results (y :scs (complex-single-reg) :load-if (not (location= x y)))))
176 (define-move-vop complex-single-move :move
177 (complex-single-reg) (complex-single-reg))
179 (define-vop (complex-double-move complex-float-move)
180 (:args (x :scs (complex-double-reg)
181 :target y :load-if (not (location= x y))))
182 (:results (y :scs (complex-double-reg) :load-if (not (location= x y)))))
183 (define-move-vop complex-double-move :move
184 (complex-double-reg) (complex-double-reg))
187 ;;; Move from float to a descriptor reg. allocating a new float
188 ;;; object in the process.
189 (define-vop (move-from-single)
190 (:args (x :scs (single-reg) :to :save))
191 (:results (y :scs (descriptor-reg)))
192 (:note "float to pointer coercion")
196 (inst or y single-float-widetag)))
198 (define-move-vop move-from-single :move
199 (single-reg) (descriptor-reg))
201 (define-vop (move-from-double)
202 (:args (x :scs (double-reg) :to :save))
203 (:results (y :scs (descriptor-reg)))
205 (:note "float to pointer coercion")
207 (with-fixed-allocation (y
211 (inst movsd (ea-for-df-desc y) x))))
212 (define-move-vop move-from-double :move
213 (double-reg) (descriptor-reg))
215 ;;; Move from a descriptor to a float register.
216 (define-vop (move-to-single)
217 (:args (x :scs (descriptor-reg) :target tmp))
218 (:temporary (:sc unsigned-reg) tmp)
219 (:results (y :scs (single-reg)))
220 (:note "pointer to float coercion")
226 (define-move-vop move-to-single :move (descriptor-reg) (single-reg))
228 (define-vop (move-to-double)
229 (:args (x :scs (descriptor-reg)))
230 (:results (y :scs (double-reg)))
231 (:note "pointer to float coercion")
233 (inst movsd y (ea-for-df-desc x))))
234 (define-move-vop move-to-double :move (descriptor-reg) (double-reg))
237 ;;; Move from complex float to a descriptor reg. allocating a new
238 ;;; complex float object in the process.
239 (define-vop (move-from-complex-single)
240 (:args (x :scs (complex-single-reg) :to :save))
241 (:results (y :scs (descriptor-reg)))
243 (:note "complex float to pointer coercion")
245 (with-fixed-allocation (y
246 complex-single-float-widetag
247 complex-single-float-size
249 (let ((real-tn (complex-single-reg-real-tn x)))
250 (inst movss (ea-for-csf-real-desc y) real-tn))
251 (let ((imag-tn (complex-single-reg-imag-tn x)))
252 (inst movss (ea-for-csf-imag-desc y) imag-tn)))))
253 (define-move-vop move-from-complex-single :move
254 (complex-single-reg) (descriptor-reg))
256 (define-vop (move-from-complex-double)
257 (:args (x :scs (complex-double-reg) :to :save))
258 (:results (y :scs (descriptor-reg)))
260 (:note "complex float to pointer coercion")
262 (with-fixed-allocation (y
263 complex-double-float-widetag
264 complex-double-float-size
266 (let ((real-tn (complex-double-reg-real-tn x)))
267 (inst movsd (ea-for-cdf-real-desc y) real-tn))
268 (let ((imag-tn (complex-double-reg-imag-tn x)))
269 (inst movsd (ea-for-cdf-imag-desc y) imag-tn)))))
270 (define-move-vop move-from-complex-double :move
271 (complex-double-reg) (descriptor-reg))
273 ;;; Move from a descriptor to a complex float register.
274 (macrolet ((frob (name sc format)
277 (:args (x :scs (descriptor-reg)))
278 (:results (y :scs (,sc)))
279 (:note "pointer to complex float coercion")
281 (let ((real-tn (complex-double-reg-real-tn y)))
285 '((inst movss real-tn (ea-for-csf-real-desc x))))
287 '((inst movsd real-tn (ea-for-cdf-real-desc x))))))
288 (let ((imag-tn (complex-double-reg-imag-tn y)))
292 '((inst movss imag-tn (ea-for-csf-imag-desc x))))
294 '((inst movsd imag-tn (ea-for-cdf-imag-desc x))))))))
295 (define-move-vop ,name :move (descriptor-reg) (,sc)))))
296 (frob move-to-complex-single complex-single-reg :single)
297 (frob move-to-complex-double complex-double-reg :double))
299 ;;;; the move argument vops
301 ;;;; Note these are also used to stuff fp numbers onto the c-call
302 ;;;; stack so the order is different than the lisp-stack.
304 ;;; the general MOVE-ARG VOP
305 (macrolet ((frob (name sc stack-sc format)
308 (:args (x :scs (,sc) :target y)
310 :load-if (not (sc-is y ,sc))))
312 (:note "float argument move")
313 (:generator ,(case format (:single 2) (:double 3) )
316 (unless (location= x y)
319 (if (= (tn-offset fp) esp-offset)
320 (let* ((offset (* (tn-offset y) n-word-bytes))
321 (ea (make-ea :dword :base fp :disp offset)))
323 (:single '((inst movss ea x)))
324 (:double '((inst movsd ea x)))))
327 :disp (- (* (+ (tn-offset y)
334 (:single '((inst movss ea x)))
335 (:double '((inst movsd ea x)))))))))))
336 (define-move-vop ,name :move-arg
337 (,sc descriptor-reg) (,sc)))))
338 (frob move-single-float-arg single-reg single-stack :single)
339 (frob move-double-float-arg double-reg double-stack :double))
341 ;;;; complex float MOVE-ARG VOP
342 (macrolet ((frob (name sc stack-sc format)
345 (:args (x :scs (,sc) :target y)
347 :load-if (not (sc-is y ,sc))))
349 (:note "complex float argument move")
350 (:generator ,(ecase format (:single 2) (:double 3))
353 (unless (location= x y)
354 (let ((x-real (complex-double-reg-real-tn x))
355 (y-real (complex-double-reg-real-tn y)))
356 (inst movsd y-real x-real))
357 (let ((x-imag (complex-double-reg-imag-tn x))
358 (y-imag (complex-double-reg-imag-tn y)))
359 (inst movsd y-imag x-imag))))
361 (let ((real-tn (complex-double-reg-real-tn x)))
365 (ea-for-csf-real-stack y fp)
369 (ea-for-cdf-real-stack y fp)
371 (let ((imag-tn (complex-double-reg-imag-tn x)))
375 (ea-for-csf-imag-stack y fp) imag-tn)))
378 (ea-for-cdf-imag-stack y fp) imag-tn)))))))))
379 (define-move-vop ,name :move-arg
380 (,sc descriptor-reg) (,sc)))))
381 (frob move-complex-single-float-arg
382 complex-single-reg complex-single-stack :single)
383 (frob move-complex-double-float-arg
384 complex-double-reg complex-double-stack :double))
386 (define-move-vop move-arg :move-arg
387 (single-reg double-reg
388 complex-single-reg complex-double-reg)
394 (define-vop (float-op)
398 (:note "inline float arithmetic")
400 (:save-p :compute-only))
402 (macrolet ((frob (name sc ptype)
403 `(define-vop (,name float-op)
404 (:args (x :scs (,sc) :target r)
406 (:results (r :scs (,sc)))
407 (:arg-types ,ptype ,ptype)
408 (:result-types ,ptype))))
409 (frob single-float-op single-reg single-float)
410 (frob double-float-op double-reg double-float))
412 (macrolet ((generate (movinst opinst commutative)
417 ((and ,commutative (location= y r))
419 ((not (location= r y))
423 (inst ,movinst tmp x)
425 (inst ,movinst r tmp)))))
426 (frob (op sinst sname scost dinst dname dcost commutative)
428 (define-vop (,sname single-float-op)
430 (:temporary (:sc single-reg) tmp)
432 (generate movss ,sinst ,commutative)))
433 (define-vop (,dname double-float-op)
435 (:temporary (:sc single-reg) tmp)
437 (generate movsd ,dinst ,commutative))))))
438 (frob + addss +/single-float 2 addsd +/double-float 2 t)
439 (frob - subss -/single-float 2 subsd -/double-float 2 nil)
440 (frob * mulss */single-float 4 mulsd */double-float 5 t)
441 (frob / divss //single-float 12 divsd //double-float 19 nil))
445 (macrolet ((frob ((name translate sc type) &body body)
447 (:args (x :scs (,sc)))
448 (:results (y :scs (,sc)))
449 (:translate ,translate)
452 (:result-types ,type)
453 (:temporary (:sc any-reg) hex8)
456 (:note "inline float arithmetic")
458 (:save-p :compute-only)
460 (note-this-location vop :internal-error)
461 ;; we should be able to do this better. what we
462 ;; really would like to do is use the target as the
463 ;; temp whenever it's not also the source
464 (unless (location= x y)
467 (frob (%negate/double-float %negate double-reg double-float)
468 (inst lea hex8 (make-ea :qword :disp 1))
469 (inst ror hex8 1) ; #x8000000000000000
472 (frob (%negate/single-float %negate single-reg single-float)
473 (inst lea hex8 (make-ea :qword :disp 1))
477 (frob (abs/double-float abs double-reg double-float)
482 (frob (abs/single-float abs single-reg single-float)
490 (define-vop (float-compare)
495 (:save-p :compute-only)
496 (:note "inline float comparison"))
498 ;;; comiss and comisd can cope with one or other arg in memory: we
499 ;;; could (should, indeed) extend these to cope with descriptor args
502 (define-vop (single-float-compare float-compare)
503 (:args (x :scs (single-reg)) (y :scs (single-reg)))
505 (:arg-types single-float single-float))
506 (define-vop (double-float-compare float-compare)
507 (:args (x :scs (double-reg)) (y :scs (double-reg)))
509 (:arg-types double-float double-float))
511 (define-vop (=/single-float single-float-compare)
516 (note-this-location vop :internal-error)
518 ;; if PF&CF, there was a NaN involved => not equal
519 ;; otherwise, ZF => equal
522 (inst jmp :ne target))
524 (let ((not-lab (gen-label)))
525 (inst jmp :p not-lab)
527 (emit-label not-lab))))))
529 (define-vop (=/double-float double-float-compare)
534 (note-this-location vop :internal-error)
538 (inst jmp :ne target))
540 (let ((not-lab (gen-label)))
541 (inst jmp :p not-lab)
543 (emit-label not-lab))))))
545 ;; XXX all of these probably have bad NaN behaviour
546 (define-vop (<double-float double-float-compare)
551 (inst jmp (if not-p :nc :c) target)))
553 (define-vop (<single-float single-float-compare)
558 (inst jmp (if not-p :nc :c) target)))
560 (define-vop (>double-float double-float-compare)
565 (inst jmp (if not-p :na :a) target)))
567 (define-vop (>single-float single-float-compare)
572 (inst jmp (if not-p :na :a) target)))
578 (macrolet ((frob (name translate inst to-sc to-type)
580 (:args (x :scs (signed-stack signed-reg) :target temp))
581 (:temporary (:sc signed-stack) temp)
582 (:results (y :scs (,to-sc)))
583 (:arg-types signed-num)
584 (:result-types ,to-type)
586 (:note "inline float coercion")
587 (:translate ,translate)
589 (:save-p :compute-only)
594 (note-this-location vop :internal-error)
597 (note-this-location vop :internal-error)
598 (inst ,inst y x)))))))
599 (frob %single-float/signed %single-float cvtsi2ss single-reg single-float)
600 (frob %double-float/signed %double-float cvtsi2sd double-reg double-float))
602 (macrolet ((frob (name translate inst from-sc from-type to-sc to-type)
604 (:args (x :scs (,from-sc) :target y))
605 (:results (y :scs (,to-sc)))
606 (:arg-types ,from-type)
607 (:result-types ,to-type)
609 (:note "inline float coercion")
610 (:translate ,translate)
612 (:save-p :compute-only)
614 (note-this-location vop :internal-error)
616 (frob %single-float/double-float %single-float cvtsd2ss double-reg
617 double-float single-reg single-float)
619 (frob %double-float/single-float %double-float cvtss2sd
620 single-reg single-float double-reg double-float))
622 (macrolet ((frob (trans inst from-sc from-type round-p)
623 (declare (ignore round-p))
624 `(define-vop (,(symbolicate trans "/" from-type))
625 (:args (x :scs (,from-sc)))
626 (:temporary (:sc any-reg) temp-reg)
627 (:results (y :scs (signed-reg)))
628 (:arg-types ,from-type)
629 (:result-types signed-num)
632 (:note "inline float truncate")
634 (:save-p :compute-only)
638 (inst ,inst temp-reg x)
643 (frob %unary-truncate cvttss2si single-reg single-float nil)
644 (frob %unary-truncate cvttsd2si double-reg double-float nil)
646 (frob %unary-round cvtss2si single-reg single-float t)
647 (frob %unary-round cvtsd2si double-reg double-float t))
649 (define-vop (make-single-float)
650 (:args (bits :scs (signed-reg) :target res
651 :load-if (not (or (and (sc-is bits signed-stack)
652 (sc-is res single-reg))
653 (and (sc-is bits signed-stack)
654 (sc-is res single-stack)
655 (location= bits res))))))
656 (:results (res :scs (single-reg single-stack)))
657 (:arg-types signed-num)
658 (:result-types single-float)
659 (:translate make-single-float)
669 (aver (location= bits res)))))
673 (inst movd res bits))
675 (inst movd res bits)))))))
677 (define-vop (make-double-float)
678 (:args (hi-bits :scs (signed-reg))
679 (lo-bits :scs (unsigned-reg)))
680 (:results (res :scs (double-reg)))
681 (:temporary (:sc unsigned-reg) temp)
682 (:arg-types signed-num unsigned-num)
683 (:result-types double-float)
684 (:translate make-double-float)
690 (inst or temp lo-bits)
691 (inst movd res temp)))
693 (define-vop (single-float-bits)
694 (:args (float :scs (single-reg descriptor-reg)
695 :load-if (not (sc-is float single-stack))))
696 (:results (bits :scs (signed-reg)))
697 (:temporary (:sc signed-stack :from :argument :to :result) stack-temp)
698 (:arg-types single-float)
699 (:result-types signed-num)
700 (:translate single-float-bits)
708 (inst movss stack-temp float)
709 (move bits stack-temp))
714 (inst shr bits 32))))
718 (inst movss bits float)))))
723 (define-vop (double-float-high-bits)
724 (:args (float :scs (double-reg descriptor-reg)
725 :load-if (not (sc-is float double-stack))))
726 (:results (hi-bits :scs (signed-reg)))
727 (:temporary (:sc signed-stack :from :argument :to :result) temp)
728 (:arg-types double-float)
729 (:result-types signed-num)
730 (:translate double-float-high-bits)
736 (inst movsd temp float)
739 (loadw hi-bits ebp-tn (- (1+ (tn-offset float)))))
741 (loadw hi-bits float double-float-value-slot
742 other-pointer-lowtag)))
743 (inst sar hi-bits 32)))
745 (define-vop (double-float-low-bits)
746 (:args (float :scs (double-reg descriptor-reg)
747 :load-if (not (sc-is float double-stack))))
748 (:results (lo-bits :scs (unsigned-reg)))
749 (:temporary (:sc signed-stack :from :argument :to :result) temp)
750 (:arg-types double-float)
751 (:result-types unsigned-num)
752 (:translate double-float-low-bits)
758 (inst movsd temp float)
761 (loadw lo-bits ebp-tn (- (1+ (tn-offset float)))))
763 (loadw lo-bits float double-float-value-slot
764 other-pointer-lowtag)))
765 (inst shl lo-bits 32)
766 (inst shr lo-bits 32)))
769 ;;;; float mode hackery
771 (sb!xc:deftype float-modes () '(unsigned-byte 64)) ; really only 16
772 (defknown floating-point-modes () float-modes (flushable))
773 (defknown ((setf floating-point-modes)) (float-modes)
776 (define-vop (floating-point-modes)
777 (:results (res :scs (unsigned-reg)))
778 (:result-types unsigned-num)
779 (:translate floating-point-modes)
781 (:temporary (:sc unsigned-stack :from :argument :to :result) temp)
785 ;; Extract status from bytes 0-5 to bytes 16-21
786 (inst and temp (1- (expt 2 6)))
788 ;; Extract mask from bytes 7-12 to bytes 0-5
790 (inst and res (1- (expt 2 6)))
791 ;; Flip the bits to convert from "1 means exception masked" to
792 ;; "1 means exception enabled".
793 (inst xor res (1- (expt 2 6)))
796 (define-vop (set-floating-point-modes)
797 (:args (new :scs (unsigned-reg) :to :result :target res))
798 (:results (res :scs (unsigned-reg)))
799 (:arg-types unsigned-num)
800 (:result-types unsigned-num)
801 (:translate (setf floating-point-modes))
803 (:temporary (:sc unsigned-reg :from :argument :to :result) temp1)
804 (:temporary (:sc unsigned-stack :from :argument :to :result) temp2)
808 ;; Clear status + masks
809 (inst and temp2 (lognot (logior (1- (expt 2 6))
810 (ash (1- (expt 2 6)) 7))))
811 ;; Replace current status
814 (inst and temp1 (1- (expt 2 6)))
815 (inst or temp2 temp1)
816 ;; Replace exception masks
818 (inst and temp1 (1- (expt 2 6)))
819 (inst xor temp1 (1- (expt 2 6)))
821 (inst or temp2 temp1)
822 (inst ldmxcsr temp2)))
825 ;;;; complex float VOPs
827 (define-vop (make-complex-single-float)
829 (:args (real :scs (single-reg) :to :result :target r
830 :load-if (not (location= real r)))
831 (imag :scs (single-reg) :to :save))
832 (:arg-types single-float single-float)
833 (:results (r :scs (complex-single-reg) :from (:argument 0)
834 :load-if (not (sc-is r complex-single-stack))))
835 (:result-types complex-single-float)
836 (:note "inline complex single-float creation")
841 (let ((r-real (complex-single-reg-real-tn r)))
842 (unless (location= real r-real)
843 (inst movss r-real real)))
844 (let ((r-imag (complex-single-reg-imag-tn r)))
845 (unless (location= imag r-imag)
846 (inst movss r-imag imag))))
847 (complex-single-stack
848 (inst movss (ea-for-csf-real-stack r) real)
849 (inst movss (ea-for-csf-imag-stack r) imag)))))
851 (define-vop (make-complex-double-float)
853 (:args (real :scs (double-reg) :target r
854 :load-if (not (location= real r)))
855 (imag :scs (double-reg) :to :save))
856 (:arg-types double-float double-float)
857 (:results (r :scs (complex-double-reg) :from (:argument 0)
858 :load-if (not (sc-is r complex-double-stack))))
859 (:result-types complex-double-float)
860 (:note "inline complex double-float creation")
865 (let ((r-real (complex-double-reg-real-tn r)))
866 (unless (location= real r-real)
867 (inst movsd r-real real)))
868 (let ((r-imag (complex-double-reg-imag-tn r)))
869 (unless (location= imag r-imag)
870 (inst movsd r-imag imag))))
871 (complex-double-stack
872 (inst movsd (ea-for-cdf-real-stack r) real)
873 (inst movsd (ea-for-cdf-imag-stack r) imag)))))
875 (define-vop (complex-float-value)
876 (:args (x :target r))
878 (:variant-vars offset)
881 (cond ((sc-is x complex-single-reg complex-double-reg)
883 (make-random-tn :kind :normal
884 :sc (sc-or-lose 'double-reg)
885 :offset (+ offset (tn-offset x)))))
886 (unless (location= value-tn r)
887 (if (sc-is x complex-single-reg)
888 (inst movss r value-tn)
889 (inst movsd r value-tn)))))
890 ((sc-is r single-reg)
892 (complex-single-stack
894 (0 (ea-for-csf-real-stack x))
895 (1 (ea-for-csf-imag-stack x))))
898 (0 (ea-for-csf-real-desc x))
899 (1 (ea-for-csf-imag-desc x)))))))
901 ((sc-is r double-reg)
903 (complex-double-stack
905 (0 (ea-for-cdf-real-stack x))
906 (1 (ea-for-cdf-imag-stack x))))
909 (0 (ea-for-cdf-real-desc x))
910 (1 (ea-for-cdf-imag-desc x)))))))
912 (t (error "COMPLEX-FLOAT-VALUE VOP failure")))))
914 (define-vop (realpart/complex-single-float complex-float-value)
915 (:translate realpart)
916 (:args (x :scs (complex-single-reg complex-single-stack descriptor-reg)
918 (:arg-types complex-single-float)
919 (:results (r :scs (single-reg)))
920 (:result-types single-float)
921 (:note "complex float realpart")
924 (define-vop (realpart/complex-double-float complex-float-value)
925 (:translate realpart)
926 (:args (x :scs (complex-double-reg complex-double-stack descriptor-reg)
928 (:arg-types complex-double-float)
929 (:results (r :scs (double-reg)))
930 (:result-types double-float)
931 (:note "complex float realpart")
934 (define-vop (imagpart/complex-single-float complex-float-value)
935 (:translate imagpart)
936 (:args (x :scs (complex-single-reg complex-single-stack descriptor-reg)
938 (:arg-types complex-single-float)
939 (:results (r :scs (single-reg)))
940 (:result-types single-float)
941 (:note "complex float imagpart")
944 (define-vop (imagpart/complex-double-float complex-float-value)
945 (:translate imagpart)
946 (:args (x :scs (complex-double-reg complex-double-stack descriptor-reg)
948 (:arg-types complex-double-float)
949 (:results (r :scs (double-reg)))
950 (:result-types double-float)
951 (:note "complex float imagpart")
955 ;;; hack dummy VOPs to bias the representation selection of their
956 ;;; arguments towards a FP register, which can help avoid consing at
957 ;;; inappropriate locations
958 (defknown double-float-reg-bias (double-float) (values))
959 (define-vop (double-float-reg-bias)
960 (:translate double-float-reg-bias)
961 (:args (x :scs (double-reg double-stack) :load-if nil))
962 (:arg-types double-float)
964 (:note "inline dummy FP register bias")
967 (defknown single-float-reg-bias (single-float) (values))
968 (define-vop (single-float-reg-bias)
969 (:translate single-float-reg-bias)
970 (:args (x :scs (single-reg single-stack) :load-if nil))
971 (:arg-types single-float)
973 (:note "inline dummy FP register bias")