Eliminate COLD-FSET. It's just fop-funcall of %DEFUN
[sbcl.git] / src / compiler / x86-64 / float.lisp
blob1e69224b1701f17015b7d0e60bab8e705219d489
1 ;;;; floating point support for x86-64
3 ;;;; This software is part of the SBCL system. See the README file for
4 ;;;; more information.
5 ;;;;
6 ;;;; This software is derived from the CMU CL system, which was
7 ;;;; written at Carnegie Mellon University and released into the
8 ;;;; public domain. The software is in the public domain and is
9 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
10 ;;;; files for more information.
12 (in-package "SB!VM")
14 (macrolet ((ea-for-xf-desc (tn slot)
15 `(make-ea
16 :qword :base ,tn
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))
21 ;; complex floats
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))
38 `(make-ea
39 :qword :base rbp-tn
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)
48 `(make-ea
49 :qword :base ,base
50 :disp (frame-byte-offset
51 (+ (tn-offset ,tn)
52 (cond ((= (tn-offset ,base) rsp-offset)
53 sp->fp-offset)
54 (t 0))
55 (ecase ,kind
56 (:single
57 (ecase ,slot
58 (:real 0)
59 (:imag -1/2)))
60 (:double
61 (ecase ,slot
62 (:real 1)
63 (:imag 0)))))))))
64 (defun ea-for-csf-data-stack (tn &optional (base rbp-tn))
65 (ea-for-cxf-stack tn :single :real base))
66 (defun ea-for-csf-real-stack (tn &optional (base rbp-tn))
67 (ea-for-cxf-stack tn :single :real base))
68 (defun ea-for-csf-imag-stack (tn &optional (base rbp-tn))
69 (ea-for-cxf-stack tn :single :imag base))
71 (defun ea-for-cdf-data-stack (tn &optional (base rbp-tn))
72 (ea-for-cxf-stack tn :double :real base))
73 (defun ea-for-cdf-real-stack (tn &optional (base rbp-tn))
74 (ea-for-cxf-stack tn :double :real base))
75 (defun ea-for-cdf-imag-stack (tn &optional (base rbp-tn))
76 (ea-for-cxf-stack tn :double :imag base)))
78 ;;;; move functions
80 ;;; X is source, Y is destination.
82 (define-move-fun (load-fp-zero 1) (vop x y)
83 ((fp-single-zero) (single-reg)
84 (fp-double-zero) (double-reg)
85 (fp-complex-single-zero) (complex-single-reg)
86 (fp-complex-double-zero) (complex-double-reg))
87 (identity x)
88 (sc-case y
89 ((single-reg complex-single-reg) (inst xorps y y))
90 ((double-reg complex-double-reg) (inst xorpd y y))))
92 (define-move-fun (load-fp-immediate 1) (vop x y)
93 ((fp-single-immediate) (single-reg)
94 (fp-double-immediate) (double-reg)
95 (fp-complex-single-immediate) (complex-single-reg)
96 (fp-complex-double-immediate) (complex-double-reg))
97 (let ((x (register-inline-constant (tn-value x))))
98 (sc-case y
99 (single-reg (inst movss y x))
100 (double-reg (inst movsd y x))
101 (complex-single-reg (inst movq y x))
102 (complex-double-reg (inst movapd y x)))))
104 (define-move-fun (load-single 2) (vop x y)
105 ((single-stack) (single-reg))
106 (inst movss y (ea-for-sf-stack x)))
108 (define-move-fun (store-single 2) (vop x y)
109 ((single-reg) (single-stack))
110 (inst movss (ea-for-sf-stack y) x))
112 (define-move-fun (load-double 2) (vop x y)
113 ((double-stack) (double-reg))
114 (inst movsd y (ea-for-df-stack x)))
116 (define-move-fun (store-double 2) (vop x y)
117 ((double-reg) (double-stack))
118 (inst movsd (ea-for-df-stack y) x))
120 (eval-when (:compile-toplevel :execute)
121 (setf *read-default-float-format* 'single-float))
123 ;;;; complex float move functions
125 ;;; X is source, Y is destination.
126 (define-move-fun (load-complex-single 2) (vop x y)
127 ((complex-single-stack) (complex-single-reg))
128 (inst movq y (ea-for-csf-data-stack x)))
130 (define-move-fun (store-complex-single 2) (vop x y)
131 ((complex-single-reg) (complex-single-stack))
132 (inst movq (ea-for-csf-data-stack y) x))
134 (define-move-fun (load-complex-double 2) (vop x y)
135 ((complex-double-stack) (complex-double-reg))
136 (inst movupd y (ea-for-cdf-data-stack x)))
138 (define-move-fun (store-complex-double 2) (vop x y)
139 ((complex-double-reg) (complex-double-stack))
140 (inst movupd (ea-for-cdf-data-stack y) x))
142 ;;;; move VOPs
144 ;;; float register to register moves
145 (macrolet ((frob (vop sc)
146 `(progn
147 (define-vop (,vop)
148 (:args (x :scs (,sc)
149 :target y
150 :load-if (not (location= x y))))
151 (:results (y :scs (,sc)
152 :load-if (not (location= x y))))
153 (:note "float move")
154 (:generator 0
155 (move y x)))
156 (define-move-vop ,vop :move (,sc) (,sc)))))
157 (frob single-move single-reg)
158 (frob double-move double-reg)
159 (frob complex-single-move complex-single-reg)
160 (frob complex-double-move complex-double-reg))
163 ;;; Move from float to a descriptor reg. allocating a new float
164 ;;; object in the process.
165 (define-vop (move-from-single)
166 (:args (x :scs (single-reg) :to :save))
167 (:results (y :scs (descriptor-reg)))
168 (:note "float to pointer coercion")
169 (:generator 4
170 (inst movd (reg-in-size y :dword) x)
171 (inst shl y 32)
172 (inst or y single-float-widetag)))
174 (define-move-vop move-from-single :move
175 (single-reg) (descriptor-reg))
177 (define-vop (move-from-double)
178 (:args (x :scs (double-reg) :to :save))
179 (:results (y :scs (descriptor-reg)))
180 (:node-var node)
181 (:note "float to pointer coercion")
182 (:generator 13
183 (with-fixed-allocation (y
184 double-float-widetag
185 double-float-size
186 node)
187 (inst movsd (ea-for-df-desc y) x))))
188 (define-move-vop move-from-double :move
189 (double-reg) (descriptor-reg))
191 ;;; Move from a descriptor to a float register.
192 (define-vop (move-to-single-reg)
193 (:args (x :scs (descriptor-reg) :target tmp
194 :load-if (not (sc-is x control-stack))))
195 (:temporary (:sc unsigned-reg :from :argument :to :result) tmp)
196 (:results (y :scs (single-reg)))
197 (:note "pointer to float coercion")
198 (:generator 2
199 (sc-case x
200 (descriptor-reg
201 (move tmp x)
202 (inst shr tmp 32)
203 (inst movd y (reg-in-size tmp :dword)))
204 (control-stack
205 ;; When the single-float descriptor is in memory, the untagging
206 ;; is done in the target XMM register. This is faster than going
207 ;; through a general-purpose register and the code is smaller.
208 (inst movq y x)
209 (inst shufps y y #4r3331)))))
210 (define-move-vop move-to-single-reg :move (descriptor-reg) (single-reg))
212 ;;; Move from a descriptor to a float stack.
213 (define-vop (move-to-single-stack)
214 (:args (x :scs (descriptor-reg) :target tmp))
215 (:temporary (:sc unsigned-reg :from :argument :to :result) tmp)
216 (:results (y :scs (single-stack)))
217 (:note "pointer to float coercion")
218 (:generator 2
219 (move tmp x)
220 (inst shr tmp 32)
221 (let ((slot (make-ea :dword :base rbp-tn
222 :disp (frame-byte-offset (tn-offset y)))))
223 (inst mov slot (reg-in-size tmp :dword)))))
224 (define-move-vop move-to-single-stack :move (descriptor-reg) (single-stack))
226 (define-vop (move-to-double)
227 (:args (x :scs (descriptor-reg)))
228 (:results (y :scs (double-reg)))
229 (:note "pointer to float coercion")
230 (:generator 2
231 (inst movsd y (ea-for-df-desc x))))
232 (define-move-vop move-to-double :move (descriptor-reg) (double-reg))
235 ;;; Move from complex float to a descriptor reg. allocating a new
236 ;;; complex float object in the process.
237 (define-vop (move-from-complex-single)
238 (:args (x :scs (complex-single-reg) :to :save))
239 (:results (y :scs (descriptor-reg)))
240 (:node-var node)
241 (:note "complex float to pointer coercion")
242 (:generator 13
243 (with-fixed-allocation (y
244 complex-single-float-widetag
245 complex-single-float-size
246 node)
247 (inst movq (ea-for-csf-data-desc y) x))))
248 (define-move-vop move-from-complex-single :move
249 (complex-single-reg) (descriptor-reg))
251 (define-vop (move-from-complex-double)
252 (:args (x :scs (complex-double-reg) :to :save))
253 (:results (y :scs (descriptor-reg)))
254 (:node-var node)
255 (:note "complex float to pointer coercion")
256 (:generator 13
257 (with-fixed-allocation (y
258 complex-double-float-widetag
259 complex-double-float-size
260 node)
261 (inst movapd (ea-for-cdf-data-desc y) x))))
262 (define-move-vop move-from-complex-double :move
263 (complex-double-reg) (descriptor-reg))
265 ;;; Move from a descriptor to a complex float register.
266 (macrolet ((frob (name sc format)
267 `(progn
268 (define-vop (,name)
269 (:args (x :scs (descriptor-reg)))
270 (:results (y :scs (,sc)))
271 (:note "pointer to complex float coercion")
272 (:generator 2
273 ,(ecase format
274 (:single
275 '(inst movq y (ea-for-csf-data-desc x)))
276 (:double
277 '(inst movapd y (ea-for-cdf-data-desc x))))))
278 (define-move-vop ,name :move (descriptor-reg) (,sc)))))
279 (frob move-to-complex-single complex-single-reg :single)
280 (frob move-to-complex-double complex-double-reg :double))
282 ;;;; the move argument vops
283 ;;;;
284 ;;;; Note these are also used to stuff fp numbers onto the c-call
285 ;;;; stack so the order is different than the lisp-stack.
287 ;;; the general MOVE-ARG VOP
288 (macrolet ((frob (name sc stack-sc format)
289 `(progn
290 (define-vop (,name)
291 (:args (x :scs (,sc) :target y)
292 (fp :scs (any-reg)
293 :load-if (not (sc-is y ,sc))))
294 (:results (y))
295 (:note "float argument move")
296 (:generator ,(case format (:single 2) (:double 3) )
297 (sc-case y
298 (,sc
299 (move y x))
300 (,stack-sc
301 (if (= (tn-offset fp) esp-offset)
302 (let* ((offset (* (tn-offset y) n-word-bytes))
303 (ea (make-ea :dword :base fp :disp offset)))
304 ,@(ecase format
305 (:single '((inst movss ea x)))
306 (:double '((inst movsd ea x)))))
307 (let ((ea (make-ea
308 :dword :base fp
309 :disp (frame-byte-offset (tn-offset y)))))
310 ,@(ecase format
311 (:single '((inst movss ea x)))
312 (:double '((inst movsd ea x))))))))))
313 (define-move-vop ,name :move-arg
314 (,sc descriptor-reg) (,sc)))))
315 (frob move-single-float-arg single-reg single-stack :single)
316 (frob move-double-float-arg double-reg double-stack :double))
318 ;;;; complex float MOVE-ARG VOP
319 (macrolet ((frob (name sc stack-sc format)
320 `(progn
321 (define-vop (,name)
322 (:args (x :scs (,sc) :target y)
323 (fp :scs (any-reg)
324 :load-if (not (sc-is y ,sc))))
325 (:results (y))
326 (:note "complex float argument move")
327 (:generator ,(ecase format (:single 2) (:double 3))
328 (sc-case y
329 (,sc
330 (move y x))
331 (,stack-sc
332 ,(ecase format
333 (:single
334 '(inst movq (ea-for-csf-data-stack y fp) x))
335 (:double
336 '(inst movupd (ea-for-cdf-data-stack y fp) x)))))))
337 (define-move-vop ,name :move-arg
338 (,sc descriptor-reg) (,sc)))))
339 (frob move-complex-single-float-arg
340 complex-single-reg complex-single-stack :single)
341 (frob move-complex-double-float-arg
342 complex-double-reg complex-double-stack :double))
344 (define-move-vop move-arg :move-arg
345 (single-reg double-reg
346 complex-single-reg complex-double-reg)
347 (descriptor-reg))
350 ;;;; arithmetic VOPs
352 (define-vop (float-op)
353 (:args (x) (y))
354 (:results (r))
355 (:policy :fast-safe)
356 (:note "inline float arithmetic")
357 (:vop-var vop)
358 (:save-p :compute-only))
360 (macrolet ((frob (name comm-name sc constant-sc ptype)
361 `(progn
362 (define-vop (,name float-op)
363 (:args (x :scs (,sc ,constant-sc)
364 :target r
365 :load-if (not (sc-is x ,constant-sc)))
366 (y :scs (,sc ,constant-sc)
367 :load-if (not (sc-is y ,constant-sc))))
368 (:results (r :scs (,sc)))
369 (:arg-types ,ptype ,ptype)
370 (:result-types ,ptype))
371 (define-vop (,comm-name float-op)
372 (:args (x :scs (,sc ,constant-sc)
373 :target r
374 :load-if (not (sc-is x ,constant-sc)))
375 (y :scs (,sc ,constant-sc)
376 :target r
377 :load-if (not (sc-is y ,constant-sc))))
378 (:results (r :scs (,sc)))
379 (:arg-types ,ptype ,ptype)
380 (:result-types ,ptype)))))
381 (frob single-float-op single-float-comm-op
382 single-reg fp-single-immediate single-float)
383 (frob double-float-op double-float-comm-op
384 double-reg fp-double-immediate double-float)
385 (frob complex-single-float-op complex-single-float-comm-op
386 complex-single-reg fp-complex-single-immediate
387 complex-single-float)
388 (frob complex-double-float-op complex-double-float-comm-op
389 complex-double-reg fp-complex-double-immediate
390 complex-double-float))
392 (macrolet ((generate (opinst commutative constant-sc load-inst)
393 `(flet ((get-constant (tn &optional maybe-aligned)
394 (declare (ignorable maybe-aligned))
395 (let ((value (tn-value tn)))
396 ,(if (eq constant-sc 'fp-complex-single-immediate)
397 `(if maybe-aligned
398 (register-inline-constant
399 :aligned value)
400 (register-inline-constant value))
401 `(register-inline-constant value)))))
402 (declare (ignorable #'get-constant))
403 (cond
404 ((location= x r)
405 (when (sc-is y ,constant-sc)
406 (setf y (get-constant y t)))
407 (inst ,opinst x y))
408 ((and ,commutative (location= y r))
409 (when (sc-is x ,constant-sc)
410 (setf x (get-constant x t)))
411 (inst ,opinst y x))
412 ((not (location= r y))
413 (if (sc-is x ,constant-sc)
414 (inst ,load-inst r (get-constant x))
415 (move r x))
416 (when (sc-is y ,constant-sc)
417 (setf y (get-constant y t)))
418 (inst ,opinst r y))
420 (if (sc-is x ,constant-sc)
421 (inst ,load-inst tmp (get-constant x))
422 (move tmp x))
423 (inst ,opinst tmp y)
424 (move r tmp)))))
425 (frob (op sinst sname scost dinst dname dcost commutative
426 &optional csinst csname cscost cdinst cdname cdcost)
427 `(progn
428 (define-vop (,sname ,(if commutative
429 'single-float-comm-op
430 'single-float-op))
431 (:translate ,op)
432 (:temporary (:sc single-reg) tmp)
433 (:generator ,scost
434 (generate ,sinst ,commutative fp-single-immediate movss)))
435 (define-vop (,dname ,(if commutative
436 'double-float-comm-op
437 'double-float-op))
438 (:translate ,op)
439 (:temporary (:sc double-reg) tmp)
440 (:generator ,dcost
441 (generate ,dinst ,commutative fp-double-immediate movsd)))
442 ,(when csinst
443 `(define-vop (,csname
444 ,(if commutative
445 'complex-single-float-comm-op
446 'complex-single-float-op))
447 (:translate ,op)
448 (:temporary (:sc complex-single-reg) tmp)
449 (:generator ,cscost
450 (generate ,csinst ,commutative
451 fp-complex-single-immediate movq))))
452 ,(when cdinst
453 `(define-vop (,cdname
454 ,(if commutative
455 'complex-double-float-comm-op
456 'complex-double-float-op))
457 (:translate ,op)
458 (:temporary (:sc complex-double-reg) tmp)
459 (:generator ,cdcost
460 (generate ,cdinst ,commutative
461 fp-complex-double-immediate movapd)))))))
462 (frob + addss +/single-float 2 addsd +/double-float 2 t
463 addps +/complex-single-float 3 addpd +/complex-double-float 3)
464 (frob - subss -/single-float 2 subsd -/double-float 2 nil
465 subps -/complex-single-float 3 subpd -/complex-double-float 3)
466 (frob * mulss */single-float 4 mulsd */double-float 5 t)
467 (frob / divss //single-float 12 divsd //double-float 19 nil))
469 (macrolet ((frob (op cost commutativep
470 duplicate-inst op-inst real-move-inst complex-move-inst
471 real-sc real-constant-sc real-type
472 complex-sc complex-constant-sc complex-type
473 real-complex-name complex-real-name)
474 (cond ((not duplicate-inst) ; simple case
475 `(flet ((load-into (r x)
476 (sc-case x
477 (,real-constant-sc
478 (inst ,real-move-inst r
479 (register-inline-constant (tn-value x))))
480 (,complex-constant-sc
481 (inst ,complex-move-inst r
482 (register-inline-constant (tn-value x))))
483 (t (move r x)))))
484 ,(when real-complex-name
485 `(define-vop (,real-complex-name float-op)
486 (:translate ,op)
487 (:args (x :scs (,real-sc ,real-constant-sc)
488 :target r
489 :load-if (not (sc-is x ,real-constant-sc)))
490 (y :scs (,complex-sc ,complex-constant-sc)
491 ,@(when commutativep '(:target r))
492 :load-if (not (sc-is y ,complex-constant-sc))))
493 (:arg-types ,real-type ,complex-type)
494 (:results (r :scs (,complex-sc)
495 ,@(unless commutativep '(:from (:argument 0)))))
496 (:result-types ,complex-type)
497 (:generator ,cost
498 ,(when commutativep
499 `(when (location= y r)
500 (rotatef x y)))
501 (load-into r x)
502 (when (sc-is y ,real-constant-sc ,complex-constant-sc)
503 (setf y (register-inline-constant
504 :aligned (tn-value y))))
505 (inst ,op-inst r y))))
507 ,(when complex-real-name
508 `(define-vop (,complex-real-name float-op)
509 (:translate ,op)
510 (:args (x :scs (,complex-sc ,complex-constant-sc)
511 :target r
512 :load-if (not (sc-is x ,complex-constant-sc)))
513 (y :scs (,real-sc ,real-constant-sc)
514 ,@(when commutativep '(:target r))
515 :load-if (not (sc-is y ,real-constant-sc))))
516 (:arg-types ,complex-type ,real-type)
517 (:results (r :scs (,complex-sc)
518 ,@(unless commutativep '(:from (:argument 0)))))
519 (:result-types ,complex-type)
520 (:generator ,cost
521 ,(when commutativep
522 `(when (location= y r)
523 (rotatef x y)))
524 (load-into r x)
525 (when (sc-is y ,real-constant-sc ,complex-constant-sc)
526 (setf y (register-inline-constant
527 :aligned (tn-value y))))
528 (inst ,op-inst r y))))))
529 (commutativep ; must duplicate, but commutative
530 `(progn
531 ,(when real-complex-name
532 `(define-vop (,real-complex-name float-op)
533 (:translate ,op)
534 (:args (x :scs (,real-sc ,real-constant-sc)
535 :target dup
536 :load-if (not (sc-is x ,real-constant-sc)))
537 (y :scs (,complex-sc ,complex-constant-sc)
538 :target r
539 :to :result
540 :load-if (not (sc-is y ,complex-constant-sc))))
541 (:arg-types ,real-type ,complex-type)
542 (:temporary (:sc ,complex-sc :target r
543 :from (:argument 0)
544 :to :result)
545 dup)
546 (:results (r :scs (,complex-sc)))
547 (:result-types ,complex-type)
548 (:generator ,cost
549 (if (sc-is x ,real-constant-sc)
550 (inst ,complex-move-inst dup
551 (register-inline-constant
552 (complex (tn-value x) (tn-value x))))
553 (let ((real x))
554 ,duplicate-inst))
555 ;; safe: dup /= y
556 (when (location= dup r)
557 (rotatef dup y))
558 (if (sc-is y ,complex-constant-sc)
559 (inst ,complex-move-inst r
560 (register-inline-constant (tn-value y)))
561 (move r y))
562 (when (sc-is dup ,complex-constant-sc)
563 (setf dup (register-inline-constant
564 :aligned (tn-value dup))))
565 (inst ,op-inst r dup))))
567 ,(when complex-real-name
568 `(define-vop (,complex-real-name float-op)
569 (:translate ,op)
570 (:args (x :scs (,complex-sc ,complex-constant-sc)
571 :target r
572 :to :result
573 :load-if (not (sc-is x ,complex-constant-sc)))
574 (y :scs (,real-sc ,real-constant-sc)
575 :target dup
576 :load-if (not (sc-is y ,real-constant-sc))))
577 (:arg-types ,complex-type ,real-type)
578 (:temporary (:sc ,complex-sc :target r
579 :from (:argument 1)
580 :to :result)
581 dup)
582 (:results (r :scs (,complex-sc)))
583 (:result-types ,complex-type)
584 (:generator ,cost
585 (if (sc-is y ,real-constant-sc)
586 (inst ,complex-move-inst dup
587 (register-inline-constant
588 (complex (tn-value y) (tn-value y))))
589 (let ((real y))
590 ,duplicate-inst))
591 (when (location= dup r)
592 (rotatef x dup))
593 (if (sc-is x ,complex-constant-sc)
594 (inst ,complex-move-inst r
595 (register-inline-constant (tn-value x)))
596 (move r x))
597 (when (sc-is dup ,complex-constant-sc)
598 (setf dup (register-inline-constant
599 :aligned (tn-value dup))))
600 (inst ,op-inst r dup))))))
601 (t ; duplicate, not commutative
602 `(progn
603 ,(when real-complex-name
604 `(define-vop (,real-complex-name float-op)
605 (:translate ,op)
606 (:args (x :scs (,real-sc ,real-constant-sc)
607 :target r
608 :load-if (not (sc-is x ,real-constant-sc)))
609 (y :scs (,complex-sc ,complex-constant-sc)
610 :to :result
611 :load-if (not (sc-is y ,complex-constant-sc))))
612 (:arg-types ,real-type ,complex-type)
613 (:results (r :scs (,complex-sc) :from (:argument 0)))
614 (:result-types ,complex-type)
615 (:generator ,cost
616 (if (sc-is x ,real-constant-sc)
617 (inst ,complex-move-inst dup
618 (register-inline-constant
619 (complex (tn-value x) (tn-value x))))
620 (let ((real x)
621 (dup r))
622 ,duplicate-inst))
623 (when (sc-is y ,complex-constant-sc)
624 (setf y (register-inline-constant
625 :aligned (tn-value y))))
626 (inst ,op-inst r y))))
628 ,(when complex-real-name
629 `(define-vop (,complex-real-name float-op)
630 (:translate ,op)
631 (:args (x :scs (,complex-sc)
632 :target r
633 :to :eval)
634 (y :scs (,real-sc ,real-constant-sc)
635 :target dup
636 :load-if (not (sc-is y ,complex-constant-sc))))
637 (:arg-types ,complex-type ,real-type)
638 (:temporary (:sc ,complex-sc :from (:argument 1))
639 dup)
640 (:results (r :scs (,complex-sc) :from :eval))
641 (:result-types ,complex-type)
642 (:generator ,cost
643 (if (sc-is y ,real-constant-sc)
644 (setf dup (register-inline-constant
645 :aligned (complex (tn-value y)
646 (tn-value y))))
647 (let ((real y))
648 ,duplicate-inst))
649 (move r x)
650 (inst ,op-inst r dup))))))))
651 (def-real-complex-op (op commutativep duplicatep
652 single-inst single-real-complex-name single-complex-real-name single-cost
653 double-inst double-real-complex-name double-complex-real-name double-cost)
654 `(progn
655 (frob ,op ,single-cost ,commutativep
656 ,(and duplicatep
657 `(progn
658 (move dup real)
659 (inst unpcklps dup dup)))
660 ,single-inst movss movq
661 single-reg fp-single-immediate single-float
662 complex-single-reg fp-complex-single-immediate complex-single-float
663 ,single-real-complex-name ,single-complex-real-name)
664 (frob ,op ,double-cost ,commutativep
665 ,(and duplicatep
666 `(progn
667 (move dup real)
668 (inst unpcklpd dup dup)))
669 ,double-inst movsd movapd
670 double-reg fp-double-immediate double-float
671 complex-double-reg fp-complex-double-immediate complex-double-float
672 ,double-real-complex-name ,double-complex-real-name))))
673 (def-real-complex-op + t nil
674 addps +/real-complex-single-float +/complex-real-single-float 3
675 addpd +/real-complex-double-float +/complex-real-double-float 4)
676 (def-real-complex-op - nil nil
677 subps -/real-complex-single-float -/complex-real-single-float 3
678 subpd -/real-complex-double-float -/complex-real-double-float 4)
679 (def-real-complex-op * t t
680 mulps */real-complex-single-float */complex-real-single-float 4
681 mulpd */real-complex-double-float */complex-real-double-float 5)
682 (def-real-complex-op / nil t
683 nil nil nil nil
684 divpd nil //complex-real-double-float 19))
686 (define-vop (//complex-real-single-float float-op)
687 (:translate /)
688 (:args (x :scs (complex-single-reg fp-complex-single-immediate fp-complex-single-zero)
689 :to (:result 0)
690 :target r
691 :load-if (not (sc-is x fp-complex-single-immediate fp-complex-single-zero)))
692 (y :scs (single-reg fp-single-immediate fp-single-zero)
693 :target dup
694 :load-if (not (sc-is y fp-single-immediate fp-single-zero))))
695 (:arg-types complex-single-float single-float)
696 (:temporary (:sc complex-single-reg :from (:argument 1)) dup)
697 (:results (r :scs (complex-single-reg)))
698 (:result-types complex-single-float)
699 (:generator 12
700 (flet ((duplicate (x)
701 (let ((word (ldb (byte 64 0)
702 (logior (ash (single-float-bits (imagpart x)) 32)
703 (ldb (byte 32 0)
704 (single-float-bits (realpart x)))))))
705 (register-inline-constant :oword (logior (ash word 64) word)))))
706 (sc-case y
707 (fp-single-immediate
708 (setf dup (duplicate (complex (tn-value y) (tn-value y)))))
709 (fp-single-zero
710 (inst xorps dup dup))
711 (t (move dup y)
712 (inst shufps dup dup #b00000000)))
713 (sc-case x
714 (fp-complex-single-immediate
715 (inst movaps r (duplicate (tn-value x))))
716 (fp-complex-single-zero
717 (inst xorps r r))
719 (move r x)
720 (inst unpcklpd r r)))
721 (inst divps r dup)
722 (inst movq r r))))
724 ;; Complex multiplication
725 ;; r := rx * ry - ix * iy
726 ;; i := rx * iy + ix * ry
728 ;; Transpose for SIMDness
729 ;; rx*ry rx*iy
730 ;; -ix*iy +ix*ry
732 ;; [rx rx] * [ry iy]
733 ;;+ [ix ix] * [-iy ry]
734 ;; [r i]
736 (macrolet ((define-complex-* (name cost type sc tmp-p &body body)
737 `(define-vop (,name float-op)
738 (:translate *)
739 (:args (x :scs (,sc) :target r)
740 (y :scs (,sc) :target copy-y))
741 (:arg-types ,type ,type)
742 (:temporary (:sc ,sc) imag)
743 (:temporary (:sc ,sc :from :eval) copy-y)
744 ,@(when tmp-p
745 `((:temporary (:sc ,sc) xmm)))
746 (:results (r :scs (,sc) :from :eval))
747 (:result-types ,type)
748 (:generator ,cost
749 (when (or (location= x copy-y)
750 (location= y r))
751 (rotatef x y))
752 ,@body))))
753 (define-complex-* */complex-single-float 20
754 complex-single-float complex-single-reg t
755 (inst xorps xmm xmm)
756 (move r x)
757 (inst unpcklps r r)
758 (move imag r)
759 (inst unpckhpd imag xmm)
760 (inst unpcklpd r xmm)
761 (move copy-y y) ; y == r only if y == x == r
762 (setf y copy-y)
764 (inst mulps r y)
766 (inst shufps y y #b11110001)
767 (inst xorps y (register-inline-constant :oword (ash 1 31)))
769 (inst mulps imag y)
770 (inst addps r imag))
771 (define-complex-* */complex-double-float 25
772 complex-double-float complex-double-reg nil
773 (move imag x)
774 (move r x)
775 (move copy-y y)
776 (setf y copy-y)
777 (inst unpcklpd r r)
778 (inst unpckhpd imag imag)
780 (inst mulpd r y)
782 (inst shufpd y y #b01)
783 (inst xorpd y (register-inline-constant :oword (ash 1 63)))
785 (inst mulpd imag y)
786 (inst addpd r imag)))
788 (define-vop (fsqrt)
789 (:args (x :scs (double-reg)))
790 (:results (y :scs (double-reg)))
791 (:translate %sqrt)
792 (:policy :fast-safe)
793 (:arg-types double-float)
794 (:result-types double-float)
795 (:note "inline float arithmetic")
796 (:vop-var vop)
797 (:save-p :compute-only)
798 (:generator 1
799 (unless (location= x y)
800 (inst xorpd y y))
801 (note-this-location vop :internal-error)
802 (inst sqrtsd y x)))
804 (macrolet ((frob ((name translate sc type) &body body)
805 `(define-vop (,name)
806 (:args (x :scs (,sc) :target y))
807 (:results (y :scs (,sc)))
808 (:translate ,translate)
809 (:policy :fast-safe)
810 (:arg-types ,type)
811 (:result-types ,type)
812 (:note "inline float arithmetic")
813 (:vop-var vop)
814 (:save-p :compute-only)
815 (:generator 1
816 (note-this-location vop :internal-error)
817 (move y x)
818 ,@body))))
819 (frob (%negate/double-float %negate double-reg double-float)
820 (inst xorpd y (register-inline-constant :oword (ash 1 63))))
821 (frob (%negate/complex-double-float %negate complex-double-reg complex-double-float)
822 (inst xorpd y (register-inline-constant
823 :oword (logior (ash 1 127) (ash 1 63)))))
824 (frob (conjugate/complex-double-float conjugate complex-double-reg complex-double-float)
825 (inst xorpd y (register-inline-constant :oword (ash 1 127))))
826 (frob (%negate/single-float %negate single-reg single-float)
827 (inst xorps y (register-inline-constant :oword (ash 1 31))))
828 (frob (%negate/complex-single-float %negate complex-single-reg complex-single-float)
829 (inst xorps y (register-inline-constant
830 :oword (logior (ash 1 31) (ash 1 63)))))
831 (frob (conjugate/complex-single-float conjugate complex-single-reg complex-single-float)
832 (inst xorpd y (register-inline-constant :oword (ash 1 63))))
833 (frob (abs/double-float abs double-reg double-float)
834 (inst andpd y (register-inline-constant :oword (ldb (byte 63 0) -1))))
835 (frob (abs/single-float abs single-reg single-float)
836 (inst andps y (register-inline-constant :oword (ldb (byte 31 0) -1)))))
839 ;;;; comparison
841 (define-vop (float-compare)
842 (:policy :fast-safe)
843 (:vop-var vop)
844 (:save-p :compute-only)
845 (:note "inline float comparison"))
847 ;;; EQL
848 (macrolet ((define-float-eql (name cost sc constant-sc type)
849 `(define-vop (,name float-compare)
850 (:translate eql)
851 (:args (x :scs (,sc ,constant-sc)
852 :target mask
853 :load-if (not (sc-is x ,constant-sc)))
854 (y :scs (,sc ,constant-sc)
855 :target mask
856 :load-if (not (sc-is y ,constant-sc))))
857 (:arg-types ,type ,type)
858 (:temporary (:sc ,sc :from :eval) mask)
859 (:temporary (:sc dword-reg) bits)
860 (:conditional :e)
861 (:generator ,cost
862 (when (or (location= y mask)
863 (not (xmm-register-p x)))
864 (rotatef x y))
865 (aver (xmm-register-p x))
866 (move mask x)
867 (when (sc-is y ,constant-sc)
868 (setf y (register-inline-constant :aligned (tn-value y))))
869 (inst pcmpeqd mask y)
870 (inst movmskps bits mask)
871 (inst cmp (if (location= bits eax-tn) al-tn bits)
872 #b1111)))))
873 (define-float-eql eql/single-float 4
874 single-reg fp-single-immediate single-float)
875 (define-float-eql eql/double-float 4
876 double-reg fp-double-immediate double-float)
877 (define-float-eql eql/complex-single-float 5
878 complex-single-reg fp-complex-single-immediate complex-single-float)
879 (define-float-eql eql/complex-double-float 5
880 complex-double-reg fp-complex-double-immediate complex-double-float))
882 ;;; comiss and comisd can cope with one or other arg in memory: we
883 ;;; could (should, indeed) extend these to cope with descriptor args
884 ;;; and stack args
886 (define-vop (single-float-compare float-compare)
887 (:args (x :scs (single-reg))
888 (y :scs (single-reg single-stack fp-single-immediate)
889 :load-if (not (sc-is y single-stack fp-single-immediate))))
890 (:arg-types single-float single-float))
891 (define-vop (double-float-compare float-compare)
892 (:args (x :scs (double-reg))
893 (y :scs (double-reg double-stack descriptor-reg fp-double-immediate)
894 :load-if (not (sc-is y double-stack descriptor-reg fp-double-immediate))))
895 (:arg-types double-float double-float))
897 (define-vop (=/single-float single-float-compare)
898 (:translate =)
899 (:args (x :scs (single-reg single-stack fp-single-immediate)
900 :target xmm
901 :load-if (not (sc-is x single-stack fp-single-immediate)))
902 (y :scs (single-reg single-stack fp-single-immediate)
903 :target xmm
904 :load-if (not (sc-is y single-stack fp-single-immediate))))
905 (:temporary (:sc single-reg :from :eval) xmm)
906 (:info)
907 (:conditional not :p :ne)
908 (:vop-var vop)
909 (:generator 3
910 (when (or (location= y xmm)
911 (and (not (xmm-register-p x))
912 (xmm-register-p y)))
913 (rotatef x y))
914 (sc-case x
915 (single-reg (setf xmm x))
916 (single-stack (inst movss xmm (ea-for-sf-stack x)))
917 (fp-single-immediate
918 (inst movss xmm (register-inline-constant (tn-value x)))))
919 (sc-case y
920 (single-stack
921 (setf y (ea-for-sf-stack y)))
922 (fp-single-immediate
923 (setf y (register-inline-constant (tn-value y))))
924 (t))
925 (note-this-location vop :internal-error)
926 (inst comiss xmm y)
927 ;; if PF&CF, there was a NaN involved => not equal
928 ;; otherwise, ZF => equal
931 (define-vop (=/double-float double-float-compare)
932 (:translate =)
933 (:args (x :scs (double-reg double-stack fp-double-immediate descriptor-reg)
934 :target xmm
935 :load-if (not (sc-is x double-stack fp-double-immediate descriptor-reg)))
936 (y :scs (double-reg double-stack fp-double-immediate descriptor-reg)
937 :target xmm
938 :load-if (not (sc-is y double-stack fp-double-immediate descriptor-reg))))
939 (:temporary (:sc double-reg :from :eval) xmm)
940 (:info)
941 (:conditional not :p :ne)
942 (:vop-var vop)
943 (:generator 3
944 (when (or (location= y xmm)
945 (and (not (xmm-register-p x))
946 (xmm-register-p y)))
947 (rotatef x y))
948 (sc-case x
949 (double-reg
950 (setf xmm x))
951 (double-stack
952 (inst movsd xmm (ea-for-df-stack x)))
953 (fp-double-immediate
954 (inst movsd xmm (register-inline-constant (tn-value x))))
955 (descriptor-reg
956 (inst movsd xmm (ea-for-df-desc x))))
957 (sc-case y
958 (double-stack
959 (setf y (ea-for-df-stack y)))
960 (fp-double-immediate
961 (setf y (register-inline-constant (tn-value y))))
962 (descriptor-reg
963 (setf y (ea-for-df-desc y)))
964 (t))
965 (note-this-location vop :internal-error)
966 (inst comisd xmm y)))
968 (macrolet ((define-complex-float-= (complex-complex-name complex-real-name real-complex-name
969 real-sc real-constant-sc real-type
970 complex-sc complex-constant-sc complex-type
971 real-move-inst complex-move-inst
972 cmp-inst mask-inst mask)
973 `(progn
974 (define-vop (,complex-complex-name float-compare)
975 (:translate =)
976 (:args (x :scs (,complex-sc ,complex-constant-sc)
977 :target cmp
978 :load-if (not (sc-is x ,complex-constant-sc)))
979 (y :scs (,complex-sc ,complex-constant-sc)
980 :target cmp
981 :load-if (not (sc-is y ,complex-constant-sc))))
982 (:arg-types ,complex-type ,complex-type)
983 (:temporary (:sc ,complex-sc :from :eval) cmp)
984 (:temporary (:sc dword-reg) bits)
985 (:info)
986 (:conditional :e)
987 (:generator 3
988 (when (location= y cmp)
989 (rotatef x y))
990 (sc-case x
991 (,real-constant-sc
992 (inst ,real-move-inst cmp (register-inline-constant
993 (tn-value x))))
994 (,complex-constant-sc
995 (inst ,complex-move-inst cmp (register-inline-constant
996 (tn-value x))))
998 (move cmp x)))
999 (when (sc-is y ,real-constant-sc ,complex-constant-sc)
1000 (setf y (register-inline-constant :aligned (tn-value y))))
1001 (note-this-location vop :internal-error)
1002 (inst ,cmp-inst :eq cmp y)
1003 (inst ,mask-inst bits cmp)
1004 (inst cmp (if (location= bits eax-tn) al-tn bits)
1005 ,mask)))
1006 (define-vop (,complex-real-name ,complex-complex-name)
1007 (:args (x :scs (,complex-sc ,complex-constant-sc)
1008 :target cmp
1009 :load-if (not (sc-is x ,complex-constant-sc)))
1010 (y :scs (,real-sc ,real-constant-sc)
1011 :target cmp
1012 :load-if (not (sc-is y ,real-constant-sc))))
1013 (:arg-types ,complex-type ,real-type))
1014 (define-vop (,real-complex-name ,complex-complex-name)
1015 (:args (x :scs (,real-sc ,real-constant-sc)
1016 :target cmp
1017 :load-if (not (sc-is x ,real-constant-sc)))
1018 (y :scs (,complex-sc ,complex-constant-sc)
1019 :target cmp
1020 :load-if (not (sc-is y ,complex-constant-sc))))
1021 (:arg-types ,real-type ,complex-type)))))
1022 (define-complex-float-= =/complex-single-float =/complex-real-single-float =/real-complex-single-float
1023 single-reg fp-single-immediate single-float
1024 complex-single-reg fp-complex-single-immediate complex-single-float
1025 movss movq cmpps movmskps #b1111)
1026 (define-complex-float-= =/complex-double-float =/complex-real-double-float =/real-complex-double-float
1027 double-reg fp-double-immediate double-float
1028 complex-double-reg fp-complex-double-immediate complex-double-float
1029 movsd movapd cmppd movmskpd #b11))
1031 (macrolet ((define-</> (op single-name double-name &rest flags)
1032 `(progn
1033 (define-vop (,double-name double-float-compare)
1034 (:translate ,op)
1035 (:info)
1036 (:conditional ,@flags)
1037 (:generator 3
1038 (sc-case y
1039 (double-stack
1040 (setf y (ea-for-df-stack y)))
1041 (descriptor-reg
1042 (setf y (ea-for-df-desc y)))
1043 (fp-double-immediate
1044 (setf y (register-inline-constant (tn-value y))))
1045 (t))
1046 (inst comisd x y)))
1047 (define-vop (,single-name single-float-compare)
1048 (:translate ,op)
1049 (:info)
1050 (:conditional ,@flags)
1051 (:generator 3
1052 (sc-case y
1053 (single-stack
1054 (setf y (ea-for-sf-stack y)))
1055 (fp-single-immediate
1056 (setf y (register-inline-constant (tn-value y))))
1057 (t))
1058 (inst comiss x y))))))
1059 (define-</> < <single-float <double-float not :p :nc)
1060 (define-</> > >single-float >double-float not :p :na))
1063 ;;;; conversion
1065 (macrolet ((frob (name translate inst to-sc to-type)
1066 `(define-vop (,name)
1067 (:args (x :scs (signed-stack signed-reg)))
1068 (:results (y :scs (,to-sc)))
1069 (:arg-types signed-num)
1070 (:result-types ,to-type)
1071 (:policy :fast-safe)
1072 (:note "inline float coercion")
1073 (:translate ,translate)
1074 (:vop-var vop)
1075 (:save-p :compute-only)
1076 (:generator 5
1077 (sc-case y
1078 (single-reg (inst xorps y y))
1079 (double-reg (inst xorpd y y)))
1080 (note-this-location vop :internal-error)
1081 (inst ,inst y x)))))
1082 (frob %single-float/signed %single-float cvtsi2ss single-reg single-float)
1083 (frob %double-float/signed %double-float cvtsi2sd double-reg double-float))
1085 (macrolet ((frob (name translate inst from-scs from-type ea-func to-sc to-type)
1086 `(define-vop (,name)
1087 (:args (x :scs ,from-scs :target y))
1088 (:results (y :scs (,to-sc)))
1089 (:arg-types ,from-type)
1090 (:result-types ,to-type)
1091 (:policy :fast-safe)
1092 (:note "inline float coercion")
1093 (:translate ,translate)
1094 (:vop-var vop)
1095 (:save-p :compute-only)
1096 (:generator 2
1097 (unless (location= x y)
1098 (sc-case y
1099 (single-reg (inst xorps y y))
1100 (double-reg (inst xorpd y y))))
1101 (note-this-location vop :internal-error)
1102 (inst ,inst y (sc-case x
1103 (,(first from-scs) x)
1104 (,(second from-scs) (,ea-func x))))
1105 ,(when (and (eq from-type 'double-float) ; if the input is wider
1106 (eq to-type 'single-float)) ; than the output, clear
1107 `(when (location= x y) ; noise in the high part
1108 (inst shufps y y #4r3330)))))))
1109 (frob %single-float/double-float %single-float cvtsd2ss
1110 (double-reg double-stack) double-float ea-for-df-stack
1111 single-reg single-float)
1113 (frob %double-float/single-float %double-float cvtss2sd
1114 (single-reg single-stack) single-float ea-for-sf-stack
1115 double-reg double-float))
1117 (macrolet ((frob (trans inst from-scs from-type ea-func)
1118 `(define-vop (,(symbolicate trans "/" from-type))
1119 (:args (x :scs ,from-scs))
1120 (:results (y :scs (signed-reg)))
1121 (:arg-types ,from-type)
1122 (:result-types signed-num)
1123 (:translate ,trans)
1124 (:policy :fast-safe)
1125 (:note "inline float truncate")
1126 (:vop-var vop)
1127 (:save-p :compute-only)
1128 (:generator 5
1129 (inst ,inst y (sc-case x
1130 (,(first from-scs) x)
1131 (,(second from-scs) (,ea-func x))))))))
1132 (frob %unary-truncate/single-float cvttss2si
1133 (single-reg single-stack) single-float ea-for-sf-stack)
1134 (frob %unary-truncate/double-float cvttsd2si
1135 (double-reg double-stack) double-float ea-for-df-stack)
1137 (frob %unary-round cvtss2si
1138 (single-reg single-stack) single-float ea-for-sf-stack)
1139 (frob %unary-round cvtsd2si
1140 (double-reg double-stack) double-float ea-for-df-stack))
1142 (define-vop (make-single-float)
1143 (:args (bits :scs (signed-reg) :target res
1144 :load-if (not (or (and (sc-is bits signed-stack)
1145 (sc-is res single-reg))
1146 (and (sc-is bits signed-stack)
1147 (sc-is res single-stack)
1148 (location= bits res))))))
1149 (:results (res :scs (single-reg single-stack)))
1150 (:arg-types signed-num)
1151 (:result-types single-float)
1152 (:translate make-single-float)
1153 (:policy :fast-safe)
1154 (:vop-var vop)
1155 (:generator 4
1156 (sc-case res
1157 (single-stack
1158 (sc-case bits
1159 (signed-reg
1160 (inst mov res bits))
1161 (signed-stack
1162 (aver (location= bits res)))))
1163 (single-reg
1164 (sc-case bits
1165 (signed-reg
1166 (inst movd res (reg-in-size bits :dword)))
1167 (signed-stack
1168 (inst movss res
1169 (make-ea :dword :base rbp-tn
1170 :disp (frame-byte-offset (tn-offset bits))))))))))
1172 (define-vop (make-single-float-c)
1173 (:results (res :scs (single-reg single-stack descriptor-reg)))
1174 (:arg-types (:constant (signed-byte 32)))
1175 (:result-types single-float)
1176 (:info bits)
1177 (:translate make-single-float)
1178 (:policy :fast-safe)
1179 (:vop-var vop)
1180 (:generator 1
1181 (sc-case res
1182 (single-stack
1183 (inst mov res bits))
1184 (single-reg
1185 (inst movss res (register-inline-constant :dword bits)))
1186 (descriptor-reg
1187 (inst mov res (logior (ash bits 32)
1188 single-float-widetag))))))
1190 (define-vop (make-double-float)
1191 (:args (hi-bits :scs (signed-reg))
1192 (lo-bits :scs (unsigned-reg)))
1193 (:results (res :scs (double-reg)))
1194 (:temporary (:sc unsigned-reg) temp)
1195 (:arg-types signed-num unsigned-num)
1196 (:result-types double-float)
1197 (:translate make-double-float)
1198 (:policy :fast-safe)
1199 (:vop-var vop)
1200 (:generator 2
1201 (move temp hi-bits)
1202 (inst shl temp 32)
1203 (inst or temp lo-bits)
1204 (inst movd res temp)))
1206 (define-vop (make-double-float-c)
1207 (:results (res :scs (double-reg)))
1208 (:arg-types (:constant (signed-byte 32)) (:constant (unsigned-byte 32)))
1209 (:result-types double-float)
1210 (:info hi lo)
1211 (:translate make-double-float)
1212 (:policy :fast-safe)
1213 (:vop-var vop)
1214 (:generator 1
1215 (inst movsd res (register-inline-constant :qword (logior (ash hi 32) lo)))))
1217 (define-vop (single-float-bits)
1218 (:args (float :scs (single-reg descriptor-reg)
1219 :load-if (not (sc-is float single-stack))))
1220 (:results (bits :scs (signed-reg)))
1221 (:arg-types single-float)
1222 (:result-types signed-num)
1223 (:translate single-float-bits)
1224 (:policy :fast-safe)
1225 (:generator 4
1226 (sc-case float
1227 (single-reg
1228 (let ((dword-bits (reg-in-size bits :dword)))
1229 (inst movd dword-bits float)
1230 (inst movsxd bits dword-bits)))
1231 (single-stack
1232 (inst movsxd bits (make-ea :dword ; c.f. ea-for-sf-stack
1233 :base rbp-tn
1234 :disp (frame-byte-offset (tn-offset float)))))
1235 (descriptor-reg
1236 (move bits float)
1237 (inst sar bits 32)))))
1239 (define-vop (double-float-high-bits)
1240 (:args (float :scs (double-reg descriptor-reg)
1241 :load-if (not (sc-is float double-stack))))
1242 (:results (hi-bits :scs (signed-reg)))
1243 (:temporary (:sc signed-stack :from :argument :to :result) temp)
1244 (:arg-types double-float)
1245 (:result-types signed-num)
1246 (:translate double-float-high-bits)
1247 (:policy :fast-safe)
1248 (:vop-var vop)
1249 (:generator 5
1250 (sc-case float
1251 (double-reg
1252 (inst movsd temp float)
1253 (move hi-bits temp))
1254 (double-stack
1255 (loadw hi-bits ebp-tn (frame-word-offset (tn-offset float))))
1256 (descriptor-reg
1257 (loadw hi-bits float double-float-value-slot
1258 other-pointer-lowtag)))
1259 (inst sar hi-bits 32)))
1261 (define-vop (double-float-low-bits)
1262 (:args (float :scs (double-reg descriptor-reg)
1263 :load-if (not (sc-is float double-stack))))
1264 (:results (lo-bits :scs (unsigned-reg)))
1265 (:temporary (:sc signed-stack :from :argument :to :result) temp)
1266 (:arg-types double-float)
1267 (:result-types unsigned-num)
1268 (:translate double-float-low-bits)
1269 (:policy :fast-safe)
1270 (:vop-var vop)
1271 (:generator 5
1272 (let ((dword-lo-bits (reg-in-size lo-bits :dword)))
1273 (sc-case float
1274 (double-reg
1275 (inst movsd temp float)
1276 (inst mov dword-lo-bits
1277 (make-ea :dword :base rbp-tn
1278 :disp (frame-byte-offset (tn-offset temp)))))
1279 (double-stack
1280 (inst mov dword-lo-bits
1281 (make-ea :dword :base rbp-tn
1282 :disp (frame-byte-offset (tn-offset float)))))
1283 (descriptor-reg
1284 (inst mov dword-lo-bits
1285 (make-ea-for-object-slot-half float double-float-value-slot
1286 other-pointer-lowtag)))))))
1290 ;;;; complex float VOPs
1292 (define-vop (make-complex-single-float)
1293 (:translate complex)
1294 (:args (real :scs (single-reg fp-single-zero)
1295 :target r
1296 :load-if (not (sc-is real fp-single-zero)))
1297 (imag :scs (single-reg fp-single-zero)
1298 :load-if (not (sc-is imag fp-single-zero))))
1299 (:arg-types single-float single-float)
1300 (:results (r :scs (complex-single-reg) :from (:argument 0)))
1301 (:result-types complex-single-float)
1302 (:note "inline complex single-float creation")
1303 (:policy :fast-safe)
1304 (:generator 5
1305 (cond ((sc-is real fp-single-zero)
1306 (inst xorps r r)
1307 (unless (sc-is imag fp-single-zero)
1308 (inst unpcklps r imag)))
1309 ((location= real imag)
1310 (move r real)
1311 (inst unpcklps r r))
1313 (move r real)
1314 (unless (sc-is imag fp-single-zero)
1315 (inst unpcklps r imag))))))
1317 (define-vop (make-complex-double-float)
1318 (:translate complex)
1319 (:args (real :scs (double-reg fp-double-zero)
1320 :target r
1321 :load-if (not (sc-is real fp-double-zero)))
1322 (imag :scs (double-reg fp-double-zero)
1323 :load-if (not (sc-is imag fp-double-zero))))
1324 (:arg-types double-float double-float)
1325 (:results (r :scs (complex-double-reg) :from (:argument 0)))
1326 (:result-types complex-double-float)
1327 (:note "inline complex double-float creation")
1328 (:policy :fast-safe)
1329 (:generator 5
1330 (cond ((sc-is real fp-double-zero)
1331 (inst xorpd r r)
1332 (unless (sc-is imag fp-double-zero)
1333 (inst unpcklpd r imag)))
1334 ((location= real imag)
1335 (move r real)
1336 (inst unpcklpd r r))
1338 (move r real)
1339 (unless (sc-is imag fp-double-zero)
1340 (inst unpcklpd r imag))))))
1342 (define-vop (complex-float-value)
1343 (:args (x :target r))
1344 (:temporary (:sc complex-double-reg) zero)
1345 (:results (r))
1346 (:variant-vars offset)
1347 (:policy :fast-safe)
1348 (:generator 3
1349 (cond ((sc-is x complex-double-reg)
1350 (move r x)
1351 (inst xorpd zero zero)
1352 (ecase offset
1353 (0 (inst unpcklpd r zero))
1354 (1 (inst unpckhpd r zero))))
1355 ((sc-is x complex-single-reg)
1356 (move r x)
1357 (ecase offset
1358 (0 (inst shufps r r #b11111100))
1359 (1 (inst shufps r r #b11111101))))
1360 ((sc-is r single-reg)
1361 (let ((ea (sc-case x
1362 (complex-single-stack
1363 (ecase offset
1364 (0 (ea-for-csf-real-stack x))
1365 (1 (ea-for-csf-imag-stack x))))
1366 (descriptor-reg
1367 (ecase offset
1368 (0 (ea-for-csf-real-desc x))
1369 (1 (ea-for-csf-imag-desc x)))))))
1370 (inst movss r ea)))
1371 ((sc-is r double-reg)
1372 (let ((ea (sc-case x
1373 (complex-double-stack
1374 (ecase offset
1375 (0 (ea-for-cdf-real-stack x))
1376 (1 (ea-for-cdf-imag-stack x))))
1377 (descriptor-reg
1378 (ecase offset
1379 (0 (ea-for-cdf-real-desc x))
1380 (1 (ea-for-cdf-imag-desc x)))))))
1381 (inst movsd r ea)))
1382 (t (error "COMPLEX-FLOAT-VALUE VOP failure")))))
1384 (define-vop (realpart/complex-single-float complex-float-value)
1385 (:translate realpart)
1386 (:args (x :scs (complex-single-reg complex-single-stack descriptor-reg)
1387 :target r))
1388 (:arg-types complex-single-float)
1389 (:results (r :scs (single-reg)))
1390 (:result-types single-float)
1391 (:note "complex float realpart")
1392 (:variant 0))
1394 (define-vop (realpart/complex-double-float complex-float-value)
1395 (:translate realpart)
1396 (:args (x :scs (complex-double-reg complex-double-stack descriptor-reg)
1397 :target r))
1398 (:arg-types complex-double-float)
1399 (:results (r :scs (double-reg)))
1400 (:result-types double-float)
1401 (:note "complex float realpart")
1402 (:variant 0))
1404 (define-vop (imagpart/complex-single-float complex-float-value)
1405 (:translate imagpart)
1406 (:args (x :scs (complex-single-reg complex-single-stack descriptor-reg)
1407 :target r))
1408 (:arg-types complex-single-float)
1409 (:results (r :scs (single-reg)))
1410 (:result-types single-float)
1411 (:note "complex float imagpart")
1412 (:variant 1))
1414 (define-vop (imagpart/complex-double-float complex-float-value)
1415 (:translate imagpart)
1416 (:args (x :scs (complex-double-reg complex-double-stack descriptor-reg)
1417 :target r))
1418 (:arg-types complex-double-float)
1419 (:results (r :scs (double-reg)))
1420 (:result-types double-float)
1421 (:note "complex float imagpart")
1422 (:variant 1))
1425 ;;; hack dummy VOPs to bias the representation selection of their
1426 ;;; arguments towards a FP register, which can help avoid consing at
1427 ;;; inappropriate locations
1428 (defknown double-float-reg-bias (double-float) (values))
1429 (define-vop (double-float-reg-bias)
1430 (:translate double-float-reg-bias)
1431 (:args (x :scs (double-reg double-stack) :load-if nil))
1432 (:arg-types double-float)
1433 (:policy :fast-safe)
1434 (:note "inline dummy FP register bias")
1435 (:ignore x)
1436 (:generator 0))
1437 (defknown single-float-reg-bias (single-float) (values))
1438 (define-vop (single-float-reg-bias)
1439 (:translate single-float-reg-bias)
1440 (:args (x :scs (single-reg single-stack) :load-if nil))
1441 (:arg-types single-float)
1442 (:policy :fast-safe)
1443 (:note "inline dummy FP register bias")
1444 (:ignore x)
1445 (:generator 0))
1447 (defknown swap-complex ((complex float)) (complex float)
1448 (foldable flushable movable always-translatable))
1449 (defoptimizer (swap-complex derive-type) ((x))
1450 (sb!c::lvar-type x))
1451 (defun swap-complex (x)
1452 (complex (imagpart x) (realpart x)))
1453 (define-vop (swap-complex-single-float)
1454 (:translate swap-complex)
1455 (:policy :fast-safe)
1456 (:args (x :scs (complex-single-reg) :target r))
1457 (:arg-types complex-single-float)
1458 (:results (r :scs (complex-single-reg)))
1459 (:result-types complex-single-float)
1460 (:generator 2
1461 (move r x)
1462 (inst shufps r r #b11110001)))
1463 (define-vop (swap-complex-double-float)
1464 (:translate swap-complex)
1465 (:policy :fast-safe)
1466 (:args (x :scs (complex-double-reg) :target r))
1467 (:arg-types complex-double-float)
1468 (:results (r :scs (complex-double-reg)))
1469 (:result-types complex-double-float)
1470 (:generator 2
1471 (move r x)
1472 (inst shufpd r r #b01)))