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