1 /* 2 * MIPS emulation helpers for qemu. 3 * 4 * Copyright (c) 2004-2005 Jocelyn Mayer 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, see <http://www.gnu.org/licenses/>. 18 * 19 */ 20 21 #include "qemu/osdep.h" 22 #include "qemu/main-loop.h" 23 #include "cpu.h" 24 #include "internal.h" 25 #include "qemu/host-utils.h" 26 #include "exec/helper-proto.h" 27 #include "exec/exec-all.h" 28 #include "exec/cpu_ldst.h" 29 #include "exec/memop.h" 30 #include "sysemu/kvm.h" 31 #include "fpu/softfloat.h" 32 33 34 /*****************************************************************************/ 35 /* Exceptions processing helpers */ 36 37 void helper_raise_exception_err(CPUMIPSState *env, uint32_t exception, 38 int error_code) 39 { 40 do_raise_exception_err(env, exception, error_code, 0); 41 } 42 43 void helper_raise_exception(CPUMIPSState *env, uint32_t exception) 44 { 45 do_raise_exception(env, exception, GETPC()); 46 } 47 48 void helper_raise_exception_debug(CPUMIPSState *env) 49 { 50 do_raise_exception(env, EXCP_DEBUG, 0); 51 } 52 53 static void raise_exception(CPUMIPSState *env, uint32_t exception) 54 { 55 do_raise_exception(env, exception, 0); 56 } 57 58 /* 64 bits arithmetic for 32 bits hosts */ 59 static inline uint64_t get_HILO(CPUMIPSState *env) 60 { 61 return ((uint64_t)(env->active_tc.HI[0]) << 32) | 62 (uint32_t)env->active_tc.LO[0]; 63 } 64 65 static inline target_ulong set_HIT0_LO(CPUMIPSState *env, uint64_t HILO) 66 { 67 env->active_tc.LO[0] = (int32_t)(HILO & 0xFFFFFFFF); 68 return env->active_tc.HI[0] = (int32_t)(HILO >> 32); 69 } 70 71 static inline target_ulong set_HI_LOT0(CPUMIPSState *env, uint64_t HILO) 72 { 73 target_ulong tmp = env->active_tc.LO[0] = (int32_t)(HILO & 0xFFFFFFFF); 74 env->active_tc.HI[0] = (int32_t)(HILO >> 32); 75 return tmp; 76 } 77 78 /* Multiplication variants of the vr54xx. */ 79 target_ulong helper_muls(CPUMIPSState *env, target_ulong arg1, 80 target_ulong arg2) 81 { 82 return set_HI_LOT0(env, 0 - ((int64_t)(int32_t)arg1 * 83 (int64_t)(int32_t)arg2)); 84 } 85 86 target_ulong helper_mulsu(CPUMIPSState *env, target_ulong arg1, 87 target_ulong arg2) 88 { 89 return set_HI_LOT0(env, 0 - (uint64_t)(uint32_t)arg1 * 90 (uint64_t)(uint32_t)arg2); 91 } 92 93 target_ulong helper_macc(CPUMIPSState *env, target_ulong arg1, 94 target_ulong arg2) 95 { 96 return set_HI_LOT0(env, (int64_t)get_HILO(env) + (int64_t)(int32_t)arg1 * 97 (int64_t)(int32_t)arg2); 98 } 99 100 target_ulong helper_macchi(CPUMIPSState *env, target_ulong arg1, 101 target_ulong arg2) 102 { 103 return set_HIT0_LO(env, (int64_t)get_HILO(env) + (int64_t)(int32_t)arg1 * 104 (int64_t)(int32_t)arg2); 105 } 106 107 target_ulong helper_maccu(CPUMIPSState *env, target_ulong arg1, 108 target_ulong arg2) 109 { 110 return set_HI_LOT0(env, (uint64_t)get_HILO(env) + 111 (uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2); 112 } 113 114 target_ulong helper_macchiu(CPUMIPSState *env, target_ulong arg1, 115 target_ulong arg2) 116 { 117 return set_HIT0_LO(env, (uint64_t)get_HILO(env) + 118 (uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2); 119 } 120 121 target_ulong helper_msac(CPUMIPSState *env, target_ulong arg1, 122 target_ulong arg2) 123 { 124 return set_HI_LOT0(env, (int64_t)get_HILO(env) - (int64_t)(int32_t)arg1 * 125 (int64_t)(int32_t)arg2); 126 } 127 128 target_ulong helper_msachi(CPUMIPSState *env, target_ulong arg1, 129 target_ulong arg2) 130 { 131 return set_HIT0_LO(env, (int64_t)get_HILO(env) - (int64_t)(int32_t)arg1 * 132 (int64_t)(int32_t)arg2); 133 } 134 135 target_ulong helper_msacu(CPUMIPSState *env, target_ulong arg1, 136 target_ulong arg2) 137 { 138 return set_HI_LOT0(env, (uint64_t)get_HILO(env) - 139 (uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2); 140 } 141 142 target_ulong helper_msachiu(CPUMIPSState *env, target_ulong arg1, 143 target_ulong arg2) 144 { 145 return set_HIT0_LO(env, (uint64_t)get_HILO(env) - 146 (uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2); 147 } 148 149 target_ulong helper_mulhi(CPUMIPSState *env, target_ulong arg1, 150 target_ulong arg2) 151 { 152 return set_HIT0_LO(env, (int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2); 153 } 154 155 target_ulong helper_mulhiu(CPUMIPSState *env, target_ulong arg1, 156 target_ulong arg2) 157 { 158 return set_HIT0_LO(env, (uint64_t)(uint32_t)arg1 * 159 (uint64_t)(uint32_t)arg2); 160 } 161 162 target_ulong helper_mulshi(CPUMIPSState *env, target_ulong arg1, 163 target_ulong arg2) 164 { 165 return set_HIT0_LO(env, 0 - (int64_t)(int32_t)arg1 * 166 (int64_t)(int32_t)arg2); 167 } 168 169 target_ulong helper_mulshiu(CPUMIPSState *env, target_ulong arg1, 170 target_ulong arg2) 171 { 172 return set_HIT0_LO(env, 0 - (uint64_t)(uint32_t)arg1 * 173 (uint64_t)(uint32_t)arg2); 174 } 175 176 static inline target_ulong bitswap(target_ulong v) 177 { 178 v = ((v >> 1) & (target_ulong)0x5555555555555555ULL) | 179 ((v & (target_ulong)0x5555555555555555ULL) << 1); 180 v = ((v >> 2) & (target_ulong)0x3333333333333333ULL) | 181 ((v & (target_ulong)0x3333333333333333ULL) << 2); 182 v = ((v >> 4) & (target_ulong)0x0F0F0F0F0F0F0F0FULL) | 183 ((v & (target_ulong)0x0F0F0F0F0F0F0F0FULL) << 4); 184 return v; 185 } 186 187 #ifdef TARGET_MIPS64 188 target_ulong helper_dbitswap(target_ulong rt) 189 { 190 return bitswap(rt); 191 } 192 #endif 193 194 target_ulong helper_bitswap(target_ulong rt) 195 { 196 return (int32_t)bitswap(rt); 197 } 198 199 target_ulong helper_rotx(target_ulong rs, uint32_t shift, uint32_t shiftx, 200 uint32_t stripe) 201 { 202 int i; 203 uint64_t tmp0 = ((uint64_t)rs) << 32 | ((uint64_t)rs & 0xffffffff); 204 uint64_t tmp1 = tmp0; 205 for (i = 0; i <= 46; i++) { 206 int s; 207 if (i & 0x8) { 208 s = shift; 209 } else { 210 s = shiftx; 211 } 212 213 if (stripe != 0 && !(i & 0x4)) { 214 s = ~s; 215 } 216 if (s & 0x10) { 217 if (tmp0 & (1LL << (i + 16))) { 218 tmp1 |= 1LL << i; 219 } else { 220 tmp1 &= ~(1LL << i); 221 } 222 } 223 } 224 225 uint64_t tmp2 = tmp1; 226 for (i = 0; i <= 38; i++) { 227 int s; 228 if (i & 0x4) { 229 s = shift; 230 } else { 231 s = shiftx; 232 } 233 234 if (s & 0x8) { 235 if (tmp1 & (1LL << (i + 8))) { 236 tmp2 |= 1LL << i; 237 } else { 238 tmp2 &= ~(1LL << i); 239 } 240 } 241 } 242 243 uint64_t tmp3 = tmp2; 244 for (i = 0; i <= 34; i++) { 245 int s; 246 if (i & 0x2) { 247 s = shift; 248 } else { 249 s = shiftx; 250 } 251 if (s & 0x4) { 252 if (tmp2 & (1LL << (i + 4))) { 253 tmp3 |= 1LL << i; 254 } else { 255 tmp3 &= ~(1LL << i); 256 } 257 } 258 } 259 260 uint64_t tmp4 = tmp3; 261 for (i = 0; i <= 32; i++) { 262 int s; 263 if (i & 0x1) { 264 s = shift; 265 } else { 266 s = shiftx; 267 } 268 if (s & 0x2) { 269 if (tmp3 & (1LL << (i + 2))) { 270 tmp4 |= 1LL << i; 271 } else { 272 tmp4 &= ~(1LL << i); 273 } 274 } 275 } 276 277 uint64_t tmp5 = tmp4; 278 for (i = 0; i <= 31; i++) { 279 int s; 280 s = shift; 281 if (s & 0x1) { 282 if (tmp4 & (1LL << (i + 1))) { 283 tmp5 |= 1LL << i; 284 } else { 285 tmp5 &= ~(1LL << i); 286 } 287 } 288 } 289 290 return (int64_t)(int32_t)(uint32_t)tmp5; 291 } 292 293 #ifndef CONFIG_USER_ONLY 294 295 static inline hwaddr do_translate_address(CPUMIPSState *env, 296 target_ulong address, 297 int rw, uintptr_t retaddr) 298 { 299 hwaddr paddr; 300 CPUState *cs = env_cpu(env); 301 302 paddr = cpu_mips_translate_address(env, address, rw); 303 304 if (paddr == -1LL) { 305 cpu_loop_exit_restore(cs, retaddr); 306 } else { 307 return paddr; 308 } 309 } 310 311 #define HELPER_LD_ATOMIC(name, insn, almask, do_cast) \ 312 target_ulong helper_##name(CPUMIPSState *env, target_ulong arg, int mem_idx) \ 313 { \ 314 if (arg & almask) { \ 315 if (!(env->hflags & MIPS_HFLAG_DM)) { \ 316 env->CP0_BadVAddr = arg; \ 317 } \ 318 do_raise_exception(env, EXCP_AdEL, GETPC()); \ 319 } \ 320 env->CP0_LLAddr = do_translate_address(env, arg, 0, GETPC()); \ 321 env->lladdr = arg; \ 322 env->llval = do_cast cpu_##insn##_mmuidx_ra(env, arg, mem_idx, GETPC()); \ 323 return env->llval; \ 324 } 325 HELPER_LD_ATOMIC(ll, ldl, 0x3, (target_long)(int32_t)) 326 #ifdef TARGET_MIPS64 327 HELPER_LD_ATOMIC(lld, ldq, 0x7, (target_ulong)) 328 #endif 329 #undef HELPER_LD_ATOMIC 330 #endif 331 332 #ifdef TARGET_WORDS_BIGENDIAN 333 #define GET_LMASK(v) ((v) & 3) 334 #define GET_OFFSET(addr, offset) (addr + (offset)) 335 #else 336 #define GET_LMASK(v) (((v) & 3) ^ 3) 337 #define GET_OFFSET(addr, offset) (addr - (offset)) 338 #endif 339 340 void helper_swl(CPUMIPSState *env, target_ulong arg1, target_ulong arg2, 341 int mem_idx) 342 { 343 cpu_stb_mmuidx_ra(env, arg2, (uint8_t)(arg1 >> 24), mem_idx, GETPC()); 344 345 if (GET_LMASK(arg2) <= 2) { 346 cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, 1), (uint8_t)(arg1 >> 16), 347 mem_idx, GETPC()); 348 } 349 350 if (GET_LMASK(arg2) <= 1) { 351 cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, 2), (uint8_t)(arg1 >> 8), 352 mem_idx, GETPC()); 353 } 354 355 if (GET_LMASK(arg2) == 0) { 356 cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, 3), (uint8_t)arg1, 357 mem_idx, GETPC()); 358 } 359 } 360 361 void helper_swr(CPUMIPSState *env, target_ulong arg1, target_ulong arg2, 362 int mem_idx) 363 { 364 cpu_stb_mmuidx_ra(env, arg2, (uint8_t)arg1, mem_idx, GETPC()); 365 366 if (GET_LMASK(arg2) >= 1) { 367 cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, -1), (uint8_t)(arg1 >> 8), 368 mem_idx, GETPC()); 369 } 370 371 if (GET_LMASK(arg2) >= 2) { 372 cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, -2), (uint8_t)(arg1 >> 16), 373 mem_idx, GETPC()); 374 } 375 376 if (GET_LMASK(arg2) == 3) { 377 cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, -3), (uint8_t)(arg1 >> 24), 378 mem_idx, GETPC()); 379 } 380 } 381 382 #if defined(TARGET_MIPS64) 383 /* 384 * "half" load and stores. We must do the memory access inline, 385 * or fault handling won't work. 386 */ 387 #ifdef TARGET_WORDS_BIGENDIAN 388 #define GET_LMASK64(v) ((v) & 7) 389 #else 390 #define GET_LMASK64(v) (((v) & 7) ^ 7) 391 #endif 392 393 void helper_sdl(CPUMIPSState *env, target_ulong arg1, target_ulong arg2, 394 int mem_idx) 395 { 396 cpu_stb_mmuidx_ra(env, arg2, (uint8_t)(arg1 >> 56), mem_idx, GETPC()); 397 398 if (GET_LMASK64(arg2) <= 6) { 399 cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, 1), (uint8_t)(arg1 >> 48), 400 mem_idx, GETPC()); 401 } 402 403 if (GET_LMASK64(arg2) <= 5) { 404 cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, 2), (uint8_t)(arg1 >> 40), 405 mem_idx, GETPC()); 406 } 407 408 if (GET_LMASK64(arg2) <= 4) { 409 cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, 3), (uint8_t)(arg1 >> 32), 410 mem_idx, GETPC()); 411 } 412 413 if (GET_LMASK64(arg2) <= 3) { 414 cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, 4), (uint8_t)(arg1 >> 24), 415 mem_idx, GETPC()); 416 } 417 418 if (GET_LMASK64(arg2) <= 2) { 419 cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, 5), (uint8_t)(arg1 >> 16), 420 mem_idx, GETPC()); 421 } 422 423 if (GET_LMASK64(arg2) <= 1) { 424 cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, 6), (uint8_t)(arg1 >> 8), 425 mem_idx, GETPC()); 426 } 427 428 if (GET_LMASK64(arg2) <= 0) { 429 cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, 7), (uint8_t)arg1, 430 mem_idx, GETPC()); 431 } 432 } 433 434 void helper_sdr(CPUMIPSState *env, target_ulong arg1, target_ulong arg2, 435 int mem_idx) 436 { 437 cpu_stb_mmuidx_ra(env, arg2, (uint8_t)arg1, mem_idx, GETPC()); 438 439 if (GET_LMASK64(arg2) >= 1) { 440 cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, -1), (uint8_t)(arg1 >> 8), 441 mem_idx, GETPC()); 442 } 443 444 if (GET_LMASK64(arg2) >= 2) { 445 cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, -2), (uint8_t)(arg1 >> 16), 446 mem_idx, GETPC()); 447 } 448 449 if (GET_LMASK64(arg2) >= 3) { 450 cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, -3), (uint8_t)(arg1 >> 24), 451 mem_idx, GETPC()); 452 } 453 454 if (GET_LMASK64(arg2) >= 4) { 455 cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, -4), (uint8_t)(arg1 >> 32), 456 mem_idx, GETPC()); 457 } 458 459 if (GET_LMASK64(arg2) >= 5) { 460 cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, -5), (uint8_t)(arg1 >> 40), 461 mem_idx, GETPC()); 462 } 463 464 if (GET_LMASK64(arg2) >= 6) { 465 cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, -6), (uint8_t)(arg1 >> 48), 466 mem_idx, GETPC()); 467 } 468 469 if (GET_LMASK64(arg2) == 7) { 470 cpu_stb_mmuidx_ra(env, GET_OFFSET(arg2, -7), (uint8_t)(arg1 >> 56), 471 mem_idx, GETPC()); 472 } 473 } 474 #endif /* TARGET_MIPS64 */ 475 476 static const int multiple_regs[] = { 16, 17, 18, 19, 20, 21, 22, 23, 30 }; 477 478 void helper_lwm(CPUMIPSState *env, target_ulong addr, target_ulong reglist, 479 uint32_t mem_idx) 480 { 481 target_ulong base_reglist = reglist & 0xf; 482 target_ulong do_r31 = reglist & 0x10; 483 484 if (base_reglist > 0 && base_reglist <= ARRAY_SIZE(multiple_regs)) { 485 target_ulong i; 486 487 for (i = 0; i < base_reglist; i++) { 488 env->active_tc.gpr[multiple_regs[i]] = 489 (target_long)cpu_ldl_mmuidx_ra(env, addr, mem_idx, GETPC()); 490 addr += 4; 491 } 492 } 493 494 if (do_r31) { 495 env->active_tc.gpr[31] = 496 (target_long)cpu_ldl_mmuidx_ra(env, addr, mem_idx, GETPC()); 497 } 498 } 499 500 void helper_swm(CPUMIPSState *env, target_ulong addr, target_ulong reglist, 501 uint32_t mem_idx) 502 { 503 target_ulong base_reglist = reglist & 0xf; 504 target_ulong do_r31 = reglist & 0x10; 505 506 if (base_reglist > 0 && base_reglist <= ARRAY_SIZE(multiple_regs)) { 507 target_ulong i; 508 509 for (i = 0; i < base_reglist; i++) { 510 cpu_stw_mmuidx_ra(env, addr, env->active_tc.gpr[multiple_regs[i]], 511 mem_idx, GETPC()); 512 addr += 4; 513 } 514 } 515 516 if (do_r31) { 517 cpu_stw_mmuidx_ra(env, addr, env->active_tc.gpr[31], mem_idx, GETPC()); 518 } 519 } 520 521 #if defined(TARGET_MIPS64) 522 void helper_ldm(CPUMIPSState *env, target_ulong addr, target_ulong reglist, 523 uint32_t mem_idx) 524 { 525 target_ulong base_reglist = reglist & 0xf; 526 target_ulong do_r31 = reglist & 0x10; 527 528 if (base_reglist > 0 && base_reglist <= ARRAY_SIZE(multiple_regs)) { 529 target_ulong i; 530 531 for (i = 0; i < base_reglist; i++) { 532 env->active_tc.gpr[multiple_regs[i]] = 533 cpu_ldq_mmuidx_ra(env, addr, mem_idx, GETPC()); 534 addr += 8; 535 } 536 } 537 538 if (do_r31) { 539 env->active_tc.gpr[31] = 540 cpu_ldq_mmuidx_ra(env, addr, mem_idx, GETPC()); 541 } 542 } 543 544 void helper_sdm(CPUMIPSState *env, target_ulong addr, target_ulong reglist, 545 uint32_t mem_idx) 546 { 547 target_ulong base_reglist = reglist & 0xf; 548 target_ulong do_r31 = reglist & 0x10; 549 550 if (base_reglist > 0 && base_reglist <= ARRAY_SIZE(multiple_regs)) { 551 target_ulong i; 552 553 for (i = 0; i < base_reglist; i++) { 554 cpu_stq_mmuidx_ra(env, addr, env->active_tc.gpr[multiple_regs[i]], 555 mem_idx, GETPC()); 556 addr += 8; 557 } 558 } 559 560 if (do_r31) { 561 cpu_stq_mmuidx_ra(env, addr, env->active_tc.gpr[31], mem_idx, GETPC()); 562 } 563 } 564 #endif 565 566 567 void helper_fork(target_ulong arg1, target_ulong arg2) 568 { 569 /* 570 * arg1 = rt, arg2 = rs 571 * TODO: store to TC register 572 */ 573 } 574 575 target_ulong helper_yield(CPUMIPSState *env, target_ulong arg) 576 { 577 target_long arg1 = arg; 578 579 if (arg1 < 0) { 580 /* No scheduling policy implemented. */ 581 if (arg1 != -2) { 582 if (env->CP0_VPEControl & (1 << CP0VPECo_YSI) && 583 env->active_tc.CP0_TCStatus & (1 << CP0TCSt_DT)) { 584 env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT); 585 env->CP0_VPEControl |= 4 << CP0VPECo_EXCPT; 586 do_raise_exception(env, EXCP_THREAD, GETPC()); 587 } 588 } 589 } else if (arg1 == 0) { 590 if (0) { 591 /* TODO: TC underflow */ 592 env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT); 593 do_raise_exception(env, EXCP_THREAD, GETPC()); 594 } else { 595 /* TODO: Deallocate TC */ 596 } 597 } else if (arg1 > 0) { 598 /* Yield qualifier inputs not implemented. */ 599 env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT); 600 env->CP0_VPEControl |= 2 << CP0VPECo_EXCPT; 601 do_raise_exception(env, EXCP_THREAD, GETPC()); 602 } 603 return env->CP0_YQMask; 604 } 605 606 #ifndef CONFIG_USER_ONLY 607 /* TLB management */ 608 static void r4k_mips_tlb_flush_extra(CPUMIPSState *env, int first) 609 { 610 /* Discard entries from env->tlb[first] onwards. */ 611 while (env->tlb->tlb_in_use > first) { 612 r4k_invalidate_tlb(env, --env->tlb->tlb_in_use, 0); 613 } 614 } 615 616 static inline uint64_t get_tlb_pfn_from_entrylo(uint64_t entrylo) 617 { 618 #if defined(TARGET_MIPS64) 619 return extract64(entrylo, 6, 54); 620 #else 621 return extract64(entrylo, 6, 24) | /* PFN */ 622 (extract64(entrylo, 32, 32) << 24); /* PFNX */ 623 #endif 624 } 625 626 static void r4k_fill_tlb(CPUMIPSState *env, int idx) 627 { 628 r4k_tlb_t *tlb; 629 uint64_t mask = env->CP0_PageMask >> (TARGET_PAGE_BITS + 1); 630 631 /* XXX: detect conflicting TLBs and raise a MCHECK exception when needed */ 632 tlb = &env->tlb->mmu.r4k.tlb[idx]; 633 if (env->CP0_EntryHi & (1 << CP0EnHi_EHINV)) { 634 tlb->EHINV = 1; 635 return; 636 } 637 tlb->EHINV = 0; 638 tlb->VPN = env->CP0_EntryHi & (TARGET_PAGE_MASK << 1); 639 #if defined(TARGET_MIPS64) 640 tlb->VPN &= env->SEGMask; 641 #endif 642 tlb->ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask; 643 tlb->MMID = env->CP0_MemoryMapID; 644 tlb->PageMask = env->CP0_PageMask; 645 tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1; 646 tlb->V0 = (env->CP0_EntryLo0 & 2) != 0; 647 tlb->D0 = (env->CP0_EntryLo0 & 4) != 0; 648 tlb->C0 = (env->CP0_EntryLo0 >> 3) & 0x7; 649 tlb->XI0 = (env->CP0_EntryLo0 >> CP0EnLo_XI) & 1; 650 tlb->RI0 = (env->CP0_EntryLo0 >> CP0EnLo_RI) & 1; 651 tlb->PFN[0] = (get_tlb_pfn_from_entrylo(env->CP0_EntryLo0) & ~mask) << 12; 652 tlb->V1 = (env->CP0_EntryLo1 & 2) != 0; 653 tlb->D1 = (env->CP0_EntryLo1 & 4) != 0; 654 tlb->C1 = (env->CP0_EntryLo1 >> 3) & 0x7; 655 tlb->XI1 = (env->CP0_EntryLo1 >> CP0EnLo_XI) & 1; 656 tlb->RI1 = (env->CP0_EntryLo1 >> CP0EnLo_RI) & 1; 657 tlb->PFN[1] = (get_tlb_pfn_from_entrylo(env->CP0_EntryLo1) & ~mask) << 12; 658 } 659 660 void r4k_helper_tlbinv(CPUMIPSState *env) 661 { 662 bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1); 663 uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask; 664 uint32_t MMID = env->CP0_MemoryMapID; 665 uint32_t tlb_mmid; 666 r4k_tlb_t *tlb; 667 int idx; 668 669 MMID = mi ? MMID : (uint32_t) ASID; 670 for (idx = 0; idx < env->tlb->nb_tlb; idx++) { 671 tlb = &env->tlb->mmu.r4k.tlb[idx]; 672 tlb_mmid = mi ? tlb->MMID : (uint32_t) tlb->ASID; 673 if (!tlb->G && tlb_mmid == MMID) { 674 tlb->EHINV = 1; 675 } 676 } 677 cpu_mips_tlb_flush(env); 678 } 679 680 void r4k_helper_tlbinvf(CPUMIPSState *env) 681 { 682 int idx; 683 684 for (idx = 0; idx < env->tlb->nb_tlb; idx++) { 685 env->tlb->mmu.r4k.tlb[idx].EHINV = 1; 686 } 687 cpu_mips_tlb_flush(env); 688 } 689 690 void r4k_helper_tlbwi(CPUMIPSState *env) 691 { 692 bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1); 693 target_ulong VPN; 694 uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask; 695 uint32_t MMID = env->CP0_MemoryMapID; 696 uint32_t tlb_mmid; 697 bool EHINV, G, V0, D0, V1, D1, XI0, XI1, RI0, RI1; 698 r4k_tlb_t *tlb; 699 int idx; 700 701 MMID = mi ? MMID : (uint32_t) ASID; 702 703 idx = (env->CP0_Index & ~0x80000000) % env->tlb->nb_tlb; 704 tlb = &env->tlb->mmu.r4k.tlb[idx]; 705 VPN = env->CP0_EntryHi & (TARGET_PAGE_MASK << 1); 706 #if defined(TARGET_MIPS64) 707 VPN &= env->SEGMask; 708 #endif 709 EHINV = (env->CP0_EntryHi & (1 << CP0EnHi_EHINV)) != 0; 710 G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1; 711 V0 = (env->CP0_EntryLo0 & 2) != 0; 712 D0 = (env->CP0_EntryLo0 & 4) != 0; 713 XI0 = (env->CP0_EntryLo0 >> CP0EnLo_XI) &1; 714 RI0 = (env->CP0_EntryLo0 >> CP0EnLo_RI) &1; 715 V1 = (env->CP0_EntryLo1 & 2) != 0; 716 D1 = (env->CP0_EntryLo1 & 4) != 0; 717 XI1 = (env->CP0_EntryLo1 >> CP0EnLo_XI) &1; 718 RI1 = (env->CP0_EntryLo1 >> CP0EnLo_RI) &1; 719 720 tlb_mmid = mi ? tlb->MMID : (uint32_t) tlb->ASID; 721 /* 722 * Discard cached TLB entries, unless tlbwi is just upgrading access 723 * permissions on the current entry. 724 */ 725 if (tlb->VPN != VPN || tlb_mmid != MMID || tlb->G != G || 726 (!tlb->EHINV && EHINV) || 727 (tlb->V0 && !V0) || (tlb->D0 && !D0) || 728 (!tlb->XI0 && XI0) || (!tlb->RI0 && RI0) || 729 (tlb->V1 && !V1) || (tlb->D1 && !D1) || 730 (!tlb->XI1 && XI1) || (!tlb->RI1 && RI1)) { 731 r4k_mips_tlb_flush_extra(env, env->tlb->nb_tlb); 732 } 733 734 r4k_invalidate_tlb(env, idx, 0); 735 r4k_fill_tlb(env, idx); 736 } 737 738 void r4k_helper_tlbwr(CPUMIPSState *env) 739 { 740 int r = cpu_mips_get_random(env); 741 742 r4k_invalidate_tlb(env, r, 1); 743 r4k_fill_tlb(env, r); 744 } 745 746 void r4k_helper_tlbp(CPUMIPSState *env) 747 { 748 bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1); 749 r4k_tlb_t *tlb; 750 target_ulong mask; 751 target_ulong tag; 752 target_ulong VPN; 753 uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask; 754 uint32_t MMID = env->CP0_MemoryMapID; 755 uint32_t tlb_mmid; 756 int i; 757 758 MMID = mi ? MMID : (uint32_t) ASID; 759 for (i = 0; i < env->tlb->nb_tlb; i++) { 760 tlb = &env->tlb->mmu.r4k.tlb[i]; 761 /* 1k pages are not supported. */ 762 mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1); 763 tag = env->CP0_EntryHi & ~mask; 764 VPN = tlb->VPN & ~mask; 765 #if defined(TARGET_MIPS64) 766 tag &= env->SEGMask; 767 #endif 768 tlb_mmid = mi ? tlb->MMID : (uint32_t) tlb->ASID; 769 /* Check ASID/MMID, virtual page number & size */ 770 if ((tlb->G == 1 || tlb_mmid == MMID) && VPN == tag && !tlb->EHINV) { 771 /* TLB match */ 772 env->CP0_Index = i; 773 break; 774 } 775 } 776 if (i == env->tlb->nb_tlb) { 777 /* No match. Discard any shadow entries, if any of them match. */ 778 for (i = env->tlb->nb_tlb; i < env->tlb->tlb_in_use; i++) { 779 tlb = &env->tlb->mmu.r4k.tlb[i]; 780 /* 1k pages are not supported. */ 781 mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1); 782 tag = env->CP0_EntryHi & ~mask; 783 VPN = tlb->VPN & ~mask; 784 #if defined(TARGET_MIPS64) 785 tag &= env->SEGMask; 786 #endif 787 tlb_mmid = mi ? tlb->MMID : (uint32_t) tlb->ASID; 788 /* Check ASID/MMID, virtual page number & size */ 789 if ((tlb->G == 1 || tlb_mmid == MMID) && VPN == tag) { 790 r4k_mips_tlb_flush_extra(env, i); 791 break; 792 } 793 } 794 795 env->CP0_Index |= 0x80000000; 796 } 797 } 798 799 static inline uint64_t get_entrylo_pfn_from_tlb(uint64_t tlb_pfn) 800 { 801 #if defined(TARGET_MIPS64) 802 return tlb_pfn << 6; 803 #else 804 return (extract64(tlb_pfn, 0, 24) << 6) | /* PFN */ 805 (extract64(tlb_pfn, 24, 32) << 32); /* PFNX */ 806 #endif 807 } 808 809 void r4k_helper_tlbr(CPUMIPSState *env) 810 { 811 bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1); 812 uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask; 813 uint32_t MMID = env->CP0_MemoryMapID; 814 uint32_t tlb_mmid; 815 r4k_tlb_t *tlb; 816 int idx; 817 818 MMID = mi ? MMID : (uint32_t) ASID; 819 idx = (env->CP0_Index & ~0x80000000) % env->tlb->nb_tlb; 820 tlb = &env->tlb->mmu.r4k.tlb[idx]; 821 822 tlb_mmid = mi ? tlb->MMID : (uint32_t) tlb->ASID; 823 /* If this will change the current ASID/MMID, flush qemu's TLB. */ 824 if (MMID != tlb_mmid) { 825 cpu_mips_tlb_flush(env); 826 } 827 828 r4k_mips_tlb_flush_extra(env, env->tlb->nb_tlb); 829 830 if (tlb->EHINV) { 831 env->CP0_EntryHi = 1 << CP0EnHi_EHINV; 832 env->CP0_PageMask = 0; 833 env->CP0_EntryLo0 = 0; 834 env->CP0_EntryLo1 = 0; 835 } else { 836 env->CP0_EntryHi = mi ? tlb->VPN : tlb->VPN | tlb->ASID; 837 env->CP0_MemoryMapID = tlb->MMID; 838 env->CP0_PageMask = tlb->PageMask; 839 env->CP0_EntryLo0 = tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2) | 840 ((uint64_t)tlb->RI0 << CP0EnLo_RI) | 841 ((uint64_t)tlb->XI0 << CP0EnLo_XI) | (tlb->C0 << 3) | 842 get_entrylo_pfn_from_tlb(tlb->PFN[0] >> 12); 843 env->CP0_EntryLo1 = tlb->G | (tlb->V1 << 1) | (tlb->D1 << 2) | 844 ((uint64_t)tlb->RI1 << CP0EnLo_RI) | 845 ((uint64_t)tlb->XI1 << CP0EnLo_XI) | (tlb->C1 << 3) | 846 get_entrylo_pfn_from_tlb(tlb->PFN[1] >> 12); 847 } 848 } 849 850 void helper_tlbwi(CPUMIPSState *env) 851 { 852 env->tlb->helper_tlbwi(env); 853 } 854 855 void helper_tlbwr(CPUMIPSState *env) 856 { 857 env->tlb->helper_tlbwr(env); 858 } 859 860 void helper_tlbp(CPUMIPSState *env) 861 { 862 env->tlb->helper_tlbp(env); 863 } 864 865 void helper_tlbr(CPUMIPSState *env) 866 { 867 env->tlb->helper_tlbr(env); 868 } 869 870 void helper_tlbinv(CPUMIPSState *env) 871 { 872 env->tlb->helper_tlbinv(env); 873 } 874 875 void helper_tlbinvf(CPUMIPSState *env) 876 { 877 env->tlb->helper_tlbinvf(env); 878 } 879 880 static void global_invalidate_tlb(CPUMIPSState *env, 881 uint32_t invMsgVPN2, 882 uint8_t invMsgR, 883 uint32_t invMsgMMid, 884 bool invAll, 885 bool invVAMMid, 886 bool invMMid, 887 bool invVA) 888 { 889 890 int idx; 891 r4k_tlb_t *tlb; 892 bool VAMatch; 893 bool MMidMatch; 894 895 for (idx = 0; idx < env->tlb->nb_tlb; idx++) { 896 tlb = &env->tlb->mmu.r4k.tlb[idx]; 897 VAMatch = 898 (((tlb->VPN & ~tlb->PageMask) == (invMsgVPN2 & ~tlb->PageMask)) 899 #ifdef TARGET_MIPS64 900 && 901 (extract64(env->CP0_EntryHi, 62, 2) == invMsgR) 902 #endif 903 ); 904 MMidMatch = tlb->MMID == invMsgMMid; 905 if ((invAll && (idx > env->CP0_Wired)) || 906 (VAMatch && invVAMMid && (tlb->G || MMidMatch)) || 907 (VAMatch && invVA) || 908 (MMidMatch && !(tlb->G) && invMMid)) { 909 tlb->EHINV = 1; 910 } 911 } 912 cpu_mips_tlb_flush(env); 913 } 914 915 void helper_ginvt(CPUMIPSState *env, target_ulong arg, uint32_t type) 916 { 917 bool invAll = type == 0; 918 bool invVA = type == 1; 919 bool invMMid = type == 2; 920 bool invVAMMid = type == 3; 921 uint32_t invMsgVPN2 = arg & (TARGET_PAGE_MASK << 1); 922 uint8_t invMsgR = 0; 923 uint32_t invMsgMMid = env->CP0_MemoryMapID; 924 CPUState *other_cs = first_cpu; 925 926 #ifdef TARGET_MIPS64 927 invMsgR = extract64(arg, 62, 2); 928 #endif 929 930 CPU_FOREACH(other_cs) { 931 MIPSCPU *other_cpu = MIPS_CPU(other_cs); 932 global_invalidate_tlb(&other_cpu->env, invMsgVPN2, invMsgR, invMsgMMid, 933 invAll, invVAMMid, invMMid, invVA); 934 } 935 } 936 937 /* Specials */ 938 target_ulong helper_di(CPUMIPSState *env) 939 { 940 target_ulong t0 = env->CP0_Status; 941 942 env->CP0_Status = t0 & ~(1 << CP0St_IE); 943 return t0; 944 } 945 946 target_ulong helper_ei(CPUMIPSState *env) 947 { 948 target_ulong t0 = env->CP0_Status; 949 950 env->CP0_Status = t0 | (1 << CP0St_IE); 951 return t0; 952 } 953 954 static void debug_pre_eret(CPUMIPSState *env) 955 { 956 if (qemu_loglevel_mask(CPU_LOG_EXEC)) { 957 qemu_log("ERET: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx, 958 env->active_tc.PC, env->CP0_EPC); 959 if (env->CP0_Status & (1 << CP0St_ERL)) { 960 qemu_log(" ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC); 961 } 962 if (env->hflags & MIPS_HFLAG_DM) { 963 qemu_log(" DEPC " TARGET_FMT_lx, env->CP0_DEPC); 964 } 965 qemu_log("\n"); 966 } 967 } 968 969 static void debug_post_eret(CPUMIPSState *env) 970 { 971 if (qemu_loglevel_mask(CPU_LOG_EXEC)) { 972 qemu_log(" => PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx, 973 env->active_tc.PC, env->CP0_EPC); 974 if (env->CP0_Status & (1 << CP0St_ERL)) { 975 qemu_log(" ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC); 976 } 977 if (env->hflags & MIPS_HFLAG_DM) { 978 qemu_log(" DEPC " TARGET_FMT_lx, env->CP0_DEPC); 979 } 980 switch (cpu_mmu_index(env, false)) { 981 case 3: 982 qemu_log(", ERL\n"); 983 break; 984 case MIPS_HFLAG_UM: 985 qemu_log(", UM\n"); 986 break; 987 case MIPS_HFLAG_SM: 988 qemu_log(", SM\n"); 989 break; 990 case MIPS_HFLAG_KM: 991 qemu_log("\n"); 992 break; 993 default: 994 cpu_abort(env_cpu(env), "Invalid MMU mode!\n"); 995 break; 996 } 997 } 998 } 999 1000 static void set_pc(CPUMIPSState *env, target_ulong error_pc) 1001 { 1002 env->active_tc.PC = error_pc & ~(target_ulong)1; 1003 if (error_pc & 1) { 1004 env->hflags |= MIPS_HFLAG_M16; 1005 } else { 1006 env->hflags &= ~(MIPS_HFLAG_M16); 1007 } 1008 } 1009 1010 static inline void exception_return(CPUMIPSState *env) 1011 { 1012 debug_pre_eret(env); 1013 if (env->CP0_Status & (1 << CP0St_ERL)) { 1014 set_pc(env, env->CP0_ErrorEPC); 1015 env->CP0_Status &= ~(1 << CP0St_ERL); 1016 } else { 1017 set_pc(env, env->CP0_EPC); 1018 env->CP0_Status &= ~(1 << CP0St_EXL); 1019 } 1020 compute_hflags(env); 1021 debug_post_eret(env); 1022 } 1023 1024 void helper_eret(CPUMIPSState *env) 1025 { 1026 exception_return(env); 1027 env->CP0_LLAddr = 1; 1028 env->lladdr = 1; 1029 } 1030 1031 void helper_eretnc(CPUMIPSState *env) 1032 { 1033 exception_return(env); 1034 } 1035 1036 void helper_deret(CPUMIPSState *env) 1037 { 1038 debug_pre_eret(env); 1039 1040 env->hflags &= ~MIPS_HFLAG_DM; 1041 compute_hflags(env); 1042 1043 set_pc(env, env->CP0_DEPC); 1044 1045 debug_post_eret(env); 1046 } 1047 #endif /* !CONFIG_USER_ONLY */ 1048 1049 static inline void check_hwrena(CPUMIPSState *env, int reg, uintptr_t pc) 1050 { 1051 if ((env->hflags & MIPS_HFLAG_CP0) || (env->CP0_HWREna & (1 << reg))) { 1052 return; 1053 } 1054 do_raise_exception(env, EXCP_RI, pc); 1055 } 1056 1057 target_ulong helper_rdhwr_cpunum(CPUMIPSState *env) 1058 { 1059 check_hwrena(env, 0, GETPC()); 1060 return env->CP0_EBase & 0x3ff; 1061 } 1062 1063 target_ulong helper_rdhwr_synci_step(CPUMIPSState *env) 1064 { 1065 check_hwrena(env, 1, GETPC()); 1066 return env->SYNCI_Step; 1067 } 1068 1069 target_ulong helper_rdhwr_cc(CPUMIPSState *env) 1070 { 1071 check_hwrena(env, 2, GETPC()); 1072 #ifdef CONFIG_USER_ONLY 1073 return env->CP0_Count; 1074 #else 1075 return (int32_t)cpu_mips_get_count(env); 1076 #endif 1077 } 1078 1079 target_ulong helper_rdhwr_ccres(CPUMIPSState *env) 1080 { 1081 check_hwrena(env, 3, GETPC()); 1082 return env->CCRes; 1083 } 1084 1085 target_ulong helper_rdhwr_performance(CPUMIPSState *env) 1086 { 1087 check_hwrena(env, 4, GETPC()); 1088 return env->CP0_Performance0; 1089 } 1090 1091 target_ulong helper_rdhwr_xnp(CPUMIPSState *env) 1092 { 1093 check_hwrena(env, 5, GETPC()); 1094 return (env->CP0_Config5 >> CP0C5_XNP) & 1; 1095 } 1096 1097 void helper_pmon(CPUMIPSState *env, int function) 1098 { 1099 function /= 2; 1100 switch (function) { 1101 case 2: /* TODO: char inbyte(int waitflag); */ 1102 if (env->active_tc.gpr[4] == 0) { 1103 env->active_tc.gpr[2] = -1; 1104 } 1105 /* Fall through */ 1106 case 11: /* TODO: char inbyte (void); */ 1107 env->active_tc.gpr[2] = -1; 1108 break; 1109 case 3: 1110 case 12: 1111 printf("%c", (char)(env->active_tc.gpr[4] & 0xFF)); 1112 break; 1113 case 17: 1114 break; 1115 case 158: 1116 { 1117 unsigned char *fmt = (void *)(uintptr_t)env->active_tc.gpr[4]; 1118 printf("%s", fmt); 1119 } 1120 break; 1121 } 1122 } 1123 1124 void helper_wait(CPUMIPSState *env) 1125 { 1126 CPUState *cs = env_cpu(env); 1127 1128 cs->halted = 1; 1129 cpu_reset_interrupt(cs, CPU_INTERRUPT_WAKE); 1130 /* 1131 * Last instruction in the block, PC was updated before 1132 * - no need to recover PC and icount. 1133 */ 1134 raise_exception(env, EXCP_HLT); 1135 } 1136 1137 #if !defined(CONFIG_USER_ONLY) 1138 1139 void mips_cpu_do_unaligned_access(CPUState *cs, vaddr addr, 1140 MMUAccessType access_type, 1141 int mmu_idx, uintptr_t retaddr) 1142 { 1143 MIPSCPU *cpu = MIPS_CPU(cs); 1144 CPUMIPSState *env = &cpu->env; 1145 int error_code = 0; 1146 int excp; 1147 1148 if (!(env->hflags & MIPS_HFLAG_DM)) { 1149 env->CP0_BadVAddr = addr; 1150 } 1151 1152 if (access_type == MMU_DATA_STORE) { 1153 excp = EXCP_AdES; 1154 } else { 1155 excp = EXCP_AdEL; 1156 if (access_type == MMU_INST_FETCH) { 1157 error_code |= EXCP_INST_NOTAVAIL; 1158 } 1159 } 1160 1161 do_raise_exception_err(env, excp, error_code, retaddr); 1162 } 1163 1164 void mips_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr, 1165 vaddr addr, unsigned size, 1166 MMUAccessType access_type, 1167 int mmu_idx, MemTxAttrs attrs, 1168 MemTxResult response, uintptr_t retaddr) 1169 { 1170 MIPSCPU *cpu = MIPS_CPU(cs); 1171 CPUMIPSState *env = &cpu->env; 1172 1173 if (access_type == MMU_INST_FETCH) { 1174 do_raise_exception(env, EXCP_IBE, retaddr); 1175 } else { 1176 do_raise_exception(env, EXCP_DBE, retaddr); 1177 } 1178 } 1179 #endif /* !CONFIG_USER_ONLY */ 1180 1181 /* Complex FPU operations which may need stack space. */ 1182 1183 #define FLOAT_TWO32 make_float32(1 << 30) 1184 #define FLOAT_TWO64 make_float64(1ULL << 62) 1185 1186 #define FP_TO_INT32_OVERFLOW 0x7fffffff 1187 #define FP_TO_INT64_OVERFLOW 0x7fffffffffffffffULL 1188 1189 /* convert MIPS rounding mode in FCR31 to IEEE library */ 1190 unsigned int ieee_rm[] = { 1191 float_round_nearest_even, 1192 float_round_to_zero, 1193 float_round_up, 1194 float_round_down 1195 }; 1196 1197 target_ulong helper_cfc1(CPUMIPSState *env, uint32_t reg) 1198 { 1199 target_ulong arg1 = 0; 1200 1201 switch (reg) { 1202 case 0: 1203 arg1 = (int32_t)env->active_fpu.fcr0; 1204 break; 1205 case 1: 1206 /* UFR Support - Read Status FR */ 1207 if (env->active_fpu.fcr0 & (1 << FCR0_UFRP)) { 1208 if (env->CP0_Config5 & (1 << CP0C5_UFR)) { 1209 arg1 = (int32_t) 1210 ((env->CP0_Status & (1 << CP0St_FR)) >> CP0St_FR); 1211 } else { 1212 do_raise_exception(env, EXCP_RI, GETPC()); 1213 } 1214 } 1215 break; 1216 case 5: 1217 /* FRE Support - read Config5.FRE bit */ 1218 if (env->active_fpu.fcr0 & (1 << FCR0_FREP)) { 1219 if (env->CP0_Config5 & (1 << CP0C5_UFE)) { 1220 arg1 = (env->CP0_Config5 >> CP0C5_FRE) & 1; 1221 } else { 1222 helper_raise_exception(env, EXCP_RI); 1223 } 1224 } 1225 break; 1226 case 25: 1227 arg1 = ((env->active_fpu.fcr31 >> 24) & 0xfe) | 1228 ((env->active_fpu.fcr31 >> 23) & 0x1); 1229 break; 1230 case 26: 1231 arg1 = env->active_fpu.fcr31 & 0x0003f07c; 1232 break; 1233 case 28: 1234 arg1 = (env->active_fpu.fcr31 & 0x00000f83) | 1235 ((env->active_fpu.fcr31 >> 22) & 0x4); 1236 break; 1237 default: 1238 arg1 = (int32_t)env->active_fpu.fcr31; 1239 break; 1240 } 1241 1242 return arg1; 1243 } 1244 1245 void helper_ctc1(CPUMIPSState *env, target_ulong arg1, uint32_t fs, uint32_t rt) 1246 { 1247 switch (fs) { 1248 case 1: 1249 /* UFR Alias - Reset Status FR */ 1250 if (!((env->active_fpu.fcr0 & (1 << FCR0_UFRP)) && (rt == 0))) { 1251 return; 1252 } 1253 if (env->CP0_Config5 & (1 << CP0C5_UFR)) { 1254 env->CP0_Status &= ~(1 << CP0St_FR); 1255 compute_hflags(env); 1256 } else { 1257 do_raise_exception(env, EXCP_RI, GETPC()); 1258 } 1259 break; 1260 case 4: 1261 /* UNFR Alias - Set Status FR */ 1262 if (!((env->active_fpu.fcr0 & (1 << FCR0_UFRP)) && (rt == 0))) { 1263 return; 1264 } 1265 if (env->CP0_Config5 & (1 << CP0C5_UFR)) { 1266 env->CP0_Status |= (1 << CP0St_FR); 1267 compute_hflags(env); 1268 } else { 1269 do_raise_exception(env, EXCP_RI, GETPC()); 1270 } 1271 break; 1272 case 5: 1273 /* FRE Support - clear Config5.FRE bit */ 1274 if (!((env->active_fpu.fcr0 & (1 << FCR0_FREP)) && (rt == 0))) { 1275 return; 1276 } 1277 if (env->CP0_Config5 & (1 << CP0C5_UFE)) { 1278 env->CP0_Config5 &= ~(1 << CP0C5_FRE); 1279 compute_hflags(env); 1280 } else { 1281 helper_raise_exception(env, EXCP_RI); 1282 } 1283 break; 1284 case 6: 1285 /* FRE Support - set Config5.FRE bit */ 1286 if (!((env->active_fpu.fcr0 & (1 << FCR0_FREP)) && (rt == 0))) { 1287 return; 1288 } 1289 if (env->CP0_Config5 & (1 << CP0C5_UFE)) { 1290 env->CP0_Config5 |= (1 << CP0C5_FRE); 1291 compute_hflags(env); 1292 } else { 1293 helper_raise_exception(env, EXCP_RI); 1294 } 1295 break; 1296 case 25: 1297 if ((env->insn_flags & ISA_MIPS32R6) || (arg1 & 0xffffff00)) { 1298 return; 1299 } 1300 env->active_fpu.fcr31 = (env->active_fpu.fcr31 & 0x017fffff) | 1301 ((arg1 & 0xfe) << 24) | 1302 ((arg1 & 0x1) << 23); 1303 break; 1304 case 26: 1305 if (arg1 & 0x007c0000) { 1306 return; 1307 } 1308 env->active_fpu.fcr31 = (env->active_fpu.fcr31 & 0xfffc0f83) | 1309 (arg1 & 0x0003f07c); 1310 break; 1311 case 28: 1312 if (arg1 & 0x007c0000) { 1313 return; 1314 } 1315 env->active_fpu.fcr31 = (env->active_fpu.fcr31 & 0xfefff07c) | 1316 (arg1 & 0x00000f83) | 1317 ((arg1 & 0x4) << 22); 1318 break; 1319 case 31: 1320 env->active_fpu.fcr31 = (arg1 & env->active_fpu.fcr31_rw_bitmask) | 1321 (env->active_fpu.fcr31 & ~(env->active_fpu.fcr31_rw_bitmask)); 1322 break; 1323 default: 1324 if (env->insn_flags & ISA_MIPS32R6) { 1325 do_raise_exception(env, EXCP_RI, GETPC()); 1326 } 1327 return; 1328 } 1329 restore_fp_status(env); 1330 set_float_exception_flags(0, &env->active_fpu.fp_status); 1331 if ((GET_FP_ENABLE(env->active_fpu.fcr31) | 0x20) & 1332 GET_FP_CAUSE(env->active_fpu.fcr31)) { 1333 do_raise_exception(env, EXCP_FPE, GETPC()); 1334 } 1335 } 1336 1337 int ieee_ex_to_mips(int xcpt) 1338 { 1339 int ret = 0; 1340 if (xcpt) { 1341 if (xcpt & float_flag_invalid) { 1342 ret |= FP_INVALID; 1343 } 1344 if (xcpt & float_flag_overflow) { 1345 ret |= FP_OVERFLOW; 1346 } 1347 if (xcpt & float_flag_underflow) { 1348 ret |= FP_UNDERFLOW; 1349 } 1350 if (xcpt & float_flag_divbyzero) { 1351 ret |= FP_DIV0; 1352 } 1353 if (xcpt & float_flag_inexact) { 1354 ret |= FP_INEXACT; 1355 } 1356 } 1357 return ret; 1358 } 1359 1360 static inline void update_fcr31(CPUMIPSState *env, uintptr_t pc) 1361 { 1362 int tmp = ieee_ex_to_mips(get_float_exception_flags( 1363 &env->active_fpu.fp_status)); 1364 1365 SET_FP_CAUSE(env->active_fpu.fcr31, tmp); 1366 1367 if (tmp) { 1368 set_float_exception_flags(0, &env->active_fpu.fp_status); 1369 1370 if (GET_FP_ENABLE(env->active_fpu.fcr31) & tmp) { 1371 do_raise_exception(env, EXCP_FPE, pc); 1372 } else { 1373 UPDATE_FP_FLAGS(env->active_fpu.fcr31, tmp); 1374 } 1375 } 1376 } 1377 1378 /* 1379 * Float support. 1380 * Single precition routines have a "s" suffix, double precision a 1381 * "d" suffix, 32bit integer "w", 64bit integer "l", paired single "ps", 1382 * paired single lower "pl", paired single upper "pu". 1383 */ 1384 1385 /* unary operations, modifying fp status */ 1386 uint64_t helper_float_sqrt_d(CPUMIPSState *env, uint64_t fdt0) 1387 { 1388 fdt0 = float64_sqrt(fdt0, &env->active_fpu.fp_status); 1389 update_fcr31(env, GETPC()); 1390 return fdt0; 1391 } 1392 1393 uint32_t helper_float_sqrt_s(CPUMIPSState *env, uint32_t fst0) 1394 { 1395 fst0 = float32_sqrt(fst0, &env->active_fpu.fp_status); 1396 update_fcr31(env, GETPC()); 1397 return fst0; 1398 } 1399 1400 uint64_t helper_float_cvtd_s(CPUMIPSState *env, uint32_t fst0) 1401 { 1402 uint64_t fdt2; 1403 1404 fdt2 = float32_to_float64(fst0, &env->active_fpu.fp_status); 1405 update_fcr31(env, GETPC()); 1406 return fdt2; 1407 } 1408 1409 uint64_t helper_float_cvtd_w(CPUMIPSState *env, uint32_t wt0) 1410 { 1411 uint64_t fdt2; 1412 1413 fdt2 = int32_to_float64(wt0, &env->active_fpu.fp_status); 1414 update_fcr31(env, GETPC()); 1415 return fdt2; 1416 } 1417 1418 uint64_t helper_float_cvtd_l(CPUMIPSState *env, uint64_t dt0) 1419 { 1420 uint64_t fdt2; 1421 1422 fdt2 = int64_to_float64(dt0, &env->active_fpu.fp_status); 1423 update_fcr31(env, GETPC()); 1424 return fdt2; 1425 } 1426 1427 uint64_t helper_float_cvt_l_d(CPUMIPSState *env, uint64_t fdt0) 1428 { 1429 uint64_t dt2; 1430 1431 dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status); 1432 if (get_float_exception_flags(&env->active_fpu.fp_status) 1433 & (float_flag_invalid | float_flag_overflow)) { 1434 dt2 = FP_TO_INT64_OVERFLOW; 1435 } 1436 update_fcr31(env, GETPC()); 1437 return dt2; 1438 } 1439 1440 uint64_t helper_float_cvt_l_s(CPUMIPSState *env, uint32_t fst0) 1441 { 1442 uint64_t dt2; 1443 1444 dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status); 1445 if (get_float_exception_flags(&env->active_fpu.fp_status) 1446 & (float_flag_invalid | float_flag_overflow)) { 1447 dt2 = FP_TO_INT64_OVERFLOW; 1448 } 1449 update_fcr31(env, GETPC()); 1450 return dt2; 1451 } 1452 1453 uint64_t helper_float_cvtps_pw(CPUMIPSState *env, uint64_t dt0) 1454 { 1455 uint32_t fst2; 1456 uint32_t fsth2; 1457 1458 fst2 = int32_to_float32(dt0 & 0XFFFFFFFF, &env->active_fpu.fp_status); 1459 fsth2 = int32_to_float32(dt0 >> 32, &env->active_fpu.fp_status); 1460 update_fcr31(env, GETPC()); 1461 return ((uint64_t)fsth2 << 32) | fst2; 1462 } 1463 1464 uint64_t helper_float_cvtpw_ps(CPUMIPSState *env, uint64_t fdt0) 1465 { 1466 uint32_t wt2; 1467 uint32_t wth2; 1468 int excp, excph; 1469 1470 wt2 = float32_to_int32(fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status); 1471 excp = get_float_exception_flags(&env->active_fpu.fp_status); 1472 if (excp & (float_flag_overflow | float_flag_invalid)) { 1473 wt2 = FP_TO_INT32_OVERFLOW; 1474 } 1475 1476 set_float_exception_flags(0, &env->active_fpu.fp_status); 1477 wth2 = float32_to_int32(fdt0 >> 32, &env->active_fpu.fp_status); 1478 excph = get_float_exception_flags(&env->active_fpu.fp_status); 1479 if (excph & (float_flag_overflow | float_flag_invalid)) { 1480 wth2 = FP_TO_INT32_OVERFLOW; 1481 } 1482 1483 set_float_exception_flags(excp | excph, &env->active_fpu.fp_status); 1484 update_fcr31(env, GETPC()); 1485 1486 return ((uint64_t)wth2 << 32) | wt2; 1487 } 1488 1489 uint32_t helper_float_cvts_d(CPUMIPSState *env, uint64_t fdt0) 1490 { 1491 uint32_t fst2; 1492 1493 fst2 = float64_to_float32(fdt0, &env->active_fpu.fp_status); 1494 update_fcr31(env, GETPC()); 1495 return fst2; 1496 } 1497 1498 uint32_t helper_float_cvts_w(CPUMIPSState *env, uint32_t wt0) 1499 { 1500 uint32_t fst2; 1501 1502 fst2 = int32_to_float32(wt0, &env->active_fpu.fp_status); 1503 update_fcr31(env, GETPC()); 1504 return fst2; 1505 } 1506 1507 uint32_t helper_float_cvts_l(CPUMIPSState *env, uint64_t dt0) 1508 { 1509 uint32_t fst2; 1510 1511 fst2 = int64_to_float32(dt0, &env->active_fpu.fp_status); 1512 update_fcr31(env, GETPC()); 1513 return fst2; 1514 } 1515 1516 uint32_t helper_float_cvts_pl(CPUMIPSState *env, uint32_t wt0) 1517 { 1518 uint32_t wt2; 1519 1520 wt2 = wt0; 1521 update_fcr31(env, GETPC()); 1522 return wt2; 1523 } 1524 1525 uint32_t helper_float_cvts_pu(CPUMIPSState *env, uint32_t wth0) 1526 { 1527 uint32_t wt2; 1528 1529 wt2 = wth0; 1530 update_fcr31(env, GETPC()); 1531 return wt2; 1532 } 1533 1534 uint32_t helper_float_cvt_w_s(CPUMIPSState *env, uint32_t fst0) 1535 { 1536 uint32_t wt2; 1537 1538 wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status); 1539 if (get_float_exception_flags(&env->active_fpu.fp_status) 1540 & (float_flag_invalid | float_flag_overflow)) { 1541 wt2 = FP_TO_INT32_OVERFLOW; 1542 } 1543 update_fcr31(env, GETPC()); 1544 return wt2; 1545 } 1546 1547 uint32_t helper_float_cvt_w_d(CPUMIPSState *env, uint64_t fdt0) 1548 { 1549 uint32_t wt2; 1550 1551 wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status); 1552 if (get_float_exception_flags(&env->active_fpu.fp_status) 1553 & (float_flag_invalid | float_flag_overflow)) { 1554 wt2 = FP_TO_INT32_OVERFLOW; 1555 } 1556 update_fcr31(env, GETPC()); 1557 return wt2; 1558 } 1559 1560 uint64_t helper_float_round_l_d(CPUMIPSState *env, uint64_t fdt0) 1561 { 1562 uint64_t dt2; 1563 1564 set_float_rounding_mode(float_round_nearest_even, 1565 &env->active_fpu.fp_status); 1566 dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status); 1567 restore_rounding_mode(env); 1568 if (get_float_exception_flags(&env->active_fpu.fp_status) 1569 & (float_flag_invalid | float_flag_overflow)) { 1570 dt2 = FP_TO_INT64_OVERFLOW; 1571 } 1572 update_fcr31(env, GETPC()); 1573 return dt2; 1574 } 1575 1576 uint64_t helper_float_round_l_s(CPUMIPSState *env, uint32_t fst0) 1577 { 1578 uint64_t dt2; 1579 1580 set_float_rounding_mode(float_round_nearest_even, 1581 &env->active_fpu.fp_status); 1582 dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status); 1583 restore_rounding_mode(env); 1584 if (get_float_exception_flags(&env->active_fpu.fp_status) 1585 & (float_flag_invalid | float_flag_overflow)) { 1586 dt2 = FP_TO_INT64_OVERFLOW; 1587 } 1588 update_fcr31(env, GETPC()); 1589 return dt2; 1590 } 1591 1592 uint32_t helper_float_round_w_d(CPUMIPSState *env, uint64_t fdt0) 1593 { 1594 uint32_t wt2; 1595 1596 set_float_rounding_mode(float_round_nearest_even, 1597 &env->active_fpu.fp_status); 1598 wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status); 1599 restore_rounding_mode(env); 1600 if (get_float_exception_flags(&env->active_fpu.fp_status) 1601 & (float_flag_invalid | float_flag_overflow)) { 1602 wt2 = FP_TO_INT32_OVERFLOW; 1603 } 1604 update_fcr31(env, GETPC()); 1605 return wt2; 1606 } 1607 1608 uint32_t helper_float_round_w_s(CPUMIPSState *env, uint32_t fst0) 1609 { 1610 uint32_t wt2; 1611 1612 set_float_rounding_mode(float_round_nearest_even, 1613 &env->active_fpu.fp_status); 1614 wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status); 1615 restore_rounding_mode(env); 1616 if (get_float_exception_flags(&env->active_fpu.fp_status) 1617 & (float_flag_invalid | float_flag_overflow)) { 1618 wt2 = FP_TO_INT32_OVERFLOW; 1619 } 1620 update_fcr31(env, GETPC()); 1621 return wt2; 1622 } 1623 1624 uint64_t helper_float_trunc_l_d(CPUMIPSState *env, uint64_t fdt0) 1625 { 1626 uint64_t dt2; 1627 1628 dt2 = float64_to_int64_round_to_zero(fdt0, 1629 &env->active_fpu.fp_status); 1630 if (get_float_exception_flags(&env->active_fpu.fp_status) 1631 & (float_flag_invalid | float_flag_overflow)) { 1632 dt2 = FP_TO_INT64_OVERFLOW; 1633 } 1634 update_fcr31(env, GETPC()); 1635 return dt2; 1636 } 1637 1638 uint64_t helper_float_trunc_l_s(CPUMIPSState *env, uint32_t fst0) 1639 { 1640 uint64_t dt2; 1641 1642 dt2 = float32_to_int64_round_to_zero(fst0, &env->active_fpu.fp_status); 1643 if (get_float_exception_flags(&env->active_fpu.fp_status) 1644 & (float_flag_invalid | float_flag_overflow)) { 1645 dt2 = FP_TO_INT64_OVERFLOW; 1646 } 1647 update_fcr31(env, GETPC()); 1648 return dt2; 1649 } 1650 1651 uint32_t helper_float_trunc_w_d(CPUMIPSState *env, uint64_t fdt0) 1652 { 1653 uint32_t wt2; 1654 1655 wt2 = float64_to_int32_round_to_zero(fdt0, &env->active_fpu.fp_status); 1656 if (get_float_exception_flags(&env->active_fpu.fp_status) 1657 & (float_flag_invalid | float_flag_overflow)) { 1658 wt2 = FP_TO_INT32_OVERFLOW; 1659 } 1660 update_fcr31(env, GETPC()); 1661 return wt2; 1662 } 1663 1664 uint32_t helper_float_trunc_w_s(CPUMIPSState *env, uint32_t fst0) 1665 { 1666 uint32_t wt2; 1667 1668 wt2 = float32_to_int32_round_to_zero(fst0, &env->active_fpu.fp_status); 1669 if (get_float_exception_flags(&env->active_fpu.fp_status) 1670 & (float_flag_invalid | float_flag_overflow)) { 1671 wt2 = FP_TO_INT32_OVERFLOW; 1672 } 1673 update_fcr31(env, GETPC()); 1674 return wt2; 1675 } 1676 1677 uint64_t helper_float_ceil_l_d(CPUMIPSState *env, uint64_t fdt0) 1678 { 1679 uint64_t dt2; 1680 1681 set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status); 1682 dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status); 1683 restore_rounding_mode(env); 1684 if (get_float_exception_flags(&env->active_fpu.fp_status) 1685 & (float_flag_invalid | float_flag_overflow)) { 1686 dt2 = FP_TO_INT64_OVERFLOW; 1687 } 1688 update_fcr31(env, GETPC()); 1689 return dt2; 1690 } 1691 1692 uint64_t helper_float_ceil_l_s(CPUMIPSState *env, uint32_t fst0) 1693 { 1694 uint64_t dt2; 1695 1696 set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status); 1697 dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status); 1698 restore_rounding_mode(env); 1699 if (get_float_exception_flags(&env->active_fpu.fp_status) 1700 & (float_flag_invalid | float_flag_overflow)) { 1701 dt2 = FP_TO_INT64_OVERFLOW; 1702 } 1703 update_fcr31(env, GETPC()); 1704 return dt2; 1705 } 1706 1707 uint32_t helper_float_ceil_w_d(CPUMIPSState *env, uint64_t fdt0) 1708 { 1709 uint32_t wt2; 1710 1711 set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status); 1712 wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status); 1713 restore_rounding_mode(env); 1714 if (get_float_exception_flags(&env->active_fpu.fp_status) 1715 & (float_flag_invalid | float_flag_overflow)) { 1716 wt2 = FP_TO_INT32_OVERFLOW; 1717 } 1718 update_fcr31(env, GETPC()); 1719 return wt2; 1720 } 1721 1722 uint32_t helper_float_ceil_w_s(CPUMIPSState *env, uint32_t fst0) 1723 { 1724 uint32_t wt2; 1725 1726 set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status); 1727 wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status); 1728 restore_rounding_mode(env); 1729 if (get_float_exception_flags(&env->active_fpu.fp_status) 1730 & (float_flag_invalid | float_flag_overflow)) { 1731 wt2 = FP_TO_INT32_OVERFLOW; 1732 } 1733 update_fcr31(env, GETPC()); 1734 return wt2; 1735 } 1736 1737 uint64_t helper_float_floor_l_d(CPUMIPSState *env, uint64_t fdt0) 1738 { 1739 uint64_t dt2; 1740 1741 set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status); 1742 dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status); 1743 restore_rounding_mode(env); 1744 if (get_float_exception_flags(&env->active_fpu.fp_status) 1745 & (float_flag_invalid | float_flag_overflow)) { 1746 dt2 = FP_TO_INT64_OVERFLOW; 1747 } 1748 update_fcr31(env, GETPC()); 1749 return dt2; 1750 } 1751 1752 uint64_t helper_float_floor_l_s(CPUMIPSState *env, uint32_t fst0) 1753 { 1754 uint64_t dt2; 1755 1756 set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status); 1757 dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status); 1758 restore_rounding_mode(env); 1759 if (get_float_exception_flags(&env->active_fpu.fp_status) 1760 & (float_flag_invalid | float_flag_overflow)) { 1761 dt2 = FP_TO_INT64_OVERFLOW; 1762 } 1763 update_fcr31(env, GETPC()); 1764 return dt2; 1765 } 1766 1767 uint32_t helper_float_floor_w_d(CPUMIPSState *env, uint64_t fdt0) 1768 { 1769 uint32_t wt2; 1770 1771 set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status); 1772 wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status); 1773 restore_rounding_mode(env); 1774 if (get_float_exception_flags(&env->active_fpu.fp_status) 1775 & (float_flag_invalid | float_flag_overflow)) { 1776 wt2 = FP_TO_INT32_OVERFLOW; 1777 } 1778 update_fcr31(env, GETPC()); 1779 return wt2; 1780 } 1781 1782 uint32_t helper_float_floor_w_s(CPUMIPSState *env, uint32_t fst0) 1783 { 1784 uint32_t wt2; 1785 1786 set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status); 1787 wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status); 1788 restore_rounding_mode(env); 1789 if (get_float_exception_flags(&env->active_fpu.fp_status) 1790 & (float_flag_invalid | float_flag_overflow)) { 1791 wt2 = FP_TO_INT32_OVERFLOW; 1792 } 1793 update_fcr31(env, GETPC()); 1794 return wt2; 1795 } 1796 1797 uint64_t helper_float_cvt_2008_l_d(CPUMIPSState *env, uint64_t fdt0) 1798 { 1799 uint64_t dt2; 1800 1801 dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status); 1802 if (get_float_exception_flags(&env->active_fpu.fp_status) 1803 & float_flag_invalid) { 1804 if (float64_is_any_nan(fdt0)) { 1805 dt2 = 0; 1806 } 1807 } 1808 update_fcr31(env, GETPC()); 1809 return dt2; 1810 } 1811 1812 uint64_t helper_float_cvt_2008_l_s(CPUMIPSState *env, uint32_t fst0) 1813 { 1814 uint64_t dt2; 1815 1816 dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status); 1817 if (get_float_exception_flags(&env->active_fpu.fp_status) 1818 & float_flag_invalid) { 1819 if (float32_is_any_nan(fst0)) { 1820 dt2 = 0; 1821 } 1822 } 1823 update_fcr31(env, GETPC()); 1824 return dt2; 1825 } 1826 1827 uint32_t helper_float_cvt_2008_w_d(CPUMIPSState *env, uint64_t fdt0) 1828 { 1829 uint32_t wt2; 1830 1831 wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status); 1832 if (get_float_exception_flags(&env->active_fpu.fp_status) 1833 & float_flag_invalid) { 1834 if (float64_is_any_nan(fdt0)) { 1835 wt2 = 0; 1836 } 1837 } 1838 update_fcr31(env, GETPC()); 1839 return wt2; 1840 } 1841 1842 uint32_t helper_float_cvt_2008_w_s(CPUMIPSState *env, uint32_t fst0) 1843 { 1844 uint32_t wt2; 1845 1846 wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status); 1847 if (get_float_exception_flags(&env->active_fpu.fp_status) 1848 & float_flag_invalid) { 1849 if (float32_is_any_nan(fst0)) { 1850 wt2 = 0; 1851 } 1852 } 1853 update_fcr31(env, GETPC()); 1854 return wt2; 1855 } 1856 1857 uint64_t helper_float_round_2008_l_d(CPUMIPSState *env, uint64_t fdt0) 1858 { 1859 uint64_t dt2; 1860 1861 set_float_rounding_mode(float_round_nearest_even, 1862 &env->active_fpu.fp_status); 1863 dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status); 1864 restore_rounding_mode(env); 1865 if (get_float_exception_flags(&env->active_fpu.fp_status) 1866 & float_flag_invalid) { 1867 if (float64_is_any_nan(fdt0)) { 1868 dt2 = 0; 1869 } 1870 } 1871 update_fcr31(env, GETPC()); 1872 return dt2; 1873 } 1874 1875 uint64_t helper_float_round_2008_l_s(CPUMIPSState *env, uint32_t fst0) 1876 { 1877 uint64_t dt2; 1878 1879 set_float_rounding_mode(float_round_nearest_even, 1880 &env->active_fpu.fp_status); 1881 dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status); 1882 restore_rounding_mode(env); 1883 if (get_float_exception_flags(&env->active_fpu.fp_status) 1884 & float_flag_invalid) { 1885 if (float32_is_any_nan(fst0)) { 1886 dt2 = 0; 1887 } 1888 } 1889 update_fcr31(env, GETPC()); 1890 return dt2; 1891 } 1892 1893 uint32_t helper_float_round_2008_w_d(CPUMIPSState *env, uint64_t fdt0) 1894 { 1895 uint32_t wt2; 1896 1897 set_float_rounding_mode(float_round_nearest_even, 1898 &env->active_fpu.fp_status); 1899 wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status); 1900 restore_rounding_mode(env); 1901 if (get_float_exception_flags(&env->active_fpu.fp_status) 1902 & float_flag_invalid) { 1903 if (float64_is_any_nan(fdt0)) { 1904 wt2 = 0; 1905 } 1906 } 1907 update_fcr31(env, GETPC()); 1908 return wt2; 1909 } 1910 1911 uint32_t helper_float_round_2008_w_s(CPUMIPSState *env, uint32_t fst0) 1912 { 1913 uint32_t wt2; 1914 1915 set_float_rounding_mode(float_round_nearest_even, 1916 &env->active_fpu.fp_status); 1917 wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status); 1918 restore_rounding_mode(env); 1919 if (get_float_exception_flags(&env->active_fpu.fp_status) 1920 & float_flag_invalid) { 1921 if (float32_is_any_nan(fst0)) { 1922 wt2 = 0; 1923 } 1924 } 1925 update_fcr31(env, GETPC()); 1926 return wt2; 1927 } 1928 1929 uint64_t helper_float_trunc_2008_l_d(CPUMIPSState *env, uint64_t fdt0) 1930 { 1931 uint64_t dt2; 1932 1933 dt2 = float64_to_int64_round_to_zero(fdt0, &env->active_fpu.fp_status); 1934 if (get_float_exception_flags(&env->active_fpu.fp_status) 1935 & float_flag_invalid) { 1936 if (float64_is_any_nan(fdt0)) { 1937 dt2 = 0; 1938 } 1939 } 1940 update_fcr31(env, GETPC()); 1941 return dt2; 1942 } 1943 1944 uint64_t helper_float_trunc_2008_l_s(CPUMIPSState *env, uint32_t fst0) 1945 { 1946 uint64_t dt2; 1947 1948 dt2 = float32_to_int64_round_to_zero(fst0, &env->active_fpu.fp_status); 1949 if (get_float_exception_flags(&env->active_fpu.fp_status) 1950 & float_flag_invalid) { 1951 if (float32_is_any_nan(fst0)) { 1952 dt2 = 0; 1953 } 1954 } 1955 update_fcr31(env, GETPC()); 1956 return dt2; 1957 } 1958 1959 uint32_t helper_float_trunc_2008_w_d(CPUMIPSState *env, uint64_t fdt0) 1960 { 1961 uint32_t wt2; 1962 1963 wt2 = float64_to_int32_round_to_zero(fdt0, &env->active_fpu.fp_status); 1964 if (get_float_exception_flags(&env->active_fpu.fp_status) 1965 & float_flag_invalid) { 1966 if (float64_is_any_nan(fdt0)) { 1967 wt2 = 0; 1968 } 1969 } 1970 update_fcr31(env, GETPC()); 1971 return wt2; 1972 } 1973 1974 uint32_t helper_float_trunc_2008_w_s(CPUMIPSState *env, uint32_t fst0) 1975 { 1976 uint32_t wt2; 1977 1978 wt2 = float32_to_int32_round_to_zero(fst0, &env->active_fpu.fp_status); 1979 if (get_float_exception_flags(&env->active_fpu.fp_status) 1980 & float_flag_invalid) { 1981 if (float32_is_any_nan(fst0)) { 1982 wt2 = 0; 1983 } 1984 } 1985 update_fcr31(env, GETPC()); 1986 return wt2; 1987 } 1988 1989 uint64_t helper_float_ceil_2008_l_d(CPUMIPSState *env, uint64_t fdt0) 1990 { 1991 uint64_t dt2; 1992 1993 set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status); 1994 dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status); 1995 restore_rounding_mode(env); 1996 if (get_float_exception_flags(&env->active_fpu.fp_status) 1997 & float_flag_invalid) { 1998 if (float64_is_any_nan(fdt0)) { 1999 dt2 = 0; 2000 } 2001 } 2002 update_fcr31(env, GETPC()); 2003 return dt2; 2004 } 2005 2006 uint64_t helper_float_ceil_2008_l_s(CPUMIPSState *env, uint32_t fst0) 2007 { 2008 uint64_t dt2; 2009 2010 set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status); 2011 dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status); 2012 restore_rounding_mode(env); 2013 if (get_float_exception_flags(&env->active_fpu.fp_status) 2014 & float_flag_invalid) { 2015 if (float32_is_any_nan(fst0)) { 2016 dt2 = 0; 2017 } 2018 } 2019 update_fcr31(env, GETPC()); 2020 return dt2; 2021 } 2022 2023 uint32_t helper_float_ceil_2008_w_d(CPUMIPSState *env, uint64_t fdt0) 2024 { 2025 uint32_t wt2; 2026 2027 set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status); 2028 wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status); 2029 restore_rounding_mode(env); 2030 if (get_float_exception_flags(&env->active_fpu.fp_status) 2031 & float_flag_invalid) { 2032 if (float64_is_any_nan(fdt0)) { 2033 wt2 = 0; 2034 } 2035 } 2036 update_fcr31(env, GETPC()); 2037 return wt2; 2038 } 2039 2040 uint32_t helper_float_ceil_2008_w_s(CPUMIPSState *env, uint32_t fst0) 2041 { 2042 uint32_t wt2; 2043 2044 set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status); 2045 wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status); 2046 restore_rounding_mode(env); 2047 if (get_float_exception_flags(&env->active_fpu.fp_status) 2048 & float_flag_invalid) { 2049 if (float32_is_any_nan(fst0)) { 2050 wt2 = 0; 2051 } 2052 } 2053 update_fcr31(env, GETPC()); 2054 return wt2; 2055 } 2056 2057 uint64_t helper_float_floor_2008_l_d(CPUMIPSState *env, uint64_t fdt0) 2058 { 2059 uint64_t dt2; 2060 2061 set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status); 2062 dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status); 2063 restore_rounding_mode(env); 2064 if (get_float_exception_flags(&env->active_fpu.fp_status) 2065 & float_flag_invalid) { 2066 if (float64_is_any_nan(fdt0)) { 2067 dt2 = 0; 2068 } 2069 } 2070 update_fcr31(env, GETPC()); 2071 return dt2; 2072 } 2073 2074 uint64_t helper_float_floor_2008_l_s(CPUMIPSState *env, uint32_t fst0) 2075 { 2076 uint64_t dt2; 2077 2078 set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status); 2079 dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status); 2080 restore_rounding_mode(env); 2081 if (get_float_exception_flags(&env->active_fpu.fp_status) 2082 & float_flag_invalid) { 2083 if (float32_is_any_nan(fst0)) { 2084 dt2 = 0; 2085 } 2086 } 2087 update_fcr31(env, GETPC()); 2088 return dt2; 2089 } 2090 2091 uint32_t helper_float_floor_2008_w_d(CPUMIPSState *env, uint64_t fdt0) 2092 { 2093 uint32_t wt2; 2094 2095 set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status); 2096 wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status); 2097 restore_rounding_mode(env); 2098 if (get_float_exception_flags(&env->active_fpu.fp_status) 2099 & float_flag_invalid) { 2100 if (float64_is_any_nan(fdt0)) { 2101 wt2 = 0; 2102 } 2103 } 2104 update_fcr31(env, GETPC()); 2105 return wt2; 2106 } 2107 2108 uint32_t helper_float_floor_2008_w_s(CPUMIPSState *env, uint32_t fst0) 2109 { 2110 uint32_t wt2; 2111 2112 set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status); 2113 wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status); 2114 restore_rounding_mode(env); 2115 if (get_float_exception_flags(&env->active_fpu.fp_status) 2116 & float_flag_invalid) { 2117 if (float32_is_any_nan(fst0)) { 2118 wt2 = 0; 2119 } 2120 } 2121 update_fcr31(env, GETPC()); 2122 return wt2; 2123 } 2124 2125 /* unary operations, not modifying fp status */ 2126 #define FLOAT_UNOP(name) \ 2127 uint64_t helper_float_ ## name ## _d(uint64_t fdt0) \ 2128 { \ 2129 return float64_ ## name(fdt0); \ 2130 } \ 2131 uint32_t helper_float_ ## name ## _s(uint32_t fst0) \ 2132 { \ 2133 return float32_ ## name(fst0); \ 2134 } \ 2135 uint64_t helper_float_ ## name ## _ps(uint64_t fdt0) \ 2136 { \ 2137 uint32_t wt0; \ 2138 uint32_t wth0; \ 2139 \ 2140 wt0 = float32_ ## name(fdt0 & 0XFFFFFFFF); \ 2141 wth0 = float32_ ## name(fdt0 >> 32); \ 2142 return ((uint64_t)wth0 << 32) | wt0; \ 2143 } 2144 FLOAT_UNOP(abs) 2145 FLOAT_UNOP(chs) 2146 #undef FLOAT_UNOP 2147 2148 /* MIPS specific unary operations */ 2149 uint64_t helper_float_recip_d(CPUMIPSState *env, uint64_t fdt0) 2150 { 2151 uint64_t fdt2; 2152 2153 fdt2 = float64_div(float64_one, fdt0, &env->active_fpu.fp_status); 2154 update_fcr31(env, GETPC()); 2155 return fdt2; 2156 } 2157 2158 uint32_t helper_float_recip_s(CPUMIPSState *env, uint32_t fst0) 2159 { 2160 uint32_t fst2; 2161 2162 fst2 = float32_div(float32_one, fst0, &env->active_fpu.fp_status); 2163 update_fcr31(env, GETPC()); 2164 return fst2; 2165 } 2166 2167 uint64_t helper_float_rsqrt_d(CPUMIPSState *env, uint64_t fdt0) 2168 { 2169 uint64_t fdt2; 2170 2171 fdt2 = float64_sqrt(fdt0, &env->active_fpu.fp_status); 2172 fdt2 = float64_div(float64_one, fdt2, &env->active_fpu.fp_status); 2173 update_fcr31(env, GETPC()); 2174 return fdt2; 2175 } 2176 2177 uint32_t helper_float_rsqrt_s(CPUMIPSState *env, uint32_t fst0) 2178 { 2179 uint32_t fst2; 2180 2181 fst2 = float32_sqrt(fst0, &env->active_fpu.fp_status); 2182 fst2 = float32_div(float32_one, fst2, &env->active_fpu.fp_status); 2183 update_fcr31(env, GETPC()); 2184 return fst2; 2185 } 2186 2187 uint64_t helper_float_recip1_d(CPUMIPSState *env, uint64_t fdt0) 2188 { 2189 uint64_t fdt2; 2190 2191 fdt2 = float64_div(float64_one, fdt0, &env->active_fpu.fp_status); 2192 update_fcr31(env, GETPC()); 2193 return fdt2; 2194 } 2195 2196 uint32_t helper_float_recip1_s(CPUMIPSState *env, uint32_t fst0) 2197 { 2198 uint32_t fst2; 2199 2200 fst2 = float32_div(float32_one, fst0, &env->active_fpu.fp_status); 2201 update_fcr31(env, GETPC()); 2202 return fst2; 2203 } 2204 2205 uint64_t helper_float_recip1_ps(CPUMIPSState *env, uint64_t fdt0) 2206 { 2207 uint32_t fst2; 2208 uint32_t fsth2; 2209 2210 fst2 = float32_div(float32_one, fdt0 & 0XFFFFFFFF, 2211 &env->active_fpu.fp_status); 2212 fsth2 = float32_div(float32_one, fdt0 >> 32, &env->active_fpu.fp_status); 2213 update_fcr31(env, GETPC()); 2214 return ((uint64_t)fsth2 << 32) | fst2; 2215 } 2216 2217 uint64_t helper_float_rsqrt1_d(CPUMIPSState *env, uint64_t fdt0) 2218 { 2219 uint64_t fdt2; 2220 2221 fdt2 = float64_sqrt(fdt0, &env->active_fpu.fp_status); 2222 fdt2 = float64_div(float64_one, fdt2, &env->active_fpu.fp_status); 2223 update_fcr31(env, GETPC()); 2224 return fdt2; 2225 } 2226 2227 uint32_t helper_float_rsqrt1_s(CPUMIPSState *env, uint32_t fst0) 2228 { 2229 uint32_t fst2; 2230 2231 fst2 = float32_sqrt(fst0, &env->active_fpu.fp_status); 2232 fst2 = float32_div(float32_one, fst2, &env->active_fpu.fp_status); 2233 update_fcr31(env, GETPC()); 2234 return fst2; 2235 } 2236 2237 uint64_t helper_float_rsqrt1_ps(CPUMIPSState *env, uint64_t fdt0) 2238 { 2239 uint32_t fst2; 2240 uint32_t fsth2; 2241 2242 fst2 = float32_sqrt(fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status); 2243 fsth2 = float32_sqrt(fdt0 >> 32, &env->active_fpu.fp_status); 2244 fst2 = float32_div(float32_one, fst2, &env->active_fpu.fp_status); 2245 fsth2 = float32_div(float32_one, fsth2, &env->active_fpu.fp_status); 2246 update_fcr31(env, GETPC()); 2247 return ((uint64_t)fsth2 << 32) | fst2; 2248 } 2249 2250 #define FLOAT_RINT(name, bits) \ 2251 uint ## bits ## _t helper_float_ ## name(CPUMIPSState *env, \ 2252 uint ## bits ## _t fs) \ 2253 { \ 2254 uint ## bits ## _t fdret; \ 2255 \ 2256 fdret = float ## bits ## _round_to_int(fs, &env->active_fpu.fp_status); \ 2257 update_fcr31(env, GETPC()); \ 2258 return fdret; \ 2259 } 2260 2261 FLOAT_RINT(rint_s, 32) 2262 FLOAT_RINT(rint_d, 64) 2263 #undef FLOAT_RINT 2264 2265 #define FLOAT_CLASS_SIGNALING_NAN 0x001 2266 #define FLOAT_CLASS_QUIET_NAN 0x002 2267 #define FLOAT_CLASS_NEGATIVE_INFINITY 0x004 2268 #define FLOAT_CLASS_NEGATIVE_NORMAL 0x008 2269 #define FLOAT_CLASS_NEGATIVE_SUBNORMAL 0x010 2270 #define FLOAT_CLASS_NEGATIVE_ZERO 0x020 2271 #define FLOAT_CLASS_POSITIVE_INFINITY 0x040 2272 #define FLOAT_CLASS_POSITIVE_NORMAL 0x080 2273 #define FLOAT_CLASS_POSITIVE_SUBNORMAL 0x100 2274 #define FLOAT_CLASS_POSITIVE_ZERO 0x200 2275 2276 #define FLOAT_CLASS(name, bits) \ 2277 uint ## bits ## _t float_ ## name(uint ## bits ## _t arg, \ 2278 float_status *status) \ 2279 { \ 2280 if (float ## bits ## _is_signaling_nan(arg, status)) { \ 2281 return FLOAT_CLASS_SIGNALING_NAN; \ 2282 } else if (float ## bits ## _is_quiet_nan(arg, status)) { \ 2283 return FLOAT_CLASS_QUIET_NAN; \ 2284 } else if (float ## bits ## _is_neg(arg)) { \ 2285 if (float ## bits ## _is_infinity(arg)) { \ 2286 return FLOAT_CLASS_NEGATIVE_INFINITY; \ 2287 } else if (float ## bits ## _is_zero(arg)) { \ 2288 return FLOAT_CLASS_NEGATIVE_ZERO; \ 2289 } else if (float ## bits ## _is_zero_or_denormal(arg)) { \ 2290 return FLOAT_CLASS_NEGATIVE_SUBNORMAL; \ 2291 } else { \ 2292 return FLOAT_CLASS_NEGATIVE_NORMAL; \ 2293 } \ 2294 } else { \ 2295 if (float ## bits ## _is_infinity(arg)) { \ 2296 return FLOAT_CLASS_POSITIVE_INFINITY; \ 2297 } else if (float ## bits ## _is_zero(arg)) { \ 2298 return FLOAT_CLASS_POSITIVE_ZERO; \ 2299 } else if (float ## bits ## _is_zero_or_denormal(arg)) { \ 2300 return FLOAT_CLASS_POSITIVE_SUBNORMAL; \ 2301 } else { \ 2302 return FLOAT_CLASS_POSITIVE_NORMAL; \ 2303 } \ 2304 } \ 2305 } \ 2306 \ 2307 uint ## bits ## _t helper_float_ ## name(CPUMIPSState *env, \ 2308 uint ## bits ## _t arg) \ 2309 { \ 2310 return float_ ## name(arg, &env->active_fpu.fp_status); \ 2311 } 2312 2313 FLOAT_CLASS(class_s, 32) 2314 FLOAT_CLASS(class_d, 64) 2315 #undef FLOAT_CLASS 2316 2317 /* binary operations */ 2318 #define FLOAT_BINOP(name) \ 2319 uint64_t helper_float_ ## name ## _d(CPUMIPSState *env, \ 2320 uint64_t fdt0, uint64_t fdt1) \ 2321 { \ 2322 uint64_t dt2; \ 2323 \ 2324 dt2 = float64_ ## name(fdt0, fdt1, &env->active_fpu.fp_status);\ 2325 update_fcr31(env, GETPC()); \ 2326 return dt2; \ 2327 } \ 2328 \ 2329 uint32_t helper_float_ ## name ## _s(CPUMIPSState *env, \ 2330 uint32_t fst0, uint32_t fst1) \ 2331 { \ 2332 uint32_t wt2; \ 2333 \ 2334 wt2 = float32_ ## name(fst0, fst1, &env->active_fpu.fp_status);\ 2335 update_fcr31(env, GETPC()); \ 2336 return wt2; \ 2337 } \ 2338 \ 2339 uint64_t helper_float_ ## name ## _ps(CPUMIPSState *env, \ 2340 uint64_t fdt0, \ 2341 uint64_t fdt1) \ 2342 { \ 2343 uint32_t fst0 = fdt0 & 0XFFFFFFFF; \ 2344 uint32_t fsth0 = fdt0 >> 32; \ 2345 uint32_t fst1 = fdt1 & 0XFFFFFFFF; \ 2346 uint32_t fsth1 = fdt1 >> 32; \ 2347 uint32_t wt2; \ 2348 uint32_t wth2; \ 2349 \ 2350 wt2 = float32_ ## name(fst0, fst1, &env->active_fpu.fp_status); \ 2351 wth2 = float32_ ## name(fsth0, fsth1, &env->active_fpu.fp_status); \ 2352 update_fcr31(env, GETPC()); \ 2353 return ((uint64_t)wth2 << 32) | wt2; \ 2354 } 2355 2356 FLOAT_BINOP(add) 2357 FLOAT_BINOP(sub) 2358 FLOAT_BINOP(mul) 2359 FLOAT_BINOP(div) 2360 #undef FLOAT_BINOP 2361 2362 /* MIPS specific binary operations */ 2363 uint64_t helper_float_recip2_d(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2) 2364 { 2365 fdt2 = float64_mul(fdt0, fdt2, &env->active_fpu.fp_status); 2366 fdt2 = float64_chs(float64_sub(fdt2, float64_one, 2367 &env->active_fpu.fp_status)); 2368 update_fcr31(env, GETPC()); 2369 return fdt2; 2370 } 2371 2372 uint32_t helper_float_recip2_s(CPUMIPSState *env, uint32_t fst0, uint32_t fst2) 2373 { 2374 fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status); 2375 fst2 = float32_chs(float32_sub(fst2, float32_one, 2376 &env->active_fpu.fp_status)); 2377 update_fcr31(env, GETPC()); 2378 return fst2; 2379 } 2380 2381 uint64_t helper_float_recip2_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2) 2382 { 2383 uint32_t fst0 = fdt0 & 0XFFFFFFFF; 2384 uint32_t fsth0 = fdt0 >> 32; 2385 uint32_t fst2 = fdt2 & 0XFFFFFFFF; 2386 uint32_t fsth2 = fdt2 >> 32; 2387 2388 fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status); 2389 fsth2 = float32_mul(fsth0, fsth2, &env->active_fpu.fp_status); 2390 fst2 = float32_chs(float32_sub(fst2, float32_one, 2391 &env->active_fpu.fp_status)); 2392 fsth2 = float32_chs(float32_sub(fsth2, float32_one, 2393 &env->active_fpu.fp_status)); 2394 update_fcr31(env, GETPC()); 2395 return ((uint64_t)fsth2 << 32) | fst2; 2396 } 2397 2398 uint64_t helper_float_rsqrt2_d(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2) 2399 { 2400 fdt2 = float64_mul(fdt0, fdt2, &env->active_fpu.fp_status); 2401 fdt2 = float64_sub(fdt2, float64_one, &env->active_fpu.fp_status); 2402 fdt2 = float64_chs(float64_div(fdt2, FLOAT_TWO64, 2403 &env->active_fpu.fp_status)); 2404 update_fcr31(env, GETPC()); 2405 return fdt2; 2406 } 2407 2408 uint32_t helper_float_rsqrt2_s(CPUMIPSState *env, uint32_t fst0, uint32_t fst2) 2409 { 2410 fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status); 2411 fst2 = float32_sub(fst2, float32_one, &env->active_fpu.fp_status); 2412 fst2 = float32_chs(float32_div(fst2, FLOAT_TWO32, 2413 &env->active_fpu.fp_status)); 2414 update_fcr31(env, GETPC()); 2415 return fst2; 2416 } 2417 2418 uint64_t helper_float_rsqrt2_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt2) 2419 { 2420 uint32_t fst0 = fdt0 & 0XFFFFFFFF; 2421 uint32_t fsth0 = fdt0 >> 32; 2422 uint32_t fst2 = fdt2 & 0XFFFFFFFF; 2423 uint32_t fsth2 = fdt2 >> 32; 2424 2425 fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status); 2426 fsth2 = float32_mul(fsth0, fsth2, &env->active_fpu.fp_status); 2427 fst2 = float32_sub(fst2, float32_one, &env->active_fpu.fp_status); 2428 fsth2 = float32_sub(fsth2, float32_one, &env->active_fpu.fp_status); 2429 fst2 = float32_chs(float32_div(fst2, FLOAT_TWO32, 2430 &env->active_fpu.fp_status)); 2431 fsth2 = float32_chs(float32_div(fsth2, FLOAT_TWO32, 2432 &env->active_fpu.fp_status)); 2433 update_fcr31(env, GETPC()); 2434 return ((uint64_t)fsth2 << 32) | fst2; 2435 } 2436 2437 uint64_t helper_float_addr_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt1) 2438 { 2439 uint32_t fst0 = fdt0 & 0XFFFFFFFF; 2440 uint32_t fsth0 = fdt0 >> 32; 2441 uint32_t fst1 = fdt1 & 0XFFFFFFFF; 2442 uint32_t fsth1 = fdt1 >> 32; 2443 uint32_t fst2; 2444 uint32_t fsth2; 2445 2446 fst2 = float32_add(fst0, fsth0, &env->active_fpu.fp_status); 2447 fsth2 = float32_add(fst1, fsth1, &env->active_fpu.fp_status); 2448 update_fcr31(env, GETPC()); 2449 return ((uint64_t)fsth2 << 32) | fst2; 2450 } 2451 2452 uint64_t helper_float_mulr_ps(CPUMIPSState *env, uint64_t fdt0, uint64_t fdt1) 2453 { 2454 uint32_t fst0 = fdt0 & 0XFFFFFFFF; 2455 uint32_t fsth0 = fdt0 >> 32; 2456 uint32_t fst1 = fdt1 & 0XFFFFFFFF; 2457 uint32_t fsth1 = fdt1 >> 32; 2458 uint32_t fst2; 2459 uint32_t fsth2; 2460 2461 fst2 = float32_mul(fst0, fsth0, &env->active_fpu.fp_status); 2462 fsth2 = float32_mul(fst1, fsth1, &env->active_fpu.fp_status); 2463 update_fcr31(env, GETPC()); 2464 return ((uint64_t)fsth2 << 32) | fst2; 2465 } 2466 2467 #define FLOAT_MINMAX(name, bits, minmaxfunc) \ 2468 uint ## bits ## _t helper_float_ ## name(CPUMIPSState *env, \ 2469 uint ## bits ## _t fs, \ 2470 uint ## bits ## _t ft) \ 2471 { \ 2472 uint ## bits ## _t fdret; \ 2473 \ 2474 fdret = float ## bits ## _ ## minmaxfunc(fs, ft, \ 2475 &env->active_fpu.fp_status); \ 2476 update_fcr31(env, GETPC()); \ 2477 return fdret; \ 2478 } 2479 2480 FLOAT_MINMAX(max_s, 32, maxnum) 2481 FLOAT_MINMAX(max_d, 64, maxnum) 2482 FLOAT_MINMAX(maxa_s, 32, maxnummag) 2483 FLOAT_MINMAX(maxa_d, 64, maxnummag) 2484 2485 FLOAT_MINMAX(min_s, 32, minnum) 2486 FLOAT_MINMAX(min_d, 64, minnum) 2487 FLOAT_MINMAX(mina_s, 32, minnummag) 2488 FLOAT_MINMAX(mina_d, 64, minnummag) 2489 #undef FLOAT_MINMAX 2490 2491 /* ternary operations */ 2492 #define UNFUSED_FMA(prefix, a, b, c, flags) \ 2493 { \ 2494 a = prefix##_mul(a, b, &env->active_fpu.fp_status); \ 2495 if ((flags) & float_muladd_negate_c) { \ 2496 a = prefix##_sub(a, c, &env->active_fpu.fp_status); \ 2497 } else { \ 2498 a = prefix##_add(a, c, &env->active_fpu.fp_status); \ 2499 } \ 2500 if ((flags) & float_muladd_negate_result) { \ 2501 a = prefix##_chs(a); \ 2502 } \ 2503 } 2504 2505 /* FMA based operations */ 2506 #define FLOAT_FMA(name, type) \ 2507 uint64_t helper_float_ ## name ## _d(CPUMIPSState *env, \ 2508 uint64_t fdt0, uint64_t fdt1, \ 2509 uint64_t fdt2) \ 2510 { \ 2511 UNFUSED_FMA(float64, fdt0, fdt1, fdt2, type); \ 2512 update_fcr31(env, GETPC()); \ 2513 return fdt0; \ 2514 } \ 2515 \ 2516 uint32_t helper_float_ ## name ## _s(CPUMIPSState *env, \ 2517 uint32_t fst0, uint32_t fst1, \ 2518 uint32_t fst2) \ 2519 { \ 2520 UNFUSED_FMA(float32, fst0, fst1, fst2, type); \ 2521 update_fcr31(env, GETPC()); \ 2522 return fst0; \ 2523 } \ 2524 \ 2525 uint64_t helper_float_ ## name ## _ps(CPUMIPSState *env, \ 2526 uint64_t fdt0, uint64_t fdt1, \ 2527 uint64_t fdt2) \ 2528 { \ 2529 uint32_t fst0 = fdt0 & 0XFFFFFFFF; \ 2530 uint32_t fsth0 = fdt0 >> 32; \ 2531 uint32_t fst1 = fdt1 & 0XFFFFFFFF; \ 2532 uint32_t fsth1 = fdt1 >> 32; \ 2533 uint32_t fst2 = fdt2 & 0XFFFFFFFF; \ 2534 uint32_t fsth2 = fdt2 >> 32; \ 2535 \ 2536 UNFUSED_FMA(float32, fst0, fst1, fst2, type); \ 2537 UNFUSED_FMA(float32, fsth0, fsth1, fsth2, type); \ 2538 update_fcr31(env, GETPC()); \ 2539 return ((uint64_t)fsth0 << 32) | fst0; \ 2540 } 2541 FLOAT_FMA(madd, 0) 2542 FLOAT_FMA(msub, float_muladd_negate_c) 2543 FLOAT_FMA(nmadd, float_muladd_negate_result) 2544 FLOAT_FMA(nmsub, float_muladd_negate_result | float_muladd_negate_c) 2545 #undef FLOAT_FMA 2546 2547 #define FLOAT_FMADDSUB(name, bits, muladd_arg) \ 2548 uint ## bits ## _t helper_float_ ## name(CPUMIPSState *env, \ 2549 uint ## bits ## _t fs, \ 2550 uint ## bits ## _t ft, \ 2551 uint ## bits ## _t fd) \ 2552 { \ 2553 uint ## bits ## _t fdret; \ 2554 \ 2555 fdret = float ## bits ## _muladd(fs, ft, fd, muladd_arg, \ 2556 &env->active_fpu.fp_status); \ 2557 update_fcr31(env, GETPC()); \ 2558 return fdret; \ 2559 } 2560 2561 FLOAT_FMADDSUB(maddf_s, 32, 0) 2562 FLOAT_FMADDSUB(maddf_d, 64, 0) 2563 FLOAT_FMADDSUB(msubf_s, 32, float_muladd_negate_product) 2564 FLOAT_FMADDSUB(msubf_d, 64, float_muladd_negate_product) 2565 #undef FLOAT_FMADDSUB 2566 2567 /* compare operations */ 2568 #define FOP_COND_D(op, cond) \ 2569 void helper_cmp_d_ ## op(CPUMIPSState *env, uint64_t fdt0, \ 2570 uint64_t fdt1, int cc) \ 2571 { \ 2572 int c; \ 2573 c = cond; \ 2574 update_fcr31(env, GETPC()); \ 2575 if (c) \ 2576 SET_FP_COND(cc, env->active_fpu); \ 2577 else \ 2578 CLEAR_FP_COND(cc, env->active_fpu); \ 2579 } \ 2580 void helper_cmpabs_d_ ## op(CPUMIPSState *env, uint64_t fdt0, \ 2581 uint64_t fdt1, int cc) \ 2582 { \ 2583 int c; \ 2584 fdt0 = float64_abs(fdt0); \ 2585 fdt1 = float64_abs(fdt1); \ 2586 c = cond; \ 2587 update_fcr31(env, GETPC()); \ 2588 if (c) \ 2589 SET_FP_COND(cc, env->active_fpu); \ 2590 else \ 2591 CLEAR_FP_COND(cc, env->active_fpu); \ 2592 } 2593 2594 /* 2595 * NOTE: the comma operator will make "cond" to eval to false, 2596 * but float64_unordered_quiet() is still called. 2597 */ 2598 FOP_COND_D(f, (float64_unordered_quiet(fdt1, fdt0, 2599 &env->active_fpu.fp_status), 0)) 2600 FOP_COND_D(un, float64_unordered_quiet(fdt1, fdt0, 2601 &env->active_fpu.fp_status)) 2602 FOP_COND_D(eq, float64_eq_quiet(fdt0, fdt1, 2603 &env->active_fpu.fp_status)) 2604 FOP_COND_D(ueq, float64_unordered_quiet(fdt1, fdt0, 2605 &env->active_fpu.fp_status) 2606 || float64_eq_quiet(fdt0, fdt1, 2607 &env->active_fpu.fp_status)) 2608 FOP_COND_D(olt, float64_lt_quiet(fdt0, fdt1, 2609 &env->active_fpu.fp_status)) 2610 FOP_COND_D(ult, float64_unordered_quiet(fdt1, fdt0, 2611 &env->active_fpu.fp_status) 2612 || float64_lt_quiet(fdt0, fdt1, 2613 &env->active_fpu.fp_status)) 2614 FOP_COND_D(ole, float64_le_quiet(fdt0, fdt1, 2615 &env->active_fpu.fp_status)) 2616 FOP_COND_D(ule, float64_unordered_quiet(fdt1, fdt0, 2617 &env->active_fpu.fp_status) 2618 || float64_le_quiet(fdt0, fdt1, 2619 &env->active_fpu.fp_status)) 2620 /* 2621 * NOTE: the comma operator will make "cond" to eval to false, 2622 * but float64_unordered() is still called. 2623 */ 2624 FOP_COND_D(sf, (float64_unordered(fdt1, fdt0, 2625 &env->active_fpu.fp_status), 0)) 2626 FOP_COND_D(ngle, float64_unordered(fdt1, fdt0, 2627 &env->active_fpu.fp_status)) 2628 FOP_COND_D(seq, float64_eq(fdt0, fdt1, 2629 &env->active_fpu.fp_status)) 2630 FOP_COND_D(ngl, float64_unordered(fdt1, fdt0, 2631 &env->active_fpu.fp_status) 2632 || float64_eq(fdt0, fdt1, 2633 &env->active_fpu.fp_status)) 2634 FOP_COND_D(lt, float64_lt(fdt0, fdt1, 2635 &env->active_fpu.fp_status)) 2636 FOP_COND_D(nge, float64_unordered(fdt1, fdt0, 2637 &env->active_fpu.fp_status) 2638 || float64_lt(fdt0, fdt1, 2639 &env->active_fpu.fp_status)) 2640 FOP_COND_D(le, float64_le(fdt0, fdt1, 2641 &env->active_fpu.fp_status)) 2642 FOP_COND_D(ngt, float64_unordered(fdt1, fdt0, 2643 &env->active_fpu.fp_status) 2644 || float64_le(fdt0, fdt1, 2645 &env->active_fpu.fp_status)) 2646 2647 #define FOP_COND_S(op, cond) \ 2648 void helper_cmp_s_ ## op(CPUMIPSState *env, uint32_t fst0, \ 2649 uint32_t fst1, int cc) \ 2650 { \ 2651 int c; \ 2652 c = cond; \ 2653 update_fcr31(env, GETPC()); \ 2654 if (c) \ 2655 SET_FP_COND(cc, env->active_fpu); \ 2656 else \ 2657 CLEAR_FP_COND(cc, env->active_fpu); \ 2658 } \ 2659 void helper_cmpabs_s_ ## op(CPUMIPSState *env, uint32_t fst0, \ 2660 uint32_t fst1, int cc) \ 2661 { \ 2662 int c; \ 2663 fst0 = float32_abs(fst0); \ 2664 fst1 = float32_abs(fst1); \ 2665 c = cond; \ 2666 update_fcr31(env, GETPC()); \ 2667 if (c) \ 2668 SET_FP_COND(cc, env->active_fpu); \ 2669 else \ 2670 CLEAR_FP_COND(cc, env->active_fpu); \ 2671 } 2672 2673 /* 2674 * NOTE: the comma operator will make "cond" to eval to false, 2675 * but float32_unordered_quiet() is still called. 2676 */ 2677 FOP_COND_S(f, (float32_unordered_quiet(fst1, fst0, 2678 &env->active_fpu.fp_status), 0)) 2679 FOP_COND_S(un, float32_unordered_quiet(fst1, fst0, 2680 &env->active_fpu.fp_status)) 2681 FOP_COND_S(eq, float32_eq_quiet(fst0, fst1, 2682 &env->active_fpu.fp_status)) 2683 FOP_COND_S(ueq, float32_unordered_quiet(fst1, fst0, 2684 &env->active_fpu.fp_status) 2685 || float32_eq_quiet(fst0, fst1, 2686 &env->active_fpu.fp_status)) 2687 FOP_COND_S(olt, float32_lt_quiet(fst0, fst1, 2688 &env->active_fpu.fp_status)) 2689 FOP_COND_S(ult, float32_unordered_quiet(fst1, fst0, 2690 &env->active_fpu.fp_status) 2691 || float32_lt_quiet(fst0, fst1, 2692 &env->active_fpu.fp_status)) 2693 FOP_COND_S(ole, float32_le_quiet(fst0, fst1, 2694 &env->active_fpu.fp_status)) 2695 FOP_COND_S(ule, float32_unordered_quiet(fst1, fst0, 2696 &env->active_fpu.fp_status) 2697 || float32_le_quiet(fst0, fst1, 2698 &env->active_fpu.fp_status)) 2699 /* 2700 * NOTE: the comma operator will make "cond" to eval to false, 2701 * but float32_unordered() is still called. 2702 */ 2703 FOP_COND_S(sf, (float32_unordered(fst1, fst0, 2704 &env->active_fpu.fp_status), 0)) 2705 FOP_COND_S(ngle, float32_unordered(fst1, fst0, 2706 &env->active_fpu.fp_status)) 2707 FOP_COND_S(seq, float32_eq(fst0, fst1, 2708 &env->active_fpu.fp_status)) 2709 FOP_COND_S(ngl, float32_unordered(fst1, fst0, 2710 &env->active_fpu.fp_status) 2711 || float32_eq(fst0, fst1, 2712 &env->active_fpu.fp_status)) 2713 FOP_COND_S(lt, float32_lt(fst0, fst1, 2714 &env->active_fpu.fp_status)) 2715 FOP_COND_S(nge, float32_unordered(fst1, fst0, 2716 &env->active_fpu.fp_status) 2717 || float32_lt(fst0, fst1, 2718 &env->active_fpu.fp_status)) 2719 FOP_COND_S(le, float32_le(fst0, fst1, 2720 &env->active_fpu.fp_status)) 2721 FOP_COND_S(ngt, float32_unordered(fst1, fst0, 2722 &env->active_fpu.fp_status) 2723 || float32_le(fst0, fst1, 2724 &env->active_fpu.fp_status)) 2725 2726 #define FOP_COND_PS(op, condl, condh) \ 2727 void helper_cmp_ps_ ## op(CPUMIPSState *env, uint64_t fdt0, \ 2728 uint64_t fdt1, int cc) \ 2729 { \ 2730 uint32_t fst0, fsth0, fst1, fsth1; \ 2731 int ch, cl; \ 2732 fst0 = fdt0 & 0XFFFFFFFF; \ 2733 fsth0 = fdt0 >> 32; \ 2734 fst1 = fdt1 & 0XFFFFFFFF; \ 2735 fsth1 = fdt1 >> 32; \ 2736 cl = condl; \ 2737 ch = condh; \ 2738 update_fcr31(env, GETPC()); \ 2739 if (cl) \ 2740 SET_FP_COND(cc, env->active_fpu); \ 2741 else \ 2742 CLEAR_FP_COND(cc, env->active_fpu); \ 2743 if (ch) \ 2744 SET_FP_COND(cc + 1, env->active_fpu); \ 2745 else \ 2746 CLEAR_FP_COND(cc + 1, env->active_fpu); \ 2747 } \ 2748 void helper_cmpabs_ps_ ## op(CPUMIPSState *env, uint64_t fdt0, \ 2749 uint64_t fdt1, int cc) \ 2750 { \ 2751 uint32_t fst0, fsth0, fst1, fsth1; \ 2752 int ch, cl; \ 2753 fst0 = float32_abs(fdt0 & 0XFFFFFFFF); \ 2754 fsth0 = float32_abs(fdt0 >> 32); \ 2755 fst1 = float32_abs(fdt1 & 0XFFFFFFFF); \ 2756 fsth1 = float32_abs(fdt1 >> 32); \ 2757 cl = condl; \ 2758 ch = condh; \ 2759 update_fcr31(env, GETPC()); \ 2760 if (cl) \ 2761 SET_FP_COND(cc, env->active_fpu); \ 2762 else \ 2763 CLEAR_FP_COND(cc, env->active_fpu); \ 2764 if (ch) \ 2765 SET_FP_COND(cc + 1, env->active_fpu); \ 2766 else \ 2767 CLEAR_FP_COND(cc + 1, env->active_fpu); \ 2768 } 2769 2770 /* 2771 * NOTE: the comma operator will make "cond" to eval to false, 2772 * but float32_unordered_quiet() is still called. 2773 */ 2774 FOP_COND_PS(f, (float32_unordered_quiet(fst1, fst0, 2775 &env->active_fpu.fp_status), 0), 2776 (float32_unordered_quiet(fsth1, fsth0, 2777 &env->active_fpu.fp_status), 0)) 2778 FOP_COND_PS(un, float32_unordered_quiet(fst1, fst0, 2779 &env->active_fpu.fp_status), 2780 float32_unordered_quiet(fsth1, fsth0, 2781 &env->active_fpu.fp_status)) 2782 FOP_COND_PS(eq, float32_eq_quiet(fst0, fst1, 2783 &env->active_fpu.fp_status), 2784 float32_eq_quiet(fsth0, fsth1, 2785 &env->active_fpu.fp_status)) 2786 FOP_COND_PS(ueq, float32_unordered_quiet(fst1, fst0, 2787 &env->active_fpu.fp_status) 2788 || float32_eq_quiet(fst0, fst1, 2789 &env->active_fpu.fp_status), 2790 float32_unordered_quiet(fsth1, fsth0, 2791 &env->active_fpu.fp_status) 2792 || float32_eq_quiet(fsth0, fsth1, 2793 &env->active_fpu.fp_status)) 2794 FOP_COND_PS(olt, float32_lt_quiet(fst0, fst1, 2795 &env->active_fpu.fp_status), 2796 float32_lt_quiet(fsth0, fsth1, 2797 &env->active_fpu.fp_status)) 2798 FOP_COND_PS(ult, float32_unordered_quiet(fst1, fst0, 2799 &env->active_fpu.fp_status) 2800 || float32_lt_quiet(fst0, fst1, 2801 &env->active_fpu.fp_status), 2802 float32_unordered_quiet(fsth1, fsth0, 2803 &env->active_fpu.fp_status) 2804 || float32_lt_quiet(fsth0, fsth1, 2805 &env->active_fpu.fp_status)) 2806 FOP_COND_PS(ole, float32_le_quiet(fst0, fst1, 2807 &env->active_fpu.fp_status), 2808 float32_le_quiet(fsth0, fsth1, 2809 &env->active_fpu.fp_status)) 2810 FOP_COND_PS(ule, float32_unordered_quiet(fst1, fst0, 2811 &env->active_fpu.fp_status) 2812 || float32_le_quiet(fst0, fst1, 2813 &env->active_fpu.fp_status), 2814 float32_unordered_quiet(fsth1, fsth0, 2815 &env->active_fpu.fp_status) 2816 || float32_le_quiet(fsth0, fsth1, 2817 &env->active_fpu.fp_status)) 2818 /* 2819 * NOTE: the comma operator will make "cond" to eval to false, 2820 * but float32_unordered() is still called. 2821 */ 2822 FOP_COND_PS(sf, (float32_unordered(fst1, fst0, 2823 &env->active_fpu.fp_status), 0), 2824 (float32_unordered(fsth1, fsth0, 2825 &env->active_fpu.fp_status), 0)) 2826 FOP_COND_PS(ngle, float32_unordered(fst1, fst0, 2827 &env->active_fpu.fp_status), 2828 float32_unordered(fsth1, fsth0, 2829 &env->active_fpu.fp_status)) 2830 FOP_COND_PS(seq, float32_eq(fst0, fst1, 2831 &env->active_fpu.fp_status), 2832 float32_eq(fsth0, fsth1, 2833 &env->active_fpu.fp_status)) 2834 FOP_COND_PS(ngl, float32_unordered(fst1, fst0, 2835 &env->active_fpu.fp_status) 2836 || float32_eq(fst0, fst1, 2837 &env->active_fpu.fp_status), 2838 float32_unordered(fsth1, fsth0, 2839 &env->active_fpu.fp_status) 2840 || float32_eq(fsth0, fsth1, 2841 &env->active_fpu.fp_status)) 2842 FOP_COND_PS(lt, float32_lt(fst0, fst1, 2843 &env->active_fpu.fp_status), 2844 float32_lt(fsth0, fsth1, 2845 &env->active_fpu.fp_status)) 2846 FOP_COND_PS(nge, float32_unordered(fst1, fst0, 2847 &env->active_fpu.fp_status) 2848 || float32_lt(fst0, fst1, 2849 &env->active_fpu.fp_status), 2850 float32_unordered(fsth1, fsth0, 2851 &env->active_fpu.fp_status) 2852 || float32_lt(fsth0, fsth1, 2853 &env->active_fpu.fp_status)) 2854 FOP_COND_PS(le, float32_le(fst0, fst1, 2855 &env->active_fpu.fp_status), 2856 float32_le(fsth0, fsth1, 2857 &env->active_fpu.fp_status)) 2858 FOP_COND_PS(ngt, float32_unordered(fst1, fst0, 2859 &env->active_fpu.fp_status) 2860 || float32_le(fst0, fst1, 2861 &env->active_fpu.fp_status), 2862 float32_unordered(fsth1, fsth0, 2863 &env->active_fpu.fp_status) 2864 || float32_le(fsth0, fsth1, 2865 &env->active_fpu.fp_status)) 2866 2867 /* R6 compare operations */ 2868 #define FOP_CONDN_D(op, cond) \ 2869 uint64_t helper_r6_cmp_d_ ## op(CPUMIPSState *env, uint64_t fdt0, \ 2870 uint64_t fdt1) \ 2871 { \ 2872 uint64_t c; \ 2873 c = cond; \ 2874 update_fcr31(env, GETPC()); \ 2875 if (c) { \ 2876 return -1; \ 2877 } else { \ 2878 return 0; \ 2879 } \ 2880 } 2881 2882 /* 2883 * NOTE: the comma operator will make "cond" to eval to false, 2884 * but float64_unordered_quiet() is still called. 2885 */ 2886 FOP_CONDN_D(af, (float64_unordered_quiet(fdt1, fdt0, 2887 &env->active_fpu.fp_status), 0)) 2888 FOP_CONDN_D(un, (float64_unordered_quiet(fdt1, fdt0, 2889 &env->active_fpu.fp_status))) 2890 FOP_CONDN_D(eq, (float64_eq_quiet(fdt0, fdt1, 2891 &env->active_fpu.fp_status))) 2892 FOP_CONDN_D(ueq, (float64_unordered_quiet(fdt1, fdt0, 2893 &env->active_fpu.fp_status) 2894 || float64_eq_quiet(fdt0, fdt1, 2895 &env->active_fpu.fp_status))) 2896 FOP_CONDN_D(lt, (float64_lt_quiet(fdt0, fdt1, 2897 &env->active_fpu.fp_status))) 2898 FOP_CONDN_D(ult, (float64_unordered_quiet(fdt1, fdt0, 2899 &env->active_fpu.fp_status) 2900 || float64_lt_quiet(fdt0, fdt1, 2901 &env->active_fpu.fp_status))) 2902 FOP_CONDN_D(le, (float64_le_quiet(fdt0, fdt1, 2903 &env->active_fpu.fp_status))) 2904 FOP_CONDN_D(ule, (float64_unordered_quiet(fdt1, fdt0, 2905 &env->active_fpu.fp_status) 2906 || float64_le_quiet(fdt0, fdt1, 2907 &env->active_fpu.fp_status))) 2908 /* 2909 * NOTE: the comma operator will make "cond" to eval to false, 2910 * but float64_unordered() is still called.\ 2911 */ 2912 FOP_CONDN_D(saf, (float64_unordered(fdt1, fdt0, 2913 &env->active_fpu.fp_status), 0)) 2914 FOP_CONDN_D(sun, (float64_unordered(fdt1, fdt0, 2915 &env->active_fpu.fp_status))) 2916 FOP_CONDN_D(seq, (float64_eq(fdt0, fdt1, 2917 &env->active_fpu.fp_status))) 2918 FOP_CONDN_D(sueq, (float64_unordered(fdt1, fdt0, 2919 &env->active_fpu.fp_status) 2920 || float64_eq(fdt0, fdt1, 2921 &env->active_fpu.fp_status))) 2922 FOP_CONDN_D(slt, (float64_lt(fdt0, fdt1, 2923 &env->active_fpu.fp_status))) 2924 FOP_CONDN_D(sult, (float64_unordered(fdt1, fdt0, 2925 &env->active_fpu.fp_status) 2926 || float64_lt(fdt0, fdt1, 2927 &env->active_fpu.fp_status))) 2928 FOP_CONDN_D(sle, (float64_le(fdt0, fdt1, 2929 &env->active_fpu.fp_status))) 2930 FOP_CONDN_D(sule, (float64_unordered(fdt1, fdt0, 2931 &env->active_fpu.fp_status) 2932 || float64_le(fdt0, fdt1, 2933 &env->active_fpu.fp_status))) 2934 FOP_CONDN_D(or, (float64_le_quiet(fdt1, fdt0, 2935 &env->active_fpu.fp_status) 2936 || float64_le_quiet(fdt0, fdt1, 2937 &env->active_fpu.fp_status))) 2938 FOP_CONDN_D(une, (float64_unordered_quiet(fdt1, fdt0, 2939 &env->active_fpu.fp_status) 2940 || float64_lt_quiet(fdt1, fdt0, 2941 &env->active_fpu.fp_status) 2942 || float64_lt_quiet(fdt0, fdt1, 2943 &env->active_fpu.fp_status))) 2944 FOP_CONDN_D(ne, (float64_lt_quiet(fdt1, fdt0, 2945 &env->active_fpu.fp_status) 2946 || float64_lt_quiet(fdt0, fdt1, 2947 &env->active_fpu.fp_status))) 2948 FOP_CONDN_D(sor, (float64_le(fdt1, fdt0, 2949 &env->active_fpu.fp_status) 2950 || float64_le(fdt0, fdt1, 2951 &env->active_fpu.fp_status))) 2952 FOP_CONDN_D(sune, (float64_unordered(fdt1, fdt0, 2953 &env->active_fpu.fp_status) 2954 || float64_lt(fdt1, fdt0, 2955 &env->active_fpu.fp_status) 2956 || float64_lt(fdt0, fdt1, 2957 &env->active_fpu.fp_status))) 2958 FOP_CONDN_D(sne, (float64_lt(fdt1, fdt0, 2959 &env->active_fpu.fp_status) 2960 || float64_lt(fdt0, fdt1, 2961 &env->active_fpu.fp_status))) 2962 2963 #define FOP_CONDN_S(op, cond) \ 2964 uint32_t helper_r6_cmp_s_ ## op(CPUMIPSState *env, uint32_t fst0, \ 2965 uint32_t fst1) \ 2966 { \ 2967 uint64_t c; \ 2968 c = cond; \ 2969 update_fcr31(env, GETPC()); \ 2970 if (c) { \ 2971 return -1; \ 2972 } else { \ 2973 return 0; \ 2974 } \ 2975 } 2976 2977 /* 2978 * NOTE: the comma operator will make "cond" to eval to false, 2979 * but float32_unordered_quiet() is still called. 2980 */ 2981 FOP_CONDN_S(af, (float32_unordered_quiet(fst1, fst0, 2982 &env->active_fpu.fp_status), 0)) 2983 FOP_CONDN_S(un, (float32_unordered_quiet(fst1, fst0, 2984 &env->active_fpu.fp_status))) 2985 FOP_CONDN_S(eq, (float32_eq_quiet(fst0, fst1, 2986 &env->active_fpu.fp_status))) 2987 FOP_CONDN_S(ueq, (float32_unordered_quiet(fst1, fst0, 2988 &env->active_fpu.fp_status) 2989 || float32_eq_quiet(fst0, fst1, 2990 &env->active_fpu.fp_status))) 2991 FOP_CONDN_S(lt, (float32_lt_quiet(fst0, fst1, 2992 &env->active_fpu.fp_status))) 2993 FOP_CONDN_S(ult, (float32_unordered_quiet(fst1, fst0, 2994 &env->active_fpu.fp_status) 2995 || float32_lt_quiet(fst0, fst1, 2996 &env->active_fpu.fp_status))) 2997 FOP_CONDN_S(le, (float32_le_quiet(fst0, fst1, 2998 &env->active_fpu.fp_status))) 2999 FOP_CONDN_S(ule, (float32_unordered_quiet(fst1, fst0, 3000 &env->active_fpu.fp_status) 3001 || float32_le_quiet(fst0, fst1, 3002 &env->active_fpu.fp_status))) 3003 /* 3004 * NOTE: the comma operator will make "cond" to eval to false, 3005 * but float32_unordered() is still called. 3006 */ 3007 FOP_CONDN_S(saf, (float32_unordered(fst1, fst0, 3008 &env->active_fpu.fp_status), 0)) 3009 FOP_CONDN_S(sun, (float32_unordered(fst1, fst0, 3010 &env->active_fpu.fp_status))) 3011 FOP_CONDN_S(seq, (float32_eq(fst0, fst1, 3012 &env->active_fpu.fp_status))) 3013 FOP_CONDN_S(sueq, (float32_unordered(fst1, fst0, 3014 &env->active_fpu.fp_status) 3015 || float32_eq(fst0, fst1, 3016 &env->active_fpu.fp_status))) 3017 FOP_CONDN_S(slt, (float32_lt(fst0, fst1, 3018 &env->active_fpu.fp_status))) 3019 FOP_CONDN_S(sult, (float32_unordered(fst1, fst0, 3020 &env->active_fpu.fp_status) 3021 || float32_lt(fst0, fst1, 3022 &env->active_fpu.fp_status))) 3023 FOP_CONDN_S(sle, (float32_le(fst0, fst1, 3024 &env->active_fpu.fp_status))) 3025 FOP_CONDN_S(sule, (float32_unordered(fst1, fst0, 3026 &env->active_fpu.fp_status) 3027 || float32_le(fst0, fst1, 3028 &env->active_fpu.fp_status))) 3029 FOP_CONDN_S(or, (float32_le_quiet(fst1, fst0, 3030 &env->active_fpu.fp_status) 3031 || float32_le_quiet(fst0, fst1, 3032 &env->active_fpu.fp_status))) 3033 FOP_CONDN_S(une, (float32_unordered_quiet(fst1, fst0, 3034 &env->active_fpu.fp_status) 3035 || float32_lt_quiet(fst1, fst0, 3036 &env->active_fpu.fp_status) 3037 || float32_lt_quiet(fst0, fst1, 3038 &env->active_fpu.fp_status))) 3039 FOP_CONDN_S(ne, (float32_lt_quiet(fst1, fst0, 3040 &env->active_fpu.fp_status) 3041 || float32_lt_quiet(fst0, fst1, 3042 &env->active_fpu.fp_status))) 3043 FOP_CONDN_S(sor, (float32_le(fst1, fst0, 3044 &env->active_fpu.fp_status) 3045 || float32_le(fst0, fst1, 3046 &env->active_fpu.fp_status))) 3047 FOP_CONDN_S(sune, (float32_unordered(fst1, fst0, 3048 &env->active_fpu.fp_status) 3049 || float32_lt(fst1, fst0, 3050 &env->active_fpu.fp_status) 3051 || float32_lt(fst0, fst1, 3052 &env->active_fpu.fp_status))) 3053 FOP_CONDN_S(sne, (float32_lt(fst1, fst0, 3054 &env->active_fpu.fp_status) 3055 || float32_lt(fst0, fst1, 3056 &env->active_fpu.fp_status))) 3057 3058 /* MSA */ 3059 /* Data format min and max values */ 3060 #define DF_BITS(df) (1 << ((df) + 3)) 3061 3062 /* Element-by-element access macros */ 3063 #define DF_ELEMENTS(df) (MSA_WRLEN / DF_BITS(df)) 3064 3065 #if !defined(CONFIG_USER_ONLY) 3066 #define MEMOP_IDX(DF) \ 3067 TCGMemOpIdx oi = make_memop_idx(MO_TE | DF | MO_UNALN, \ 3068 cpu_mmu_index(env, false)); 3069 #else 3070 #define MEMOP_IDX(DF) 3071 #endif 3072 3073 void helper_msa_ld_b(CPUMIPSState *env, uint32_t wd, 3074 target_ulong addr) 3075 { 3076 wr_t *pwd = &(env->active_fpu.fpr[wd].wr); 3077 MEMOP_IDX(DF_BYTE) 3078 #if !defined(CONFIG_USER_ONLY) 3079 #if !defined(HOST_WORDS_BIGENDIAN) 3080 pwd->b[0] = helper_ret_ldub_mmu(env, addr + (0 << DF_BYTE), oi, GETPC()); 3081 pwd->b[1] = helper_ret_ldub_mmu(env, addr + (1 << DF_BYTE), oi, GETPC()); 3082 pwd->b[2] = helper_ret_ldub_mmu(env, addr + (2 << DF_BYTE), oi, GETPC()); 3083 pwd->b[3] = helper_ret_ldub_mmu(env, addr + (3 << DF_BYTE), oi, GETPC()); 3084 pwd->b[4] = helper_ret_ldub_mmu(env, addr + (4 << DF_BYTE), oi, GETPC()); 3085 pwd->b[5] = helper_ret_ldub_mmu(env, addr + (5 << DF_BYTE), oi, GETPC()); 3086 pwd->b[6] = helper_ret_ldub_mmu(env, addr + (6 << DF_BYTE), oi, GETPC()); 3087 pwd->b[7] = helper_ret_ldub_mmu(env, addr + (7 << DF_BYTE), oi, GETPC()); 3088 pwd->b[8] = helper_ret_ldub_mmu(env, addr + (8 << DF_BYTE), oi, GETPC()); 3089 pwd->b[9] = helper_ret_ldub_mmu(env, addr + (9 << DF_BYTE), oi, GETPC()); 3090 pwd->b[10] = helper_ret_ldub_mmu(env, addr + (10 << DF_BYTE), oi, GETPC()); 3091 pwd->b[11] = helper_ret_ldub_mmu(env, addr + (11 << DF_BYTE), oi, GETPC()); 3092 pwd->b[12] = helper_ret_ldub_mmu(env, addr + (12 << DF_BYTE), oi, GETPC()); 3093 pwd->b[13] = helper_ret_ldub_mmu(env, addr + (13 << DF_BYTE), oi, GETPC()); 3094 pwd->b[14] = helper_ret_ldub_mmu(env, addr + (14 << DF_BYTE), oi, GETPC()); 3095 pwd->b[15] = helper_ret_ldub_mmu(env, addr + (15 << DF_BYTE), oi, GETPC()); 3096 #else 3097 pwd->b[0] = helper_ret_ldub_mmu(env, addr + (7 << DF_BYTE), oi, GETPC()); 3098 pwd->b[1] = helper_ret_ldub_mmu(env, addr + (6 << DF_BYTE), oi, GETPC()); 3099 pwd->b[2] = helper_ret_ldub_mmu(env, addr + (5 << DF_BYTE), oi, GETPC()); 3100 pwd->b[3] = helper_ret_ldub_mmu(env, addr + (4 << DF_BYTE), oi, GETPC()); 3101 pwd->b[4] = helper_ret_ldub_mmu(env, addr + (3 << DF_BYTE), oi, GETPC()); 3102 pwd->b[5] = helper_ret_ldub_mmu(env, addr + (2 << DF_BYTE), oi, GETPC()); 3103 pwd->b[6] = helper_ret_ldub_mmu(env, addr + (1 << DF_BYTE), oi, GETPC()); 3104 pwd->b[7] = helper_ret_ldub_mmu(env, addr + (0 << DF_BYTE), oi, GETPC()); 3105 pwd->b[8] = helper_ret_ldub_mmu(env, addr + (15 << DF_BYTE), oi, GETPC()); 3106 pwd->b[9] = helper_ret_ldub_mmu(env, addr + (14 << DF_BYTE), oi, GETPC()); 3107 pwd->b[10] = helper_ret_ldub_mmu(env, addr + (13 << DF_BYTE), oi, GETPC()); 3108 pwd->b[11] = helper_ret_ldub_mmu(env, addr + (12 << DF_BYTE), oi, GETPC()); 3109 pwd->b[12] = helper_ret_ldub_mmu(env, addr + (11 << DF_BYTE), oi, GETPC()); 3110 pwd->b[13] = helper_ret_ldub_mmu(env, addr + (10 << DF_BYTE), oi, GETPC()); 3111 pwd->b[14] = helper_ret_ldub_mmu(env, addr + (9 << DF_BYTE), oi, GETPC()); 3112 pwd->b[15] = helper_ret_ldub_mmu(env, addr + (8 << DF_BYTE), oi, GETPC()); 3113 #endif 3114 #else 3115 #if !defined(HOST_WORDS_BIGENDIAN) 3116 pwd->b[0] = cpu_ldub_data(env, addr + (0 << DF_BYTE)); 3117 pwd->b[1] = cpu_ldub_data(env, addr + (1 << DF_BYTE)); 3118 pwd->b[2] = cpu_ldub_data(env, addr + (2 << DF_BYTE)); 3119 pwd->b[3] = cpu_ldub_data(env, addr + (3 << DF_BYTE)); 3120 pwd->b[4] = cpu_ldub_data(env, addr + (4 << DF_BYTE)); 3121 pwd->b[5] = cpu_ldub_data(env, addr + (5 << DF_BYTE)); 3122 pwd->b[6] = cpu_ldub_data(env, addr + (6 << DF_BYTE)); 3123 pwd->b[7] = cpu_ldub_data(env, addr + (7 << DF_BYTE)); 3124 pwd->b[8] = cpu_ldub_data(env, addr + (8 << DF_BYTE)); 3125 pwd->b[9] = cpu_ldub_data(env, addr + (9 << DF_BYTE)); 3126 pwd->b[10] = cpu_ldub_data(env, addr + (10 << DF_BYTE)); 3127 pwd->b[11] = cpu_ldub_data(env, addr + (11 << DF_BYTE)); 3128 pwd->b[12] = cpu_ldub_data(env, addr + (12 << DF_BYTE)); 3129 pwd->b[13] = cpu_ldub_data(env, addr + (13 << DF_BYTE)); 3130 pwd->b[14] = cpu_ldub_data(env, addr + (14 << DF_BYTE)); 3131 pwd->b[15] = cpu_ldub_data(env, addr + (15 << DF_BYTE)); 3132 #else 3133 pwd->b[0] = cpu_ldub_data(env, addr + (7 << DF_BYTE)); 3134 pwd->b[1] = cpu_ldub_data(env, addr + (6 << DF_BYTE)); 3135 pwd->b[2] = cpu_ldub_data(env, addr + (5 << DF_BYTE)); 3136 pwd->b[3] = cpu_ldub_data(env, addr + (4 << DF_BYTE)); 3137 pwd->b[4] = cpu_ldub_data(env, addr + (3 << DF_BYTE)); 3138 pwd->b[5] = cpu_ldub_data(env, addr + (2 << DF_BYTE)); 3139 pwd->b[6] = cpu_ldub_data(env, addr + (1 << DF_BYTE)); 3140 pwd->b[7] = cpu_ldub_data(env, addr + (0 << DF_BYTE)); 3141 pwd->b[8] = cpu_ldub_data(env, addr + (15 << DF_BYTE)); 3142 pwd->b[9] = cpu_ldub_data(env, addr + (14 << DF_BYTE)); 3143 pwd->b[10] = cpu_ldub_data(env, addr + (13 << DF_BYTE)); 3144 pwd->b[11] = cpu_ldub_data(env, addr + (12 << DF_BYTE)); 3145 pwd->b[12] = cpu_ldub_data(env, addr + (11 << DF_BYTE)); 3146 pwd->b[13] = cpu_ldub_data(env, addr + (10 << DF_BYTE)); 3147 pwd->b[14] = cpu_ldub_data(env, addr + (9 << DF_BYTE)); 3148 pwd->b[15] = cpu_ldub_data(env, addr + (8 << DF_BYTE)); 3149 #endif 3150 #endif 3151 } 3152 3153 void helper_msa_ld_h(CPUMIPSState *env, uint32_t wd, 3154 target_ulong addr) 3155 { 3156 wr_t *pwd = &(env->active_fpu.fpr[wd].wr); 3157 MEMOP_IDX(DF_HALF) 3158 #if !defined(CONFIG_USER_ONLY) 3159 #if !defined(HOST_WORDS_BIGENDIAN) 3160 pwd->h[0] = helper_ret_lduw_mmu(env, addr + (0 << DF_HALF), oi, GETPC()); 3161 pwd->h[1] = helper_ret_lduw_mmu(env, addr + (1 << DF_HALF), oi, GETPC()); 3162 pwd->h[2] = helper_ret_lduw_mmu(env, addr + (2 << DF_HALF), oi, GETPC()); 3163 pwd->h[3] = helper_ret_lduw_mmu(env, addr + (3 << DF_HALF), oi, GETPC()); 3164 pwd->h[4] = helper_ret_lduw_mmu(env, addr + (4 << DF_HALF), oi, GETPC()); 3165 pwd->h[5] = helper_ret_lduw_mmu(env, addr + (5 << DF_HALF), oi, GETPC()); 3166 pwd->h[6] = helper_ret_lduw_mmu(env, addr + (6 << DF_HALF), oi, GETPC()); 3167 pwd->h[7] = helper_ret_lduw_mmu(env, addr + (7 << DF_HALF), oi, GETPC()); 3168 #else 3169 pwd->h[0] = helper_ret_lduw_mmu(env, addr + (3 << DF_HALF), oi, GETPC()); 3170 pwd->h[1] = helper_ret_lduw_mmu(env, addr + (2 << DF_HALF), oi, GETPC()); 3171 pwd->h[2] = helper_ret_lduw_mmu(env, addr + (1 << DF_HALF), oi, GETPC()); 3172 pwd->h[3] = helper_ret_lduw_mmu(env, addr + (0 << DF_HALF), oi, GETPC()); 3173 pwd->h[4] = helper_ret_lduw_mmu(env, addr + (7 << DF_HALF), oi, GETPC()); 3174 pwd->h[5] = helper_ret_lduw_mmu(env, addr + (6 << DF_HALF), oi, GETPC()); 3175 pwd->h[6] = helper_ret_lduw_mmu(env, addr + (5 << DF_HALF), oi, GETPC()); 3176 pwd->h[7] = helper_ret_lduw_mmu(env, addr + (4 << DF_HALF), oi, GETPC()); 3177 #endif 3178 #else 3179 #if !defined(HOST_WORDS_BIGENDIAN) 3180 pwd->h[0] = cpu_lduw_data(env, addr + (0 << DF_HALF)); 3181 pwd->h[1] = cpu_lduw_data(env, addr + (1 << DF_HALF)); 3182 pwd->h[2] = cpu_lduw_data(env, addr + (2 << DF_HALF)); 3183 pwd->h[3] = cpu_lduw_data(env, addr + (3 << DF_HALF)); 3184 pwd->h[4] = cpu_lduw_data(env, addr + (4 << DF_HALF)); 3185 pwd->h[5] = cpu_lduw_data(env, addr + (5 << DF_HALF)); 3186 pwd->h[6] = cpu_lduw_data(env, addr + (6 << DF_HALF)); 3187 pwd->h[7] = cpu_lduw_data(env, addr + (7 << DF_HALF)); 3188 #else 3189 pwd->h[0] = cpu_lduw_data(env, addr + (3 << DF_HALF)); 3190 pwd->h[1] = cpu_lduw_data(env, addr + (2 << DF_HALF)); 3191 pwd->h[2] = cpu_lduw_data(env, addr + (1 << DF_HALF)); 3192 pwd->h[3] = cpu_lduw_data(env, addr + (0 << DF_HALF)); 3193 pwd->h[4] = cpu_lduw_data(env, addr + (7 << DF_HALF)); 3194 pwd->h[5] = cpu_lduw_data(env, addr + (6 << DF_HALF)); 3195 pwd->h[6] = cpu_lduw_data(env, addr + (5 << DF_HALF)); 3196 pwd->h[7] = cpu_lduw_data(env, addr + (4 << DF_HALF)); 3197 #endif 3198 #endif 3199 } 3200 3201 void helper_msa_ld_w(CPUMIPSState *env, uint32_t wd, 3202 target_ulong addr) 3203 { 3204 wr_t *pwd = &(env->active_fpu.fpr[wd].wr); 3205 MEMOP_IDX(DF_WORD) 3206 #if !defined(CONFIG_USER_ONLY) 3207 #if !defined(HOST_WORDS_BIGENDIAN) 3208 pwd->w[0] = helper_ret_ldul_mmu(env, addr + (0 << DF_WORD), oi, GETPC()); 3209 pwd->w[1] = helper_ret_ldul_mmu(env, addr + (1 << DF_WORD), oi, GETPC()); 3210 pwd->w[2] = helper_ret_ldul_mmu(env, addr + (2 << DF_WORD), oi, GETPC()); 3211 pwd->w[3] = helper_ret_ldul_mmu(env, addr + (3 << DF_WORD), oi, GETPC()); 3212 #else 3213 pwd->w[0] = helper_ret_ldul_mmu(env, addr + (1 << DF_WORD), oi, GETPC()); 3214 pwd->w[1] = helper_ret_ldul_mmu(env, addr + (0 << DF_WORD), oi, GETPC()); 3215 pwd->w[2] = helper_ret_ldul_mmu(env, addr + (3 << DF_WORD), oi, GETPC()); 3216 pwd->w[3] = helper_ret_ldul_mmu(env, addr + (2 << DF_WORD), oi, GETPC()); 3217 #endif 3218 #else 3219 #if !defined(HOST_WORDS_BIGENDIAN) 3220 pwd->w[0] = cpu_ldl_data(env, addr + (0 << DF_WORD)); 3221 pwd->w[1] = cpu_ldl_data(env, addr + (1 << DF_WORD)); 3222 pwd->w[2] = cpu_ldl_data(env, addr + (2 << DF_WORD)); 3223 pwd->w[3] = cpu_ldl_data(env, addr + (3 << DF_WORD)); 3224 #else 3225 pwd->w[0] = cpu_ldl_data(env, addr + (1 << DF_WORD)); 3226 pwd->w[1] = cpu_ldl_data(env, addr + (0 << DF_WORD)); 3227 pwd->w[2] = cpu_ldl_data(env, addr + (3 << DF_WORD)); 3228 pwd->w[3] = cpu_ldl_data(env, addr + (2 << DF_WORD)); 3229 #endif 3230 #endif 3231 } 3232 3233 void helper_msa_ld_d(CPUMIPSState *env, uint32_t wd, 3234 target_ulong addr) 3235 { 3236 wr_t *pwd = &(env->active_fpu.fpr[wd].wr); 3237 MEMOP_IDX(DF_DOUBLE) 3238 #if !defined(CONFIG_USER_ONLY) 3239 pwd->d[0] = helper_ret_ldq_mmu(env, addr + (0 << DF_DOUBLE), oi, GETPC()); 3240 pwd->d[1] = helper_ret_ldq_mmu(env, addr + (1 << DF_DOUBLE), oi, GETPC()); 3241 #else 3242 pwd->d[0] = cpu_ldq_data(env, addr + (0 << DF_DOUBLE)); 3243 pwd->d[1] = cpu_ldq_data(env, addr + (1 << DF_DOUBLE)); 3244 #endif 3245 } 3246 3247 #define MSA_PAGESPAN(x) \ 3248 ((((x) & ~TARGET_PAGE_MASK) + MSA_WRLEN / 8 - 1) >= TARGET_PAGE_SIZE) 3249 3250 static inline void ensure_writable_pages(CPUMIPSState *env, 3251 target_ulong addr, 3252 int mmu_idx, 3253 uintptr_t retaddr) 3254 { 3255 /* FIXME: Probe the actual accesses (pass and use a size) */ 3256 if (unlikely(MSA_PAGESPAN(addr))) { 3257 /* first page */ 3258 probe_write(env, addr, 0, mmu_idx, retaddr); 3259 /* second page */ 3260 addr = (addr & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; 3261 probe_write(env, addr, 0, mmu_idx, retaddr); 3262 } 3263 } 3264 3265 void helper_msa_st_b(CPUMIPSState *env, uint32_t wd, 3266 target_ulong addr) 3267 { 3268 wr_t *pwd = &(env->active_fpu.fpr[wd].wr); 3269 int mmu_idx = cpu_mmu_index(env, false); 3270 3271 MEMOP_IDX(DF_BYTE) 3272 ensure_writable_pages(env, addr, mmu_idx, GETPC()); 3273 #if !defined(CONFIG_USER_ONLY) 3274 #if !defined(HOST_WORDS_BIGENDIAN) 3275 helper_ret_stb_mmu(env, addr + (0 << DF_BYTE), pwd->b[0], oi, GETPC()); 3276 helper_ret_stb_mmu(env, addr + (1 << DF_BYTE), pwd->b[1], oi, GETPC()); 3277 helper_ret_stb_mmu(env, addr + (2 << DF_BYTE), pwd->b[2], oi, GETPC()); 3278 helper_ret_stb_mmu(env, addr + (3 << DF_BYTE), pwd->b[3], oi, GETPC()); 3279 helper_ret_stb_mmu(env, addr + (4 << DF_BYTE), pwd->b[4], oi, GETPC()); 3280 helper_ret_stb_mmu(env, addr + (5 << DF_BYTE), pwd->b[5], oi, GETPC()); 3281 helper_ret_stb_mmu(env, addr + (6 << DF_BYTE), pwd->b[6], oi, GETPC()); 3282 helper_ret_stb_mmu(env, addr + (7 << DF_BYTE), pwd->b[7], oi, GETPC()); 3283 helper_ret_stb_mmu(env, addr + (8 << DF_BYTE), pwd->b[8], oi, GETPC()); 3284 helper_ret_stb_mmu(env, addr + (9 << DF_BYTE), pwd->b[9], oi, GETPC()); 3285 helper_ret_stb_mmu(env, addr + (10 << DF_BYTE), pwd->b[10], oi, GETPC()); 3286 helper_ret_stb_mmu(env, addr + (11 << DF_BYTE), pwd->b[11], oi, GETPC()); 3287 helper_ret_stb_mmu(env, addr + (12 << DF_BYTE), pwd->b[12], oi, GETPC()); 3288 helper_ret_stb_mmu(env, addr + (13 << DF_BYTE), pwd->b[13], oi, GETPC()); 3289 helper_ret_stb_mmu(env, addr + (14 << DF_BYTE), pwd->b[14], oi, GETPC()); 3290 helper_ret_stb_mmu(env, addr + (15 << DF_BYTE), pwd->b[15], oi, GETPC()); 3291 #else 3292 helper_ret_stb_mmu(env, addr + (7 << DF_BYTE), pwd->b[0], oi, GETPC()); 3293 helper_ret_stb_mmu(env, addr + (6 << DF_BYTE), pwd->b[1], oi, GETPC()); 3294 helper_ret_stb_mmu(env, addr + (5 << DF_BYTE), pwd->b[2], oi, GETPC()); 3295 helper_ret_stb_mmu(env, addr + (4 << DF_BYTE), pwd->b[3], oi, GETPC()); 3296 helper_ret_stb_mmu(env, addr + (3 << DF_BYTE), pwd->b[4], oi, GETPC()); 3297 helper_ret_stb_mmu(env, addr + (2 << DF_BYTE), pwd->b[5], oi, GETPC()); 3298 helper_ret_stb_mmu(env, addr + (1 << DF_BYTE), pwd->b[6], oi, GETPC()); 3299 helper_ret_stb_mmu(env, addr + (0 << DF_BYTE), pwd->b[7], oi, GETPC()); 3300 helper_ret_stb_mmu(env, addr + (15 << DF_BYTE), pwd->b[8], oi, GETPC()); 3301 helper_ret_stb_mmu(env, addr + (14 << DF_BYTE), pwd->b[9], oi, GETPC()); 3302 helper_ret_stb_mmu(env, addr + (13 << DF_BYTE), pwd->b[10], oi, GETPC()); 3303 helper_ret_stb_mmu(env, addr + (12 << DF_BYTE), pwd->b[11], oi, GETPC()); 3304 helper_ret_stb_mmu(env, addr + (11 << DF_BYTE), pwd->b[12], oi, GETPC()); 3305 helper_ret_stb_mmu(env, addr + (10 << DF_BYTE), pwd->b[13], oi, GETPC()); 3306 helper_ret_stb_mmu(env, addr + (9 << DF_BYTE), pwd->b[14], oi, GETPC()); 3307 helper_ret_stb_mmu(env, addr + (8 << DF_BYTE), pwd->b[15], oi, GETPC()); 3308 #endif 3309 #else 3310 #if !defined(HOST_WORDS_BIGENDIAN) 3311 cpu_stb_data(env, addr + (0 << DF_BYTE), pwd->b[0]); 3312 cpu_stb_data(env, addr + (1 << DF_BYTE), pwd->b[1]); 3313 cpu_stb_data(env, addr + (2 << DF_BYTE), pwd->b[2]); 3314 cpu_stb_data(env, addr + (3 << DF_BYTE), pwd->b[3]); 3315 cpu_stb_data(env, addr + (4 << DF_BYTE), pwd->b[4]); 3316 cpu_stb_data(env, addr + (5 << DF_BYTE), pwd->b[5]); 3317 cpu_stb_data(env, addr + (6 << DF_BYTE), pwd->b[6]); 3318 cpu_stb_data(env, addr + (7 << DF_BYTE), pwd->b[7]); 3319 cpu_stb_data(env, addr + (8 << DF_BYTE), pwd->b[8]); 3320 cpu_stb_data(env, addr + (9 << DF_BYTE), pwd->b[9]); 3321 cpu_stb_data(env, addr + (10 << DF_BYTE), pwd->b[10]); 3322 cpu_stb_data(env, addr + (11 << DF_BYTE), pwd->b[11]); 3323 cpu_stb_data(env, addr + (12 << DF_BYTE), pwd->b[12]); 3324 cpu_stb_data(env, addr + (13 << DF_BYTE), pwd->b[13]); 3325 cpu_stb_data(env, addr + (14 << DF_BYTE), pwd->b[14]); 3326 cpu_stb_data(env, addr + (15 << DF_BYTE), pwd->b[15]); 3327 #else 3328 cpu_stb_data(env, addr + (7 << DF_BYTE), pwd->b[0]); 3329 cpu_stb_data(env, addr + (6 << DF_BYTE), pwd->b[1]); 3330 cpu_stb_data(env, addr + (5 << DF_BYTE), pwd->b[2]); 3331 cpu_stb_data(env, addr + (4 << DF_BYTE), pwd->b[3]); 3332 cpu_stb_data(env, addr + (3 << DF_BYTE), pwd->b[4]); 3333 cpu_stb_data(env, addr + (2 << DF_BYTE), pwd->b[5]); 3334 cpu_stb_data(env, addr + (1 << DF_BYTE), pwd->b[6]); 3335 cpu_stb_data(env, addr + (0 << DF_BYTE), pwd->b[7]); 3336 cpu_stb_data(env, addr + (15 << DF_BYTE), pwd->b[8]); 3337 cpu_stb_data(env, addr + (14 << DF_BYTE), pwd->b[9]); 3338 cpu_stb_data(env, addr + (13 << DF_BYTE), pwd->b[10]); 3339 cpu_stb_data(env, addr + (12 << DF_BYTE), pwd->b[11]); 3340 cpu_stb_data(env, addr + (11 << DF_BYTE), pwd->b[12]); 3341 cpu_stb_data(env, addr + (10 << DF_BYTE), pwd->b[13]); 3342 cpu_stb_data(env, addr + (9 << DF_BYTE), pwd->b[14]); 3343 cpu_stb_data(env, addr + (8 << DF_BYTE), pwd->b[15]); 3344 #endif 3345 #endif 3346 } 3347 3348 void helper_msa_st_h(CPUMIPSState *env, uint32_t wd, 3349 target_ulong addr) 3350 { 3351 wr_t *pwd = &(env->active_fpu.fpr[wd].wr); 3352 int mmu_idx = cpu_mmu_index(env, false); 3353 3354 MEMOP_IDX(DF_HALF) 3355 ensure_writable_pages(env, addr, mmu_idx, GETPC()); 3356 #if !defined(CONFIG_USER_ONLY) 3357 #if !defined(HOST_WORDS_BIGENDIAN) 3358 helper_ret_stw_mmu(env, addr + (0 << DF_HALF), pwd->h[0], oi, GETPC()); 3359 helper_ret_stw_mmu(env, addr + (1 << DF_HALF), pwd->h[1], oi, GETPC()); 3360 helper_ret_stw_mmu(env, addr + (2 << DF_HALF), pwd->h[2], oi, GETPC()); 3361 helper_ret_stw_mmu(env, addr + (3 << DF_HALF), pwd->h[3], oi, GETPC()); 3362 helper_ret_stw_mmu(env, addr + (4 << DF_HALF), pwd->h[4], oi, GETPC()); 3363 helper_ret_stw_mmu(env, addr + (5 << DF_HALF), pwd->h[5], oi, GETPC()); 3364 helper_ret_stw_mmu(env, addr + (6 << DF_HALF), pwd->h[6], oi, GETPC()); 3365 helper_ret_stw_mmu(env, addr + (7 << DF_HALF), pwd->h[7], oi, GETPC()); 3366 #else 3367 helper_ret_stw_mmu(env, addr + (3 << DF_HALF), pwd->h[0], oi, GETPC()); 3368 helper_ret_stw_mmu(env, addr + (2 << DF_HALF), pwd->h[1], oi, GETPC()); 3369 helper_ret_stw_mmu(env, addr + (1 << DF_HALF), pwd->h[2], oi, GETPC()); 3370 helper_ret_stw_mmu(env, addr + (0 << DF_HALF), pwd->h[3], oi, GETPC()); 3371 helper_ret_stw_mmu(env, addr + (7 << DF_HALF), pwd->h[4], oi, GETPC()); 3372 helper_ret_stw_mmu(env, addr + (6 << DF_HALF), pwd->h[5], oi, GETPC()); 3373 helper_ret_stw_mmu(env, addr + (5 << DF_HALF), pwd->h[6], oi, GETPC()); 3374 helper_ret_stw_mmu(env, addr + (4 << DF_HALF), pwd->h[7], oi, GETPC()); 3375 #endif 3376 #else 3377 #if !defined(HOST_WORDS_BIGENDIAN) 3378 cpu_stw_data(env, addr + (0 << DF_HALF), pwd->h[0]); 3379 cpu_stw_data(env, addr + (1 << DF_HALF), pwd->h[1]); 3380 cpu_stw_data(env, addr + (2 << DF_HALF), pwd->h[2]); 3381 cpu_stw_data(env, addr + (3 << DF_HALF), pwd->h[3]); 3382 cpu_stw_data(env, addr + (4 << DF_HALF), pwd->h[4]); 3383 cpu_stw_data(env, addr + (5 << DF_HALF), pwd->h[5]); 3384 cpu_stw_data(env, addr + (6 << DF_HALF), pwd->h[6]); 3385 cpu_stw_data(env, addr + (7 << DF_HALF), pwd->h[7]); 3386 #else 3387 cpu_stw_data(env, addr + (3 << DF_HALF), pwd->h[0]); 3388 cpu_stw_data(env, addr + (2 << DF_HALF), pwd->h[1]); 3389 cpu_stw_data(env, addr + (1 << DF_HALF), pwd->h[2]); 3390 cpu_stw_data(env, addr + (0 << DF_HALF), pwd->h[3]); 3391 cpu_stw_data(env, addr + (7 << DF_HALF), pwd->h[4]); 3392 cpu_stw_data(env, addr + (6 << DF_HALF), pwd->h[5]); 3393 cpu_stw_data(env, addr + (5 << DF_HALF), pwd->h[6]); 3394 cpu_stw_data(env, addr + (4 << DF_HALF), pwd->h[7]); 3395 #endif 3396 #endif 3397 } 3398 3399 void helper_msa_st_w(CPUMIPSState *env, uint32_t wd, 3400 target_ulong addr) 3401 { 3402 wr_t *pwd = &(env->active_fpu.fpr[wd].wr); 3403 int mmu_idx = cpu_mmu_index(env, false); 3404 3405 MEMOP_IDX(DF_WORD) 3406 ensure_writable_pages(env, addr, mmu_idx, GETPC()); 3407 #if !defined(CONFIG_USER_ONLY) 3408 #if !defined(HOST_WORDS_BIGENDIAN) 3409 helper_ret_stl_mmu(env, addr + (0 << DF_WORD), pwd->w[0], oi, GETPC()); 3410 helper_ret_stl_mmu(env, addr + (1 << DF_WORD), pwd->w[1], oi, GETPC()); 3411 helper_ret_stl_mmu(env, addr + (2 << DF_WORD), pwd->w[2], oi, GETPC()); 3412 helper_ret_stl_mmu(env, addr + (3 << DF_WORD), pwd->w[3], oi, GETPC()); 3413 #else 3414 helper_ret_stl_mmu(env, addr + (1 << DF_WORD), pwd->w[0], oi, GETPC()); 3415 helper_ret_stl_mmu(env, addr + (0 << DF_WORD), pwd->w[1], oi, GETPC()); 3416 helper_ret_stl_mmu(env, addr + (3 << DF_WORD), pwd->w[2], oi, GETPC()); 3417 helper_ret_stl_mmu(env, addr + (2 << DF_WORD), pwd->w[3], oi, GETPC()); 3418 #endif 3419 #else 3420 #if !defined(HOST_WORDS_BIGENDIAN) 3421 cpu_stl_data(env, addr + (0 << DF_WORD), pwd->w[0]); 3422 cpu_stl_data(env, addr + (1 << DF_WORD), pwd->w[1]); 3423 cpu_stl_data(env, addr + (2 << DF_WORD), pwd->w[2]); 3424 cpu_stl_data(env, addr + (3 << DF_WORD), pwd->w[3]); 3425 #else 3426 cpu_stl_data(env, addr + (1 << DF_WORD), pwd->w[0]); 3427 cpu_stl_data(env, addr + (0 << DF_WORD), pwd->w[1]); 3428 cpu_stl_data(env, addr + (3 << DF_WORD), pwd->w[2]); 3429 cpu_stl_data(env, addr + (2 << DF_WORD), pwd->w[3]); 3430 #endif 3431 #endif 3432 } 3433 3434 void helper_msa_st_d(CPUMIPSState *env, uint32_t wd, 3435 target_ulong addr) 3436 { 3437 wr_t *pwd = &(env->active_fpu.fpr[wd].wr); 3438 int mmu_idx = cpu_mmu_index(env, false); 3439 3440 MEMOP_IDX(DF_DOUBLE) 3441 ensure_writable_pages(env, addr, mmu_idx, GETPC()); 3442 #if !defined(CONFIG_USER_ONLY) 3443 helper_ret_stq_mmu(env, addr + (0 << DF_DOUBLE), pwd->d[0], oi, GETPC()); 3444 helper_ret_stq_mmu(env, addr + (1 << DF_DOUBLE), pwd->d[1], oi, GETPC()); 3445 #else 3446 cpu_stq_data(env, addr + (0 << DF_DOUBLE), pwd->d[0]); 3447 cpu_stq_data(env, addr + (1 << DF_DOUBLE), pwd->d[1]); 3448 #endif 3449 } 3450 3451 void helper_cache(CPUMIPSState *env, target_ulong addr, uint32_t op) 3452 { 3453 #ifndef CONFIG_USER_ONLY 3454 target_ulong index = addr & 0x1fffffff; 3455 if (op == 9) { 3456 /* Index Store Tag */ 3457 memory_region_dispatch_write(env->itc_tag, index, env->CP0_TagLo, 3458 MO_64, MEMTXATTRS_UNSPECIFIED); 3459 } else if (op == 5) { 3460 /* Index Load Tag */ 3461 memory_region_dispatch_read(env->itc_tag, index, &env->CP0_TagLo, 3462 MO_64, MEMTXATTRS_UNSPECIFIED); 3463 } 3464 #endif 3465 } 3466