fpu_helper.c (78493B)
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 41target_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 89void 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 181static 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 204static 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 */ 235uint64_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 242uint32_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 249uint64_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 258uint64_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 267uint64_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 276uint64_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 289uint64_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 302uint64_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 313uint64_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 338uint32_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 347uint32_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 356uint32_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 365uint32_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 374uint32_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 383uint32_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 396uint32_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 409uint64_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 425uint64_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 441uint32_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 457uint32_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 473uint64_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 487uint64_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 500uint32_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 513uint32_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 526uint64_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 541uint64_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 556uint32_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 571uint32_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 586uint64_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 601uint64_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 616uint32_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 631uint32_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 646uint64_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 661uint64_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 676uint32_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 691uint32_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 706uint64_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 724uint64_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 742uint32_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 760uint32_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 778uint64_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 793uint64_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 808uint32_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 823uint32_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 838uint64_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 855uint64_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 872uint32_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 889uint32_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 906uint64_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 923uint64_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 940uint32_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 957uint32_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 976uint64_t helper_float_abs_d(uint64_t fdt0) 977{ 978 return float64_abs(fdt0); 979} 980 981uint32_t helper_float_abs_s(uint32_t fst0) 982{ 983 return float32_abs(fst0); 984} 985 986uint64_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 996uint64_t helper_float_chs_d(uint64_t fdt0) 997{ 998 return float64_chs(fdt0); 999} 1000 1001uint32_t helper_float_chs_s(uint32_t fst0) 1002{ 1003 return float32_chs(fst0); 1004} 1005 1006uint64_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 */ 1017uint64_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 1026uint32_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 1035uint64_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 1045uint32_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 1055uint64_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 1064uint32_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 1073uint64_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 1085uint64_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 1095uint32_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 1105uint64_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 1118uint64_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 1127uint32_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 1147uint64_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 1176uint64_t helper_float_class_d(CPUMIPSState *env, uint64_t arg) 1177{ 1178 return float_class_d(arg, &env->active_fpu.fp_status); 1179} 1180 1181uint32_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 1210uint32_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 1217uint64_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 1227uint32_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 1237uint64_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 1253uint64_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 1263uint32_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 1273uint64_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 1289uint64_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 1299uint32_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 1309uint64_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 1325uint64_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 1335uint32_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 1345uint64_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 */ 1363uint64_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 1372uint32_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 1381uint64_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 1398uint64_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 1408uint32_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 1418uint64_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 1437uint64_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 1452uint64_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 1468uint32_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 1478uint64_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 1488uint32_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 1498uint64_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 1508uint32_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 1518uint64_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 1528uint32_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 1538uint64_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 1551uint64_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 1561uint32_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 1571uint64_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 1590uint64_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 1600uint32_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 1610uint64_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 1629uint64_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 1640uint32_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 1651uint64_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 1672uint64_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 1683uint32_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 1694uint64_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 1716uint32_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 1728uint64_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 1740uint32_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 1752uint64_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) \ 1767void 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} \ 1778void 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 */ 1796FOP_COND_D(f, (float64_unordered_quiet(fdt1, fdt0, 1797 &env->active_fpu.fp_status), 0)) 1798FOP_COND_D(un, float64_unordered_quiet(fdt1, fdt0, 1799 &env->active_fpu.fp_status)) 1800FOP_COND_D(eq, float64_eq_quiet(fdt0, fdt1, 1801 &env->active_fpu.fp_status)) 1802FOP_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)) 1806FOP_COND_D(olt, float64_lt_quiet(fdt0, fdt1, 1807 &env->active_fpu.fp_status)) 1808FOP_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)) 1812FOP_COND_D(ole, float64_le_quiet(fdt0, fdt1, 1813 &env->active_fpu.fp_status)) 1814FOP_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 */ 1822FOP_COND_D(sf, (float64_unordered(fdt1, fdt0, 1823 &env->active_fpu.fp_status), 0)) 1824FOP_COND_D(ngle, float64_unordered(fdt1, fdt0, 1825 &env->active_fpu.fp_status)) 1826FOP_COND_D(seq, float64_eq(fdt0, fdt1, 1827 &env->active_fpu.fp_status)) 1828FOP_COND_D(ngl, float64_unordered(fdt1, fdt0, 1829 &env->active_fpu.fp_status) 1830 || float64_eq(fdt0, fdt1, 1831 &env->active_fpu.fp_status)) 1832FOP_COND_D(lt, float64_lt(fdt0, fdt1, 1833 &env->active_fpu.fp_status)) 1834FOP_COND_D(nge, float64_unordered(fdt1, fdt0, 1835 &env->active_fpu.fp_status) 1836 || float64_lt(fdt0, fdt1, 1837 &env->active_fpu.fp_status)) 1838FOP_COND_D(le, float64_le(fdt0, fdt1, 1839 &env->active_fpu.fp_status)) 1840FOP_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) \ 1846void 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} \ 1857void 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 */ 1875FOP_COND_S(f, (float32_unordered_quiet(fst1, fst0, 1876 &env->active_fpu.fp_status), 0)) 1877FOP_COND_S(un, float32_unordered_quiet(fst1, fst0, 1878 &env->active_fpu.fp_status)) 1879FOP_COND_S(eq, float32_eq_quiet(fst0, fst1, 1880 &env->active_fpu.fp_status)) 1881FOP_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)) 1885FOP_COND_S(olt, float32_lt_quiet(fst0, fst1, 1886 &env->active_fpu.fp_status)) 1887FOP_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)) 1891FOP_COND_S(ole, float32_le_quiet(fst0, fst1, 1892 &env->active_fpu.fp_status)) 1893FOP_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 */ 1901FOP_COND_S(sf, (float32_unordered(fst1, fst0, 1902 &env->active_fpu.fp_status), 0)) 1903FOP_COND_S(ngle, float32_unordered(fst1, fst0, 1904 &env->active_fpu.fp_status)) 1905FOP_COND_S(seq, float32_eq(fst0, fst1, 1906 &env->active_fpu.fp_status)) 1907FOP_COND_S(ngl, float32_unordered(fst1, fst0, 1908 &env->active_fpu.fp_status) 1909 || float32_eq(fst0, fst1, 1910 &env->active_fpu.fp_status)) 1911FOP_COND_S(lt, float32_lt(fst0, fst1, 1912 &env->active_fpu.fp_status)) 1913FOP_COND_S(nge, float32_unordered(fst1, fst0, 1914 &env->active_fpu.fp_status) 1915 || float32_lt(fst0, fst1, 1916 &env->active_fpu.fp_status)) 1917FOP_COND_S(le, float32_le(fst0, fst1, 1918 &env->active_fpu.fp_status)) 1919FOP_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) \ 1925void 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} \ 1946void 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 */ 1972FOP_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)) 1976FOP_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)) 1980FOP_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)) 1984FOP_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)) 1992FOP_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)) 1996FOP_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)) 2004FOP_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)) 2008FOP_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 */ 2020FOP_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)) 2024FOP_COND_PS(ngle, float32_unordered(fst1, fst0, 2025 &env->active_fpu.fp_status), 2026 float32_unordered(fsth1, fsth0, 2027 &env->active_fpu.fp_status)) 2028FOP_COND_PS(seq, float32_eq(fst0, fst1, 2029 &env->active_fpu.fp_status), 2030 float32_eq(fsth0, fsth1, 2031 &env->active_fpu.fp_status)) 2032FOP_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)) 2040FOP_COND_PS(lt, float32_lt(fst0, fst1, 2041 &env->active_fpu.fp_status), 2042 float32_lt(fsth0, fsth1, 2043 &env->active_fpu.fp_status)) 2044FOP_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)) 2052FOP_COND_PS(le, float32_le(fst0, fst1, 2053 &env->active_fpu.fp_status), 2054 float32_le(fsth0, fsth1, 2055 &env->active_fpu.fp_status)) 2056FOP_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) \ 2067uint64_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 */ 2084FOP_CONDN_D(af, (float64_unordered_quiet(fdt1, fdt0, 2085 &env->active_fpu.fp_status), 0)) 2086FOP_CONDN_D(un, (float64_unordered_quiet(fdt1, fdt0, 2087 &env->active_fpu.fp_status))) 2088FOP_CONDN_D(eq, (float64_eq_quiet(fdt0, fdt1, 2089 &env->active_fpu.fp_status))) 2090FOP_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))) 2094FOP_CONDN_D(lt, (float64_lt_quiet(fdt0, fdt1, 2095 &env->active_fpu.fp_status))) 2096FOP_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))) 2100FOP_CONDN_D(le, (float64_le_quiet(fdt0, fdt1, 2101 &env->active_fpu.fp_status))) 2102FOP_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 */ 2110FOP_CONDN_D(saf, (float64_unordered(fdt1, fdt0, 2111 &env->active_fpu.fp_status), 0)) 2112FOP_CONDN_D(sun, (float64_unordered(fdt1, fdt0, 2113 &env->active_fpu.fp_status))) 2114FOP_CONDN_D(seq, (float64_eq(fdt0, fdt1, 2115 &env->active_fpu.fp_status))) 2116FOP_CONDN_D(sueq, (float64_unordered(fdt1, fdt0, 2117 &env->active_fpu.fp_status) 2118 || float64_eq(fdt0, fdt1, 2119 &env->active_fpu.fp_status))) 2120FOP_CONDN_D(slt, (float64_lt(fdt0, fdt1, 2121 &env->active_fpu.fp_status))) 2122FOP_CONDN_D(sult, (float64_unordered(fdt1, fdt0, 2123 &env->active_fpu.fp_status) 2124 || float64_lt(fdt0, fdt1, 2125 &env->active_fpu.fp_status))) 2126FOP_CONDN_D(sle, (float64_le(fdt0, fdt1, 2127 &env->active_fpu.fp_status))) 2128FOP_CONDN_D(sule, (float64_unordered(fdt1, fdt0, 2129 &env->active_fpu.fp_status) 2130 || float64_le(fdt0, fdt1, 2131 &env->active_fpu.fp_status))) 2132FOP_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))) 2136FOP_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))) 2142FOP_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))) 2146FOP_CONDN_D(sor, (float64_le(fdt1, fdt0, 2147 &env->active_fpu.fp_status) 2148 || float64_le(fdt0, fdt1, 2149 &env->active_fpu.fp_status))) 2150FOP_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))) 2156FOP_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) \ 2162uint32_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 */ 2179FOP_CONDN_S(af, (float32_unordered_quiet(fst1, fst0, 2180 &env->active_fpu.fp_status), 0)) 2181FOP_CONDN_S(un, (float32_unordered_quiet(fst1, fst0, 2182 &env->active_fpu.fp_status))) 2183FOP_CONDN_S(eq, (float32_eq_quiet(fst0, fst1, 2184 &env->active_fpu.fp_status))) 2185FOP_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))) 2189FOP_CONDN_S(lt, (float32_lt_quiet(fst0, fst1, 2190 &env->active_fpu.fp_status))) 2191FOP_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))) 2195FOP_CONDN_S(le, (float32_le_quiet(fst0, fst1, 2196 &env->active_fpu.fp_status))) 2197FOP_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 */ 2205FOP_CONDN_S(saf, (float32_unordered(fst1, fst0, 2206 &env->active_fpu.fp_status), 0)) 2207FOP_CONDN_S(sun, (float32_unordered(fst1, fst0, 2208 &env->active_fpu.fp_status))) 2209FOP_CONDN_S(seq, (float32_eq(fst0, fst1, 2210 &env->active_fpu.fp_status))) 2211FOP_CONDN_S(sueq, (float32_unordered(fst1, fst0, 2212 &env->active_fpu.fp_status) 2213 || float32_eq(fst0, fst1, 2214 &env->active_fpu.fp_status))) 2215FOP_CONDN_S(slt, (float32_lt(fst0, fst1, 2216 &env->active_fpu.fp_status))) 2217FOP_CONDN_S(sult, (float32_unordered(fst1, fst0, 2218 &env->active_fpu.fp_status) 2219 || float32_lt(fst0, fst1, 2220 &env->active_fpu.fp_status))) 2221FOP_CONDN_S(sle, (float32_le(fst0, fst1, 2222 &env->active_fpu.fp_status))) 2223FOP_CONDN_S(sule, (float32_unordered(fst1, fst0, 2224 &env->active_fpu.fp_status) 2225 || float32_le(fst0, fst1, 2226 &env->active_fpu.fp_status))) 2227FOP_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))) 2231FOP_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))) 2237FOP_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))) 2241FOP_CONDN_S(sor, (float32_le(fst1, fst0, 2242 &env->active_fpu.fp_status) 2243 || float32_le(fst0, fst1, 2244 &env->active_fpu.fp_status))) 2245FOP_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))) 2251FOP_CONDN_S(sne, (float32_lt(fst1, fst0, 2252 &env->active_fpu.fp_status) 2253 || float32_lt(fst0, fst1, 2254 &env->active_fpu.fp_status)))