📄 float.lisp
字号:
;;;; floating point support for the Sparc;;;; This software is part of the SBCL system. See the README file for;;;; more information.;;;;;;;; This software is derived from the CMU CL system, which was;;;; written at Carnegie Mellon University and released into the;;;; public domain. The software is in the public domain and is;;;; provided with absolutely no warranty. See the COPYING and CREDITS;;;; files for more information.(in-package "SB!VM");;;; float move functions(define-move-fun (load-single 1) (vop x y) ((single-stack) (single-reg)) (inst ldf y (current-nfp-tn vop) (* (tn-offset x) n-word-bytes)))(define-move-fun (store-single 1) (vop x y) ((single-reg) (single-stack)) (inst stf x (current-nfp-tn vop) (* (tn-offset y) n-word-bytes)))(define-move-fun (load-double 2) (vop x y) ((double-stack) (double-reg)) (let ((nfp (current-nfp-tn vop)) (offset (* (tn-offset x) n-word-bytes))) (inst lddf y nfp offset)))(define-move-fun (store-double 2) (vop x y) ((double-reg) (double-stack)) (let ((nfp (current-nfp-tn vop)) (offset (* (tn-offset y) n-word-bytes))) (inst stdf x nfp offset)));;; The offset may be an integer or a TN in which case it will be;;; temporarily modified but is restored if restore-offset is true.(defun load-long-reg (reg base offset &optional (restore-offset t)) (cond ((member :sparc-v9 *backend-subfeatures*) (inst ldqf reg base offset)) (t (let ((reg0 (make-random-tn :kind :normal :sc (sc-or-lose 'double-reg) :offset (tn-offset reg))) (reg2 (make-random-tn :kind :normal :sc (sc-or-lose 'double-reg) :offset (+ 2 (tn-offset reg))))) (cond ((integerp offset) (inst lddf reg0 base offset) (inst lddf reg2 base (+ offset (* 2 n-word-bytes)))) (t (inst lddf reg0 base offset) (inst add offset (* 2 n-word-bytes)) (inst lddf reg2 base offset) (when restore-offset (inst sub offset (* 2 n-word-bytes)))))))))#!+long-float(define-move-fun (load-long 2) (vop x y) ((long-stack) (long-reg)) (let ((nfp (current-nfp-tn vop)) (offset (* (tn-offset x) n-word-bytes))) (load-long-reg y nfp offset)));;; The offset may be an integer or a TN in which case it will be;;; temporarily modified but is restored if restore-offset is true.(defun store-long-reg (reg base offset &optional (restore-offset t)) (cond ((member :sparc-v9 *backend-subfeatures*) (inst stqf reg base offset)) (t (let ((reg0 (make-random-tn :kind :normal :sc (sc-or-lose 'double-reg) :offset (tn-offset reg))) (reg2 (make-random-tn :kind :normal :sc (sc-or-lose 'double-reg) :offset (+ 2 (tn-offset reg))))) (cond ((integerp offset) (inst stdf reg0 base offset) (inst stdf reg2 base (+ offset (* 2 n-word-bytes)))) (t (inst stdf reg0 base offset) (inst add offset (* 2 n-word-bytes)) (inst stdf reg2 base offset) (when restore-offset (inst sub offset (* 2 n-word-bytes)))))))))#!+long-float(define-move-fun (store-long 2) (vop x y) ((long-reg) (long-stack)) (let ((nfp (current-nfp-tn vop)) (offset (* (tn-offset y) n-word-bytes))) (store-long-reg x nfp offset)));;;; Move VOPs:;;; Exploit the V9 double-float move instruction. This is conditional;;; on the :sparc-v9 feature.(defun move-double-reg (dst src) (cond ((member :sparc-v9 *backend-subfeatures*) (inst fmovd dst src)) (t (dotimes (i 2) (let ((dst (make-random-tn :kind :normal :sc (sc-or-lose 'single-reg) :offset (+ i (tn-offset dst)))) (src (make-random-tn :kind :normal :sc (sc-or-lose 'single-reg) :offset (+ i (tn-offset src))))) (inst fmovs dst src))))));;; Exploit the V9 long-float move instruction. This is conditional;;; on the :sparc-v9 feature.(defun move-long-reg (dst src) (cond ((member :sparc-v9 *backend-subfeatures*) (inst fmovq dst src)) (t (dotimes (i 4) (let ((dst (make-random-tn :kind :normal :sc (sc-or-lose 'single-reg) :offset (+ i (tn-offset dst)))) (src (make-random-tn :kind :normal :sc (sc-or-lose 'single-reg) :offset (+ i (tn-offset src))))) (inst fmovs dst src))))))(macrolet ((frob (vop sc format) `(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) ,@(ecase format (:single `((inst fmovs y x))) (:double `((move-double-reg y x))) (:long `((move-long-reg y x))))))) (define-move-vop ,vop :move (,sc) (,sc))))) (frob single-move single-reg :single) (frob double-move double-reg :double) #!+long-float (frob long-move long-reg :long))(define-vop (move-from-float) (:args (x :to :save)) (:results (y)) (:note "float to pointer coercion") (:temporary (:scs (non-descriptor-reg)) ndescr) (:variant-vars format size type data) (:generator 13 (with-fixed-allocation (y ndescr type size) (ecase format (:single (inst stf x y (- (* data n-word-bytes) other-pointer-lowtag))) (:double (inst stdf x y (- (* data n-word-bytes) other-pointer-lowtag))) (:long (store-long-reg x y (- (* data n-word-bytes) other-pointer-lowtag)))))))(macrolet ((frob (name sc &rest args) `(progn (define-vop (,name move-from-float) (:args (x :scs (,sc) :to :save)) (:results (y :scs (descriptor-reg))) (:variant ,@args)) (define-move-vop ,name :move (,sc) (descriptor-reg))))) (frob move-from-single single-reg :single single-float-size single-float-widetag single-float-value-slot) (frob move-from-double double-reg :double double-float-size double-float-widetag double-float-value-slot) #!+long-float (frob move-from-long long-reg :long long-float-size long-float-widetag long-float-value-slot))(macrolet ((frob (name sc format value) `(progn (define-vop (,name) (:args (x :scs (descriptor-reg))) (:results (y :scs (,sc))) (:note "pointer to float coercion") (:generator 2 (inst ,(ecase format (:single 'ldf) (:double 'lddf)) y x (- (* ,value n-word-bytes) other-pointer-lowtag)))) (define-move-vop ,name :move (descriptor-reg) (,sc))))) (frob move-to-single single-reg :single single-float-value-slot) (frob move-to-double double-reg :double double-float-value-slot))#!+long-float(define-vop (move-to-long) (:args (x :scs (descriptor-reg))) (:results (y :scs (long-reg))) (:note "pointer to float coercion") (:generator 2 (load-long-reg y x (- (* long-float-value-slot n-word-bytes) other-pointer-lowtag))))#!+long-float(define-move-vop move-to-long :move (descriptor-reg) (long-reg))(macrolet ((frob (name sc stack-sc format) `(progn (define-vop (,name) (:args (x :scs (,sc) :target y) (nfp :scs (any-reg) :load-if (not (sc-is y ,sc)))) (:results (y)) (:note "float argument move") (:generator ,(ecase format (:single 1) (:double 2)) (sc-case y (,sc (unless (location= x y) ,@(ecase format (:single '((inst fmovs y x))) (:double '((move-double-reg y x)))))) (,stack-sc (let ((offset (* (tn-offset y) n-word-bytes))) (inst ,(ecase format (:single 'stf) (:double 'stdf)) x nfp offset)))))) (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))#!+long-float(define-vop (move-long-float-arg) (:args (x :scs (long-reg) :target y) (nfp :scs (any-reg) :load-if (not (sc-is y long-reg)))) (:results (y)) (:note "float argument move") (:generator 3 (sc-case y (long-reg (unless (location= x y) (move-long-reg y x))) (long-stack (let ((offset (* (tn-offset y) n-word-bytes))) (store-long-reg x nfp offset))))));;;#!+long-float(define-move-vop move-long-float-arg :move-arg (long-reg descriptor-reg) (long-reg));;;; Complex float move functions(defun complex-single-reg-real-tn (x) (make-random-tn :kind :normal :sc (sc-or-lose 'single-reg) :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))))(defun complex-double-reg-real-tn (x) (make-random-tn :kind :normal :sc (sc-or-lose 'double-reg) :offset (tn-offset x)))(defun complex-double-reg-imag-tn (x) (make-random-tn :kind :normal :sc (sc-or-lose 'double-reg) :offset (+ (tn-offset x) 2)))#!+long-float(defun complex-long-reg-real-tn (x) (make-random-tn :kind :normal :sc (sc-or-lose 'long-reg) :offset (tn-offset x)))#!+long-float(defun complex-long-reg-imag-tn (x) (make-random-tn :kind :normal :sc (sc-or-lose 'long-reg) :offset (+ (tn-offset x) 4)))(define-move-fun (load-complex-single 2) (vop x y) ((complex-single-stack) (complex-single-reg)) (let ((nfp (current-nfp-tn vop)) (offset (* (tn-offset x) n-word-bytes))) (let ((real-tn (complex-single-reg-real-tn y))) (inst ldf real-tn nfp offset)) (let ((imag-tn (complex-single-reg-imag-tn y))) (inst ldf imag-tn nfp (+ offset n-word-bytes)))))(define-move-fun (store-complex-single 2) (vop x y) ((complex-single-reg) (complex-single-stack)) (let ((nfp (current-nfp-tn vop)) (offset (* (tn-offset y) n-word-bytes))) (let ((real-tn (complex-single-reg-real-tn x))) (inst stf real-tn nfp offset)) (let ((imag-tn (complex-single-reg-imag-tn x))) (inst stf imag-tn nfp (+ offset n-word-bytes)))))(define-move-fun (load-complex-double 4) (vop x y) ((complex-double-stack) (complex-double-reg)) (let ((nfp (current-nfp-tn vop)) (offset (* (tn-offset x) n-word-bytes))) (let ((real-tn (complex-double-reg-real-tn y))) (inst lddf real-tn nfp offset)) (let ((imag-tn (complex-double-reg-imag-tn y))) (inst lddf imag-tn nfp (+ offset (* 2 n-word-bytes))))))(define-move-fun (store-complex-double 4) (vop x y) ((complex-double-reg) (complex-double-stack)) (let ((nfp (current-nfp-tn vop)) (offset (* (tn-offset y) n-word-bytes))) (let ((real-tn (complex-double-reg-real-tn x))) (inst stdf real-tn nfp offset)) (let ((imag-tn (complex-double-reg-imag-tn x))) (inst stdf imag-tn nfp (+ offset (* 2 n-word-bytes))))))#!+long-float(define-move-fun (load-complex-long 5) (vop x y) ((complex-long-stack) (complex-long-reg)) (let ((nfp (current-nfp-tn vop)) (offset (* (tn-offset x) n-word-bytes))) (let ((real-tn (complex-long-reg-real-tn y))) (load-long-reg real-tn nfp offset)) (let ((imag-tn (complex-long-reg-imag-tn y))) (load-long-reg imag-tn nfp (+ offset (* 4 n-word-bytes))))))#!+long-float(define-move-fun (store-complex-long 5) (vop x y) ((complex-long-reg) (complex-long-stack)) (let ((nfp (current-nfp-tn vop)) (offset (* (tn-offset y) n-word-bytes))) (let ((real-tn (complex-long-reg-real-tn x))) (store-long-reg real-tn nfp offset)) (let ((imag-tn (complex-long-reg-imag-tn x))) (store-long-reg imag-tn nfp (+ offset (* 4 n-word-bytes))))));;;;;; Complex float register to register moves.;;;(define-vop (complex-single-move) (:args (x :scs (complex-single-reg) :target y :load-if (not (location= x y))))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -