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 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-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 "trace-tcg.h"
  31#include "exec/log.h"
  32
  33/* Since we have a distinction between register size and address size,
  34   we need to redefine all of these.  */
  35
  36#undef TCGv
  37#undef tcg_temp_new
  38#undef tcg_global_reg_new
  39#undef tcg_global_mem_new
  40#undef tcg_temp_local_new
  41#undef tcg_temp_free
  42
  43#if TARGET_LONG_BITS == 64
  44#define TCGv_tl              TCGv_i64
  45#define tcg_temp_new_tl      tcg_temp_new_i64
  46#define tcg_temp_free_tl     tcg_temp_free_i64
  47#if TARGET_REGISTER_BITS == 64
  48#define tcg_gen_extu_reg_tl  tcg_gen_mov_i64
  49#else
  50#define tcg_gen_extu_reg_tl  tcg_gen_extu_i32_i64
  51#endif
  52#else
  53#define TCGv_tl              TCGv_i32
  54#define tcg_temp_new_tl      tcg_temp_new_i32
  55#define tcg_temp_free_tl     tcg_temp_free_i32
  56#define tcg_gen_extu_reg_tl  tcg_gen_mov_i32
  57#endif
  58
  59#if TARGET_REGISTER_BITS == 64
  60#define TCGv_reg             TCGv_i64
  61
  62#define tcg_temp_new         tcg_temp_new_i64
  63#define tcg_global_reg_new   tcg_global_reg_new_i64
  64#define tcg_global_mem_new   tcg_global_mem_new_i64
  65#define tcg_temp_local_new   tcg_temp_local_new_i64
  66#define tcg_temp_free        tcg_temp_free_i64
  67
  68#define tcg_gen_movi_reg     tcg_gen_movi_i64
  69#define tcg_gen_mov_reg      tcg_gen_mov_i64
  70#define tcg_gen_ld8u_reg     tcg_gen_ld8u_i64
  71#define tcg_gen_ld8s_reg     tcg_gen_ld8s_i64
  72#define tcg_gen_ld16u_reg    tcg_gen_ld16u_i64
  73#define tcg_gen_ld16s_reg    tcg_gen_ld16s_i64
  74#define tcg_gen_ld32u_reg    tcg_gen_ld32u_i64
  75#define tcg_gen_ld32s_reg    tcg_gen_ld32s_i64
  76#define tcg_gen_ld_reg       tcg_gen_ld_i64
  77#define tcg_gen_st8_reg      tcg_gen_st8_i64
  78#define tcg_gen_st16_reg     tcg_gen_st16_i64
  79#define tcg_gen_st32_reg     tcg_gen_st32_i64
  80#define tcg_gen_st_reg       tcg_gen_st_i64
  81#define tcg_gen_add_reg      tcg_gen_add_i64
  82#define tcg_gen_addi_reg     tcg_gen_addi_i64
  83#define tcg_gen_sub_reg      tcg_gen_sub_i64
  84#define tcg_gen_neg_reg      tcg_gen_neg_i64
  85#define tcg_gen_subfi_reg    tcg_gen_subfi_i64
  86#define tcg_gen_subi_reg     tcg_gen_subi_i64
  87#define tcg_gen_and_reg      tcg_gen_and_i64
  88#define tcg_gen_andi_reg     tcg_gen_andi_i64
  89#define tcg_gen_or_reg       tcg_gen_or_i64
  90#define tcg_gen_ori_reg      tcg_gen_ori_i64
  91#define tcg_gen_xor_reg      tcg_gen_xor_i64
  92#define tcg_gen_xori_reg     tcg_gen_xori_i64
  93#define tcg_gen_not_reg      tcg_gen_not_i64
  94#define tcg_gen_shl_reg      tcg_gen_shl_i64
  95#define tcg_gen_shli_reg     tcg_gen_shli_i64
  96#define tcg_gen_shr_reg      tcg_gen_shr_i64
  97#define tcg_gen_shri_reg     tcg_gen_shri_i64
  98#define tcg_gen_sar_reg      tcg_gen_sar_i64
  99#define tcg_gen_sari_reg     tcg_gen_sari_i64
 100#define tcg_gen_brcond_reg   tcg_gen_brcond_i64
 101#define tcg_gen_brcondi_reg  tcg_gen_brcondi_i64
 102#define tcg_gen_setcond_reg  tcg_gen_setcond_i64
 103#define tcg_gen_setcondi_reg tcg_gen_setcondi_i64
 104#define tcg_gen_mul_reg      tcg_gen_mul_i64
 105#define tcg_gen_muli_reg     tcg_gen_muli_i64
 106#define tcg_gen_div_reg      tcg_gen_div_i64
 107#define tcg_gen_rem_reg      tcg_gen_rem_i64
 108#define tcg_gen_divu_reg     tcg_gen_divu_i64
 109#define tcg_gen_remu_reg     tcg_gen_remu_i64
 110#define tcg_gen_discard_reg  tcg_gen_discard_i64
 111#define tcg_gen_trunc_reg_i32 tcg_gen_extrl_i64_i32
 112#define tcg_gen_trunc_i64_reg tcg_gen_mov_i64
 113#define tcg_gen_extu_i32_reg tcg_gen_extu_i32_i64
 114#define tcg_gen_ext_i32_reg  tcg_gen_ext_i32_i64
 115#define tcg_gen_extu_reg_i64 tcg_gen_mov_i64
 116#define tcg_gen_ext_reg_i64  tcg_gen_mov_i64
 117#define tcg_gen_ext8u_reg    tcg_gen_ext8u_i64
 118#define tcg_gen_ext8s_reg    tcg_gen_ext8s_i64
 119#define tcg_gen_ext16u_reg   tcg_gen_ext16u_i64
 120#define tcg_gen_ext16s_reg   tcg_gen_ext16s_i64
 121#define tcg_gen_ext32u_reg   tcg_gen_ext32u_i64
 122#define tcg_gen_ext32s_reg   tcg_gen_ext32s_i64
 123#define tcg_gen_bswap16_reg  tcg_gen_bswap16_i64
 124#define tcg_gen_bswap32_reg  tcg_gen_bswap32_i64
 125#define tcg_gen_bswap64_reg  tcg_gen_bswap64_i64
 126#define tcg_gen_concat_reg_i64 tcg_gen_concat32_i64
 127#define tcg_gen_andc_reg     tcg_gen_andc_i64
 128#define tcg_gen_eqv_reg      tcg_gen_eqv_i64
 129#define tcg_gen_nand_reg     tcg_gen_nand_i64
 130#define tcg_gen_nor_reg      tcg_gen_nor_i64
 131#define tcg_gen_orc_reg      tcg_gen_orc_i64
 132#define tcg_gen_clz_reg      tcg_gen_clz_i64
 133#define tcg_gen_ctz_reg      tcg_gen_ctz_i64
 134#define tcg_gen_clzi_reg     tcg_gen_clzi_i64
 135#define tcg_gen_ctzi_reg     tcg_gen_ctzi_i64
 136#define tcg_gen_clrsb_reg    tcg_gen_clrsb_i64
 137#define tcg_gen_ctpop_reg    tcg_gen_ctpop_i64
 138#define tcg_gen_rotl_reg     tcg_gen_rotl_i64
 139#define tcg_gen_rotli_reg    tcg_gen_rotli_i64
 140#define tcg_gen_rotr_reg     tcg_gen_rotr_i64
 141#define tcg_gen_rotri_reg    tcg_gen_rotri_i64
 142#define tcg_gen_deposit_reg  tcg_gen_deposit_i64
 143#define tcg_gen_deposit_z_reg tcg_gen_deposit_z_i64
 144#define tcg_gen_extract_reg  tcg_gen_extract_i64
 145#define tcg_gen_sextract_reg tcg_gen_sextract_i64
 146#define tcg_const_reg        tcg_const_i64
 147#define tcg_const_local_reg  tcg_const_local_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#if UINTPTR_MAX == UINT32_MAX
 155# define tcg_gen_trunc_reg_ptr(p, r) \
 156    tcg_gen_trunc_i64_i32(TCGV_PTR_TO_NAT(p), r)
 157#else
 158# define tcg_gen_trunc_reg_ptr(p, r) \
 159    tcg_gen_mov_i64(TCGV_PTR_TO_NAT(p), r)
 160#endif
 161#else
 162#define TCGv_reg             TCGv_i32
 163#define tcg_temp_new         tcg_temp_new_i32
 164#define tcg_global_reg_new   tcg_global_reg_new_i32
 165#define tcg_global_mem_new   tcg_global_mem_new_i32
 166#define tcg_temp_local_new   tcg_temp_local_new_i32
 167#define tcg_temp_free        tcg_temp_free_i32
 168
 169#define tcg_gen_movi_reg     tcg_gen_movi_i32
 170#define tcg_gen_mov_reg      tcg_gen_mov_i32
 171#define tcg_gen_ld8u_reg     tcg_gen_ld8u_i32
 172#define tcg_gen_ld8s_reg     tcg_gen_ld8s_i32
 173#define tcg_gen_ld16u_reg    tcg_gen_ld16u_i32
 174#define tcg_gen_ld16s_reg    tcg_gen_ld16s_i32
 175#define tcg_gen_ld32u_reg    tcg_gen_ld_i32
 176#define tcg_gen_ld32s_reg    tcg_gen_ld_i32
 177#define tcg_gen_ld_reg       tcg_gen_ld_i32
 178#define tcg_gen_st8_reg      tcg_gen_st8_i32
 179#define tcg_gen_st16_reg     tcg_gen_st16_i32
 180#define tcg_gen_st32_reg     tcg_gen_st32_i32
 181#define tcg_gen_st_reg       tcg_gen_st_i32
 182#define tcg_gen_add_reg      tcg_gen_add_i32
 183#define tcg_gen_addi_reg     tcg_gen_addi_i32
 184#define tcg_gen_sub_reg      tcg_gen_sub_i32
 185#define tcg_gen_neg_reg      tcg_gen_neg_i32
 186#define tcg_gen_subfi_reg    tcg_gen_subfi_i32
 187#define tcg_gen_subi_reg     tcg_gen_subi_i32
 188#define tcg_gen_and_reg      tcg_gen_and_i32
 189#define tcg_gen_andi_reg     tcg_gen_andi_i32
 190#define tcg_gen_or_reg       tcg_gen_or_i32
 191#define tcg_gen_ori_reg      tcg_gen_ori_i32
 192#define tcg_gen_xor_reg      tcg_gen_xor_i32
 193#define tcg_gen_xori_reg     tcg_gen_xori_i32
 194#define tcg_gen_not_reg      tcg_gen_not_i32
 195#define tcg_gen_shl_reg      tcg_gen_shl_i32
 196#define tcg_gen_shli_reg     tcg_gen_shli_i32
 197#define tcg_gen_shr_reg      tcg_gen_shr_i32
 198#define tcg_gen_shri_reg     tcg_gen_shri_i32
 199#define tcg_gen_sar_reg      tcg_gen_sar_i32
 200#define tcg_gen_sari_reg     tcg_gen_sari_i32
 201#define tcg_gen_brcond_reg   tcg_gen_brcond_i32
 202#define tcg_gen_brcondi_reg  tcg_gen_brcondi_i32
 203#define tcg_gen_setcond_reg  tcg_gen_setcond_i32
 204#define tcg_gen_setcondi_reg tcg_gen_setcondi_i32
 205#define tcg_gen_mul_reg      tcg_gen_mul_i32
 206#define tcg_gen_muli_reg     tcg_gen_muli_i32
 207#define tcg_gen_div_reg      tcg_gen_div_i32
 208#define tcg_gen_rem_reg      tcg_gen_rem_i32
 209#define tcg_gen_divu_reg     tcg_gen_divu_i32
 210#define tcg_gen_remu_reg     tcg_gen_remu_i32
 211#define tcg_gen_discard_reg  tcg_gen_discard_i32
 212#define tcg_gen_trunc_reg_i32 tcg_gen_mov_i32
 213#define tcg_gen_trunc_i64_reg tcg_gen_extrl_i64_i32
 214#define tcg_gen_extu_i32_reg tcg_gen_mov_i32
 215#define tcg_gen_ext_i32_reg  tcg_gen_mov_i32
 216#define tcg_gen_extu_reg_i64 tcg_gen_extu_i32_i64
 217#define tcg_gen_ext_reg_i64  tcg_gen_ext_i32_i64
 218#define tcg_gen_ext8u_reg    tcg_gen_ext8u_i32
 219#define tcg_gen_ext8s_reg    tcg_gen_ext8s_i32
 220#define tcg_gen_ext16u_reg   tcg_gen_ext16u_i32
 221#define tcg_gen_ext16s_reg   tcg_gen_ext16s_i32
 222#define tcg_gen_ext32u_reg   tcg_gen_mov_i32
 223#define tcg_gen_ext32s_reg   tcg_gen_mov_i32
 224#define tcg_gen_bswap16_reg  tcg_gen_bswap16_i32
 225#define tcg_gen_bswap32_reg  tcg_gen_bswap32_i32
 226#define tcg_gen_concat_reg_i64 tcg_gen_concat_i32_i64
 227#define tcg_gen_andc_reg     tcg_gen_andc_i32
 228#define tcg_gen_eqv_reg      tcg_gen_eqv_i32
 229#define tcg_gen_nand_reg     tcg_gen_nand_i32
 230#define tcg_gen_nor_reg      tcg_gen_nor_i32
 231#define tcg_gen_orc_reg      tcg_gen_orc_i32
 232#define tcg_gen_clz_reg      tcg_gen_clz_i32
 233#define tcg_gen_ctz_reg      tcg_gen_ctz_i32
 234#define tcg_gen_clzi_reg     tcg_gen_clzi_i32
 235#define tcg_gen_ctzi_reg     tcg_gen_ctzi_i32
 236#define tcg_gen_clrsb_reg    tcg_gen_clrsb_i32
 237#define tcg_gen_ctpop_reg    tcg_gen_ctpop_i32
 238#define tcg_gen_rotl_reg     tcg_gen_rotl_i32
 239#define tcg_gen_rotli_reg    tcg_gen_rotli_i32
 240#define tcg_gen_rotr_reg     tcg_gen_rotr_i32
 241#define tcg_gen_rotri_reg    tcg_gen_rotri_i32
 242#define tcg_gen_deposit_reg  tcg_gen_deposit_i32
 243#define tcg_gen_deposit_z_reg tcg_gen_deposit_z_i32
 244#define tcg_gen_extract_reg  tcg_gen_extract_i32
 245#define tcg_gen_sextract_reg tcg_gen_sextract_i32
 246#define tcg_const_reg        tcg_const_i32
 247#define tcg_const_local_reg  tcg_const_local_i32
 248#define tcg_gen_movcond_reg  tcg_gen_movcond_i32
 249#define tcg_gen_add2_reg     tcg_gen_add2_i32
 250#define tcg_gen_sub2_reg     tcg_gen_sub2_i32
 251#define tcg_gen_qemu_ld_reg  tcg_gen_qemu_ld_i32
 252#define tcg_gen_qemu_st_reg  tcg_gen_qemu_st_i32
 253#define tcg_gen_atomic_xchg_reg tcg_gen_atomic_xchg_i32
 254#if UINTPTR_MAX == UINT32_MAX
 255# define tcg_gen_trunc_reg_ptr(p, r) \
 256    tcg_gen_mov_i32(TCGV_PTR_TO_NAT(p), r)
 257#else
 258# define tcg_gen_trunc_reg_ptr(p, r) \
 259    tcg_gen_extu_i32_i64(TCGV_PTR_TO_NAT(p), r)
 260#endif
 261#endif /* TARGET_REGISTER_BITS */
 262
 263typedef struct DisasCond {
 264    TCGCond c;
 265    TCGv_reg a0, a1;
 266    bool a0_is_n;
 267    bool a1_is_0;
 268} DisasCond;
 269
 270typedef struct DisasContext {
 271    DisasContextBase base;
 272    CPUState *cs;
 273
 274    target_ureg iaoq_f;
 275    target_ureg iaoq_b;
 276    target_ureg iaoq_n;
 277    TCGv_reg iaoq_n_var;
 278
 279    int ntempr, ntempl;
 280    TCGv_reg tempr[8];
 281    TCGv_tl  templ[4];
 282
 283    DisasCond null_cond;
 284    TCGLabel *null_lab;
 285
 286    uint32_t insn;
 287    uint32_t tb_flags;
 288    int mmu_idx;
 289    int privilege;
 290    bool psw_n_nonzero;
 291} DisasContext;
 292
 293/* Target-specific return values from translate_one, indicating the
 294   state of the TB.  Note that DISAS_NEXT indicates that we are not
 295   exiting the TB.  */
 296
 297/* We are not using a goto_tb (for whatever reason), but have updated
 298   the iaq (for whatever reason), so don't do it again on exit.  */
 299#define DISAS_IAQ_N_UPDATED  DISAS_TARGET_0
 300
 301/* We are exiting the TB, but have neither emitted a goto_tb, nor
 302   updated the iaq for the next instruction to be executed.  */
 303#define DISAS_IAQ_N_STALE    DISAS_TARGET_1
 304
 305/* Similarly, but we want to return to the main loop immediately
 306   to recognize unmasked interrupts.  */
 307#define DISAS_IAQ_N_STALE_EXIT      DISAS_TARGET_2
 308
 309typedef struct DisasInsn {
 310    uint32_t insn, mask;
 311    DisasJumpType (*trans)(DisasContext *ctx, uint32_t insn,
 312                           const struct DisasInsn *f);
 313    union {
 314        void (*ttt)(TCGv_reg, TCGv_reg, TCGv_reg);
 315        void (*weww)(TCGv_i32, TCGv_env, TCGv_i32, TCGv_i32);
 316        void (*dedd)(TCGv_i64, TCGv_env, TCGv_i64, TCGv_i64);
 317        void (*wew)(TCGv_i32, TCGv_env, TCGv_i32);
 318        void (*ded)(TCGv_i64, TCGv_env, TCGv_i64);
 319        void (*wed)(TCGv_i32, TCGv_env, TCGv_i64);
 320        void (*dew)(TCGv_i64, TCGv_env, TCGv_i32);
 321    } f;
 322} DisasInsn;
 323
 324/* global register indexes */
 325static TCGv_reg cpu_gr[32];
 326static TCGv_i64 cpu_sr[4];
 327static TCGv_i64 cpu_srH;
 328static TCGv_reg cpu_iaoq_f;
 329static TCGv_reg cpu_iaoq_b;
 330static TCGv_i64 cpu_iasq_f;
 331static TCGv_i64 cpu_iasq_b;
 332static TCGv_reg cpu_sar;
 333static TCGv_reg cpu_psw_n;
 334static TCGv_reg cpu_psw_v;
 335static TCGv_reg cpu_psw_cb;
 336static TCGv_reg cpu_psw_cb_msb;
 337
 338#include "exec/gen-icount.h"
 339
 340void hppa_translate_init(void)
 341{
 342#define DEF_VAR(V)  { &cpu_##V, #V, offsetof(CPUHPPAState, V) }
 343
 344    typedef struct { TCGv_reg *var; const char *name; int ofs; } GlobalVar;
 345    static const GlobalVar vars[] = {
 346        { &cpu_sar, "sar", offsetof(CPUHPPAState, cr[CR_SAR]) },
 347        DEF_VAR(psw_n),
 348        DEF_VAR(psw_v),
 349        DEF_VAR(psw_cb),
 350        DEF_VAR(psw_cb_msb),
 351        DEF_VAR(iaoq_f),
 352        DEF_VAR(iaoq_b),
 353    };
 354
 355#undef DEF_VAR
 356
 357    /* Use the symbolic register names that match the disassembler.  */
 358    static const char gr_names[32][4] = {
 359        "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
 360        "r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15",
 361        "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
 362        "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31"
 363    };
 364    /* SR[4-7] are not global registers so that we can index them.  */
 365    static const char sr_names[5][4] = {
 366        "sr0", "sr1", "sr2", "sr3", "srH"
 367    };
 368
 369    int i;
 370
 371    cpu_gr[0] = NULL;
 372    for (i = 1; i < 32; i++) {
 373        cpu_gr[i] = tcg_global_mem_new(cpu_env,
 374                                       offsetof(CPUHPPAState, gr[i]),
 375                                       gr_names[i]);
 376    }
 377    for (i = 0; i < 4; i++) {
 378        cpu_sr[i] = tcg_global_mem_new_i64(cpu_env,
 379                                           offsetof(CPUHPPAState, sr[i]),
 380                                           sr_names[i]);
 381    }
 382    cpu_srH = tcg_global_mem_new_i64(cpu_env,
 383                                     offsetof(CPUHPPAState, sr[4]),
 384                                     sr_names[4]);
 385
 386    for (i = 0; i < ARRAY_SIZE(vars); ++i) {
 387        const GlobalVar *v = &vars[i];
 388        *v->var = tcg_global_mem_new(cpu_env, v->ofs, v->name);
 389    }
 390
 391    cpu_iasq_f = tcg_global_mem_new_i64(cpu_env,
 392                                        offsetof(CPUHPPAState, iasq_f),
 393                                        "iasq_f");
 394    cpu_iasq_b = tcg_global_mem_new_i64(cpu_env,
 395                                        offsetof(CPUHPPAState, iasq_b),
 396                                        "iasq_b");
 397}
 398
 399static DisasCond cond_make_f(void)
 400{
 401    return (DisasCond){
 402        .c = TCG_COND_NEVER,
 403        .a0 = NULL,
 404        .a1 = NULL,
 405    };
 406}
 407
 408static DisasCond cond_make_n(void)
 409{
 410    return (DisasCond){
 411        .c = TCG_COND_NE,
 412        .a0 = cpu_psw_n,
 413        .a0_is_n = true,
 414        .a1 = NULL,
 415        .a1_is_0 = true
 416    };
 417}
 418
 419static DisasCond cond_make_0(TCGCond c, TCGv_reg a0)
 420{
 421    DisasCond r = { .c = c, .a1 = NULL, .a1_is_0 = true };
 422
 423    assert (c != TCG_COND_NEVER && c != TCG_COND_ALWAYS);
 424    r.a0 = tcg_temp_new();
 425    tcg_gen_mov_reg(r.a0, a0);
 426
 427    return r;
 428}
 429
 430static DisasCond cond_make(TCGCond c, TCGv_reg a0, TCGv_reg a1)
 431{
 432    DisasCond r = { .c = c };
 433
 434    assert (c != TCG_COND_NEVER && c != TCG_COND_ALWAYS);
 435    r.a0 = tcg_temp_new();
 436    tcg_gen_mov_reg(r.a0, a0);
 437    r.a1 = tcg_temp_new();
 438    tcg_gen_mov_reg(r.a1, a1);
 439
 440    return r;
 441}
 442
 443static void cond_prep(DisasCond *cond)
 444{
 445    if (cond->a1_is_0) {
 446        cond->a1_is_0 = false;
 447        cond->a1 = tcg_const_reg(0);
 448    }
 449}
 450
 451static void cond_free(DisasCond *cond)
 452{
 453    switch (cond->c) {
 454    default:
 455        if (!cond->a0_is_n) {
 456            tcg_temp_free(cond->a0);
 457        }
 458        if (!cond->a1_is_0) {
 459            tcg_temp_free(cond->a1);
 460        }
 461        cond->a0_is_n = false;
 462        cond->a1_is_0 = false;
 463        cond->a0 = NULL;
 464        cond->a1 = NULL;
 465        /* fallthru */
 466    case TCG_COND_ALWAYS:
 467        cond->c = TCG_COND_NEVER;
 468        break;
 469    case TCG_COND_NEVER:
 470        break;
 471    }
 472}
 473
 474static TCGv_reg get_temp(DisasContext *ctx)
 475{
 476    unsigned i = ctx->ntempr++;
 477    g_assert(i < ARRAY_SIZE(ctx->tempr));
 478    return ctx->tempr[i] = tcg_temp_new();
 479}
 480
 481#ifndef CONFIG_USER_ONLY
 482static TCGv_tl get_temp_tl(DisasContext *ctx)
 483{
 484    unsigned i = ctx->ntempl++;
 485    g_assert(i < ARRAY_SIZE(ctx->templ));
 486    return ctx->templ[i] = tcg_temp_new_tl();
 487}
 488#endif
 489
 490static TCGv_reg load_const(DisasContext *ctx, target_sreg v)
 491{
 492    TCGv_reg t = get_temp(ctx);
 493    tcg_gen_movi_reg(t, v);
 494    return t;
 495}
 496
 497static TCGv_reg load_gpr(DisasContext *ctx, unsigned reg)
 498{
 499    if (reg == 0) {
 500        TCGv_reg t = get_temp(ctx);
 501        tcg_gen_movi_reg(t, 0);
 502        return t;
 503    } else {
 504        return cpu_gr[reg];
 505    }
 506}
 507
 508static TCGv_reg dest_gpr(DisasContext *ctx, unsigned reg)
 509{
 510    if (reg == 0 || ctx->null_cond.c != TCG_COND_NEVER) {
 511        return get_temp(ctx);
 512    } else {
 513        return cpu_gr[reg];
 514    }
 515}
 516
 517static void save_or_nullify(DisasContext *ctx, TCGv_reg dest, TCGv_reg t)
 518{
 519    if (ctx->null_cond.c != TCG_COND_NEVER) {
 520        cond_prep(&ctx->null_cond);
 521        tcg_gen_movcond_reg(ctx->null_cond.c, dest, ctx->null_cond.a0,
 522                           ctx->null_cond.a1, dest, t);
 523    } else {
 524        tcg_gen_mov_reg(dest, t);
 525    }
 526}
 527
 528static void save_gpr(DisasContext *ctx, unsigned reg, TCGv_reg t)
 529{
 530    if (reg != 0) {
 531        save_or_nullify(ctx, cpu_gr[reg], t);
 532    }
 533}
 534
 535#ifdef HOST_WORDS_BIGENDIAN
 536# define HI_OFS  0
 537# define LO_OFS  4
 538#else
 539# define HI_OFS  4
 540# define LO_OFS  0
 541#endif
 542
 543static TCGv_i32 load_frw_i32(unsigned rt)
 544{
 545    TCGv_i32 ret = tcg_temp_new_i32();
 546    tcg_gen_ld_i32(ret, cpu_env,
 547                   offsetof(CPUHPPAState, fr[rt & 31])
 548                   + (rt & 32 ? LO_OFS : HI_OFS));
 549    return ret;
 550}
 551
 552static TCGv_i32 load_frw0_i32(unsigned rt)
 553{
 554    if (rt == 0) {
 555        return tcg_const_i32(0);
 556    } else {
 557        return load_frw_i32(rt);
 558    }
 559}
 560
 561static TCGv_i64 load_frw0_i64(unsigned rt)
 562{
 563    if (rt == 0) {
 564        return tcg_const_i64(0);
 565    } else {
 566        TCGv_i64 ret = tcg_temp_new_i64();
 567        tcg_gen_ld32u_i64(ret, cpu_env,
 568                          offsetof(CPUHPPAState, fr[rt & 31])
 569                          + (rt & 32 ? LO_OFS : HI_OFS));
 570        return ret;
 571    }
 572}
 573
 574static void save_frw_i32(unsigned rt, TCGv_i32 val)
 575{
 576    tcg_gen_st_i32(val, cpu_env,
 577                   offsetof(CPUHPPAState, fr[rt & 31])
 578                   + (rt & 32 ? LO_OFS : HI_OFS));
 579}
 580
 581#undef HI_OFS
 582#undef LO_OFS
 583
 584static TCGv_i64 load_frd(unsigned rt)
 585{
 586    TCGv_i64 ret = tcg_temp_new_i64();
 587    tcg_gen_ld_i64(ret, cpu_env, offsetof(CPUHPPAState, fr[rt]));
 588    return ret;
 589}
 590
 591static TCGv_i64 load_frd0(unsigned rt)
 592{
 593    if (rt == 0) {
 594        return tcg_const_i64(0);
 595    } else {
 596        return load_frd(rt);
 597    }
 598}
 599
 600static void save_frd(unsigned rt, TCGv_i64 val)
 601{
 602    tcg_gen_st_i64(val, cpu_env, offsetof(CPUHPPAState, fr[rt]));
 603}
 604
 605static void load_spr(DisasContext *ctx, TCGv_i64 dest, unsigned reg)
 606{
 607#ifdef CONFIG_USER_ONLY
 608    tcg_gen_movi_i64(dest, 0);
 609#else
 610    if (reg < 4) {
 611        tcg_gen_mov_i64(dest, cpu_sr[reg]);
 612    } else if (ctx->tb_flags & TB_FLAG_SR_SAME) {
 613        tcg_gen_mov_i64(dest, cpu_srH);
 614    } else {
 615        tcg_gen_ld_i64(dest, cpu_env, offsetof(CPUHPPAState, sr[reg]));
 616    }
 617#endif
 618}
 619
 620/* Skip over the implementation of an insn that has been nullified.
 621   Use this when the insn is too complex for a conditional move.  */
 622static void nullify_over(DisasContext *ctx)
 623{
 624    if (ctx->null_cond.c != TCG_COND_NEVER) {
 625        /* The always condition should have been handled in the main loop.  */
 626        assert(ctx->null_cond.c != TCG_COND_ALWAYS);
 627
 628        ctx->null_lab = gen_new_label();
 629        cond_prep(&ctx->null_cond);
 630
 631        /* If we're using PSW[N], copy it to a temp because... */
 632        if (ctx->null_cond.a0_is_n) {
 633            ctx->null_cond.a0_is_n = false;
 634            ctx->null_cond.a0 = tcg_temp_new();
 635            tcg_gen_mov_reg(ctx->null_cond.a0, cpu_psw_n);
 636        }
 637        /* ... we clear it before branching over the implementation,
 638           so that (1) it's clear after nullifying this insn and
 639           (2) if this insn nullifies the next, PSW[N] is valid.  */
 640        if (ctx->psw_n_nonzero) {
 641            ctx->psw_n_nonzero = false;
 642            tcg_gen_movi_reg(cpu_psw_n, 0);
 643        }
 644
 645        tcg_gen_brcond_reg(ctx->null_cond.c, ctx->null_cond.a0,
 646                          ctx->null_cond.a1, ctx->null_lab);
 647        cond_free(&ctx->null_cond);
 648    }
 649}
 650
 651/* Save the current nullification state to PSW[N].  */
 652static void nullify_save(DisasContext *ctx)
 653{
 654    if (ctx->null_cond.c == TCG_COND_NEVER) {
 655        if (ctx->psw_n_nonzero) {
 656            tcg_gen_movi_reg(cpu_psw_n, 0);
 657        }
 658        return;
 659    }
 660    if (!ctx->null_cond.a0_is_n) {
 661        cond_prep(&ctx->null_cond);
 662        tcg_gen_setcond_reg(ctx->null_cond.c, cpu_psw_n,
 663                           ctx->null_cond.a0, ctx->null_cond.a1);
 664        ctx->psw_n_nonzero = true;
 665    }
 666    cond_free(&ctx->null_cond);
 667}
 668
 669/* Set a PSW[N] to X.  The intention is that this is used immediately
 670   before a goto_tb/exit_tb, so that there is no fallthru path to other
 671   code within the TB.  Therefore we do not update psw_n_nonzero.  */
 672static void nullify_set(DisasContext *ctx, bool x)
 673{
 674    if (ctx->psw_n_nonzero || x) {
 675        tcg_gen_movi_reg(cpu_psw_n, x);
 676    }
 677}
 678
 679/* Mark the end of an instruction that may have been nullified.
 680   This is the pair to nullify_over.  */
 681static DisasJumpType nullify_end(DisasContext *ctx, DisasJumpType status)
 682{
 683    TCGLabel *null_lab = ctx->null_lab;
 684
 685    /* For NEXT, NORETURN, STALE, we can easily continue (or exit).
 686       For UPDATED, we cannot update on the nullified path.  */
 687    assert(status != DISAS_IAQ_N_UPDATED);
 688
 689    if (likely(null_lab == NULL)) {
 690        /* The current insn wasn't conditional or handled the condition
 691           applied to it without a branch, so the (new) setting of
 692           NULL_COND can be applied directly to the next insn.  */
 693        return status;
 694    }
 695    ctx->null_lab = NULL;
 696
 697    if (likely(ctx->null_cond.c == TCG_COND_NEVER)) {
 698        /* The next instruction will be unconditional,
 699           and NULL_COND already reflects that.  */
 700        gen_set_label(null_lab);
 701    } else {
 702        /* The insn that we just executed is itself nullifying the next
 703           instruction.  Store the condition in the PSW[N] global.
 704           We asserted PSW[N] = 0 in nullify_over, so that after the
 705           label we have the proper value in place.  */
 706        nullify_save(ctx);
 707        gen_set_label(null_lab);
 708        ctx->null_cond = cond_make_n();
 709    }
 710    if (status == DISAS_NORETURN) {
 711        status = DISAS_NEXT;
 712    }
 713    return status;
 714}
 715
 716static void copy_iaoq_entry(TCGv_reg dest, target_ureg ival, TCGv_reg vval)
 717{
 718    if (unlikely(ival == -1)) {
 719        tcg_gen_mov_reg(dest, vval);
 720    } else {
 721        tcg_gen_movi_reg(dest, ival);
 722    }
 723}
 724
 725static inline target_ureg iaoq_dest(DisasContext *ctx, target_sreg disp)
 726{
 727    return ctx->iaoq_f + disp + 8;
 728}
 729
 730static void gen_excp_1(int exception)
 731{
 732    TCGv_i32 t = tcg_const_i32(exception);
 733    gen_helper_excp(cpu_env, t);
 734    tcg_temp_free_i32(t);
 735}
 736
 737static DisasJumpType gen_excp(DisasContext *ctx, int exception)
 738{
 739    copy_iaoq_entry(cpu_iaoq_f, ctx->iaoq_f, cpu_iaoq_f);
 740    copy_iaoq_entry(cpu_iaoq_b, ctx->iaoq_b, cpu_iaoq_b);
 741    nullify_save(ctx);
 742    gen_excp_1(exception);
 743    return DISAS_NORETURN;
 744}
 745
 746static DisasJumpType gen_excp_iir(DisasContext *ctx, int exc)
 747{
 748    TCGv_reg tmp = tcg_const_reg(ctx->insn);
 749    tcg_gen_st_reg(tmp, cpu_env, offsetof(CPUHPPAState, cr[CR_IIR]));
 750    tcg_temp_free(tmp);
 751    return gen_excp(ctx, exc);
 752}
 753
 754static DisasJumpType gen_illegal(DisasContext *ctx)
 755{
 756    nullify_over(ctx);
 757    return nullify_end(ctx, gen_excp_iir(ctx, EXCP_ILL));
 758}
 759
 760#define CHECK_MOST_PRIVILEGED(EXCP)                               \
 761    do {                                                          \
 762        if (ctx->privilege != 0) {                                \
 763            nullify_over(ctx);                                    \
 764            return nullify_end(ctx, gen_excp_iir(ctx, EXCP));     \
 765        }                                                         \
 766    } while (0)
 767
 768static bool use_goto_tb(DisasContext *ctx, target_ureg dest)
 769{
 770    /* Suppress goto_tb in the case of single-steping and IO.  */
 771    if ((tb_cflags(ctx->base.tb) & CF_LAST_IO) || ctx->base.singlestep_enabled) {
 772        return false;
 773    }
 774    return true;
 775}
 776
 777/* If the next insn is to be nullified, and it's on the same page,
 778   and we're not attempting to set a breakpoint on it, then we can
 779   totally skip the nullified insn.  This avoids creating and
 780   executing a TB that merely branches to the next TB.  */
 781static bool use_nullify_skip(DisasContext *ctx)
 782{
 783    return (((ctx->iaoq_b ^ ctx->iaoq_f) & TARGET_PAGE_MASK) == 0
 784            && !cpu_breakpoint_test(ctx->cs, ctx->iaoq_b, BP_ANY));
 785}
 786
 787static void gen_goto_tb(DisasContext *ctx, int which,
 788                        target_ureg f, target_ureg b)
 789{
 790    if (f != -1 && b != -1 && use_goto_tb(ctx, f)) {
 791        tcg_gen_goto_tb(which);
 792        tcg_gen_movi_reg(cpu_iaoq_f, f);
 793        tcg_gen_movi_reg(cpu_iaoq_b, b);
 794        tcg_gen_exit_tb((uintptr_t)ctx->base.tb + which);
 795    } else {
 796        copy_iaoq_entry(cpu_iaoq_f, f, cpu_iaoq_b);
 797        copy_iaoq_entry(cpu_iaoq_b, b, ctx->iaoq_n_var);
 798        if (ctx->base.singlestep_enabled) {
 799            gen_excp_1(EXCP_DEBUG);
 800        } else {
 801            tcg_gen_lookup_and_goto_ptr();
 802        }
 803    }
 804}
 805
 806/* PA has a habit of taking the LSB of a field and using that as the sign,
 807   with the rest of the field becoming the least significant bits.  */
 808static target_sreg low_sextract(uint32_t val, int pos, int len)
 809{
 810    target_ureg x = -(target_ureg)extract32(val, pos, 1);
 811    x = (x << (len - 1)) | extract32(val, pos + 1, len - 1);
 812    return x;
 813}
 814
 815static unsigned assemble_rt64(uint32_t insn)
 816{
 817    unsigned r1 = extract32(insn, 6, 1);
 818    unsigned r0 = extract32(insn, 0, 5);
 819    return r1 * 32 + r0;
 820}
 821
 822static unsigned assemble_ra64(uint32_t insn)
 823{
 824    unsigned r1 = extract32(insn, 7, 1);
 825    unsigned r0 = extract32(insn, 21, 5);
 826    return r1 * 32 + r0;
 827}
 828
 829static unsigned assemble_rb64(uint32_t insn)
 830{
 831    unsigned r1 = extract32(insn, 12, 1);
 832    unsigned r0 = extract32(insn, 16, 5);
 833    return r1 * 32 + r0;
 834}
 835
 836static unsigned assemble_rc64(uint32_t insn)
 837{
 838    unsigned r2 = extract32(insn, 8, 1);
 839    unsigned r1 = extract32(insn, 13, 3);
 840    unsigned r0 = extract32(insn, 9, 2);
 841    return r2 * 32 + r1 * 4 + r0;
 842}
 843
 844static unsigned assemble_sr3(uint32_t insn)
 845{
 846    unsigned s2 = extract32(insn, 13, 1);
 847    unsigned s0 = extract32(insn, 14, 2);
 848    return s2 * 4 + s0;
 849}
 850
 851static target_sreg assemble_12(uint32_t insn)
 852{
 853    target_ureg x = -(target_ureg)(insn & 1);
 854    x = (x <<  1) | extract32(insn, 2, 1);
 855    x = (x << 10) | extract32(insn, 3, 10);
 856    return x;
 857}
 858
 859static target_sreg assemble_16(uint32_t insn)
 860{
 861    /* Take the name from PA2.0, which produces a 16-bit number
 862       only with wide mode; otherwise a 14-bit number.  Since we don't
 863       implement wide mode, this is always the 14-bit number.  */
 864    return low_sextract(insn, 0, 14);
 865}
 866
 867static target_sreg assemble_16a(uint32_t insn)
 868{
 869    /* Take the name from PA2.0, which produces a 14-bit shifted number
 870       only with wide mode; otherwise a 12-bit shifted number.  Since we
 871       don't implement wide mode, this is always the 12-bit number.  */
 872    target_ureg x = -(target_ureg)(insn & 1);
 873    x = (x << 11) | extract32(insn, 2, 11);
 874    return x << 2;
 875}
 876
 877static target_sreg assemble_17(uint32_t insn)
 878{
 879    target_ureg x = -(target_ureg)(insn & 1);
 880    x = (x <<  5) | extract32(insn, 16, 5);
 881    x = (x <<  1) | extract32(insn, 2, 1);
 882    x = (x << 10) | extract32(insn, 3, 10);
 883    return x << 2;
 884}
 885
 886static target_sreg assemble_21(uint32_t insn)
 887{
 888    target_ureg x = -(target_ureg)(insn & 1);
 889    x = (x << 11) | extract32(insn, 1, 11);
 890    x = (x <<  2) | extract32(insn, 14, 2);
 891    x = (x <<  5) | extract32(insn, 16, 5);
 892    x = (x <<  2) | extract32(insn, 12, 2);
 893    return x << 11;
 894}
 895
 896static target_sreg assemble_22(uint32_t insn)
 897{
 898    target_ureg x = -(target_ureg)(insn & 1);
 899    x = (x << 10) | extract32(insn, 16, 10);
 900    x = (x <<  1) | extract32(insn, 2, 1);
 901    x = (x << 10) | extract32(insn, 3, 10);
 902    return x << 2;
 903}
 904
 905/* The parisc documentation describes only the general interpretation of
 906   the conditions, without describing their exact implementation.  The
 907   interpretations do not stand up well when considering ADD,C and SUB,B.
 908   However, considering the Addition, Subtraction and Logical conditions
 909   as a whole it would appear that these relations are similar to what
 910   a traditional NZCV set of flags would produce.  */
 911
 912static DisasCond do_cond(unsigned cf, TCGv_reg res,
 913                         TCGv_reg cb_msb, TCGv_reg sv)
 914{
 915    DisasCond cond;
 916    TCGv_reg tmp;
 917
 918    switch (cf >> 1) {
 919    case 0: /* Never / TR */
 920        cond = cond_make_f();
 921        break;
 922    case 1: /* = / <>        (Z / !Z) */
 923        cond = cond_make_0(TCG_COND_EQ, res);
 924        break;
 925    case 2: /* < / >=        (N / !N) */
 926        cond = cond_make_0(TCG_COND_LT, res);
 927        break;
 928    case 3: /* <= / >        (N | Z / !N & !Z) */
 929        cond = cond_make_0(TCG_COND_LE, res);
 930        break;
 931    case 4: /* NUV / UV      (!C / C) */
 932        cond = cond_make_0(TCG_COND_EQ, cb_msb);
 933        break;
 934    case 5: /* ZNV / VNZ     (!C | Z / C & !Z) */
 935        tmp = tcg_temp_new();
 936        tcg_gen_neg_reg(tmp, cb_msb);
 937        tcg_gen_and_reg(tmp, tmp, res);
 938        cond = cond_make_0(TCG_COND_EQ, tmp);
 939        tcg_temp_free(tmp);
 940        break;
 941    case 6: /* SV / NSV      (V / !V) */
 942        cond = cond_make_0(TCG_COND_LT, sv);
 943        break;
 944    case 7: /* OD / EV */
 945        tmp = tcg_temp_new();
 946        tcg_gen_andi_reg(tmp, res, 1);
 947        cond = cond_make_0(TCG_COND_NE, tmp);
 948        tcg_temp_free(tmp);
 949        break;
 950    default:
 951        g_assert_not_reached();
 952    }
 953    if (cf & 1) {
 954        cond.c = tcg_invert_cond(cond.c);
 955    }
 956
 957    return cond;
 958}
 959
 960/* Similar, but for the special case of subtraction without borrow, we
 961   can use the inputs directly.  This can allow other computation to be
 962   deleted as unused.  */
 963
 964static DisasCond do_sub_cond(unsigned cf, TCGv_reg res,
 965                             TCGv_reg in1, TCGv_reg in2, TCGv_reg sv)
 966{
 967    DisasCond cond;
 968
 969    switch (cf >> 1) {
 970    case 1: /* = / <> */
 971        cond = cond_make(TCG_COND_EQ, in1, in2);
 972        break;
 973    case 2: /* < / >= */
 974        cond = cond_make(TCG_COND_LT, in1, in2);
 975        break;
 976    case 3: /* <= / > */
 977        cond = cond_make(TCG_COND_LE, in1, in2);
 978        break;
 979    case 4: /* << / >>= */
 980        cond = cond_make(TCG_COND_LTU, in1, in2);
 981        break;
 982    case 5: /* <<= / >> */
 983        cond = cond_make(TCG_COND_LEU, in1, in2);
 984        break;
 985    default:
 986        return do_cond(cf, res, sv, sv);
 987    }
 988    if (cf & 1) {
 989        cond.c = tcg_invert_cond(cond.c);
 990    }
 991
 992    return cond;
 993}
 994
 995/* Similar, but for logicals, where the carry and overflow bits are not
 996   computed, and use of them is undefined.  */
 997
 998static DisasCond do_log_cond(unsigned cf, TCGv_reg res)
 999{
1000    switch (cf >> 1) {
1001    case 4: case 5: case 6:
1002        cf &= 1;
1003        break;
1004    }
1005    return do_cond(cf, res, res, res);
1006}
1007
1008/* Similar, but for shift/extract/deposit conditions.  */
1009
1010static DisasCond do_sed_cond(unsigned orig, TCGv_reg res)
1011{
1012    unsigned c, f;
1013
1014    /* Convert the compressed condition codes to standard.
1015       0-2 are the same as logicals (nv,<,<=), while 3 is OD.
1016       4-7 are the reverse of 0-3.  */
1017    c = orig & 3;
1018    if (c == 3) {
1019        c = 7;
1020    }
1021    f = (orig & 4) / 4;
1022
1023    return do_log_cond(c * 2 + f, res);
1024}
1025
1026/* Similar, but for unit conditions.  */
1027
1028static DisasCond do_unit_cond(unsigned cf, TCGv_reg res,
1029                              TCGv_reg in1, TCGv_reg in2)
1030{
1031    DisasCond cond;
1032    TCGv_reg tmp, cb = NULL;
1033
1034    if (cf & 8) {
1035        /* Since we want to test lots of carry-out bits all at once, do not
1036         * do our normal thing and compute carry-in of bit B+1 since that
1037         * leaves us with carry bits spread across two words.
1038         */
1039        cb = tcg_temp_new();
1040        tmp = tcg_temp_new();
1041        tcg_gen_or_reg(cb, in1, in2);
1042        tcg_gen_and_reg(tmp, in1, in2);
1043        tcg_gen_andc_reg(cb, cb, res);
1044        tcg_gen_or_reg(cb, cb, tmp);
1045        tcg_temp_free(tmp);
1046    }
1047
1048    switch (cf >> 1) {
1049    case 0: /* never / TR */
1050    case 1: /* undefined */
1051    case 5: /* undefined */
1052        cond = cond_make_f();
1053        break;
1054
1055    case 2: /* SBZ / NBZ */
1056        /* See hasless(v,1) from
1057         * https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord
1058         */
1059        tmp = tcg_temp_new();
1060        tcg_gen_subi_reg(tmp, res, 0x01010101u);
1061        tcg_gen_andc_reg(tmp, tmp, res);
1062        tcg_gen_andi_reg(tmp, tmp, 0x80808080u);
1063        cond = cond_make_0(TCG_COND_NE, tmp);
1064        tcg_temp_free(tmp);
1065        break;
1066
1067    case 3: /* SHZ / NHZ */
1068        tmp = tcg_temp_new();
1069        tcg_gen_subi_reg(tmp, res, 0x00010001u);
1070        tcg_gen_andc_reg(tmp, tmp, res);
1071        tcg_gen_andi_reg(tmp, tmp, 0x80008000u);
1072        cond = cond_make_0(TCG_COND_NE, tmp);
1073        tcg_temp_free(tmp);
1074        break;
1075
1076    case 4: /* SDC / NDC */
1077        tcg_gen_andi_reg(cb, cb, 0x88888888u);
1078        cond = cond_make_0(TCG_COND_NE, cb);
1079        break;
1080
1081    case 6: /* SBC / NBC */
1082        tcg_gen_andi_reg(cb, cb, 0x80808080u);
1083        cond = cond_make_0(TCG_COND_NE, cb);
1084        break;
1085
1086    case 7: /* SHC / NHC */
1087        tcg_gen_andi_reg(cb, cb, 0x80008000u);
1088        cond = cond_make_0(TCG_COND_NE, cb);
1089        break;
1090
1091    default:
1092        g_assert_not_reached();
1093    }
1094    if (cf & 8) {
1095        tcg_temp_free(cb);
1096    }
1097    if (cf & 1) {
1098        cond.c = tcg_invert_cond(cond.c);
1099    }
1100
1101    return cond;
1102}
1103
1104/* Compute signed overflow for addition.  */
1105static TCGv_reg do_add_sv(DisasContext *ctx, TCGv_reg res,
1106                          TCGv_reg in1, TCGv_reg in2)
1107{
1108    TCGv_reg sv = get_temp(ctx);
1109    TCGv_reg tmp = tcg_temp_new();
1110
1111    tcg_gen_xor_reg(sv, res, in1);
1112    tcg_gen_xor_reg(tmp, in1, in2);
1113    tcg_gen_andc_reg(sv, sv, tmp);
1114    tcg_temp_free(tmp);
1115
1116    return sv;
1117}
1118
1119/* Compute signed overflow for subtraction.  */
1120static TCGv_reg do_sub_sv(DisasContext *ctx, TCGv_reg res,
1121                          TCGv_reg in1, TCGv_reg in2)
1122{
1123    TCGv_reg sv = get_temp(ctx);
1124    TCGv_reg tmp = tcg_temp_new();
1125
1126    tcg_gen_xor_reg(sv, res, in1);
1127    tcg_gen_xor_reg(tmp, in1, in2);
1128    tcg_gen_and_reg(sv, sv, tmp);
1129    tcg_temp_free(tmp);
1130
1131    return sv;
1132}
1133
1134static DisasJumpType do_add(DisasContext *ctx, unsigned rt, TCGv_reg in1,
1135                            TCGv_reg in2, unsigned shift, bool is_l,
1136                            bool is_tsv, bool is_tc, bool is_c, unsigned cf)
1137{
1138    TCGv_reg dest, cb, cb_msb, sv, tmp;
1139    unsigned c = cf >> 1;
1140    DisasCond cond;
1141
1142    dest = tcg_temp_new();
1143    cb = NULL;
1144    cb_msb = NULL;
1145
1146    if (shift) {
1147        tmp = get_temp(ctx);
1148        tcg_gen_shli_reg(tmp, in1, shift);
1149        in1 = tmp;
1150    }
1151
1152    if (!is_l || c == 4 || c == 5) {
1153        TCGv_reg zero = tcg_const_reg(0);
1154        cb_msb = get_temp(ctx);
1155        tcg_gen_add2_reg(dest, cb_msb, in1, zero, in2, zero);
1156        if (is_c) {
1157            tcg_gen_add2_reg(dest, cb_msb, dest, cb_msb, cpu_psw_cb_msb, zero);
1158        }
1159        tcg_temp_free(zero);
1160        if (!is_l) {
1161            cb = get_temp(ctx);
1162            tcg_gen_xor_reg(cb, in1, in2);
1163            tcg_gen_xor_reg(cb, cb, dest);
1164        }
1165    } else {
1166        tcg_gen_add_reg(dest, in1, in2);
1167        if (is_c) {
1168            tcg_gen_add_reg(dest, dest, cpu_psw_cb_msb);
1169        }
1170    }
1171
1172    /* Compute signed overflow if required.  */
1173    sv = NULL;
1174    if (is_tsv || c == 6) {
1175        sv = do_add_sv(ctx, dest, in1, in2);
1176        if (is_tsv) {
1177            /* ??? Need to include overflow from shift.  */
1178            gen_helper_tsv(cpu_env, sv);
1179        }
1180    }
1181
1182    /* Emit any conditional trap before any writeback.  */
1183    cond = do_cond(cf, dest, cb_msb, sv);
1184    if (is_tc) {
1185        cond_prep(&cond);
1186        tmp = tcg_temp_new();
1187        tcg_gen_setcond_reg(cond.c, tmp, cond.a0, cond.a1);
1188        gen_helper_tcond(cpu_env, tmp);
1189        tcg_temp_free(tmp);
1190    }
1191
1192    /* Write back the result.  */
1193    if (!is_l) {
1194        save_or_nullify(ctx, cpu_psw_cb, cb);
1195        save_or_nullify(ctx, cpu_psw_cb_msb, cb_msb);
1196    }
1197    save_gpr(ctx, rt, dest);
1198    tcg_temp_free(dest);
1199
1200    /* Install the new nullification.  */
1201    cond_free(&ctx->null_cond);
1202    ctx->null_cond = cond;
1203    return DISAS_NEXT;
1204}
1205
1206static DisasJumpType do_sub(DisasContext *ctx, unsigned rt, TCGv_reg in1,
1207                            TCGv_reg in2, bool is_tsv, bool is_b,
1208                            bool is_tc, unsigned cf)
1209{
1210    TCGv_reg dest, sv, cb, cb_msb, zero, tmp;
1211    unsigned c = cf >> 1;
1212    DisasCond cond;
1213
1214    dest = tcg_temp_new();
1215    cb = tcg_temp_new();
1216    cb_msb = tcg_temp_new();
1217
1218    zero = tcg_const_reg(0);
1219    if (is_b) {
1220        /* DEST,C = IN1 + ~IN2 + C.  */
1221        tcg_gen_not_reg(cb, in2);
1222        tcg_gen_add2_reg(dest, cb_msb, in1, zero, cpu_psw_cb_msb, zero);
1223        tcg_gen_add2_reg(dest, cb_msb, dest, cb_msb, cb, zero);
1224        tcg_gen_xor_reg(cb, cb, in1);
1225        tcg_gen_xor_reg(cb, cb, dest);
1226    } else {
1227        /* DEST,C = IN1 + ~IN2 + 1.  We can produce the same result in fewer
1228           operations by seeding the high word with 1 and subtracting.  */
1229        tcg_gen_movi_reg(cb_msb, 1);
1230        tcg_gen_sub2_reg(dest, cb_msb, in1, cb_msb, in2, zero);
1231        tcg_gen_eqv_reg(cb, in1, in2);
1232        tcg_gen_xor_reg(cb, cb, dest);
1233    }
1234    tcg_temp_free(zero);
1235
1236    /* Compute signed overflow if required.  */
1237    sv = NULL;
1238    if (is_tsv || c == 6) {
1239        sv = do_sub_sv(ctx, dest, in1, in2);
1240        if (is_tsv) {
1241            gen_helper_tsv(cpu_env, sv);
1242        }
1243    }
1244
1245    /* Compute the condition.  We cannot use the special case for borrow.  */
1246    if (!is_b) {
1247        cond = do_sub_cond(cf, dest, in1, in2, sv);
1248    } else {
1249        cond = do_cond(cf, dest, cb_msb, sv);
1250    }
1251
1252    /* Emit any conditional trap before any writeback.  */
1253    if (is_tc) {
1254        cond_prep(&cond);
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
1267    /* Install the new nullification.  */
1268    cond_free(&ctx->null_cond);
1269    ctx->null_cond = cond;
1270    return DISAS_NEXT;
1271}
1272
1273static DisasJumpType do_cmpclr(DisasContext *ctx, unsigned rt, TCGv_reg in1,
1274                               TCGv_reg in2, unsigned cf)
1275{
1276    TCGv_reg dest, sv;
1277    DisasCond cond;
1278
1279    dest = tcg_temp_new();
1280    tcg_gen_sub_reg(dest, in1, in2);
1281
1282    /* Compute signed overflow if required.  */
1283    sv = NULL;
1284    if ((cf >> 1) == 6) {
1285        sv = do_sub_sv(ctx, dest, in1, in2);
1286    }
1287
1288    /* Form the condition for the compare.  */
1289    cond = do_sub_cond(cf, dest, in1, in2, sv);
1290
1291    /* Clear.  */
1292    tcg_gen_movi_reg(dest, 0);
1293    save_gpr(ctx, rt, dest);
1294    tcg_temp_free(dest);
1295
1296    /* Install the new nullification.  */
1297    cond_free(&ctx->null_cond);
1298    ctx->null_cond = cond;
1299    return DISAS_NEXT;
1300}
1301
1302static DisasJumpType do_log(DisasContext *ctx, unsigned rt, TCGv_reg in1,
1303                            TCGv_reg in2, unsigned cf,
1304                            void (*fn)(TCGv_reg, TCGv_reg, TCGv_reg))
1305{
1306    TCGv_reg dest = dest_gpr(ctx, rt);
1307
1308    /* Perform the operation, and writeback.  */
1309    fn(dest, in1, in2);
1310    save_gpr(ctx, rt, dest);
1311
1312    /* Install the new nullification.  */
1313    cond_free(&ctx->null_cond);
1314    if (cf) {
1315        ctx->null_cond = do_log_cond(cf, dest);
1316    }
1317    return DISAS_NEXT;
1318}
1319
1320static DisasJumpType do_unit(DisasContext *ctx, unsigned rt, TCGv_reg in1,
1321                             TCGv_reg in2, unsigned cf, bool is_tc,
1322                             void (*fn)(TCGv_reg, TCGv_reg, TCGv_reg))
1323{
1324    TCGv_reg dest;
1325    DisasCond cond;
1326
1327    if (cf == 0) {
1328        dest = dest_gpr(ctx, rt);
1329        fn(dest, in1, in2);
1330        save_gpr(ctx, rt, dest);
1331        cond_free(&ctx->null_cond);
1332    } else {
1333        dest = tcg_temp_new();
1334        fn(dest, in1, in2);
1335
1336        cond = do_unit_cond(cf, dest, in1, in2);
1337
1338        if (is_tc) {
1339            TCGv_reg tmp = tcg_temp_new();
1340            cond_prep(&cond);
1341            tcg_gen_setcond_reg(cond.c, tmp, cond.a0, cond.a1);
1342            gen_helper_tcond(cpu_env, tmp);
1343            tcg_temp_free(tmp);
1344        }
1345        save_gpr(ctx, rt, dest);
1346
1347        cond_free(&ctx->null_cond);
1348        ctx->null_cond = cond;
1349    }
1350    return DISAS_NEXT;
1351}
1352
1353#ifndef CONFIG_USER_ONLY
1354/* The "normal" usage is SP >= 0, wherein SP == 0 selects the space
1355   from the top 2 bits of the base register.  There are a few system
1356   instructions that have a 3-bit space specifier, for which SR0 is
1357   not special.  To handle this, pass ~SP.  */
1358static TCGv_i64 space_select(DisasContext *ctx, int sp, TCGv_reg base)
1359{
1360    TCGv_ptr ptr;
1361    TCGv_reg tmp;
1362    TCGv_i64 spc;
1363
1364    if (sp != 0) {
1365        if (sp < 0) {
1366            sp = ~sp;
1367        }
1368        spc = get_temp_tl(ctx);
1369        load_spr(ctx, spc, sp);
1370        return spc;
1371    }
1372    if (ctx->tb_flags & TB_FLAG_SR_SAME) {
1373        return cpu_srH;
1374    }
1375
1376    ptr = tcg_temp_new_ptr();
1377    tmp = tcg_temp_new();
1378    spc = get_temp_tl(ctx);
1379
1380    tcg_gen_shri_reg(tmp, base, TARGET_REGISTER_BITS - 5);
1381    tcg_gen_andi_reg(tmp, tmp, 030);
1382    tcg_gen_trunc_reg_ptr(ptr, tmp);
1383    tcg_temp_free(tmp);
1384
1385    tcg_gen_add_ptr(ptr, ptr, cpu_env);
1386    tcg_gen_ld_i64(spc, ptr, offsetof(CPUHPPAState, sr[4]));
1387    tcg_temp_free_ptr(ptr);
1388
1389    return spc;
1390}
1391#endif
1392
1393static void form_gva(DisasContext *ctx, TCGv_tl *pgva, TCGv_reg *pofs,
1394                     unsigned rb, unsigned rx, int scale, target_sreg disp,
1395                     unsigned sp, int modify, bool is_phys)
1396{
1397    TCGv_reg base = load_gpr(ctx, rb);
1398    TCGv_reg ofs;
1399
1400    /* Note that RX is mutually exclusive with DISP.  */
1401    if (rx) {
1402        ofs = get_temp(ctx);
1403        tcg_gen_shli_reg(ofs, cpu_gr[rx], scale);
1404        tcg_gen_add_reg(ofs, ofs, base);
1405    } else if (disp || modify) {
1406        ofs = get_temp(ctx);
1407        tcg_gen_addi_reg(ofs, base, disp);
1408    } else {
1409        ofs = base;
1410    }
1411
1412    *pofs = ofs;
1413#ifdef CONFIG_USER_ONLY
1414    *pgva = (modify <= 0 ? ofs : base);
1415#else
1416    TCGv_tl addr = get_temp_tl(ctx);
1417    tcg_gen_extu_reg_tl(addr, modify <= 0 ? ofs : base);
1418    if (ctx->tb_flags & PSW_W) {
1419        tcg_gen_andi_tl(addr, addr, 0x3fffffffffffffffull);
1420    }
1421    if (!is_phys) {
1422        tcg_gen_or_tl(addr, addr, space_select(ctx, sp, base));
1423    }
1424    *pgva = addr;
1425#endif
1426}
1427
1428/* Emit a memory load.  The modify parameter should be
1429 * < 0 for pre-modify,
1430 * > 0 for post-modify,
1431 * = 0 for no base register update.
1432 */
1433static void do_load_32(DisasContext *ctx, TCGv_i32 dest, unsigned rb,
1434                       unsigned rx, int scale, target_sreg disp,
1435                       unsigned sp, int modify, TCGMemOp mop)
1436{
1437    TCGv_reg ofs;
1438    TCGv_tl addr;
1439
1440    /* Caller uses nullify_over/nullify_end.  */
1441    assert(ctx->null_cond.c == TCG_COND_NEVER);
1442
1443    form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify,
1444             ctx->mmu_idx == MMU_PHYS_IDX);
1445    tcg_gen_qemu_ld_reg(dest, addr, ctx->mmu_idx, mop);
1446    if (modify) {
1447        save_gpr(ctx, rb, ofs);
1448    }
1449}
1450
1451static void do_load_64(DisasContext *ctx, TCGv_i64 dest, unsigned rb,
1452                       unsigned rx, int scale, target_sreg disp,
1453                       unsigned sp, int modify, TCGMemOp mop)
1454{
1455    TCGv_reg ofs;
1456    TCGv_tl addr;
1457
1458    /* Caller uses nullify_over/nullify_end.  */
1459    assert(ctx->null_cond.c == TCG_COND_NEVER);
1460
1461    form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify,
1462             ctx->mmu_idx == MMU_PHYS_IDX);
1463    tcg_gen_qemu_ld_i64(dest, addr, ctx->mmu_idx, mop);
1464    if (modify) {
1465        save_gpr(ctx, rb, ofs);
1466    }
1467}
1468
1469static void do_store_32(DisasContext *ctx, TCGv_i32 src, unsigned rb,
1470                        unsigned rx, int scale, target_sreg disp,
1471                        unsigned sp, int modify, TCGMemOp mop)
1472{
1473    TCGv_reg ofs;
1474    TCGv_tl addr;
1475
1476    /* Caller uses nullify_over/nullify_end.  */
1477    assert(ctx->null_cond.c == TCG_COND_NEVER);
1478
1479    form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify,
1480             ctx->mmu_idx == MMU_PHYS_IDX);
1481    tcg_gen_qemu_st_i32(src, addr, ctx->mmu_idx, mop);
1482    if (modify) {
1483        save_gpr(ctx, rb, ofs);
1484    }
1485}
1486
1487static void do_store_64(DisasContext *ctx, TCGv_i64 src, unsigned rb,
1488                        unsigned rx, int scale, target_sreg disp,
1489                        unsigned sp, int modify, TCGMemOp mop)
1490{
1491    TCGv_reg ofs;
1492    TCGv_tl addr;
1493
1494    /* Caller uses nullify_over/nullify_end.  */
1495    assert(ctx->null_cond.c == TCG_COND_NEVER);
1496
1497    form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify,
1498             ctx->mmu_idx == MMU_PHYS_IDX);
1499    tcg_gen_qemu_st_i64(src, addr, ctx->mmu_idx, mop);
1500    if (modify) {
1501        save_gpr(ctx, rb, ofs);
1502    }
1503}
1504
1505#if TARGET_REGISTER_BITS == 64
1506#define do_load_reg   do_load_64
1507#define do_store_reg  do_store_64
1508#else
1509#define do_load_reg   do_load_32
1510#define do_store_reg  do_store_32
1511#endif
1512
1513static DisasJumpType do_load(DisasContext *ctx, unsigned rt, unsigned rb,
1514                             unsigned rx, int scale, target_sreg disp,
1515                             unsigned sp, int modify, TCGMemOp mop)
1516{
1517    TCGv_reg dest;
1518
1519    nullify_over(ctx);
1520
1521    if (modify == 0) {
1522        /* No base register update.  */
1523        dest = dest_gpr(ctx, rt);
1524    } else {
1525        /* Make sure if RT == RB, we see the result of the load.  */
1526        dest = get_temp(ctx);
1527    }
1528    do_load_reg(ctx, dest, rb, rx, scale, disp, sp, modify, mop);
1529    save_gpr(ctx, rt, dest);
1530
1531    return nullify_end(ctx, DISAS_NEXT);
1532}
1533
1534static DisasJumpType do_floadw(DisasContext *ctx, unsigned rt, unsigned rb,
1535                               unsigned rx, int scale, target_sreg disp,
1536                               unsigned sp, int modify)
1537{
1538    TCGv_i32 tmp;
1539
1540    nullify_over(ctx);
1541
1542    tmp = tcg_temp_new_i32();
1543    do_load_32(ctx, tmp, rb, rx, scale, disp, sp, modify, MO_TEUL);
1544    save_frw_i32(rt, tmp);
1545    tcg_temp_free_i32(tmp);
1546
1547    if (rt == 0) {
1548        gen_helper_loaded_fr0(cpu_env);
1549    }
1550
1551    return nullify_end(ctx, DISAS_NEXT);
1552}
1553
1554static DisasJumpType do_floadd(DisasContext *ctx, unsigned rt, unsigned rb,
1555                               unsigned rx, int scale, target_sreg disp,
1556                               unsigned sp, int modify)
1557{
1558    TCGv_i64 tmp;
1559
1560    nullify_over(ctx);
1561
1562    tmp = tcg_temp_new_i64();
1563    do_load_64(ctx, tmp, rb, rx, scale, disp, sp, modify, MO_TEQ);
1564    save_frd(rt, tmp);
1565    tcg_temp_free_i64(tmp);
1566
1567    if (rt == 0) {
1568        gen_helper_loaded_fr0(cpu_env);
1569    }
1570
1571    return nullify_end(ctx, DISAS_NEXT);
1572}
1573
1574static DisasJumpType do_store(DisasContext *ctx, unsigned rt, unsigned rb,
1575                              target_sreg disp, unsigned sp,
1576                              int modify, TCGMemOp mop)
1577{
1578    nullify_over(ctx);
1579    do_store_reg(ctx, load_gpr(ctx, rt), rb, 0, 0, disp, sp, modify, mop);
1580    return nullify_end(ctx, DISAS_NEXT);
1581}
1582
1583static DisasJumpType do_fstorew(DisasContext *ctx, unsigned rt, unsigned rb,
1584                                unsigned rx, int scale, target_sreg disp,
1585                                unsigned sp, int modify)
1586{
1587    TCGv_i32 tmp;
1588
1589    nullify_over(ctx);
1590
1591    tmp = load_frw_i32(rt);
1592    do_store_32(ctx, tmp, rb, rx, scale, disp, sp, modify, MO_TEUL);
1593    tcg_temp_free_i32(tmp);
1594
1595    return nullify_end(ctx, DISAS_NEXT);
1596}
1597
1598static DisasJumpType do_fstored(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 = load_frd(rt);
1607    do_store_64(ctx, tmp, rb, rx, scale, disp, sp, modify, MO_TEQ);
1608    tcg_temp_free_i64(tmp);
1609
1610    return nullify_end(ctx, DISAS_NEXT);
1611}
1612
1613static DisasJumpType do_fop_wew(DisasContext *ctx, unsigned rt, unsigned ra,
1614                                void (*func)(TCGv_i32, TCGv_env, TCGv_i32))
1615{
1616    TCGv_i32 tmp;
1617
1618    nullify_over(ctx);
1619    tmp = load_frw0_i32(ra);
1620
1621    func(tmp, cpu_env, tmp);
1622
1623    save_frw_i32(rt, tmp);
1624    tcg_temp_free_i32(tmp);
1625    return nullify_end(ctx, DISAS_NEXT);
1626}
1627
1628static DisasJumpType do_fop_wed(DisasContext *ctx, unsigned rt, unsigned ra,
1629                                void (*func)(TCGv_i32, TCGv_env, TCGv_i64))
1630{
1631    TCGv_i32 dst;
1632    TCGv_i64 src;
1633
1634    nullify_over(ctx);
1635    src = load_frd(ra);
1636    dst = tcg_temp_new_i32();
1637
1638    func(dst, cpu_env, src);
1639
1640    tcg_temp_free_i64(src);
1641    save_frw_i32(rt, dst);
1642    tcg_temp_free_i32(dst);
1643    return nullify_end(ctx, DISAS_NEXT);
1644}
1645
1646static DisasJumpType do_fop_ded(DisasContext *ctx, unsigned rt, unsigned ra,
1647                                void (*func)(TCGv_i64, TCGv_env, TCGv_i64))
1648{
1649    TCGv_i64 tmp;
1650
1651    nullify_over(ctx);
1652    tmp = load_frd0(ra);
1653
1654    func(tmp, cpu_env, tmp);
1655
1656    save_frd(rt, tmp);
1657    tcg_temp_free_i64(tmp);
1658    return nullify_end(ctx, DISAS_NEXT);
1659}
1660
1661static DisasJumpType do_fop_dew(DisasContext *ctx, unsigned rt, unsigned ra,
1662                                void (*func)(TCGv_i64, TCGv_env, TCGv_i32))
1663{
1664    TCGv_i32 src;
1665    TCGv_i64 dst;
1666
1667    nullify_over(ctx);
1668    src = load_frw0_i32(ra);
1669    dst = tcg_temp_new_i64();
1670
1671    func(dst, cpu_env, src);
1672
1673    tcg_temp_free_i32(src);
1674    save_frd(rt, dst);
1675    tcg_temp_free_i64(dst);
1676    return nullify_end(ctx, DISAS_NEXT);
1677}
1678
1679static DisasJumpType do_fop_weww(DisasContext *ctx, unsigned rt,
1680                                 unsigned ra, unsigned rb,
1681                                 void (*func)(TCGv_i32, TCGv_env,
1682                                              TCGv_i32, TCGv_i32))
1683{
1684    TCGv_i32 a, b;
1685
1686    nullify_over(ctx);
1687    a = load_frw0_i32(ra);
1688    b = load_frw0_i32(rb);
1689
1690    func(a, cpu_env, a, b);
1691
1692    tcg_temp_free_i32(b);
1693    save_frw_i32(rt, a);
1694    tcg_temp_free_i32(a);
1695    return nullify_end(ctx, DISAS_NEXT);
1696}
1697
1698static DisasJumpType do_fop_dedd(DisasContext *ctx, unsigned rt,
1699                                 unsigned ra, unsigned rb,
1700                                 void (*func)(TCGv_i64, TCGv_env,
1701                                              TCGv_i64, TCGv_i64))
1702{
1703    TCGv_i64 a, b;
1704
1705    nullify_over(ctx);
1706    a = load_frd0(ra);
1707    b = load_frd0(rb);
1708
1709    func(a, cpu_env, a, b);
1710
1711    tcg_temp_free_i64(b);
1712    save_frd(rt, a);
1713    tcg_temp_free_i64(a);
1714    return nullify_end(ctx, DISAS_NEXT);
1715}
1716
1717/* Emit an unconditional branch to a direct target, which may or may not
1718   have already had nullification handled.  */
1719static DisasJumpType do_dbranch(DisasContext *ctx, target_ureg dest,
1720                                unsigned link, bool is_n)
1721{
1722    if (ctx->null_cond.c == TCG_COND_NEVER && ctx->null_lab == NULL) {
1723        if (link != 0) {
1724            copy_iaoq_entry(cpu_gr[link], ctx->iaoq_n, ctx->iaoq_n_var);
1725        }
1726        ctx->iaoq_n = dest;
1727        if (is_n) {
1728            ctx->null_cond.c = TCG_COND_ALWAYS;
1729        }
1730        return DISAS_NEXT;
1731    } else {
1732        nullify_over(ctx);
1733
1734        if (link != 0) {
1735            copy_iaoq_entry(cpu_gr[link], ctx->iaoq_n, ctx->iaoq_n_var);
1736        }
1737
1738        if (is_n && use_nullify_skip(ctx)) {
1739            nullify_set(ctx, 0);
1740            gen_goto_tb(ctx, 0, dest, dest + 4);
1741        } else {
1742            nullify_set(ctx, is_n);
1743            gen_goto_tb(ctx, 0, ctx->iaoq_b, dest);
1744        }
1745
1746        nullify_end(ctx, DISAS_NEXT);
1747
1748        nullify_set(ctx, 0);
1749        gen_goto_tb(ctx, 1, ctx->iaoq_b, ctx->iaoq_n);
1750        return DISAS_NORETURN;
1751    }
1752}
1753
1754/* Emit a conditional branch to a direct target.  If the branch itself
1755   is nullified, we should have already used nullify_over.  */
1756static DisasJumpType do_cbranch(DisasContext *ctx, target_sreg disp, bool is_n,
1757                                DisasCond *cond)
1758{
1759    target_ureg dest = iaoq_dest(ctx, disp);
1760    TCGLabel *taken = NULL;
1761    TCGCond c = cond->c;
1762    bool n;
1763
1764    assert(ctx->null_cond.c == TCG_COND_NEVER);
1765
1766    /* Handle TRUE and NEVER as direct branches.  */
1767    if (c == TCG_COND_ALWAYS) {
1768        return do_dbranch(ctx, dest, 0, is_n && disp >= 0);
1769    }
1770    if (c == TCG_COND_NEVER) {
1771        return do_dbranch(ctx, ctx->iaoq_n, 0, is_n && disp < 0);
1772    }
1773
1774    taken = gen_new_label();
1775    cond_prep(cond);
1776    tcg_gen_brcond_reg(c, cond->a0, cond->a1, taken);
1777    cond_free(cond);
1778
1779    /* Not taken: Condition not satisfied; nullify on backward branches. */
1780    n = is_n && disp < 0;
1781    if (n && use_nullify_skip(ctx)) {
1782        nullify_set(ctx, 0);
1783        gen_goto_tb(ctx, 0, ctx->iaoq_n, ctx->iaoq_n + 4);
1784    } else {
1785        if (!n && ctx->null_lab) {
1786            gen_set_label(ctx->null_lab);
1787            ctx->null_lab = NULL;
1788        }
1789        nullify_set(ctx, n);
1790        if (ctx->iaoq_n == -1) {
1791            /* The temporary iaoq_n_var died at the branch above.
1792               Regenerate it here instead of saving it.  */
1793            tcg_gen_addi_reg(ctx->iaoq_n_var, cpu_iaoq_b, 4);
1794        }
1795        gen_goto_tb(ctx, 0, ctx->iaoq_b, ctx->iaoq_n);
1796    }
1797
1798    gen_set_label(taken);
1799
1800    /* Taken: Condition satisfied; nullify on forward branches.  */
1801    n = is_n && disp >= 0;
1802    if (n && use_nullify_skip(ctx)) {
1803        nullify_set(ctx, 0);
1804        gen_goto_tb(ctx, 1, dest, dest + 4);
1805    } else {
1806        nullify_set(ctx, n);
1807        gen_goto_tb(ctx, 1, ctx->iaoq_b, dest);
1808    }
1809
1810    /* Not taken: the branch itself was nullified.  */
1811    if (ctx->null_lab) {
1812        gen_set_label(ctx->null_lab);
1813        ctx->null_lab = NULL;
1814        return DISAS_IAQ_N_STALE;
1815    } else {
1816        return DISAS_NORETURN;
1817    }
1818}
1819
1820/* Emit an unconditional branch to an indirect target.  This handles
1821   nullification of the branch itself.  */
1822static DisasJumpType do_ibranch(DisasContext *ctx, TCGv_reg dest,
1823                                unsigned link, bool is_n)
1824{
1825    TCGv_reg a0, a1, next, tmp;
1826    TCGCond c;
1827
1828    assert(ctx->null_lab == NULL);
1829
1830    if (ctx->null_cond.c == TCG_COND_NEVER) {
1831        if (link != 0) {
1832            copy_iaoq_entry(cpu_gr[link], ctx->iaoq_n, ctx->iaoq_n_var);
1833        }
1834        next = get_temp(ctx);
1835        tcg_gen_mov_reg(next, dest);
1836        if (is_n) {
1837            if (use_nullify_skip(ctx)) {
1838                tcg_gen_mov_reg(cpu_iaoq_f, next);
1839                tcg_gen_addi_reg(cpu_iaoq_b, next, 4);
1840                nullify_set(ctx, 0);
1841                return DISAS_IAQ_N_UPDATED;
1842            }
1843            ctx->null_cond.c = TCG_COND_ALWAYS;
1844        }
1845        ctx->iaoq_n = -1;
1846        ctx->iaoq_n_var = next;
1847    } else if (is_n && use_nullify_skip(ctx)) {
1848        /* The (conditional) branch, B, nullifies the next insn, N,
1849           and we're allowed to skip execution N (no single-step or
1850           tracepoint in effect).  Since the goto_ptr that we must use
1851           for the indirect branch consumes no special resources, we
1852           can (conditionally) skip B and continue execution.  */
1853        /* The use_nullify_skip test implies we have a known control path.  */
1854        tcg_debug_assert(ctx->iaoq_b != -1);
1855        tcg_debug_assert(ctx->iaoq_n != -1);
1856
1857        /* We do have to handle the non-local temporary, DEST, before
1858           branching.  Since IOAQ_F is not really live at this point, we
1859           can simply store DEST optimistically.  Similarly with IAOQ_B.  */
1860        tcg_gen_mov_reg(cpu_iaoq_f, dest);
1861        tcg_gen_addi_reg(cpu_iaoq_b, dest, 4);
1862
1863        nullify_over(ctx);
1864        if (link != 0) {
1865            tcg_gen_movi_reg(cpu_gr[link], ctx->iaoq_n);
1866        }
1867        tcg_gen_lookup_and_goto_ptr();
1868        return nullify_end(ctx, DISAS_NEXT);
1869    } else {
1870        cond_prep(&ctx->null_cond);
1871        c = ctx->null_cond.c;
1872        a0 = ctx->null_cond.a0;
1873        a1 = ctx->null_cond.a1;
1874
1875        tmp = tcg_temp_new();
1876        next = get_temp(ctx);
1877
1878        copy_iaoq_entry(tmp, ctx->iaoq_n, ctx->iaoq_n_var);
1879        tcg_gen_movcond_reg(c, next, a0, a1, tmp, dest);
1880        ctx->iaoq_n = -1;
1881        ctx->iaoq_n_var = next;
1882
1883        if (link != 0) {
1884            tcg_gen_movcond_reg(c, cpu_gr[link], a0, a1, cpu_gr[link], tmp);
1885        }
1886
1887        if (is_n) {
1888            /* The branch nullifies the next insn, which means the state of N
1889               after the branch is the inverse of the state of N that applied
1890               to the branch.  */
1891            tcg_gen_setcond_reg(tcg_invert_cond(c), cpu_psw_n, a0, a1);
1892            cond_free(&ctx->null_cond);
1893            ctx->null_cond = cond_make_n();
1894            ctx->psw_n_nonzero = true;
1895        } else {
1896            cond_free(&ctx->null_cond);
1897        }
1898    }
1899
1900    return DISAS_NEXT;
1901}
1902
1903/* Implement
1904 *    if (IAOQ_Front{30..31} < GR[b]{30..31})
1905 *      IAOQ_Next{30..31} ← GR[b]{30..31};
1906 *    else
1907 *      IAOQ_Next{30..31} ← IAOQ_Front{30..31};
1908 * which keeps the privilege level from being increased.
1909 */
1910static TCGv_reg do_ibranch_priv(DisasContext *ctx, TCGv_reg offset)
1911{
1912    TCGv_reg dest;
1913    switch (ctx->privilege) {
1914    case 0:
1915        /* Privilege 0 is maximum and is allowed to decrease.  */
1916        return offset;
1917    case 3:
1918        /* Privilege 3 is minimum and is never allowed increase.  */
1919        dest = get_temp(ctx);
1920        tcg_gen_ori_reg(dest, offset, 3);
1921        break;
1922    default:
1923        dest = tcg_temp_new();
1924        tcg_gen_andi_reg(dest, offset, -4);
1925        tcg_gen_ori_reg(dest, dest, ctx->privilege);
1926        tcg_gen_movcond_reg(TCG_COND_GTU, dest, dest, offset, dest, offset);
1927        tcg_temp_free(dest);
1928        break;
1929    }
1930    return dest;
1931}
1932
1933#ifdef CONFIG_USER_ONLY
1934/* On Linux, page zero is normally marked execute only + gateway.
1935   Therefore normal read or write is supposed to fail, but specific
1936   offsets have kernel code mapped to raise permissions to implement
1937   system calls.  Handling this via an explicit check here, rather
1938   in than the "be disp(sr2,r0)" instruction that probably sent us
1939   here, is the easiest way to handle the branch delay slot on the
1940   aforementioned BE.  */
1941static DisasJumpType do_page_zero(DisasContext *ctx)
1942{
1943    /* If by some means we get here with PSW[N]=1, that implies that
1944       the B,GATE instruction would be skipped, and we'd fault on the
1945       next insn within the privilaged page.  */
1946    switch (ctx->null_cond.c) {
1947    case TCG_COND_NEVER:
1948        break;
1949    case TCG_COND_ALWAYS:
1950        tcg_gen_movi_reg(cpu_psw_n, 0);
1951        goto do_sigill;
1952    default:
1953        /* Since this is always the first (and only) insn within the
1954           TB, we should know the state of PSW[N] from TB->FLAGS.  */
1955        g_assert_not_reached();
1956    }
1957
1958    /* Check that we didn't arrive here via some means that allowed
1959       non-sequential instruction execution.  Normally the PSW[B] bit
1960       detects this by disallowing the B,GATE instruction to execute
1961       under such conditions.  */
1962    if (ctx->iaoq_b != ctx->iaoq_f + 4) {
1963        goto do_sigill;
1964    }
1965
1966    switch (ctx->iaoq_f & -4) {
1967    case 0x00: /* Null pointer call */
1968        gen_excp_1(EXCP_IMP);
1969        return DISAS_NORETURN;
1970
1971    case 0xb0: /* LWS */
1972        gen_excp_1(EXCP_SYSCALL_LWS);
1973        return DISAS_NORETURN;
1974
1975    case 0xe0: /* SET_THREAD_POINTER */
1976        tcg_gen_st_reg(cpu_gr[26], cpu_env, offsetof(CPUHPPAState, cr[27]));
1977        tcg_gen_ori_reg(cpu_iaoq_f, cpu_gr[31], 3);
1978        tcg_gen_addi_reg(cpu_iaoq_b, cpu_iaoq_f, 4);
1979        return DISAS_IAQ_N_UPDATED;
1980
1981    case 0x100: /* SYSCALL */
1982        gen_excp_1(EXCP_SYSCALL);
1983        return DISAS_NORETURN;
1984
1985    default:
1986    do_sigill:
1987        gen_excp_1(EXCP_ILL);
1988        return DISAS_NORETURN;
1989    }
1990}
1991#endif
1992
1993static DisasJumpType trans_nop(DisasContext *ctx, uint32_t insn,
1994                               const DisasInsn *di)
1995{
1996    cond_free(&ctx->null_cond);
1997    return DISAS_NEXT;
1998}
1999
2000static DisasJumpType trans_break(DisasContext *ctx, uint32_t insn,
2001                                 const DisasInsn *di)
2002{
2003    nullify_over(ctx);
2004    return nullify_end(ctx, gen_excp_iir(ctx, EXCP_BREAK));
2005}
2006
2007static DisasJumpType trans_sync(DisasContext *ctx, uint32_t insn,
2008                                const DisasInsn *di)
2009{
2010    /* No point in nullifying the memory barrier.  */
2011    tcg_gen_mb(TCG_BAR_SC | TCG_MO_ALL);
2012
2013    cond_free(&ctx->null_cond);
2014    return DISAS_NEXT;
2015}
2016
2017static DisasJumpType trans_mfia(DisasContext *ctx, uint32_t insn,
2018                                const DisasInsn *di)
2019{
2020    unsigned rt = extract32(insn, 0, 5);
2021    TCGv_reg tmp = dest_gpr(ctx, rt);
2022    tcg_gen_movi_reg(tmp, ctx->iaoq_f);
2023    save_gpr(ctx, rt, tmp);
2024
2025    cond_free(&ctx->null_cond);
2026    return DISAS_NEXT;
2027}
2028
2029static DisasJumpType trans_mfsp(DisasContext *ctx, uint32_t insn,
2030                                const DisasInsn *di)
2031{
2032    unsigned rt = extract32(insn, 0, 5);
2033    unsigned rs = assemble_sr3(insn);
2034    TCGv_i64 t0 = tcg_temp_new_i64();
2035    TCGv_reg t1 = tcg_temp_new();
2036
2037    load_spr(ctx, t0, rs);
2038    tcg_gen_shri_i64(t0, t0, 32);
2039    tcg_gen_trunc_i64_reg(t1, t0);
2040
2041    save_gpr(ctx, rt, t1);
2042    tcg_temp_free(t1);
2043    tcg_temp_free_i64(t0);
2044
2045    cond_free(&ctx->null_cond);
2046    return DISAS_NEXT;
2047}
2048
2049static DisasJumpType trans_mfctl(DisasContext *ctx, uint32_t insn,
2050                                 const DisasInsn *di)
2051{
2052    unsigned rt = extract32(insn, 0, 5);
2053    unsigned ctl = extract32(insn, 21, 5);
2054    TCGv_reg tmp;
2055    DisasJumpType ret;
2056
2057    switch (ctl) {
2058    case CR_SAR:
2059#ifdef TARGET_HPPA64
2060        if (extract32(insn, 14, 1) == 0) {
2061            /* MFSAR without ,W masks low 5 bits.  */
2062            tmp = dest_gpr(ctx, rt);
2063            tcg_gen_andi_reg(tmp, cpu_sar, 31);
2064            save_gpr(ctx, rt, tmp);
2065            goto done;
2066        }
2067#endif
2068        save_gpr(ctx, rt, cpu_sar);
2069        goto done;
2070    case CR_IT: /* Interval Timer */
2071        /* FIXME: Respect PSW_S bit.  */
2072        nullify_over(ctx);
2073        tmp = dest_gpr(ctx, rt);
2074        if (ctx->base.tb->cflags & CF_USE_ICOUNT) {
2075            gen_io_start();
2076            gen_helper_read_interval_timer(tmp);
2077            gen_io_end();
2078            ret = DISAS_IAQ_N_STALE;
2079        } else {
2080            gen_helper_read_interval_timer(tmp);
2081            ret = DISAS_NEXT;
2082        }
2083        save_gpr(ctx, rt, tmp);
2084        return nullify_end(ctx, ret);
2085    case 26:
2086    case 27:
2087        break;
2088    default:
2089        /* All other control registers are privileged.  */
2090        CHECK_MOST_PRIVILEGED(EXCP_PRIV_REG);
2091        break;
2092    }
2093
2094    tmp = get_temp(ctx);
2095    tcg_gen_ld_reg(tmp, cpu_env, offsetof(CPUHPPAState, cr[ctl]));
2096    save_gpr(ctx, rt, tmp);
2097
2098 done:
2099    cond_free(&ctx->null_cond);
2100    return DISAS_NEXT;
2101}
2102
2103static DisasJumpType trans_mtsp(DisasContext *ctx, uint32_t insn,
2104                                const DisasInsn *di)
2105{
2106    unsigned rr = extract32(insn, 16, 5);
2107    unsigned rs = assemble_sr3(insn);
2108    TCGv_i64 t64;
2109
2110    if (rs >= 5) {
2111        CHECK_MOST_PRIVILEGED(EXCP_PRIV_REG);
2112    }
2113    nullify_over(ctx);
2114
2115    t64 = tcg_temp_new_i64();
2116    tcg_gen_extu_reg_i64(t64, load_gpr(ctx, rr));
2117    tcg_gen_shli_i64(t64, t64, 32);
2118
2119    if (rs >= 4) {
2120        tcg_gen_st_i64(t64, cpu_env, offsetof(CPUHPPAState, sr[rs]));
2121        ctx->tb_flags &= ~TB_FLAG_SR_SAME;
2122    } else {
2123        tcg_gen_mov_i64(cpu_sr[rs], t64);
2124    }
2125    tcg_temp_free_i64(t64);
2126
2127    return nullify_end(ctx, DISAS_NEXT);
2128}
2129
2130static DisasJumpType trans_mtctl(DisasContext *ctx, uint32_t insn,
2131                                 const DisasInsn *di)
2132{
2133    unsigned rin = extract32(insn, 16, 5);
2134    unsigned ctl = extract32(insn, 21, 5);
2135    TCGv_reg reg = load_gpr(ctx, rin);
2136    TCGv_reg tmp;
2137
2138    if (ctl == CR_SAR) {
2139        tmp = tcg_temp_new();
2140        tcg_gen_andi_reg(tmp, reg, TARGET_REGISTER_BITS - 1);
2141        save_or_nullify(ctx, cpu_sar, tmp);
2142        tcg_temp_free(tmp);
2143
2144        cond_free(&ctx->null_cond);
2145        return DISAS_NEXT;
2146    }
2147
2148    /* All other control registers are privileged or read-only.  */
2149    CHECK_MOST_PRIVILEGED(EXCP_PRIV_REG);
2150
2151#ifdef CONFIG_USER_ONLY
2152    g_assert_not_reached();
2153#else
2154    DisasJumpType ret = DISAS_NEXT;
2155
2156    nullify_over(ctx);
2157    switch (ctl) {
2158    case CR_IT:
2159        gen_helper_write_interval_timer(cpu_env, reg);
2160        break;
2161    case CR_EIRR:
2162        gen_helper_write_eirr(cpu_env, reg);
2163        break;
2164    case CR_EIEM:
2165        gen_helper_write_eiem(cpu_env, reg);
2166        ret = DISAS_IAQ_N_STALE_EXIT;
2167        break;
2168
2169    case CR_IIASQ:
2170    case CR_IIAOQ:
2171        /* FIXME: Respect PSW_Q bit */
2172        /* The write advances the queue and stores to the back element.  */
2173        tmp = get_temp(ctx);
2174        tcg_gen_ld_reg(tmp, cpu_env,
2175                       offsetof(CPUHPPAState, cr_back[ctl - CR_IIASQ]));
2176        tcg_gen_st_reg(tmp, cpu_env, offsetof(CPUHPPAState, cr[ctl]));
2177        tcg_gen_st_reg(reg, cpu_env,
2178                       offsetof(CPUHPPAState, cr_back[ctl - CR_IIASQ]));
2179        break;
2180
2181    default:
2182        tcg_gen_st_reg(reg, cpu_env, offsetof(CPUHPPAState, cr[ctl]));
2183        break;
2184    }
2185    return nullify_end(ctx, ret);
2186#endif
2187}
2188
2189static DisasJumpType trans_mtsarcm(DisasContext *ctx, uint32_t insn,
2190                                   const DisasInsn *di)
2191{
2192    unsigned rin = extract32(insn, 16, 5);
2193    TCGv_reg tmp = tcg_temp_new();
2194
2195    tcg_gen_not_reg(tmp, load_gpr(ctx, rin));
2196    tcg_gen_andi_reg(tmp, tmp, TARGET_REGISTER_BITS - 1);
2197    save_or_nullify(ctx, cpu_sar, tmp);
2198    tcg_temp_free(tmp);
2199
2200    cond_free(&ctx->null_cond);
2201    return DISAS_NEXT;
2202}
2203
2204static DisasJumpType trans_ldsid(DisasContext *ctx, uint32_t insn,
2205                                 const DisasInsn *di)
2206{
2207    unsigned rt = extract32(insn, 0, 5);
2208    TCGv_reg dest = dest_gpr(ctx, rt);
2209
2210#ifdef CONFIG_USER_ONLY
2211    /* We don't implement space registers in user mode. */
2212    tcg_gen_movi_reg(dest, 0);
2213#else
2214    unsigned rb = extract32(insn, 21, 5);
2215    unsigned sp = extract32(insn, 14, 2);
2216    TCGv_i64 t0 = tcg_temp_new_i64();
2217
2218    tcg_gen_mov_i64(t0, space_select(ctx, sp, load_gpr(ctx, rb)));
2219    tcg_gen_shri_i64(t0, t0, 32);
2220    tcg_gen_trunc_i64_reg(dest, t0);
2221
2222    tcg_temp_free_i64(t0);
2223#endif
2224    save_gpr(ctx, rt, dest);
2225
2226    cond_free(&ctx->null_cond);
2227    return DISAS_NEXT;
2228}
2229
2230#ifndef CONFIG_USER_ONLY
2231/* Note that ssm/rsm instructions number PSW_W and PSW_E differently.  */
2232static target_ureg extract_sm_imm(uint32_t insn)
2233{
2234    target_ureg val = extract32(insn, 16, 10);
2235
2236    if (val & PSW_SM_E) {
2237        val = (val & ~PSW_SM_E) | PSW_E;
2238    }
2239    if (val & PSW_SM_W) {
2240        val = (val & ~PSW_SM_W) | PSW_W;
2241    }
2242    return val;
2243}
2244
2245static DisasJumpType trans_rsm(DisasContext *ctx, uint32_t insn,
2246                               const DisasInsn *di)
2247{
2248    unsigned rt = extract32(insn, 0, 5);
2249    target_ureg sm = extract_sm_imm(insn);
2250    TCGv_reg tmp;
2251
2252    CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2253    nullify_over(ctx);
2254
2255    tmp = get_temp(ctx);
2256    tcg_gen_ld_reg(tmp, cpu_env, offsetof(CPUHPPAState, psw));
2257    tcg_gen_andi_reg(tmp, tmp, ~sm);
2258    gen_helper_swap_system_mask(tmp, cpu_env, tmp);
2259    save_gpr(ctx, rt, tmp);
2260
2261    /* Exit the TB to recognize new interrupts, e.g. PSW_M.  */
2262    return nullify_end(ctx, DISAS_IAQ_N_STALE_EXIT);
2263}
2264
2265static DisasJumpType trans_ssm(DisasContext *ctx, uint32_t insn,
2266                               const DisasInsn *di)
2267{
2268    unsigned rt = extract32(insn, 0, 5);
2269    target_ureg sm = extract_sm_imm(insn);
2270    TCGv_reg tmp;
2271
2272    CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2273    nullify_over(ctx);
2274
2275    tmp = get_temp(ctx);
2276    tcg_gen_ld_reg(tmp, cpu_env, offsetof(CPUHPPAState, psw));
2277    tcg_gen_ori_reg(tmp, tmp, sm);
2278    gen_helper_swap_system_mask(tmp, cpu_env, tmp);
2279    save_gpr(ctx, rt, tmp);
2280
2281    /* Exit the TB to recognize new interrupts, e.g. PSW_I.  */
2282    return nullify_end(ctx, DISAS_IAQ_N_STALE_EXIT);
2283}
2284
2285static DisasJumpType trans_mtsm(DisasContext *ctx, uint32_t insn,
2286                                const DisasInsn *di)
2287{
2288    unsigned rr = extract32(insn, 16, 5);
2289    TCGv_reg tmp, reg;
2290
2291    CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2292    nullify_over(ctx);
2293
2294    reg = load_gpr(ctx, rr);
2295    tmp = get_temp(ctx);
2296    gen_helper_swap_system_mask(tmp, cpu_env, reg);
2297
2298    /* Exit the TB to recognize new interrupts.  */
2299    return nullify_end(ctx, DISAS_IAQ_N_STALE_EXIT);
2300}
2301
2302static DisasJumpType trans_rfi(DisasContext *ctx, uint32_t insn,
2303                               const DisasInsn *di)
2304{
2305    unsigned comp = extract32(insn, 5, 4);
2306
2307    CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2308    nullify_over(ctx);
2309
2310    if (comp == 5) {
2311        gen_helper_rfi_r(cpu_env);
2312    } else {
2313        gen_helper_rfi(cpu_env);
2314    }
2315    if (ctx->base.singlestep_enabled) {
2316        gen_excp_1(EXCP_DEBUG);
2317    } else {
2318        tcg_gen_exit_tb(0);
2319    }
2320
2321    /* Exit the TB to recognize new interrupts.  */
2322    return nullify_end(ctx, DISAS_NORETURN);
2323}
2324
2325static DisasJumpType gen_hlt(DisasContext *ctx, int reset)
2326{
2327    CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2328    nullify_over(ctx);
2329    if (reset) {
2330        gen_helper_reset(cpu_env);
2331    } else {
2332        gen_helper_halt(cpu_env);
2333    }
2334    return nullify_end(ctx, DISAS_NORETURN);
2335}
2336#endif /* !CONFIG_USER_ONLY */
2337
2338static const DisasInsn table_system[] = {
2339    { 0x00000000u, 0xfc001fe0u, trans_break },
2340    { 0x00001820u, 0xffe01fffu, trans_mtsp },
2341    { 0x00001840u, 0xfc00ffffu, trans_mtctl },
2342    { 0x016018c0u, 0xffe0ffffu, trans_mtsarcm },
2343    { 0x000014a0u, 0xffffffe0u, trans_mfia },
2344    { 0x000004a0u, 0xffff1fe0u, trans_mfsp },
2345    { 0x000008a0u, 0xfc1fbfe0u, trans_mfctl },
2346    { 0x00000400u, 0xffffffffu, trans_sync },  /* sync */
2347    { 0x00100400u, 0xffffffffu, trans_sync },  /* syncdma */
2348    { 0x000010a0u, 0xfc1f3fe0u, trans_ldsid },
2349#ifndef CONFIG_USER_ONLY
2350    { 0x00000e60u, 0xfc00ffe0u, trans_rsm },
2351    { 0x00000d60u, 0xfc00ffe0u, trans_ssm },
2352    { 0x00001860u, 0xffe0ffffu, trans_mtsm },
2353    { 0x00000c00u, 0xfffffe1fu, trans_rfi },
2354#endif
2355};
2356
2357static DisasJumpType trans_base_idx_mod(DisasContext *ctx, uint32_t insn,
2358                                        const DisasInsn *di)
2359{
2360    unsigned rb = extract32(insn, 21, 5);
2361    unsigned rx = extract32(insn, 16, 5);
2362    TCGv_reg dest = dest_gpr(ctx, rb);
2363    TCGv_reg src1 = load_gpr(ctx, rb);
2364    TCGv_reg src2 = load_gpr(ctx, rx);
2365
2366    /* The only thing we need to do is the base register modification.  */
2367    tcg_gen_add_reg(dest, src1, src2);
2368    save_gpr(ctx, rb, dest);
2369
2370    cond_free(&ctx->null_cond);
2371    return DISAS_NEXT;
2372}
2373
2374static DisasJumpType trans_probe(DisasContext *ctx, uint32_t insn,
2375                                 const DisasInsn *di)
2376{
2377    unsigned rt = extract32(insn, 0, 5);
2378    unsigned sp = extract32(insn, 14, 2);
2379    unsigned rr = extract32(insn, 16, 5);
2380    unsigned rb = extract32(insn, 21, 5);
2381    unsigned is_write = extract32(insn, 6, 1);
2382    unsigned is_imm = extract32(insn, 13, 1);
2383    TCGv_reg dest, ofs;
2384    TCGv_i32 level, want;
2385    TCGv_tl addr;
2386
2387    nullify_over(ctx);
2388
2389    dest = dest_gpr(ctx, rt);
2390    form_gva(ctx, &addr, &ofs, rb, 0, 0, 0, sp, 0, false);
2391
2392    if (is_imm) {
2393        level = tcg_const_i32(extract32(insn, 16, 2));
2394    } else {
2395        level = tcg_temp_new_i32();
2396        tcg_gen_trunc_reg_i32(level, load_gpr(ctx, rr));
2397        tcg_gen_andi_i32(level, level, 3);
2398    }
2399    want = tcg_const_i32(is_write ? PAGE_WRITE : PAGE_READ);
2400
2401    gen_helper_probe(dest, cpu_env, addr, level, want);
2402
2403    tcg_temp_free_i32(want);
2404    tcg_temp_free_i32(level);
2405
2406    save_gpr(ctx, rt, dest);
2407    return nullify_end(ctx, DISAS_NEXT);
2408}
2409
2410#ifndef CONFIG_USER_ONLY
2411static DisasJumpType trans_ixtlbx(DisasContext *ctx, uint32_t insn,
2412                                  const DisasInsn *di)
2413{
2414    unsigned sp;
2415    unsigned rr = extract32(insn, 16, 5);
2416    unsigned rb = extract32(insn, 21, 5);
2417    unsigned is_data = insn & 0x1000;
2418    unsigned is_addr = insn & 0x40;
2419    TCGv_tl addr;
2420    TCGv_reg ofs, reg;
2421
2422    if (is_data) {
2423        sp = extract32(insn, 14, 2);
2424    } else {
2425        sp = ~assemble_sr3(insn);
2426    }
2427
2428    CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2429    nullify_over(ctx);
2430
2431    form_gva(ctx, &addr, &ofs, rb, 0, 0, 0, sp, 0, false);
2432    reg = load_gpr(ctx, rr);
2433    if (is_addr) {
2434        gen_helper_itlba(cpu_env, addr, reg);
2435    } else {
2436        gen_helper_itlbp(cpu_env, addr, reg);
2437    }
2438
2439    /* Exit TB for ITLB change if mmu is enabled.  This *should* not be
2440       the case, since the OS TLB fill handler runs with mmu disabled.  */
2441    return nullify_end(ctx, !is_data && (ctx->tb_flags & PSW_C)
2442                       ? DISAS_IAQ_N_STALE : DISAS_NEXT);
2443}
2444
2445static DisasJumpType trans_pxtlbx(DisasContext *ctx, uint32_t insn,
2446                                  const DisasInsn *di)
2447{
2448    unsigned m = extract32(insn, 5, 1);
2449    unsigned sp;
2450    unsigned rx = extract32(insn, 16, 5);
2451    unsigned rb = extract32(insn, 21, 5);
2452    unsigned is_data = insn & 0x1000;
2453    unsigned is_local = insn & 0x40;
2454    TCGv_tl addr;
2455    TCGv_reg ofs;
2456
2457    if (is_data) {
2458        sp = extract32(insn, 14, 2);
2459    } else {
2460        sp = ~assemble_sr3(insn);
2461    }
2462
2463    CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2464    nullify_over(ctx);
2465
2466    form_gva(ctx, &addr, &ofs, rb, rx, 0, 0, sp, m, false);
2467    if (m) {
2468        save_gpr(ctx, rb, ofs);
2469    }
2470    if (is_local) {
2471        gen_helper_ptlbe(cpu_env);
2472    } else {
2473        gen_helper_ptlb(cpu_env, addr);
2474    }
2475
2476    /* Exit TB for TLB change if mmu is enabled.  */
2477    return nullify_end(ctx, !is_data && (ctx->tb_flags & PSW_C)
2478                       ? DISAS_IAQ_N_STALE : DISAS_NEXT);
2479}
2480
2481static DisasJumpType trans_lpa(DisasContext *ctx, uint32_t insn,
2482                               const DisasInsn *di)
2483{
2484    unsigned rt = extract32(insn, 0, 5);
2485    unsigned m = extract32(insn, 5, 1);
2486    unsigned sp = extract32(insn, 14, 2);
2487    unsigned rx = extract32(insn, 16, 5);
2488    unsigned rb = extract32(insn, 21, 5);
2489    TCGv_tl vaddr;
2490    TCGv_reg ofs, paddr;
2491
2492    CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2493    nullify_over(ctx);
2494
2495    form_gva(ctx, &vaddr, &ofs, rb, rx, 0, 0, sp, m, false);
2496
2497    paddr = tcg_temp_new();
2498    gen_helper_lpa(paddr, cpu_env, vaddr);
2499
2500    /* Note that physical address result overrides base modification.  */
2501    if (m) {
2502        save_gpr(ctx, rb, ofs);
2503    }
2504    save_gpr(ctx, rt, paddr);
2505    tcg_temp_free(paddr);
2506
2507    return nullify_end(ctx, DISAS_NEXT);
2508}
2509
2510static DisasJumpType trans_lci(DisasContext *ctx, uint32_t insn,
2511                               const DisasInsn *di)
2512{
2513    unsigned rt = extract32(insn, 0, 5);
2514    TCGv_reg ci;
2515
2516    CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
2517
2518    /* The Coherence Index is an implementation-defined function of the
2519       physical address.  Two addresses with the same CI have a coherent
2520       view of the cache.  Our implementation is to return 0 for all,
2521       since the entire address space is coherent.  */
2522    ci = tcg_const_reg(0);
2523    save_gpr(ctx, rt, ci);
2524    tcg_temp_free(ci);
2525
2526    return DISAS_NEXT;
2527}
2528#endif /* !CONFIG_USER_ONLY */
2529
2530static const DisasInsn table_mem_mgmt[] = {
2531    { 0x04003280u, 0xfc003fffu, trans_nop },          /* fdc, disp */
2532    { 0x04001280u, 0xfc003fffu, trans_nop },          /* fdc, index */
2533    { 0x040012a0u, 0xfc003fffu, trans_base_idx_mod }, /* fdc, index, base mod */
2534    { 0x040012c0u, 0xfc003fffu, trans_nop },          /* fdce */
2535    { 0x040012e0u, 0xfc003fffu, trans_base_idx_mod }, /* fdce, base mod */
2536    { 0x04000280u, 0xfc001fffu, trans_nop },          /* fic 0a */
2537    { 0x040002a0u, 0xfc001fffu, trans_base_idx_mod }, /* fic 0a, base mod */
2538    { 0x040013c0u, 0xfc003fffu, trans_nop },          /* fic 4f */
2539    { 0x040013e0u, 0xfc003fffu, trans_base_idx_mod }, /* fic 4f, base mod */
2540    { 0x040002c0u, 0xfc001fffu, trans_nop },          /* fice */
2541    { 0x040002e0u, 0xfc001fffu, trans_base_idx_mod }, /* fice, base mod */
2542    { 0x04002700u, 0xfc003fffu, trans_nop },          /* pdc */
2543    { 0x04002720u, 0xfc003fffu, trans_base_idx_mod }, /* pdc, base mod */
2544    { 0x04001180u, 0xfc003fa0u, trans_probe },        /* probe */
2545    { 0x04003180u, 0xfc003fa0u, trans_probe },        /* probei */
2546#ifndef CONFIG_USER_ONLY
2547    { 0x04000000u, 0xfc001fffu, trans_ixtlbx },       /* iitlbp */
2548    { 0x04000040u, 0xfc001fffu, trans_ixtlbx },       /* iitlba */
2549    { 0x04001000u, 0xfc001fffu, trans_ixtlbx },       /* idtlbp */
2550    { 0x04001040u, 0xfc001fffu, trans_ixtlbx },       /* idtlba */
2551    { 0x04000200u, 0xfc001fdfu, trans_pxtlbx },       /* pitlb */
2552    { 0x04000240u, 0xfc001fdfu, trans_pxtlbx },       /* pitlbe */
2553    { 0x04001200u, 0xfc001fdfu, trans_pxtlbx },       /* pdtlb */
2554    { 0x04001240u, 0xfc001fdfu, trans_pxtlbx },       /* pdtlbe */
2555    { 0x04001340u, 0xfc003fc0u, trans_lpa },
2556    { 0x04001300u, 0xfc003fe0u, trans_lci },
2557#endif
2558};
2559
2560static DisasJumpType trans_add(DisasContext *ctx, uint32_t insn,
2561                               const DisasInsn *di)
2562{
2563    unsigned r2 = extract32(insn, 21, 5);
2564    unsigned r1 = extract32(insn, 16, 5);
2565    unsigned cf = extract32(insn, 12, 4);
2566    unsigned ext = extract32(insn, 8, 4);
2567    unsigned shift = extract32(insn, 6, 2);
2568    unsigned rt = extract32(insn,  0, 5);
2569    TCGv_reg tcg_r1, tcg_r2;
2570    bool is_c = false;
2571    bool is_l = false;
2572    bool is_tc = false;
2573    bool is_tsv = false;
2574    DisasJumpType ret;
2575
2576    switch (ext) {
2577    case 0x6: /* ADD, SHLADD */
2578        break;
2579    case 0xa: /* ADD,L, SHLADD,L */
2580        is_l = true;
2581        break;
2582    case 0xe: /* ADD,TSV, SHLADD,TSV (1) */
2583        is_tsv = true;
2584        break;
2585    case 0x7: /* ADD,C */
2586        is_c = true;
2587        break;
2588    case 0xf: /* ADD,C,TSV */
2589        is_c = is_tsv = true;
2590        break;
2591    default:
2592        return gen_illegal(ctx);
2593    }
2594
2595    if (cf) {
2596        nullify_over(ctx);
2597    }
2598    tcg_r1 = load_gpr(ctx, r1);
2599    tcg_r2 = load_gpr(ctx, r2);
2600    ret = do_add(ctx, rt, tcg_r1, tcg_r2, shift, is_l, is_tsv, is_tc, is_c, cf);
2601    return nullify_end(ctx, ret);
2602}
2603
2604static DisasJumpType trans_sub(DisasContext *ctx, uint32_t insn,
2605                               const DisasInsn *di)
2606{
2607    unsigned r2 = extract32(insn, 21, 5);
2608    unsigned r1 = extract32(insn, 16, 5);
2609    unsigned cf = extract32(insn, 12, 4);
2610    unsigned ext = extract32(insn, 6, 6);
2611    unsigned rt = extract32(insn,  0, 5);
2612    TCGv_reg tcg_r1, tcg_r2;
2613    bool is_b = false;
2614    bool is_tc = false;
2615    bool is_tsv = false;
2616    DisasJumpType ret;
2617
2618    switch (ext) {
2619    case 0x10: /* SUB */
2620        break;
2621    case 0x30: /* SUB,TSV */
2622        is_tsv = true;
2623        break;
2624    case 0x14: /* SUB,B */
2625        is_b = true;
2626        break;
2627    case 0x34: /* SUB,B,TSV */
2628        is_b = is_tsv = true;
2629        break;
2630    case 0x13: /* SUB,TC */
2631        is_tc = true;
2632        break;
2633    case 0x33: /* SUB,TSV,TC */
2634        is_tc = is_tsv = true;
2635        break;
2636    default:
2637        return gen_illegal(ctx);
2638    }
2639
2640    if (cf) {
2641        nullify_over(ctx);
2642    }
2643    tcg_r1 = load_gpr(ctx, r1);
2644    tcg_r2 = load_gpr(ctx, r2);
2645    ret = do_sub(ctx, rt, tcg_r1, tcg_r2, is_tsv, is_b, is_tc, cf);
2646    return nullify_end(ctx, ret);
2647}
2648
2649static DisasJumpType trans_log(DisasContext *ctx, uint32_t insn,
2650                               const DisasInsn *di)
2651{
2652    unsigned r2 = extract32(insn, 21, 5);
2653    unsigned r1 = extract32(insn, 16, 5);
2654    unsigned cf = extract32(insn, 12, 4);
2655    unsigned rt = extract32(insn,  0, 5);
2656    TCGv_reg tcg_r1, tcg_r2;
2657    DisasJumpType ret;
2658
2659    if (cf) {
2660        nullify_over(ctx);
2661    }
2662    tcg_r1 = load_gpr(ctx, r1);
2663    tcg_r2 = load_gpr(ctx, r2);
2664    ret = do_log(ctx, rt, tcg_r1, tcg_r2, cf, di->f.ttt);
2665    return nullify_end(ctx, ret);
2666}
2667
2668/* OR r,0,t -> COPY (according to gas) */
2669static DisasJumpType trans_copy(DisasContext *ctx, uint32_t insn,
2670                                const DisasInsn *di)
2671{
2672    unsigned r1 = extract32(insn, 16, 5);
2673    unsigned rt = extract32(insn,  0, 5);
2674
2675    if (r1 == 0) {
2676        TCGv_reg dest = dest_gpr(ctx, rt);
2677        tcg_gen_movi_reg(dest, 0);
2678        save_gpr(ctx, rt, dest);
2679    } else {
2680        save_gpr(ctx, rt, cpu_gr[r1]);
2681    }
2682    cond_free(&ctx->null_cond);
2683    return DISAS_NEXT;
2684}
2685
2686static DisasJumpType trans_cmpclr(DisasContext *ctx, uint32_t insn,
2687                                  const DisasInsn *di)
2688{
2689    unsigned r2 = extract32(insn, 21, 5);
2690    unsigned r1 = extract32(insn, 16, 5);
2691    unsigned cf = extract32(insn, 12, 4);
2692    unsigned rt = extract32(insn,  0, 5);
2693    TCGv_reg tcg_r1, tcg_r2;
2694    DisasJumpType ret;
2695
2696    if (cf) {
2697        nullify_over(ctx);
2698    }
2699    tcg_r1 = load_gpr(ctx, r1);
2700    tcg_r2 = load_gpr(ctx, r2);
2701    ret = do_cmpclr(ctx, rt, tcg_r1, tcg_r2, cf);
2702    return nullify_end(ctx, ret);
2703}
2704
2705static DisasJumpType trans_uxor(DisasContext *ctx, uint32_t insn,
2706                                const DisasInsn *di)
2707{
2708    unsigned r2 = extract32(insn, 21, 5);
2709    unsigned r1 = extract32(insn, 16, 5);
2710    unsigned cf = extract32(insn, 12, 4);
2711    unsigned rt = extract32(insn,  0, 5);
2712    TCGv_reg tcg_r1, tcg_r2;
2713    DisasJumpType ret;
2714
2715    if (cf) {
2716        nullify_over(ctx);
2717    }
2718    tcg_r1 = load_gpr(ctx, r1);
2719    tcg_r2 = load_gpr(ctx, r2);
2720    ret = do_unit(ctx, rt, tcg_r1, tcg_r2, cf, false, tcg_gen_xor_reg);
2721    return nullify_end(ctx, ret);
2722}
2723
2724static DisasJumpType trans_uaddcm(DisasContext *ctx, uint32_t insn,
2725                                  const DisasInsn *di)
2726{
2727    unsigned r2 = extract32(insn, 21, 5);
2728    unsigned r1 = extract32(insn, 16, 5);
2729    unsigned cf = extract32(insn, 12, 4);
2730    unsigned is_tc = extract32(insn, 6, 1);
2731    unsigned rt = extract32(insn,  0, 5);
2732    TCGv_reg tcg_r1, tcg_r2, tmp;
2733    DisasJumpType ret;
2734
2735    if (cf) {
2736        nullify_over(ctx);
2737    }
2738    tcg_r1 = load_gpr(ctx, r1);
2739    tcg_r2 = load_gpr(ctx, r2);
2740    tmp = get_temp(ctx);
2741    tcg_gen_not_reg(tmp, tcg_r2);
2742    ret = do_unit(ctx, rt, tcg_r1, tmp, cf, is_tc, tcg_gen_add_reg);
2743    return nullify_end(ctx, ret);
2744}
2745
2746static DisasJumpType trans_dcor(DisasContext *ctx, uint32_t insn,
2747                                const DisasInsn *di)
2748{
2749    unsigned r2 = extract32(insn, 21, 5);
2750    unsigned cf = extract32(insn, 12, 4);
2751    unsigned is_i = extract32(insn, 6, 1);
2752    unsigned rt = extract32(insn,  0, 5);
2753    TCGv_reg tmp;
2754    DisasJumpType ret;
2755
2756    nullify_over(ctx);
2757
2758    tmp = get_temp(ctx);
2759    tcg_gen_shri_reg(tmp, cpu_psw_cb, 3);
2760    if (!is_i) {
2761        tcg_gen_not_reg(tmp, tmp);
2762    }
2763    tcg_gen_andi_reg(tmp, tmp, 0x11111111);
2764    tcg_gen_muli_reg(tmp, tmp, 6);
2765    ret = do_unit(ctx, rt, tmp, load_gpr(ctx, r2), cf, false,
2766                  is_i ? tcg_gen_add_reg : tcg_gen_sub_reg);
2767
2768    return nullify_end(ctx, ret);
2769}
2770
2771static DisasJumpType trans_ds(DisasContext *ctx, uint32_t insn,
2772                              const DisasInsn *di)
2773{
2774    unsigned r2 = extract32(insn, 21, 5);
2775    unsigned r1 = extract32(insn, 16, 5);
2776    unsigned cf = extract32(insn, 12, 4);
2777    unsigned rt = extract32(insn,  0, 5);
2778    TCGv_reg dest, add1, add2, addc, zero, in1, in2;
2779
2780    nullify_over(ctx);
2781
2782    in1 = load_gpr(ctx, r1);
2783    in2 = load_gpr(ctx, r2);
2784
2785    add1 = tcg_temp_new();
2786    add2 = tcg_temp_new();
2787    addc = tcg_temp_new();
2788    dest = tcg_temp_new();
2789    zero = tcg_const_reg(0);
2790
2791    /* Form R1 << 1 | PSW[CB]{8}.  */
2792    tcg_gen_add_reg(add1, in1, in1);
2793    tcg_gen_add_reg(add1, add1, cpu_psw_cb_msb);
2794
2795    /* Add or subtract R2, depending on PSW[V].  Proper computation of
2796       carry{8} requires that we subtract via + ~R2 + 1, as described in
2797       the manual.  By extracting and masking V, we can produce the
2798       proper inputs to the addition without movcond.  */
2799    tcg_gen_sari_reg(addc, cpu_psw_v, TARGET_REGISTER_BITS - 1);
2800    tcg_gen_xor_reg(add2, in2, addc);
2801    tcg_gen_andi_reg(addc, addc, 1);
2802    /* ??? This is only correct for 32-bit.  */
2803    tcg_gen_add2_i32(dest, cpu_psw_cb_msb, add1, zero, add2, zero);
2804    tcg_gen_add2_i32(dest, cpu_psw_cb_msb, dest, cpu_psw_cb_msb, addc, zero);
2805
2806    tcg_temp_free(addc);
2807    tcg_temp_free(zero);
2808
2809    /* Write back the result register.  */
2810    save_gpr(ctx, rt, dest);
2811
2812    /* Write back PSW[CB].  */
2813    tcg_gen_xor_reg(cpu_psw_cb, add1, add2);
2814    tcg_gen_xor_reg(cpu_psw_cb, cpu_psw_cb, dest);
2815
2816    /* Write back PSW[V] for the division step.  */
2817    tcg_gen_neg_reg(cpu_psw_v, cpu_psw_cb_msb);
2818    tcg_gen_xor_reg(cpu_psw_v, cpu_psw_v, in2);
2819
2820    /* Install the new nullification.  */
2821    if (cf) {
2822        TCGv_reg sv = NULL;
2823        if (cf >> 1 == 6) {
2824            /* ??? The lshift is supposed to contribute to overflow.  */
2825            sv = do_add_sv(ctx, dest, add1, add2);
2826        }
2827        ctx->null_cond = do_cond(cf, dest, cpu_psw_cb_msb, sv);
2828    }
2829
2830    tcg_temp_free(add1);
2831    tcg_temp_free(add2);
2832    tcg_temp_free(dest);
2833
2834    return nullify_end(ctx, DISAS_NEXT);
2835}
2836
2837#ifndef CONFIG_USER_ONLY
2838/* These are QEMU extensions and are nops in the real architecture:
2839 *
2840 * or %r10,%r10,%r10 -- idle loop; wait for interrupt
2841 * or %r31,%r31,%r31 -- death loop; offline cpu
2842 *                      currently implemented as idle.
2843 */
2844static DisasJumpType trans_pause(DisasContext *ctx, uint32_t insn,
2845                                 const DisasInsn *di)
2846{
2847    TCGv_i32 tmp;
2848
2849    /* No need to check for supervisor, as userland can only pause
2850       until the next timer interrupt.  */
2851    nullify_over(ctx);
2852
2853    /* Advance the instruction queue.  */
2854    copy_iaoq_entry(cpu_iaoq_f, ctx->iaoq_b, cpu_iaoq_b);
2855    copy_iaoq_entry(cpu_iaoq_b, ctx->iaoq_n, ctx->iaoq_n_var);
2856    nullify_set(ctx, 0);
2857
2858    /* Tell the qemu main loop to halt until this cpu has work.  */
2859    tmp = tcg_const_i32(1);
2860    tcg_gen_st_i32(tmp, cpu_env, -offsetof(HPPACPU, env) +
2861                                 offsetof(CPUState, halted));
2862    tcg_temp_free_i32(tmp);
2863    gen_excp_1(EXCP_HALTED);
2864
2865    return nullify_end(ctx, DISAS_NORETURN);
2866}
2867#endif
2868
2869static const DisasInsn table_arith_log[] = {
2870    { 0x08000240u, 0xfc00ffffu, trans_nop },  /* or x,y,0 */
2871    { 0x08000240u, 0xffe0ffe0u, trans_copy }, /* or x,0,t */
2872#ifndef CONFIG_USER_ONLY
2873    { 0x094a024au, 0xffffffffu, trans_pause }, /* or r10,r10,r10 */
2874    { 0x0bff025fu, 0xffffffffu, trans_pause }, /* or r31,r31,r31 */
2875#endif
2876    { 0x08000000u, 0xfc000fe0u, trans_log, .f.ttt = tcg_gen_andc_reg },
2877    { 0x08000200u, 0xfc000fe0u, trans_log, .f.ttt = tcg_gen_and_reg },
2878    { 0x08000240u, 0xfc000fe0u, trans_log, .f.ttt = tcg_gen_or_reg },
2879    { 0x08000280u, 0xfc000fe0u, trans_log, .f.ttt = tcg_gen_xor_reg },
2880    { 0x08000880u, 0xfc000fe0u, trans_cmpclr },
2881    { 0x08000380u, 0xfc000fe0u, trans_uxor },
2882    { 0x08000980u, 0xfc000fa0u, trans_uaddcm },
2883    { 0x08000b80u, 0xfc1f0fa0u, trans_dcor },
2884    { 0x08000440u, 0xfc000fe0u, trans_ds },
2885    { 0x08000700u, 0xfc0007e0u, trans_add }, /* add */
2886    { 0x08000400u, 0xfc0006e0u, trans_sub }, /* sub; sub,b; sub,tsv */
2887    { 0x080004c0u, 0xfc0007e0u, trans_sub }, /* sub,tc; sub,tsv,tc */
2888    { 0x08000200u, 0xfc000320u, trans_add }, /* shladd */
2889};
2890
2891static DisasJumpType trans_addi(DisasContext *ctx, uint32_t insn)
2892{
2893    target_sreg im = low_sextract(insn, 0, 11);
2894    unsigned e1 = extract32(insn, 11, 1);
2895    unsigned cf = extract32(insn, 12, 4);
2896    unsigned rt = extract32(insn, 16, 5);
2897    unsigned r2 = extract32(insn, 21, 5);
2898    unsigned o1 = extract32(insn, 26, 1);
2899    TCGv_reg tcg_im, tcg_r2;
2900    DisasJumpType ret;
2901
2902    if (cf) {
2903        nullify_over(ctx);
2904    }
2905
2906    tcg_im = load_const(ctx, im);
2907    tcg_r2 = load_gpr(ctx, r2);
2908    ret = do_add(ctx, rt, tcg_im, tcg_r2, 0, false, e1, !o1, false, cf);
2909
2910    return nullify_end(ctx, ret);
2911}
2912
2913static DisasJumpType trans_subi(DisasContext *ctx, uint32_t insn)
2914{
2915    target_sreg im = low_sextract(insn, 0, 11);
2916    unsigned e1 = extract32(insn, 11, 1);
2917    unsigned cf = extract32(insn, 12, 4);
2918    unsigned rt = extract32(insn, 16, 5);
2919    unsigned r2 = extract32(insn, 21, 5);
2920    TCGv_reg tcg_im, tcg_r2;
2921    DisasJumpType ret;
2922
2923    if (cf) {
2924        nullify_over(ctx);
2925    }
2926
2927    tcg_im = load_const(ctx, im);
2928    tcg_r2 = load_gpr(ctx, r2);
2929    ret = do_sub(ctx, rt, tcg_im, tcg_r2, e1, false, false, cf);
2930
2931    return nullify_end(ctx, ret);
2932}
2933
2934static DisasJumpType trans_cmpiclr(DisasContext *ctx, uint32_t insn)
2935{
2936    target_sreg im = low_sextract(insn, 0, 11);
2937    unsigned cf = extract32(insn, 12, 4);
2938    unsigned rt = extract32(insn, 16, 5);
2939    unsigned r2 = extract32(insn, 21, 5);
2940    TCGv_reg tcg_im, tcg_r2;
2941    DisasJumpType ret;
2942
2943    if (cf) {
2944        nullify_over(ctx);
2945    }
2946
2947    tcg_im = load_const(ctx, im);
2948    tcg_r2 = load_gpr(ctx, r2);
2949    ret = do_cmpclr(ctx, rt, tcg_im, tcg_r2, cf);
2950
2951    return nullify_end(ctx, ret);
2952}
2953
2954static DisasJumpType trans_ld_idx_i(DisasContext *ctx, uint32_t insn,
2955                                    const DisasInsn *di)
2956{
2957    unsigned rt = extract32(insn, 0, 5);
2958    unsigned m = extract32(insn, 5, 1);
2959    unsigned sz = extract32(insn, 6, 2);
2960    unsigned a = extract32(insn, 13, 1);
2961    unsigned sp = extract32(insn, 14, 2);
2962    int disp = low_sextract(insn, 16, 5);
2963    unsigned rb = extract32(insn, 21, 5);
2964    int modify = (m ? (a ? -1 : 1) : 0);
2965    TCGMemOp mop = MO_TE | sz;
2966
2967    return do_load(ctx, rt, rb, 0, 0, disp, sp, modify, mop);
2968}
2969
2970static DisasJumpType trans_ld_idx_x(DisasContext *ctx, uint32_t insn,
2971                                    const DisasInsn *di)
2972{
2973    unsigned rt = extract32(insn, 0, 5);
2974    unsigned m = extract32(insn, 5, 1);
2975    unsigned sz = extract32(insn, 6, 2);
2976    unsigned u = extract32(insn, 13, 1);
2977    unsigned sp = extract32(insn, 14, 2);
2978    unsigned rx = extract32(insn, 16, 5);
2979    unsigned rb = extract32(insn, 21, 5);
2980    TCGMemOp mop = MO_TE | sz;
2981
2982    return do_load(ctx, rt, rb, rx, u ? sz : 0, 0, sp, m, mop);
2983}
2984
2985static DisasJumpType trans_st_idx_i(DisasContext *ctx, uint32_t insn,
2986                                    const DisasInsn *di)
2987{
2988    int disp = low_sextract(insn, 0, 5);
2989    unsigned m = extract32(insn, 5, 1);
2990    unsigned sz = extract32(insn, 6, 2);
2991    unsigned a = extract32(insn, 13, 1);
2992    unsigned sp = extract32(insn, 14, 2);
2993    unsigned rr = extract32(insn, 16, 5);
2994    unsigned rb = extract32(insn, 21, 5);
2995    int modify = (m ? (a ? -1 : 1) : 0);
2996    TCGMemOp mop = MO_TE | sz;
2997
2998    return do_store(ctx, rr, rb, disp, sp, modify, mop);
2999}
3000
3001static DisasJumpType trans_ldcw(DisasContext *ctx, uint32_t insn,
3002                                const DisasInsn *di)
3003{
3004    unsigned rt = extract32(insn, 0, 5);
3005    unsigned m = extract32(insn, 5, 1);
3006    unsigned i = extract32(insn, 12, 1);
3007    unsigned au = extract32(insn, 13, 1);
3008    unsigned sp = extract32(insn, 14, 2);
3009    unsigned rx = extract32(insn, 16, 5);
3010    unsigned rb = extract32(insn, 21, 5);
3011    TCGMemOp mop = MO_TEUL | MO_ALIGN_16;
3012    TCGv_reg zero, dest, ofs;
3013    TCGv_tl addr;
3014    int modify, disp = 0, scale = 0;
3015
3016    nullify_over(ctx);
3017
3018    if (i) {
3019        modify = (m ? (au ? -1 : 1) : 0);
3020        disp = low_sextract(rx, 0, 5);
3021        rx = 0;
3022    } else {
3023        modify = m;
3024        if (au) {
3025            scale = mop & MO_SIZE;
3026        }
3027    }
3028    if (modify) {
3029        /* Base register modification.  Make sure if RT == RB,
3030           we see the result of the load.  */
3031        dest = get_temp(ctx);
3032    } else {
3033        dest = dest_gpr(ctx, rt);
3034    }
3035
3036    form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify,
3037             ctx->mmu_idx == MMU_PHYS_IDX);
3038    zero = tcg_const_reg(0);
3039    tcg_gen_atomic_xchg_reg(dest, addr, zero, ctx->mmu_idx, mop);
3040    if (modify) {
3041        save_gpr(ctx, rb, ofs);
3042    }
3043    save_gpr(ctx, rt, dest);
3044
3045    return nullify_end(ctx, DISAS_NEXT);
3046}
3047
3048static DisasJumpType trans_stby(DisasContext *ctx, uint32_t insn,
3049                                const DisasInsn *di)
3050{
3051    target_sreg disp = low_sextract(insn, 0, 5);
3052    unsigned m = extract32(insn, 5, 1);
3053    unsigned a = extract32(insn, 13, 1);
3054    unsigned sp = extract32(insn, 14, 2);
3055    unsigned rt = extract32(insn, 16, 5);
3056    unsigned rb = extract32(insn, 21, 5);
3057    TCGv_reg ofs, val;
3058    TCGv_tl addr;
3059
3060    nullify_over(ctx);
3061
3062    form_gva(ctx, &addr, &ofs, rb, 0, 0, disp, sp, m,
3063             ctx->mmu_idx == MMU_PHYS_IDX);
3064    val = load_gpr(ctx, rt);
3065    if (a) {
3066        if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
3067            gen_helper_stby_e_parallel(cpu_env, addr, val);
3068        } else {
3069            gen_helper_stby_e(cpu_env, addr, val);
3070        }
3071    } else {
3072        if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
3073            gen_helper_stby_b_parallel(cpu_env, addr, val);
3074        } else {
3075            gen_helper_stby_b(cpu_env, addr, val);
3076        }
3077    }
3078
3079    if (m) {
3080        tcg_gen_andi_reg(ofs, ofs, ~3);
3081        save_gpr(ctx, rb, ofs);
3082    }
3083
3084    return nullify_end(ctx, DISAS_NEXT);
3085}
3086
3087#ifndef CONFIG_USER_ONLY
3088static DisasJumpType trans_ldwa_idx_i(DisasContext *ctx, uint32_t insn,
3089                                      const DisasInsn *di)
3090{
3091    int hold_mmu_idx = ctx->mmu_idx;
3092    DisasJumpType ret;
3093
3094    CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
3095
3096    /* ??? needs fixing for hppa64 -- ldda does not follow the same
3097       format wrt the sub-opcode in bits 6:9.  */
3098    ctx->mmu_idx = MMU_PHYS_IDX;
3099    ret = trans_ld_idx_i(ctx, insn, di);
3100    ctx->mmu_idx = hold_mmu_idx;
3101    return ret;
3102}
3103
3104static DisasJumpType trans_ldwa_idx_x(DisasContext *ctx, uint32_t insn,
3105                                      const DisasInsn *di)
3106{
3107    int hold_mmu_idx = ctx->mmu_idx;
3108    DisasJumpType ret;
3109
3110    CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
3111
3112    /* ??? needs fixing for hppa64 -- ldda does not follow the same
3113       format wrt the sub-opcode in bits 6:9.  */
3114    ctx->mmu_idx = MMU_PHYS_IDX;
3115    ret = trans_ld_idx_x(ctx, insn, di);
3116    ctx->mmu_idx = hold_mmu_idx;
3117    return ret;
3118}
3119
3120static DisasJumpType trans_stwa_idx_i(DisasContext *ctx, uint32_t insn,
3121                                      const DisasInsn *di)
3122{
3123    int hold_mmu_idx = ctx->mmu_idx;
3124    DisasJumpType ret;
3125
3126    CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
3127
3128    /* ??? needs fixing for hppa64 -- ldda does not follow the same
3129       format wrt the sub-opcode in bits 6:9.  */
3130    ctx->mmu_idx = MMU_PHYS_IDX;
3131    ret = trans_st_idx_i(ctx, insn, di);
3132    ctx->mmu_idx = hold_mmu_idx;
3133    return ret;
3134}
3135#endif
3136
3137static const DisasInsn table_index_mem[] = {
3138    { 0x0c001000u, 0xfc001300, trans_ld_idx_i }, /* LD[BHWD], im */
3139    { 0x0c000000u, 0xfc001300, trans_ld_idx_x }, /* LD[BHWD], rx */
3140    { 0x0c001200u, 0xfc001300, trans_st_idx_i }, /* ST[BHWD] */
3141    { 0x0c0001c0u, 0xfc0003c0, trans_ldcw },
3142    { 0x0c001300u, 0xfc0013c0, trans_stby },
3143#ifndef CONFIG_USER_ONLY
3144    { 0x0c000180u, 0xfc00d3c0, trans_ldwa_idx_x }, /* LDWA, rx */
3145    { 0x0c001180u, 0xfc00d3c0, trans_ldwa_idx_i }, /* LDWA, im */
3146    { 0x0c001380u, 0xfc00d3c0, trans_stwa_idx_i }, /* STWA, im */
3147#endif
3148};
3149
3150static DisasJumpType trans_ldil(DisasContext *ctx, uint32_t insn)
3151{
3152    unsigned rt = extract32(insn, 21, 5);
3153    target_sreg i = assemble_21(insn);
3154    TCGv_reg tcg_rt = dest_gpr(ctx, rt);
3155
3156    tcg_gen_movi_reg(tcg_rt, i);
3157    save_gpr(ctx, rt, tcg_rt);
3158    cond_free(&ctx->null_cond);
3159
3160    return DISAS_NEXT;
3161}
3162
3163static DisasJumpType trans_addil(DisasContext *ctx, uint32_t insn)
3164{
3165    unsigned rt = extract32(insn, 21, 5);
3166    target_sreg i = assemble_21(insn);
3167    TCGv_reg tcg_rt = load_gpr(ctx, rt);
3168    TCGv_reg tcg_r1 = dest_gpr(ctx, 1);
3169
3170    tcg_gen_addi_reg(tcg_r1, tcg_rt, i);
3171    save_gpr(ctx, 1, tcg_r1);
3172    cond_free(&ctx->null_cond);
3173
3174    return DISAS_NEXT;
3175}
3176
3177static DisasJumpType trans_ldo(DisasContext *ctx, uint32_t insn)
3178{
3179    unsigned rb = extract32(insn, 21, 5);
3180    unsigned rt = extract32(insn, 16, 5);
3181    target_sreg i = assemble_16(insn);
3182    TCGv_reg tcg_rt = dest_gpr(ctx, rt);
3183
3184    /* Special case rb == 0, for the LDI pseudo-op.
3185       The COPY pseudo-op is handled for free within tcg_gen_addi_tl.  */
3186    if (rb == 0) {
3187        tcg_gen_movi_reg(tcg_rt, i);
3188    } else {
3189        tcg_gen_addi_reg(tcg_rt, cpu_gr[rb], i);
3190    }
3191    save_gpr(ctx, rt, tcg_rt);
3192    cond_free(&ctx->null_cond);
3193
3194    return DISAS_NEXT;
3195}
3196
3197static DisasJumpType trans_load(DisasContext *ctx, uint32_t insn,
3198                                bool is_mod, TCGMemOp mop)
3199{
3200    unsigned rb = extract32(insn, 21, 5);
3201    unsigned rt = extract32(insn, 16, 5);
3202    unsigned sp = extract32(insn, 14, 2);
3203    target_sreg i = assemble_16(insn);
3204
3205    return do_load(ctx, rt, rb, 0, 0, i, sp,
3206                   is_mod ? (i < 0 ? -1 : 1) : 0, mop);
3207}
3208
3209static DisasJumpType trans_load_w(DisasContext *ctx, uint32_t insn)
3210{
3211    unsigned rb = extract32(insn, 21, 5);
3212    unsigned rt = extract32(insn, 16, 5);
3213    unsigned sp = extract32(insn, 14, 2);
3214    target_sreg i = assemble_16a(insn);
3215    unsigned ext2 = extract32(insn, 1, 2);
3216
3217    switch (ext2) {
3218    case 0:
3219    case 1:
3220        /* FLDW without modification.  */
3221        return do_floadw(ctx, ext2 * 32 + rt, rb, 0, 0, i, sp, 0);
3222    case 2:
3223        /* LDW with modification.  Note that the sign of I selects
3224           post-dec vs pre-inc.  */
3225        return do_load(ctx, rt, rb, 0, 0, i, sp, (i < 0 ? 1 : -1), MO_TEUL);
3226    default:
3227        return gen_illegal(ctx);
3228    }
3229}
3230
3231static DisasJumpType trans_fload_mod(DisasContext *ctx, uint32_t insn)
3232{
3233    target_sreg i = assemble_16a(insn);
3234    unsigned t1 = extract32(insn, 1, 1);
3235    unsigned a = extract32(insn, 2, 1);
3236    unsigned sp = extract32(insn, 14, 2);
3237    unsigned t0 = extract32(insn, 16, 5);
3238    unsigned rb = extract32(insn, 21, 5);
3239
3240    /* FLDW with modification.  */
3241    return do_floadw(ctx, t1 * 32 + t0, rb, 0, 0, i, sp, (a ? -1 : 1));
3242}
3243
3244static DisasJumpType trans_store(DisasContext *ctx, uint32_t insn,
3245                                 bool is_mod, TCGMemOp mop)
3246{
3247    unsigned rb = extract32(insn, 21, 5);
3248    unsigned rt = extract32(insn, 16, 5);
3249    unsigned sp = extract32(insn, 14, 2);
3250    target_sreg i = assemble_16(insn);
3251
3252    return do_store(ctx, rt, rb, i, sp, is_mod ? (i < 0 ? -1 : 1) : 0, mop);
3253}
3254
3255static DisasJumpType trans_store_w(DisasContext *ctx, uint32_t insn)
3256{
3257    unsigned rb = extract32(insn, 21, 5);
3258    unsigned rt = extract32(insn, 16, 5);
3259    unsigned sp = extract32(insn, 14, 2);
3260    target_sreg i = assemble_16a(insn);
3261    unsigned ext2 = extract32(insn, 1, 2);
3262
3263    switch (ext2) {
3264    case 0:
3265    case 1:
3266        /* FSTW without modification.  */
3267        return do_fstorew(ctx, ext2 * 32 + rt, rb, 0, 0, i, sp, 0);
3268    case 2:
3269        /* STW with modification.  */
3270        return do_store(ctx, rt, rb, i, sp, (i < 0 ? 1 : -1), MO_TEUL);
3271    default:
3272        return gen_illegal(ctx);
3273    }
3274}
3275
3276static DisasJumpType trans_fstore_mod(DisasContext *ctx, uint32_t insn)
3277{
3278    target_sreg i = assemble_16a(insn);
3279    unsigned t1 = extract32(insn, 1, 1);
3280    unsigned a = extract32(insn, 2, 1);
3281    unsigned sp = extract32(insn, 14, 2);
3282    unsigned t0 = extract32(insn, 16, 5);
3283    unsigned rb = extract32(insn, 21, 5);
3284
3285    /* FSTW with modification.  */
3286    return do_fstorew(ctx, t1 * 32 + t0, rb, 0, 0, i, sp, (a ? -1 : 1));
3287}
3288
3289static DisasJumpType trans_copr_w(DisasContext *ctx, uint32_t insn)
3290{
3291    unsigned t0 = extract32(insn, 0, 5);
3292    unsigned m = extract32(insn, 5, 1);
3293    unsigned t1 = extract32(insn, 6, 1);
3294    unsigned ext3 = extract32(insn, 7, 3);
3295    /* unsigned cc = extract32(insn, 10, 2); */
3296    unsigned i = extract32(insn, 12, 1);
3297    unsigned ua = extract32(insn, 13, 1);
3298    unsigned sp = extract32(insn, 14, 2);
3299    unsigned rx = extract32(insn, 16, 5);
3300    unsigned rb = extract32(insn, 21, 5);
3301    unsigned rt = t1 * 32 + t0;
3302    int modify = (m ? (ua ? -1 : 1) : 0);
3303    int disp, scale;
3304
3305    if (i == 0) {
3306        scale = (ua ? 2 : 0);
3307        disp = 0;
3308        modify = m;
3309    } else {
3310        disp = low_sextract(rx, 0, 5);
3311        scale = 0;
3312        rx = 0;
3313        modify = (m ? (ua ? -1 : 1) : 0);
3314    }
3315
3316    switch (ext3) {
3317    case 0: /* FLDW */
3318        return do_floadw(ctx, rt, rb, rx, scale, disp, sp, modify);
3319    case 4: /* FSTW */
3320        return do_fstorew(ctx, rt, rb, rx, scale, disp, sp, modify);
3321    }
3322    return gen_illegal(ctx);
3323}
3324
3325static DisasJumpType trans_copr_dw(DisasContext *ctx, uint32_t insn)
3326{
3327    unsigned rt = extract32(insn, 0, 5);
3328    unsigned m = extract32(insn, 5, 1);
3329    unsigned ext4 = extract32(insn, 6, 4);
3330    /* unsigned cc = extract32(insn, 10, 2); */
3331    unsigned i = extract32(insn, 12, 1);
3332    unsigned ua = extract32(insn, 13, 1);
3333    unsigned sp = extract32(insn, 14, 2);
3334    unsigned rx = extract32(insn, 16, 5);
3335    unsigned rb = extract32(insn, 21, 5);
3336    int modify = (m ? (ua ? -1 : 1) : 0);
3337    int disp, scale;
3338
3339    if (i == 0) {
3340        scale = (ua ? 3 : 0);
3341        disp = 0;
3342        modify = m;
3343    } else {
3344        disp = low_sextract(rx, 0, 5);
3345        scale = 0;
3346        rx = 0;
3347        modify = (m ? (ua ? -1 : 1) : 0);
3348    }
3349
3350    switch (ext4) {
3351    case 0: /* FLDD */
3352        return do_floadd(ctx, rt, rb, rx, scale, disp, sp, modify);
3353    case 8: /* FSTD */
3354        return do_fstored(ctx, rt, rb, rx, scale, disp, sp, modify);
3355    default:
3356        return gen_illegal(ctx);
3357    }
3358}
3359
3360static DisasJumpType trans_cmpb(DisasContext *ctx, uint32_t insn,
3361                                bool is_true, bool is_imm, bool is_dw)
3362{
3363    target_sreg disp = assemble_12(insn) * 4;
3364    unsigned n = extract32(insn, 1, 1);
3365    unsigned c = extract32(insn, 13, 3);
3366    unsigned r = extract32(insn, 21, 5);
3367    unsigned cf = c * 2 + !is_true;
3368    TCGv_reg dest, in1, in2, sv;
3369    DisasCond cond;
3370
3371    nullify_over(ctx);
3372
3373    if (is_imm) {
3374        in1 = load_const(ctx, low_sextract(insn, 16, 5));
3375    } else {
3376        in1 = load_gpr(ctx, extract32(insn, 16, 5));
3377    }
3378    in2 = load_gpr(ctx, r);
3379    dest = get_temp(ctx);
3380
3381    tcg_gen_sub_reg(dest, in1, in2);
3382
3383    sv = NULL;
3384    if (c == 6) {
3385        sv = do_sub_sv(ctx, dest, in1, in2);
3386    }
3387
3388    cond = do_sub_cond(cf, dest, in1, in2, sv);
3389    return do_cbranch(ctx, disp, n, &cond);
3390}
3391
3392static DisasJumpType trans_addb(DisasContext *ctx, uint32_t insn,
3393                                bool is_true, bool is_imm)
3394{
3395    target_sreg disp = assemble_12(insn) * 4;
3396    unsigned n = extract32(insn, 1, 1);
3397    unsigned c = extract32(insn, 13, 3);
3398    unsigned r = extract32(insn, 21, 5);
3399    unsigned cf = c * 2 + !is_true;
3400    TCGv_reg dest, in1, in2, sv, cb_msb;
3401    DisasCond cond;
3402
3403    nullify_over(ctx);
3404
3405    if (is_imm) {
3406        in1 = load_const(ctx, low_sextract(insn, 16, 5));
3407    } else {
3408        in1 = load_gpr(ctx, extract32(insn, 16, 5));
3409    }
3410    in2 = load_gpr(ctx, r);
3411    dest = dest_gpr(ctx, r);
3412    sv = NULL;
3413    cb_msb = NULL;
3414
3415    switch (c) {
3416    default:
3417        tcg_gen_add_reg(dest, in1, in2);
3418        break;
3419    case 4: case 5:
3420        cb_msb = get_temp(ctx);
3421        tcg_gen_movi_reg(cb_msb, 0);
3422        tcg_gen_add2_reg(dest, cb_msb, in1, cb_msb, in2, cb_msb);
3423        break;
3424    case 6:
3425        tcg_gen_add_reg(dest, in1, in2);
3426        sv = do_add_sv(ctx, dest, in1, in2);
3427        break;
3428    }
3429
3430    cond = do_cond(cf, dest, cb_msb, sv);
3431    return do_cbranch(ctx, disp, n, &cond);
3432}
3433
3434static DisasJumpType trans_bb(DisasContext *ctx, uint32_t insn)
3435{
3436    target_sreg disp = assemble_12(insn) * 4;
3437    unsigned n = extract32(insn, 1, 1);
3438    unsigned c = extract32(insn, 15, 1);
3439    unsigned r = extract32(insn, 16, 5);
3440    unsigned p = extract32(insn, 21, 5);
3441    unsigned i = extract32(insn, 26, 1);
3442    TCGv_reg tmp, tcg_r;
3443    DisasCond cond;
3444
3445    nullify_over(ctx);
3446
3447    tmp = tcg_temp_new();
3448    tcg_r = load_gpr(ctx, r);
3449    if (i) {
3450        tcg_gen_shli_reg(tmp, tcg_r, p);
3451    } else {
3452        tcg_gen_shl_reg(tmp, tcg_r, cpu_sar);
3453    }
3454
3455    cond = cond_make_0(c ? TCG_COND_GE : TCG_COND_LT, tmp);
3456    tcg_temp_free(tmp);
3457    return do_cbranch(ctx, disp, n, &cond);
3458}
3459
3460static DisasJumpType trans_movb(DisasContext *ctx, uint32_t insn, bool is_imm)
3461{
3462    target_sreg disp = assemble_12(insn) * 4;
3463    unsigned n = extract32(insn, 1, 1);
3464    unsigned c = extract32(insn, 13, 3);
3465    unsigned t = extract32(insn, 16, 5);
3466    unsigned r = extract32(insn, 21, 5);
3467    TCGv_reg dest;
3468    DisasCond cond;
3469
3470    nullify_over(ctx);
3471
3472    dest = dest_gpr(ctx, r);
3473    if (is_imm) {
3474        tcg_gen_movi_reg(dest, low_sextract(t, 0, 5));
3475    } else if (t == 0) {
3476        tcg_gen_movi_reg(dest, 0);
3477    } else {
3478        tcg_gen_mov_reg(dest, cpu_gr[t]);
3479    }
3480
3481    cond = do_sed_cond(c, dest);
3482    return do_cbranch(ctx, disp, n, &cond);
3483}
3484
3485static DisasJumpType trans_shrpw_sar(DisasContext *ctx, uint32_t insn,
3486                                    const DisasInsn *di)
3487{
3488    unsigned rt = extract32(insn, 0, 5);
3489    unsigned c = extract32(insn, 13, 3);
3490    unsigned r1 = extract32(insn, 16, 5);
3491    unsigned r2 = extract32(insn, 21, 5);
3492    TCGv_reg dest;
3493
3494    if (c) {
3495        nullify_over(ctx);
3496    }
3497
3498    dest = dest_gpr(ctx, rt);
3499    if (r1 == 0) {
3500        tcg_gen_ext32u_reg(dest, load_gpr(ctx, r2));
3501        tcg_gen_shr_reg(dest, dest, cpu_sar);
3502    } else if (r1 == r2) {
3503        TCGv_i32 t32 = tcg_temp_new_i32();
3504        tcg_gen_trunc_reg_i32(t32, load_gpr(ctx, r2));
3505        tcg_gen_rotr_i32(t32, t32, cpu_sar);
3506        tcg_gen_extu_i32_reg(dest, t32);
3507        tcg_temp_free_i32(t32);
3508    } else {
3509        TCGv_i64 t = tcg_temp_new_i64();
3510        TCGv_i64 s = tcg_temp_new_i64();
3511
3512        tcg_gen_concat_reg_i64(t, load_gpr(ctx, r2), load_gpr(ctx, r1));
3513        tcg_gen_extu_reg_i64(s, cpu_sar);
3514        tcg_gen_shr_i64(t, t, s);
3515        tcg_gen_trunc_i64_reg(dest, t);
3516
3517        tcg_temp_free_i64(t);
3518        tcg_temp_free_i64(s);
3519    }
3520    save_gpr(ctx, rt, dest);
3521
3522    /* Install the new nullification.  */
3523    cond_free(&ctx->null_cond);
3524    if (c) {
3525        ctx->null_cond = do_sed_cond(c, dest);
3526    }
3527    return nullify_end(ctx, DISAS_NEXT);
3528}
3529
3530static DisasJumpType trans_shrpw_imm(DisasContext *ctx, uint32_t insn,
3531                                     const DisasInsn *di)
3532{
3533    unsigned rt = extract32(insn, 0, 5);
3534    unsigned cpos = extract32(insn, 5, 5);
3535    unsigned c = extract32(insn, 13, 3);
3536    unsigned r1 = extract32(insn, 16, 5);
3537    unsigned r2 = extract32(insn, 21, 5);
3538    unsigned sa = 31 - cpos;
3539    TCGv_reg dest, t2;
3540
3541    if (c) {
3542        nullify_over(ctx);
3543    }
3544
3545    dest = dest_gpr(ctx, rt);
3546    t2 = load_gpr(ctx, r2);
3547    if (r1 == r2) {
3548        TCGv_i32 t32 = tcg_temp_new_i32();
3549        tcg_gen_trunc_reg_i32(t32, t2);
3550        tcg_gen_rotri_i32(t32, t32, sa);
3551        tcg_gen_extu_i32_reg(dest, t32);
3552        tcg_temp_free_i32(t32);
3553    } else if (r1 == 0) {
3554        tcg_gen_extract_reg(dest, t2, sa, 32 - sa);
3555    } else {
3556        TCGv_reg t0 = tcg_temp_new();
3557        tcg_gen_extract_reg(t0, t2, sa, 32 - sa);
3558        tcg_gen_deposit_reg(dest, t0, cpu_gr[r1], 32 - sa, sa);
3559        tcg_temp_free(t0);
3560    }
3561    save_gpr(ctx, rt, dest);
3562
3563    /* Install the new nullification.  */
3564    cond_free(&ctx->null_cond);
3565    if (c) {
3566        ctx->null_cond = do_sed_cond(c, dest);
3567    }
3568    return nullify_end(ctx, DISAS_NEXT);
3569}
3570
3571static DisasJumpType trans_extrw_sar(DisasContext *ctx, uint32_t insn,
3572                                     const DisasInsn *di)
3573{
3574    unsigned clen = extract32(insn, 0, 5);
3575    unsigned is_se = extract32(insn, 10, 1);
3576    unsigned c = extract32(insn, 13, 3);
3577    unsigned rt = extract32(insn, 16, 5);
3578    unsigned rr = extract32(insn, 21, 5);
3579    unsigned len = 32 - clen;
3580    TCGv_reg dest, src, tmp;
3581
3582    if (c) {
3583        nullify_over(ctx);
3584    }
3585
3586    dest = dest_gpr(ctx, rt);
3587    src = load_gpr(ctx, rr);
3588    tmp = tcg_temp_new();
3589
3590    /* Recall that SAR is using big-endian bit numbering.  */
3591    tcg_gen_xori_reg(tmp, cpu_sar, TARGET_REGISTER_BITS - 1);
3592    if (is_se) {
3593        tcg_gen_sar_reg(dest, src, tmp);
3594        tcg_gen_sextract_reg(dest, dest, 0, len);
3595    } else {
3596        tcg_gen_shr_reg(dest, src, tmp);
3597        tcg_gen_extract_reg(dest, dest, 0, len);
3598    }
3599    tcg_temp_free(tmp);
3600    save_gpr(ctx, rt, dest);
3601
3602    /* Install the new nullification.  */
3603    cond_free(&ctx->null_cond);
3604    if (c) {
3605        ctx->null_cond = do_sed_cond(c, dest);
3606    }
3607    return nullify_end(ctx, DISAS_NEXT);
3608}
3609
3610static DisasJumpType trans_extrw_imm(DisasContext *ctx, uint32_t insn,
3611                                     const DisasInsn *di)
3612{
3613    unsigned clen = extract32(insn, 0, 5);
3614    unsigned pos = extract32(insn, 5, 5);
3615    unsigned is_se = extract32(insn, 10, 1);
3616    unsigned c = extract32(insn, 13, 3);
3617    unsigned rt = extract32(insn, 16, 5);
3618    unsigned rr = extract32(insn, 21, 5);
3619    unsigned len = 32 - clen;
3620    unsigned cpos = 31 - pos;
3621    TCGv_reg dest, src;
3622
3623    if (c) {
3624        nullify_over(ctx);
3625    }
3626
3627    dest = dest_gpr(ctx, rt);
3628    src = load_gpr(ctx, rr);
3629    if (is_se) {
3630        tcg_gen_sextract_reg(dest, src, cpos, len);
3631    } else {
3632        tcg_gen_extract_reg(dest, src, cpos, len);
3633    }
3634    save_gpr(ctx, rt, dest);
3635
3636    /* Install the new nullification.  */
3637    cond_free(&ctx->null_cond);
3638    if (c) {
3639        ctx->null_cond = do_sed_cond(c, dest);
3640    }
3641    return nullify_end(ctx, DISAS_NEXT);
3642}
3643
3644static const DisasInsn table_sh_ex[] = {
3645    { 0xd0000000u, 0xfc001fe0u, trans_shrpw_sar },
3646    { 0xd0000800u, 0xfc001c00u, trans_shrpw_imm },
3647    { 0xd0001000u, 0xfc001be0u, trans_extrw_sar },
3648    { 0xd0001800u, 0xfc001800u, trans_extrw_imm },
3649};
3650
3651static DisasJumpType trans_depw_imm_c(DisasContext *ctx, uint32_t insn,
3652                                      const DisasInsn *di)
3653{
3654    unsigned clen = extract32(insn, 0, 5);
3655    unsigned cpos = extract32(insn, 5, 5);
3656    unsigned nz = extract32(insn, 10, 1);
3657    unsigned c = extract32(insn, 13, 3);
3658    target_sreg val = low_sextract(insn, 16, 5);
3659    unsigned rt = extract32(insn, 21, 5);
3660    unsigned len = 32 - clen;
3661    target_sreg mask0, mask1;
3662    TCGv_reg dest;
3663
3664    if (c) {
3665        nullify_over(ctx);
3666    }
3667    if (cpos + len > 32) {
3668        len = 32 - cpos;
3669    }
3670
3671    dest = dest_gpr(ctx, rt);
3672    mask0 = deposit64(0, cpos, len, val);
3673    mask1 = deposit64(-1, cpos, len, val);
3674
3675    if (nz) {
3676        TCGv_reg src = load_gpr(ctx, rt);
3677        if (mask1 != -1) {
3678            tcg_gen_andi_reg(dest, src, mask1);
3679            src = dest;
3680        }
3681        tcg_gen_ori_reg(dest, src, mask0);
3682    } else {
3683        tcg_gen_movi_reg(dest, mask0);
3684    }
3685    save_gpr(ctx, rt, dest);
3686
3687    /* Install the new nullification.  */
3688    cond_free(&ctx->null_cond);
3689    if (c) {
3690        ctx->null_cond = do_sed_cond(c, dest);
3691    }
3692    return nullify_end(ctx, DISAS_NEXT);
3693}
3694
3695static DisasJumpType trans_depw_imm(DisasContext *ctx, uint32_t insn,
3696                                    const DisasInsn *di)
3697{
3698    unsigned clen = extract32(insn, 0, 5);
3699    unsigned cpos = extract32(insn, 5, 5);
3700    unsigned nz = extract32(insn, 10, 1);
3701    unsigned c = extract32(insn, 13, 3);
3702    unsigned rr = extract32(insn, 16, 5);
3703    unsigned rt = extract32(insn, 21, 5);
3704    unsigned rs = nz ? rt : 0;
3705    unsigned len = 32 - clen;
3706    TCGv_reg dest, val;
3707
3708    if (c) {
3709        nullify_over(ctx);
3710    }
3711    if (cpos + len > 32) {
3712        len = 32 - cpos;
3713    }
3714
3715    dest = dest_gpr(ctx, rt);
3716    val = load_gpr(ctx, rr);
3717    if (rs == 0) {
3718        tcg_gen_deposit_z_reg(dest, val, cpos, len);
3719    } else {
3720        tcg_gen_deposit_reg(dest, cpu_gr[rs], val, cpos, len);
3721    }
3722    save_gpr(ctx, rt, dest);
3723
3724    /* Install the new nullification.  */
3725    cond_free(&ctx->null_cond);
3726    if (c) {
3727        ctx->null_cond = do_sed_cond(c, dest);
3728    }
3729    return nullify_end(ctx, DISAS_NEXT);
3730}
3731
3732static DisasJumpType trans_depw_sar(DisasContext *ctx, uint32_t insn,
3733                                    const DisasInsn *di)
3734{
3735    unsigned clen = extract32(insn, 0, 5);
3736    unsigned nz = extract32(insn, 10, 1);
3737    unsigned i = extract32(insn, 12, 1);
3738    unsigned c = extract32(insn, 13, 3);
3739    unsigned rt = extract32(insn, 21, 5);
3740    unsigned rs = nz ? rt : 0;
3741    unsigned len = 32 - clen;
3742    TCGv_reg val, mask, tmp, shift, dest;
3743    unsigned msb = 1U << (len - 1);
3744
3745    if (c) {
3746        nullify_over(ctx);
3747    }
3748
3749    if (i) {
3750        val = load_const(ctx, low_sextract(insn, 16, 5));
3751    } else {
3752        val = load_gpr(ctx, extract32(insn, 16, 5));
3753    }
3754    dest = dest_gpr(ctx, rt);
3755    shift = tcg_temp_new();
3756    tmp = tcg_temp_new();
3757
3758    /* Convert big-endian bit numbering in SAR to left-shift.  */
3759    tcg_gen_xori_reg(shift, cpu_sar, TARGET_REGISTER_BITS - 1);
3760
3761    mask = tcg_const_reg(msb + (msb - 1));
3762    tcg_gen_and_reg(tmp, val, mask);
3763    if (rs) {
3764        tcg_gen_shl_reg(mask, mask, shift);
3765        tcg_gen_shl_reg(tmp, tmp, shift);
3766        tcg_gen_andc_reg(dest, cpu_gr[rs], mask);
3767        tcg_gen_or_reg(dest, dest, tmp);
3768    } else {
3769        tcg_gen_shl_reg(dest, tmp, shift);
3770    }
3771    tcg_temp_free(shift);
3772    tcg_temp_free(mask);
3773    tcg_temp_free(tmp);
3774    save_gpr(ctx, rt, dest);
3775
3776    /* Install the new nullification.  */
3777    cond_free(&ctx->null_cond);
3778    if (c) {
3779        ctx->null_cond = do_sed_cond(c, dest);
3780    }
3781    return nullify_end(ctx, DISAS_NEXT);
3782}
3783
3784static const DisasInsn table_depw[] = {
3785    { 0xd4000000u, 0xfc000be0u, trans_depw_sar },
3786    { 0xd4000800u, 0xfc001800u, trans_depw_imm },
3787    { 0xd4001800u, 0xfc001800u, trans_depw_imm_c },
3788};
3789
3790static DisasJumpType trans_be(DisasContext *ctx, uint32_t insn, bool is_l)
3791{
3792    unsigned n = extract32(insn, 1, 1);
3793    unsigned b = extract32(insn, 21, 5);
3794    target_sreg disp = assemble_17(insn);
3795    TCGv_reg tmp;
3796
3797#ifdef CONFIG_USER_ONLY
3798    /* ??? It seems like there should be a good way of using
3799       "be disp(sr2, r0)", the canonical gateway entry mechanism
3800       to our advantage.  But that appears to be inconvenient to
3801       manage along side branch delay slots.  Therefore we handle
3802       entry into the gateway page via absolute address.  */
3803    /* Since we don't implement spaces, just branch.  Do notice the special
3804       case of "be disp(*,r0)" using a direct branch to disp, so that we can
3805       goto_tb to the TB containing the syscall.  */
3806    if (b == 0) {
3807        return do_dbranch(ctx, disp, is_l ? 31 : 0, n);
3808    }
3809#else
3810    int sp = assemble_sr3(insn);
3811    nullify_over(ctx);
3812#endif
3813
3814    tmp = get_temp(ctx);
3815    tcg_gen_addi_reg(tmp, load_gpr(ctx, b), disp);
3816    tmp = do_ibranch_priv(ctx, tmp);
3817
3818#ifdef CONFIG_USER_ONLY
3819    return do_ibranch(ctx, tmp, is_l ? 31 : 0, n);
3820#else
3821    TCGv_i64 new_spc = tcg_temp_new_i64();
3822
3823    load_spr(ctx, new_spc, sp);
3824    if (is_l) {
3825        copy_iaoq_entry(cpu_gr[31], ctx->iaoq_n, ctx->iaoq_n_var);
3826        tcg_gen_mov_i64(cpu_sr[0], cpu_iasq_f);
3827    }
3828    if (n && use_nullify_skip(ctx)) {
3829        tcg_gen_mov_reg(cpu_iaoq_f, tmp);
3830        tcg_gen_addi_reg(cpu_iaoq_b, cpu_iaoq_f, 4);
3831        tcg_gen_mov_i64(cpu_iasq_f, new_spc);
3832        tcg_gen_mov_i64(cpu_iasq_b, cpu_iasq_f);
3833    } else {
3834        copy_iaoq_entry(cpu_iaoq_f, ctx->iaoq_b, cpu_iaoq_b);
3835        if (ctx->iaoq_b == -1) {
3836            tcg_gen_mov_i64(cpu_iasq_f, cpu_iasq_b);
3837        }
3838        tcg_gen_mov_reg(cpu_iaoq_b, tmp);
3839        tcg_gen_mov_i64(cpu_iasq_b, new_spc);
3840        nullify_set(ctx, n);
3841    }
3842    tcg_temp_free_i64(new_spc);
3843    tcg_gen_lookup_and_goto_ptr();
3844    return nullify_end(ctx, DISAS_NORETURN);
3845#endif
3846}
3847
3848static DisasJumpType trans_bl(DisasContext *ctx, uint32_t insn,
3849                              const DisasInsn *di)
3850{
3851    unsigned n = extract32(insn, 1, 1);
3852    unsigned link = extract32(insn, 21, 5);
3853    target_sreg disp = assemble_17(insn);
3854
3855    return do_dbranch(ctx, iaoq_dest(ctx, disp), link, n);
3856}
3857
3858static DisasJumpType trans_b_gate(DisasContext *ctx, uint32_t insn,
3859                                  const DisasInsn *di)
3860{
3861    unsigned n = extract32(insn, 1, 1);
3862    unsigned link = extract32(insn, 21, 5);
3863    target_sreg disp = assemble_17(insn);
3864    target_ureg dest = iaoq_dest(ctx, disp);
3865
3866    /* Make sure the caller hasn't done something weird with the queue.
3867     * ??? This is not quite the same as the PSW[B] bit, which would be
3868     * expensive to track.  Real hardware will trap for
3869     *    b  gateway
3870     *    b  gateway+4  (in delay slot of first branch)
3871     * However, checking for a non-sequential instruction queue *will*
3872     * diagnose the security hole
3873     *    b  gateway
3874     *    b  evil
3875     * in which instructions at evil would run with increased privs.
3876     */
3877    if (ctx->iaoq_b == -1 || ctx->iaoq_b != ctx->iaoq_f + 4) {
3878        return gen_illegal(ctx);
3879    }
3880
3881#ifndef CONFIG_USER_ONLY
3882    if (ctx->tb_flags & PSW_C) {
3883        CPUHPPAState *env = ctx->cs->env_ptr;
3884        int type = hppa_artype_for_page(env, ctx->base.pc_next);
3885        /* If we could not find a TLB entry, then we need to generate an
3886           ITLB miss exception so the kernel will provide it.
3887           The resulting TLB fill operation will invalidate this TB and
3888           we will re-translate, at which point we *will* be able to find
3889           the TLB entry and determine if this is in fact a gateway page.  */
3890        if (type < 0) {
3891            return gen_excp(ctx, EXCP_ITLB_MISS);
3892        }
3893        /* No change for non-gateway pages or for priv decrease.  */
3894        if (type >= 4 && type - 4 < ctx->privilege) {
3895            dest = deposit32(dest, 0, 2, type - 4);
3896        }
3897    } else {
3898        dest &= -4;  /* priv = 0 */
3899    }
3900#endif
3901
3902    return do_dbranch(ctx, dest, link, n);
3903}
3904
3905static DisasJumpType trans_bl_long(DisasContext *ctx, uint32_t insn,
3906                                   const DisasInsn *di)
3907{
3908    unsigned n = extract32(insn, 1, 1);
3909    target_sreg disp = assemble_22(insn);
3910
3911    return do_dbranch(ctx, iaoq_dest(ctx, disp), 2, n);
3912}
3913
3914static DisasJumpType trans_blr(DisasContext *ctx, uint32_t insn,
3915                               const DisasInsn *di)
3916{
3917    unsigned n = extract32(insn, 1, 1);
3918    unsigned rx = extract32(insn, 16, 5);
3919    unsigned link = extract32(insn, 21, 5);
3920    TCGv_reg tmp = get_temp(ctx);
3921
3922    tcg_gen_shli_reg(tmp, load_gpr(ctx, rx), 3);
3923    tcg_gen_addi_reg(tmp, tmp, ctx->iaoq_f + 8);
3924    /* The computation here never changes privilege level.  */
3925    return do_ibranch(ctx, tmp, link, n);
3926}
3927
3928static DisasJumpType trans_bv(DisasContext *ctx, uint32_t insn,
3929                              const DisasInsn *di)
3930{
3931    unsigned n = extract32(insn, 1, 1);
3932    unsigned rx = extract32(insn, 16, 5);
3933    unsigned rb = extract32(insn, 21, 5);
3934    TCGv_reg dest;
3935
3936    if (rx == 0) {
3937        dest = load_gpr(ctx, rb);
3938    } else {
3939        dest = get_temp(ctx);
3940        tcg_gen_shli_reg(dest, load_gpr(ctx, rx), 3);
3941        tcg_gen_add_reg(dest, dest, load_gpr(ctx, rb));
3942    }
3943    dest = do_ibranch_priv(ctx, dest);
3944    return do_ibranch(ctx, dest, 0, n);
3945}
3946
3947static DisasJumpType trans_bve(DisasContext *ctx, uint32_t insn,
3948                               const DisasInsn *di)
3949{
3950    unsigned n = extract32(insn, 1, 1);
3951    unsigned rb = extract32(insn, 21, 5);
3952    unsigned link = extract32(insn, 13, 1) ? 2 : 0;
3953    TCGv_reg dest;
3954
3955#ifdef CONFIG_USER_ONLY
3956    dest = do_ibranch_priv(ctx, load_gpr(ctx, rb));
3957    return do_ibranch(ctx, dest, link, n);
3958#else
3959    nullify_over(ctx);
3960    dest = do_ibranch_priv(ctx, load_gpr(ctx, rb));
3961
3962    copy_iaoq_entry(cpu_iaoq_f, ctx->iaoq_b, cpu_iaoq_b);
3963    if (ctx->iaoq_b == -1) {
3964        tcg_gen_mov_i64(cpu_iasq_f, cpu_iasq_b);
3965    }
3966    copy_iaoq_entry(cpu_iaoq_b, -1, dest);
3967    tcg_gen_mov_i64(cpu_iasq_b, space_select(ctx, 0, dest));
3968    if (link) {
3969        copy_iaoq_entry(cpu_gr[link], ctx->iaoq_n, ctx->iaoq_n_var);
3970    }
3971    nullify_set(ctx, n);
3972    tcg_gen_lookup_and_goto_ptr();
3973    return nullify_end(ctx, DISAS_NORETURN);
3974#endif
3975}
3976
3977static const DisasInsn table_branch[] = {
3978    { 0xe8000000u, 0xfc006000u, trans_bl }, /* B,L and B,L,PUSH */
3979    { 0xe800a000u, 0xfc00e000u, trans_bl_long },
3980    { 0xe8004000u, 0xfc00fffdu, trans_blr },
3981    { 0xe800c000u, 0xfc00fffdu, trans_bv },
3982    { 0xe800d000u, 0xfc00dffcu, trans_bve },
3983    { 0xe8002000u, 0xfc00e000u, trans_b_gate },
3984};
3985
3986static DisasJumpType trans_fop_wew_0c(DisasContext *ctx, uint32_t insn,
3987                                      const DisasInsn *di)
3988{
3989    unsigned rt = extract32(insn, 0, 5);
3990    unsigned ra = extract32(insn, 21, 5);
3991    return do_fop_wew(ctx, rt, ra, di->f.wew);
3992}
3993
3994static DisasJumpType trans_fop_wew_0e(DisasContext *ctx, uint32_t insn,
3995                                      const DisasInsn *di)
3996{
3997    unsigned rt = assemble_rt64(insn);
3998    unsigned ra = assemble_ra64(insn);
3999    return do_fop_wew(ctx, rt, ra, di->f.wew);
4000}
4001
4002static DisasJumpType trans_fop_ded(DisasContext *ctx, uint32_t insn,
4003                                   const DisasInsn *di)
4004{
4005    unsigned rt = extract32(insn, 0, 5);
4006    unsigned ra = extract32(insn, 21, 5);
4007    return do_fop_ded(ctx, rt, ra, di->f.ded);
4008}
4009
4010static DisasJumpType trans_fop_wed_0c(DisasContext *ctx, uint32_t insn,
4011                                      const DisasInsn *di)
4012{
4013    unsigned rt = extract32(insn, 0, 5);
4014    unsigned ra = extract32(insn, 21, 5);
4015    return do_fop_wed(ctx, rt, ra, di->f.wed);
4016}
4017
4018static DisasJumpType trans_fop_wed_0e(DisasContext *ctx, uint32_t insn,
4019                                      const DisasInsn *di)
4020{
4021    unsigned rt = assemble_rt64(insn);
4022    unsigned ra = extract32(insn, 21, 5);
4023    return do_fop_wed(ctx, rt, ra, di->f.wed);
4024}
4025
4026static DisasJumpType trans_fop_dew_0c(DisasContext *ctx, uint32_t insn,
4027                                      const DisasInsn *di)
4028{
4029    unsigned rt = extract32(insn, 0, 5);
4030    unsigned ra = extract32(insn, 21, 5);
4031    return do_fop_dew(ctx, rt, ra, di->f.dew);
4032}
4033
4034static DisasJumpType trans_fop_dew_0e(DisasContext *ctx, uint32_t insn,
4035                                      const DisasInsn *di)
4036{
4037    unsigned rt = extract32(insn, 0, 5);
4038    unsigned ra = assemble_ra64(insn);
4039    return do_fop_dew(ctx, rt, ra, di->f.dew);
4040}
4041
4042static DisasJumpType trans_fop_weww_0c(DisasContext *ctx, uint32_t insn,
4043                                       const DisasInsn *di)
4044{
4045    unsigned rt = extract32(insn, 0, 5);
4046    unsigned rb = extract32(insn, 16, 5);
4047    unsigned ra = extract32(insn, 21, 5);
4048    return do_fop_weww(ctx, rt, ra, rb, di->f.weww);
4049}
4050
4051static DisasJumpType trans_fop_weww_0e(DisasContext *ctx, uint32_t insn,
4052                                       const DisasInsn *di)
4053{
4054    unsigned rt = assemble_rt64(insn);
4055    unsigned rb = assemble_rb64(insn);
4056    unsigned ra = assemble_ra64(insn);
4057    return do_fop_weww(ctx, rt, ra, rb, di->f.weww);
4058}
4059
4060static DisasJumpType trans_fop_dedd(DisasContext *ctx, uint32_t insn,
4061                                    const DisasInsn *di)
4062{
4063    unsigned rt = extract32(insn, 0, 5);
4064    unsigned rb = extract32(insn, 16, 5);
4065    unsigned ra = extract32(insn, 21, 5);
4066    return do_fop_dedd(ctx, rt, ra, rb, di->f.dedd);
4067}
4068
4069static void gen_fcpy_s(TCGv_i32 dst, TCGv_env unused, TCGv_i32 src)
4070{
4071    tcg_gen_mov_i32(dst, src);
4072}
4073
4074static void gen_fcpy_d(TCGv_i64 dst, TCGv_env unused, TCGv_i64 src)
4075{
4076    tcg_gen_mov_i64(dst, src);
4077}
4078
4079static void gen_fabs_s(TCGv_i32 dst, TCGv_env unused, TCGv_i32 src)
4080{
4081    tcg_gen_andi_i32(dst, src, INT32_MAX);
4082}
4083
4084static void gen_fabs_d(TCGv_i64 dst, TCGv_env unused, TCGv_i64 src)
4085{
4086    tcg_gen_andi_i64(dst, src, INT64_MAX);
4087}
4088
4089static void gen_fneg_s(TCGv_i32 dst, TCGv_env unused, TCGv_i32 src)
4090{
4091    tcg_gen_xori_i32(dst, src, INT32_MIN);
4092}
4093
4094static void gen_fneg_d(TCGv_i64 dst, TCGv_env unused, TCGv_i64 src)
4095{
4096    tcg_gen_xori_i64(dst, src, INT64_MIN);
4097}
4098
4099static void gen_fnegabs_s(TCGv_i32 dst, TCGv_env unused, TCGv_i32 src)
4100{
4101    tcg_gen_ori_i32(dst, src, INT32_MIN);
4102}
4103
4104static void gen_fnegabs_d(TCGv_i64 dst, TCGv_env unused, TCGv_i64 src)
4105{
4106    tcg_gen_ori_i64(dst, src, INT64_MIN);
4107}
4108
4109static DisasJumpType do_fcmp_s(DisasContext *ctx, unsigned ra, unsigned rb,
4110                               unsigned y, unsigned c)
4111{
4112    TCGv_i32 ta, tb, tc, ty;
4113
4114    nullify_over(ctx);
4115
4116    ta = load_frw0_i32(ra);
4117    tb = load_frw0_i32(rb);
4118    ty = tcg_const_i32(y);
4119    tc = tcg_const_i32(c);
4120
4121    gen_helper_fcmp_s(cpu_env, ta, tb, ty, tc);
4122
4123    tcg_temp_free_i32(ta);
4124    tcg_temp_free_i32(tb);
4125    tcg_temp_free_i32(ty);
4126    tcg_temp_free_i32(tc);
4127
4128    return nullify_end(ctx, DISAS_NEXT);
4129}
4130
4131static DisasJumpType trans_fcmp_s_0c(DisasContext *ctx, uint32_t insn,
4132                                     const DisasInsn *di)
4133{
4134    unsigned c = extract32(insn, 0, 5);
4135    unsigned y = extract32(insn, 13, 3);
4136    unsigned rb = extract32(insn, 16, 5);
4137    unsigned ra = extract32(insn, 21, 5);
4138    return do_fcmp_s(ctx, ra, rb, y, c);
4139}
4140
4141static DisasJumpType trans_fcmp_s_0e(DisasContext *ctx, uint32_t insn,
4142                                     const DisasInsn *di)
4143{
4144    unsigned c = extract32(insn, 0, 5);
4145    unsigned y = extract32(insn, 13, 3);
4146    unsigned rb = assemble_rb64(insn);
4147    unsigned ra = assemble_ra64(insn);
4148    return do_fcmp_s(ctx, ra, rb, y, c);
4149}
4150
4151static DisasJumpType trans_fcmp_d(DisasContext *ctx, uint32_t insn,
4152                                  const DisasInsn *di)
4153{
4154    unsigned c = extract32(insn, 0, 5);
4155    unsigned y = extract32(insn, 13, 3);
4156    unsigned rb = extract32(insn, 16, 5);
4157    unsigned ra = extract32(insn, 21, 5);
4158    TCGv_i64 ta, tb;
4159    TCGv_i32 tc, ty;
4160
4161    nullify_over(ctx);
4162
4163    ta = load_frd0(ra);
4164    tb = load_frd0(rb);
4165    ty = tcg_const_i32(y);
4166    tc = tcg_const_i32(c);
4167
4168    gen_helper_fcmp_d(cpu_env, ta, tb, ty, tc);
4169
4170    tcg_temp_free_i64(ta);
4171    tcg_temp_free_i64(tb);
4172    tcg_temp_free_i32(ty);
4173    tcg_temp_free_i32(tc);
4174
4175    return nullify_end(ctx, DISAS_NEXT);
4176}
4177
4178static DisasJumpType trans_ftest_t(DisasContext *ctx, uint32_t insn,
4179                                   const DisasInsn *di)
4180{
4181    unsigned y = extract32(insn, 13, 3);
4182    unsigned cbit = (y ^ 1) - 1;
4183    TCGv_reg t;
4184
4185    nullify_over(ctx);
4186
4187    t = tcg_temp_new();
4188    tcg_gen_ld32u_reg(t, cpu_env, offsetof(CPUHPPAState, fr0_shadow));
4189    tcg_gen_extract_reg(t, t, 21 - cbit, 1);
4190    ctx->null_cond = cond_make_0(TCG_COND_NE, t);
4191    tcg_temp_free(t);
4192
4193    return nullify_end(ctx, DISAS_NEXT);
4194}
4195
4196static DisasJumpType trans_ftest_q(DisasContext *ctx, uint32_t insn,
4197                                   const DisasInsn *di)
4198{
4199    unsigned c = extract32(insn, 0, 5);
4200    int mask;
4201    bool inv = false;
4202    TCGv_reg t;
4203
4204    nullify_over(ctx);
4205
4206    t = tcg_temp_new();
4207    tcg_gen_ld32u_reg(t, cpu_env, offsetof(CPUHPPAState, fr0_shadow));
4208
4209    switch (c) {
4210    case 0: /* simple */
4211        tcg_gen_andi_reg(t, t, 0x4000000);
4212        ctx->null_cond = cond_make_0(TCG_COND_NE, t);
4213        goto done;
4214    case 2: /* rej */
4215        inv = true;
4216        /* fallthru */
4217    case 1: /* acc */
4218        mask = 0x43ff800;
4219        break;
4220    case 6: /* rej8 */
4221        inv = true;
4222        /* fallthru */
4223    case 5: /* acc8 */
4224        mask = 0x43f8000;
4225        break;
4226    case 9: /* acc6 */
4227        mask = 0x43e0000;
4228        break;
4229    case 13: /* acc4 */
4230        mask = 0x4380000;
4231        break;
4232    case 17: /* acc2 */
4233        mask = 0x4200000;
4234        break;
4235    default:
4236        return gen_illegal(ctx);
4237    }
4238    if (inv) {
4239        TCGv_reg c = load_const(ctx, mask);
4240        tcg_gen_or_reg(t, t, c);
4241        ctx->null_cond = cond_make(TCG_COND_EQ, t, c);
4242    } else {
4243        tcg_gen_andi_reg(t, t, mask);
4244        ctx->null_cond = cond_make_0(TCG_COND_EQ, t);
4245    }
4246 done:
4247    return nullify_end(ctx, DISAS_NEXT);
4248}
4249
4250static DisasJumpType trans_xmpyu(DisasContext *ctx, uint32_t insn,
4251                                 const DisasInsn *di)
4252{
4253    unsigned rt = extract32(insn, 0, 5);
4254    unsigned rb = assemble_rb64(insn);
4255    unsigned ra = assemble_ra64(insn);
4256    TCGv_i64 a, b;
4257
4258    nullify_over(ctx);
4259
4260    a = load_frw0_i64(ra);
4261    b = load_frw0_i64(rb);
4262    tcg_gen_mul_i64(a, a, b);
4263    save_frd(rt, a);
4264    tcg_temp_free_i64(a);
4265    tcg_temp_free_i64(b);
4266
4267    return nullify_end(ctx, DISAS_NEXT);
4268}
4269
4270#define FOP_DED  trans_fop_ded, .f.ded
4271#define FOP_DEDD trans_fop_dedd, .f.dedd
4272
4273#define FOP_WEW  trans_fop_wew_0c, .f.wew
4274#define FOP_DEW  trans_fop_dew_0c, .f.dew
4275#define FOP_WED  trans_fop_wed_0c, .f.wed
4276#define FOP_WEWW trans_fop_weww_0c, .f.weww
4277
4278static const DisasInsn table_float_0c[] = {
4279    /* floating point class zero */
4280    { 0x30004000, 0xfc1fffe0, FOP_WEW = gen_fcpy_s },
4281    { 0x30006000, 0xfc1fffe0, FOP_WEW = gen_fabs_s },
4282    { 0x30008000, 0xfc1fffe0, FOP_WEW = gen_helper_fsqrt_s },
4283    { 0x3000a000, 0xfc1fffe0, FOP_WEW = gen_helper_frnd_s },
4284    { 0x3000c000, 0xfc1fffe0, FOP_WEW = gen_fneg_s },
4285    { 0x3000e000, 0xfc1fffe0, FOP_WEW = gen_fnegabs_s },
4286
4287    { 0x30004800, 0xfc1fffe0, FOP_DED = gen_fcpy_d },
4288    { 0x30006800, 0xfc1fffe0, FOP_DED = gen_fabs_d },
4289    { 0x30008800, 0xfc1fffe0, FOP_DED = gen_helper_fsqrt_d },
4290    { 0x3000a800, 0xfc1fffe0, FOP_DED = gen_helper_frnd_d },
4291    { 0x3000c800, 0xfc1fffe0, FOP_DED = gen_fneg_d },
4292    { 0x3000e800, 0xfc1fffe0, FOP_DED = gen_fnegabs_d },
4293
4294    /* floating point class three */
4295    { 0x30000600, 0xfc00ffe0, FOP_WEWW = gen_helper_fadd_s },
4296    { 0x30002600, 0xfc00ffe0, FOP_WEWW = gen_helper_fsub_s },
4297    { 0x30004600, 0xfc00ffe0, FOP_WEWW = gen_helper_fmpy_s },
4298    { 0x30006600, 0xfc00ffe0, FOP_WEWW = gen_helper_fdiv_s },
4299
4300    { 0x30000e00, 0xfc00ffe0, FOP_DEDD = gen_helper_fadd_d },
4301    { 0x30002e00, 0xfc00ffe0, FOP_DEDD = gen_helper_fsub_d },
4302    { 0x30004e00, 0xfc00ffe0, FOP_DEDD = gen_helper_fmpy_d },
4303    { 0x30006e00, 0xfc00ffe0, FOP_DEDD = gen_helper_fdiv_d },
4304
4305    /* floating point class one */
4306    /* float/float */
4307    { 0x30000a00, 0xfc1fffe0, FOP_WED = gen_helper_fcnv_d_s },
4308    { 0x30002200, 0xfc1fffe0, FOP_DEW = gen_helper_fcnv_s_d },
4309    /* int/float */
4310    { 0x30008200, 0xfc1fffe0, FOP_WEW = gen_helper_fcnv_w_s },
4311    { 0x30008a00, 0xfc1fffe0, FOP_WED = gen_helper_fcnv_dw_s },
4312    { 0x3000a200, 0xfc1fffe0, FOP_DEW = gen_helper_fcnv_w_d },
4313    { 0x3000aa00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_dw_d },
4314    /* float/int */
4315    { 0x30010200, 0xfc1fffe0, FOP_WEW = gen_helper_fcnv_s_w },
4316    { 0x30010a00, 0xfc1fffe0, FOP_WED = gen_helper_fcnv_d_w },
4317    { 0x30012200, 0xfc1fffe0, FOP_DEW = gen_helper_fcnv_s_dw },
4318    { 0x30012a00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_d_dw },
4319    /* float/int truncate */
4320    { 0x30018200, 0xfc1fffe0, FOP_WEW = gen_helper_fcnv_t_s_w },
4321    { 0x30018a00, 0xfc1fffe0, FOP_WED = gen_helper_fcnv_t_d_w },
4322    { 0x3001a200, 0xfc1fffe0, FOP_DEW = gen_helper_fcnv_t_s_dw },
4323    { 0x3001aa00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_t_d_dw },
4324    /* uint/float */
4325    { 0x30028200, 0xfc1fffe0, FOP_WEW = gen_helper_fcnv_uw_s },
4326    { 0x30028a00, 0xfc1fffe0, FOP_WED = gen_helper_fcnv_udw_s },
4327    { 0x3002a200, 0xfc1fffe0, FOP_DEW = gen_helper_fcnv_uw_d },
4328    { 0x3002aa00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_udw_d },
4329    /* float/uint */
4330    { 0x30030200, 0xfc1fffe0, FOP_WEW = gen_helper_fcnv_s_uw },
4331    { 0x30030a00, 0xfc1fffe0, FOP_WED = gen_helper_fcnv_d_uw },
4332    { 0x30032200, 0xfc1fffe0, FOP_DEW = gen_helper_fcnv_s_udw },
4333    { 0x30032a00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_d_udw },
4334    /* float/uint truncate */
4335    { 0x30038200, 0xfc1fffe0, FOP_WEW = gen_helper_fcnv_t_s_uw },
4336    { 0x30038a00, 0xfc1fffe0, FOP_WED = gen_helper_fcnv_t_d_uw },
4337    { 0x3003a200, 0xfc1fffe0, FOP_DEW = gen_helper_fcnv_t_s_udw },
4338    { 0x3003aa00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_t_d_udw },
4339
4340    /* floating point class two */
4341    { 0x30000400, 0xfc001fe0, trans_fcmp_s_0c },
4342    { 0x30000c00, 0xfc001fe0, trans_fcmp_d },
4343    { 0x30002420, 0xffffffe0, trans_ftest_q },
4344    { 0x30000420, 0xffff1fff, trans_ftest_t },
4345
4346    /* FID.  Note that ra == rt == 0, which via fcpy puts 0 into fr0.
4347       This is machine/revision == 0, which is reserved for simulator.  */
4348    { 0x30000000, 0xffffffff, FOP_WEW = gen_fcpy_s },
4349};
4350
4351#undef FOP_WEW
4352#undef FOP_DEW
4353#undef FOP_WED
4354#undef FOP_WEWW
4355#define FOP_WEW  trans_fop_wew_0e, .f.wew
4356#define FOP_DEW  trans_fop_dew_0e, .f.dew
4357#define FOP_WED  trans_fop_wed_0e, .f.wed
4358#define FOP_WEWW trans_fop_weww_0e, .f.weww
4359
4360static const DisasInsn table_float_0e[] = {
4361    /* floating point class zero */
4362    { 0x38004000, 0xfc1fff20, FOP_WEW = gen_fcpy_s },
4363    { 0x38006000, 0xfc1fff20, FOP_WEW = gen_fabs_s },
4364    { 0x38008000, 0xfc1fff20, FOP_WEW = gen_helper_fsqrt_s },
4365    { 0x3800a000, 0xfc1fff20, FOP_WEW = gen_helper_frnd_s },
4366    { 0x3800c000, 0xfc1fff20, FOP_WEW = gen_fneg_s },
4367    { 0x3800e000, 0xfc1fff20, FOP_WEW = gen_fnegabs_s },
4368
4369    { 0x38004800, 0xfc1fffe0, FOP_DED = gen_fcpy_d },
4370    { 0x38006800, 0xfc1fffe0, FOP_DED = gen_fabs_d },
4371    { 0x38008800, 0xfc1fffe0, FOP_DED = gen_helper_fsqrt_d },
4372    { 0x3800a800, 0xfc1fffe0, FOP_DED = gen_helper_frnd_d },
4373    { 0x3800c800, 0xfc1fffe0, FOP_DED = gen_fneg_d },
4374    { 0x3800e800, 0xfc1fffe0, FOP_DED = gen_fnegabs_d },
4375
4376    /* floating point class three */
4377    { 0x38000600, 0xfc00ef20, FOP_WEWW = gen_helper_fadd_s },
4378    { 0x38002600, 0xfc00ef20, FOP_WEWW = gen_helper_fsub_s },
4379    { 0x38004600, 0xfc00ef20, FOP_WEWW = gen_helper_fmpy_s },
4380    { 0x38006600, 0xfc00ef20, FOP_WEWW = gen_helper_fdiv_s },
4381
4382    { 0x38000e00, 0xfc00ffe0, FOP_DEDD = gen_helper_fadd_d },
4383    { 0x38002e00, 0xfc00ffe0, FOP_DEDD = gen_helper_fsub_d },
4384    { 0x38004e00, 0xfc00ffe0, FOP_DEDD = gen_helper_fmpy_d },
4385    { 0x38006e00, 0xfc00ffe0, FOP_DEDD = gen_helper_fdiv_d },
4386
4387    { 0x38004700, 0xfc00ef60, trans_xmpyu },
4388
4389    /* floating point class one */
4390    /* float/float */
4391    { 0x38000a00, 0xfc1fffa0, FOP_WED = gen_helper_fcnv_d_s },
4392    { 0x38002200, 0xfc1fff60, FOP_DEW = gen_helper_fcnv_s_d },
4393    /* int/float */
4394    { 0x38008200, 0xfc1ffe20, FOP_WEW = gen_helper_fcnv_w_s },
4395    { 0x38008a00, 0xfc1fffa0, FOP_WED = gen_helper_fcnv_dw_s },
4396    { 0x3800a200, 0xfc1fff60, FOP_DEW = gen_helper_fcnv_w_d },
4397    { 0x3800aa00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_dw_d },
4398    /* float/int */
4399    { 0x38010200, 0xfc1ffe20, FOP_WEW = gen_helper_fcnv_s_w },
4400    { 0x38010a00, 0xfc1fffa0, FOP_WED = gen_helper_fcnv_d_w },
4401    { 0x38012200, 0xfc1fff60, FOP_DEW = gen_helper_fcnv_s_dw },
4402    { 0x38012a00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_d_dw },
4403    /* float/int truncate */
4404    { 0x38018200, 0xfc1ffe20, FOP_WEW = gen_helper_fcnv_t_s_w },
4405    { 0x38018a00, 0xfc1fffa0, FOP_WED = gen_helper_fcnv_t_d_w },
4406    { 0x3801a200, 0xfc1fff60, FOP_DEW = gen_helper_fcnv_t_s_dw },
4407    { 0x3801aa00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_t_d_dw },
4408    /* uint/float */
4409    { 0x38028200, 0xfc1ffe20, FOP_WEW = gen_helper_fcnv_uw_s },
4410    { 0x38028a00, 0xfc1fffa0, FOP_WED = gen_helper_fcnv_udw_s },
4411    { 0x3802a200, 0xfc1fff60, FOP_DEW = gen_helper_fcnv_uw_d },
4412    { 0x3802aa00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_udw_d },
4413    /* float/uint */
4414    { 0x38030200, 0xfc1ffe20, FOP_WEW = gen_helper_fcnv_s_uw },
4415    { 0x38030a00, 0xfc1fffa0, FOP_WED = gen_helper_fcnv_d_uw },
4416    { 0x38032200, 0xfc1fff60, FOP_DEW = gen_helper_fcnv_s_udw },
4417    { 0x38032a00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_d_udw },
4418    /* float/uint truncate */
4419    { 0x38038200, 0xfc1ffe20, FOP_WEW = gen_helper_fcnv_t_s_uw },
4420    { 0x38038a00, 0xfc1fffa0, FOP_WED = gen_helper_fcnv_t_d_uw },
4421    { 0x3803a200, 0xfc1fff60, FOP_DEW = gen_helper_fcnv_t_s_udw },
4422    { 0x3803aa00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_t_d_udw },
4423
4424    /* floating point class two */
4425    { 0x38000400, 0xfc000f60, trans_fcmp_s_0e },
4426    { 0x38000c00, 0xfc001fe0, trans_fcmp_d },
4427};
4428
4429#undef FOP_WEW
4430#undef FOP_DEW
4431#undef FOP_WED
4432#undef FOP_WEWW
4433#undef FOP_DED
4434#undef FOP_DEDD
4435
4436/* Convert the fmpyadd single-precision register encodings to standard.  */
4437static inline int fmpyadd_s_reg(unsigned r)
4438{
4439    return (r & 16) * 2 + 16 + (r & 15);
4440}
4441
4442static DisasJumpType trans_fmpyadd(DisasContext *ctx,
4443                                   uint32_t insn, bool is_sub)
4444{
4445    unsigned tm = extract32(insn, 0, 5);
4446    unsigned f = extract32(insn, 5, 1);
4447    unsigned ra = extract32(insn, 6, 5);
4448    unsigned ta = extract32(insn, 11, 5);
4449    unsigned rm2 = extract32(insn, 16, 5);
4450    unsigned rm1 = extract32(insn, 21, 5);
4451
4452    nullify_over(ctx);
4453
4454    /* Independent multiply & add/sub, with undefined behaviour
4455       if outputs overlap inputs.  */
4456    if (f == 0) {
4457        tm = fmpyadd_s_reg(tm);
4458        ra = fmpyadd_s_reg(ra);
4459        ta = fmpyadd_s_reg(ta);
4460        rm2 = fmpyadd_s_reg(rm2);
4461        rm1 = fmpyadd_s_reg(rm1);
4462        do_fop_weww(ctx, tm, rm1, rm2, gen_helper_fmpy_s);
4463        do_fop_weww(ctx, ta, ta, ra,
4464                    is_sub ? gen_helper_fsub_s : gen_helper_fadd_s);
4465    } else {
4466        do_fop_dedd(ctx, tm, rm1, rm2, gen_helper_fmpy_d);
4467        do_fop_dedd(ctx, ta, ta, ra,
4468                    is_sub ? gen_helper_fsub_d : gen_helper_fadd_d);
4469    }
4470
4471    return nullify_end(ctx, DISAS_NEXT);
4472}
4473
4474static DisasJumpType trans_fmpyfadd_s(DisasContext *ctx, uint32_t insn,
4475                                      const DisasInsn *di)
4476{
4477    unsigned rt = assemble_rt64(insn);
4478    unsigned neg = extract32(insn, 5, 1);
4479    unsigned rm1 = assemble_ra64(insn);
4480    unsigned rm2 = assemble_rb64(insn);
4481    unsigned ra3 = assemble_rc64(insn);
4482    TCGv_i32 a, b, c;
4483
4484    nullify_over(ctx);
4485    a = load_frw0_i32(rm1);
4486    b = load_frw0_i32(rm2);
4487    c = load_frw0_i32(ra3);
4488
4489    if (neg) {
4490        gen_helper_fmpynfadd_s(a, cpu_env, a, b, c);
4491    } else {
4492        gen_helper_fmpyfadd_s(a, cpu_env, a, b, c);
4493    }
4494
4495    tcg_temp_free_i32(b);
4496    tcg_temp_free_i32(c);
4497    save_frw_i32(rt, a);
4498    tcg_temp_free_i32(a);
4499    return nullify_end(ctx, DISAS_NEXT);
4500}
4501
4502static DisasJumpType trans_fmpyfadd_d(DisasContext *ctx, uint32_t insn,
4503                                      const DisasInsn *di)
4504{
4505    unsigned rt = extract32(insn, 0, 5);
4506    unsigned neg = extract32(insn, 5, 1);
4507    unsigned rm1 = extract32(insn, 21, 5);
4508    unsigned rm2 = extract32(insn, 16, 5);
4509    unsigned ra3 = assemble_rc64(insn);
4510    TCGv_i64 a, b, c;
4511
4512    nullify_over(ctx);
4513    a = load_frd0(rm1);
4514    b = load_frd0(rm2);
4515    c = load_frd0(ra3);
4516
4517    if (neg) {
4518        gen_helper_fmpynfadd_d(a, cpu_env, a, b, c);
4519    } else {
4520        gen_helper_fmpyfadd_d(a, cpu_env, a, b, c);
4521    }
4522
4523    tcg_temp_free_i64(b);
4524    tcg_temp_free_i64(c);
4525    save_frd(rt, a);
4526    tcg_temp_free_i64(a);
4527    return nullify_end(ctx, DISAS_NEXT);
4528}
4529
4530static const DisasInsn table_fp_fused[] = {
4531    { 0xb8000000u, 0xfc000800u, trans_fmpyfadd_s },
4532    { 0xb8000800u, 0xfc0019c0u, trans_fmpyfadd_d }
4533};
4534
4535static DisasJumpType translate_table_int(DisasContext *ctx, uint32_t insn,
4536                                         const DisasInsn table[], size_t n)
4537{
4538    size_t i;
4539    for (i = 0; i < n; ++i) {
4540        if ((insn & table[i].mask) == table[i].insn) {
4541            return table[i].trans(ctx, insn, &table[i]);
4542        }
4543    }
4544    qemu_log_mask(LOG_UNIMP, "UNIMP insn %08x @ " TARGET_FMT_lx "\n",
4545                  insn, ctx->base.pc_next);
4546    return gen_illegal(ctx);
4547}
4548
4549#define translate_table(ctx, insn, table) \
4550    translate_table_int(ctx, insn, table, ARRAY_SIZE(table))
4551
4552static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn)
4553{
4554    uint32_t opc = extract32(insn, 26, 6);
4555
4556    switch (opc) {
4557    case 0x00: /* system op */
4558        return translate_table(ctx, insn, table_system);
4559    case 0x01:
4560        return translate_table(ctx, insn, table_mem_mgmt);
4561    case 0x02:
4562        return translate_table(ctx, insn, table_arith_log);
4563    case 0x03:
4564        return translate_table(ctx, insn, table_index_mem);
4565    case 0x06:
4566        return trans_fmpyadd(ctx, insn, false);
4567    case 0x08:
4568        return trans_ldil(ctx, insn);
4569    case 0x09:
4570        return trans_copr_w(ctx, insn);
4571    case 0x0A:
4572        return trans_addil(ctx, insn);
4573    case 0x0B:
4574        return trans_copr_dw(ctx, insn);
4575    case 0x0C:
4576        return translate_table(ctx, insn, table_float_0c);
4577    case 0x0D:
4578        return trans_ldo(ctx, insn);
4579    case 0x0E:
4580        return translate_table(ctx, insn, table_float_0e);
4581
4582    case 0x10:
4583        return trans_load(ctx, insn, false, MO_UB);
4584    case 0x11:
4585        return trans_load(ctx, insn, false, MO_TEUW);
4586    case 0x12:
4587        return trans_load(ctx, insn, false, MO_TEUL);
4588    case 0x13:
4589        return trans_load(ctx, insn, true, MO_TEUL);
4590    case 0x16:
4591        return trans_fload_mod(ctx, insn);
4592    case 0x17:
4593        return trans_load_w(ctx, insn);
4594    case 0x18:
4595        return trans_store(ctx, insn, false, MO_UB);
4596    case 0x19:
4597        return trans_store(ctx, insn, false, MO_TEUW);
4598    case 0x1A:
4599        return trans_store(ctx, insn, false, MO_TEUL);
4600    case 0x1B:
4601        return trans_store(ctx, insn, true, MO_TEUL);
4602    case 0x1E:
4603        return trans_fstore_mod(ctx, insn);
4604    case 0x1F:
4605        return trans_store_w(ctx, insn);
4606
4607    case 0x20:
4608        return trans_cmpb(ctx, insn, true, false, false);
4609    case 0x21:
4610        return trans_cmpb(ctx, insn, true, true, false);
4611    case 0x22:
4612        return trans_cmpb(ctx, insn, false, false, false);
4613    case 0x23:
4614        return trans_cmpb(ctx, insn, false, true, false);
4615    case 0x24:
4616        return trans_cmpiclr(ctx, insn);
4617    case 0x25:
4618        return trans_subi(ctx, insn);
4619    case 0x26:
4620        return trans_fmpyadd(ctx, insn, true);
4621    case 0x27:
4622        return trans_cmpb(ctx, insn, true, false, true);
4623    case 0x28:
4624        return trans_addb(ctx, insn, true, false);
4625    case 0x29:
4626        return trans_addb(ctx, insn, true, true);
4627    case 0x2A:
4628        return trans_addb(ctx, insn, false, false);
4629    case 0x2B:
4630        return trans_addb(ctx, insn, false, true);
4631    case 0x2C:
4632    case 0x2D:
4633        return trans_addi(ctx, insn);
4634    case 0x2E:
4635        return translate_table(ctx, insn, table_fp_fused);
4636    case 0x2F:
4637        return trans_cmpb(ctx, insn, false, false, true);
4638
4639    case 0x30:
4640    case 0x31:
4641        return trans_bb(ctx, insn);
4642    case 0x32:
4643        return trans_movb(ctx, insn, false);
4644    case 0x33:
4645        return trans_movb(ctx, insn, true);
4646    case 0x34:
4647        return translate_table(ctx, insn, table_sh_ex);
4648    case 0x35:
4649        return translate_table(ctx, insn, table_depw);
4650    case 0x38:
4651        return trans_be(ctx, insn, false);
4652    case 0x39:
4653        return trans_be(ctx, insn, true);
4654    case 0x3A:
4655        return translate_table(ctx, insn, table_branch);
4656
4657    case 0x04: /* spopn */
4658    case 0x05: /* diag */
4659    case 0x0F: /* product specific */
4660        break;
4661
4662    case 0x07: /* unassigned */
4663    case 0x15: /* unassigned */
4664    case 0x1D: /* unassigned */
4665    case 0x37: /* unassigned */
4666        break;
4667    case 0x3F:
4668#ifndef CONFIG_USER_ONLY
4669        /* Unassigned, but use as system-halt.  */
4670        if (insn == 0xfffdead0) {
4671            return gen_hlt(ctx, 0); /* halt system */
4672        }
4673        if (insn == 0xfffdead1) {
4674            return gen_hlt(ctx, 1); /* reset system */
4675        }
4676#endif
4677        break;
4678    default:
4679        break;
4680    }
4681    return gen_illegal(ctx);
4682}
4683
4684static int hppa_tr_init_disas_context(DisasContextBase *dcbase,
4685                                      CPUState *cs, int max_insns)
4686{
4687    DisasContext *ctx = container_of(dcbase, DisasContext, base);
4688    int bound;
4689
4690    ctx->cs = cs;
4691    ctx->tb_flags = ctx->base.tb->flags;
4692
4693#ifdef CONFIG_USER_ONLY
4694    ctx->privilege = MMU_USER_IDX;
4695    ctx->mmu_idx = MMU_USER_IDX;
4696    ctx->iaoq_f = ctx->base.pc_first | MMU_USER_IDX;
4697    ctx->iaoq_b = ctx->base.tb->cs_base | MMU_USER_IDX;
4698#else
4699    ctx->privilege = (ctx->tb_flags >> TB_FLAG_PRIV_SHIFT) & 3;
4700    ctx->mmu_idx = (ctx->tb_flags & PSW_D ? ctx->privilege : MMU_PHYS_IDX);
4701
4702    /* Recover the IAOQ values from the GVA + PRIV.  */
4703    uint64_t cs_base = ctx->base.tb->cs_base;
4704    uint64_t iasq_f = cs_base & ~0xffffffffull;
4705    int32_t diff = cs_base;
4706
4707    ctx->iaoq_f = (ctx->base.pc_first & ~iasq_f) + ctx->privilege;
4708    ctx->iaoq_b = (diff ? ctx->iaoq_f + diff : -1);
4709#endif
4710    ctx->iaoq_n = -1;
4711    ctx->iaoq_n_var = NULL;
4712
4713    /* Bound the number of instructions by those left on the page.  */
4714    bound = -(ctx->base.pc_first | TARGET_PAGE_MASK) / 4;
4715    bound = MIN(max_insns, bound);
4716
4717    ctx->ntempr = 0;
4718    ctx->ntempl = 0;
4719    memset(ctx->tempr, 0, sizeof(ctx->tempr));
4720    memset(ctx->templ, 0, sizeof(ctx->templ));
4721
4722    return bound;
4723}
4724
4725static void hppa_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
4726{
4727    DisasContext *ctx = container_of(dcbase, DisasContext, base);
4728
4729    /* Seed the nullification status from PSW[N], as saved in TB->FLAGS.  */
4730    ctx->null_cond = cond_make_f();
4731    ctx->psw_n_nonzero = false;
4732    if (ctx->tb_flags & PSW_N) {
4733        ctx->null_cond.c = TCG_COND_ALWAYS;
4734        ctx->psw_n_nonzero = true;
4735    }
4736    ctx->null_lab = NULL;
4737}
4738
4739static void hppa_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
4740{
4741    DisasContext *ctx = container_of(dcbase, DisasContext, base);
4742
4743    tcg_gen_insn_start(ctx->iaoq_f, ctx->iaoq_b);
4744}
4745
4746static bool hppa_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
4747                                      const CPUBreakpoint *bp)
4748{
4749    DisasContext *ctx = container_of(dcbase, DisasContext, base);
4750
4751    ctx->base.is_jmp = gen_excp(ctx, EXCP_DEBUG);
4752    ctx->base.pc_next += 4;
4753    return true;
4754}
4755
4756static void hppa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
4757{
4758    DisasContext *ctx = container_of(dcbase, DisasContext, base);
4759    CPUHPPAState *env = cs->env_ptr;
4760    DisasJumpType ret;
4761    int i, n;
4762
4763    /* Execute one insn.  */
4764#ifdef CONFIG_USER_ONLY
4765    if (ctx->base.pc_next < TARGET_PAGE_SIZE) {
4766        ret = do_page_zero(ctx);
4767        assert(ret != DISAS_NEXT);
4768    } else
4769#endif
4770    {
4771        /* Always fetch the insn, even if nullified, so that we check
4772           the page permissions for execute.  */
4773        uint32_t insn = cpu_ldl_code(env, ctx->base.pc_next);
4774
4775        /* Set up the IA queue for the next insn.
4776           This will be overwritten by a branch.  */
4777        if (ctx->iaoq_b == -1) {
4778            ctx->iaoq_n = -1;
4779            ctx->iaoq_n_var = get_temp(ctx);
4780            tcg_gen_addi_reg(ctx->iaoq_n_var, cpu_iaoq_b, 4);
4781        } else {
4782            ctx->iaoq_n = ctx->iaoq_b + 4;
4783            ctx->iaoq_n_var = NULL;
4784        }
4785
4786        if (unlikely(ctx->null_cond.c == TCG_COND_ALWAYS)) {
4787            ctx->null_cond.c = TCG_COND_NEVER;
4788            ret = DISAS_NEXT;
4789        } else {
4790            ctx->insn = insn;
4791            ret = translate_one(ctx, insn);
4792            assert(ctx->null_lab == NULL);
4793        }
4794    }
4795
4796    /* Free any temporaries allocated.  */
4797    for (i = 0, n = ctx->ntempr; i < n; ++i) {
4798        tcg_temp_free(ctx->tempr[i]);
4799        ctx->tempr[i] = NULL;
4800    }
4801    for (i = 0, n = ctx->ntempl; i < n; ++i) {
4802        tcg_temp_free_tl(ctx->templ[i]);
4803        ctx->templ[i] = NULL;
4804    }
4805    ctx->ntempr = 0;
4806    ctx->ntempl = 0;
4807
4808    /* Advance the insn queue.  Note that this check also detects
4809       a priority change within the instruction queue.  */
4810    if (ret == DISAS_NEXT && ctx->iaoq_b != ctx->iaoq_f + 4) {
4811        if (ctx->iaoq_b != -1 && ctx->iaoq_n != -1
4812            && use_goto_tb(ctx, ctx->iaoq_b)
4813            && (ctx->null_cond.c == TCG_COND_NEVER
4814                || ctx->null_cond.c == TCG_COND_ALWAYS)) {
4815            nullify_set(ctx, ctx->null_cond.c == TCG_COND_ALWAYS);
4816            gen_goto_tb(ctx, 0, ctx->iaoq_b, ctx->iaoq_n);
4817            ret = DISAS_NORETURN;
4818        } else {
4819            ret = DISAS_IAQ_N_STALE;
4820        }
4821    }
4822    ctx->iaoq_f = ctx->iaoq_b;
4823    ctx->iaoq_b = ctx->iaoq_n;
4824    ctx->base.is_jmp = ret;
4825    ctx->base.pc_next += 4;
4826
4827    if (ret == DISAS_NORETURN || ret == DISAS_IAQ_N_UPDATED) {
4828        return;
4829    }
4830    if (ctx->iaoq_f == -1) {
4831        tcg_gen_mov_reg(cpu_iaoq_f, cpu_iaoq_b);
4832        copy_iaoq_entry(cpu_iaoq_b, ctx->iaoq_n, ctx->iaoq_n_var);
4833#ifndef CONFIG_USER_ONLY
4834        tcg_gen_mov_i64(cpu_iasq_f, cpu_iasq_b);
4835#endif
4836        nullify_save(ctx);
4837        ctx->base.is_jmp = DISAS_IAQ_N_UPDATED;
4838    } else if (ctx->iaoq_b == -1) {
4839        tcg_gen_mov_reg(cpu_iaoq_b, ctx->iaoq_n_var);
4840    }
4841}
4842
4843static void hppa_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
4844{
4845    DisasContext *ctx = container_of(dcbase, DisasContext, base);
4846    DisasJumpType is_jmp = ctx->base.is_jmp;
4847
4848    switch (is_jmp) {
4849    case DISAS_NORETURN:
4850        break;
4851    case DISAS_TOO_MANY:
4852    case DISAS_IAQ_N_STALE:
4853    case DISAS_IAQ_N_STALE_EXIT:
4854        copy_iaoq_entry(cpu_iaoq_f, ctx->iaoq_f, cpu_iaoq_f);
4855        copy_iaoq_entry(cpu_iaoq_b, ctx->iaoq_b, cpu_iaoq_b);
4856        nullify_save(ctx);
4857        /* FALLTHRU */
4858    case DISAS_IAQ_N_UPDATED:
4859        if (ctx->base.singlestep_enabled) {
4860            gen_excp_1(EXCP_DEBUG);
4861        } else if (is_jmp == DISAS_IAQ_N_STALE_EXIT) {
4862            tcg_gen_exit_tb(0);
4863        } else {
4864            tcg_gen_lookup_and_goto_ptr();
4865        }
4866        break;
4867    default:
4868        g_assert_not_reached();
4869    }
4870}
4871
4872static void hppa_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
4873{
4874    target_ulong pc = dcbase->pc_first;
4875
4876#ifdef CONFIG_USER_ONLY
4877    switch (pc) {
4878    case 0x00:
4879        qemu_log("IN:\n0x00000000:  (null)\n");
4880        return;
4881    case 0xb0:
4882        qemu_log("IN:\n0x000000b0:  light-weight-syscall\n");
4883        return;
4884    case 0xe0:
4885        qemu_log("IN:\n0x000000e0:  set-thread-pointer-syscall\n");
4886        return;
4887    case 0x100:
4888        qemu_log("IN:\n0x00000100:  syscall\n");
4889        return;
4890    }
4891#endif
4892
4893    qemu_log("IN: %s\n", lookup_symbol(pc));
4894    log_target_disas(cs, pc, dcbase->tb->size);
4895}
4896
4897static const TranslatorOps hppa_tr_ops = {
4898    .init_disas_context = hppa_tr_init_disas_context,
4899    .tb_start           = hppa_tr_tb_start,
4900    .insn_start         = hppa_tr_insn_start,
4901    .breakpoint_check   = hppa_tr_breakpoint_check,
4902    .translate_insn     = hppa_tr_translate_insn,
4903    .tb_stop            = hppa_tr_tb_stop,
4904    .disas_log          = hppa_tr_disas_log,
4905};
4906
4907void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
4908
4909{
4910    DisasContext ctx;
4911    translator_loop(&hppa_tr_ops, &ctx.base, cs, tb);
4912}
4913
4914void restore_state_to_opc(CPUHPPAState *env, TranslationBlock *tb,
4915                          target_ulong *data)
4916{
4917    env->iaoq_f = data[0];
4918    if (data[1] != (target_ureg)-1) {
4919        env->iaoq_b = data[1];
4920    }
4921    /* Since we were executing the instruction at IAOQ_F, and took some
4922       sort of action that provoked the cpu_restore_state, we can infer
4923       that the instruction was not nullified.  */
4924    env->psw_n = 0;
4925}
4926