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