1 /* 2 * RISC-V FPU Emulation Helpers for QEMU. 3 * 4 * Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms and conditions of the GNU General Public License, 8 * version 2 or later, as published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 * more details. 14 * 15 * You should have received a copy of the GNU General Public License along with 16 * this program. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 #include "qemu/osdep.h" 20 #include "cpu.h" 21 #include "qemu/host-utils.h" 22 #include "exec/helper-proto.h" 23 #include "fpu/softfloat.h" 24 #include "internals.h" 25 26 target_ulong riscv_cpu_get_fflags(CPURISCVState *env) 27 { 28 int soft = get_float_exception_flags(&env->fp_status); 29 target_ulong hard = 0; 30 31 hard |= (soft & float_flag_inexact) ? FPEXC_NX : 0; 32 hard |= (soft & float_flag_underflow) ? FPEXC_UF : 0; 33 hard |= (soft & float_flag_overflow) ? FPEXC_OF : 0; 34 hard |= (soft & float_flag_divbyzero) ? FPEXC_DZ : 0; 35 hard |= (soft & float_flag_invalid) ? FPEXC_NV : 0; 36 37 return hard; 38 } 39 40 void riscv_cpu_set_fflags(CPURISCVState *env, target_ulong hard) 41 { 42 int soft = 0; 43 44 soft |= (hard & FPEXC_NX) ? float_flag_inexact : 0; 45 soft |= (hard & FPEXC_UF) ? float_flag_underflow : 0; 46 soft |= (hard & FPEXC_OF) ? float_flag_overflow : 0; 47 soft |= (hard & FPEXC_DZ) ? float_flag_divbyzero : 0; 48 soft |= (hard & FPEXC_NV) ? float_flag_invalid : 0; 49 50 set_float_exception_flags(soft, &env->fp_status); 51 } 52 53 void helper_set_rounding_mode(CPURISCVState *env, uint32_t rm) 54 { 55 int softrm; 56 57 if (rm == RISCV_FRM_DYN) { 58 rm = env->frm; 59 } 60 switch (rm) { 61 case RISCV_FRM_RNE: 62 softrm = float_round_nearest_even; 63 break; 64 case RISCV_FRM_RTZ: 65 softrm = float_round_to_zero; 66 break; 67 case RISCV_FRM_RDN: 68 softrm = float_round_down; 69 break; 70 case RISCV_FRM_RUP: 71 softrm = float_round_up; 72 break; 73 case RISCV_FRM_RMM: 74 softrm = float_round_ties_away; 75 break; 76 default: 77 riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); 78 } 79 80 set_float_rounding_mode(softrm, &env->fp_status); 81 } 82 83 void helper_set_rounding_mode_chkfrm(CPURISCVState *env, uint32_t rm) 84 { 85 int softrm; 86 87 /* Always validate frm, even if rm != DYN. */ 88 if (unlikely(env->frm >= 5)) { 89 riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); 90 } 91 if (rm == RISCV_FRM_DYN) { 92 rm = env->frm; 93 } 94 switch (rm) { 95 case RISCV_FRM_RNE: 96 softrm = float_round_nearest_even; 97 break; 98 case RISCV_FRM_RTZ: 99 softrm = float_round_to_zero; 100 break; 101 case RISCV_FRM_RDN: 102 softrm = float_round_down; 103 break; 104 case RISCV_FRM_RUP: 105 softrm = float_round_up; 106 break; 107 case RISCV_FRM_RMM: 108 softrm = float_round_ties_away; 109 break; 110 case RISCV_FRM_ROD: 111 softrm = float_round_to_odd; 112 break; 113 default: 114 g_assert_not_reached(); 115 } 116 117 set_float_rounding_mode(softrm, &env->fp_status); 118 } 119 120 static uint64_t do_fmadd_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2, 121 uint64_t rs3, int flags) 122 { 123 float16 frs1 = check_nanbox_h(env, rs1); 124 float16 frs2 = check_nanbox_h(env, rs2); 125 float16 frs3 = check_nanbox_h(env, rs3); 126 return nanbox_h(env, float16_muladd(frs1, frs2, frs3, flags, 127 &env->fp_status)); 128 } 129 130 static uint64_t do_fmadd_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2, 131 uint64_t rs3, int flags) 132 { 133 float32 frs1 = check_nanbox_s(env, rs1); 134 float32 frs2 = check_nanbox_s(env, rs2); 135 float32 frs3 = check_nanbox_s(env, rs3); 136 return nanbox_s(env, float32_muladd(frs1, frs2, frs3, flags, 137 &env->fp_status)); 138 } 139 140 uint64_t helper_fmadd_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2, 141 uint64_t frs3) 142 { 143 return do_fmadd_s(env, frs1, frs2, frs3, 0); 144 } 145 146 uint64_t helper_fmadd_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2, 147 uint64_t frs3) 148 { 149 return float64_muladd(frs1, frs2, frs3, 0, &env->fp_status); 150 } 151 152 uint64_t helper_fmadd_h(CPURISCVState *env, uint64_t frs1, uint64_t frs2, 153 uint64_t frs3) 154 { 155 return do_fmadd_h(env, frs1, frs2, frs3, 0); 156 } 157 158 uint64_t helper_fmsub_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2, 159 uint64_t frs3) 160 { 161 return do_fmadd_s(env, frs1, frs2, frs3, float_muladd_negate_c); 162 } 163 164 uint64_t helper_fmsub_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2, 165 uint64_t frs3) 166 { 167 return float64_muladd(frs1, frs2, frs3, float_muladd_negate_c, 168 &env->fp_status); 169 } 170 171 uint64_t helper_fmsub_h(CPURISCVState *env, uint64_t frs1, uint64_t frs2, 172 uint64_t frs3) 173 { 174 return do_fmadd_h(env, frs1, frs2, frs3, float_muladd_negate_c); 175 } 176 177 uint64_t helper_fnmsub_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2, 178 uint64_t frs3) 179 { 180 return do_fmadd_s(env, frs1, frs2, frs3, float_muladd_negate_product); 181 } 182 183 uint64_t helper_fnmsub_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2, 184 uint64_t frs3) 185 { 186 return float64_muladd(frs1, frs2, frs3, float_muladd_negate_product, 187 &env->fp_status); 188 } 189 190 uint64_t helper_fnmsub_h(CPURISCVState *env, uint64_t frs1, uint64_t frs2, 191 uint64_t frs3) 192 { 193 return do_fmadd_h(env, frs1, frs2, frs3, float_muladd_negate_product); 194 } 195 196 uint64_t helper_fnmadd_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2, 197 uint64_t frs3) 198 { 199 return do_fmadd_s(env, frs1, frs2, frs3, 200 float_muladd_negate_c | float_muladd_negate_product); 201 } 202 203 uint64_t helper_fnmadd_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2, 204 uint64_t frs3) 205 { 206 return float64_muladd(frs1, frs2, frs3, float_muladd_negate_c | 207 float_muladd_negate_product, &env->fp_status); 208 } 209 210 uint64_t helper_fnmadd_h(CPURISCVState *env, uint64_t frs1, uint64_t frs2, 211 uint64_t frs3) 212 { 213 return do_fmadd_h(env, frs1, frs2, frs3, 214 float_muladd_negate_c | float_muladd_negate_product); 215 } 216 217 uint64_t helper_fadd_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2) 218 { 219 float32 frs1 = check_nanbox_s(env, rs1); 220 float32 frs2 = check_nanbox_s(env, rs2); 221 return nanbox_s(env, float32_add(frs1, frs2, &env->fp_status)); 222 } 223 224 uint64_t helper_fsub_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2) 225 { 226 float32 frs1 = check_nanbox_s(env, rs1); 227 float32 frs2 = check_nanbox_s(env, rs2); 228 return nanbox_s(env, float32_sub(frs1, frs2, &env->fp_status)); 229 } 230 231 uint64_t helper_fmul_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2) 232 { 233 float32 frs1 = check_nanbox_s(env, rs1); 234 float32 frs2 = check_nanbox_s(env, rs2); 235 return nanbox_s(env, float32_mul(frs1, frs2, &env->fp_status)); 236 } 237 238 uint64_t helper_fdiv_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2) 239 { 240 float32 frs1 = check_nanbox_s(env, rs1); 241 float32 frs2 = check_nanbox_s(env, rs2); 242 return nanbox_s(env, float32_div(frs1, frs2, &env->fp_status)); 243 } 244 245 uint64_t helper_fmin_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2) 246 { 247 float32 frs1 = check_nanbox_s(env, rs1); 248 float32 frs2 = check_nanbox_s(env, rs2); 249 return nanbox_s(env, env->priv_ver < PRIV_VERSION_1_11_0 ? 250 float32_minnum(frs1, frs2, &env->fp_status) : 251 float32_minimum_number(frs1, frs2, &env->fp_status)); 252 } 253 254 uint64_t helper_fminm_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2) 255 { 256 float32 frs1 = check_nanbox_s(env, rs1); 257 float32 frs2 = check_nanbox_s(env, rs2); 258 float32 ret = float32_min(frs1, frs2, &env->fp_status); 259 return nanbox_s(env, ret); 260 } 261 262 uint64_t helper_fmax_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2) 263 { 264 float32 frs1 = check_nanbox_s(env, rs1); 265 float32 frs2 = check_nanbox_s(env, rs2); 266 return nanbox_s(env, env->priv_ver < PRIV_VERSION_1_11_0 ? 267 float32_maxnum(frs1, frs2, &env->fp_status) : 268 float32_maximum_number(frs1, frs2, &env->fp_status)); 269 } 270 271 uint64_t helper_fmaxm_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2) 272 { 273 float32 frs1 = check_nanbox_s(env, rs1); 274 float32 frs2 = check_nanbox_s(env, rs2); 275 float32 ret = float32_max(frs1, frs2, &env->fp_status); 276 return nanbox_s(env, ret); 277 } 278 279 uint64_t helper_fsqrt_s(CPURISCVState *env, uint64_t rs1) 280 { 281 float32 frs1 = check_nanbox_s(env, rs1); 282 return nanbox_s(env, float32_sqrt(frs1, &env->fp_status)); 283 } 284 285 target_ulong helper_fle_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2) 286 { 287 float32 frs1 = check_nanbox_s(env, rs1); 288 float32 frs2 = check_nanbox_s(env, rs2); 289 return float32_le(frs1, frs2, &env->fp_status); 290 } 291 292 target_ulong helper_fleq_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2) 293 { 294 float32 frs1 = check_nanbox_s(env, rs1); 295 float32 frs2 = check_nanbox_s(env, rs2); 296 return float32_le_quiet(frs1, frs2, &env->fp_status); 297 } 298 299 target_ulong helper_flt_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2) 300 { 301 float32 frs1 = check_nanbox_s(env, rs1); 302 float32 frs2 = check_nanbox_s(env, rs2); 303 return float32_lt(frs1, frs2, &env->fp_status); 304 } 305 306 target_ulong helper_fltq_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2) 307 { 308 float32 frs1 = check_nanbox_s(env, rs1); 309 float32 frs2 = check_nanbox_s(env, rs2); 310 return float32_lt_quiet(frs1, frs2, &env->fp_status); 311 } 312 313 target_ulong helper_feq_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2) 314 { 315 float32 frs1 = check_nanbox_s(env, rs1); 316 float32 frs2 = check_nanbox_s(env, rs2); 317 return float32_eq_quiet(frs1, frs2, &env->fp_status); 318 } 319 320 target_ulong helper_fcvt_w_s(CPURISCVState *env, uint64_t rs1) 321 { 322 float32 frs1 = check_nanbox_s(env, rs1); 323 return float32_to_int32(frs1, &env->fp_status); 324 } 325 326 target_ulong helper_fcvt_wu_s(CPURISCVState *env, uint64_t rs1) 327 { 328 float32 frs1 = check_nanbox_s(env, rs1); 329 return (int32_t)float32_to_uint32(frs1, &env->fp_status); 330 } 331 332 target_ulong helper_fcvt_l_s(CPURISCVState *env, uint64_t rs1) 333 { 334 float32 frs1 = check_nanbox_s(env, rs1); 335 return float32_to_int64(frs1, &env->fp_status); 336 } 337 338 target_ulong helper_fcvt_lu_s(CPURISCVState *env, uint64_t rs1) 339 { 340 float32 frs1 = check_nanbox_s(env, rs1); 341 return float32_to_uint64(frs1, &env->fp_status); 342 } 343 344 uint64_t helper_fcvt_s_w(CPURISCVState *env, target_ulong rs1) 345 { 346 return nanbox_s(env, int32_to_float32((int32_t)rs1, &env->fp_status)); 347 } 348 349 uint64_t helper_fcvt_s_wu(CPURISCVState *env, target_ulong rs1) 350 { 351 return nanbox_s(env, uint32_to_float32((uint32_t)rs1, &env->fp_status)); 352 } 353 354 uint64_t helper_fcvt_s_l(CPURISCVState *env, target_ulong rs1) 355 { 356 return nanbox_s(env, int64_to_float32(rs1, &env->fp_status)); 357 } 358 359 uint64_t helper_fcvt_s_lu(CPURISCVState *env, target_ulong rs1) 360 { 361 return nanbox_s(env, uint64_to_float32(rs1, &env->fp_status)); 362 } 363 364 target_ulong helper_fclass_s(CPURISCVState *env, uint64_t rs1) 365 { 366 float32 frs1 = check_nanbox_s(env, rs1); 367 return fclass_s(frs1); 368 } 369 370 uint64_t helper_fround_s(CPURISCVState *env, uint64_t rs1) 371 { 372 float_status *fs = &env->fp_status; 373 uint16_t nx_old = get_float_exception_flags(fs) & float_flag_inexact; 374 float32 frs1 = check_nanbox_s(env, rs1); 375 376 frs1 = float32_round_to_int(frs1, fs); 377 378 /* Restore the original NX flag. */ 379 uint16_t flags = get_float_exception_flags(fs); 380 flags &= ~float_flag_inexact; 381 flags |= nx_old; 382 set_float_exception_flags(flags, fs); 383 384 return nanbox_s(env, frs1); 385 } 386 387 uint64_t helper_froundnx_s(CPURISCVState *env, uint64_t rs1) 388 { 389 float32 frs1 = check_nanbox_s(env, rs1); 390 frs1 = float32_round_to_int(frs1, &env->fp_status); 391 return nanbox_s(env, frs1); 392 } 393 394 uint64_t helper_fadd_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2) 395 { 396 return float64_add(frs1, frs2, &env->fp_status); 397 } 398 399 uint64_t helper_fsub_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2) 400 { 401 return float64_sub(frs1, frs2, &env->fp_status); 402 } 403 404 uint64_t helper_fmul_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2) 405 { 406 return float64_mul(frs1, frs2, &env->fp_status); 407 } 408 409 uint64_t helper_fdiv_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2) 410 { 411 return float64_div(frs1, frs2, &env->fp_status); 412 } 413 414 uint64_t helper_fmin_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2) 415 { 416 return env->priv_ver < PRIV_VERSION_1_11_0 ? 417 float64_minnum(frs1, frs2, &env->fp_status) : 418 float64_minimum_number(frs1, frs2, &env->fp_status); 419 } 420 421 uint64_t helper_fminm_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2) 422 { 423 return float64_min(frs1, frs2, &env->fp_status); 424 } 425 426 uint64_t helper_fmax_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2) 427 { 428 return env->priv_ver < PRIV_VERSION_1_11_0 ? 429 float64_maxnum(frs1, frs2, &env->fp_status) : 430 float64_maximum_number(frs1, frs2, &env->fp_status); 431 } 432 433 uint64_t helper_fmaxm_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2) 434 { 435 return float64_max(frs1, frs2, &env->fp_status); 436 } 437 438 uint64_t helper_fcvt_s_d(CPURISCVState *env, uint64_t rs1) 439 { 440 return nanbox_s(env, float64_to_float32(rs1, &env->fp_status)); 441 } 442 443 uint64_t helper_fcvt_d_s(CPURISCVState *env, uint64_t rs1) 444 { 445 float32 frs1 = check_nanbox_s(env, rs1); 446 return float32_to_float64(frs1, &env->fp_status); 447 } 448 449 uint64_t helper_fsqrt_d(CPURISCVState *env, uint64_t frs1) 450 { 451 return float64_sqrt(frs1, &env->fp_status); 452 } 453 454 target_ulong helper_fle_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2) 455 { 456 return float64_le(frs1, frs2, &env->fp_status); 457 } 458 459 target_ulong helper_fleq_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2) 460 { 461 return float64_le_quiet(frs1, frs2, &env->fp_status); 462 } 463 464 target_ulong helper_flt_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2) 465 { 466 return float64_lt(frs1, frs2, &env->fp_status); 467 } 468 469 target_ulong helper_fltq_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2) 470 { 471 return float64_lt_quiet(frs1, frs2, &env->fp_status); 472 } 473 474 target_ulong helper_feq_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2) 475 { 476 return float64_eq_quiet(frs1, frs2, &env->fp_status); 477 } 478 479 target_ulong helper_fcvt_w_d(CPURISCVState *env, uint64_t frs1) 480 { 481 return float64_to_int32(frs1, &env->fp_status); 482 } 483 484 uint64_t helper_fcvtmod_w_d(CPURISCVState *env, uint64_t value) 485 { 486 return float64_to_int32_modulo(value, float_round_to_zero, &env->fp_status); 487 } 488 489 target_ulong helper_fcvt_wu_d(CPURISCVState *env, uint64_t frs1) 490 { 491 return (int32_t)float64_to_uint32(frs1, &env->fp_status); 492 } 493 494 target_ulong helper_fcvt_l_d(CPURISCVState *env, uint64_t frs1) 495 { 496 return float64_to_int64(frs1, &env->fp_status); 497 } 498 499 target_ulong helper_fcvt_lu_d(CPURISCVState *env, uint64_t frs1) 500 { 501 return float64_to_uint64(frs1, &env->fp_status); 502 } 503 504 uint64_t helper_fcvt_d_w(CPURISCVState *env, target_ulong rs1) 505 { 506 return int32_to_float64((int32_t)rs1, &env->fp_status); 507 } 508 509 uint64_t helper_fcvt_d_wu(CPURISCVState *env, target_ulong rs1) 510 { 511 return uint32_to_float64((uint32_t)rs1, &env->fp_status); 512 } 513 514 uint64_t helper_fcvt_d_l(CPURISCVState *env, target_ulong rs1) 515 { 516 return int64_to_float64(rs1, &env->fp_status); 517 } 518 519 uint64_t helper_fcvt_d_lu(CPURISCVState *env, target_ulong rs1) 520 { 521 return uint64_to_float64(rs1, &env->fp_status); 522 } 523 524 target_ulong helper_fclass_d(uint64_t frs1) 525 { 526 return fclass_d(frs1); 527 } 528 529 uint64_t helper_fround_d(CPURISCVState *env, uint64_t frs1) 530 { 531 float_status *fs = &env->fp_status; 532 uint16_t nx_old = get_float_exception_flags(fs) & float_flag_inexact; 533 534 frs1 = float64_round_to_int(frs1, fs); 535 536 /* Restore the original NX flag. */ 537 uint16_t flags = get_float_exception_flags(fs); 538 flags &= ~float_flag_inexact; 539 flags |= nx_old; 540 set_float_exception_flags(flags, fs); 541 542 return frs1; 543 } 544 545 uint64_t helper_froundnx_d(CPURISCVState *env, uint64_t frs1) 546 { 547 return float64_round_to_int(frs1, &env->fp_status); 548 } 549 550 uint64_t helper_fadd_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2) 551 { 552 float16 frs1 = check_nanbox_h(env, rs1); 553 float16 frs2 = check_nanbox_h(env, rs2); 554 return nanbox_h(env, float16_add(frs1, frs2, &env->fp_status)); 555 } 556 557 uint64_t helper_fsub_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2) 558 { 559 float16 frs1 = check_nanbox_h(env, rs1); 560 float16 frs2 = check_nanbox_h(env, rs2); 561 return nanbox_h(env, float16_sub(frs1, frs2, &env->fp_status)); 562 } 563 564 uint64_t helper_fmul_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2) 565 { 566 float16 frs1 = check_nanbox_h(env, rs1); 567 float16 frs2 = check_nanbox_h(env, rs2); 568 return nanbox_h(env, float16_mul(frs1, frs2, &env->fp_status)); 569 } 570 571 uint64_t helper_fdiv_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2) 572 { 573 float16 frs1 = check_nanbox_h(env, rs1); 574 float16 frs2 = check_nanbox_h(env, rs2); 575 return nanbox_h(env, float16_div(frs1, frs2, &env->fp_status)); 576 } 577 578 uint64_t helper_fmin_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2) 579 { 580 float16 frs1 = check_nanbox_h(env, rs1); 581 float16 frs2 = check_nanbox_h(env, rs2); 582 return nanbox_h(env, env->priv_ver < PRIV_VERSION_1_11_0 ? 583 float16_minnum(frs1, frs2, &env->fp_status) : 584 float16_minimum_number(frs1, frs2, &env->fp_status)); 585 } 586 587 uint64_t helper_fminm_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2) 588 { 589 float16 frs1 = check_nanbox_h(env, rs1); 590 float16 frs2 = check_nanbox_h(env, rs2); 591 float16 ret = float16_min(frs1, frs2, &env->fp_status); 592 return nanbox_h(env, ret); 593 } 594 595 uint64_t helper_fmax_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2) 596 { 597 float16 frs1 = check_nanbox_h(env, rs1); 598 float16 frs2 = check_nanbox_h(env, rs2); 599 return nanbox_h(env, env->priv_ver < PRIV_VERSION_1_11_0 ? 600 float16_maxnum(frs1, frs2, &env->fp_status) : 601 float16_maximum_number(frs1, frs2, &env->fp_status)); 602 } 603 604 uint64_t helper_fmaxm_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2) 605 { 606 float16 frs1 = check_nanbox_h(env, rs1); 607 float16 frs2 = check_nanbox_h(env, rs2); 608 float16 ret = float16_max(frs1, frs2, &env->fp_status); 609 return nanbox_h(env, ret); 610 } 611 612 uint64_t helper_fsqrt_h(CPURISCVState *env, uint64_t rs1) 613 { 614 float16 frs1 = check_nanbox_h(env, rs1); 615 return nanbox_h(env, float16_sqrt(frs1, &env->fp_status)); 616 } 617 618 target_ulong helper_fle_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2) 619 { 620 float16 frs1 = check_nanbox_h(env, rs1); 621 float16 frs2 = check_nanbox_h(env, rs2); 622 return float16_le(frs1, frs2, &env->fp_status); 623 } 624 625 target_ulong helper_fleq_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2) 626 { 627 float16 frs1 = check_nanbox_h(env, rs1); 628 float16 frs2 = check_nanbox_h(env, rs2); 629 return float16_le_quiet(frs1, frs2, &env->fp_status); 630 } 631 632 target_ulong helper_flt_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2) 633 { 634 float16 frs1 = check_nanbox_h(env, rs1); 635 float16 frs2 = check_nanbox_h(env, rs2); 636 return float16_lt(frs1, frs2, &env->fp_status); 637 } 638 639 target_ulong helper_fltq_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2) 640 { 641 float16 frs1 = check_nanbox_h(env, rs1); 642 float16 frs2 = check_nanbox_h(env, rs2); 643 return float16_lt_quiet(frs1, frs2, &env->fp_status); 644 } 645 646 target_ulong helper_feq_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2) 647 { 648 float16 frs1 = check_nanbox_h(env, rs1); 649 float16 frs2 = check_nanbox_h(env, rs2); 650 return float16_eq_quiet(frs1, frs2, &env->fp_status); 651 } 652 653 target_ulong helper_fclass_h(CPURISCVState *env, uint64_t rs1) 654 { 655 float16 frs1 = check_nanbox_h(env, rs1); 656 return fclass_h(frs1); 657 } 658 659 uint64_t helper_fround_h(CPURISCVState *env, uint64_t rs1) 660 { 661 float_status *fs = &env->fp_status; 662 uint16_t nx_old = get_float_exception_flags(fs) & float_flag_inexact; 663 float16 frs1 = check_nanbox_h(env, rs1); 664 665 frs1 = float16_round_to_int(frs1, fs); 666 667 /* Restore the original NX flag. */ 668 uint16_t flags = get_float_exception_flags(fs); 669 flags &= ~float_flag_inexact; 670 flags |= nx_old; 671 set_float_exception_flags(flags, fs); 672 673 return nanbox_h(env, frs1); 674 } 675 676 uint64_t helper_froundnx_h(CPURISCVState *env, uint64_t rs1) 677 { 678 float16 frs1 = check_nanbox_h(env, rs1); 679 frs1 = float16_round_to_int(frs1, &env->fp_status); 680 return nanbox_h(env, frs1); 681 } 682 683 target_ulong helper_fcvt_w_h(CPURISCVState *env, uint64_t rs1) 684 { 685 float16 frs1 = check_nanbox_h(env, rs1); 686 return float16_to_int32(frs1, &env->fp_status); 687 } 688 689 target_ulong helper_fcvt_wu_h(CPURISCVState *env, uint64_t rs1) 690 { 691 float16 frs1 = check_nanbox_h(env, rs1); 692 return (int32_t)float16_to_uint32(frs1, &env->fp_status); 693 } 694 695 target_ulong helper_fcvt_l_h(CPURISCVState *env, uint64_t rs1) 696 { 697 float16 frs1 = check_nanbox_h(env, rs1); 698 return float16_to_int64(frs1, &env->fp_status); 699 } 700 701 target_ulong helper_fcvt_lu_h(CPURISCVState *env, uint64_t rs1) 702 { 703 float16 frs1 = check_nanbox_h(env, rs1); 704 return float16_to_uint64(frs1, &env->fp_status); 705 } 706 707 uint64_t helper_fcvt_h_w(CPURISCVState *env, target_ulong rs1) 708 { 709 return nanbox_h(env, int32_to_float16((int32_t)rs1, &env->fp_status)); 710 } 711 712 uint64_t helper_fcvt_h_wu(CPURISCVState *env, target_ulong rs1) 713 { 714 return nanbox_h(env, uint32_to_float16((uint32_t)rs1, &env->fp_status)); 715 } 716 717 uint64_t helper_fcvt_h_l(CPURISCVState *env, target_ulong rs1) 718 { 719 return nanbox_h(env, int64_to_float16(rs1, &env->fp_status)); 720 } 721 722 uint64_t helper_fcvt_h_lu(CPURISCVState *env, target_ulong rs1) 723 { 724 return nanbox_h(env, uint64_to_float16(rs1, &env->fp_status)); 725 } 726 727 uint64_t helper_fcvt_h_s(CPURISCVState *env, uint64_t rs1) 728 { 729 float32 frs1 = check_nanbox_s(env, rs1); 730 return nanbox_h(env, float32_to_float16(frs1, true, &env->fp_status)); 731 } 732 733 uint64_t helper_fcvt_s_h(CPURISCVState *env, uint64_t rs1) 734 { 735 float16 frs1 = check_nanbox_h(env, rs1); 736 return nanbox_s(env, float16_to_float32(frs1, true, &env->fp_status)); 737 } 738 739 uint64_t helper_fcvt_h_d(CPURISCVState *env, uint64_t rs1) 740 { 741 return nanbox_h(env, float64_to_float16(rs1, true, &env->fp_status)); 742 } 743 744 uint64_t helper_fcvt_d_h(CPURISCVState *env, uint64_t rs1) 745 { 746 float16 frs1 = check_nanbox_h(env, rs1); 747 return float16_to_float64(frs1, true, &env->fp_status); 748 } 749 750 uint64_t helper_fcvt_bf16_s(CPURISCVState *env, uint64_t rs1) 751 { 752 float32 frs1 = check_nanbox_s(env, rs1); 753 return nanbox_h(env, float32_to_bfloat16(frs1, &env->fp_status)); 754 } 755 756 uint64_t helper_fcvt_s_bf16(CPURISCVState *env, uint64_t rs1) 757 { 758 float16 frs1 = check_nanbox_h(env, rs1); 759 return nanbox_s(env, bfloat16_to_float32(frs1, &env->fp_status)); 760 } 761