qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

op_helper.c (19279B)


      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