161766fe9SRichard Henderson /* 261766fe9SRichard Henderson * HPPA emulation cpu translation for qemu. 361766fe9SRichard Henderson * 461766fe9SRichard Henderson * Copyright (c) 2016 Richard Henderson <rth@twiddle.net> 561766fe9SRichard Henderson * 661766fe9SRichard Henderson * This library is free software; you can redistribute it and/or 761766fe9SRichard Henderson * modify it under the terms of the GNU Lesser General Public 861766fe9SRichard Henderson * License as published by the Free Software Foundation; either 961766fe9SRichard Henderson * version 2 of the License, or (at your option) any later version. 1061766fe9SRichard Henderson * 1161766fe9SRichard Henderson * This library is distributed in the hope that it will be useful, 1261766fe9SRichard Henderson * but WITHOUT ANY WARRANTY; without even the implied warranty of 1361766fe9SRichard Henderson * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1461766fe9SRichard Henderson * Lesser General Public License for more details. 1561766fe9SRichard Henderson * 1661766fe9SRichard Henderson * You should have received a copy of the GNU Lesser General Public 1761766fe9SRichard Henderson * License along with this library; if not, see <http://www.gnu.org/licenses/>. 1861766fe9SRichard Henderson */ 1961766fe9SRichard Henderson 2061766fe9SRichard Henderson #include "qemu/osdep.h" 2161766fe9SRichard Henderson #include "cpu.h" 2261766fe9SRichard Henderson #include "disas/disas.h" 2361766fe9SRichard Henderson #include "qemu/host-utils.h" 2461766fe9SRichard Henderson #include "exec/exec-all.h" 2561766fe9SRichard Henderson #include "tcg-op.h" 2661766fe9SRichard Henderson #include "exec/cpu_ldst.h" 2761766fe9SRichard Henderson #include "exec/helper-proto.h" 2861766fe9SRichard Henderson #include "exec/helper-gen.h" 29869051eaSRichard Henderson #include "exec/translator.h" 3061766fe9SRichard Henderson #include "trace-tcg.h" 3161766fe9SRichard Henderson #include "exec/log.h" 3261766fe9SRichard Henderson 33eaa3783bSRichard Henderson /* Since we have a distinction between register size and address size, 34eaa3783bSRichard Henderson we need to redefine all of these. */ 35eaa3783bSRichard Henderson 36eaa3783bSRichard Henderson #undef TCGv 37eaa3783bSRichard Henderson #undef tcg_temp_new 38eaa3783bSRichard Henderson #undef tcg_global_reg_new 39eaa3783bSRichard Henderson #undef tcg_global_mem_new 40eaa3783bSRichard Henderson #undef tcg_temp_local_new 41eaa3783bSRichard Henderson #undef tcg_temp_free 42eaa3783bSRichard Henderson 43eaa3783bSRichard Henderson #if TARGET_LONG_BITS == 64 44eaa3783bSRichard Henderson #define TCGv_tl TCGv_i64 45eaa3783bSRichard Henderson #define tcg_temp_new_tl tcg_temp_new_i64 46eaa3783bSRichard Henderson #define tcg_temp_free_tl tcg_temp_free_i64 47eaa3783bSRichard Henderson #if TARGET_REGISTER_BITS == 64 48eaa3783bSRichard Henderson #define tcg_gen_extu_reg_tl tcg_gen_mov_i64 49eaa3783bSRichard Henderson #else 50eaa3783bSRichard Henderson #define tcg_gen_extu_reg_tl tcg_gen_extu_i32_i64 51eaa3783bSRichard Henderson #endif 52eaa3783bSRichard Henderson #else 53eaa3783bSRichard Henderson #define TCGv_tl TCGv_i32 54eaa3783bSRichard Henderson #define tcg_temp_new_tl tcg_temp_new_i32 55eaa3783bSRichard Henderson #define tcg_temp_free_tl tcg_temp_free_i32 56eaa3783bSRichard Henderson #define tcg_gen_extu_reg_tl tcg_gen_mov_i32 57eaa3783bSRichard Henderson #endif 58eaa3783bSRichard Henderson 59eaa3783bSRichard Henderson #if TARGET_REGISTER_BITS == 64 60eaa3783bSRichard Henderson #define TCGv_reg TCGv_i64 61eaa3783bSRichard Henderson 62eaa3783bSRichard Henderson #define tcg_temp_new tcg_temp_new_i64 63eaa3783bSRichard Henderson #define tcg_global_reg_new tcg_global_reg_new_i64 64eaa3783bSRichard Henderson #define tcg_global_mem_new tcg_global_mem_new_i64 65eaa3783bSRichard Henderson #define tcg_temp_local_new tcg_temp_local_new_i64 66eaa3783bSRichard Henderson #define tcg_temp_free tcg_temp_free_i64 67eaa3783bSRichard Henderson 68eaa3783bSRichard Henderson #define tcg_gen_movi_reg tcg_gen_movi_i64 69eaa3783bSRichard Henderson #define tcg_gen_mov_reg tcg_gen_mov_i64 70eaa3783bSRichard Henderson #define tcg_gen_ld8u_reg tcg_gen_ld8u_i64 71eaa3783bSRichard Henderson #define tcg_gen_ld8s_reg tcg_gen_ld8s_i64 72eaa3783bSRichard Henderson #define tcg_gen_ld16u_reg tcg_gen_ld16u_i64 73eaa3783bSRichard Henderson #define tcg_gen_ld16s_reg tcg_gen_ld16s_i64 74eaa3783bSRichard Henderson #define tcg_gen_ld32u_reg tcg_gen_ld32u_i64 75eaa3783bSRichard Henderson #define tcg_gen_ld32s_reg tcg_gen_ld32s_i64 76eaa3783bSRichard Henderson #define tcg_gen_ld_reg tcg_gen_ld_i64 77eaa3783bSRichard Henderson #define tcg_gen_st8_reg tcg_gen_st8_i64 78eaa3783bSRichard Henderson #define tcg_gen_st16_reg tcg_gen_st16_i64 79eaa3783bSRichard Henderson #define tcg_gen_st32_reg tcg_gen_st32_i64 80eaa3783bSRichard Henderson #define tcg_gen_st_reg tcg_gen_st_i64 81eaa3783bSRichard Henderson #define tcg_gen_add_reg tcg_gen_add_i64 82eaa3783bSRichard Henderson #define tcg_gen_addi_reg tcg_gen_addi_i64 83eaa3783bSRichard Henderson #define tcg_gen_sub_reg tcg_gen_sub_i64 84eaa3783bSRichard Henderson #define tcg_gen_neg_reg tcg_gen_neg_i64 85eaa3783bSRichard Henderson #define tcg_gen_subfi_reg tcg_gen_subfi_i64 86eaa3783bSRichard Henderson #define tcg_gen_subi_reg tcg_gen_subi_i64 87eaa3783bSRichard Henderson #define tcg_gen_and_reg tcg_gen_and_i64 88eaa3783bSRichard Henderson #define tcg_gen_andi_reg tcg_gen_andi_i64 89eaa3783bSRichard Henderson #define tcg_gen_or_reg tcg_gen_or_i64 90eaa3783bSRichard Henderson #define tcg_gen_ori_reg tcg_gen_ori_i64 91eaa3783bSRichard Henderson #define tcg_gen_xor_reg tcg_gen_xor_i64 92eaa3783bSRichard Henderson #define tcg_gen_xori_reg tcg_gen_xori_i64 93eaa3783bSRichard Henderson #define tcg_gen_not_reg tcg_gen_not_i64 94eaa3783bSRichard Henderson #define tcg_gen_shl_reg tcg_gen_shl_i64 95eaa3783bSRichard Henderson #define tcg_gen_shli_reg tcg_gen_shli_i64 96eaa3783bSRichard Henderson #define tcg_gen_shr_reg tcg_gen_shr_i64 97eaa3783bSRichard Henderson #define tcg_gen_shri_reg tcg_gen_shri_i64 98eaa3783bSRichard Henderson #define tcg_gen_sar_reg tcg_gen_sar_i64 99eaa3783bSRichard Henderson #define tcg_gen_sari_reg tcg_gen_sari_i64 100eaa3783bSRichard Henderson #define tcg_gen_brcond_reg tcg_gen_brcond_i64 101eaa3783bSRichard Henderson #define tcg_gen_brcondi_reg tcg_gen_brcondi_i64 102eaa3783bSRichard Henderson #define tcg_gen_setcond_reg tcg_gen_setcond_i64 103eaa3783bSRichard Henderson #define tcg_gen_setcondi_reg tcg_gen_setcondi_i64 104eaa3783bSRichard Henderson #define tcg_gen_mul_reg tcg_gen_mul_i64 105eaa3783bSRichard Henderson #define tcg_gen_muli_reg tcg_gen_muli_i64 106eaa3783bSRichard Henderson #define tcg_gen_div_reg tcg_gen_div_i64 107eaa3783bSRichard Henderson #define tcg_gen_rem_reg tcg_gen_rem_i64 108eaa3783bSRichard Henderson #define tcg_gen_divu_reg tcg_gen_divu_i64 109eaa3783bSRichard Henderson #define tcg_gen_remu_reg tcg_gen_remu_i64 110eaa3783bSRichard Henderson #define tcg_gen_discard_reg tcg_gen_discard_i64 111eaa3783bSRichard Henderson #define tcg_gen_trunc_reg_i32 tcg_gen_extrl_i64_i32 112eaa3783bSRichard Henderson #define tcg_gen_trunc_i64_reg tcg_gen_mov_i64 113eaa3783bSRichard Henderson #define tcg_gen_extu_i32_reg tcg_gen_extu_i32_i64 114eaa3783bSRichard Henderson #define tcg_gen_ext_i32_reg tcg_gen_ext_i32_i64 115eaa3783bSRichard Henderson #define tcg_gen_extu_reg_i64 tcg_gen_mov_i64 116eaa3783bSRichard Henderson #define tcg_gen_ext_reg_i64 tcg_gen_mov_i64 117eaa3783bSRichard Henderson #define tcg_gen_ext8u_reg tcg_gen_ext8u_i64 118eaa3783bSRichard Henderson #define tcg_gen_ext8s_reg tcg_gen_ext8s_i64 119eaa3783bSRichard Henderson #define tcg_gen_ext16u_reg tcg_gen_ext16u_i64 120eaa3783bSRichard Henderson #define tcg_gen_ext16s_reg tcg_gen_ext16s_i64 121eaa3783bSRichard Henderson #define tcg_gen_ext32u_reg tcg_gen_ext32u_i64 122eaa3783bSRichard Henderson #define tcg_gen_ext32s_reg tcg_gen_ext32s_i64 123eaa3783bSRichard Henderson #define tcg_gen_bswap16_reg tcg_gen_bswap16_i64 124eaa3783bSRichard Henderson #define tcg_gen_bswap32_reg tcg_gen_bswap32_i64 125eaa3783bSRichard Henderson #define tcg_gen_bswap64_reg tcg_gen_bswap64_i64 126eaa3783bSRichard Henderson #define tcg_gen_concat_reg_i64 tcg_gen_concat32_i64 127eaa3783bSRichard Henderson #define tcg_gen_andc_reg tcg_gen_andc_i64 128eaa3783bSRichard Henderson #define tcg_gen_eqv_reg tcg_gen_eqv_i64 129eaa3783bSRichard Henderson #define tcg_gen_nand_reg tcg_gen_nand_i64 130eaa3783bSRichard Henderson #define tcg_gen_nor_reg tcg_gen_nor_i64 131eaa3783bSRichard Henderson #define tcg_gen_orc_reg tcg_gen_orc_i64 132eaa3783bSRichard Henderson #define tcg_gen_clz_reg tcg_gen_clz_i64 133eaa3783bSRichard Henderson #define tcg_gen_ctz_reg tcg_gen_ctz_i64 134eaa3783bSRichard Henderson #define tcg_gen_clzi_reg tcg_gen_clzi_i64 135eaa3783bSRichard Henderson #define tcg_gen_ctzi_reg tcg_gen_ctzi_i64 136eaa3783bSRichard Henderson #define tcg_gen_clrsb_reg tcg_gen_clrsb_i64 137eaa3783bSRichard Henderson #define tcg_gen_ctpop_reg tcg_gen_ctpop_i64 138eaa3783bSRichard Henderson #define tcg_gen_rotl_reg tcg_gen_rotl_i64 139eaa3783bSRichard Henderson #define tcg_gen_rotli_reg tcg_gen_rotli_i64 140eaa3783bSRichard Henderson #define tcg_gen_rotr_reg tcg_gen_rotr_i64 141eaa3783bSRichard Henderson #define tcg_gen_rotri_reg tcg_gen_rotri_i64 142eaa3783bSRichard Henderson #define tcg_gen_deposit_reg tcg_gen_deposit_i64 143eaa3783bSRichard Henderson #define tcg_gen_deposit_z_reg tcg_gen_deposit_z_i64 144eaa3783bSRichard Henderson #define tcg_gen_extract_reg tcg_gen_extract_i64 145eaa3783bSRichard Henderson #define tcg_gen_sextract_reg tcg_gen_sextract_i64 146eaa3783bSRichard Henderson #define tcg_const_reg tcg_const_i64 147eaa3783bSRichard Henderson #define tcg_const_local_reg tcg_const_local_i64 148eaa3783bSRichard Henderson #define tcg_gen_movcond_reg tcg_gen_movcond_i64 149eaa3783bSRichard Henderson #define tcg_gen_add2_reg tcg_gen_add2_i64 150eaa3783bSRichard Henderson #define tcg_gen_sub2_reg tcg_gen_sub2_i64 151eaa3783bSRichard Henderson #define tcg_gen_qemu_ld_reg tcg_gen_qemu_ld_i64 152eaa3783bSRichard Henderson #define tcg_gen_qemu_st_reg tcg_gen_qemu_st_i64 153eaa3783bSRichard Henderson #define tcg_gen_atomic_xchg_reg tcg_gen_atomic_xchg_i64 154eaa3783bSRichard Henderson #if UINTPTR_MAX == UINT32_MAX 155eaa3783bSRichard Henderson # define tcg_gen_trunc_reg_ptr(p, r) \ 156eaa3783bSRichard Henderson tcg_gen_trunc_i64_i32(TCGV_PTR_TO_NAT(p), r) 157eaa3783bSRichard Henderson #else 158eaa3783bSRichard Henderson # define tcg_gen_trunc_reg_ptr(p, r) \ 159eaa3783bSRichard Henderson tcg_gen_mov_i64(TCGV_PTR_TO_NAT(p), r) 160eaa3783bSRichard Henderson #endif 161eaa3783bSRichard Henderson #else 162eaa3783bSRichard Henderson #define TCGv_reg TCGv_i32 163eaa3783bSRichard Henderson #define tcg_temp_new tcg_temp_new_i32 164eaa3783bSRichard Henderson #define tcg_global_reg_new tcg_global_reg_new_i32 165eaa3783bSRichard Henderson #define tcg_global_mem_new tcg_global_mem_new_i32 166eaa3783bSRichard Henderson #define tcg_temp_local_new tcg_temp_local_new_i32 167eaa3783bSRichard Henderson #define tcg_temp_free tcg_temp_free_i32 168eaa3783bSRichard Henderson 169eaa3783bSRichard Henderson #define tcg_gen_movi_reg tcg_gen_movi_i32 170eaa3783bSRichard Henderson #define tcg_gen_mov_reg tcg_gen_mov_i32 171eaa3783bSRichard Henderson #define tcg_gen_ld8u_reg tcg_gen_ld8u_i32 172eaa3783bSRichard Henderson #define tcg_gen_ld8s_reg tcg_gen_ld8s_i32 173eaa3783bSRichard Henderson #define tcg_gen_ld16u_reg tcg_gen_ld16u_i32 174eaa3783bSRichard Henderson #define tcg_gen_ld16s_reg tcg_gen_ld16s_i32 175eaa3783bSRichard Henderson #define tcg_gen_ld32u_reg tcg_gen_ld_i32 176eaa3783bSRichard Henderson #define tcg_gen_ld32s_reg tcg_gen_ld_i32 177eaa3783bSRichard Henderson #define tcg_gen_ld_reg tcg_gen_ld_i32 178eaa3783bSRichard Henderson #define tcg_gen_st8_reg tcg_gen_st8_i32 179eaa3783bSRichard Henderson #define tcg_gen_st16_reg tcg_gen_st16_i32 180eaa3783bSRichard Henderson #define tcg_gen_st32_reg tcg_gen_st32_i32 181eaa3783bSRichard Henderson #define tcg_gen_st_reg tcg_gen_st_i32 182eaa3783bSRichard Henderson #define tcg_gen_add_reg tcg_gen_add_i32 183eaa3783bSRichard Henderson #define tcg_gen_addi_reg tcg_gen_addi_i32 184eaa3783bSRichard Henderson #define tcg_gen_sub_reg tcg_gen_sub_i32 185eaa3783bSRichard Henderson #define tcg_gen_neg_reg tcg_gen_neg_i32 186eaa3783bSRichard Henderson #define tcg_gen_subfi_reg tcg_gen_subfi_i32 187eaa3783bSRichard Henderson #define tcg_gen_subi_reg tcg_gen_subi_i32 188eaa3783bSRichard Henderson #define tcg_gen_and_reg tcg_gen_and_i32 189eaa3783bSRichard Henderson #define tcg_gen_andi_reg tcg_gen_andi_i32 190eaa3783bSRichard Henderson #define tcg_gen_or_reg tcg_gen_or_i32 191eaa3783bSRichard Henderson #define tcg_gen_ori_reg tcg_gen_ori_i32 192eaa3783bSRichard Henderson #define tcg_gen_xor_reg tcg_gen_xor_i32 193eaa3783bSRichard Henderson #define tcg_gen_xori_reg tcg_gen_xori_i32 194eaa3783bSRichard Henderson #define tcg_gen_not_reg tcg_gen_not_i32 195eaa3783bSRichard Henderson #define tcg_gen_shl_reg tcg_gen_shl_i32 196eaa3783bSRichard Henderson #define tcg_gen_shli_reg tcg_gen_shli_i32 197eaa3783bSRichard Henderson #define tcg_gen_shr_reg tcg_gen_shr_i32 198eaa3783bSRichard Henderson #define tcg_gen_shri_reg tcg_gen_shri_i32 199eaa3783bSRichard Henderson #define tcg_gen_sar_reg tcg_gen_sar_i32 200eaa3783bSRichard Henderson #define tcg_gen_sari_reg tcg_gen_sari_i32 201eaa3783bSRichard Henderson #define tcg_gen_brcond_reg tcg_gen_brcond_i32 202eaa3783bSRichard Henderson #define tcg_gen_brcondi_reg tcg_gen_brcondi_i32 203eaa3783bSRichard Henderson #define tcg_gen_setcond_reg tcg_gen_setcond_i32 204eaa3783bSRichard Henderson #define tcg_gen_setcondi_reg tcg_gen_setcondi_i32 205eaa3783bSRichard Henderson #define tcg_gen_mul_reg tcg_gen_mul_i32 206eaa3783bSRichard Henderson #define tcg_gen_muli_reg tcg_gen_muli_i32 207eaa3783bSRichard Henderson #define tcg_gen_div_reg tcg_gen_div_i32 208eaa3783bSRichard Henderson #define tcg_gen_rem_reg tcg_gen_rem_i32 209eaa3783bSRichard Henderson #define tcg_gen_divu_reg tcg_gen_divu_i32 210eaa3783bSRichard Henderson #define tcg_gen_remu_reg tcg_gen_remu_i32 211eaa3783bSRichard Henderson #define tcg_gen_discard_reg tcg_gen_discard_i32 212eaa3783bSRichard Henderson #define tcg_gen_trunc_reg_i32 tcg_gen_mov_i32 213eaa3783bSRichard Henderson #define tcg_gen_trunc_i64_reg tcg_gen_extrl_i64_i32 214eaa3783bSRichard Henderson #define tcg_gen_extu_i32_reg tcg_gen_mov_i32 215eaa3783bSRichard Henderson #define tcg_gen_ext_i32_reg tcg_gen_mov_i32 216eaa3783bSRichard Henderson #define tcg_gen_extu_reg_i64 tcg_gen_extu_i32_i64 217eaa3783bSRichard Henderson #define tcg_gen_ext_reg_i64 tcg_gen_ext_i32_i64 218eaa3783bSRichard Henderson #define tcg_gen_ext8u_reg tcg_gen_ext8u_i32 219eaa3783bSRichard Henderson #define tcg_gen_ext8s_reg tcg_gen_ext8s_i32 220eaa3783bSRichard Henderson #define tcg_gen_ext16u_reg tcg_gen_ext16u_i32 221eaa3783bSRichard Henderson #define tcg_gen_ext16s_reg tcg_gen_ext16s_i32 222eaa3783bSRichard Henderson #define tcg_gen_ext32u_reg tcg_gen_mov_i32 223eaa3783bSRichard Henderson #define tcg_gen_ext32s_reg tcg_gen_mov_i32 224eaa3783bSRichard Henderson #define tcg_gen_bswap16_reg tcg_gen_bswap16_i32 225eaa3783bSRichard Henderson #define tcg_gen_bswap32_reg tcg_gen_bswap32_i32 226eaa3783bSRichard Henderson #define tcg_gen_concat_reg_i64 tcg_gen_concat_i32_i64 227eaa3783bSRichard Henderson #define tcg_gen_andc_reg tcg_gen_andc_i32 228eaa3783bSRichard Henderson #define tcg_gen_eqv_reg tcg_gen_eqv_i32 229eaa3783bSRichard Henderson #define tcg_gen_nand_reg tcg_gen_nand_i32 230eaa3783bSRichard Henderson #define tcg_gen_nor_reg tcg_gen_nor_i32 231eaa3783bSRichard Henderson #define tcg_gen_orc_reg tcg_gen_orc_i32 232eaa3783bSRichard Henderson #define tcg_gen_clz_reg tcg_gen_clz_i32 233eaa3783bSRichard Henderson #define tcg_gen_ctz_reg tcg_gen_ctz_i32 234eaa3783bSRichard Henderson #define tcg_gen_clzi_reg tcg_gen_clzi_i32 235eaa3783bSRichard Henderson #define tcg_gen_ctzi_reg tcg_gen_ctzi_i32 236eaa3783bSRichard Henderson #define tcg_gen_clrsb_reg tcg_gen_clrsb_i32 237eaa3783bSRichard Henderson #define tcg_gen_ctpop_reg tcg_gen_ctpop_i32 238eaa3783bSRichard Henderson #define tcg_gen_rotl_reg tcg_gen_rotl_i32 239eaa3783bSRichard Henderson #define tcg_gen_rotli_reg tcg_gen_rotli_i32 240eaa3783bSRichard Henderson #define tcg_gen_rotr_reg tcg_gen_rotr_i32 241eaa3783bSRichard Henderson #define tcg_gen_rotri_reg tcg_gen_rotri_i32 242eaa3783bSRichard Henderson #define tcg_gen_deposit_reg tcg_gen_deposit_i32 243eaa3783bSRichard Henderson #define tcg_gen_deposit_z_reg tcg_gen_deposit_z_i32 244eaa3783bSRichard Henderson #define tcg_gen_extract_reg tcg_gen_extract_i32 245eaa3783bSRichard Henderson #define tcg_gen_sextract_reg tcg_gen_sextract_i32 246eaa3783bSRichard Henderson #define tcg_const_reg tcg_const_i32 247eaa3783bSRichard Henderson #define tcg_const_local_reg tcg_const_local_i32 248eaa3783bSRichard Henderson #define tcg_gen_movcond_reg tcg_gen_movcond_i32 249eaa3783bSRichard Henderson #define tcg_gen_add2_reg tcg_gen_add2_i32 250eaa3783bSRichard Henderson #define tcg_gen_sub2_reg tcg_gen_sub2_i32 251eaa3783bSRichard Henderson #define tcg_gen_qemu_ld_reg tcg_gen_qemu_ld_i32 252eaa3783bSRichard Henderson #define tcg_gen_qemu_st_reg tcg_gen_qemu_st_i32 253eaa3783bSRichard Henderson #define tcg_gen_atomic_xchg_reg tcg_gen_atomic_xchg_i32 254eaa3783bSRichard Henderson #if UINTPTR_MAX == UINT32_MAX 255eaa3783bSRichard Henderson # define tcg_gen_trunc_reg_ptr(p, r) \ 256eaa3783bSRichard Henderson tcg_gen_mov_i32(TCGV_PTR_TO_NAT(p), r) 257eaa3783bSRichard Henderson #else 258eaa3783bSRichard Henderson # define tcg_gen_trunc_reg_ptr(p, r) \ 259eaa3783bSRichard Henderson tcg_gen_extu_i32_i64(TCGV_PTR_TO_NAT(p), r) 260eaa3783bSRichard Henderson #endif 261eaa3783bSRichard Henderson #endif /* TARGET_REGISTER_BITS */ 262eaa3783bSRichard Henderson 26361766fe9SRichard Henderson typedef struct DisasCond { 26461766fe9SRichard Henderson TCGCond c; 265eaa3783bSRichard Henderson TCGv_reg a0, a1; 26661766fe9SRichard Henderson bool a0_is_n; 26761766fe9SRichard Henderson bool a1_is_0; 26861766fe9SRichard Henderson } DisasCond; 26961766fe9SRichard Henderson 27061766fe9SRichard Henderson typedef struct DisasContext { 271d01a3625SRichard Henderson DisasContextBase base; 27261766fe9SRichard Henderson CPUState *cs; 27361766fe9SRichard Henderson 274eaa3783bSRichard Henderson target_ureg iaoq_f; 275eaa3783bSRichard Henderson target_ureg iaoq_b; 276eaa3783bSRichard Henderson target_ureg iaoq_n; 277eaa3783bSRichard Henderson TCGv_reg iaoq_n_var; 27861766fe9SRichard Henderson 27961766fe9SRichard Henderson int ntemps; 280eaa3783bSRichard Henderson TCGv_reg temps[8]; 28161766fe9SRichard Henderson 28261766fe9SRichard Henderson DisasCond null_cond; 28361766fe9SRichard Henderson TCGLabel *null_lab; 28461766fe9SRichard Henderson 285*3d68ee7bSRichard Henderson int mmu_idx; 286*3d68ee7bSRichard Henderson int privilege; 28761766fe9SRichard Henderson bool psw_n_nonzero; 28861766fe9SRichard Henderson } DisasContext; 28961766fe9SRichard Henderson 290869051eaSRichard Henderson /* Target-specific return values from translate_one, indicating the 291869051eaSRichard Henderson state of the TB. Note that DISAS_NEXT indicates that we are not 292869051eaSRichard Henderson exiting the TB. */ 29361766fe9SRichard Henderson 29461766fe9SRichard Henderson /* We are not using a goto_tb (for whatever reason), but have updated 29561766fe9SRichard Henderson the iaq (for whatever reason), so don't do it again on exit. */ 296869051eaSRichard Henderson #define DISAS_IAQ_N_UPDATED DISAS_TARGET_0 29761766fe9SRichard Henderson 29861766fe9SRichard Henderson /* We are exiting the TB, but have neither emitted a goto_tb, nor 29961766fe9SRichard Henderson updated the iaq for the next instruction to be executed. */ 300869051eaSRichard Henderson #define DISAS_IAQ_N_STALE DISAS_TARGET_1 30161766fe9SRichard Henderson 30261766fe9SRichard Henderson typedef struct DisasInsn { 30361766fe9SRichard Henderson uint32_t insn, mask; 304869051eaSRichard Henderson DisasJumpType (*trans)(DisasContext *ctx, uint32_t insn, 30561766fe9SRichard Henderson const struct DisasInsn *f); 306b2167459SRichard Henderson union { 307eaa3783bSRichard Henderson void (*ttt)(TCGv_reg, TCGv_reg, TCGv_reg); 308eff235ebSPaolo Bonzini void (*weww)(TCGv_i32, TCGv_env, TCGv_i32, TCGv_i32); 309eff235ebSPaolo Bonzini void (*dedd)(TCGv_i64, TCGv_env, TCGv_i64, TCGv_i64); 310eff235ebSPaolo Bonzini void (*wew)(TCGv_i32, TCGv_env, TCGv_i32); 311eff235ebSPaolo Bonzini void (*ded)(TCGv_i64, TCGv_env, TCGv_i64); 312eff235ebSPaolo Bonzini void (*wed)(TCGv_i32, TCGv_env, TCGv_i64); 313eff235ebSPaolo Bonzini void (*dew)(TCGv_i64, TCGv_env, TCGv_i32); 314eff235ebSPaolo Bonzini } f; 31561766fe9SRichard Henderson } DisasInsn; 31661766fe9SRichard Henderson 31761766fe9SRichard Henderson /* global register indexes */ 318eaa3783bSRichard Henderson static TCGv_reg cpu_gr[32]; 319eaa3783bSRichard Henderson static TCGv_reg cpu_iaoq_f; 320eaa3783bSRichard Henderson static TCGv_reg cpu_iaoq_b; 321eaa3783bSRichard Henderson static TCGv_reg cpu_sar; 322eaa3783bSRichard Henderson static TCGv_reg cpu_psw_n; 323eaa3783bSRichard Henderson static TCGv_reg cpu_psw_v; 324eaa3783bSRichard Henderson static TCGv_reg cpu_psw_cb; 325eaa3783bSRichard Henderson static TCGv_reg cpu_psw_cb_msb; 326eaa3783bSRichard Henderson static TCGv_reg cpu_cr26; 327eaa3783bSRichard Henderson static TCGv_reg cpu_cr27; 32861766fe9SRichard Henderson 32961766fe9SRichard Henderson #include "exec/gen-icount.h" 33061766fe9SRichard Henderson 33161766fe9SRichard Henderson void hppa_translate_init(void) 33261766fe9SRichard Henderson { 33361766fe9SRichard Henderson #define DEF_VAR(V) { &cpu_##V, #V, offsetof(CPUHPPAState, V) } 33461766fe9SRichard Henderson 335eaa3783bSRichard Henderson typedef struct { TCGv_reg *var; const char *name; int ofs; } GlobalVar; 33661766fe9SRichard Henderson static const GlobalVar vars[] = { 33761766fe9SRichard Henderson DEF_VAR(sar), 33861766fe9SRichard Henderson DEF_VAR(cr26), 33961766fe9SRichard Henderson DEF_VAR(cr27), 34061766fe9SRichard Henderson DEF_VAR(psw_n), 34161766fe9SRichard Henderson DEF_VAR(psw_v), 34261766fe9SRichard Henderson DEF_VAR(psw_cb), 34361766fe9SRichard Henderson DEF_VAR(psw_cb_msb), 34461766fe9SRichard Henderson DEF_VAR(iaoq_f), 34561766fe9SRichard Henderson DEF_VAR(iaoq_b), 34661766fe9SRichard Henderson }; 34761766fe9SRichard Henderson 34861766fe9SRichard Henderson #undef DEF_VAR 34961766fe9SRichard Henderson 35061766fe9SRichard Henderson /* Use the symbolic register names that match the disassembler. */ 35161766fe9SRichard Henderson static const char gr_names[32][4] = { 35261766fe9SRichard Henderson "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", 35361766fe9SRichard Henderson "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", 35461766fe9SRichard Henderson "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", 35561766fe9SRichard Henderson "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31" 35661766fe9SRichard Henderson }; 35761766fe9SRichard Henderson 35861766fe9SRichard Henderson int i; 35961766fe9SRichard Henderson 360f764718dSRichard Henderson cpu_gr[0] = NULL; 36161766fe9SRichard Henderson for (i = 1; i < 32; i++) { 36261766fe9SRichard Henderson cpu_gr[i] = tcg_global_mem_new(cpu_env, 36361766fe9SRichard Henderson offsetof(CPUHPPAState, gr[i]), 36461766fe9SRichard Henderson gr_names[i]); 36561766fe9SRichard Henderson } 36661766fe9SRichard Henderson 36761766fe9SRichard Henderson for (i = 0; i < ARRAY_SIZE(vars); ++i) { 36861766fe9SRichard Henderson const GlobalVar *v = &vars[i]; 36961766fe9SRichard Henderson *v->var = tcg_global_mem_new(cpu_env, v->ofs, v->name); 37061766fe9SRichard Henderson } 37161766fe9SRichard Henderson } 37261766fe9SRichard Henderson 373129e9cc3SRichard Henderson static DisasCond cond_make_f(void) 374129e9cc3SRichard Henderson { 375f764718dSRichard Henderson return (DisasCond){ 376f764718dSRichard Henderson .c = TCG_COND_NEVER, 377f764718dSRichard Henderson .a0 = NULL, 378f764718dSRichard Henderson .a1 = NULL, 379f764718dSRichard Henderson }; 380129e9cc3SRichard Henderson } 381129e9cc3SRichard Henderson 382129e9cc3SRichard Henderson static DisasCond cond_make_n(void) 383129e9cc3SRichard Henderson { 384f764718dSRichard Henderson return (DisasCond){ 385f764718dSRichard Henderson .c = TCG_COND_NE, 386f764718dSRichard Henderson .a0 = cpu_psw_n, 387f764718dSRichard Henderson .a0_is_n = true, 388f764718dSRichard Henderson .a1 = NULL, 389f764718dSRichard Henderson .a1_is_0 = true 390f764718dSRichard Henderson }; 391129e9cc3SRichard Henderson } 392129e9cc3SRichard Henderson 393eaa3783bSRichard Henderson static DisasCond cond_make_0(TCGCond c, TCGv_reg a0) 394129e9cc3SRichard Henderson { 395f764718dSRichard Henderson DisasCond r = { .c = c, .a1 = NULL, .a1_is_0 = true }; 396129e9cc3SRichard Henderson 397129e9cc3SRichard Henderson assert (c != TCG_COND_NEVER && c != TCG_COND_ALWAYS); 398129e9cc3SRichard Henderson r.a0 = tcg_temp_new(); 399eaa3783bSRichard Henderson tcg_gen_mov_reg(r.a0, a0); 400129e9cc3SRichard Henderson 401129e9cc3SRichard Henderson return r; 402129e9cc3SRichard Henderson } 403129e9cc3SRichard Henderson 404eaa3783bSRichard Henderson static DisasCond cond_make(TCGCond c, TCGv_reg a0, TCGv_reg a1) 405129e9cc3SRichard Henderson { 406129e9cc3SRichard Henderson DisasCond r = { .c = c }; 407129e9cc3SRichard Henderson 408129e9cc3SRichard Henderson assert (c != TCG_COND_NEVER && c != TCG_COND_ALWAYS); 409129e9cc3SRichard Henderson r.a0 = tcg_temp_new(); 410eaa3783bSRichard Henderson tcg_gen_mov_reg(r.a0, a0); 411129e9cc3SRichard Henderson r.a1 = tcg_temp_new(); 412eaa3783bSRichard Henderson tcg_gen_mov_reg(r.a1, a1); 413129e9cc3SRichard Henderson 414129e9cc3SRichard Henderson return r; 415129e9cc3SRichard Henderson } 416129e9cc3SRichard Henderson 417129e9cc3SRichard Henderson static void cond_prep(DisasCond *cond) 418129e9cc3SRichard Henderson { 419129e9cc3SRichard Henderson if (cond->a1_is_0) { 420129e9cc3SRichard Henderson cond->a1_is_0 = false; 421eaa3783bSRichard Henderson cond->a1 = tcg_const_reg(0); 422129e9cc3SRichard Henderson } 423129e9cc3SRichard Henderson } 424129e9cc3SRichard Henderson 425129e9cc3SRichard Henderson static void cond_free(DisasCond *cond) 426129e9cc3SRichard Henderson { 427129e9cc3SRichard Henderson switch (cond->c) { 428129e9cc3SRichard Henderson default: 429129e9cc3SRichard Henderson if (!cond->a0_is_n) { 430129e9cc3SRichard Henderson tcg_temp_free(cond->a0); 431129e9cc3SRichard Henderson } 432129e9cc3SRichard Henderson if (!cond->a1_is_0) { 433129e9cc3SRichard Henderson tcg_temp_free(cond->a1); 434129e9cc3SRichard Henderson } 435129e9cc3SRichard Henderson cond->a0_is_n = false; 436129e9cc3SRichard Henderson cond->a1_is_0 = false; 437f764718dSRichard Henderson cond->a0 = NULL; 438f764718dSRichard Henderson cond->a1 = NULL; 439129e9cc3SRichard Henderson /* fallthru */ 440129e9cc3SRichard Henderson case TCG_COND_ALWAYS: 441129e9cc3SRichard Henderson cond->c = TCG_COND_NEVER; 442129e9cc3SRichard Henderson break; 443129e9cc3SRichard Henderson case TCG_COND_NEVER: 444129e9cc3SRichard Henderson break; 445129e9cc3SRichard Henderson } 446129e9cc3SRichard Henderson } 447129e9cc3SRichard Henderson 448eaa3783bSRichard Henderson static TCGv_reg get_temp(DisasContext *ctx) 44961766fe9SRichard Henderson { 45061766fe9SRichard Henderson unsigned i = ctx->ntemps++; 45161766fe9SRichard Henderson g_assert(i < ARRAY_SIZE(ctx->temps)); 45261766fe9SRichard Henderson return ctx->temps[i] = tcg_temp_new(); 45361766fe9SRichard Henderson } 45461766fe9SRichard Henderson 455eaa3783bSRichard Henderson static TCGv_reg load_const(DisasContext *ctx, target_sreg v) 45661766fe9SRichard Henderson { 457eaa3783bSRichard Henderson TCGv_reg t = get_temp(ctx); 458eaa3783bSRichard Henderson tcg_gen_movi_reg(t, v); 45961766fe9SRichard Henderson return t; 46061766fe9SRichard Henderson } 46161766fe9SRichard Henderson 462eaa3783bSRichard Henderson static TCGv_reg load_gpr(DisasContext *ctx, unsigned reg) 46361766fe9SRichard Henderson { 46461766fe9SRichard Henderson if (reg == 0) { 465eaa3783bSRichard Henderson TCGv_reg t = get_temp(ctx); 466eaa3783bSRichard Henderson tcg_gen_movi_reg(t, 0); 46761766fe9SRichard Henderson return t; 46861766fe9SRichard Henderson } else { 46961766fe9SRichard Henderson return cpu_gr[reg]; 47061766fe9SRichard Henderson } 47161766fe9SRichard Henderson } 47261766fe9SRichard Henderson 473eaa3783bSRichard Henderson static TCGv_reg dest_gpr(DisasContext *ctx, unsigned reg) 47461766fe9SRichard Henderson { 475129e9cc3SRichard Henderson if (reg == 0 || ctx->null_cond.c != TCG_COND_NEVER) { 47661766fe9SRichard Henderson return get_temp(ctx); 47761766fe9SRichard Henderson } else { 47861766fe9SRichard Henderson return cpu_gr[reg]; 47961766fe9SRichard Henderson } 48061766fe9SRichard Henderson } 48161766fe9SRichard Henderson 482eaa3783bSRichard Henderson static void save_or_nullify(DisasContext *ctx, TCGv_reg dest, TCGv_reg t) 483129e9cc3SRichard Henderson { 484129e9cc3SRichard Henderson if (ctx->null_cond.c != TCG_COND_NEVER) { 485129e9cc3SRichard Henderson cond_prep(&ctx->null_cond); 486eaa3783bSRichard Henderson tcg_gen_movcond_reg(ctx->null_cond.c, dest, ctx->null_cond.a0, 487129e9cc3SRichard Henderson ctx->null_cond.a1, dest, t); 488129e9cc3SRichard Henderson } else { 489eaa3783bSRichard Henderson tcg_gen_mov_reg(dest, t); 490129e9cc3SRichard Henderson } 491129e9cc3SRichard Henderson } 492129e9cc3SRichard Henderson 493eaa3783bSRichard Henderson static void save_gpr(DisasContext *ctx, unsigned reg, TCGv_reg t) 494129e9cc3SRichard Henderson { 495129e9cc3SRichard Henderson if (reg != 0) { 496129e9cc3SRichard Henderson save_or_nullify(ctx, cpu_gr[reg], t); 497129e9cc3SRichard Henderson } 498129e9cc3SRichard Henderson } 499129e9cc3SRichard Henderson 50096d6407fSRichard Henderson #ifdef HOST_WORDS_BIGENDIAN 50196d6407fSRichard Henderson # define HI_OFS 0 50296d6407fSRichard Henderson # define LO_OFS 4 50396d6407fSRichard Henderson #else 50496d6407fSRichard Henderson # define HI_OFS 4 50596d6407fSRichard Henderson # define LO_OFS 0 50696d6407fSRichard Henderson #endif 50796d6407fSRichard Henderson 50896d6407fSRichard Henderson static TCGv_i32 load_frw_i32(unsigned rt) 50996d6407fSRichard Henderson { 51096d6407fSRichard Henderson TCGv_i32 ret = tcg_temp_new_i32(); 51196d6407fSRichard Henderson tcg_gen_ld_i32(ret, cpu_env, 51296d6407fSRichard Henderson offsetof(CPUHPPAState, fr[rt & 31]) 51396d6407fSRichard Henderson + (rt & 32 ? LO_OFS : HI_OFS)); 51496d6407fSRichard Henderson return ret; 51596d6407fSRichard Henderson } 51696d6407fSRichard Henderson 517ebe9383cSRichard Henderson static TCGv_i32 load_frw0_i32(unsigned rt) 518ebe9383cSRichard Henderson { 519ebe9383cSRichard Henderson if (rt == 0) { 520ebe9383cSRichard Henderson return tcg_const_i32(0); 521ebe9383cSRichard Henderson } else { 522ebe9383cSRichard Henderson return load_frw_i32(rt); 523ebe9383cSRichard Henderson } 524ebe9383cSRichard Henderson } 525ebe9383cSRichard Henderson 526ebe9383cSRichard Henderson static TCGv_i64 load_frw0_i64(unsigned rt) 527ebe9383cSRichard Henderson { 528ebe9383cSRichard Henderson if (rt == 0) { 529ebe9383cSRichard Henderson return tcg_const_i64(0); 530ebe9383cSRichard Henderson } else { 531ebe9383cSRichard Henderson TCGv_i64 ret = tcg_temp_new_i64(); 532ebe9383cSRichard Henderson tcg_gen_ld32u_i64(ret, cpu_env, 533ebe9383cSRichard Henderson offsetof(CPUHPPAState, fr[rt & 31]) 534ebe9383cSRichard Henderson + (rt & 32 ? LO_OFS : HI_OFS)); 535ebe9383cSRichard Henderson return ret; 536ebe9383cSRichard Henderson } 537ebe9383cSRichard Henderson } 538ebe9383cSRichard Henderson 53996d6407fSRichard Henderson static void save_frw_i32(unsigned rt, TCGv_i32 val) 54096d6407fSRichard Henderson { 54196d6407fSRichard Henderson tcg_gen_st_i32(val, cpu_env, 54296d6407fSRichard Henderson offsetof(CPUHPPAState, fr[rt & 31]) 54396d6407fSRichard Henderson + (rt & 32 ? LO_OFS : HI_OFS)); 54496d6407fSRichard Henderson } 54596d6407fSRichard Henderson 54696d6407fSRichard Henderson #undef HI_OFS 54796d6407fSRichard Henderson #undef LO_OFS 54896d6407fSRichard Henderson 54996d6407fSRichard Henderson static TCGv_i64 load_frd(unsigned rt) 55096d6407fSRichard Henderson { 55196d6407fSRichard Henderson TCGv_i64 ret = tcg_temp_new_i64(); 55296d6407fSRichard Henderson tcg_gen_ld_i64(ret, cpu_env, offsetof(CPUHPPAState, fr[rt])); 55396d6407fSRichard Henderson return ret; 55496d6407fSRichard Henderson } 55596d6407fSRichard Henderson 556ebe9383cSRichard Henderson static TCGv_i64 load_frd0(unsigned rt) 557ebe9383cSRichard Henderson { 558ebe9383cSRichard Henderson if (rt == 0) { 559ebe9383cSRichard Henderson return tcg_const_i64(0); 560ebe9383cSRichard Henderson } else { 561ebe9383cSRichard Henderson return load_frd(rt); 562ebe9383cSRichard Henderson } 563ebe9383cSRichard Henderson } 564ebe9383cSRichard Henderson 56596d6407fSRichard Henderson static void save_frd(unsigned rt, TCGv_i64 val) 56696d6407fSRichard Henderson { 56796d6407fSRichard Henderson tcg_gen_st_i64(val, cpu_env, offsetof(CPUHPPAState, fr[rt])); 56896d6407fSRichard Henderson } 56996d6407fSRichard Henderson 570129e9cc3SRichard Henderson /* Skip over the implementation of an insn that has been nullified. 571129e9cc3SRichard Henderson Use this when the insn is too complex for a conditional move. */ 572129e9cc3SRichard Henderson static void nullify_over(DisasContext *ctx) 573129e9cc3SRichard Henderson { 574129e9cc3SRichard Henderson if (ctx->null_cond.c != TCG_COND_NEVER) { 575129e9cc3SRichard Henderson /* The always condition should have been handled in the main loop. */ 576129e9cc3SRichard Henderson assert(ctx->null_cond.c != TCG_COND_ALWAYS); 577129e9cc3SRichard Henderson 578129e9cc3SRichard Henderson ctx->null_lab = gen_new_label(); 579129e9cc3SRichard Henderson cond_prep(&ctx->null_cond); 580129e9cc3SRichard Henderson 581129e9cc3SRichard Henderson /* If we're using PSW[N], copy it to a temp because... */ 582129e9cc3SRichard Henderson if (ctx->null_cond.a0_is_n) { 583129e9cc3SRichard Henderson ctx->null_cond.a0_is_n = false; 584129e9cc3SRichard Henderson ctx->null_cond.a0 = tcg_temp_new(); 585eaa3783bSRichard Henderson tcg_gen_mov_reg(ctx->null_cond.a0, cpu_psw_n); 586129e9cc3SRichard Henderson } 587129e9cc3SRichard Henderson /* ... we clear it before branching over the implementation, 588129e9cc3SRichard Henderson so that (1) it's clear after nullifying this insn and 589129e9cc3SRichard Henderson (2) if this insn nullifies the next, PSW[N] is valid. */ 590129e9cc3SRichard Henderson if (ctx->psw_n_nonzero) { 591129e9cc3SRichard Henderson ctx->psw_n_nonzero = false; 592eaa3783bSRichard Henderson tcg_gen_movi_reg(cpu_psw_n, 0); 593129e9cc3SRichard Henderson } 594129e9cc3SRichard Henderson 595eaa3783bSRichard Henderson tcg_gen_brcond_reg(ctx->null_cond.c, ctx->null_cond.a0, 596129e9cc3SRichard Henderson ctx->null_cond.a1, ctx->null_lab); 597129e9cc3SRichard Henderson cond_free(&ctx->null_cond); 598129e9cc3SRichard Henderson } 599129e9cc3SRichard Henderson } 600129e9cc3SRichard Henderson 601129e9cc3SRichard Henderson /* Save the current nullification state to PSW[N]. */ 602129e9cc3SRichard Henderson static void nullify_save(DisasContext *ctx) 603129e9cc3SRichard Henderson { 604129e9cc3SRichard Henderson if (ctx->null_cond.c == TCG_COND_NEVER) { 605129e9cc3SRichard Henderson if (ctx->psw_n_nonzero) { 606eaa3783bSRichard Henderson tcg_gen_movi_reg(cpu_psw_n, 0); 607129e9cc3SRichard Henderson } 608129e9cc3SRichard Henderson return; 609129e9cc3SRichard Henderson } 610129e9cc3SRichard Henderson if (!ctx->null_cond.a0_is_n) { 611129e9cc3SRichard Henderson cond_prep(&ctx->null_cond); 612eaa3783bSRichard Henderson tcg_gen_setcond_reg(ctx->null_cond.c, cpu_psw_n, 613129e9cc3SRichard Henderson ctx->null_cond.a0, ctx->null_cond.a1); 614129e9cc3SRichard Henderson ctx->psw_n_nonzero = true; 615129e9cc3SRichard Henderson } 616129e9cc3SRichard Henderson cond_free(&ctx->null_cond); 617129e9cc3SRichard Henderson } 618129e9cc3SRichard Henderson 619129e9cc3SRichard Henderson /* Set a PSW[N] to X. The intention is that this is used immediately 620129e9cc3SRichard Henderson before a goto_tb/exit_tb, so that there is no fallthru path to other 621129e9cc3SRichard Henderson code within the TB. Therefore we do not update psw_n_nonzero. */ 622129e9cc3SRichard Henderson static void nullify_set(DisasContext *ctx, bool x) 623129e9cc3SRichard Henderson { 624129e9cc3SRichard Henderson if (ctx->psw_n_nonzero || x) { 625eaa3783bSRichard Henderson tcg_gen_movi_reg(cpu_psw_n, x); 626129e9cc3SRichard Henderson } 627129e9cc3SRichard Henderson } 628129e9cc3SRichard Henderson 629129e9cc3SRichard Henderson /* Mark the end of an instruction that may have been nullified. 630129e9cc3SRichard Henderson This is the pair to nullify_over. */ 631869051eaSRichard Henderson static DisasJumpType nullify_end(DisasContext *ctx, DisasJumpType status) 632129e9cc3SRichard Henderson { 633129e9cc3SRichard Henderson TCGLabel *null_lab = ctx->null_lab; 634129e9cc3SRichard Henderson 635129e9cc3SRichard Henderson if (likely(null_lab == NULL)) { 636129e9cc3SRichard Henderson /* The current insn wasn't conditional or handled the condition 637129e9cc3SRichard Henderson applied to it without a branch, so the (new) setting of 638129e9cc3SRichard Henderson NULL_COND can be applied directly to the next insn. */ 639129e9cc3SRichard Henderson return status; 640129e9cc3SRichard Henderson } 641129e9cc3SRichard Henderson ctx->null_lab = NULL; 642129e9cc3SRichard Henderson 643129e9cc3SRichard Henderson if (likely(ctx->null_cond.c == TCG_COND_NEVER)) { 644129e9cc3SRichard Henderson /* The next instruction will be unconditional, 645129e9cc3SRichard Henderson and NULL_COND already reflects that. */ 646129e9cc3SRichard Henderson gen_set_label(null_lab); 647129e9cc3SRichard Henderson } else { 648129e9cc3SRichard Henderson /* The insn that we just executed is itself nullifying the next 649129e9cc3SRichard Henderson instruction. Store the condition in the PSW[N] global. 650129e9cc3SRichard Henderson We asserted PSW[N] = 0 in nullify_over, so that after the 651129e9cc3SRichard Henderson label we have the proper value in place. */ 652129e9cc3SRichard Henderson nullify_save(ctx); 653129e9cc3SRichard Henderson gen_set_label(null_lab); 654129e9cc3SRichard Henderson ctx->null_cond = cond_make_n(); 655129e9cc3SRichard Henderson } 656129e9cc3SRichard Henderson 657869051eaSRichard Henderson assert(status != DISAS_NORETURN && status != DISAS_IAQ_N_UPDATED); 658869051eaSRichard Henderson if (status == DISAS_NORETURN) { 659869051eaSRichard Henderson status = DISAS_NEXT; 660129e9cc3SRichard Henderson } 661129e9cc3SRichard Henderson return status; 662129e9cc3SRichard Henderson } 663129e9cc3SRichard Henderson 664eaa3783bSRichard Henderson static void copy_iaoq_entry(TCGv_reg dest, target_ureg ival, TCGv_reg vval) 66561766fe9SRichard Henderson { 66661766fe9SRichard Henderson if (unlikely(ival == -1)) { 667eaa3783bSRichard Henderson tcg_gen_mov_reg(dest, vval); 66861766fe9SRichard Henderson } else { 669eaa3783bSRichard Henderson tcg_gen_movi_reg(dest, ival); 67061766fe9SRichard Henderson } 67161766fe9SRichard Henderson } 67261766fe9SRichard Henderson 673eaa3783bSRichard Henderson static inline target_ureg iaoq_dest(DisasContext *ctx, target_sreg disp) 67461766fe9SRichard Henderson { 67561766fe9SRichard Henderson return ctx->iaoq_f + disp + 8; 67661766fe9SRichard Henderson } 67761766fe9SRichard Henderson 67861766fe9SRichard Henderson static void gen_excp_1(int exception) 67961766fe9SRichard Henderson { 68061766fe9SRichard Henderson TCGv_i32 t = tcg_const_i32(exception); 68161766fe9SRichard Henderson gen_helper_excp(cpu_env, t); 68261766fe9SRichard Henderson tcg_temp_free_i32(t); 68361766fe9SRichard Henderson } 68461766fe9SRichard Henderson 685869051eaSRichard Henderson static DisasJumpType gen_excp(DisasContext *ctx, int exception) 68661766fe9SRichard Henderson { 68761766fe9SRichard Henderson copy_iaoq_entry(cpu_iaoq_f, ctx->iaoq_f, cpu_iaoq_f); 68861766fe9SRichard Henderson copy_iaoq_entry(cpu_iaoq_b, ctx->iaoq_b, cpu_iaoq_b); 689129e9cc3SRichard Henderson nullify_save(ctx); 69061766fe9SRichard Henderson gen_excp_1(exception); 691869051eaSRichard Henderson return DISAS_NORETURN; 69261766fe9SRichard Henderson } 69361766fe9SRichard Henderson 694869051eaSRichard Henderson static DisasJumpType gen_illegal(DisasContext *ctx) 69561766fe9SRichard Henderson { 696129e9cc3SRichard Henderson nullify_over(ctx); 6972986721dSRichard Henderson return nullify_end(ctx, gen_excp(ctx, EXCP_ILL)); 69861766fe9SRichard Henderson } 69961766fe9SRichard Henderson 700eaa3783bSRichard Henderson static bool use_goto_tb(DisasContext *ctx, target_ureg dest) 70161766fe9SRichard Henderson { 70261766fe9SRichard Henderson /* Suppress goto_tb in the case of single-steping and IO. */ 703c5a49c63SEmilio G. Cota if ((tb_cflags(ctx->base.tb) & CF_LAST_IO) || ctx->base.singlestep_enabled) { 70461766fe9SRichard Henderson return false; 70561766fe9SRichard Henderson } 70661766fe9SRichard Henderson return true; 70761766fe9SRichard Henderson } 70861766fe9SRichard Henderson 709129e9cc3SRichard Henderson /* If the next insn is to be nullified, and it's on the same page, 710129e9cc3SRichard Henderson and we're not attempting to set a breakpoint on it, then we can 711129e9cc3SRichard Henderson totally skip the nullified insn. This avoids creating and 712129e9cc3SRichard Henderson executing a TB that merely branches to the next TB. */ 713129e9cc3SRichard Henderson static bool use_nullify_skip(DisasContext *ctx) 714129e9cc3SRichard Henderson { 715129e9cc3SRichard Henderson return (((ctx->iaoq_b ^ ctx->iaoq_f) & TARGET_PAGE_MASK) == 0 716129e9cc3SRichard Henderson && !cpu_breakpoint_test(ctx->cs, ctx->iaoq_b, BP_ANY)); 717129e9cc3SRichard Henderson } 718129e9cc3SRichard Henderson 71961766fe9SRichard Henderson static void gen_goto_tb(DisasContext *ctx, int which, 720eaa3783bSRichard Henderson target_ureg f, target_ureg b) 72161766fe9SRichard Henderson { 72261766fe9SRichard Henderson if (f != -1 && b != -1 && use_goto_tb(ctx, f)) { 72361766fe9SRichard Henderson tcg_gen_goto_tb(which); 724eaa3783bSRichard Henderson tcg_gen_movi_reg(cpu_iaoq_f, f); 725eaa3783bSRichard Henderson tcg_gen_movi_reg(cpu_iaoq_b, b); 726d01a3625SRichard Henderson tcg_gen_exit_tb((uintptr_t)ctx->base.tb + which); 72761766fe9SRichard Henderson } else { 72861766fe9SRichard Henderson copy_iaoq_entry(cpu_iaoq_f, f, cpu_iaoq_b); 72961766fe9SRichard Henderson copy_iaoq_entry(cpu_iaoq_b, b, ctx->iaoq_n_var); 730d01a3625SRichard Henderson if (ctx->base.singlestep_enabled) { 73161766fe9SRichard Henderson gen_excp_1(EXCP_DEBUG); 73261766fe9SRichard Henderson } else { 7337f11636dSEmilio G. Cota tcg_gen_lookup_and_goto_ptr(); 73461766fe9SRichard Henderson } 73561766fe9SRichard Henderson } 73661766fe9SRichard Henderson } 73761766fe9SRichard Henderson 738b2167459SRichard Henderson /* PA has a habit of taking the LSB of a field and using that as the sign, 739b2167459SRichard Henderson with the rest of the field becoming the least significant bits. */ 740eaa3783bSRichard Henderson static target_sreg low_sextract(uint32_t val, int pos, int len) 741b2167459SRichard Henderson { 742eaa3783bSRichard Henderson target_ureg x = -(target_ureg)extract32(val, pos, 1); 743b2167459SRichard Henderson x = (x << (len - 1)) | extract32(val, pos + 1, len - 1); 744b2167459SRichard Henderson return x; 745b2167459SRichard Henderson } 746b2167459SRichard Henderson 747ebe9383cSRichard Henderson static unsigned assemble_rt64(uint32_t insn) 748ebe9383cSRichard Henderson { 749ebe9383cSRichard Henderson unsigned r1 = extract32(insn, 6, 1); 750ebe9383cSRichard Henderson unsigned r0 = extract32(insn, 0, 5); 751ebe9383cSRichard Henderson return r1 * 32 + r0; 752ebe9383cSRichard Henderson } 753ebe9383cSRichard Henderson 754ebe9383cSRichard Henderson static unsigned assemble_ra64(uint32_t insn) 755ebe9383cSRichard Henderson { 756ebe9383cSRichard Henderson unsigned r1 = extract32(insn, 7, 1); 757ebe9383cSRichard Henderson unsigned r0 = extract32(insn, 21, 5); 758ebe9383cSRichard Henderson return r1 * 32 + r0; 759ebe9383cSRichard Henderson } 760ebe9383cSRichard Henderson 761ebe9383cSRichard Henderson static unsigned assemble_rb64(uint32_t insn) 762ebe9383cSRichard Henderson { 763ebe9383cSRichard Henderson unsigned r1 = extract32(insn, 12, 1); 764ebe9383cSRichard Henderson unsigned r0 = extract32(insn, 16, 5); 765ebe9383cSRichard Henderson return r1 * 32 + r0; 766ebe9383cSRichard Henderson } 767ebe9383cSRichard Henderson 768ebe9383cSRichard Henderson static unsigned assemble_rc64(uint32_t insn) 769ebe9383cSRichard Henderson { 770ebe9383cSRichard Henderson unsigned r2 = extract32(insn, 8, 1); 771ebe9383cSRichard Henderson unsigned r1 = extract32(insn, 13, 3); 772ebe9383cSRichard Henderson unsigned r0 = extract32(insn, 9, 2); 773ebe9383cSRichard Henderson return r2 * 32 + r1 * 4 + r0; 774ebe9383cSRichard Henderson } 775ebe9383cSRichard Henderson 776eaa3783bSRichard Henderson static target_sreg assemble_12(uint32_t insn) 77798cd9ca7SRichard Henderson { 778eaa3783bSRichard Henderson target_ureg x = -(target_ureg)(insn & 1); 77998cd9ca7SRichard Henderson x = (x << 1) | extract32(insn, 2, 1); 78098cd9ca7SRichard Henderson x = (x << 10) | extract32(insn, 3, 10); 78198cd9ca7SRichard Henderson return x; 78298cd9ca7SRichard Henderson } 78398cd9ca7SRichard Henderson 784eaa3783bSRichard Henderson static target_sreg assemble_16(uint32_t insn) 785b2167459SRichard Henderson { 786b2167459SRichard Henderson /* Take the name from PA2.0, which produces a 16-bit number 787b2167459SRichard Henderson only with wide mode; otherwise a 14-bit number. Since we don't 788b2167459SRichard Henderson implement wide mode, this is always the 14-bit number. */ 789b2167459SRichard Henderson return low_sextract(insn, 0, 14); 790b2167459SRichard Henderson } 791b2167459SRichard Henderson 792eaa3783bSRichard Henderson static target_sreg assemble_16a(uint32_t insn) 79396d6407fSRichard Henderson { 79496d6407fSRichard Henderson /* Take the name from PA2.0, which produces a 14-bit shifted number 79596d6407fSRichard Henderson only with wide mode; otherwise a 12-bit shifted number. Since we 79696d6407fSRichard Henderson don't implement wide mode, this is always the 12-bit number. */ 797eaa3783bSRichard Henderson target_ureg x = -(target_ureg)(insn & 1); 79896d6407fSRichard Henderson x = (x << 11) | extract32(insn, 2, 11); 79996d6407fSRichard Henderson return x << 2; 80096d6407fSRichard Henderson } 80196d6407fSRichard Henderson 802eaa3783bSRichard Henderson static target_sreg assemble_17(uint32_t insn) 80398cd9ca7SRichard Henderson { 804eaa3783bSRichard Henderson target_ureg x = -(target_ureg)(insn & 1); 80598cd9ca7SRichard Henderson x = (x << 5) | extract32(insn, 16, 5); 80698cd9ca7SRichard Henderson x = (x << 1) | extract32(insn, 2, 1); 80798cd9ca7SRichard Henderson x = (x << 10) | extract32(insn, 3, 10); 80898cd9ca7SRichard Henderson return x << 2; 80998cd9ca7SRichard Henderson } 81098cd9ca7SRichard Henderson 811eaa3783bSRichard Henderson static target_sreg assemble_21(uint32_t insn) 812b2167459SRichard Henderson { 813eaa3783bSRichard Henderson target_ureg x = -(target_ureg)(insn & 1); 814b2167459SRichard Henderson x = (x << 11) | extract32(insn, 1, 11); 815b2167459SRichard Henderson x = (x << 2) | extract32(insn, 14, 2); 816b2167459SRichard Henderson x = (x << 5) | extract32(insn, 16, 5); 817b2167459SRichard Henderson x = (x << 2) | extract32(insn, 12, 2); 818b2167459SRichard Henderson return x << 11; 819b2167459SRichard Henderson } 820b2167459SRichard Henderson 821eaa3783bSRichard Henderson static target_sreg assemble_22(uint32_t insn) 82298cd9ca7SRichard Henderson { 823eaa3783bSRichard Henderson target_ureg x = -(target_ureg)(insn & 1); 82498cd9ca7SRichard Henderson x = (x << 10) | extract32(insn, 16, 10); 82598cd9ca7SRichard Henderson x = (x << 1) | extract32(insn, 2, 1); 82698cd9ca7SRichard Henderson x = (x << 10) | extract32(insn, 3, 10); 82798cd9ca7SRichard Henderson return x << 2; 82898cd9ca7SRichard Henderson } 82998cd9ca7SRichard Henderson 830b2167459SRichard Henderson /* The parisc documentation describes only the general interpretation of 831b2167459SRichard Henderson the conditions, without describing their exact implementation. The 832b2167459SRichard Henderson interpretations do not stand up well when considering ADD,C and SUB,B. 833b2167459SRichard Henderson However, considering the Addition, Subtraction and Logical conditions 834b2167459SRichard Henderson as a whole it would appear that these relations are similar to what 835b2167459SRichard Henderson a traditional NZCV set of flags would produce. */ 836b2167459SRichard Henderson 837eaa3783bSRichard Henderson static DisasCond do_cond(unsigned cf, TCGv_reg res, 838eaa3783bSRichard Henderson TCGv_reg cb_msb, TCGv_reg sv) 839b2167459SRichard Henderson { 840b2167459SRichard Henderson DisasCond cond; 841eaa3783bSRichard Henderson TCGv_reg tmp; 842b2167459SRichard Henderson 843b2167459SRichard Henderson switch (cf >> 1) { 844b2167459SRichard Henderson case 0: /* Never / TR */ 845b2167459SRichard Henderson cond = cond_make_f(); 846b2167459SRichard Henderson break; 847b2167459SRichard Henderson case 1: /* = / <> (Z / !Z) */ 848b2167459SRichard Henderson cond = cond_make_0(TCG_COND_EQ, res); 849b2167459SRichard Henderson break; 850b2167459SRichard Henderson case 2: /* < / >= (N / !N) */ 851b2167459SRichard Henderson cond = cond_make_0(TCG_COND_LT, res); 852b2167459SRichard Henderson break; 853b2167459SRichard Henderson case 3: /* <= / > (N | Z / !N & !Z) */ 854b2167459SRichard Henderson cond = cond_make_0(TCG_COND_LE, res); 855b2167459SRichard Henderson break; 856b2167459SRichard Henderson case 4: /* NUV / UV (!C / C) */ 857b2167459SRichard Henderson cond = cond_make_0(TCG_COND_EQ, cb_msb); 858b2167459SRichard Henderson break; 859b2167459SRichard Henderson case 5: /* ZNV / VNZ (!C | Z / C & !Z) */ 860b2167459SRichard Henderson tmp = tcg_temp_new(); 861eaa3783bSRichard Henderson tcg_gen_neg_reg(tmp, cb_msb); 862eaa3783bSRichard Henderson tcg_gen_and_reg(tmp, tmp, res); 863b2167459SRichard Henderson cond = cond_make_0(TCG_COND_EQ, tmp); 864b2167459SRichard Henderson tcg_temp_free(tmp); 865b2167459SRichard Henderson break; 866b2167459SRichard Henderson case 6: /* SV / NSV (V / !V) */ 867b2167459SRichard Henderson cond = cond_make_0(TCG_COND_LT, sv); 868b2167459SRichard Henderson break; 869b2167459SRichard Henderson case 7: /* OD / EV */ 870b2167459SRichard Henderson tmp = tcg_temp_new(); 871eaa3783bSRichard Henderson tcg_gen_andi_reg(tmp, res, 1); 872b2167459SRichard Henderson cond = cond_make_0(TCG_COND_NE, tmp); 873b2167459SRichard Henderson tcg_temp_free(tmp); 874b2167459SRichard Henderson break; 875b2167459SRichard Henderson default: 876b2167459SRichard Henderson g_assert_not_reached(); 877b2167459SRichard Henderson } 878b2167459SRichard Henderson if (cf & 1) { 879b2167459SRichard Henderson cond.c = tcg_invert_cond(cond.c); 880b2167459SRichard Henderson } 881b2167459SRichard Henderson 882b2167459SRichard Henderson return cond; 883b2167459SRichard Henderson } 884b2167459SRichard Henderson 885b2167459SRichard Henderson /* Similar, but for the special case of subtraction without borrow, we 886b2167459SRichard Henderson can use the inputs directly. This can allow other computation to be 887b2167459SRichard Henderson deleted as unused. */ 888b2167459SRichard Henderson 889eaa3783bSRichard Henderson static DisasCond do_sub_cond(unsigned cf, TCGv_reg res, 890eaa3783bSRichard Henderson TCGv_reg in1, TCGv_reg in2, TCGv_reg sv) 891b2167459SRichard Henderson { 892b2167459SRichard Henderson DisasCond cond; 893b2167459SRichard Henderson 894b2167459SRichard Henderson switch (cf >> 1) { 895b2167459SRichard Henderson case 1: /* = / <> */ 896b2167459SRichard Henderson cond = cond_make(TCG_COND_EQ, in1, in2); 897b2167459SRichard Henderson break; 898b2167459SRichard Henderson case 2: /* < / >= */ 899b2167459SRichard Henderson cond = cond_make(TCG_COND_LT, in1, in2); 900b2167459SRichard Henderson break; 901b2167459SRichard Henderson case 3: /* <= / > */ 902b2167459SRichard Henderson cond = cond_make(TCG_COND_LE, in1, in2); 903b2167459SRichard Henderson break; 904b2167459SRichard Henderson case 4: /* << / >>= */ 905b2167459SRichard Henderson cond = cond_make(TCG_COND_LTU, in1, in2); 906b2167459SRichard Henderson break; 907b2167459SRichard Henderson case 5: /* <<= / >> */ 908b2167459SRichard Henderson cond = cond_make(TCG_COND_LEU, in1, in2); 909b2167459SRichard Henderson break; 910b2167459SRichard Henderson default: 911b2167459SRichard Henderson return do_cond(cf, res, sv, sv); 912b2167459SRichard Henderson } 913b2167459SRichard Henderson if (cf & 1) { 914b2167459SRichard Henderson cond.c = tcg_invert_cond(cond.c); 915b2167459SRichard Henderson } 916b2167459SRichard Henderson 917b2167459SRichard Henderson return cond; 918b2167459SRichard Henderson } 919b2167459SRichard Henderson 920b2167459SRichard Henderson /* Similar, but for logicals, where the carry and overflow bits are not 921b2167459SRichard Henderson computed, and use of them is undefined. */ 922b2167459SRichard Henderson 923eaa3783bSRichard Henderson static DisasCond do_log_cond(unsigned cf, TCGv_reg res) 924b2167459SRichard Henderson { 925b2167459SRichard Henderson switch (cf >> 1) { 926b2167459SRichard Henderson case 4: case 5: case 6: 927b2167459SRichard Henderson cf &= 1; 928b2167459SRichard Henderson break; 929b2167459SRichard Henderson } 930b2167459SRichard Henderson return do_cond(cf, res, res, res); 931b2167459SRichard Henderson } 932b2167459SRichard Henderson 93398cd9ca7SRichard Henderson /* Similar, but for shift/extract/deposit conditions. */ 93498cd9ca7SRichard Henderson 935eaa3783bSRichard Henderson static DisasCond do_sed_cond(unsigned orig, TCGv_reg res) 93698cd9ca7SRichard Henderson { 93798cd9ca7SRichard Henderson unsigned c, f; 93898cd9ca7SRichard Henderson 93998cd9ca7SRichard Henderson /* Convert the compressed condition codes to standard. 94098cd9ca7SRichard Henderson 0-2 are the same as logicals (nv,<,<=), while 3 is OD. 94198cd9ca7SRichard Henderson 4-7 are the reverse of 0-3. */ 94298cd9ca7SRichard Henderson c = orig & 3; 94398cd9ca7SRichard Henderson if (c == 3) { 94498cd9ca7SRichard Henderson c = 7; 94598cd9ca7SRichard Henderson } 94698cd9ca7SRichard Henderson f = (orig & 4) / 4; 94798cd9ca7SRichard Henderson 94898cd9ca7SRichard Henderson return do_log_cond(c * 2 + f, res); 94998cd9ca7SRichard Henderson } 95098cd9ca7SRichard Henderson 951b2167459SRichard Henderson /* Similar, but for unit conditions. */ 952b2167459SRichard Henderson 953eaa3783bSRichard Henderson static DisasCond do_unit_cond(unsigned cf, TCGv_reg res, 954eaa3783bSRichard Henderson TCGv_reg in1, TCGv_reg in2) 955b2167459SRichard Henderson { 956b2167459SRichard Henderson DisasCond cond; 957eaa3783bSRichard Henderson TCGv_reg tmp, cb = NULL; 958b2167459SRichard Henderson 959b2167459SRichard Henderson if (cf & 8) { 960b2167459SRichard Henderson /* Since we want to test lots of carry-out bits all at once, do not 961b2167459SRichard Henderson * do our normal thing and compute carry-in of bit B+1 since that 962b2167459SRichard Henderson * leaves us with carry bits spread across two words. 963b2167459SRichard Henderson */ 964b2167459SRichard Henderson cb = tcg_temp_new(); 965b2167459SRichard Henderson tmp = tcg_temp_new(); 966eaa3783bSRichard Henderson tcg_gen_or_reg(cb, in1, in2); 967eaa3783bSRichard Henderson tcg_gen_and_reg(tmp, in1, in2); 968eaa3783bSRichard Henderson tcg_gen_andc_reg(cb, cb, res); 969eaa3783bSRichard Henderson tcg_gen_or_reg(cb, cb, tmp); 970b2167459SRichard Henderson tcg_temp_free(tmp); 971b2167459SRichard Henderson } 972b2167459SRichard Henderson 973b2167459SRichard Henderson switch (cf >> 1) { 974b2167459SRichard Henderson case 0: /* never / TR */ 975b2167459SRichard Henderson case 1: /* undefined */ 976b2167459SRichard Henderson case 5: /* undefined */ 977b2167459SRichard Henderson cond = cond_make_f(); 978b2167459SRichard Henderson break; 979b2167459SRichard Henderson 980b2167459SRichard Henderson case 2: /* SBZ / NBZ */ 981b2167459SRichard Henderson /* See hasless(v,1) from 982b2167459SRichard Henderson * https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord 983b2167459SRichard Henderson */ 984b2167459SRichard Henderson tmp = tcg_temp_new(); 985eaa3783bSRichard Henderson tcg_gen_subi_reg(tmp, res, 0x01010101u); 986eaa3783bSRichard Henderson tcg_gen_andc_reg(tmp, tmp, res); 987eaa3783bSRichard Henderson tcg_gen_andi_reg(tmp, tmp, 0x80808080u); 988b2167459SRichard Henderson cond = cond_make_0(TCG_COND_NE, tmp); 989b2167459SRichard Henderson tcg_temp_free(tmp); 990b2167459SRichard Henderson break; 991b2167459SRichard Henderson 992b2167459SRichard Henderson case 3: /* SHZ / NHZ */ 993b2167459SRichard Henderson tmp = tcg_temp_new(); 994eaa3783bSRichard Henderson tcg_gen_subi_reg(tmp, res, 0x00010001u); 995eaa3783bSRichard Henderson tcg_gen_andc_reg(tmp, tmp, res); 996eaa3783bSRichard Henderson tcg_gen_andi_reg(tmp, tmp, 0x80008000u); 997b2167459SRichard Henderson cond = cond_make_0(TCG_COND_NE, tmp); 998b2167459SRichard Henderson tcg_temp_free(tmp); 999b2167459SRichard Henderson break; 1000b2167459SRichard Henderson 1001b2167459SRichard Henderson case 4: /* SDC / NDC */ 1002eaa3783bSRichard Henderson tcg_gen_andi_reg(cb, cb, 0x88888888u); 1003b2167459SRichard Henderson cond = cond_make_0(TCG_COND_NE, cb); 1004b2167459SRichard Henderson break; 1005b2167459SRichard Henderson 1006b2167459SRichard Henderson case 6: /* SBC / NBC */ 1007eaa3783bSRichard Henderson tcg_gen_andi_reg(cb, cb, 0x80808080u); 1008b2167459SRichard Henderson cond = cond_make_0(TCG_COND_NE, cb); 1009b2167459SRichard Henderson break; 1010b2167459SRichard Henderson 1011b2167459SRichard Henderson case 7: /* SHC / NHC */ 1012eaa3783bSRichard Henderson tcg_gen_andi_reg(cb, cb, 0x80008000u); 1013b2167459SRichard Henderson cond = cond_make_0(TCG_COND_NE, cb); 1014b2167459SRichard Henderson break; 1015b2167459SRichard Henderson 1016b2167459SRichard Henderson default: 1017b2167459SRichard Henderson g_assert_not_reached(); 1018b2167459SRichard Henderson } 1019b2167459SRichard Henderson if (cf & 8) { 1020b2167459SRichard Henderson tcg_temp_free(cb); 1021b2167459SRichard Henderson } 1022b2167459SRichard Henderson if (cf & 1) { 1023b2167459SRichard Henderson cond.c = tcg_invert_cond(cond.c); 1024b2167459SRichard Henderson } 1025b2167459SRichard Henderson 1026b2167459SRichard Henderson return cond; 1027b2167459SRichard Henderson } 1028b2167459SRichard Henderson 1029b2167459SRichard Henderson /* Compute signed overflow for addition. */ 1030eaa3783bSRichard Henderson static TCGv_reg do_add_sv(DisasContext *ctx, TCGv_reg res, 1031eaa3783bSRichard Henderson TCGv_reg in1, TCGv_reg in2) 1032b2167459SRichard Henderson { 1033eaa3783bSRichard Henderson TCGv_reg sv = get_temp(ctx); 1034eaa3783bSRichard Henderson TCGv_reg tmp = tcg_temp_new(); 1035b2167459SRichard Henderson 1036eaa3783bSRichard Henderson tcg_gen_xor_reg(sv, res, in1); 1037eaa3783bSRichard Henderson tcg_gen_xor_reg(tmp, in1, in2); 1038eaa3783bSRichard Henderson tcg_gen_andc_reg(sv, sv, tmp); 1039b2167459SRichard Henderson tcg_temp_free(tmp); 1040b2167459SRichard Henderson 1041b2167459SRichard Henderson return sv; 1042b2167459SRichard Henderson } 1043b2167459SRichard Henderson 1044b2167459SRichard Henderson /* Compute signed overflow for subtraction. */ 1045eaa3783bSRichard Henderson static TCGv_reg do_sub_sv(DisasContext *ctx, TCGv_reg res, 1046eaa3783bSRichard Henderson TCGv_reg in1, TCGv_reg in2) 1047b2167459SRichard Henderson { 1048eaa3783bSRichard Henderson TCGv_reg sv = get_temp(ctx); 1049eaa3783bSRichard Henderson TCGv_reg tmp = tcg_temp_new(); 1050b2167459SRichard Henderson 1051eaa3783bSRichard Henderson tcg_gen_xor_reg(sv, res, in1); 1052eaa3783bSRichard Henderson tcg_gen_xor_reg(tmp, in1, in2); 1053eaa3783bSRichard Henderson tcg_gen_and_reg(sv, sv, tmp); 1054b2167459SRichard Henderson tcg_temp_free(tmp); 1055b2167459SRichard Henderson 1056b2167459SRichard Henderson return sv; 1057b2167459SRichard Henderson } 1058b2167459SRichard Henderson 1059eaa3783bSRichard Henderson static DisasJumpType do_add(DisasContext *ctx, unsigned rt, TCGv_reg in1, 1060eaa3783bSRichard Henderson TCGv_reg in2, unsigned shift, bool is_l, 1061eaa3783bSRichard Henderson bool is_tsv, bool is_tc, bool is_c, unsigned cf) 1062b2167459SRichard Henderson { 1063eaa3783bSRichard Henderson TCGv_reg dest, cb, cb_msb, sv, tmp; 1064b2167459SRichard Henderson unsigned c = cf >> 1; 1065b2167459SRichard Henderson DisasCond cond; 1066b2167459SRichard Henderson 1067b2167459SRichard Henderson dest = tcg_temp_new(); 1068f764718dSRichard Henderson cb = NULL; 1069f764718dSRichard Henderson cb_msb = NULL; 1070b2167459SRichard Henderson 1071b2167459SRichard Henderson if (shift) { 1072b2167459SRichard Henderson tmp = get_temp(ctx); 1073eaa3783bSRichard Henderson tcg_gen_shli_reg(tmp, in1, shift); 1074b2167459SRichard Henderson in1 = tmp; 1075b2167459SRichard Henderson } 1076b2167459SRichard Henderson 1077b2167459SRichard Henderson if (!is_l || c == 4 || c == 5) { 1078eaa3783bSRichard Henderson TCGv_reg zero = tcg_const_reg(0); 1079b2167459SRichard Henderson cb_msb = get_temp(ctx); 1080eaa3783bSRichard Henderson tcg_gen_add2_reg(dest, cb_msb, in1, zero, in2, zero); 1081b2167459SRichard Henderson if (is_c) { 1082eaa3783bSRichard Henderson tcg_gen_add2_reg(dest, cb_msb, dest, cb_msb, cpu_psw_cb_msb, zero); 1083b2167459SRichard Henderson } 1084b2167459SRichard Henderson tcg_temp_free(zero); 1085b2167459SRichard Henderson if (!is_l) { 1086b2167459SRichard Henderson cb = get_temp(ctx); 1087eaa3783bSRichard Henderson tcg_gen_xor_reg(cb, in1, in2); 1088eaa3783bSRichard Henderson tcg_gen_xor_reg(cb, cb, dest); 1089b2167459SRichard Henderson } 1090b2167459SRichard Henderson } else { 1091eaa3783bSRichard Henderson tcg_gen_add_reg(dest, in1, in2); 1092b2167459SRichard Henderson if (is_c) { 1093eaa3783bSRichard Henderson tcg_gen_add_reg(dest, dest, cpu_psw_cb_msb); 1094b2167459SRichard Henderson } 1095b2167459SRichard Henderson } 1096b2167459SRichard Henderson 1097b2167459SRichard Henderson /* Compute signed overflow if required. */ 1098f764718dSRichard Henderson sv = NULL; 1099b2167459SRichard Henderson if (is_tsv || c == 6) { 1100b2167459SRichard Henderson sv = do_add_sv(ctx, dest, in1, in2); 1101b2167459SRichard Henderson if (is_tsv) { 1102b2167459SRichard Henderson /* ??? Need to include overflow from shift. */ 1103b2167459SRichard Henderson gen_helper_tsv(cpu_env, sv); 1104b2167459SRichard Henderson } 1105b2167459SRichard Henderson } 1106b2167459SRichard Henderson 1107b2167459SRichard Henderson /* Emit any conditional trap before any writeback. */ 1108b2167459SRichard Henderson cond = do_cond(cf, dest, cb_msb, sv); 1109b2167459SRichard Henderson if (is_tc) { 1110b2167459SRichard Henderson cond_prep(&cond); 1111b2167459SRichard Henderson tmp = tcg_temp_new(); 1112eaa3783bSRichard Henderson tcg_gen_setcond_reg(cond.c, tmp, cond.a0, cond.a1); 1113b2167459SRichard Henderson gen_helper_tcond(cpu_env, tmp); 1114b2167459SRichard Henderson tcg_temp_free(tmp); 1115b2167459SRichard Henderson } 1116b2167459SRichard Henderson 1117b2167459SRichard Henderson /* Write back the result. */ 1118b2167459SRichard Henderson if (!is_l) { 1119b2167459SRichard Henderson save_or_nullify(ctx, cpu_psw_cb, cb); 1120b2167459SRichard Henderson save_or_nullify(ctx, cpu_psw_cb_msb, cb_msb); 1121b2167459SRichard Henderson } 1122b2167459SRichard Henderson save_gpr(ctx, rt, dest); 1123b2167459SRichard Henderson tcg_temp_free(dest); 1124b2167459SRichard Henderson 1125b2167459SRichard Henderson /* Install the new nullification. */ 1126b2167459SRichard Henderson cond_free(&ctx->null_cond); 1127b2167459SRichard Henderson ctx->null_cond = cond; 1128869051eaSRichard Henderson return DISAS_NEXT; 1129b2167459SRichard Henderson } 1130b2167459SRichard Henderson 1131eaa3783bSRichard Henderson static DisasJumpType do_sub(DisasContext *ctx, unsigned rt, TCGv_reg in1, 1132eaa3783bSRichard Henderson TCGv_reg in2, bool is_tsv, bool is_b, 1133eaa3783bSRichard Henderson bool is_tc, unsigned cf) 1134b2167459SRichard Henderson { 1135eaa3783bSRichard Henderson TCGv_reg dest, sv, cb, cb_msb, zero, tmp; 1136b2167459SRichard Henderson unsigned c = cf >> 1; 1137b2167459SRichard Henderson DisasCond cond; 1138b2167459SRichard Henderson 1139b2167459SRichard Henderson dest = tcg_temp_new(); 1140b2167459SRichard Henderson cb = tcg_temp_new(); 1141b2167459SRichard Henderson cb_msb = tcg_temp_new(); 1142b2167459SRichard Henderson 1143eaa3783bSRichard Henderson zero = tcg_const_reg(0); 1144b2167459SRichard Henderson if (is_b) { 1145b2167459SRichard Henderson /* DEST,C = IN1 + ~IN2 + C. */ 1146eaa3783bSRichard Henderson tcg_gen_not_reg(cb, in2); 1147eaa3783bSRichard Henderson tcg_gen_add2_reg(dest, cb_msb, in1, zero, cpu_psw_cb_msb, zero); 1148eaa3783bSRichard Henderson tcg_gen_add2_reg(dest, cb_msb, dest, cb_msb, cb, zero); 1149eaa3783bSRichard Henderson tcg_gen_xor_reg(cb, cb, in1); 1150eaa3783bSRichard Henderson tcg_gen_xor_reg(cb, cb, dest); 1151b2167459SRichard Henderson } else { 1152b2167459SRichard Henderson /* DEST,C = IN1 + ~IN2 + 1. We can produce the same result in fewer 1153b2167459SRichard Henderson operations by seeding the high word with 1 and subtracting. */ 1154eaa3783bSRichard Henderson tcg_gen_movi_reg(cb_msb, 1); 1155eaa3783bSRichard Henderson tcg_gen_sub2_reg(dest, cb_msb, in1, cb_msb, in2, zero); 1156eaa3783bSRichard Henderson tcg_gen_eqv_reg(cb, in1, in2); 1157eaa3783bSRichard Henderson tcg_gen_xor_reg(cb, cb, dest); 1158b2167459SRichard Henderson } 1159b2167459SRichard Henderson tcg_temp_free(zero); 1160b2167459SRichard Henderson 1161b2167459SRichard Henderson /* Compute signed overflow if required. */ 1162f764718dSRichard Henderson sv = NULL; 1163b2167459SRichard Henderson if (is_tsv || c == 6) { 1164b2167459SRichard Henderson sv = do_sub_sv(ctx, dest, in1, in2); 1165b2167459SRichard Henderson if (is_tsv) { 1166b2167459SRichard Henderson gen_helper_tsv(cpu_env, sv); 1167b2167459SRichard Henderson } 1168b2167459SRichard Henderson } 1169b2167459SRichard Henderson 1170b2167459SRichard Henderson /* Compute the condition. We cannot use the special case for borrow. */ 1171b2167459SRichard Henderson if (!is_b) { 1172b2167459SRichard Henderson cond = do_sub_cond(cf, dest, in1, in2, sv); 1173b2167459SRichard Henderson } else { 1174b2167459SRichard Henderson cond = do_cond(cf, dest, cb_msb, sv); 1175b2167459SRichard Henderson } 1176b2167459SRichard Henderson 1177b2167459SRichard Henderson /* Emit any conditional trap before any writeback. */ 1178b2167459SRichard Henderson if (is_tc) { 1179b2167459SRichard Henderson cond_prep(&cond); 1180b2167459SRichard Henderson tmp = tcg_temp_new(); 1181eaa3783bSRichard Henderson tcg_gen_setcond_reg(cond.c, tmp, cond.a0, cond.a1); 1182b2167459SRichard Henderson gen_helper_tcond(cpu_env, tmp); 1183b2167459SRichard Henderson tcg_temp_free(tmp); 1184b2167459SRichard Henderson } 1185b2167459SRichard Henderson 1186b2167459SRichard Henderson /* Write back the result. */ 1187b2167459SRichard Henderson save_or_nullify(ctx, cpu_psw_cb, cb); 1188b2167459SRichard Henderson save_or_nullify(ctx, cpu_psw_cb_msb, cb_msb); 1189b2167459SRichard Henderson save_gpr(ctx, rt, dest); 1190b2167459SRichard Henderson tcg_temp_free(dest); 1191b2167459SRichard Henderson 1192b2167459SRichard Henderson /* Install the new nullification. */ 1193b2167459SRichard Henderson cond_free(&ctx->null_cond); 1194b2167459SRichard Henderson ctx->null_cond = cond; 1195869051eaSRichard Henderson return DISAS_NEXT; 1196b2167459SRichard Henderson } 1197b2167459SRichard Henderson 1198eaa3783bSRichard Henderson static DisasJumpType do_cmpclr(DisasContext *ctx, unsigned rt, TCGv_reg in1, 1199eaa3783bSRichard Henderson TCGv_reg in2, unsigned cf) 1200b2167459SRichard Henderson { 1201eaa3783bSRichard Henderson TCGv_reg dest, sv; 1202b2167459SRichard Henderson DisasCond cond; 1203b2167459SRichard Henderson 1204b2167459SRichard Henderson dest = tcg_temp_new(); 1205eaa3783bSRichard Henderson tcg_gen_sub_reg(dest, in1, in2); 1206b2167459SRichard Henderson 1207b2167459SRichard Henderson /* Compute signed overflow if required. */ 1208f764718dSRichard Henderson sv = NULL; 1209b2167459SRichard Henderson if ((cf >> 1) == 6) { 1210b2167459SRichard Henderson sv = do_sub_sv(ctx, dest, in1, in2); 1211b2167459SRichard Henderson } 1212b2167459SRichard Henderson 1213b2167459SRichard Henderson /* Form the condition for the compare. */ 1214b2167459SRichard Henderson cond = do_sub_cond(cf, dest, in1, in2, sv); 1215b2167459SRichard Henderson 1216b2167459SRichard Henderson /* Clear. */ 1217eaa3783bSRichard Henderson tcg_gen_movi_reg(dest, 0); 1218b2167459SRichard Henderson save_gpr(ctx, rt, dest); 1219b2167459SRichard Henderson tcg_temp_free(dest); 1220b2167459SRichard Henderson 1221b2167459SRichard Henderson /* Install the new nullification. */ 1222b2167459SRichard Henderson cond_free(&ctx->null_cond); 1223b2167459SRichard Henderson ctx->null_cond = cond; 1224869051eaSRichard Henderson return DISAS_NEXT; 1225b2167459SRichard Henderson } 1226b2167459SRichard Henderson 1227eaa3783bSRichard Henderson static DisasJumpType do_log(DisasContext *ctx, unsigned rt, TCGv_reg in1, 1228eaa3783bSRichard Henderson TCGv_reg in2, unsigned cf, 1229eaa3783bSRichard Henderson void (*fn)(TCGv_reg, TCGv_reg, TCGv_reg)) 1230b2167459SRichard Henderson { 1231eaa3783bSRichard Henderson TCGv_reg dest = dest_gpr(ctx, rt); 1232b2167459SRichard Henderson 1233b2167459SRichard Henderson /* Perform the operation, and writeback. */ 1234b2167459SRichard Henderson fn(dest, in1, in2); 1235b2167459SRichard Henderson save_gpr(ctx, rt, dest); 1236b2167459SRichard Henderson 1237b2167459SRichard Henderson /* Install the new nullification. */ 1238b2167459SRichard Henderson cond_free(&ctx->null_cond); 1239b2167459SRichard Henderson if (cf) { 1240b2167459SRichard Henderson ctx->null_cond = do_log_cond(cf, dest); 1241b2167459SRichard Henderson } 1242869051eaSRichard Henderson return DISAS_NEXT; 1243b2167459SRichard Henderson } 1244b2167459SRichard Henderson 1245eaa3783bSRichard Henderson static DisasJumpType do_unit(DisasContext *ctx, unsigned rt, TCGv_reg in1, 1246eaa3783bSRichard Henderson TCGv_reg in2, unsigned cf, bool is_tc, 1247eaa3783bSRichard Henderson void (*fn)(TCGv_reg, TCGv_reg, TCGv_reg)) 1248b2167459SRichard Henderson { 1249eaa3783bSRichard Henderson TCGv_reg dest; 1250b2167459SRichard Henderson DisasCond cond; 1251b2167459SRichard Henderson 1252b2167459SRichard Henderson if (cf == 0) { 1253b2167459SRichard Henderson dest = dest_gpr(ctx, rt); 1254b2167459SRichard Henderson fn(dest, in1, in2); 1255b2167459SRichard Henderson save_gpr(ctx, rt, dest); 1256b2167459SRichard Henderson cond_free(&ctx->null_cond); 1257b2167459SRichard Henderson } else { 1258b2167459SRichard Henderson dest = tcg_temp_new(); 1259b2167459SRichard Henderson fn(dest, in1, in2); 1260b2167459SRichard Henderson 1261b2167459SRichard Henderson cond = do_unit_cond(cf, dest, in1, in2); 1262b2167459SRichard Henderson 1263b2167459SRichard Henderson if (is_tc) { 1264eaa3783bSRichard Henderson TCGv_reg tmp = tcg_temp_new(); 1265b2167459SRichard Henderson cond_prep(&cond); 1266eaa3783bSRichard Henderson tcg_gen_setcond_reg(cond.c, tmp, cond.a0, cond.a1); 1267b2167459SRichard Henderson gen_helper_tcond(cpu_env, tmp); 1268b2167459SRichard Henderson tcg_temp_free(tmp); 1269b2167459SRichard Henderson } 1270b2167459SRichard Henderson save_gpr(ctx, rt, dest); 1271b2167459SRichard Henderson 1272b2167459SRichard Henderson cond_free(&ctx->null_cond); 1273b2167459SRichard Henderson ctx->null_cond = cond; 1274b2167459SRichard Henderson } 1275869051eaSRichard Henderson return DISAS_NEXT; 1276b2167459SRichard Henderson } 1277b2167459SRichard Henderson 127896d6407fSRichard Henderson /* Emit a memory load. The modify parameter should be 127996d6407fSRichard Henderson * < 0 for pre-modify, 128096d6407fSRichard Henderson * > 0 for post-modify, 128196d6407fSRichard Henderson * = 0 for no base register update. 128296d6407fSRichard Henderson */ 128396d6407fSRichard Henderson static void do_load_32(DisasContext *ctx, TCGv_i32 dest, unsigned rb, 1284eaa3783bSRichard Henderson unsigned rx, int scale, target_sreg disp, 128596d6407fSRichard Henderson int modify, TCGMemOp mop) 128696d6407fSRichard Henderson { 1287eaa3783bSRichard Henderson TCGv_reg addr, base; 128896d6407fSRichard Henderson 128996d6407fSRichard Henderson /* Caller uses nullify_over/nullify_end. */ 129096d6407fSRichard Henderson assert(ctx->null_cond.c == TCG_COND_NEVER); 129196d6407fSRichard Henderson 129296d6407fSRichard Henderson addr = tcg_temp_new(); 129396d6407fSRichard Henderson base = load_gpr(ctx, rb); 129496d6407fSRichard Henderson 129596d6407fSRichard Henderson /* Note that RX is mutually exclusive with DISP. */ 129696d6407fSRichard Henderson if (rx) { 1297eaa3783bSRichard Henderson tcg_gen_shli_reg(addr, cpu_gr[rx], scale); 1298eaa3783bSRichard Henderson tcg_gen_add_reg(addr, addr, base); 129996d6407fSRichard Henderson } else { 1300eaa3783bSRichard Henderson tcg_gen_addi_reg(addr, base, disp); 130196d6407fSRichard Henderson } 130296d6407fSRichard Henderson 130396d6407fSRichard Henderson if (modify == 0) { 1304*3d68ee7bSRichard Henderson tcg_gen_qemu_ld_i32(dest, addr, ctx->mmu_idx, mop); 130596d6407fSRichard Henderson } else { 130696d6407fSRichard Henderson tcg_gen_qemu_ld_i32(dest, (modify < 0 ? addr : base), 1307*3d68ee7bSRichard Henderson ctx->mmu_idx, mop); 130896d6407fSRichard Henderson save_gpr(ctx, rb, addr); 130996d6407fSRichard Henderson } 131096d6407fSRichard Henderson tcg_temp_free(addr); 131196d6407fSRichard Henderson } 131296d6407fSRichard Henderson 131396d6407fSRichard Henderson static void do_load_64(DisasContext *ctx, TCGv_i64 dest, unsigned rb, 1314eaa3783bSRichard Henderson unsigned rx, int scale, target_sreg disp, 131596d6407fSRichard Henderson int modify, TCGMemOp mop) 131696d6407fSRichard Henderson { 1317eaa3783bSRichard Henderson TCGv_reg addr, base; 131896d6407fSRichard Henderson 131996d6407fSRichard Henderson /* Caller uses nullify_over/nullify_end. */ 132096d6407fSRichard Henderson assert(ctx->null_cond.c == TCG_COND_NEVER); 132196d6407fSRichard Henderson 132296d6407fSRichard Henderson addr = tcg_temp_new(); 132396d6407fSRichard Henderson base = load_gpr(ctx, rb); 132496d6407fSRichard Henderson 132596d6407fSRichard Henderson /* Note that RX is mutually exclusive with DISP. */ 132696d6407fSRichard Henderson if (rx) { 1327eaa3783bSRichard Henderson tcg_gen_shli_reg(addr, cpu_gr[rx], scale); 1328eaa3783bSRichard Henderson tcg_gen_add_reg(addr, addr, base); 132996d6407fSRichard Henderson } else { 1330eaa3783bSRichard Henderson tcg_gen_addi_reg(addr, base, disp); 133196d6407fSRichard Henderson } 133296d6407fSRichard Henderson 133396d6407fSRichard Henderson if (modify == 0) { 1334*3d68ee7bSRichard Henderson tcg_gen_qemu_ld_i64(dest, addr, ctx->mmu_idx, mop); 133596d6407fSRichard Henderson } else { 133696d6407fSRichard Henderson tcg_gen_qemu_ld_i64(dest, (modify < 0 ? addr : base), 1337*3d68ee7bSRichard Henderson ctx->mmu_idx, mop); 133896d6407fSRichard Henderson save_gpr(ctx, rb, addr); 133996d6407fSRichard Henderson } 134096d6407fSRichard Henderson tcg_temp_free(addr); 134196d6407fSRichard Henderson } 134296d6407fSRichard Henderson 134396d6407fSRichard Henderson static void do_store_32(DisasContext *ctx, TCGv_i32 src, unsigned rb, 1344eaa3783bSRichard Henderson unsigned rx, int scale, target_sreg disp, 134596d6407fSRichard Henderson int modify, TCGMemOp mop) 134696d6407fSRichard Henderson { 1347eaa3783bSRichard Henderson TCGv_reg addr, base; 134896d6407fSRichard Henderson 134996d6407fSRichard Henderson /* Caller uses nullify_over/nullify_end. */ 135096d6407fSRichard Henderson assert(ctx->null_cond.c == TCG_COND_NEVER); 135196d6407fSRichard Henderson 135296d6407fSRichard Henderson addr = tcg_temp_new(); 135396d6407fSRichard Henderson base = load_gpr(ctx, rb); 135496d6407fSRichard Henderson 135596d6407fSRichard Henderson /* Note that RX is mutually exclusive with DISP. */ 135696d6407fSRichard Henderson if (rx) { 1357eaa3783bSRichard Henderson tcg_gen_shli_reg(addr, cpu_gr[rx], scale); 1358eaa3783bSRichard Henderson tcg_gen_add_reg(addr, addr, base); 135996d6407fSRichard Henderson } else { 1360eaa3783bSRichard Henderson tcg_gen_addi_reg(addr, base, disp); 136196d6407fSRichard Henderson } 136296d6407fSRichard Henderson 1363*3d68ee7bSRichard Henderson tcg_gen_qemu_st_i32(src, (modify <= 0 ? addr : base), ctx->mmu_idx, mop); 136496d6407fSRichard Henderson 136596d6407fSRichard Henderson if (modify != 0) { 136696d6407fSRichard Henderson save_gpr(ctx, rb, addr); 136796d6407fSRichard Henderson } 136896d6407fSRichard Henderson tcg_temp_free(addr); 136996d6407fSRichard Henderson } 137096d6407fSRichard Henderson 137196d6407fSRichard Henderson static void do_store_64(DisasContext *ctx, TCGv_i64 src, unsigned rb, 1372eaa3783bSRichard Henderson unsigned rx, int scale, target_sreg disp, 137396d6407fSRichard Henderson int modify, TCGMemOp mop) 137496d6407fSRichard Henderson { 1375eaa3783bSRichard Henderson TCGv_reg addr, base; 137696d6407fSRichard Henderson 137796d6407fSRichard Henderson /* Caller uses nullify_over/nullify_end. */ 137896d6407fSRichard Henderson assert(ctx->null_cond.c == TCG_COND_NEVER); 137996d6407fSRichard Henderson 138096d6407fSRichard Henderson addr = tcg_temp_new(); 138196d6407fSRichard Henderson base = load_gpr(ctx, rb); 138296d6407fSRichard Henderson 138396d6407fSRichard Henderson /* Note that RX is mutually exclusive with DISP. */ 138496d6407fSRichard Henderson if (rx) { 1385eaa3783bSRichard Henderson tcg_gen_shli_reg(addr, cpu_gr[rx], scale); 1386eaa3783bSRichard Henderson tcg_gen_add_reg(addr, addr, base); 138796d6407fSRichard Henderson } else { 1388eaa3783bSRichard Henderson tcg_gen_addi_reg(addr, base, disp); 138996d6407fSRichard Henderson } 139096d6407fSRichard Henderson 1391*3d68ee7bSRichard Henderson tcg_gen_qemu_st_i64(src, (modify <= 0 ? addr : base), ctx->mmu_idx, mop); 139296d6407fSRichard Henderson 139396d6407fSRichard Henderson if (modify != 0) { 139496d6407fSRichard Henderson save_gpr(ctx, rb, addr); 139596d6407fSRichard Henderson } 139696d6407fSRichard Henderson tcg_temp_free(addr); 139796d6407fSRichard Henderson } 139896d6407fSRichard Henderson 1399eaa3783bSRichard Henderson #if TARGET_REGISTER_BITS == 64 1400eaa3783bSRichard Henderson #define do_load_reg do_load_64 1401eaa3783bSRichard Henderson #define do_store_reg do_store_64 140296d6407fSRichard Henderson #else 1403eaa3783bSRichard Henderson #define do_load_reg do_load_32 1404eaa3783bSRichard Henderson #define do_store_reg do_store_32 140596d6407fSRichard Henderson #endif 140696d6407fSRichard Henderson 1407869051eaSRichard Henderson static DisasJumpType do_load(DisasContext *ctx, unsigned rt, unsigned rb, 1408eaa3783bSRichard Henderson unsigned rx, int scale, target_sreg disp, 140996d6407fSRichard Henderson int modify, TCGMemOp mop) 141096d6407fSRichard Henderson { 1411eaa3783bSRichard Henderson TCGv_reg dest; 141296d6407fSRichard Henderson 141396d6407fSRichard Henderson nullify_over(ctx); 141496d6407fSRichard Henderson 141596d6407fSRichard Henderson if (modify == 0) { 141696d6407fSRichard Henderson /* No base register update. */ 141796d6407fSRichard Henderson dest = dest_gpr(ctx, rt); 141896d6407fSRichard Henderson } else { 141996d6407fSRichard Henderson /* Make sure if RT == RB, we see the result of the load. */ 142096d6407fSRichard Henderson dest = get_temp(ctx); 142196d6407fSRichard Henderson } 1422eaa3783bSRichard Henderson do_load_reg(ctx, dest, rb, rx, scale, disp, modify, mop); 142396d6407fSRichard Henderson save_gpr(ctx, rt, dest); 142496d6407fSRichard Henderson 1425869051eaSRichard Henderson return nullify_end(ctx, DISAS_NEXT); 142696d6407fSRichard Henderson } 142796d6407fSRichard Henderson 1428869051eaSRichard Henderson static DisasJumpType do_floadw(DisasContext *ctx, unsigned rt, unsigned rb, 1429eaa3783bSRichard Henderson unsigned rx, int scale, target_sreg disp, 143096d6407fSRichard Henderson int modify) 143196d6407fSRichard Henderson { 143296d6407fSRichard Henderson TCGv_i32 tmp; 143396d6407fSRichard Henderson 143496d6407fSRichard Henderson nullify_over(ctx); 143596d6407fSRichard Henderson 143696d6407fSRichard Henderson tmp = tcg_temp_new_i32(); 143796d6407fSRichard Henderson do_load_32(ctx, tmp, rb, rx, scale, disp, modify, MO_TEUL); 143896d6407fSRichard Henderson save_frw_i32(rt, tmp); 143996d6407fSRichard Henderson tcg_temp_free_i32(tmp); 144096d6407fSRichard Henderson 144196d6407fSRichard Henderson if (rt == 0) { 144296d6407fSRichard Henderson gen_helper_loaded_fr0(cpu_env); 144396d6407fSRichard Henderson } 144496d6407fSRichard Henderson 1445869051eaSRichard Henderson return nullify_end(ctx, DISAS_NEXT); 144696d6407fSRichard Henderson } 144796d6407fSRichard Henderson 1448869051eaSRichard Henderson static DisasJumpType do_floadd(DisasContext *ctx, unsigned rt, unsigned rb, 1449eaa3783bSRichard Henderson unsigned rx, int scale, target_sreg disp, 145096d6407fSRichard Henderson int modify) 145196d6407fSRichard Henderson { 145296d6407fSRichard Henderson TCGv_i64 tmp; 145396d6407fSRichard Henderson 145496d6407fSRichard Henderson nullify_over(ctx); 145596d6407fSRichard Henderson 145696d6407fSRichard Henderson tmp = tcg_temp_new_i64(); 145796d6407fSRichard Henderson do_load_64(ctx, tmp, rb, rx, scale, disp, modify, MO_TEQ); 145896d6407fSRichard Henderson save_frd(rt, tmp); 145996d6407fSRichard Henderson tcg_temp_free_i64(tmp); 146096d6407fSRichard Henderson 146196d6407fSRichard Henderson if (rt == 0) { 146296d6407fSRichard Henderson gen_helper_loaded_fr0(cpu_env); 146396d6407fSRichard Henderson } 146496d6407fSRichard Henderson 1465869051eaSRichard Henderson return nullify_end(ctx, DISAS_NEXT); 146696d6407fSRichard Henderson } 146796d6407fSRichard Henderson 1468869051eaSRichard Henderson static DisasJumpType do_store(DisasContext *ctx, unsigned rt, unsigned rb, 1469eaa3783bSRichard Henderson target_sreg disp, int modify, TCGMemOp mop) 147096d6407fSRichard Henderson { 147196d6407fSRichard Henderson nullify_over(ctx); 1472eaa3783bSRichard Henderson do_store_reg(ctx, load_gpr(ctx, rt), rb, 0, 0, disp, modify, mop); 1473869051eaSRichard Henderson return nullify_end(ctx, DISAS_NEXT); 147496d6407fSRichard Henderson } 147596d6407fSRichard Henderson 1476869051eaSRichard Henderson static DisasJumpType do_fstorew(DisasContext *ctx, unsigned rt, unsigned rb, 1477eaa3783bSRichard Henderson unsigned rx, int scale, target_sreg disp, 147896d6407fSRichard Henderson int modify) 147996d6407fSRichard Henderson { 148096d6407fSRichard Henderson TCGv_i32 tmp; 148196d6407fSRichard Henderson 148296d6407fSRichard Henderson nullify_over(ctx); 148396d6407fSRichard Henderson 148496d6407fSRichard Henderson tmp = load_frw_i32(rt); 148596d6407fSRichard Henderson do_store_32(ctx, tmp, rb, rx, scale, disp, modify, MO_TEUL); 148696d6407fSRichard Henderson tcg_temp_free_i32(tmp); 148796d6407fSRichard Henderson 1488869051eaSRichard Henderson return nullify_end(ctx, DISAS_NEXT); 148996d6407fSRichard Henderson } 149096d6407fSRichard Henderson 1491869051eaSRichard Henderson static DisasJumpType do_fstored(DisasContext *ctx, unsigned rt, unsigned rb, 1492eaa3783bSRichard Henderson unsigned rx, int scale, target_sreg disp, 149396d6407fSRichard Henderson int modify) 149496d6407fSRichard Henderson { 149596d6407fSRichard Henderson TCGv_i64 tmp; 149696d6407fSRichard Henderson 149796d6407fSRichard Henderson nullify_over(ctx); 149896d6407fSRichard Henderson 149996d6407fSRichard Henderson tmp = load_frd(rt); 150096d6407fSRichard Henderson do_store_64(ctx, tmp, rb, rx, scale, disp, modify, MO_TEQ); 150196d6407fSRichard Henderson tcg_temp_free_i64(tmp); 150296d6407fSRichard Henderson 1503869051eaSRichard Henderson return nullify_end(ctx, DISAS_NEXT); 150496d6407fSRichard Henderson } 150596d6407fSRichard Henderson 1506869051eaSRichard Henderson static DisasJumpType do_fop_wew(DisasContext *ctx, unsigned rt, unsigned ra, 1507ebe9383cSRichard Henderson void (*func)(TCGv_i32, TCGv_env, TCGv_i32)) 1508ebe9383cSRichard Henderson { 1509ebe9383cSRichard Henderson TCGv_i32 tmp; 1510ebe9383cSRichard Henderson 1511ebe9383cSRichard Henderson nullify_over(ctx); 1512ebe9383cSRichard Henderson tmp = load_frw0_i32(ra); 1513ebe9383cSRichard Henderson 1514ebe9383cSRichard Henderson func(tmp, cpu_env, tmp); 1515ebe9383cSRichard Henderson 1516ebe9383cSRichard Henderson save_frw_i32(rt, tmp); 1517ebe9383cSRichard Henderson tcg_temp_free_i32(tmp); 1518869051eaSRichard Henderson return nullify_end(ctx, DISAS_NEXT); 1519ebe9383cSRichard Henderson } 1520ebe9383cSRichard Henderson 1521869051eaSRichard Henderson static DisasJumpType do_fop_wed(DisasContext *ctx, unsigned rt, unsigned ra, 1522ebe9383cSRichard Henderson void (*func)(TCGv_i32, TCGv_env, TCGv_i64)) 1523ebe9383cSRichard Henderson { 1524ebe9383cSRichard Henderson TCGv_i32 dst; 1525ebe9383cSRichard Henderson TCGv_i64 src; 1526ebe9383cSRichard Henderson 1527ebe9383cSRichard Henderson nullify_over(ctx); 1528ebe9383cSRichard Henderson src = load_frd(ra); 1529ebe9383cSRichard Henderson dst = tcg_temp_new_i32(); 1530ebe9383cSRichard Henderson 1531ebe9383cSRichard Henderson func(dst, cpu_env, src); 1532ebe9383cSRichard Henderson 1533ebe9383cSRichard Henderson tcg_temp_free_i64(src); 1534ebe9383cSRichard Henderson save_frw_i32(rt, dst); 1535ebe9383cSRichard Henderson tcg_temp_free_i32(dst); 1536869051eaSRichard Henderson return nullify_end(ctx, DISAS_NEXT); 1537ebe9383cSRichard Henderson } 1538ebe9383cSRichard Henderson 1539869051eaSRichard Henderson static DisasJumpType do_fop_ded(DisasContext *ctx, unsigned rt, unsigned ra, 1540ebe9383cSRichard Henderson void (*func)(TCGv_i64, TCGv_env, TCGv_i64)) 1541ebe9383cSRichard Henderson { 1542ebe9383cSRichard Henderson TCGv_i64 tmp; 1543ebe9383cSRichard Henderson 1544ebe9383cSRichard Henderson nullify_over(ctx); 1545ebe9383cSRichard Henderson tmp = load_frd0(ra); 1546ebe9383cSRichard Henderson 1547ebe9383cSRichard Henderson func(tmp, cpu_env, tmp); 1548ebe9383cSRichard Henderson 1549ebe9383cSRichard Henderson save_frd(rt, tmp); 1550ebe9383cSRichard Henderson tcg_temp_free_i64(tmp); 1551869051eaSRichard Henderson return nullify_end(ctx, DISAS_NEXT); 1552ebe9383cSRichard Henderson } 1553ebe9383cSRichard Henderson 1554869051eaSRichard Henderson static DisasJumpType do_fop_dew(DisasContext *ctx, unsigned rt, unsigned ra, 1555ebe9383cSRichard Henderson void (*func)(TCGv_i64, TCGv_env, TCGv_i32)) 1556ebe9383cSRichard Henderson { 1557ebe9383cSRichard Henderson TCGv_i32 src; 1558ebe9383cSRichard Henderson TCGv_i64 dst; 1559ebe9383cSRichard Henderson 1560ebe9383cSRichard Henderson nullify_over(ctx); 1561ebe9383cSRichard Henderson src = load_frw0_i32(ra); 1562ebe9383cSRichard Henderson dst = tcg_temp_new_i64(); 1563ebe9383cSRichard Henderson 1564ebe9383cSRichard Henderson func(dst, cpu_env, src); 1565ebe9383cSRichard Henderson 1566ebe9383cSRichard Henderson tcg_temp_free_i32(src); 1567ebe9383cSRichard Henderson save_frd(rt, dst); 1568ebe9383cSRichard Henderson tcg_temp_free_i64(dst); 1569869051eaSRichard Henderson return nullify_end(ctx, DISAS_NEXT); 1570ebe9383cSRichard Henderson } 1571ebe9383cSRichard Henderson 1572869051eaSRichard Henderson static DisasJumpType do_fop_weww(DisasContext *ctx, unsigned rt, 1573ebe9383cSRichard Henderson unsigned ra, unsigned rb, 1574ebe9383cSRichard Henderson void (*func)(TCGv_i32, TCGv_env, 1575ebe9383cSRichard Henderson TCGv_i32, TCGv_i32)) 1576ebe9383cSRichard Henderson { 1577ebe9383cSRichard Henderson TCGv_i32 a, b; 1578ebe9383cSRichard Henderson 1579ebe9383cSRichard Henderson nullify_over(ctx); 1580ebe9383cSRichard Henderson a = load_frw0_i32(ra); 1581ebe9383cSRichard Henderson b = load_frw0_i32(rb); 1582ebe9383cSRichard Henderson 1583ebe9383cSRichard Henderson func(a, cpu_env, a, b); 1584ebe9383cSRichard Henderson 1585ebe9383cSRichard Henderson tcg_temp_free_i32(b); 1586ebe9383cSRichard Henderson save_frw_i32(rt, a); 1587ebe9383cSRichard Henderson tcg_temp_free_i32(a); 1588869051eaSRichard Henderson return nullify_end(ctx, DISAS_NEXT); 1589ebe9383cSRichard Henderson } 1590ebe9383cSRichard Henderson 1591869051eaSRichard Henderson static DisasJumpType do_fop_dedd(DisasContext *ctx, unsigned rt, 1592ebe9383cSRichard Henderson unsigned ra, unsigned rb, 1593ebe9383cSRichard Henderson void (*func)(TCGv_i64, TCGv_env, 1594ebe9383cSRichard Henderson TCGv_i64, TCGv_i64)) 1595ebe9383cSRichard Henderson { 1596ebe9383cSRichard Henderson TCGv_i64 a, b; 1597ebe9383cSRichard Henderson 1598ebe9383cSRichard Henderson nullify_over(ctx); 1599ebe9383cSRichard Henderson a = load_frd0(ra); 1600ebe9383cSRichard Henderson b = load_frd0(rb); 1601ebe9383cSRichard Henderson 1602ebe9383cSRichard Henderson func(a, cpu_env, a, b); 1603ebe9383cSRichard Henderson 1604ebe9383cSRichard Henderson tcg_temp_free_i64(b); 1605ebe9383cSRichard Henderson save_frd(rt, a); 1606ebe9383cSRichard Henderson tcg_temp_free_i64(a); 1607869051eaSRichard Henderson return nullify_end(ctx, DISAS_NEXT); 1608ebe9383cSRichard Henderson } 1609ebe9383cSRichard Henderson 161098cd9ca7SRichard Henderson /* Emit an unconditional branch to a direct target, which may or may not 161198cd9ca7SRichard Henderson have already had nullification handled. */ 1612eaa3783bSRichard Henderson static DisasJumpType do_dbranch(DisasContext *ctx, target_ureg dest, 161398cd9ca7SRichard Henderson unsigned link, bool is_n) 161498cd9ca7SRichard Henderson { 161598cd9ca7SRichard Henderson if (ctx->null_cond.c == TCG_COND_NEVER && ctx->null_lab == NULL) { 161698cd9ca7SRichard Henderson if (link != 0) { 161798cd9ca7SRichard Henderson copy_iaoq_entry(cpu_gr[link], ctx->iaoq_n, ctx->iaoq_n_var); 161898cd9ca7SRichard Henderson } 161998cd9ca7SRichard Henderson ctx->iaoq_n = dest; 162098cd9ca7SRichard Henderson if (is_n) { 162198cd9ca7SRichard Henderson ctx->null_cond.c = TCG_COND_ALWAYS; 162298cd9ca7SRichard Henderson } 1623869051eaSRichard Henderson return DISAS_NEXT; 162498cd9ca7SRichard Henderson } else { 162598cd9ca7SRichard Henderson nullify_over(ctx); 162698cd9ca7SRichard Henderson 162798cd9ca7SRichard Henderson if (link != 0) { 162898cd9ca7SRichard Henderson copy_iaoq_entry(cpu_gr[link], ctx->iaoq_n, ctx->iaoq_n_var); 162998cd9ca7SRichard Henderson } 163098cd9ca7SRichard Henderson 163198cd9ca7SRichard Henderson if (is_n && use_nullify_skip(ctx)) { 163298cd9ca7SRichard Henderson nullify_set(ctx, 0); 163398cd9ca7SRichard Henderson gen_goto_tb(ctx, 0, dest, dest + 4); 163498cd9ca7SRichard Henderson } else { 163598cd9ca7SRichard Henderson nullify_set(ctx, is_n); 163698cd9ca7SRichard Henderson gen_goto_tb(ctx, 0, ctx->iaoq_b, dest); 163798cd9ca7SRichard Henderson } 163898cd9ca7SRichard Henderson 1639869051eaSRichard Henderson nullify_end(ctx, DISAS_NEXT); 164098cd9ca7SRichard Henderson 164198cd9ca7SRichard Henderson nullify_set(ctx, 0); 164298cd9ca7SRichard Henderson gen_goto_tb(ctx, 1, ctx->iaoq_b, ctx->iaoq_n); 1643869051eaSRichard Henderson return DISAS_NORETURN; 164498cd9ca7SRichard Henderson } 164598cd9ca7SRichard Henderson } 164698cd9ca7SRichard Henderson 164798cd9ca7SRichard Henderson /* Emit a conditional branch to a direct target. If the branch itself 164898cd9ca7SRichard Henderson is nullified, we should have already used nullify_over. */ 1649eaa3783bSRichard Henderson static DisasJumpType do_cbranch(DisasContext *ctx, target_sreg disp, bool is_n, 165098cd9ca7SRichard Henderson DisasCond *cond) 165198cd9ca7SRichard Henderson { 1652eaa3783bSRichard Henderson target_ureg dest = iaoq_dest(ctx, disp); 165398cd9ca7SRichard Henderson TCGLabel *taken = NULL; 165498cd9ca7SRichard Henderson TCGCond c = cond->c; 165598cd9ca7SRichard Henderson bool n; 165698cd9ca7SRichard Henderson 165798cd9ca7SRichard Henderson assert(ctx->null_cond.c == TCG_COND_NEVER); 165898cd9ca7SRichard Henderson 165998cd9ca7SRichard Henderson /* Handle TRUE and NEVER as direct branches. */ 166098cd9ca7SRichard Henderson if (c == TCG_COND_ALWAYS) { 166198cd9ca7SRichard Henderson return do_dbranch(ctx, dest, 0, is_n && disp >= 0); 166298cd9ca7SRichard Henderson } 166398cd9ca7SRichard Henderson if (c == TCG_COND_NEVER) { 166498cd9ca7SRichard Henderson return do_dbranch(ctx, ctx->iaoq_n, 0, is_n && disp < 0); 166598cd9ca7SRichard Henderson } 166698cd9ca7SRichard Henderson 166798cd9ca7SRichard Henderson taken = gen_new_label(); 166898cd9ca7SRichard Henderson cond_prep(cond); 1669eaa3783bSRichard Henderson tcg_gen_brcond_reg(c, cond->a0, cond->a1, taken); 167098cd9ca7SRichard Henderson cond_free(cond); 167198cd9ca7SRichard Henderson 167298cd9ca7SRichard Henderson /* Not taken: Condition not satisfied; nullify on backward branches. */ 167398cd9ca7SRichard Henderson n = is_n && disp < 0; 167498cd9ca7SRichard Henderson if (n && use_nullify_skip(ctx)) { 167598cd9ca7SRichard Henderson nullify_set(ctx, 0); 1676a881c8e7SRichard Henderson gen_goto_tb(ctx, 0, ctx->iaoq_n, ctx->iaoq_n + 4); 167798cd9ca7SRichard Henderson } else { 167898cd9ca7SRichard Henderson if (!n && ctx->null_lab) { 167998cd9ca7SRichard Henderson gen_set_label(ctx->null_lab); 168098cd9ca7SRichard Henderson ctx->null_lab = NULL; 168198cd9ca7SRichard Henderson } 168298cd9ca7SRichard Henderson nullify_set(ctx, n); 1683a881c8e7SRichard Henderson gen_goto_tb(ctx, 0, ctx->iaoq_b, ctx->iaoq_n); 168498cd9ca7SRichard Henderson } 168598cd9ca7SRichard Henderson 168698cd9ca7SRichard Henderson gen_set_label(taken); 168798cd9ca7SRichard Henderson 168898cd9ca7SRichard Henderson /* Taken: Condition satisfied; nullify on forward branches. */ 168998cd9ca7SRichard Henderson n = is_n && disp >= 0; 169098cd9ca7SRichard Henderson if (n && use_nullify_skip(ctx)) { 169198cd9ca7SRichard Henderson nullify_set(ctx, 0); 1692a881c8e7SRichard Henderson gen_goto_tb(ctx, 1, dest, dest + 4); 169398cd9ca7SRichard Henderson } else { 169498cd9ca7SRichard Henderson nullify_set(ctx, n); 1695a881c8e7SRichard Henderson gen_goto_tb(ctx, 1, ctx->iaoq_b, dest); 169698cd9ca7SRichard Henderson } 169798cd9ca7SRichard Henderson 169898cd9ca7SRichard Henderson /* Not taken: the branch itself was nullified. */ 169998cd9ca7SRichard Henderson if (ctx->null_lab) { 170098cd9ca7SRichard Henderson gen_set_label(ctx->null_lab); 170198cd9ca7SRichard Henderson ctx->null_lab = NULL; 1702869051eaSRichard Henderson return DISAS_IAQ_N_STALE; 170398cd9ca7SRichard Henderson } else { 1704869051eaSRichard Henderson return DISAS_NORETURN; 170598cd9ca7SRichard Henderson } 170698cd9ca7SRichard Henderson } 170798cd9ca7SRichard Henderson 170898cd9ca7SRichard Henderson /* Emit an unconditional branch to an indirect target. This handles 170998cd9ca7SRichard Henderson nullification of the branch itself. */ 1710eaa3783bSRichard Henderson static DisasJumpType do_ibranch(DisasContext *ctx, TCGv_reg dest, 171198cd9ca7SRichard Henderson unsigned link, bool is_n) 171298cd9ca7SRichard Henderson { 1713eaa3783bSRichard Henderson TCGv_reg a0, a1, next, tmp; 171498cd9ca7SRichard Henderson TCGCond c; 171598cd9ca7SRichard Henderson 171698cd9ca7SRichard Henderson assert(ctx->null_lab == NULL); 171798cd9ca7SRichard Henderson 171898cd9ca7SRichard Henderson if (ctx->null_cond.c == TCG_COND_NEVER) { 171998cd9ca7SRichard Henderson if (link != 0) { 172098cd9ca7SRichard Henderson copy_iaoq_entry(cpu_gr[link], ctx->iaoq_n, ctx->iaoq_n_var); 172198cd9ca7SRichard Henderson } 172298cd9ca7SRichard Henderson next = get_temp(ctx); 1723eaa3783bSRichard Henderson tcg_gen_mov_reg(next, dest); 172498cd9ca7SRichard Henderson ctx->iaoq_n = -1; 172598cd9ca7SRichard Henderson ctx->iaoq_n_var = next; 172698cd9ca7SRichard Henderson if (is_n) { 172798cd9ca7SRichard Henderson ctx->null_cond.c = TCG_COND_ALWAYS; 172898cd9ca7SRichard Henderson } 172998cd9ca7SRichard Henderson } else if (is_n && use_nullify_skip(ctx)) { 173098cd9ca7SRichard Henderson /* The (conditional) branch, B, nullifies the next insn, N, 173198cd9ca7SRichard Henderson and we're allowed to skip execution N (no single-step or 17324137cb83SRichard Henderson tracepoint in effect). Since the goto_ptr that we must use 173398cd9ca7SRichard Henderson for the indirect branch consumes no special resources, we 173498cd9ca7SRichard Henderson can (conditionally) skip B and continue execution. */ 173598cd9ca7SRichard Henderson /* The use_nullify_skip test implies we have a known control path. */ 173698cd9ca7SRichard Henderson tcg_debug_assert(ctx->iaoq_b != -1); 173798cd9ca7SRichard Henderson tcg_debug_assert(ctx->iaoq_n != -1); 173898cd9ca7SRichard Henderson 173998cd9ca7SRichard Henderson /* We do have to handle the non-local temporary, DEST, before 174098cd9ca7SRichard Henderson branching. Since IOAQ_F is not really live at this point, we 174198cd9ca7SRichard Henderson can simply store DEST optimistically. Similarly with IAOQ_B. */ 1742eaa3783bSRichard Henderson tcg_gen_mov_reg(cpu_iaoq_f, dest); 1743eaa3783bSRichard Henderson tcg_gen_addi_reg(cpu_iaoq_b, dest, 4); 174498cd9ca7SRichard Henderson 174598cd9ca7SRichard Henderson nullify_over(ctx); 174698cd9ca7SRichard Henderson if (link != 0) { 1747eaa3783bSRichard Henderson tcg_gen_movi_reg(cpu_gr[link], ctx->iaoq_n); 174898cd9ca7SRichard Henderson } 17497f11636dSEmilio G. Cota tcg_gen_lookup_and_goto_ptr(); 1750869051eaSRichard Henderson return nullify_end(ctx, DISAS_NEXT); 175198cd9ca7SRichard Henderson } else { 175298cd9ca7SRichard Henderson cond_prep(&ctx->null_cond); 175398cd9ca7SRichard Henderson c = ctx->null_cond.c; 175498cd9ca7SRichard Henderson a0 = ctx->null_cond.a0; 175598cd9ca7SRichard Henderson a1 = ctx->null_cond.a1; 175698cd9ca7SRichard Henderson 175798cd9ca7SRichard Henderson tmp = tcg_temp_new(); 175898cd9ca7SRichard Henderson next = get_temp(ctx); 175998cd9ca7SRichard Henderson 176098cd9ca7SRichard Henderson copy_iaoq_entry(tmp, ctx->iaoq_n, ctx->iaoq_n_var); 1761eaa3783bSRichard Henderson tcg_gen_movcond_reg(c, next, a0, a1, tmp, dest); 176298cd9ca7SRichard Henderson ctx->iaoq_n = -1; 176398cd9ca7SRichard Henderson ctx->iaoq_n_var = next; 176498cd9ca7SRichard Henderson 176598cd9ca7SRichard Henderson if (link != 0) { 1766eaa3783bSRichard Henderson tcg_gen_movcond_reg(c, cpu_gr[link], a0, a1, cpu_gr[link], tmp); 176798cd9ca7SRichard Henderson } 176898cd9ca7SRichard Henderson 176998cd9ca7SRichard Henderson if (is_n) { 177098cd9ca7SRichard Henderson /* The branch nullifies the next insn, which means the state of N 177198cd9ca7SRichard Henderson after the branch is the inverse of the state of N that applied 177298cd9ca7SRichard Henderson to the branch. */ 1773eaa3783bSRichard Henderson tcg_gen_setcond_reg(tcg_invert_cond(c), cpu_psw_n, a0, a1); 177498cd9ca7SRichard Henderson cond_free(&ctx->null_cond); 177598cd9ca7SRichard Henderson ctx->null_cond = cond_make_n(); 177698cd9ca7SRichard Henderson ctx->psw_n_nonzero = true; 177798cd9ca7SRichard Henderson } else { 177898cd9ca7SRichard Henderson cond_free(&ctx->null_cond); 177998cd9ca7SRichard Henderson } 178098cd9ca7SRichard Henderson } 178198cd9ca7SRichard Henderson 1782869051eaSRichard Henderson return DISAS_NEXT; 178398cd9ca7SRichard Henderson } 178498cd9ca7SRichard Henderson 1785ba1d0b44SRichard Henderson #ifdef CONFIG_USER_ONLY 17867ad439dfSRichard Henderson /* On Linux, page zero is normally marked execute only + gateway. 17877ad439dfSRichard Henderson Therefore normal read or write is supposed to fail, but specific 17887ad439dfSRichard Henderson offsets have kernel code mapped to raise permissions to implement 17897ad439dfSRichard Henderson system calls. Handling this via an explicit check here, rather 17907ad439dfSRichard Henderson in than the "be disp(sr2,r0)" instruction that probably sent us 17917ad439dfSRichard Henderson here, is the easiest way to handle the branch delay slot on the 17927ad439dfSRichard Henderson aforementioned BE. */ 1793869051eaSRichard Henderson static DisasJumpType do_page_zero(DisasContext *ctx) 17947ad439dfSRichard Henderson { 17957ad439dfSRichard Henderson /* If by some means we get here with PSW[N]=1, that implies that 17967ad439dfSRichard Henderson the B,GATE instruction would be skipped, and we'd fault on the 17977ad439dfSRichard Henderson next insn within the privilaged page. */ 17987ad439dfSRichard Henderson switch (ctx->null_cond.c) { 17997ad439dfSRichard Henderson case TCG_COND_NEVER: 18007ad439dfSRichard Henderson break; 18017ad439dfSRichard Henderson case TCG_COND_ALWAYS: 1802eaa3783bSRichard Henderson tcg_gen_movi_reg(cpu_psw_n, 0); 18037ad439dfSRichard Henderson goto do_sigill; 18047ad439dfSRichard Henderson default: 18057ad439dfSRichard Henderson /* Since this is always the first (and only) insn within the 18067ad439dfSRichard Henderson TB, we should know the state of PSW[N] from TB->FLAGS. */ 18077ad439dfSRichard Henderson g_assert_not_reached(); 18087ad439dfSRichard Henderson } 18097ad439dfSRichard Henderson 18107ad439dfSRichard Henderson /* Check that we didn't arrive here via some means that allowed 18117ad439dfSRichard Henderson non-sequential instruction execution. Normally the PSW[B] bit 18127ad439dfSRichard Henderson detects this by disallowing the B,GATE instruction to execute 18137ad439dfSRichard Henderson under such conditions. */ 18147ad439dfSRichard Henderson if (ctx->iaoq_b != ctx->iaoq_f + 4) { 18157ad439dfSRichard Henderson goto do_sigill; 18167ad439dfSRichard Henderson } 18177ad439dfSRichard Henderson 18187ad439dfSRichard Henderson switch (ctx->iaoq_f) { 18197ad439dfSRichard Henderson case 0x00: /* Null pointer call */ 18202986721dSRichard Henderson gen_excp_1(EXCP_IMP); 1821869051eaSRichard Henderson return DISAS_NORETURN; 18227ad439dfSRichard Henderson 18237ad439dfSRichard Henderson case 0xb0: /* LWS */ 18247ad439dfSRichard Henderson gen_excp_1(EXCP_SYSCALL_LWS); 1825869051eaSRichard Henderson return DISAS_NORETURN; 18267ad439dfSRichard Henderson 18277ad439dfSRichard Henderson case 0xe0: /* SET_THREAD_POINTER */ 1828eaa3783bSRichard Henderson tcg_gen_mov_reg(cpu_cr27, cpu_gr[26]); 1829eaa3783bSRichard Henderson tcg_gen_mov_reg(cpu_iaoq_f, cpu_gr[31]); 1830eaa3783bSRichard Henderson tcg_gen_addi_reg(cpu_iaoq_b, cpu_iaoq_f, 4); 1831869051eaSRichard Henderson return DISAS_IAQ_N_UPDATED; 18327ad439dfSRichard Henderson 18337ad439dfSRichard Henderson case 0x100: /* SYSCALL */ 18347ad439dfSRichard Henderson gen_excp_1(EXCP_SYSCALL); 1835869051eaSRichard Henderson return DISAS_NORETURN; 18367ad439dfSRichard Henderson 18377ad439dfSRichard Henderson default: 18387ad439dfSRichard Henderson do_sigill: 18392986721dSRichard Henderson gen_excp_1(EXCP_ILL); 1840869051eaSRichard Henderson return DISAS_NORETURN; 18417ad439dfSRichard Henderson } 18427ad439dfSRichard Henderson } 1843ba1d0b44SRichard Henderson #endif 18447ad439dfSRichard Henderson 1845869051eaSRichard Henderson static DisasJumpType trans_nop(DisasContext *ctx, uint32_t insn, 1846b2167459SRichard Henderson const DisasInsn *di) 1847b2167459SRichard Henderson { 1848b2167459SRichard Henderson cond_free(&ctx->null_cond); 1849869051eaSRichard Henderson return DISAS_NEXT; 1850b2167459SRichard Henderson } 1851b2167459SRichard Henderson 1852869051eaSRichard Henderson static DisasJumpType trans_break(DisasContext *ctx, uint32_t insn, 185398a9cb79SRichard Henderson const DisasInsn *di) 185498a9cb79SRichard Henderson { 185598a9cb79SRichard Henderson nullify_over(ctx); 18562986721dSRichard Henderson return nullify_end(ctx, gen_excp(ctx, EXCP_BREAK)); 185798a9cb79SRichard Henderson } 185898a9cb79SRichard Henderson 1859869051eaSRichard Henderson static DisasJumpType trans_sync(DisasContext *ctx, uint32_t insn, 186098a9cb79SRichard Henderson const DisasInsn *di) 186198a9cb79SRichard Henderson { 186298a9cb79SRichard Henderson /* No point in nullifying the memory barrier. */ 186398a9cb79SRichard Henderson tcg_gen_mb(TCG_BAR_SC | TCG_MO_ALL); 186498a9cb79SRichard Henderson 186598a9cb79SRichard Henderson cond_free(&ctx->null_cond); 1866869051eaSRichard Henderson return DISAS_NEXT; 186798a9cb79SRichard Henderson } 186898a9cb79SRichard Henderson 1869869051eaSRichard Henderson static DisasJumpType trans_mfia(DisasContext *ctx, uint32_t insn, 187098a9cb79SRichard Henderson const DisasInsn *di) 187198a9cb79SRichard Henderson { 187298a9cb79SRichard Henderson unsigned rt = extract32(insn, 0, 5); 1873eaa3783bSRichard Henderson TCGv_reg tmp = dest_gpr(ctx, rt); 1874eaa3783bSRichard Henderson tcg_gen_movi_reg(tmp, ctx->iaoq_f); 187598a9cb79SRichard Henderson save_gpr(ctx, rt, tmp); 187698a9cb79SRichard Henderson 187798a9cb79SRichard Henderson cond_free(&ctx->null_cond); 1878869051eaSRichard Henderson return DISAS_NEXT; 187998a9cb79SRichard Henderson } 188098a9cb79SRichard Henderson 1881869051eaSRichard Henderson static DisasJumpType trans_mfsp(DisasContext *ctx, uint32_t insn, 188298a9cb79SRichard Henderson const DisasInsn *di) 188398a9cb79SRichard Henderson { 188498a9cb79SRichard Henderson unsigned rt = extract32(insn, 0, 5); 1885eaa3783bSRichard Henderson TCGv_reg tmp = dest_gpr(ctx, rt); 188698a9cb79SRichard Henderson 188798a9cb79SRichard Henderson /* ??? We don't implement space registers. */ 1888eaa3783bSRichard Henderson tcg_gen_movi_reg(tmp, 0); 188998a9cb79SRichard Henderson save_gpr(ctx, rt, tmp); 189098a9cb79SRichard Henderson 189198a9cb79SRichard Henderson cond_free(&ctx->null_cond); 1892869051eaSRichard Henderson return DISAS_NEXT; 189398a9cb79SRichard Henderson } 189498a9cb79SRichard Henderson 1895869051eaSRichard Henderson static DisasJumpType trans_mfctl(DisasContext *ctx, uint32_t insn, 189698a9cb79SRichard Henderson const DisasInsn *di) 189798a9cb79SRichard Henderson { 189898a9cb79SRichard Henderson unsigned rt = extract32(insn, 0, 5); 189998a9cb79SRichard Henderson unsigned ctl = extract32(insn, 21, 5); 1900eaa3783bSRichard Henderson TCGv_reg tmp; 190198a9cb79SRichard Henderson 190298a9cb79SRichard Henderson switch (ctl) { 190398a9cb79SRichard Henderson case 11: /* SAR */ 190498a9cb79SRichard Henderson #ifdef TARGET_HPPA64 190598a9cb79SRichard Henderson if (extract32(insn, 14, 1) == 0) { 190698a9cb79SRichard Henderson /* MFSAR without ,W masks low 5 bits. */ 190798a9cb79SRichard Henderson tmp = dest_gpr(ctx, rt); 1908eaa3783bSRichard Henderson tcg_gen_andi_reg(tmp, cpu_sar, 31); 190998a9cb79SRichard Henderson save_gpr(ctx, rt, tmp); 191098a9cb79SRichard Henderson break; 191198a9cb79SRichard Henderson } 191298a9cb79SRichard Henderson #endif 191398a9cb79SRichard Henderson save_gpr(ctx, rt, cpu_sar); 191498a9cb79SRichard Henderson break; 191598a9cb79SRichard Henderson case 16: /* Interval Timer */ 191698a9cb79SRichard Henderson tmp = dest_gpr(ctx, rt); 191798a9cb79SRichard Henderson tcg_gen_movi_tl(tmp, 0); /* FIXME */ 191898a9cb79SRichard Henderson save_gpr(ctx, rt, tmp); 191998a9cb79SRichard Henderson break; 192098a9cb79SRichard Henderson case 26: 192198a9cb79SRichard Henderson save_gpr(ctx, rt, cpu_cr26); 192298a9cb79SRichard Henderson break; 192398a9cb79SRichard Henderson case 27: 192498a9cb79SRichard Henderson save_gpr(ctx, rt, cpu_cr27); 192598a9cb79SRichard Henderson break; 192698a9cb79SRichard Henderson default: 192798a9cb79SRichard Henderson /* All other control registers are privileged. */ 192898a9cb79SRichard Henderson return gen_illegal(ctx); 192998a9cb79SRichard Henderson } 193098a9cb79SRichard Henderson 193198a9cb79SRichard Henderson cond_free(&ctx->null_cond); 1932869051eaSRichard Henderson return DISAS_NEXT; 193398a9cb79SRichard Henderson } 193498a9cb79SRichard Henderson 1935869051eaSRichard Henderson static DisasJumpType trans_mtctl(DisasContext *ctx, uint32_t insn, 193698a9cb79SRichard Henderson const DisasInsn *di) 193798a9cb79SRichard Henderson { 193898a9cb79SRichard Henderson unsigned rin = extract32(insn, 16, 5); 193998a9cb79SRichard Henderson unsigned ctl = extract32(insn, 21, 5); 1940eaa3783bSRichard Henderson TCGv_reg tmp; 194198a9cb79SRichard Henderson 194298a9cb79SRichard Henderson if (ctl == 11) { /* SAR */ 194398a9cb79SRichard Henderson tmp = tcg_temp_new(); 1944eaa3783bSRichard Henderson tcg_gen_andi_reg(tmp, load_gpr(ctx, rin), TARGET_REGISTER_BITS - 1); 194598a9cb79SRichard Henderson save_or_nullify(ctx, cpu_sar, tmp); 194698a9cb79SRichard Henderson tcg_temp_free(tmp); 194798a9cb79SRichard Henderson } else { 194898a9cb79SRichard Henderson /* All other control registers are privileged or read-only. */ 194998a9cb79SRichard Henderson return gen_illegal(ctx); 195098a9cb79SRichard Henderson } 195198a9cb79SRichard Henderson 195298a9cb79SRichard Henderson cond_free(&ctx->null_cond); 1953869051eaSRichard Henderson return DISAS_NEXT; 195498a9cb79SRichard Henderson } 195598a9cb79SRichard Henderson 1956869051eaSRichard Henderson static DisasJumpType trans_mtsarcm(DisasContext *ctx, uint32_t insn, 195798a9cb79SRichard Henderson const DisasInsn *di) 195898a9cb79SRichard Henderson { 195998a9cb79SRichard Henderson unsigned rin = extract32(insn, 16, 5); 1960eaa3783bSRichard Henderson TCGv_reg tmp = tcg_temp_new(); 196198a9cb79SRichard Henderson 1962eaa3783bSRichard Henderson tcg_gen_not_reg(tmp, load_gpr(ctx, rin)); 1963eaa3783bSRichard Henderson tcg_gen_andi_reg(tmp, tmp, TARGET_REGISTER_BITS - 1); 196498a9cb79SRichard Henderson save_or_nullify(ctx, cpu_sar, tmp); 196598a9cb79SRichard Henderson tcg_temp_free(tmp); 196698a9cb79SRichard Henderson 196798a9cb79SRichard Henderson cond_free(&ctx->null_cond); 1968869051eaSRichard Henderson return DISAS_NEXT; 196998a9cb79SRichard Henderson } 197098a9cb79SRichard Henderson 1971869051eaSRichard Henderson static DisasJumpType trans_ldsid(DisasContext *ctx, uint32_t insn, 197298a9cb79SRichard Henderson const DisasInsn *di) 197398a9cb79SRichard Henderson { 197498a9cb79SRichard Henderson unsigned rt = extract32(insn, 0, 5); 1975eaa3783bSRichard Henderson TCGv_reg dest = dest_gpr(ctx, rt); 197698a9cb79SRichard Henderson 197798a9cb79SRichard Henderson /* Since we don't implement space registers, this returns zero. */ 1978eaa3783bSRichard Henderson tcg_gen_movi_reg(dest, 0); 197998a9cb79SRichard Henderson save_gpr(ctx, rt, dest); 198098a9cb79SRichard Henderson 198198a9cb79SRichard Henderson cond_free(&ctx->null_cond); 1982869051eaSRichard Henderson return DISAS_NEXT; 198398a9cb79SRichard Henderson } 198498a9cb79SRichard Henderson 198598a9cb79SRichard Henderson static const DisasInsn table_system[] = { 198698a9cb79SRichard Henderson { 0x00000000u, 0xfc001fe0u, trans_break }, 198798a9cb79SRichard Henderson /* We don't implement space register, so MTSP is a nop. */ 198898a9cb79SRichard Henderson { 0x00001820u, 0xffe01fffu, trans_nop }, 198998a9cb79SRichard Henderson { 0x00001840u, 0xfc00ffffu, trans_mtctl }, 199098a9cb79SRichard Henderson { 0x016018c0u, 0xffe0ffffu, trans_mtsarcm }, 199198a9cb79SRichard Henderson { 0x000014a0u, 0xffffffe0u, trans_mfia }, 199298a9cb79SRichard Henderson { 0x000004a0u, 0xffff1fe0u, trans_mfsp }, 199398a9cb79SRichard Henderson { 0x000008a0u, 0xfc1fffe0u, trans_mfctl }, 199498a9cb79SRichard Henderson { 0x00000400u, 0xffffffffu, trans_sync }, 199598a9cb79SRichard Henderson { 0x000010a0u, 0xfc1f3fe0u, trans_ldsid }, 199698a9cb79SRichard Henderson }; 199798a9cb79SRichard Henderson 1998869051eaSRichard Henderson static DisasJumpType trans_base_idx_mod(DisasContext *ctx, uint32_t insn, 199998a9cb79SRichard Henderson const DisasInsn *di) 200098a9cb79SRichard Henderson { 200198a9cb79SRichard Henderson unsigned rb = extract32(insn, 21, 5); 200298a9cb79SRichard Henderson unsigned rx = extract32(insn, 16, 5); 2003eaa3783bSRichard Henderson TCGv_reg dest = dest_gpr(ctx, rb); 2004eaa3783bSRichard Henderson TCGv_reg src1 = load_gpr(ctx, rb); 2005eaa3783bSRichard Henderson TCGv_reg src2 = load_gpr(ctx, rx); 200698a9cb79SRichard Henderson 200798a9cb79SRichard Henderson /* The only thing we need to do is the base register modification. */ 2008eaa3783bSRichard Henderson tcg_gen_add_reg(dest, src1, src2); 200998a9cb79SRichard Henderson save_gpr(ctx, rb, dest); 201098a9cb79SRichard Henderson 201198a9cb79SRichard Henderson cond_free(&ctx->null_cond); 2012869051eaSRichard Henderson return DISAS_NEXT; 201398a9cb79SRichard Henderson } 201498a9cb79SRichard Henderson 2015869051eaSRichard Henderson static DisasJumpType trans_probe(DisasContext *ctx, uint32_t insn, 201698a9cb79SRichard Henderson const DisasInsn *di) 201798a9cb79SRichard Henderson { 201898a9cb79SRichard Henderson unsigned rt = extract32(insn, 0, 5); 201998a9cb79SRichard Henderson unsigned rb = extract32(insn, 21, 5); 202098a9cb79SRichard Henderson unsigned is_write = extract32(insn, 6, 1); 2021eaa3783bSRichard Henderson TCGv_reg dest; 202298a9cb79SRichard Henderson 202398a9cb79SRichard Henderson nullify_over(ctx); 202498a9cb79SRichard Henderson 202598a9cb79SRichard Henderson /* ??? Do something with priv level operand. */ 202698a9cb79SRichard Henderson dest = dest_gpr(ctx, rt); 202798a9cb79SRichard Henderson if (is_write) { 202898a9cb79SRichard Henderson gen_helper_probe_w(dest, load_gpr(ctx, rb)); 202998a9cb79SRichard Henderson } else { 203098a9cb79SRichard Henderson gen_helper_probe_r(dest, load_gpr(ctx, rb)); 203198a9cb79SRichard Henderson } 203298a9cb79SRichard Henderson save_gpr(ctx, rt, dest); 2033869051eaSRichard Henderson return nullify_end(ctx, DISAS_NEXT); 203498a9cb79SRichard Henderson } 203598a9cb79SRichard Henderson 203698a9cb79SRichard Henderson static const DisasInsn table_mem_mgmt[] = { 203798a9cb79SRichard Henderson { 0x04003280u, 0xfc003fffu, trans_nop }, /* fdc, disp */ 203898a9cb79SRichard Henderson { 0x04001280u, 0xfc003fffu, trans_nop }, /* fdc, index */ 203998a9cb79SRichard Henderson { 0x040012a0u, 0xfc003fffu, trans_base_idx_mod }, /* fdc, index, base mod */ 204098a9cb79SRichard Henderson { 0x040012c0u, 0xfc003fffu, trans_nop }, /* fdce */ 204198a9cb79SRichard Henderson { 0x040012e0u, 0xfc003fffu, trans_base_idx_mod }, /* fdce, base mod */ 204298a9cb79SRichard Henderson { 0x04000280u, 0xfc001fffu, trans_nop }, /* fic 0a */ 204398a9cb79SRichard Henderson { 0x040002a0u, 0xfc001fffu, trans_base_idx_mod }, /* fic 0a, base mod */ 204498a9cb79SRichard Henderson { 0x040013c0u, 0xfc003fffu, trans_nop }, /* fic 4f */ 204598a9cb79SRichard Henderson { 0x040013e0u, 0xfc003fffu, trans_base_idx_mod }, /* fic 4f, base mod */ 204698a9cb79SRichard Henderson { 0x040002c0u, 0xfc001fffu, trans_nop }, /* fice */ 204798a9cb79SRichard Henderson { 0x040002e0u, 0xfc001fffu, trans_base_idx_mod }, /* fice, base mod */ 204898a9cb79SRichard Henderson { 0x04002700u, 0xfc003fffu, trans_nop }, /* pdc */ 204998a9cb79SRichard Henderson { 0x04002720u, 0xfc003fffu, trans_base_idx_mod }, /* pdc, base mod */ 205098a9cb79SRichard Henderson { 0x04001180u, 0xfc003fa0u, trans_probe }, /* probe */ 205198a9cb79SRichard Henderson { 0x04003180u, 0xfc003fa0u, trans_probe }, /* probei */ 205298a9cb79SRichard Henderson }; 205398a9cb79SRichard Henderson 2054869051eaSRichard Henderson static DisasJumpType trans_add(DisasContext *ctx, uint32_t insn, 2055b2167459SRichard Henderson const DisasInsn *di) 2056b2167459SRichard Henderson { 2057b2167459SRichard Henderson unsigned r2 = extract32(insn, 21, 5); 2058b2167459SRichard Henderson unsigned r1 = extract32(insn, 16, 5); 2059b2167459SRichard Henderson unsigned cf = extract32(insn, 12, 4); 2060b2167459SRichard Henderson unsigned ext = extract32(insn, 8, 4); 2061b2167459SRichard Henderson unsigned shift = extract32(insn, 6, 2); 2062b2167459SRichard Henderson unsigned rt = extract32(insn, 0, 5); 2063eaa3783bSRichard Henderson TCGv_reg tcg_r1, tcg_r2; 2064b2167459SRichard Henderson bool is_c = false; 2065b2167459SRichard Henderson bool is_l = false; 2066b2167459SRichard Henderson bool is_tc = false; 2067b2167459SRichard Henderson bool is_tsv = false; 2068869051eaSRichard Henderson DisasJumpType ret; 2069b2167459SRichard Henderson 2070b2167459SRichard Henderson switch (ext) { 2071b2167459SRichard Henderson case 0x6: /* ADD, SHLADD */ 2072b2167459SRichard Henderson break; 2073b2167459SRichard Henderson case 0xa: /* ADD,L, SHLADD,L */ 2074b2167459SRichard Henderson is_l = true; 2075b2167459SRichard Henderson break; 2076b2167459SRichard Henderson case 0xe: /* ADD,TSV, SHLADD,TSV (1) */ 2077b2167459SRichard Henderson is_tsv = true; 2078b2167459SRichard Henderson break; 2079b2167459SRichard Henderson case 0x7: /* ADD,C */ 2080b2167459SRichard Henderson is_c = true; 2081b2167459SRichard Henderson break; 2082b2167459SRichard Henderson case 0xf: /* ADD,C,TSV */ 2083b2167459SRichard Henderson is_c = is_tsv = true; 2084b2167459SRichard Henderson break; 2085b2167459SRichard Henderson default: 2086b2167459SRichard Henderson return gen_illegal(ctx); 2087b2167459SRichard Henderson } 2088b2167459SRichard Henderson 2089b2167459SRichard Henderson if (cf) { 2090b2167459SRichard Henderson nullify_over(ctx); 2091b2167459SRichard Henderson } 2092b2167459SRichard Henderson tcg_r1 = load_gpr(ctx, r1); 2093b2167459SRichard Henderson tcg_r2 = load_gpr(ctx, r2); 2094b2167459SRichard Henderson ret = do_add(ctx, rt, tcg_r1, tcg_r2, shift, is_l, is_tsv, is_tc, is_c, cf); 2095b2167459SRichard Henderson return nullify_end(ctx, ret); 2096b2167459SRichard Henderson } 2097b2167459SRichard Henderson 2098869051eaSRichard Henderson static DisasJumpType trans_sub(DisasContext *ctx, uint32_t insn, 2099b2167459SRichard Henderson const DisasInsn *di) 2100b2167459SRichard Henderson { 2101b2167459SRichard Henderson unsigned r2 = extract32(insn, 21, 5); 2102b2167459SRichard Henderson unsigned r1 = extract32(insn, 16, 5); 2103b2167459SRichard Henderson unsigned cf = extract32(insn, 12, 4); 2104b2167459SRichard Henderson unsigned ext = extract32(insn, 6, 6); 2105b2167459SRichard Henderson unsigned rt = extract32(insn, 0, 5); 2106eaa3783bSRichard Henderson TCGv_reg tcg_r1, tcg_r2; 2107b2167459SRichard Henderson bool is_b = false; 2108b2167459SRichard Henderson bool is_tc = false; 2109b2167459SRichard Henderson bool is_tsv = false; 2110869051eaSRichard Henderson DisasJumpType ret; 2111b2167459SRichard Henderson 2112b2167459SRichard Henderson switch (ext) { 2113b2167459SRichard Henderson case 0x10: /* SUB */ 2114b2167459SRichard Henderson break; 2115b2167459SRichard Henderson case 0x30: /* SUB,TSV */ 2116b2167459SRichard Henderson is_tsv = true; 2117b2167459SRichard Henderson break; 2118b2167459SRichard Henderson case 0x14: /* SUB,B */ 2119b2167459SRichard Henderson is_b = true; 2120b2167459SRichard Henderson break; 2121b2167459SRichard Henderson case 0x34: /* SUB,B,TSV */ 2122b2167459SRichard Henderson is_b = is_tsv = true; 2123b2167459SRichard Henderson break; 2124b2167459SRichard Henderson case 0x13: /* SUB,TC */ 2125b2167459SRichard Henderson is_tc = true; 2126b2167459SRichard Henderson break; 2127b2167459SRichard Henderson case 0x33: /* SUB,TSV,TC */ 2128b2167459SRichard Henderson is_tc = is_tsv = true; 2129b2167459SRichard Henderson break; 2130b2167459SRichard Henderson default: 2131b2167459SRichard Henderson return gen_illegal(ctx); 2132b2167459SRichard Henderson } 2133b2167459SRichard Henderson 2134b2167459SRichard Henderson if (cf) { 2135b2167459SRichard Henderson nullify_over(ctx); 2136b2167459SRichard Henderson } 2137b2167459SRichard Henderson tcg_r1 = load_gpr(ctx, r1); 2138b2167459SRichard Henderson tcg_r2 = load_gpr(ctx, r2); 2139b2167459SRichard Henderson ret = do_sub(ctx, rt, tcg_r1, tcg_r2, is_tsv, is_b, is_tc, cf); 2140b2167459SRichard Henderson return nullify_end(ctx, ret); 2141b2167459SRichard Henderson } 2142b2167459SRichard Henderson 2143869051eaSRichard Henderson static DisasJumpType trans_log(DisasContext *ctx, uint32_t insn, 2144b2167459SRichard Henderson const DisasInsn *di) 2145b2167459SRichard Henderson { 2146b2167459SRichard Henderson unsigned r2 = extract32(insn, 21, 5); 2147b2167459SRichard Henderson unsigned r1 = extract32(insn, 16, 5); 2148b2167459SRichard Henderson unsigned cf = extract32(insn, 12, 4); 2149b2167459SRichard Henderson unsigned rt = extract32(insn, 0, 5); 2150eaa3783bSRichard Henderson TCGv_reg tcg_r1, tcg_r2; 2151869051eaSRichard Henderson DisasJumpType ret; 2152b2167459SRichard Henderson 2153b2167459SRichard Henderson if (cf) { 2154b2167459SRichard Henderson nullify_over(ctx); 2155b2167459SRichard Henderson } 2156b2167459SRichard Henderson tcg_r1 = load_gpr(ctx, r1); 2157b2167459SRichard Henderson tcg_r2 = load_gpr(ctx, r2); 2158eff235ebSPaolo Bonzini ret = do_log(ctx, rt, tcg_r1, tcg_r2, cf, di->f.ttt); 2159b2167459SRichard Henderson return nullify_end(ctx, ret); 2160b2167459SRichard Henderson } 2161b2167459SRichard Henderson 2162b2167459SRichard Henderson /* OR r,0,t -> COPY (according to gas) */ 2163869051eaSRichard Henderson static DisasJumpType trans_copy(DisasContext *ctx, uint32_t insn, 2164b2167459SRichard Henderson const DisasInsn *di) 2165b2167459SRichard Henderson { 2166b2167459SRichard Henderson unsigned r1 = extract32(insn, 16, 5); 2167b2167459SRichard Henderson unsigned rt = extract32(insn, 0, 5); 2168b2167459SRichard Henderson 2169b2167459SRichard Henderson if (r1 == 0) { 2170eaa3783bSRichard Henderson TCGv_reg dest = dest_gpr(ctx, rt); 2171eaa3783bSRichard Henderson tcg_gen_movi_reg(dest, 0); 2172b2167459SRichard Henderson save_gpr(ctx, rt, dest); 2173b2167459SRichard Henderson } else { 2174b2167459SRichard Henderson save_gpr(ctx, rt, cpu_gr[r1]); 2175b2167459SRichard Henderson } 2176b2167459SRichard Henderson cond_free(&ctx->null_cond); 2177869051eaSRichard Henderson return DISAS_NEXT; 2178b2167459SRichard Henderson } 2179b2167459SRichard Henderson 2180869051eaSRichard Henderson static DisasJumpType trans_cmpclr(DisasContext *ctx, uint32_t insn, 2181b2167459SRichard Henderson const DisasInsn *di) 2182b2167459SRichard Henderson { 2183b2167459SRichard Henderson unsigned r2 = extract32(insn, 21, 5); 2184b2167459SRichard Henderson unsigned r1 = extract32(insn, 16, 5); 2185b2167459SRichard Henderson unsigned cf = extract32(insn, 12, 4); 2186b2167459SRichard Henderson unsigned rt = extract32(insn, 0, 5); 2187eaa3783bSRichard Henderson TCGv_reg tcg_r1, tcg_r2; 2188869051eaSRichard Henderson DisasJumpType ret; 2189b2167459SRichard Henderson 2190b2167459SRichard Henderson if (cf) { 2191b2167459SRichard Henderson nullify_over(ctx); 2192b2167459SRichard Henderson } 2193b2167459SRichard Henderson tcg_r1 = load_gpr(ctx, r1); 2194b2167459SRichard Henderson tcg_r2 = load_gpr(ctx, r2); 2195b2167459SRichard Henderson ret = do_cmpclr(ctx, rt, tcg_r1, tcg_r2, cf); 2196b2167459SRichard Henderson return nullify_end(ctx, ret); 2197b2167459SRichard Henderson } 2198b2167459SRichard Henderson 2199869051eaSRichard Henderson static DisasJumpType trans_uxor(DisasContext *ctx, uint32_t insn, 2200b2167459SRichard Henderson const DisasInsn *di) 2201b2167459SRichard Henderson { 2202b2167459SRichard Henderson unsigned r2 = extract32(insn, 21, 5); 2203b2167459SRichard Henderson unsigned r1 = extract32(insn, 16, 5); 2204b2167459SRichard Henderson unsigned cf = extract32(insn, 12, 4); 2205b2167459SRichard Henderson unsigned rt = extract32(insn, 0, 5); 2206eaa3783bSRichard Henderson TCGv_reg tcg_r1, tcg_r2; 2207869051eaSRichard Henderson DisasJumpType ret; 2208b2167459SRichard Henderson 2209b2167459SRichard Henderson if (cf) { 2210b2167459SRichard Henderson nullify_over(ctx); 2211b2167459SRichard Henderson } 2212b2167459SRichard Henderson tcg_r1 = load_gpr(ctx, r1); 2213b2167459SRichard Henderson tcg_r2 = load_gpr(ctx, r2); 2214eaa3783bSRichard Henderson ret = do_unit(ctx, rt, tcg_r1, tcg_r2, cf, false, tcg_gen_xor_reg); 2215b2167459SRichard Henderson return nullify_end(ctx, ret); 2216b2167459SRichard Henderson } 2217b2167459SRichard Henderson 2218869051eaSRichard Henderson static DisasJumpType trans_uaddcm(DisasContext *ctx, uint32_t insn, 2219b2167459SRichard Henderson const DisasInsn *di) 2220b2167459SRichard Henderson { 2221b2167459SRichard Henderson unsigned r2 = extract32(insn, 21, 5); 2222b2167459SRichard Henderson unsigned r1 = extract32(insn, 16, 5); 2223b2167459SRichard Henderson unsigned cf = extract32(insn, 12, 4); 2224b2167459SRichard Henderson unsigned is_tc = extract32(insn, 6, 1); 2225b2167459SRichard Henderson unsigned rt = extract32(insn, 0, 5); 2226eaa3783bSRichard Henderson TCGv_reg tcg_r1, tcg_r2, tmp; 2227869051eaSRichard Henderson DisasJumpType ret; 2228b2167459SRichard Henderson 2229b2167459SRichard Henderson if (cf) { 2230b2167459SRichard Henderson nullify_over(ctx); 2231b2167459SRichard Henderson } 2232b2167459SRichard Henderson tcg_r1 = load_gpr(ctx, r1); 2233b2167459SRichard Henderson tcg_r2 = load_gpr(ctx, r2); 2234b2167459SRichard Henderson tmp = get_temp(ctx); 2235eaa3783bSRichard Henderson tcg_gen_not_reg(tmp, tcg_r2); 2236eaa3783bSRichard Henderson ret = do_unit(ctx, rt, tcg_r1, tmp, cf, is_tc, tcg_gen_add_reg); 2237b2167459SRichard Henderson return nullify_end(ctx, ret); 2238b2167459SRichard Henderson } 2239b2167459SRichard Henderson 2240869051eaSRichard Henderson static DisasJumpType trans_dcor(DisasContext *ctx, uint32_t insn, 2241b2167459SRichard Henderson const DisasInsn *di) 2242b2167459SRichard Henderson { 2243b2167459SRichard Henderson unsigned r2 = extract32(insn, 21, 5); 2244b2167459SRichard Henderson unsigned cf = extract32(insn, 12, 4); 2245b2167459SRichard Henderson unsigned is_i = extract32(insn, 6, 1); 2246b2167459SRichard Henderson unsigned rt = extract32(insn, 0, 5); 2247eaa3783bSRichard Henderson TCGv_reg tmp; 2248869051eaSRichard Henderson DisasJumpType ret; 2249b2167459SRichard Henderson 2250b2167459SRichard Henderson nullify_over(ctx); 2251b2167459SRichard Henderson 2252b2167459SRichard Henderson tmp = get_temp(ctx); 2253eaa3783bSRichard Henderson tcg_gen_shri_reg(tmp, cpu_psw_cb, 3); 2254b2167459SRichard Henderson if (!is_i) { 2255eaa3783bSRichard Henderson tcg_gen_not_reg(tmp, tmp); 2256b2167459SRichard Henderson } 2257eaa3783bSRichard Henderson tcg_gen_andi_reg(tmp, tmp, 0x11111111); 2258eaa3783bSRichard Henderson tcg_gen_muli_reg(tmp, tmp, 6); 2259b2167459SRichard Henderson ret = do_unit(ctx, rt, tmp, load_gpr(ctx, r2), cf, false, 2260eaa3783bSRichard Henderson is_i ? tcg_gen_add_reg : tcg_gen_sub_reg); 2261b2167459SRichard Henderson 2262b2167459SRichard Henderson return nullify_end(ctx, ret); 2263b2167459SRichard Henderson } 2264b2167459SRichard Henderson 2265869051eaSRichard Henderson static DisasJumpType trans_ds(DisasContext *ctx, uint32_t insn, 2266b2167459SRichard Henderson const DisasInsn *di) 2267b2167459SRichard Henderson { 2268b2167459SRichard Henderson unsigned r2 = extract32(insn, 21, 5); 2269b2167459SRichard Henderson unsigned r1 = extract32(insn, 16, 5); 2270b2167459SRichard Henderson unsigned cf = extract32(insn, 12, 4); 2271b2167459SRichard Henderson unsigned rt = extract32(insn, 0, 5); 2272eaa3783bSRichard Henderson TCGv_reg dest, add1, add2, addc, zero, in1, in2; 2273b2167459SRichard Henderson 2274b2167459SRichard Henderson nullify_over(ctx); 2275b2167459SRichard Henderson 2276b2167459SRichard Henderson in1 = load_gpr(ctx, r1); 2277b2167459SRichard Henderson in2 = load_gpr(ctx, r2); 2278b2167459SRichard Henderson 2279b2167459SRichard Henderson add1 = tcg_temp_new(); 2280b2167459SRichard Henderson add2 = tcg_temp_new(); 2281b2167459SRichard Henderson addc = tcg_temp_new(); 2282b2167459SRichard Henderson dest = tcg_temp_new(); 2283eaa3783bSRichard Henderson zero = tcg_const_reg(0); 2284b2167459SRichard Henderson 2285b2167459SRichard Henderson /* Form R1 << 1 | PSW[CB]{8}. */ 2286eaa3783bSRichard Henderson tcg_gen_add_reg(add1, in1, in1); 2287eaa3783bSRichard Henderson tcg_gen_add_reg(add1, add1, cpu_psw_cb_msb); 2288b2167459SRichard Henderson 2289b2167459SRichard Henderson /* Add or subtract R2, depending on PSW[V]. Proper computation of 2290b2167459SRichard Henderson carry{8} requires that we subtract via + ~R2 + 1, as described in 2291b2167459SRichard Henderson the manual. By extracting and masking V, we can produce the 2292b2167459SRichard Henderson proper inputs to the addition without movcond. */ 2293eaa3783bSRichard Henderson tcg_gen_sari_reg(addc, cpu_psw_v, TARGET_REGISTER_BITS - 1); 2294eaa3783bSRichard Henderson tcg_gen_xor_reg(add2, in2, addc); 2295eaa3783bSRichard Henderson tcg_gen_andi_reg(addc, addc, 1); 2296b2167459SRichard Henderson /* ??? This is only correct for 32-bit. */ 2297b2167459SRichard Henderson tcg_gen_add2_i32(dest, cpu_psw_cb_msb, add1, zero, add2, zero); 2298b2167459SRichard Henderson tcg_gen_add2_i32(dest, cpu_psw_cb_msb, dest, cpu_psw_cb_msb, addc, zero); 2299b2167459SRichard Henderson 2300b2167459SRichard Henderson tcg_temp_free(addc); 2301b2167459SRichard Henderson tcg_temp_free(zero); 2302b2167459SRichard Henderson 2303b2167459SRichard Henderson /* Write back the result register. */ 2304b2167459SRichard Henderson save_gpr(ctx, rt, dest); 2305b2167459SRichard Henderson 2306b2167459SRichard Henderson /* Write back PSW[CB]. */ 2307eaa3783bSRichard Henderson tcg_gen_xor_reg(cpu_psw_cb, add1, add2); 2308eaa3783bSRichard Henderson tcg_gen_xor_reg(cpu_psw_cb, cpu_psw_cb, dest); 2309b2167459SRichard Henderson 2310b2167459SRichard Henderson /* Write back PSW[V] for the division step. */ 2311eaa3783bSRichard Henderson tcg_gen_neg_reg(cpu_psw_v, cpu_psw_cb_msb); 2312eaa3783bSRichard Henderson tcg_gen_xor_reg(cpu_psw_v, cpu_psw_v, in2); 2313b2167459SRichard Henderson 2314b2167459SRichard Henderson /* Install the new nullification. */ 2315b2167459SRichard Henderson if (cf) { 2316eaa3783bSRichard Henderson TCGv_reg sv = NULL; 2317b2167459SRichard Henderson if (cf >> 1 == 6) { 2318b2167459SRichard Henderson /* ??? The lshift is supposed to contribute to overflow. */ 2319b2167459SRichard Henderson sv = do_add_sv(ctx, dest, add1, add2); 2320b2167459SRichard Henderson } 2321b2167459SRichard Henderson ctx->null_cond = do_cond(cf, dest, cpu_psw_cb_msb, sv); 2322b2167459SRichard Henderson } 2323b2167459SRichard Henderson 2324b2167459SRichard Henderson tcg_temp_free(add1); 2325b2167459SRichard Henderson tcg_temp_free(add2); 2326b2167459SRichard Henderson tcg_temp_free(dest); 2327b2167459SRichard Henderson 2328869051eaSRichard Henderson return nullify_end(ctx, DISAS_NEXT); 2329b2167459SRichard Henderson } 2330b2167459SRichard Henderson 2331b2167459SRichard Henderson static const DisasInsn table_arith_log[] = { 2332b2167459SRichard Henderson { 0x08000240u, 0xfc00ffffu, trans_nop }, /* or x,y,0 */ 2333b2167459SRichard Henderson { 0x08000240u, 0xffe0ffe0u, trans_copy }, /* or x,0,t */ 2334eaa3783bSRichard Henderson { 0x08000000u, 0xfc000fe0u, trans_log, .f.ttt = tcg_gen_andc_reg }, 2335eaa3783bSRichard Henderson { 0x08000200u, 0xfc000fe0u, trans_log, .f.ttt = tcg_gen_and_reg }, 2336eaa3783bSRichard Henderson { 0x08000240u, 0xfc000fe0u, trans_log, .f.ttt = tcg_gen_or_reg }, 2337eaa3783bSRichard Henderson { 0x08000280u, 0xfc000fe0u, trans_log, .f.ttt = tcg_gen_xor_reg }, 2338b2167459SRichard Henderson { 0x08000880u, 0xfc000fe0u, trans_cmpclr }, 2339b2167459SRichard Henderson { 0x08000380u, 0xfc000fe0u, trans_uxor }, 2340b2167459SRichard Henderson { 0x08000980u, 0xfc000fa0u, trans_uaddcm }, 2341b2167459SRichard Henderson { 0x08000b80u, 0xfc1f0fa0u, trans_dcor }, 2342b2167459SRichard Henderson { 0x08000440u, 0xfc000fe0u, trans_ds }, 2343b2167459SRichard Henderson { 0x08000700u, 0xfc0007e0u, trans_add }, /* add */ 2344b2167459SRichard Henderson { 0x08000400u, 0xfc0006e0u, trans_sub }, /* sub; sub,b; sub,tsv */ 2345b2167459SRichard Henderson { 0x080004c0u, 0xfc0007e0u, trans_sub }, /* sub,tc; sub,tsv,tc */ 2346b2167459SRichard Henderson { 0x08000200u, 0xfc000320u, trans_add }, /* shladd */ 2347b2167459SRichard Henderson }; 2348b2167459SRichard Henderson 2349869051eaSRichard Henderson static DisasJumpType trans_addi(DisasContext *ctx, uint32_t insn) 2350b2167459SRichard Henderson { 2351eaa3783bSRichard Henderson target_sreg im = low_sextract(insn, 0, 11); 2352b2167459SRichard Henderson unsigned e1 = extract32(insn, 11, 1); 2353b2167459SRichard Henderson unsigned cf = extract32(insn, 12, 4); 2354b2167459SRichard Henderson unsigned rt = extract32(insn, 16, 5); 2355b2167459SRichard Henderson unsigned r2 = extract32(insn, 21, 5); 2356b2167459SRichard Henderson unsigned o1 = extract32(insn, 26, 1); 2357eaa3783bSRichard Henderson TCGv_reg tcg_im, tcg_r2; 2358869051eaSRichard Henderson DisasJumpType ret; 2359b2167459SRichard Henderson 2360b2167459SRichard Henderson if (cf) { 2361b2167459SRichard Henderson nullify_over(ctx); 2362b2167459SRichard Henderson } 2363b2167459SRichard Henderson 2364b2167459SRichard Henderson tcg_im = load_const(ctx, im); 2365b2167459SRichard Henderson tcg_r2 = load_gpr(ctx, r2); 2366b2167459SRichard Henderson ret = do_add(ctx, rt, tcg_im, tcg_r2, 0, false, e1, !o1, false, cf); 2367b2167459SRichard Henderson 2368b2167459SRichard Henderson return nullify_end(ctx, ret); 2369b2167459SRichard Henderson } 2370b2167459SRichard Henderson 2371869051eaSRichard Henderson static DisasJumpType trans_subi(DisasContext *ctx, uint32_t insn) 2372b2167459SRichard Henderson { 2373eaa3783bSRichard Henderson target_sreg im = low_sextract(insn, 0, 11); 2374b2167459SRichard Henderson unsigned e1 = extract32(insn, 11, 1); 2375b2167459SRichard Henderson unsigned cf = extract32(insn, 12, 4); 2376b2167459SRichard Henderson unsigned rt = extract32(insn, 16, 5); 2377b2167459SRichard Henderson unsigned r2 = extract32(insn, 21, 5); 2378eaa3783bSRichard Henderson TCGv_reg tcg_im, tcg_r2; 2379869051eaSRichard Henderson DisasJumpType ret; 2380b2167459SRichard Henderson 2381b2167459SRichard Henderson if (cf) { 2382b2167459SRichard Henderson nullify_over(ctx); 2383b2167459SRichard Henderson } 2384b2167459SRichard Henderson 2385b2167459SRichard Henderson tcg_im = load_const(ctx, im); 2386b2167459SRichard Henderson tcg_r2 = load_gpr(ctx, r2); 2387b2167459SRichard Henderson ret = do_sub(ctx, rt, tcg_im, tcg_r2, e1, false, false, cf); 2388b2167459SRichard Henderson 2389b2167459SRichard Henderson return nullify_end(ctx, ret); 2390b2167459SRichard Henderson } 2391b2167459SRichard Henderson 2392869051eaSRichard Henderson static DisasJumpType trans_cmpiclr(DisasContext *ctx, uint32_t insn) 2393b2167459SRichard Henderson { 2394eaa3783bSRichard Henderson target_sreg im = low_sextract(insn, 0, 11); 2395b2167459SRichard Henderson unsigned cf = extract32(insn, 12, 4); 2396b2167459SRichard Henderson unsigned rt = extract32(insn, 16, 5); 2397b2167459SRichard Henderson unsigned r2 = extract32(insn, 21, 5); 2398eaa3783bSRichard Henderson TCGv_reg tcg_im, tcg_r2; 2399869051eaSRichard Henderson DisasJumpType ret; 2400b2167459SRichard Henderson 2401b2167459SRichard Henderson if (cf) { 2402b2167459SRichard Henderson nullify_over(ctx); 2403b2167459SRichard Henderson } 2404b2167459SRichard Henderson 2405b2167459SRichard Henderson tcg_im = load_const(ctx, im); 2406b2167459SRichard Henderson tcg_r2 = load_gpr(ctx, r2); 2407b2167459SRichard Henderson ret = do_cmpclr(ctx, rt, tcg_im, tcg_r2, cf); 2408b2167459SRichard Henderson 2409b2167459SRichard Henderson return nullify_end(ctx, ret); 2410b2167459SRichard Henderson } 2411b2167459SRichard Henderson 2412869051eaSRichard Henderson static DisasJumpType trans_ld_idx_i(DisasContext *ctx, uint32_t insn, 241396d6407fSRichard Henderson const DisasInsn *di) 241496d6407fSRichard Henderson { 241596d6407fSRichard Henderson unsigned rt = extract32(insn, 0, 5); 241696d6407fSRichard Henderson unsigned m = extract32(insn, 5, 1); 241796d6407fSRichard Henderson unsigned sz = extract32(insn, 6, 2); 241896d6407fSRichard Henderson unsigned a = extract32(insn, 13, 1); 241996d6407fSRichard Henderson int disp = low_sextract(insn, 16, 5); 242096d6407fSRichard Henderson unsigned rb = extract32(insn, 21, 5); 242196d6407fSRichard Henderson int modify = (m ? (a ? -1 : 1) : 0); 242296d6407fSRichard Henderson TCGMemOp mop = MO_TE | sz; 242396d6407fSRichard Henderson 242496d6407fSRichard Henderson return do_load(ctx, rt, rb, 0, 0, disp, modify, mop); 242596d6407fSRichard Henderson } 242696d6407fSRichard Henderson 2427869051eaSRichard Henderson static DisasJumpType trans_ld_idx_x(DisasContext *ctx, uint32_t insn, 242896d6407fSRichard Henderson const DisasInsn *di) 242996d6407fSRichard Henderson { 243096d6407fSRichard Henderson unsigned rt = extract32(insn, 0, 5); 243196d6407fSRichard Henderson unsigned m = extract32(insn, 5, 1); 243296d6407fSRichard Henderson unsigned sz = extract32(insn, 6, 2); 243396d6407fSRichard Henderson unsigned u = extract32(insn, 13, 1); 243496d6407fSRichard Henderson unsigned rx = extract32(insn, 16, 5); 243596d6407fSRichard Henderson unsigned rb = extract32(insn, 21, 5); 243696d6407fSRichard Henderson TCGMemOp mop = MO_TE | sz; 243796d6407fSRichard Henderson 243896d6407fSRichard Henderson return do_load(ctx, rt, rb, rx, u ? sz : 0, 0, m, mop); 243996d6407fSRichard Henderson } 244096d6407fSRichard Henderson 2441869051eaSRichard Henderson static DisasJumpType trans_st_idx_i(DisasContext *ctx, uint32_t insn, 244296d6407fSRichard Henderson const DisasInsn *di) 244396d6407fSRichard Henderson { 244496d6407fSRichard Henderson int disp = low_sextract(insn, 0, 5); 244596d6407fSRichard Henderson unsigned m = extract32(insn, 5, 1); 244696d6407fSRichard Henderson unsigned sz = extract32(insn, 6, 2); 244796d6407fSRichard Henderson unsigned a = extract32(insn, 13, 1); 244896d6407fSRichard Henderson unsigned rr = extract32(insn, 16, 5); 244996d6407fSRichard Henderson unsigned rb = extract32(insn, 21, 5); 245096d6407fSRichard Henderson int modify = (m ? (a ? -1 : 1) : 0); 245196d6407fSRichard Henderson TCGMemOp mop = MO_TE | sz; 245296d6407fSRichard Henderson 245396d6407fSRichard Henderson return do_store(ctx, rr, rb, disp, modify, mop); 245496d6407fSRichard Henderson } 245596d6407fSRichard Henderson 2456869051eaSRichard Henderson static DisasJumpType trans_ldcw(DisasContext *ctx, uint32_t insn, 245796d6407fSRichard Henderson const DisasInsn *di) 245896d6407fSRichard Henderson { 245996d6407fSRichard Henderson unsigned rt = extract32(insn, 0, 5); 246096d6407fSRichard Henderson unsigned m = extract32(insn, 5, 1); 246196d6407fSRichard Henderson unsigned i = extract32(insn, 12, 1); 246296d6407fSRichard Henderson unsigned au = extract32(insn, 13, 1); 246396d6407fSRichard Henderson unsigned rx = extract32(insn, 16, 5); 246496d6407fSRichard Henderson unsigned rb = extract32(insn, 21, 5); 246596d6407fSRichard Henderson TCGMemOp mop = MO_TEUL | MO_ALIGN_16; 2466eaa3783bSRichard Henderson TCGv_reg zero, addr, base, dest; 246796d6407fSRichard Henderson int modify, disp = 0, scale = 0; 246896d6407fSRichard Henderson 246996d6407fSRichard Henderson nullify_over(ctx); 247096d6407fSRichard Henderson 247196d6407fSRichard Henderson /* ??? Share more code with do_load and do_load_{32,64}. */ 247296d6407fSRichard Henderson 247396d6407fSRichard Henderson if (i) { 247496d6407fSRichard Henderson modify = (m ? (au ? -1 : 1) : 0); 247596d6407fSRichard Henderson disp = low_sextract(rx, 0, 5); 247696d6407fSRichard Henderson rx = 0; 247796d6407fSRichard Henderson } else { 247896d6407fSRichard Henderson modify = m; 247996d6407fSRichard Henderson if (au) { 248096d6407fSRichard Henderson scale = mop & MO_SIZE; 248196d6407fSRichard Henderson } 248296d6407fSRichard Henderson } 248396d6407fSRichard Henderson if (modify) { 248496d6407fSRichard Henderson /* Base register modification. Make sure if RT == RB, we see 248596d6407fSRichard Henderson the result of the load. */ 248696d6407fSRichard Henderson dest = get_temp(ctx); 248796d6407fSRichard Henderson } else { 248896d6407fSRichard Henderson dest = dest_gpr(ctx, rt); 248996d6407fSRichard Henderson } 249096d6407fSRichard Henderson 249196d6407fSRichard Henderson addr = tcg_temp_new(); 249296d6407fSRichard Henderson base = load_gpr(ctx, rb); 249396d6407fSRichard Henderson if (rx) { 2494eaa3783bSRichard Henderson tcg_gen_shli_reg(addr, cpu_gr[rx], scale); 2495eaa3783bSRichard Henderson tcg_gen_add_reg(addr, addr, base); 249696d6407fSRichard Henderson } else { 2497eaa3783bSRichard Henderson tcg_gen_addi_reg(addr, base, disp); 249896d6407fSRichard Henderson } 249996d6407fSRichard Henderson 2500eaa3783bSRichard Henderson zero = tcg_const_reg(0); 2501eaa3783bSRichard Henderson tcg_gen_atomic_xchg_reg(dest, (modify <= 0 ? addr : base), 2502*3d68ee7bSRichard Henderson zero, ctx->mmu_idx, mop); 250396d6407fSRichard Henderson if (modify) { 250496d6407fSRichard Henderson save_gpr(ctx, rb, addr); 250596d6407fSRichard Henderson } 250696d6407fSRichard Henderson save_gpr(ctx, rt, dest); 250796d6407fSRichard Henderson 2508869051eaSRichard Henderson return nullify_end(ctx, DISAS_NEXT); 250996d6407fSRichard Henderson } 251096d6407fSRichard Henderson 2511869051eaSRichard Henderson static DisasJumpType trans_stby(DisasContext *ctx, uint32_t insn, 251296d6407fSRichard Henderson const DisasInsn *di) 251396d6407fSRichard Henderson { 2514eaa3783bSRichard Henderson target_sreg disp = low_sextract(insn, 0, 5); 251596d6407fSRichard Henderson unsigned m = extract32(insn, 5, 1); 251696d6407fSRichard Henderson unsigned a = extract32(insn, 13, 1); 251796d6407fSRichard Henderson unsigned rt = extract32(insn, 16, 5); 251896d6407fSRichard Henderson unsigned rb = extract32(insn, 21, 5); 2519eaa3783bSRichard Henderson TCGv_reg addr, val; 252096d6407fSRichard Henderson 252196d6407fSRichard Henderson nullify_over(ctx); 252296d6407fSRichard Henderson 252396d6407fSRichard Henderson addr = tcg_temp_new(); 252496d6407fSRichard Henderson if (m || disp == 0) { 2525eaa3783bSRichard Henderson tcg_gen_mov_reg(addr, load_gpr(ctx, rb)); 252696d6407fSRichard Henderson } else { 2527eaa3783bSRichard Henderson tcg_gen_addi_reg(addr, load_gpr(ctx, rb), disp); 252896d6407fSRichard Henderson } 252996d6407fSRichard Henderson val = load_gpr(ctx, rt); 253096d6407fSRichard Henderson 253196d6407fSRichard Henderson if (a) { 2532f9f46db4SEmilio G. Cota if (tb_cflags(ctx->base.tb) & CF_PARALLEL) { 2533f9f46db4SEmilio G. Cota gen_helper_stby_e_parallel(cpu_env, addr, val); 2534f9f46db4SEmilio G. Cota } else { 253596d6407fSRichard Henderson gen_helper_stby_e(cpu_env, addr, val); 2536f9f46db4SEmilio G. Cota } 2537f9f46db4SEmilio G. Cota } else { 2538f9f46db4SEmilio G. Cota if (tb_cflags(ctx->base.tb) & CF_PARALLEL) { 2539f9f46db4SEmilio G. Cota gen_helper_stby_b_parallel(cpu_env, addr, val); 254096d6407fSRichard Henderson } else { 254196d6407fSRichard Henderson gen_helper_stby_b(cpu_env, addr, val); 254296d6407fSRichard Henderson } 2543f9f46db4SEmilio G. Cota } 254496d6407fSRichard Henderson 254596d6407fSRichard Henderson if (m) { 2546eaa3783bSRichard Henderson tcg_gen_addi_reg(addr, addr, disp); 2547eaa3783bSRichard Henderson tcg_gen_andi_reg(addr, addr, ~3); 254896d6407fSRichard Henderson save_gpr(ctx, rb, addr); 254996d6407fSRichard Henderson } 255096d6407fSRichard Henderson tcg_temp_free(addr); 255196d6407fSRichard Henderson 2552869051eaSRichard Henderson return nullify_end(ctx, DISAS_NEXT); 255396d6407fSRichard Henderson } 255496d6407fSRichard Henderson 255596d6407fSRichard Henderson static const DisasInsn table_index_mem[] = { 255696d6407fSRichard Henderson { 0x0c001000u, 0xfc001300, trans_ld_idx_i }, /* LD[BHWD], im */ 255796d6407fSRichard Henderson { 0x0c000000u, 0xfc001300, trans_ld_idx_x }, /* LD[BHWD], rx */ 255896d6407fSRichard Henderson { 0x0c001200u, 0xfc001300, trans_st_idx_i }, /* ST[BHWD] */ 255996d6407fSRichard Henderson { 0x0c0001c0u, 0xfc0003c0, trans_ldcw }, 256096d6407fSRichard Henderson { 0x0c001300u, 0xfc0013c0, trans_stby }, 256196d6407fSRichard Henderson }; 256296d6407fSRichard Henderson 2563869051eaSRichard Henderson static DisasJumpType trans_ldil(DisasContext *ctx, uint32_t insn) 2564b2167459SRichard Henderson { 2565b2167459SRichard Henderson unsigned rt = extract32(insn, 21, 5); 2566eaa3783bSRichard Henderson target_sreg i = assemble_21(insn); 2567eaa3783bSRichard Henderson TCGv_reg tcg_rt = dest_gpr(ctx, rt); 2568b2167459SRichard Henderson 2569eaa3783bSRichard Henderson tcg_gen_movi_reg(tcg_rt, i); 2570b2167459SRichard Henderson save_gpr(ctx, rt, tcg_rt); 2571b2167459SRichard Henderson cond_free(&ctx->null_cond); 2572b2167459SRichard Henderson 2573869051eaSRichard Henderson return DISAS_NEXT; 2574b2167459SRichard Henderson } 2575b2167459SRichard Henderson 2576869051eaSRichard Henderson static DisasJumpType trans_addil(DisasContext *ctx, uint32_t insn) 2577b2167459SRichard Henderson { 2578b2167459SRichard Henderson unsigned rt = extract32(insn, 21, 5); 2579eaa3783bSRichard Henderson target_sreg i = assemble_21(insn); 2580eaa3783bSRichard Henderson TCGv_reg tcg_rt = load_gpr(ctx, rt); 2581eaa3783bSRichard Henderson TCGv_reg tcg_r1 = dest_gpr(ctx, 1); 2582b2167459SRichard Henderson 2583eaa3783bSRichard Henderson tcg_gen_addi_reg(tcg_r1, tcg_rt, i); 2584b2167459SRichard Henderson save_gpr(ctx, 1, tcg_r1); 2585b2167459SRichard Henderson cond_free(&ctx->null_cond); 2586b2167459SRichard Henderson 2587869051eaSRichard Henderson return DISAS_NEXT; 2588b2167459SRichard Henderson } 2589b2167459SRichard Henderson 2590869051eaSRichard Henderson static DisasJumpType trans_ldo(DisasContext *ctx, uint32_t insn) 2591b2167459SRichard Henderson { 2592b2167459SRichard Henderson unsigned rb = extract32(insn, 21, 5); 2593b2167459SRichard Henderson unsigned rt = extract32(insn, 16, 5); 2594eaa3783bSRichard Henderson target_sreg i = assemble_16(insn); 2595eaa3783bSRichard Henderson TCGv_reg tcg_rt = dest_gpr(ctx, rt); 2596b2167459SRichard Henderson 2597b2167459SRichard Henderson /* Special case rb == 0, for the LDI pseudo-op. 2598b2167459SRichard Henderson The COPY pseudo-op is handled for free within tcg_gen_addi_tl. */ 2599b2167459SRichard Henderson if (rb == 0) { 2600eaa3783bSRichard Henderson tcg_gen_movi_reg(tcg_rt, i); 2601b2167459SRichard Henderson } else { 2602eaa3783bSRichard Henderson tcg_gen_addi_reg(tcg_rt, cpu_gr[rb], i); 2603b2167459SRichard Henderson } 2604b2167459SRichard Henderson save_gpr(ctx, rt, tcg_rt); 2605b2167459SRichard Henderson cond_free(&ctx->null_cond); 2606b2167459SRichard Henderson 2607869051eaSRichard Henderson return DISAS_NEXT; 2608b2167459SRichard Henderson } 2609b2167459SRichard Henderson 2610869051eaSRichard Henderson static DisasJumpType trans_load(DisasContext *ctx, uint32_t insn, 261196d6407fSRichard Henderson bool is_mod, TCGMemOp mop) 261296d6407fSRichard Henderson { 261396d6407fSRichard Henderson unsigned rb = extract32(insn, 21, 5); 261496d6407fSRichard Henderson unsigned rt = extract32(insn, 16, 5); 2615eaa3783bSRichard Henderson target_sreg i = assemble_16(insn); 261696d6407fSRichard Henderson 261796d6407fSRichard Henderson return do_load(ctx, rt, rb, 0, 0, i, is_mod ? (i < 0 ? -1 : 1) : 0, mop); 261896d6407fSRichard Henderson } 261996d6407fSRichard Henderson 2620869051eaSRichard Henderson static DisasJumpType trans_load_w(DisasContext *ctx, uint32_t insn) 262196d6407fSRichard Henderson { 262296d6407fSRichard Henderson unsigned rb = extract32(insn, 21, 5); 262396d6407fSRichard Henderson unsigned rt = extract32(insn, 16, 5); 2624eaa3783bSRichard Henderson target_sreg i = assemble_16a(insn); 262596d6407fSRichard Henderson unsigned ext2 = extract32(insn, 1, 2); 262696d6407fSRichard Henderson 262796d6407fSRichard Henderson switch (ext2) { 262896d6407fSRichard Henderson case 0: 262996d6407fSRichard Henderson case 1: 263096d6407fSRichard Henderson /* FLDW without modification. */ 263196d6407fSRichard Henderson return do_floadw(ctx, ext2 * 32 + rt, rb, 0, 0, i, 0); 263296d6407fSRichard Henderson case 2: 263396d6407fSRichard Henderson /* LDW with modification. Note that the sign of I selects 263496d6407fSRichard Henderson post-dec vs pre-inc. */ 263596d6407fSRichard Henderson return do_load(ctx, rt, rb, 0, 0, i, (i < 0 ? 1 : -1), MO_TEUL); 263696d6407fSRichard Henderson default: 263796d6407fSRichard Henderson return gen_illegal(ctx); 263896d6407fSRichard Henderson } 263996d6407fSRichard Henderson } 264096d6407fSRichard Henderson 2641869051eaSRichard Henderson static DisasJumpType trans_fload_mod(DisasContext *ctx, uint32_t insn) 264296d6407fSRichard Henderson { 2643eaa3783bSRichard Henderson target_sreg i = assemble_16a(insn); 264496d6407fSRichard Henderson unsigned t1 = extract32(insn, 1, 1); 264596d6407fSRichard Henderson unsigned a = extract32(insn, 2, 1); 264696d6407fSRichard Henderson unsigned t0 = extract32(insn, 16, 5); 264796d6407fSRichard Henderson unsigned rb = extract32(insn, 21, 5); 264896d6407fSRichard Henderson 264996d6407fSRichard Henderson /* FLDW with modification. */ 265096d6407fSRichard Henderson return do_floadw(ctx, t1 * 32 + t0, rb, 0, 0, i, (a ? -1 : 1)); 265196d6407fSRichard Henderson } 265296d6407fSRichard Henderson 2653869051eaSRichard Henderson static DisasJumpType trans_store(DisasContext *ctx, uint32_t insn, 265496d6407fSRichard Henderson bool is_mod, TCGMemOp mop) 265596d6407fSRichard Henderson { 265696d6407fSRichard Henderson unsigned rb = extract32(insn, 21, 5); 265796d6407fSRichard Henderson unsigned rt = extract32(insn, 16, 5); 2658eaa3783bSRichard Henderson target_sreg i = assemble_16(insn); 265996d6407fSRichard Henderson 266096d6407fSRichard Henderson return do_store(ctx, rt, rb, i, is_mod ? (i < 0 ? -1 : 1) : 0, mop); 266196d6407fSRichard Henderson } 266296d6407fSRichard Henderson 2663869051eaSRichard Henderson static DisasJumpType trans_store_w(DisasContext *ctx, uint32_t insn) 266496d6407fSRichard Henderson { 266596d6407fSRichard Henderson unsigned rb = extract32(insn, 21, 5); 266696d6407fSRichard Henderson unsigned rt = extract32(insn, 16, 5); 2667eaa3783bSRichard Henderson target_sreg i = assemble_16a(insn); 266896d6407fSRichard Henderson unsigned ext2 = extract32(insn, 1, 2); 266996d6407fSRichard Henderson 267096d6407fSRichard Henderson switch (ext2) { 267196d6407fSRichard Henderson case 0: 267296d6407fSRichard Henderson case 1: 267396d6407fSRichard Henderson /* FSTW without modification. */ 267496d6407fSRichard Henderson return do_fstorew(ctx, ext2 * 32 + rt, rb, 0, 0, i, 0); 267596d6407fSRichard Henderson case 2: 267696d6407fSRichard Henderson /* LDW with modification. */ 267796d6407fSRichard Henderson return do_store(ctx, rt, rb, i, (i < 0 ? 1 : -1), MO_TEUL); 267896d6407fSRichard Henderson default: 267996d6407fSRichard Henderson return gen_illegal(ctx); 268096d6407fSRichard Henderson } 268196d6407fSRichard Henderson } 268296d6407fSRichard Henderson 2683869051eaSRichard Henderson static DisasJumpType trans_fstore_mod(DisasContext *ctx, uint32_t insn) 268496d6407fSRichard Henderson { 2685eaa3783bSRichard Henderson target_sreg i = assemble_16a(insn); 268696d6407fSRichard Henderson unsigned t1 = extract32(insn, 1, 1); 268796d6407fSRichard Henderson unsigned a = extract32(insn, 2, 1); 268896d6407fSRichard Henderson unsigned t0 = extract32(insn, 16, 5); 268996d6407fSRichard Henderson unsigned rb = extract32(insn, 21, 5); 269096d6407fSRichard Henderson 269196d6407fSRichard Henderson /* FSTW with modification. */ 269296d6407fSRichard Henderson return do_fstorew(ctx, t1 * 32 + t0, rb, 0, 0, i, (a ? -1 : 1)); 269396d6407fSRichard Henderson } 269496d6407fSRichard Henderson 2695869051eaSRichard Henderson static DisasJumpType trans_copr_w(DisasContext *ctx, uint32_t insn) 269696d6407fSRichard Henderson { 269796d6407fSRichard Henderson unsigned t0 = extract32(insn, 0, 5); 269896d6407fSRichard Henderson unsigned m = extract32(insn, 5, 1); 269996d6407fSRichard Henderson unsigned t1 = extract32(insn, 6, 1); 270096d6407fSRichard Henderson unsigned ext3 = extract32(insn, 7, 3); 270196d6407fSRichard Henderson /* unsigned cc = extract32(insn, 10, 2); */ 270296d6407fSRichard Henderson unsigned i = extract32(insn, 12, 1); 270396d6407fSRichard Henderson unsigned ua = extract32(insn, 13, 1); 270496d6407fSRichard Henderson unsigned rx = extract32(insn, 16, 5); 270596d6407fSRichard Henderson unsigned rb = extract32(insn, 21, 5); 270696d6407fSRichard Henderson unsigned rt = t1 * 32 + t0; 270796d6407fSRichard Henderson int modify = (m ? (ua ? -1 : 1) : 0); 270896d6407fSRichard Henderson int disp, scale; 270996d6407fSRichard Henderson 271096d6407fSRichard Henderson if (i == 0) { 271196d6407fSRichard Henderson scale = (ua ? 2 : 0); 271296d6407fSRichard Henderson disp = 0; 271396d6407fSRichard Henderson modify = m; 271496d6407fSRichard Henderson } else { 271596d6407fSRichard Henderson disp = low_sextract(rx, 0, 5); 271696d6407fSRichard Henderson scale = 0; 271796d6407fSRichard Henderson rx = 0; 271896d6407fSRichard Henderson modify = (m ? (ua ? -1 : 1) : 0); 271996d6407fSRichard Henderson } 272096d6407fSRichard Henderson 272196d6407fSRichard Henderson switch (ext3) { 272296d6407fSRichard Henderson case 0: /* FLDW */ 272396d6407fSRichard Henderson return do_floadw(ctx, rt, rb, rx, scale, disp, modify); 272496d6407fSRichard Henderson case 4: /* FSTW */ 272596d6407fSRichard Henderson return do_fstorew(ctx, rt, rb, rx, scale, disp, modify); 272696d6407fSRichard Henderson } 272796d6407fSRichard Henderson return gen_illegal(ctx); 272896d6407fSRichard Henderson } 272996d6407fSRichard Henderson 2730869051eaSRichard Henderson static DisasJumpType trans_copr_dw(DisasContext *ctx, uint32_t insn) 273196d6407fSRichard Henderson { 273296d6407fSRichard Henderson unsigned rt = extract32(insn, 0, 5); 273396d6407fSRichard Henderson unsigned m = extract32(insn, 5, 1); 273496d6407fSRichard Henderson unsigned ext4 = extract32(insn, 6, 4); 273596d6407fSRichard Henderson /* unsigned cc = extract32(insn, 10, 2); */ 273696d6407fSRichard Henderson unsigned i = extract32(insn, 12, 1); 273796d6407fSRichard Henderson unsigned ua = extract32(insn, 13, 1); 273896d6407fSRichard Henderson unsigned rx = extract32(insn, 16, 5); 273996d6407fSRichard Henderson unsigned rb = extract32(insn, 21, 5); 274096d6407fSRichard Henderson int modify = (m ? (ua ? -1 : 1) : 0); 274196d6407fSRichard Henderson int disp, scale; 274296d6407fSRichard Henderson 274396d6407fSRichard Henderson if (i == 0) { 274496d6407fSRichard Henderson scale = (ua ? 3 : 0); 274596d6407fSRichard Henderson disp = 0; 274696d6407fSRichard Henderson modify = m; 274796d6407fSRichard Henderson } else { 274896d6407fSRichard Henderson disp = low_sextract(rx, 0, 5); 274996d6407fSRichard Henderson scale = 0; 275096d6407fSRichard Henderson rx = 0; 275196d6407fSRichard Henderson modify = (m ? (ua ? -1 : 1) : 0); 275296d6407fSRichard Henderson } 275396d6407fSRichard Henderson 275496d6407fSRichard Henderson switch (ext4) { 275596d6407fSRichard Henderson case 0: /* FLDD */ 275696d6407fSRichard Henderson return do_floadd(ctx, rt, rb, rx, scale, disp, modify); 275796d6407fSRichard Henderson case 8: /* FSTD */ 275896d6407fSRichard Henderson return do_fstored(ctx, rt, rb, rx, scale, disp, modify); 275996d6407fSRichard Henderson default: 276096d6407fSRichard Henderson return gen_illegal(ctx); 276196d6407fSRichard Henderson } 276296d6407fSRichard Henderson } 276396d6407fSRichard Henderson 2764869051eaSRichard Henderson static DisasJumpType trans_cmpb(DisasContext *ctx, uint32_t insn, 276598cd9ca7SRichard Henderson bool is_true, bool is_imm, bool is_dw) 276698cd9ca7SRichard Henderson { 2767eaa3783bSRichard Henderson target_sreg disp = assemble_12(insn) * 4; 276898cd9ca7SRichard Henderson unsigned n = extract32(insn, 1, 1); 276998cd9ca7SRichard Henderson unsigned c = extract32(insn, 13, 3); 277098cd9ca7SRichard Henderson unsigned r = extract32(insn, 21, 5); 277198cd9ca7SRichard Henderson unsigned cf = c * 2 + !is_true; 2772eaa3783bSRichard Henderson TCGv_reg dest, in1, in2, sv; 277398cd9ca7SRichard Henderson DisasCond cond; 277498cd9ca7SRichard Henderson 277598cd9ca7SRichard Henderson nullify_over(ctx); 277698cd9ca7SRichard Henderson 277798cd9ca7SRichard Henderson if (is_imm) { 277898cd9ca7SRichard Henderson in1 = load_const(ctx, low_sextract(insn, 16, 5)); 277998cd9ca7SRichard Henderson } else { 278098cd9ca7SRichard Henderson in1 = load_gpr(ctx, extract32(insn, 16, 5)); 278198cd9ca7SRichard Henderson } 278298cd9ca7SRichard Henderson in2 = load_gpr(ctx, r); 278398cd9ca7SRichard Henderson dest = get_temp(ctx); 278498cd9ca7SRichard Henderson 2785eaa3783bSRichard Henderson tcg_gen_sub_reg(dest, in1, in2); 278698cd9ca7SRichard Henderson 2787f764718dSRichard Henderson sv = NULL; 278898cd9ca7SRichard Henderson if (c == 6) { 278998cd9ca7SRichard Henderson sv = do_sub_sv(ctx, dest, in1, in2); 279098cd9ca7SRichard Henderson } 279198cd9ca7SRichard Henderson 279298cd9ca7SRichard Henderson cond = do_sub_cond(cf, dest, in1, in2, sv); 279398cd9ca7SRichard Henderson return do_cbranch(ctx, disp, n, &cond); 279498cd9ca7SRichard Henderson } 279598cd9ca7SRichard Henderson 2796869051eaSRichard Henderson static DisasJumpType trans_addb(DisasContext *ctx, uint32_t insn, 279798cd9ca7SRichard Henderson bool is_true, bool is_imm) 279898cd9ca7SRichard Henderson { 2799eaa3783bSRichard Henderson target_sreg disp = assemble_12(insn) * 4; 280098cd9ca7SRichard Henderson unsigned n = extract32(insn, 1, 1); 280198cd9ca7SRichard Henderson unsigned c = extract32(insn, 13, 3); 280298cd9ca7SRichard Henderson unsigned r = extract32(insn, 21, 5); 280398cd9ca7SRichard Henderson unsigned cf = c * 2 + !is_true; 2804eaa3783bSRichard Henderson TCGv_reg dest, in1, in2, sv, cb_msb; 280598cd9ca7SRichard Henderson DisasCond cond; 280698cd9ca7SRichard Henderson 280798cd9ca7SRichard Henderson nullify_over(ctx); 280898cd9ca7SRichard Henderson 280998cd9ca7SRichard Henderson if (is_imm) { 281098cd9ca7SRichard Henderson in1 = load_const(ctx, low_sextract(insn, 16, 5)); 281198cd9ca7SRichard Henderson } else { 281298cd9ca7SRichard Henderson in1 = load_gpr(ctx, extract32(insn, 16, 5)); 281398cd9ca7SRichard Henderson } 281498cd9ca7SRichard Henderson in2 = load_gpr(ctx, r); 281598cd9ca7SRichard Henderson dest = dest_gpr(ctx, r); 2816f764718dSRichard Henderson sv = NULL; 2817f764718dSRichard Henderson cb_msb = NULL; 281898cd9ca7SRichard Henderson 281998cd9ca7SRichard Henderson switch (c) { 282098cd9ca7SRichard Henderson default: 2821eaa3783bSRichard Henderson tcg_gen_add_reg(dest, in1, in2); 282298cd9ca7SRichard Henderson break; 282398cd9ca7SRichard Henderson case 4: case 5: 282498cd9ca7SRichard Henderson cb_msb = get_temp(ctx); 2825eaa3783bSRichard Henderson tcg_gen_movi_reg(cb_msb, 0); 2826eaa3783bSRichard Henderson tcg_gen_add2_reg(dest, cb_msb, in1, cb_msb, in2, cb_msb); 282798cd9ca7SRichard Henderson break; 282898cd9ca7SRichard Henderson case 6: 2829eaa3783bSRichard Henderson tcg_gen_add_reg(dest, in1, in2); 283098cd9ca7SRichard Henderson sv = do_add_sv(ctx, dest, in1, in2); 283198cd9ca7SRichard Henderson break; 283298cd9ca7SRichard Henderson } 283398cd9ca7SRichard Henderson 283498cd9ca7SRichard Henderson cond = do_cond(cf, dest, cb_msb, sv); 283598cd9ca7SRichard Henderson return do_cbranch(ctx, disp, n, &cond); 283698cd9ca7SRichard Henderson } 283798cd9ca7SRichard Henderson 2838869051eaSRichard Henderson static DisasJumpType trans_bb(DisasContext *ctx, uint32_t insn) 283998cd9ca7SRichard Henderson { 2840eaa3783bSRichard Henderson target_sreg disp = assemble_12(insn) * 4; 284198cd9ca7SRichard Henderson unsigned n = extract32(insn, 1, 1); 284298cd9ca7SRichard Henderson unsigned c = extract32(insn, 15, 1); 284398cd9ca7SRichard Henderson unsigned r = extract32(insn, 16, 5); 284498cd9ca7SRichard Henderson unsigned p = extract32(insn, 21, 5); 284598cd9ca7SRichard Henderson unsigned i = extract32(insn, 26, 1); 2846eaa3783bSRichard Henderson TCGv_reg tmp, tcg_r; 284798cd9ca7SRichard Henderson DisasCond cond; 284898cd9ca7SRichard Henderson 284998cd9ca7SRichard Henderson nullify_over(ctx); 285098cd9ca7SRichard Henderson 285198cd9ca7SRichard Henderson tmp = tcg_temp_new(); 285298cd9ca7SRichard Henderson tcg_r = load_gpr(ctx, r); 285398cd9ca7SRichard Henderson if (i) { 2854eaa3783bSRichard Henderson tcg_gen_shli_reg(tmp, tcg_r, p); 285598cd9ca7SRichard Henderson } else { 2856eaa3783bSRichard Henderson tcg_gen_shl_reg(tmp, tcg_r, cpu_sar); 285798cd9ca7SRichard Henderson } 285898cd9ca7SRichard Henderson 285998cd9ca7SRichard Henderson cond = cond_make_0(c ? TCG_COND_GE : TCG_COND_LT, tmp); 286098cd9ca7SRichard Henderson tcg_temp_free(tmp); 286198cd9ca7SRichard Henderson return do_cbranch(ctx, disp, n, &cond); 286298cd9ca7SRichard Henderson } 286398cd9ca7SRichard Henderson 2864869051eaSRichard Henderson static DisasJumpType trans_movb(DisasContext *ctx, uint32_t insn, bool is_imm) 286598cd9ca7SRichard Henderson { 2866eaa3783bSRichard Henderson target_sreg disp = assemble_12(insn) * 4; 286798cd9ca7SRichard Henderson unsigned n = extract32(insn, 1, 1); 286898cd9ca7SRichard Henderson unsigned c = extract32(insn, 13, 3); 286998cd9ca7SRichard Henderson unsigned t = extract32(insn, 16, 5); 287098cd9ca7SRichard Henderson unsigned r = extract32(insn, 21, 5); 2871eaa3783bSRichard Henderson TCGv_reg dest; 287298cd9ca7SRichard Henderson DisasCond cond; 287398cd9ca7SRichard Henderson 287498cd9ca7SRichard Henderson nullify_over(ctx); 287598cd9ca7SRichard Henderson 287698cd9ca7SRichard Henderson dest = dest_gpr(ctx, r); 287798cd9ca7SRichard Henderson if (is_imm) { 2878eaa3783bSRichard Henderson tcg_gen_movi_reg(dest, low_sextract(t, 0, 5)); 287998cd9ca7SRichard Henderson } else if (t == 0) { 2880eaa3783bSRichard Henderson tcg_gen_movi_reg(dest, 0); 288198cd9ca7SRichard Henderson } else { 2882eaa3783bSRichard Henderson tcg_gen_mov_reg(dest, cpu_gr[t]); 288398cd9ca7SRichard Henderson } 288498cd9ca7SRichard Henderson 288598cd9ca7SRichard Henderson cond = do_sed_cond(c, dest); 288698cd9ca7SRichard Henderson return do_cbranch(ctx, disp, n, &cond); 288798cd9ca7SRichard Henderson } 288898cd9ca7SRichard Henderson 2889869051eaSRichard Henderson static DisasJumpType trans_shrpw_sar(DisasContext *ctx, uint32_t insn, 28900b1347d2SRichard Henderson const DisasInsn *di) 28910b1347d2SRichard Henderson { 28920b1347d2SRichard Henderson unsigned rt = extract32(insn, 0, 5); 28930b1347d2SRichard Henderson unsigned c = extract32(insn, 13, 3); 28940b1347d2SRichard Henderson unsigned r1 = extract32(insn, 16, 5); 28950b1347d2SRichard Henderson unsigned r2 = extract32(insn, 21, 5); 2896eaa3783bSRichard Henderson TCGv_reg dest; 28970b1347d2SRichard Henderson 28980b1347d2SRichard Henderson if (c) { 28990b1347d2SRichard Henderson nullify_over(ctx); 29000b1347d2SRichard Henderson } 29010b1347d2SRichard Henderson 29020b1347d2SRichard Henderson dest = dest_gpr(ctx, rt); 29030b1347d2SRichard Henderson if (r1 == 0) { 2904eaa3783bSRichard Henderson tcg_gen_ext32u_reg(dest, load_gpr(ctx, r2)); 2905eaa3783bSRichard Henderson tcg_gen_shr_reg(dest, dest, cpu_sar); 29060b1347d2SRichard Henderson } else if (r1 == r2) { 29070b1347d2SRichard Henderson TCGv_i32 t32 = tcg_temp_new_i32(); 2908eaa3783bSRichard Henderson tcg_gen_trunc_reg_i32(t32, load_gpr(ctx, r2)); 29090b1347d2SRichard Henderson tcg_gen_rotr_i32(t32, t32, cpu_sar); 2910eaa3783bSRichard Henderson tcg_gen_extu_i32_reg(dest, t32); 29110b1347d2SRichard Henderson tcg_temp_free_i32(t32); 29120b1347d2SRichard Henderson } else { 29130b1347d2SRichard Henderson TCGv_i64 t = tcg_temp_new_i64(); 29140b1347d2SRichard Henderson TCGv_i64 s = tcg_temp_new_i64(); 29150b1347d2SRichard Henderson 2916eaa3783bSRichard Henderson tcg_gen_concat_reg_i64(t, load_gpr(ctx, r2), load_gpr(ctx, r1)); 2917eaa3783bSRichard Henderson tcg_gen_extu_reg_i64(s, cpu_sar); 29180b1347d2SRichard Henderson tcg_gen_shr_i64(t, t, s); 2919eaa3783bSRichard Henderson tcg_gen_trunc_i64_reg(dest, t); 29200b1347d2SRichard Henderson 29210b1347d2SRichard Henderson tcg_temp_free_i64(t); 29220b1347d2SRichard Henderson tcg_temp_free_i64(s); 29230b1347d2SRichard Henderson } 29240b1347d2SRichard Henderson save_gpr(ctx, rt, dest); 29250b1347d2SRichard Henderson 29260b1347d2SRichard Henderson /* Install the new nullification. */ 29270b1347d2SRichard Henderson cond_free(&ctx->null_cond); 29280b1347d2SRichard Henderson if (c) { 29290b1347d2SRichard Henderson ctx->null_cond = do_sed_cond(c, dest); 29300b1347d2SRichard Henderson } 2931869051eaSRichard Henderson return nullify_end(ctx, DISAS_NEXT); 29320b1347d2SRichard Henderson } 29330b1347d2SRichard Henderson 2934869051eaSRichard Henderson static DisasJumpType trans_shrpw_imm(DisasContext *ctx, uint32_t insn, 29350b1347d2SRichard Henderson const DisasInsn *di) 29360b1347d2SRichard Henderson { 29370b1347d2SRichard Henderson unsigned rt = extract32(insn, 0, 5); 29380b1347d2SRichard Henderson unsigned cpos = extract32(insn, 5, 5); 29390b1347d2SRichard Henderson unsigned c = extract32(insn, 13, 3); 29400b1347d2SRichard Henderson unsigned r1 = extract32(insn, 16, 5); 29410b1347d2SRichard Henderson unsigned r2 = extract32(insn, 21, 5); 29420b1347d2SRichard Henderson unsigned sa = 31 - cpos; 2943eaa3783bSRichard Henderson TCGv_reg dest, t2; 29440b1347d2SRichard Henderson 29450b1347d2SRichard Henderson if (c) { 29460b1347d2SRichard Henderson nullify_over(ctx); 29470b1347d2SRichard Henderson } 29480b1347d2SRichard Henderson 29490b1347d2SRichard Henderson dest = dest_gpr(ctx, rt); 29500b1347d2SRichard Henderson t2 = load_gpr(ctx, r2); 29510b1347d2SRichard Henderson if (r1 == r2) { 29520b1347d2SRichard Henderson TCGv_i32 t32 = tcg_temp_new_i32(); 2953eaa3783bSRichard Henderson tcg_gen_trunc_reg_i32(t32, t2); 29540b1347d2SRichard Henderson tcg_gen_rotri_i32(t32, t32, sa); 2955eaa3783bSRichard Henderson tcg_gen_extu_i32_reg(dest, t32); 29560b1347d2SRichard Henderson tcg_temp_free_i32(t32); 29570b1347d2SRichard Henderson } else if (r1 == 0) { 2958eaa3783bSRichard Henderson tcg_gen_extract_reg(dest, t2, sa, 32 - sa); 29590b1347d2SRichard Henderson } else { 2960eaa3783bSRichard Henderson TCGv_reg t0 = tcg_temp_new(); 2961eaa3783bSRichard Henderson tcg_gen_extract_reg(t0, t2, sa, 32 - sa); 2962eaa3783bSRichard Henderson tcg_gen_deposit_reg(dest, t0, cpu_gr[r1], 32 - sa, sa); 29630b1347d2SRichard Henderson tcg_temp_free(t0); 29640b1347d2SRichard Henderson } 29650b1347d2SRichard Henderson save_gpr(ctx, rt, dest); 29660b1347d2SRichard Henderson 29670b1347d2SRichard Henderson /* Install the new nullification. */ 29680b1347d2SRichard Henderson cond_free(&ctx->null_cond); 29690b1347d2SRichard Henderson if (c) { 29700b1347d2SRichard Henderson ctx->null_cond = do_sed_cond(c, dest); 29710b1347d2SRichard Henderson } 2972869051eaSRichard Henderson return nullify_end(ctx, DISAS_NEXT); 29730b1347d2SRichard Henderson } 29740b1347d2SRichard Henderson 2975869051eaSRichard Henderson static DisasJumpType trans_extrw_sar(DisasContext *ctx, uint32_t insn, 29760b1347d2SRichard Henderson const DisasInsn *di) 29770b1347d2SRichard Henderson { 29780b1347d2SRichard Henderson unsigned clen = extract32(insn, 0, 5); 29790b1347d2SRichard Henderson unsigned is_se = extract32(insn, 10, 1); 29800b1347d2SRichard Henderson unsigned c = extract32(insn, 13, 3); 29810b1347d2SRichard Henderson unsigned rt = extract32(insn, 16, 5); 29820b1347d2SRichard Henderson unsigned rr = extract32(insn, 21, 5); 29830b1347d2SRichard Henderson unsigned len = 32 - clen; 2984eaa3783bSRichard Henderson TCGv_reg dest, src, tmp; 29850b1347d2SRichard Henderson 29860b1347d2SRichard Henderson if (c) { 29870b1347d2SRichard Henderson nullify_over(ctx); 29880b1347d2SRichard Henderson } 29890b1347d2SRichard Henderson 29900b1347d2SRichard Henderson dest = dest_gpr(ctx, rt); 29910b1347d2SRichard Henderson src = load_gpr(ctx, rr); 29920b1347d2SRichard Henderson tmp = tcg_temp_new(); 29930b1347d2SRichard Henderson 29940b1347d2SRichard Henderson /* Recall that SAR is using big-endian bit numbering. */ 2995eaa3783bSRichard Henderson tcg_gen_xori_reg(tmp, cpu_sar, TARGET_REGISTER_BITS - 1); 29960b1347d2SRichard Henderson if (is_se) { 2997eaa3783bSRichard Henderson tcg_gen_sar_reg(dest, src, tmp); 2998eaa3783bSRichard Henderson tcg_gen_sextract_reg(dest, dest, 0, len); 29990b1347d2SRichard Henderson } else { 3000eaa3783bSRichard Henderson tcg_gen_shr_reg(dest, src, tmp); 3001eaa3783bSRichard Henderson tcg_gen_extract_reg(dest, dest, 0, len); 30020b1347d2SRichard Henderson } 30030b1347d2SRichard Henderson tcg_temp_free(tmp); 30040b1347d2SRichard Henderson save_gpr(ctx, rt, dest); 30050b1347d2SRichard Henderson 30060b1347d2SRichard Henderson /* Install the new nullification. */ 30070b1347d2SRichard Henderson cond_free(&ctx->null_cond); 30080b1347d2SRichard Henderson if (c) { 30090b1347d2SRichard Henderson ctx->null_cond = do_sed_cond(c, dest); 30100b1347d2SRichard Henderson } 3011869051eaSRichard Henderson return nullify_end(ctx, DISAS_NEXT); 30120b1347d2SRichard Henderson } 30130b1347d2SRichard Henderson 3014869051eaSRichard Henderson static DisasJumpType trans_extrw_imm(DisasContext *ctx, uint32_t insn, 30150b1347d2SRichard Henderson const DisasInsn *di) 30160b1347d2SRichard Henderson { 30170b1347d2SRichard Henderson unsigned clen = extract32(insn, 0, 5); 30180b1347d2SRichard Henderson unsigned pos = extract32(insn, 5, 5); 30190b1347d2SRichard Henderson unsigned is_se = extract32(insn, 10, 1); 30200b1347d2SRichard Henderson unsigned c = extract32(insn, 13, 3); 30210b1347d2SRichard Henderson unsigned rt = extract32(insn, 16, 5); 30220b1347d2SRichard Henderson unsigned rr = extract32(insn, 21, 5); 30230b1347d2SRichard Henderson unsigned len = 32 - clen; 30240b1347d2SRichard Henderson unsigned cpos = 31 - pos; 3025eaa3783bSRichard Henderson TCGv_reg dest, src; 30260b1347d2SRichard Henderson 30270b1347d2SRichard Henderson if (c) { 30280b1347d2SRichard Henderson nullify_over(ctx); 30290b1347d2SRichard Henderson } 30300b1347d2SRichard Henderson 30310b1347d2SRichard Henderson dest = dest_gpr(ctx, rt); 30320b1347d2SRichard Henderson src = load_gpr(ctx, rr); 30330b1347d2SRichard Henderson if (is_se) { 3034eaa3783bSRichard Henderson tcg_gen_sextract_reg(dest, src, cpos, len); 30350b1347d2SRichard Henderson } else { 3036eaa3783bSRichard Henderson tcg_gen_extract_reg(dest, src, cpos, len); 30370b1347d2SRichard Henderson } 30380b1347d2SRichard Henderson save_gpr(ctx, rt, dest); 30390b1347d2SRichard Henderson 30400b1347d2SRichard Henderson /* Install the new nullification. */ 30410b1347d2SRichard Henderson cond_free(&ctx->null_cond); 30420b1347d2SRichard Henderson if (c) { 30430b1347d2SRichard Henderson ctx->null_cond = do_sed_cond(c, dest); 30440b1347d2SRichard Henderson } 3045869051eaSRichard Henderson return nullify_end(ctx, DISAS_NEXT); 30460b1347d2SRichard Henderson } 30470b1347d2SRichard Henderson 30480b1347d2SRichard Henderson static const DisasInsn table_sh_ex[] = { 30490b1347d2SRichard Henderson { 0xd0000000u, 0xfc001fe0u, trans_shrpw_sar }, 30500b1347d2SRichard Henderson { 0xd0000800u, 0xfc001c00u, trans_shrpw_imm }, 30510b1347d2SRichard Henderson { 0xd0001000u, 0xfc001be0u, trans_extrw_sar }, 30520b1347d2SRichard Henderson { 0xd0001800u, 0xfc001800u, trans_extrw_imm }, 30530b1347d2SRichard Henderson }; 30540b1347d2SRichard Henderson 3055869051eaSRichard Henderson static DisasJumpType trans_depw_imm_c(DisasContext *ctx, uint32_t insn, 30560b1347d2SRichard Henderson const DisasInsn *di) 30570b1347d2SRichard Henderson { 30580b1347d2SRichard Henderson unsigned clen = extract32(insn, 0, 5); 30590b1347d2SRichard Henderson unsigned cpos = extract32(insn, 5, 5); 30600b1347d2SRichard Henderson unsigned nz = extract32(insn, 10, 1); 30610b1347d2SRichard Henderson unsigned c = extract32(insn, 13, 3); 3062eaa3783bSRichard Henderson target_sreg val = low_sextract(insn, 16, 5); 30630b1347d2SRichard Henderson unsigned rt = extract32(insn, 21, 5); 30640b1347d2SRichard Henderson unsigned len = 32 - clen; 3065eaa3783bSRichard Henderson target_sreg mask0, mask1; 3066eaa3783bSRichard Henderson TCGv_reg dest; 30670b1347d2SRichard Henderson 30680b1347d2SRichard Henderson if (c) { 30690b1347d2SRichard Henderson nullify_over(ctx); 30700b1347d2SRichard Henderson } 30710b1347d2SRichard Henderson if (cpos + len > 32) { 30720b1347d2SRichard Henderson len = 32 - cpos; 30730b1347d2SRichard Henderson } 30740b1347d2SRichard Henderson 30750b1347d2SRichard Henderson dest = dest_gpr(ctx, rt); 30760b1347d2SRichard Henderson mask0 = deposit64(0, cpos, len, val); 30770b1347d2SRichard Henderson mask1 = deposit64(-1, cpos, len, val); 30780b1347d2SRichard Henderson 30790b1347d2SRichard Henderson if (nz) { 3080eaa3783bSRichard Henderson TCGv_reg src = load_gpr(ctx, rt); 30810b1347d2SRichard Henderson if (mask1 != -1) { 3082eaa3783bSRichard Henderson tcg_gen_andi_reg(dest, src, mask1); 30830b1347d2SRichard Henderson src = dest; 30840b1347d2SRichard Henderson } 3085eaa3783bSRichard Henderson tcg_gen_ori_reg(dest, src, mask0); 30860b1347d2SRichard Henderson } else { 3087eaa3783bSRichard Henderson tcg_gen_movi_reg(dest, mask0); 30880b1347d2SRichard Henderson } 30890b1347d2SRichard Henderson save_gpr(ctx, rt, dest); 30900b1347d2SRichard Henderson 30910b1347d2SRichard Henderson /* Install the new nullification. */ 30920b1347d2SRichard Henderson cond_free(&ctx->null_cond); 30930b1347d2SRichard Henderson if (c) { 30940b1347d2SRichard Henderson ctx->null_cond = do_sed_cond(c, dest); 30950b1347d2SRichard Henderson } 3096869051eaSRichard Henderson return nullify_end(ctx, DISAS_NEXT); 30970b1347d2SRichard Henderson } 30980b1347d2SRichard Henderson 3099869051eaSRichard Henderson static DisasJumpType trans_depw_imm(DisasContext *ctx, uint32_t insn, 31000b1347d2SRichard Henderson const DisasInsn *di) 31010b1347d2SRichard Henderson { 31020b1347d2SRichard Henderson unsigned clen = extract32(insn, 0, 5); 31030b1347d2SRichard Henderson unsigned cpos = extract32(insn, 5, 5); 31040b1347d2SRichard Henderson unsigned nz = extract32(insn, 10, 1); 31050b1347d2SRichard Henderson unsigned c = extract32(insn, 13, 3); 31060b1347d2SRichard Henderson unsigned rr = extract32(insn, 16, 5); 31070b1347d2SRichard Henderson unsigned rt = extract32(insn, 21, 5); 31080b1347d2SRichard Henderson unsigned rs = nz ? rt : 0; 31090b1347d2SRichard Henderson unsigned len = 32 - clen; 3110eaa3783bSRichard Henderson TCGv_reg dest, val; 31110b1347d2SRichard Henderson 31120b1347d2SRichard Henderson if (c) { 31130b1347d2SRichard Henderson nullify_over(ctx); 31140b1347d2SRichard Henderson } 31150b1347d2SRichard Henderson if (cpos + len > 32) { 31160b1347d2SRichard Henderson len = 32 - cpos; 31170b1347d2SRichard Henderson } 31180b1347d2SRichard Henderson 31190b1347d2SRichard Henderson dest = dest_gpr(ctx, rt); 31200b1347d2SRichard Henderson val = load_gpr(ctx, rr); 31210b1347d2SRichard Henderson if (rs == 0) { 3122eaa3783bSRichard Henderson tcg_gen_deposit_z_reg(dest, val, cpos, len); 31230b1347d2SRichard Henderson } else { 3124eaa3783bSRichard Henderson tcg_gen_deposit_reg(dest, cpu_gr[rs], val, cpos, len); 31250b1347d2SRichard Henderson } 31260b1347d2SRichard Henderson save_gpr(ctx, rt, dest); 31270b1347d2SRichard Henderson 31280b1347d2SRichard Henderson /* Install the new nullification. */ 31290b1347d2SRichard Henderson cond_free(&ctx->null_cond); 31300b1347d2SRichard Henderson if (c) { 31310b1347d2SRichard Henderson ctx->null_cond = do_sed_cond(c, dest); 31320b1347d2SRichard Henderson } 3133869051eaSRichard Henderson return nullify_end(ctx, DISAS_NEXT); 31340b1347d2SRichard Henderson } 31350b1347d2SRichard Henderson 3136869051eaSRichard Henderson static DisasJumpType trans_depw_sar(DisasContext *ctx, uint32_t insn, 31370b1347d2SRichard Henderson const DisasInsn *di) 31380b1347d2SRichard Henderson { 31390b1347d2SRichard Henderson unsigned clen = extract32(insn, 0, 5); 31400b1347d2SRichard Henderson unsigned nz = extract32(insn, 10, 1); 31410b1347d2SRichard Henderson unsigned i = extract32(insn, 12, 1); 31420b1347d2SRichard Henderson unsigned c = extract32(insn, 13, 3); 31430b1347d2SRichard Henderson unsigned rt = extract32(insn, 21, 5); 31440b1347d2SRichard Henderson unsigned rs = nz ? rt : 0; 31450b1347d2SRichard Henderson unsigned len = 32 - clen; 3146eaa3783bSRichard Henderson TCGv_reg val, mask, tmp, shift, dest; 31470b1347d2SRichard Henderson unsigned msb = 1U << (len - 1); 31480b1347d2SRichard Henderson 31490b1347d2SRichard Henderson if (c) { 31500b1347d2SRichard Henderson nullify_over(ctx); 31510b1347d2SRichard Henderson } 31520b1347d2SRichard Henderson 31530b1347d2SRichard Henderson if (i) { 31540b1347d2SRichard Henderson val = load_const(ctx, low_sextract(insn, 16, 5)); 31550b1347d2SRichard Henderson } else { 31560b1347d2SRichard Henderson val = load_gpr(ctx, extract32(insn, 16, 5)); 31570b1347d2SRichard Henderson } 31580b1347d2SRichard Henderson dest = dest_gpr(ctx, rt); 31590b1347d2SRichard Henderson shift = tcg_temp_new(); 31600b1347d2SRichard Henderson tmp = tcg_temp_new(); 31610b1347d2SRichard Henderson 31620b1347d2SRichard Henderson /* Convert big-endian bit numbering in SAR to left-shift. */ 3163eaa3783bSRichard Henderson tcg_gen_xori_reg(shift, cpu_sar, TARGET_REGISTER_BITS - 1); 31640b1347d2SRichard Henderson 3165eaa3783bSRichard Henderson mask = tcg_const_reg(msb + (msb - 1)); 3166eaa3783bSRichard Henderson tcg_gen_and_reg(tmp, val, mask); 31670b1347d2SRichard Henderson if (rs) { 3168eaa3783bSRichard Henderson tcg_gen_shl_reg(mask, mask, shift); 3169eaa3783bSRichard Henderson tcg_gen_shl_reg(tmp, tmp, shift); 3170eaa3783bSRichard Henderson tcg_gen_andc_reg(dest, cpu_gr[rs], mask); 3171eaa3783bSRichard Henderson tcg_gen_or_reg(dest, dest, tmp); 31720b1347d2SRichard Henderson } else { 3173eaa3783bSRichard Henderson tcg_gen_shl_reg(dest, tmp, shift); 31740b1347d2SRichard Henderson } 31750b1347d2SRichard Henderson tcg_temp_free(shift); 31760b1347d2SRichard Henderson tcg_temp_free(mask); 31770b1347d2SRichard Henderson tcg_temp_free(tmp); 31780b1347d2SRichard Henderson save_gpr(ctx, rt, dest); 31790b1347d2SRichard Henderson 31800b1347d2SRichard Henderson /* Install the new nullification. */ 31810b1347d2SRichard Henderson cond_free(&ctx->null_cond); 31820b1347d2SRichard Henderson if (c) { 31830b1347d2SRichard Henderson ctx->null_cond = do_sed_cond(c, dest); 31840b1347d2SRichard Henderson } 3185869051eaSRichard Henderson return nullify_end(ctx, DISAS_NEXT); 31860b1347d2SRichard Henderson } 31870b1347d2SRichard Henderson 31880b1347d2SRichard Henderson static const DisasInsn table_depw[] = { 31890b1347d2SRichard Henderson { 0xd4000000u, 0xfc000be0u, trans_depw_sar }, 31900b1347d2SRichard Henderson { 0xd4000800u, 0xfc001800u, trans_depw_imm }, 31910b1347d2SRichard Henderson { 0xd4001800u, 0xfc001800u, trans_depw_imm_c }, 31920b1347d2SRichard Henderson }; 31930b1347d2SRichard Henderson 3194869051eaSRichard Henderson static DisasJumpType trans_be(DisasContext *ctx, uint32_t insn, bool is_l) 319598cd9ca7SRichard Henderson { 319698cd9ca7SRichard Henderson unsigned n = extract32(insn, 1, 1); 319798cd9ca7SRichard Henderson unsigned b = extract32(insn, 21, 5); 3198eaa3783bSRichard Henderson target_sreg disp = assemble_17(insn); 319998cd9ca7SRichard Henderson 320098cd9ca7SRichard Henderson /* unsigned s = low_uextract(insn, 13, 3); */ 320198cd9ca7SRichard Henderson /* ??? It seems like there should be a good way of using 320298cd9ca7SRichard Henderson "be disp(sr2, r0)", the canonical gateway entry mechanism 320398cd9ca7SRichard Henderson to our advantage. But that appears to be inconvenient to 320498cd9ca7SRichard Henderson manage along side branch delay slots. Therefore we handle 320598cd9ca7SRichard Henderson entry into the gateway page via absolute address. */ 320698cd9ca7SRichard Henderson 320798cd9ca7SRichard Henderson /* Since we don't implement spaces, just branch. Do notice the special 320898cd9ca7SRichard Henderson case of "be disp(*,r0)" using a direct branch to disp, so that we can 320998cd9ca7SRichard Henderson goto_tb to the TB containing the syscall. */ 321098cd9ca7SRichard Henderson if (b == 0) { 321198cd9ca7SRichard Henderson return do_dbranch(ctx, disp, is_l ? 31 : 0, n); 321298cd9ca7SRichard Henderson } else { 3213eaa3783bSRichard Henderson TCGv_reg tmp = get_temp(ctx); 3214eaa3783bSRichard Henderson tcg_gen_addi_reg(tmp, load_gpr(ctx, b), disp); 321598cd9ca7SRichard Henderson return do_ibranch(ctx, tmp, is_l ? 31 : 0, n); 321698cd9ca7SRichard Henderson } 321798cd9ca7SRichard Henderson } 321898cd9ca7SRichard Henderson 3219869051eaSRichard Henderson static DisasJumpType trans_bl(DisasContext *ctx, uint32_t insn, 322098cd9ca7SRichard Henderson const DisasInsn *di) 322198cd9ca7SRichard Henderson { 322298cd9ca7SRichard Henderson unsigned n = extract32(insn, 1, 1); 322398cd9ca7SRichard Henderson unsigned link = extract32(insn, 21, 5); 3224eaa3783bSRichard Henderson target_sreg disp = assemble_17(insn); 322598cd9ca7SRichard Henderson 322698cd9ca7SRichard Henderson return do_dbranch(ctx, iaoq_dest(ctx, disp), link, n); 322798cd9ca7SRichard Henderson } 322898cd9ca7SRichard Henderson 3229869051eaSRichard Henderson static DisasJumpType trans_bl_long(DisasContext *ctx, uint32_t insn, 323098cd9ca7SRichard Henderson const DisasInsn *di) 323198cd9ca7SRichard Henderson { 323298cd9ca7SRichard Henderson unsigned n = extract32(insn, 1, 1); 3233eaa3783bSRichard Henderson target_sreg disp = assemble_22(insn); 323498cd9ca7SRichard Henderson 323598cd9ca7SRichard Henderson return do_dbranch(ctx, iaoq_dest(ctx, disp), 2, n); 323698cd9ca7SRichard Henderson } 323798cd9ca7SRichard Henderson 3238869051eaSRichard Henderson static DisasJumpType trans_blr(DisasContext *ctx, uint32_t insn, 323998cd9ca7SRichard Henderson const DisasInsn *di) 324098cd9ca7SRichard Henderson { 324198cd9ca7SRichard Henderson unsigned n = extract32(insn, 1, 1); 324298cd9ca7SRichard Henderson unsigned rx = extract32(insn, 16, 5); 324398cd9ca7SRichard Henderson unsigned link = extract32(insn, 21, 5); 3244eaa3783bSRichard Henderson TCGv_reg tmp = get_temp(ctx); 324598cd9ca7SRichard Henderson 3246eaa3783bSRichard Henderson tcg_gen_shli_reg(tmp, load_gpr(ctx, rx), 3); 3247eaa3783bSRichard Henderson tcg_gen_addi_reg(tmp, tmp, ctx->iaoq_f + 8); 324898cd9ca7SRichard Henderson return do_ibranch(ctx, tmp, link, n); 324998cd9ca7SRichard Henderson } 325098cd9ca7SRichard Henderson 3251869051eaSRichard Henderson static DisasJumpType trans_bv(DisasContext *ctx, uint32_t insn, 325298cd9ca7SRichard Henderson const DisasInsn *di) 325398cd9ca7SRichard Henderson { 325498cd9ca7SRichard Henderson unsigned n = extract32(insn, 1, 1); 325598cd9ca7SRichard Henderson unsigned rx = extract32(insn, 16, 5); 325698cd9ca7SRichard Henderson unsigned rb = extract32(insn, 21, 5); 3257eaa3783bSRichard Henderson TCGv_reg dest; 325898cd9ca7SRichard Henderson 325998cd9ca7SRichard Henderson if (rx == 0) { 326098cd9ca7SRichard Henderson dest = load_gpr(ctx, rb); 326198cd9ca7SRichard Henderson } else { 326298cd9ca7SRichard Henderson dest = get_temp(ctx); 3263eaa3783bSRichard Henderson tcg_gen_shli_reg(dest, load_gpr(ctx, rx), 3); 3264eaa3783bSRichard Henderson tcg_gen_add_reg(dest, dest, load_gpr(ctx, rb)); 326598cd9ca7SRichard Henderson } 326698cd9ca7SRichard Henderson return do_ibranch(ctx, dest, 0, n); 326798cd9ca7SRichard Henderson } 326898cd9ca7SRichard Henderson 3269869051eaSRichard Henderson static DisasJumpType trans_bve(DisasContext *ctx, uint32_t insn, 327098cd9ca7SRichard Henderson const DisasInsn *di) 327198cd9ca7SRichard Henderson { 327298cd9ca7SRichard Henderson unsigned n = extract32(insn, 1, 1); 327398cd9ca7SRichard Henderson unsigned rb = extract32(insn, 21, 5); 327498cd9ca7SRichard Henderson unsigned link = extract32(insn, 13, 1) ? 2 : 0; 327598cd9ca7SRichard Henderson 327698cd9ca7SRichard Henderson return do_ibranch(ctx, load_gpr(ctx, rb), link, n); 327798cd9ca7SRichard Henderson } 327898cd9ca7SRichard Henderson 327998cd9ca7SRichard Henderson static const DisasInsn table_branch[] = { 328098cd9ca7SRichard Henderson { 0xe8000000u, 0xfc006000u, trans_bl }, /* B,L and B,L,PUSH */ 328198cd9ca7SRichard Henderson { 0xe800a000u, 0xfc00e000u, trans_bl_long }, 328298cd9ca7SRichard Henderson { 0xe8004000u, 0xfc00fffdu, trans_blr }, 328398cd9ca7SRichard Henderson { 0xe800c000u, 0xfc00fffdu, trans_bv }, 328498cd9ca7SRichard Henderson { 0xe800d000u, 0xfc00dffcu, trans_bve }, 328598cd9ca7SRichard Henderson }; 328698cd9ca7SRichard Henderson 3287869051eaSRichard Henderson static DisasJumpType trans_fop_wew_0c(DisasContext *ctx, uint32_t insn, 3288ebe9383cSRichard Henderson const DisasInsn *di) 3289ebe9383cSRichard Henderson { 3290ebe9383cSRichard Henderson unsigned rt = extract32(insn, 0, 5); 3291ebe9383cSRichard Henderson unsigned ra = extract32(insn, 21, 5); 3292eff235ebSPaolo Bonzini return do_fop_wew(ctx, rt, ra, di->f.wew); 3293ebe9383cSRichard Henderson } 3294ebe9383cSRichard Henderson 3295869051eaSRichard Henderson static DisasJumpType trans_fop_wew_0e(DisasContext *ctx, uint32_t insn, 3296ebe9383cSRichard Henderson const DisasInsn *di) 3297ebe9383cSRichard Henderson { 3298ebe9383cSRichard Henderson unsigned rt = assemble_rt64(insn); 3299ebe9383cSRichard Henderson unsigned ra = assemble_ra64(insn); 3300eff235ebSPaolo Bonzini return do_fop_wew(ctx, rt, ra, di->f.wew); 3301ebe9383cSRichard Henderson } 3302ebe9383cSRichard Henderson 3303869051eaSRichard Henderson static DisasJumpType trans_fop_ded(DisasContext *ctx, uint32_t insn, 3304ebe9383cSRichard Henderson const DisasInsn *di) 3305ebe9383cSRichard Henderson { 3306ebe9383cSRichard Henderson unsigned rt = extract32(insn, 0, 5); 3307ebe9383cSRichard Henderson unsigned ra = extract32(insn, 21, 5); 3308eff235ebSPaolo Bonzini return do_fop_ded(ctx, rt, ra, di->f.ded); 3309ebe9383cSRichard Henderson } 3310ebe9383cSRichard Henderson 3311869051eaSRichard Henderson static DisasJumpType trans_fop_wed_0c(DisasContext *ctx, uint32_t insn, 3312ebe9383cSRichard Henderson const DisasInsn *di) 3313ebe9383cSRichard Henderson { 3314ebe9383cSRichard Henderson unsigned rt = extract32(insn, 0, 5); 3315ebe9383cSRichard Henderson unsigned ra = extract32(insn, 21, 5); 3316eff235ebSPaolo Bonzini return do_fop_wed(ctx, rt, ra, di->f.wed); 3317ebe9383cSRichard Henderson } 3318ebe9383cSRichard Henderson 3319869051eaSRichard Henderson static DisasJumpType trans_fop_wed_0e(DisasContext *ctx, uint32_t insn, 3320ebe9383cSRichard Henderson const DisasInsn *di) 3321ebe9383cSRichard Henderson { 3322ebe9383cSRichard Henderson unsigned rt = assemble_rt64(insn); 3323ebe9383cSRichard Henderson unsigned ra = extract32(insn, 21, 5); 3324eff235ebSPaolo Bonzini return do_fop_wed(ctx, rt, ra, di->f.wed); 3325ebe9383cSRichard Henderson } 3326ebe9383cSRichard Henderson 3327869051eaSRichard Henderson static DisasJumpType trans_fop_dew_0c(DisasContext *ctx, uint32_t insn, 3328ebe9383cSRichard Henderson const DisasInsn *di) 3329ebe9383cSRichard Henderson { 3330ebe9383cSRichard Henderson unsigned rt = extract32(insn, 0, 5); 3331ebe9383cSRichard Henderson unsigned ra = extract32(insn, 21, 5); 3332eff235ebSPaolo Bonzini return do_fop_dew(ctx, rt, ra, di->f.dew); 3333ebe9383cSRichard Henderson } 3334ebe9383cSRichard Henderson 3335869051eaSRichard Henderson static DisasJumpType trans_fop_dew_0e(DisasContext *ctx, uint32_t insn, 3336ebe9383cSRichard Henderson const DisasInsn *di) 3337ebe9383cSRichard Henderson { 3338ebe9383cSRichard Henderson unsigned rt = extract32(insn, 0, 5); 3339ebe9383cSRichard Henderson unsigned ra = assemble_ra64(insn); 3340eff235ebSPaolo Bonzini return do_fop_dew(ctx, rt, ra, di->f.dew); 3341ebe9383cSRichard Henderson } 3342ebe9383cSRichard Henderson 3343869051eaSRichard Henderson static DisasJumpType trans_fop_weww_0c(DisasContext *ctx, uint32_t insn, 3344ebe9383cSRichard Henderson const DisasInsn *di) 3345ebe9383cSRichard Henderson { 3346ebe9383cSRichard Henderson unsigned rt = extract32(insn, 0, 5); 3347ebe9383cSRichard Henderson unsigned rb = extract32(insn, 16, 5); 3348ebe9383cSRichard Henderson unsigned ra = extract32(insn, 21, 5); 3349eff235ebSPaolo Bonzini return do_fop_weww(ctx, rt, ra, rb, di->f.weww); 3350ebe9383cSRichard Henderson } 3351ebe9383cSRichard Henderson 3352869051eaSRichard Henderson static DisasJumpType trans_fop_weww_0e(DisasContext *ctx, uint32_t insn, 3353ebe9383cSRichard Henderson const DisasInsn *di) 3354ebe9383cSRichard Henderson { 3355ebe9383cSRichard Henderson unsigned rt = assemble_rt64(insn); 3356ebe9383cSRichard Henderson unsigned rb = assemble_rb64(insn); 3357ebe9383cSRichard Henderson unsigned ra = assemble_ra64(insn); 3358eff235ebSPaolo Bonzini return do_fop_weww(ctx, rt, ra, rb, di->f.weww); 3359ebe9383cSRichard Henderson } 3360ebe9383cSRichard Henderson 3361869051eaSRichard Henderson static DisasJumpType trans_fop_dedd(DisasContext *ctx, uint32_t insn, 3362ebe9383cSRichard Henderson const DisasInsn *di) 3363ebe9383cSRichard Henderson { 3364ebe9383cSRichard Henderson unsigned rt = extract32(insn, 0, 5); 3365ebe9383cSRichard Henderson unsigned rb = extract32(insn, 16, 5); 3366ebe9383cSRichard Henderson unsigned ra = extract32(insn, 21, 5); 3367eff235ebSPaolo Bonzini return do_fop_dedd(ctx, rt, ra, rb, di->f.dedd); 3368ebe9383cSRichard Henderson } 3369ebe9383cSRichard Henderson 3370ebe9383cSRichard Henderson static void gen_fcpy_s(TCGv_i32 dst, TCGv_env unused, TCGv_i32 src) 3371ebe9383cSRichard Henderson { 3372ebe9383cSRichard Henderson tcg_gen_mov_i32(dst, src); 3373ebe9383cSRichard Henderson } 3374ebe9383cSRichard Henderson 3375ebe9383cSRichard Henderson static void gen_fcpy_d(TCGv_i64 dst, TCGv_env unused, TCGv_i64 src) 3376ebe9383cSRichard Henderson { 3377ebe9383cSRichard Henderson tcg_gen_mov_i64(dst, src); 3378ebe9383cSRichard Henderson } 3379ebe9383cSRichard Henderson 3380ebe9383cSRichard Henderson static void gen_fabs_s(TCGv_i32 dst, TCGv_env unused, TCGv_i32 src) 3381ebe9383cSRichard Henderson { 3382ebe9383cSRichard Henderson tcg_gen_andi_i32(dst, src, INT32_MAX); 3383ebe9383cSRichard Henderson } 3384ebe9383cSRichard Henderson 3385ebe9383cSRichard Henderson static void gen_fabs_d(TCGv_i64 dst, TCGv_env unused, TCGv_i64 src) 3386ebe9383cSRichard Henderson { 3387ebe9383cSRichard Henderson tcg_gen_andi_i64(dst, src, INT64_MAX); 3388ebe9383cSRichard Henderson } 3389ebe9383cSRichard Henderson 3390ebe9383cSRichard Henderson static void gen_fneg_s(TCGv_i32 dst, TCGv_env unused, TCGv_i32 src) 3391ebe9383cSRichard Henderson { 3392ebe9383cSRichard Henderson tcg_gen_xori_i32(dst, src, INT32_MIN); 3393ebe9383cSRichard Henderson } 3394ebe9383cSRichard Henderson 3395ebe9383cSRichard Henderson static void gen_fneg_d(TCGv_i64 dst, TCGv_env unused, TCGv_i64 src) 3396ebe9383cSRichard Henderson { 3397ebe9383cSRichard Henderson tcg_gen_xori_i64(dst, src, INT64_MIN); 3398ebe9383cSRichard Henderson } 3399ebe9383cSRichard Henderson 3400ebe9383cSRichard Henderson static void gen_fnegabs_s(TCGv_i32 dst, TCGv_env unused, TCGv_i32 src) 3401ebe9383cSRichard Henderson { 3402ebe9383cSRichard Henderson tcg_gen_ori_i32(dst, src, INT32_MIN); 3403ebe9383cSRichard Henderson } 3404ebe9383cSRichard Henderson 3405ebe9383cSRichard Henderson static void gen_fnegabs_d(TCGv_i64 dst, TCGv_env unused, TCGv_i64 src) 3406ebe9383cSRichard Henderson { 3407ebe9383cSRichard Henderson tcg_gen_ori_i64(dst, src, INT64_MIN); 3408ebe9383cSRichard Henderson } 3409ebe9383cSRichard Henderson 3410869051eaSRichard Henderson static DisasJumpType do_fcmp_s(DisasContext *ctx, unsigned ra, unsigned rb, 3411ebe9383cSRichard Henderson unsigned y, unsigned c) 3412ebe9383cSRichard Henderson { 3413ebe9383cSRichard Henderson TCGv_i32 ta, tb, tc, ty; 3414ebe9383cSRichard Henderson 3415ebe9383cSRichard Henderson nullify_over(ctx); 3416ebe9383cSRichard Henderson 3417ebe9383cSRichard Henderson ta = load_frw0_i32(ra); 3418ebe9383cSRichard Henderson tb = load_frw0_i32(rb); 3419ebe9383cSRichard Henderson ty = tcg_const_i32(y); 3420ebe9383cSRichard Henderson tc = tcg_const_i32(c); 3421ebe9383cSRichard Henderson 3422ebe9383cSRichard Henderson gen_helper_fcmp_s(cpu_env, ta, tb, ty, tc); 3423ebe9383cSRichard Henderson 3424ebe9383cSRichard Henderson tcg_temp_free_i32(ta); 3425ebe9383cSRichard Henderson tcg_temp_free_i32(tb); 3426ebe9383cSRichard Henderson tcg_temp_free_i32(ty); 3427ebe9383cSRichard Henderson tcg_temp_free_i32(tc); 3428ebe9383cSRichard Henderson 3429869051eaSRichard Henderson return nullify_end(ctx, DISAS_NEXT); 3430ebe9383cSRichard Henderson } 3431ebe9383cSRichard Henderson 3432869051eaSRichard Henderson static DisasJumpType trans_fcmp_s_0c(DisasContext *ctx, uint32_t insn, 3433ebe9383cSRichard Henderson const DisasInsn *di) 3434ebe9383cSRichard Henderson { 3435ebe9383cSRichard Henderson unsigned c = extract32(insn, 0, 5); 3436ebe9383cSRichard Henderson unsigned y = extract32(insn, 13, 3); 3437ebe9383cSRichard Henderson unsigned rb = extract32(insn, 16, 5); 3438ebe9383cSRichard Henderson unsigned ra = extract32(insn, 21, 5); 3439ebe9383cSRichard Henderson return do_fcmp_s(ctx, ra, rb, y, c); 3440ebe9383cSRichard Henderson } 3441ebe9383cSRichard Henderson 3442869051eaSRichard Henderson static DisasJumpType trans_fcmp_s_0e(DisasContext *ctx, uint32_t insn, 3443ebe9383cSRichard Henderson const DisasInsn *di) 3444ebe9383cSRichard Henderson { 3445ebe9383cSRichard Henderson unsigned c = extract32(insn, 0, 5); 3446ebe9383cSRichard Henderson unsigned y = extract32(insn, 13, 3); 3447ebe9383cSRichard Henderson unsigned rb = assemble_rb64(insn); 3448ebe9383cSRichard Henderson unsigned ra = assemble_ra64(insn); 3449ebe9383cSRichard Henderson return do_fcmp_s(ctx, ra, rb, y, c); 3450ebe9383cSRichard Henderson } 3451ebe9383cSRichard Henderson 3452869051eaSRichard Henderson static DisasJumpType trans_fcmp_d(DisasContext *ctx, uint32_t insn, 3453ebe9383cSRichard Henderson const DisasInsn *di) 3454ebe9383cSRichard Henderson { 3455ebe9383cSRichard Henderson unsigned c = extract32(insn, 0, 5); 3456ebe9383cSRichard Henderson unsigned y = extract32(insn, 13, 3); 3457ebe9383cSRichard Henderson unsigned rb = extract32(insn, 16, 5); 3458ebe9383cSRichard Henderson unsigned ra = extract32(insn, 21, 5); 3459ebe9383cSRichard Henderson TCGv_i64 ta, tb; 3460ebe9383cSRichard Henderson TCGv_i32 tc, ty; 3461ebe9383cSRichard Henderson 3462ebe9383cSRichard Henderson nullify_over(ctx); 3463ebe9383cSRichard Henderson 3464ebe9383cSRichard Henderson ta = load_frd0(ra); 3465ebe9383cSRichard Henderson tb = load_frd0(rb); 3466ebe9383cSRichard Henderson ty = tcg_const_i32(y); 3467ebe9383cSRichard Henderson tc = tcg_const_i32(c); 3468ebe9383cSRichard Henderson 3469ebe9383cSRichard Henderson gen_helper_fcmp_d(cpu_env, ta, tb, ty, tc); 3470ebe9383cSRichard Henderson 3471ebe9383cSRichard Henderson tcg_temp_free_i64(ta); 3472ebe9383cSRichard Henderson tcg_temp_free_i64(tb); 3473ebe9383cSRichard Henderson tcg_temp_free_i32(ty); 3474ebe9383cSRichard Henderson tcg_temp_free_i32(tc); 3475ebe9383cSRichard Henderson 3476869051eaSRichard Henderson return nullify_end(ctx, DISAS_NEXT); 3477ebe9383cSRichard Henderson } 3478ebe9383cSRichard Henderson 3479869051eaSRichard Henderson static DisasJumpType trans_ftest_t(DisasContext *ctx, uint32_t insn, 3480ebe9383cSRichard Henderson const DisasInsn *di) 3481ebe9383cSRichard Henderson { 3482ebe9383cSRichard Henderson unsigned y = extract32(insn, 13, 3); 3483ebe9383cSRichard Henderson unsigned cbit = (y ^ 1) - 1; 3484eaa3783bSRichard Henderson TCGv_reg t; 3485ebe9383cSRichard Henderson 3486ebe9383cSRichard Henderson nullify_over(ctx); 3487ebe9383cSRichard Henderson 3488ebe9383cSRichard Henderson t = tcg_temp_new(); 3489eaa3783bSRichard Henderson tcg_gen_ld32u_reg(t, cpu_env, offsetof(CPUHPPAState, fr0_shadow)); 3490eaa3783bSRichard Henderson tcg_gen_extract_reg(t, t, 21 - cbit, 1); 3491ebe9383cSRichard Henderson ctx->null_cond = cond_make_0(TCG_COND_NE, t); 3492ebe9383cSRichard Henderson tcg_temp_free(t); 3493ebe9383cSRichard Henderson 3494869051eaSRichard Henderson return nullify_end(ctx, DISAS_NEXT); 3495ebe9383cSRichard Henderson } 3496ebe9383cSRichard Henderson 3497869051eaSRichard Henderson static DisasJumpType trans_ftest_q(DisasContext *ctx, uint32_t insn, 3498ebe9383cSRichard Henderson const DisasInsn *di) 3499ebe9383cSRichard Henderson { 3500ebe9383cSRichard Henderson unsigned c = extract32(insn, 0, 5); 3501ebe9383cSRichard Henderson int mask; 3502ebe9383cSRichard Henderson bool inv = false; 3503eaa3783bSRichard Henderson TCGv_reg t; 3504ebe9383cSRichard Henderson 3505ebe9383cSRichard Henderson nullify_over(ctx); 3506ebe9383cSRichard Henderson 3507ebe9383cSRichard Henderson t = tcg_temp_new(); 3508eaa3783bSRichard Henderson tcg_gen_ld32u_reg(t, cpu_env, offsetof(CPUHPPAState, fr0_shadow)); 3509ebe9383cSRichard Henderson 3510ebe9383cSRichard Henderson switch (c) { 3511ebe9383cSRichard Henderson case 0: /* simple */ 3512eaa3783bSRichard Henderson tcg_gen_andi_reg(t, t, 0x4000000); 3513ebe9383cSRichard Henderson ctx->null_cond = cond_make_0(TCG_COND_NE, t); 3514ebe9383cSRichard Henderson goto done; 3515ebe9383cSRichard Henderson case 2: /* rej */ 3516ebe9383cSRichard Henderson inv = true; 3517ebe9383cSRichard Henderson /* fallthru */ 3518ebe9383cSRichard Henderson case 1: /* acc */ 3519ebe9383cSRichard Henderson mask = 0x43ff800; 3520ebe9383cSRichard Henderson break; 3521ebe9383cSRichard Henderson case 6: /* rej8 */ 3522ebe9383cSRichard Henderson inv = true; 3523ebe9383cSRichard Henderson /* fallthru */ 3524ebe9383cSRichard Henderson case 5: /* acc8 */ 3525ebe9383cSRichard Henderson mask = 0x43f8000; 3526ebe9383cSRichard Henderson break; 3527ebe9383cSRichard Henderson case 9: /* acc6 */ 3528ebe9383cSRichard Henderson mask = 0x43e0000; 3529ebe9383cSRichard Henderson break; 3530ebe9383cSRichard Henderson case 13: /* acc4 */ 3531ebe9383cSRichard Henderson mask = 0x4380000; 3532ebe9383cSRichard Henderson break; 3533ebe9383cSRichard Henderson case 17: /* acc2 */ 3534ebe9383cSRichard Henderson mask = 0x4200000; 3535ebe9383cSRichard Henderson break; 3536ebe9383cSRichard Henderson default: 3537ebe9383cSRichard Henderson return gen_illegal(ctx); 3538ebe9383cSRichard Henderson } 3539ebe9383cSRichard Henderson if (inv) { 3540eaa3783bSRichard Henderson TCGv_reg c = load_const(ctx, mask); 3541eaa3783bSRichard Henderson tcg_gen_or_reg(t, t, c); 3542ebe9383cSRichard Henderson ctx->null_cond = cond_make(TCG_COND_EQ, t, c); 3543ebe9383cSRichard Henderson } else { 3544eaa3783bSRichard Henderson tcg_gen_andi_reg(t, t, mask); 3545ebe9383cSRichard Henderson ctx->null_cond = cond_make_0(TCG_COND_EQ, t); 3546ebe9383cSRichard Henderson } 3547ebe9383cSRichard Henderson done: 3548869051eaSRichard Henderson return nullify_end(ctx, DISAS_NEXT); 3549ebe9383cSRichard Henderson } 3550ebe9383cSRichard Henderson 3551869051eaSRichard Henderson static DisasJumpType trans_xmpyu(DisasContext *ctx, uint32_t insn, 3552ebe9383cSRichard Henderson const DisasInsn *di) 3553ebe9383cSRichard Henderson { 3554ebe9383cSRichard Henderson unsigned rt = extract32(insn, 0, 5); 3555ebe9383cSRichard Henderson unsigned rb = assemble_rb64(insn); 3556ebe9383cSRichard Henderson unsigned ra = assemble_ra64(insn); 3557ebe9383cSRichard Henderson TCGv_i64 a, b; 3558ebe9383cSRichard Henderson 3559ebe9383cSRichard Henderson nullify_over(ctx); 3560ebe9383cSRichard Henderson 3561ebe9383cSRichard Henderson a = load_frw0_i64(ra); 3562ebe9383cSRichard Henderson b = load_frw0_i64(rb); 3563ebe9383cSRichard Henderson tcg_gen_mul_i64(a, a, b); 3564ebe9383cSRichard Henderson save_frd(rt, a); 3565ebe9383cSRichard Henderson tcg_temp_free_i64(a); 3566ebe9383cSRichard Henderson tcg_temp_free_i64(b); 3567ebe9383cSRichard Henderson 3568869051eaSRichard Henderson return nullify_end(ctx, DISAS_NEXT); 3569ebe9383cSRichard Henderson } 3570ebe9383cSRichard Henderson 3571eff235ebSPaolo Bonzini #define FOP_DED trans_fop_ded, .f.ded 3572eff235ebSPaolo Bonzini #define FOP_DEDD trans_fop_dedd, .f.dedd 3573ebe9383cSRichard Henderson 3574eff235ebSPaolo Bonzini #define FOP_WEW trans_fop_wew_0c, .f.wew 3575eff235ebSPaolo Bonzini #define FOP_DEW trans_fop_dew_0c, .f.dew 3576eff235ebSPaolo Bonzini #define FOP_WED trans_fop_wed_0c, .f.wed 3577eff235ebSPaolo Bonzini #define FOP_WEWW trans_fop_weww_0c, .f.weww 3578ebe9383cSRichard Henderson 3579ebe9383cSRichard Henderson static const DisasInsn table_float_0c[] = { 3580ebe9383cSRichard Henderson /* floating point class zero */ 3581ebe9383cSRichard Henderson { 0x30004000, 0xfc1fffe0, FOP_WEW = gen_fcpy_s }, 3582ebe9383cSRichard Henderson { 0x30006000, 0xfc1fffe0, FOP_WEW = gen_fabs_s }, 3583ebe9383cSRichard Henderson { 0x30008000, 0xfc1fffe0, FOP_WEW = gen_helper_fsqrt_s }, 3584ebe9383cSRichard Henderson { 0x3000a000, 0xfc1fffe0, FOP_WEW = gen_helper_frnd_s }, 3585ebe9383cSRichard Henderson { 0x3000c000, 0xfc1fffe0, FOP_WEW = gen_fneg_s }, 3586ebe9383cSRichard Henderson { 0x3000e000, 0xfc1fffe0, FOP_WEW = gen_fnegabs_s }, 3587ebe9383cSRichard Henderson 3588ebe9383cSRichard Henderson { 0x30004800, 0xfc1fffe0, FOP_DED = gen_fcpy_d }, 3589ebe9383cSRichard Henderson { 0x30006800, 0xfc1fffe0, FOP_DED = gen_fabs_d }, 3590ebe9383cSRichard Henderson { 0x30008800, 0xfc1fffe0, FOP_DED = gen_helper_fsqrt_d }, 3591ebe9383cSRichard Henderson { 0x3000a800, 0xfc1fffe0, FOP_DED = gen_helper_frnd_d }, 3592ebe9383cSRichard Henderson { 0x3000c800, 0xfc1fffe0, FOP_DED = gen_fneg_d }, 3593ebe9383cSRichard Henderson { 0x3000e800, 0xfc1fffe0, FOP_DED = gen_fnegabs_d }, 3594ebe9383cSRichard Henderson 3595ebe9383cSRichard Henderson /* floating point class three */ 3596ebe9383cSRichard Henderson { 0x30000600, 0xfc00ffe0, FOP_WEWW = gen_helper_fadd_s }, 3597ebe9383cSRichard Henderson { 0x30002600, 0xfc00ffe0, FOP_WEWW = gen_helper_fsub_s }, 3598ebe9383cSRichard Henderson { 0x30004600, 0xfc00ffe0, FOP_WEWW = gen_helper_fmpy_s }, 3599ebe9383cSRichard Henderson { 0x30006600, 0xfc00ffe0, FOP_WEWW = gen_helper_fdiv_s }, 3600ebe9383cSRichard Henderson 3601ebe9383cSRichard Henderson { 0x30000e00, 0xfc00ffe0, FOP_DEDD = gen_helper_fadd_d }, 3602ebe9383cSRichard Henderson { 0x30002e00, 0xfc00ffe0, FOP_DEDD = gen_helper_fsub_d }, 3603ebe9383cSRichard Henderson { 0x30004e00, 0xfc00ffe0, FOP_DEDD = gen_helper_fmpy_d }, 3604ebe9383cSRichard Henderson { 0x30006e00, 0xfc00ffe0, FOP_DEDD = gen_helper_fdiv_d }, 3605ebe9383cSRichard Henderson 3606ebe9383cSRichard Henderson /* floating point class one */ 3607ebe9383cSRichard Henderson /* float/float */ 3608ebe9383cSRichard Henderson { 0x30000a00, 0xfc1fffe0, FOP_WED = gen_helper_fcnv_d_s }, 3609ebe9383cSRichard Henderson { 0x30002200, 0xfc1fffe0, FOP_DEW = gen_helper_fcnv_s_d }, 3610ebe9383cSRichard Henderson /* int/float */ 3611ebe9383cSRichard Henderson { 0x30008200, 0xfc1fffe0, FOP_WEW = gen_helper_fcnv_w_s }, 3612ebe9383cSRichard Henderson { 0x30008a00, 0xfc1fffe0, FOP_WED = gen_helper_fcnv_dw_s }, 3613ebe9383cSRichard Henderson { 0x3000a200, 0xfc1fffe0, FOP_DEW = gen_helper_fcnv_w_d }, 3614ebe9383cSRichard Henderson { 0x3000aa00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_dw_d }, 3615ebe9383cSRichard Henderson /* float/int */ 3616ebe9383cSRichard Henderson { 0x30010200, 0xfc1fffe0, FOP_WEW = gen_helper_fcnv_s_w }, 3617ebe9383cSRichard Henderson { 0x30010a00, 0xfc1fffe0, FOP_WED = gen_helper_fcnv_d_w }, 3618ebe9383cSRichard Henderson { 0x30012200, 0xfc1fffe0, FOP_DEW = gen_helper_fcnv_s_dw }, 3619ebe9383cSRichard Henderson { 0x30012a00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_d_dw }, 3620ebe9383cSRichard Henderson /* float/int truncate */ 3621ebe9383cSRichard Henderson { 0x30018200, 0xfc1fffe0, FOP_WEW = gen_helper_fcnv_t_s_w }, 3622ebe9383cSRichard Henderson { 0x30018a00, 0xfc1fffe0, FOP_WED = gen_helper_fcnv_t_d_w }, 3623ebe9383cSRichard Henderson { 0x3001a200, 0xfc1fffe0, FOP_DEW = gen_helper_fcnv_t_s_dw }, 3624ebe9383cSRichard Henderson { 0x3001aa00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_t_d_dw }, 3625ebe9383cSRichard Henderson /* uint/float */ 3626ebe9383cSRichard Henderson { 0x30028200, 0xfc1fffe0, FOP_WEW = gen_helper_fcnv_uw_s }, 3627ebe9383cSRichard Henderson { 0x30028a00, 0xfc1fffe0, FOP_WED = gen_helper_fcnv_udw_s }, 3628ebe9383cSRichard Henderson { 0x3002a200, 0xfc1fffe0, FOP_DEW = gen_helper_fcnv_uw_d }, 3629ebe9383cSRichard Henderson { 0x3002aa00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_udw_d }, 3630ebe9383cSRichard Henderson /* float/uint */ 3631ebe9383cSRichard Henderson { 0x30030200, 0xfc1fffe0, FOP_WEW = gen_helper_fcnv_s_uw }, 3632ebe9383cSRichard Henderson { 0x30030a00, 0xfc1fffe0, FOP_WED = gen_helper_fcnv_d_uw }, 3633ebe9383cSRichard Henderson { 0x30032200, 0xfc1fffe0, FOP_DEW = gen_helper_fcnv_s_udw }, 3634ebe9383cSRichard Henderson { 0x30032a00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_d_udw }, 3635ebe9383cSRichard Henderson /* float/uint truncate */ 3636ebe9383cSRichard Henderson { 0x30038200, 0xfc1fffe0, FOP_WEW = gen_helper_fcnv_t_s_uw }, 3637ebe9383cSRichard Henderson { 0x30038a00, 0xfc1fffe0, FOP_WED = gen_helper_fcnv_t_d_uw }, 3638ebe9383cSRichard Henderson { 0x3003a200, 0xfc1fffe0, FOP_DEW = gen_helper_fcnv_t_s_udw }, 3639ebe9383cSRichard Henderson { 0x3003aa00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_t_d_udw }, 3640ebe9383cSRichard Henderson 3641ebe9383cSRichard Henderson /* floating point class two */ 3642ebe9383cSRichard Henderson { 0x30000400, 0xfc001fe0, trans_fcmp_s_0c }, 3643ebe9383cSRichard Henderson { 0x30000c00, 0xfc001fe0, trans_fcmp_d }, 3644ebe9383cSRichard Henderson { 0x30002420, 0xffffffe0, trans_ftest_q }, 3645ebe9383cSRichard Henderson { 0x30000420, 0xffff1fff, trans_ftest_t }, 3646ebe9383cSRichard Henderson 3647ebe9383cSRichard Henderson /* FID. Note that ra == rt == 0, which via fcpy puts 0 into fr0. 3648ebe9383cSRichard Henderson This is machine/revision == 0, which is reserved for simulator. */ 3649ebe9383cSRichard Henderson { 0x30000000, 0xffffffff, FOP_WEW = gen_fcpy_s }, 3650ebe9383cSRichard Henderson }; 3651ebe9383cSRichard Henderson 3652ebe9383cSRichard Henderson #undef FOP_WEW 3653ebe9383cSRichard Henderson #undef FOP_DEW 3654ebe9383cSRichard Henderson #undef FOP_WED 3655ebe9383cSRichard Henderson #undef FOP_WEWW 3656eff235ebSPaolo Bonzini #define FOP_WEW trans_fop_wew_0e, .f.wew 3657eff235ebSPaolo Bonzini #define FOP_DEW trans_fop_dew_0e, .f.dew 3658eff235ebSPaolo Bonzini #define FOP_WED trans_fop_wed_0e, .f.wed 3659eff235ebSPaolo Bonzini #define FOP_WEWW trans_fop_weww_0e, .f.weww 3660ebe9383cSRichard Henderson 3661ebe9383cSRichard Henderson static const DisasInsn table_float_0e[] = { 3662ebe9383cSRichard Henderson /* floating point class zero */ 3663ebe9383cSRichard Henderson { 0x38004000, 0xfc1fff20, FOP_WEW = gen_fcpy_s }, 3664ebe9383cSRichard Henderson { 0x38006000, 0xfc1fff20, FOP_WEW = gen_fabs_s }, 3665ebe9383cSRichard Henderson { 0x38008000, 0xfc1fff20, FOP_WEW = gen_helper_fsqrt_s }, 3666ebe9383cSRichard Henderson { 0x3800a000, 0xfc1fff20, FOP_WEW = gen_helper_frnd_s }, 3667ebe9383cSRichard Henderson { 0x3800c000, 0xfc1fff20, FOP_WEW = gen_fneg_s }, 3668ebe9383cSRichard Henderson { 0x3800e000, 0xfc1fff20, FOP_WEW = gen_fnegabs_s }, 3669ebe9383cSRichard Henderson 3670ebe9383cSRichard Henderson { 0x38004800, 0xfc1fffe0, FOP_DED = gen_fcpy_d }, 3671ebe9383cSRichard Henderson { 0x38006800, 0xfc1fffe0, FOP_DED = gen_fabs_d }, 3672ebe9383cSRichard Henderson { 0x38008800, 0xfc1fffe0, FOP_DED = gen_helper_fsqrt_d }, 3673ebe9383cSRichard Henderson { 0x3800a800, 0xfc1fffe0, FOP_DED = gen_helper_frnd_d }, 3674ebe9383cSRichard Henderson { 0x3800c800, 0xfc1fffe0, FOP_DED = gen_fneg_d }, 3675ebe9383cSRichard Henderson { 0x3800e800, 0xfc1fffe0, FOP_DED = gen_fnegabs_d }, 3676ebe9383cSRichard Henderson 3677ebe9383cSRichard Henderson /* floating point class three */ 3678ebe9383cSRichard Henderson { 0x38000600, 0xfc00ef20, FOP_WEWW = gen_helper_fadd_s }, 3679ebe9383cSRichard Henderson { 0x38002600, 0xfc00ef20, FOP_WEWW = gen_helper_fsub_s }, 3680ebe9383cSRichard Henderson { 0x38004600, 0xfc00ef20, FOP_WEWW = gen_helper_fmpy_s }, 3681ebe9383cSRichard Henderson { 0x38006600, 0xfc00ef20, FOP_WEWW = gen_helper_fdiv_s }, 3682ebe9383cSRichard Henderson 3683ebe9383cSRichard Henderson { 0x38000e00, 0xfc00ffe0, FOP_DEDD = gen_helper_fadd_d }, 3684ebe9383cSRichard Henderson { 0x38002e00, 0xfc00ffe0, FOP_DEDD = gen_helper_fsub_d }, 3685ebe9383cSRichard Henderson { 0x38004e00, 0xfc00ffe0, FOP_DEDD = gen_helper_fmpy_d }, 3686ebe9383cSRichard Henderson { 0x38006e00, 0xfc00ffe0, FOP_DEDD = gen_helper_fdiv_d }, 3687ebe9383cSRichard Henderson 3688ebe9383cSRichard Henderson { 0x38004700, 0xfc00ef60, trans_xmpyu }, 3689ebe9383cSRichard Henderson 3690ebe9383cSRichard Henderson /* floating point class one */ 3691ebe9383cSRichard Henderson /* float/float */ 3692ebe9383cSRichard Henderson { 0x38000a00, 0xfc1fffa0, FOP_WED = gen_helper_fcnv_d_s }, 3693ebe9383cSRichard Henderson { 0x38002200, 0xfc1fffc0, FOP_DEW = gen_helper_fcnv_s_d }, 3694ebe9383cSRichard Henderson /* int/float */ 3695ebe9383cSRichard Henderson { 0x38008200, 0xfc1ffe60, FOP_WEW = gen_helper_fcnv_w_s }, 3696ebe9383cSRichard Henderson { 0x38008a00, 0xfc1fffa0, FOP_WED = gen_helper_fcnv_dw_s }, 3697ebe9383cSRichard Henderson { 0x3800a200, 0xfc1fff60, FOP_DEW = gen_helper_fcnv_w_d }, 3698ebe9383cSRichard Henderson { 0x3800aa00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_dw_d }, 3699ebe9383cSRichard Henderson /* float/int */ 3700ebe9383cSRichard Henderson { 0x38010200, 0xfc1ffe60, FOP_WEW = gen_helper_fcnv_s_w }, 3701ebe9383cSRichard Henderson { 0x38010a00, 0xfc1fffa0, FOP_WED = gen_helper_fcnv_d_w }, 3702ebe9383cSRichard Henderson { 0x38012200, 0xfc1fff60, FOP_DEW = gen_helper_fcnv_s_dw }, 3703ebe9383cSRichard Henderson { 0x38012a00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_d_dw }, 3704ebe9383cSRichard Henderson /* float/int truncate */ 3705ebe9383cSRichard Henderson { 0x38018200, 0xfc1ffe60, FOP_WEW = gen_helper_fcnv_t_s_w }, 3706ebe9383cSRichard Henderson { 0x38018a00, 0xfc1fffa0, FOP_WED = gen_helper_fcnv_t_d_w }, 3707ebe9383cSRichard Henderson { 0x3801a200, 0xfc1fff60, FOP_DEW = gen_helper_fcnv_t_s_dw }, 3708ebe9383cSRichard Henderson { 0x3801aa00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_t_d_dw }, 3709ebe9383cSRichard Henderson /* uint/float */ 3710ebe9383cSRichard Henderson { 0x38028200, 0xfc1ffe60, FOP_WEW = gen_helper_fcnv_uw_s }, 3711ebe9383cSRichard Henderson { 0x38028a00, 0xfc1fffa0, FOP_WED = gen_helper_fcnv_udw_s }, 3712ebe9383cSRichard Henderson { 0x3802a200, 0xfc1fff60, FOP_DEW = gen_helper_fcnv_uw_d }, 3713ebe9383cSRichard Henderson { 0x3802aa00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_udw_d }, 3714ebe9383cSRichard Henderson /* float/uint */ 3715ebe9383cSRichard Henderson { 0x38030200, 0xfc1ffe60, FOP_WEW = gen_helper_fcnv_s_uw }, 3716ebe9383cSRichard Henderson { 0x38030a00, 0xfc1fffa0, FOP_WED = gen_helper_fcnv_d_uw }, 3717ebe9383cSRichard Henderson { 0x38032200, 0xfc1fff60, FOP_DEW = gen_helper_fcnv_s_udw }, 3718ebe9383cSRichard Henderson { 0x38032a00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_d_udw }, 3719ebe9383cSRichard Henderson /* float/uint truncate */ 3720ebe9383cSRichard Henderson { 0x38038200, 0xfc1ffe60, FOP_WEW = gen_helper_fcnv_t_s_uw }, 3721ebe9383cSRichard Henderson { 0x38038a00, 0xfc1fffa0, FOP_WED = gen_helper_fcnv_t_d_uw }, 3722ebe9383cSRichard Henderson { 0x3803a200, 0xfc1fff60, FOP_DEW = gen_helper_fcnv_t_s_udw }, 3723ebe9383cSRichard Henderson { 0x3803aa00, 0xfc1fffe0, FOP_DED = gen_helper_fcnv_t_d_udw }, 3724ebe9383cSRichard Henderson 3725ebe9383cSRichard Henderson /* floating point class two */ 3726ebe9383cSRichard Henderson { 0x38000400, 0xfc000f60, trans_fcmp_s_0e }, 3727ebe9383cSRichard Henderson { 0x38000c00, 0xfc001fe0, trans_fcmp_d }, 3728ebe9383cSRichard Henderson }; 3729ebe9383cSRichard Henderson 3730ebe9383cSRichard Henderson #undef FOP_WEW 3731ebe9383cSRichard Henderson #undef FOP_DEW 3732ebe9383cSRichard Henderson #undef FOP_WED 3733ebe9383cSRichard Henderson #undef FOP_WEWW 3734ebe9383cSRichard Henderson #undef FOP_DED 3735ebe9383cSRichard Henderson #undef FOP_DEDD 3736ebe9383cSRichard Henderson 3737ebe9383cSRichard Henderson /* Convert the fmpyadd single-precision register encodings to standard. */ 3738ebe9383cSRichard Henderson static inline int fmpyadd_s_reg(unsigned r) 3739ebe9383cSRichard Henderson { 3740ebe9383cSRichard Henderson return (r & 16) * 2 + 16 + (r & 15); 3741ebe9383cSRichard Henderson } 3742ebe9383cSRichard Henderson 3743869051eaSRichard Henderson static DisasJumpType trans_fmpyadd(DisasContext *ctx, 3744869051eaSRichard Henderson uint32_t insn, bool is_sub) 3745ebe9383cSRichard Henderson { 3746ebe9383cSRichard Henderson unsigned tm = extract32(insn, 0, 5); 3747ebe9383cSRichard Henderson unsigned f = extract32(insn, 5, 1); 3748ebe9383cSRichard Henderson unsigned ra = extract32(insn, 6, 5); 3749ebe9383cSRichard Henderson unsigned ta = extract32(insn, 11, 5); 3750ebe9383cSRichard Henderson unsigned rm2 = extract32(insn, 16, 5); 3751ebe9383cSRichard Henderson unsigned rm1 = extract32(insn, 21, 5); 3752ebe9383cSRichard Henderson 3753ebe9383cSRichard Henderson nullify_over(ctx); 3754ebe9383cSRichard Henderson 3755ebe9383cSRichard Henderson /* Independent multiply & add/sub, with undefined behaviour 3756ebe9383cSRichard Henderson if outputs overlap inputs. */ 3757ebe9383cSRichard Henderson if (f == 0) { 3758ebe9383cSRichard Henderson tm = fmpyadd_s_reg(tm); 3759ebe9383cSRichard Henderson ra = fmpyadd_s_reg(ra); 3760ebe9383cSRichard Henderson ta = fmpyadd_s_reg(ta); 3761ebe9383cSRichard Henderson rm2 = fmpyadd_s_reg(rm2); 3762ebe9383cSRichard Henderson rm1 = fmpyadd_s_reg(rm1); 3763ebe9383cSRichard Henderson do_fop_weww(ctx, tm, rm1, rm2, gen_helper_fmpy_s); 3764ebe9383cSRichard Henderson do_fop_weww(ctx, ta, ta, ra, 3765ebe9383cSRichard Henderson is_sub ? gen_helper_fsub_s : gen_helper_fadd_s); 3766ebe9383cSRichard Henderson } else { 3767ebe9383cSRichard Henderson do_fop_dedd(ctx, tm, rm1, rm2, gen_helper_fmpy_d); 3768ebe9383cSRichard Henderson do_fop_dedd(ctx, ta, ta, ra, 3769ebe9383cSRichard Henderson is_sub ? gen_helper_fsub_d : gen_helper_fadd_d); 3770ebe9383cSRichard Henderson } 3771ebe9383cSRichard Henderson 3772869051eaSRichard Henderson return nullify_end(ctx, DISAS_NEXT); 3773ebe9383cSRichard Henderson } 3774ebe9383cSRichard Henderson 3775869051eaSRichard Henderson static DisasJumpType trans_fmpyfadd_s(DisasContext *ctx, uint32_t insn, 3776ebe9383cSRichard Henderson const DisasInsn *di) 3777ebe9383cSRichard Henderson { 3778ebe9383cSRichard Henderson unsigned rt = assemble_rt64(insn); 3779ebe9383cSRichard Henderson unsigned neg = extract32(insn, 5, 1); 3780ebe9383cSRichard Henderson unsigned rm1 = assemble_ra64(insn); 3781ebe9383cSRichard Henderson unsigned rm2 = assemble_rb64(insn); 3782ebe9383cSRichard Henderson unsigned ra3 = assemble_rc64(insn); 3783ebe9383cSRichard Henderson TCGv_i32 a, b, c; 3784ebe9383cSRichard Henderson 3785ebe9383cSRichard Henderson nullify_over(ctx); 3786ebe9383cSRichard Henderson a = load_frw0_i32(rm1); 3787ebe9383cSRichard Henderson b = load_frw0_i32(rm2); 3788ebe9383cSRichard Henderson c = load_frw0_i32(ra3); 3789ebe9383cSRichard Henderson 3790ebe9383cSRichard Henderson if (neg) { 3791ebe9383cSRichard Henderson gen_helper_fmpynfadd_s(a, cpu_env, a, b, c); 3792ebe9383cSRichard Henderson } else { 3793ebe9383cSRichard Henderson gen_helper_fmpyfadd_s(a, cpu_env, a, b, c); 3794ebe9383cSRichard Henderson } 3795ebe9383cSRichard Henderson 3796ebe9383cSRichard Henderson tcg_temp_free_i32(b); 3797ebe9383cSRichard Henderson tcg_temp_free_i32(c); 3798ebe9383cSRichard Henderson save_frw_i32(rt, a); 3799ebe9383cSRichard Henderson tcg_temp_free_i32(a); 3800869051eaSRichard Henderson return nullify_end(ctx, DISAS_NEXT); 3801ebe9383cSRichard Henderson } 3802ebe9383cSRichard Henderson 3803869051eaSRichard Henderson static DisasJumpType trans_fmpyfadd_d(DisasContext *ctx, uint32_t insn, 3804ebe9383cSRichard Henderson const DisasInsn *di) 3805ebe9383cSRichard Henderson { 3806ebe9383cSRichard Henderson unsigned rt = extract32(insn, 0, 5); 3807ebe9383cSRichard Henderson unsigned neg = extract32(insn, 5, 1); 3808ebe9383cSRichard Henderson unsigned rm1 = extract32(insn, 21, 5); 3809ebe9383cSRichard Henderson unsigned rm2 = extract32(insn, 16, 5); 3810ebe9383cSRichard Henderson unsigned ra3 = assemble_rc64(insn); 3811ebe9383cSRichard Henderson TCGv_i64 a, b, c; 3812ebe9383cSRichard Henderson 3813ebe9383cSRichard Henderson nullify_over(ctx); 3814ebe9383cSRichard Henderson a = load_frd0(rm1); 3815ebe9383cSRichard Henderson b = load_frd0(rm2); 3816ebe9383cSRichard Henderson c = load_frd0(ra3); 3817ebe9383cSRichard Henderson 3818ebe9383cSRichard Henderson if (neg) { 3819ebe9383cSRichard Henderson gen_helper_fmpynfadd_d(a, cpu_env, a, b, c); 3820ebe9383cSRichard Henderson } else { 3821ebe9383cSRichard Henderson gen_helper_fmpyfadd_d(a, cpu_env, a, b, c); 3822ebe9383cSRichard Henderson } 3823ebe9383cSRichard Henderson 3824ebe9383cSRichard Henderson tcg_temp_free_i64(b); 3825ebe9383cSRichard Henderson tcg_temp_free_i64(c); 3826ebe9383cSRichard Henderson save_frd(rt, a); 3827ebe9383cSRichard Henderson tcg_temp_free_i64(a); 3828869051eaSRichard Henderson return nullify_end(ctx, DISAS_NEXT); 3829ebe9383cSRichard Henderson } 3830ebe9383cSRichard Henderson 3831ebe9383cSRichard Henderson static const DisasInsn table_fp_fused[] = { 3832ebe9383cSRichard Henderson { 0xb8000000u, 0xfc000800u, trans_fmpyfadd_s }, 3833ebe9383cSRichard Henderson { 0xb8000800u, 0xfc0019c0u, trans_fmpyfadd_d } 3834ebe9383cSRichard Henderson }; 3835ebe9383cSRichard Henderson 3836869051eaSRichard Henderson static DisasJumpType translate_table_int(DisasContext *ctx, uint32_t insn, 383761766fe9SRichard Henderson const DisasInsn table[], size_t n) 383861766fe9SRichard Henderson { 383961766fe9SRichard Henderson size_t i; 384061766fe9SRichard Henderson for (i = 0; i < n; ++i) { 384161766fe9SRichard Henderson if ((insn & table[i].mask) == table[i].insn) { 384261766fe9SRichard Henderson return table[i].trans(ctx, insn, &table[i]); 384361766fe9SRichard Henderson } 384461766fe9SRichard Henderson } 384561766fe9SRichard Henderson return gen_illegal(ctx); 384661766fe9SRichard Henderson } 384761766fe9SRichard Henderson 384861766fe9SRichard Henderson #define translate_table(ctx, insn, table) \ 384961766fe9SRichard Henderson translate_table_int(ctx, insn, table, ARRAY_SIZE(table)) 385061766fe9SRichard Henderson 3851869051eaSRichard Henderson static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn) 385261766fe9SRichard Henderson { 385361766fe9SRichard Henderson uint32_t opc = extract32(insn, 26, 6); 385461766fe9SRichard Henderson 385561766fe9SRichard Henderson switch (opc) { 385698a9cb79SRichard Henderson case 0x00: /* system op */ 385798a9cb79SRichard Henderson return translate_table(ctx, insn, table_system); 385898a9cb79SRichard Henderson case 0x01: 385998a9cb79SRichard Henderson return translate_table(ctx, insn, table_mem_mgmt); 3860b2167459SRichard Henderson case 0x02: 3861b2167459SRichard Henderson return translate_table(ctx, insn, table_arith_log); 386296d6407fSRichard Henderson case 0x03: 386396d6407fSRichard Henderson return translate_table(ctx, insn, table_index_mem); 3864ebe9383cSRichard Henderson case 0x06: 3865ebe9383cSRichard Henderson return trans_fmpyadd(ctx, insn, false); 3866b2167459SRichard Henderson case 0x08: 3867b2167459SRichard Henderson return trans_ldil(ctx, insn); 386896d6407fSRichard Henderson case 0x09: 386996d6407fSRichard Henderson return trans_copr_w(ctx, insn); 3870b2167459SRichard Henderson case 0x0A: 3871b2167459SRichard Henderson return trans_addil(ctx, insn); 387296d6407fSRichard Henderson case 0x0B: 387396d6407fSRichard Henderson return trans_copr_dw(ctx, insn); 3874ebe9383cSRichard Henderson case 0x0C: 3875ebe9383cSRichard Henderson return translate_table(ctx, insn, table_float_0c); 3876b2167459SRichard Henderson case 0x0D: 3877b2167459SRichard Henderson return trans_ldo(ctx, insn); 3878ebe9383cSRichard Henderson case 0x0E: 3879ebe9383cSRichard Henderson return translate_table(ctx, insn, table_float_0e); 388096d6407fSRichard Henderson 388196d6407fSRichard Henderson case 0x10: 388296d6407fSRichard Henderson return trans_load(ctx, insn, false, MO_UB); 388396d6407fSRichard Henderson case 0x11: 388496d6407fSRichard Henderson return trans_load(ctx, insn, false, MO_TEUW); 388596d6407fSRichard Henderson case 0x12: 388696d6407fSRichard Henderson return trans_load(ctx, insn, false, MO_TEUL); 388796d6407fSRichard Henderson case 0x13: 388896d6407fSRichard Henderson return trans_load(ctx, insn, true, MO_TEUL); 388996d6407fSRichard Henderson case 0x16: 389096d6407fSRichard Henderson return trans_fload_mod(ctx, insn); 389196d6407fSRichard Henderson case 0x17: 389296d6407fSRichard Henderson return trans_load_w(ctx, insn); 389396d6407fSRichard Henderson case 0x18: 389496d6407fSRichard Henderson return trans_store(ctx, insn, false, MO_UB); 389596d6407fSRichard Henderson case 0x19: 389696d6407fSRichard Henderson return trans_store(ctx, insn, false, MO_TEUW); 389796d6407fSRichard Henderson case 0x1A: 389896d6407fSRichard Henderson return trans_store(ctx, insn, false, MO_TEUL); 389996d6407fSRichard Henderson case 0x1B: 390096d6407fSRichard Henderson return trans_store(ctx, insn, true, MO_TEUL); 390196d6407fSRichard Henderson case 0x1E: 390296d6407fSRichard Henderson return trans_fstore_mod(ctx, insn); 390396d6407fSRichard Henderson case 0x1F: 390496d6407fSRichard Henderson return trans_store_w(ctx, insn); 390596d6407fSRichard Henderson 390698cd9ca7SRichard Henderson case 0x20: 390798cd9ca7SRichard Henderson return trans_cmpb(ctx, insn, true, false, false); 390898cd9ca7SRichard Henderson case 0x21: 390998cd9ca7SRichard Henderson return trans_cmpb(ctx, insn, true, true, false); 391098cd9ca7SRichard Henderson case 0x22: 391198cd9ca7SRichard Henderson return trans_cmpb(ctx, insn, false, false, false); 391298cd9ca7SRichard Henderson case 0x23: 391398cd9ca7SRichard Henderson return trans_cmpb(ctx, insn, false, true, false); 3914b2167459SRichard Henderson case 0x24: 3915b2167459SRichard Henderson return trans_cmpiclr(ctx, insn); 3916b2167459SRichard Henderson case 0x25: 3917b2167459SRichard Henderson return trans_subi(ctx, insn); 3918ebe9383cSRichard Henderson case 0x26: 3919ebe9383cSRichard Henderson return trans_fmpyadd(ctx, insn, true); 392098cd9ca7SRichard Henderson case 0x27: 392198cd9ca7SRichard Henderson return trans_cmpb(ctx, insn, true, false, true); 392298cd9ca7SRichard Henderson case 0x28: 392398cd9ca7SRichard Henderson return trans_addb(ctx, insn, true, false); 392498cd9ca7SRichard Henderson case 0x29: 392598cd9ca7SRichard Henderson return trans_addb(ctx, insn, true, true); 392698cd9ca7SRichard Henderson case 0x2A: 392798cd9ca7SRichard Henderson return trans_addb(ctx, insn, false, false); 392898cd9ca7SRichard Henderson case 0x2B: 392998cd9ca7SRichard Henderson return trans_addb(ctx, insn, false, true); 3930b2167459SRichard Henderson case 0x2C: 3931b2167459SRichard Henderson case 0x2D: 3932b2167459SRichard Henderson return trans_addi(ctx, insn); 3933ebe9383cSRichard Henderson case 0x2E: 3934ebe9383cSRichard Henderson return translate_table(ctx, insn, table_fp_fused); 393598cd9ca7SRichard Henderson case 0x2F: 393698cd9ca7SRichard Henderson return trans_cmpb(ctx, insn, false, false, true); 393796d6407fSRichard Henderson 393898cd9ca7SRichard Henderson case 0x30: 393998cd9ca7SRichard Henderson case 0x31: 394098cd9ca7SRichard Henderson return trans_bb(ctx, insn); 394198cd9ca7SRichard Henderson case 0x32: 394298cd9ca7SRichard Henderson return trans_movb(ctx, insn, false); 394398cd9ca7SRichard Henderson case 0x33: 394498cd9ca7SRichard Henderson return trans_movb(ctx, insn, true); 39450b1347d2SRichard Henderson case 0x34: 39460b1347d2SRichard Henderson return translate_table(ctx, insn, table_sh_ex); 39470b1347d2SRichard Henderson case 0x35: 39480b1347d2SRichard Henderson return translate_table(ctx, insn, table_depw); 394998cd9ca7SRichard Henderson case 0x38: 395098cd9ca7SRichard Henderson return trans_be(ctx, insn, false); 395198cd9ca7SRichard Henderson case 0x39: 395298cd9ca7SRichard Henderson return trans_be(ctx, insn, true); 395398cd9ca7SRichard Henderson case 0x3A: 395498cd9ca7SRichard Henderson return translate_table(ctx, insn, table_branch); 395596d6407fSRichard Henderson 395696d6407fSRichard Henderson case 0x04: /* spopn */ 395796d6407fSRichard Henderson case 0x05: /* diag */ 395896d6407fSRichard Henderson case 0x0F: /* product specific */ 395996d6407fSRichard Henderson break; 396096d6407fSRichard Henderson 396196d6407fSRichard Henderson case 0x07: /* unassigned */ 396296d6407fSRichard Henderson case 0x15: /* unassigned */ 396396d6407fSRichard Henderson case 0x1D: /* unassigned */ 396496d6407fSRichard Henderson case 0x37: /* unassigned */ 396596d6407fSRichard Henderson case 0x3F: /* unassigned */ 396661766fe9SRichard Henderson default: 396761766fe9SRichard Henderson break; 396861766fe9SRichard Henderson } 396961766fe9SRichard Henderson return gen_illegal(ctx); 397061766fe9SRichard Henderson } 397161766fe9SRichard Henderson 397251b061fbSRichard Henderson static int hppa_tr_init_disas_context(DisasContextBase *dcbase, 397351b061fbSRichard Henderson CPUState *cs, int max_insns) 397461766fe9SRichard Henderson { 397551b061fbSRichard Henderson DisasContext *ctx = container_of(dcbase, DisasContext, base); 3976f764718dSRichard Henderson int bound; 397761766fe9SRichard Henderson 397851b061fbSRichard Henderson ctx->cs = cs; 3979*3d68ee7bSRichard Henderson 3980*3d68ee7bSRichard Henderson #ifdef CONFIG_USER_ONLY 3981*3d68ee7bSRichard Henderson ctx->privilege = MMU_USER_IDX; 3982*3d68ee7bSRichard Henderson ctx->mmu_idx = MMU_USER_IDX; 3983*3d68ee7bSRichard Henderson #else 3984*3d68ee7bSRichard Henderson ctx->privilege = ctx->base.pc_first & 3; 3985*3d68ee7bSRichard Henderson ctx->mmu_idx = (ctx->base.tb->flags & PSW_D 3986*3d68ee7bSRichard Henderson ? ctx->privilege : MMU_PHYS_IDX); 3987*3d68ee7bSRichard Henderson #endif 3988*3d68ee7bSRichard Henderson ctx->iaoq_f = ctx->base.pc_first; 3989*3d68ee7bSRichard Henderson ctx->iaoq_b = ctx->base.tb->cs_base; 3990*3d68ee7bSRichard Henderson ctx->base.pc_first &= -4; 3991*3d68ee7bSRichard Henderson 399251b061fbSRichard Henderson ctx->iaoq_n = -1; 3993f764718dSRichard Henderson ctx->iaoq_n_var = NULL; 399461766fe9SRichard Henderson 3995*3d68ee7bSRichard Henderson /* Bound the number of instructions by those left on the page. */ 3996*3d68ee7bSRichard Henderson bound = -(ctx->base.pc_first | TARGET_PAGE_MASK) / 4; 3997*3d68ee7bSRichard Henderson bound = MIN(max_insns, bound); 3998*3d68ee7bSRichard Henderson 399951b061fbSRichard Henderson ctx->ntemps = 0; 4000f764718dSRichard Henderson memset(ctx->temps, 0, sizeof(ctx->temps)); 400161766fe9SRichard Henderson 4002*3d68ee7bSRichard Henderson return bound; 400361766fe9SRichard Henderson } 400461766fe9SRichard Henderson 400551b061fbSRichard Henderson static void hppa_tr_tb_start(DisasContextBase *dcbase, CPUState *cs) 400651b061fbSRichard Henderson { 400751b061fbSRichard Henderson DisasContext *ctx = container_of(dcbase, DisasContext, base); 400861766fe9SRichard Henderson 4009*3d68ee7bSRichard Henderson /* Seed the nullification status from PSW[N], as saved in TB->FLAGS. */ 401051b061fbSRichard Henderson ctx->null_cond = cond_make_f(); 401151b061fbSRichard Henderson ctx->psw_n_nonzero = false; 4012*3d68ee7bSRichard Henderson if (ctx->base.tb->flags & PSW_N) { 401351b061fbSRichard Henderson ctx->null_cond.c = TCG_COND_ALWAYS; 401451b061fbSRichard Henderson ctx->psw_n_nonzero = true; 4015129e9cc3SRichard Henderson } 401651b061fbSRichard Henderson ctx->null_lab = NULL; 401761766fe9SRichard Henderson } 401861766fe9SRichard Henderson 401951b061fbSRichard Henderson static void hppa_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) 402051b061fbSRichard Henderson { 402151b061fbSRichard Henderson DisasContext *ctx = container_of(dcbase, DisasContext, base); 402251b061fbSRichard Henderson 402351b061fbSRichard Henderson tcg_gen_insn_start(ctx->iaoq_f, ctx->iaoq_b); 402451b061fbSRichard Henderson } 402551b061fbSRichard Henderson 402651b061fbSRichard Henderson static bool hppa_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs, 402751b061fbSRichard Henderson const CPUBreakpoint *bp) 402851b061fbSRichard Henderson { 402951b061fbSRichard Henderson DisasContext *ctx = container_of(dcbase, DisasContext, base); 403051b061fbSRichard Henderson 403151b061fbSRichard Henderson ctx->base.is_jmp = gen_excp(ctx, EXCP_DEBUG); 4032*3d68ee7bSRichard Henderson ctx->base.pc_next = (ctx->iaoq_f & -4) + 4; 403351b061fbSRichard Henderson return true; 403451b061fbSRichard Henderson } 403551b061fbSRichard Henderson 403651b061fbSRichard Henderson static void hppa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) 403751b061fbSRichard Henderson { 403851b061fbSRichard Henderson DisasContext *ctx = container_of(dcbase, DisasContext, base); 403951b061fbSRichard Henderson CPUHPPAState *env = cs->env_ptr; 404051b061fbSRichard Henderson DisasJumpType ret; 404151b061fbSRichard Henderson int i, n; 404251b061fbSRichard Henderson 404351b061fbSRichard Henderson /* Execute one insn. */ 4044ba1d0b44SRichard Henderson #ifdef CONFIG_USER_ONLY 404551b061fbSRichard Henderson if (ctx->iaoq_f < TARGET_PAGE_SIZE) { 404651b061fbSRichard Henderson ret = do_page_zero(ctx); 4047869051eaSRichard Henderson assert(ret != DISAS_NEXT); 4048ba1d0b44SRichard Henderson } else 4049ba1d0b44SRichard Henderson #endif 4050ba1d0b44SRichard Henderson { 405161766fe9SRichard Henderson /* Always fetch the insn, even if nullified, so that we check 405261766fe9SRichard Henderson the page permissions for execute. */ 4053*3d68ee7bSRichard Henderson uint32_t insn = cpu_ldl_code(env, ctx->iaoq_f & -4); 405461766fe9SRichard Henderson 405561766fe9SRichard Henderson /* Set up the IA queue for the next insn. 405661766fe9SRichard Henderson This will be overwritten by a branch. */ 405751b061fbSRichard Henderson if (ctx->iaoq_b == -1) { 405851b061fbSRichard Henderson ctx->iaoq_n = -1; 405951b061fbSRichard Henderson ctx->iaoq_n_var = get_temp(ctx); 4060eaa3783bSRichard Henderson tcg_gen_addi_reg(ctx->iaoq_n_var, cpu_iaoq_b, 4); 406161766fe9SRichard Henderson } else { 406251b061fbSRichard Henderson ctx->iaoq_n = ctx->iaoq_b + 4; 4063f764718dSRichard Henderson ctx->iaoq_n_var = NULL; 406461766fe9SRichard Henderson } 406561766fe9SRichard Henderson 406651b061fbSRichard Henderson if (unlikely(ctx->null_cond.c == TCG_COND_ALWAYS)) { 406751b061fbSRichard Henderson ctx->null_cond.c = TCG_COND_NEVER; 4068869051eaSRichard Henderson ret = DISAS_NEXT; 4069129e9cc3SRichard Henderson } else { 407051b061fbSRichard Henderson ret = translate_one(ctx, insn); 407151b061fbSRichard Henderson assert(ctx->null_lab == NULL); 4072129e9cc3SRichard Henderson } 407361766fe9SRichard Henderson } 407461766fe9SRichard Henderson 407551b061fbSRichard Henderson /* Free any temporaries allocated. */ 407651b061fbSRichard Henderson for (i = 0, n = ctx->ntemps; i < n; ++i) { 407751b061fbSRichard Henderson tcg_temp_free(ctx->temps[i]); 4078f764718dSRichard Henderson ctx->temps[i] = NULL; 407961766fe9SRichard Henderson } 408051b061fbSRichard Henderson ctx->ntemps = 0; 408161766fe9SRichard Henderson 4082*3d68ee7bSRichard Henderson /* Advance the insn queue. Note that this check also detects 4083*3d68ee7bSRichard Henderson a priority change within the instruction queue. */ 408451b061fbSRichard Henderson if (ret == DISAS_NEXT && ctx->iaoq_b != ctx->iaoq_f + 4) { 408551b061fbSRichard Henderson if (ctx->null_cond.c == TCG_COND_NEVER 408651b061fbSRichard Henderson || ctx->null_cond.c == TCG_COND_ALWAYS) { 408751b061fbSRichard Henderson nullify_set(ctx, ctx->null_cond.c == TCG_COND_ALWAYS); 408851b061fbSRichard Henderson gen_goto_tb(ctx, 0, ctx->iaoq_b, ctx->iaoq_n); 4089869051eaSRichard Henderson ret = DISAS_NORETURN; 4090129e9cc3SRichard Henderson } else { 4091869051eaSRichard Henderson ret = DISAS_IAQ_N_STALE; 409261766fe9SRichard Henderson } 4093129e9cc3SRichard Henderson } 409451b061fbSRichard Henderson ctx->iaoq_f = ctx->iaoq_b; 409551b061fbSRichard Henderson ctx->iaoq_b = ctx->iaoq_n; 409651b061fbSRichard Henderson ctx->base.is_jmp = ret; 409761766fe9SRichard Henderson 4098869051eaSRichard Henderson if (ret == DISAS_NORETURN || ret == DISAS_IAQ_N_UPDATED) { 409951b061fbSRichard Henderson return; 410061766fe9SRichard Henderson } 410151b061fbSRichard Henderson if (ctx->iaoq_f == -1) { 4102eaa3783bSRichard Henderson tcg_gen_mov_reg(cpu_iaoq_f, cpu_iaoq_b); 410351b061fbSRichard Henderson copy_iaoq_entry(cpu_iaoq_b, ctx->iaoq_n, ctx->iaoq_n_var); 410451b061fbSRichard Henderson nullify_save(ctx); 410551b061fbSRichard Henderson ctx->base.is_jmp = DISAS_IAQ_N_UPDATED; 410651b061fbSRichard Henderson } else if (ctx->iaoq_b == -1) { 4107eaa3783bSRichard Henderson tcg_gen_mov_reg(cpu_iaoq_b, ctx->iaoq_n_var); 410861766fe9SRichard Henderson } 410961766fe9SRichard Henderson } 411061766fe9SRichard Henderson 411151b061fbSRichard Henderson static void hppa_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) 411251b061fbSRichard Henderson { 411351b061fbSRichard Henderson DisasContext *ctx = container_of(dcbase, DisasContext, base); 411451b061fbSRichard Henderson 411551b061fbSRichard Henderson switch (ctx->base.is_jmp) { 4116869051eaSRichard Henderson case DISAS_NORETURN: 411761766fe9SRichard Henderson break; 411851b061fbSRichard Henderson case DISAS_TOO_MANY: 4119869051eaSRichard Henderson case DISAS_IAQ_N_STALE: 412051b061fbSRichard Henderson copy_iaoq_entry(cpu_iaoq_f, ctx->iaoq_f, cpu_iaoq_f); 412151b061fbSRichard Henderson copy_iaoq_entry(cpu_iaoq_b, ctx->iaoq_b, cpu_iaoq_b); 412251b061fbSRichard Henderson nullify_save(ctx); 412361766fe9SRichard Henderson /* FALLTHRU */ 4124869051eaSRichard Henderson case DISAS_IAQ_N_UPDATED: 412551b061fbSRichard Henderson if (ctx->base.singlestep_enabled) { 412661766fe9SRichard Henderson gen_excp_1(EXCP_DEBUG); 412761766fe9SRichard Henderson } else { 41287f11636dSEmilio G. Cota tcg_gen_lookup_and_goto_ptr(); 412961766fe9SRichard Henderson } 413061766fe9SRichard Henderson break; 413161766fe9SRichard Henderson default: 413251b061fbSRichard Henderson g_assert_not_reached(); 413361766fe9SRichard Henderson } 413461766fe9SRichard Henderson 413551b061fbSRichard Henderson /* We don't actually use this during normal translation, 413651b061fbSRichard Henderson but we should interact with the generic main loop. */ 4137*3d68ee7bSRichard Henderson ctx->base.pc_next = ctx->base.pc_first + 4 * ctx->base.num_insns; 413851b061fbSRichard Henderson } 413961766fe9SRichard Henderson 414051b061fbSRichard Henderson static void hppa_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs) 414151b061fbSRichard Henderson { 4142eaa3783bSRichard Henderson target_ureg pc = dcbase->pc_first; 414361766fe9SRichard Henderson 4144ba1d0b44SRichard Henderson #ifdef CONFIG_USER_ONLY 4145ba1d0b44SRichard Henderson switch (pc) { 41467ad439dfSRichard Henderson case 0x00: 414751b061fbSRichard Henderson qemu_log("IN:\n0x00000000: (null)\n"); 4148ba1d0b44SRichard Henderson return; 41497ad439dfSRichard Henderson case 0xb0: 415051b061fbSRichard Henderson qemu_log("IN:\n0x000000b0: light-weight-syscall\n"); 4151ba1d0b44SRichard Henderson return; 41527ad439dfSRichard Henderson case 0xe0: 415351b061fbSRichard Henderson qemu_log("IN:\n0x000000e0: set-thread-pointer-syscall\n"); 4154ba1d0b44SRichard Henderson return; 41557ad439dfSRichard Henderson case 0x100: 415651b061fbSRichard Henderson qemu_log("IN:\n0x00000100: syscall\n"); 4157ba1d0b44SRichard Henderson return; 41587ad439dfSRichard Henderson } 4159ba1d0b44SRichard Henderson #endif 4160ba1d0b44SRichard Henderson 4161ba1d0b44SRichard Henderson qemu_log("IN: %s\n", lookup_symbol(pc)); 4162eaa3783bSRichard Henderson log_target_disas(cs, pc, dcbase->tb->size); 416361766fe9SRichard Henderson } 416451b061fbSRichard Henderson 416551b061fbSRichard Henderson static const TranslatorOps hppa_tr_ops = { 416651b061fbSRichard Henderson .init_disas_context = hppa_tr_init_disas_context, 416751b061fbSRichard Henderson .tb_start = hppa_tr_tb_start, 416851b061fbSRichard Henderson .insn_start = hppa_tr_insn_start, 416951b061fbSRichard Henderson .breakpoint_check = hppa_tr_breakpoint_check, 417051b061fbSRichard Henderson .translate_insn = hppa_tr_translate_insn, 417151b061fbSRichard Henderson .tb_stop = hppa_tr_tb_stop, 417251b061fbSRichard Henderson .disas_log = hppa_tr_disas_log, 417351b061fbSRichard Henderson }; 417451b061fbSRichard Henderson 417551b061fbSRichard Henderson void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb) 417651b061fbSRichard Henderson 417751b061fbSRichard Henderson { 417851b061fbSRichard Henderson DisasContext ctx; 417951b061fbSRichard Henderson translator_loop(&hppa_tr_ops, &ctx.base, cs, tb); 418061766fe9SRichard Henderson } 418161766fe9SRichard Henderson 418261766fe9SRichard Henderson void restore_state_to_opc(CPUHPPAState *env, TranslationBlock *tb, 418361766fe9SRichard Henderson target_ulong *data) 418461766fe9SRichard Henderson { 418561766fe9SRichard Henderson env->iaoq_f = data[0]; 418661766fe9SRichard Henderson if (data[1] != -1) { 418761766fe9SRichard Henderson env->iaoq_b = data[1]; 418861766fe9SRichard Henderson } 418961766fe9SRichard Henderson /* Since we were executing the instruction at IAOQ_F, and took some 419061766fe9SRichard Henderson sort of action that provoked the cpu_restore_state, we can infer 419161766fe9SRichard Henderson that the instruction was not nullified. */ 419261766fe9SRichard Henderson env->psw_n = 0; 419361766fe9SRichard Henderson } 4194