1 /* 2 * Helpers for emulation of FPU-related MIPS instructions. 3 * 4 * Copyright (C) 2004-2005 Jocelyn Mayer 5 * Copyright (C) 2020 Wave Computing, Inc. 6 * Copyright (C) 2020 Aleksandar Markovic <amarkovic@wavecomp.com> 7 * 8 * This library is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Lesser General Public 10 * License as published by the Free Software Foundation; either 11 * version 2.1 of the License, or (at your option) any later version. 12 * 13 * This library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public 19 * License along with this library; if not, see <http://www.gnu.org/licenses/>. 20 * 21 */ 22 23 #include "qemu/osdep.h" 24 #include "cpu.h" 25 #include "internal.h" 26 #include "exec/helper-proto.h" 27 #include "exec/exec-all.h" 28 #include "exec/cpu_ldst.h" 29 #include "fpu/softfloat.h" 30 #include "fpu_helper.h" 31 32 33 /* Complex FPU operations which may need stack space. */ 34 35 #define FLOAT_TWO32 make_float32(1 << 30) 36 #define FLOAT_TWO64 make_float64(1ULL << 62) 37 38 #define FP_TO_INT32_OVERFLOW 0x7fffffff 39 #define FP_TO_INT64_OVERFLOW 0x7fffffffffffffffULL 40 41 target_ulong helper_cfc1(CPUMIPSState *env, uint32_t reg) 42 { 43 target_ulong arg1 = 0; 44 45 switch (reg) { 46 case 0: 47 arg1 = (int32_t)env->active_fpu.fcr0; 48 break; 49 case 1: 50 /* UFR Support - Read Status FR */ 51 if (env->active_fpu.fcr0 & (1 << FCR0_UFRP)) { 52 if (env->CP0_Config5 & (1 << CP0C5_UFR)) { 53 arg1 = (int32_t) 54 ((env->CP0_Status & (1 << CP0St_FR)) >> CP0St_FR); 55 } else { 56 do_raise_exception(env, EXCP_RI, GETPC()); 57 } 58 } 59 break; 60 case 5: 61 /* FRE Support - read Config5.FRE bit */ 62 if (env->active_fpu.fcr0 & (1 << FCR0_FREP)) { 63 if (env->CP0_Config5 & (1 << CP0C5_UFE)) { 64 arg1 = (env->CP0_Config5 >> CP0C5_FRE) & 1; 65 } else { 66 helper_raise_exception(env, EXCP_RI); 67 } 68 } 69 break; 70 case 25: 71 arg1 = ((env->active_fpu.fcr31 >> 24) & 0xfe) | 72 ((env->active_fpu.fcr31 >> 23) & 0x1); 73 break; 74 case 26: 75 arg1 = env->active_fpu.fcr31 & 0x0003f07c; 76 break; 77 case 28: 78 arg1 = (env->active_fpu.fcr31 & 0x00000f83) | 79 ((env->active_fpu.fcr31 >> 22) & 0x4); 80 break; 81 default: 82 arg1 = (int32_t)env->active_fpu.fcr31; 83 break; 84 } 85 86 return arg1; 87 } 88 89 void helper_ctc1(CPUMIPSState *env, target_ulong arg1, uint32_t fs, uint32_t rt) 90 { 91 switch (fs) { 92 case 1: 93 /* UFR Alias - Reset Status FR */ 94 if (!((env->active_fpu.fcr0 & (1 << FCR0_UFRP)) && (rt == 0))) { 95 return; 96 } 97 if (env->CP0_Config5 & (1 << CP0C5_UFR)) { 98 env->CP0_Status &= ~(1 << CP0St_FR); 99 compute_hflags(env); 100 } else { 101 do_raise_exception(env, EXCP_RI, GETPC()); 102 } 103 break; 104 case 4: 105 /* UNFR Alias - Set Status FR */ 106 if (!((env->active_fpu.fcr0 & (1 << FCR0_UFRP)) && (rt == 0))) { 107 return; 108 } 109 if (env->CP0_Config5 & (1 << CP0C5_UFR)) { 110 env->CP0_Status |= (1 << CP0St_FR); 111 compute_hflags(env); 112 } else { 113 do_raise_exception(env, EXCP_RI, GETPC()); 114 } 115 break; 116 case 5: 117 /* FRE Support - clear Config5.FRE bit */ 118 if (!((env->active_fpu.fcr0 & (1 << FCR0_FREP)) && (rt == 0))) { 119 return; 120 } 121 if (env->CP0_Config5 & (1 << CP0C5_UFE)) { 122 env->CP0_Config5 &= ~(1 << CP0C5_FRE); 123 compute_hflags(env); 124 } else { 125 helper_raise_exception(env, EXCP_RI); 126 } 127 break; 128 case 6: 129 /* FRE Support - set Config5.FRE bit */ 130 if (!((env->active_fpu.fcr0 & (1 << FCR0_FREP)) && (rt == 0))) { 131 return; 132 } 133 if (env->CP0_Config5 & (1 << CP0C5_UFE)) { 134 env->CP0_Config5 |= (1 << CP0C5_FRE); 135 compute_hflags(env); 136 } else { 137 helper_raise_exception(env, EXCP_RI); 138 } 139 break; 140 case 25: 141 if ((env->insn_flags & ISA_MIPS_R6) || (arg1 & 0xffffff00)) { 142 return; 143 } 144 env->active_fpu.fcr31 = (env->active_fpu.fcr31 & 0x017fffff) | 145 ((arg1 & 0xfe) << 24) | 146 ((arg1 & 0x1) << 23); 147 break; 148 case 26: 149 if (arg1 & 0x007c0000) { 150 return; 151 } 152 env->active_fpu.fcr31 = (env->active_fpu.fcr31 & 0xfffc0f83) | 153 (arg1 & 0x0003f07c); 154 break; 155 case 28: 156 if (arg1 & 0x007c0000) { 157 return; 158 } 159 env->active_fpu.fcr31 = (env->active_fpu.fcr31 & 0xfefff07c) | 160 (arg1 & 0x00000f83) | 161 ((arg1 & 0x4) << 22); 162 break; 163 case 31: 164 env->active_fpu.fcr31 = (arg1 & env->active_fpu.fcr31_rw_bitmask) | 165 (env->active_fpu.fcr31 & ~(env->active_fpu.fcr31_rw_bitmask)); 166 break; 167 default: 168 if (env->insn_flags & ISA_MIPS_R6) { 169 do_raise_exception(env, EXCP_RI, GETPC()); 170 } 171 return; 172 } 173 restore_fp_status(env); 174 set_float_exception_flags(0, &env->active_fpu.fp_status); 175 if ((GET_FP_ENABLE(env->active_fpu.fcr31) | 0x20) & 176 GET_FP_CAUSE(env->active_fpu.fcr31)) { 177 do_raise_exception(env, EXCP_FPE, GETPC()); 178 } 179 } 180 181 static inline int ieee_to_mips_xcpt(int ieee_xcpt) 182 { 183 int mips_xcpt = 0; 184 185 if (ieee_xcpt & float_flag_invalid) { 186 mips_xcpt |= FP_INVALID; 187 } 188 if (ieee_xcpt & float_flag_overflow) { 189 mips_xcpt |= FP_OVERFLOW; 190 } 191 if (ieee_xcpt & float_flag_underflow) { 192 mips_xcpt |= FP_UNDERFLOW; 193 } 194 if (ieee_xcpt & float_flag_divbyzero) { 195 mips_xcpt |= FP_DIV0; 196 } 197 if (ieee_xcpt & float_flag_inexact) { 198 mips_xcpt |= FP_INEXACT; 199 } 200 201 return mips_xcpt; 202 } 203 204 static inline void update_fcr31(CPUMIPSState *env, uintptr_t pc) 205 { 206 int ieee_exception_flags = get_float_exception_flags( 207 &env->active_fpu.fp_status); 208 int mips_exception_flags = 0; 209 210 if (ieee_exception_flags) { 211 mips_exception_flags = ieee_to_mips_xcpt(ieee_exception_flags); 212 } 213 214 SET_FP_CAUSE(env->active_fpu.fcr31, mips_exception_flags); 215 216 if (mips_exception_flags) { 217 set_float_exception_flags(0, &env->active_fpu.fp_status); 218 219 if (GET_FP_ENABLE(env->active_fpu.fcr31) & mips_exception_flags) { 220 do_raise_exception(env, EXCP_FPE, pc); 221 } else { 222 UPDATE_FP_FLAGS(env->active_fpu.fcr31, mips_exception_flags); 223 } 224 } 225 } 226 227 /* 228 * Float support. 229 * Single precition routines have a "s" suffix, double precision a 230 * "d" suffix, 32bit integer "w", 64bit integer "l", paired single "ps", 231 * paired single lower "pl", paired single upper "pu". 232 */ 233 234 /* unary operations, modifying fp status */ 235 uint64_t helper_float_sqrt_d(CPUMIPSState *env, uint64_t fdt0) 236 { 237 fdt0 = float64_sqrt(fdt0, &env->active_fpu.fp_status); 238 update_fcr31(env, GETPC()); 239 return fdt0; 240 } 241 242 uint32_t helper_float_sqrt_s(CPUMIPSState *env, uint32_t fst0) 243 { 244 fst0 = float32_sqrt(fst0, &env->active_fpu.fp_status); 245 update_fcr31(env, GETPC()); 246 return fst0; 247 } 248 249 uint64_t helper_float_cvtd_s(CPUMIPSState *env, uint32_t fst0) 250 { 251 uint64_t fdt2; 252 253 fdt2 = float32_to_float64(fst0, &env->active_fpu.fp_status); 254 update_fcr31(env, GETPC()); 255 return fdt2; 256 } 257 258 uint64_t helper_float_cvtd_w(CPUMIPSState *env, uint32_t wt0) 259 { 260 uint64_t fdt2; 261 262 fdt2 = int32_to_float64(wt0, &env->active_fpu.fp_status); 263 update_fcr31(env, GETPC()); 264 return fdt2; 265 } 266 267 uint64_t helper_float_cvtd_l(CPUMIPSState *env, uint64_t dt0) 268 { 269 uint64_t fdt2; 270 271 fdt2 = int64_to_float64(dt0, &env->active_fpu.fp_status); 272 update_fcr31(env, GETPC()); 273 return fdt2; 274 } 275 276 uint64_t helper_float_cvt_l_d(CPUMIPSState *env, uint64_t fdt0) 277 { 278 uint64_t dt2; 279 280 dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status); 281 if (get_float_exception_flags(&env->active_fpu.fp_status) 282 & (float_flag_invalid | float_flag_overflow)) { 283 dt2 = FP_TO_INT64_OVERFLOW; 284 } 285 update_fcr31(env, GETPC()); 286 return dt2; 287 } 288 289 uint64_t helper_float_cvt_l_s(CPUMIPSState *env, uint32_t fst0) 290 { 291 uint64_t dt2; 292 293 dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status); 294 if (get_float_exception_flags(&env->active_fpu.fp_status) 295 & (float_flag_invalid | float_flag_overflow)) { 296 dt2 = FP_TO_INT64_OVERFLOW; 297 } 298 update_fcr31(env, GETPC()); 299 return dt2; 300 } 301 302 uint64_t helper_float_cvtps_pw(CPUMIPSState *env, uint64_t dt0) 303 { 304 uint32_t fst2; 305 uint32_t fsth2; 306 307 fst2 = int32_to_float32(dt0 & 0XFFFFFFFF, &env->active_fpu.fp_status); 308 fsth2 = int32_to_float32(dt0 >> 32, &env->active_fpu.fp_status); 309 update_fcr31(env, GETPC()); 310 return ((uint64_t)fsth2 << 32) | fst2; 311 } 312 313 uint64_t helper_float_cvtpw_ps(CPUMIPSState *env, uint64_t fdt0) 314 { 315 uint32_t wt2; 316 uint32_t wth2; 317 int excp, excph; 318 319 wt2 = float32_to_int32(fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status); 320 excp = get_float_exception_flags(&env->active_fpu.fp_status); 321 if (excp & (float_flag_overflow | float_flag_invalid)) { 322 wt2 = FP_TO_INT32_OVERFLOW; 323 } 324 325 set_float_exception_flags(0, &env->active_fpu.fp_status); 326 wth2 = float32_to_int32(fdt0 >> 32, &env->active_fpu.fp_status); 327 excph = get_float_exception_flags(&env->active_fpu.fp_status); 328 if (excph & (float_flag_overflow | float_flag_invalid)) { 329 wth2 = FP_TO_INT32_OVERFLOW; 330 } 331 332 set_float_exception_flags(excp | excph, &env->active_fpu.fp_status); 333 update_fcr31(env, GETPC()); 334 335 return ((uint64_t)wth2 << 32) | wt2; 336 } 337 338 uint32_t helper_float_cvts_d(CPUMIPSState *env, uint64_t fdt0) 339 { 340 uint32_t fst2; 341 342 fst2 = float64_to_float32(fdt0, &env->active_fpu.fp_status); 343 update_fcr31(env, GETPC()); 344 return fst2; 345 } 346 347 uint32_t helper_float_cvts_w(CPUMIPSState *env, uint32_t wt0) 348 { 349 uint32_t fst2; 350 351 fst2 = int32_to_float32(wt0, &env->active_fpu.fp_status); 352 update_fcr31(env, GETPC()); 353 return fst2; 354 } 355 356 uint32_t helper_float_cvts_l(CPUMIPSState *env, uint64_t dt0) 357 { 358 uint32_t fst2; 359 360 fst2 = int64_to_float32(dt0, &env->active_fpu.fp_status); 361 update_fcr31(env, GETPC()); 362 return fst2; 363 } 364 365 uint32_t helper_float_cvts_pl(CPUMIPSState *env, uint32_t wt0) 366 { 367 uint32_t wt2; 368 369 wt2 = wt0; 370 update_fcr31(env, GETPC()); 371 return wt2; 372 } 373 374 uint32_t helper_float_cvts_pu(CPUMIPSState *env, uint32_t wth0) 375 { 376 uint32_t wt2; 377 378 wt2 = wth0; 379 update_fcr31(env, GETPC()); 380 return wt2; 381 } 382 383 uint32_t helper_float_cvt_w_s(CPUMIPSState *env, uint32_t fst0) 384 { 385 uint32_t wt2; 386 387 wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status); 388 if (get_float_exception_flags(&env->active_fpu.fp_status) 389 & (float_flag_invalid | float_flag_overflow)) { 390 wt2 = FP_TO_INT32_OVERFLOW; 391 } 392 update_fcr31(env, GETPC()); 393 return wt2; 394 } 395 396 uint32_t helper_float_cvt_w_d(CPUMIPSState *env, uint64_t fdt0) 397 { 398 uint32_t wt2; 399 400 wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status); 401 if (get_float_exception_flags(&env->active_fpu.fp_status) 402 & (float_flag_invalid | float_flag_overflow)) { 403 wt2 = FP_TO_INT32_OVERFLOW; 404 } 405 update_fcr31(env, GETPC()); 406 return wt2; 407 } 408 409 uint64_t helper_float_round_l_d(CPUMIPSState *env, uint64_t fdt0) 410 { 411 uint64_t dt2; 412 413 set_float_rounding_mode(float_round_nearest_even, 414 &env->active_fpu.fp_status); 415 dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status); 416 restore_rounding_mode(env); 417 if (get_float_exception_flags(&env->active_fpu.fp_status) 418 & (float_flag_invalid | float_flag_overflow)) { 419 dt2 = FP_TO_INT64_OVERFLOW; 420 } 421 update_fcr31(env, GETPC()); 422 return dt2; 423 } 424 425 uint64_t helper_float_round_l_s(CPUMIPSState *env, uint32_t fst0) 426 { 427 uint64_t dt2; 428 429 set_float_rounding_mode(float_round_nearest_even, 430 &env->active_fpu.fp_status); 431 dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status); 432 restore_rounding_mode(env); 433 if (get_float_exception_flags(&env->active_fpu.fp_status) 434 & (float_flag_invalid | float_flag_overflow)) { 435 dt2 = FP_TO_INT64_OVERFLOW; 436 } 437 update_fcr31(env, GETPC()); 438 return dt2; 439 } 440 441 uint32_t helper_float_round_w_d(CPUMIPSState *env, uint64_t fdt0) 442 { 443 uint32_t wt2; 444 445 set_float_rounding_mode(float_round_nearest_even, 446 &env->active_fpu.fp_status); 447 wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status); 448 restore_rounding_mode(env); 449 if (get_float_exception_flags(&env->active_fpu.fp_status) 450 & (float_flag_invalid | float_flag_overflow)) { 451 wt2 = FP_TO_INT32_OVERFLOW; 452 } 453 update_fcr31(env, GETPC()); 454 return wt2; 455 } 456 457 uint32_t helper_float_round_w_s(CPUMIPSState *env, uint32_t fst0) 458 { 459 uint32_t wt2; 460 461 set_float_rounding_mode(float_round_nearest_even, 462 &env->active_fpu.fp_status); 463 wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status); 464 restore_rounding_mode(env); 465 if (get_float_exception_flags(&env->active_fpu.fp_status) 466 & (float_flag_invalid | float_flag_overflow)) { 467 wt2 = FP_TO_INT32_OVERFLOW; 468 } 469 update_fcr31(env, GETPC()); 470 return wt2; 471 } 472 473 uint64_t helper_float_trunc_l_d(CPUMIPSState *env, uint64_t fdt0) 474 { 475 uint64_t dt2; 476 477 dt2 = float64_to_int64_round_to_zero(fdt0, 478 &env->active_fpu.fp_status); 479 if (get_float_exception_flags(&env->active_fpu.fp_status) 480 & (float_flag_invalid | float_flag_overflow)) { 481 dt2 = FP_TO_INT64_OVERFLOW; 482 } 483 update_fcr31(env, GETPC()); 484 return dt2; 485 } 486 487 uint64_t helper_float_trunc_l_s(CPUMIPSState *env, uint32_t fst0) 488 { 489 uint64_t dt2; 490 491 dt2 = float32_to_int64_round_to_zero(fst0, &env->active_fpu.fp_status); 492 if (get_float_exception_flags(&env->active_fpu.fp_status) 493 & (float_flag_invalid | float_flag_overflow)) { 494 dt2 = FP_TO_INT64_OVERFLOW; 495 } 496 update_fcr31(env, GETPC()); 497 return dt2; 498 } 499 500 uint32_t helper_float_trunc_w_d(CPUMIPSState *env, uint64_t fdt0) 501 { 502 uint32_t wt2; 503 504 wt2 = float64_to_int32_round_to_zero(fdt0, &env->active_fpu.fp_status); 505 if (get_float_exception_flags(&env->active_fpu.fp_status) 506 & (float_flag_invalid | float_flag_overflow)) { 507 wt2 = FP_TO_INT32_OVERFLOW; 508 } 509 update_fcr31(env, GETPC()); 510 return wt2; 511 } 512 513 uint32_t helper_float_trunc_w_s(CPUMIPSState *env, uint32_t fst0) 514 { 515 uint32_t wt2; 516 517 wt2 = float32_to_int32_round_to_zero(fst0, &env->active_fpu.fp_status); 518 if (get_float_exception_flags(&env->active_fpu.fp_status) 519 & (float_flag_invalid | float_flag_overflow)) { 520 wt2 = FP_TO_INT32_OVERFLOW; 521 } 522 update_fcr31(env, GETPC()); 523 return wt2; 524 } 525 526 uint64_t helper_float_ceil_l_d(CPUMIPSState *env, uint64_t fdt0) 527 { 528 uint64_t dt2; 529 530 set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status); 531 dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status); 532 restore_rounding_mode(env); 533 if (get_float_exception_flags(&env->active_fpu.fp_status) 534 & (float_flag_invalid | float_flag_overflow)) { 535 dt2 = FP_TO_INT64_OVERFLOW; 536 } 537 update_fcr31(env, GETPC()); 538 return dt2; 539 } 540 541 uint64_t helper_float_ceil_l_s(CPUMIPSState *env, uint32_t fst0) 542 { 543 uint64_t dt2; 544 545 set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status); 546 dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status); 547 restore_rounding_mode(env); 548 if (get_float_exception_flags(&env->active_fpu.fp_status) 549 & (float_flag_invalid | float_flag_overflow)) { 550 dt2 = FP_TO_INT64_OVERFLOW; 551 } 552 update_fcr31(env, GETPC()); 553 return dt2; 554 } 555 556 uint32_t helper_float_ceil_w_d(CPUMIPSState *env, uint64_t fdt0) 557 { 558 uint32_t wt2; 559 560 set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status); 561 wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status); 562 restore_rounding_mode(env); 563 if (get_float_exception_flags(&env->active_fpu.fp_status) 564 & (float_flag_invalid | float_flag_overflow)) { 565 wt2 = FP_TO_INT32_OVERFLOW; 566 } 567 update_fcr31(env, GETPC()); 568 return wt2; 569 } 570 571 uint32_t helper_float_ceil_w_s(CPUMIPSState *env, uint32_t fst0) 572 { 573 uint32_t wt2; 574 575 set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status); 576 wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status); 577 restore_rounding_mode(env); 578 if (get_float_exception_flags(&env->active_fpu.fp_status) 579 & (float_flag_invalid | float_flag_overflow)) { 580 wt2 = FP_TO_INT32_OVERFLOW; 581 } 582 update_fcr31(env, GETPC()); 583 return wt2; 584 } 585 586 uint64_t helper_float_floor_l_d(CPUMIPSState *env, uint64_t fdt0) 587 { 588 uint64_t dt2; 589 590 set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status); 591 dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status); 592 restore_rounding_mode(env); 593 if (get_float_exception_flags(&env->active_fpu.fp_status) 594 & (float_flag_invalid | float_flag_overflow)) { 595 dt2 = FP_TO_INT64_OVERFLOW; 596 } 597 update_fcr31(env, GETPC()); 598 return dt2; 599 } 600 601 uint64_t helper_float_floor_l_s(CPUMIPSState *env, uint32_t fst0) 602 { 603 uint64_t dt2; 604 605 set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status); 606 dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status); 607 restore_rounding_mode(env); 608 if (get_float_exception_flags(&env->active_fpu.fp_status) 609 & (float_flag_invalid | float_flag_overflow)) { 610 dt2 = FP_TO_INT64_OVERFLOW; 611 } 612 update_fcr31(env, GETPC()); 613 return dt2; 614 } 615 616 uint32_t helper_float_floor_w_d(CPUMIPSState *env, uint64_t fdt0) 617 { 618 uint32_t wt2; 619 620 set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status); 621 wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status); 622 restore_rounding_mode(env); 623 if (get_float_exception_flags(&env->active_fpu.fp_status) 624 & (float_flag_invalid | float_flag_overflow)) { 625 wt2 = FP_TO_INT32_OVERFLOW; 626 } 627 update_fcr31(env, GETPC()); 628 return wt2; 629 } 630 631 uint32_t helper_float_floor_w_s(CPUMIPSState *env, uint32_t fst0) 632 { 633 uint32_t wt2; 634 635 set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status); 636 wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status); 637 restore_rounding_mode(env); 638 if (get_float_exception_flags(&env->active_fpu.fp_status) 639 & (float_flag_invalid | float_flag_overflow)) { 640 wt2 = FP_TO_INT32_OVERFLOW; 641 } 642 update_fcr31(env, GETPC()); 643 return wt2; 644 } 645 646 uint64_t helper_float_cvt_2008_l_d(CPUMIPSState *env, uint64_t fdt0) 647 { 648 uint64_t dt2; 649 650 dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status); 651 if (get_float_exception_flags(&env->active_fpu.fp_status) 652 & float_flag_invalid) { 653 if (float64_is_any_nan(fdt0)) { 654 dt2 = 0; 655 } 656 } 657 update_fcr31(env, GETPC()); 658 return dt2; 659 } 660 661 uint64_t helper_float_cvt_2008_l_s(CPUMIPSState *env, uint32_t fst0) 662 { 663 uint64_t dt2; 664 665 dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status); 666 if (get_float_exception_flags(&env->active_fpu.fp_status) 667 & float_flag_invalid) { 668 if (float32_is_any_nan(fst0)) { 669 dt2 = 0; 670 } 671 } 672 update_fcr31(env, GETPC()); 673 return dt2; 674 } 675 676 uint32_t helper_float_cvt_2008_w_d(CPUMIPSState *env, uint64_t fdt0) 677 { 678 uint32_t wt2; 679 680 wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status); 681 if (get_float_exception_flags(&env->active_fpu.fp_status) 682 & float_flag_invalid) { 683 if (float64_is_any_nan(fdt0)) { 684 wt2 = 0; 685 } 686 } 687 update_fcr31(env, GETPC()); 688 return wt2; 689 } 690 691 uint32_t helper_float_cvt_2008_w_s(CPUMIPSState *env, uint32_t fst0) 692 { 693 uint32_t wt2; 694 695 wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status); 696 if (get_float_exception_flags(&env->active_fpu.fp_status) 697 & float_flag_invalid) { 698 if (float32_is_any_nan(fst0)) { 699 wt2 = 0; 700 } 701 } 702 update_fcr31(env, GETPC()); 703 return wt2; 704 } 705 706 uint64_t helper_float_round_2008_l_d(CPUMIPSState *env, uint64_t fdt0) 707 { 708 uint64_t dt2; 709 710 set_float_rounding_mode(float_round_nearest_even, 711 &env->active_fpu.fp_status); 712 dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status); 713 restore_rounding_mode(env); 714 if (get_float_exception_flags(&env->active_fpu.fp_status) 715 & float_flag_invalid) { 716 if (float64_is_any_nan(fdt0)) { 717 dt2 = 0; 718 } 719 } 720 update_fcr31(env, GETPC()); 721 return dt2; 722 } 723 724 uint64_t helper_float_round_2008_l_s(CPUMIPSState *env, uint32_t fst0) 725 { 726 uint64_t dt2; 727 728 set_float_rounding_mode(float_round_nearest_even, 729 &env->active_fpu.fp_status); 730 dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status); 731 restore_rounding_mode(env); 732 if (get_float_exception_flags(&env->active_fpu.fp_status) 733 & float_flag_invalid) { 734 if (float32_is_any_nan(fst0)) { 735 dt2 = 0; 736 } 737 } 738 update_fcr31(env, GETPC()); 739 return dt2; 740 } 741 742 uint32_t helper_float_round_2008_w_d(CPUMIPSState *env, uint64_t fdt0) 743 { 744 uint32_t wt2; 745 746 set_float_rounding_mode(float_round_nearest_even, 747 &env->active_fpu.fp_status); 748 wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status); 749 restore_rounding_mode(env); 750 if (get_float_exception_flags(&env->active_fpu.fp_status) 751 & float_flag_invalid) { 752 if (float64_is_any_nan(fdt0)) { 753 wt2 = 0; 754 } 755 } 756 update_fcr31(env, GETPC()); 757 return wt2; 758 } 759 760 uint32_t helper_float_round_2008_w_s(CPUMIPSState *env, uint32_t fst0) 761 { 762 uint32_t wt2; 763 764 set_float_rounding_mode(float_round_nearest_even, 765 &env->active_fpu.fp_status); 766 wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status); 767 restore_rounding_mode(env); 768 if (get_float_exception_flags(&env->active_fpu.fp_status) 769 & float_flag_invalid) { 770 if (float32_is_any_nan(fst0)) { 771 wt2 = 0; 772 } 773 } 774 update_fcr31(env, GETPC()); 775 return wt2; 776 } 777 778 uint64_t helper_float_trunc_2008_l_d(CPUMIPSState *env, uint64_t fdt0) 779 { 780 uint64_t dt2; 781 782 dt2 = float64_to_int64_round_to_zero(fdt0, &env->active_fpu.fp_status); 783 if (get_float_exception_flags(&env->active_fpu.fp_status) 784 & float_flag_invalid) { 785 if (float64_is_any_nan(fdt0)) { 786 dt2 = 0; 787 } 788 } 789 update_fcr31(env, GETPC()); 790 return dt2; 791 } 792 793 uint64_t helper_float_trunc_2008_l_s(CPUMIPSState *env, uint32_t fst0) 794 { 795 uint64_t dt2; 796 797 dt2 = float32_to_int64_round_to_zero(fst0, &env->active_fpu.fp_status); 798 if (get_float_exception_flags(&env->active_fpu.fp_status) 799 & float_flag_invalid) { 800 if (float32_is_any_nan(fst0)) { 801 dt2 = 0; 802 } 803 } 804 update_fcr31(env, GETPC()); 805 return dt2; 806 } 807 808 uint32_t helper_float_trunc_2008_w_d(CPUMIPSState *env, uint64_t fdt0) 809 { 810 uint32_t wt2; 811 812 wt2 = float64_to_int32_round_to_zero(fdt0, &env->active_fpu.fp_status); 813 if (get_float_exception_flags(&env->active_fpu.fp_status) 814 & float_flag_invalid) { 815 if (float64_is_any_nan(fdt0)) { 816 wt2 = 0; 817 } 818 } 819 update_fcr31(env, GETPC()); 820 return wt2; 821 } 822 823 uint32_t helper_float_trunc_2008_w_s(CPUMIPSState *env, uint32_t fst0) 824 { 825 uint32_t wt2; 826 827 wt2 = float32_to_int32_round_to_zero(fst0, &env->active_fpu.fp_status); 828 if (get_float_exception_flags(&env->active_fpu.fp_status) 829 & float_flag_invalid) { 830 if (float32_is_any_nan(fst0)) { 831 wt2 = 0; 832 } 833 } 834 update_fcr31(env, GETPC()); 835 return wt2; 836 } 837 838 uint64_t helper_float_ceil_2008_l_d(CPUMIPSState *env, uint64_t fdt0) 839 { 840 uint64_t dt2; 841 842 set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status); 843 dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status); 844 restore_rounding_mode(env); 845 if (get_float_exception_flags(&env->active_fpu.fp_status) 846 & float_flag_invalid) { 847 if (float64_is_any_nan(fdt0)) { 848 dt2 = 0; 849 } 850 } 851 update_fcr31(env, GETPC()); 852 return dt2; 853 } 854 855 uint64_t helper_float_ceil_2008_l_s(CPUMIPSState *env, uint32_t fst0) 856 { 857 uint64_t dt2; 858 859 set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status); 860 dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status); 861 restore_rounding_mode(env); 862 if (get_float_exception_flags(&env->active_fpu.fp_status) 863 & float_flag_invalid) { 864 if (float32_is_any_nan(fst0)) { 865 dt2 = 0; 866 } 867 } 868 update_fcr31(env, GETPC()); 869 return dt2; 870 } 871 872 uint32_t helper_float_ceil_2008_w_d(CPUMIPSState *env, uint64_t fdt0) 873 { 874 uint32_t wt2; 875 876 set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status); 877 wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status); 878 restore_rounding_mode(env); 879 if (get_float_exception_flags(&env->active_fpu.fp_status) 880 & float_flag_invalid) { 881 if (float64_is_any_nan(fdt0)) { 882 wt2 = 0; 883 } 884 } 885 update_fcr31(env, GETPC()); 886 return wt2; 887 } 888 889 uint32_t helper_float_ceil_2008_w_s(CPUMIPSState *env, uint32_t fst0) 890 { 891 uint32_t wt2; 892 893 set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status); 894 wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status); 895 restore_rounding_mode(env); 896 if (get_float_exception_flags(&env->active_fpu.fp_status) 897 & float_flag_invalid) { 898 if (float32_is_any_nan(fst0)) { 899 wt2 = 0; 900 } 901 } 902 update_fcr31(env, GETPC()); 903 return wt2; 904 } 905 906 uint64_t helper_float_floor_2008_l_d(CPUMIPSState *env, uint64_t fdt0) 907 { 908 uint64_t dt2; 909 910 set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status); 911 dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status); 912 restore_rounding_mode(env); 913 if (get_float_exception_flags(&env->active_fpu.fp_status) 914 & float_flag_invalid) { 915 if (float64_is_any_nan(fdt0)) { 916 dt2 = 0; 917 } 918 } 919 update_fcr31(env, GETPC()); 920 return dt2; 921 } 922 923 uint64_t helper_float_floor_2008_l_s(CPUMIPSState *env, uint32_t fst0) 924 { 925 uint64_t dt2; 926 927 set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status); 928 dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status); 929 restore_rounding_mode(env); 930 if (get_float_exception_flags(&env->active_fpu.fp_status) 931 & float_flag_invalid) { 932 if (float32_is_any_nan(fst0)) { 933 dt2 = 0; 934 } 935 } 936 update_fcr31(env, GETPC()); 937 return dt2; 938 } 939 940 uint32_t helper_float_floor_2008_w_d(CPUMIPSState *env, uint64_t fdt0) 941 { 942 uint32_t wt2; 943 944 set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status); 945 wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status); 946 restore_rounding_mode(env); 947 if (get_float_exception_flags(&env->active_fpu.fp_status) 948 & float_flag_invalid) { 949 if (float64_is_any_nan(fdt0)) { 950 wt2 = 0; 951 } 952 } 953 update_fcr31(env, GETPC()); 954 return wt2; 955 } 956 957 uint32_t helper_float_floor_2008_w_s(CPUMIPSState *env, uint32_t fst0) 958 { 959 uint32_t wt2; 960 961 set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status); 962 wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status); 963 restore_rounding_mode(env); 964 if (get_float_exception_flags(&env->active_fpu.fp_status) 965 & float_flag_invalid) { 966 if (float32_is_any_nan(fst0)) { 967 wt2 = 0; 968 } 969 } 970 update_fcr31(env, GETPC()); 971 return wt2; 972 } 973 974 /* unary operations, not modifying fp status */ 975 976 uint64_t helper_float_abs_d(uint64_t fdt0) 977 { 978 return float64_abs(fdt0); 979 } 980 981 uint32_t helper_float_abs_s(uint32_t fst0) 982 { 983 return float32_abs(fst0); 984 } 985 986 uint64_t helper_float_abs_ps(uint64_t fdt0) 987 { 988 uint32_t wt0; 989 uint32_t wth0; 990 991 wt0 = float32_abs(fdt0 & 0XFFFFFFFF); 992 wth0 = float32_abs(fdt0 >> 32); 993 return ((uint64_t)wth0 << 32) | wt0; 994 } 995 996 uint64_t helper_float_chs_d(uint64_t fdt0) 997 { 998 return float64_chs(fdt0); 999 } 1000 1001 uint32_t helper_float_chs_s(uint32_t fst0) 1002 { 1003 return float32_chs(fst0); 1004 } 1005 1006 uint64_t helper_float_chs_ps(uint64_t fdt0) 1007 { 1008 uint32_t wt0; 1009 uint32_t wth0; 1010 1011 wt0 = float32_chs(fdt0 & 0XFFFFFFFF); 1012 wth0 = float32_chs(fdt0 >> 32); 1013 return ((uint64_t)wth0 << 32) | wt0; 1014 } 1015 1016 /* MIPS specific unary operations */ 1017 uint64_t helper_float_recip_d(CPUMIPSState *env, uint64_t fdt0) 1018 { 1019 uint64_t fdt2; 1020 1021 fdt2 = float64_div(float64_one, fdt0, &env->active_fpu.fp_status); 1022 update_fcr31(env, GETPC()); 1023 return fdt2; 1024 } 1025 1026 uint32_t helper_float_recip_s(CPUMIPSState *env, uint32_t fst0) 1027 { 1028 uint32_t fst2; 1029 1030 fst2 = float32_div(float32_one, fst0, &env->active_fpu.fp_status); 1031 update_fcr31(env, GETPC()); 1032 return fst2; 1033 } 1034 1035 uint64_t helper_float_rsqrt_d(CPUMIPSState *env, uint64_t fdt0) 1036 { 1037 uint64_t fdt2; 1038 1039 fdt2 = float64_sqrt(fdt0, &env->active_fpu.fp_status); 1040 fdt2 = float64_div(float64_one, fdt2, &env->active_fpu.fp_status); 1041 update_fcr31(env, GETPC()); 1042 return fdt2; 1043 } 1044 1045 uint32_t helper_float_rsqrt_s(CPUMIPSState *env, uint32_t fst0) 1046 { 1047 uint32_t fst2; 1048 1049 fst2 = float32_sqrt(fst0, &env->active_fpu.fp_status); 1050 fst2 = float32_div(float32_one, fst2, &env->active_fpu.fp_status); 1051 update_fcr31(env, GETPC()); 1052 return fst2; 1053 } 1054 1055 uint64_t helper_float_recip1_d(CPUMIPSState *env, uint64_t fdt0) 1056 { 1057 uint64_t fdt2; 1058 1059 fdt2 = float64_div(float64_one, fdt0, &env->active_fpu.fp_status); 1060 update_fcr31(env, GETPC()); 1061 return fdt2; 1062 } 1063 1064 uint32_t helper_float_recip1_s(CPUMIPSState *env, uint32_t fst0) 1065 { 1066 uint32_t fst2; 1067 1068 fst2 = float32_div(float32_one, fst0, &env->active_fpu.fp_status); 1069 update_fcr31(env, GETPC()); 1070 return fst2; 1071 } 1072 1073 uint64_t helper_float_recip1_ps(CPUMIPSState *env, uint64_t fdt0) 1074 { 1075 uint32_t fstl2; 1076 uint32_t fsth2; 1077 1078 fstl2 = float32_div(float32_one, fdt0 & 0XFFFFFFFF, 1079 &env->active_fpu.fp_status); 1080 fsth2 = float32_div(float32_one, fdt0 >> 32, &env->active_fpu.fp_status); 1081 update_fcr31(env, GETPC()); 1082 return ((uint64_t)fsth2 << 32) | fstl2; 1083 } 1084 1085 uint64_t helper_float_rsqrt1_d(CPUMIPSState *env, uint64_t fdt0) 1086 { 1087 uint64_t fdt2; 1088 1089 fdt2 = float64_sqrt(fdt0, &env->active_fpu.fp_status); 1090 fdt2 = float64_div(float64_one, fdt2, &env->active_fpu.fp_status); 1091 update_fcr31(env, GETPC()); 1092 return fdt2; 1093 } 1094 1095 uint32_t helper_float_rsqrt1_s(CPUMIPSState *env, uint32_t fst0) 1096 { 1097 uint32_t fst2; 1098 1099 fst2 = float32_sqrt(fst0, &env->active_fpu.fp_status); 1100 fst2 = float32_div(float32_one, fst2, &env->active_fpu.fp_status); 1101 update_fcr31(env, GETPC()); 1102 return fst2; 1103 } 1104 1105 uint64_t helper_float_rsqrt1_ps(CPUMIPSState *env, uint64_t fdt0) 1106 { 1107 uint32_t fstl2; 1108 uint32_t fsth2; 1109 1110 fstl2 = float32_sqrt(fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status); 1111 fsth2 = float32_sqrt(fdt0 >> 32, &env->active_fpu.fp_status); 1112 fstl2 = float32_div(float32_one, fstl2, &env->active_fpu.fp_status); 1113 fsth2 = float32_div(float32_one, fsth2, &env->active_fpu.fp_status); 1114 update_fcr31(env, GETPC()); 1115 return ((uint64_t)fsth2 << 32) | fstl2; 1116 } 1117 1118 uint64_t helper_float_rint_d(CPUMIPSState *env, uint64_t fs) 1119 { 1120 uint64_t fdret; 1121 1122 fdret = float64_round_to_int(fs, &env->active_fpu.fp_status); 1123 update_fcr31(env, GETPC()); 1124 return fdret; 1125 } 1126 1127 uint32_t helper_float_rint_s(CPUMIPSState *env, uint32_t fs) 1128 { 1129 uint32_t fdret; 1130 1131 fdret = float32_round_to_int(fs, &env->active_fpu.fp_status); 1132 update_fcr31(env, GETPC()); 1133 return fdret; 1134 } 1135 1136 #define FLOAT_CLASS_SIGNALING_NAN 0x001 1137 #define FLOAT_CLASS_QUIET_NAN 0x002 1138 #define FLOAT_CLASS_NEGATIVE_INFINITY 0x004 1139 #define FLOAT_CLASS_NEGATIVE_NORMAL 0x008 1140 #define FLOAT_CLASS_NEGATIVE_SUBNORMAL 0x010 1141 #define FLOAT_CLASS_NEGATIVE_ZERO 0x020 1142 #define FLOAT_CLASS_POSITIVE_INFINITY 0x040 1143 #define FLOAT_CLASS_POSITIVE_NORMAL 0x080 1144 #define FLOAT_CLASS_POSITIVE_SUBNORMAL 0x100 1145 #define FLOAT_CLASS_POSITIVE_ZERO 0x200 1146 1147 uint64_t float_class_d(uint64_t arg, float_status *status) 1148 { 1149 if (float64_is_signaling_nan(arg, status)) { 1150 return FLOAT_CLASS_SIGNALING_NAN; 1151 } else if (float64_is_quiet_nan(arg, status)) { 1152 return FLOAT_CLASS_QUIET_NAN; 1153 } else if (float64_is_neg(arg)) { 1154 if (float64_is_infinity(arg)) { 1155 return FLOAT_CLASS_NEGATIVE_INFINITY; 1156 } else if (float64_is_zero(arg)) { 1157 return FLOAT_CLASS_NEGATIVE_ZERO; 1158 } else if (float64_is_zero_or_denormal(arg)) { 1159 return FLOAT_CLASS_NEGATIVE_SUBNORMAL; 1160 } else { 1161 return FLOAT_CLASS_NEGATIVE_NORMAL; 1162 } 1163 } else { 1164 if (float64_is_infinity(arg)) { 1165 return FLOAT_CLASS_POSITIVE_INFINITY; 1166 } else if (float64_is_zero(arg)) { 1167 return FLOAT_CLASS_POSITIVE_ZERO; 1168 } else if (float64_is_zero_or_denormal(arg)) { 1169 return FLOAT_CLASS_POSITIVE_SUBNORMAL; 1170 } else { 1171 return FLOAT_CLASS_POSITIVE_NORMAL; 1172 } 1173 } 1174 } 1175 1176 uint64_t helper_float_class_d(CPUMIPSState *env, uint64_t arg) 1177 { 1178 return float_class_d(arg, &env->active_fpu.fp_status); 1179 } 1180 1181 uint32_t float_class_s(uint32_t arg, float_status *status) 1182 { 1183 if (float32_is_signaling_nan(arg, status)) { 1184 return FLOAT_CLASS_SIGNALING_NAN; 1185 } else if (float32_is_quiet_nan(arg, status)) { 1186 return FLOAT_CLASS_QUIET_NAN; 1187 } else if (float32_is_neg(arg)) { 1188 if (float32_is_infinity(arg)) { 1189 return FLOAT_CLASS_NEGATIVE_INFINITY; 1190 } else if (float32_is_zero(arg)) { 1191 return FLOAT_CLASS_NEGATIVE_ZERO; 1192 } else if (float32_is_zero_or_denormal(arg)) { 1193 return FLOAT_CLASS_NEGATIVE_SUBNORMAL; 1194 } else { 1195 return FLOAT_CLASS_NEGATIVE_NORMAL; 1196 } 1197 } else { 1198 if (float32_is_infinity(arg)) { 1199 return FLOAT_CLASS_POSITIVE_INFINITY; 1200 } else if (float32_is_zero(arg)) { 1201 return FLOAT_CLASS_POSITIVE_ZERO; 1202 } else if (float32_is_zero_or_denormal(arg)) { 1203 return FLOAT_CLASS_POSITIVE_SUBNORMAL; 1204 } else { 1205 return FLOAT_CLASS_POSITIVE_NORMAL; 1206 } 1207 } 1208 } 1209 1210 uint32_t helper_float_class_s(CPUMIPSState *env, uint32_t arg) 1211 { 1212 return float_class_s(arg, &env->active_fpu.fp_status); 1213 } 1214 1215 /* binary operations */ 1216 1217 uint64_t helper_float_add_d(CPUMIPSState *env, 1218 uint64_t fdt0, uint64_t fdt1) 1219 { 1220 uint64_t dt2; 1221 1222 dt2 = float64_add(fdt0, fdt1, &env->active_fpu.fp_status); 1223 update_fcr31(env, GETPC()); 1224 return dt2; 1225 } 1226 1227 uint32_t helper_float_add_s(CPUMIPSState *env, 1228 uint32_t fst0, uint32_t fst1) 1229 { 1230 uint32_t wt2; 1231 1232 wt2 = float32_add(fst0, fst1, &env->active_fpu.fp_status); 1233 update_fcr31(env, GETPC()); 1234 return wt2; 1235 } 1236 1237 uint64_t helper_float_add_ps(CPUMIPSState *env, 1238 uint64_t fdt0, uint64_t fdt1) 1239 { 1240 uint32_t fstl0 = fdt0 & 0XFFFFFFFF; 1241 uint32_t fsth0 = fdt0 >> 32; 1242 uint32_t fstl1 = fdt1 & 0XFFFFFFFF; 1243 uint32_t fsth1 = fdt1 >> 32; 1244 uint32_t wtl2; 1245 uint32_t wth2; 1246 1247 wtl2 = float32_add(fstl0, fstl1, &env->active_fpu.fp_status); 1248 wth2 = float32_add(fsth0, fsth1, &env->active_fpu.fp_status); 1249 update_fcr31(env, GETPC()); 1250 return ((uint64_t)wth2 << 32) | wtl2; 1251 } 1252 1253 uint64_t helper_float_sub_d(CPUMIPSState *env, 1254 uint64_t fdt0, uint64_t fdt1) 1255 { 1256 uint64_t dt2; 1257 1258 dt2 = float64_sub(fdt0, fdt1, &env->active_fpu.fp_status); 1259 update_fcr31(env, GETPC()); 1260 return dt2; 1261 } 1262 1263 uint32_t helper_float_sub_s(CPUMIPSState *env, 1264 uint32_t fst0, uint32_t fst1) 1265 { 1266 uint32_t wt2; 1267 1268 wt2 = float32_sub(fst0, fst1, &env->active_fpu.fp_status); 1269 update_fcr31(env, GETPC()); 1270 return wt2; 1271 } 1272 1273 uint64_t helper_float_sub_ps(CPUMIPSState *env, 1274 uint64_t fdt0, uint64_t fdt1) 1275 { 1276 uint32_t fstl0 = fdt0 & 0XFFFFFFFF; 1277 uint32_t fsth0 = fdt0 >> 32; 1278 uint32_t fstl1 = fdt1 & 0XFFFFFFFF; 1279 uint32_t fsth1 = fdt1 >> 32; 1280 uint32_t wtl2; 1281 uint32_t wth2; 1282 1283 wtl2 = float32_sub(fstl0, fstl1, &env->active_fpu.fp_status); 1284 wth2 = float32_sub(fsth0, fsth1, &env->active_fpu.fp_status); 1285 update_fcr31(env, GETPC()); 1286 return ((uint64_t)wth2 << 32) | wtl2; 1287 } 1288 1289 uint64_t helper_float_mul_d(CPUMIPSState *env, 1290 uint64_t fdt0, uint64_t fdt1) 1291 { 1292 uint64_t dt2; 1293 1294 dt2 = float64_mul(fdt0, fdt1, &env->active_fpu.fp_status); 1295 update_fcr31(env, GETPC()); 1296 return dt2; 1297 } 1298 1299 uint32_t helper_float_mul_s(CPUMIPSState *env, 1300 uint32_t fst0, uint32_t fst1) 1301 { 1302 uint32_t wt2; 1303 1304 wt2 = float32_mul(fst0, fst1, &env->active_fpu.fp_status); 1305 update_fcr31(env, GETPC()); 1306 return wt2; 1307 } 1308 1309 uint64_t helper_float_mul_ps(CPUMIPSState *env, 1310 uint64_t fdt0, uint64_t fdt1) 1311 { 1312 uint32_t fstl0 = fdt0 & 0XFFFFFFFF; 1313 uint32_t fsth0 = fdt0 >> 32; 1314 uint32_t fstl1 = fdt1 & 0XFFFFFFFF; 1315 uint32_t fsth1 = fdt1 >> 32; 1316 uint32_t wtl2; 1317 uint32_t wth2; 1318 1319 wtl2 = float32_mul(fstl0, fstl1, &env->active_fpu.fp_status); 1320 wth2 = float32_mul(fsth0, fsth1, &env->active_fpu.fp_status); 1321 update_fcr31(env, GETPC()); 1322 return ((uint64_t)wth2 << 32) | wtl2; 1323 } 1324 1325 uint64_t helper_float_div_d(CPUMIPSState *env, 1326 uint64_t fdt0, uint64_t fdt1) 1327 { 1328 uint64_t dt2; 1329 1330 dt2 = float64_div(fdt0, fdt1, &env->active_fpu.fp_status); 1331 update_fcr31(env, GETPC()); 1332 return dt2; 1333 } 1334 1335 uint32_t helper_float_div_s(CPUMIPSState *env, 1336 uint32_t fst0, uint32_t fst1) 1337 { 1338 uint32_t wt2; 1339 1340 wt2 = float32_div(fst0, fst1, &env->active_fpu.fp_status); 1341 update_fcr31(env, GETPC()); 1342 return wt2; 1343 } 1344 1345 uint64_t helper_float_div_ps(CPUMIPSState *env, 1346 uint64_t fdt0, uint64_t fdt1) 1347 { 1348 uint32_t fstl0 = fdt0 & 0XFFFFFFFF; 1349 uint32_t fsth0 = fdt0 >> 32; 1350 uint32_t fstl1 = fdt1 & 0XFFFFFFFF; 1351 uint32_t fsth1 = fdt1 >> 32; 1352 uint32_t wtl2; 1353 uint32_t wth2; 1354 1355 wtl2 = float32_div(fstl0, fstl1, &env->active_fpu.fp_status); 1356 wth2 = float32_div(fsth0, fsth1, &env->active_fpu.fp_status); 1357 update_fcr31(env, GETPC()); 1358 return ((uint64_t)wth2 << 32) | wtl2; 1359 } 1360 1361 1362 /* MIPS specific binary operations */ 1363 uint64_t helper_float_recip2_d(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2) 1364 { 1365 fdt2 = float64_mul(fdt0, fdt2, &env->active_fpu.fp_status); 1366 fdt2 = float64_chs(float64_sub(fdt2, float64_one, 1367 &env->active_fpu.fp_status)); 1368 update_fcr31(env, GETPC()); 1369 return fdt2; 1370 } 1371 1372 uint32_t helper_float_recip2_s(CPUMIPSState *env, uint32_t fst0, uint32_t fst2) 1373 { 1374 fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status); 1375 fst2 = float32_chs(float32_sub(fst2, float32_one, 1376 &env->active_fpu.fp_status)); 1377 update_fcr31(env, GETPC()); 1378 return fst2; 1379 } 1380 1381 uint64_t helper_float_recip2_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2) 1382 { 1383 uint32_t fstl0 = fdt0 & 0XFFFFFFFF; 1384 uint32_t fsth0 = fdt0 >> 32; 1385 uint32_t fstl2 = fdt2 & 0XFFFFFFFF; 1386 uint32_t fsth2 = fdt2 >> 32; 1387 1388 fstl2 = float32_mul(fstl0, fstl2, &env->active_fpu.fp_status); 1389 fsth2 = float32_mul(fsth0, fsth2, &env->active_fpu.fp_status); 1390 fstl2 = float32_chs(float32_sub(fstl2, float32_one, 1391 &env->active_fpu.fp_status)); 1392 fsth2 = float32_chs(float32_sub(fsth2, float32_one, 1393 &env->active_fpu.fp_status)); 1394 update_fcr31(env, GETPC()); 1395 return ((uint64_t)fsth2 << 32) | fstl2; 1396 } 1397 1398 uint64_t helper_float_rsqrt2_d(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2) 1399 { 1400 fdt2 = float64_mul(fdt0, fdt2, &env->active_fpu.fp_status); 1401 fdt2 = float64_sub(fdt2, float64_one, &env->active_fpu.fp_status); 1402 fdt2 = float64_chs(float64_div(fdt2, FLOAT_TWO64, 1403 &env->active_fpu.fp_status)); 1404 update_fcr31(env, GETPC()); 1405 return fdt2; 1406 } 1407 1408 uint32_t helper_float_rsqrt2_s(CPUMIPSState *env, uint32_t fst0, uint32_t fst2) 1409 { 1410 fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status); 1411 fst2 = float32_sub(fst2, float32_one, &env->active_fpu.fp_status); 1412 fst2 = float32_chs(float32_div(fst2, FLOAT_TWO32, 1413 &env->active_fpu.fp_status)); 1414 update_fcr31(env, GETPC()); 1415 return fst2; 1416 } 1417 1418 uint64_t helper_float_rsqrt2_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2) 1419 { 1420 uint32_t fstl0 = fdt0 & 0XFFFFFFFF; 1421 uint32_t fsth0 = fdt0 >> 32; 1422 uint32_t fstl2 = fdt2 & 0XFFFFFFFF; 1423 uint32_t fsth2 = fdt2 >> 32; 1424 1425 fstl2 = float32_mul(fstl0, fstl2, &env->active_fpu.fp_status); 1426 fsth2 = float32_mul(fsth0, fsth2, &env->active_fpu.fp_status); 1427 fstl2 = float32_sub(fstl2, float32_one, &env->active_fpu.fp_status); 1428 fsth2 = float32_sub(fsth2, float32_one, &env->active_fpu.fp_status); 1429 fstl2 = float32_chs(float32_div(fstl2, FLOAT_TWO32, 1430 &env->active_fpu.fp_status)); 1431 fsth2 = float32_chs(float32_div(fsth2, FLOAT_TWO32, 1432 &env->active_fpu.fp_status)); 1433 update_fcr31(env, GETPC()); 1434 return ((uint64_t)fsth2 << 32) | fstl2; 1435 } 1436 1437 uint64_t helper_float_addr_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt1) 1438 { 1439 uint32_t fstl0 = fdt0 & 0XFFFFFFFF; 1440 uint32_t fsth0 = fdt0 >> 32; 1441 uint32_t fstl1 = fdt1 & 0XFFFFFFFF; 1442 uint32_t fsth1 = fdt1 >> 32; 1443 uint32_t fstl2; 1444 uint32_t fsth2; 1445 1446 fstl2 = float32_add(fstl0, fsth0, &env->active_fpu.fp_status); 1447 fsth2 = float32_add(fstl1, fsth1, &env->active_fpu.fp_status); 1448 update_fcr31(env, GETPC()); 1449 return ((uint64_t)fsth2 << 32) | fstl2; 1450 } 1451 1452 uint64_t helper_float_mulr_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt1) 1453 { 1454 uint32_t fstl0 = fdt0 & 0XFFFFFFFF; 1455 uint32_t fsth0 = fdt0 >> 32; 1456 uint32_t fstl1 = fdt1 & 0XFFFFFFFF; 1457 uint32_t fsth1 = fdt1 >> 32; 1458 uint32_t fstl2; 1459 uint32_t fsth2; 1460 1461 fstl2 = float32_mul(fstl0, fsth0, &env->active_fpu.fp_status); 1462 fsth2 = float32_mul(fstl1, fsth1, &env->active_fpu.fp_status); 1463 update_fcr31(env, GETPC()); 1464 return ((uint64_t)fsth2 << 32) | fstl2; 1465 } 1466 1467 1468 uint32_t helper_float_max_s(CPUMIPSState *env, uint32_t fs, uint32_t ft) 1469 { 1470 uint32_t fdret; 1471 1472 fdret = float32_maxnum(fs, ft, &env->active_fpu.fp_status); 1473 1474 update_fcr31(env, GETPC()); 1475 return fdret; 1476 } 1477 1478 uint64_t helper_float_max_d(CPUMIPSState *env, uint64_t fs, uint64_t ft) 1479 { 1480 uint64_t fdret; 1481 1482 fdret = float64_maxnum(fs, ft, &env->active_fpu.fp_status); 1483 1484 update_fcr31(env, GETPC()); 1485 return fdret; 1486 } 1487 1488 uint32_t helper_float_maxa_s(CPUMIPSState *env, uint32_t fs, uint32_t ft) 1489 { 1490 uint32_t fdret; 1491 1492 fdret = float32_maxnummag(fs, ft, &env->active_fpu.fp_status); 1493 1494 update_fcr31(env, GETPC()); 1495 return fdret; 1496 } 1497 1498 uint64_t helper_float_maxa_d(CPUMIPSState *env, uint64_t fs, uint64_t ft) 1499 { 1500 uint64_t fdret; 1501 1502 fdret = float64_maxnummag(fs, ft, &env->active_fpu.fp_status); 1503 1504 update_fcr31(env, GETPC()); 1505 return fdret; 1506 } 1507 1508 uint32_t helper_float_min_s(CPUMIPSState *env, uint32_t fs, uint32_t ft) 1509 { 1510 uint32_t fdret; 1511 1512 fdret = float32_minnum(fs, ft, &env->active_fpu.fp_status); 1513 1514 update_fcr31(env, GETPC()); 1515 return fdret; 1516 } 1517 1518 uint64_t helper_float_min_d(CPUMIPSState *env, uint64_t fs, uint64_t ft) 1519 { 1520 uint64_t fdret; 1521 1522 fdret = float64_minnum(fs, ft, &env->active_fpu.fp_status); 1523 1524 update_fcr31(env, GETPC()); 1525 return fdret; 1526 } 1527 1528 uint32_t helper_float_mina_s(CPUMIPSState *env, uint32_t fs, uint32_t ft) 1529 { 1530 uint32_t fdret; 1531 1532 fdret = float32_minnummag(fs, ft, &env->active_fpu.fp_status); 1533 1534 update_fcr31(env, GETPC()); 1535 return fdret; 1536 } 1537 1538 uint64_t helper_float_mina_d(CPUMIPSState *env, uint64_t fs, uint64_t ft) 1539 { 1540 uint64_t fdret; 1541 1542 fdret = float64_minnummag(fs, ft, &env->active_fpu.fp_status); 1543 1544 update_fcr31(env, GETPC()); 1545 return fdret; 1546 } 1547 1548 1549 /* ternary operations */ 1550 1551 uint64_t helper_float_madd_d(CPUMIPSState *env, uint64_t fst0, 1552 uint64_t fst1, uint64_t fst2) 1553 { 1554 fst0 = float64_mul(fst0, fst1, &env->active_fpu.fp_status); 1555 fst0 = float64_add(fst0, fst2, &env->active_fpu.fp_status); 1556 1557 update_fcr31(env, GETPC()); 1558 return fst0; 1559 } 1560 1561 uint32_t helper_float_madd_s(CPUMIPSState *env, uint32_t fst0, 1562 uint32_t fst1, uint32_t fst2) 1563 { 1564 fst0 = float32_mul(fst0, fst1, &env->active_fpu.fp_status); 1565 fst0 = float32_add(fst0, fst2, &env->active_fpu.fp_status); 1566 1567 update_fcr31(env, GETPC()); 1568 return fst0; 1569 } 1570 1571 uint64_t helper_float_madd_ps(CPUMIPSState *env, uint64_t fdt0, 1572 uint64_t fdt1, uint64_t fdt2) 1573 { 1574 uint32_t fstl0 = fdt0 & 0XFFFFFFFF; 1575 uint32_t fsth0 = fdt0 >> 32; 1576 uint32_t fstl1 = fdt1 & 0XFFFFFFFF; 1577 uint32_t fsth1 = fdt1 >> 32; 1578 uint32_t fstl2 = fdt2 & 0XFFFFFFFF; 1579 uint32_t fsth2 = fdt2 >> 32; 1580 1581 fstl0 = float32_mul(fstl0, fstl1, &env->active_fpu.fp_status); 1582 fstl0 = float32_add(fstl0, fstl2, &env->active_fpu.fp_status); 1583 fsth0 = float32_mul(fsth0, fsth1, &env->active_fpu.fp_status); 1584 fsth0 = float32_add(fsth0, fsth2, &env->active_fpu.fp_status); 1585 1586 update_fcr31(env, GETPC()); 1587 return ((uint64_t)fsth0 << 32) | fstl0; 1588 } 1589 1590 uint64_t helper_float_msub_d(CPUMIPSState *env, uint64_t fst0, 1591 uint64_t fst1, uint64_t fst2) 1592 { 1593 fst0 = float64_mul(fst0, fst1, &env->active_fpu.fp_status); 1594 fst0 = float64_sub(fst0, fst2, &env->active_fpu.fp_status); 1595 1596 update_fcr31(env, GETPC()); 1597 return fst0; 1598 } 1599 1600 uint32_t helper_float_msub_s(CPUMIPSState *env, uint32_t fst0, 1601 uint32_t fst1, uint32_t fst2) 1602 { 1603 fst0 = float32_mul(fst0, fst1, &env->active_fpu.fp_status); 1604 fst0 = float32_sub(fst0, fst2, &env->active_fpu.fp_status); 1605 1606 update_fcr31(env, GETPC()); 1607 return fst0; 1608 } 1609 1610 uint64_t helper_float_msub_ps(CPUMIPSState *env, uint64_t fdt0, 1611 uint64_t fdt1, uint64_t fdt2) 1612 { 1613 uint32_t fstl0 = fdt0 & 0XFFFFFFFF; 1614 uint32_t fsth0 = fdt0 >> 32; 1615 uint32_t fstl1 = fdt1 & 0XFFFFFFFF; 1616 uint32_t fsth1 = fdt1 >> 32; 1617 uint32_t fstl2 = fdt2 & 0XFFFFFFFF; 1618 uint32_t fsth2 = fdt2 >> 32; 1619 1620 fstl0 = float32_mul(fstl0, fstl1, &env->active_fpu.fp_status); 1621 fstl0 = float32_sub(fstl0, fstl2, &env->active_fpu.fp_status); 1622 fsth0 = float32_mul(fsth0, fsth1, &env->active_fpu.fp_status); 1623 fsth0 = float32_sub(fsth0, fsth2, &env->active_fpu.fp_status); 1624 1625 update_fcr31(env, GETPC()); 1626 return ((uint64_t)fsth0 << 32) | fstl0; 1627 } 1628 1629 uint64_t helper_float_nmadd_d(CPUMIPSState *env, uint64_t fst0, 1630 uint64_t fst1, uint64_t fst2) 1631 { 1632 fst0 = float64_mul(fst0, fst1, &env->active_fpu.fp_status); 1633 fst0 = float64_add(fst0, fst2, &env->active_fpu.fp_status); 1634 fst0 = float64_chs(fst0); 1635 1636 update_fcr31(env, GETPC()); 1637 return fst0; 1638 } 1639 1640 uint32_t helper_float_nmadd_s(CPUMIPSState *env, uint32_t fst0, 1641 uint32_t fst1, uint32_t fst2) 1642 { 1643 fst0 = float32_mul(fst0, fst1, &env->active_fpu.fp_status); 1644 fst0 = float32_add(fst0, fst2, &env->active_fpu.fp_status); 1645 fst0 = float32_chs(fst0); 1646 1647 update_fcr31(env, GETPC()); 1648 return fst0; 1649 } 1650 1651 uint64_t helper_float_nmadd_ps(CPUMIPSState *env, uint64_t fdt0, 1652 uint64_t fdt1, uint64_t fdt2) 1653 { 1654 uint32_t fstl0 = fdt0 & 0XFFFFFFFF; 1655 uint32_t fsth0 = fdt0 >> 32; 1656 uint32_t fstl1 = fdt1 & 0XFFFFFFFF; 1657 uint32_t fsth1 = fdt1 >> 32; 1658 uint32_t fstl2 = fdt2 & 0XFFFFFFFF; 1659 uint32_t fsth2 = fdt2 >> 32; 1660 1661 fstl0 = float32_mul(fstl0, fstl1, &env->active_fpu.fp_status); 1662 fstl0 = float32_add(fstl0, fstl2, &env->active_fpu.fp_status); 1663 fstl0 = float32_chs(fstl0); 1664 fsth0 = float32_mul(fsth0, fsth1, &env->active_fpu.fp_status); 1665 fsth0 = float32_add(fsth0, fsth2, &env->active_fpu.fp_status); 1666 fsth0 = float32_chs(fsth0); 1667 1668 update_fcr31(env, GETPC()); 1669 return ((uint64_t)fsth0 << 32) | fstl0; 1670 } 1671 1672 uint64_t helper_float_nmsub_d(CPUMIPSState *env, uint64_t fst0, 1673 uint64_t fst1, uint64_t fst2) 1674 { 1675 fst0 = float64_mul(fst0, fst1, &env->active_fpu.fp_status); 1676 fst0 = float64_sub(fst0, fst2, &env->active_fpu.fp_status); 1677 fst0 = float64_chs(fst0); 1678 1679 update_fcr31(env, GETPC()); 1680 return fst0; 1681 } 1682 1683 uint32_t helper_float_nmsub_s(CPUMIPSState *env, uint32_t fst0, 1684 uint32_t fst1, uint32_t fst2) 1685 { 1686 fst0 = float32_mul(fst0, fst1, &env->active_fpu.fp_status); 1687 fst0 = float32_sub(fst0, fst2, &env->active_fpu.fp_status); 1688 fst0 = float32_chs(fst0); 1689 1690 update_fcr31(env, GETPC()); 1691 return fst0; 1692 } 1693 1694 uint64_t helper_float_nmsub_ps(CPUMIPSState *env, uint64_t fdt0, 1695 uint64_t fdt1, uint64_t fdt2) 1696 { 1697 uint32_t fstl0 = fdt0 & 0XFFFFFFFF; 1698 uint32_t fsth0 = fdt0 >> 32; 1699 uint32_t fstl1 = fdt1 & 0XFFFFFFFF; 1700 uint32_t fsth1 = fdt1 >> 32; 1701 uint32_t fstl2 = fdt2 & 0XFFFFFFFF; 1702 uint32_t fsth2 = fdt2 >> 32; 1703 1704 fstl0 = float32_mul(fstl0, fstl1, &env->active_fpu.fp_status); 1705 fstl0 = float32_sub(fstl0, fstl2, &env->active_fpu.fp_status); 1706 fstl0 = float32_chs(fstl0); 1707 fsth0 = float32_mul(fsth0, fsth1, &env->active_fpu.fp_status); 1708 fsth0 = float32_sub(fsth0, fsth2, &env->active_fpu.fp_status); 1709 fsth0 = float32_chs(fsth0); 1710 1711 update_fcr31(env, GETPC()); 1712 return ((uint64_t)fsth0 << 32) | fstl0; 1713 } 1714 1715 1716 uint32_t helper_float_maddf_s(CPUMIPSState *env, uint32_t fs, 1717 uint32_t ft, uint32_t fd) 1718 { 1719 uint32_t fdret; 1720 1721 fdret = float32_muladd(fs, ft, fd, 0, 1722 &env->active_fpu.fp_status); 1723 1724 update_fcr31(env, GETPC()); 1725 return fdret; 1726 } 1727 1728 uint64_t helper_float_maddf_d(CPUMIPSState *env, uint64_t fs, 1729 uint64_t ft, uint64_t fd) 1730 { 1731 uint64_t fdret; 1732 1733 fdret = float64_muladd(fs, ft, fd, 0, 1734 &env->active_fpu.fp_status); 1735 1736 update_fcr31(env, GETPC()); 1737 return fdret; 1738 } 1739 1740 uint32_t helper_float_msubf_s(CPUMIPSState *env, uint32_t fs, 1741 uint32_t ft, uint32_t fd) 1742 { 1743 uint32_t fdret; 1744 1745 fdret = float32_muladd(fs, ft, fd, float_muladd_negate_product, 1746 &env->active_fpu.fp_status); 1747 1748 update_fcr31(env, GETPC()); 1749 return fdret; 1750 } 1751 1752 uint64_t helper_float_msubf_d(CPUMIPSState *env, uint64_t fs, 1753 uint64_t ft, uint64_t fd) 1754 { 1755 uint64_t fdret; 1756 1757 fdret = float64_muladd(fs, ft, fd, float_muladd_negate_product, 1758 &env->active_fpu.fp_status); 1759 1760 update_fcr31(env, GETPC()); 1761 return fdret; 1762 } 1763 1764 1765 /* compare operations */ 1766 #define FOP_COND_D(op, cond) \ 1767 void helper_cmp_d_ ## op(CPUMIPSState *env, uint64_t fdt0, \ 1768 uint64_t fdt1, int cc) \ 1769 { \ 1770 int c; \ 1771 c = cond; \ 1772 update_fcr31(env, GETPC()); \ 1773 if (c) \ 1774 SET_FP_COND(cc, env->active_fpu); \ 1775 else \ 1776 CLEAR_FP_COND(cc, env->active_fpu); \ 1777 } \ 1778 void helper_cmpabs_d_ ## op(CPUMIPSState *env, uint64_t fdt0, \ 1779 uint64_t fdt1, int cc) \ 1780 { \ 1781 int c; \ 1782 fdt0 = float64_abs(fdt0); \ 1783 fdt1 = float64_abs(fdt1); \ 1784 c = cond; \ 1785 update_fcr31(env, GETPC()); \ 1786 if (c) \ 1787 SET_FP_COND(cc, env->active_fpu); \ 1788 else \ 1789 CLEAR_FP_COND(cc, env->active_fpu); \ 1790 } 1791 1792 /* 1793 * NOTE: the comma operator will make "cond" to eval to false, 1794 * but float64_unordered_quiet() is still called. 1795 */ 1796 FOP_COND_D(f, (float64_unordered_quiet(fdt1, fdt0, 1797 &env->active_fpu.fp_status), 0)) 1798 FOP_COND_D(un, float64_unordered_quiet(fdt1, fdt0, 1799 &env->active_fpu.fp_status)) 1800 FOP_COND_D(eq, float64_eq_quiet(fdt0, fdt1, 1801 &env->active_fpu.fp_status)) 1802 FOP_COND_D(ueq, float64_unordered_quiet(fdt1, fdt0, 1803 &env->active_fpu.fp_status) 1804 || float64_eq_quiet(fdt0, fdt1, 1805 &env->active_fpu.fp_status)) 1806 FOP_COND_D(olt, float64_lt_quiet(fdt0, fdt1, 1807 &env->active_fpu.fp_status)) 1808 FOP_COND_D(ult, float64_unordered_quiet(fdt1, fdt0, 1809 &env->active_fpu.fp_status) 1810 || float64_lt_quiet(fdt0, fdt1, 1811 &env->active_fpu.fp_status)) 1812 FOP_COND_D(ole, float64_le_quiet(fdt0, fdt1, 1813 &env->active_fpu.fp_status)) 1814 FOP_COND_D(ule, float64_unordered_quiet(fdt1, fdt0, 1815 &env->active_fpu.fp_status) 1816 || float64_le_quiet(fdt0, fdt1, 1817 &env->active_fpu.fp_status)) 1818 /* 1819 * NOTE: the comma operator will make "cond" to eval to false, 1820 * but float64_unordered() is still called. 1821 */ 1822 FOP_COND_D(sf, (float64_unordered(fdt1, fdt0, 1823 &env->active_fpu.fp_status), 0)) 1824 FOP_COND_D(ngle, float64_unordered(fdt1, fdt0, 1825 &env->active_fpu.fp_status)) 1826 FOP_COND_D(seq, float64_eq(fdt0, fdt1, 1827 &env->active_fpu.fp_status)) 1828 FOP_COND_D(ngl, float64_unordered(fdt1, fdt0, 1829 &env->active_fpu.fp_status) 1830 || float64_eq(fdt0, fdt1, 1831 &env->active_fpu.fp_status)) 1832 FOP_COND_D(lt, float64_lt(fdt0, fdt1, 1833 &env->active_fpu.fp_status)) 1834 FOP_COND_D(nge, float64_unordered(fdt1, fdt0, 1835 &env->active_fpu.fp_status) 1836 || float64_lt(fdt0, fdt1, 1837 &env->active_fpu.fp_status)) 1838 FOP_COND_D(le, float64_le(fdt0, fdt1, 1839 &env->active_fpu.fp_status)) 1840 FOP_COND_D(ngt, float64_unordered(fdt1, fdt0, 1841 &env->active_fpu.fp_status) 1842 || float64_le(fdt0, fdt1, 1843 &env->active_fpu.fp_status)) 1844 1845 #define FOP_COND_S(op, cond) \ 1846 void helper_cmp_s_ ## op(CPUMIPSState *env, uint32_t fst0, \ 1847 uint32_t fst1, int cc) \ 1848 { \ 1849 int c; \ 1850 c = cond; \ 1851 update_fcr31(env, GETPC()); \ 1852 if (c) \ 1853 SET_FP_COND(cc, env->active_fpu); \ 1854 else \ 1855 CLEAR_FP_COND(cc, env->active_fpu); \ 1856 } \ 1857 void helper_cmpabs_s_ ## op(CPUMIPSState *env, uint32_t fst0, \ 1858 uint32_t fst1, int cc) \ 1859 { \ 1860 int c; \ 1861 fst0 = float32_abs(fst0); \ 1862 fst1 = float32_abs(fst1); \ 1863 c = cond; \ 1864 update_fcr31(env, GETPC()); \ 1865 if (c) \ 1866 SET_FP_COND(cc, env->active_fpu); \ 1867 else \ 1868 CLEAR_FP_COND(cc, env->active_fpu); \ 1869 } 1870 1871 /* 1872 * NOTE: the comma operator will make "cond" to eval to false, 1873 * but float32_unordered_quiet() is still called. 1874 */ 1875 FOP_COND_S(f, (float32_unordered_quiet(fst1, fst0, 1876 &env->active_fpu.fp_status), 0)) 1877 FOP_COND_S(un, float32_unordered_quiet(fst1, fst0, 1878 &env->active_fpu.fp_status)) 1879 FOP_COND_S(eq, float32_eq_quiet(fst0, fst1, 1880 &env->active_fpu.fp_status)) 1881 FOP_COND_S(ueq, float32_unordered_quiet(fst1, fst0, 1882 &env->active_fpu.fp_status) 1883 || float32_eq_quiet(fst0, fst1, 1884 &env->active_fpu.fp_status)) 1885 FOP_COND_S(olt, float32_lt_quiet(fst0, fst1, 1886 &env->active_fpu.fp_status)) 1887 FOP_COND_S(ult, float32_unordered_quiet(fst1, fst0, 1888 &env->active_fpu.fp_status) 1889 || float32_lt_quiet(fst0, fst1, 1890 &env->active_fpu.fp_status)) 1891 FOP_COND_S(ole, float32_le_quiet(fst0, fst1, 1892 &env->active_fpu.fp_status)) 1893 FOP_COND_S(ule, float32_unordered_quiet(fst1, fst0, 1894 &env->active_fpu.fp_status) 1895 || float32_le_quiet(fst0, fst1, 1896 &env->active_fpu.fp_status)) 1897 /* 1898 * NOTE: the comma operator will make "cond" to eval to false, 1899 * but float32_unordered() is still called. 1900 */ 1901 FOP_COND_S(sf, (float32_unordered(fst1, fst0, 1902 &env->active_fpu.fp_status), 0)) 1903 FOP_COND_S(ngle, float32_unordered(fst1, fst0, 1904 &env->active_fpu.fp_status)) 1905 FOP_COND_S(seq, float32_eq(fst0, fst1, 1906 &env->active_fpu.fp_status)) 1907 FOP_COND_S(ngl, float32_unordered(fst1, fst0, 1908 &env->active_fpu.fp_status) 1909 || float32_eq(fst0, fst1, 1910 &env->active_fpu.fp_status)) 1911 FOP_COND_S(lt, float32_lt(fst0, fst1, 1912 &env->active_fpu.fp_status)) 1913 FOP_COND_S(nge, float32_unordered(fst1, fst0, 1914 &env->active_fpu.fp_status) 1915 || float32_lt(fst0, fst1, 1916 &env->active_fpu.fp_status)) 1917 FOP_COND_S(le, float32_le(fst0, fst1, 1918 &env->active_fpu.fp_status)) 1919 FOP_COND_S(ngt, float32_unordered(fst1, fst0, 1920 &env->active_fpu.fp_status) 1921 || float32_le(fst0, fst1, 1922 &env->active_fpu.fp_status)) 1923 1924 #define FOP_COND_PS(op, condl, condh) \ 1925 void helper_cmp_ps_ ## op(CPUMIPSState *env, uint64_t fdt0, \ 1926 uint64_t fdt1, int cc) \ 1927 { \ 1928 uint32_t fst0, fsth0, fst1, fsth1; \ 1929 int ch, cl; \ 1930 fst0 = fdt0 & 0XFFFFFFFF; \ 1931 fsth0 = fdt0 >> 32; \ 1932 fst1 = fdt1 & 0XFFFFFFFF; \ 1933 fsth1 = fdt1 >> 32; \ 1934 cl = condl; \ 1935 ch = condh; \ 1936 update_fcr31(env, GETPC()); \ 1937 if (cl) \ 1938 SET_FP_COND(cc, env->active_fpu); \ 1939 else \ 1940 CLEAR_FP_COND(cc, env->active_fpu); \ 1941 if (ch) \ 1942 SET_FP_COND(cc + 1, env->active_fpu); \ 1943 else \ 1944 CLEAR_FP_COND(cc + 1, env->active_fpu); \ 1945 } \ 1946 void helper_cmpabs_ps_ ## op(CPUMIPSState *env, uint64_t fdt0, \ 1947 uint64_t fdt1, int cc) \ 1948 { \ 1949 uint32_t fst0, fsth0, fst1, fsth1; \ 1950 int ch, cl; \ 1951 fst0 = float32_abs(fdt0 & 0XFFFFFFFF); \ 1952 fsth0 = float32_abs(fdt0 >> 32); \ 1953 fst1 = float32_abs(fdt1 & 0XFFFFFFFF); \ 1954 fsth1 = float32_abs(fdt1 >> 32); \ 1955 cl = condl; \ 1956 ch = condh; \ 1957 update_fcr31(env, GETPC()); \ 1958 if (cl) \ 1959 SET_FP_COND(cc, env->active_fpu); \ 1960 else \ 1961 CLEAR_FP_COND(cc, env->active_fpu); \ 1962 if (ch) \ 1963 SET_FP_COND(cc + 1, env->active_fpu); \ 1964 else \ 1965 CLEAR_FP_COND(cc + 1, env->active_fpu); \ 1966 } 1967 1968 /* 1969 * NOTE: the comma operator will make "cond" to eval to false, 1970 * but float32_unordered_quiet() is still called. 1971 */ 1972 FOP_COND_PS(f, (float32_unordered_quiet(fst1, fst0, 1973 &env->active_fpu.fp_status), 0), 1974 (float32_unordered_quiet(fsth1, fsth0, 1975 &env->active_fpu.fp_status), 0)) 1976 FOP_COND_PS(un, float32_unordered_quiet(fst1, fst0, 1977 &env->active_fpu.fp_status), 1978 float32_unordered_quiet(fsth1, fsth0, 1979 &env->active_fpu.fp_status)) 1980 FOP_COND_PS(eq, float32_eq_quiet(fst0, fst1, 1981 &env->active_fpu.fp_status), 1982 float32_eq_quiet(fsth0, fsth1, 1983 &env->active_fpu.fp_status)) 1984 FOP_COND_PS(ueq, float32_unordered_quiet(fst1, fst0, 1985 &env->active_fpu.fp_status) 1986 || float32_eq_quiet(fst0, fst1, 1987 &env->active_fpu.fp_status), 1988 float32_unordered_quiet(fsth1, fsth0, 1989 &env->active_fpu.fp_status) 1990 || float32_eq_quiet(fsth0, fsth1, 1991 &env->active_fpu.fp_status)) 1992 FOP_COND_PS(olt, float32_lt_quiet(fst0, fst1, 1993 &env->active_fpu.fp_status), 1994 float32_lt_quiet(fsth0, fsth1, 1995 &env->active_fpu.fp_status)) 1996 FOP_COND_PS(ult, float32_unordered_quiet(fst1, fst0, 1997 &env->active_fpu.fp_status) 1998 || float32_lt_quiet(fst0, fst1, 1999 &env->active_fpu.fp_status), 2000 float32_unordered_quiet(fsth1, fsth0, 2001 &env->active_fpu.fp_status) 2002 || float32_lt_quiet(fsth0, fsth1, 2003 &env->active_fpu.fp_status)) 2004 FOP_COND_PS(ole, float32_le_quiet(fst0, fst1, 2005 &env->active_fpu.fp_status), 2006 float32_le_quiet(fsth0, fsth1, 2007 &env->active_fpu.fp_status)) 2008 FOP_COND_PS(ule, float32_unordered_quiet(fst1, fst0, 2009 &env->active_fpu.fp_status) 2010 || float32_le_quiet(fst0, fst1, 2011 &env->active_fpu.fp_status), 2012 float32_unordered_quiet(fsth1, fsth0, 2013 &env->active_fpu.fp_status) 2014 || float32_le_quiet(fsth0, fsth1, 2015 &env->active_fpu.fp_status)) 2016 /* 2017 * NOTE: the comma operator will make "cond" to eval to false, 2018 * but float32_unordered() is still called. 2019 */ 2020 FOP_COND_PS(sf, (float32_unordered(fst1, fst0, 2021 &env->active_fpu.fp_status), 0), 2022 (float32_unordered(fsth1, fsth0, 2023 &env->active_fpu.fp_status), 0)) 2024 FOP_COND_PS(ngle, float32_unordered(fst1, fst0, 2025 &env->active_fpu.fp_status), 2026 float32_unordered(fsth1, fsth0, 2027 &env->active_fpu.fp_status)) 2028 FOP_COND_PS(seq, float32_eq(fst0, fst1, 2029 &env->active_fpu.fp_status), 2030 float32_eq(fsth0, fsth1, 2031 &env->active_fpu.fp_status)) 2032 FOP_COND_PS(ngl, float32_unordered(fst1, fst0, 2033 &env->active_fpu.fp_status) 2034 || float32_eq(fst0, fst1, 2035 &env->active_fpu.fp_status), 2036 float32_unordered(fsth1, fsth0, 2037 &env->active_fpu.fp_status) 2038 || float32_eq(fsth0, fsth1, 2039 &env->active_fpu.fp_status)) 2040 FOP_COND_PS(lt, float32_lt(fst0, fst1, 2041 &env->active_fpu.fp_status), 2042 float32_lt(fsth0, fsth1, 2043 &env->active_fpu.fp_status)) 2044 FOP_COND_PS(nge, float32_unordered(fst1, fst0, 2045 &env->active_fpu.fp_status) 2046 || float32_lt(fst0, fst1, 2047 &env->active_fpu.fp_status), 2048 float32_unordered(fsth1, fsth0, 2049 &env->active_fpu.fp_status) 2050 || float32_lt(fsth0, fsth1, 2051 &env->active_fpu.fp_status)) 2052 FOP_COND_PS(le, float32_le(fst0, fst1, 2053 &env->active_fpu.fp_status), 2054 float32_le(fsth0, fsth1, 2055 &env->active_fpu.fp_status)) 2056 FOP_COND_PS(ngt, float32_unordered(fst1, fst0, 2057 &env->active_fpu.fp_status) 2058 || float32_le(fst0, fst1, 2059 &env->active_fpu.fp_status), 2060 float32_unordered(fsth1, fsth0, 2061 &env->active_fpu.fp_status) 2062 || float32_le(fsth0, fsth1, 2063 &env->active_fpu.fp_status)) 2064 2065 /* R6 compare operations */ 2066 #define FOP_CONDN_D(op, cond) \ 2067 uint64_t helper_r6_cmp_d_ ## op(CPUMIPSState *env, uint64_t fdt0, \ 2068 uint64_t fdt1) \ 2069 { \ 2070 uint64_t c; \ 2071 c = cond; \ 2072 update_fcr31(env, GETPC()); \ 2073 if (c) { \ 2074 return -1; \ 2075 } else { \ 2076 return 0; \ 2077 } \ 2078 } 2079 2080 /* 2081 * NOTE: the comma operator will make "cond" to eval to false, 2082 * but float64_unordered_quiet() is still called. 2083 */ 2084 FOP_CONDN_D(af, (float64_unordered_quiet(fdt1, fdt0, 2085 &env->active_fpu.fp_status), 0)) 2086 FOP_CONDN_D(un, (float64_unordered_quiet(fdt1, fdt0, 2087 &env->active_fpu.fp_status))) 2088 FOP_CONDN_D(eq, (float64_eq_quiet(fdt0, fdt1, 2089 &env->active_fpu.fp_status))) 2090 FOP_CONDN_D(ueq, (float64_unordered_quiet(fdt1, fdt0, 2091 &env->active_fpu.fp_status) 2092 || float64_eq_quiet(fdt0, fdt1, 2093 &env->active_fpu.fp_status))) 2094 FOP_CONDN_D(lt, (float64_lt_quiet(fdt0, fdt1, 2095 &env->active_fpu.fp_status))) 2096 FOP_CONDN_D(ult, (float64_unordered_quiet(fdt1, fdt0, 2097 &env->active_fpu.fp_status) 2098 || float64_lt_quiet(fdt0, fdt1, 2099 &env->active_fpu.fp_status))) 2100 FOP_CONDN_D(le, (float64_le_quiet(fdt0, fdt1, 2101 &env->active_fpu.fp_status))) 2102 FOP_CONDN_D(ule, (float64_unordered_quiet(fdt1, fdt0, 2103 &env->active_fpu.fp_status) 2104 || float64_le_quiet(fdt0, fdt1, 2105 &env->active_fpu.fp_status))) 2106 /* 2107 * NOTE: the comma operator will make "cond" to eval to false, 2108 * but float64_unordered() is still called.\ 2109 */ 2110 FOP_CONDN_D(saf, (float64_unordered(fdt1, fdt0, 2111 &env->active_fpu.fp_status), 0)) 2112 FOP_CONDN_D(sun, (float64_unordered(fdt1, fdt0, 2113 &env->active_fpu.fp_status))) 2114 FOP_CONDN_D(seq, (float64_eq(fdt0, fdt1, 2115 &env->active_fpu.fp_status))) 2116 FOP_CONDN_D(sueq, (float64_unordered(fdt1, fdt0, 2117 &env->active_fpu.fp_status) 2118 || float64_eq(fdt0, fdt1, 2119 &env->active_fpu.fp_status))) 2120 FOP_CONDN_D(slt, (float64_lt(fdt0, fdt1, 2121 &env->active_fpu.fp_status))) 2122 FOP_CONDN_D(sult, (float64_unordered(fdt1, fdt0, 2123 &env->active_fpu.fp_status) 2124 || float64_lt(fdt0, fdt1, 2125 &env->active_fpu.fp_status))) 2126 FOP_CONDN_D(sle, (float64_le(fdt0, fdt1, 2127 &env->active_fpu.fp_status))) 2128 FOP_CONDN_D(sule, (float64_unordered(fdt1, fdt0, 2129 &env->active_fpu.fp_status) 2130 || float64_le(fdt0, fdt1, 2131 &env->active_fpu.fp_status))) 2132 FOP_CONDN_D(or, (float64_le_quiet(fdt1, fdt0, 2133 &env->active_fpu.fp_status) 2134 || float64_le_quiet(fdt0, fdt1, 2135 &env->active_fpu.fp_status))) 2136 FOP_CONDN_D(une, (float64_unordered_quiet(fdt1, fdt0, 2137 &env->active_fpu.fp_status) 2138 || float64_lt_quiet(fdt1, fdt0, 2139 &env->active_fpu.fp_status) 2140 || float64_lt_quiet(fdt0, fdt1, 2141 &env->active_fpu.fp_status))) 2142 FOP_CONDN_D(ne, (float64_lt_quiet(fdt1, fdt0, 2143 &env->active_fpu.fp_status) 2144 || float64_lt_quiet(fdt0, fdt1, 2145 &env->active_fpu.fp_status))) 2146 FOP_CONDN_D(sor, (float64_le(fdt1, fdt0, 2147 &env->active_fpu.fp_status) 2148 || float64_le(fdt0, fdt1, 2149 &env->active_fpu.fp_status))) 2150 FOP_CONDN_D(sune, (float64_unordered(fdt1, fdt0, 2151 &env->active_fpu.fp_status) 2152 || float64_lt(fdt1, fdt0, 2153 &env->active_fpu.fp_status) 2154 || float64_lt(fdt0, fdt1, 2155 &env->active_fpu.fp_status))) 2156 FOP_CONDN_D(sne, (float64_lt(fdt1, fdt0, 2157 &env->active_fpu.fp_status) 2158 || float64_lt(fdt0, fdt1, 2159 &env->active_fpu.fp_status))) 2160 2161 #define FOP_CONDN_S(op, cond) \ 2162 uint32_t helper_r6_cmp_s_ ## op(CPUMIPSState *env, uint32_t fst0, \ 2163 uint32_t fst1) \ 2164 { \ 2165 uint64_t c; \ 2166 c = cond; \ 2167 update_fcr31(env, GETPC()); \ 2168 if (c) { \ 2169 return -1; \ 2170 } else { \ 2171 return 0; \ 2172 } \ 2173 } 2174 2175 /* 2176 * NOTE: the comma operator will make "cond" to eval to false, 2177 * but float32_unordered_quiet() is still called. 2178 */ 2179 FOP_CONDN_S(af, (float32_unordered_quiet(fst1, fst0, 2180 &env->active_fpu.fp_status), 0)) 2181 FOP_CONDN_S(un, (float32_unordered_quiet(fst1, fst0, 2182 &env->active_fpu.fp_status))) 2183 FOP_CONDN_S(eq, (float32_eq_quiet(fst0, fst1, 2184 &env->active_fpu.fp_status))) 2185 FOP_CONDN_S(ueq, (float32_unordered_quiet(fst1, fst0, 2186 &env->active_fpu.fp_status) 2187 || float32_eq_quiet(fst0, fst1, 2188 &env->active_fpu.fp_status))) 2189 FOP_CONDN_S(lt, (float32_lt_quiet(fst0, fst1, 2190 &env->active_fpu.fp_status))) 2191 FOP_CONDN_S(ult, (float32_unordered_quiet(fst1, fst0, 2192 &env->active_fpu.fp_status) 2193 || float32_lt_quiet(fst0, fst1, 2194 &env->active_fpu.fp_status))) 2195 FOP_CONDN_S(le, (float32_le_quiet(fst0, fst1, 2196 &env->active_fpu.fp_status))) 2197 FOP_CONDN_S(ule, (float32_unordered_quiet(fst1, fst0, 2198 &env->active_fpu.fp_status) 2199 || float32_le_quiet(fst0, fst1, 2200 &env->active_fpu.fp_status))) 2201 /* 2202 * NOTE: the comma operator will make "cond" to eval to false, 2203 * but float32_unordered() is still called. 2204 */ 2205 FOP_CONDN_S(saf, (float32_unordered(fst1, fst0, 2206 &env->active_fpu.fp_status), 0)) 2207 FOP_CONDN_S(sun, (float32_unordered(fst1, fst0, 2208 &env->active_fpu.fp_status))) 2209 FOP_CONDN_S(seq, (float32_eq(fst0, fst1, 2210 &env->active_fpu.fp_status))) 2211 FOP_CONDN_S(sueq, (float32_unordered(fst1, fst0, 2212 &env->active_fpu.fp_status) 2213 || float32_eq(fst0, fst1, 2214 &env->active_fpu.fp_status))) 2215 FOP_CONDN_S(slt, (float32_lt(fst0, fst1, 2216 &env->active_fpu.fp_status))) 2217 FOP_CONDN_S(sult, (float32_unordered(fst1, fst0, 2218 &env->active_fpu.fp_status) 2219 || float32_lt(fst0, fst1, 2220 &env->active_fpu.fp_status))) 2221 FOP_CONDN_S(sle, (float32_le(fst0, fst1, 2222 &env->active_fpu.fp_status))) 2223 FOP_CONDN_S(sule, (float32_unordered(fst1, fst0, 2224 &env->active_fpu.fp_status) 2225 || float32_le(fst0, fst1, 2226 &env->active_fpu.fp_status))) 2227 FOP_CONDN_S(or, (float32_le_quiet(fst1, fst0, 2228 &env->active_fpu.fp_status) 2229 || float32_le_quiet(fst0, fst1, 2230 &env->active_fpu.fp_status))) 2231 FOP_CONDN_S(une, (float32_unordered_quiet(fst1, fst0, 2232 &env->active_fpu.fp_status) 2233 || float32_lt_quiet(fst1, fst0, 2234 &env->active_fpu.fp_status) 2235 || float32_lt_quiet(fst0, fst1, 2236 &env->active_fpu.fp_status))) 2237 FOP_CONDN_S(ne, (float32_lt_quiet(fst1, fst0, 2238 &env->active_fpu.fp_status) 2239 || float32_lt_quiet(fst0, fst1, 2240 &env->active_fpu.fp_status))) 2241 FOP_CONDN_S(sor, (float32_le(fst1, fst0, 2242 &env->active_fpu.fp_status) 2243 || float32_le(fst0, fst1, 2244 &env->active_fpu.fp_status))) 2245 FOP_CONDN_S(sune, (float32_unordered(fst1, fst0, 2246 &env->active_fpu.fp_status) 2247 || float32_lt(fst1, fst0, 2248 &env->active_fpu.fp_status) 2249 || float32_lt(fst0, fst1, 2250 &env->active_fpu.fp_status))) 2251 FOP_CONDN_S(sne, (float32_lt(fst1, fst0, 2252 &env->active_fpu.fp_status) 2253 || float32_lt(fst0, fst1, 2254 &env->active_fpu.fp_status))) 2255