X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fcompiler%2Fx86-64%2Ffloat.lisp;h=63ae04004b73aa9202f219579e3c8f74f6b040df;hb=085501b44cc1cbdd9e260139d30b383372ddd1b8;hp=c885e1305cd6006428286b543d13e9235f61f547;hpb=ffde26c7766d109683ab73622b5b4294a3dd1c52;p=sbcl.git diff --git a/src/compiler/x86-64/float.lisp b/src/compiler/x86-64/float.lisp index c885e13..63ae040 100644 --- a/src/compiler/x86-64/float.lisp +++ b/src/compiler/x86-64/float.lisp @@ -12,10 +12,10 @@ (in-package "SB!VM") (macrolet ((ea-for-xf-desc (tn slot) - `(make-ea - :qword :base ,tn - :disp (- (* ,slot n-word-bytes) - other-pointer-lowtag)))) + `(make-ea + :qword :base ,tn + :disp (- (* ,slot n-word-bytes) + other-pointer-lowtag)))) (defun ea-for-df-desc (tn) (ea-for-xf-desc tn double-float-value-slot)) ;; complex floats @@ -29,11 +29,11 @@ (ea-for-xf-desc tn complex-double-float-imag-slot))) (macrolet ((ea-for-xf-stack (tn kind) - (declare (ignore kind)) - `(make-ea - :qword :base rbp-tn - :disp (- (* (+ (tn-offset ,tn) 1) - n-word-bytes))))) + (declare (ignore kind)) + `(make-ea + :qword :base rbp-tn + :disp (- (* (+ (tn-offset ,tn) 1) + n-word-bytes))))) (defun ea-for-sf-stack (tn) (ea-for-xf-stack tn :single)) (defun ea-for-df-stack (tn) @@ -41,12 +41,12 @@ ;;; complex float stack EAs (macrolet ((ea-for-cxf-stack (tn kind slot &optional base) - (declare (ignore kind)) - `(make-ea - :qword :base ,base - :disp (- (* (+ (tn-offset ,tn) - (* 1 (ecase ,slot (:real 1) (:imag 2)))) - n-word-bytes))))) + (declare (ignore kind)) + `(make-ea + :qword :base ,base + :disp (- (* (+ (tn-offset ,tn) + (* 1 (ecase ,slot (:real 1) (:imag 2)))) + n-word-bytes))))) (defun ea-for-csf-real-stack (tn &optional (base rbp-tn)) (ea-for-cxf-stack tn :single :real base)) (defun ea-for-csf-imag-stack (tn &optional (base rbp-tn)) @@ -64,8 +64,10 @@ (define-move-fun (load-fp-zero 1) (vop x y) ((fp-single-zero) (single-reg) (fp-double-zero) (double-reg)) - (identity x) ; KLUDGE: IDENTITY as IGNORABLE... - (inst movq y fp-double-zero-tn)) + (identity x) + (sc-case y + (single-reg (inst xorps y y)) + (double-reg (inst xorpd y y)))) (define-move-fun (load-single 2) (vop x y) ((single-stack) (single-reg)) @@ -90,17 +92,17 @@ (defun complex-single-reg-real-tn (x) (make-random-tn :kind :normal :sc (sc-or-lose 'single-reg) - :offset (tn-offset x))) + :offset (tn-offset x))) (defun complex-single-reg-imag-tn (x) (make-random-tn :kind :normal :sc (sc-or-lose 'single-reg) - :offset (1+ (tn-offset x)))) + :offset (1+ (tn-offset x)))) (defun complex-double-reg-real-tn (x) (make-random-tn :kind :normal :sc (sc-or-lose 'double-reg) - :offset (tn-offset x))) + :offset (tn-offset x))) (defun complex-double-reg-imag-tn (x) (make-random-tn :kind :normal :sc (sc-or-lose 'double-reg) - :offset (1+ (tn-offset x)))) + :offset (1+ (tn-offset x)))) ;;; X is source, Y is destination. (define-move-fun (load-complex-single 2) (vop x y) @@ -113,7 +115,7 @@ (define-move-fun (store-complex-single 2) (vop x y) ((complex-single-reg) (complex-single-stack)) (let ((real-tn (complex-single-reg-real-tn x)) - (imag-tn (complex-single-reg-imag-tn x))) + (imag-tn (complex-single-reg-imag-tn x))) (inst movss (ea-for-csf-real-stack y) real-tn) (inst movss (ea-for-csf-imag-stack y) imag-tn))) @@ -127,7 +129,7 @@ (define-move-fun (store-complex-double 2) (vop x y) ((complex-double-reg) (complex-double-stack)) (let ((real-tn (complex-double-reg-real-tn x)) - (imag-tn (complex-double-reg-imag-tn x))) + (imag-tn (complex-double-reg-imag-tn x))) (inst movsd (ea-for-cdf-real-stack y) real-tn) (inst movsd (ea-for-cdf-imag-stack y) imag-tn))) @@ -136,18 +138,18 @@ ;;; float register to register moves (macrolet ((frob (vop sc) - `(progn - (define-vop (,vop) - (:args (x :scs (,sc) - :target y - :load-if (not (location= x y)))) - (:results (y :scs (,sc) - :load-if (not (location= x y)))) - (:note "float move") - (:generator 0 - (unless (location= y x) - (inst movq y x)))) - (define-move-vop ,vop :move (,sc) (,sc))))) + `(progn + (define-vop (,vop) + (:args (x :scs (,sc) + :target y + :load-if (not (location= x y)))) + (:results (y :scs (,sc) + :load-if (not (location= x y)))) + (:note "float move") + (:generator 0 + (unless (location= y x) + (inst movq y x)))) + (define-move-vop ,vop :move (,sc) (,sc))))) (frob single-move single-reg) (frob double-move double-reg)) @@ -160,25 +162,25 @@ (unless (location= x y) ;; Note the complex-float-regs are aligned to every second ;; float register so there is not need to worry about overlap. - ;; (It would be better to put the imagpart in the top half of the + ;; (It would be better to put the imagpart in the top half of the ;; register, or something, but let's worry about that later) (let ((x-real (complex-single-reg-real-tn x)) - (y-real (complex-single-reg-real-tn y))) - (inst movq y-real x-real)) + (y-real (complex-single-reg-real-tn y))) + (inst movq y-real x-real)) (let ((x-imag (complex-single-reg-imag-tn x)) - (y-imag (complex-single-reg-imag-tn y))) - (inst movq y-imag x-imag))))) + (y-imag (complex-single-reg-imag-tn y))) + (inst movq y-imag x-imag))))) (define-vop (complex-single-move complex-float-move) (:args (x :scs (complex-single-reg) :target y - :load-if (not (location= x y)))) + :load-if (not (location= x y)))) (:results (y :scs (complex-single-reg) :load-if (not (location= x y))))) (define-move-vop complex-single-move :move (complex-single-reg) (complex-single-reg)) (define-vop (complex-double-move complex-float-move) (:args (x :scs (complex-double-reg) - :target y :load-if (not (location= x y)))) + :target y :load-if (not (location= x y)))) (:results (y :scs (complex-double-reg) :load-if (not (location= x y))))) (define-move-vop complex-double-move :move (complex-double-reg) (complex-double-reg)) @@ -205,9 +207,9 @@ (:note "float to pointer coercion") (:generator 13 (with-fixed-allocation (y - double-float-widetag - double-float-size - node) + double-float-widetag + double-float-size + node) (inst movsd (ea-for-df-desc y) x)))) (define-move-vop move-from-double :move (double-reg) (descriptor-reg)) @@ -243,13 +245,13 @@ (:note "complex float to pointer coercion") (:generator 13 (with-fixed-allocation (y - complex-single-float-widetag - complex-single-float-size - node) + complex-single-float-widetag + complex-single-float-size + node) (let ((real-tn (complex-single-reg-real-tn x))) - (inst movss (ea-for-csf-real-desc y) real-tn)) + (inst movss (ea-for-csf-real-desc y) real-tn)) (let ((imag-tn (complex-single-reg-imag-tn x))) - (inst movss (ea-for-csf-imag-desc y) imag-tn))))) + (inst movss (ea-for-csf-imag-desc y) imag-tn))))) (define-move-vop move-from-complex-single :move (complex-single-reg) (descriptor-reg)) @@ -260,39 +262,39 @@ (:note "complex float to pointer coercion") (:generator 13 (with-fixed-allocation (y - complex-double-float-widetag - complex-double-float-size - node) + complex-double-float-widetag + complex-double-float-size + node) (let ((real-tn (complex-double-reg-real-tn x))) - (inst movsd (ea-for-cdf-real-desc y) real-tn)) + (inst movsd (ea-for-cdf-real-desc y) real-tn)) (let ((imag-tn (complex-double-reg-imag-tn x))) - (inst movsd (ea-for-cdf-imag-desc y) imag-tn))))) + (inst movsd (ea-for-cdf-imag-desc y) imag-tn))))) (define-move-vop move-from-complex-double :move (complex-double-reg) (descriptor-reg)) ;;; Move from a descriptor to a complex float register. (macrolet ((frob (name sc format) - `(progn - (define-vop (,name) - (:args (x :scs (descriptor-reg))) - (:results (y :scs (,sc))) - (:note "pointer to complex float coercion") - (:generator 2 - (let ((real-tn (complex-double-reg-real-tn y))) - ,@(ecase - format - (:single - '((inst movss real-tn (ea-for-csf-real-desc x)))) - (:double - '((inst movsd real-tn (ea-for-cdf-real-desc x)))))) - (let ((imag-tn (complex-double-reg-imag-tn y))) - ,@(ecase - format - (:single - '((inst movss imag-tn (ea-for-csf-imag-desc x)))) - (:double - '((inst movsd imag-tn (ea-for-cdf-imag-desc x)))))))) - (define-move-vop ,name :move (descriptor-reg) (,sc))))) + `(progn + (define-vop (,name) + (:args (x :scs (descriptor-reg))) + (:results (y :scs (,sc))) + (:note "pointer to complex float coercion") + (:generator 2 + (let ((real-tn (complex-double-reg-real-tn y))) + ,@(ecase + format + (:single + '((inst movss real-tn (ea-for-csf-real-desc x)))) + (:double + '((inst movsd real-tn (ea-for-cdf-real-desc x)))))) + (let ((imag-tn (complex-double-reg-imag-tn y))) + ,@(ecase + format + (:single + '((inst movss imag-tn (ea-for-csf-imag-desc x)))) + (:double + '((inst movsd imag-tn (ea-for-cdf-imag-desc x)))))))) + (define-move-vop ,name :move (descriptor-reg) (,sc))))) (frob move-to-complex-single complex-single-reg :single) (frob move-to-complex-double complex-double-reg :double)) @@ -303,84 +305,81 @@ ;;; the general MOVE-ARG VOP (macrolet ((frob (name sc stack-sc format) - `(progn - (define-vop (,name) - (:args (x :scs (,sc) :target y) - (fp :scs (any-reg) - :load-if (not (sc-is y ,sc)))) - (:results (y)) - (:note "float argument move") - (:generator ,(case format (:single 2) (:double 3) ) - (sc-case y - (,sc - (unless (location= x y) - (inst movq y x))) - (,stack-sc - (if (= (tn-offset fp) esp-offset) - (let* ((offset (* (tn-offset y) n-word-bytes)) - (ea (make-ea :dword :base fp :disp offset))) - ,@(ecase format - (:single '((inst movss ea x))) - (:double '((inst movsd ea x))))) - (let ((ea (make-ea - :dword :base fp - :disp (- (* (+ (tn-offset y) - ,(case format - (:single 1) - (:double 2) )) - n-word-bytes))))) - ,@(ecase format - (:single '((inst movss ea x))) - (:double '((inst movsd ea x)))))))))) - (define-move-vop ,name :move-arg - (,sc descriptor-reg) (,sc))))) + `(progn + (define-vop (,name) + (:args (x :scs (,sc) :target y) + (fp :scs (any-reg) + :load-if (not (sc-is y ,sc)))) + (:results (y)) + (:note "float argument move") + (:generator ,(case format (:single 2) (:double 3) ) + (sc-case y + (,sc + (unless (location= x y) + (inst movq y x))) + (,stack-sc + (if (= (tn-offset fp) esp-offset) + (let* ((offset (* (tn-offset y) n-word-bytes)) + (ea (make-ea :dword :base fp :disp offset))) + ,@(ecase format + (:single '((inst movss ea x))) + (:double '((inst movsd ea x))))) + (let ((ea (make-ea + :dword :base fp + :disp (- (* (1+ (tn-offset y)) + n-word-bytes))))) + ,@(ecase format + (:single '((inst movss ea x))) + (:double '((inst movsd ea x)))))))))) + (define-move-vop ,name :move-arg + (,sc descriptor-reg) (,sc))))) (frob move-single-float-arg single-reg single-stack :single) (frob move-double-float-arg double-reg double-stack :double)) ;;;; complex float MOVE-ARG VOP (macrolet ((frob (name sc stack-sc format) - `(progn - (define-vop (,name) - (:args (x :scs (,sc) :target y) - (fp :scs (any-reg) - :load-if (not (sc-is y ,sc)))) - (:results (y)) - (:note "complex float argument move") - (:generator ,(ecase format (:single 2) (:double 3)) - (sc-case y - (,sc - (unless (location= x y) - (let ((x-real (complex-double-reg-real-tn x)) - (y-real (complex-double-reg-real-tn y))) - (inst movsd y-real x-real)) - (let ((x-imag (complex-double-reg-imag-tn x)) - (y-imag (complex-double-reg-imag-tn y))) - (inst movsd y-imag x-imag)))) - (,stack-sc - (let ((real-tn (complex-double-reg-real-tn x))) - ,@(ecase format - (:single - '((inst movss - (ea-for-csf-real-stack y fp) - real-tn))) - (:double - '((inst movsd - (ea-for-cdf-real-stack y fp) - real-tn))))) - (let ((imag-tn (complex-double-reg-imag-tn x))) - ,@(ecase format - (:single - '((inst movss - (ea-for-csf-imag-stack y fp) imag-tn))) - (:double - '((inst movsd - (ea-for-cdf-imag-stack y fp) imag-tn))))))))) - (define-move-vop ,name :move-arg - (,sc descriptor-reg) (,sc))))) + `(progn + (define-vop (,name) + (:args (x :scs (,sc) :target y) + (fp :scs (any-reg) + :load-if (not (sc-is y ,sc)))) + (:results (y)) + (:note "complex float argument move") + (:generator ,(ecase format (:single 2) (:double 3)) + (sc-case y + (,sc + (unless (location= x y) + (let ((x-real (complex-double-reg-real-tn x)) + (y-real (complex-double-reg-real-tn y))) + (inst movsd y-real x-real)) + (let ((x-imag (complex-double-reg-imag-tn x)) + (y-imag (complex-double-reg-imag-tn y))) + (inst movsd y-imag x-imag)))) + (,stack-sc + (let ((real-tn (complex-double-reg-real-tn x))) + ,@(ecase format + (:single + '((inst movss + (ea-for-csf-real-stack y fp) + real-tn))) + (:double + '((inst movsd + (ea-for-cdf-real-stack y fp) + real-tn))))) + (let ((imag-tn (complex-double-reg-imag-tn x))) + ,@(ecase format + (:single + '((inst movss + (ea-for-csf-imag-stack y fp) imag-tn))) + (:double + '((inst movsd + (ea-for-cdf-imag-stack y fp) imag-tn))))))))) + (define-move-vop ,name :move-arg + (,sc descriptor-reg) (,sc))))) (frob move-complex-single-float-arg - complex-single-reg complex-single-stack :single) + complex-single-reg complex-single-stack :single) (frob move-complex-double-float-arg - complex-double-reg complex-double-stack :double)) + complex-double-reg complex-double-stack :double)) (define-move-vop move-arg :move-arg (single-reg double-reg @@ -399,90 +398,102 @@ (:save-p :compute-only)) (macrolet ((frob (name sc ptype) - `(define-vop (,name float-op) - (:args (x :scs (,sc) :target r) - (y :scs (,sc))) - (:results (r :scs (,sc))) - (:arg-types ,ptype ,ptype) - (:result-types ,ptype)))) + `(define-vop (,name float-op) + (:args (x :scs (,sc) :target r) + (y :scs (,sc))) + (:results (r :scs (,sc))) + (:arg-types ,ptype ,ptype) + (:result-types ,ptype)))) (frob single-float-op single-reg single-float) (frob double-float-op double-reg double-float)) (macrolet ((generate (movinst opinst commutative) - `(progn - (cond - ((location= x r) - (inst ,opinst x y)) - ((and ,commutative (location= y r)) - (inst ,opinst y x)) - ((not (location= r y)) - (inst ,movinst r x) - (inst ,opinst r y)) - (t - (inst ,movinst tmp x) - (inst ,opinst tmp y) - (inst ,movinst r tmp))))) - (frob (op sinst sname scost dinst dname dcost commutative) - `(progn - (define-vop (,sname single-float-op) - (:translate ,op) - (:temporary (:sc single-reg) tmp) - (:generator ,scost - (generate movss ,sinst ,commutative))) - (define-vop (,dname double-float-op) - (:translate ,op) - (:temporary (:sc single-reg) tmp) - (:generator ,dcost + `(progn + (cond + ((location= x r) + (inst ,opinst x y)) + ((and ,commutative (location= y r)) + (inst ,opinst y x)) + ((not (location= r y)) + (inst ,movinst r x) + (inst ,opinst r y)) + (t + (inst ,movinst tmp x) + (inst ,opinst tmp y) + (inst ,movinst r tmp))))) + (frob (op sinst sname scost dinst dname dcost commutative) + `(progn + (define-vop (,sname single-float-op) + (:translate ,op) + (:temporary (:sc single-reg) tmp) + (:generator ,scost + (generate movss ,sinst ,commutative))) + (define-vop (,dname double-float-op) + (:translate ,op) + (:temporary (:sc single-reg) tmp) + (:generator ,dcost (generate movsd ,dinst ,commutative)))))) (frob + addss +/single-float 2 addsd +/double-float 2 t) (frob - subss -/single-float 2 subsd -/double-float 2 nil) (frob * mulss */single-float 4 mulsd */double-float 5 t) (frob / divss //single-float 12 divsd //double-float 19 nil)) - +(define-vop (fsqrt) + (:args (x :scs (double-reg))) + (:results (y :scs (double-reg))) + (:translate %sqrt) + (:policy :fast-safe) + (:arg-types double-float) + (:result-types double-float) + (:note "inline float arithmetic") + (:vop-var vop) + (:save-p :compute-only) + (:generator 1 + (note-this-location vop :internal-error) + (inst sqrtsd y x))) (macrolet ((frob ((name translate sc type) &body body) - `(define-vop (,name) - (:args (x :scs (,sc))) - (:results (y :scs (,sc))) - (:translate ,translate) - (:policy :fast-safe) - (:arg-types ,type) - (:result-types ,type) - (:temporary (:sc any-reg) hex8) - (:temporary - (:sc ,sc) xmm) - (:note "inline float arithmetic") - (:vop-var vop) - (:save-p :compute-only) - (:generator 1 - (note-this-location vop :internal-error) - ;; we should be able to do this better. what we - ;; really would like to do is use the target as the - ;; temp whenever it's not also the source - (unless (location= x y) - (inst movq y x)) - ,@body)))) + `(define-vop (,name) + (:args (x :scs (,sc))) + (:results (y :scs (,sc))) + (:translate ,translate) + (:policy :fast-safe) + (:arg-types ,type) + (:result-types ,type) + (:temporary (:sc any-reg) hex8) + (:temporary + (:sc ,sc) xmm) + (:note "inline float arithmetic") + (:vop-var vop) + (:save-p :compute-only) + (:generator 1 + (note-this-location vop :internal-error) + ;; we should be able to do this better. what we + ;; really would like to do is use the target as the + ;; temp whenever it's not also the source + (unless (location= x y) + (inst movq y x)) + ,@body)))) (frob (%negate/double-float %negate double-reg double-float) - (inst lea hex8 (make-ea :qword :disp 1)) - (inst ror hex8 1) ; #x8000000000000000 - (inst movd xmm hex8) - (inst xorpd y xmm)) + (inst lea hex8 (make-ea :qword :disp 1)) + (inst ror hex8 1) ; #x8000000000000000 + (inst movd xmm hex8) + (inst xorpd y xmm)) (frob (%negate/single-float %negate single-reg single-float) - (inst lea hex8 (make-ea :qword :disp 1)) - (inst rol hex8 31) - (inst movd xmm hex8) - (inst xorps y xmm)) + (inst lea hex8 (make-ea :qword :disp 1)) + (inst rol hex8 31) + (inst movd xmm hex8) + (inst xorps y xmm)) (frob (abs/double-float abs double-reg double-float) - (inst mov hex8 -1) - (inst shr hex8 1) - (inst movd xmm hex8) - (inst andpd y xmm)) + (inst mov hex8 -1) + (inst shr hex8 1) + (inst movd xmm hex8) + (inst andpd y xmm)) (frob (abs/single-float abs single-reg single-float) - (inst mov hex8 -1) - (inst shr hex8 33) - (inst movd xmm hex8) - (inst andps y xmm))) + (inst mov hex8 -1) + (inst shr hex8 33) + (inst movd xmm hex8) + (inst andps y xmm))) ;;;; comparison @@ -517,13 +528,13 @@ ;; if PF&CF, there was a NaN involved => not equal ;; otherwise, ZF => equal (cond (not-p - (inst jmp :p target) - (inst jmp :ne target)) - (t - (let ((not-lab (gen-label))) - (inst jmp :p not-lab) - (inst jmp :e target) - (emit-label not-lab)))))) + (inst jmp :p target) + (inst jmp :ne target)) + (t + (let ((not-lab (gen-label))) + (inst jmp :p not-lab) + (inst jmp :e target) + (emit-label not-lab)))))) (define-vop (=/double-float double-float-compare) (:translate =) @@ -533,13 +544,13 @@ (note-this-location vop :internal-error) (inst comisd x y) (cond (not-p - (inst jmp :p target) - (inst jmp :ne target)) - (t - (let ((not-lab (gen-label))) - (inst jmp :p not-lab) - (inst jmp :e target) - (emit-label not-lab)))))) + (inst jmp :p target) + (inst jmp :ne target)) + (t + (let ((not-lab (gen-label))) + (inst jmp :p not-lab) + (inst jmp :e target) + (emit-label not-lab)))))) ;; XXX all of these probably have bad NaN behaviour (define-vop (