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