~ubuntu-branches/debian/squeeze/cmucl/squeeze

« back to all changes in this revision

Viewing changes to src/compiler/x86/float.lisp

  • Committer: Bazaar Package Importer
  • Author(s): Peter Van Eynde
  • Date: 2009-02-18 05:50:05 UTC
  • mfrom: (0.2.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20090218055005-kt6ookdcasemovhl
Tags: 19e-20080501-2
* fix brown bag bug: use cmucl in script, not lisp
* New version should Fixes: #483331 because of asm change

Show diffs side-by-side

added added

removed removed

Lines of Context:
7
7
;;; Scott Fahlman or slisp-group@cs.cmu.edu.
8
8
;;;
9
9
(ext:file-comment
10
 
  "$Header: /project/cmucl/cvsroot/src/compiler/x86/float.lisp,v 1.44 2006/07/19 02:54:31 rtoy Exp $")
 
10
  "$Header: /project/cmucl/cvsroot/src/compiler/x86/float.lisp,v 1.56 2008/02/04 20:33:22 rtoy Exp $")
11
11
;;;
12
12
;;; **********************************************************************
13
13
;;;
161
161
;;; The x86 can't store a long-float to memory without popping the
162
162
;;; stack and marking a register as empty, so it is necessary to
163
163
;;; restore the register from memory.
164
 
#+long-float
165
164
(defun store-long-float (ea)
166
165
   (inst fstpl ea)
167
166
   (inst fldl ea))
843
842
#+double-double
844
843
(define-vop (move-complex-double-double-float-argument)
845
844
  (:args (x :scs (complex-double-double-reg) :target y)
846
 
         (nfp :scs (any-reg) :load-if (not (sc-is y complex-double-double-reg))))
 
845
         (fp :scs (any-reg) :load-if (not (sc-is y complex-double-double-reg))))
847
846
  (:results (y))
848
847
  (:note "complex double-double-float argument move")
849
848
  (:generator 2
883
882
      (complex-double-double-stack
884
883
       (let ((real-tn (complex-double-double-reg-real-hi-tn x)))
885
884
         (cond ((zerop (tn-offset real-tn))
886
 
                (inst fstd (ea-for-cddf-real-hi-stack y)))
 
885
                (inst fstd (ea-for-cddf-real-hi-stack y fp)))
887
886
               (t
888
887
                (inst fxch real-tn)
889
 
                (inst fstd (ea-for-cddf-real-hi-stack y))
 
888
                (inst fstd (ea-for-cddf-real-hi-stack y fp))
890
889
                (inst fxch real-tn))))
891
 
       (let ((real-tn (complex-double-double-reg-real-hi-tn x)))
 
890
       (let ((real-tn (complex-double-double-reg-real-lo-tn x)))
892
891
         (cond ((zerop (tn-offset real-tn))
893
 
                (inst fstd (ea-for-cddf-real-lo-stack y)))
 
892
                (inst fstd (ea-for-cddf-real-lo-stack y fp)))
894
893
               (t
895
894
                (inst fxch real-tn)
896
 
                (inst fstd (ea-for-cddf-real-lo-stack y))
 
895
                (inst fstd (ea-for-cddf-real-lo-stack y fp))
897
896
                (inst fxch real-tn))))
898
897
       (let ((imag-tn (complex-double-double-reg-imag-hi-tn x)))
899
898
         (inst fxch imag-tn)
900
 
         (inst fstd (ea-for-cddf-imag-hi-stack y))
 
899
         (inst fstd (ea-for-cddf-imag-hi-stack y fp))
901
900
         (inst fxch imag-tn))
902
901
       (let ((imag-tn (complex-double-double-reg-imag-lo-tn x)))
903
902
         (inst fxch imag-tn)
904
 
         (inst fstd (ea-for-cddf-imag-lo-stack y))
 
903
         (inst fstd (ea-for-cddf-imag-lo-stack y fp))
905
904
         (inst fxch imag-tn))))
906
905
    ))
907
906
 
919
918
 
920
919
;;;; Arithmetic VOPs:
921
920
 
 
921
 
 
922
;; Save the top-of-stack to memory and reload it.  This ensures that
 
923
;; the stack top has the desired precision.
 
924
(defmacro save-and-reload-tos (tmp)
 
925
  `(progn
 
926
     (inst fstp ,tmp)
 
927
     (inst fld ,tmp)))
 
928
 
922
929
;;; dtc: The floating point arithmetic vops.
923
930
;;; 
924
931
;;; Note: Although these can accept x and y on the stack or pointed to
962
969
                     :to :eval))
963
970
           (:temporary (:sc single-reg :offset fr0-offset
964
971
                            :from :eval :to :result) fr0)
 
972
           (:temporary (:sc single-stack) tmp)
965
973
           (:results (r :scs (single-reg single-stack)))
966
974
           (:arg-types single-float single-float)
967
975
           (:result-types single-float)
976
984
              ;; x, y, and r are the same register.
977
985
              ((and (sc-is x single-reg) (location= x r) (location= y r))
978
986
               (cond ((zerop (tn-offset r))
979
 
                      (inst ,fop fr0))
 
987
                      (inst ,fop fr0)
 
988
                      (save-and-reload-tos tmp))
980
989
                     (t
981
990
                      (inst fxch r)
982
991
                      (inst ,fop fr0)
 
992
                      (save-and-reload-tos tmp)
983
993
                      ;; XX the source register will not be valid.
984
994
                      (note-next-instruction vop :internal-error)
985
995
                      (inst fxch r))))
1009
1019
                            (inst fld (ea-for-sf-desc y)))))
1010
1020
                      ;; ST(i) = ST(i) op ST0
1011
1021
                      (inst ,fop-sti r)))
 
1022
               (unless (zerop (tn-offset r))
 
1023
                 (inst fxch r))
 
1024
               (save-and-reload-tos tmp)
 
1025
               (unless (zerop (tn-offset r))
 
1026
                 (inst fxch r))
1012
1027
               (when (policy node (or (= debug 3) (> safety speed)))
1013
 
                     (note-next-instruction vop :internal-error)
1014
 
                     (inst wait)))
 
1028
                 (note-next-instruction vop :internal-error)
 
1029
                 (inst wait)))
1015
1030
              ;; y and r are the same register.
1016
1031
              ((and (sc-is y single-reg) (location= y r))
1017
1032
               (cond ((zerop (tn-offset r))
1037
1052
                           (inst fld (ea-for-sf-desc x)))))
1038
1053
                      ;; ST(i) = ST(0) op ST(i)
1039
1054
                      (inst ,fopr-sti r)))
 
1055
 
 
1056
               (unless (zerop (tn-offset r))
 
1057
                 (inst fxch r))
 
1058
               (save-and-reload-tos tmp)
 
1059
               (unless (zerop (tn-offset r))
 
1060
                 (inst fxch r))
1040
1061
               (when (policy node (or (= debug 3) (> safety speed)))
1041
 
                     (note-next-instruction vop :internal-error)
1042
 
                     (inst wait)))
 
1062
                 (note-next-instruction vop :internal-error)
 
1063
                 (inst wait)))
1043
1064
              ;; The default case
1044
1065
              (t
1045
1066
               ;; Get the result to ST0.
1092
1113
               ;; Finally save the result
1093
1114
               (sc-case r
1094
1115
                 (single-reg
 
1116
                  (save-and-reload-tos tmp)
1095
1117
                  (cond ((zerop (tn-offset r))
1096
1118
                         (when (policy node (or (= debug 3) (> safety speed)))
1097
1119
                               (inst wait)))
1858
1880
                     (with-empty-tn@fp-top(y)
1859
1881
                       (note-this-location vop :internal-error)
1860
1882
                       (inst fild x))))))))
 
1883
  #+(or)
1861
1884
  (frob %single-float/signed %single-float single-reg single-float)
1862
1885
  (frob %double-float/signed %double-float double-reg double-float)
1863
1886
  #+long-float
1864
1887
  (frob %long-float/signed %long-float long-reg long-float))
1865
1888
 
 
1889
(define-vop (%single-float/signed)
 
1890
  (:args (x :scs (signed-stack signed-reg) :target temp))
 
1891
  (:temporary (:sc signed-stack) temp)
 
1892
  (:temporary (:sc single-stack) sf-temp)
 
1893
  (:results (y :scs (single-reg)))
 
1894
  (:arg-types signed-num)
 
1895
  (:result-types single-float)
 
1896
  (:policy :fast-safe)
 
1897
  (:note "inline float coercion")
 
1898
  (:translate %single-float)
 
1899
  (:vop-var vop)
 
1900
  (:save-p :compute-only)
 
1901
  (:generator 5
 
1902
    (sc-case x
 
1903
      (signed-reg
 
1904
       (inst mov temp x)
 
1905
       (with-empty-tn@fp-top(y)
 
1906
         (note-this-location vop :internal-error)
 
1907
         (inst fild temp)
 
1908
         (inst fstp sf-temp)
 
1909
         (inst fld sf-temp)))
 
1910
      (signed-stack
 
1911
       (with-empty-tn@fp-top(y)
 
1912
         (note-this-location vop :internal-error)
 
1913
         (inst fild x)
 
1914
         (inst fstp sf-temp)
 
1915
         (inst fld sf-temp))))))
 
1916
 
1866
1917
(macrolet ((frob (name translate to-sc to-type)
1867
1918
             `(define-vop (,name)
1868
1919
                (:args (x :scs (unsigned-reg)))
1881
1932
                   (note-this-location vop :internal-error)
1882
1933
                   (inst fildl (make-ea :dword :base esp-tn)))
1883
1934
                 (inst add esp-tn 8)))))
 
1935
  #+(or)
1884
1936
  (frob %single-float/unsigned %single-float single-reg single-float)
1885
1937
  (frob %double-float/unsigned %double-float double-reg double-float)
1886
1938
  #+long-float
1887
1939
  (frob %long-float/unsigned %long-float long-reg long-float))
1888
1940
 
 
1941
;;#+(or)
 
1942
(define-vop (%single-float/unsigned)
 
1943
  (:args (x :scs (unsigned-reg)))
 
1944
  (:results (y :scs (single-reg)))
 
1945
  (:arg-types unsigned-num)
 
1946
  (:result-types single-float)
 
1947
  (:policy :fast-safe)
 
1948
  (:note "inline float coercion")
 
1949
  (:translate %single-float)
 
1950
  (:vop-var vop)
 
1951
  (:save-p :compute-only)
 
1952
  (:generator 6
 
1953
    (inst push 0)
 
1954
    (inst push x)
 
1955
    (with-empty-tn@fp-top(y)
 
1956
      (note-this-location vop :internal-error)
 
1957
      (inst fildl (make-ea :dword :base esp-tn))
 
1958
      (inst fstp (make-ea :dword :base esp-tn))
 
1959
      (inst fld (make-ea :dword :base esp-tn)))
 
1960
    (inst add esp-tn 8)))
 
1961
 
1889
1962
;;; These should be no-ops but the compiler might want to move
1890
1963
;;; some things around
1891
1964
(macrolet ((frob (name translate from-sc from-type to-sc to-type)
1916
1989
                    (inst fst  y)
1917
1990
                    (inst fxch x))))))))
1918
1991
  
 
1992
  #+(or)
1919
1993
  (frob %single-float/double-float %single-float double-reg
1920
1994
        double-float single-reg single-float)
1921
1995
  #+long-float
1933
2007
  (frob %long-float/double-float %long-float double-reg double-float
1934
2008
        long-reg long-float))
1935
2009
 
 
2010
(define-vop (%single-float/double-float)
 
2011
  (:args (x :scs (double-reg) :target y))
 
2012
  (:results (y :scs (single-reg)))
 
2013
  (:arg-types double-float)
 
2014
  (:result-types single-float)
 
2015
  (:policy :fast-safe)
 
2016
  (:note "inline float coercion")
 
2017
  (:translate %single-float)
 
2018
  (:temporary (:sc single-stack) sf-temp)
 
2019
  (:vop-var vop)
 
2020
  (:save-p :compute-only)
 
2021
  (:generator 2
 
2022
    (note-this-location vop :internal-error)
 
2023
    (cond
 
2024
      ((zerop (tn-offset x))
 
2025
       (cond
 
2026
         ((zerop (tn-offset y))
 
2027
          ;; x is in ST0, y is also in ST0
 
2028
          (inst fstp sf-temp)
 
2029
          (inst fld sf-temp))
 
2030
         (t
 
2031
          ;; x is in ST0, y is in another reg. not ST0
 
2032
          ;; Save st0 (x) to memory, swap, reload, then swap back.
 
2033
          (inst fst sf-temp)
 
2034
          (inst fxch y)
 
2035
          (fp-pop)
 
2036
          (inst fld sf-temp)
 
2037
          (inst fxch y))))
 
2038
      ((zerop (tn-offset y))
 
2039
       ;; y is in ST0, x is in another reg. not ST0
 
2040
       ;; Swap, save x to memory, reload, swap back
 
2041
       (inst fxch x)
 
2042
       (inst fstp sf-temp)
 
2043
       (inst fld sf-temp)
 
2044
       (inst fxch x))
 
2045
      (t
 
2046
       ;; Neither x or y are in ST0, and they are not in
 
2047
       ;; the same reg.
1936
2048
 
 
2049
       ;; Get x to st0.  Store it away.  Swap back.  Get y to st0,
 
2050
       ;; load.  Swap back.
 
2051
       (inst fxch x)
 
2052
       (inst fst sf-temp)
 
2053
       (inst fxch x)
 
2054
       (inst fxch y)
 
2055
       (fp-pop)
 
2056
       (inst fld sf-temp)
 
2057
       (inst fxch y)))))
1937
2058
 
1938
2059
(macrolet ((frob (trans from-sc from-type round-p)
1939
2060
             `(define-vop (,(symbolicate trans "/" from-type))
2267
2388
 
2268
2389
;;;; Float mode hackery:
2269
2390
 
2270
 
(deftype float-modes () '(unsigned-byte 32)) ; really only 16
 
2391
(deftype float-modes () '(unsigned-byte 24))
2271
2392
(defknown floating-point-modes () float-modes (flushable))
2272
2393
(defknown ((setf floating-point-modes)) (float-modes)
2273
2394
  float-modes)
2274
2395
 
2275
 
(defconstant npx-env-size (* 7 vm:word-bytes))
2276
 
(defconstant npx-cw-offset 0)
2277
 
(defconstant npx-sw-offset 4)
2278
 
 
2279
2396
(define-vop (floating-point-modes)
2280
2397
  (:results (res :scs (unsigned-reg)))
2281
2398
  (:result-types unsigned-num)
2282
2399
  (:translate floating-point-modes)
2283
2400
  (:policy :fast-safe)
2284
 
  (:temporary (:sc unsigned-reg :offset eax-offset :target res
2285
 
                   :to :result) eax)
 
2401
  (:temporary (:sc unsigned-stack) cw-stack)
 
2402
  (:temporary (:sc unsigned-reg :offset eax-offset) sw-reg)
2286
2403
  (:generator 8
2287
 
   (inst sub esp-tn npx-env-size)       ; make space on stack
2288
 
   (inst wait)                          ; Catch any pending FPE exceptions
2289
 
   (inst fstenv (make-ea :dword :base esp-tn)) ; masks all exceptions
2290
 
   (inst fldenv (make-ea :dword :base esp-tn)) ; restore previous state
2291
 
   ;; Current status to high word
2292
 
   (inst mov eax (make-ea :dword :base esp-tn :disp (- npx-sw-offset 2)))
2293
 
   ;; Exception mask to low word
2294
 
   (inst mov ax-tn (make-ea :word :base esp-tn :disp npx-cw-offset))
2295
 
   (inst add esp-tn npx-env-size)       ; Pop stack
2296
 
   (inst xor eax #x3f)  ; Flip exception mask to trap enable bits
2297
 
   (move res eax)))
 
2404
   (inst fnstsw)
 
2405
   (inst fnstcw cw-stack)
 
2406
   (inst and sw-reg #xff)  ; mask exception flags
 
2407
   (inst shl sw-reg 16)
 
2408
   (inst byte #x66)  ; operand size prefix
 
2409
   (inst or sw-reg cw-stack)
 
2410
   (inst xor sw-reg #x3f)  ; invert exception mask
 
2411
   (move res sw-reg)))
2298
2412
 
2299
2413
(define-vop (set-floating-point-modes)
2300
2414
  (:args (new :scs (unsigned-reg) :to :result :target res))
2303
2417
  (:result-types unsigned-num)
2304
2418
  (:translate (setf floating-point-modes))
2305
2419
  (:policy :fast-safe)
2306
 
  (:temporary (:sc unsigned-reg :offset eax-offset
2307
 
                   :from :eval :to :result) eax)
2308
 
  (:generator 3
2309
 
   (inst sub esp-tn npx-env-size)       ; make space on stack
2310
 
   (inst wait)                          ; Catch any pending FPE exceptions
 
2420
  (:temporary (:sc unsigned-stack) cw-stack)
 
2421
  (:temporary (:sc byte-reg :offset al-offset) sw-reg)
 
2422
  (:temporary (:sc unsigned-reg :offset ecx-offset) old)
 
2423
  (:generator 6
 
2424
   (inst mov cw-stack new)
 
2425
   (inst xor cw-stack #x3f)  ; invert exception mask
 
2426
   (inst fnstsw)
 
2427
   (inst fldcw cw-stack)  ; always update the control word
 
2428
   (inst mov old new)
 
2429
   (inst shr old 16)
 
2430
   (inst cmp cl-tn sw-reg)  ; compare exception flags
 
2431
   (inst jmp :z DONE)  ; skip updating the status word
 
2432
   (inst sub esp-tn 28)
2311
2433
   (inst fstenv (make-ea :dword :base esp-tn))
2312
 
   (inst mov eax new)
2313
 
   (inst xor eax #x3f)      ; turn trap enable bits into exception mask
2314
 
   (inst mov (make-ea :word :base esp-tn :disp npx-cw-offset) ax-tn)
2315
 
   (inst shr eax 16)                    ; position status word
2316
 
   (inst mov (make-ea :word :base esp-tn :disp npx-sw-offset) ax-tn)
 
2434
   (inst mov (make-ea :byte :base esp-tn :disp 4) cl-tn)
2317
2435
   (inst fldenv (make-ea :dword :base esp-tn))
2318
 
   (inst add esp-tn npx-env-size)       ; Pop stack
 
2436
   (inst add esp-tn 28)
 
2437
   DONE
2319
2438
   (move res new)))
2320
2439
 
2321
2440
 
5110
5229
(define-vop (make-complex-double-double-float)
5111
5230
  (:translate complex)
5112
5231
  (:args (real :scs (double-double-reg) :target r
5113
 
               :load-if (not (location= real r)))
 
5232
               :load-if (not (location= real r))
 
5233
               )
5114
5234
         (imag :scs (double-double-reg) :to :save))
5115
5235
  (:arg-types double-double-float double-double-float)
5116
5236
  (:results (r :scs (complex-double-double-reg) :from (:argument 0)
5169
5289
                (inst fxch real)
5170
5290
                (inst fstd (ea-for-cddf-real-hi-stack r))
5171
5291
                (inst fxch real))))
5172
 
       (cond ((zerop (tn-offset real))
 
5292
       (let ((real-lo (double-double-reg-lo-tn real)))
 
5293
         (cond ((zerop (tn-offset real-lo))
5173
5294
                (inst fstd (ea-for-cddf-real-lo-stack r)))
5174
5295
               (t
5175
 
                (inst fxch real)
 
5296
                (inst fxch real-lo)
5176
5297
                (inst fstd (ea-for-cddf-real-lo-stack r))
5177
 
                (inst fxch real)))
5178
 
       (let ((imag-val (complex-double-double-reg-imag-hi-tn imag)))
 
5298
                (inst fxch real-lo))))
 
5299
       (let ((imag-val (double-double-reg-hi-tn imag)))
5179
5300
         (inst fxch imag-val)
5180
5301
         (inst fstd (ea-for-cddf-imag-hi-stack r))
5181
5302
         (inst fxch imag-val))
5182
 
       (let ((imag-val (complex-double-double-reg-imag-lo-tn imag)))
 
5303
       (let ((imag-val (double-double-reg-lo-tn imag)))
5183
5304
         (inst fxch imag-val)
5184
5305
         (inst fstd (ea-for-cddf-imag-lo-stack r))
5185
5306
         (inst fxch imag-val))))))
5186
5307
 
5187
5308
(define-vop (complex-double-double-float-value)
5188
 
  (:args (x :scs (complex-double-double-reg) :target r
 
5309
  (:args (x :scs (complex-double-double-reg descriptor-reg) :target r
5189
5310
            :load-if (not (sc-is x complex-double-double-stack))))
5190
5311
  (:arg-types complex-double-double-float)
5191
5312
  (:results (r :scs (double-double-reg)))
5224
5345
      (complex-double-double-stack
5225
5346
       (let ((r-hi (double-double-reg-hi-tn r)))
5226
5347
         (with-empty-tn@fp-top (r-hi)
5227
 
           (inst fld (ecase slot
 
5348
           (inst fldd (ecase slot
5228
5349
                       (:real (ea-for-cddf-real-hi-stack x))
5229
5350
                       (:imag (ea-for-cddf-imag-hi-stack x))))))
5230
5351
       (let ((r-lo (double-double-reg-lo-tn r)))
5231
5352
         (with-empty-tn@fp-top (r-lo)
5232
 
           (inst fld (ecase slot
 
5353
           (inst fldd (ecase slot
5233
5354
                       (:real (ea-for-cddf-real-lo-stack x))
5234
 
                       (:imag (ea-for-cddf-imag-lo-stack x))))))))))
 
5355
                       (:imag (ea-for-cddf-imag-lo-stack x)))))))
 
5356
      (descriptor-reg
 
5357
       (let ((r-hi (double-double-reg-hi-tn r)))
 
5358
         (with-empty-tn@fp-top (r-hi)
 
5359
           (inst fldd (ecase slot
 
5360
                       (:real (ea-for-cddf-real-hi-desc x))
 
5361
                       (:imag (ea-for-cddf-imag-hi-desc x))))))
 
5362
       (let ((r-lo (double-double-reg-lo-tn r)))
 
5363
         (with-empty-tn@fp-top (r-lo)
 
5364
           (inst fldd (ecase slot
 
5365
                       (:real (ea-for-cddf-real-lo-desc x))
 
5366
                       (:imag (ea-for-cddf-imag-lo-desc x))))))))))
5235
5367
 
5236
5368
(define-vop (realpart/complex-double-double-float complex-double-double-float-value)
5237
5369
  (:translate realpart)