1 ! (c)Joe Groff bsd license
2 USING: alien.syntax assocs biassocs combinators continuations
3 generalizations kernel literals locals math math.bitwise
16 +fp-invalid-operation+
28 UNION: fp-rounding-mode
38 UNION: fp-denormal-mode
44 ! These functions are provided in the VM; see cpu-*.S
45 FUNCTION: uint get_fp_control_register ( ) ;
46 FUNCTION: void set_fp_control_register ( uint reg ) ;
48 HOOK: exception-flag-bits cpu ( -- bits )
49 HOOK: exception-flag>bit cpu ( -- assoc )
50 HOOK: fp-traps-bits cpu ( -- bits )
51 HOOK: fp-traps>bit cpu ( -- assoc )
52 HOOK: >fp-traps cpu ( mask -- enable )
53 HOOK: rounding-mode-bits cpu ( -- bits )
54 HOOK: rounding-mode>bit cpu ( -- assoc )
55 HOOK: denormal-mode-bits cpu ( -- bits )
57 M: x86 exception-flag-bits HEX: 3f ;
58 M: x86 exception-flag>bit
60 { +fp-invalid-operation+ HEX: 01 }
61 { +fp-overflow+ HEX: 08 }
62 { +fp-underflow+ HEX: 10 }
63 { +fp-zero-divide+ HEX: 04 }
64 { +fp-inexact+ HEX: 20 }
67 M: x86 fp-traps-bits HEX: 1f80 ;
70 { +fp-invalid-operation+ HEX: 0080 }
71 { +fp-overflow+ HEX: 0400 }
72 { +fp-underflow+ HEX: 0800 }
73 { +fp-zero-divide+ HEX: 0200 }
74 { +fp-inexact+ HEX: 1000 }
77 M: x86 >fp-traps bitnot ;
79 M: x86 rounding-mode-bits HEX: 6000 ;
80 M: x86 rounding-mode>bit
82 { +round-nearest+ HEX: 0000 }
83 { +round-down+ HEX: 2000 }
84 { +round-up+ HEX: 4000 }
85 { +round-zero+ HEX: 6000 }
88 M: x86 denormal-mode-bits HEX: 8040 ;
90 M: ppc exception-flag-bits HEX: 3e00,0000 ;
91 M: ppc exception-flag>bit
93 { +fp-invalid-operation+ HEX: 2000,0000 }
94 { +fp-overflow+ HEX: 1000,0000 }
95 { +fp-underflow+ HEX: 0800,0000 }
96 { +fp-zero-divide+ HEX: 0400,0000 }
97 { +fp-inexact+ HEX: 0200,0000 }
100 M: ppc fp-traps-bits HEX: f80 ;
103 { +fp-invalid-operation+ HEX: 8000 }
104 { +fp-overflow+ HEX: 4000 }
105 { +fp-underflow+ HEX: 2000 }
106 { +fp-zero-divide+ HEX: 1000 }
107 { +fp-inexact+ HEX: 0800 }
112 M: ppc rounding-mode-bits HEX: 3 ;
113 M: ppc rounding-mode>bit
115 { +round-nearest+ HEX: 0 }
116 { +round-zero+ HEX: 1 }
117 { +round-up+ HEX: 2 }
118 { +round-down+ HEX: 3 }
121 M: ppc denormal-mode-bits HEX: 4 ;
123 :: mask> ( bits assoc -- symbols )
124 assoc [| k v | bits v mask zero? not ] assoc-filter keys ;
125 : >mask ( symbols assoc -- bits )
128 [ [ at ] curry [ bitor ] map-reduce ] if ;
130 : remask ( x new-bits mask-bits -- x' )
131 [ unmask ] [ mask ] bi-curry bi* bitor ; inline
133 : (get-exception-flags) ( register -- exceptions )
134 exception-flag>bit mask> ; inline
135 : (set-exception-flags) ( register exceptions -- register' )
136 exception-flag>bit >mask exception-flag-bits remask ; inline
138 : (get-fp-traps) ( register -- exceptions )
139 >fp-traps fp-traps>bit mask> ; inline
140 : (set-fp-traps) ( register exceptions -- register' )
141 fp-traps>bit >mask >fp-traps fp-traps-bits remask ; inline
143 : (get-rounding-mode) ( register -- mode )
144 rounding-mode-bits mask rounding-mode>bit value-at ; inline
145 : (set-rounding-mode) ( register mode -- register' )
146 rounding-mode>bit at rounding-mode-bits remask ; inline
148 : (get-denormal-mode) ( register -- mode )
149 denormal-mode-bits mask zero? +denormal-keep+ +denormal-flush+ ? ; inline
150 : (set-denormal-mode) ( register ? -- register' )
152 { +denormal-keep+ [ denormal-mode-bits unmask ] }
153 { +denormal-flush+ [ denormal-mode-bits bitor ] }
156 : change-control-register ( quot -- )
157 get_fp_control_register swap call set_fp_control_register ; inline
159 : set-fp-traps ( exceptions -- ) [ (set-fp-traps) ] curry change-control-register ;
160 : set-rounding-mode ( exceptions -- ) [ (set-rounding-mode) ] curry change-control-register ;
161 : set-denormal-mode ( mode -- ) [ (set-denormal-mode) ] curry change-control-register ;
163 : get-fp-env ( -- exception-flags fp-traps rounding-mode denormals? )
164 get_fp_control_register {
165 [ (get-exception-flags) ]
167 [ (get-rounding-mode) ]
168 [ (get-denormal-mode) ]
171 : set-fp-env ( exception-flags fp-traps rounding-mode denormal-mode -- )
174 [ [ (set-exception-flags) ] when* ]
175 [ [ (set-fp-traps) ] when* ]
176 [ [ (set-rounding-mode) ] when* ]
177 [ [ (set-denormal-mode) ] when* ]
179 ] 4 ncurry change-control-register ;
183 : fp-exception-flags ( -- exceptions ) get_fp_control_register (get-exception-flags) ;
184 : set-fp-exception-flags ( exceptions -- ) [ (set-exception-flags) ] curry change-control-register ;
185 : clear-fp-exception-flags ( -- ) { } set-fp-exception-flags ; inline
187 : collect-fp-exceptions ( quot -- exceptions )
188 clear-fp-exception-flags call fp-exception-flags ; inline
190 : denormal-mode ( -- mode ) get_fp_control_register (get-denormal-mode) ;
192 :: with-denormal-mode ( mode quot -- )
193 denormal-mode :> orig
194 mode set-denormal-mode
195 quot [ orig set-denormal-mode ] [ ] cleanup ; inline
197 : rounding-mode ( -- mode ) get_fp_control_register (get-rounding-mode) ;
199 :: with-rounding-mode ( mode quot -- )
200 rounding-mode :> orig
201 mode set-rounding-mode
202 quot [ orig set-rounding-mode ] [ ] cleanup ; inline
204 : fp-traps ( -- exceptions ) get_fp_control_register (get-fp-traps) ;
206 :: with-fp-traps ( exceptions quot -- )
208 exceptions set-fp-traps
209 quot [ orig set-fp-traps ] [ ] cleanup ; inline
211 : without-fp-traps ( quot -- )
212 { } swap with-fp-traps ; inline