1 /* 2 * Helpers for HPPA instructions. 3 * 4 * Copyright (c) 2016 Richard Henderson <rth@twiddle.net> 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 #include "qemu/osdep.h" 21 #include "cpu.h" 22 #include "exec/exec-all.h" 23 #include "exec/helper-proto.h" 24 #include "exec/cpu_ldst.h" 25 #include "sysemu/sysemu.h" 26 #include "qemu/timer.h" 27 #include "fpu/softfloat.h" 28 29 void QEMU_NORETURN HELPER(excp)(CPUHPPAState *env, int excp) 30 { 31 HPPACPU *cpu = hppa_env_get_cpu(env); 32 CPUState *cs = CPU(cpu); 33 34 cs->exception_index = excp; 35 cpu_loop_exit(cs); 36 } 37 38 void QEMU_NORETURN hppa_dynamic_excp(CPUHPPAState *env, int excp, uintptr_t ra) 39 { 40 HPPACPU *cpu = hppa_env_get_cpu(env); 41 CPUState *cs = CPU(cpu); 42 43 cs->exception_index = excp; 44 cpu_loop_exit_restore(cs, ra); 45 } 46 47 void HELPER(tsv)(CPUHPPAState *env, target_ureg cond) 48 { 49 if (unlikely((target_sreg)cond < 0)) { 50 hppa_dynamic_excp(env, EXCP_OVERFLOW, GETPC()); 51 } 52 } 53 54 void HELPER(tcond)(CPUHPPAState *env, target_ureg cond) 55 { 56 if (unlikely(cond)) { 57 hppa_dynamic_excp(env, EXCP_COND, GETPC()); 58 } 59 } 60 61 static void atomic_store_3(CPUHPPAState *env, target_ulong addr, uint32_t val, 62 uint32_t mask, uintptr_t ra) 63 { 64 #ifdef CONFIG_USER_ONLY 65 uint32_t old, new, cmp; 66 67 uint32_t *haddr = g2h(addr - 1); 68 old = *haddr; 69 while (1) { 70 new = (old & ~mask) | (val & mask); 71 cmp = atomic_cmpxchg(haddr, old, new); 72 if (cmp == old) { 73 return; 74 } 75 old = cmp; 76 } 77 #else 78 /* FIXME -- we can do better. */ 79 cpu_loop_exit_atomic(ENV_GET_CPU(env), ra); 80 #endif 81 } 82 83 static void do_stby_b(CPUHPPAState *env, target_ulong addr, target_ureg val, 84 bool parallel) 85 { 86 uintptr_t ra = GETPC(); 87 88 switch (addr & 3) { 89 case 3: 90 cpu_stb_data_ra(env, addr, val, ra); 91 break; 92 case 2: 93 cpu_stw_data_ra(env, addr, val, ra); 94 break; 95 case 1: 96 /* The 3 byte store must appear atomic. */ 97 if (parallel) { 98 atomic_store_3(env, addr, val, 0x00ffffffu, ra); 99 } else { 100 cpu_stb_data_ra(env, addr, val >> 16, ra); 101 cpu_stw_data_ra(env, addr + 1, val, ra); 102 } 103 break; 104 default: 105 cpu_stl_data_ra(env, addr, val, ra); 106 break; 107 } 108 } 109 110 void HELPER(stby_b)(CPUHPPAState *env, target_ulong addr, target_ureg val) 111 { 112 do_stby_b(env, addr, val, false); 113 } 114 115 void HELPER(stby_b_parallel)(CPUHPPAState *env, target_ulong addr, 116 target_ureg val) 117 { 118 do_stby_b(env, addr, val, true); 119 } 120 121 static void do_stby_e(CPUHPPAState *env, target_ulong addr, target_ureg val, 122 bool parallel) 123 { 124 uintptr_t ra = GETPC(); 125 126 switch (addr & 3) { 127 case 3: 128 /* The 3 byte store must appear atomic. */ 129 if (parallel) { 130 atomic_store_3(env, addr - 3, val, 0xffffff00u, ra); 131 } else { 132 cpu_stw_data_ra(env, addr - 3, val >> 16, ra); 133 cpu_stb_data_ra(env, addr - 1, val >> 8, ra); 134 } 135 break; 136 case 2: 137 cpu_stw_data_ra(env, addr - 2, val >> 16, ra); 138 break; 139 case 1: 140 cpu_stb_data_ra(env, addr - 1, val >> 24, ra); 141 break; 142 default: 143 /* Nothing is stored, but protection is checked and the 144 cacheline is marked dirty. */ 145 #ifndef CONFIG_USER_ONLY 146 probe_write(env, addr, 0, cpu_mmu_index(env, 0), ra); 147 #endif 148 break; 149 } 150 } 151 152 void HELPER(stby_e)(CPUHPPAState *env, target_ulong addr, target_ureg val) 153 { 154 do_stby_e(env, addr, val, false); 155 } 156 157 void HELPER(stby_e_parallel)(CPUHPPAState *env, target_ulong addr, 158 target_ureg val) 159 { 160 do_stby_e(env, addr, val, true); 161 } 162 163 target_ureg HELPER(probe)(CPUHPPAState *env, target_ulong addr, 164 uint32_t level, uint32_t want) 165 { 166 #ifdef CONFIG_USER_ONLY 167 return page_check_range(addr, 1, want); 168 #else 169 int prot, excp; 170 hwaddr phys; 171 172 /* Fail if the requested privilege level is higher than current. */ 173 if (level < (env->iaoq_f & 3)) { 174 return 0; 175 } 176 177 excp = hppa_get_physical_address(env, addr, level, 0, &phys, &prot); 178 if (excp >= 0) { 179 if (env->psw & PSW_Q) { 180 /* ??? Needs tweaking for hppa64. */ 181 env->cr[CR_IOR] = addr; 182 env->cr[CR_ISR] = addr >> 32; 183 } 184 if (excp == EXCP_DTLB_MISS) { 185 excp = EXCP_NA_DTLB_MISS; 186 } 187 hppa_dynamic_excp(env, excp, GETPC()); 188 } 189 return (want & prot) != 0; 190 #endif 191 } 192 193 void HELPER(loaded_fr0)(CPUHPPAState *env) 194 { 195 uint32_t shadow = env->fr[0] >> 32; 196 int rm, d; 197 198 env->fr0_shadow = shadow; 199 200 switch (extract32(shadow, 9, 2)) { 201 default: 202 rm = float_round_nearest_even; 203 break; 204 case 1: 205 rm = float_round_to_zero; 206 break; 207 case 2: 208 rm = float_round_up; 209 break; 210 case 3: 211 rm = float_round_down; 212 break; 213 } 214 set_float_rounding_mode(rm, &env->fp_status); 215 216 d = extract32(shadow, 5, 1); 217 set_flush_to_zero(d, &env->fp_status); 218 set_flush_inputs_to_zero(d, &env->fp_status); 219 } 220 221 void cpu_hppa_loaded_fr0(CPUHPPAState *env) 222 { 223 helper_loaded_fr0(env); 224 } 225 226 #define CONVERT_BIT(X, SRC, DST) \ 227 ((SRC) > (DST) \ 228 ? (X) / ((SRC) / (DST)) & (DST) \ 229 : ((X) & (SRC)) * ((DST) / (SRC))) 230 231 static void update_fr0_op(CPUHPPAState *env, uintptr_t ra) 232 { 233 uint32_t soft_exp = get_float_exception_flags(&env->fp_status); 234 uint32_t hard_exp = 0; 235 uint32_t shadow = env->fr0_shadow; 236 237 if (likely(soft_exp == 0)) { 238 env->fr[0] = (uint64_t)shadow << 32; 239 return; 240 } 241 set_float_exception_flags(0, &env->fp_status); 242 243 hard_exp |= CONVERT_BIT(soft_exp, float_flag_inexact, 1u << 0); 244 hard_exp |= CONVERT_BIT(soft_exp, float_flag_underflow, 1u << 1); 245 hard_exp |= CONVERT_BIT(soft_exp, float_flag_overflow, 1u << 2); 246 hard_exp |= CONVERT_BIT(soft_exp, float_flag_divbyzero, 1u << 3); 247 hard_exp |= CONVERT_BIT(soft_exp, float_flag_invalid, 1u << 4); 248 shadow |= hard_exp << (32 - 5); 249 env->fr0_shadow = shadow; 250 env->fr[0] = (uint64_t)shadow << 32; 251 252 if (hard_exp & shadow) { 253 hppa_dynamic_excp(env, EXCP_ASSIST, ra); 254 } 255 } 256 257 float32 HELPER(fsqrt_s)(CPUHPPAState *env, float32 arg) 258 { 259 float32 ret = float32_sqrt(arg, &env->fp_status); 260 update_fr0_op(env, GETPC()); 261 return ret; 262 } 263 264 float32 HELPER(frnd_s)(CPUHPPAState *env, float32 arg) 265 { 266 float32 ret = float32_round_to_int(arg, &env->fp_status); 267 update_fr0_op(env, GETPC()); 268 return ret; 269 } 270 271 float32 HELPER(fadd_s)(CPUHPPAState *env, float32 a, float32 b) 272 { 273 float32 ret = float32_add(a, b, &env->fp_status); 274 update_fr0_op(env, GETPC()); 275 return ret; 276 } 277 278 float32 HELPER(fsub_s)(CPUHPPAState *env, float32 a, float32 b) 279 { 280 float32 ret = float32_sub(a, b, &env->fp_status); 281 update_fr0_op(env, GETPC()); 282 return ret; 283 } 284 285 float32 HELPER(fmpy_s)(CPUHPPAState *env, float32 a, float32 b) 286 { 287 float32 ret = float32_mul(a, b, &env->fp_status); 288 update_fr0_op(env, GETPC()); 289 return ret; 290 } 291 292 float32 HELPER(fdiv_s)(CPUHPPAState *env, float32 a, float32 b) 293 { 294 float32 ret = float32_div(a, b, &env->fp_status); 295 update_fr0_op(env, GETPC()); 296 return ret; 297 } 298 299 float64 HELPER(fsqrt_d)(CPUHPPAState *env, float64 arg) 300 { 301 float64 ret = float64_sqrt(arg, &env->fp_status); 302 update_fr0_op(env, GETPC()); 303 return ret; 304 } 305 306 float64 HELPER(frnd_d)(CPUHPPAState *env, float64 arg) 307 { 308 float64 ret = float64_round_to_int(arg, &env->fp_status); 309 update_fr0_op(env, GETPC()); 310 return ret; 311 } 312 313 float64 HELPER(fadd_d)(CPUHPPAState *env, float64 a, float64 b) 314 { 315 float64 ret = float64_add(a, b, &env->fp_status); 316 update_fr0_op(env, GETPC()); 317 return ret; 318 } 319 320 float64 HELPER(fsub_d)(CPUHPPAState *env, float64 a, float64 b) 321 { 322 float64 ret = float64_sub(a, b, &env->fp_status); 323 update_fr0_op(env, GETPC()); 324 return ret; 325 } 326 327 float64 HELPER(fmpy_d)(CPUHPPAState *env, float64 a, float64 b) 328 { 329 float64 ret = float64_mul(a, b, &env->fp_status); 330 update_fr0_op(env, GETPC()); 331 return ret; 332 } 333 334 float64 HELPER(fdiv_d)(CPUHPPAState *env, float64 a, float64 b) 335 { 336 float64 ret = float64_div(a, b, &env->fp_status); 337 update_fr0_op(env, GETPC()); 338 return ret; 339 } 340 341 float64 HELPER(fcnv_s_d)(CPUHPPAState *env, float32 arg) 342 { 343 float64 ret = float32_to_float64(arg, &env->fp_status); 344 update_fr0_op(env, GETPC()); 345 return ret; 346 } 347 348 float32 HELPER(fcnv_d_s)(CPUHPPAState *env, float64 arg) 349 { 350 float32 ret = float64_to_float32(arg, &env->fp_status); 351 update_fr0_op(env, GETPC()); 352 return ret; 353 } 354 355 float32 HELPER(fcnv_w_s)(CPUHPPAState *env, int32_t arg) 356 { 357 float32 ret = int32_to_float32(arg, &env->fp_status); 358 update_fr0_op(env, GETPC()); 359 return ret; 360 } 361 362 float32 HELPER(fcnv_dw_s)(CPUHPPAState *env, int64_t arg) 363 { 364 float32 ret = int64_to_float32(arg, &env->fp_status); 365 update_fr0_op(env, GETPC()); 366 return ret; 367 } 368 369 float64 HELPER(fcnv_w_d)(CPUHPPAState *env, int32_t arg) 370 { 371 float64 ret = int32_to_float64(arg, &env->fp_status); 372 update_fr0_op(env, GETPC()); 373 return ret; 374 } 375 376 float64 HELPER(fcnv_dw_d)(CPUHPPAState *env, int64_t arg) 377 { 378 float64 ret = int64_to_float64(arg, &env->fp_status); 379 update_fr0_op(env, GETPC()); 380 return ret; 381 } 382 383 int32_t HELPER(fcnv_s_w)(CPUHPPAState *env, float32 arg) 384 { 385 int32_t ret = float32_to_int32(arg, &env->fp_status); 386 update_fr0_op(env, GETPC()); 387 return ret; 388 } 389 390 int32_t HELPER(fcnv_d_w)(CPUHPPAState *env, float64 arg) 391 { 392 int32_t ret = float64_to_int32(arg, &env->fp_status); 393 update_fr0_op(env, GETPC()); 394 return ret; 395 } 396 397 int64_t HELPER(fcnv_s_dw)(CPUHPPAState *env, float32 arg) 398 { 399 int64_t ret = float32_to_int64(arg, &env->fp_status); 400 update_fr0_op(env, GETPC()); 401 return ret; 402 } 403 404 int64_t HELPER(fcnv_d_dw)(CPUHPPAState *env, float64 arg) 405 { 406 int64_t ret = float64_to_int64(arg, &env->fp_status); 407 update_fr0_op(env, GETPC()); 408 return ret; 409 } 410 411 int32_t HELPER(fcnv_t_s_w)(CPUHPPAState *env, float32 arg) 412 { 413 int32_t ret = float32_to_int32_round_to_zero(arg, &env->fp_status); 414 update_fr0_op(env, GETPC()); 415 return ret; 416 } 417 418 int32_t HELPER(fcnv_t_d_w)(CPUHPPAState *env, float64 arg) 419 { 420 int32_t ret = float64_to_int32_round_to_zero(arg, &env->fp_status); 421 update_fr0_op(env, GETPC()); 422 return ret; 423 } 424 425 int64_t HELPER(fcnv_t_s_dw)(CPUHPPAState *env, float32 arg) 426 { 427 int64_t ret = float32_to_int64_round_to_zero(arg, &env->fp_status); 428 update_fr0_op(env, GETPC()); 429 return ret; 430 } 431 432 int64_t HELPER(fcnv_t_d_dw)(CPUHPPAState *env, float64 arg) 433 { 434 int64_t ret = float64_to_int64_round_to_zero(arg, &env->fp_status); 435 update_fr0_op(env, GETPC()); 436 return ret; 437 } 438 439 float32 HELPER(fcnv_uw_s)(CPUHPPAState *env, uint32_t arg) 440 { 441 float32 ret = uint32_to_float32(arg, &env->fp_status); 442 update_fr0_op(env, GETPC()); 443 return ret; 444 } 445 446 float32 HELPER(fcnv_udw_s)(CPUHPPAState *env, uint64_t arg) 447 { 448 float32 ret = uint64_to_float32(arg, &env->fp_status); 449 update_fr0_op(env, GETPC()); 450 return ret; 451 } 452 453 float64 HELPER(fcnv_uw_d)(CPUHPPAState *env, uint32_t arg) 454 { 455 float64 ret = uint32_to_float64(arg, &env->fp_status); 456 update_fr0_op(env, GETPC()); 457 return ret; 458 } 459 460 float64 HELPER(fcnv_udw_d)(CPUHPPAState *env, uint64_t arg) 461 { 462 float64 ret = uint64_to_float64(arg, &env->fp_status); 463 update_fr0_op(env, GETPC()); 464 return ret; 465 } 466 467 uint32_t HELPER(fcnv_s_uw)(CPUHPPAState *env, float32 arg) 468 { 469 uint32_t ret = float32_to_uint32(arg, &env->fp_status); 470 update_fr0_op(env, GETPC()); 471 return ret; 472 } 473 474 uint32_t HELPER(fcnv_d_uw)(CPUHPPAState *env, float64 arg) 475 { 476 uint32_t ret = float64_to_uint32(arg, &env->fp_status); 477 update_fr0_op(env, GETPC()); 478 return ret; 479 } 480 481 uint64_t HELPER(fcnv_s_udw)(CPUHPPAState *env, float32 arg) 482 { 483 uint64_t ret = float32_to_uint64(arg, &env->fp_status); 484 update_fr0_op(env, GETPC()); 485 return ret; 486 } 487 488 uint64_t HELPER(fcnv_d_udw)(CPUHPPAState *env, float64 arg) 489 { 490 uint64_t ret = float64_to_uint64(arg, &env->fp_status); 491 update_fr0_op(env, GETPC()); 492 return ret; 493 } 494 495 uint32_t HELPER(fcnv_t_s_uw)(CPUHPPAState *env, float32 arg) 496 { 497 uint32_t ret = float32_to_uint32_round_to_zero(arg, &env->fp_status); 498 update_fr0_op(env, GETPC()); 499 return ret; 500 } 501 502 uint32_t HELPER(fcnv_t_d_uw)(CPUHPPAState *env, float64 arg) 503 { 504 uint32_t ret = float64_to_uint32_round_to_zero(arg, &env->fp_status); 505 update_fr0_op(env, GETPC()); 506 return ret; 507 } 508 509 uint64_t HELPER(fcnv_t_s_udw)(CPUHPPAState *env, float32 arg) 510 { 511 uint64_t ret = float32_to_uint64_round_to_zero(arg, &env->fp_status); 512 update_fr0_op(env, GETPC()); 513 return ret; 514 } 515 516 uint64_t HELPER(fcnv_t_d_udw)(CPUHPPAState *env, float64 arg) 517 { 518 uint64_t ret = float64_to_uint64_round_to_zero(arg, &env->fp_status); 519 update_fr0_op(env, GETPC()); 520 return ret; 521 } 522 523 static void update_fr0_cmp(CPUHPPAState *env, uint32_t y, uint32_t c, int r) 524 { 525 uint32_t shadow = env->fr0_shadow; 526 527 switch (r) { 528 case float_relation_greater: 529 c = extract32(c, 4, 1); 530 break; 531 case float_relation_less: 532 c = extract32(c, 3, 1); 533 break; 534 case float_relation_equal: 535 c = extract32(c, 2, 1); 536 break; 537 case float_relation_unordered: 538 c = extract32(c, 1, 1); 539 break; 540 default: 541 g_assert_not_reached(); 542 } 543 544 if (y) { 545 /* targeted comparison */ 546 /* set fpsr[ca[y - 1]] to current compare */ 547 shadow = deposit32(shadow, 21 - (y - 1), 1, c); 548 } else { 549 /* queued comparison */ 550 /* shift cq right by one place */ 551 shadow = deposit32(shadow, 11, 10, extract32(shadow, 12, 10)); 552 /* move fpsr[c] to fpsr[cq[0]] */ 553 shadow = deposit32(shadow, 21, 1, extract32(shadow, 26, 1)); 554 /* set fpsr[c] to current compare */ 555 shadow = deposit32(shadow, 26, 1, c); 556 } 557 558 env->fr0_shadow = shadow; 559 env->fr[0] = (uint64_t)shadow << 32; 560 } 561 562 void HELPER(fcmp_s)(CPUHPPAState *env, float32 a, float32 b, 563 uint32_t y, uint32_t c) 564 { 565 int r; 566 if (c & 1) { 567 r = float32_compare(a, b, &env->fp_status); 568 } else { 569 r = float32_compare_quiet(a, b, &env->fp_status); 570 } 571 update_fr0_op(env, GETPC()); 572 update_fr0_cmp(env, y, c, r); 573 } 574 575 void HELPER(fcmp_d)(CPUHPPAState *env, float64 a, float64 b, 576 uint32_t y, uint32_t c) 577 { 578 int r; 579 if (c & 1) { 580 r = float64_compare(a, b, &env->fp_status); 581 } else { 582 r = float64_compare_quiet(a, b, &env->fp_status); 583 } 584 update_fr0_op(env, GETPC()); 585 update_fr0_cmp(env, y, c, r); 586 } 587 588 float32 HELPER(fmpyfadd_s)(CPUHPPAState *env, float32 a, float32 b, float32 c) 589 { 590 float32 ret = float32_muladd(a, b, c, 0, &env->fp_status); 591 update_fr0_op(env, GETPC()); 592 return ret; 593 } 594 595 float32 HELPER(fmpynfadd_s)(CPUHPPAState *env, float32 a, float32 b, float32 c) 596 { 597 float32 ret = float32_muladd(a, b, c, float_muladd_negate_product, 598 &env->fp_status); 599 update_fr0_op(env, GETPC()); 600 return ret; 601 } 602 603 float64 HELPER(fmpyfadd_d)(CPUHPPAState *env, float64 a, float64 b, float64 c) 604 { 605 float64 ret = float64_muladd(a, b, c, 0, &env->fp_status); 606 update_fr0_op(env, GETPC()); 607 return ret; 608 } 609 610 float64 HELPER(fmpynfadd_d)(CPUHPPAState *env, float64 a, float64 b, float64 c) 611 { 612 float64 ret = float64_muladd(a, b, c, float_muladd_negate_product, 613 &env->fp_status); 614 update_fr0_op(env, GETPC()); 615 return ret; 616 } 617 618 target_ureg HELPER(read_interval_timer)(void) 619 { 620 #ifdef CONFIG_USER_ONLY 621 /* In user-mode, QEMU_CLOCK_VIRTUAL doesn't exist. 622 Just pass through the host cpu clock ticks. */ 623 return cpu_get_host_ticks(); 624 #else 625 /* In system mode we have access to a decent high-resolution clock. 626 In order to make OS-level time accounting work with the cr16, 627 present it with a well-timed clock fixed at 250MHz. */ 628 return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) >> 2; 629 #endif 630 } 631 632 #ifndef CONFIG_USER_ONLY 633 void HELPER(write_interval_timer)(CPUHPPAState *env, target_ureg val) 634 { 635 HPPACPU *cpu = hppa_env_get_cpu(env); 636 uint64_t current = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); 637 uint64_t timeout; 638 639 /* Even in 64-bit mode, the comparator is always 32-bit. But the 640 value we expose to the guest is 1/4 of the speed of the clock, 641 so moosh in 34 bits. */ 642 timeout = deposit64(current, 0, 34, (uint64_t)val << 2); 643 644 /* If the mooshing puts the clock in the past, advance to next round. */ 645 if (timeout < current + 1000) { 646 timeout += 1ULL << 34; 647 } 648 649 cpu->env.cr[CR_IT] = timeout; 650 timer_mod(cpu->alarm_timer, timeout); 651 } 652 653 void HELPER(halt)(CPUHPPAState *env) 654 { 655 qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); 656 helper_excp(env, EXCP_HLT); 657 } 658 659 void HELPER(reset)(CPUHPPAState *env) 660 { 661 qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); 662 helper_excp(env, EXCP_HLT); 663 } 664 665 target_ureg HELPER(swap_system_mask)(CPUHPPAState *env, target_ureg nsm) 666 { 667 target_ulong psw = env->psw; 668 /* ??? On second reading this condition simply seems 669 to be undefined rather than a diagnosed trap. */ 670 if (nsm & ~psw & PSW_Q) { 671 hppa_dynamic_excp(env, EXCP_ILL, GETPC()); 672 } 673 env->psw = (psw & ~PSW_SM) | (nsm & PSW_SM); 674 return psw & PSW_SM; 675 } 676 677 void HELPER(rfi)(CPUHPPAState *env) 678 { 679 /* ??? On second reading this condition simply seems 680 to be undefined rather than a diagnosed trap. */ 681 if (env->psw & (PSW_I | PSW_R | PSW_Q)) { 682 helper_excp(env, EXCP_ILL); 683 } 684 env->iasq_f = (uint64_t)env->cr[CR_IIASQ] << 32; 685 env->iasq_b = (uint64_t)env->cr_back[0] << 32; 686 env->iaoq_f = env->cr[CR_IIAOQ]; 687 env->iaoq_b = env->cr_back[1]; 688 cpu_hppa_put_psw(env, env->cr[CR_IPSW]); 689 } 690 691 void HELPER(rfi_r)(CPUHPPAState *env) 692 { 693 env->gr[1] = env->shadow[0]; 694 env->gr[8] = env->shadow[1]; 695 env->gr[9] = env->shadow[2]; 696 env->gr[16] = env->shadow[3]; 697 env->gr[17] = env->shadow[4]; 698 env->gr[24] = env->shadow[5]; 699 env->gr[25] = env->shadow[6]; 700 helper_rfi(env); 701 } 702 #endif 703