| author | |
| committer | |
| log | 225910f9341fbc725ff5e0d2c653e29bc2f21cb8 |
| tree | eac47d40ae555398c46e4ccdff9cace12eeabd3b |
| parent | 63ee6e662582ee75ac804eb1a4dbdf4457b8f2d0 |
| parent | a0a71709bc2104c708f045fbb42c6247aff136ac |
| signature |
Add f8025 files changed, 953 insertions(+), 44 deletions(-)
CMakeLists.txt+31| ... | @@ -142,15 +142,19 @@ include_directories(${CLANG_INCLUDE_DIRS}) | ... | @@ -142,15 +142,19 @@ include_directories(${CLANG_INCLUDE_DIRS}) |
| 142 | # No patches have been applied to SoftFloat-3e | 142 | # No patches have been applied to SoftFloat-3e |
| 143 | set(EMBEDDED_SOFTFLOAT_SOURCES | 143 | set(EMBEDDED_SOFTFLOAT_SOURCES |
| 144 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/f128M_isSignalingNaN.c" | 144 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/f128M_isSignalingNaN.c" |
| 145 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/extF80M_isSignalingNaN.c" | ||
| 145 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_commonNaNToF128M.c" | 146 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_commonNaNToF128M.c" |
| 147 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_commonNaNToExtF80M.c" | ||
| 146 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_commonNaNToF16UI.c" | 148 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_commonNaNToF16UI.c" |
| 147 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_commonNaNToF32UI.c" | 149 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_commonNaNToF32UI.c" |
| 148 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_commonNaNToF64UI.c" | 150 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_commonNaNToF64UI.c" |
| 149 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_f128MToCommonNaN.c" | 151 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_f128MToCommonNaN.c" |
| 152 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_extF80MToCommonNaN.c" | ||
| 150 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_f16UIToCommonNaN.c" | 153 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_f16UIToCommonNaN.c" |
| 151 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_f32UIToCommonNaN.c" | 154 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_f32UIToCommonNaN.c" |
| 152 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_f64UIToCommonNaN.c" | 155 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_f64UIToCommonNaN.c" |
| 153 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_propagateNaNF128M.c" | 156 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_propagateNaNF128M.c" |
| 157 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_propagateNaNExtF80M.c" | ||
| 154 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_propagateNaNF16UI.c" | 158 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_propagateNaNF16UI.c" |
| 155 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/softfloat_raiseFlags.c" | 159 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/softfloat_raiseFlags.c" |
| 156 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_add.c" | 160 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_add.c" |
| ... | @@ -170,6 +174,7 @@ set(EMBEDDED_SOFTFLOAT_SOURCES | ... | @@ -170,6 +174,7 @@ set(EMBEDDED_SOFTFLOAT_SOURCES |
| 170 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_f16.c" | 174 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_f16.c" |
| 171 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_f32.c" | 175 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_f32.c" |
| 172 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_f64.c" | 176 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_f64.c" |
| 177 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_extF80M.c" | ||
| 173 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_i32.c" | 178 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_i32.c" |
| 174 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_i32_r_minMag.c" | 179 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_i32_r_minMag.c" |
| 175 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_i64.c" | 180 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_i64.c" |
| ... | @@ -178,6 +183,20 @@ set(EMBEDDED_SOFTFLOAT_SOURCES | ... | @@ -178,6 +183,20 @@ set(EMBEDDED_SOFTFLOAT_SOURCES |
| 178 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_ui32_r_minMag.c" | 183 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_ui32_r_minMag.c" |
| 179 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_ui64.c" | 184 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_ui64.c" |
| 180 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_ui64_r_minMag.c" | 185 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_ui64_r_minMag.c" |
| 186 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_add.c" | ||
| 187 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_div.c" | ||
| 188 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_eq.c" | ||
| 189 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_le.c" | ||
| 190 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_lt.c" | ||
| 191 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_mul.c" | ||
| 192 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_rem.c" | ||
| 193 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_roundToInt.c" | ||
| 194 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_sqrt.c" | ||
| 195 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_sub.c" | ||
| 196 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_to_f16.c" | ||
| 197 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_to_f32.c" | ||
| 198 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_to_f64.c" | ||
| 199 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_to_f128M.c" | ||
| 181 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_add.c" | 200 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_add.c" |
| 182 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_div.c" | 201 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_div.c" |
| 183 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_eq.c" | 202 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_eq.c" |
| ... | @@ -188,9 +207,12 @@ set(EMBEDDED_SOFTFLOAT_SOURCES | ... | @@ -188,9 +207,12 @@ set(EMBEDDED_SOFTFLOAT_SOURCES |
| 188 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_roundToInt.c" | 207 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_roundToInt.c" |
| 189 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_sqrt.c" | 208 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_sqrt.c" |
| 190 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_sub.c" | 209 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_sub.c" |
| 210 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_to_extF80M.c" | ||
| 191 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_to_f128M.c" | 211 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_to_f128M.c" |
| 192 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_to_f64.c" | 212 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_to_f64.c" |
| 213 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f32_to_extF80M.c" | ||
| 193 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f32_to_f128M.c" | 214 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f32_to_f128M.c" |
| 215 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f64_to_extF80M.c" | ||
| 194 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f64_to_f128M.c" | 216 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f64_to_f128M.c" |
| 195 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f64_to_f16.c" | 217 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f64_to_f16.c" |
| 196 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/i32_to_f128M.c" | 218 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/i32_to_f128M.c" |
| ... | @@ -198,6 +220,7 @@ set(EMBEDDED_SOFTFLOAT_SOURCES | ... | @@ -198,6 +220,7 @@ set(EMBEDDED_SOFTFLOAT_SOURCES |
| 198 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_addCarryM.c" | 220 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_addCarryM.c" |
| 199 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_addComplCarryM.c" | 221 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_addComplCarryM.c" |
| 200 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_addF128M.c" | 222 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_addF128M.c" |
| 223 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_addExtF80M.c" | ||
| 201 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_addM.c" | 224 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_addM.c" |
| 202 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_addMagsF16.c" | 225 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_addMagsF16.c" |
| 203 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_addMagsF32.c" | 226 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_addMagsF32.c" |
| ... | @@ -208,12 +231,14 @@ set(EMBEDDED_SOFTFLOAT_SOURCES | ... | @@ -208,12 +231,14 @@ set(EMBEDDED_SOFTFLOAT_SOURCES |
| 208 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_approxRecip_1Ks.c" | 231 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_approxRecip_1Ks.c" |
| 209 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_compare128M.c" | 232 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_compare128M.c" |
| 210 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_compare96M.c" | 233 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_compare96M.c" |
| 234 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_compareNonnormExtF80M.c" | ||
| 211 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_countLeadingZeros16.c" | 235 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_countLeadingZeros16.c" |
| 212 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_countLeadingZeros32.c" | 236 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_countLeadingZeros32.c" |
| 213 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_countLeadingZeros64.c" | 237 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_countLeadingZeros64.c" |
| 214 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_countLeadingZeros8.c" | 238 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_countLeadingZeros8.c" |
| 215 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_eq128.c" | 239 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_eq128.c" |
| 216 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_invalidF128M.c" | 240 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_invalidF128M.c" |
| 241 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_invalidExtF80M.c" | ||
| 217 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_isNaNF128M.c" | 242 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_isNaNF128M.c" |
| 218 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_le128.c" | 243 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_le128.c" |
| 219 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_lt128.c" | 244 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_lt128.c" |
| ... | @@ -224,7 +249,9 @@ set(EMBEDDED_SOFTFLOAT_SOURCES | ... | @@ -224,7 +249,9 @@ set(EMBEDDED_SOFTFLOAT_SOURCES |
| 224 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_mulAddF32.c" | 249 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_mulAddF32.c" |
| 225 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_mulAddF64.c" | 250 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_mulAddF64.c" |
| 226 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_negXM.c" | 251 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_negXM.c" |
| 252 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_normExtF80SigM.c" | ||
| 227 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_normRoundPackMToF128M.c" | 253 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_normRoundPackMToF128M.c" |
| 254 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_normRoundPackMToExtF80M.c" | ||
| 228 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_normRoundPackToF16.c" | 255 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_normRoundPackToF16.c" |
| 229 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_normRoundPackToF32.c" | 256 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_normRoundPackToF32.c" |
| 230 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_normRoundPackToF64.c" | 257 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_normRoundPackToF64.c" |
| ... | @@ -235,6 +262,7 @@ set(EMBEDDED_SOFTFLOAT_SOURCES | ... | @@ -235,6 +262,7 @@ set(EMBEDDED_SOFTFLOAT_SOURCES |
| 235 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_remStepMBy32.c" | 262 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_remStepMBy32.c" |
| 236 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_roundMToI64.c" | 263 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_roundMToI64.c" |
| 237 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_roundMToUI64.c" | 264 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_roundMToUI64.c" |
| 265 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_roundPackMToExtF80M.c" | ||
| 238 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_roundPackMToF128M.c" | 266 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_roundPackMToF128M.c" |
| 239 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_roundPackToF16.c" | 267 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_roundPackToF16.c" |
| 240 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_roundPackToF32.c" | 268 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_roundPackToF32.c" |
| ... | @@ -263,11 +291,14 @@ set(EMBEDDED_SOFTFLOAT_SOURCES | ... | @@ -263,11 +291,14 @@ set(EMBEDDED_SOFTFLOAT_SOURCES |
| 263 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_subMagsF32.c" | 291 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_subMagsF32.c" |
| 264 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_subMagsF64.c" | 292 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_subMagsF64.c" |
| 265 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_tryPropagateNaNF128M.c" | 293 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_tryPropagateNaNF128M.c" |
| 294 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_tryPropagateNaNExtF80M.c" | ||
| 266 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_mulAdd.c" | 295 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_mulAdd.c" |
| 267 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_mulAdd.c" | 296 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_mulAdd.c" |
| 268 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/softfloat_state.c" | 297 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/softfloat_state.c" |
| 269 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/ui32_to_f128M.c" | 298 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/ui32_to_f128M.c" |
| 270 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/ui64_to_f128M.c" | 299 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/ui64_to_f128M.c" |
| 300 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/ui32_to_extF80M.c" | ||
| 301 | "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/ui64_to_extF80M.c" | ||
| 271 | ) | 302 | ) |
| 272 | add_library(embedded_softfloat STATIC ${EMBEDDED_SOFTFLOAT_SOURCES}) | 303 | add_library(embedded_softfloat STATIC ${EMBEDDED_SOFTFLOAT_SOURCES}) |
| 273 | if(MSVC) | 304 | if(MSVC) |
doc/langref.html.in+6| ... | @@ -737,6 +737,11 @@ pub fn main() void { | ... | @@ -737,6 +737,11 @@ pub fn main() void { |
| 737 | <td><code class="c">double</code></td> | 737 | <td><code class="c">double</code></td> |
| 738 | <td>64-bit floating point (52-bit mantissa) IEEE-754-2008 binary64</td> | 738 | <td>64-bit floating point (52-bit mantissa) IEEE-754-2008 binary64</td> |
| 739 | </tr> | 739 | </tr> |
| 740 | <tr> | ||
| 741 | <th scope="row">{#syntax#}f80{#endsyntax#}</th> | ||
| 742 | <td><code class="c">double</code></td> | ||
| 743 | <td>64-bit floating point (64-bit mantissa) IEEE-754-2008 80-bit extended precision</td> | ||
| 744 | </tr> | ||
| 740 | <tr> | 745 | <tr> |
| 741 | <th scope="row">{#syntax#}f128{#endsyntax#}</th> | 746 | <th scope="row">{#syntax#}f128{#endsyntax#}</th> |
| 742 | <td><code class="c">_Float128</code></td> | 747 | <td><code class="c">_Float128</code></td> |
| ... | @@ -1500,6 +1505,7 @@ fn divide(a: i32, b: i32) i32 { | ... | @@ -1500,6 +1505,7 @@ fn divide(a: i32, b: i32) i32 { |
| 1500 | <li>{#syntax#}f16{#endsyntax#} - IEEE-754-2008 binary16</li> | 1505 | <li>{#syntax#}f16{#endsyntax#} - IEEE-754-2008 binary16</li> |
| 1501 | <li>{#syntax#}f32{#endsyntax#} - IEEE-754-2008 binary32</li> | 1506 | <li>{#syntax#}f32{#endsyntax#} - IEEE-754-2008 binary32</li> |
| 1502 | <li>{#syntax#}f64{#endsyntax#} - IEEE-754-2008 binary64</li> | 1507 | <li>{#syntax#}f64{#endsyntax#} - IEEE-754-2008 binary64</li> |
| 1508 | <li>{#syntax#}f80{#endsyntax#} - IEEE-754-2008 80-bit extended precision</li> | ||
| 1503 | <li>{#syntax#}f128{#endsyntax#} - IEEE-754-2008 binary128</li> | 1509 | <li>{#syntax#}f128{#endsyntax#} - IEEE-754-2008 binary128</li> |
| 1504 | <li>{#syntax#}c_longdouble{#endsyntax#} - matches <code class="c">long double</code> for the target C ABI</li> | 1510 | <li>{#syntax#}c_longdouble{#endsyntax#} - matches <code class="c">long double</code> for the target C ABI</li> |
| 1505 | </ul> | 1511 | </ul> |
lib/std/math.zig+18| ... | @@ -43,7 +43,21 @@ pub const f128_max = @bitCast(f128, @as(u128, 0x7FFEFFFFFFFFFFFFFFFFFFFFFFFFFFFF | ... | @@ -43,7 +43,21 @@ pub const f128_max = @bitCast(f128, @as(u128, 0x7FFEFFFFFFFFFFFFFFFFFFFFFFFFFFFF |
| 43 | pub const f128_epsilon = @bitCast(f128, @as(u128, 0x3F8F0000000000000000000000000000)); | 43 | pub const f128_epsilon = @bitCast(f128, @as(u128, 0x3F8F0000000000000000000000000000)); |
| 44 | pub const f128_toint = 1.0 / f128_epsilon; | 44 | pub const f128_toint = 1.0 / f128_epsilon; |
| 45 | 45 | ||
| 46 | const F80Repr = if (@import("builtin").cpu.arch.endian() == .Little) extern struct { | ||
| 47 | fraction: u64, | ||
| 48 | exp: u16, | ||
| 49 | } else extern struct { | ||
| 50 | exp: u16, | ||
| 51 | fraction: u64, | ||
| 52 | }; | ||
| 53 | |||
| 46 | // float.h details | 54 | // float.h details |
| 55 | pub const f80_true_min = @ptrCast(*const f80, &F80Repr{ .fraction = 1, .exp = 0 }).*; | ||
| 56 | pub const f80_min = @ptrCast(*const f80, &F80Repr{ .fraction = 0x8000000000000000, .exp = 1 }).*; | ||
| 57 | pub const f80_max = @ptrCast(*const f80, &F80Repr{ .fraction = 0xFFFFFFFFFFFFFFFF, .exp = 0x7FFE }).*; | ||
| 58 | pub const f80_epsilon = @ptrCast(*const f80, &F80Repr{ .fraction = 0x8000000000000000, .exp = 0x3FC0 }).*; | ||
| 59 | pub const f80_toint = 1.0 / f80_epsilon; | ||
| 60 | |||
| 47 | pub const f64_true_min = 4.94065645841246544177e-324; | 61 | pub const f64_true_min = 4.94065645841246544177e-324; |
| 48 | pub const f64_min = 2.2250738585072014e-308; | 62 | pub const f64_min = 2.2250738585072014e-308; |
| 49 | pub const f64_max = 1.79769313486231570815e+308; | 63 | pub const f64_max = 1.79769313486231570815e+308; |
| ... | @@ -91,6 +105,10 @@ pub const qnan_f64 = @bitCast(f64, qnan_u64); | ... | @@ -91,6 +105,10 @@ pub const qnan_f64 = @bitCast(f64, qnan_u64); |
| 91 | pub const inf_u64 = @as(u64, 0x7FF << 52); | 105 | pub const inf_u64 = @as(u64, 0x7FF << 52); |
| 92 | pub const inf_f64 = @bitCast(f64, inf_u64); | 106 | pub const inf_f64 = @bitCast(f64, inf_u64); |
| 93 | 107 | ||
| 108 | pub const inf_f80 = @ptrCast(*const f80, &F80Repr{ .fraction = 0x8000000000000000, .exp = 0x7fff }).*; | ||
| 109 | pub const nan_f80 = @ptrCast(*const f80, &F80Repr{ .fraction = 0xA000000000000000, .exp = 0x7fff }).*; | ||
| 110 | pub const qnan_f80 = @ptrCast(*const f80, &F80Repr{ .fraction = 0xC000000000000000, .exp = 0x7fff }).*; | ||
| 111 | |||
| 94 | pub const nan_u128 = @as(u128, 0x7fff0000000000000000000000000001); | 112 | pub const nan_u128 = @as(u128, 0x7fff0000000000000000000000000001); |
| 95 | pub const nan_f128 = @bitCast(f128, nan_u128); | 113 | pub const nan_f128 = @bitCast(f128, nan_u128); |
| 96 | 114 |
lib/std/math/epsilon.zig+1| ... | @@ -8,6 +8,7 @@ pub fn epsilon(comptime T: type) T { | ... | @@ -8,6 +8,7 @@ pub fn epsilon(comptime T: type) T { |
| 8 | f16 => math.f16_epsilon, | 8 | f16 => math.f16_epsilon, |
| 9 | f32 => math.f32_epsilon, | 9 | f32 => math.f32_epsilon, |
| 10 | f64 => math.f64_epsilon, | 10 | f64 => math.f64_epsilon, |
| 11 | f80 => math.f80_epsilon, | ||
| 11 | f128 => math.f128_epsilon, | 12 | f128 => math.f128_epsilon, |
| 12 | else => @compileError("epsilon not implemented for " ++ @typeName(T)), | 13 | else => @compileError("epsilon not implemented for " ++ @typeName(T)), |
| 13 | }; | 14 | }; |
lib/std/math/inf.zig+1| ... | @@ -7,6 +7,7 @@ pub fn inf(comptime T: type) T { | ... | @@ -7,6 +7,7 @@ pub fn inf(comptime T: type) T { |
| 7 | f16 => math.inf_f16, | 7 | f16 => math.inf_f16, |
| 8 | f32 => math.inf_f32, | 8 | f32 => math.inf_f32, |
| 9 | f64 => math.inf_f64, | 9 | f64 => math.inf_f64, |
| 10 | f80 => math.inf_f80, | ||
| 10 | f128 => math.inf_f128, | 11 | f128 => math.inf_f128, |
| 11 | else => @compileError("inf not implemented for " ++ @typeName(T)), | 12 | else => @compileError("inf not implemented for " ++ @typeName(T)), |
| 12 | }; | 13 | }; |
lib/std/math/nan.zig+3| ... | @@ -6,6 +6,7 @@ pub fn nan(comptime T: type) T { | ... | @@ -6,6 +6,7 @@ pub fn nan(comptime T: type) T { |
| 6 | f16 => math.nan_f16, | 6 | f16 => math.nan_f16, |
| 7 | f32 => math.nan_f32, | 7 | f32 => math.nan_f32, |
| 8 | f64 => math.nan_f64, | 8 | f64 => math.nan_f64, |
| 9 | f80 => math.nan_f80, | ||
| 9 | f128 => math.nan_f128, | 10 | f128 => math.nan_f128, |
| 10 | else => @compileError("nan not implemented for " ++ @typeName(T)), | 11 | else => @compileError("nan not implemented for " ++ @typeName(T)), |
| 11 | }; | 12 | }; |
| ... | @@ -19,6 +20,8 @@ pub fn snan(comptime T: type) T { | ... | @@ -19,6 +20,8 @@ pub fn snan(comptime T: type) T { |
| 19 | f16 => @bitCast(f16, math.nan_u16), | 20 | f16 => @bitCast(f16, math.nan_u16), |
| 20 | f32 => @bitCast(f32, math.nan_u32), | 21 | f32 => @bitCast(f32, math.nan_u32), |
| 21 | f64 => @bitCast(f64, math.nan_u64), | 22 | f64 => @bitCast(f64, math.nan_u64), |
| 23 | f80 => @bitCast(f80, math.nan_u80), | ||
| 24 | f128 => @bitCast(f128, math.nan_u128), | ||
| 22 | else => @compileError("snan not implemented for " ++ @typeName(T)), | 25 | else => @compileError("snan not implemented for " ++ @typeName(T)), |
| 23 | }; | 26 | }; |
| 24 | } | 27 | } |
src/AstGen.zig+2| ... | @@ -7723,6 +7723,7 @@ const primitives = std.ComptimeStringMap(Zir.Inst.Ref, .{ | ... | @@ -7723,6 +7723,7 @@ const primitives = std.ComptimeStringMap(Zir.Inst.Ref, .{ |
| 7723 | .{ "f16", .f16_type }, | 7723 | .{ "f16", .f16_type }, |
| 7724 | .{ "f32", .f32_type }, | 7724 | .{ "f32", .f32_type }, |
| 7725 | .{ "f64", .f64_type }, | 7725 | .{ "f64", .f64_type }, |
| 7726 | .{ "f80", .f80_type }, | ||
| 7726 | .{ "false", .bool_false }, | 7727 | .{ "false", .bool_false }, |
| 7727 | .{ "i16", .i16_type }, | 7728 | .{ "i16", .i16_type }, |
| 7728 | .{ "i32", .i32_type }, | 7729 | .{ "i32", .i32_type }, |
| ... | @@ -8732,6 +8733,7 @@ fn rvalue( | ... | @@ -8732,6 +8733,7 @@ fn rvalue( |
| 8732 | as_ty | @enumToInt(Zir.Inst.Ref.f16_type), | 8733 | as_ty | @enumToInt(Zir.Inst.Ref.f16_type), |
| 8733 | as_ty | @enumToInt(Zir.Inst.Ref.f32_type), | 8734 | as_ty | @enumToInt(Zir.Inst.Ref.f32_type), |
| 8734 | as_ty | @enumToInt(Zir.Inst.Ref.f64_type), | 8735 | as_ty | @enumToInt(Zir.Inst.Ref.f64_type), |
| 8736 | as_ty | @enumToInt(Zir.Inst.Ref.f80_type), | ||
| 8735 | as_ty | @enumToInt(Zir.Inst.Ref.f128_type), | 8737 | as_ty | @enumToInt(Zir.Inst.Ref.f128_type), |
| 8736 | as_ty | @enumToInt(Zir.Inst.Ref.anyopaque_type), | 8738 | as_ty | @enumToInt(Zir.Inst.Ref.anyopaque_type), |
| 8737 | as_ty | @enumToInt(Zir.Inst.Ref.bool_type), | 8739 | as_ty | @enumToInt(Zir.Inst.Ref.bool_type), |
src/Sema.zig+3| ... | @@ -16950,6 +16950,7 @@ pub fn typeHasOnePossibleValue( | ... | @@ -16950,6 +16950,7 @@ pub fn typeHasOnePossibleValue( |
| 16950 | .f16, | 16950 | .f16, |
| 16951 | .f32, | 16951 | .f32, |
| 16952 | .f64, | 16952 | .f64, |
| 16953 | .f80, | ||
| 16953 | .f128, | 16954 | .f128, |
| 16954 | .c_longdouble, | 16955 | .c_longdouble, |
| 16955 | .comptime_int, | 16956 | .comptime_int, |
| ... | @@ -17227,6 +17228,7 @@ pub fn addType(sema: *Sema, ty: Type) !Air.Inst.Ref { | ... | @@ -17227,6 +17228,7 @@ pub fn addType(sema: *Sema, ty: Type) !Air.Inst.Ref { |
| 17227 | .f16 => return .f16_type, | 17228 | .f16 => return .f16_type, |
| 17228 | .f32 => return .f32_type, | 17229 | .f32 => return .f32_type, |
| 17229 | .f64 => return .f64_type, | 17230 | .f64 => return .f64_type, |
| 17231 | .f80 => return .f80_type, | ||
| 17230 | .f128 => return .f128_type, | 17232 | .f128 => return .f128_type, |
| 17231 | .anyopaque => return .anyopaque_type, | 17233 | .anyopaque => return .anyopaque_type, |
| 17232 | .bool => return .bool_type, | 17234 | .bool => return .bool_type, |
| ... | @@ -17572,6 +17574,7 @@ fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) C | ... | @@ -17572,6 +17574,7 @@ fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) C |
| 17572 | .f16, | 17574 | .f16, |
| 17573 | .f32, | 17575 | .f32, |
| 17574 | .f64, | 17576 | .f64, |
| 17577 | .f80, | ||
| 17575 | .f128, | 17578 | .f128, |
| 17576 | .anyopaque, | 17579 | .anyopaque, |
| 17577 | .bool, | 17580 | .bool, |
src/Zir.zig+5| ... | @@ -1639,6 +1639,7 @@ pub const Inst = struct { | ... | @@ -1639,6 +1639,7 @@ pub const Inst = struct { |
| 1639 | f16_type, | 1639 | f16_type, |
| 1640 | f32_type, | 1640 | f32_type, |
| 1641 | f64_type, | 1641 | f64_type, |
| 1642 | f80_type, | ||
| 1642 | f128_type, | 1643 | f128_type, |
| 1643 | anyopaque_type, | 1644 | anyopaque_type, |
| 1644 | bool_type, | 1645 | bool_type, |
| ... | @@ -1809,6 +1810,10 @@ pub const Inst = struct { | ... | @@ -1809,6 +1810,10 @@ pub const Inst = struct { |
| 1809 | .ty = Type.initTag(.type), | 1810 | .ty = Type.initTag(.type), |
| 1810 | .val = Value.initTag(.f64_type), | 1811 | .val = Value.initTag(.f64_type), |
| 1811 | }, | 1812 | }, |
| 1813 | .f80_type = .{ | ||
| 1814 | .ty = Type.initTag(.type), | ||
| 1815 | .val = Value.initTag(.f80_type), | ||
| 1816 | }, | ||
| 1812 | .f128_type = .{ | 1817 | .f128_type = .{ |
| 1813 | .ty = Type.initTag(.type), | 1818 | .ty = Type.initTag(.type), |
| 1814 | .val = Value.initTag(.f128_type), | 1819 | .val = Value.initTag(.f128_type), |
src/stage1/all_types.hpp+2| ... | @@ -516,6 +516,7 @@ struct ZigValue { | ... | @@ -516,6 +516,7 @@ struct ZigValue { |
| 516 | float16_t x_f16; | 516 | float16_t x_f16; |
| 517 | float x_f32; | 517 | float x_f32; |
| 518 | double x_f64; | 518 | double x_f64; |
| 519 | extFloat80_t x_f80; | ||
| 519 | float128_t x_f128; | 520 | float128_t x_f128; |
| 520 | bool x_bool; | 521 | bool x_bool; |
| 521 | ConstBoundFnValue x_bound_fn; | 522 | ConstBoundFnValue x_bound_fn; |
| ... | @@ -2089,6 +2090,7 @@ struct CodeGen { | ... | @@ -2089,6 +2090,7 @@ struct CodeGen { |
| 2089 | ZigType *entry_f16; | 2090 | ZigType *entry_f16; |
| 2090 | ZigType *entry_f32; | 2091 | ZigType *entry_f32; |
| 2091 | ZigType *entry_f64; | 2092 | ZigType *entry_f64; |
| 2093 | ZigType *entry_f80; | ||
| 2092 | ZigType *entry_f128; | 2094 | ZigType *entry_f128; |
| 2093 | ZigType *entry_void; | 2095 | ZigType *entry_void; |
| 2094 | ZigType *entry_unreachable; | 2096 | ZigType *entry_unreachable; |
src/stage1/analyze.cpp+13| ... | @@ -5647,6 +5647,9 @@ static uint32_t hash_combine_const_val(uint32_t hash_val, ZigValue *const_val) { | ... | @@ -5647,6 +5647,9 @@ static uint32_t hash_combine_const_val(uint32_t hash_val, ZigValue *const_val) { |
| 5647 | case 16: return hash_combine(hash_val, &const_val->data.x_f16); | 5647 | case 16: return hash_combine(hash_val, &const_val->data.x_f16); |
| 5648 | case 32: return hash_combine(hash_val, &const_val->data.x_f32); | 5648 | case 32: return hash_combine(hash_val, &const_val->data.x_f32); |
| 5649 | case 64: return hash_combine(hash_val, &const_val->data.x_f64); | 5649 | case 64: return hash_combine(hash_val, &const_val->data.x_f64); |
| 5650 | case 80: | ||
| 5651 | hash_val = hash_combine(hash_val, &const_val->data.x_f80.signExp); | ||
| 5652 | return hash_combine(hash_val, &const_val->data.x_f80.signif); | ||
| 5650 | case 128: return hash_combine(hash_val, &const_val->data.x_f128); | 5653 | case 128: return hash_combine(hash_val, &const_val->data.x_f128); |
| 5651 | default: zig_unreachable(); | 5654 | default: zig_unreachable(); |
| 5652 | } | 5655 | } |
| ... | @@ -6325,6 +6328,7 @@ void init_const_float(ZigValue *const_val, ZigType *type, double value) { | ... | @@ -6325,6 +6328,7 @@ void init_const_float(ZigValue *const_val, ZigType *type, double value) { |
| 6325 | case 64: | 6328 | case 64: |
| 6326 | const_val->data.x_f64 = value; | 6329 | const_val->data.x_f64 = value; |
| 6327 | break; | 6330 | break; |
| 6331 | case 80: | ||
| 6328 | case 128: | 6332 | case 128: |
| 6329 | // if we need this, we should add a function that accepts a float128_t param | 6333 | // if we need this, we should add a function that accepts a float128_t param |
| 6330 | zig_unreachable(); | 6334 | zig_unreachable(); |
| ... | @@ -7218,6 +7222,8 @@ bool const_values_equal(CodeGen *g, ZigValue *a, ZigValue *b) { | ... | @@ -7218,6 +7222,8 @@ bool const_values_equal(CodeGen *g, ZigValue *a, ZigValue *b) { |
| 7218 | return a->data.x_f32 == b->data.x_f32; | 7222 | return a->data.x_f32 == b->data.x_f32; |
| 7219 | case 64: | 7223 | case 64: |
| 7220 | return a->data.x_f64 == b->data.x_f64; | 7224 | return a->data.x_f64 == b->data.x_f64; |
| 7225 | case 80: | ||
| 7226 | return extF80M_eq(&a->data.x_f80, &b->data.x_f80); | ||
| 7221 | case 128: | 7227 | case 128: |
| 7222 | return f128M_eq(&a->data.x_f128, &b->data.x_f128); | 7228 | return f128M_eq(&a->data.x_f128, &b->data.x_f128); |
| 7223 | default: | 7229 | default: |
| ... | @@ -7470,6 +7476,13 @@ void render_const_value(CodeGen *g, Buf *buf, ZigValue *const_val) { | ... | @@ -7470,6 +7476,13 @@ void render_const_value(CodeGen *g, Buf *buf, ZigValue *const_val) { |
| 7470 | case 64: | 7476 | case 64: |
| 7471 | buf_appendf(buf, "%f", const_val->data.x_f64); | 7477 | buf_appendf(buf, "%f", const_val->data.x_f64); |
| 7472 | return; | 7478 | return; |
| 7479 | case 80: { | ||
| 7480 | float64_t f64_value = extF80M_to_f64(&const_val->data.x_f80); | ||
| 7481 | double double_value; | ||
| 7482 | memcpy(&double_value, &f64_value, sizeof(double)); | ||
| 7483 | buf_appendf(buf, "%f", double_value); | ||
| 7484 | return; | ||
| 7485 | } | ||
| 7473 | case 128: | 7486 | case 128: |
| 7474 | { | 7487 | { |
| 7475 | const size_t extra_len = 100; | 7488 | const size_t extra_len = 100; |
src/stage1/codegen.cpp+444-12| ... | @@ -1598,6 +1598,81 @@ static LLVMValueRef gen_assert_zero(CodeGen *g, LLVMValueRef expr_val, ZigType * | ... | @@ -1598,6 +1598,81 @@ static LLVMValueRef gen_assert_zero(CodeGen *g, LLVMValueRef expr_val, ZigType * |
| 1598 | return nullptr; | 1598 | return nullptr; |
| 1599 | } | 1599 | } |
| 1600 | 1600 | ||
| 1601 | |||
| 1602 | static LLVMValueRef gen_soft_f80_widen_or_shorten(CodeGen *g, ZigType *actual_type, | ||
| 1603 | ZigType *wanted_type, LLVMValueRef expr_val) | ||
| 1604 | { | ||
| 1605 | ZigType *scalar_actual_type = (actual_type->id == ZigTypeIdVector) ? | ||
| 1606 | actual_type->data.vector.elem_type : actual_type; | ||
| 1607 | ZigType *scalar_wanted_type = (wanted_type->id == ZigTypeIdVector) ? | ||
| 1608 | wanted_type->data.vector.elem_type : wanted_type; | ||
| 1609 | uint64_t actual_bits = scalar_actual_type->data.floating.bit_count; | ||
| 1610 | uint64_t wanted_bits = scalar_wanted_type->data.floating.bit_count; | ||
| 1611 | |||
| 1612 | |||
| 1613 | LLVMTypeRef param_type; | ||
| 1614 | LLVMTypeRef return_type; | ||
| 1615 | const char *func_name; | ||
| 1616 | |||
| 1617 | if (actual_bits == wanted_bits) { | ||
| 1618 | return expr_val; | ||
| 1619 | } else if (actual_bits == 80) { | ||
| 1620 | param_type = g->builtin_types.entry_f80->llvm_type; | ||
| 1621 | switch (wanted_bits) { | ||
| 1622 | case 16: | ||
| 1623 | return_type = g->builtin_types.entry_f16->llvm_type; | ||
| 1624 | func_name = "__truncxfhf2"; | ||
| 1625 | break; | ||
| 1626 | case 32: | ||
| 1627 | return_type = g->builtin_types.entry_f32->llvm_type; | ||
| 1628 | func_name = "__truncxfff2"; | ||
| 1629 | break; | ||
| 1630 | case 64: | ||
| 1631 | return_type = g->builtin_types.entry_f64->llvm_type; | ||
| 1632 | func_name = "__truncxfdf2"; | ||
| 1633 | break; | ||
| 1634 | case 128: | ||
| 1635 | return_type = g->builtin_types.entry_f128->llvm_type; | ||
| 1636 | func_name = "__extendxftf2"; | ||
| 1637 | break; | ||
| 1638 | default: | ||
| 1639 | zig_unreachable(); | ||
| 1640 | } | ||
| 1641 | } else if (wanted_bits == 80) { | ||
| 1642 | return_type = g->builtin_types.entry_f80->llvm_type; | ||
| 1643 | switch (actual_bits) { | ||
| 1644 | case 16: | ||
| 1645 | param_type = g->builtin_types.entry_f16->llvm_type; | ||
| 1646 | func_name = "__extendhfxf2"; | ||
| 1647 | break; | ||
| 1648 | case 32: | ||
| 1649 | param_type = g->builtin_types.entry_f32->llvm_type; | ||
| 1650 | func_name = "__extendffxf2"; | ||
| 1651 | break; | ||
| 1652 | case 64: | ||
| 1653 | param_type = g->builtin_types.entry_f64->llvm_type; | ||
| 1654 | func_name = "__extenddfxf2"; | ||
| 1655 | break; | ||
| 1656 | case 128: | ||
| 1657 | param_type = g->builtin_types.entry_f128->llvm_type; | ||
| 1658 | func_name = "__trunctfxf2"; | ||
| 1659 | break; | ||
| 1660 | default: | ||
| 1661 | zig_unreachable(); | ||
| 1662 | } | ||
| 1663 | } else { | ||
| 1664 | zig_unreachable(); | ||
| 1665 | } | ||
| 1666 | |||
| 1667 | LLVMValueRef func_ref = LLVMGetNamedFunction(g->module, func_name); | ||
| 1668 | if (func_ref == nullptr) { | ||
| 1669 | LLVMTypeRef fn_type = LLVMFunctionType(return_type, &param_type, 1, false); | ||
| 1670 | func_ref = LLVMAddFunction(g->module, func_name, fn_type); | ||
| 1671 | } | ||
| 1672 | |||
| 1673 | return LLVMBuildCall(g->builder, func_ref, &expr_val, 1, ""); | ||
| 1674 | } | ||
| 1675 | |||
| 1601 | static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, ZigType *actual_type, | 1676 | static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, ZigType *actual_type, |
| 1602 | ZigType *wanted_type, LLVMValueRef expr_val) | 1677 | ZigType *wanted_type, LLVMValueRef expr_val) |
| 1603 | { | 1678 | { |
| ... | @@ -1612,6 +1687,13 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, Z | ... | @@ -1612,6 +1687,13 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, Z |
| 1612 | uint64_t actual_bits; | 1687 | uint64_t actual_bits; |
| 1613 | uint64_t wanted_bits; | 1688 | uint64_t wanted_bits; |
| 1614 | if (scalar_actual_type->id == ZigTypeIdFloat) { | 1689 | if (scalar_actual_type->id == ZigTypeIdFloat) { |
| 1690 | |||
| 1691 | if ((scalar_actual_type == g->builtin_types.entry_f80 | ||
| 1692 | || scalar_wanted_type == g->builtin_types.entry_f80) | ||
| 1693 | && !target_has_f80(g->zig_target)) | ||
| 1694 | { | ||
| 1695 | return gen_soft_f80_widen_or_shorten(g, actual_type, wanted_type, expr_val); | ||
| 1696 | } | ||
| 1615 | actual_bits = scalar_actual_type->data.floating.bit_count; | 1697 | actual_bits = scalar_actual_type->data.floating.bit_count; |
| 1616 | wanted_bits = scalar_wanted_type->data.floating.bit_count; | 1698 | wanted_bits = scalar_wanted_type->data.floating.bit_count; |
| 1617 | } else if (scalar_actual_type->id == ZigTypeIdInt) { | 1699 | } else if (scalar_actual_type->id == ZigTypeIdInt) { |
| ... | @@ -3142,6 +3224,187 @@ static void gen_shift_rhs_check(CodeGen *g, ZigType *lhs_type, ZigType *rhs_type | ... | @@ -3142,6 +3224,187 @@ static void gen_shift_rhs_check(CodeGen *g, ZigType *lhs_type, ZigType *rhs_type |
| 3142 | } | 3224 | } |
| 3143 | } | 3225 | } |
| 3144 | 3226 | ||
| 3227 | static LLVMValueRef get_soft_f80_bin_op_func(CodeGen *g, const char *name, int param_count, LLVMTypeRef return_type) { | ||
| 3228 | LLVMValueRef existing_llvm_fn = LLVMGetNamedFunction(g->module, name); | ||
| 3229 | if (existing_llvm_fn != nullptr) return existing_llvm_fn; | ||
| 3230 | |||
| 3231 | LLVMTypeRef float_type_ref = g->builtin_types.entry_f80->llvm_type; | ||
| 3232 | LLVMTypeRef param_types[2] = { float_type_ref, float_type_ref }; | ||
| 3233 | LLVMTypeRef fn_type = LLVMFunctionType(return_type, param_types, param_count, false); | ||
| 3234 | return LLVMAddFunction(g->module, name, fn_type); | ||
| 3235 | } | ||
| 3236 | |||
| 3237 | static LLVMValueRef ir_render_soft_f80_bin_op(CodeGen *g, Stage1Air *executable, | ||
| 3238 | Stage1AirInstBinOp *bin_op_instruction) | ||
| 3239 | { | ||
| 3240 | IrBinOp op_id = bin_op_instruction->op_id; | ||
| 3241 | Stage1AirInst *op1 = bin_op_instruction->op1; | ||
| 3242 | Stage1AirInst *op2 = bin_op_instruction->op2; | ||
| 3243 | uint32_t vector_len = op1->value->type->id == ZigTypeIdVector ? op1->value->type->data.vector.len : 0; | ||
| 3244 | |||
| 3245 | LLVMValueRef op1_value = ir_llvm_value(g, op1); | ||
| 3246 | LLVMValueRef op2_value = ir_llvm_value(g, op2); | ||
| 3247 | |||
| 3248 | bool div_exact_safety_check = false; | ||
| 3249 | LLVMTypeRef return_type = g->builtin_types.entry_f80->llvm_type; | ||
| 3250 | int param_count = 2; | ||
| 3251 | const char *func_name; | ||
| 3252 | switch (op_id) { | ||
| 3253 | case IrBinOpInvalid: | ||
| 3254 | case IrBinOpArrayCat: | ||
| 3255 | case IrBinOpArrayMult: | ||
| 3256 | case IrBinOpRemUnspecified: | ||
| 3257 | case IrBinOpBitShiftLeftLossy: | ||
| 3258 | case IrBinOpBitShiftLeftExact: | ||
| 3259 | case IrBinOpBitShiftRightLossy: | ||
| 3260 | case IrBinOpBitShiftRightExact: | ||
| 3261 | case IrBinOpBoolOr: | ||
| 3262 | case IrBinOpBoolAnd: | ||
| 3263 | case IrBinOpMultWrap: | ||
| 3264 | case IrBinOpAddWrap: | ||
| 3265 | case IrBinOpSubWrap: | ||
| 3266 | case IrBinOpBinOr: | ||
| 3267 | case IrBinOpBinXor: | ||
| 3268 | case IrBinOpBinAnd: | ||
| 3269 | case IrBinOpAddSat: | ||
| 3270 | case IrBinOpSubSat: | ||
| 3271 | case IrBinOpMultSat: | ||
| 3272 | case IrBinOpShlSat: | ||
| 3273 | zig_unreachable(); | ||
| 3274 | case IrBinOpCmpEq: | ||
| 3275 | return_type = g->builtin_types.entry_i32->llvm_type; | ||
| 3276 | func_name = "__eqxf2"; | ||
| 3277 | break; | ||
| 3278 | case IrBinOpCmpNotEq: | ||
| 3279 | return_type = g->builtin_types.entry_i32->llvm_type; | ||
| 3280 | func_name = "__nexf2"; | ||
| 3281 | break; | ||
| 3282 | case IrBinOpCmpLessOrEq: | ||
| 3283 | case IrBinOpCmpLessThan: | ||
| 3284 | return_type = g->builtin_types.entry_i32->llvm_type; | ||
| 3285 | func_name = "__lexf2"; | ||
| 3286 | break; | ||
| 3287 | case IrBinOpCmpGreaterOrEq: | ||
| 3288 | case IrBinOpCmpGreaterThan: | ||
| 3289 | return_type = g->builtin_types.entry_i32->llvm_type; | ||
| 3290 | func_name = "__gexf2"; | ||
| 3291 | break; | ||
| 3292 | case IrBinOpMaximum: | ||
| 3293 | func_name = "__fmaxx"; | ||
| 3294 | break; | ||
| 3295 | case IrBinOpMinimum: | ||
| 3296 | func_name = "__fminx"; | ||
| 3297 | break; | ||
| 3298 | case IrBinOpMult: | ||
| 3299 | func_name = "__mulxf3"; | ||
| 3300 | break; | ||
| 3301 | case IrBinOpAdd: | ||
| 3302 | func_name = "__addxf3"; | ||
| 3303 | break; | ||
| 3304 | case IrBinOpSub: | ||
| 3305 | func_name = "__subxf3"; | ||
| 3306 | break; | ||
| 3307 | case IrBinOpDivUnspecified: | ||
| 3308 | func_name = "__divxf3"; | ||
| 3309 | break; | ||
| 3310 | case IrBinOpDivExact: | ||
| 3311 | func_name = "__divxf3"; | ||
| 3312 | div_exact_safety_check = bin_op_instruction->safety_check_on && | ||
| 3313 | ir_want_runtime_safety(g, &bin_op_instruction->base); | ||
| 3314 | break; | ||
| 3315 | case IrBinOpDivTrunc: | ||
| 3316 | param_count = 1; | ||
| 3317 | func_name = "__truncx"; | ||
| 3318 | break; | ||
| 3319 | case IrBinOpDivFloor: | ||
| 3320 | param_count = 1; | ||
| 3321 | func_name = "__floorx"; | ||
| 3322 | break; | ||
| 3323 | case IrBinOpRemRem: | ||
| 3324 | param_count = 1; | ||
| 3325 | func_name = "__remx"; | ||
| 3326 | break; | ||
| 3327 | case IrBinOpRemMod: | ||
| 3328 | param_count = 1; | ||
| 3329 | func_name = "__modx"; | ||
| 3330 | break; | ||
| 3331 | default: | ||
| 3332 | zig_unreachable(); | ||
| 3333 | } | ||
| 3334 | |||
| 3335 | LLVMValueRef func_ref = get_soft_f80_bin_op_func(g, func_name, param_count, return_type); | ||
| 3336 | |||
| 3337 | LLVMValueRef result; | ||
| 3338 | if (vector_len == 0) { | ||
| 3339 | LLVMValueRef params[2] = {op1_value, op2_value}; | ||
| 3340 | result = LLVMBuildCall(g->builder, func_ref, params, param_count, ""); | ||
| 3341 | } else { | ||
| 3342 | result = build_alloca(g, op1->value->type, "", 0); | ||
| 3343 | } | ||
| 3344 | |||
| 3345 | LLVMTypeRef usize_ref = g->builtin_types.entry_usize->llvm_type; | ||
| 3346 | for (uint32_t i = 0; i < vector_len; i++) { | ||
| 3347 | LLVMValueRef index_value = LLVMConstInt(usize_ref, i, false); | ||
| 3348 | LLVMValueRef params[2] = { | ||
| 3349 | LLVMBuildExtractElement(g->builder, op1_value, index_value, ""), | ||
| 3350 | LLVMBuildExtractElement(g->builder, op2_value, index_value, ""), | ||
| 3351 | }; | ||
| 3352 | LLVMValueRef call_result = LLVMBuildCall(g->builder, func_ref, params, param_count, ""); | ||
| 3353 | LLVMBuildInsertElement(g->builder, LLVMBuildLoad(g->builder, result, ""), | ||
| 3354 | call_result, index_value, ""); | ||
| 3355 | } | ||
| 3356 | |||
| 3357 | if (div_exact_safety_check) { | ||
| 3358 | // Safety check: a / b == floor(a / b) | ||
| 3359 | LLVMValueRef floor_func = get_soft_f80_bin_op_func(g, "__floorx", 1, return_type); | ||
| 3360 | LLVMValueRef eq_func = get_soft_f80_bin_op_func(g, "__eqxf2", 2, g->builtin_types.entry_i32->llvm_type); | ||
| 3361 | |||
| 3362 | LLVMValueRef ok_bit; | ||
| 3363 | if (vector_len == 0) { | ||
| 3364 | LLVMValueRef floored = LLVMBuildCall(g->builder, floor_func, &result, 1, ""); | ||
| 3365 | |||
| 3366 | LLVMValueRef params[2] = {result, floored}; | ||
| 3367 | ok_bit = LLVMBuildCall(g->builder, eq_func, params, 2, ""); | ||
| 3368 | } else { | ||
| 3369 | ZigType *bool_vec_ty = get_vector_type(g, vector_len, g->builtin_types.entry_bool); | ||
| 3370 | ok_bit = build_alloca(g, bool_vec_ty, "", 0); | ||
| 3371 | } | ||
| 3372 | |||
| 3373 | for (uint32_t i = 0; i < vector_len; i++) { | ||
| 3374 | LLVMValueRef index_value = LLVMConstInt(usize_ref, i, false); | ||
| 3375 | LLVMValueRef div_res = LLVMBuildExtractElement(g->builder, | ||
| 3376 | LLVMBuildLoad(g->builder, result, ""), index_value, ""); | ||
| 3377 | |||
| 3378 | LLVMValueRef params[2] = { | ||
| 3379 | div_res, | ||
| 3380 | LLVMBuildCall(g->builder, floor_func, &div_res, 1, ""), | ||
| 3381 | }; | ||
| 3382 | LLVMValueRef cmp_res = LLVMBuildCall(g->builder, eq_func, params, 2, ""); | ||
| 3383 | cmp_res = LLVMBuildTrunc(g->builder, cmp_res, g->builtin_types.entry_bool->llvm_type, ""); | ||
| 3384 | LLVMBuildInsertElement(g->builder, LLVMBuildLoad(g->builder, ok_bit, ""), | ||
| 3385 | cmp_res, index_value, ""); | ||
| 3386 | } | ||
| 3387 | |||
| 3388 | if (vector_len != 0) { | ||
| 3389 | ok_bit = ZigLLVMBuildAndReduce(g->builder, LLVMBuildLoad(g->builder, ok_bit, "")); | ||
| 3390 | } | ||
| 3391 | LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivExactOk"); | ||
| 3392 | LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivExactFail"); | ||
| 3393 | |||
| 3394 | LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block); | ||
| 3395 | |||
| 3396 | LLVMPositionBuilderAtEnd(g->builder, fail_block); | ||
| 3397 | gen_safety_crash(g, PanicMsgIdExactDivisionRemainder); | ||
| 3398 | |||
| 3399 | LLVMPositionBuilderAtEnd(g->builder, ok_block); | ||
| 3400 | } | ||
| 3401 | |||
| 3402 | if (vector_len != 0) { | ||
| 3403 | result = LLVMBuildLoad(g->builder, result, ""); | ||
| 3404 | } | ||
| 3405 | return result; | ||
| 3406 | } | ||
| 3407 | |||
| 3145 | static LLVMValueRef ir_render_bin_op(CodeGen *g, Stage1Air *executable, | 3408 | static LLVMValueRef ir_render_bin_op(CodeGen *g, Stage1Air *executable, |
| 3146 | Stage1AirInstBinOp *bin_op_instruction) | 3409 | Stage1AirInstBinOp *bin_op_instruction) |
| 3147 | { | 3410 | { |
| ... | @@ -3151,6 +3414,10 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, Stage1Air *executable, | ... | @@ -3151,6 +3414,10 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, Stage1Air *executable, |
| 3151 | 3414 | ||
| 3152 | ZigType *operand_type = op1->value->type; | 3415 | ZigType *operand_type = op1->value->type; |
| 3153 | ZigType *scalar_type = (operand_type->id == ZigTypeIdVector) ? operand_type->data.vector.elem_type : operand_type; | 3416 | ZigType *scalar_type = (operand_type->id == ZigTypeIdVector) ? operand_type->data.vector.elem_type : operand_type; |
| 3417 | if (scalar_type == g->builtin_types.entry_f80 && !target_has_f80(g->zig_target)) { | ||
| 3418 | return ir_render_soft_f80_bin_op(g, executable, bin_op_instruction); | ||
| 3419 | } | ||
| 3420 | |||
| 3154 | 3421 | ||
| 3155 | bool want_runtime_safety = bin_op_instruction->safety_check_on && | 3422 | bool want_runtime_safety = bin_op_instruction->safety_check_on && |
| 3156 | ir_want_runtime_safety(g, &bin_op_instruction->base); | 3423 | ir_want_runtime_safety(g, &bin_op_instruction->base); |
| ... | @@ -3158,7 +3425,6 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, Stage1Air *executable, | ... | @@ -3158,7 +3425,6 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, Stage1Air *executable, |
| 3158 | LLVMValueRef op1_value = ir_llvm_value(g, op1); | 3425 | LLVMValueRef op1_value = ir_llvm_value(g, op1); |
| 3159 | LLVMValueRef op2_value = ir_llvm_value(g, op2); | 3426 | LLVMValueRef op2_value = ir_llvm_value(g, op2); |
| 3160 | 3427 | ||
| 3161 | |||
| 3162 | switch (op_id) { | 3428 | switch (op_id) { |
| 3163 | case IrBinOpInvalid: | 3429 | case IrBinOpInvalid: |
| 3164 | case IrBinOpArrayCat: | 3430 | case IrBinOpArrayCat: |
| ... | @@ -5927,7 +6193,7 @@ static LLVMValueRef ir_render_prefetch(CodeGen *g, Stage1Air *executable, Stage1 | ... | @@ -5927,7 +6193,7 @@ static LLVMValueRef ir_render_prefetch(CodeGen *g, Stage1Air *executable, Stage1 |
| 5927 | static_assert(PrefetchCacheInstruction == 0, ""); | 6193 | static_assert(PrefetchCacheInstruction == 0, ""); |
| 5928 | static_assert(PrefetchCacheData == 1, ""); | 6194 | static_assert(PrefetchCacheData == 1, ""); |
| 5929 | assert(instruction->cache == PrefetchCacheData || instruction->cache == PrefetchCacheInstruction); | 6195 | assert(instruction->cache == PrefetchCacheData || instruction->cache == PrefetchCacheInstruction); |
| 5930 | 6196 | ||
| 5931 | // LLVM fails during codegen of instruction cache prefetchs for these architectures. | 6197 | // LLVM fails during codegen of instruction cache prefetchs for these architectures. |
| 5932 | // This is an LLVM bug as the prefetch intrinsic should be a noop if not supported by the target. | 6198 | // This is an LLVM bug as the prefetch intrinsic should be a noop if not supported by the target. |
| 5933 | // To work around this, simply don't emit llvm.prefetch in this case. | 6199 | // To work around this, simply don't emit llvm.prefetch in this case. |
| ... | @@ -6622,13 +6888,148 @@ static LLVMValueRef ir_render_atomic_store(CodeGen *g, Stage1Air *executable, | ... | @@ -6622,13 +6888,148 @@ static LLVMValueRef ir_render_atomic_store(CodeGen *g, Stage1Air *executable, |
| 6622 | return nullptr; | 6888 | return nullptr; |
| 6623 | } | 6889 | } |
| 6624 | 6890 | ||
| 6891 | static LLVMValueRef ir_render_soft_f80_float_op(CodeGen *g, Stage1Air *executable, Stage1AirInstFloatOp *instruction) { | ||
| 6892 | ZigType *op_type = instruction->operand->value->type; | ||
| 6893 | uint32_t vector_len = op_type->id == ZigTypeIdVector ? op_type->data.vector.len : 0; | ||
| 6894 | |||
| 6895 | const char *func_name; | ||
| 6896 | switch (instruction->fn_id) { | ||
| 6897 | case BuiltinFnIdSqrt: | ||
| 6898 | func_name = "__sqrt"; | ||
| 6899 | break; | ||
| 6900 | case BuiltinFnIdSin: | ||
| 6901 | func_name = "__sinx"; | ||
| 6902 | break; | ||
| 6903 | case BuiltinFnIdCos: | ||
| 6904 | func_name = "__cosx"; | ||
| 6905 | break; | ||
| 6906 | case BuiltinFnIdExp: | ||
| 6907 | func_name = "__expx"; | ||
| 6908 | break; | ||
| 6909 | case BuiltinFnIdExp2: | ||
| 6910 | func_name = "__exp2x"; | ||
| 6911 | break; | ||
| 6912 | case BuiltinFnIdLog: | ||
| 6913 | func_name = "__logx"; | ||
| 6914 | break; | ||
| 6915 | case BuiltinFnIdLog2: | ||
| 6916 | func_name = "__log2x"; | ||
| 6917 | break; | ||
| 6918 | case BuiltinFnIdLog10: | ||
| 6919 | func_name = "__log10x"; | ||
| 6920 | break; | ||
| 6921 | case BuiltinFnIdFabs: | ||
| 6922 | func_name = "__fabsx"; | ||
| 6923 | break; | ||
| 6924 | case BuiltinFnIdFloor: | ||
| 6925 | func_name = "__floorx"; | ||
| 6926 | break; | ||
| 6927 | case BuiltinFnIdCeil: | ||
| 6928 | func_name = "__ceilx"; | ||
| 6929 | break; | ||
| 6930 | case BuiltinFnIdTrunc: | ||
| 6931 | func_name = "__truncx"; | ||
| 6932 | break; | ||
| 6933 | case BuiltinFnIdNearbyInt: | ||
| 6934 | func_name = "__nearbyintx"; | ||
| 6935 | break; | ||
| 6936 | case BuiltinFnIdRound: | ||
| 6937 | func_name = "__roundx"; | ||
| 6938 | break; | ||
| 6939 | default: | ||
| 6940 | zig_unreachable(); | ||
| 6941 | } | ||
| 6942 | |||
| 6943 | |||
| 6944 | LLVMValueRef func_ref = LLVMGetNamedFunction(g->module, func_name); | ||
| 6945 | if (func_ref == nullptr) { | ||
| 6946 | LLVMTypeRef f80_ref = g->builtin_types.entry_f80->llvm_type; | ||
| 6947 | LLVMTypeRef fn_type = LLVMFunctionType(f80_ref, &f80_ref, 1, false); | ||
| 6948 | func_ref = LLVMAddFunction(g->module, func_name, fn_type); | ||
| 6949 | } | ||
| 6950 | |||
| 6951 | LLVMValueRef operand = ir_llvm_value(g, instruction->operand); | ||
| 6952 | LLVMValueRef result; | ||
| 6953 | if (vector_len == 0) { | ||
| 6954 | result = LLVMBuildCall(g->builder, func_ref, &operand, 1, ""); | ||
| 6955 | } else { | ||
| 6956 | result = build_alloca(g, instruction->operand->value->type, "", 0); | ||
| 6957 | } | ||
| 6958 | |||
| 6959 | LLVMTypeRef usize_ref = g->builtin_types.entry_usize->llvm_type; | ||
| 6960 | for (uint32_t i = 0; i < vector_len; i++) { | ||
| 6961 | LLVMValueRef index_value = LLVMConstInt(usize_ref, i, false); | ||
| 6962 | LLVMValueRef param = LLVMBuildExtractElement(g->builder, operand, index_value, ""); | ||
| 6963 | LLVMValueRef call_result = LLVMBuildCall(g->builder, func_ref, &param, 1, ""); | ||
| 6964 | LLVMBuildInsertElement(g->builder, LLVMBuildLoad(g->builder, result, ""), | ||
| 6965 | call_result, index_value, ""); | ||
| 6966 | } | ||
| 6967 | if (vector_len != 0) { | ||
| 6968 | result = LLVMBuildLoad(g->builder, result, ""); | ||
| 6969 | } | ||
| 6970 | return result; | ||
| 6971 | } | ||
| 6972 | |||
| 6625 | static LLVMValueRef ir_render_float_op(CodeGen *g, Stage1Air *executable, Stage1AirInstFloatOp *instruction) { | 6973 | static LLVMValueRef ir_render_float_op(CodeGen *g, Stage1Air *executable, Stage1AirInstFloatOp *instruction) { |
| 6974 | ZigType *op_type = instruction->operand->value->type; | ||
| 6975 | op_type = op_type->id == ZigTypeIdVector ? op_type->data.vector.elem_type : op_type; | ||
| 6976 | if (op_type == g->builtin_types.entry_f80 && !target_has_f80(g->zig_target)) { | ||
| 6977 | return ir_render_soft_f80_float_op(g, executable, instruction); | ||
| 6978 | } | ||
| 6626 | LLVMValueRef operand = ir_llvm_value(g, instruction->operand); | 6979 | LLVMValueRef operand = ir_llvm_value(g, instruction->operand); |
| 6627 | LLVMValueRef fn_val = get_float_fn(g, instruction->base.value->type, ZigLLVMFnIdFloatOp, instruction->fn_id); | 6980 | LLVMValueRef fn_val = get_float_fn(g, instruction->base.value->type, ZigLLVMFnIdFloatOp, instruction->fn_id); |
| 6628 | return LLVMBuildCall(g->builder, fn_val, &operand, 1, ""); | 6981 | return LLVMBuildCall(g->builder, fn_val, &operand, 1, ""); |
| 6629 | } | 6982 | } |
| 6630 | 6983 | ||
| 6984 | static LLVMValueRef ir_render_soft_f80_mul_add(CodeGen *g, Stage1Air *executable, Stage1AirInstMulAdd *instruction) { | ||
| 6985 | ZigType *op_type = instruction->op1->value->type; | ||
| 6986 | uint32_t vector_len = op_type->id == ZigTypeIdVector ? op_type->data.vector.len : 0; | ||
| 6987 | |||
| 6988 | const char *func_name = "__fmax"; | ||
| 6989 | LLVMValueRef func_ref = LLVMGetNamedFunction(g->module, func_name); | ||
| 6990 | if (func_ref == nullptr) { | ||
| 6991 | LLVMTypeRef f80_ref = g->builtin_types.entry_f80->llvm_type; | ||
| 6992 | LLVMTypeRef params[3] = { f80_ref, f80_ref, f80_ref }; | ||
| 6993 | LLVMTypeRef fn_type = LLVMFunctionType(f80_ref, params, 3, false); | ||
| 6994 | func_ref = LLVMAddFunction(g->module, func_name, fn_type); | ||
| 6995 | } | ||
| 6996 | |||
| 6997 | LLVMValueRef op1 = ir_llvm_value(g, instruction->op1); | ||
| 6998 | LLVMValueRef op2 = ir_llvm_value(g, instruction->op2); | ||
| 6999 | LLVMValueRef op3 = ir_llvm_value(g, instruction->op3); | ||
| 7000 | LLVMValueRef result; | ||
| 7001 | if (vector_len == 0) { | ||
| 7002 | LLVMValueRef params[3] = { op1, op2, op3 }; | ||
| 7003 | result = LLVMBuildCall(g->builder, func_ref, params, 3, ""); | ||
| 7004 | } else { | ||
| 7005 | result = build_alloca(g, instruction->op1->value->type, "", 0); | ||
| 7006 | } | ||
| 7007 | |||
| 7008 | LLVMTypeRef usize_ref = g->builtin_types.entry_usize->llvm_type; | ||
| 7009 | for (uint32_t i = 0; i < vector_len; i++) { | ||
| 7010 | LLVMValueRef index_value = LLVMConstInt(usize_ref, i, false); | ||
| 7011 | |||
| 7012 | LLVMValueRef params[3] = { | ||
| 7013 | LLVMBuildExtractElement(g->builder, op1, index_value, ""), | ||
| 7014 | LLVMBuildExtractElement(g->builder, op2, index_value, ""), | ||
| 7015 | LLVMBuildExtractElement(g->builder, op3, index_value, ""), | ||
| 7016 | }; | ||
| 7017 | LLVMValueRef call_result = LLVMBuildCall(g->builder, func_ref, params, 3, ""); | ||
| 7018 | LLVMBuildInsertElement(g->builder, LLVMBuildLoad(g->builder, result, ""), | ||
| 7019 | call_result, index_value, ""); | ||
| 7020 | } | ||
| 7021 | if (vector_len != 0) { | ||
| 7022 | result = LLVMBuildLoad(g->builder, result, ""); | ||
| 7023 | } | ||
| 7024 | return result; | ||
| 7025 | } | ||
| 7026 | |||
| 6631 | static LLVMValueRef ir_render_mul_add(CodeGen *g, Stage1Air *executable, Stage1AirInstMulAdd *instruction) { | 7027 | static LLVMValueRef ir_render_mul_add(CodeGen *g, Stage1Air *executable, Stage1AirInstMulAdd *instruction) { |
| 7028 | ZigType *op_type = instruction->op1->value->type; | ||
| 7029 | op_type = op_type->id == ZigTypeIdVector ? op_type->data.vector.elem_type : op_type; | ||
| 7030 | if (op_type == g->builtin_types.entry_f80 && !target_has_f80(g->zig_target)) { | ||
| 7031 | return ir_render_soft_f80_mul_add(g, executable, instruction); | ||
| 7032 | } | ||
| 6632 | LLVMValueRef op1 = ir_llvm_value(g, instruction->op1); | 7033 | LLVMValueRef op1 = ir_llvm_value(g, instruction->op1); |
| 6633 | LLVMValueRef op2 = ir_llvm_value(g, instruction->op2); | 7034 | LLVMValueRef op2 = ir_llvm_value(g, instruction->op2); |
| 6634 | LLVMValueRef op3 = ir_llvm_value(g, instruction->op3); | 7035 | LLVMValueRef op3 = ir_llvm_value(g, instruction->op3); |
| ... | @@ -7692,20 +8093,33 @@ static LLVMValueRef gen_const_val(CodeGen *g, ZigValue *const_val, const char *n | ... | @@ -7692,20 +8093,33 @@ static LLVMValueRef gen_const_val(CodeGen *g, ZigValue *const_val, const char *n |
| 7692 | return LLVMConstReal(get_llvm_type(g, type_entry), const_val->data.x_f32); | 8093 | return LLVMConstReal(get_llvm_type(g, type_entry), const_val->data.x_f32); |
| 7693 | case 64: | 8094 | case 64: |
| 7694 | return LLVMConstReal(get_llvm_type(g, type_entry), const_val->data.x_f64); | 8095 | return LLVMConstReal(get_llvm_type(g, type_entry), const_val->data.x_f64); |
| 8096 | case 80: { | ||
| 8097 | uint64_t buf[2]; | ||
| 8098 | memcpy(&buf, &const_val->data.x_f80, 16); | ||
| 8099 | #if ZIG_BYTE_ORDER == ZIG_BIG_ENDIAN | ||
| 8100 | uint64_t tmp = buf[0]; | ||
| 8101 | buf[0] = buf[1]; | ||
| 8102 | buf[1] = tmp; | ||
| 8103 | #endif | ||
| 8104 | LLVMValueRef as_i128 = LLVMConstIntOfArbitraryPrecision(LLVMInt128Type(), 2, buf); | ||
| 8105 | LLVMValueRef as_int = LLVMConstTrunc(as_i128, LLVMIntType(80)); | ||
| 8106 | return LLVMConstBitCast(as_int, get_llvm_type(g, type_entry)); | ||
| 8107 | } | ||
| 7695 | case 128: | 8108 | case 128: |
| 7696 | { | 8109 | { |
| 7697 | uint64_t buf[2]; | 8110 | uint64_t buf[2]; |
| 7698 | 8111 | ||
| 7699 | // LLVM seems to require that the lower half of the f128 be placed first in the buffer. | 8112 | // LLVM seems to require that the lower half of the f128 be |
| 7700 | #if defined(ZIG_BYTE_ORDER) && ZIG_BYTE_ORDER == ZIG_LITTLE_ENDIAN | 8113 | // placed first in the buffer. |
| 7701 | buf[0] = const_val->data.x_f128.v[0]; | 8114 | #if ZIG_BYTE_ORDER == ZIG_LITTLE_ENDIAN |
| 7702 | buf[1] = const_val->data.x_f128.v[1]; | 8115 | buf[0] = const_val->data.x_f128.v[0]; |
| 7703 | #elif defined(ZIG_BYTE_ORDER) && ZIG_BYTE_ORDER == ZIG_BIG_ENDIAN | 8116 | buf[1] = const_val->data.x_f128.v[1]; |
| 7704 | buf[0] = const_val->data.x_f128.v[1]; | 8117 | #elif ZIG_BYTE_ORDER == ZIG_BIG_ENDIAN |
| 7705 | buf[1] = const_val->data.x_f128.v[0]; | 8118 | buf[0] = const_val->data.x_f128.v[1]; |
| 7706 | #else | 8119 | buf[1] = const_val->data.x_f128.v[0]; |
| 7707 | #error Unsupported endian | 8120 | #else |
| 7708 | #endif | 8121 | #error Unsupported endian |
| 8122 | #endif | ||
| 7709 | 8123 | ||
| 7710 | LLVMValueRef as_int = LLVMConstIntOfArbitraryPrecision(LLVMInt128Type(), 2, buf); | 8124 | LLVMValueRef as_int = LLVMConstIntOfArbitraryPrecision(LLVMInt128Type(), 2, buf); |
| 7711 | return LLVMConstBitCast(as_int, get_llvm_type(g, type_entry)); | 8125 | return LLVMConstBitCast(as_int, get_llvm_type(g, type_entry)); |
| ... | @@ -8911,6 +9325,24 @@ static void define_builtin_types(CodeGen *g) { | ... | @@ -8911,6 +9325,24 @@ static void define_builtin_types(CodeGen *g) { |
| 8911 | add_fp_entry(g, "f64", 64, LLVMDoubleType(), &g->builtin_types.entry_f64); | 9325 | add_fp_entry(g, "f64", 64, LLVMDoubleType(), &g->builtin_types.entry_f64); |
| 8912 | add_fp_entry(g, "f128", 128, LLVMFP128Type(), &g->builtin_types.entry_f128); | 9326 | add_fp_entry(g, "f128", 128, LLVMFP128Type(), &g->builtin_types.entry_f128); |
| 8913 | 9327 | ||
| 9328 | if (target_has_f80(g->zig_target)) { | ||
| 9329 | add_fp_entry(g, "f80", 80, LLVMX86FP80Type(), &g->builtin_types.entry_f80); | ||
| 9330 | } else { | ||
| 9331 | ZigType *entry = new_type_table_entry(ZigTypeIdFloat); | ||
| 9332 | entry->llvm_type = get_int_type(g, false, 128)->llvm_type; | ||
| 9333 | entry->size_in_bits = 8 * LLVMStoreSizeOfType(g->target_data_ref, entry->llvm_type); | ||
| 9334 | entry->abi_size = LLVMABISizeOfType(g->target_data_ref, entry->llvm_type); | ||
| 9335 | entry->abi_align = 16; | ||
| 9336 | buf_init_from_str(&entry->name, "f80"); | ||
| 9337 | entry->data.floating.bit_count = 80; | ||
| 9338 | |||
| 9339 | entry->llvm_di_type = ZigLLVMCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), | ||
| 9340 | entry->size_in_bits, ZigLLVMEncoding_DW_ATE_unsigned()); | ||
| 9341 | |||
| 9342 | g->builtin_types.entry_f80 = entry; | ||
| 9343 | g->primitive_type_table.put(&entry->name, entry); | ||
| 9344 | } | ||
| 9345 | |||
| 8914 | switch (g->zig_target->arch) { | 9346 | switch (g->zig_target->arch) { |
| 8915 | case ZigLLVM_x86: | 9347 | case ZigLLVM_x86: |
| 8916 | case ZigLLVM_x86_64: | 9348 | case ZigLLVM_x86_64: |
src/stage1/ir.cpp+239-23| ... | @@ -2688,6 +2688,12 @@ static bool float_has_fraction(ZigValue *const_val) { | ... | @@ -2688,6 +2688,12 @@ static bool float_has_fraction(ZigValue *const_val) { |
| 2688 | return floorf(const_val->data.x_f32) != const_val->data.x_f32; | 2688 | return floorf(const_val->data.x_f32) != const_val->data.x_f32; |
| 2689 | case 64: | 2689 | case 64: |
| 2690 | return floor(const_val->data.x_f64) != const_val->data.x_f64; | 2690 | return floor(const_val->data.x_f64) != const_val->data.x_f64; |
| 2691 | case 80: | ||
| 2692 | { | ||
| 2693 | extFloat80_t floored; | ||
| 2694 | extF80M_roundToInt(&const_val->data.x_f80, softfloat_round_minMag, false, &floored); | ||
| 2695 | return !extF80M_eq(&floored, &const_val->data.x_f80); | ||
| 2696 | } | ||
| 2691 | case 128: | 2697 | case 128: |
| 2692 | { | 2698 | { |
| 2693 | float128_t floored; | 2699 | float128_t floored; |
| ... | @@ -2716,6 +2722,15 @@ static void float_append_buf(Buf *buf, ZigValue *const_val) { | ... | @@ -2716,6 +2722,15 @@ static void float_append_buf(Buf *buf, ZigValue *const_val) { |
| 2716 | case 64: | 2722 | case 64: |
| 2717 | buf_appendf(buf, "%f", const_val->data.x_f64); | 2723 | buf_appendf(buf, "%f", const_val->data.x_f64); |
| 2718 | break; | 2724 | break; |
| 2725 | case 80: | ||
| 2726 | { | ||
| 2727 | float64_t f64_value = extF80M_to_f64(&const_val->data.x_f80); | ||
| 2728 | double double_value; | ||
| 2729 | memcpy(&double_value, &f64_value, sizeof(double)); | ||
| 2730 | |||
| 2731 | buf_appendf(buf, "%f", const_val->data.x_f64); | ||
| 2732 | break; | ||
| 2733 | } | ||
| 2719 | case 128: | 2734 | case 128: |
| 2720 | { | 2735 | { |
| 2721 | // TODO actual implementation | 2736 | // TODO actual implementation |
| ... | @@ -2772,6 +2787,15 @@ static void float_init_bigint(BigInt *bigint, ZigValue *const_val) { | ... | @@ -2772,6 +2787,15 @@ static void float_init_bigint(BigInt *bigint, ZigValue *const_val) { |
| 2772 | bigint->is_negative = true; | 2787 | bigint->is_negative = true; |
| 2773 | } | 2788 | } |
| 2774 | break; | 2789 | break; |
| 2790 | case 80: | ||
| 2791 | { | ||
| 2792 | float128_t f128_value; | ||
| 2793 | extF80M_to_f128M(&const_val->data.x_f80, &f128_value); | ||
| 2794 | BigFloat tmp_float; | ||
| 2795 | bigfloat_init_128(&tmp_float, f128_value); | ||
| 2796 | bigint_init_bigfloat(bigint, &tmp_float); | ||
| 2797 | } | ||
| 2798 | break; | ||
| 2775 | case 128: | 2799 | case 128: |
| 2776 | { | 2800 | { |
| 2777 | BigFloat tmp_float; | 2801 | BigFloat tmp_float; |
| ... | @@ -2801,8 +2825,11 @@ static void float_init_bigfloat(ZigValue *dest_val, BigFloat *bigfloat) { | ... | @@ -2801,8 +2825,11 @@ static void float_init_bigfloat(ZigValue *dest_val, BigFloat *bigfloat) { |
| 2801 | case 64: | 2825 | case 64: |
| 2802 | dest_val->data.x_f64 = bigfloat_to_f64(bigfloat); | 2826 | dest_val->data.x_f64 = bigfloat_to_f64(bigfloat); |
| 2803 | break; | 2827 | break; |
| 2804 | case 80: | 2828 | case 80: { |
| 2805 | zig_panic("TODO: float_init_bigfloat c_longdouble"); | 2829 | float128_t f128_value = bigfloat_to_f128(bigfloat); |
| 2830 | f128M_to_extF80M(&f128_value, &dest_val->data.x_f80); | ||
| 2831 | break; | ||
| 2832 | } | ||
| 2806 | case 128: | 2833 | case 128: |
| 2807 | dest_val->data.x_f128 = bigfloat_to_f128(bigfloat); | 2834 | dest_val->data.x_f128 = bigfloat_to_f128(bigfloat); |
| 2808 | break; | 2835 | break; |
| ... | @@ -2828,6 +2855,9 @@ static void float_init_f16(ZigValue *dest_val, float16_t x) { | ... | @@ -2828,6 +2855,9 @@ static void float_init_f16(ZigValue *dest_val, float16_t x) { |
| 2828 | case 64: | 2855 | case 64: |
| 2829 | dest_val->data.x_f64 = zig_f16_to_double(x); | 2856 | dest_val->data.x_f64 = zig_f16_to_double(x); |
| 2830 | break; | 2857 | break; |
| 2858 | case 80: | ||
| 2859 | f16_to_extF80M(x, &dest_val->data.x_f80); | ||
| 2860 | break; | ||
| 2831 | case 128: | 2861 | case 128: |
| 2832 | f16_to_f128M(x, &dest_val->data.x_f128); | 2862 | f16_to_f128M(x, &dest_val->data.x_f128); |
| 2833 | break; | 2863 | break; |
| ... | @@ -2853,6 +2883,12 @@ static void float_init_f32(ZigValue *dest_val, float x) { | ... | @@ -2853,6 +2883,12 @@ static void float_init_f32(ZigValue *dest_val, float x) { |
| 2853 | case 64: | 2883 | case 64: |
| 2854 | dest_val->data.x_f64 = x; | 2884 | dest_val->data.x_f64 = x; |
| 2855 | break; | 2885 | break; |
| 2886 | case 80: { | ||
| 2887 | float32_t x_f32; | ||
| 2888 | memcpy(&x_f32, &x, sizeof(float)); | ||
| 2889 | f32_to_extF80M(x_f32, &dest_val->data.x_f80); | ||
| 2890 | break; | ||
| 2891 | } | ||
| 2856 | case 128: | 2892 | case 128: |
| 2857 | { | 2893 | { |
| 2858 | float32_t x_f32; | 2894 | float32_t x_f32; |
| ... | @@ -2882,6 +2918,12 @@ static void float_init_f64(ZigValue *dest_val, double x) { | ... | @@ -2882,6 +2918,12 @@ static void float_init_f64(ZigValue *dest_val, double x) { |
| 2882 | case 64: | 2918 | case 64: |
| 2883 | dest_val->data.x_f64 = x; | 2919 | dest_val->data.x_f64 = x; |
| 2884 | break; | 2920 | break; |
| 2921 | case 80: { | ||
| 2922 | float64_t x_f64; | ||
| 2923 | memcpy(&x_f64, &x, sizeof(double)); | ||
| 2924 | f64_to_extF80M(x_f64, &dest_val->data.x_f80); | ||
| 2925 | break; | ||
| 2926 | } | ||
| 2885 | case 128: | 2927 | case 128: |
| 2886 | { | 2928 | { |
| 2887 | float64_t x_f64; | 2929 | float64_t x_f64; |
| ... | @@ -2917,6 +2959,9 @@ static void float_init_f128(ZigValue *dest_val, float128_t x) { | ... | @@ -2917,6 +2959,9 @@ static void float_init_f128(ZigValue *dest_val, float128_t x) { |
| 2917 | memcpy(&dest_val->data.x_f64, &f64_val, sizeof(double)); | 2959 | memcpy(&dest_val->data.x_f64, &f64_val, sizeof(double)); |
| 2918 | break; | 2960 | break; |
| 2919 | } | 2961 | } |
| 2962 | case 80: | ||
| 2963 | f128M_to_extF80M(&x, &dest_val->data.x_f80); | ||
| 2964 | break; | ||
| 2920 | case 128: | 2965 | case 128: |
| 2921 | { | 2966 | { |
| 2922 | memcpy(&dest_val->data.x_f128, &x, sizeof(float128_t)); | 2967 | memcpy(&dest_val->data.x_f128, &x, sizeof(float128_t)); |
| ... | @@ -2944,6 +2989,12 @@ static void float_init_float(ZigValue *dest_val, ZigValue *src_val) { | ... | @@ -2944,6 +2989,12 @@ static void float_init_float(ZigValue *dest_val, ZigValue *src_val) { |
| 2944 | case 64: | 2989 | case 64: |
| 2945 | float_init_f64(dest_val, src_val->data.x_f64); | 2990 | float_init_f64(dest_val, src_val->data.x_f64); |
| 2946 | break; | 2991 | break; |
| 2992 | case 80: { | ||
| 2993 | float128_t f128_value; | ||
| 2994 | extF80M_to_f128M(&src_val->data.x_f80, &f128_value); | ||
| 2995 | float_init_f128(dest_val, f128_value); | ||
| 2996 | break; | ||
| 2997 | } | ||
| 2947 | case 128: | 2998 | case 128: |
| 2948 | float_init_f128(dest_val, src_val->data.x_f128); | 2999 | float_init_f128(dest_val, src_val->data.x_f128); |
| 2949 | break; | 3000 | break; |
| ... | @@ -2966,6 +3017,8 @@ static bool float_is_nan(ZigValue *op) { | ... | @@ -2966,6 +3017,8 @@ static bool float_is_nan(ZigValue *op) { |
| 2966 | return op->data.x_f32 != op->data.x_f32; | 3017 | return op->data.x_f32 != op->data.x_f32; |
| 2967 | case 64: | 3018 | case 64: |
| 2968 | return op->data.x_f64 != op->data.x_f64; | 3019 | return op->data.x_f64 != op->data.x_f64; |
| 3020 | case 80: | ||
| 3021 | return zig_extF80_isNaN(&op->data.x_f80); | ||
| 2969 | case 128: | 3022 | case 128: |
| 2970 | return zig_f128_isNaN(&op->data.x_f128); | 3023 | return zig_f128_isNaN(&op->data.x_f128); |
| 2971 | default: | 3024 | default: |
| ... | @@ -3006,6 +3059,14 @@ static Cmp float_cmp(ZigValue *op1, ZigValue *op2) { | ... | @@ -3006,6 +3059,14 @@ static Cmp float_cmp(ZigValue *op1, ZigValue *op2) { |
| 3006 | } else { | 3059 | } else { |
| 3007 | return CmpEQ; | 3060 | return CmpEQ; |
| 3008 | } | 3061 | } |
| 3062 | case 80: | ||
| 3063 | if (extF80M_lt(&op1->data.x_f80, &op2->data.x_f80)) { | ||
| 3064 | return CmpLT; | ||
| 3065 | } else if (extF80M_eq(&op1->data.x_f80, &op2->data.x_f80)) { | ||
| 3066 | return CmpEQ; | ||
| 3067 | } else { | ||
| 3068 | return CmpGT; | ||
| 3069 | } | ||
| 3009 | case 128: | 3070 | case 128: |
| 3010 | if (f128M_lt(&op1->data.x_f128, &op2->data.x_f128)) { | 3071 | if (f128M_lt(&op1->data.x_f128, &op2->data.x_f128)) { |
| 3011 | return CmpLT; | 3072 | return CmpLT; |
| ... | @@ -3061,7 +3122,18 @@ static Cmp float_cmp_zero(ZigValue *op) { | ... | @@ -3061,7 +3122,18 @@ static Cmp float_cmp_zero(ZigValue *op) { |
| 3061 | } else { | 3122 | } else { |
| 3062 | return CmpEQ; | 3123 | return CmpEQ; |
| 3063 | } | 3124 | } |
| 3064 | case 128: | 3125 | case 80: { |
| 3126 | extFloat80_t zero_float; | ||
| 3127 | ui32_to_extF80M(0, &zero_float); | ||
| 3128 | if (extF80M_lt(&op->data.x_f80, &zero_float)) { | ||
| 3129 | return CmpLT; | ||
| 3130 | } else if (extF80M_eq(&op->data.x_f80, &zero_float)) { | ||
| 3131 | return CmpEQ; | ||
| 3132 | } else { | ||
| 3133 | return CmpGT; | ||
| 3134 | } | ||
| 3135 | } | ||
| 3136 | case 128: { | ||
| 3065 | float128_t zero_float; | 3137 | float128_t zero_float; |
| 3066 | ui32_to_f128M(0, &zero_float); | 3138 | ui32_to_f128M(0, &zero_float); |
| 3067 | if (f128M_lt(&op->data.x_f128, &zero_float)) { | 3139 | if (f128M_lt(&op->data.x_f128, &zero_float)) { |
| ... | @@ -3071,6 +3143,7 @@ static Cmp float_cmp_zero(ZigValue *op) { | ... | @@ -3071,6 +3143,7 @@ static Cmp float_cmp_zero(ZigValue *op) { |
| 3071 | } else { | 3143 | } else { |
| 3072 | return CmpGT; | 3144 | return CmpGT; |
| 3073 | } | 3145 | } |
| 3146 | } | ||
| 3074 | default: | 3147 | default: |
| 3075 | zig_unreachable(); | 3148 | zig_unreachable(); |
| 3076 | } | 3149 | } |
| ... | @@ -3095,6 +3168,9 @@ static void float_add(ZigValue *out_val, ZigValue *op1, ZigValue *op2) { | ... | @@ -3095,6 +3168,9 @@ static void float_add(ZigValue *out_val, ZigValue *op1, ZigValue *op2) { |
| 3095 | case 64: | 3168 | case 64: |
| 3096 | out_val->data.x_f64 = op1->data.x_f64 + op2->data.x_f64; | 3169 | out_val->data.x_f64 = op1->data.x_f64 + op2->data.x_f64; |
| 3097 | return; | 3170 | return; |
| 3171 | case 80: | ||
| 3172 | extF80M_add(&op1->data.x_f80, &op2->data.x_f80, &out_val->data.x_f80); | ||
| 3173 | return; | ||
| 3098 | case 128: | 3174 | case 128: |
| 3099 | f128M_add(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128); | 3175 | f128M_add(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128); |
| 3100 | return; | 3176 | return; |
| ... | @@ -3122,6 +3198,9 @@ static void float_sub(ZigValue *out_val, ZigValue *op1, ZigValue *op2) { | ... | @@ -3122,6 +3198,9 @@ static void float_sub(ZigValue *out_val, ZigValue *op1, ZigValue *op2) { |
| 3122 | case 64: | 3198 | case 64: |
| 3123 | out_val->data.x_f64 = op1->data.x_f64 - op2->data.x_f64; | 3199 | out_val->data.x_f64 = op1->data.x_f64 - op2->data.x_f64; |
| 3124 | return; | 3200 | return; |
| 3201 | case 80: | ||
| 3202 | extF80M_sub(&op1->data.x_f80, &op2->data.x_f80, &out_val->data.x_f80); | ||
| 3203 | return; | ||
| 3125 | case 128: | 3204 | case 128: |
| 3126 | f128M_sub(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128); | 3205 | f128M_sub(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128); |
| 3127 | return; | 3206 | return; |
| ... | @@ -3149,6 +3228,9 @@ static void float_mul(ZigValue *out_val, ZigValue *op1, ZigValue *op2) { | ... | @@ -3149,6 +3228,9 @@ static void float_mul(ZigValue *out_val, ZigValue *op1, ZigValue *op2) { |
| 3149 | case 64: | 3228 | case 64: |
| 3150 | out_val->data.x_f64 = op1->data.x_f64 * op2->data.x_f64; | 3229 | out_val->data.x_f64 = op1->data.x_f64 * op2->data.x_f64; |
| 3151 | return; | 3230 | return; |
| 3231 | case 80: | ||
| 3232 | extF80M_mul(&op1->data.x_f80, &op2->data.x_f80, &out_val->data.x_f80); | ||
| 3233 | return; | ||
| 3152 | case 128: | 3234 | case 128: |
| 3153 | f128M_mul(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128); | 3235 | f128M_mul(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128); |
| 3154 | return; | 3236 | return; |
| ... | @@ -3176,6 +3258,9 @@ static void float_div(ZigValue *out_val, ZigValue *op1, ZigValue *op2) { | ... | @@ -3176,6 +3258,9 @@ static void float_div(ZigValue *out_val, ZigValue *op1, ZigValue *op2) { |
| 3176 | case 64: | 3258 | case 64: |
| 3177 | out_val->data.x_f64 = op1->data.x_f64 / op2->data.x_f64; | 3259 | out_val->data.x_f64 = op1->data.x_f64 / op2->data.x_f64; |
| 3178 | return; | 3260 | return; |
| 3261 | case 80: | ||
| 3262 | extF80M_div(&op1->data.x_f80, &op2->data.x_f80, &out_val->data.x_f80); | ||
| 3263 | return; | ||
| 3179 | case 128: | 3264 | case 128: |
| 3180 | f128M_div(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128); | 3265 | f128M_div(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128); |
| 3181 | return; | 3266 | return; |
| ... | @@ -3204,6 +3289,10 @@ static void float_div_trunc(ZigValue *out_val, ZigValue *op1, ZigValue *op2) { | ... | @@ -3204,6 +3289,10 @@ static void float_div_trunc(ZigValue *out_val, ZigValue *op1, ZigValue *op2) { |
| 3204 | case 64: | 3289 | case 64: |
| 3205 | out_val->data.x_f64 = trunc(op1->data.x_f64 / op2->data.x_f64); | 3290 | out_val->data.x_f64 = trunc(op1->data.x_f64 / op2->data.x_f64); |
| 3206 | return; | 3291 | return; |
| 3292 | case 80: | ||
| 3293 | extF80M_div(&op1->data.x_f80, &op2->data.x_f80, &out_val->data.x_f80); | ||
| 3294 | extF80M_roundToInt(&out_val->data.x_f80, softfloat_round_minMag, false, &out_val->data.x_f80); | ||
| 3295 | return; | ||
| 3207 | case 128: | 3296 | case 128: |
| 3208 | f128M_div(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128); | 3297 | f128M_div(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128); |
| 3209 | f128M_roundToInt(&out_val->data.x_f128, softfloat_round_minMag, false, &out_val->data.x_f128); | 3298 | f128M_roundToInt(&out_val->data.x_f128, softfloat_round_minMag, false, &out_val->data.x_f128); |
| ... | @@ -3233,6 +3322,10 @@ static void float_div_floor(ZigValue *out_val, ZigValue *op1, ZigValue *op2) { | ... | @@ -3233,6 +3322,10 @@ static void float_div_floor(ZigValue *out_val, ZigValue *op1, ZigValue *op2) { |
| 3233 | case 64: | 3322 | case 64: |
| 3234 | out_val->data.x_f64 = floor(op1->data.x_f64 / op2->data.x_f64); | 3323 | out_val->data.x_f64 = floor(op1->data.x_f64 / op2->data.x_f64); |
| 3235 | return; | 3324 | return; |
| 3325 | case 80: | ||
| 3326 | extF80M_div(&op1->data.x_f80, &op2->data.x_f80, &out_val->data.x_f80); | ||
| 3327 | extF80M_roundToInt(&out_val->data.x_f80, softfloat_round_min, false, &out_val->data.x_f80); | ||
| 3328 | return; | ||
| 3236 | case 128: | 3329 | case 128: |
| 3237 | f128M_div(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128); | 3330 | f128M_div(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128); |
| 3238 | f128M_roundToInt(&out_val->data.x_f128, softfloat_round_min, false, &out_val->data.x_f128); | 3331 | f128M_roundToInt(&out_val->data.x_f128, softfloat_round_min, false, &out_val->data.x_f128); |
| ... | @@ -3261,6 +3354,9 @@ static void float_rem(ZigValue *out_val, ZigValue *op1, ZigValue *op2) { | ... | @@ -3261,6 +3354,9 @@ static void float_rem(ZigValue *out_val, ZigValue *op1, ZigValue *op2) { |
| 3261 | case 64: | 3354 | case 64: |
| 3262 | out_val->data.x_f64 = fmod(op1->data.x_f64, op2->data.x_f64); | 3355 | out_val->data.x_f64 = fmod(op1->data.x_f64, op2->data.x_f64); |
| 3263 | return; | 3356 | return; |
| 3357 | case 80: | ||
| 3358 | extF80M_rem(&op1->data.x_f80, &op2->data.x_f80, &out_val->data.x_f80); | ||
| 3359 | return; | ||
| 3264 | case 128: | 3360 | case 128: |
| 3265 | f128M_rem(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128); | 3361 | f128M_rem(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128); |
| 3266 | return; | 3362 | return; |
| ... | @@ -3290,6 +3386,14 @@ static void zig_f128M_mod(const float128_t* a, const float128_t* b, float128_t* | ... | @@ -3290,6 +3386,14 @@ static void zig_f128M_mod(const float128_t* a, const float128_t* b, float128_t* |
| 3290 | f128M_sub(a, c, c); | 3386 | f128M_sub(a, c, c); |
| 3291 | } | 3387 | } |
| 3292 | 3388 | ||
| 3389 | // c = a - b * trunc(a / b) | ||
| 3390 | static void zig_extF80M_mod(const extFloat80_t* a, const extFloat80_t* b, extFloat80_t* c) { | ||
| 3391 | extF80M_div(a, b, c); | ||
| 3392 | extF80M_roundToInt(c, softfloat_round_min, true, c); | ||
| 3393 | extF80M_mul(b, c, c); | ||
| 3394 | extF80M_sub(a, c, c); | ||
| 3395 | } | ||
| 3396 | |||
| 3293 | static void float_mod(ZigValue *out_val, ZigValue *op1, ZigValue *op2) { | 3397 | static void float_mod(ZigValue *out_val, ZigValue *op1, ZigValue *op2) { |
| 3294 | assert(op1->type == op2->type); | 3398 | assert(op1->type == op2->type); |
| 3295 | out_val->type = op1->type; | 3399 | out_val->type = op1->type; |
| ... | @@ -3306,6 +3410,9 @@ static void float_mod(ZigValue *out_val, ZigValue *op1, ZigValue *op2) { | ... | @@ -3306,6 +3410,9 @@ static void float_mod(ZigValue *out_val, ZigValue *op1, ZigValue *op2) { |
| 3306 | case 64: | 3410 | case 64: |
| 3307 | out_val->data.x_f64 = fmod(fmod(op1->data.x_f64, op2->data.x_f64) + op2->data.x_f64, op2->data.x_f64); | 3411 | out_val->data.x_f64 = fmod(fmod(op1->data.x_f64, op2->data.x_f64) + op2->data.x_f64, op2->data.x_f64); |
| 3308 | return; | 3412 | return; |
| 3413 | case 80: | ||
| 3414 | zig_extF80M_mod(&op1->data.x_f80, &op2->data.x_f80, &out_val->data.x_f80); | ||
| 3415 | return; | ||
| 3309 | case 128: | 3416 | case 128: |
| 3310 | zig_f128M_mod(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128); | 3417 | zig_f128M_mod(&op1->data.x_f128, &op2->data.x_f128, &out_val->data.x_f128); |
| 3311 | return; | 3418 | return; |
| ... | @@ -3351,6 +3458,15 @@ static void float_max(ZigValue *out_val, ZigValue *op1, ZigValue *op2) { | ... | @@ -3351,6 +3458,15 @@ static void float_max(ZigValue *out_val, ZigValue *op1, ZigValue *op2) { |
| 3351 | out_val->data.x_f64 = op1->data.x_f64 > op2->data.x_f64 ? op1->data.x_f64 : op2->data.x_f64; | 3458 | out_val->data.x_f64 = op1->data.x_f64 > op2->data.x_f64 ? op1->data.x_f64 : op2->data.x_f64; |
| 3352 | } | 3459 | } |
| 3353 | return; | 3460 | return; |
| 3461 | case 80: | ||
| 3462 | if (zig_extF80_isNaN(&op1->data.x_f80)) { | ||
| 3463 | out_val->data.x_f80 = op2->data.x_f80; | ||
| 3464 | } else if (zig_extF80_isNaN(&op2->data.x_f80)) { | ||
| 3465 | out_val->data.x_f80 = op1->data.x_f80; | ||
| 3466 | } else { | ||
| 3467 | out_val->data.x_f80 = extF80M_lt(&op1->data.x_f80, &op2->data.x_f80) ? op2->data.x_f80 : op1->data.x_f80; | ||
| 3468 | } | ||
| 3469 | return; | ||
| 3354 | case 128: | 3470 | case 128: |
| 3355 | if (zig_f128_isNaN(&op1->data.x_f128)) { | 3471 | if (zig_f128_isNaN(&op1->data.x_f128)) { |
| 3356 | out_val->data.x_f128 = op2->data.x_f128; | 3472 | out_val->data.x_f128 = op2->data.x_f128; |
| ... | @@ -3402,6 +3518,15 @@ static void float_min(ZigValue *out_val, ZigValue *op1, ZigValue *op2) { | ... | @@ -3402,6 +3518,15 @@ static void float_min(ZigValue *out_val, ZigValue *op1, ZigValue *op2) { |
| 3402 | out_val->data.x_f64 = op1->data.x_f32 < op2->data.x_f64 ? op1->data.x_f64 : op2->data.x_f64; | 3518 | out_val->data.x_f64 = op1->data.x_f32 < op2->data.x_f64 ? op1->data.x_f64 : op2->data.x_f64; |
| 3403 | } | 3519 | } |
| 3404 | return; | 3520 | return; |
| 3521 | case 80: | ||
| 3522 | if (zig_extF80_isNaN(&op1->data.x_f80)) { | ||
| 3523 | out_val->data.x_f80 = op2->data.x_f80; | ||
| 3524 | } else if (zig_extF80_isNaN(&op2->data.x_f80)) { | ||
| 3525 | out_val->data.x_f80 = op1->data.x_f80; | ||
| 3526 | } else { | ||
| 3527 | out_val->data.x_f80 = extF80M_lt(&op1->data.x_f80, &op2->data.x_f80) ? op1->data.x_f80 : op2->data.x_f80; | ||
| 3528 | } | ||
| 3529 | return; | ||
| 3405 | case 128: | 3530 | case 128: |
| 3406 | if (zig_f128_isNaN(&op1->data.x_f128)) { | 3531 | if (zig_f128_isNaN(&op1->data.x_f128)) { |
| 3407 | out_val->data.x_f128 = op2->data.x_f128; | 3532 | out_val->data.x_f128 = op2->data.x_f128; |
| ... | @@ -3434,6 +3559,9 @@ static void float_negate(ZigValue *out_val, ZigValue *op) { | ... | @@ -3434,6 +3559,9 @@ static void float_negate(ZigValue *out_val, ZigValue *op) { |
| 3434 | case 64: | 3559 | case 64: |
| 3435 | out_val->data.x_f64 = -op->data.x_f64; | 3560 | out_val->data.x_f64 = -op->data.x_f64; |
| 3436 | return; | 3561 | return; |
| 3562 | case 80: | ||
| 3563 | extF80M_neg(&op->data.x_f80, &out_val->data.x_f80); | ||
| 3564 | return; | ||
| 3437 | case 128: | 3565 | case 128: |
| 3438 | f128M_neg(&op->data.x_f128, &out_val->data.x_f128); | 3566 | f128M_neg(&op->data.x_f128, &out_val->data.x_f128); |
| 3439 | return; | 3567 | return; |
| ... | @@ -3462,6 +3590,9 @@ void float_write_ieee597(ZigValue *op, uint8_t *buf, bool target_is_big_endian) | ... | @@ -3462,6 +3590,9 @@ void float_write_ieee597(ZigValue *op, uint8_t *buf, bool target_is_big_endian) |
| 3462 | case 64: | 3590 | case 64: |
| 3463 | memcpy(buf, &op->data.x_f64, 8); | 3591 | memcpy(buf, &op->data.x_f64, 8); |
| 3464 | break; | 3592 | break; |
| 3593 | case 80: | ||
| 3594 | memcpy(buf, &op->data.x_f80, 16); | ||
| 3595 | break; | ||
| 3465 | case 128: | 3596 | case 128: |
| 3466 | memcpy(buf, &op->data.x_f128, 16); | 3597 | memcpy(buf, &op->data.x_f128, 16); |
| 3467 | break; | 3598 | break; |
| ... | @@ -3511,6 +3642,9 @@ void float_read_ieee597(ZigValue *val, uint8_t *buf, bool target_is_big_endian) | ... | @@ -3511,6 +3642,9 @@ void float_read_ieee597(ZigValue *val, uint8_t *buf, bool target_is_big_endian) |
| 3511 | case 64: | 3642 | case 64: |
| 3512 | memcpy(&val->data.x_f64, ptr, 8); | 3643 | memcpy(&val->data.x_f64, ptr, 8); |
| 3513 | return; | 3644 | return; |
| 3645 | case 80: | ||
| 3646 | memcpy(&val->data.x_f80, ptr, 16); | ||
| 3647 | return; | ||
| 3514 | case 128: | 3648 | case 128: |
| 3515 | memcpy(&val->data.x_f128, ptr, 16); | 3649 | memcpy(&val->data.x_f128, ptr, 16); |
| 3516 | return; | 3650 | return; |
| ... | @@ -3538,8 +3672,12 @@ static void value_to_bigfloat(BigFloat *out, ZigValue *val) { | ... | @@ -3538,8 +3672,12 @@ static void value_to_bigfloat(BigFloat *out, ZigValue *val) { |
| 3538 | case 64: | 3672 | case 64: |
| 3539 | bigfloat_init_64(out, val->data.x_f64); | 3673 | bigfloat_init_64(out, val->data.x_f64); |
| 3540 | return; | 3674 | return; |
| 3541 | case 80: | 3675 | case 80: { |
| 3542 | zig_panic("TODO: value_to_bigfloat c_longdouble"); | 3676 | float128_t f128_value; |
| 3677 | extF80M_to_f128M(&val->data.x_f80, &f128_value); | ||
| 3678 | bigfloat_init_128(out, f128_value); | ||
| 3679 | return; | ||
| 3680 | } | ||
| 3543 | case 128: | 3681 | case 128: |
| 3544 | bigfloat_init_128(out, val->data.x_f128); | 3682 | bigfloat_init_128(out, val->data.x_f128); |
| 3545 | return; | 3683 | return; |
| ... | @@ -3628,8 +3766,14 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, Stage1AirInst *instruc | ... | @@ -3628,8 +3766,14 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, Stage1AirInst *instruc |
| 3628 | bigfloat_init_64(&orig_bf, tmp); | 3766 | bigfloat_init_64(&orig_bf, tmp); |
| 3629 | break; | 3767 | break; |
| 3630 | } | 3768 | } |
| 3631 | case 80: | 3769 | case 80: { |
| 3632 | zig_panic("TODO: ir_num_lit_fits_in_other_type c_longdouble"); | 3770 | float128_t tmp = bigfloat_to_f128(&tmp_bf); |
| 3771 | extFloat80_t tmp80; | ||
| 3772 | f128M_to_extF80M(&tmp, &tmp80); | ||
| 3773 | extF80M_to_f128M(&tmp80, &tmp); | ||
| 3774 | bigfloat_init_128(&orig_bf, tmp); | ||
| 3775 | break; | ||
| 3776 | } | ||
| 3633 | case 128: { | 3777 | case 128: { |
| 3634 | float128_t tmp = bigfloat_to_f128(&tmp_bf); | 3778 | float128_t tmp = bigfloat_to_f128(&tmp_bf); |
| 3635 | bigfloat_init_128(&orig_bf, tmp); | 3779 | bigfloat_init_128(&orig_bf, tmp); |
| ... | @@ -3673,8 +3817,15 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, Stage1AirInst *instruc | ... | @@ -3673,8 +3817,15 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, Stage1AirInst *instruc |
| 3673 | } | 3817 | } |
| 3674 | break; | 3818 | break; |
| 3675 | } | 3819 | } |
| 3676 | case 80: | 3820 | case 80: { |
| 3677 | zig_panic("TODO: ir_num_lit_fits_in_other_type c_longdouble"); | 3821 | float16_t tmp = extF80M_to_f16(&const_val->data.x_f80); |
| 3822 | extFloat80_t orig; | ||
| 3823 | f16_to_extF80M(tmp, &orig); | ||
| 3824 | if (extF80M_eq(&orig, &const_val->data.x_f80)) { | ||
| 3825 | return true; | ||
| 3826 | } | ||
| 3827 | break; | ||
| 3828 | } | ||
| 3678 | case 128: { | 3829 | case 128: { |
| 3679 | float16_t tmp = f128M_to_f16(&const_val->data.x_f128); | 3830 | float16_t tmp = f128M_to_f16(&const_val->data.x_f128); |
| 3680 | float128_t orig; | 3831 | float128_t orig; |
| ... | @@ -3698,8 +3849,15 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, Stage1AirInst *instruc | ... | @@ -3698,8 +3849,15 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, Stage1AirInst *instruc |
| 3698 | } | 3849 | } |
| 3699 | break; | 3850 | break; |
| 3700 | } | 3851 | } |
| 3701 | case 80: | 3852 | case 80: { |
| 3702 | zig_panic("TODO: ir_num_lit_fits_in_other_type c_longdouble"); | 3853 | float32_t tmp = extF80M_to_f32(&const_val->data.x_f80); |
| 3854 | extFloat80_t orig; | ||
| 3855 | f32_to_extF80M(tmp, &orig); | ||
| 3856 | if (extF80M_eq(&orig, &const_val->data.x_f80)) { | ||
| 3857 | return true; | ||
| 3858 | } | ||
| 3859 | break; | ||
| 3860 | } | ||
| 3703 | case 128: { | 3861 | case 128: { |
| 3704 | float32_t tmp = f128M_to_f32(&const_val->data.x_f128); | 3862 | float32_t tmp = f128M_to_f32(&const_val->data.x_f128); |
| 3705 | float128_t orig; | 3863 | float128_t orig; |
| ... | @@ -3715,8 +3873,15 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, Stage1AirInst *instruc | ... | @@ -3715,8 +3873,15 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, Stage1AirInst *instruc |
| 3715 | break; | 3873 | break; |
| 3716 | case 64: | 3874 | case 64: |
| 3717 | switch (const_val->type->data.floating.bit_count) { | 3875 | switch (const_val->type->data.floating.bit_count) { |
| 3718 | case 80: | 3876 | case 80: { |
| 3719 | zig_panic("TODO: ir_num_lit_fits_in_other_type c_longdouble"); | 3877 | float64_t tmp = extF80M_to_f64(&const_val->data.x_f80); |
| 3878 | extFloat80_t orig; | ||
| 3879 | f64_to_extF80M(tmp, &orig); | ||
| 3880 | if (extF80M_eq(&orig, &const_val->data.x_f80)) { | ||
| 3881 | return true; | ||
| 3882 | } | ||
| 3883 | break; | ||
| 3884 | } | ||
| 3720 | case 128: { | 3885 | case 128: { |
| 3721 | float64_t tmp = f128M_to_f64(&const_val->data.x_f128); | 3886 | float64_t tmp = f128M_to_f64(&const_val->data.x_f128); |
| 3722 | float128_t orig; | 3887 | float128_t orig; |
| ... | @@ -3730,9 +3895,17 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, Stage1AirInst *instruc | ... | @@ -3730,9 +3895,17 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, Stage1AirInst *instruc |
| 3730 | zig_unreachable(); | 3895 | zig_unreachable(); |
| 3731 | } | 3896 | } |
| 3732 | break; | 3897 | break; |
| 3733 | case 80: | 3898 | case 80: { |
| 3734 | assert(const_val->type->data.floating.bit_count == 128); | 3899 | assert(const_val->type->data.floating.bit_count == 128); |
| 3735 | zig_panic("TODO: ir_num_lit_fits_in_other_type c_longdouble"); | 3900 | extFloat80_t tmp; |
| 3901 | f128M_to_extF80M(&const_val->data.x_f128, &tmp); | ||
| 3902 | float128_t orig; | ||
| 3903 | extF80M_to_f128M(&tmp, &orig); | ||
| 3904 | if (f128M_eq(&orig, &const_val->data.x_f128)) { | ||
| 3905 | return true; | ||
| 3906 | } | ||
| 3907 | break; | ||
| 3908 | } | ||
| 3736 | case 128: | 3909 | case 128: |
| 3737 | return true; | 3910 | return true; |
| 3738 | default: | 3911 | default: |
| ... | @@ -5143,8 +5316,11 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, Scope *scope, AstNode | ... | @@ -5143,8 +5316,11 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, Scope *scope, AstNode |
| 5143 | case 64: | 5316 | case 64: |
| 5144 | const_val->data.x_f64 = bigfloat_to_f64(&other_val->data.x_bigfloat); | 5317 | const_val->data.x_f64 = bigfloat_to_f64(&other_val->data.x_bigfloat); |
| 5145 | break; | 5318 | break; |
| 5146 | case 80: | 5319 | case 80: { |
| 5147 | zig_panic("TODO: eval_const_expr_implicit_cast c_longdouble"); | 5320 | float128_t tmp = bigfloat_to_f128(&other_val->data.x_bigfloat); |
| 5321 | f128M_to_extF80M(&tmp, &const_val->data.x_f80); | ||
| 5322 | break; | ||
| 5323 | } | ||
| 5148 | case 128: | 5324 | case 128: |
| 5149 | const_val->data.x_f128 = bigfloat_to_f128(&other_val->data.x_bigfloat); | 5325 | const_val->data.x_f128 = bigfloat_to_f128(&other_val->data.x_bigfloat); |
| 5150 | break; | 5326 | break; |
| ... | @@ -5172,8 +5348,11 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, Scope *scope, AstNode | ... | @@ -5172,8 +5348,11 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, Scope *scope, AstNode |
| 5172 | case 64: | 5348 | case 64: |
| 5173 | const_val->data.x_f64 = bigfloat_to_f64(&bigfloat); | 5349 | const_val->data.x_f64 = bigfloat_to_f64(&bigfloat); |
| 5174 | break; | 5350 | break; |
| 5175 | case 80: | 5351 | case 80: { |
| 5176 | zig_panic("TODO: eval_const_expr_implicit_cast c_longdouble"); | 5352 | float128_t tmp = bigfloat_to_f128(&other_val->data.x_bigfloat); |
| 5353 | f128M_to_extF80M(&tmp, &const_val->data.x_f80); | ||
| 5354 | break; | ||
| 5355 | } | ||
| 5177 | case 128: | 5356 | case 128: |
| 5178 | const_val->data.x_f128 = bigfloat_to_f128(&bigfloat); | 5357 | const_val->data.x_f128 = bigfloat_to_f128(&bigfloat); |
| 5179 | break; | 5358 | break; |
| ... | @@ -18960,6 +19139,7 @@ static ZigType *type_info_to_type(IrAnalyze *ira, Scope *scope, AstNode *source_ | ... | @@ -18960,6 +19139,7 @@ static ZigType *type_info_to_type(IrAnalyze *ira, Scope *scope, AstNode *source_ |
| 18960 | case 16: return ira->codegen->builtin_types.entry_f16; | 19139 | case 16: return ira->codegen->builtin_types.entry_f16; |
| 18961 | case 32: return ira->codegen->builtin_types.entry_f32; | 19140 | case 32: return ira->codegen->builtin_types.entry_f32; |
| 18962 | case 64: return ira->codegen->builtin_types.entry_f64; | 19141 | case 64: return ira->codegen->builtin_types.entry_f64; |
| 19142 | case 80: return ira->codegen->builtin_types.entry_f80; | ||
| 18963 | case 128: return ira->codegen->builtin_types.entry_f128; | 19143 | case 128: return ira->codegen->builtin_types.entry_f128; |
| 18964 | } | 19144 | } |
| 18965 | ir_add_error_node(ira, source_node, buf_sprintf("%d-bit float unsupported", bits)); | 19145 | ir_add_error_node(ira, source_node, buf_sprintf("%d-bit float unsupported", bits)); |
| ... | @@ -21943,6 +22123,8 @@ static void ir_eval_mul_add(IrAnalyze *ira, ZigType *float_type, | ... | @@ -21943,6 +22123,8 @@ static void ir_eval_mul_add(IrAnalyze *ira, ZigType *float_type, |
| 21943 | case 64: | 22123 | case 64: |
| 21944 | out_val->data.x_f64 = fma(op1->data.x_f64, op2->data.x_f64, op3->data.x_f64); | 22124 | out_val->data.x_f64 = fma(op1->data.x_f64, op2->data.x_f64, op3->data.x_f64); |
| 21945 | break; | 22125 | break; |
| 22126 | case 80: | ||
| 22127 | zig_panic("compiler bug: TODO: implement 'mulAdd' for type 'f80'. See https://github.com/ziglang/zig/issues/4026"); | ||
| 21946 | case 128: | 22128 | case 128: |
| 21947 | f128M_mulAdd(&op1->data.x_f128, &op2->data.x_f128, &op3->data.x_f128, &out_val->data.x_f128); | 22129 | f128M_mulAdd(&op1->data.x_f128, &op2->data.x_f128, &op3->data.x_f128, &out_val->data.x_f128); |
| 21948 | break; | 22130 | break; |
| ... | @@ -24156,10 +24338,44 @@ static ErrorMsg *ir_eval_float_op(IrAnalyze *ira, Scope *scope, AstNode *source_ | ... | @@ -24156,10 +24338,44 @@ static ErrorMsg *ir_eval_float_op(IrAnalyze *ira, Scope *scope, AstNode *source_ |
| 24156 | } | 24338 | } |
| 24157 | break; | 24339 | break; |
| 24158 | } | 24340 | } |
| 24159 | case 80: | 24341 | case 80: { |
| 24160 | return ir_add_error_node(ira, source_node, | 24342 | extFloat80_t *out = &out_val->data.x_f80; |
| 24161 | buf_sprintf("compiler bug: TODO: implement '%s' for type '%s'. See https://github.com/ziglang/zig/issues/4026", | 24343 | extFloat80_t *in = &op->data.x_f80; |
| 24162 | float_op_to_name(fop), buf_ptr(&float_type->name))); | 24344 | switch (fop) { |
| 24345 | case BuiltinFnIdSqrt: | ||
| 24346 | extF80M_sqrt(in, out); | ||
| 24347 | break; | ||
| 24348 | case BuiltinFnIdFabs: | ||
| 24349 | extF80M_abs(in, out); | ||
| 24350 | break; | ||
| 24351 | case BuiltinFnIdFloor: | ||
| 24352 | extF80M_roundToInt(in, softfloat_round_min, false, out); | ||
| 24353 | break; | ||
| 24354 | case BuiltinFnIdCeil: | ||
| 24355 | extF80M_roundToInt(in, softfloat_round_max, false, out); | ||
| 24356 | break; | ||
| 24357 | case BuiltinFnIdTrunc: | ||
| 24358 | extF80M_trunc(in, out); | ||
| 24359 | break; | ||
| 24360 | case BuiltinFnIdRound: | ||
| 24361 | extF80M_roundToInt(in, softfloat_round_near_maxMag, false, out); | ||
| 24362 | break; | ||
| 24363 | case BuiltinFnIdNearbyInt: | ||
| 24364 | case BuiltinFnIdSin: | ||
| 24365 | case BuiltinFnIdCos: | ||
| 24366 | case BuiltinFnIdExp: | ||
| 24367 | case BuiltinFnIdExp2: | ||
| 24368 | case BuiltinFnIdLog: | ||
| 24369 | case BuiltinFnIdLog10: | ||
| 24370 | case BuiltinFnIdLog2: | ||
| 24371 | return ir_add_error_node(ira, source_node, | ||
| 24372 | buf_sprintf("compiler bug: TODO: implement '%s' for type '%s'. See https://github.com/ziglang/zig/issues/4026", | ||
| 24373 | float_op_to_name(fop), buf_ptr(&float_type->name))); | ||
| 24374 | default: | ||
| 24375 | zig_unreachable(); | ||
| 24376 | } | ||
| 24377 | break; | ||
| 24378 | } | ||
| 24163 | case 128: { | 24379 | case 128: { |
| 24164 | float128_t *out, *in; | 24380 | float128_t *out, *in; |
| 24165 | if (float_type->id == ZigTypeIdComptimeFloat) { | 24381 | if (float_type->id == ZigTypeIdComptimeFloat) { |
src/stage1/softfloat.hpp+4| ... | @@ -56,4 +56,8 @@ static inline bool zig_f128_isNaN(float128_t *aPtr) { | ... | @@ -56,4 +56,8 @@ static inline bool zig_f128_isNaN(float128_t *aPtr) { |
| 56 | || ((absA64 == UINT64_C(0x7FFF000000000000)) && lo); | 56 | || ((absA64 == UINT64_C(0x7FFF000000000000)) && lo); |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | static inline bool zig_extF80_isNaN(extFloat80_t *aPtr) { | ||
| 60 | return (aPtr->signExp & 0x7FFF) == 0x7FFF && aPtr->signif & UINT64_C(0x7FFFFFFFFFFFFFFF); | ||
| 61 | } | ||
| 62 | |||
| 59 | #endif | 63 | #endif |
src/stage1/softfloat_ext.cpp+30-8| ... | @@ -28,13 +28,6 @@ void f128M_trunc(const float128_t *aPtr, float128_t *zPtr) { | ... | @@ -28,13 +28,6 @@ void f128M_trunc(const float128_t *aPtr, float128_t *zPtr) { |
| 28 | } | 28 | } |
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | float16_t f16_neg(const float16_t a) { | ||
| 32 | union { uint16_t ui; float16_t f; } uA; | ||
| 33 | // Toggle the sign bit. | ||
| 34 | uA.ui = a.v ^ (UINT16_C(1) << 15); | ||
| 35 | return uA.f; | ||
| 36 | } | ||
| 37 | |||
| 38 | void f128M_neg(const float128_t *aPtr, float128_t *zPtr) { | 31 | void f128M_neg(const float128_t *aPtr, float128_t *zPtr) { |
| 39 | // Toggle the sign bit. | 32 | // Toggle the sign bit. |
| 40 | #if ZIG_BYTE_ORDER == ZIG_LITTLE_ENDIAN | 33 | #if ZIG_BYTE_ORDER == ZIG_LITTLE_ENDIAN |
| ... | @@ -46,4 +39,33 @@ void f128M_neg(const float128_t *aPtr, float128_t *zPtr) { | ... | @@ -46,4 +39,33 @@ void f128M_neg(const float128_t *aPtr, float128_t *zPtr) { |
| 46 | #else | 39 | #else |
| 47 | #error Unsupported endian | 40 | #error Unsupported endian |
| 48 | #endif | 41 | #endif |
| 49 | } | ||
| \ No newline at end of file | |||
| 42 | } | ||
| 43 | |||
| 44 | void extF80M_abs(const extFloat80_t *aPtr, extFloat80_t *zPtr) { | ||
| 45 | // Clear the sign bit. | ||
| 46 | zPtr->signExp = aPtr->signExp & UINT16_C(0x7FFF); | ||
| 47 | zPtr->signif = aPtr->signif; | ||
| 48 | } | ||
| 49 | |||
| 50 | void extF80M_trunc(const extFloat80_t *aPtr, extFloat80_t *zPtr) { | ||
| 51 | extFloat80_t zero_float; | ||
| 52 | ui32_to_extF80M(0, &zero_float); | ||
| 53 | if (extF80M_lt(aPtr, &zero_float)) { | ||
| 54 | extF80M_roundToInt(aPtr, softfloat_round_max, false, zPtr); | ||
| 55 | } else { | ||
| 56 | extF80M_roundToInt(aPtr, softfloat_round_min, false, zPtr); | ||
| 57 | } | ||
| 58 | } | ||
| 59 | |||
| 60 | void extF80M_neg(const extFloat80_t *aPtr, extFloat80_t *zPtr) { | ||
| 61 | // Toggle the sign bit. | ||
| 62 | zPtr->signExp = aPtr->signExp ^ UINT16_C(0x8000); | ||
| 63 | zPtr->signif = aPtr->signif; | ||
| 64 | } | ||
| 65 | |||
| 66 | float16_t f16_neg(const float16_t a) { | ||
| 67 | union { uint16_t ui; float16_t f; } uA; | ||
| 68 | // Toggle the sign bit. | ||
| 69 | uA.ui = a.v ^ (UINT16_C(1) << 15); | ||
| 70 | return uA.f; | ||
| 71 | } | ||
src/stage1/softfloat_ext.hpp+4| ... | @@ -7,6 +7,10 @@ void f128M_abs(const float128_t *aPtr, float128_t *zPtr); | ... | @@ -7,6 +7,10 @@ void f128M_abs(const float128_t *aPtr, float128_t *zPtr); |
| 7 | void f128M_trunc(const float128_t *aPtr, float128_t *zPtr); | 7 | void f128M_trunc(const float128_t *aPtr, float128_t *zPtr); |
| 8 | void f128M_neg(const float128_t *aPtr, float128_t *zPtr); | 8 | void f128M_neg(const float128_t *aPtr, float128_t *zPtr); |
| 9 | 9 | ||
| 10 | void extF80M_abs(const extFloat80_t *aPtr, extFloat80_t *zPtr); | ||
| 11 | void extF80M_trunc(const extFloat80_t *aPtr, extFloat80_t *zPtr); | ||
| 12 | void extF80M_neg(const extFloat80_t *aPtr, extFloat80_t *zPtr); | ||
| 13 | |||
| 10 | float16_t f16_neg(const float16_t a); | 14 | float16_t f16_neg(const float16_t a); |
| 11 | 15 | ||
| 12 | #endif | 16 | #endif |
| \ No newline at end of file | |||
src/stage1/target.cpp+11| ... | @@ -1019,6 +1019,17 @@ bool target_long_double_is_f128(const ZigTarget *target) { | ... | @@ -1019,6 +1019,17 @@ bool target_long_double_is_f128(const ZigTarget *target) { |
| 1019 | } | 1019 | } |
| 1020 | } | 1020 | } |
| 1021 | 1021 | ||
| 1022 | bool target_has_f80(const ZigTarget *target) { | ||
| 1023 | switch (target->arch) { | ||
| 1024 | case ZigLLVM_x86: | ||
| 1025 | case ZigLLVM_x86_64: | ||
| 1026 | return true; | ||
| 1027 | |||
| 1028 | default: | ||
| 1029 | return false; | ||
| 1030 | } | ||
| 1031 | } | ||
| 1032 | |||
| 1022 | bool target_is_riscv(const ZigTarget *target) { | 1033 | bool target_is_riscv(const ZigTarget *target) { |
| 1023 | return target->arch == ZigLLVM_riscv32 || target->arch == ZigLLVM_riscv64; | 1034 | return target->arch == ZigLLVM_riscv32 || target->arch == ZigLLVM_riscv64; |
| 1024 | } | 1035 | } |
src/stage1/target.hpp+1| ... | @@ -81,6 +81,7 @@ bool target_is_sparc(const ZigTarget *target); | ... | @@ -81,6 +81,7 @@ bool target_is_sparc(const ZigTarget *target); |
| 81 | bool target_is_android(const ZigTarget *target); | 81 | bool target_is_android(const ZigTarget *target); |
| 82 | bool target_has_debug_info(const ZigTarget *target); | 82 | bool target_has_debug_info(const ZigTarget *target); |
| 83 | bool target_long_double_is_f128(const ZigTarget *target); | 83 | bool target_long_double_is_f128(const ZigTarget *target); |
| 84 | bool target_has_f80(const ZigTarget *target); | ||
| 84 | 85 | ||
| 85 | uint32_t target_arch_pointer_bit_width(ZigLLVM_ArchType arch); | 86 | uint32_t target_arch_pointer_bit_width(ZigLLVM_ArchType arch); |
| 86 | uint32_t target_arch_largest_atomic_bits(ZigLLVM_ArchType arch); | 87 | uint32_t target_arch_largest_atomic_bits(ZigLLVM_ArchType arch); |
src/type.zig+17| ... | @@ -58,6 +58,7 @@ pub const Type = extern union { | ... | @@ -58,6 +58,7 @@ pub const Type = extern union { |
| 58 | .f16, | 58 | .f16, |
| 59 | .f32, | 59 | .f32, |
| 60 | .f64, | 60 | .f64, |
| 61 | .f80, | ||
| 61 | .f128, | 62 | .f128, |
| 62 | .c_longdouble, | 63 | .c_longdouble, |
| 63 | => return .Float, | 64 | => return .Float, |
| ... | @@ -833,6 +834,7 @@ pub const Type = extern union { | ... | @@ -833,6 +834,7 @@ pub const Type = extern union { |
| 833 | .f16, | 834 | .f16, |
| 834 | .f32, | 835 | .f32, |
| 835 | .f64, | 836 | .f64, |
| 837 | .f80, | ||
| 836 | .f128, | 838 | .f128, |
| 837 | .bool, | 839 | .bool, |
| 838 | .void, | 840 | .void, |
| ... | @@ -1053,6 +1055,7 @@ pub const Type = extern union { | ... | @@ -1053,6 +1055,7 @@ pub const Type = extern union { |
| 1053 | .f16, | 1055 | .f16, |
| 1054 | .f32, | 1056 | .f32, |
| 1055 | .f64, | 1057 | .f64, |
| 1058 | .f80, | ||
| 1056 | .f128, | 1059 | .f128, |
| 1057 | .bool, | 1060 | .bool, |
| 1058 | .void, | 1061 | .void, |
| ... | @@ -1371,6 +1374,7 @@ pub const Type = extern union { | ... | @@ -1371,6 +1374,7 @@ pub const Type = extern union { |
| 1371 | .f16, | 1374 | .f16, |
| 1372 | .f32, | 1375 | .f32, |
| 1373 | .f64, | 1376 | .f64, |
| 1377 | .f80, | ||
| 1374 | .f128, | 1378 | .f128, |
| 1375 | .bool, | 1379 | .bool, |
| 1376 | .void, | 1380 | .void, |
| ... | @@ -1473,6 +1477,7 @@ pub const Type = extern union { | ... | @@ -1473,6 +1477,7 @@ pub const Type = extern union { |
| 1473 | .f16 => return Value.initTag(.f16_type), | 1477 | .f16 => return Value.initTag(.f16_type), |
| 1474 | .f32 => return Value.initTag(.f32_type), | 1478 | .f32 => return Value.initTag(.f32_type), |
| 1475 | .f64 => return Value.initTag(.f64_type), | 1479 | .f64 => return Value.initTag(.f64_type), |
| 1480 | .f80 => return Value.initTag(.f80_type), | ||
| 1476 | .f128 => return Value.initTag(.f128_type), | 1481 | .f128 => return Value.initTag(.f128_type), |
| 1477 | .bool => return Value.initTag(.bool_type), | 1482 | .bool => return Value.initTag(.bool_type), |
| 1478 | .void => return Value.initTag(.void_type), | 1483 | .void => return Value.initTag(.void_type), |
| ... | @@ -1543,6 +1548,7 @@ pub const Type = extern union { | ... | @@ -1543,6 +1548,7 @@ pub const Type = extern union { |
| 1543 | .f16, | 1548 | .f16, |
| 1544 | .f32, | 1549 | .f32, |
| 1545 | .f64, | 1550 | .f64, |
| 1551 | .f80, | ||
| 1546 | .f128, | 1552 | .f128, |
| 1547 | .bool, | 1553 | .bool, |
| 1548 | .anyerror, | 1554 | .anyerror, |
| ... | @@ -1858,6 +1864,7 @@ pub const Type = extern union { | ... | @@ -1858,6 +1864,7 @@ pub const Type = extern union { |
| 1858 | .f16 => return 2, | 1864 | .f16 => return 2, |
| 1859 | .f32 => return 4, | 1865 | .f32 => return 4, |
| 1860 | .f64 => return 8, | 1866 | .f64 => return 8, |
| 1867 | .f80 => return 16, | ||
| 1861 | .f128 => return 16, | 1868 | .f128 => return 16, |
| 1862 | .c_longdouble => return 16, | 1869 | .c_longdouble => return 16, |
| 1863 | 1870 | ||
| ... | @@ -2138,6 +2145,7 @@ pub const Type = extern union { | ... | @@ -2138,6 +2145,7 @@ pub const Type = extern union { |
| 2138 | .f16 => return 2, | 2145 | .f16 => return 2, |
| 2139 | .f32 => return 4, | 2146 | .f32 => return 4, |
| 2140 | .f64 => return 8, | 2147 | .f64 => return 8, |
| 2148 | .f80 => return 16, | ||
| 2141 | .f128 => return 16, | 2149 | .f128 => return 16, |
| 2142 | .c_longdouble => return 16, | 2150 | .c_longdouble => return 16, |
| 2143 | 2151 | ||
| ... | @@ -2277,6 +2285,7 @@ pub const Type = extern union { | ... | @@ -2277,6 +2285,7 @@ pub const Type = extern union { |
| 2277 | .i16, .u16, .f16 => 16, | 2285 | .i16, .u16, .f16 => 16, |
| 2278 | .i32, .u32, .f32 => 32, | 2286 | .i32, .u32, .f32 => 32, |
| 2279 | .i64, .u64, .f64 => 64, | 2287 | .i64, .u64, .f64 => 64, |
| 2288 | .f80 => 80, | ||
| 2280 | .u128, .i128, .f128 => 128, | 2289 | .u128, .i128, .f128 => 128, |
| 2281 | 2290 | ||
| 2282 | .isize, | 2291 | .isize, |
| ... | @@ -3170,6 +3179,7 @@ pub const Type = extern union { | ... | @@ -3170,6 +3179,7 @@ pub const Type = extern union { |
| 3170 | .f16, | 3179 | .f16, |
| 3171 | .f32, | 3180 | .f32, |
| 3172 | .f64, | 3181 | .f64, |
| 3182 | .f80, | ||
| 3173 | .f128, | 3183 | .f128, |
| 3174 | .c_longdouble, | 3184 | .c_longdouble, |
| 3175 | => true, | 3185 | => true, |
| ... | @@ -3184,6 +3194,7 @@ pub const Type = extern union { | ... | @@ -3184,6 +3194,7 @@ pub const Type = extern union { |
| 3184 | .f16, | 3194 | .f16, |
| 3185 | .f32, | 3195 | .f32, |
| 3186 | .f64, | 3196 | .f64, |
| 3197 | .f80, | ||
| 3187 | .f128, | 3198 | .f128, |
| 3188 | .c_longdouble, | 3199 | .c_longdouble, |
| 3189 | .comptime_float, | 3200 | .comptime_float, |
| ... | @@ -3200,6 +3211,7 @@ pub const Type = extern union { | ... | @@ -3200,6 +3211,7 @@ pub const Type = extern union { |
| 3200 | .f16 => 16, | 3211 | .f16 => 16, |
| 3201 | .f32 => 32, | 3212 | .f32 => 32, |
| 3202 | .f64 => 64, | 3213 | .f64 => 64, |
| 3214 | .f80 => 80, | ||
| 3203 | .f128, .comptime_float => 128, | 3215 | .f128, .comptime_float => 128, |
| 3204 | .c_longdouble => CType.longdouble.sizeInBits(target), | 3216 | .c_longdouble => CType.longdouble.sizeInBits(target), |
| 3205 | 3217 | ||
| ... | @@ -3340,6 +3352,7 @@ pub const Type = extern union { | ... | @@ -3340,6 +3352,7 @@ pub const Type = extern union { |
| 3340 | .f16, | 3352 | .f16, |
| 3341 | .f32, | 3353 | .f32, |
| 3342 | .f64, | 3354 | .f64, |
| 3355 | .f80, | ||
| 3343 | .f128, | 3356 | .f128, |
| 3344 | .c_longdouble, | 3357 | .c_longdouble, |
| 3345 | .comptime_int, | 3358 | .comptime_int, |
| ... | @@ -3381,6 +3394,7 @@ pub const Type = extern union { | ... | @@ -3381,6 +3394,7 @@ pub const Type = extern union { |
| 3381 | .f16, | 3394 | .f16, |
| 3382 | .f32, | 3395 | .f32, |
| 3383 | .f64, | 3396 | .f64, |
| 3397 | .f80, | ||
| 3384 | .f128, | 3398 | .f128, |
| 3385 | .c_longdouble, | 3399 | .c_longdouble, |
| 3386 | .comptime_int, | 3400 | .comptime_int, |
| ... | @@ -3579,6 +3593,7 @@ pub const Type = extern union { | ... | @@ -3579,6 +3593,7 @@ pub const Type = extern union { |
| 3579 | .f16, | 3593 | .f16, |
| 3580 | .f32, | 3594 | .f32, |
| 3581 | .f64, | 3595 | .f64, |
| 3596 | .f80, | ||
| 3582 | .f128, | 3597 | .f128, |
| 3583 | .anyopaque, | 3598 | .anyopaque, |
| 3584 | .bool, | 3599 | .bool, |
| ... | @@ -4334,6 +4349,7 @@ pub const Type = extern union { | ... | @@ -4334,6 +4349,7 @@ pub const Type = extern union { |
| 4334 | f16, | 4349 | f16, |
| 4335 | f32, | 4350 | f32, |
| 4336 | f64, | 4351 | f64, |
| 4352 | f80, | ||
| 4337 | f128, | 4353 | f128, |
| 4338 | anyopaque, | 4354 | anyopaque, |
| 4339 | bool, | 4355 | bool, |
| ... | @@ -4453,6 +4469,7 @@ pub const Type = extern union { | ... | @@ -4453,6 +4469,7 @@ pub const Type = extern union { |
| 4453 | .f16, | 4469 | .f16, |
| 4454 | .f32, | 4470 | .f32, |
| 4455 | .f64, | 4471 | .f64, |
| 4472 | .f80, | ||
| 4456 | .f128, | 4473 | .f128, |
| 4457 | .anyopaque, | 4474 | .anyopaque, |
| 4458 | .bool, | 4475 | .bool, |
src/value.zig+5| ... | @@ -47,6 +47,7 @@ pub const Value = extern union { | ... | @@ -47,6 +47,7 @@ pub const Value = extern union { |
| 47 | f16_type, | 47 | f16_type, |
| 48 | f32_type, | 48 | f32_type, |
| 49 | f64_type, | 49 | f64_type, |
| 50 | f80_type, | ||
| 50 | f128_type, | 51 | f128_type, |
| 51 | anyopaque_type, | 52 | anyopaque_type, |
| 52 | bool_type, | 53 | bool_type, |
| ... | @@ -205,6 +206,7 @@ pub const Value = extern union { | ... | @@ -205,6 +206,7 @@ pub const Value = extern union { |
| 205 | .f16_type, | 206 | .f16_type, |
| 206 | .f32_type, | 207 | .f32_type, |
| 207 | .f64_type, | 208 | .f64_type, |
| 209 | .f80_type, | ||
| 208 | .f128_type, | 210 | .f128_type, |
| 209 | .anyopaque_type, | 211 | .anyopaque_type, |
| 210 | .bool_type, | 212 | .bool_type, |
| ... | @@ -398,6 +400,7 @@ pub const Value = extern union { | ... | @@ -398,6 +400,7 @@ pub const Value = extern union { |
| 398 | .f16_type, | 400 | .f16_type, |
| 399 | .f32_type, | 401 | .f32_type, |
| 400 | .f64_type, | 402 | .f64_type, |
| 403 | .f80_type, | ||
| 401 | .f128_type, | 404 | .f128_type, |
| 402 | .anyopaque_type, | 405 | .anyopaque_type, |
| 403 | .bool_type, | 406 | .bool_type, |
| ... | @@ -630,6 +633,7 @@ pub const Value = extern union { | ... | @@ -630,6 +633,7 @@ pub const Value = extern union { |
| 630 | .f16_type => return out_stream.writeAll("f16"), | 633 | .f16_type => return out_stream.writeAll("f16"), |
| 631 | .f32_type => return out_stream.writeAll("f32"), | 634 | .f32_type => return out_stream.writeAll("f32"), |
| 632 | .f64_type => return out_stream.writeAll("f64"), | 635 | .f64_type => return out_stream.writeAll("f64"), |
| 636 | .f80_type => return out_stream.writeAll("f80"), | ||
| 633 | .f128_type => return out_stream.writeAll("f128"), | 637 | .f128_type => return out_stream.writeAll("f128"), |
| 634 | .anyopaque_type => return out_stream.writeAll("anyopaque"), | 638 | .anyopaque_type => return out_stream.writeAll("anyopaque"), |
| 635 | .bool_type => return out_stream.writeAll("bool"), | 639 | .bool_type => return out_stream.writeAll("bool"), |
| ... | @@ -824,6 +828,7 @@ pub const Value = extern union { | ... | @@ -824,6 +828,7 @@ pub const Value = extern union { |
| 824 | .f16_type => Type.initTag(.f16), | 828 | .f16_type => Type.initTag(.f16), |
| 825 | .f32_type => Type.initTag(.f32), | 829 | .f32_type => Type.initTag(.f32), |
| 826 | .f64_type => Type.initTag(.f64), | 830 | .f64_type => Type.initTag(.f64), |
| 831 | .f80_type => Type.initTag(.f80), | ||
| 827 | .f128_type => Type.initTag(.f128), | 832 | .f128_type => Type.initTag(.f128), |
| 828 | .anyopaque_type => Type.initTag(.anyopaque), | 833 | .anyopaque_type => Type.initTag(.anyopaque), |
| 829 | .bool_type => Type.initTag(.bool), | 834 | .bool_type => Type.initTag(.bool), |
test/behavior/floatop_stage1.zig+81| ... | @@ -4,6 +4,7 @@ const math = std.math; | ... | @@ -4,6 +4,7 @@ const math = std.math; |
| 4 | const pi = std.math.pi; | 4 | const pi = std.math.pi; |
| 5 | const e = std.math.e; | 5 | const e = std.math.e; |
| 6 | const Vector = std.meta.Vector; | 6 | const Vector = std.meta.Vector; |
| 7 | const has_f80_rt = @import("builtin").cpu.arch == .x86_64; | ||
| 7 | 8 | ||
| 8 | const epsilon = 0.000001; | 9 | const epsilon = 0.000001; |
| 9 | 10 | ||
| ... | @@ -27,6 +28,10 @@ fn testSqrt() !void { | ... | @@ -27,6 +28,10 @@ fn testSqrt() !void { |
| 27 | var a: f64 = 25; | 28 | var a: f64 = 25; |
| 28 | try expect(@sqrt(a) == 5); | 29 | try expect(@sqrt(a) == 5); |
| 29 | } | 30 | } |
| 31 | if (has_f80_rt) { | ||
| 32 | var a: f80 = 25; | ||
| 33 | try expect(@sqrt(a) == 5); | ||
| 34 | } | ||
| 30 | { | 35 | { |
| 31 | const a: comptime_float = 25.0; | 36 | const a: comptime_float = 25.0; |
| 32 | try expect(@sqrt(a) == 5.0); | 37 | try expect(@sqrt(a) == 5.0); |
| ... | @@ -86,6 +91,10 @@ fn testSin() !void { | ... | @@ -86,6 +91,10 @@ fn testSin() !void { |
| 86 | var a: f64 = 0; | 91 | var a: f64 = 0; |
| 87 | try expect(@sin(a) == 0); | 92 | try expect(@sin(a) == 0); |
| 88 | } | 93 | } |
| 94 | // { | ||
| 95 | // var a: f80 = 0; | ||
| 96 | // try expect(@sin(a) == 0); | ||
| 97 | // } | ||
| 89 | { | 98 | { |
| 90 | var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 3.3, 4.4 }; | 99 | var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 3.3, 4.4 }; |
| 91 | var result = @sin(v); | 100 | var result = @sin(v); |
| ... | @@ -116,6 +125,10 @@ fn testCos() !void { | ... | @@ -116,6 +125,10 @@ fn testCos() !void { |
| 116 | var a: f64 = 0; | 125 | var a: f64 = 0; |
| 117 | try expect(@cos(a) == 1); | 126 | try expect(@cos(a) == 1); |
| 118 | } | 127 | } |
| 128 | // { | ||
| 129 | // var a: f80 = 0; | ||
| 130 | // try expect(@cos(a) == 1); | ||
| 131 | // } | ||
| 119 | { | 132 | { |
| 120 | var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 3.3, 4.4 }; | 133 | var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 3.3, 4.4 }; |
| 121 | var result = @cos(v); | 134 | var result = @cos(v); |
| ... | @@ -146,6 +159,10 @@ fn testExp() !void { | ... | @@ -146,6 +159,10 @@ fn testExp() !void { |
| 146 | var a: f64 = 0; | 159 | var a: f64 = 0; |
| 147 | try expect(@exp(a) == 1); | 160 | try expect(@exp(a) == 1); |
| 148 | } | 161 | } |
| 162 | // { | ||
| 163 | // var a: f80 = 0; | ||
| 164 | // try expect(@exp(a) == 1); | ||
| 165 | // } | ||
| 149 | { | 166 | { |
| 150 | var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 }; | 167 | var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 }; |
| 151 | var result = @exp(v); | 168 | var result = @exp(v); |
| ... | @@ -176,6 +193,10 @@ fn testExp2() !void { | ... | @@ -176,6 +193,10 @@ fn testExp2() !void { |
| 176 | var a: f64 = 2; | 193 | var a: f64 = 2; |
| 177 | try expect(@exp2(a) == 4); | 194 | try expect(@exp2(a) == 4); |
| 178 | } | 195 | } |
| 196 | // { | ||
| 197 | // var a: f80 = 2; | ||
| 198 | // try expect(@exp2(a) == 4); | ||
| 199 | // } | ||
| 179 | { | 200 | { |
| 180 | var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 }; | 201 | var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 }; |
| 181 | var result = @exp2(v); | 202 | var result = @exp2(v); |
| ... | @@ -208,6 +229,10 @@ fn testLog() !void { | ... | @@ -208,6 +229,10 @@ fn testLog() !void { |
| 208 | var a: f64 = e; | 229 | var a: f64 = e; |
| 209 | try expect(@log(a) == 1 or @log(a) == @bitCast(f64, @as(u64, 0x3ff0000000000000))); | 230 | try expect(@log(a) == 1 or @log(a) == @bitCast(f64, @as(u64, 0x3ff0000000000000))); |
| 210 | } | 231 | } |
| 232 | // { | ||
| 233 | // var a: f80 = e; | ||
| 234 | // try expect(@log(a) == 1); | ||
| 235 | // } | ||
| 211 | { | 236 | { |
| 212 | var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 }; | 237 | var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 }; |
| 213 | var result = @log(v); | 238 | var result = @log(v); |
| ... | @@ -238,6 +263,10 @@ fn testLog2() !void { | ... | @@ -238,6 +263,10 @@ fn testLog2() !void { |
| 238 | var a: f64 = 4; | 263 | var a: f64 = 4; |
| 239 | try expect(@log2(a) == 2); | 264 | try expect(@log2(a) == 2); |
| 240 | } | 265 | } |
| 266 | // { | ||
| 267 | // var a: f80 = 4; | ||
| 268 | // try expect(@log2(a) == 2); | ||
| 269 | // } | ||
| 241 | { | 270 | { |
| 242 | var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 }; | 271 | var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 }; |
| 243 | var result = @log2(v); | 272 | var result = @log2(v); |
| ... | @@ -268,6 +297,10 @@ fn testLog10() !void { | ... | @@ -268,6 +297,10 @@ fn testLog10() !void { |
| 268 | var a: f64 = 1000; | 297 | var a: f64 = 1000; |
| 269 | try expect(@log10(a) == 3); | 298 | try expect(@log10(a) == 3); |
| 270 | } | 299 | } |
| 300 | // { | ||
| 301 | // var a: f80 = 1000; | ||
| 302 | // try expect(@log10(a) == 3); | ||
| 303 | // } | ||
| 271 | { | 304 | { |
| 272 | var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 }; | 305 | var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 }; |
| 273 | var result = @log10(v); | 306 | var result = @log10(v); |
| ... | @@ -304,6 +337,12 @@ fn testFabs() !void { | ... | @@ -304,6 +337,12 @@ fn testFabs() !void { |
| 304 | try expect(@fabs(a) == 2.5); | 337 | try expect(@fabs(a) == 2.5); |
| 305 | try expect(@fabs(b) == 2.5); | 338 | try expect(@fabs(b) == 2.5); |
| 306 | } | 339 | } |
| 340 | // { | ||
| 341 | // var a: f80 = -2.5; | ||
| 342 | // var b: f80 = 2.5; | ||
| 343 | // try expect(@fabs(a) == 2.5); | ||
| 344 | // try expect(@fabs(b) == 2.5); | ||
| 345 | // } | ||
| 307 | { | 346 | { |
| 308 | var v: Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 }; | 347 | var v: Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 }; |
| 309 | var result = @fabs(v); | 348 | var result = @fabs(v); |
| ... | @@ -334,6 +373,10 @@ fn testFloor() !void { | ... | @@ -334,6 +373,10 @@ fn testFloor() !void { |
| 334 | var a: f64 = 3.5; | 373 | var a: f64 = 3.5; |
| 335 | try expect(@floor(a) == 3); | 374 | try expect(@floor(a) == 3); |
| 336 | } | 375 | } |
| 376 | // { | ||
| 377 | // var a: f80 = 3.5; | ||
| 378 | // try expect(@floor(a) == 3); | ||
| 379 | // } | ||
| 337 | { | 380 | { |
| 338 | var v: Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 }; | 381 | var v: Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 }; |
| 339 | var result = @floor(v); | 382 | var result = @floor(v); |
| ... | @@ -364,6 +407,10 @@ fn testCeil() !void { | ... | @@ -364,6 +407,10 @@ fn testCeil() !void { |
| 364 | var a: f64 = 3.5; | 407 | var a: f64 = 3.5; |
| 365 | try expect(@ceil(a) == 4); | 408 | try expect(@ceil(a) == 4); |
| 366 | } | 409 | } |
| 410 | // { | ||
| 411 | // var a: f80 = 3.5; | ||
| 412 | // try expect(@ceil(a) == 4); | ||
| 413 | // } | ||
| 367 | { | 414 | { |
| 368 | var v: Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 }; | 415 | var v: Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 }; |
| 369 | var result = @ceil(v); | 416 | var result = @ceil(v); |
| ... | @@ -394,6 +441,10 @@ fn testTrunc() !void { | ... | @@ -394,6 +441,10 @@ fn testTrunc() !void { |
| 394 | var a: f64 = -3.5; | 441 | var a: f64 = -3.5; |
| 395 | try expect(@trunc(a) == -3); | 442 | try expect(@trunc(a) == -3); |
| 396 | } | 443 | } |
| 444 | // { | ||
| 445 | // var a: f80 = -3.5; | ||
| 446 | // try expect(@trunc(a) == -3); | ||
| 447 | // } | ||
| 397 | { | 448 | { |
| 398 | var v: Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 }; | 449 | var v: Vector(4, f32) = [_]f32{ 1.1, -2.2, 0.3, -0.4 }; |
| 399 | var result = @trunc(v); | 450 | var result = @trunc(v); |
| ... | @@ -403,3 +454,33 @@ fn testTrunc() !void { | ... | @@ -403,3 +454,33 @@ fn testTrunc() !void { |
| 403 | try expect(math.approxEqAbs(f32, @trunc(@as(f32, -0.4)), result[3], epsilon)); | 454 | try expect(math.approxEqAbs(f32, @trunc(@as(f32, -0.4)), result[3], epsilon)); |
| 404 | } | 455 | } |
| 405 | } | 456 | } |
| 457 | |||
| 458 | test "floating point comparisons" { | ||
| 459 | if (has_f80_rt) try testFloatComparisons(); | ||
| 460 | comptime try testFloatComparisons(); | ||
| 461 | } | ||
| 462 | |||
| 463 | fn testFloatComparisons() !void { | ||
| 464 | inline for ([_]type{ f16, f32, f64, f80, f128 }) |ty| { | ||
| 465 | // No decimal part | ||
| 466 | { | ||
| 467 | const x: ty = 1.0; | ||
| 468 | try expect(x == 1); | ||
| 469 | try expect(x != 0); | ||
| 470 | try expect(x > 0); | ||
| 471 | try expect(x < 2); | ||
| 472 | try expect(x >= 1); | ||
| 473 | try expect(x <= 1); | ||
| 474 | } | ||
| 475 | // Non-zero decimal part | ||
| 476 | { | ||
| 477 | const x: ty = 1.5; | ||
| 478 | try expect(x != 1); | ||
| 479 | try expect(x != 2); | ||
| 480 | try expect(x > 1); | ||
| 481 | try expect(x < 2); | ||
| 482 | try expect(x >= 1); | ||
| 483 | try expect(x <= 2); | ||
| 484 | } | ||
| 485 | } | ||
| 486 | } |
test/behavior/math_stage1.zig+19| ... | @@ -5,6 +5,7 @@ const expectEqualSlices = std.testing.expectEqualSlices; | ... | @@ -5,6 +5,7 @@ const expectEqualSlices = std.testing.expectEqualSlices; |
| 5 | const maxInt = std.math.maxInt; | 5 | const maxInt = std.math.maxInt; |
| 6 | const minInt = std.math.minInt; | 6 | const minInt = std.math.minInt; |
| 7 | const mem = std.mem; | 7 | const mem = std.mem; |
| 8 | const has_f80_rt = @import("builtin").cpu.arch == .x86_64; | ||
| 8 | 9 | ||
| 9 | test "allow signed integer division/remainder when values are comptime known and positive or exact" { | 10 | test "allow signed integer division/remainder when values are comptime known and positive or exact" { |
| 10 | try expect(5 / 3 == 1); | 11 | try expect(5 / 3 == 1); |
| ... | @@ -194,6 +195,8 @@ fn testSqrt(comptime T: type, x: T) !void { | ... | @@ -194,6 +195,8 @@ fn testSqrt(comptime T: type, x: T) !void { |
| 194 | test "@fabs" { | 195 | test "@fabs" { |
| 195 | try testFabs(f128, 12.0); | 196 | try testFabs(f128, 12.0); |
| 196 | comptime try testFabs(f128, 12.0); | 197 | comptime try testFabs(f128, 12.0); |
| 198 | if (has_f80_rt) try testFabs(f80, 12.0); | ||
| 199 | // comptime try testFabs(f80, 12.0); | ||
| 197 | try testFabs(f64, 12.0); | 200 | try testFabs(f64, 12.0); |
| 198 | comptime try testFabs(f64, 12.0); | 201 | comptime try testFabs(f64, 12.0); |
| 199 | try testFabs(f32, 12.0); | 202 | try testFabs(f32, 12.0); |
| ... | @@ -217,6 +220,8 @@ test "@floor" { | ... | @@ -217,6 +220,8 @@ test "@floor" { |
| 217 | // FIXME: Generates a floorl function call | 220 | // FIXME: Generates a floorl function call |
| 218 | // testFloor(f128, 12.0); | 221 | // testFloor(f128, 12.0); |
| 219 | comptime try testFloor(f128, 12.0); | 222 | comptime try testFloor(f128, 12.0); |
| 223 | // try testFloor(f80, 12.0); | ||
| 224 | comptime try testFloor(f80, 12.0); | ||
| 220 | try testFloor(f64, 12.0); | 225 | try testFloor(f64, 12.0); |
| 221 | comptime try testFloor(f64, 12.0); | 226 | comptime try testFloor(f64, 12.0); |
| 222 | try testFloor(f32, 12.0); | 227 | try testFloor(f32, 12.0); |
| ... | @@ -240,6 +245,8 @@ test "@ceil" { | ... | @@ -240,6 +245,8 @@ test "@ceil" { |
| 240 | // FIXME: Generates a ceill function call | 245 | // FIXME: Generates a ceill function call |
| 241 | //testCeil(f128, 12.0); | 246 | //testCeil(f128, 12.0); |
| 242 | comptime try testCeil(f128, 12.0); | 247 | comptime try testCeil(f128, 12.0); |
| 248 | // try testCeil(f80, 12.0); | ||
| 249 | comptime try testCeil(f80, 12.0); | ||
| 243 | try testCeil(f64, 12.0); | 250 | try testCeil(f64, 12.0); |
| 244 | comptime try testCeil(f64, 12.0); | 251 | comptime try testCeil(f64, 12.0); |
| 245 | try testCeil(f32, 12.0); | 252 | try testCeil(f32, 12.0); |
| ... | @@ -263,6 +270,14 @@ test "@trunc" { | ... | @@ -263,6 +270,14 @@ test "@trunc" { |
| 263 | // FIXME: Generates a truncl function call | 270 | // FIXME: Generates a truncl function call |
| 264 | //testTrunc(f128, 12.0); | 271 | //testTrunc(f128, 12.0); |
| 265 | comptime try testTrunc(f128, 12.0); | 272 | comptime try testTrunc(f128, 12.0); |
| 273 | // try testTrunc(f80, 12.0); | ||
| 274 | // comptime try testTrunc(f80, 12.0); | ||
| 275 | comptime { | ||
| 276 | const x: f80 = 12.0; | ||
| 277 | const y = x + 0.8; | ||
| 278 | const z = @trunc(y); | ||
| 279 | try expectEqual(x, z); | ||
| 280 | } | ||
| 266 | try testTrunc(f64, 12.0); | 281 | try testTrunc(f64, 12.0); |
| 267 | comptime try testTrunc(f64, 12.0); | 282 | comptime try testTrunc(f64, 12.0); |
| 268 | try testTrunc(f32, 12.0); | 283 | try testTrunc(f32, 12.0); |
| ... | @@ -294,6 +309,8 @@ test "@round" { | ... | @@ -294,6 +309,8 @@ test "@round" { |
| 294 | // FIXME: Generates a roundl function call | 309 | // FIXME: Generates a roundl function call |
| 295 | //testRound(f128, 12.0); | 310 | //testRound(f128, 12.0); |
| 296 | comptime try testRound(f128, 12.0); | 311 | comptime try testRound(f128, 12.0); |
| 312 | // try testRound(f80, 12.0); | ||
| 313 | comptime try testRound(f80, 12.0); | ||
| 297 | try testRound(f64, 12.0); | 314 | try testRound(f64, 12.0); |
| 298 | comptime try testRound(f64, 12.0); | 315 | comptime try testRound(f64, 12.0); |
| 299 | try testRound(f32, 12.0); | 316 | try testRound(f32, 12.0); |
| ... | @@ -333,10 +350,12 @@ test "NaN comparison" { | ... | @@ -333,10 +350,12 @@ test "NaN comparison" { |
| 333 | try testNanEqNan(f32); | 350 | try testNanEqNan(f32); |
| 334 | try testNanEqNan(f64); | 351 | try testNanEqNan(f64); |
| 335 | try testNanEqNan(f128); | 352 | try testNanEqNan(f128); |
| 353 | if (has_f80_rt) try testNanEqNan(f80); | ||
| 336 | comptime try testNanEqNan(f16); | 354 | comptime try testNanEqNan(f16); |
| 337 | comptime try testNanEqNan(f32); | 355 | comptime try testNanEqNan(f32); |
| 338 | comptime try testNanEqNan(f64); | 356 | comptime try testNanEqNan(f64); |
| 339 | comptime try testNanEqNan(f128); | 357 | comptime try testNanEqNan(f128); |
| 358 | // comptime try testNanEqNan(f80); | ||
| 340 | } | 359 | } |
| 341 | 360 | ||
| 342 | fn testNanEqNan(comptime F: type) !void { | 361 | fn testNanEqNan(comptime F: type) !void { |
test/behavior/muladd.zig+6| ... | @@ -25,6 +25,12 @@ fn testMulAdd() !void { | ... | @@ -25,6 +25,12 @@ fn testMulAdd() !void { |
| 25 | var c: f64 = 6.25; | 25 | var c: f64 = 6.25; |
| 26 | try expect(@mulAdd(f64, a, b, c) == 20); | 26 | try expect(@mulAdd(f64, a, b, c) == 20); |
| 27 | } | 27 | } |
| 28 | // { | ||
| 29 | // var a: f16 = 5.5; | ||
| 30 | // var b: f80 = 2.5; | ||
| 31 | // var c: f80 = 6.25; | ||
| 32 | // try expect(@mulAdd(f80, a, b, c) == 20); | ||
| 33 | // } | ||
| 28 | if (builtin.os.tag == .macos and builtin.cpu.arch == .aarch64) { | 34 | if (builtin.os.tag == .macos and builtin.cpu.arch == .aarch64) { |
| 29 | // https://github.com/ziglang/zig/issues/9900 | 35 | // https://github.com/ziglang/zig/issues/9900 |
| 30 | return error.SkipZigTest; | 36 | return error.SkipZigTest; |
test/behavior/type_stage1.zig+2-1| ... | @@ -13,8 +13,9 @@ test "Type.Float" { | ... | @@ -13,8 +13,9 @@ test "Type.Float" { |
| 13 | try testing.expect(f16 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 16 } })); | 13 | try testing.expect(f16 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 16 } })); |
| 14 | try testing.expect(f32 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 32 } })); | 14 | try testing.expect(f32 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 32 } })); |
| 15 | try testing.expect(f64 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 64 } })); | 15 | try testing.expect(f64 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 64 } })); |
| 16 | try testing.expect(f80 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 80 } })); | ||
| 16 | try testing.expect(f128 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 128 } })); | 17 | try testing.expect(f128 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 128 } })); |
| 17 | try testTypes(&[_]type{ f16, f32, f64, f128 }); | 18 | try testTypes(&[_]type{ f16, f32, f64, f80, f128 }); |
| 18 | } | 19 | } |
| 19 | 20 | ||
| 20 | test "Type.Array" { | 21 | test "Type.Array" { |
test/behavior/widening.zig+5| ... | @@ -2,6 +2,7 @@ const std = @import("std"); | ... | @@ -2,6 +2,7 @@ const std = @import("std"); |
| 2 | const expect = std.testing.expect; | 2 | const expect = std.testing.expect; |
| 3 | const mem = std.mem; | 3 | const mem = std.mem; |
| 4 | const builtin = @import("builtin"); | 4 | const builtin = @import("builtin"); |
| 5 | const has_f80_rt = @import("builtin").cpu.arch == .x86_64; | ||
| 5 | 6 | ||
| 6 | test "integer widening" { | 7 | test "integer widening" { |
| 7 | var a: u8 = 250; | 8 | var a: u8 = 250; |
| ... | @@ -27,6 +28,10 @@ test "float widening" { | ... | @@ -27,6 +28,10 @@ test "float widening" { |
| 27 | try expect(a == b); | 28 | try expect(a == b); |
| 28 | try expect(b == c); | 29 | try expect(b == c); |
| 29 | try expect(c == d); | 30 | try expect(c == d); |
| 31 | if (has_f80_rt) { | ||
| 32 | var e: f80 = c; | ||
| 33 | try expect(c == e); | ||
| 34 | } | ||
| 30 | } | 35 | } |
| 31 | 36 | ||
| 32 | test "float widening f16 to f128" { | 37 | test "float widening f16 to f128" { |