qemu/target/riscv/fpu_helper.c
<<
>>
Prefs
   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/exec-all.h"
  23#include "exec/helper-proto.h"
  24#include "fpu/softfloat.h"
  25#include "internals.h"
  26
  27target_ulong riscv_cpu_get_fflags(CPURISCVState *env)
  28{
  29    int soft = get_float_exception_flags(&env->fp_status);
  30    target_ulong hard = 0;
  31
  32    hard |= (soft & float_flag_inexact) ? FPEXC_NX : 0;
  33    hard |= (soft & float_flag_underflow) ? FPEXC_UF : 0;
  34    hard |= (soft & float_flag_overflow) ? FPEXC_OF : 0;
  35    hard |= (soft & float_flag_divbyzero) ? FPEXC_DZ : 0;
  36    hard |= (soft & float_flag_invalid) ? FPEXC_NV : 0;
  37
  38    return hard;
  39}
  40
  41void riscv_cpu_set_fflags(CPURISCVState *env, target_ulong hard)
  42{
  43    int soft = 0;
  44
  45    soft |= (hard & FPEXC_NX) ? float_flag_inexact : 0;
  46    soft |= (hard & FPEXC_UF) ? float_flag_underflow : 0;
  47    soft |= (hard & FPEXC_OF) ? float_flag_overflow : 0;
  48    soft |= (hard & FPEXC_DZ) ? float_flag_divbyzero : 0;
  49    soft |= (hard & FPEXC_NV) ? float_flag_invalid : 0;
  50
  51    set_float_exception_flags(soft, &env->fp_status);
  52}
  53
  54void helper_set_rounding_mode(CPURISCVState *env, uint32_t rm)
  55{
  56    int softrm;
  57
  58    if (rm == RISCV_FRM_DYN) {
  59        rm = env->frm;
  60    }
  61    switch (rm) {
  62    case RISCV_FRM_RNE:
  63        softrm = float_round_nearest_even;
  64        break;
  65    case RISCV_FRM_RTZ:
  66        softrm = float_round_to_zero;
  67        break;
  68    case RISCV_FRM_RDN:
  69        softrm = float_round_down;
  70        break;
  71    case RISCV_FRM_RUP:
  72        softrm = float_round_up;
  73        break;
  74    case RISCV_FRM_RMM:
  75        softrm = float_round_ties_away;
  76        break;
  77    default:
  78        riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
  79    }
  80
  81    set_float_rounding_mode(softrm, &env->fp_status);
  82}
  83
  84void helper_set_rod_rounding_mode(CPURISCVState *env)
  85{
  86    set_float_rounding_mode(float_round_to_odd, &env->fp_status);
  87}
  88
  89static uint64_t do_fmadd_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2,
  90                           uint64_t rs3, int flags)
  91{
  92    float16 frs1 = check_nanbox_h(env, rs1);
  93    float16 frs2 = check_nanbox_h(env, rs2);
  94    float16 frs3 = check_nanbox_h(env, rs3);
  95    return nanbox_h(env, float16_muladd(frs1, frs2, frs3, flags,
  96                                        &env->fp_status));
  97}
  98
  99static uint64_t do_fmadd_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2,
 100                           uint64_t rs3, int flags)
 101{
 102    float32 frs1 = check_nanbox_s(env, rs1);
 103    float32 frs2 = check_nanbox_s(env, rs2);
 104    float32 frs3 = check_nanbox_s(env, rs3);
 105    return nanbox_s(env, float32_muladd(frs1, frs2, frs3, flags,
 106                                        &env->fp_status));
 107}
 108
 109uint64_t helper_fmadd_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
 110                        uint64_t frs3)
 111{
 112    return do_fmadd_s(env, frs1, frs2, frs3, 0);
 113}
 114
 115uint64_t helper_fmadd_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
 116                        uint64_t frs3)
 117{
 118    return float64_muladd(frs1, frs2, frs3, 0, &env->fp_status);
 119}
 120
 121uint64_t helper_fmadd_h(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
 122                        uint64_t frs3)
 123{
 124    return do_fmadd_h(env, frs1, frs2, frs3, 0);
 125}
 126
 127uint64_t helper_fmsub_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
 128                        uint64_t frs3)
 129{
 130    return do_fmadd_s(env, frs1, frs2, frs3, float_muladd_negate_c);
 131}
 132
 133uint64_t helper_fmsub_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
 134                        uint64_t frs3)
 135{
 136    return float64_muladd(frs1, frs2, frs3, float_muladd_negate_c,
 137                          &env->fp_status);
 138}
 139
 140uint64_t helper_fmsub_h(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
 141                        uint64_t frs3)
 142{
 143    return do_fmadd_h(env, frs1, frs2, frs3, float_muladd_negate_c);
 144}
 145
 146uint64_t helper_fnmsub_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
 147                         uint64_t frs3)
 148{
 149    return do_fmadd_s(env, frs1, frs2, frs3, float_muladd_negate_product);
 150}
 151
 152uint64_t helper_fnmsub_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
 153                         uint64_t frs3)
 154{
 155    return float64_muladd(frs1, frs2, frs3, float_muladd_negate_product,
 156                          &env->fp_status);
 157}
 158
 159uint64_t helper_fnmsub_h(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
 160                         uint64_t frs3)
 161{
 162    return do_fmadd_h(env, frs1, frs2, frs3, float_muladd_negate_product);
 163}
 164
 165uint64_t helper_fnmadd_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
 166                         uint64_t frs3)
 167{
 168    return do_fmadd_s(env, frs1, frs2, frs3,
 169                      float_muladd_negate_c | float_muladd_negate_product);
 170}
 171
 172uint64_t helper_fnmadd_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
 173                         uint64_t frs3)
 174{
 175    return float64_muladd(frs1, frs2, frs3, float_muladd_negate_c |
 176                          float_muladd_negate_product, &env->fp_status);
 177}
 178
 179uint64_t helper_fnmadd_h(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
 180                         uint64_t frs3)
 181{
 182    return do_fmadd_h(env, frs1, frs2, frs3,
 183                      float_muladd_negate_c | float_muladd_negate_product);
 184}
 185
 186uint64_t helper_fadd_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
 187{
 188    float32 frs1 = check_nanbox_s(env, rs1);
 189    float32 frs2 = check_nanbox_s(env, rs2);
 190    return nanbox_s(env, float32_add(frs1, frs2, &env->fp_status));
 191}
 192
 193uint64_t helper_fsub_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
 194{
 195    float32 frs1 = check_nanbox_s(env, rs1);
 196    float32 frs2 = check_nanbox_s(env, rs2);
 197    return nanbox_s(env, float32_sub(frs1, frs2, &env->fp_status));
 198}
 199
 200uint64_t helper_fmul_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
 201{
 202    float32 frs1 = check_nanbox_s(env, rs1);
 203    float32 frs2 = check_nanbox_s(env, rs2);
 204    return nanbox_s(env, float32_mul(frs1, frs2, &env->fp_status));
 205}
 206
 207uint64_t helper_fdiv_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
 208{
 209    float32 frs1 = check_nanbox_s(env, rs1);
 210    float32 frs2 = check_nanbox_s(env, rs2);
 211    return nanbox_s(env, float32_div(frs1, frs2, &env->fp_status));
 212}
 213
 214uint64_t helper_fmin_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
 215{
 216    float32 frs1 = check_nanbox_s(env, rs1);
 217    float32 frs2 = check_nanbox_s(env, rs2);
 218    return nanbox_s(env, env->priv_ver < PRIV_VERSION_1_11_0 ?
 219                    float32_minnum(frs1, frs2, &env->fp_status) :
 220                    float32_minimum_number(frs1, frs2, &env->fp_status));
 221}
 222
 223uint64_t helper_fmax_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
 224{
 225    float32 frs1 = check_nanbox_s(env, rs1);
 226    float32 frs2 = check_nanbox_s(env, rs2);
 227    return nanbox_s(env, env->priv_ver < PRIV_VERSION_1_11_0 ?
 228                    float32_maxnum(frs1, frs2, &env->fp_status) :
 229                    float32_maximum_number(frs1, frs2, &env->fp_status));
 230}
 231
 232uint64_t helper_fsqrt_s(CPURISCVState *env, uint64_t rs1)
 233{
 234    float32 frs1 = check_nanbox_s(env, rs1);
 235    return nanbox_s(env, float32_sqrt(frs1, &env->fp_status));
 236}
 237
 238target_ulong helper_fle_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 float32_le(frs1, frs2, &env->fp_status);
 243}
 244
 245target_ulong helper_flt_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 float32_lt(frs1, frs2, &env->fp_status);
 250}
 251
 252target_ulong helper_feq_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
 253{
 254    float32 frs1 = check_nanbox_s(env, rs1);
 255    float32 frs2 = check_nanbox_s(env, rs2);
 256    return float32_eq_quiet(frs1, frs2, &env->fp_status);
 257}
 258
 259target_ulong helper_fcvt_w_s(CPURISCVState *env, uint64_t rs1)
 260{
 261    float32 frs1 = check_nanbox_s(env, rs1);
 262    return float32_to_int32(frs1, &env->fp_status);
 263}
 264
 265target_ulong helper_fcvt_wu_s(CPURISCVState *env, uint64_t rs1)
 266{
 267    float32 frs1 = check_nanbox_s(env, rs1);
 268    return (int32_t)float32_to_uint32(frs1, &env->fp_status);
 269}
 270
 271target_ulong helper_fcvt_l_s(CPURISCVState *env, uint64_t rs1)
 272{
 273    float32 frs1 = check_nanbox_s(env, rs1);
 274    return float32_to_int64(frs1, &env->fp_status);
 275}
 276
 277target_ulong helper_fcvt_lu_s(CPURISCVState *env, uint64_t rs1)
 278{
 279    float32 frs1 = check_nanbox_s(env, rs1);
 280    return float32_to_uint64(frs1, &env->fp_status);
 281}
 282
 283uint64_t helper_fcvt_s_w(CPURISCVState *env, target_ulong rs1)
 284{
 285    return nanbox_s(env, int32_to_float32((int32_t)rs1, &env->fp_status));
 286}
 287
 288uint64_t helper_fcvt_s_wu(CPURISCVState *env, target_ulong rs1)
 289{
 290    return nanbox_s(env, uint32_to_float32((uint32_t)rs1, &env->fp_status));
 291}
 292
 293uint64_t helper_fcvt_s_l(CPURISCVState *env, target_ulong rs1)
 294{
 295    return nanbox_s(env, int64_to_float32(rs1, &env->fp_status));
 296}
 297
 298uint64_t helper_fcvt_s_lu(CPURISCVState *env, target_ulong rs1)
 299{
 300    return nanbox_s(env, uint64_to_float32(rs1, &env->fp_status));
 301}
 302
 303target_ulong helper_fclass_s(CPURISCVState *env, uint64_t rs1)
 304{
 305    float32 frs1 = check_nanbox_s(env, rs1);
 306    return fclass_s(frs1);
 307}
 308
 309uint64_t helper_fadd_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
 310{
 311    return float64_add(frs1, frs2, &env->fp_status);
 312}
 313
 314uint64_t helper_fsub_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
 315{
 316    return float64_sub(frs1, frs2, &env->fp_status);
 317}
 318
 319uint64_t helper_fmul_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
 320{
 321    return float64_mul(frs1, frs2, &env->fp_status);
 322}
 323
 324uint64_t helper_fdiv_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
 325{
 326    return float64_div(frs1, frs2, &env->fp_status);
 327}
 328
 329uint64_t helper_fmin_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
 330{
 331    return env->priv_ver < PRIV_VERSION_1_11_0 ?
 332            float64_minnum(frs1, frs2, &env->fp_status) :
 333            float64_minimum_number(frs1, frs2, &env->fp_status);
 334}
 335
 336uint64_t helper_fmax_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
 337{
 338    return env->priv_ver < PRIV_VERSION_1_11_0 ?
 339            float64_maxnum(frs1, frs2, &env->fp_status) :
 340            float64_maximum_number(frs1, frs2, &env->fp_status);
 341}
 342
 343uint64_t helper_fcvt_s_d(CPURISCVState *env, uint64_t rs1)
 344{
 345    return nanbox_s(env, float64_to_float32(rs1, &env->fp_status));
 346}
 347
 348uint64_t helper_fcvt_d_s(CPURISCVState *env, uint64_t rs1)
 349{
 350    float32 frs1 = check_nanbox_s(env, rs1);
 351    return float32_to_float64(frs1, &env->fp_status);
 352}
 353
 354uint64_t helper_fsqrt_d(CPURISCVState *env, uint64_t frs1)
 355{
 356    return float64_sqrt(frs1, &env->fp_status);
 357}
 358
 359target_ulong helper_fle_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
 360{
 361    return float64_le(frs1, frs2, &env->fp_status);
 362}
 363
 364target_ulong helper_flt_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
 365{
 366    return float64_lt(frs1, frs2, &env->fp_status);
 367}
 368
 369target_ulong helper_feq_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
 370{
 371    return float64_eq_quiet(frs1, frs2, &env->fp_status);
 372}
 373
 374target_ulong helper_fcvt_w_d(CPURISCVState *env, uint64_t frs1)
 375{
 376    return float64_to_int32(frs1, &env->fp_status);
 377}
 378
 379target_ulong helper_fcvt_wu_d(CPURISCVState *env, uint64_t frs1)
 380{
 381    return (int32_t)float64_to_uint32(frs1, &env->fp_status);
 382}
 383
 384target_ulong helper_fcvt_l_d(CPURISCVState *env, uint64_t frs1)
 385{
 386    return float64_to_int64(frs1, &env->fp_status);
 387}
 388
 389target_ulong helper_fcvt_lu_d(CPURISCVState *env, uint64_t frs1)
 390{
 391    return float64_to_uint64(frs1, &env->fp_status);
 392}
 393
 394uint64_t helper_fcvt_d_w(CPURISCVState *env, target_ulong rs1)
 395{
 396    return int32_to_float64((int32_t)rs1, &env->fp_status);
 397}
 398
 399uint64_t helper_fcvt_d_wu(CPURISCVState *env, target_ulong rs1)
 400{
 401    return uint32_to_float64((uint32_t)rs1, &env->fp_status);
 402}
 403
 404uint64_t helper_fcvt_d_l(CPURISCVState *env, target_ulong rs1)
 405{
 406    return int64_to_float64(rs1, &env->fp_status);
 407}
 408
 409uint64_t helper_fcvt_d_lu(CPURISCVState *env, target_ulong rs1)
 410{
 411    return uint64_to_float64(rs1, &env->fp_status);
 412}
 413
 414target_ulong helper_fclass_d(uint64_t frs1)
 415{
 416    return fclass_d(frs1);
 417}
 418
 419uint64_t helper_fadd_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
 420{
 421    float16 frs1 = check_nanbox_h(env, rs1);
 422    float16 frs2 = check_nanbox_h(env, rs2);
 423    return nanbox_h(env, float16_add(frs1, frs2, &env->fp_status));
 424}
 425
 426uint64_t helper_fsub_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
 427{
 428    float16 frs1 = check_nanbox_h(env, rs1);
 429    float16 frs2 = check_nanbox_h(env, rs2);
 430    return nanbox_h(env, float16_sub(frs1, frs2, &env->fp_status));
 431}
 432
 433uint64_t helper_fmul_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
 434{
 435    float16 frs1 = check_nanbox_h(env, rs1);
 436    float16 frs2 = check_nanbox_h(env, rs2);
 437    return nanbox_h(env, float16_mul(frs1, frs2, &env->fp_status));
 438}
 439
 440uint64_t helper_fdiv_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
 441{
 442    float16 frs1 = check_nanbox_h(env, rs1);
 443    float16 frs2 = check_nanbox_h(env, rs2);
 444    return nanbox_h(env, float16_div(frs1, frs2, &env->fp_status));
 445}
 446
 447uint64_t helper_fmin_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
 448{
 449    float16 frs1 = check_nanbox_h(env, rs1);
 450    float16 frs2 = check_nanbox_h(env, rs2);
 451    return nanbox_h(env, env->priv_ver < PRIV_VERSION_1_11_0 ?
 452                    float16_minnum(frs1, frs2, &env->fp_status) :
 453                    float16_minimum_number(frs1, frs2, &env->fp_status));
 454}
 455
 456uint64_t helper_fmax_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
 457{
 458    float16 frs1 = check_nanbox_h(env, rs1);
 459    float16 frs2 = check_nanbox_h(env, rs2);
 460    return nanbox_h(env, env->priv_ver < PRIV_VERSION_1_11_0 ?
 461                    float16_maxnum(frs1, frs2, &env->fp_status) :
 462                    float16_maximum_number(frs1, frs2, &env->fp_status));
 463}
 464
 465uint64_t helper_fsqrt_h(CPURISCVState *env, uint64_t rs1)
 466{
 467    float16 frs1 = check_nanbox_h(env, rs1);
 468    return nanbox_h(env, float16_sqrt(frs1, &env->fp_status));
 469}
 470
 471target_ulong helper_fle_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
 472{
 473    float16 frs1 = check_nanbox_h(env, rs1);
 474    float16 frs2 = check_nanbox_h(env, rs2);
 475    return float16_le(frs1, frs2, &env->fp_status);
 476}
 477
 478target_ulong helper_flt_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
 479{
 480    float16 frs1 = check_nanbox_h(env, rs1);
 481    float16 frs2 = check_nanbox_h(env, rs2);
 482    return float16_lt(frs1, frs2, &env->fp_status);
 483}
 484
 485target_ulong helper_feq_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
 486{
 487    float16 frs1 = check_nanbox_h(env, rs1);
 488    float16 frs2 = check_nanbox_h(env, rs2);
 489    return float16_eq_quiet(frs1, frs2, &env->fp_status);
 490}
 491
 492target_ulong helper_fclass_h(CPURISCVState *env, uint64_t rs1)
 493{
 494    float16 frs1 = check_nanbox_h(env, rs1);
 495    return fclass_h(frs1);
 496}
 497
 498target_ulong helper_fcvt_w_h(CPURISCVState *env, uint64_t rs1)
 499{
 500    float16 frs1 = check_nanbox_h(env, rs1);
 501    return float16_to_int32(frs1, &env->fp_status);
 502}
 503
 504target_ulong helper_fcvt_wu_h(CPURISCVState *env, uint64_t rs1)
 505{
 506    float16 frs1 = check_nanbox_h(env, rs1);
 507    return (int32_t)float16_to_uint32(frs1, &env->fp_status);
 508}
 509
 510target_ulong helper_fcvt_l_h(CPURISCVState *env, uint64_t rs1)
 511{
 512    float16 frs1 = check_nanbox_h(env, rs1);
 513    return float16_to_int64(frs1, &env->fp_status);
 514}
 515
 516target_ulong helper_fcvt_lu_h(CPURISCVState *env, uint64_t rs1)
 517{
 518    float16 frs1 = check_nanbox_h(env, rs1);
 519    return float16_to_uint64(frs1, &env->fp_status);
 520}
 521
 522uint64_t helper_fcvt_h_w(CPURISCVState *env, target_ulong rs1)
 523{
 524    return nanbox_h(env, int32_to_float16((int32_t)rs1, &env->fp_status));
 525}
 526
 527uint64_t helper_fcvt_h_wu(CPURISCVState *env, target_ulong rs1)
 528{
 529    return nanbox_h(env, uint32_to_float16((uint32_t)rs1, &env->fp_status));
 530}
 531
 532uint64_t helper_fcvt_h_l(CPURISCVState *env, target_ulong rs1)
 533{
 534    return nanbox_h(env, int64_to_float16(rs1, &env->fp_status));
 535}
 536
 537uint64_t helper_fcvt_h_lu(CPURISCVState *env, target_ulong rs1)
 538{
 539    return nanbox_h(env, uint64_to_float16(rs1, &env->fp_status));
 540}
 541
 542uint64_t helper_fcvt_h_s(CPURISCVState *env, uint64_t rs1)
 543{
 544    float32 frs1 = check_nanbox_s(env, rs1);
 545    return nanbox_h(env, float32_to_float16(frs1, true, &env->fp_status));
 546}
 547
 548uint64_t helper_fcvt_s_h(CPURISCVState *env, uint64_t rs1)
 549{
 550    float16 frs1 = check_nanbox_h(env, rs1);
 551    return nanbox_s(env, float16_to_float32(frs1, true, &env->fp_status));
 552}
 553
 554uint64_t helper_fcvt_h_d(CPURISCVState *env, uint64_t rs1)
 555{
 556    return nanbox_h(env, float64_to_float16(rs1, true, &env->fp_status));
 557}
 558
 559uint64_t helper_fcvt_d_h(CPURISCVState *env, uint64_t rs1)
 560{
 561    float16 frs1 = check_nanbox_h(env, rs1);
 562    return float16_to_float64(frs1, true, &env->fp_status);
 563}
 564