Raymond Toy pushed to branch issue-431-fix-set-floating-point-modes at cmucl / cmucl
Commits:
-
e80d2fe4
by Raymond Toy at 2025-08-15T15:15:00-07:00
-
1dfdaba2
by Raymond Toy at 2025-08-15T19:17:20-07:00
-
3f9a71d1
by Raymond Toy at 2025-08-16T07:52:41-07:00
-
a1adbe86
by Raymond Toy at 2025-08-16T07:54:15-07:00
-
0ac12cb6
by Raymond Toy at 2025-08-16T07:54:43-07:00
7 changed files:
- src/bootfiles/21e/boot-2025-07.lisp
- src/code/float-trap.lisp
- src/compiler/x86/float-sse2.lisp
- src/compiler/x86/parms.lisp
- src/i18n/locale/cmucl-sse2.pot
- src/i18n/locale/cmucl-x86-vm.pot
- tests/float.lisp
Changes:
... | ... | @@ -2,18 +2,24 @@ |
2 | 2 | |
3 | 3 | (in-package :x86)
|
4 | 4 | |
5 | -(defconstant x87-exceptions-byte
|
|
6 | - (byte 6 0))
|
|
7 | -(defconstant x87-infinity-control-byte
|
|
8 | - (byte 1 (+ 12 16)))
|
|
9 | -(defconstant x87-rounding-control-byte
|
|
10 | - (byte 2 (+ 10 16)))
|
|
11 | -(defconstant x87-precision-control-byte
|
|
12 | - (byte 2 (+ 8 16)))
|
|
13 | -(defconstant x87-exceptions-mask-byte
|
|
14 | - (byte 6 16))
|
|
15 | -(defconstant x87-precision-control-alist
|
|
5 | +(defconstant x87-float-infinity-control-byte
|
|
6 | + (byte 1 (+ 12 16))
|
|
7 | + "The bit in the x87 FPU control word that controls the infinity mode.")
|
|
8 | +(defconstant x87-float-rounding-mode
|
|
9 | + (byte 2 (+ 10 16))
|
|
10 | + "The bits in the x87 FPU control word for the rounding mode.")
|
|
11 | +(defconstant x87-float-precision-control-byte
|
|
12 | + (byte 2 (+ 8 16))
|
|
13 | + "The bits in the x87 FPU contol word for the FP operation precision.")
|
|
14 | +(defconstant x87-float-traps-byte
|
|
15 | + (byte 6 16)
|
|
16 | + "The bits in the x87 FPU control word indicating the exceptions that
|
|
17 | + are enabled.")
|
|
18 | +(defconstant x87-float-precision-control-alist
|
|
16 | 19 | `((:24-bits . 0)
|
17 | 20 | (:reserved . 1)
|
18 | 21 | (:53-bits . 2)
|
19 | - (:64-bits . 3))) |
|
22 | + (:64-bits . 3))
|
|
23 | + "Alist for the x87 precison control. The car is the symbolic
|
|
24 | + precision and the cdr is the value for the precision control field.")
|
|
25 | + |
... | ... | @@ -139,16 +139,15 @@ |
139 | 139 | (new-exceptions (ldb float-exceptions-byte new-mode))
|
140 | 140 | (new-enables (ldb float-traps-byte new-mode))
|
141 | 141 | (x87-modes 0))
|
142 | - ;; From the new mode, update the x87 FPU mode with the same set
|
|
143 | - ;; of accrued exceptions, enabled exceptions, and rounding mode.
|
|
144 | - (setf x87-modes (dpb new-exceptions x87-exceptions-byte x87-modes))
|
|
145 | - (setf x87-modes (dpb new-enables x87-exceptions-mask-byte x87-modes))
|
|
146 | - (setf x87-modes (dpb rc x87-rounding-control-byte x87-modes))
|
|
142 | + ;; From the new mode, update the x87 FPU mode with the same set of accrued exceptions, enabled exceptions, and rounding mode.
|
|
143 | + (setf x87-modes (dpb new-exceptions float-exceptions-byte x87-modes))
|
|
144 | + (setf x87-modes (dpb new-enables x87-float-traps-byte x87-modes))
|
|
145 | + (setf x87-modes (dpb rc x87-float-rounding-mode x87-modes))
|
|
147 | 146 | |
148 | 147 | ;; Set precision to 64-bits (double-extended).
|
149 | 148 | (setf x87-modes
|
150 | - (dpb (cdr (assoc :64-bits x87-precision-control-alist))
|
|
151 | - x87-precision-control-byte
|
|
149 | + (dpb (cdr (assoc :64-bits x87-float-precision-control-alist))
|
|
150 | + x87-float-precision-control-byte
|
|
152 | 151 | x87-modes))
|
153 | 152 | |
154 | 153 | (setf (vm::sse2-floating-point-modes) (ldb (byte 16 0) new-mode))
|
... | ... | @@ -1379,21 +1379,26 @@ |
1379 | 1379 | ;; 10 double precision (53 bits)
|
1380 | 1380 | ;; 11 double extended precision (64 bits)
|
1381 | 1381 | |
1382 | -(defconstant x87-exceptions-byte
|
|
1383 | - (byte 6 0))
|
|
1384 | -(defconstant x87-infinity-control-byte
|
|
1385 | - (byte 1 (+ 12 16)))
|
|
1386 | -(defconstant x87-rounding-control-byte
|
|
1387 | - (byte 2 (+ 10 16)))
|
|
1388 | -(defconstant x87-precision-control-byte
|
|
1389 | - (byte 2 (+ 8 16)))
|
|
1390 | -(defconstant x87-exceptions-mask-byte
|
|
1391 | - (byte 6 16))
|
|
1392 | -(defconstant x87-precision-control-alist
|
|
1382 | +(defconstant x87-float-infinity-control-byte
|
|
1383 | + (byte 1 (+ 12 16))
|
|
1384 | + "The bit in the x87 FPU control word that controls the infinity mode.")
|
|
1385 | +(defconstant x87-float-rounding-mode
|
|
1386 | + (byte 2 (+ 10 16))
|
|
1387 | + "The bits in the x87 FPU control word for the rounding mode.")
|
|
1388 | +(defconstant x87-float-precision-control-byte
|
|
1389 | + (byte 2 (+ 8 16))
|
|
1390 | + "The bits in the x87 FPU contol word for the FP operation precision.")
|
|
1391 | +(defconstant x87-float-traps-byte
|
|
1392 | + (byte 6 16)
|
|
1393 | + "The bits in the x87 FPU control word indicating the exceptions that
|
|
1394 | + are enabled.")
|
|
1395 | +(defconstant x87-float-precision-control-alist
|
|
1393 | 1396 | `((:24-bits . 0)
|
1394 | 1397 | (:reserved . 1)
|
1395 | 1398 | (:53-bits . 2)
|
1396 | - (:64-bits . 3)))
|
|
1399 | + (:64-bits . 3))
|
|
1400 | + "Alist for the x87 precison control. The car is the symbolic
|
|
1401 | + precision and the cdr is the value for the precision control field.")
|
|
1397 | 1402 | |
1398 | 1403 | (defun print-fp-exceptions-enabled (enabled)
|
1399 | 1404 | (format t "Precision enable: ~30T~A~%" (ldb (byte 1 5) enabled))
|
... | ... | @@ -1416,7 +1421,7 @@ |
1416 | 1421 | ;; Note that Intel uses masks to disable the exception, but to match
|
1417 | 1422 | ;; the rest of cmucl, these bits are represented as enable bits.
|
1418 | 1423 | (format t "Flush-to-zero: ~30T~A~%" (ldb (byte 1 15) sse-mode))
|
1419 | - (let ((rc (ldb (byte 2 13) sse-mode)))
|
|
1424 | + (let ((rc (ldb float-rounding-mode sse-mode)))
|
|
1420 | 1425 | (format t "Rounding control: ~30T~A ~A~%"
|
1421 | 1426 | rc
|
1422 | 1427 | (car (rassoc rc rounding-mode-alist))))
|
... | ... | @@ -1437,17 +1442,17 @@ |
1437 | 1442 | (format t "SW: Stack fault: ~30T~A~%" (ldb (byte 1 6) x87-mode))
|
1438 | 1443 | (print-fp-current-exceptions (ldb float-exceptions-byte x87-mode))
|
1439 | 1444 | (format t "CW: Reserved: ~30T~A~%" (ldb (byte 2 (+ 13 16)) x87-mode))
|
1440 | - (format t "CW: Infinity control: ~30T~A~%" (ldb (byte 1 (+ 12 16)) x87-mode))
|
|
1441 | - (let ((rc (ldb (byte 2 (+ 10 16)) x87-mode)))
|
|
1445 | + (format t "CW: Infinity control: ~30T~A~%" (ldb x87-float-infinity-control-byte x87-mode))
|
|
1446 | + (let ((rc (ldb x87-float-rounding-mode x87-mode)))
|
|
1442 | 1447 | (format t "CW: Rounding control: ~30T~A ~A~%"
|
1443 | 1448 | rc
|
1444 | 1449 | (car (rassoc rc rounding-mode-alist))))
|
1445 | - (let ((pc (ldb (byte 2 (+ 8 16)) x87-mode)))
|
|
1450 | + (let ((pc (ldb x87-float-precision-control-byte x87-mode)))
|
|
1446 | 1451 | (format t "CW: Precision control: ~30T~A ~A~%"
|
1447 | 1452 | pc
|
1448 | - (car (rassoc pc x87-precision-control-alist))))
|
|
1453 | + (car (rassoc pc x87-float-precision-control-alist))))
|
|
1449 | 1454 | (format t "CW: Reserved: ~30T~A~%" (ldb (byte 2 (+ 6 16)) x87-mode))
|
1450 | - (print-fp-exceptions-enabled (ldb x87-exceptions-mask-byte x87-mode)))
|
|
1455 | + (print-fp-exceptions-enabled (ldb x87-float-traps-byte x87-mode)))
|
|
1451 | 1456 | |
1452 | 1457 | (defknown x87-floating-point-modes () float-modes (flushable))
|
1453 | 1458 | (defknown ((setf x87-floating-point-modes)) (float-modes)
|
... | ... | @@ -205,9 +205,15 @@ |
205 | 205 | ;; need to do it this way because the interface assumes the modes are
|
206 | 206 | ;; in the same order as the MXCSR register.
|
207 | 207 | (defconstant float-rounding-mode (byte 2 13))
|
208 | -(defconstant float-sticky-bits (byte 6 0))
|
|
209 | -(defconstant float-traps-byte (byte 6 7))
|
|
210 | -(defconstant float-exceptions-byte (byte 6 0))
|
|
208 | +(defconstant float-sticky-bits (byte 6 0)
|
|
209 | + "The bits in the FP mode that hold the accrued exceptions that have
|
|
210 | + occurred since the bits were reset.")
|
|
211 | +(defconstant float-traps-byte (byte 6 7)
|
|
212 | + "The bits in the FP mode that hold FP exceptions that are enabled.")
|
|
213 | +(defconstant float-exceptions-byte (byte 6 0)
|
|
214 | + "The bits in the FP mode that hold the current exception. However
|
|
215 | + for x86, there aren't separate bits for this, so we use the stick
|
|
216 | + bits from the accrued exceptions")
|
|
211 | 217 | |
212 | 218 | (progn
|
213 | 219 | ;; SSE2 has a flush-to-zero flag, which we use as the fast bit. Some
|
... | ... | @@ -86,6 +86,30 @@ msgstr "" |
86 | 86 | msgid "inline ftruncate"
|
87 | 87 | msgstr ""
|
88 | 88 | |
89 | +#: src/compiler/x86/float-sse2.lisp
|
|
90 | +msgid "The bit in the x87 FPU control word that controls the infinity mode."
|
|
91 | +msgstr ""
|
|
92 | + |
|
93 | +#: src/compiler/x86/float-sse2.lisp
|
|
94 | +msgid "The bits in the x87 FPU control word for the rounding mode."
|
|
95 | +msgstr ""
|
|
96 | + |
|
97 | +#: src/compiler/x86/float-sse2.lisp
|
|
98 | +msgid "The bits in the x87 FPU contol word for the FP operation precision."
|
|
99 | +msgstr ""
|
|
100 | + |
|
101 | +#: src/compiler/x86/float-sse2.lisp
|
|
102 | +msgid ""
|
|
103 | +"The bits in the x87 FPU control word indicating the exceptions that\n"
|
|
104 | +" are enabled."
|
|
105 | +msgstr ""
|
|
106 | + |
|
107 | +#: src/compiler/x86/float-sse2.lisp
|
|
108 | +msgid ""
|
|
109 | +"Alist for the x87 precison control. The car is the symbolic\n"
|
|
110 | +" precision and the cdr is the value for the precision control field."
|
|
111 | +msgstr ""
|
|
112 | + |
|
89 | 113 | #: src/compiler/x86/float-sse2.lisp
|
90 | 114 | msgid "Print SSE2 modes word in a readable fashion."
|
91 | 115 | msgstr ""
|
... | ... | @@ -136,6 +136,23 @@ msgstr "" |
136 | 136 | msgid "Maximum number of bits in a positive fixnum"
|
137 | 137 | msgstr ""
|
138 | 138 | |
139 | +#: src/compiler/x86/parms.lisp
|
|
140 | +msgid ""
|
|
141 | +"The bits in the FP mode that hold the accrued exceptions that have\n"
|
|
142 | +" occurred since the bits were reset."
|
|
143 | +msgstr ""
|
|
144 | + |
|
145 | +#: src/compiler/x86/parms.lisp
|
|
146 | +msgid "The bits in the FP mode that hold FP exceptions that are enabled."
|
|
147 | +msgstr ""
|
|
148 | + |
|
149 | +#: src/compiler/x86/parms.lisp
|
|
150 | +msgid ""
|
|
151 | +"The bits in the FP mode that hold the current exception. However\n"
|
|
152 | +" for x86, there aren't separate bits for this, so we use the stick\n"
|
|
153 | +" bits from the accrued exceptions"
|
|
154 | +msgstr ""
|
|
155 | + |
|
139 | 156 | #: src/compiler/x86/vm.lisp
|
140 | 157 | msgid "Redefining SC number ~D from ~S to ~S."
|
141 | 158 | msgstr ""
|
... | ... | @@ -343,3 +343,48 @@ |
343 | 343 | (assert-true (typep new-mode 'x86::float-modes))
|
344 | 344 | (assert-equal new-mode (setf (x86::x87-floating-point-modes) new-mode))))
|
345 | 345 | |
346 | +(define-test set-floating-point-modes
|
|
347 | + (let ((old-x87-modes (x86::x87-floating-point-modes))
|
|
348 | + (old-sse2-modes (x86::sse2-floating-point-modes)))
|
|
349 | + (unwind-protect
|
|
350 | + (progn
|
|
351 | + ;; Set some new traps and rounding mode
|
|
352 | + (ext:set-floating-point-modes :traps '(:underflow
|
|
353 | + :overflow
|
|
354 | + :invalid
|
|
355 | + :divide-by-zero)
|
|
356 | + :rounding-mode :zero)
|
|
357 | + (let* ((x87-modes (x86::x87-floating-point-modes))
|
|
358 | + (x87-exceptions-enabled (ldb x86::x87-float-traps-byte x87-modes))
|
|
359 | + (x87-rc (ldb x86::x87-float-rounding-mode x87-modes))
|
|
360 | + (sse2-modes (x86::sse2-floating-point-modes))
|
|
361 | + (sse2-exceptions-enabled (ldb x86::float-traps-byte sse2-modes))
|
|
362 | + (sse2-rc (ldb x86::float-rounding-mode sse2-modes)))
|
|
363 | + (x86::print-x87-fp-modes x87-modes)
|
|
364 | + ;; Verify that we set the enabled exceptions
|
|
365 | + ;; correctly. First for sse2, then for x87.
|
|
366 | + (assert-false (logbitp 5 sse2-exceptions-enabled)) ; precision
|
|
367 | + (assert-true (logbitp 4 sse2-exceptions-enabled)) ; underflow
|
|
368 | + (assert-true (logbitp 3 sse2-exceptions-enabled)) ; overflow
|
|
369 | + (assert-true (logbitp 2 sse2-exceptions-enabled)) ; divide-by-zero
|
|
370 | + (assert-false (logbitp 1 sse2-exceptions-enabled)) ; denormal
|
|
371 | + (assert-true (logbitp 0 sse2-exceptions-enabled)) ; invalid
|
|
372 | +
|
|
373 | + (assert-false (logbitp 5 x87-exceptions-enabled)) ; precision
|
|
374 | + (assert-true (logbitp 4 x87-exceptions-enabled)) ; underflow
|
|
375 | + (assert-true (logbitp 3 x87-exceptions-enabled)) ; overflow
|
|
376 | + (assert-true (logbitp 2 x87-exceptions-enabled)) ; divide-by-zero
|
|
377 | + (assert-false (logbitp 1 x87-exceptions-enabled)) ; denormal
|
|
378 | + (assert-true (logbitp 0 x87-exceptions-enabled)) ; invalid
|
|
379 | + |
|
380 | + ;; Verify the rounding mode is set to zero
|
|
381 | + (assert-eql :zero (car (rassoc sse2-rc x86::rounding-mode-alist)))
|
|
382 | + (assert-eql :zero (car (rassoc x87-rc x86::rounding-mode-alist)))
|
|
383 | + |
|
384 | + ;; Verify precision for x87
|
|
385 | + (assert-eql :64-bits
|
|
386 | + (car (rassoc (ldb x86::x87-float-precision-control-byte x87-modes)
|
|
387 | + x86::x87-float-precision-control-alist)))))
|
|
388 | + |
|
389 | + (setf (x86::x87-floating-point-modes) old-x87-modes)
|
|
390 | + (setf (x86::sse2-floating-point-modes) old-sse2-modes)))) |