(+ (tn-offset ,tn)
(cond ((= (tn-offset ,base) rsp-offset)
sp->fp-offset)
- ((= (tn-offset ,base) rbp-offset)
- 0)
- (t (error "Unexpected offset.")))
+ (t 0))
(ecase ,kind
(:single
(ecase ,slot
(double-reg) (descriptor-reg))
;;; Move from a descriptor to a float register.
-(define-vop (move-to-single)
+(define-vop (move-to-single-reg)
+ (:args (x :scs (descriptor-reg) :target tmp
+ :load-if (not (sc-is x control-stack))))
+ (:temporary (:sc unsigned-reg :from :argument :to :result) tmp)
+ (:results (y :scs (single-reg)))
+ (:note "pointer to float coercion")
+ (:generator 2
+ (sc-case x
+ (descriptor-reg
+ (move tmp x)
+ (inst shr tmp 32)
+ (inst movd y tmp))
+ (control-stack
+ ;; When the single-float descriptor is in memory, the untagging
+ ;; is done in the target XMM register. This is faster than going
+ ;; through a general-purpose register and the code is smaller.
+ (inst movq y x)
+ (inst shufps y y #4r3331)))))
+(define-move-vop move-to-single-reg :move (descriptor-reg) (single-reg))
+
+;;; Move from a descriptor to a float stack.
+(define-vop (move-to-single-stack)
(:args (x :scs (descriptor-reg) :target tmp))
- (:temporary (:sc unsigned-reg) tmp)
- (:results (y :scs (single-reg)))
+ (:temporary (:sc unsigned-reg :from :argument :to :result) tmp)
+ (:results (y :scs (single-stack)))
(:note "pointer to float coercion")
(:generator 2
(move tmp x)
(inst shr tmp 32)
- (inst movd y tmp)))
-
-(define-move-vop move-to-single :move (descriptor-reg) (single-reg))
+ (let ((slot (make-ea :dword :base rbp-tn
+ :disp (frame-byte-offset (tn-offset y)))))
+ (inst mov slot (reg-in-size tmp :dword)))))
+(define-move-vop move-to-single-stack :move (descriptor-reg) (single-stack))
(define-vop (move-to-double)
(:args (x :scs (descriptor-reg)))
(:vop-var vop)
(:save-p :compute-only)
(:generator 1
+ (unless (location= x y)
+ (inst xorpd y y))
(note-this-location vop :internal-error)
(inst sqrtsd y x)))
\f
(:vop-var vop)
(:save-p :compute-only)
(:generator 5
+ (sc-case y
+ (single-reg (inst xorps y y))
+ (double-reg (inst xorpd y y)))
(note-this-location vop :internal-error)
(inst ,inst y x)))))
(frob %single-float/signed %single-float cvtsi2ss single-reg single-float)
(:vop-var vop)
(:save-p :compute-only)
(:generator 2
+ (unless (location= x y)
+ (sc-case y
+ (single-reg (inst xorps y y))
+ (double-reg (inst xorpd y y))))
(note-this-location vop :internal-error)
(inst ,inst y (sc-case x
(,(first from-scs) x)
- (,(second from-scs) (,ea-func x))))))))
+ (,(second from-scs) (,ea-func x))))
+ ,(when (and (eq from-type 'double-float) ; if the input is wider
+ (eq to-type 'single-float)) ; than the output, clear
+ `(when (location= x y) ; noise in the high part
+ (inst shufps y y #4r3330)))))))
(frob %single-float/double-float %single-float cvtsd2ss
(double-reg double-stack) double-float ea-for-df-stack
single-reg single-float)