qemu/target/hppa/translate.c
<<
>>
Prefs
   1/*
   2 * HPPA emulation cpu translation for qemu.
   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 "disas/disas.h"
  23#include "qemu/host-utils.h"
  24#include "exec/exec-all.h"
  25#include "tcg/tcg-op.h"
  26#include "exec/cpu_ldst.h"
  27#include "exec/helper-proto.h"
  28#include "exec/helper-gen.h"
  29#include "exec/translator.h"
  30#include "exec/log.h"
  31
  32/* Since we have a distinction between register size and address size,
  33   we need to redefine all of these.  */
  34
  35#undef TCGv
  36#undef tcg_temp_new
  37#undef tcg_global_reg_new
  38#undef tcg_global_mem_new
  39#undef tcg_temp_local_new
  40#undef tcg_temp_free
  41
  42#if TARGET_LONG_BITS == 64
  43#define TCGv_tl              TCGv_i64
  44#define tcg_temp_new_tl      tcg_temp_new_i64
  45#define tcg_temp_free_tl     tcg_temp_free_i64
  46#if TARGET_REGISTER_BITS == 64
  47#define tcg_gen_extu_reg_tl  tcg_gen_mov_i64
  48#else
  49#define tcg_gen_extu_reg_tl  tcg_gen_extu_i32_i64
  50#endif
  51#else
  52#define TCGv_tl              TCGv_i32
  53#define tcg_temp_new_tl      tcg_temp_new_i32
  54#define tcg_temp_free_tl     tcg_temp_free_i32
  55#define tcg_gen_extu_reg_tl  tcg_gen_mov_i32
  56#endif
  57
  58#if TARGET_REGISTER_BITS == 64
  59#define TCGv_reg             TCGv_i64
  60
  61#define tcg_temp_new         tcg_temp_new_i64
  62#define tcg_global_reg_new   tcg_global_reg_new_i64
  63#define tcg_global_mem_new   tcg_global_mem_new_i64
  64#define tcg_temp_local_new   tcg_temp_local_new_i64
  65#define tcg_temp_free        tcg_temp_free_i64
  66
  67#define tcg_gen_movi_reg     tcg_gen_movi_i64
  68#define tcg_gen_mov_reg      tcg_gen_mov_i64
  69#define tcg_gen_ld8u_reg     tcg_gen_ld8u_i64
  70#define tcg_gen_ld8s_reg     tcg_gen_ld8s_i64
  71#define tcg_gen_ld16u_reg    tcg_gen_ld16u_i64
  72#define tcg_gen_ld16s_reg    tcg_gen_ld16s_i64
  73#define tcg_gen_ld32u_reg    tcg_gen_ld32u_i64
  74#define tcg_gen_ld32s_reg    tcg_gen_ld32s_i64
  75#define tcg_gen_ld_reg       tcg_gen_ld_i64
  76#define tcg_gen_st8_reg      tcg_gen_st8_i64
  77#define tcg_gen_st16_reg     tcg_gen_st16_i64
  78#define tcg_gen_st32_reg     tcg_gen_st32_i64
  79#define tcg_gen_st_reg       tcg_gen_st_i64
  80#define tcg_gen_add_reg      tcg_gen_add_i64
  81#define tcg_gen_addi_reg     tcg_gen_addi_i64
  82#define tcg_gen_sub_reg      tcg_gen_sub_i64
  83#define tcg_gen_neg_reg      tcg_gen_neg_i64
  84#define tcg_gen_subfi_reg    tcg_gen_subfi_i64
  85#define tcg_gen_subi_reg     tcg_gen_subi_i64
  86#define tcg_gen_and_reg      tcg_gen_and_i64
  87#define tcg_gen_andi_reg     tcg_gen_andi_i64
  88#define tcg_gen_or_reg       tcg_gen_or_i64
  89#define tcg_gen_ori_reg      tcg_gen_ori_i64
  90#define tcg_gen_xor_reg      tcg_gen_xor_i64
  91#define tcg_gen_xori_reg     tcg_gen_xori_i64
  92#define tcg_gen_not_reg      tcg_gen_not_i64
  93#define tcg_gen_shl_reg      tcg_gen_shl_i64
  94#define tcg_gen_shli_reg     tcg_gen_shli_i64
  95#define tcg_gen_shr_reg      tcg_gen_shr_i64
  96#define tcg_gen_shri_reg     tcg_gen_shri_i64
  97#define tcg_gen_sar_reg      tcg_gen_sar_i64
  98#define tcg_gen_sari_reg     tcg_gen_sari_i64
  99#define tcg_gen_brcond_reg   tcg_gen_brcond_i64
 100#define tcg_gen_brcondi_reg  tcg_gen_brcondi_i64
 101#define tcg_gen_setcond_reg  tcg_gen_setcond_i64
 102#define tcg_gen_setcondi_reg tcg_gen_setcondi_i64
 103#define tcg_gen_mul_reg      tcg_gen_mul_i64
 104#define tcg_gen_muli_reg     tcg_gen_muli_i64
 105#define tcg_gen_div_reg      tcg_gen_div_i64
 106#define tcg_gen_rem_reg      tcg_gen_rem_i64
 107#define tcg_gen_divu_reg     tcg_gen_divu_i64
 108#define tcg_gen_remu_reg     tcg_gen_remu_i64
 109#define tcg_gen_discard_reg  tcg_gen_discard_i64
 110#define tcg_gen_trunc_reg_i32 tcg_gen_extrl_i64_i32
 111#define tcg_gen_trunc_i64_reg tcg_gen_mov_i64
 112#define tcg_gen_extu_i32_reg tcg_gen_extu_i32_i64
 113#define tcg_gen_ext_i32_reg  tcg_gen_ext_i32_i64
 114#define tcg_gen_extu_reg_i64 tcg_gen_mov_i64
 115#define tcg_gen_ext_reg_i64  tcg_gen_mov_i64
 116#define tcg_gen_ext8u_reg    tcg_gen_ext8u_i64
 117#define tcg_gen_ext8s_reg    tcg_gen_ext8s_i64
 118#define tcg_gen_ext16u_reg   tcg_gen_ext16u_i64
 119#define tcg_gen_ext16s_reg   tcg_gen_ext16s_i64
 120#define tcg_gen_ext32u_reg   tcg_gen_ext32u_i64
 121#define tcg_gen_ext32s_reg   tcg_gen_ext32s_i64
 122#define tcg_gen_bswap16_reg  tcg_gen_bswap16_i64
 123#define tcg_gen_bswap32_reg  tcg_gen_bswap32_i64
 124#define tcg_gen_bswap64_reg  tcg_gen_bswap64_i64
 125#define tcg_gen_concat_reg_i64 tcg_gen_concat32_i64
 126#define tcg_gen_andc_reg     tcg_gen_andc_i64
 127#define tcg_gen_eqv_reg      tcg_gen_eqv_i64
 128#define tcg_gen_nand_reg     tcg_gen_nand_i64
 129#define tcg_gen_nor_reg      tcg_gen_nor_i64
 130#define tcg_gen_orc_reg      tcg_gen_orc_i64
 131#define tcg_gen_clz_reg      tcg_gen_clz_i64
 132#define tcg_gen_ctz_reg      tcg_gen_ctz_i64
 133#define tcg_gen_clzi_reg     tcg_gen_clzi_i64
 134#define tcg_gen_ctzi_reg     tcg_gen_ctzi_i64
 135#define tcg_gen_clrsb_reg    tcg_gen_clrsb_i64
 136#define tcg_gen_ctpop_reg    tcg_gen_ctpop_i64
 137#define tcg_gen_rotl_reg     tcg_gen_rotl_i64
 138#define tcg_gen_rotli_reg    tcg_gen_rotli_i64
 139#define tcg_gen_rotr_reg     tcg_gen_rotr_i64
 140#define tcg_gen_rotri_reg    tcg_gen_rotri_i64
 141#define tcg_gen_deposit_reg  tcg_gen_deposit_i64
 142#define tcg_gen_deposit_z_reg tcg_gen_deposit_z_i64
 143#define tcg_gen_extract_reg  tcg_gen_extract_i64
 144#define tcg_gen_sextract_reg tcg_gen_sextract_i64
 145#define tcg_const_reg        tcg_const_i64
 146#define tcg_const_local_reg  tcg_const_local_i64
 147#define tcg_constant_reg     tcg_constant_i64
 148#define tcg_gen_movcond_reg  tcg_gen_movcond_i64
 149#define tcg_gen_add2_reg     tcg_gen_add2_i64
 150#define tcg_gen_sub2_reg     tcg_gen_sub2_i64
 151#define tcg_gen_qemu_ld_reg  tcg_gen_qemu_ld_i64
 152#define tcg_gen_qemu_st_reg  tcg_gen_qemu_st_i64
 153#define tcg_gen_atomic_xchg_reg tcg_gen_atomic_xchg_i64
 154#define tcg_gen_trunc_reg_ptr   tcg_gen_trunc_i64_ptr
 155#else
 156#define TCGv_reg             TCGv_i32
 157#define tcg_temp_new         tcg_temp_new_i32
 158#define tcg_global_reg_new   tcg_global_reg_new_i32
 159#define tcg_global_mem_new   tcg_global_mem_new_i32
 160#define tcg_temp_local_new   tcg_temp_local_new_i32
 161#define tcg_temp_free        tcg_temp_free_i32
 162
 163#define tcg_gen_movi_reg     tcg_gen_movi_i32
 164#define tcg_gen_mov_reg      tcg_gen_mov_i32
 165#define tcg_gen_ld8u_reg     tcg_gen_ld8u_i32
 166#define tcg_gen_ld8s_reg     tcg_gen_ld8s_i32
 167#define tcg_gen_ld16u_reg    tcg_gen_ld16u_i32
 168#define tcg_gen_ld16s_reg    tcg_gen_ld16s_i32
 169#define tcg_gen_ld32u_reg    tcg_gen_ld_i32
 170#define tcg_gen_ld32s_reg    tcg_gen_ld_i32
 171#define tcg_gen_ld_reg       tcg_gen_ld_i32
 172#define tcg_gen_st8_reg      tcg_gen_st8_i32
 173#define tcg_gen_st16_reg     tcg_gen_st16_i32
 174#define tcg_gen_st32_reg     tcg_gen_st32_i32
 175#define tcg_gen_st_reg       tcg_gen_st_i32
 176#define tcg_gen_add_reg      tcg_gen_add_i32
 177#define tcg_gen_addi_reg     tcg_gen_addi_i32
 178#define tcg_gen_sub_reg      tcg_gen_sub_i32
 179#define tcg_gen_neg_reg      tcg_gen_neg_i32
 180#define tcg_gen_subfi_reg    tcg_gen_subfi_i32
 181#define tcg_gen_subi_reg     tcg_gen_subi_i32
 182#define tcg_gen_and_reg      tcg_gen_and_i32
 183#define tcg_gen_andi_reg     tcg_gen_andi_i32
 184#define tcg_gen_or_reg       tcg_gen_or_i32
 185#define tcg_gen_ori_reg      tcg_gen_ori_i32
 186#define tcg_gen_xor_reg      tcg_gen_xor_i32
 187#define tcg_gen_xori_reg     tcg_gen_xori_i32
 188#define tcg_gen_not_reg      tcg_gen_not_i32
 189#define tcg_gen_shl_reg      tcg_gen_shl_i32
 190#define tcg_gen_shli_reg     tcg_gen_shli_i32
 191#define tcg_gen_shr_reg      tcg_gen_shr_i32
 192#define tcg_gen_shri_reg     tcg_gen_shri_i32
 193#define tcg_gen_sar_reg      tcg_gen_sar_i32
 194#define tcg_gen_sari_reg     tcg_gen_sari_i32
 195#define tcg_gen_brcond_reg   tcg_gen_brcond_i32
 196#define tcg_gen_brcondi_reg  tcg_gen_brcondi_i32
 197#define tcg_gen_setcond_reg  tcg_gen_setcond_i32
 198#define tcg_gen_setcondi_reg tcg_gen_setcondi_i32
 199#define tcg_gen_mul_reg      tcg_gen_mul_i32
 200#define tcg_gen_muli_reg     tcg_gen_muli_i32
 201#define tcg_gen_div_reg      tcg_gen_div_i32
 202#define tcg_gen_rem_reg      tcg_gen_rem_i32
 203#define tcg_gen_divu_reg     tcg_gen_divu_i32
 204#define tcg_gen_remu_reg     tcg_gen_remu_i32
 205#define tcg_gen_discard_reg  tcg_gen_discard_i32
 206#define tcg_gen_trunc_reg_i32 tcg_gen_mov_i32
 207#define tcg_gen_trunc_i64_reg tcg_gen_extrl_i64_i32
 208#define tcg_gen_extu_i32_reg tcg_gen_mov_i32
 209#define tcg_gen_ext_i32_reg  tcg_gen_mov_i32
 210#define tcg_gen_extu_reg_i64 tcg_gen_extu_i32_i64
 211#define tcg_gen_ext_reg_i64  tcg_gen_ext_i32_i64
 212#define tcg_gen_ext8u_reg    tcg_gen_ext8u_i32
 213#define tcg_gen_ext8s_reg    tcg_gen_ext8s_i32
 214#define tcg_gen_ext16u_reg   tcg_gen_ext16u_i32
 215#define tcg_gen_ext16s_reg   tcg_gen_ext16s_i32
 216#define tcg_gen_ext32u_reg   tcg_gen_mov_i32
 217#define tcg_gen_ext32s_reg   tcg_gen_mov_i32
 218#define tcg_gen_bswap16_reg  tcg_gen_bswap16_i32
 219#define tcg_gen_bswap32_reg  tcg_gen_bswap32_i32
 220#define tcg_gen_concat_reg_i64 tcg_gen_concat_i32_i64
 221#define tcg_gen_andc_reg     tcg_gen_andc_i32
 222#define tcg_gen_eqv_reg      tcg_gen_eqv_i32
 223#define tcg_gen_nand_reg     tcg_gen_nand_i32
 224#define tcg_gen_nor_reg      tcg_gen_nor_i32
 225#define tcg_gen_orc_reg      tcg_gen_orc_i32
 226#define tcg_gen_clz_reg      tcg_gen_clz_i32
 227#define tcg_gen_ctz_reg      tcg_gen_ctz_i32
 228#define tcg_gen_clzi_reg     tcg_gen_clzi_i32
 229#define tcg_gen_ctzi_reg     tcg_gen_ctzi_i32
 230#define tcg_gen_clrsb_reg    tcg_gen_clrsb_i32
 231#define tcg_gen_ctpop_reg    tcg_gen_ctpop_i32
 232#define tcg_gen_rotl_reg     tcg_gen_rotl_i32
 233#define tcg_gen_rotli_reg    tcg_gen_rotli_i32
 234#define tcg_gen_rotr_reg     tcg_gen_rotr_i32
 235#define tcg_gen_rotri_reg    tcg_gen_rotri_i32
 236#define tcg_gen_deposit_reg  tcg_gen_deposit_i32
 237#define tcg_gen_deposit_z_reg tcg_gen_deposit_z_i32
 238#define tcg_gen_extract_reg  tcg_gen_extract_i32
 239#define tcg_gen_sextract_reg tcg_gen_sextract_i32
 240#define tcg_const_reg        tcg_const_i32
 241#define tcg_const_local_reg  tcg_const_local_i32
 242#define tcg_constant_reg     tcg_constant_i32
 243#define tcg_gen_movcond_reg  tcg_gen_movcond_i32
 244#define tcg_gen_add2_reg     tcg_gen_add2_i32
 245#define tcg_gen_sub2_reg     tcg_gen_sub2_i32
 246#define tcg_gen_qemu_ld_reg  tcg_gen_qemu_ld_i32
 247#define tcg_gen_qemu_st_reg  tcg_gen_qemu_st_i32
 248#define tcg_gen_atomic_xchg_reg tcg_gen_atomic_xchg_i32
 249#define tcg_gen_trunc_reg_ptr   tcg_gen_ext_i32_ptr
 250#endif /* TARGET_REGISTER_BITS */
 251
 252typedef struct DisasCond {
 253    TCGCond c;
 254    TCGv_reg a0, a1;
 255} DisasCond;
 256
 257typedef struct DisasContext {
 258    DisasContextBase base;
 259    CPUState *cs;
 260
 261    target_ureg iaoq_f;
 262    target_ureg iaoq_b;
 263    target_ureg iaoq_n;
 264    TCGv_reg iaoq_n_var;
 265
 266    int ntempr, ntempl;
 267    TCGv_reg tempr[8];
 268    TCGv_tl  templ[4];
 269
 270    DisasCond null_cond;
 271    TCGLabel *null_lab;
 272
 273    uint32_t insn;
 274    uint32_t tb_flags;
 275    int mmu_idx;
 276    int privilege;
 277    bool psw_n_nonzero;
 278} DisasContext;
 279
 280/* Note that ssm/rsm instructions number PSW_W and PSW_E differently.  */
 281static int expand_sm_imm(DisasContext *ctx, int val)
 282{
 283    if (val & PSW_SM_E) {
 284        val = (val & ~PSW_SM_E) | PSW_E;
 285    }
 286    if (val & PSW_SM_W) {
 287        val = (val & ~PSW_SM_W) | PSW_W;
 288    }
 289    return val;
 290}
 291
 292/* Inverted space register indicates 0 means sr0 not inferred from base.  */
 293static int expand_sr3x(DisasContext *ctx, int val)
 294{
 295    return ~val;
 296}
 297
 298/* Convert the M:A bits within a memory insn to the tri-state value
 299   we use for the final M.  */
 300static int ma_to_m(DisasContext *ctx, int val)
 301{
 302    return val & 2 ? (val & 1 ? -1 : 1) : 0;
 303}
 304
 305/* Convert the sign of the displacement to a pre or post-modify.  */
 306static int pos_to_m(DisasContext *ctx, int val)
 307{
 308    return val ? 1 : -1;
 309}
 310
 311static int neg_to_m(DisasContext *ctx, int val)
 312{
 313    return val ? -1 : 1;
 314}
 315
 316/* Used for branch targets and fp memory ops.  */
 317static int expand_shl2(DisasContext *ctx, int val)
 318{
 319    return val << 2;
 320}
 321
 322/* Used for fp memory ops.  */
 323static int expand_shl3(DisasContext *ctx, int val)
 324{
 325    return val << 3;
 326}
 327
 328/* Used for assemble_21.  */
 329static int expand_shl11(DisasContext *ctx, int val)
 330{
 331    return val << 11;
 332}
 333
 334
 335/* Include the auto-generated decoder.  */
 336#include "decode-insns.c.inc"
 337
 338/* We are not using a goto_tb (for whatever reason), but have updated
 339   the iaq (for whatever reason), so don't do it again on exit.  */
 340#define DISAS_IAQ_N_UPDATED  DISAS_TARGET_0
 341
 342/* We are exiting the TB, but have neither emitted a goto_tb, nor
 343   updated the iaq for the next instruction to be executed.  */
 344#define DISAS_IAQ_N_STALE    DISAS_TARGET_1
 345
 346/* Similarly, but we want to return to the main loop immediately
 347   to recognize unmasked interrupts.  */
 348#define DISAS_IAQ_N_STALE_EXIT      DISAS_TARGET_2
 349#define DISAS_EXIT                  DISAS_TARGET_3
 350
 351/* global register indexes */
 352static TCGv_reg cpu_gr[32];
 353static TCGv_i64 cpu_sr[4];
 354static TCGv_i64 cpu_srH;
 355static TCGv_reg cpu_iaoq_f;
 356static TCGv_reg cpu_iaoq_b;
 357static TCGv_i64 cpu_iasq_f;
 358static TCGv_i64 cpu_iasq_b;
 359static TCGv_reg cpu_sar;
 360static TCGv_reg cpu_psw_n;
 361static TCGv_reg cpu_psw_v;
 362static TCGv_reg cpu_psw_cb;
 363static TCGv_reg cpu_psw_cb_msb;
 364
 365#include "exec/gen-icount.h"
 366
 367void hppa_translate_init(void)
 368{
 369#define DEF_VAR(V)  { &cpu_##V, #V, offsetof(CPUHPPAState, V) }
 370
 371    typedef struct { TCGv_reg *var; const char *name; int ofs; } GlobalVar;
 372    static const GlobalVar vars[] = {
 373        { &cpu_sar, "sar", offsetof(CPUHPPAState, cr[CR_SAR]) },
 374        DEF_VAR(psw_n),
 375        DEF_VAR(psw_v),
 376        DEF_VAR(psw_cb),
 377        DEF_VAR(psw_cb_msb),
 378        DEF_VAR(iaoq_f),
 379        DEF_VAR(iaoq_b),
 380    };
 381
 382#undef DEF_VAR
 383
 384    /* Use the symbolic register names that match the disassembler.  */
 385    static const char gr_names[32][4] = {
 386        "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
 387        "r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15",
 388        "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
 389        "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31"
 390    };
 391    /* SR[4-7] are not global registers so that we can index them.  */
 392    static const char sr_names[5][4] = {
 393        "sr0", "sr1", "sr2", "sr3", "srH"
 394    };
 395
 396    int i;
 397
 398    cpu_gr[0] = NULL;
 399    for (i = 1; i < 32; i++) {
 400        cpu_gr[i] = tcg_global_mem_new(cpu_env,
 401                                       offsetof(CPUHPPAState, gr[i]),
 402                                       gr_names[i]);
 403    }
 404    for (i = 0; i < 4; i++) {
 405        cpu_sr[i] = tcg_global_mem_new_i64(cpu_env,
 406                                           offsetof(CPUHPPAState, sr[i]),
 407                                           sr_names[i]);
 408    }
 409    cpu_srH = tcg_global_mem_new_i64(cpu_env,
 410                                     offsetof(CPUHPPAState, sr[4]),
 411                                     sr_names[4]);
 412
 413    for (i = 0; i < ARRAY_SIZE(vars); ++i) {
 414        const GlobalVar *v = &vars[i];
 415        *v->var = tcg_global_mem_new(cpu_env, v->ofs, v->name);
 416    }
 417
 418    cpu_iasq_f = tcg_global_mem_new_i64(cpu_env,
 419                                        offsetof(CPUHPPAState, iasq_f),
 420                                        "iasq_f");
 421    cpu_iasq_b = tcg_global_mem_new_i64(cpu_env,
 422                                        offsetof(CPUHPPAState, iasq_b),
 423                                        "iasq_b");
 424}
 425
 426static DisasCond cond_make_f(void)
 427{
 428    return (DisasCond){
 429        .c = TCG_COND_NEVER,
 430        .a0 = NULL,
 431        .a1 = NULL,
 432    };
 433}
 434
 435static DisasCond cond_make_t(void)
 436{
 437    return (DisasCond){
 438        .c = TCG_COND_ALWAYS,
 439        .a0 = NULL,
 440        .a1 = NULL,
 441    };
 442}
 443
 444static DisasCond cond_make_n(void)
 445{
 446    return (DisasCond){
 447        .c = TCG_COND_NE,
 448        .a0 = cpu_psw_n,
 449        .a1 = tcg_constant_reg(0)
 450    };
 451}
 452
 453static DisasCond cond_make_0_tmp(TCGCond c, TCGv_reg a0)
 454{
 455    assert (c != TCG_COND_NEVER && c != TCG_COND_ALWAYS);
 456    return (DisasCond){
 457        .c = c, .a0 = a0, .a1 = tcg_constant_reg(0)
 458    };
 459}
 460
 461static DisasCond cond_make_0(TCGCond c, TCGv_reg a0)
 462{
 463    TCGv_reg tmp = tcg_temp_new();
 464    tcg_gen_mov_reg(tmp, a0);
 465    return cond_make_0_tmp(c, tmp);
 466}
 467
 468static DisasCond cond_make(TCGCond c, TCGv_reg a0, TCGv_reg a1)
 469{
 470    DisasCond r = { .c = c };
 471
 472    assert (c != TCG_COND_NEVER && c != TCG_COND_ALWAYS);
 473    r.a0 = tcg_temp_new();
 474    tcg_gen_mov_reg(r.a0, a0);
 475    r.a1 = tcg_temp_new();
 476    tcg_gen_mov_reg(r.a1, a1);
 477
 478    return r;
 479}
 480
 481static void cond_free(DisasCond *cond)
 482{
 483    switch (cond->c) {
 484    default:
 485        if (cond->a0 != cpu_psw_n) {
 486            tcg_temp_free(cond->a0);
 487        }
 488        tcg_temp_free(cond->a1);
 489        cond->a0 = NULL;
 490        cond->a1 = NULL;
 491        /* fallthru */
 492    case TCG_COND_ALWAYS:
 493        cond->c = TCG_COND_NEVER;
 494        break;
 495    case TCG_COND_NEVER:
 496        break;
 497    }
 498}
 499
 500static TCGv_reg get_temp(DisasContext *ctx)
 501{
 502    unsigned i = ctx->ntempr++;
 503    g_assert(i < ARRAY_SIZE(ctx->tempr));
 504    return ctx->tempr[i] = tcg_temp_new();
 505}
 506
 507#ifndef CONFIG_USER_ONLY
 508static TCGv_tl get_temp_tl(DisasContext *ctx)
 509{
 510    unsigned i = ctx->ntempl++;
 511    g_assert(i < ARRAY_SIZE(ctx->templ));
 512    return ctx->templ[i] = tcg_temp_new_tl();
 513}
 514#endif
 515
 516static TCGv_reg load_const(DisasContext *ctx, target_sreg v)
 517{
 518    TCGv_reg t = get_temp(ctx);
 519    tcg_gen_movi_reg(t, v);
 520    return t;
 521}
 522
 523static TCGv_reg load_gpr(DisasContext *ctx, unsigned reg)
 524{
 525    if (reg == 0) {
 526        TCGv_reg t = get_temp(ctx);
 527        tcg_gen_movi_reg(t, 0);
 528        return t;
 529    } else {
 530        return cpu_gr[reg];
 531    }
 532}
 533
 534static TCGv_reg dest_gpr(DisasContext *ctx, unsigned reg)
 535{
 536    if (reg == 0 || ctx->null_cond.c != TCG_COND_NEVER) {
 537        return get_temp(ctx);
 538    } else {
 539        return cpu_gr[reg];
 540    }
 541}
 542
 543static void save_or_nullify(DisasContext *ctx, TCGv_reg dest, TCGv_reg t)
 544{
 545    if (ctx->null_cond.c != TCG_COND_NEVER) {
 546        tcg_gen_movcond_reg(ctx->null_cond.c, dest, ctx->null_cond.a0,
 547                            ctx->null_cond.a1, dest, t);
 548    } else {
 549        tcg_gen_mov_reg(dest, t);
 550    }
 551}
 552
 553static void save_gpr(DisasContext *ctx, unsigned reg, TCGv_reg t)
 554{
 555    if (reg != 0) {
 556        save_or_nullify(ctx, cpu_gr[reg], t);
 557    }
 558}
 559
 560#ifdef HOST_WORDS_BIGENDIAN
 561# define HI_OFS  0
 562# define LO_OFS  4
 563#else
 564# define HI_OFS  4
 565# define LO_OFS  0
 566#endif
 567
 568static TCGv_i32 load_frw_i32(unsigned rt)
 569{
 570    TCGv_i32 ret = tcg_temp_new_i32();
 571    tcg_gen_ld_i32(ret, cpu_env,
 572                   offsetof(CPUHPPAState, fr[rt & 31])
 573                   + (rt & 32 ? LO_OFS : HI_OFS));
 574    return ret;
 575}
 576
 577static TCGv_i32 load_frw0_i32(unsigned rt)
 578{
 579    if (rt == 0) {
 580        return tcg_const_i32(0);
 581    } else {
 582        return load_frw_i32(rt);
 583    }
 584}
 585
 586static TCGv_i64 load_frw0_i64(unsigned rt)
 587{
 588    if (rt == 0) {
 589        return tcg_const_i64(0);
 590    } else {
 591        TCGv_i64 ret = tcg_temp_new_i64();
 592        tcg_gen_ld32u_i64(ret, cpu_env,
 593                          offsetof(CPUHPPAState, fr[rt & 31])
 594                          + (rt & 32 ? LO_OFS : HI_OFS));
 595        return ret;
 596    }
 597}
 598
 599static void save_frw_i32(unsigned rt, TCGv_i32 val)
 600{
 601    tcg_gen_st_i32(val, cpu_env,
 602                   offsetof(CPUHPPAState, fr[rt & 31])
 603                   + (rt & 32 ? LO_OFS : HI_OFS));
 604}
 605
 606#undef HI_OFS
 607#undef LO_OFS
 608
 609static TCGv_i64 load_frd(unsigned rt)
 610{
 611    TCGv_i64 ret = tcg_temp_new_i64();
 612    tcg_gen_ld_i64(ret, cpu_env, offsetof(CPUHPPAState, fr[rt]));
 613    return ret;
 614}
 615
 616static TCGv_i64 load_frd0(unsigned rt)
 617{
 618    if (rt == 0) {
 619        return tcg_const_i64(0);
 620    } else {
 621        return load_frd(rt);
 622    }
 623}
 624
 625static void save_frd(unsigned rt, TCGv_i64 val)
 626{
 627    tcg_gen_st_i64(val, cpu_env, offsetof(CPUHPPAState, fr[rt]));
 628}
 629
 630static void load_spr(DisasContext *ctx, TCGv_i64 dest, unsigned reg)
 631{
 632#ifdef CONFIG_USER_ONLY
 633    tcg_gen_movi_i64(dest, 0);
 634#else
 635    if (reg < 4) {
 636        tcg_gen_mov_i64(dest, cpu_sr[reg]);
 637    } else if (ctx->tb_flags & TB_FLAG_SR_SAME) {
 638        tcg_gen_mov_i64(dest, cpu_srH);
 639    } else {
 640        tcg_gen_ld_i64(dest, cpu_env, offsetof(CPUHPPAState, sr[reg]));
 641    }
 642#endif
 643}
 644
 645/* Skip over the implementation of an insn that has been nullified.
 646   Use this when the insn is too complex for a conditional move.  */
 647static void nullify_over(DisasContext *ctx)
 648{
 649    if (ctx->null_cond.c != TCG_COND_NEVER) {
 650        /* The always condition should have been handled in the main loop.  */
 651        assert(ctx->null_cond.c != TCG_COND_ALWAYS);
 652
 653        ctx->null_lab = gen_new_label();
 654
 655        /* If we're using PSW[N], copy it to a temp because... */
 656        if (ctx->null_cond.a0 == cpu_psw_n) {
 657            ctx->null_cond.a0 = tcg_temp_new();
 658            tcg_gen_mov_reg(ctx->null_cond.a0, cpu_psw_n);
 659        }
 660        /* ... we clear it before branching over the implementation,
 661           so that (1) it's clear after nullifying this insn and
 662           (2) if this insn nullifies the next, PSW[N] is valid.  */
 663        if (ctx->psw_n_nonzero) {
 664            ctx->psw_n_nonzero = false;
 665            tcg_gen_movi_reg(cpu_psw_n, 0);
 666        }
 667
 668        tcg_gen_brcond_reg(ctx->null_cond.c, ctx->null_cond.a0,
 669                           ctx->null_cond.a1, ctx->null_lab);
 670        cond_free(&ctx->null_cond);
 671    }
 672}
 673
 674/* Save the current nullification state to PSW[N].  */
 675static void nullify_save(DisasContext *ctx)
 676{
 677    if (ctx->null_cond.c == TCG_COND_NEVER) {
 678        if (ctx->psw_n_nonzero) {
 679            tcg_gen_movi_reg(cpu_psw_n, 0);
 680        }
 681        return;
 682    }
 683    if (ctx->null_cond.a0 != cpu_psw_n) {
 684        tcg_gen_setcond_reg(ctx->null_cond.c, cpu_psw_n,
 685                            ctx->null_cond.a0, ctx->null_cond.a1);
 686        ctx->psw_n_nonzero = true;
 687    }
 688    cond_free(&ctx->null_cond);
 689}
 690
 691/* Set a PSW[N] to X.  The intention is that this is used immediately
 692   before a goto_tb/exit_tb, so that there is no fallthru path to other
 693   code within the TB.  Therefore we do not update psw_n_nonzero.  */
 694static void nullify_set(DisasContext *ctx, bool x)
 695{
 696    if (ctx->psw_n_nonzero || x) {
 697        tcg_gen_movi_reg(cpu_psw_n, x);
 698    }
 699}
 700
 701/* Mark the end of an instruction that may have been nullified.
 702   This is the pair to nullify_over.  Always returns true so that
 703   it may be tail-called from a translate function.  */
 704static bool nullify_end(DisasContext *ctx)
 705{
 706    TCGLabel *null_lab = ctx->null_lab;
 707    DisasJumpType status = ctx->base.is_jmp;
 708
 709    /* For NEXT, NORETURN, STALE, we can easily continue (or exit).
 710       For UPDATED, we cannot update on the nullified path.  */
 711    assert(status != DISAS_IAQ_N_UPDATED);
 712
 713    if (likely(null_lab == NULL)) {
 714        /* The current insn wasn't conditional or handled the condition
 715           applied to it without a branch, so the (new) setting of
 716           NULL_COND can be applied directly to the next insn.  */
 717        return true;
 718    }
 719    ctx->null_lab = NULL;
 720
 721    if (likely(ctx->null_cond.c == TCG_COND_NEVER)) {
 722        /* The next instruction will be unconditional,
 723           and NULL_COND already reflects that.  */
 724        gen_set_label(null_lab);
 725    } else {
 726        /* The insn that we just executed is itself nullifying the next
 727           instruction.  Store the condition in the PSW[N] global.
 728           We asserted PSW[N] = 0 in nullify_over, so that after the
 729           label we have the proper value in place.  */
 730        nullify_save(ctx);
 731        gen_set_label(null_lab);
 732        ctx->null_cond = cond_make_n();
 733    }
 734    if (status == DISAS_NORETURN) {
 735        ctx->base.is_jmp = DISAS_NEXT;
 736    }
 737    return true;
 738}
 739
 740static void copy_iaoq_entry(TCGv_reg dest, target_ureg ival, TCGv_reg vval)
 741{
 742    if (unlikely(ival == -1)) {
 743        tcg_gen_mov_reg(dest, vval);
 744    } else {
 745        tcg_gen_movi_reg(dest, ival);
 746    }
 747}
 748
 749static inline target_ureg iaoq_dest(DisasContext *ctx, target_sreg disp)
 750{
 751    return ctx->iaoq_f + disp + 8;
 752}
 753
 754static void gen_excp_1(int exception)
 755{
 756    gen_helper_excp(cpu_env, tcg_constant_i32(exception));
 757}
 758
 759static void gen_excp(DisasContext *ctx, int exception)
 760{
 761    copy_iaoq_entry(cpu_iaoq_f, ctx->iaoq_f, cpu_iaoq_f);
 762    copy_iaoq_entry(cpu_iaoq_b, ctx->iaoq_b, cpu_iaoq_b);
 763    nullify_save(ctx);
 764    gen_excp_1(exception);
 765    ctx->base.is_jmp = DISAS_NORETURN;
 766}
 767
 768static bool gen_excp_iir(DisasContext *ctx, int exc)
 769{
 770    nullify_over(ctx);
 771    tcg_gen_st_reg(tcg_constant_reg(ctx->insn),
 772                   cpu_env, offsetof(CPUHPPAState, cr[CR_IIR]));
 773    gen_excp(ctx, exc);
 774    return nullify_end(ctx);
 775}
 776
 777static bool gen_illegal(DisasContext *ctx)
 778{
 779    return gen_excp_iir(ctx, EXCP_ILL);
 780}
 781
 782#ifdef CONFIG_USER_ONLY
 783#define CHECK_MOST_PRIVILEGED(EXCP) \
 784    return gen_excp_iir(ctx, EXCP)
 785#else
 786#define CHECK_MOST_PRIVILEGED(EXCP) \
 787    do {                                     \
 788        if (ctx->privilege != 0) {           \
 789            return gen_excp_iir(ctx, EXCP);  \
 790        }                                    \
 791    } while (0)
 792#endif
 793
 794static bool use_goto_tb(DisasContext *ctx, target_ureg dest)
 795{
 796    return translator_use_goto_tb(&ctx->base, dest);
 797}
 798
 799/* If the next insn is to be nullified, and it's on the same page,
 800   and we're not attempting to set a breakpoint on it, then we can
 801   totally skip the nullified insn.  This avoids creating and
 802   executing a TB that merely branches to the next TB.  */
 803static bool use_nullify_skip(DisasContext *ctx)
 804{
 805    return (((ctx->iaoq_b ^ ctx->iaoq_f) & TARGET_PAGE_MASK) == 0
 806            && !cpu_breakpoint_test(ctx->cs, ctx->iaoq_b, BP_ANY));
 807}
 808
 809static void gen_goto_tb(DisasContext *ctx, int which,
 810                        target_ureg f, target_ureg b)
 811{
 812    if (f != -1 && b != -1 && use_goto_tb(ctx, f)) {
 813        tcg_gen_goto_tb(which);
 814        tcg_gen_movi_reg(cpu_iaoq_f, f);
 815        tcg_gen_movi_reg(cpu_iaoq_b, b);
 816        tcg_gen_exit_tb(ctx->base.tb, which);
 817    } else {
 818        copy_iaoq_entry(cpu_iaoq_f, f, cpu_iaoq_b);
 819        copy_iaoq_entry(cpu_iaoq_b, b, ctx->iaoq_n_var);
 820        if (ctx->base.singlestep_enabled) {
 821            gen_excp_1(EXCP_DEBUG);
 822        } else {
 823            tcg_gen_lookup_and_goto_ptr();
 824        }
 825    }
 826}
 827
 828static bool cond_need_sv(int c)
 829{
 830    return c == 2 || c == 3 || c == 6;
 831}
 832
 833static bool cond_need_cb(int c)
 834{
 835    return c == 4 || c == 5;
 836}
 837
 838/*
 839 * Compute conditional for arithmetic.  See Page 5-3, Table 5-1, of
 840 * the Parisc 1.1 Architecture Reference Manual for details.
 841 */
 842
 843static DisasCond do_cond(unsigned cf, TCGv_reg res,
 844                         TCGv_reg cb_msb, TCGv_reg sv)
 845{
 846    DisasCond cond;
 847    TCGv_reg tmp;
 848
 849    switch (cf >> 1) {
 850    case 0: /* Never / TR    (0 / 1) */
 851        cond = cond_make_f();
 852        break;
 853    case 1: /* = / <>        (Z / !Z) */
 854        cond = cond_make_0(TCG_COND_EQ, res);
 855        break;
 856    case 2: /* < / >=        (N ^ V / !(N ^ V) */
 857        tmp = tcg_temp_new();
 858        tcg_gen_xor_reg(tmp, res, sv);
 859        cond = cond_make_0_tmp(TCG_COND_LT, tmp);
 860        break;
 861    case 3: /* <= / >        (N ^ V) | Z / !((N ^ V) | Z) */
 862        /*
 863         * Simplify:
 864         *   (N ^ V) | Z
 865         *   ((res < 0) ^ (sv < 0)) | !res
 866         *   ((res ^ sv) < 0) | !res
 867         *   (~(res ^ sv) >= 0) | !res
 868         *   !(~(res ^ sv) >> 31) | !res
 869         *   !(~(res ^ sv) >> 31 & res)
 870         */
 871        tmp = tcg_temp_new();
 872        tcg_gen_eqv_reg(tmp, res, sv);
 873        tcg_gen_sari_reg(tmp, tmp, TARGET_REGISTER_BITS - 1);
 874        tcg_gen_and_reg(tmp, tmp, res);
 875        cond = cond_make_0_tmp(TCG_COND_EQ, tmp);
 876        break;
 877    case 4: /* NUV / UV      (!C / C) */
 878        cond = cond_make_0(TCG_COND_EQ, cb_msb);
 879        break;
 880    case 5: /* ZNV / VNZ     (!C | Z / C & !Z) */
 881        tmp = tcg_temp_new();
 882        tcg_gen_neg_reg(tmp, cb_msb);
 883        tcg_gen_and_reg(tmp, tmp, res);
 884        cond = cond_make_0_tmp(TCG_COND_EQ, tmp);
 885        break;
 886    case 6: /* SV / NSV      (V / !V) */
 887        cond = cond_make_0(TCG_COND_LT, sv);
 888        break;
 889    case 7: /* OD / EV */
 890        tmp = tcg_temp_new();
 891        tcg_gen_andi_reg(tmp, res, 1);
 892        cond = cond_make_0_tmp(TCG_COND_NE, tmp);
 893        break;
 894    default:
 895        g_assert_not_reached();
 896    }
 897    if (cf & 1) {
 898        cond.c = tcg_invert_cond(cond.c);
 899    }
 900
 901    return cond;
 902}
 903
 904/* Similar, but for the special case of subtraction without borrow, we
 905   can use the inputs directly.  This can allow other computation to be
 906   deleted as unused.  */
 907
 908static DisasCond do_sub_cond(unsigned cf, TCGv_reg res,
 909                             TCGv_reg in1, TCGv_reg in2, TCGv_reg sv)
 910{
 911    DisasCond cond;
 912
 913    switch (cf >> 1) {
 914    case 1: /* = / <> */
 915        cond = cond_make(TCG_COND_EQ, in1, in2);
 916        break;
 917    case 2: /* < / >= */
 918        cond = cond_make(TCG_COND_LT, in1, in2);
 919        break;
 920    case 3: /* <= / > */
 921        cond = cond_make(TCG_COND_LE, in1, in2);
 922        break;
 923    case 4: /* << / >>= */
 924        cond = cond_make(TCG_COND_LTU, in1, in2);
 925        break;
 926    case 5: /* <<= / >> */
 927        cond = cond_make(TCG_COND_LEU, in1, in2);
 928        break;
 929    default:
 930        return do_cond(cf, res, NULL, sv);
 931    }
 932    if (cf & 1) {
 933        cond.c = tcg_invert_cond(cond.c);
 934    }
 935
 936    return cond;
 937}
 938
 939/*
 940 * Similar, but for logicals, where the carry and overflow bits are not
 941 * computed, and use of them is undefined.
 942 *
 943 * Undefined or not, hardware does not trap.  It seems reasonable to
 944 * assume hardware treats cases c={4,5,6} as if C=0 & V=0, since that's
 945 * how cases c={2,3} are treated.
 946 */
 947
 948static DisasCond do_log_cond(unsigned cf, TCGv_reg res)
 949{
 950    switch (cf) {
 951    case 0:  /* never */
 952    case 9:  /* undef, C */
 953    case 11: /* undef, C & !Z */
 954    case 12: /* undef, V */
 955        return cond_make_f();
 956
 957    case 1:  /* true */
 958    case 8:  /* undef, !C */
 959    case 10: /* undef, !C | Z */
 960    case 13: /* undef, !V */
 961        return cond_make_t();
 962
 963    case 2:  /* == */
 964        return cond_make_0(TCG_COND_EQ, res);
 965    case 3:  /* <> */
 966        return cond_make_0(TCG_COND_NE, res);
 967    case 4:  /* < */
 968        return cond_make_0(TCG_COND_LT, res);
 969    case 5:  /* >= */
 970        return cond_make_0(TCG_COND_GE, res);
 971    case 6:  /* <= */
 972        return cond_make_0(TCG_COND_LE, res);
 973    case 7:  /* > */
 974        return cond_make_0(TCG_COND_GT, res);
 975
 976    case 14: /* OD */
 977    case 15: /* EV */
 978        return do_cond(cf, res, NULL, NULL);
 979
 980    default:
 981        g_assert_not_reached();
 982    }
 983}
 984
 985/* Similar, but for shift/extract/deposit conditions.  */
 986
 987static DisasCond do_sed_cond(unsigned orig, TCGv_reg res)
 988{
 989    unsigned c, f;
 990
 991    /* Convert the compressed condition codes to standard.
 992       0-2 are the same as logicals (nv,<,<=), while 3 is OD.
 993       4-7 are the reverse of 0-3.  */
 994    c = orig & 3;
 995    if (c == 3) {
 996        c = 7;
 997    }
 998    f = (orig & 4) / 4;
 999
1000    return do_log_cond(c * 2 + f, res);
1001}
1002
1003/* Similar, but for unit conditions.  */
1004
1005static DisasCond do_unit_cond(unsigned cf, TCGv_reg res,
1006                              TCGv_reg in1, TCGv_reg in2)
1007{
1008    DisasCond cond;
1009    TCGv_reg tmp, cb = NULL;
1010
1011    if (cf & 8) {
1012        /* Since we want to test lots of carry-out bits all at once, do not
1013         * do our normal thing and compute carry-in of bit B+1 since that
1014         * leaves us with carry bits spread across two words.
1015         */
1016        cb = tcg_temp_new();
1017        tmp = tcg_temp_new();
1018        tcg_gen_or_reg(cb, in1, in2);
1019        tcg_gen_and_reg(tmp, in1, in2);
1020        tcg_gen_andc_reg(cb, cb, res);
1021        tcg_gen_or_reg(cb, cb, tmp);
1022        tcg_temp_free(tmp);
1023    }
1024
1025    switch (cf >> 1) {
1026    case 0: /* never / TR */
1027    case 1: /* undefined */
1028    case 5: /* undefined */
1029        cond = cond_make_f();
1030        break;
1031
1032    case 2: /* SBZ / NBZ */
1033        /* See hasless(v,1) from
1034         * https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord
1035         */
1036        tmp = tcg_temp_new();
1037        tcg_gen_subi_reg(tmp, res, 0x01010101u);
1038        tcg_gen_andc_reg(tmp, tmp, res);
1039        tcg_gen_andi_reg(tmp, tmp, 0x80808080u);
1040        cond = cond_make_0(TCG_COND_NE, tmp);
1041        tcg_temp_free(tmp);
1042        break;
1043
1044    case 3: /* SHZ / NHZ */
1045        tmp = tcg_temp_new();
1046        tcg_gen_subi_reg(tmp, res, 0x00010001u);
1047        tcg_gen_andc_reg(tmp, tmp, res);
1048        tcg_gen_andi_reg(tmp, tmp, 0x80008000u);
1049        cond = cond_make_0(TCG_COND_NE, tmp);
1050        tcg_temp_free(tmp);
1051        break;
1052
1053    case 4: /* SDC / NDC */
1054        tcg_gen_andi_reg(cb, cb, 0x88888888u);
1055        cond = cond_make_0(TCG_COND_NE, cb);
1056        break;
1057
1058    case 6: /* SBC / NBC */
1059        tcg_gen_andi_reg(cb, cb, 0x80808080u);
1060        cond = cond_make_0(TCG_COND_NE, cb);
1061        break;
1062
1063    case 7: /* SHC / NHC */
1064        tcg_gen_andi_reg(cb, cb, 0x80008000u);
1065        cond = cond_make_0(TCG_COND_NE, cb);
1066        break;
1067
1068    default:
1069        g_assert_not_reached();
1070    }
1071    if (cf & 8) {
1072        tcg_temp_free(cb);
1073    }
1074    if (cf & 1) {
1075        cond.c = tcg_invert_cond(cond.c);
1076    }
1077
1078    return cond;
1079}
1080
1081/* Compute signed overflow for addition.  */
1082static TCGv_reg do_add_sv(DisasContext *ctx, TCGv_reg res,
1083                          TCGv_reg in1, TCGv_reg in2)
1084{
1085    TCGv_reg sv = get_temp(ctx);
1086    TCGv_reg tmp = tcg_temp_new();
1087
1088    tcg_gen_xor_reg(sv, res, in1);
1089    tcg_gen_xor_reg(tmp, in1, in2);
1090    tcg_gen_andc_reg(sv, sv, tmp);
1091    tcg_temp_free(tmp);
1092
1093    return sv;
1094}
1095
1096/* Compute signed overflow for subtraction.  */
1097static TCGv_reg do_sub_sv(DisasContext *ctx, TCGv_reg res,
1098                          TCGv_reg in1, TCGv_reg in2)
1099{
1100    TCGv_reg sv = get_temp(ctx);
1101    TCGv_reg tmp = tcg_temp_new();
1102
1103    tcg_gen_xor_reg(sv, res, in1);
1104    tcg_gen_xor_reg(tmp, in1, in2);
1105    tcg_gen_and_reg(sv, sv, tmp);
1106    tcg_temp_free(tmp);
1107
1108    return sv;
1109}
1110
1111static void do_add(DisasContext *ctx, unsigned rt, TCGv_reg in1,
1112                   TCGv_reg in2, unsigned shift, bool is_l,
1113                   bool is_tsv, bool is_tc, bool is_c, unsigned cf)
1114{
1115    TCGv_reg dest, cb, cb_msb, sv, tmp;
1116    unsigned c = cf >> 1;
1117    DisasCond cond;
1118
1119    dest = tcg_temp_new();
1120    cb = NULL;
1121    cb_msb = NULL;
1122
1123    if (shift) {
1124        tmp = get_temp(ctx);
1125        tcg_gen_shli_reg(tmp, in1, shift);
1126        in1 = tmp;
1127    }
1128
1129    if (!is_l || cond_need_cb(c)) {
1130        TCGv_reg zero = tcg_constant_reg(0);
1131        cb_msb = get_temp(ctx);
1132        tcg_gen_add2_reg(dest, cb_msb, in1, zero, in2, zero);
1133        if (is_c) {
1134            tcg_gen_add2_reg(dest, cb_msb, dest, cb_msb, cpu_psw_cb_msb, zero);
1135        }
1136        if (!is_l) {
1137            cb = get_temp(ctx);
1138            tcg_gen_xor_reg(cb, in1, in2);
1139            tcg_gen_xor_reg(cb, cb, dest);
1140        }
1141    } else {
1142        tcg_gen_add_reg(dest, in1, in2);
1143        if (is_c) {
1144            tcg_gen_add_reg(dest, dest, cpu_psw_cb_msb);
1145        }
1146    }
1147
1148    /* Compute signed overflow if required.  */
1149    sv = NULL;
1150    if (is_tsv || cond_need_sv(c)) {
1151        sv = do_add_sv(ctx, dest, in1, in2);
1152        if (is_tsv) {
1153            /* ??? Need to include overflow from shift.  */
1154            gen_helper_tsv(cpu_env, sv);
1155        }
1156    }
1157
1158    /* Emit any conditional trap before any writeback.  */
1159    cond = do_cond(cf, dest, cb_msb, sv);
1160    if (is_tc) {
1161        tmp = tcg_temp_new();
1162        tcg_gen_setcond_reg(cond.c, tmp, cond.a0, cond.a1);
1163        gen_helper_tcond(cpu_env, tmp);
1164        tcg_temp_free(tmp);
1165    }
1166
1167    /* Write back the result.  */
1168    if (!is_l) {
1169        save_or_nullify(ctx, cpu_psw_cb, cb);
1170        save_or_nullify(ctx, cpu_psw_cb_msb, cb_msb);
1171    }
1172    save_gpr(ctx, rt, dest);
1173    tcg_temp_free(dest);
1174
1175    /* Install the new nullification.  */
1176    cond_free(&ctx->null_cond);
1177    ctx->null_cond = cond;
1178}
1179
1180static bool do_add_reg(DisasContext *ctx, arg_rrr_cf_sh *a,
1181                       bool is_l, bool is_tsv, bool is_tc, bool is_c)
1182{
1183    TCGv_reg tcg_r1, tcg_r2;
1184
1185    if (a->cf) {
1186        nullify_over(ctx);
1187    }
1188    tcg_r1 = load_gpr(ctx, a->r1);
1189    tcg_r2 = load_gpr(ctx, a->r2);
1190    do_add(ctx, a->t, tcg_r1, tcg_r2, a->sh, is_l, is_tsv, is_tc, is_c, a->cf);
1191    return nullify_end(ctx);
1192}
1193
1194static bool do_add_imm(DisasContext *ctx, arg_rri_cf *a,
1195                       bool is_tsv, bool is_tc)
1196{
1197    TCGv_reg tcg_im, tcg_r2;
1198
1199    if (a->cf) {
1200        nullify_over(ctx);
1201    }
1202    tcg_im = load_const(ctx, a->i);
1203    tcg_r2 = load_gpr(ctx, a->r);
1204    do_add(ctx, a->t, tcg_im, tcg_r2, 0, 0, is_tsv, is_tc, 0, a->cf);
1205    return nullify_end(ctx);
1206}
1207
1208static void do_sub(DisasContext *ctx, unsigned rt, TCGv_reg in1,
1209                   TCGv_reg in2, bool is_tsv, bool is_b,
1210                   bool is_tc, unsigned cf)
1211{
1212    TCGv_reg dest, sv, cb, cb_msb, zero, tmp;
1213    unsigned c = cf >> 1;
1214    DisasCond cond;
1215
1216    dest = tcg_temp_new();
1217    cb = tcg_temp_new();
1218    cb_msb = tcg_temp_new();
1219
1220    zero = tcg_constant_reg(0);
1221    if (is_b) {
1222        /* DEST,C = IN1 + ~IN2 + C.  */
1223        tcg_gen_not_reg(cb, in2);
1224        tcg_gen_add2_reg(dest, cb_msb, in1, zero, cpu_psw_cb_msb, zero);
1225        tcg_gen_add2_reg(dest, cb_msb, dest, cb_msb, cb, zero);
1226        tcg_gen_xor_reg(cb, cb, in1);
1227        tcg_gen_xor_reg(cb, cb, dest);
1228    } else {
1229        /* DEST,C = IN1 + ~IN2 + 1.  We can produce the same result in fewer
1230           operations by seeding the high word with 1 and subtracting.  */
1231        tcg_gen_movi_reg(cb_msb, 1);
1232        tcg_gen_sub2_reg(dest, cb_msb, in1, cb_msb, in2, zero);
1233        tcg_gen_eqv_reg(cb, in1, in2);
1234        tcg_gen_xor_reg(cb, cb, dest);
1235    }
1236
1237    /* Compute signed overflow if required.  */
1238    sv = NULL;
1239    if (is_tsv || cond_need_sv(c)) {
1240        sv = do_sub_sv(ctx, dest, in1, in2);
1241        if (is_tsv) {
1242            gen_helper_tsv(cpu_env, sv);
1243        }
1244    }
1245
1246    /* Compute the condition.  We cannot use the special case for borrow.  */
1247    if (!is_b) {
1248        cond = do_sub_cond(cf, dest, in1, in2, sv);
1249    } else {
1250        cond = do_cond(cf, dest, cb_msb, sv);
1251    }
1252
1253    /* Emit any conditional trap before any writeback.  */
1254    if (is_tc) {
1255        tmp = tcg_temp_new();
1256        tcg_gen_setcond_reg(cond.c, tmp, cond.a0, cond.a1);
1257        gen_helper_tcond(cpu_env, tmp);
1258        tcg_temp_free(tmp);
1259    }
1260
1261    /* Write back the result.  */
1262    save_or_nullify(ctx, cpu_psw_cb, cb);
1263    save_or_nullify(ctx, cpu_psw_cb_msb, cb_msb);
1264    save_gpr(ctx, rt, dest);
1265    tcg_temp_free(dest);
1266    tcg_temp_free(cb);
1267    tcg_temp_free(cb_msb);
1268
1269    /* Install the new nullification.  */
1270    cond_free(&ctx->null_cond);
1271    ctx->null_cond = cond;
1272}
1273
1274static bool do_sub_reg(DisasContext *ctx, arg_rrr_cf *a,
1275                       bool is_tsv, bool is_b, bool is_tc)
1276{
1277    TCGv_reg tcg_r1, tcg_r2;
1278
1279    if (a->cf) {
1280        nullify_over(ctx);
1281    }
1282    tcg_r1 = load_gpr(ctx, a->r1);
1283    tcg_r2 = load_gpr(ctx, a->r2);
1284    do_sub(ctx, a->t, tcg_r1, tcg_r2, is_tsv, is_b, is_tc, a->cf);
1285    return nullify_end(ctx);
1286}
1287
1288static bool do_sub_imm(DisasContext *ctx, arg_rri_cf *a, bool is_tsv)
1289{
1290    TCGv_reg tcg_im, tcg_r2;
1291
1292    if (a->cf) {
1293        nullify_over(ctx);
1294    }
1295    tcg_im = load_const(ctx, a->i);
1296    tcg_r2 = load_gpr(ctx, a->r);
1297    do_sub(ctx, a->t, tcg_im, tcg_r2, is_tsv, 0, 0, a->cf);
1298    return nullify_end(ctx);
1299}
1300
1301static void do_cmpclr(DisasContext *ctx, unsigned rt, TCGv_reg in1,
1302                      TCGv_reg in2, unsigned cf)
1303{
1304    TCGv_reg dest, sv;
1305    DisasCond cond;
1306
1307    dest = tcg_temp_new();
1308    tcg_gen_sub_reg(dest, in1, in2);
1309
1310    /* Compute signed overflow if required.  */
1311    sv = NULL;
1312    if (cond_need_sv(cf >> 1)) {
1313        sv = do_sub_sv(ctx, dest, in1, in2);
1314    }
1315
1316    /* Form the condition for the compare.  */
1317    cond = do_sub_cond(cf, dest, in1, in2, sv);
1318
1319    /* Clear.  */
1320    tcg_gen_movi_reg(dest, 0);
1321    save_gpr(ctx, rt, dest);
1322    tcg_temp_free(dest);
1323
1324    /* Install the new nullification.  */
1325    cond_free(&ctx->null_cond);
1326    ctx->null_cond = cond;
1327}
1328
1329static void do_log(DisasContext *ctx, unsigned rt, TCGv_reg in1,
1330                   TCGv_reg in2, unsigned cf,
1331                   void (*fn)(TCGv_reg, TCGv_reg, TCGv_reg))
1332{
1333    TCGv_reg dest = dest_gpr(ctx, rt);
1334
1335    /* Perform the operation, and writeback.  */
1336    fn(dest, in1, in2);
1337    save_gpr(ctx, rt, dest);
1338
1339    /* Install the new nullification.  */
1340    cond_free(&ctx->null_cond);
1341    if (cf) {
1342        ctx->null_cond = do_log_cond(cf, dest);
1343    }
1344}
1345
1346static bool do_log_reg(DisasContext *ctx, arg_rrr_cf *a,
1347                       void (*fn)(TCGv_reg, TCGv_reg, TCGv_reg))
1348{
1349    TCGv_reg tcg_r1, tcg_r2;
1350
1351    if (a->cf) {
1352        nullify_over(ctx);
1353    }
1354    tcg_r1 = load_gpr(ctx, a->r1);
1355    tcg_r2 = load_gpr(ctx, a->r2);
1356    do_log(ctx, a->t, tcg_r1, tcg_r2, a->cf, fn);
1357    return nullify_end(ctx);
1358}
1359
1360static void do_unit(DisasContext *ctx, unsigned rt, TCGv_reg in1,
1361                    TCGv_reg in2, unsigned cf, bool is_tc,
1362                    void (*fn)(TCGv_reg, TCGv_reg, TCGv_reg))
1363{
1364    TCGv_reg dest;
1365    DisasCond cond;
1366
1367    if (cf == 0) {
1368        dest = dest_gpr(ctx, rt);
1369        fn(dest, in1, in2);
1370        save_gpr(ctx, rt, dest);
1371        cond_free(&ctx->null_cond);
1372    } else {
1373        dest = tcg_temp_new();
1374        fn(dest, in1, in2);
1375
1376        cond = do_unit_cond(cf, dest, in1, in2);
1377
1378        if (is_tc) {
1379            TCGv_reg tmp = tcg_temp_new();
1380            tcg_gen_setcond_reg(cond.c, tmp, cond.a0, cond.a1);
1381            gen_helper_tcond(cpu_env, tmp);
1382            tcg_temp_free(tmp);
1383        }
1384        save_gpr(ctx, rt, dest);
1385
1386        cond_free(&ctx->null_cond);
1387        ctx->null_cond = cond;
1388    }
1389}
1390
1391#ifndef CONFIG_USER_ONLY
1392/* The "normal" usage is SP >= 0, wherein SP == 0 selects the space
1393   from the top 2 bits of the base register.  There are a few system
1394   instructions that have a 3-bit space specifier, for which SR0 is
1395   not special.  To handle this, pass ~SP.  */
1396static TCGv_i64 space_select(DisasContext *ctx, int sp, TCGv_reg base)
1397{
1398    TCGv_ptr ptr;
1399    TCGv_reg tmp;
1400    TCGv_i64 spc;
1401
1402    if (sp != 0) {
1403        if (sp < 0) {
1404            sp = ~sp;
1405        }
1406        spc = get_temp_tl(ctx);
1407        load_spr(ctx, spc, sp);
1408        return spc;
1409    }
1410    if (ctx->tb_flags & TB_FLAG_SR_SAME) {
1411        return cpu_srH;
1412    }
1413
1414    ptr = tcg_temp_new_ptr();
1415    tmp = tcg_temp_new();
1416    spc = get_temp_tl(ctx);
1417
1418    tcg_gen_shri_reg(tmp, base, TARGET_REGISTER_BITS - 5);
1419    tcg_gen_andi_reg(tmp, tmp, 030);
1420    tcg_gen_trunc_reg_ptr(ptr, tmp);
1421    tcg_temp_free(tmp);
1422
1423    tcg_gen_add_ptr(ptr, ptr, cpu_env);
1424    tcg_gen_ld_i64(spc, ptr, offsetof(CPUHPPAState, sr[4]));
1425    tcg_temp_free_ptr(ptr);
1426
1427    return spc;
1428}
1429#endif
1430
1431static void form_gva(DisasContext *ctx, TCGv_tl *pgva, TCGv_reg *pofs,
1432                     unsigned rb, unsigned rx, int scale, target_sreg disp,
1433                     unsigned sp, int modify, bool is_phys)
1434{
1435    TCGv_reg base = load_gpr(ctx, rb);
1436    TCGv_reg ofs;
1437
1438    /* Note that RX is mutually exclusive with DISP.  */
1439    if (rx) {
1440        ofs = get_temp(ctx);
1441        tcg_gen_shli_reg(ofs, cpu_gr[rx], scale);
1442        tcg_gen_add_reg(ofs, ofs, base);
1443    } else if (disp || modify) {
1444        ofs = get_temp(ctx);
1445        tcg_gen_addi_reg(ofs, base, disp);
1446    } else {
1447        ofs = base;
1448    }
1449
1450    *pofs = ofs;
1451#ifdef CONFIG_USER_ONLY
1452    *pgva = (modify <= 0 ? ofs : base);
1453#else
1454    TCGv_tl addr = get_temp_tl(ctx);
1455    tcg_gen_extu_reg_tl(addr, modify <= 0 ? ofs : base);
1456    if (ctx->tb_flags & PSW_W) {
1457        tcg_gen_andi_tl(addr, addr, 0x3fffffffffffffffull);
1458    }
1459    if (!is_phys) {
1460        tcg_gen_or_tl(addr, addr, space_select(ctx, sp, base));
1461    }
1462    *pgva = addr;
1463#endif
1464}
1465
1466/* Emit a memory load.  The modify parameter should be
1467 * < 0 for pre-modify,
1468 * > 0 for post-modify,
1469 * = 0 for no base register update.
1470 */
1471static void do_load_32(DisasContext *ctx, TCGv_i32 dest, unsigned rb,
1472                       unsigned rx, int scale, target_sreg disp,
1473                       unsigned sp, int modify, MemOp mop)
1474{
1475    TCGv_reg ofs;
1476    TCGv_tl addr;
1477
1478    /* Caller uses nullify_over/nullify_end.  */
1479    assert(ctx->null_cond.c == TCG_COND_NEVER);
1480
1481    form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify,
1482             ctx->mmu_idx == MMU_PHYS_IDX);
1483    tcg_gen_qemu_ld_reg(dest, addr, ctx->mmu_idx, mop);
1484    if (modify) {
1485        save_gpr(ctx, rb, ofs);
1486    }
1487}
1488
1489static void do_load_64(DisasContext *ctx, TCGv_i64 dest, unsigned rb,
1490                       unsigned rx, int scale, target_sreg disp,
1491                       unsigned sp, int modify, MemOp mop)
1492{
1493    TCGv_reg ofs;
1494    TCGv_tl addr;
1495
1496    /* Caller uses nullify_over/nullify_end.  */
1497    assert(ctx->null_cond.c == TCG_COND_NEVER);
1498
1499    form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify,
1500             ctx->mmu_idx == MMU_PHYS_IDX);
1501    tcg_gen_qemu_ld_i64(dest, addr, ctx->mmu_idx, mop);
1502    if (modify) {
1503        save_gpr(ctx, rb, ofs);
1504    }
1505}
1506
1507static void do_store_32(DisasContext *ctx, TCGv_i32 src, unsigned rb,
1508                        unsigned rx, int scale, target_sreg disp,
1509                        unsigned sp, int modify, MemOp mop)
1510{
1511    TCGv_reg ofs;
1512    TCGv_tl addr;
1513
1514    /* Caller uses nullify_over/nullify_end.  */
1515    assert(ctx->null_cond.c == TCG_COND_NEVER);
1516
1517    form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify,
1518             ctx->mmu_idx == MMU_PHYS_IDX);
1519    tcg_gen_qemu_st_i32(src, addr, ctx->mmu_idx, mop);
1520    if (modify) {
1521        save_gpr(ctx, rb, ofs);
1522    }
1523}
1524
1525static void do_store_64(DisasContext *ctx, TCGv_i64 src, unsigned rb,
1526                        unsigned rx, int scale, target_sreg disp,
1527                        unsigned sp, int modify, MemOp mop)
1528{
1529    TCGv_reg ofs;
1530    TCGv_tl addr;
1531
1532    /* Caller uses nullify_over/nullify_end.  */
1533    assert(ctx->null_cond.c == TCG_COND_NEVER);
1534
1535    form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify,
1536             ctx->mmu_idx == MMU_PHYS_IDX);
1537    tcg_gen_qemu_st_i64(src, addr, ctx->mmu_idx, mop);
1538    if (modify) {
1539        save_gpr(ctx, rb, ofs);
1540    }
1541}
1542
1543#if TARGET_REGISTER_BITS == 64
1544#define do_load_reg   do_load_64
1545#define do_store_reg  do_store_64
1546#else
1547#define do_load_reg   do_load_32
1548#define do_store_reg  do_store_32
1549#endif
1550
1551static bool do_load(DisasContext *ctx, unsigned rt, unsigned rb,
1552                    unsigned rx, int scale, target_sreg disp,
1553                    unsigned sp, int modify, MemOp mop)
1554{
1555    TCGv_reg dest;
1556
1557    nullify_over(ctx);
1558
1559    if (modify == 0) {
1560        /* No base register update.  */
1561        dest = dest_gpr(ctx, rt);
1562    } else {
1563        /* Make sure if RT == RB, we see the result of the load.  */
1564        dest = get_temp(ctx);
1565    }
1566    do_load_reg(ctx, dest, rb, rx, scale, disp, sp, modify, mop);
1567    save_gpr(ctx, rt, dest);
1568
1569    return nullify_end(ctx);
1570}
1571
1572static bool do_floadw(DisasContext *ctx, unsigned rt, unsigned rb,
1573                      unsigned rx, int scale, target_sreg disp,
1574                      unsigned sp, int modify)
1575{
1576    TCGv_i32 tmp;
1577
1578    nullify_over(ctx);
1579
1580    tmp = tcg_temp_new_i32();
1581    do_load_32(ctx, tmp, rb, rx, scale, disp, sp, modify, MO_TEUL);
1582    save_frw_i32(rt, tmp);
1583    tcg_temp_free_i32(tmp);
1584
1585    if (rt == 0) {
1586        gen_helper_loaded_fr0(cpu_env);
1587    }
1588
1589    return nullify_end(ctx);
1590}
1591
1592static bool trans_fldw(DisasContext *ctx, arg_ldst *a)
1593{
1594    return do_floadw(ctx, a->t, a->b, a->x, a->scale ? 2 : 0,
1595                     a->disp, a->sp, a->m);
1596}
1597
1598static bool do_floadd(DisasContext *ctx, unsigned rt, unsigned rb,
1599                      unsigned rx, int scale, target_sreg disp,
1600                      unsigned sp, int modify)
1601{
1602    TCGv_i64 tmp;
1603
1604    nullify_over(ctx);
1605
1606    tmp = tcg_temp_new_i64();
1607    do_load_64(ctx, tmp, rb, rx, scale, disp, sp, modify, MO_TEQ);
1608    save_frd(rt, tmp);
1609    tcg_temp_free_i64(tmp);
1610
1611    if (rt == 0) {
1612        gen_helper_loaded_fr0(cpu_env);
1613    }
1614
1615    return nullify_end(ctx);
1616}
1617
1618static bool trans_fldd(DisasContext *ctx, arg_ldst *a)
1619{
1620    return do_floadd(ctx, a->t, a->b, a->x, a->scale ? 3 : 0,
1621                     a->disp, a->sp, a->m);
1622}
1623
1624static bool do_store(DisasContext *ctx, unsigned rt, unsigned rb,
1625                     target_sreg disp, unsigned sp,
1626                     int modify, MemOp mop)
1627{
1628    nullify_over(ctx);
1629    do_store_reg(ctx, load_gpr(ctx, rt), rb, 0, 0, disp, sp, modify, mop);
1630    return nullify_end(ctx);
1631}
1632
1633static bool do_fstorew(DisasContext *ctx, unsigned rt, unsigned rb,
1634                       unsigned rx, int scale, target_sreg disp,
1635                       unsigned sp, int modify)
1636{
1637    TCGv_i32 tmp;
1638
1639    nullify_over(ctx);
1640
1641    tmp = load_frw_i32(rt);
1642    do_store_32(ctx, tmp, rb, rx, scale, disp, sp, modify, MO_TEUL);
1643    tcg_temp_free_i32(tmp);
1644
1645    return nullify_end(ctx);
1646}
1647
1648static bool trans_fstw(DisasContext *ctx, arg_ldst *a)
1649{
1650    return do_fstorew(ctx, a->t, a->b, a->x, a->scale ? 2 : 0,
1651                      a->disp, a->sp, a->m);
1652}
1653
1654static bool do_fstored(DisasContext *ctx, unsigned rt, unsigned rb,
1655                       unsigned rx, int scale, target_sreg disp,
1656                       unsigned sp, int modify)
1657{
1658    TCGv_i64 tmp;
1659
1660    nullify_over(ctx);
1661
1662    tmp = load_frd(rt);
1663    do_store_64(ctx, tmp, rb, rx, scale, disp, sp, modify, MO_TEQ);
1664    tcg_temp_free_i64(tmp);
1665
1666    return nullify_end(ctx);
1667}
1668
1669static bool trans_fstd(DisasContext *ctx, arg_ldst *a)
1670{
1671    return do_fstored(ctx, a->t, a->b, a->x, a->scale ? 3 : 0,
1672                      a->disp, a->sp, a->m);
1673}
1674
1675static bool do_fop_wew(DisasContext *ctx, unsigned rt, unsigned ra,
1676                       void (*func)(TCGv_i32, TCGv_env, TCGv_i32))
1677{
1678    TCGv_i32 tmp;
1679
1680    nullify_over(ctx);
1681    tmp = load_frw0_i32(ra);
1682
1683    func(tmp, cpu_env, tmp);
1684
1685    save_frw_i32(rt, tmp);
1686    tcg_temp_free_i32(tmp);
1687    return nullify_end(ctx);
1688}
1689
1690static bool do_fop_wed(DisasContext *ctx, unsigned rt, unsigned ra,
1691                       void (*func)(TCGv_i32, TCGv_env, TCGv_i64))
1692{
1693    TCGv_i32 dst;
1694    TCGv_i64 src;
1695
1696    nullify_over(ctx);
1697    src = load_frd(ra);
1698    dst = tcg_temp_new_i32();
1699
1700    func(dst, cpu_env, src);
1701
1702    tcg_temp_free_i64(src);
1703    save_frw_i32(rt, dst);
1704    tcg_temp_free_i32(dst);
1705    return nullify_end(ctx);
1706}
1707
1708static bool do_fop_ded(DisasContext *ctx, unsigned rt, unsigned ra,
1709                       void (*func)(TCGv_i64, TCGv_env, TCGv_i64))
1710{
1711    TCGv_i64 tmp;
1712
1713    nullify_over(ctx);
1714    tmp = load_frd0(ra);
1715
1716    func(tmp, cpu_env, tmp);
1717
1718    save_frd(rt, tmp);
1719    tcg_temp_free_i64(tmp);
1720    return nullify_end(ctx);
1721}
1722
1723static bool do_fop_dew(DisasContext *ctx, unsigned rt, unsigned ra,
1724                       void (*func)(TCGv_i64, TCGv_env, TCGv_i32))
1725{
1726    TCGv_i32 src;
1727    TCGv_i64 dst;
1728
1729    nullify_over(ctx);
1730    src = load_frw0_i32(ra);
1731    dst = tcg_temp_new_i64();
1732
1733    func(dst, cpu_env, src);
1734
1735    tcg_temp_free_i32(src);
1736    save_frd(rt, dst);
1737    tcg_temp_free_i64(dst);
1738    return nullify_end(ctx);
1739}
1740
1741static bool do_fop_weww(DisasContext *ctx, unsigned rt,
1742                        unsigned ra, unsigned rb,
1743                        void (*func)(TCGv_i32, TCGv_env, TCGv_i32, TCGv_i32))
1744{
1745    TCGv_i32 a, b;
1746
1747    nullify_over(ctx);
1748    a = load_frw0_i32(ra);
1749    b = load_frw0_i32(rb);
1750
1751    func(a, cpu_env, a, b);
1752
1753    tcg_temp_free_i32(b);
1754    save_frw_i32(rt, a);
1755    tcg_temp_free_i32(a);
1756    return nullify_end(ctx);
1757}
1758
1759static bool do_fop_dedd(DisasContext *ctx, unsigned rt,
1760                        unsigned ra, unsigned rb,
1761                        void (*func)(TCGv_i64, TCGv_env, TCGv_i64, TCGv_i64))
1762{
1763    TCGv_i64 a, b;
1764
1765    nullify_over(ctx);
1766    a = load_frd0(ra);
1767    b = load_frd0(rb);
1768
1769    func(a, cpu_env, a, b);
1770
1771    tcg_temp_free_i64(b);
1772    save_frd(rt, a);
1773    tcg_temp_free_i64(a);
1774    return nullify_end(ctx);
1775}
1776
1777/* Emit an unconditional branch to a direct target, which may or may not
1778   have already had nullification handled.  */
1779static bool do_dbranch(DisasContext *ctx, target_ureg dest,
1780                       unsigned link, bool is_n)
1781{
1782    if (ctx->null_cond.c == TCG_COND_NEVER && ctx->null_lab == NULL) {
1783        if (link != 0) {
1784            copy_iaoq_entry(cpu_gr[link], ctx->iaoq_n, ctx->iaoq_n_var);
1785        }
1786        ctx->iaoq_n = dest;
1787        if (is_n) {
1788            ctx->null_cond.c = TCG_COND_ALWAYS;
1789        }
1790    } else {
1791        nullify_over(ctx);
1792
1793        if (link != 0) {
1794            copy_iaoq_entry(cpu_gr[link], ctx->iaoq_n, ctx->iaoq_n_var);
1795        }
1796
1797        if (is_n && use_nullify_skip(ctx)) {
1798            nullify_set(ctx, 0);
1799            gen_goto_tb(ctx, 0, dest, dest + 4);
1800        } else {
1801            nullify_set(ctx, is_n);
1802            gen_goto_tb(ctx, 0, ctx->iaoq_b, dest);
1803        }
1804
1805        nullify_end(ctx);
1806
1807        nullify_set(ctx, 0);
1808        gen_goto_tb(ctx, 1, ctx->iaoq_b, ctx->iaoq_n);
1809        ctx->base.is_jmp = DISAS_NORETURN;
1810    }
1811    return true;
1812}
1813
1814/* Emit a conditional branch to a direct target.  If the branch itself
1815   is nullified, we should have already used nullify_over.  */
1816static bool do_cbranch(DisasContext *ctx, target_sreg disp, bool is_n,
1817                       DisasCond *cond)
1818{
1819    target_ureg dest = iaoq_dest(ctx, disp);
1820    TCGLabel *taken = NULL;
1821    TCGCond c = cond->c;
1822    bool n;
1823
1824    assert(ctx->null_cond.c == TCG_COND_NEVER);
1825
1826    /* Handle TRUE and NEVER as direct branches.  */
1827    if (c == TCG_COND_ALWAYS) {
1828        return do_dbranch(ctx, dest, 0, is_n && disp >= 0);
1829    }
1830    if (c == TCG_COND_NEVER) {
1831        return do_dbranch(ctx, ctx->iaoq_n, 0, is_n && disp < 0);
1832    }
1833
1834    taken = gen_new_label();
1835    tcg_gen_brcond_reg(c, cond->a0, cond->a1, taken);
1836    cond_free(cond);
1837
1838    /* Not taken: Condition not satisfied; nullify on backward branches. */
1839    n = is_n && disp < 0;
1840    if (n && use_nullify_skip(ctx)) {
1841        nullify_set(ctx, 0);
1842        gen_goto_tb(ctx, 0, ctx->iaoq_n, ctx->iaoq_n + 4);
1843    } else {
1844        if (!n && ctx->null_lab) {
1845            gen_set_label(ctx->null_lab);
1846            ctx->null_lab = NULL;
1847        }
1848        nullify_set(ctx, n);
1849        if (ctx->iaoq_n == -1) {
1850            /* The temporary iaoq_n_var died at the branch above.
1851               Regenerate it here instead of saving it.  */
1852            tcg_gen_addi_reg(ctx->iaoq_n_var, cpu_iaoq_b, 4);
1853        }
1854        gen_goto_tb(ctx, 0, ctx->iaoq_b, ctx->iaoq_n);
1855    }
1856
1857    gen_set_label(taken);
1858
1859    /* Taken: Condition satisfied; nullify on forward branches.  */
1860    n = is_n && disp >= 0;
1861    if (n && use_nullify_skip(ctx)) {
1862        nullify_set(ctx, 0);
1863        gen_goto_tb(ctx, 1, dest, dest + 4);
1864    } else {
1865        nullify_set(ctx, n);
1866        gen_goto_tb(ctx, 1, ctx->iaoq_b, dest);
1867    }
1868
1869    /* Not taken: the branch itself was nullified.  */
1870    if (ctx->null_lab) {
1871        gen_set_label(ctx->null_lab);
1872        ctx->null_lab = NULL;
1873        ctx->base.is_jmp = DISAS_IAQ_N_STALE;
1874    } else {
1875        ctx->base.is_jmp = DISAS_NORETURN;
1876    }
1877    return true;
1878}
1879
1880/* Emit an unconditional branch to an indirect target.  This handles
1881   nullification of the branch itself.  */
1882static bool do_ibranch(DisasContext *ctx, TCGv_reg dest,
1883                       unsigned link, bool is_n)
1884{
1885    TCGv_reg a0, a1, next, tmp;
1886    TCGCond c;
1887
1888    assert(ctx->null_lab == NULL);
1889
1890    if (ctx->null_cond.c == TCG_COND_NEVER) {
1891        if (link != 0) {
1892            copy_iaoq_entry(cpu_gr[link], ctx->iaoq_n, ctx->iaoq_n_var);
1893        }
1894        next = get_temp(ctx);
1895        tcg_gen_mov_reg(next, dest);
1896        if (is_n) {
1897            if (use_nullify_skip(ctx)) {
1898                tcg_gen_mov_reg(cpu_iaoq_f, next);
1899                tcg_gen_addi_reg(cpu_iaoq_b, next, 4);
1900                nullify_set(ctx, 0);
1901                ctx->base.is_jmp = DISAS_IAQ_N_UPDATED;
1902                return true;
1903            }
1904            ctx->null_cond.c = TCG_COND_ALWAYS;
1905        }
1906        ctx->iaoq_n = -1;
1907        ctx->iaoq_n_var = next;
1908    } else if (is_n && use_nullify_skip(ctx)) {
1909        /* The (conditional) branch, B, nullifies the next insn, N,
1910           and we're allowed to skip execution N (no single-step or
1911           tracepoint in effect).  Since the goto_ptr that we must use
1912           for the indirect branch consumes no special resources, we
1913           can (conditionally) skip B and continue execution.  */
1914        /* The use_nullify_skip test implies we have a known control path.  */
1915        tcg_debug_assert(ctx->iaoq_b != -1);
1916        tcg_debug_assert(ctx->iaoq_n != -1);
1917
1918        /* We do have to handle the non-local temporary, DEST, before
1919           branching.  Since IOAQ_F is not really live at this point, we
1920           can simply store DEST optimistically.  Similarly with IAOQ_B.  */
1921        tcg_gen_mov_reg(cpu_iaoq_f, dest);
1922        tcg_gen_addi_reg(cpu_iaoq_b, dest, 4);
1923
1924        nullify_over(ctx);
1925        if (link != 0) {
1926            tcg_gen_movi_reg(cpu_gr[link], ctx->iaoq_n);
1927        }
1928        tcg_gen_lookup_and_goto_ptr();
1929        return nullify_end(ctx);
1930    } else {
1931        c = ctx->null_cond.c;
1932        a0 = ctx->null_cond.a0;
1933        a1 = ctx->null_cond.a1;
1934
1935        tmp = tcg_temp_new();
1936        next = get_temp(ctx);
1937
1938        copy_iaoq_entry(tmp, ctx->iaoq_n, ctx->iaoq_n_var);
1939        tcg_gen_movcond_reg(c, next, a0, a1, tmp, dest);
1940        ctx->iaoq_n = -1;
1941        ctx->iaoq_n_var = next;
1942
1943        if (link != 0) {
1944            tcg_gen_movcond_reg(c, cpu_gr[link], a0, a1, cpu_gr[link], tmp);
1945        }
1946
1947        if (is_n) {
1948            /* The branch nullifies the next insn, which means the state of N
1949               after the branch is the inverse of the state of N that applied
1950               to the branch.  */
1951            tcg_gen_setcond_reg(tcg_invert_cond(c), cpu_psw_n, a0, a1);
1952            cond_free(&ctx->null_cond);
1953            ctx->null_cond = cond_make_n();
1954            ctx->psw_n_nonzero = true;
1955        } else {
1956            cond_free(&ctx->null_cond);
1957        }
1958    }
1959    return true;
1960}
1961
1962/* Implement
1963 *    if (IAOQ_Front{30..31} < GR[b]{30..31})
1964 *      IAOQ_Next{30..31} ← GR[b]{30..31};
1965 *    else
1966 *      IAOQ_Next{30..31} ← IAOQ_Front{30..31};
1967 * which keeps the privilege level from being increased.
1968 */
1969static TCGv_reg do_ibranch_priv(DisasContext *ctx, TCGv_reg offset)
1970{
1971    TCGv_reg dest;
1972    switch (ctx->privilege) {
1973    case 0:
1974        /* Privilege 0 is maximum and is allowed to decrease.  */
1975        return offset;
1976    case 3:
1977        /* Privilege 3 is minimum and is never allowed to increase.  */
1978        dest = get_temp(ctx);
1979        tcg_gen_ori_reg(dest, offset, 3);
1980        break;
1981    default:
1982        dest = get_temp(ctx);
1983        tcg_gen_andi_reg(dest, offset, -4);
1984        tcg_gen_ori_reg(dest, dest, ctx->privilege);
1985        tcg_gen_movcond_reg(TCG_COND_GTU, dest, dest, offset, dest, offset);
1986        break;
1987    }
1988    return dest;
1989}
1990
1991#ifdef CONFIG_USER_ONLY
1992/* On Linux, page zero is normally marked execute only + gateway.
1993   Therefore normal read or write is supposed to fail, but specific
1994   offsets have kernel code mapped to raise permissions to implement
1995   system calls.  Handling this via an explicit check here, rather
1996   in than the "be disp(sr2,r0)" instruction that probably sent us
1997   here, is the easiest way to handle the branch delay slot on the
1998   aforementioned BE.  */
1999static void do_page_zero(DisasContext *ctx)
2000{
2001    /* If by some means we get here with PSW[N]=1, that implies that
2002       the B,GATE instruction would be skipped, and we'd fault on the
2003       next insn within the privilaged page.  */
2004    switch (ctx->null_cond.c) {
2005    case TCG_COND_NEVER:
2006        break;
2007    case TCG_COND_ALWAYS:
2008        tcg_gen_movi_reg(cpu_psw_n, 0);
2009        goto do_sigill;
2010    default:
2011        /* Since this is always the first (and only) insn within the
2012           TB, we should know the state of PSW[N] from TB->FLAGS.  */
2013        g_assert_not_reached();
2014    }
2015
2016    /* Check that we didn't arrive here via some means that allowed
2017       non-sequential instruction execution.  Normally the PSW[B] bit
2018       detects this by disallowing the B,GATE instruction to execute
2019       under such conditions.  */
2020    if (ctx->iaoq_b != ctx->iaoq_f + 4) {
2021        goto do_sigill;
2022    }
2023
2024    switch (ctx->iaoq_f & -4) {
2025    case 0x00: /* Null pointer call */
2026        gen_excp_1(EXCP_IMP);
2027        ctx->base.is_jmp = DISAS_NORETURN;
2028        break;
2029
2030    case 0xb0: /* LWS */
2031        gen_excp_1(EXCP_SYSCALL_LWS);
2032        ctx->base.is_jmp = DISAS_NORETURN;
2033        break;
2034
2035    case 0xe0: /* SET_THREAD_POINTER */
2036        tcg_gen_st_reg(cpu_gr[26], cpu_env, offsetof(CPUHPPAState, cr[27]));
2037        tcg_gen_ori_reg(cpu_iaoq_f, cpu_gr[31], 3);
2038        tcg_gen_addi_reg(cpu_iaoq_b, cpu_iaoq_f, 4);
2039        ctx->base.is_jmp = DISAS_IAQ_N_UPDATED;
2040        break;
2041
2042    case 0x100: /* SYSCALL */
2043        gen_excp_1(EXCP_SYSCALL);
2044        ctx->base.is_jmp = DISAS_NORETURN;
2045        break;
2046
2047    default:
2048    do_sigill:
2049        gen_excp_1(EXCP_ILL);
2050        ctx->base.is_jmp = DISAS_NORETURN;
2051        break;
2052    }
2053}
2054#endif
2055
2056static bool trans_nop(DisasContext *ctx, arg_nop *a)
2057{
2058    cond_free(&ctx->null_cond);
2059    return true;
2060}
2061
2062static bool trans_break(DisasContext *ctx, arg_break *a)
2063{
2064    return gen_excp_iir(ctx, EXCP_BREAK);
2065}
2066
2067static bool trans_sync(DisasContext *ctx, arg_sync *a)
2068{
2069    /* No point in nullifying the memory barrier.  */
2070    tcg_gen_mb(TCG_BAR_SC | TCG_MO_ALL);
2071
2072    cond_free(&ctx->null_cond);
2073    return true;
2074}
2075
2076static bool trans_mfia(DisasContext *ctx, arg_mfia *a)
2077{
2078    unsigned rt = a->t;
2079    TCGv_reg tmp = dest_gpr(ctx, rt);
2080    tcg_gen_movi_reg(tmp, ctx->iaoq_f);
2081    save_gpr(ctx, rt, tmp);
2082
2083    cond_free(&ctx->null_cond);
2084    return true;
2085}
2086
2087static bool trans_mfsp(DisasContext *ctx, arg_mfsp *a)
2088{
2089    unsigned rt = a->t;
2090    unsigned rs = a->sp;
2091    TCGv_i64 t0 = tcg_temp_new_i64();
2092    TCGv_reg t1 = tcg_temp_new();
2093
2094    load_spr(ctx, t0, rs);
2095    tcg_gen_shri_i64(t0, t0, 32);
2096    tcg_gen_trunc_i64_reg(t1, t0);
2097
2098    save_gpr(ctx, rt, t1);
2099    tcg_temp_free(t1);
2100    tcg_temp_free_i64(t0);
2101
2102    cond_free(&ctx->null_cond);
2103    return true;
2104}
2105
2106static bool trans_mfctl(DisasContext *ctx, arg_mfctl *a)
2107{
2108    unsigned rt = a->t;
2109    unsigned ctl = a->r;
2110    TCGv_reg tmp;
2111
2112    switch (ctl) {
2113    case CR_SAR:
2114#ifdef TARGET_HPPA64
2115        if (a->e == 0) {
2116            /* MFSAR without ,W masks low 5 bits.  */
2117            tmp = dest_gpr(ctx, rt);
2118            tcg_gen_andi_reg(tmp, cpu_sar, 31);
2119            save_gpr(ctx, rt, tmp);
2120            goto done;
2121        }
2122#endif
2123        save_gpr(ctx, rt, cpu_sar);
2124        goto done;
2125    case CR_IT: /* Interval Timer */
2126        /* FIXME: Respect PSW_S bit.  */
2127        nullify_over(ctx);
2128        tmp = dest_gpr(ctx, rt);
2129        if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
2130            gen_io_start();
2131            gen_helper_read_interval_timer(tmp);
2132            ctx->base.is_jmp = DISAS_IAQ_N_STALE;
2133        } else {
2134            gen_helper_read_interval_timer(tmp);
2135        }
2136        save_gpr(ctx, rt, tmp);
2137        return nullify_end(ctx);
2138    case 26:
2139    case 27:
2140        break;
2141    default:
2142        /* All other control registers are privileged.  */
2143        CHECK_MOST_PRIVILEGED(EXCP_PRIV_REG);
2144        break;
2145    }
2146
2147    tmp = get_temp(ctx);
2148    tcg_gen_ld_reg(tmp, cpu_env, offsetof(CPUHPPAState, cr[ctl]));
2149    save_gpr(ctx, rt, tmp);
2150
2151 done:
2152    cond_free(&ctx->null_cond);
2153    return true;
2154}
2155
2156static bool trans_mtsp(DisasContext *ctx, arg_mtsp *a)
2157{
2158    unsigned rr = a->r;
2159    unsigned rs = a->sp;
2160    TCGv_i64 t64;
2161
2162    if (rs >= 5) {
2163        CHECK_MOST_PRIVILEGED(EXCP_PRIV_REG);
2164    }
2165    nullify_over(ctx);
2166
2167    t64 = tcg_temp_new_i64();
2168    tcg_gen_extu_reg_i64(t64, load_gpr(ctx, rr));
2169    tcg_gen_shli_i64(t64, t64, 32);
2170
2171    if (rs >= 4) {
2172        tcg_gen_st_i64(t64, cpu_env, offsetof(CPUHPPAState, sr[rs]));
2173        ctx->tb_flags &= ~TB_FLAG_SR_SAME;
2174    } else {
2175        tcg_gen_mov_i64(cpu_sr[rs], t64);
2176    }
2177    tcg_temp_free_i64(t64);
2178
2179    return nullify_end(ctx);
2180}
2181
2182static bool trans_mtctl(DisasContext *ctx, arg_mtctl *a)
2183{
2184    unsigned ctl = a->t;
2185    TCGv_reg reg;
2186    TCGv_reg tmp;
2187
2188    if (ctl == CR_SAR) {
2189        reg = load_gpr(ctx, a->r);
2190        tmp = tcg_temp_new();
2191        tcg_gen_andi_reg(tmp, reg, TARGET_REGISTER_BITS - 1);
2192        save_or_nullify(ctx, cpu_sar, tmp);
2193        tcg_temp_free(tmp);
2194
2195        cond_free(&ctx->null_cond);
2196        return true;
2197    }
2198
2199    /* All other control registers are privileged or read-only.  */
2200    CHECK_MOST_PRIVILEGED(EXCP_PRIV_REG);
2201
2202#ifndef CONFIG_USER_ONLY
2203    nullify_over(ctx);
2204    reg = load_gpr(ctx, a->r);
2205
2206    switch (ctl) {
2207    case CR_IT:
2208        gen_helper_write_interval_timer(cpu_env, reg);
2209        break;
2210    case CR_EIRR:
2211        gen_helper_write_eirr(cpu_env, reg);
2212        break;
2213    case CR_EIEM:
2214        gen_helper_write_eiem(cpu_env, reg);
2215        ctx->base.is_jmp = DISAS_IAQ_N_STALE_EXIT;
2216        break;
2217
2218    case CR_IIASQ:
2219    case CR_IIAOQ:
2220        /* FIXME: Respect PSW_Q bit */
2221        /* The write advances the queue and stores to the back element.  */
2222        tmp = get_temp(ctx);
2223        tcg_gen_ld_reg(tmp, cpu_env,
2224                       offsetof(CPUHPPAState, cr_back[ctl - CR_IIASQ]));
2225        tcg_gen_st_reg(tmp, cpu_env, offsetof(CPUHPPAState, cr[ctl]));
2226        tcg_gen_st_reg(reg, cpu_env,
2227                       offsetof(CPUHPPAState, cr_back[ctl - CR_IIASQ]));
2228        break;
2229
2230    case CR_PID1:
2231    case CR_PID2:
2232    case CR_PID3:
2233    case CR_PID4:
2234        tcg_gen_st_reg(reg, cpu_env, offsetof(CPUHPPAState, cr[ctl]));
2235#ifndef CONFIG_USER_ONLY
2236        gen_helper_change_prot_id(cpu_env);
2237#endif
2238        break;
2239
2240    default:
2241        tcg_gen_st_reg(reg, cpu_env, offsetof(CPUHPPAState, cr[ctl]));
2242        break;
2243    }
2244    return nullify_end(ctx);
2245#endif
2246}
2247
2248static bool trans_mtsarcm(DisasContext *ctx, arg_mtsarcm *a)
2249{
2250    TCGv_reg tmp = tcg_temp_new();
2251
2252    tcg_gen_not_reg(tmp, load_gpr(ctx, a->r));
2253    tcg_gen_andi_reg(tmp, tmp, TARGET_REGISTER_BITS - 1);
2254    save_or_nullify(ctx, cpu_sar, tmp);
2255    tcg_temp_free(tmp);
2256
2257    cond_free(&ctx->null_cond);
2258    return true;
2259}
2260
2261static bool trans_ldsid(DisasContext *ctx, arg_ldsid *a)
2262{
2263    TCGv_reg dest = dest_gpr(ctx, a->t);
2264
2265#ifdef CONFIG_USER_ONLY
2266    /* We don't implement space registers in user mode. */
2267    tcg_gen_movi_reg(dest, 0);
2268#else
2269    TCGv_i64 t0 = tcg_temp_new_i64();
2270
2271    tcg_gen_mov_i64(t0, space_select(ctx, a->sp, load_gpr(ctx, a->b)));
2272    tcg_gen_shri_i64(t0, t0, 32);
2273    tcg_gen_trunc_i64_reg(dest, t0);
2274
2275    tcg_temp_free_i64(t0);
2276#endif
2277    save_gpr(ctx, a->t, dest);
2278
2279    cond_free(&ctx->null_cond);
2280    return true;
2281}
2282
2283static bool trans_rsm(DisasContext *ctx, arg_rsm *a)
2284{
2285    CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2286#ifndef CONFIG_USER_ONLY
2287    TCGv_reg tmp;
2288
2289    nullify_over(ctx);
2290
2291    tmp = get_temp(ctx);
2292    tcg_gen_ld_reg(tmp, cpu_env, offsetof(CPUHPPAState, psw));
2293    tcg_gen_andi_reg(tmp, tmp, ~a->i);
2294    gen_helper_swap_system_mask(tmp, cpu_env, tmp);
2295    save_gpr(ctx, a->t, tmp);
2296
2297    /* Exit the TB to recognize new interrupts, e.g. PSW_M.  */
2298    ctx->base.is_jmp = DISAS_IAQ_N_STALE_EXIT;
2299    return nullify_end(ctx);
2300#endif
2301}
2302
2303static bool trans_ssm(DisasContext *ctx, arg_ssm *a)
2304{
2305    CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2306#ifndef CONFIG_USER_ONLY
2307    TCGv_reg tmp;
2308
2309    nullify_over(ctx);
2310
2311    tmp = get_temp(ctx);
2312    tcg_gen_ld_reg(tmp, cpu_env, offsetof(CPUHPPAState, psw));
2313    tcg_gen_ori_reg(tmp, tmp, a->i);
2314    gen_helper_swap_system_mask(tmp, cpu_env, tmp);
2315    save_gpr(ctx, a->t, tmp);
2316
2317    /* Exit the TB to recognize new interrupts, e.g. PSW_I.  */
2318    ctx->base.is_jmp = DISAS_IAQ_N_STALE_EXIT;
2319    return nullify_end(ctx);
2320#endif
2321}
2322
2323static bool trans_mtsm(DisasContext *ctx, arg_mtsm *a)
2324{
2325    CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2326#ifndef CONFIG_USER_ONLY
2327    TCGv_reg tmp, reg;
2328    nullify_over(ctx);
2329
2330    reg = load_gpr(ctx, a->r);
2331    tmp = get_temp(ctx);
2332    gen_helper_swap_system_mask(tmp, cpu_env, reg);
2333
2334    /* Exit the TB to recognize new interrupts.  */
2335    ctx->base.is_jmp = DISAS_IAQ_N_STALE_EXIT;
2336    return nullify_end(ctx);
2337#endif
2338}
2339
2340static bool do_rfi(DisasContext *ctx, bool rfi_r)
2341{
2342    CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2343#ifndef CONFIG_USER_ONLY
2344    nullify_over(ctx);
2345
2346    if (rfi_r) {
2347        gen_helper_rfi_r(cpu_env);
2348    } else {
2349        gen_helper_rfi(cpu_env);
2350    }
2351    /* Exit the TB to recognize new interrupts.  */
2352    if (ctx->base.singlestep_enabled) {
2353        gen_excp_1(EXCP_DEBUG);
2354    } else {
2355        tcg_gen_exit_tb(NULL, 0);
2356    }
2357    ctx->base.is_jmp = DISAS_NORETURN;
2358
2359    return nullify_end(ctx);
2360#endif
2361}
2362
2363static bool trans_rfi(DisasContext *ctx, arg_rfi *a)
2364{
2365    return do_rfi(ctx, false);
2366}
2367
2368static bool trans_rfi_r(DisasContext *ctx, arg_rfi_r *a)
2369{
2370    return do_rfi(ctx, true);
2371}
2372
2373static bool trans_halt(DisasContext *ctx, arg_halt *a)
2374{
2375    CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2376#ifndef CONFIG_USER_ONLY
2377    nullify_over(ctx);
2378    gen_helper_halt(cpu_env);
2379    ctx->base.is_jmp = DISAS_NORETURN;
2380    return nullify_end(ctx);
2381#endif
2382}
2383
2384static bool trans_reset(DisasContext *ctx, arg_reset *a)
2385{
2386    CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2387#ifndef CONFIG_USER_ONLY
2388    nullify_over(ctx);
2389    gen_helper_reset(cpu_env);
2390    ctx->base.is_jmp = DISAS_NORETURN;
2391    return nullify_end(ctx);
2392#endif
2393}
2394
2395static bool trans_nop_addrx(DisasContext *ctx, arg_ldst *a)
2396{
2397    if (a->m) {
2398        TCGv_reg dest = dest_gpr(ctx, a->b);
2399        TCGv_reg src1 = load_gpr(ctx, a->b);
2400        TCGv_reg src2 = load_gpr(ctx, a->x);
2401
2402        /* The only thing we need to do is the base register modification.  */
2403        tcg_gen_add_reg(dest, src1, src2);
2404        save_gpr(ctx, a->b, dest);
2405    }
2406    cond_free(&ctx->null_cond);
2407    return true;
2408}
2409
2410static bool trans_probe(DisasContext *ctx, arg_probe *a)
2411{
2412    TCGv_reg dest, ofs;
2413    TCGv_i32 level, want;
2414    TCGv_tl addr;
2415
2416    nullify_over(ctx);
2417
2418    dest = dest_gpr(ctx, a->t);
2419    form_gva(ctx, &addr, &ofs, a->b, 0, 0, 0, a->sp, 0, false);
2420
2421    if (a->imm) {
2422        level = tcg_constant_i32(a->ri);
2423    } else {
2424        level = tcg_temp_new_i32();
2425        tcg_gen_trunc_reg_i32(level, load_gpr(ctx, a->ri));
2426        tcg_gen_andi_i32(level, level, 3);
2427    }
2428    want = tcg_constant_i32(a->write ? PAGE_WRITE : PAGE_READ);
2429
2430    gen_helper_probe(dest, cpu_env, addr, level, want);
2431
2432    tcg_temp_free_i32(level);
2433
2434    save_gpr(ctx, a->t, dest);
2435    return nullify_end(ctx);
2436}
2437
2438static bool trans_ixtlbx(DisasContext *ctx, arg_ixtlbx *a)
2439{
2440    CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2441#ifndef CONFIG_USER_ONLY
2442    TCGv_tl addr;
2443    TCGv_reg ofs, reg;
2444
2445    nullify_over(ctx);
2446
2447    form_gva(ctx, &addr, &ofs, a->b, 0, 0, 0, a->sp, 0, false);
2448    reg = load_gpr(ctx, a->r);
2449    if (a->addr) {
2450        gen_helper_itlba(cpu_env, addr, reg);
2451    } else {
2452        gen_helper_itlbp(cpu_env, addr, reg);
2453    }
2454
2455    /* Exit TB for TLB change if mmu is enabled.  */
2456    if (ctx->tb_flags & PSW_C) {
2457        ctx->base.is_jmp = DISAS_IAQ_N_STALE;
2458    }
2459    return nullify_end(ctx);
2460#endif
2461}
2462
2463static bool trans_pxtlbx(DisasContext *ctx, arg_pxtlbx *a)
2464{
2465    CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2466#ifndef CONFIG_USER_ONLY
2467    TCGv_tl addr;
2468    TCGv_reg ofs;
2469
2470    nullify_over(ctx);
2471
2472    form_gva(ctx, &addr, &ofs, a->b, a->x, 0, 0, a->sp, a->m, false);
2473    if (a->m) {
2474        save_gpr(ctx, a->b, ofs);
2475    }
2476    if (a->local) {
2477        gen_helper_ptlbe(cpu_env);
2478    } else {
2479        gen_helper_ptlb(cpu_env, addr);
2480    }
2481
2482    /* Exit TB for TLB change if mmu is enabled.  */
2483    if (ctx->tb_flags & PSW_C) {
2484        ctx->base.is_jmp = DISAS_IAQ_N_STALE;
2485    }
2486    return nullify_end(ctx);
2487#endif
2488}
2489
2490/*
2491 * Implement the pcxl and pcxl2 Fast TLB Insert instructions.
2492 * See
2493 *     https://parisc.wiki.kernel.org/images-parisc/a/a9/Pcxl2_ers.pdf
2494 *     page 13-9 (195/206)
2495 */
2496static bool trans_ixtlbxf(DisasContext *ctx, arg_ixtlbxf *a)
2497{
2498    CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2499#ifndef CONFIG_USER_ONLY
2500    TCGv_tl addr, atl, stl;
2501    TCGv_reg reg;
2502
2503    nullify_over(ctx);
2504
2505    /*
2506     * FIXME:
2507     *  if (not (pcxl or pcxl2))
2508     *    return gen_illegal(ctx);
2509     *
2510     * Note for future: these are 32-bit systems; no hppa64.
2511     */
2512
2513    atl = tcg_temp_new_tl();
2514    stl = tcg_temp_new_tl();
2515    addr = tcg_temp_new_tl();
2516
2517    tcg_gen_ld32u_i64(stl, cpu_env,
2518                      a->data ? offsetof(CPUHPPAState, cr[CR_ISR])
2519                      : offsetof(CPUHPPAState, cr[CR_IIASQ]));
2520    tcg_gen_ld32u_i64(atl, cpu_env,
2521                      a->data ? offsetof(CPUHPPAState, cr[CR_IOR])
2522                      : offsetof(CPUHPPAState, cr[CR_IIAOQ]));
2523    tcg_gen_shli_i64(stl, stl, 32);
2524    tcg_gen_or_tl(addr, atl, stl);
2525    tcg_temp_free_tl(atl);
2526    tcg_temp_free_tl(stl);
2527
2528    reg = load_gpr(ctx, a->r);
2529    if (a->addr) {
2530        gen_helper_itlba(cpu_env, addr, reg);
2531    } else {
2532        gen_helper_itlbp(cpu_env, addr, reg);
2533    }
2534    tcg_temp_free_tl(addr);
2535
2536    /* Exit TB for TLB change if mmu is enabled.  */
2537    if (ctx->tb_flags & PSW_C) {
2538        ctx->base.is_jmp = DISAS_IAQ_N_STALE;
2539    }
2540    return nullify_end(ctx);
2541#endif
2542}
2543
2544static bool trans_lpa(DisasContext *ctx, arg_ldst *a)
2545{
2546    CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2547#ifndef CONFIG_USER_ONLY
2548    TCGv_tl vaddr;
2549    TCGv_reg ofs, paddr;
2550
2551    nullify_over(ctx);
2552
2553    form_gva(ctx, &vaddr, &ofs, a->b, a->x, 0, 0, a->sp, a->m, false);
2554
2555    paddr = tcg_temp_new();
2556    gen_helper_lpa(paddr, cpu_env, vaddr);
2557
2558    /* Note that physical address result overrides base modification.  */
2559    if (a->m) {
2560        save_gpr(ctx, a->b, ofs);
2561    }
2562    save_gpr(ctx, a->t, paddr);
2563    tcg_temp_free(paddr);
2564
2565    return nullify_end(ctx);
2566#endif
2567}
2568
2569static bool trans_lci(DisasContext *ctx, arg_lci *a)
2570{
2571    CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2572
2573    /* The Coherence Index is an implementation-defined function of the
2574       physical address.  Two addresses with the same CI have a coherent
2575       view of the cache.  Our implementation is to return 0 for all,
2576       since the entire address space is coherent.  */
2577    save_gpr(ctx, a->t, tcg_constant_reg(0));
2578
2579    cond_free(&ctx->null_cond);
2580    return true;
2581}
2582
2583static bool trans_add(DisasContext *ctx, arg_rrr_cf_sh *a)
2584{
2585    return do_add_reg(ctx, a, false, false, false, false);
2586}
2587
2588static bool trans_add_l(DisasContext *ctx, arg_rrr_cf_sh *a)
2589{
2590    return do_add_reg(ctx, a, true, false, false, false);
2591}
2592
2593static bool trans_add_tsv(DisasContext *ctx, arg_rrr_cf_sh *a)
2594{
2595    return do_add_reg(ctx, a, false, true, false, false);
2596}
2597
2598static bool trans_add_c(DisasContext *ctx, arg_rrr_cf_sh *a)
2599{
2600    return do_add_reg(ctx, a, false, false, false, true);
2601}
2602
2603static bool trans_add_c_tsv(DisasContext *ctx, arg_rrr_cf_sh *a)
2604{
2605    return do_add_reg(ctx, a, false, true, false, true);
2606}
2607
2608static bool trans_sub(DisasContext *ctx, arg_rrr_cf *a)
2609{
2610    return do_sub_reg(ctx, a, false, false, false);
2611}
2612
2613static bool trans_sub_tsv(DisasContext *ctx, arg_rrr_cf *a)
2614{
2615    return do_sub_reg(ctx, a, true, false, false);
2616}
2617
2618static bool trans_sub_tc(DisasContext *ctx, arg_rrr_cf *a)
2619{
2620    return do_sub_reg(ctx, a, false, false, true);
2621}
2622
2623static bool trans_sub_tsv_tc(DisasContext *ctx, arg_rrr_cf *a)
2624{
2625    return do_sub_reg(ctx, a, true, false, true);
2626}
2627
2628static bool trans_sub_b(DisasContext *ctx, arg_rrr_cf *a)
2629{
2630    return do_sub_reg(ctx, a, false, true, false);
2631}
2632
2633static bool trans_sub_b_tsv(DisasContext *ctx, arg_rrr_cf *a)
2634{
2635    return do_sub_reg(ctx, a, true, true, false);
2636}
2637
2638static bool trans_andcm(DisasContext *ctx, arg_rrr_cf *a)
2639{
2640    return do_log_reg(ctx, a, tcg_gen_andc_reg);
2641}
2642
2643static bool trans_and(DisasContext *ctx, arg_rrr_cf *a)
2644{
2645    return do_log_reg(ctx, a, tcg_gen_and_reg);
2646}
2647
2648static bool trans_or(DisasContext *ctx, arg_rrr_cf *a)
2649{
2650    if (a->cf == 0) {
2651        unsigned r2 = a->r2;
2652        unsigned r1 = a->r1;
2653        unsigned rt = a->t;
2654
2655        if (rt == 0) { /* NOP */
2656            cond_free(&ctx->null_cond);
2657            return true;
2658        }
2659        if (r2 == 0) { /* COPY */
2660            if (r1 == 0) {
2661                TCGv_reg dest = dest_gpr(ctx, rt);
2662                tcg_gen_movi_reg(dest, 0);
2663                save_gpr(ctx, rt, dest);
2664            } else {
2665                save_gpr(ctx, rt, cpu_gr[r1]);
2666            }
2667            cond_free(&ctx->null_cond);
2668            return true;
2669        }
2670#ifndef CONFIG_USER_ONLY
2671        /* These are QEMU extensions and are nops in the real architecture:
2672         *
2673         * or %r10,%r10,%r10 -- idle loop; wait for interrupt
2674         * or %r31,%r31,%r31 -- death loop; offline cpu
2675         *                      currently implemented as idle.
2676         */
2677        if ((rt == 10 || rt == 31) && r1 == rt && r2 == rt) { /* PAUSE */
2678            /* No need to check for supervisor, as userland can only pause
2679               until the next timer interrupt.  */
2680            nullify_over(ctx);
2681
2682            /* Advance the instruction queue.  */
2683            copy_iaoq_entry(cpu_iaoq_f, ctx->iaoq_b, cpu_iaoq_b);
2684            copy_iaoq_entry(cpu_iaoq_b, ctx->iaoq_n, ctx->iaoq_n_var);
2685            nullify_set(ctx, 0);
2686
2687            /* Tell the qemu main loop to halt until this cpu has work.  */
2688            tcg_gen_st_i32(tcg_constant_i32(1), cpu_env,
2689                           offsetof(CPUState, halted) - offsetof(HPPACPU, env));
2690            gen_excp_1(EXCP_HALTED);
2691            ctx->base.is_jmp = DISAS_NORETURN;
2692
2693            return nullify_end(ctx);
2694        }
2695#endif
2696    }
2697    return do_log_reg(ctx, a, tcg_gen_or_reg);
2698}
2699
2700static bool trans_xor(DisasContext *ctx, arg_rrr_cf *a)
2701{
2702    return do_log_reg(ctx, a, tcg_gen_xor_reg);
2703}
2704
2705static bool trans_cmpclr(DisasContext *ctx, arg_rrr_cf *a)
2706{
2707    TCGv_reg tcg_r1, tcg_r2;
2708
2709    if (a->cf) {
2710        nullify_over(ctx);
2711    }
2712    tcg_r1 = load_gpr(ctx, a->r1);
2713    tcg_r2 = load_gpr(ctx, a->r2);
2714    do_cmpclr(ctx, a->t, tcg_r1, tcg_r2, a->cf);
2715    return nullify_end(ctx);
2716}
2717
2718static bool trans_uxor(DisasContext *ctx, arg_rrr_cf *a)
2719{
2720    TCGv_reg tcg_r1, tcg_r2;
2721
2722    if (a->cf) {
2723        nullify_over(ctx);
2724    }
2725    tcg_r1 = load_gpr(ctx, a->r1);
2726    tcg_r2 = load_gpr(ctx, a->r2);
2727    do_unit(ctx, a->t, tcg_r1, tcg_r2, a->cf, false, tcg_gen_xor_reg);
2728    return nullify_end(ctx);
2729}
2730
2731static bool do_uaddcm(DisasContext *ctx, arg_rrr_cf *a, bool is_tc)
2732{
2733    TCGv_reg tcg_r1, tcg_r2, tmp;
2734
2735    if (a->cf) {
2736        nullify_over(ctx);
2737    }
2738    tcg_r1 = load_gpr(ctx, a->r1);
2739    tcg_r2 = load_gpr(ctx, a->r2);
2740    tmp = get_temp(ctx);
2741    tcg_gen_not_reg(tmp, tcg_r2);
2742    do_unit(ctx, a->t, tcg_r1, tmp, a->cf, is_tc, tcg_gen_add_reg);
2743    return nullify_end(ctx);
2744}
2745
2746static bool trans_uaddcm(DisasContext *ctx, arg_rrr_cf *a)
2747{
2748    return do_uaddcm(ctx, a, false);
2749}
2750
2751static bool trans_uaddcm_tc(DisasContext *ctx, arg_rrr_cf *a)
2752{
2753    return do_uaddcm(ctx, a, true);
2754}
2755
2756static bool do_dcor(DisasContext *ctx, arg_rr_cf *a, bool is_i)
2757{
2758    TCGv_reg tmp;
2759
2760    nullify_over(ctx);
2761
2762    tmp = get_temp(ctx);
2763    tcg_gen_shri_reg(tmp, cpu_psw_cb, 3);
2764    if (!is_i) {
2765        tcg_gen_not_reg(tmp, tmp);
2766    }
2767    tcg_gen_andi_reg(tmp, tmp, 0x11111111);
2768    tcg_gen_muli_reg(tmp, tmp, 6);
2769    do_unit(ctx, a->t, load_gpr(ctx, a->r), tmp, a->cf, false,
2770            is_i ? tcg_gen_add_reg : tcg_gen_sub_reg);
2771    return nullify_end(ctx);
2772}
2773
2774static bool trans_dcor(DisasContext *ctx, arg_rr_cf *a)
2775{
2776    return do_dcor(ctx, a, false);
2777}
2778
2779static bool trans_dcor_i(DisasContext *ctx, arg_rr_cf *a)
2780{
2781    return do_dcor(ctx, a, true);
2782}
2783
2784static bool trans_ds(DisasContext *ctx, arg_rrr_cf *a)
2785{
2786    TCGv_reg dest, add1, add2, addc, zero, in1, in2;
2787
2788    nullify_over(ctx);
2789
2790    in1 = load_gpr(ctx, a->r1);
2791    in2 = load_gpr(ctx, a->r2);
2792
2793    add1 = tcg_temp_new();
2794    add2 = tcg_temp_new();
2795    addc = tcg_temp_new();
2796    dest = tcg_temp_new();
2797    zero = tcg_constant_reg(0);
2798
2799    /* Form R1 << 1 | PSW[CB]{8}.  */
2800    tcg_gen_add_reg(add1, in1, in1);
2801    tcg_gen_add_reg(add1, add1, cpu_psw_cb_msb);
2802
2803    /* Add or subtract R2, depending on PSW[V].  Proper computation of
2804       carry{8} requires that we subtract via + ~R2 + 1, as described in
2805       the manual.  By extracting and masking V, we can produce the
2806       proper inputs to the addition without movcond.  */
2807    tcg_gen_sari_reg(addc, cpu_psw_v, TARGET_REGISTER_BITS - 1);
2808    tcg_gen_xor_reg(add2, in2, addc);
2809    tcg_gen_andi_reg(addc, addc, 1);
2810    /* ??? This is only correct for 32-bit.  */
2811    tcg_gen_add2_i32(dest, cpu_psw_cb_msb, add1, zero, add2, zero);
2812    tcg_gen_add2_i32(dest, cpu_psw_cb_msb, dest, cpu_psw_cb_msb, addc, zero);
2813
2814    tcg_temp_free(addc);
2815
2816    /* Write back the result register.  */
2817    save_gpr(ctx, a->t, dest);
2818
2819    /* Write back PSW[CB].  */
2820    tcg_gen_xor_reg(cpu_psw_cb, add1, add2);
2821    tcg_gen_xor_reg(cpu_psw_cb, cpu_psw_cb, dest);
2822
2823    /* Write back PSW[V] for the division step.  */
2824    tcg_gen_neg_reg(cpu_psw_v, cpu_psw_cb_msb);
2825    tcg_gen_xor_reg(cpu_psw_v, cpu_psw_v, in2);
2826
2827    /* Install the new nullification.  */
2828    if (a->cf) {
2829        TCGv_reg sv = NULL;
2830        if (cond_need_sv(a->cf >> 1)) {
2831            /* ??? The lshift is supposed to contribute to overflow.  */
2832            sv = do_add_sv(ctx, dest, add1, add2);
2833        }
2834        ctx->null_cond = do_cond(a->cf, dest, cpu_psw_cb_msb, sv);
2835    }
2836
2837    tcg_temp_free(add1);
2838    tcg_temp_free(add2);
2839    tcg_temp_free(dest);
2840
2841    return nullify_end(ctx);
2842}
2843
2844static bool trans_addi(DisasContext *ctx, arg_rri_cf *a)
2845{
2846    return do_add_imm(ctx, a, false, false);
2847}
2848
2849static bool trans_addi_tsv(DisasContext *ctx, arg_rri_cf *a)
2850{
2851    return do_add_imm(ctx, a, true, false);
2852}
2853
2854static bool trans_addi_tc(DisasContext *ctx, arg_rri_cf *a)
2855{
2856    return do_add_imm(ctx, a, false, true);
2857}
2858
2859static bool trans_addi_tc_tsv(DisasContext *ctx, arg_rri_cf *a)
2860{
2861    return do_add_imm(ctx, a, true, true);
2862}
2863
2864static bool trans_subi(DisasContext *ctx, arg_rri_cf *a)
2865{
2866    return do_sub_imm(ctx, a, false);
2867}
2868
2869static bool trans_subi_tsv(DisasContext *ctx, arg_rri_cf *a)
2870{
2871    return do_sub_imm(ctx, a, true);
2872}
2873
2874static bool trans_cmpiclr(DisasContext *ctx, arg_rri_cf *a)
2875{
2876    TCGv_reg tcg_im, tcg_r2;
2877
2878    if (a->cf) {
2879        nullify_over(ctx);
2880    }
2881
2882    tcg_im = load_const(ctx, a->i);
2883    tcg_r2 = load_gpr(ctx, a->r);
2884    do_cmpclr(ctx, a->t, tcg_im, tcg_r2, a->cf);
2885
2886    return nullify_end(ctx);
2887}
2888
2889static bool trans_ld(DisasContext *ctx, arg_ldst *a)
2890{
2891    return do_load(ctx, a->t, a->b, a->x, a->scale ? a->size : 0,
2892                   a->disp, a->sp, a->m, a->size | MO_TE);
2893}
2894
2895static bool trans_st(DisasContext *ctx, arg_ldst *a)
2896{
2897    assert(a->x == 0 && a->scale == 0);
2898    return do_store(ctx, a->t, a->b, a->disp, a->sp, a->m, a->size | MO_TE);
2899}
2900
2901static bool trans_ldc(DisasContext *ctx, arg_ldst *a)
2902{
2903    MemOp mop = MO_TE | MO_ALIGN | a->size;
2904    TCGv_reg zero, dest, ofs;
2905    TCGv_tl addr;
2906
2907    nullify_over(ctx);
2908
2909    if (a->m) {
2910        /* Base register modification.  Make sure if RT == RB,
2911           we see the result of the load.  */
2912        dest = get_temp(ctx);
2913    } else {
2914        dest = dest_gpr(ctx, a->t);
2915    }
2916
2917    form_gva(ctx, &addr, &ofs, a->b, a->x, a->scale ? a->size : 0,
2918             a->disp, a->sp, a->m, ctx->mmu_idx == MMU_PHYS_IDX);
2919
2920    /*
2921     * For hppa1.1, LDCW is undefined unless aligned mod 16.
2922     * However actual hardware succeeds with aligned mod 4.
2923     * Detect this case and log a GUEST_ERROR.
2924     *
2925     * TODO: HPPA64 relaxes the over-alignment requirement
2926     * with the ,co completer.
2927     */
2928    gen_helper_ldc_check(addr);
2929
2930    zero = tcg_constant_reg(0);
2931    tcg_gen_atomic_xchg_reg(dest, addr, zero, ctx->mmu_idx, mop);
2932
2933    if (a->m) {
2934        save_gpr(ctx, a->b, ofs);
2935    }
2936    save_gpr(ctx, a->t, dest);
2937
2938    return nullify_end(ctx);
2939}
2940
2941static bool trans_stby(DisasContext *ctx, arg_stby *a)
2942{
2943    TCGv_reg ofs, val;
2944    TCGv_tl addr;
2945
2946    nullify_over(ctx);
2947
2948    form_gva(ctx, &addr, &ofs, a->b, 0, 0, a->disp, a->sp, a->m,
2949             ctx->mmu_idx == MMU_PHYS_IDX);
2950    val = load_gpr(ctx, a->r);
2951    if (a->a) {
2952        if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
2953            gen_helper_stby_e_parallel(cpu_env, addr, val);
2954        } else {
2955            gen_helper_stby_e(cpu_env, addr, val);
2956        }
2957    } else {
2958        if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
2959            gen_helper_stby_b_parallel(cpu_env, addr, val);
2960        } else {
2961            gen_helper_stby_b(cpu_env, addr, val);
2962        }
2963    }
2964    if (a->m) {
2965        tcg_gen_andi_reg(ofs, ofs, ~3);
2966        save_gpr(ctx, a->b, ofs);
2967    }
2968
2969    return nullify_end(ctx);
2970}
2971
2972static bool trans_lda(DisasContext *ctx, arg_ldst *a)
2973{
2974    int hold_mmu_idx = ctx->mmu_idx;
2975
2976    CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2977    ctx->mmu_idx = MMU_PHYS_IDX;
2978    trans_ld(ctx, a);
2979    ctx->mmu_idx = hold_mmu_idx;
2980    return true;
2981}
2982
2983static bool trans_sta(DisasContext *ctx, arg_ldst *a)
2984{
2985    int hold_mmu_idx = ctx->mmu_idx;
2986
2987    CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2988    ctx->mmu_idx = MMU_PHYS_IDX;
2989    trans_st(ctx, a);
2990    ctx->mmu_idx = hold_mmu_idx;
2991    return true;
2992}
2993
2994static bool trans_ldil(DisasContext *ctx, arg_ldil *a)
2995{
2996    TCGv_reg tcg_rt = dest_gpr(ctx, a->t);
2997
2998    tcg_gen_movi_reg(tcg_rt, a->i);
2999    save_gpr(ctx, a->t, tcg_rt);
3000    cond_free(&ctx->null_cond);
3001    return true;
3002}
3003
3004static bool trans_addil(DisasContext *ctx, arg_addil *a)
3005{
3006    TCGv_reg tcg_rt = load_gpr(ctx, a->r);
3007    TCGv_reg tcg_r1 = dest_gpr(ctx, 1);
3008
3009    tcg_gen_addi_reg(tcg_r1, tcg_rt, a->i);
3010    save_gpr(ctx, 1, tcg_r1);
3011    cond_free(&ctx->null_cond);
3012    return true;
3013}
3014
3015static bool trans_ldo(DisasContext *ctx, arg_ldo *a)
3016{
3017    TCGv_reg tcg_rt = dest_gpr(ctx, a->t);
3018
3019    /* Special case rb == 0, for the LDI pseudo-op.
3020       The COPY pseudo-op is handled for free within tcg_gen_addi_tl.  */
3021    if (a->b == 0) {
3022        tcg_gen_movi_reg(tcg_rt, a->i);
3023    } else {
3024        tcg_gen_addi_reg(tcg_rt, cpu_gr[a->b], a->i);
3025    }
3026    save_gpr(ctx, a->t, tcg_rt);
3027    cond_free(&ctx->null_cond);
3028    return true;
3029}
3030
3031static bool do_cmpb(DisasContext *ctx, unsigned r, TCGv_reg in1,
3032                    unsigned c, unsigned f, unsigned n, int disp)
3033{
3034    TCGv_reg dest, in2, sv;
3035    DisasCond cond;
3036
3037    in2 = load_gpr(ctx, r);
3038    dest = get_temp(ctx);
3039
3040    tcg_gen_sub_reg(dest, in1, in2);
3041
3042    sv = NULL;
3043    if (cond_need_sv(c)) {
3044        sv = do_sub_sv(ctx, dest, in1, in2);
3045    }
3046
3047    cond = do_sub_cond(c * 2 + f, dest, in1, in2, sv);
3048    return do_cbranch(ctx, disp, n, &cond);
3049}
3050
3051static bool trans_cmpb(DisasContext *ctx, arg_cmpb *a)
3052{
3053    nullify_over(ctx);
3054    return do_cmpb(ctx, a->r2, load_gpr(ctx, a->r1), a->c, a->f, a->n, a->disp);
3055}
3056
3057static bool trans_cmpbi(DisasContext *ctx, arg_cmpbi *a)
3058{
3059    nullify_over(ctx);
3060    return do_cmpb(ctx, a->r, load_const(ctx, a->i), a->c, a->f, a->n, a->disp);
3061}
3062
3063static bool do_addb(DisasContext *ctx, unsigned r, TCGv_reg in1,
3064                    unsigned c, unsigned f, unsigned n, int disp)
3065{
3066    TCGv_reg dest, in2, sv, cb_msb;
3067    DisasCond cond;
3068
3069    in2 = load_gpr(ctx, r);
3070    dest = tcg_temp_new();
3071    sv = NULL;
3072    cb_msb = NULL;
3073
3074    if (cond_need_cb(c)) {
3075        cb_msb = get_temp(ctx);
3076        tcg_gen_movi_reg(cb_msb, 0);
3077        tcg_gen_add2_reg(dest, cb_msb, in1, cb_msb, in2, cb_msb);
3078    } else {
3079        tcg_gen_add_reg(dest, in1, in2);
3080    }
3081    if (cond_need_sv(c)) {
3082        sv = do_add_sv(ctx, dest, in1, in2);
3083    }
3084
3085    cond = do_cond(c * 2 + f, dest, cb_msb, sv);
3086    save_gpr(ctx, r, dest);
3087    tcg_temp_free(dest);
3088    return do_cbranch(ctx, disp, n, &cond);
3089}
3090
3091static bool trans_addb(DisasContext *ctx, arg_addb *a)
3092{
3093    nullify_over(ctx);
3094    return do_addb(ctx, a->r2, load_gpr(ctx, a->r1), a->c, a->f, a->n, a->disp);
3095}
3096
3097static bool trans_addbi(DisasContext *ctx, arg_addbi *a)
3098{
3099    nullify_over(ctx);
3100    return do_addb(ctx, a->r, load_const(ctx, a->i), a->c, a->f, a->n, a->disp);
3101}
3102
3103static bool trans_bb_sar(DisasContext *ctx, arg_bb_sar *a)
3104{
3105    TCGv_reg tmp, tcg_r;
3106    DisasCond cond;
3107
3108    nullify_over(ctx);
3109
3110    tmp = tcg_temp_new();
3111    tcg_r = load_gpr(ctx, a->r);
3112    tcg_gen_shl_reg(tmp, tcg_r, cpu_sar);
3113
3114    cond = cond_make_0(a->c ? TCG_COND_GE : TCG_COND_LT, tmp);
3115    tcg_temp_free(tmp);
3116    return do_cbranch(ctx, a->disp, a->n, &cond);
3117}
3118
3119static bool trans_bb_imm(DisasContext *ctx, arg_bb_imm *a)
3120{
3121    TCGv_reg tmp, tcg_r;
3122    DisasCond cond;
3123
3124    nullify_over(ctx);
3125
3126    tmp = tcg_temp_new();
3127    tcg_r = load_gpr(ctx, a->r);
3128    tcg_gen_shli_reg(tmp, tcg_r, a->p);
3129
3130    cond = cond_make_0(a->c ? TCG_COND_GE : TCG_COND_LT, tmp);
3131    tcg_temp_free(tmp);
3132    return do_cbranch(ctx, a->disp, a->n, &cond);
3133}
3134
3135static bool trans_movb(DisasContext *ctx, arg_movb *a)
3136{
3137    TCGv_reg dest;
3138    DisasCond cond;
3139
3140    nullify_over(ctx);
3141
3142    dest = dest_gpr(ctx, a->r2);
3143    if (a->r1 == 0) {
3144        tcg_gen_movi_reg(dest, 0);
3145    } else {
3146        tcg_gen_mov_reg(dest, cpu_gr[a->r1]);
3147    }
3148
3149    cond = do_sed_cond(a->c, dest);
3150    return do_cbranch(ctx, a->disp, a->n, &cond);
3151}
3152
3153static bool trans_movbi(DisasContext *ctx, arg_movbi *a)
3154{
3155    TCGv_reg dest;
3156    DisasCond cond;
3157
3158    nullify_over(ctx);
3159
3160    dest = dest_gpr(ctx, a->r);
3161    tcg_gen_movi_reg(dest, a->i);
3162
3163    cond = do_sed_cond(a->c, dest);
3164    return do_cbranch(ctx, a->disp, a->n, &cond);
3165}
3166
3167static bool trans_shrpw_sar(DisasContext *ctx, arg_shrpw_sar *a)
3168{
3169    TCGv_reg dest;
3170
3171    if (a->c) {
3172        nullify_over(ctx);
3173    }
3174
3175    dest = dest_gpr(ctx, a->t);
3176    if (a->r1 == 0) {
3177        tcg_gen_ext32u_reg(dest, load_gpr(ctx, a->r2));
3178        tcg_gen_shr_reg(dest, dest, cpu_sar);
3179    } else if (a->r1 == a->r2) {
3180        TCGv_i32 t32 = tcg_temp_new_i32();
3181        tcg_gen_trunc_reg_i32(t32, load_gpr(ctx, a->r2));
3182        tcg_gen_rotr_i32(t32, t32, cpu_sar);
3183        tcg_gen_extu_i32_reg(dest, t32);
3184        tcg_temp_free_i32(t32);
3185    } else {
3186        TCGv_i64 t = tcg_temp_new_i64();
3187        TCGv_i64 s = tcg_temp_new_i64();
3188
3189        tcg_gen_concat_reg_i64(t, load_gpr(ctx, a->r2), load_gpr(ctx, a->r1));
3190        tcg_gen_extu_reg_i64(s, cpu_sar);
3191        tcg_gen_shr_i64(t, t, s);
3192        tcg_gen_trunc_i64_reg(dest, t);
3193
3194        tcg_temp_free_i64(t);
3195        tcg_temp_free_i64(s);
3196    }
3197    save_gpr(ctx, a->t, dest);
3198
3199    /* Install the new nullification.  */
3200    cond_free(&ctx->null_cond);
3201    if (a->c) {
3202        ctx->null_cond = do_sed_cond(a->c, dest);
3203    }
3204    return nullify_end(ctx);
3205}
3206
3207static bool trans_shrpw_imm(DisasContext *ctx, arg_shrpw_imm *a)
3208{
3209    unsigned sa = 31 - a->cpos;
3210    TCGv_reg dest, t2;
3211
3212    if (a->c) {
3213        nullify_over(ctx);
3214    }
3215
3216    dest = dest_gpr(ctx, a->t);
3217    t2 = load_gpr(ctx, a->r2);
3218    if (a->r1 == a->r2) {
3219        TCGv_i32 t32 = tcg_temp_new_i32();
3220        tcg_gen_trunc_reg_i32(t32, t2);
3221        tcg_gen_rotri_i32(t32, t32, sa);
3222        tcg_gen_extu_i32_reg(dest, t32);
3223        tcg_temp_free_i32(t32);
3224    } else if (a->r1 == 0) {
3225        tcg_gen_extract_reg(dest, t2, sa, 32 - sa);
3226    } else {
3227        TCGv_reg t0 = tcg_temp_new();
3228        tcg_gen_extract_reg(t0, t2, sa, 32 - sa);
3229        tcg_gen_deposit_reg(dest, t0, cpu_gr[a->r1], 32 - sa, sa);
3230        tcg_temp_free(t0);
3231    }
3232    save_gpr(ctx, a->t, dest);
3233
3234    /* Install the new nullification.  */
3235    cond_free(&ctx->null_cond);
3236    if (a->c) {
3237        ctx->null_cond = do_sed_cond(a->c, dest);
3238    }
3239    return nullify_end(ctx);
3240}
3241
3242static bool trans_extrw_sar(DisasContext *ctx, arg_extrw_sar *a)
3243{
3244    unsigned len = 32 - a->clen;
3245    TCGv_reg dest, src, tmp;
3246
3247    if (a->c) {
3248        nullify_over(ctx);
3249    }
3250
3251    dest = dest_gpr(ctx, a->t);
3252    src = load_gpr(ctx, a->r);
3253    tmp = tcg_temp_new();
3254
3255    /* Recall that SAR is using big-endian bit numbering.  */
3256    tcg_gen_xori_reg(tmp, cpu_sar, TARGET_REGISTER_BITS - 1);
3257    if (a->se) {
3258        tcg_gen_sar_reg(dest, src, tmp);
3259        tcg_gen_sextract_reg(dest, dest, 0, len);
3260    } else {
3261        tcg_gen_shr_reg(dest, src, tmp);
3262        tcg_gen_extract_reg(dest, dest, 0, len);
3263    }
3264    tcg_temp_free(tmp);
3265    save_gpr(ctx, a->t, dest);
3266
3267    /* Install the new nullification.  */
3268    cond_free(&ctx->null_cond);
3269    if (a->c) {
3270        ctx->null_cond = do_sed_cond(a->c, dest);
3271    }
3272    return nullify_end(ctx);
3273}
3274
3275static bool trans_extrw_imm(DisasContext *ctx, arg_extrw_imm *a)
3276{
3277    unsigned len = 32 - a->clen;
3278    unsigned cpos = 31 - a->pos;
3279    TCGv_reg dest, src;
3280
3281    if (a->c) {
3282        nullify_over(ctx);
3283    }
3284
3285    dest = dest_gpr(ctx, a->t);
3286    src = load_gpr(ctx, a->r);
3287    if (a->se) {
3288        tcg_gen_sextract_reg(dest, src, cpos, len);
3289    } else {
3290        tcg_gen_extract_reg(dest, src, cpos, len);
3291    }
3292    save_gpr(ctx, a->t, dest);
3293
3294    /* Install the new nullification.  */
3295    cond_free(&ctx->null_cond);
3296    if (a->c) {
3297        ctx->null_cond = do_sed_cond(a->c, dest);
3298    }
3299    return nullify_end(ctx);
3300}
3301
3302static bool trans_depwi_imm(DisasContext *ctx, arg_depwi_imm *a)
3303{
3304    unsigned len = 32 - a->clen;
3305    target_sreg mask0, mask1;
3306    TCGv_reg dest;
3307
3308    if (a->c) {
3309        nullify_over(ctx);
3310    }
3311    if (a->cpos + len > 32) {
3312        len = 32 - a->cpos;
3313    }
3314
3315    dest = dest_gpr(ctx, a->t);
3316    mask0 = deposit64(0, a->cpos, len, a->i);
3317    mask1 = deposit64(-1, a->cpos, len, a->i);
3318
3319    if (a->nz) {
3320        TCGv_reg src = load_gpr(ctx, a->t);
3321        if (mask1 != -1) {
3322            tcg_gen_andi_reg(dest, src, mask1);
3323            src = dest;
3324        }
3325        tcg_gen_ori_reg(dest, src, mask0);
3326    } else {
3327        tcg_gen_movi_reg(dest, mask0);
3328    }
3329    save_gpr(ctx, a->t, dest);
3330
3331    /* Install the new nullification.  */
3332    cond_free(&ctx->null_cond);
3333    if (a->c) {
3334        ctx->null_cond = do_sed_cond(a->c, dest);
3335    }
3336    return nullify_end(ctx);
3337}
3338
3339static bool trans_depw_imm(DisasContext *ctx, arg_depw_imm *a)
3340{
3341    unsigned rs = a->nz ? a->t : 0;
3342    unsigned len = 32 - a->clen;
3343    TCGv_reg dest, val;
3344
3345    if (a->c) {
3346        nullify_over(ctx);
3347    }
3348    if (a->cpos + len > 32) {
3349        len = 32 - a->cpos;
3350    }
3351
3352    dest = dest_gpr(ctx, a->t);
3353    val = load_gpr(ctx, a->r);
3354    if (rs == 0) {
3355        tcg_gen_deposit_z_reg(dest, val, a->cpos, len);
3356    } else {
3357        tcg_gen_deposit_reg(dest, cpu_gr[rs], val, a->cpos, len);
3358    }
3359    save_gpr(ctx, a->t, dest);
3360
3361    /* Install the new nullification.  */
3362    cond_free(&ctx->null_cond);
3363    if (a->c) {
3364        ctx->null_cond = do_sed_cond(a->c, dest);
3365    }
3366    return nullify_end(ctx);
3367}
3368
3369static bool do_depw_sar(DisasContext *ctx, unsigned rt, unsigned c,
3370                        unsigned nz, unsigned clen, TCGv_reg val)
3371{
3372    unsigned rs = nz ? rt : 0;
3373    unsigned len = 32 - clen;
3374    TCGv_reg mask, tmp, shift, dest;
3375    unsigned msb = 1U << (len - 1);
3376
3377    dest = dest_gpr(ctx, rt);
3378    shift = tcg_temp_new();
3379    tmp = tcg_temp_new();
3380
3381    /* Convert big-endian bit numbering in SAR to left-shift.  */
3382    tcg_gen_xori_reg(shift, cpu_sar, TARGET_REGISTER_BITS - 1);
3383
3384    mask = tcg_const_reg(msb + (msb - 1));
3385    tcg_gen_and_reg(tmp, val, mask);
3386    if (rs) {
3387        tcg_gen_shl_reg(mask, mask, shift);
3388        tcg_gen_shl_reg(tmp, tmp, shift);
3389        tcg_gen_andc_reg(dest, cpu_gr[rs], mask);
3390        tcg_gen_or_reg(dest, dest, tmp);
3391    } else {
3392        tcg_gen_shl_reg(dest, tmp, shift);
3393    }
3394    tcg_temp_free(shift);
3395    tcg_temp_free(mask);
3396    tcg_temp_free(tmp);
3397    save_gpr(ctx, rt, dest);
3398
3399    /* Install the new nullification.  */
3400    cond_free(&ctx->null_cond);
3401    if (c) {
3402        ctx->null_cond = do_sed_cond(c, dest);
3403    }
3404    return nullify_end(ctx);
3405}
3406
3407static bool trans_depw_sar(DisasContext *ctx, arg_depw_sar *a)
3408{
3409    if (a->c) {
3410        nullify_over(ctx);
3411    }
3412    return do_depw_sar(ctx, a->t, a->c, a->nz, a->clen, load_gpr(ctx, a->r));
3413}
3414
3415static bool trans_depwi_sar(DisasContext *ctx, arg_depwi_sar *a)
3416{
3417    if (a->c) {
3418        nullify_over(ctx);
3419    }
3420    return do_depw_sar(ctx, a->t, a->c, a->nz, a->clen, load_const(ctx, a->i));
3421}
3422
3423static bool trans_be(DisasContext *ctx, arg_be *a)
3424{
3425    TCGv_reg tmp;
3426
3427#ifdef CONFIG_USER_ONLY
3428    /* ??? It seems like there should be a good way of using
3429       "be disp(sr2, r0)", the canonical gateway entry mechanism
3430       to our advantage.  But that appears to be inconvenient to
3431       manage along side branch delay slots.  Therefore we handle
3432       entry into the gateway page via absolute address.  */
3433    /* Since we don't implement spaces, just branch.  Do notice the special
3434       case of "be disp(*,r0)" using a direct branch to disp, so that we can
3435       goto_tb to the TB containing the syscall.  */
3436    if (a->b == 0) {
3437        return do_dbranch(ctx, a->disp, a->l, a->n);
3438    }
3439#else
3440    nullify_over(ctx);
3441#endif
3442
3443    tmp = get_temp(ctx);
3444    tcg_gen_addi_reg(tmp, load_gpr(ctx, a->b), a->disp);
3445    tmp = do_ibranch_priv(ctx, tmp);
3446
3447#ifdef CONFIG_USER_ONLY
3448    return do_ibranch(ctx, tmp, a->l, a->n);
3449#else
3450    TCGv_i64 new_spc = tcg_temp_new_i64();
3451
3452    load_spr(ctx, new_spc, a->sp);
3453    if (a->l) {
3454        copy_iaoq_entry(cpu_gr[31], ctx->iaoq_n, ctx->iaoq_n_var);
3455        tcg_gen_mov_i64(cpu_sr[0], cpu_iasq_f);
3456    }
3457    if (a->n && use_nullify_skip(ctx)) {
3458        tcg_gen_mov_reg(cpu_iaoq_f, tmp);
3459        tcg_gen_addi_reg(cpu_iaoq_b, cpu_iaoq_f, 4);
3460        tcg_gen_mov_i64(cpu_iasq_f, new_spc);
3461        tcg_gen_mov_i64(cpu_iasq_b, cpu_iasq_f);
3462    } else {
3463        copy_iaoq_entry(cpu_iaoq_f, ctx->iaoq_b, cpu_iaoq_b);
3464        if (ctx->iaoq_b == -1) {
3465            tcg_gen_mov_i64(cpu_iasq_f, cpu_iasq_b);
3466        }
3467        tcg_gen_mov_reg(cpu_iaoq_b, tmp);
3468        tcg_gen_mov_i64(cpu_iasq_b, new_spc);
3469        nullify_set(ctx, a->n);
3470    }
3471    tcg_temp_free_i64(new_spc);
3472    tcg_gen_lookup_and_goto_ptr();
3473    ctx->base.is_jmp = DISAS_NORETURN;
3474    return nullify_end(ctx);
3475#endif
3476}
3477
3478static bool trans_bl(DisasContext *ctx, arg_bl *a)
3479{
3480    return do_dbranch(ctx, iaoq_dest(ctx, a->disp), a->l, a->n);
3481}
3482
3483static bool trans_b_gate(DisasContext *ctx, arg_b_gate *a)
3484{
3485    target_ureg dest = iaoq_dest(ctx, a->disp);
3486
3487    nullify_over(ctx);
3488
3489    /* Make sure the caller hasn't done something weird with the queue.
3490     * ??? This is not quite the same as the PSW[B] bit, which would be
3491     * expensive to track.  Real hardware will trap for
3492     *    b  gateway
3493     *    b  gateway+4  (in delay slot of first branch)
3494     * However, checking for a non-sequential instruction queue *will*
3495     * diagnose the security hole
3496     *    b  gateway
3497     *    b  evil
3498     * in which instructions at evil would run with increased privs.
3499     */
3500    if (ctx->iaoq_b == -1 || ctx->iaoq_b != ctx->iaoq_f + 4) {
3501        return gen_illegal(ctx);
3502    }
3503
3504#ifndef CONFIG_USER_ONLY
3505    if (ctx->tb_flags & PSW_C) {
3506        CPUHPPAState *env = ctx->cs->env_ptr;
3507        int type = hppa_artype_for_page(env, ctx->base.pc_next);
3508        /* If we could not find a TLB entry, then we need to generate an
3509           ITLB miss exception so the kernel will provide it.
3510           The resulting TLB fill operation will invalidate this TB and
3511           we will re-translate, at which point we *will* be able to find
3512           the TLB entry and determine if this is in fact a gateway page.  */
3513        if (type < 0) {
3514            gen_excp(ctx, EXCP_ITLB_MISS);
3515            return true;
3516        }
3517        /* No change for non-gateway pages or for priv decrease.  */
3518        if (type >= 4 && type - 4 < ctx->privilege) {
3519            dest = deposit32(dest, 0, 2, type - 4);
3520        }
3521    } else {
3522        dest &= -4;  /* priv = 0 */
3523    }
3524#endif
3525
3526    if (a->l) {
3527        TCGv_reg tmp = dest_gpr(ctx, a->l);
3528        if (ctx->privilege < 3) {
3529            tcg_gen_andi_reg(tmp, tmp, -4);
3530        }
3531        tcg_gen_ori_reg(tmp, tmp, ctx->privilege);
3532        save_gpr(ctx, a->l, tmp);
3533    }
3534
3535    return do_dbranch(ctx, dest, 0, a->n);
3536}
3537
3538static bool trans_blr(DisasContext *ctx, arg_blr *a)
3539{
3540    if (a->x) {
3541        TCGv_reg tmp = get_temp(ctx);
3542        tcg_gen_shli_reg(tmp, load_gpr(ctx, a->x), 3);
3543        tcg_gen_addi_reg(tmp, tmp, ctx->iaoq_f + 8);
3544        /* The computation here never changes privilege level.  */
3545        return do_ibranch(ctx, tmp, a->l, a->n);
3546    } else {
3547        /* BLR R0,RX is a good way to load PC+8 into RX.  */
3548        return do_dbranch(ctx, ctx->iaoq_f + 8, a->l, a->n);
3549    }
3550}
3551
3552static bool trans_bv(DisasContext *ctx, arg_bv *a)
3553{
3554    TCGv_reg dest;
3555
3556    if (a->x == 0) {
3557        dest = load_gpr(ctx, a->b);
3558    } else {
3559        dest = get_temp(ctx);
3560        tcg_gen_shli_reg(dest, load_gpr(ctx, a->x), 3);
3561        tcg_gen_add_reg(dest, dest, load_gpr(ctx, a->b));
3562    }
3563    dest = do_ibranch_priv(ctx, dest);
3564    return do_ibranch(ctx, dest, 0, a->n);
3565}
3566
3567static bool trans_bve(DisasContext *ctx, arg_bve *a)
3568{
3569    TCGv_reg dest;
3570
3571#ifdef CONFIG_USER_ONLY
3572    dest = do_ibranch_priv(ctx, load_gpr(ctx, a->b));
3573    return do_ibranch(ctx, dest, a->l, a->n);
3574#else
3575    nullify_over(ctx);
3576    dest = do_ibranch_priv(ctx, load_gpr(ctx, a->b));
3577
3578    copy_iaoq_entry(cpu_iaoq_f, ctx->iaoq_b, cpu_iaoq_b);
3579    if (ctx->iaoq_b == -1) {
3580        tcg_gen_mov_i64(cpu_iasq_f, cpu_iasq_b);
3581    }
3582    copy_iaoq_entry(cpu_iaoq_b, -1, dest);
3583    tcg_gen_mov_i64(cpu_iasq_b, space_select(ctx, 0, dest));
3584    if (a->l) {
3585        copy_iaoq_entry(cpu_gr[a->l], ctx->iaoq_n, ctx->iaoq_n_var);
3586    }
3587    nullify_set(ctx, a->n);
3588    tcg_gen_lookup_and_goto_ptr();
3589    ctx->base.is_jmp = DISAS_NORETURN;
3590    return nullify_end(ctx);
3591#endif
3592}
3593
3594/*
3595 * Float class 0
3596 */
3597
3598static void gen_fcpy_f(TCGv_i32 dst, TCGv_env unused, TCGv_i32 src)
3599{
3600    tcg_gen_mov_i32(dst, src);
3601}
3602
3603static bool trans_fcpy_f(DisasContext *ctx, arg_fclass01 *a)
3604{
3605    return do_fop_wew(ctx, a->t, a->r, gen_fcpy_f);
3606}
3607
3608static void gen_fcpy_d(TCGv_i64 dst, TCGv_env unused, TCGv_i64 src)
3609{
3610    tcg_gen_mov_i64(dst, src);
3611}
3612
3613static bool trans_fcpy_d(DisasContext *ctx, arg_fclass01 *a)
3614{
3615    return do_fop_ded(ctx, a->t, a->r, gen_fcpy_d);
3616}
3617
3618static void gen_fabs_f(TCGv_i32 dst, TCGv_env unused, TCGv_i32 src)
3619{
3620    tcg_gen_andi_i32(dst, src, INT32_MAX);
3621}
3622
3623static bool trans_fabs_f(DisasContext *ctx, arg_fclass01 *a)
3624{
3625    return do_fop_wew(ctx, a->t, a->r, gen_fabs_f);
3626}
3627
3628static void gen_fabs_d(TCGv_i64 dst, TCGv_env unused, TCGv_i64 src)
3629{
3630    tcg_gen_andi_i64(dst, src, INT64_MAX);
3631}
3632
3633static bool trans_fabs_d(DisasContext *ctx, arg_fclass01 *a)
3634{
3635    return do_fop_ded(ctx, a->t, a->r, gen_fabs_d);
3636}
3637
3638static bool trans_fsqrt_f(DisasContext *ctx, arg_fclass01 *a)
3639{
3640    return do_fop_wew(ctx, a->t, a->r, gen_helper_fsqrt_s);
3641}
3642
3643static bool trans_fsqrt_d(DisasContext *ctx, arg_fclass01 *a)
3644{
3645    return do_fop_ded(ctx, a->t, a->r, gen_helper_fsqrt_d);
3646}
3647
3648static bool trans_frnd_f(DisasContext *ctx, arg_fclass01 *a)
3649{
3650    return do_fop_wew(ctx, a->t, a->r, gen_helper_frnd_s);
3651}
3652
3653static bool trans_frnd_d(DisasContext *ctx, arg_fclass01 *a)
3654{
3655    return do_fop_ded(ctx, a->t, a->r, gen_helper_frnd_d);
3656}
3657
3658static void gen_fneg_f(TCGv_i32 dst, TCGv_env unused, TCGv_i32 src)
3659{
3660    tcg_gen_xori_i32(dst, src, INT32_MIN);
3661}
3662
3663static bool trans_fneg_f(DisasContext *ctx, arg_fclass01 *a)
3664{
3665    return do_fop_wew(ctx, a->t, a->r, gen_fneg_f);
3666}
3667
3668static void gen_fneg_d(TCGv_i64 dst, TCGv_env unused, TCGv_i64 src)
3669{
3670    tcg_gen_xori_i64(dst, src, INT64_MIN);
3671}
3672
3673static bool trans_fneg_d(DisasContext *ctx, arg_fclass01 *a)
3674{
3675    return do_fop_ded(ctx, a->t, a->r, gen_fneg_d);
3676}
3677
3678static void gen_fnegabs_f(TCGv_i32 dst, TCGv_env unused, TCGv_i32 src)
3679{
3680    tcg_gen_ori_i32(dst, src, INT32_MIN);
3681}
3682
3683static bool trans_fnegabs_f(DisasContext *ctx, arg_fclass01 *a)
3684{
3685    return do_fop_wew(ctx, a->t, a->r, gen_fnegabs_f);
3686}
3687
3688static void gen_fnegabs_d(TCGv_i64 dst, TCGv_env unused, TCGv_i64 src)
3689{
3690    tcg_gen_ori_i64(dst, src, INT64_MIN);
3691}
3692
3693static bool trans_fnegabs_d(DisasContext *ctx, arg_fclass01 *a)
3694{
3695    return do_fop_ded(ctx, a->t, a->r, gen_fnegabs_d);
3696}
3697
3698/*
3699 * Float class 1
3700 */
3701
3702static bool trans_fcnv_d_f(DisasContext *ctx, arg_fclass01 *a)
3703{
3704    return do_fop_wed(ctx, a->t, a->r, gen_helper_fcnv_d_s);
3705}
3706
3707static bool trans_fcnv_f_d(DisasContext *ctx, arg_fclass01 *a)
3708{
3709    return do_fop_dew(ctx, a->t, a->r, gen_helper_fcnv_s_d);
3710}
3711
3712static bool trans_fcnv_w_f(DisasContext *ctx, arg_fclass01 *a)
3713{
3714    return do_fop_wew(ctx, a->t, a->r, gen_helper_fcnv_w_s);
3715}
3716
3717static bool trans_fcnv_q_f(DisasContext *ctx, arg_fclass01 *a)
3718{
3719    return do_fop_wed(ctx, a->t, a->r, gen_helper_fcnv_dw_s);
3720}
3721
3722static bool trans_fcnv_w_d(DisasContext *ctx, arg_fclass01 *a)
3723{
3724    return do_fop_dew(ctx, a->t, a->r, gen_helper_fcnv_w_d);
3725}
3726
3727static bool trans_fcnv_q_d(DisasContext *ctx, arg_fclass01 *a)
3728{
3729    return do_fop_ded(ctx, a->t, a->r, gen_helper_fcnv_dw_d);
3730}
3731
3732static bool trans_fcnv_f_w(DisasContext *ctx, arg_fclass01 *a)
3733{
3734    return do_fop_wew(ctx, a->t, a->r, gen_helper_fcnv_s_w);
3735}
3736
3737static bool trans_fcnv_d_w(DisasContext *ctx, arg_fclass01 *a)
3738{
3739    return do_fop_wed(ctx, a->t, a->r, gen_helper_fcnv_d_w);
3740}
3741
3742static bool trans_fcnv_f_q(DisasContext *ctx, arg_fclass01 *a)
3743{
3744    return do_fop_dew(ctx, a->t, a->r, gen_helper_fcnv_s_dw);
3745}
3746
3747static bool trans_fcnv_d_q(DisasContext *ctx, arg_fclass01 *a)
3748{
3749    return do_fop_ded(ctx, a->t, a->r, gen_helper_fcnv_d_dw);
3750}
3751
3752static bool trans_fcnv_t_f_w(DisasContext *ctx, arg_fclass01 *a)
3753{
3754    return do_fop_wew(ctx, a->t, a->r, gen_helper_fcnv_t_s_w);
3755}
3756
3757static bool trans_fcnv_t_d_w(DisasContext *ctx, arg_fclass01 *a)
3758{
3759    return do_fop_wed(ctx, a->t, a->r, gen_helper_fcnv_t_d_w);
3760}
3761
3762static bool trans_fcnv_t_f_q(DisasContext *ctx, arg_fclass01 *a)
3763{
3764    return do_fop_dew(ctx, a->t, a->r, gen_helper_fcnv_t_s_dw);
3765}
3766
3767static bool trans_fcnv_t_d_q(DisasContext *ctx, arg_fclass01 *a)
3768{
3769    return do_fop_ded(ctx, a->t, a->r, gen_helper_fcnv_t_d_dw);
3770}
3771
3772static bool trans_fcnv_uw_f(DisasContext *ctx, arg_fclass01 *a)
3773{
3774    return do_fop_wew(ctx, a->t, a->r, gen_helper_fcnv_uw_s);
3775}
3776
3777static bool trans_fcnv_uq_f(DisasContext *ctx, arg_fclass01 *a)
3778{
3779    return do_fop_wed(ctx, a->t, a->r, gen_helper_fcnv_udw_s);
3780}
3781
3782static bool trans_fcnv_uw_d(DisasContext *ctx, arg_fclass01 *a)
3783{
3784    return do_fop_dew(ctx, a->t, a->r, gen_helper_fcnv_uw_d);
3785}
3786
3787static bool trans_fcnv_uq_d(DisasContext *ctx, arg_fclass01 *a)
3788{
3789    return do_fop_ded(ctx, a->t, a->r, gen_helper_fcnv_udw_d);
3790}
3791
3792static bool trans_fcnv_f_uw(DisasContext *ctx, arg_fclass01 *a)
3793{
3794    return do_fop_wew(ctx, a->t, a->r, gen_helper_fcnv_s_uw);
3795}
3796
3797static bool trans_fcnv_d_uw(DisasContext *ctx, arg_fclass01 *a)
3798{
3799    return do_fop_wed(ctx, a->t, a->r, gen_helper_fcnv_d_uw);
3800}
3801
3802static bool trans_fcnv_f_uq(DisasContext *ctx, arg_fclass01 *a)
3803{
3804    return do_fop_dew(ctx, a->t, a->r, gen_helper_fcnv_s_udw);
3805}
3806
3807static bool trans_fcnv_d_uq(DisasContext *ctx, arg_fclass01 *a)
3808{
3809    return do_fop_ded(ctx, a->t, a->r, gen_helper_fcnv_d_udw);
3810}
3811
3812static bool trans_fcnv_t_f_uw(DisasContext *ctx, arg_fclass01 *a)
3813{
3814    return do_fop_wew(ctx, a->t, a->r, gen_helper_fcnv_t_s_uw);
3815}
3816
3817static bool trans_fcnv_t_d_uw(DisasContext *ctx, arg_fclass01 *a)
3818{
3819    return do_fop_wed(ctx, a->t, a->r, gen_helper_fcnv_t_d_uw);
3820}
3821
3822static bool trans_fcnv_t_f_uq(DisasContext *ctx, arg_fclass01 *a)
3823{
3824    return do_fop_dew(ctx, a->t, a->r, gen_helper_fcnv_t_s_udw);
3825}
3826
3827static bool trans_fcnv_t_d_uq(DisasContext *ctx, arg_fclass01 *a)
3828{
3829    return do_fop_ded(ctx, a->t, a->r, gen_helper_fcnv_t_d_udw);
3830}
3831
3832/*
3833 * Float class 2
3834 */
3835
3836static bool trans_fcmp_f(DisasContext *ctx, arg_fclass2 *a)
3837{
3838    TCGv_i32 ta, tb, tc, ty;
3839
3840    nullify_over(ctx);
3841
3842    ta = load_frw0_i32(a->r1);
3843    tb = load_frw0_i32(a->r2);
3844    ty = tcg_constant_i32(a->y);
3845    tc = tcg_constant_i32(a->c);
3846
3847    gen_helper_fcmp_s(cpu_env, ta, tb, ty, tc);
3848
3849    tcg_temp_free_i32(ta);
3850    tcg_temp_free_i32(tb);
3851
3852    return nullify_end(ctx);
3853}
3854
3855static bool trans_fcmp_d(DisasContext *ctx, arg_fclass2 *a)
3856{
3857    TCGv_i64 ta, tb;
3858    TCGv_i32 tc, ty;
3859
3860    nullify_over(ctx);
3861
3862    ta = load_frd0(a->r1);
3863    tb = load_frd0(a->r2);
3864    ty = tcg_constant_i32(a->y);
3865    tc = tcg_constant_i32(a->c);
3866
3867    gen_helper_fcmp_d(cpu_env, ta, tb, ty, tc);
3868
3869    tcg_temp_free_i64(ta);
3870    tcg_temp_free_i64(tb);
3871
3872    return nullify_end(ctx);
3873}
3874
3875static bool trans_ftest(DisasContext *ctx, arg_ftest *a)
3876{
3877    TCGv_reg t;
3878
3879    nullify_over(ctx);
3880
3881    t = get_temp(ctx);
3882    tcg_gen_ld32u_reg(t, cpu_env, offsetof(CPUHPPAState, fr0_shadow));
3883
3884    if (a->y == 1) {
3885        int mask;
3886        bool inv = false;
3887
3888        switch (a->c) {
3889        case 0: /* simple */
3890            tcg_gen_andi_reg(t, t, 0x4000000);
3891            ctx->null_cond = cond_make_0(TCG_COND_NE, t);
3892            goto done;
3893        case 2: /* rej */
3894            inv = true;
3895            /* fallthru */
3896        case 1: /* acc */
3897            mask = 0x43ff800;
3898            break;
3899        case 6: /* rej8 */
3900            inv = true;
3901            /* fallthru */
3902        case 5: /* acc8 */
3903            mask = 0x43f8000;
3904            break;
3905        case 9: /* acc6 */
3906            mask = 0x43e0000;
3907            break;
3908        case 13: /* acc4 */
3909            mask = 0x4380000;
3910            break;
3911        case 17: /* acc2 */
3912            mask = 0x4200000;
3913            break;
3914        default:
3915            gen_illegal(ctx);
3916            return true;
3917        }
3918        if (inv) {
3919            TCGv_reg c = load_const(ctx, mask);
3920            tcg_gen_or_reg(t, t, c);
3921            ctx->null_cond = cond_make(TCG_COND_EQ, t, c);
3922        } else {
3923            tcg_gen_andi_reg(t, t, mask);
3924            ctx->null_cond = cond_make_0(TCG_COND_EQ, t);
3925        }
3926    } else {
3927        unsigned cbit = (a->y ^ 1) - 1;
3928
3929        tcg_gen_extract_reg(t, t, 21 - cbit, 1);
3930        ctx->null_cond = cond_make_0(TCG_COND_NE, t);
3931        tcg_temp_free(t);
3932    }
3933
3934 done:
3935    return nullify_end(ctx);
3936}
3937
3938/*
3939 * Float class 2
3940 */
3941
3942static bool trans_fadd_f(DisasContext *ctx, arg_fclass3 *a)
3943{
3944    return do_fop_weww(ctx, a->t, a->r1, a->r2, gen_helper_fadd_s);
3945}
3946
3947static bool trans_fadd_d(DisasContext *ctx, arg_fclass3 *a)
3948{
3949    return do_fop_dedd(ctx, a->t, a->r1, a->r2, gen_helper_fadd_d);
3950}
3951
3952static bool trans_fsub_f(DisasContext *ctx, arg_fclass3 *a)
3953{
3954    return do_fop_weww(ctx, a->t, a->r1, a->r2, gen_helper_fsub_s);
3955}
3956
3957static bool trans_fsub_d(DisasContext *ctx, arg_fclass3 *a)
3958{
3959    return do_fop_dedd(ctx, a->t, a->r1, a->r2, gen_helper_fsub_d);
3960}
3961
3962static bool trans_fmpy_f(DisasContext *ctx, arg_fclass3 *a)
3963{
3964    return do_fop_weww(ctx, a->t, a->r1, a->r2, gen_helper_fmpy_s);
3965}
3966
3967static bool trans_fmpy_d(DisasContext *ctx, arg_fclass3 *a)
3968{
3969    return do_fop_dedd(ctx, a->t, a->r1, a->r2, gen_helper_fmpy_d);
3970}
3971
3972static bool trans_fdiv_f(DisasContext *ctx, arg_fclass3 *a)
3973{
3974    return do_fop_weww(ctx, a->t, a->r1, a->r2, gen_helper_fdiv_s);
3975}
3976
3977static bool trans_fdiv_d(DisasContext *ctx, arg_fclass3 *a)
3978{
3979    return do_fop_dedd(ctx, a->t, a->r1, a->r2, gen_helper_fdiv_d);
3980}
3981
3982static bool trans_xmpyu(DisasContext *ctx, arg_xmpyu *a)
3983{
3984    TCGv_i64 x, y;
3985
3986    nullify_over(ctx);
3987
3988    x = load_frw0_i64(a->r1);
3989    y = load_frw0_i64(a->r2);
3990    tcg_gen_mul_i64(x, x, y);
3991    save_frd(a->t, x);
3992    tcg_temp_free_i64(x);
3993    tcg_temp_free_i64(y);
3994
3995    return nullify_end(ctx);
3996}
3997
3998/* Convert the fmpyadd single-precision register encodings to standard.  */
3999static inline int fmpyadd_s_reg(unsigned r)
4000{
4001    return (r & 16) * 2 + 16 + (r & 15);
4002}
4003
4004static bool do_fmpyadd_s(DisasContext *ctx, arg_mpyadd *a, bool is_sub)
4005{
4006    int tm = fmpyadd_s_reg(a->tm);
4007    int ra = fmpyadd_s_reg(a->ra);
4008    int ta = fmpyadd_s_reg(a->ta);
4009    int rm2 = fmpyadd_s_reg(a->rm2);
4010    int rm1 = fmpyadd_s_reg(a->rm1);
4011
4012    nullify_over(ctx);
4013
4014    do_fop_weww(ctx, tm, rm1, rm2, gen_helper_fmpy_s);
4015    do_fop_weww(ctx, ta, ta, ra,
4016                is_sub ? gen_helper_fsub_s : gen_helper_fadd_s);
4017
4018    return nullify_end(ctx);
4019}
4020
4021static bool trans_fmpyadd_f(DisasContext *ctx, arg_mpyadd *a)
4022{
4023    return do_fmpyadd_s(ctx, a, false);
4024}
4025
4026static bool trans_fmpysub_f(DisasContext *ctx, arg_mpyadd *a)
4027{
4028    return do_fmpyadd_s(ctx, a, true);
4029}
4030
4031static bool do_fmpyadd_d(DisasContext *ctx, arg_mpyadd *a, bool is_sub)
4032{
4033    nullify_over(ctx);
4034
4035    do_fop_dedd(ctx, a->tm, a->rm1, a->rm2, gen_helper_fmpy_d);
4036    do_fop_dedd(ctx, a->ta, a->ta, a->ra,
4037                is_sub ? gen_helper_fsub_d : gen_helper_fadd_d);
4038
4039    return nullify_end(ctx);
4040}
4041
4042static bool trans_fmpyadd_d(DisasContext *ctx, arg_mpyadd *a)
4043{
4044    return do_fmpyadd_d(ctx, a, false);
4045}
4046
4047static bool trans_fmpysub_d(DisasContext *ctx, arg_mpyadd *a)
4048{
4049    return do_fmpyadd_d(ctx, a, true);
4050}
4051
4052static bool trans_fmpyfadd_f(DisasContext *ctx, arg_fmpyfadd_f *a)
4053{
4054    TCGv_i32 x, y, z;
4055
4056    nullify_over(ctx);
4057    x = load_frw0_i32(a->rm1);
4058    y = load_frw0_i32(a->rm2);
4059    z = load_frw0_i32(a->ra3);
4060
4061    if (a->neg) {
4062        gen_helper_fmpynfadd_s(x, cpu_env, x, y, z);
4063    } else {
4064        gen_helper_fmpyfadd_s(x, cpu_env, x, y, z);
4065    }
4066
4067    tcg_temp_free_i32(y);
4068    tcg_temp_free_i32(z);
4069    save_frw_i32(a->t, x);
4070    tcg_temp_free_i32(x);
4071    return nullify_end(ctx);
4072}
4073
4074static bool trans_fmpyfadd_d(DisasContext *ctx, arg_fmpyfadd_d *a)
4075{
4076    TCGv_i64 x, y, z;
4077
4078    nullify_over(ctx);
4079    x = load_frd0(a->rm1);
4080    y = load_frd0(a->rm2);
4081    z = load_frd0(a->ra3);
4082
4083    if (a->neg) {
4084        gen_helper_fmpynfadd_d(x, cpu_env, x, y, z);
4085    } else {
4086        gen_helper_fmpyfadd_d(x, cpu_env, x, y, z);
4087    }
4088
4089    tcg_temp_free_i64(y);
4090    tcg_temp_free_i64(z);
4091    save_frd(a->t, x);
4092    tcg_temp_free_i64(x);
4093    return nullify_end(ctx);
4094}
4095
4096static bool trans_diag(DisasContext *ctx, arg_diag *a)
4097{
4098    qemu_log_mask(LOG_UNIMP, "DIAG opcode ignored\n");
4099    cond_free(&ctx->null_cond);
4100    return true;
4101}
4102
4103static void hppa_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
4104{
4105    DisasContext *ctx = container_of(dcbase, DisasContext, base);
4106    int bound;
4107
4108    ctx->cs = cs;
4109    ctx->tb_flags = ctx->base.tb->flags;
4110
4111#ifdef CONFIG_USER_ONLY
4112    ctx->privilege = MMU_USER_IDX;
4113    ctx->mmu_idx = MMU_USER_IDX;
4114    ctx->iaoq_f = ctx->base.pc_first | MMU_USER_IDX;
4115    ctx->iaoq_b = ctx->base.tb->cs_base | MMU_USER_IDX;
4116#else
4117    ctx->privilege = (ctx->tb_flags >> TB_FLAG_PRIV_SHIFT) & 3;
4118    ctx->mmu_idx = (ctx->tb_flags & PSW_D ? ctx->privilege : MMU_PHYS_IDX);
4119
4120    /* Recover the IAOQ values from the GVA + PRIV.  */
4121    uint64_t cs_base = ctx->base.tb->cs_base;
4122    uint64_t iasq_f = cs_base & ~0xffffffffull;
4123    int32_t diff = cs_base;
4124
4125    ctx->iaoq_f = (ctx->base.pc_first & ~iasq_f) + ctx->privilege;
4126    ctx->iaoq_b = (diff ? ctx->iaoq_f + diff : -1);
4127#endif
4128    ctx->iaoq_n = -1;
4129    ctx->iaoq_n_var = NULL;
4130
4131    /* Bound the number of instructions by those left on the page.  */
4132    bound = -(ctx->base.pc_first | TARGET_PAGE_MASK) / 4;
4133    ctx->base.max_insns = MIN(ctx->base.max_insns, bound);
4134
4135    ctx->ntempr = 0;
4136    ctx->ntempl = 0;
4137    memset(ctx->tempr, 0, sizeof(ctx->tempr));
4138    memset(ctx->templ, 0, sizeof(ctx->templ));
4139}
4140
4141static void hppa_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
4142{
4143    DisasContext *ctx = container_of(dcbase, DisasContext, base);
4144
4145    /* Seed the nullification status from PSW[N], as saved in TB->FLAGS.  */
4146    ctx->null_cond = cond_make_f();
4147    ctx->psw_n_nonzero = false;
4148    if (ctx->tb_flags & PSW_N) {
4149        ctx->null_cond.c = TCG_COND_ALWAYS;
4150        ctx->psw_n_nonzero = true;
4151    }
4152    ctx->null_lab = NULL;
4153}
4154
4155static void hppa_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
4156{
4157    DisasContext *ctx = container_of(dcbase, DisasContext, base);
4158
4159    tcg_gen_insn_start(ctx->iaoq_f, ctx->iaoq_b);
4160}
4161
4162static void hppa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
4163{
4164    DisasContext *ctx = container_of(dcbase, DisasContext, base);
4165    CPUHPPAState *env = cs->env_ptr;
4166    DisasJumpType ret;
4167    int i, n;
4168
4169    /* Execute one insn.  */
4170#ifdef CONFIG_USER_ONLY
4171    if (ctx->base.pc_next < TARGET_PAGE_SIZE) {
4172        do_page_zero(ctx);
4173        ret = ctx->base.is_jmp;
4174        assert(ret != DISAS_NEXT);
4175    } else
4176#endif
4177    {
4178        /* Always fetch the insn, even if nullified, so that we check
4179           the page permissions for execute.  */
4180        uint32_t insn = translator_ldl(env, ctx->base.pc_next);
4181
4182        /* Set up the IA queue for the next insn.
4183           This will be overwritten by a branch.  */
4184        if (ctx->iaoq_b == -1) {
4185            ctx->iaoq_n = -1;
4186            ctx->iaoq_n_var = get_temp(ctx);
4187            tcg_gen_addi_reg(ctx->iaoq_n_var, cpu_iaoq_b, 4);
4188        } else {
4189            ctx->iaoq_n = ctx->iaoq_b + 4;
4190            ctx->iaoq_n_var = NULL;
4191        }
4192
4193        if (unlikely(ctx->null_cond.c == TCG_COND_ALWAYS)) {
4194            ctx->null_cond.c = TCG_COND_NEVER;
4195            ret = DISAS_NEXT;
4196        } else {
4197            ctx->insn = insn;
4198            if (!decode(ctx, insn)) {
4199                gen_illegal(ctx);
4200            }
4201            ret = ctx->base.is_jmp;
4202            assert(ctx->null_lab == NULL);
4203        }
4204    }
4205
4206    /* Free any temporaries allocated.  */
4207    for (i = 0, n = ctx->ntempr; i < n; ++i) {
4208        tcg_temp_free(ctx->tempr[i]);
4209        ctx->tempr[i] = NULL;
4210    }
4211    for (i = 0, n = ctx->ntempl; i < n; ++i) {
4212        tcg_temp_free_tl(ctx->templ[i]);
4213        ctx->templ[i] = NULL;
4214    }
4215    ctx->ntempr = 0;
4216    ctx->ntempl = 0;
4217
4218    /* Advance the insn queue.  Note that this check also detects
4219       a priority change within the instruction queue.  */
4220    if (ret == DISAS_NEXT && ctx->iaoq_b != ctx->iaoq_f + 4) {
4221        if (ctx->iaoq_b != -1 && ctx->iaoq_n != -1
4222            && use_goto_tb(ctx, ctx->iaoq_b)
4223            && (ctx->null_cond.c == TCG_COND_NEVER
4224                || ctx->null_cond.c == TCG_COND_ALWAYS)) {
4225            nullify_set(ctx, ctx->null_cond.c == TCG_COND_ALWAYS);
4226            gen_goto_tb(ctx, 0, ctx->iaoq_b, ctx->iaoq_n);
4227            ctx->base.is_jmp = ret = DISAS_NORETURN;
4228        } else {
4229            ctx->base.is_jmp = ret = DISAS_IAQ_N_STALE;
4230        }
4231    }
4232    ctx->iaoq_f = ctx->iaoq_b;
4233    ctx->iaoq_b = ctx->iaoq_n;
4234    ctx->base.pc_next += 4;
4235
4236    switch (ret) {
4237    case DISAS_NORETURN:
4238    case DISAS_IAQ_N_UPDATED:
4239        break;
4240
4241    case DISAS_NEXT:
4242    case DISAS_IAQ_N_STALE:
4243    case DISAS_IAQ_N_STALE_EXIT:
4244        if (ctx->iaoq_f == -1) {
4245            tcg_gen_mov_reg(cpu_iaoq_f, cpu_iaoq_b);
4246            copy_iaoq_entry(cpu_iaoq_b, ctx->iaoq_n, ctx->iaoq_n_var);
4247#ifndef CONFIG_USER_ONLY
4248            tcg_gen_mov_i64(cpu_iasq_f, cpu_iasq_b);
4249#endif
4250            nullify_save(ctx);
4251            ctx->base.is_jmp = (ret == DISAS_IAQ_N_STALE_EXIT
4252                                ? DISAS_EXIT
4253                                : DISAS_IAQ_N_UPDATED);
4254        } else if (ctx->iaoq_b == -1) {
4255            tcg_gen_mov_reg(cpu_iaoq_b, ctx->iaoq_n_var);
4256        }
4257        break;
4258
4259    default:
4260        g_assert_not_reached();
4261    }
4262}
4263
4264static void hppa_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
4265{
4266    DisasContext *ctx = container_of(dcbase, DisasContext, base);
4267    DisasJumpType is_jmp = ctx->base.is_jmp;
4268
4269    switch (is_jmp) {
4270    case DISAS_NORETURN:
4271        break;
4272    case DISAS_TOO_MANY:
4273    case DISAS_IAQ_N_STALE:
4274    case DISAS_IAQ_N_STALE_EXIT:
4275        copy_iaoq_entry(cpu_iaoq_f, ctx->iaoq_f, cpu_iaoq_f);
4276        copy_iaoq_entry(cpu_iaoq_b, ctx->iaoq_b, cpu_iaoq_b);
4277        nullify_save(ctx);
4278        /* FALLTHRU */
4279    case DISAS_IAQ_N_UPDATED:
4280        if (ctx->base.singlestep_enabled) {
4281            gen_excp_1(EXCP_DEBUG);
4282        } else if (is_jmp != DISAS_IAQ_N_STALE_EXIT) {
4283            tcg_gen_lookup_and_goto_ptr();
4284        }
4285        /* FALLTHRU */
4286    case DISAS_EXIT:
4287        tcg_gen_exit_tb(NULL, 0);
4288        break;
4289    default:
4290        g_assert_not_reached();
4291    }
4292}
4293
4294static void hppa_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
4295{
4296    target_ulong pc = dcbase->pc_first;
4297
4298#ifdef CONFIG_USER_ONLY
4299    switch (pc) {
4300    case 0x00:
4301        qemu_log("IN:\n0x00000000:  (null)\n");
4302        return;
4303    case 0xb0:
4304        qemu_log("IN:\n0x000000b0:  light-weight-syscall\n");
4305        return;
4306    case 0xe0:
4307        qemu_log("IN:\n0x000000e0:  set-thread-pointer-syscall\n");
4308        return;
4309    case 0x100:
4310        qemu_log("IN:\n0x00000100:  syscall\n");
4311        return;
4312    }
4313#endif
4314
4315    qemu_log("IN: %s\n", lookup_symbol(pc));
4316    log_target_disas(cs, pc, dcbase->tb->size);
4317}
4318
4319static const TranslatorOps hppa_tr_ops = {
4320    .init_disas_context = hppa_tr_init_disas_context,
4321    .tb_start           = hppa_tr_tb_start,
4322    .insn_start         = hppa_tr_insn_start,
4323    .translate_insn     = hppa_tr_translate_insn,
4324    .tb_stop            = hppa_tr_tb_stop,
4325    .disas_log          = hppa_tr_disas_log,
4326};
4327
4328void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
4329{
4330    DisasContext ctx;
4331    translator_loop(&hppa_tr_ops, &ctx.base, cs, tb, max_insns);
4332}
4333
4334void restore_state_to_opc(CPUHPPAState *env, TranslationBlock *tb,
4335                          target_ulong *data)
4336{
4337    env->iaoq_f = data[0];
4338    if (data[1] != (target_ureg)-1) {
4339        env->iaoq_b = data[1];
4340    }
4341    /* Since we were executing the instruction at IAOQ_F, and took some
4342       sort of action that provoked the cpu_restore_state, we can infer
4343       that the instruction was not nullified.  */
4344    env->psw_n = 0;
4345}
4346