1/* 2 * Copyright (c) 2016 The University of Virginia 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Alec Roelke 29 */ 30 31#include <cstdint> 32#include <limits> 33 34#include "insttest.h" 35#include "rv64f.h" 36 37int main() 38{ 39 using namespace std; 40 using namespace insttest; 41 42 // FLAGS 43 expect<uint64_t>(0, []{ 44 F::fsflags(0); 45 return F::frflags(); 46 }, "clear fsflags"); 47 48 // Memory 49 expect<float>(3.14, []{return F::load(3.14);}, "flw"); 50 expect<float>(1.816, []{return F::store(1.816);}, "fsw"); 51 52 // FMADD.S 53 expect<float>(7.11624, []{return F::fmadd_s(3.14, 1.816, 1.414);}, 54 "fmadd.s"); 55 expect<bool>(true, []{ 56 float fd = F::fmadd_s(numeric_limits<float>::quiet_NaN(), 3.14, 57 1.816); 58 return F::isquietnan(fd); 59 }, "fmadd.s, quiet NaN"); 60 expect<bool>(true, []{ 61 float fd = F::fmadd_s(3.14, numeric_limits<float>::signaling_NaN(), 62 1.816); 63 return F::isquietnan(fd); 64 }, "fmadd.s, signaling NaN"); 65 expect<float>(numeric_limits<float>::infinity(), 66 []{return F::fmadd_s(3.14, numeric_limits<float>::infinity(), 67 1.414);}, 68 "fmadd.s, infinity"); 69 expect<float>(-numeric_limits<float>::infinity(), 70 []{return F::fmadd_s(3.14, -numeric_limits<float>::infinity(), 71 1.414);}, 72 "fmadd.s, -infinity"); 73 74 // FMSUB.S 75 expect<float>(4.28824, []{return F::fmsub_s(3.14, 1.816, 1.414);}, 76 "fmsub.s"); 77 expect<bool>(true, []{ 78 float fd = F::fmsub_s(3.14, numeric_limits<float>::quiet_NaN(), 79 1.816); 80 return F::isquietnan(fd); 81 }, "fmsub.s, quiet NaN"); 82 expect<bool>(true, []{ 83 float fd = F::fmsub_s(3.14, 1.816, 84 numeric_limits<float>::signaling_NaN()); 85 return F::isquietnan(fd); 86 }, "fmsub.s, signaling NaN"); 87 expect<float>(numeric_limits<float>::infinity(), 88 []{return F::fmsub_s(numeric_limits<float>::infinity(), 1.816, 89 1.414);}, 90 "fmsub.s, infinity"); 91 expect<float>(-numeric_limits<float>::infinity(), 92 []{return F::fmsub_s(3.14, -numeric_limits<float>::infinity(), 93 1.414);}, 94 "fmsub.s, -infinity"); 95 expect<float>(-numeric_limits<float>::infinity(), 96 []{return F::fmsub_s(3.14, 1.816, 97 numeric_limits<float>::infinity());}, 98 "fmsub.s, subtract infinity"); 99 100 // FNMSUB.S 101 expect<float>(-4.28824, []{return F::fnmsub_s(3.14, 1.816, 1.414);}, 102 "fnmsub.s"); 103 expect<bool>(true, []{ 104 float fd = F::fnmsub_s(3.14, 1.816, 105 numeric_limits<float>::quiet_NaN()); 106 return F::isquietnan(fd); 107 }, "fnmsub.s, quiet NaN"); 108 expect<bool>(true, []{ 109 float fd = F::fnmsub_s(numeric_limits<float>::signaling_NaN(), 110 1.816, 1.414); 111 return F::isquietnan(fd); 112 }, "fnmsub.s, signaling NaN"); 113 expect<float>(-numeric_limits<float>::infinity(), 114 []{return F::fnmsub_s(numeric_limits<float>::infinity(), 115 1.816, 1.414);}, 116 "fnmsub.s, infinity"); 117 expect<float>(numeric_limits<float>::infinity(), 118 []{return F::fnmsub_s(3.14, -numeric_limits<float>::infinity(), 119 1.414);}, 120 "fnmsub.s, -infinity"); 121 expect<float>(numeric_limits<float>::infinity(), 122 []{return F::fnmsub_s(3.14, 1.816, 123 numeric_limits<float>::infinity());}, 124 "fnmsub.s, subtract infinity"); 125 126 // FNMADD.S 127 expect<float>(-7.11624, []{return F::fnmadd_s(3.14, 1.816, 1.414);}, 128 "fnmadd.s"); 129 expect<bool>(true, []{ 130 float fd = F::fnmadd_s(numeric_limits<float>::quiet_NaN(), 3.14, 131 1.816); 132 return F::isquietnan(fd); 133 }, "fnmadd.s, quiet NaN"); 134 expect<bool>(true, []{ 135 float fd = F::fnmadd_s(3.14,numeric_limits<float>::signaling_NaN(), 136 1.816); 137 return F::isquietnan(fd); 138 }, "fnmadd.s, signaling NaN"); 139 expect<float>(-numeric_limits<float>::infinity(), 140 []{return F::fnmadd_s(3.14, numeric_limits<float>::infinity(), 141 1.414);}, 142 "fnmadd.s, infinity"); 143 expect<float>(numeric_limits<float>::infinity(), 144 []{return F::fnmadd_s(3.14, -numeric_limits<float>::infinity(), 145 1.414);}, 146 "fnmadd.s, -infinity"); 147 148 // FADD.S 149 expect<float>(4.554, []{return F::fadd_s(3.14, 1.414);}, "fadd.s"); 150 expect<bool>(true, []{ 151 float fd = F::fadd_s(numeric_limits<float>::quiet_NaN(), 1.414); 152 return F::isquietnan(fd); 153 }, "fadd.s, quiet NaN"); 154 expect<bool>(true, []{ 155 float fd = F::fadd_s(3.14, numeric_limits<float>::signaling_NaN()); 156 return F::isquietnan(fd); 157 }, "fadd.s, signaling NaN"); 158 expect<float>(numeric_limits<float>::infinity(), 159 []{return F::fadd_s(3.14, numeric_limits<float>::infinity());}, 160 "fadd.s, infinity"); 161 expect<float>(-numeric_limits<float>::infinity(), 162 []{return F::fadd_s(-numeric_limits<float>::infinity(), 1.816);}, 163 "fadd.s, -infinity"); 164 165 // FSUB.S 166 expect<float>(F::number(0xbfdced92), []{return F::fsub_s(1.414, 3.14);}, 167 "fsub.s"); 168 expect<bool>(true, []{ 169 float fd = F::fsub_s(numeric_limits<float>::quiet_NaN(), 1.414); 170 return F::isquietnan(fd); 171 }, "fsub.s, quiet NaN"); 172 expect<bool>(true, []{ 173 float fd = F::fsub_s(3.14, numeric_limits<float>::signaling_NaN()); 174 return F::isquietnan(fd); 175 }, "fsub.s, signaling NaN"); 176 expect<float>(numeric_limits<float>::infinity(), 177 []{return F::fsub_s(numeric_limits<float>::infinity(), 3.14);}, 178 "fsub.s, infinity"); 179 expect<float>(-numeric_limits<float>::infinity(), 180 []{return F::fsub_s(-numeric_limits<float>::infinity(), 3.14);}, 181 "fsub.s, -infinity"); 182 expect<float>(-numeric_limits<float>::infinity(), 183 []{return F::fsub_s(1.414, numeric_limits<float>::infinity());}, 184 "fsub.s, subtract infinity"); 185 186 // FMUL.S 187 expect<float>(F::number(0x4024573b), []{return F::fmul_s(1.816, 1.414);}, 188 "fmul.s"); 189 expect<bool>(true, []{ 190 float fd = F::fmul_s(numeric_limits<float>::quiet_NaN(), 1.414); 191 return F::isquietnan(fd); 192 }, "fmul.s, quiet NaN"); 193 expect<bool>(true, []{ 194 float fd = F::fmul_s(1.816, 195 numeric_limits<float>::signaling_NaN()); 196 return F::isquietnan(fd); 197 }, "fmul.s, signaling NaN"); 198 expect<float>(numeric_limits<float>::infinity(), 199 []{return F::fmul_s(numeric_limits<float>::infinity(), 2.718);}, 200 "fmul.s, infinity"); 201 expect<float>(-numeric_limits<float>::infinity(), 202 []{return F::fmul_s(2.5966, -numeric_limits<float>::infinity());}, 203 "fmul.s, -infinity"); 204 expect<bool>(true, []{ 205 float fd = F::fmul_s(0.0, numeric_limits<float>::infinity()); 206 return F::isquietnan(fd); 207 }, "fmul.s, 0*infinity"); 208 expect<float>(numeric_limits<float>::infinity(), 209 []{return F::fmul_s(numeric_limits<float>::max(), 2.0);}, 210 "fmul.s, overflow"); 211 expect<float>(0.0, 212 []{return F::fmul_s(numeric_limits<float>::min(), 213 numeric_limits<float>::min());}, 214 "fmul.s, underflow"); 215 216 // FDIV.S 217 expect<float>(2.5, []{return F::fdiv_s(10.0, 4.0);}, "fdiv.s"); 218 expect<bool>(true, []{ 219 float fd = F::fdiv_s(numeric_limits<float>::quiet_NaN(), 4.0); 220 return F::isquietnan(fd); 221 }, "fdiv.s, quiet NaN"); 222 expect<bool>(true, []{ 223 float fd = F::fdiv_s(10.0, numeric_limits<float>::signaling_NaN()); 224 return F::isquietnan(fd); 225 }, "fdiv.s, signaling NaN"); 226 expect<float>(numeric_limits<float>::infinity(), 227 []{return F::fdiv_s(10.0, 0.0);}, "fdiv.s/0"); 228 expect<float>(0.0, 229 []{return F::fdiv_s(10.0, numeric_limits<float>::infinity());}, 230 "fdiv.s/infinity"); 231 expect<bool>(true, []{ 232 float fd = F::fdiv_s(numeric_limits<float>::infinity(), 233 numeric_limits<float>::infinity()); 234 return F::isquietnan(fd); 235 }, "fdiv.s, infinity/infinity"); 236 expect<bool>(true, []{ 237 float fd = F::fdiv_s(0.0, 0.0); 238 return F::isquietnan(fd); 239 }, "fdiv.s, 0/0"); 240 expect<float>(numeric_limits<float>::infinity(), 241 []{return F::fdiv_s(numeric_limits<float>::infinity(), 0.0);}, 242 "fdiv.s, infinity/0"); 243 expect<float>(0.0, 244 []{return F::fdiv_s(0.0, numeric_limits<float>::infinity());}, 245 "fdiv.s, 0/infinity"); 246 expect<float>(0.0, 247 []{return F::fdiv_s(numeric_limits<float>::min(), 248 numeric_limits<float>::max());}, 249 "fdiv.s, underflow"); 250 expect<float>(numeric_limits<float>::infinity(), 251 []{return F::fdiv_s(numeric_limits<float>::max(), 252 numeric_limits<float>::min());}, 253 "fdiv.s, overflow"); 254 255 // FSQRT.S 256 expect<float>(0.3, []{return F::fsqrt_s(0.09);}, "fsqrt.s"); 257 expect<bool>(true, []{ 258 float fd = F::fsqrt_s(-1.0); 259 return F::isquietnan(fd); 260 }, "fsqrt.s, NaN"); 261 expect<bool>(true, []{ 262 float fd = F::fsqrt_s(numeric_limits<float>::quiet_NaN()); 263 return F::isquietnan(fd); 264 }, "fsqrt.s, quiet NaN"); 265 expect<bool>(true, []{ 266 float fd = F::fsqrt_s(numeric_limits<float>::signaling_NaN()); 267 return F::isquietnan(fd); 268 }, "fsqrt.s, signaling NaN"); 269 expect<float>(numeric_limits<float>::infinity(), 270 []{return F::fsqrt_s(numeric_limits<float>::infinity());}, 271 "fsqrt.s, infinity"); 272 273 // FSGNJ.S 274 expect<float>(1.0, []{return F::fsgnj_s(1.0, 25.0);}, "fsgnj.s, ++"); 275 expect<float>(-1.0, []{return F::fsgnj_s(1.0, -25.0);}, "fsgnj.s, +-"); 276 expect<float>(1.0, []{return F::fsgnj_s(-1.0, 25.0);}, "fsgnj.s, -+"); 277 expect<float>(-1.0, []{return F::fsgnj_s(-1.0, -25.0);}, "fsgnj.s, --"); 278 expect<bool>(true, []{ 279 float fd = F::fsgnj_s(numeric_limits<float>::quiet_NaN(), -4.0); 280 return F::isquietnan(fd); 281 }, "fsgnj.s, quiet NaN"); 282 expect<bool>(true, []{ 283 float fd = F::fsgnj_s(numeric_limits<float>::signaling_NaN(), 284 -4.0); 285 return F::issignalingnan(fd); 286 }, "fsgnj.s, signaling NaN"); 287 expect<float>(4.0, []{return F::fsgnj_s(4.0, 288 numeric_limits<float>::quiet_NaN());}, "fsgnj.s, inject NaN"); 289 expect<float>(-4.0, 290 []{return F::fsgnj_s(4.0, -numeric_limits<float>::quiet_NaN());}, 291 "fsgnj.s, inject -NaN"); 292 293 // FSGNJN.S 294 expect<float>(-1.0, []{return F::fsgnjn_s(1.0, 25.0);}, "fsgnjn.s, ++"); 295 expect<float>(1.0, []{return F::fsgnjn_s(1.0, -25.0);}, "fsgnjn.s, +-"); 296 expect<float>(-1.0, []{return F::fsgnjn_s(-1.0, 25.0);}, "fsgnjn.s, -+"); 297 expect<float>(1.0, []{return F::fsgnjn_s(-1.0, -25.0);}, "fsgnjn.s, --"); 298 expect<bool>(true, []{ 299 float fd = F::fsgnjn_s(numeric_limits<float>::quiet_NaN(), -4.0); 300 return F::isquietnan(fd); 301 }, "fsgnjn.s, quiet NaN"); 302 expect<bool>(true, []{ 303 float fd = F::fsgnjn_s(numeric_limits<float>::signaling_NaN(), 304 -4.0); 305 return F::issignalingnan(fd); 306 }, "fsgnjn.s, signaling NaN"); 307 expect<float>(-4.0, 308 []{return F::fsgnjn_s(4.0, numeric_limits<float>::quiet_NaN());}, 309 "fsgnjn.s, inject NaN"); 310 expect<float>(4.0, 311 []{return F::fsgnjn_s(4.0, -numeric_limits<float>::quiet_NaN());}, 312 "fsgnjn.s, inject NaN"); 313 314 // FSGNJX.S 315 expect<float>(1.0, []{return F::fsgnjx_s(1.0, 25.0);}, "fsgnjx.s, ++"); 316 expect<float>(-1.0, []{return F::fsgnjx_s(1.0, -25.0);}, "fsgnjx.s, +-"); 317 expect<float>(-1.0, []{return F::fsgnjx_s(-1.0, 25.0);}, "fsgnjx.s, -+"); 318 expect<float>(1.0, []{return F::fsgnjx_s(-1.0, -25.0);}, "fsgnjx.s, --"); 319 expect<bool>(true, []{ 320 float fd = F::fsgnjx_s(numeric_limits<float>::quiet_NaN(), -4.0); 321 return F::isquietnan(fd); 322 }, "fsgnjx.s, quiet NaN"); 323 expect<bool>(true, []{ 324 float fd = F::fsgnjx_s(numeric_limits<float>::signaling_NaN(), 325 -4.0); 326 return F::issignalingnan(fd); 327 }, "fsgnjx.s, signaling NaN"); 328 expect<float>(4.0, 329 []{return F::fsgnjx_s(4.0, numeric_limits<float>::quiet_NaN());}, 330 "fsgnjx.s, inject NaN"); 331 expect<float>(-4.0, 332 []{return F::fsgnjx_s(4.0, -numeric_limits<float>::quiet_NaN());}, 333 "fsgnjx.s, inject -NaN"); 334 335 // FMIN.S 336 expect<float>(2.718, []{return F::fmin_s(3.14, 2.718);}, "fmin.s"); 337 expect<float>(-numeric_limits<float>::infinity(), 338 []{return F::fmin_s(-numeric_limits<float>::infinity(), 339 numeric_limits<float>::min());}, 340 "fmin.s, -infinity"); 341 expect<float>(numeric_limits<float>::max(), 342 []{return F::fmin_s(numeric_limits<float>::infinity(), 343 numeric_limits<float>::max());}, 344 "fmin.s, infinity"); 345 expect<float>(-1.414, 346 []{return F::fmin_s(numeric_limits<float>::quiet_NaN(), -1.414);}, 347 "fmin.s, quiet NaN first"); 348 expect<float>(2.718, 349 []{return F::fmin_s(2.718, numeric_limits<float>::quiet_NaN());}, 350 "fmin.s, quiet NaN second"); 351 expect<bool>(true, []{ 352 float fd = F::fmin_s(numeric_limits<float>::quiet_NaN(), 353 numeric_limits<float>::quiet_NaN()); 354 return F::isquietnan(fd); 355 }, "fmin.s, quiet NaN both"); 356 expect<float>(3.14, 357 []{return F::fmin_s(numeric_limits<float>::signaling_NaN(), 358 3.14);}, 359 "fmin.s, signaling NaN first"); 360 expect<float>(1.816, 361 []{return F::fmin_s(1.816, 362 numeric_limits<float>::signaling_NaN());}, 363 "fmin.s, signaling NaN second"); 364 expect<bool>(true, []{ 365 float fd = F::fmin_s(numeric_limits<float>::signaling_NaN(), 366 numeric_limits<float>::signaling_NaN()); 367 return F::issignalingnan(fd); 368 }, "fmin.s, signaling NaN both"); 369 370 // FMAX.S 371 expect<float>(3.14, []{return F::fmax_s(3.14, 2.718);}, "fmax.s"); 372 expect<float>(numeric_limits<float>::min(), 373 []{return F::fmax_s(-numeric_limits<float>::infinity(), 374 numeric_limits<float>::min());}, 375 "fmax.s, -infinity"); 376 expect<float>(numeric_limits<float>::infinity(), 377 []{return F::fmax_s(numeric_limits<float>::infinity(), 378 numeric_limits<float>::max());}, 379 "fmax.s, infinity"); 380 expect<float>(-1.414, 381 []{return F::fmax_s(numeric_limits<float>::quiet_NaN(), -1.414);}, 382 "fmax.s, quiet NaN first"); 383 expect<float>(2.718, 384 []{return F::fmax_s(2.718, numeric_limits<float>::quiet_NaN());}, 385 "fmax.s, quiet NaN second"); 386 expect<bool>(true, []{ 387 float fd = F::fmax_s(numeric_limits<float>::quiet_NaN(), 388 numeric_limits<float>::quiet_NaN()); 389 return F::isquietnan(fd); 390 }, "fmax.s, quiet NaN both"); 391 expect<float>(3.14, 392 []{return F::fmax_s(numeric_limits<float>::signaling_NaN(), 393 3.14);}, 394 "fmax.s, signaling NaN first"); 395 expect<float>(1.816, []{return F::fmax_s(1.816, 396 numeric_limits<float>::signaling_NaN());}, 397 "fmax.s, signaling NaN second"); 398 expect<bool>(true, []{ 399 float fd = F::fmax_s(numeric_limits<float>::signaling_NaN(), 400 numeric_limits<float>::signaling_NaN()); 401 return F::issignalingnan(fd); 402 }, "fmax.s, signaling NaN both"); 403 404 // FCVT.W.S 405 expect<int64_t>(256, []{return F::fcvt_w_s(256.3);}, 406 "fcvt.w.s, truncate positive"); 407 expect<int64_t>(-256, []{return F::fcvt_w_s(-256.2);}, 408 "fcvt.w.s, truncate negative"); 409 expect<int64_t>(0, []{return F::fcvt_w_s(0.0);}, "fcvt.w.s, 0.0"); 410 expect<int64_t>(0, []{return F::fcvt_w_s(-0.0);}, "fcvt.w.s, -0.0"); 411 expect<int64_t>(numeric_limits<int32_t>::max(), 412 []{return F::fcvt_w_s(numeric_limits<float>::max());}, 413 "fcvt.w.s, overflow"); 414 expect<int64_t>(0, []{return F::fcvt_w_s(numeric_limits<float>::min());}, 415 "fcvt.w.s, underflow"); 416 expect<int64_t>(numeric_limits<int32_t>::max(), 417 []{return F::fcvt_w_s(numeric_limits<float>::infinity());}, 418 "fcvt.w.s, infinity"); 419 expect<int64_t>(numeric_limits<int32_t>::min(), 420 []{return F::fcvt_w_s(-numeric_limits<float>::infinity());}, 421 "fcvt.w.s, -infinity"); 422 expect<int64_t>(numeric_limits<int32_t>::max(), 423 []{return F::fcvt_w_s(numeric_limits<float>::quiet_NaN());}, 424 "fcvt.w.s, quiet NaN"); 425 expect<int64_t>(numeric_limits<int32_t>::max(), 426 []{return F::fcvt_w_s(-numeric_limits<float>::quiet_NaN());}, 427 "fcvt.w.s, quiet -NaN"); 428 expect<int64_t>(numeric_limits<int32_t>::max(), 429 []{return F::fcvt_w_s(numeric_limits<float>::signaling_NaN());}, 430 "fcvt.w.s, signaling NaN"); 431 432 // FCVT.WU.S 433 expect<uint64_t>(256, []{return F::fcvt_wu_s(256.3);}, 434 "fcvt.wu.s, truncate positive"); 435 expect<uint64_t>(0, []{return F::fcvt_wu_s(-256.2);}, 436 "fcvt.wu.s, truncate negative"); 437 expect<uint64_t>(0, []{return F::fcvt_wu_s(0.0);}, "fcvt.wu.s, 0.0"); 438 expect<uint64_t>(0, []{return F::fcvt_wu_s(-0.0);}, "fcvt.wu.s, -0.0"); 439 expect<uint64_t>(numeric_limits<uint64_t>::max(), 440 []{return F::fcvt_wu_s(numeric_limits<float>::max());}, 441 "fcvt.wu.s, overflow"); 442 expect<uint64_t>(0, []{return F::fcvt_wu_s(numeric_limits<float>::min());}, 443 "fcvt.wu.s, underflow"); 444 expect<uint64_t>(numeric_limits<uint64_t>::max(), 445 []{return F::fcvt_wu_s(numeric_limits<float>::infinity());}, 446 "fcvt.wu.s, infinity"); 447 expect<uint64_t>(0, 448 []{return F::fcvt_wu_s(-numeric_limits<float>::infinity());}, 449 "fcvt.wu.s, -infinity"); 450 expect<uint64_t>(0xFFFFFFFFFFFFFFFFULL, 451 []{return F::fcvt_wu_s(numeric_limits<float>::quiet_NaN());}, 452 "fcvt.wu.s, quiet NaN"); 453 expect<uint64_t>(0xFFFFFFFFFFFFFFFFULL, 454 []{return F::fcvt_wu_s(-numeric_limits<float>::quiet_NaN());}, 455 "fcvt.wu.s, quiet -NaN"); 456 expect<uint64_t>(0xFFFFFFFFFFFFFFFFULL, 457 []{return F::fcvt_wu_s(numeric_limits<float>::signaling_NaN());}, 458 "fcvt.wu.s, signaling NaN"); 459 460 // FMV.X.S 461 expect<uint64_t>(0x000000004048F5C3ULL, []{return F::fmv_x_s(3.14);}, 462 "fmv.x.s, positive"); 463 expect<uint64_t>(0xFFFFFFFFC048F5C3ULL, []{return F::fmv_x_s(-3.14);}, 464 "fmv.x.s, negative"); 465 expect<uint64_t>(0x0000000000000000ULL, []{return F::fmv_x_s(0.0);}, 466 "fmv.x.s, 0.0"); 467 expect<uint64_t>(0xFFFFFFFF80000000ULL, []{return F::fmv_x_s(-0.0);}, 468 "fmv.x.s, -0.0"); 469 470 // FEQ.S 471 expect<bool>(true, []{return F::feq_s(1.414, 1.414);}, "feq.s, equal"); 472 expect<bool>(false, []{return F::feq_s(2.718, 1.816);}, 473 "feq.s, not equal"); 474 expect<bool>(true, []{return F::feq_s(0.0, -0.0);}, "feq.s, 0 == -0"); 475 expect<bool>(false, 476 []{return F::feq_s(numeric_limits<float>::quiet_NaN(), -1.0);}, 477 "feq.s, quiet NaN first"); 478 expect<bool>(false, 479 []{return F::feq_s(2.0, numeric_limits<float>::quiet_NaN());}, 480 "feq.s, quiet NaN second"); 481 expect<bool>(false, 482 []{return F::feq_s(numeric_limits<float>::quiet_NaN(), 483 numeric_limits<float>::quiet_NaN());}, 484 "feq.s, quiet NaN both"); 485 expect<bool>(false, 486 []{return F::feq_s(numeric_limits<float>::signaling_NaN(), -1.0);}, 487 "feq.s, signaling NaN first"); 488 expect<bool>(false, 489 []{return F::feq_s(2.0, numeric_limits<float>::signaling_NaN());}, 490 "feq.s, signaling NaN second"); 491 expect<bool>(false, 492 []{return F::feq_s(numeric_limits<float>::signaling_NaN(), 493 numeric_limits<float>::signaling_NaN());}, 494 "feq.s, signaling NaN both"); 495 496 // FLT.S 497 expect<bool>(false, []{return F::flt_s(1.414, 1.414);}, "flt.s, equal"); 498 expect<bool>(true, []{return F::flt_s(1.816, 2.718);}, "flt.s, less"); 499 expect<bool>(false, []{return F::flt_s(2.718, 1.816);}, "flt.s, greater"); 500 expect<bool>(false, 501 []{return F::flt_s(numeric_limits<float>::quiet_NaN(), -1.0);}, 502 "flt.s, quiet NaN first"); 503 expect<bool>(false, 504 []{return F::flt_s(2.0, numeric_limits<float>::quiet_NaN());}, 505 "flt.s, quiet NaN second"); 506 expect<bool>(false, 507 []{return F::flt_s(numeric_limits<float>::quiet_NaN(), 508 numeric_limits<float>::quiet_NaN());}, 509 "flt.s, quiet NaN both"); 510 expect<bool>(false, 511 []{return F::flt_s(numeric_limits<float>::signaling_NaN(), -1.0);}, 512 "flt.s, signaling NaN first"); 513 expect<bool>(false, 514 []{return F::flt_s(2.0, numeric_limits<float>::signaling_NaN());}, 515 "flt.s, signaling NaN second"); 516 expect<bool>(false, 517 []{return F::flt_s(numeric_limits<float>::signaling_NaN(), 518 numeric_limits<float>::signaling_NaN());}, 519 "flt.s, signaling NaN both"); 520 521 // FLE.S 522 expect<bool>(true, []{return F::fle_s(1.414, 1.414);}, "fle.s, equal"); 523 expect<bool>(true, []{return F::fle_s(1.816, 2.718);}, "fle.s, less"); 524 expect<bool>(false, []{return F::fle_s(2.718, 1.816);}, "fle.s, greater"); 525 expect<bool>(true, []{return F::fle_s(0.0, -0.0);}, "fle.s, 0 == -0"); 526 expect<bool>(false, 527 []{return F::fle_s(numeric_limits<float>::quiet_NaN(), -1.0);}, 528 "fle.s, quiet NaN first"); 529 expect<bool>(false, 530 []{return F::fle_s(2.0, numeric_limits<float>::quiet_NaN());}, 531 "fle.s, quiet NaN second"); 532 expect<bool>(false, 533 []{return F::fle_s(numeric_limits<float>::quiet_NaN(), 534 numeric_limits<float>::quiet_NaN());}, 535 "fle.s, quiet NaN both"); 536 expect<bool>(false, 537 []{return F::fle_s(numeric_limits<float>::signaling_NaN(), -1.0);}, 538 "fle.s, signaling NaN first"); 539 expect<bool>(false, 540 []{return F::fle_s(2.0, numeric_limits<float>::signaling_NaN());}, 541 "fle.s, signaling NaN second"); 542 expect<bool>(false, 543 []{return F::fle_s(numeric_limits<float>::signaling_NaN(), 544 numeric_limits<float>::signaling_NaN());}, 545 "fle.s, signaling NaN both"); 546 547 // FCLASS.S 548 expect<uint64_t>(0x1, 549 []{return F::fclass_s(-numeric_limits<float>::infinity());}, 550 "fclass.s, -infinity"); 551 expect<uint64_t>(0x2, []{return F::fclass_s(-3.14);}, "fclass.s, -normal"); 552 expect<uint64_t>(0x4, []{return F::fclass_s(F::number(0x807FFFFF));}, 553 "fclass.s, -subnormal"); 554 expect<uint64_t>(0x8, []{return F::fclass_s(-0.0);}, "fclass.s, -0.0"); 555 expect<uint64_t>(0x10, []{return F::fclass_s(0.0);}, "fclass.s, 0.0"); 556 expect<uint64_t>(0x20, []{return F::fclass_s(F::number(0x007FFFFF));}, 557 "fclass.s, subnormal"); 558 expect<uint64_t>(0x40, []{return F::fclass_s(1.816);}, "fclass.s, normal"); 559 expect<uint64_t>(0x80, 560 []{return F::fclass_s(numeric_limits<float>::infinity());}, 561 "fclass.s, infinity"); 562 expect<uint64_t>(0x100, 563 []{return F::fclass_s(numeric_limits<float>::signaling_NaN());}, 564 "fclass.s, signaling NaN"); 565 expect<uint64_t>(0x200, 566 []{return F::fclass_s(numeric_limits<float>::quiet_NaN());}, 567 "fclass.s, quiet NaN"); 568 569 // FCVT.S.W 570 expect<float>(0.0, []{return F::fcvt_s_w(0);}, "fcvt.s.w, 0"); 571 expect<float>(-2147483648.0, 572 []{return F::fcvt_s_w(numeric_limits<int32_t>::min());}, 573 "fcvt.s.w, negative"); 574 expect<float>(255.0, []{return F::fcvt_s_w(0xFFFFFFFF000000FFLL);}, 575 "fcvt.s.w, truncate"); 576 577 // FCVT.S.WU 578 expect<float>(0.0, []{return F::fcvt_s_wu(0);}, "fcvt.s.wu, 0"); 579 expect<float>(2147483648.0, 580 []{return F::fcvt_s_wu(numeric_limits<int32_t>::min());}, 581 "fcvt.s.wu"); 582 expect<float>(255.0, []{return F::fcvt_s_wu(0xFFFFFFFF000000FFLL);}, 583 "fcvt.s.wu, truncate"); 584 585 // FMV.S.X 586 expect<float>(numeric_limits<float>::infinity(), 587 []{return F::fmv_s_x(0x7F800000);}, "fmv.s.x"); 588 expect<float>(-0.0, []{return F::fmv_s_x(0xFFFFFFFF80000000ULL);}, 589 "fmv.s.x, truncate"); 590 591 // FCSR functions 592 int rm = F::frrm(); 593 expect<uint64_t>(0x7, []{ // FSRM 594 F::fsrm(-1); 595 return F::frrm(); 596 }, "fsrm"); 597 expect<uint64_t>(0x1F, []{ // FSFLAGS 598 F::fsflags(0); 599 F::fsflags(-1); 600 return F::frflags(); 601 }, "fsflags"); 602 expect<uint64_t>(0xFF, []{ // FSCSR 603 F::fsflags(0); 604 F::fsrm(0); 605 F::fscsr(-1); 606 return F::frcsr(); 607 }, "fscsr"); 608 expect<int>(rm << 5, [=]{ 609 F::fscsr(0); 610 F::fsrm(rm); 611 return F::frcsr(); 612 }, "restore initial round mode"); 613 614 F::fsflags(0); 615 616 // FCVT.L.S 617 expect<int64_t>(256, []{return F::fcvt_l_s(256.3);}, 618 "fcvt.l.s, truncate positive"); 619 expect<int64_t>(-256, []{return F::fcvt_l_s(-256.2);}, 620 "fcvt.l.s, truncate negative"); 621 expect<int64_t>(0, []{return F::fcvt_l_s(0.0);}, "fcvt.l.s, 0.0"); 622 expect<int64_t>(0, []{return F::fcvt_l_s(-0.0);}, "fcvt.l.s, -0.0"); 623 expect<int64_t>(-8589934592LL, []{return F::fcvt_l_s(-8589934592.0);}, 624 "fcvt.l.s, 32-bit overflow"); 625 expect<int64_t>(numeric_limits<int64_t>::max(), 626 []{return F::fcvt_l_s(numeric_limits<float>::max());}, 627 "fcvt.l.s, overflow"); 628 expect<int64_t>(0, []{return F::fcvt_l_s(numeric_limits<float>::min());}, 629 "fcvt.l.s, underflow"); 630 expect<int64_t>(numeric_limits<int64_t>::max(), 631 []{return F::fcvt_l_s(numeric_limits<float>::infinity());}, 632 "fcvt.l.s, infinity"); 633 expect<int64_t>(numeric_limits<int64_t>::min(), 634 []{return F::fcvt_l_s(-numeric_limits<float>::infinity());}, 635 "fcvt.l.s, -infinity"); 636 expect<int64_t>(numeric_limits<int64_t>::max(), 637 []{return F::fcvt_l_s(numeric_limits<float>::quiet_NaN());}, 638 "fcvt.l.s, quiet NaN"); 639 expect<int64_t>(numeric_limits<int64_t>::max(), 640 []{return F::fcvt_l_s(-numeric_limits<float>::quiet_NaN());}, 641 "fcvt.l.s, quiet -NaN"); 642 expect<int64_t>(numeric_limits<int64_t>::max(), 643 []{return F::fcvt_l_s(numeric_limits<float>::signaling_NaN());}, 644 "fcvt.l.s, signaling NaN"); 645 646 // FCVT.LU.S 647 expect<uint64_t>(256, []{return F::fcvt_lu_s(256.3);}, 648 "fcvt.lu.s, truncate positive"); 649 expect<uint64_t>(0, []{return F::fcvt_lu_s(-256.2);}, 650 "fcvt.lu.s, truncate negative"); 651 expect<uint64_t>(0, []{return F::fcvt_lu_s(0.0);}, "fcvt.lu.s, 0.0"); 652 expect<uint64_t>(0, []{return F::fcvt_lu_s(-0.0);}, "fcvt.lu.s, -0.0"); 653 expect<uint64_t>(8589934592LL, 654 []{return F::fcvt_lu_s(8589934592.0);}, 655 "fcvt.lu.s, 32-bit overflow"); 656 expect<uint64_t>(numeric_limits<uint64_t>::max(), 657 []{return F::fcvt_lu_s(numeric_limits<float>::max());}, 658 "fcvt.lu.s, overflow"); 659 expect<uint64_t>(0, []{return F::fcvt_lu_s(numeric_limits<float>::min());}, 660 "fcvt.lu.s, underflow"); 661 expect<uint64_t>(numeric_limits<uint64_t>::max(), 662 []{return F::fcvt_lu_s(numeric_limits<float>::infinity());}, 663 "fcvt.lu.s, infinity"); 664 expect<uint64_t>(0, 665 []{return F::fcvt_lu_s(-numeric_limits<float>::infinity());}, 666 "fcvt.lu.s, -infinity"); 667 expect<uint64_t>(0xFFFFFFFFFFFFFFFFULL, 668 []{return F::fcvt_lu_s(numeric_limits<float>::quiet_NaN());}, 669 "fcvt.lu.s, quiet NaN"); 670 expect<uint64_t>(0xFFFFFFFFFFFFFFFFULL, 671 []{return F::fcvt_lu_s(-numeric_limits<float>::quiet_NaN());}, 672 "fcvt.lu.s, quiet -NaN"); 673 expect<uint64_t>(0xFFFFFFFFFFFFFFFFULL, 674 []{return F::fcvt_lu_s(numeric_limits<float>::signaling_NaN());}, 675 "fcvt.lu.s, signaling NaN"); 676 677 // FCVT.S.L 678 expect<float>(0.0, []{return F::fcvt_s_l(0);}, "fcvt.s.l, 0"); 679 expect<float>(-9.223372e18, 680 []{return F::fcvt_s_l(numeric_limits<int64_t>::min());}, 681 "fcvt.s.l, negative"); 682 expect<float>(-4.29496704e9, []{return F::fcvt_s_l(0xFFFFFFFF000000FFLL);}, 683 "fcvt.s.l, 32-bit truncate"); 684 685 // FCVT.S.LU 686 expect<float>(0.0, []{return F::fcvt_s_lu(0);}, "fcvt.s.lu, 0"); 687 expect<float>(9.223372e18, 688 []{return F::fcvt_s_lu(numeric_limits<int64_t>::min());}, 689 "fcvt.s.lu"); 690 expect<float>(1.8446744e19, []{return F::fcvt_s_lu(0xFFFFFFFF000000FFLL);}, 691 "fcvt.s.lu, 32-bit truncate"); 692 693 return 0; 694} 695