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 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 ret = float64_maybe_silence_nan(ret, &env->fp_status); 345 update_fr0_op(env, GETPC()); 346 return ret; 347 } 348 349 float32 HELPER(fcnv_d_s)(CPUHPPAState *env, float64 arg) 350 { 351 float32 ret = float64_to_float32(arg, &env->fp_status); 352 ret = float32_maybe_silence_nan(ret, &env->fp_status); 353 update_fr0_op(env, GETPC()); 354 return ret; 355 } 356 357 float32 HELPER(fcnv_w_s)(CPUHPPAState *env, int32_t arg) 358 { 359 float32 ret = int32_to_float32(arg, &env->fp_status); 360 update_fr0_op(env, GETPC()); 361 return ret; 362 } 363 364 float32 HELPER(fcnv_dw_s)(CPUHPPAState *env, int64_t arg) 365 { 366 float32 ret = int64_to_float32(arg, &env->fp_status); 367 update_fr0_op(env, GETPC()); 368 return ret; 369 } 370 371 float64 HELPER(fcnv_w_d)(CPUHPPAState *env, int32_t arg) 372 { 373 float64 ret = int32_to_float64(arg, &env->fp_status); 374 update_fr0_op(env, GETPC()); 375 return ret; 376 } 377 378 float64 HELPER(fcnv_dw_d)(CPUHPPAState *env, int64_t arg) 379 { 380 float64 ret = int64_to_float64(arg, &env->fp_status); 381 update_fr0_op(env, GETPC()); 382 return ret; 383 } 384 385 int32_t HELPER(fcnv_s_w)(CPUHPPAState *env, float32 arg) 386 { 387 int32_t ret = float32_to_int32(arg, &env->fp_status); 388 update_fr0_op(env, GETPC()); 389 return ret; 390 } 391 392 int32_t HELPER(fcnv_d_w)(CPUHPPAState *env, float64 arg) 393 { 394 int32_t ret = float64_to_int32(arg, &env->fp_status); 395 update_fr0_op(env, GETPC()); 396 return ret; 397 } 398 399 int64_t HELPER(fcnv_s_dw)(CPUHPPAState *env, float32 arg) 400 { 401 int64_t ret = float32_to_int64(arg, &env->fp_status); 402 update_fr0_op(env, GETPC()); 403 return ret; 404 } 405 406 int64_t HELPER(fcnv_d_dw)(CPUHPPAState *env, float64 arg) 407 { 408 int64_t ret = float64_to_int64(arg, &env->fp_status); 409 update_fr0_op(env, GETPC()); 410 return ret; 411 } 412 413 int32_t HELPER(fcnv_t_s_w)(CPUHPPAState *env, float32 arg) 414 { 415 int32_t ret = float32_to_int32_round_to_zero(arg, &env->fp_status); 416 update_fr0_op(env, GETPC()); 417 return ret; 418 } 419 420 int32_t HELPER(fcnv_t_d_w)(CPUHPPAState *env, float64 arg) 421 { 422 int32_t ret = float64_to_int32_round_to_zero(arg, &env->fp_status); 423 update_fr0_op(env, GETPC()); 424 return ret; 425 } 426 427 int64_t HELPER(fcnv_t_s_dw)(CPUHPPAState *env, float32 arg) 428 { 429 int64_t ret = float32_to_int64_round_to_zero(arg, &env->fp_status); 430 update_fr0_op(env, GETPC()); 431 return ret; 432 } 433 434 int64_t HELPER(fcnv_t_d_dw)(CPUHPPAState *env, float64 arg) 435 { 436 int64_t ret = float64_to_int64_round_to_zero(arg, &env->fp_status); 437 update_fr0_op(env, GETPC()); 438 return ret; 439 } 440 441 float32 HELPER(fcnv_uw_s)(CPUHPPAState *env, uint32_t arg) 442 { 443 float32 ret = uint32_to_float32(arg, &env->fp_status); 444 update_fr0_op(env, GETPC()); 445 return ret; 446 } 447 448 float32 HELPER(fcnv_udw_s)(CPUHPPAState *env, uint64_t arg) 449 { 450 float32 ret = uint64_to_float32(arg, &env->fp_status); 451 update_fr0_op(env, GETPC()); 452 return ret; 453 } 454 455 float64 HELPER(fcnv_uw_d)(CPUHPPAState *env, uint32_t arg) 456 { 457 float64 ret = uint32_to_float64(arg, &env->fp_status); 458 update_fr0_op(env, GETPC()); 459 return ret; 460 } 461 462 float64 HELPER(fcnv_udw_d)(CPUHPPAState *env, uint64_t arg) 463 { 464 float64 ret = uint64_to_float64(arg, &env->fp_status); 465 update_fr0_op(env, GETPC()); 466 return ret; 467 } 468 469 uint32_t HELPER(fcnv_s_uw)(CPUHPPAState *env, float32 arg) 470 { 471 uint32_t ret = float32_to_uint32(arg, &env->fp_status); 472 update_fr0_op(env, GETPC()); 473 return ret; 474 } 475 476 uint32_t HELPER(fcnv_d_uw)(CPUHPPAState *env, float64 arg) 477 { 478 uint32_t ret = float64_to_uint32(arg, &env->fp_status); 479 update_fr0_op(env, GETPC()); 480 return ret; 481 } 482 483 uint64_t HELPER(fcnv_s_udw)(CPUHPPAState *env, float32 arg) 484 { 485 uint64_t ret = float32_to_uint64(arg, &env->fp_status); 486 update_fr0_op(env, GETPC()); 487 return ret; 488 } 489 490 uint64_t HELPER(fcnv_d_udw)(CPUHPPAState *env, float64 arg) 491 { 492 uint64_t ret = float64_to_uint64(arg, &env->fp_status); 493 update_fr0_op(env, GETPC()); 494 return ret; 495 } 496 497 uint32_t HELPER(fcnv_t_s_uw)(CPUHPPAState *env, float32 arg) 498 { 499 uint32_t ret = float32_to_uint32_round_to_zero(arg, &env->fp_status); 500 update_fr0_op(env, GETPC()); 501 return ret; 502 } 503 504 uint32_t HELPER(fcnv_t_d_uw)(CPUHPPAState *env, float64 arg) 505 { 506 uint32_t ret = float64_to_uint32_round_to_zero(arg, &env->fp_status); 507 update_fr0_op(env, GETPC()); 508 return ret; 509 } 510 511 uint64_t HELPER(fcnv_t_s_udw)(CPUHPPAState *env, float32 arg) 512 { 513 uint64_t ret = float32_to_uint64_round_to_zero(arg, &env->fp_status); 514 update_fr0_op(env, GETPC()); 515 return ret; 516 } 517 518 uint64_t HELPER(fcnv_t_d_udw)(CPUHPPAState *env, float64 arg) 519 { 520 uint64_t ret = float64_to_uint64_round_to_zero(arg, &env->fp_status); 521 update_fr0_op(env, GETPC()); 522 return ret; 523 } 524 525 static void update_fr0_cmp(CPUHPPAState *env, uint32_t y, uint32_t c, int r) 526 { 527 uint32_t shadow = env->fr0_shadow; 528 529 switch (r) { 530 case float_relation_greater: 531 c = extract32(c, 4, 1); 532 break; 533 case float_relation_less: 534 c = extract32(c, 3, 1); 535 break; 536 case float_relation_equal: 537 c = extract32(c, 2, 1); 538 break; 539 case float_relation_unordered: 540 c = extract32(c, 1, 1); 541 break; 542 default: 543 g_assert_not_reached(); 544 } 545 546 if (y) { 547 /* targeted comparison */ 548 /* set fpsr[ca[y - 1]] to current compare */ 549 shadow = deposit32(shadow, 21 - (y - 1), 1, c); 550 } else { 551 /* queued comparison */ 552 /* shift cq right by one place */ 553 shadow = deposit32(shadow, 11, 10, extract32(shadow, 12, 10)); 554 /* move fpsr[c] to fpsr[cq[0]] */ 555 shadow = deposit32(shadow, 21, 1, extract32(shadow, 26, 1)); 556 /* set fpsr[c] to current compare */ 557 shadow = deposit32(shadow, 26, 1, c); 558 } 559 560 env->fr0_shadow = shadow; 561 env->fr[0] = (uint64_t)shadow << 32; 562 } 563 564 void HELPER(fcmp_s)(CPUHPPAState *env, float32 a, float32 b, 565 uint32_t y, uint32_t c) 566 { 567 int r; 568 if (c & 1) { 569 r = float32_compare(a, b, &env->fp_status); 570 } else { 571 r = float32_compare_quiet(a, b, &env->fp_status); 572 } 573 update_fr0_op(env, GETPC()); 574 update_fr0_cmp(env, y, c, r); 575 } 576 577 void HELPER(fcmp_d)(CPUHPPAState *env, float64 a, float64 b, 578 uint32_t y, uint32_t c) 579 { 580 int r; 581 if (c & 1) { 582 r = float64_compare(a, b, &env->fp_status); 583 } else { 584 r = float64_compare_quiet(a, b, &env->fp_status); 585 } 586 update_fr0_op(env, GETPC()); 587 update_fr0_cmp(env, y, c, r); 588 } 589 590 float32 HELPER(fmpyfadd_s)(CPUHPPAState *env, float32 a, float32 b, float32 c) 591 { 592 float32 ret = float32_muladd(a, b, c, 0, &env->fp_status); 593 update_fr0_op(env, GETPC()); 594 return ret; 595 } 596 597 float32 HELPER(fmpynfadd_s)(CPUHPPAState *env, float32 a, float32 b, float32 c) 598 { 599 float32 ret = float32_muladd(a, b, c, float_muladd_negate_product, 600 &env->fp_status); 601 update_fr0_op(env, GETPC()); 602 return ret; 603 } 604 605 float64 HELPER(fmpyfadd_d)(CPUHPPAState *env, float64 a, float64 b, float64 c) 606 { 607 float64 ret = float64_muladd(a, b, c, 0, &env->fp_status); 608 update_fr0_op(env, GETPC()); 609 return ret; 610 } 611 612 float64 HELPER(fmpynfadd_d)(CPUHPPAState *env, float64 a, float64 b, float64 c) 613 { 614 float64 ret = float64_muladd(a, b, c, float_muladd_negate_product, 615 &env->fp_status); 616 update_fr0_op(env, GETPC()); 617 return ret; 618 } 619 620 target_ureg HELPER(read_interval_timer)(void) 621 { 622 #ifdef CONFIG_USER_ONLY 623 /* In user-mode, QEMU_CLOCK_VIRTUAL doesn't exist. 624 Just pass through the host cpu clock ticks. */ 625 return cpu_get_host_ticks(); 626 #else 627 /* In system mode we have access to a decent high-resolution clock. 628 In order to make OS-level time accounting work with the cr16, 629 present it with a well-timed clock fixed at 250MHz. */ 630 return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) >> 2; 631 #endif 632 } 633 634 #ifndef CONFIG_USER_ONLY 635 void HELPER(write_interval_timer)(CPUHPPAState *env, target_ureg val) 636 { 637 HPPACPU *cpu = hppa_env_get_cpu(env); 638 uint64_t current = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); 639 uint64_t timeout; 640 641 /* Even in 64-bit mode, the comparator is always 32-bit. But the 642 value we expose to the guest is 1/4 of the speed of the clock, 643 so moosh in 34 bits. */ 644 timeout = deposit64(current, 0, 34, (uint64_t)val << 2); 645 646 /* If the mooshing puts the clock in the past, advance to next round. */ 647 if (timeout < current + 1000) { 648 timeout += 1ULL << 34; 649 } 650 651 cpu->env.cr[CR_IT] = timeout; 652 timer_mod(cpu->alarm_timer, timeout); 653 } 654 655 void HELPER(halt)(CPUHPPAState *env) 656 { 657 qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); 658 helper_excp(env, EXCP_HLT); 659 } 660 661 void HELPER(reset)(CPUHPPAState *env) 662 { 663 qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); 664 helper_excp(env, EXCP_HLT); 665 } 666 667 target_ureg HELPER(swap_system_mask)(CPUHPPAState *env, target_ureg nsm) 668 { 669 target_ulong psw = env->psw; 670 /* ??? On second reading this condition simply seems 671 to be undefined rather than a diagnosed trap. */ 672 if (nsm & ~psw & PSW_Q) { 673 hppa_dynamic_excp(env, EXCP_ILL, GETPC()); 674 } 675 env->psw = (psw & ~PSW_SM) | (nsm & PSW_SM); 676 return psw & PSW_SM; 677 } 678 679 void HELPER(rfi)(CPUHPPAState *env) 680 { 681 /* ??? On second reading this condition simply seems 682 to be undefined rather than a diagnosed trap. */ 683 if (env->psw & (PSW_I | PSW_R | PSW_Q)) { 684 helper_excp(env, EXCP_ILL); 685 } 686 env->iasq_f = (uint64_t)env->cr[CR_IIASQ] << 32; 687 env->iasq_b = (uint64_t)env->cr_back[0] << 32; 688 env->iaoq_f = env->cr[CR_IIAOQ]; 689 env->iaoq_b = env->cr_back[1]; 690 cpu_hppa_put_psw(env, env->cr[CR_IPSW]); 691 } 692 693 void HELPER(rfi_r)(CPUHPPAState *env) 694 { 695 env->gr[1] = env->shadow[0]; 696 env->gr[8] = env->shadow[1]; 697 env->gr[9] = env->shadow[2]; 698 env->gr[16] = env->shadow[3]; 699 env->gr[17] = env->shadow[4]; 700 env->gr[24] = env->shadow[5]; 701 env->gr[25] = env->shadow[6]; 702 helper_rfi(env); 703 } 704 #endif 705