1 /* 2 SPARC translation 3 4 Copyright (C) 2003 Thomas M. Ogrisegg <tom@fnord.at> 5 Copyright (C) 2003-2005 Fabrice Bellard 6 7 This library is free software; you can redistribute it and/or 8 modify it under the terms of the GNU Lesser General Public 9 License as published by the Free Software Foundation; either 10 version 2.1 of the License, or (at your option) any later version. 11 12 This library is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 Lesser General Public License for more details. 16 17 You should have received a copy of the GNU Lesser General Public 18 License along with this library; if not, see <http://www.gnu.org/licenses/>. 19 */ 20 21 #include "qemu/osdep.h" 22 23 #include "cpu.h" 24 #include "exec/helper-proto.h" 25 #include "exec/exec-all.h" 26 #include "tcg/tcg-op.h" 27 #include "tcg/tcg-op-gvec.h" 28 #include "exec/helper-gen.h" 29 #include "exec/translator.h" 30 #include "exec/log.h" 31 #include "fpu/softfloat.h" 32 #include "asi.h" 33 34 #define HELPER_H "helper.h" 35 #include "exec/helper-info.c.inc" 36 #undef HELPER_H 37 38 #ifdef TARGET_SPARC64 39 # define gen_helper_rdpsr(D, E) qemu_build_not_reached() 40 # define gen_helper_rdasr17(D, E) qemu_build_not_reached() 41 # define gen_helper_rett(E) qemu_build_not_reached() 42 # define gen_helper_power_down(E) qemu_build_not_reached() 43 # define gen_helper_wrpsr(E, S) qemu_build_not_reached() 44 #else 45 # define gen_helper_clear_softint(E, S) qemu_build_not_reached() 46 # define gen_helper_done(E) qemu_build_not_reached() 47 # define gen_helper_flushw(E) qemu_build_not_reached() 48 # define gen_helper_fmul8x16a(D, S1, S2) qemu_build_not_reached() 49 # define gen_helper_rdccr(D, E) qemu_build_not_reached() 50 # define gen_helper_rdcwp(D, E) qemu_build_not_reached() 51 # define gen_helper_restored(E) qemu_build_not_reached() 52 # define gen_helper_retry(E) qemu_build_not_reached() 53 # define gen_helper_saved(E) qemu_build_not_reached() 54 # define gen_helper_set_softint(E, S) qemu_build_not_reached() 55 # define gen_helper_tick_get_count(D, E, T, C) qemu_build_not_reached() 56 # define gen_helper_tick_set_count(P, S) qemu_build_not_reached() 57 # define gen_helper_tick_set_limit(P, S) qemu_build_not_reached() 58 # define gen_helper_wrccr(E, S) qemu_build_not_reached() 59 # define gen_helper_wrcwp(E, S) qemu_build_not_reached() 60 # define gen_helper_wrgl(E, S) qemu_build_not_reached() 61 # define gen_helper_write_softint(E, S) qemu_build_not_reached() 62 # define gen_helper_wrpil(E, S) qemu_build_not_reached() 63 # define gen_helper_wrpstate(E, S) qemu_build_not_reached() 64 # define gen_helper_cmask8 ({ qemu_build_not_reached(); NULL; }) 65 # define gen_helper_cmask16 ({ qemu_build_not_reached(); NULL; }) 66 # define gen_helper_cmask32 ({ qemu_build_not_reached(); NULL; }) 67 # define gen_helper_fcmpeq8 ({ qemu_build_not_reached(); NULL; }) 68 # define gen_helper_fcmpeq16 ({ qemu_build_not_reached(); NULL; }) 69 # define gen_helper_fcmpeq32 ({ qemu_build_not_reached(); NULL; }) 70 # define gen_helper_fcmpgt8 ({ qemu_build_not_reached(); NULL; }) 71 # define gen_helper_fcmpgt16 ({ qemu_build_not_reached(); NULL; }) 72 # define gen_helper_fcmpgt32 ({ qemu_build_not_reached(); NULL; }) 73 # define gen_helper_fcmple8 ({ qemu_build_not_reached(); NULL; }) 74 # define gen_helper_fcmple16 ({ qemu_build_not_reached(); NULL; }) 75 # define gen_helper_fcmple32 ({ qemu_build_not_reached(); NULL; }) 76 # define gen_helper_fcmpne8 ({ qemu_build_not_reached(); NULL; }) 77 # define gen_helper_fcmpne16 ({ qemu_build_not_reached(); NULL; }) 78 # define gen_helper_fcmpne32 ({ qemu_build_not_reached(); NULL; }) 79 # define gen_helper_fcmpule8 ({ qemu_build_not_reached(); NULL; }) 80 # define gen_helper_fcmpule16 ({ qemu_build_not_reached(); NULL; }) 81 # define gen_helper_fcmpule32 ({ qemu_build_not_reached(); NULL; }) 82 # define gen_helper_fcmpugt8 ({ qemu_build_not_reached(); NULL; }) 83 # define gen_helper_fcmpugt16 ({ qemu_build_not_reached(); NULL; }) 84 # define gen_helper_fcmpugt32 ({ qemu_build_not_reached(); NULL; }) 85 # define gen_helper_fdtox ({ qemu_build_not_reached(); NULL; }) 86 # define gen_helper_fexpand ({ qemu_build_not_reached(); NULL; }) 87 # define gen_helper_fmul8sux16 ({ qemu_build_not_reached(); NULL; }) 88 # define gen_helper_fmul8ulx16 ({ qemu_build_not_reached(); NULL; }) 89 # define gen_helper_fmul8x16 ({ qemu_build_not_reached(); NULL; }) 90 # define gen_helper_fpmerge ({ qemu_build_not_reached(); NULL; }) 91 # define gen_helper_fqtox ({ qemu_build_not_reached(); NULL; }) 92 # define gen_helper_fslas16 ({ qemu_build_not_reached(); NULL; }) 93 # define gen_helper_fslas32 ({ qemu_build_not_reached(); NULL; }) 94 # define gen_helper_fstox ({ qemu_build_not_reached(); NULL; }) 95 # define gen_helper_fxtod ({ qemu_build_not_reached(); NULL; }) 96 # define gen_helper_fxtoq ({ qemu_build_not_reached(); NULL; }) 97 # define gen_helper_fxtos ({ qemu_build_not_reached(); NULL; }) 98 # define gen_helper_pdist ({ qemu_build_not_reached(); NULL; }) 99 # define gen_helper_xmulx ({ qemu_build_not_reached(); NULL; }) 100 # define gen_helper_xmulxhi ({ qemu_build_not_reached(); NULL; }) 101 # define MAXTL_MASK 0 102 #endif 103 104 /* Dynamic PC, must exit to main loop. */ 105 #define DYNAMIC_PC 1 106 /* Dynamic PC, one of two values according to jump_pc[T2]. */ 107 #define JUMP_PC 2 108 /* Dynamic PC, may lookup next TB. */ 109 #define DYNAMIC_PC_LOOKUP 3 110 111 #define DISAS_EXIT DISAS_TARGET_0 112 113 /* global register indexes */ 114 static TCGv_ptr cpu_regwptr; 115 static TCGv cpu_pc, cpu_npc; 116 static TCGv cpu_regs[32]; 117 static TCGv cpu_y; 118 static TCGv cpu_tbr; 119 static TCGv cpu_cond; 120 static TCGv cpu_cc_N; 121 static TCGv cpu_cc_V; 122 static TCGv cpu_icc_Z; 123 static TCGv cpu_icc_C; 124 #ifdef TARGET_SPARC64 125 static TCGv cpu_xcc_Z; 126 static TCGv cpu_xcc_C; 127 static TCGv_i32 cpu_fprs; 128 static TCGv cpu_gsr; 129 #else 130 # define cpu_fprs ({ qemu_build_not_reached(); (TCGv)NULL; }) 131 # define cpu_gsr ({ qemu_build_not_reached(); (TCGv)NULL; }) 132 #endif 133 134 #ifdef TARGET_SPARC64 135 #define cpu_cc_Z cpu_xcc_Z 136 #define cpu_cc_C cpu_xcc_C 137 #else 138 #define cpu_cc_Z cpu_icc_Z 139 #define cpu_cc_C cpu_icc_C 140 #define cpu_xcc_Z ({ qemu_build_not_reached(); NULL; }) 141 #define cpu_xcc_C ({ qemu_build_not_reached(); NULL; }) 142 #endif 143 144 /* Floating point comparison registers */ 145 static TCGv_i32 cpu_fcc[TARGET_FCCREGS]; 146 147 #define env_field_offsetof(X) offsetof(CPUSPARCState, X) 148 #ifdef TARGET_SPARC64 149 # define env32_field_offsetof(X) ({ qemu_build_not_reached(); 0; }) 150 # define env64_field_offsetof(X) env_field_offsetof(X) 151 #else 152 # define env32_field_offsetof(X) env_field_offsetof(X) 153 # define env64_field_offsetof(X) ({ qemu_build_not_reached(); 0; }) 154 #endif 155 156 typedef struct DisasCompare { 157 TCGCond cond; 158 TCGv c1; 159 int c2; 160 } DisasCompare; 161 162 typedef struct DisasDelayException { 163 struct DisasDelayException *next; 164 TCGLabel *lab; 165 TCGv_i32 excp; 166 /* Saved state at parent insn. */ 167 target_ulong pc; 168 target_ulong npc; 169 } DisasDelayException; 170 171 typedef struct DisasContext { 172 DisasContextBase base; 173 target_ulong pc; /* current Program Counter: integer or DYNAMIC_PC */ 174 target_ulong npc; /* next PC: integer or DYNAMIC_PC or JUMP_PC */ 175 176 /* Used when JUMP_PC value is used. */ 177 DisasCompare jump; 178 target_ulong jump_pc[2]; 179 180 int mem_idx; 181 bool cpu_cond_live; 182 bool fpu_enabled; 183 bool address_mask_32bit; 184 #ifndef CONFIG_USER_ONLY 185 bool supervisor; 186 #ifdef TARGET_SPARC64 187 bool hypervisor; 188 #else 189 bool fsr_qne; 190 #endif 191 #endif 192 193 sparc_def_t *def; 194 #ifdef TARGET_SPARC64 195 int fprs_dirty; 196 int asi; 197 #endif 198 DisasDelayException *delay_excp_list; 199 } DisasContext; 200 201 // This function uses non-native bit order 202 #define GET_FIELD(X, FROM, TO) \ 203 ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1)) 204 205 // This function uses the order in the manuals, i.e. bit 0 is 2^0 206 #define GET_FIELD_SP(X, FROM, TO) \ 207 GET_FIELD(X, 31 - (TO), 31 - (FROM)) 208 209 #define GET_FIELDs(x,a,b) sign_extend (GET_FIELD(x,a,b), (b) - (a) + 1) 210 #define GET_FIELD_SPs(x,a,b) sign_extend (GET_FIELD_SP(x,a,b), ((b) - (a) + 1)) 211 212 #define UA2005_HTRAP_MASK 0xff 213 #define V8_TRAP_MASK 0x7f 214 215 #define IS_IMM (insn & (1<<13)) 216 217 static void gen_update_fprs_dirty(DisasContext *dc, int rd) 218 { 219 #if defined(TARGET_SPARC64) 220 int bit = (rd < 32) ? 1 : 2; 221 /* If we know we've already set this bit within the TB, 222 we can avoid setting it again. */ 223 if (!(dc->fprs_dirty & bit)) { 224 dc->fprs_dirty |= bit; 225 tcg_gen_ori_i32(cpu_fprs, cpu_fprs, bit); 226 } 227 #endif 228 } 229 230 /* floating point registers moves */ 231 232 static int gen_offset_fpr_F(unsigned int reg) 233 { 234 int ret; 235 236 tcg_debug_assert(reg < 32); 237 ret= offsetof(CPUSPARCState, fpr[reg / 2]); 238 if (reg & 1) { 239 ret += offsetof(CPU_DoubleU, l.lower); 240 } else { 241 ret += offsetof(CPU_DoubleU, l.upper); 242 } 243 return ret; 244 } 245 246 static TCGv_i32 gen_load_fpr_F(DisasContext *dc, unsigned int src) 247 { 248 TCGv_i32 ret = tcg_temp_new_i32(); 249 tcg_gen_ld_i32(ret, tcg_env, gen_offset_fpr_F(src)); 250 return ret; 251 } 252 253 static void gen_store_fpr_F(DisasContext *dc, unsigned int dst, TCGv_i32 v) 254 { 255 tcg_gen_st_i32(v, tcg_env, gen_offset_fpr_F(dst)); 256 gen_update_fprs_dirty(dc, dst); 257 } 258 259 static int gen_offset_fpr_D(unsigned int reg) 260 { 261 tcg_debug_assert(reg < 64); 262 tcg_debug_assert(reg % 2 == 0); 263 return offsetof(CPUSPARCState, fpr[reg / 2]); 264 } 265 266 static TCGv_i64 gen_load_fpr_D(DisasContext *dc, unsigned int src) 267 { 268 TCGv_i64 ret = tcg_temp_new_i64(); 269 tcg_gen_ld_i64(ret, tcg_env, gen_offset_fpr_D(src)); 270 return ret; 271 } 272 273 static void gen_store_fpr_D(DisasContext *dc, unsigned int dst, TCGv_i64 v) 274 { 275 tcg_gen_st_i64(v, tcg_env, gen_offset_fpr_D(dst)); 276 gen_update_fprs_dirty(dc, dst); 277 } 278 279 static TCGv_i128 gen_load_fpr_Q(DisasContext *dc, unsigned int src) 280 { 281 TCGv_i128 ret = tcg_temp_new_i128(); 282 TCGv_i64 h = gen_load_fpr_D(dc, src); 283 TCGv_i64 l = gen_load_fpr_D(dc, src + 2); 284 285 tcg_gen_concat_i64_i128(ret, l, h); 286 return ret; 287 } 288 289 static void gen_store_fpr_Q(DisasContext *dc, unsigned int dst, TCGv_i128 v) 290 { 291 TCGv_i64 h = tcg_temp_new_i64(); 292 TCGv_i64 l = tcg_temp_new_i64(); 293 294 tcg_gen_extr_i128_i64(l, h, v); 295 gen_store_fpr_D(dc, dst, h); 296 gen_store_fpr_D(dc, dst + 2, l); 297 } 298 299 /* moves */ 300 #ifdef CONFIG_USER_ONLY 301 #define supervisor(dc) 0 302 #define hypervisor(dc) 0 303 #else 304 #ifdef TARGET_SPARC64 305 #define hypervisor(dc) (dc->hypervisor) 306 #define supervisor(dc) (dc->supervisor | dc->hypervisor) 307 #else 308 #define supervisor(dc) (dc->supervisor) 309 #define hypervisor(dc) 0 310 #endif 311 #endif 312 313 #if !defined(TARGET_SPARC64) 314 # define AM_CHECK(dc) false 315 #elif defined(TARGET_ABI32) 316 # define AM_CHECK(dc) true 317 #elif defined(CONFIG_USER_ONLY) 318 # define AM_CHECK(dc) false 319 #else 320 # define AM_CHECK(dc) ((dc)->address_mask_32bit) 321 #endif 322 323 static void gen_address_mask(DisasContext *dc, TCGv addr) 324 { 325 if (AM_CHECK(dc)) { 326 tcg_gen_andi_tl(addr, addr, 0xffffffffULL); 327 } 328 } 329 330 static target_ulong address_mask_i(DisasContext *dc, target_ulong addr) 331 { 332 return AM_CHECK(dc) ? (uint32_t)addr : addr; 333 } 334 335 static TCGv gen_load_gpr(DisasContext *dc, int reg) 336 { 337 if (reg > 0) { 338 assert(reg < 32); 339 return cpu_regs[reg]; 340 } else { 341 TCGv t = tcg_temp_new(); 342 tcg_gen_movi_tl(t, 0); 343 return t; 344 } 345 } 346 347 static void gen_store_gpr(DisasContext *dc, int reg, TCGv v) 348 { 349 if (reg > 0) { 350 assert(reg < 32); 351 tcg_gen_mov_tl(cpu_regs[reg], v); 352 } 353 } 354 355 static TCGv gen_dest_gpr(DisasContext *dc, int reg) 356 { 357 if (reg > 0) { 358 assert(reg < 32); 359 return cpu_regs[reg]; 360 } else { 361 return tcg_temp_new(); 362 } 363 } 364 365 static bool use_goto_tb(DisasContext *s, target_ulong pc, target_ulong npc) 366 { 367 return translator_use_goto_tb(&s->base, pc) && 368 translator_use_goto_tb(&s->base, npc); 369 } 370 371 static void gen_goto_tb(DisasContext *s, int tb_num, 372 target_ulong pc, target_ulong npc) 373 { 374 if (use_goto_tb(s, pc, npc)) { 375 /* jump to same page: we can use a direct jump */ 376 tcg_gen_goto_tb(tb_num); 377 tcg_gen_movi_tl(cpu_pc, pc); 378 tcg_gen_movi_tl(cpu_npc, npc); 379 tcg_gen_exit_tb(s->base.tb, tb_num); 380 } else { 381 /* jump to another page: we can use an indirect jump */ 382 tcg_gen_movi_tl(cpu_pc, pc); 383 tcg_gen_movi_tl(cpu_npc, npc); 384 tcg_gen_lookup_and_goto_ptr(); 385 } 386 } 387 388 static TCGv gen_carry32(void) 389 { 390 if (TARGET_LONG_BITS == 64) { 391 TCGv t = tcg_temp_new(); 392 tcg_gen_extract_tl(t, cpu_icc_C, 32, 1); 393 return t; 394 } 395 return cpu_icc_C; 396 } 397 398 static void gen_op_addcc_int(TCGv dst, TCGv src1, TCGv src2, TCGv cin) 399 { 400 TCGv z = tcg_constant_tl(0); 401 402 if (cin) { 403 tcg_gen_add2_tl(cpu_cc_N, cpu_cc_C, src1, z, cin, z); 404 tcg_gen_add2_tl(cpu_cc_N, cpu_cc_C, cpu_cc_N, cpu_cc_C, src2, z); 405 } else { 406 tcg_gen_add2_tl(cpu_cc_N, cpu_cc_C, src1, z, src2, z); 407 } 408 tcg_gen_xor_tl(cpu_cc_Z, src1, src2); 409 tcg_gen_xor_tl(cpu_cc_V, cpu_cc_N, src2); 410 tcg_gen_andc_tl(cpu_cc_V, cpu_cc_V, cpu_cc_Z); 411 if (TARGET_LONG_BITS == 64) { 412 /* 413 * Carry-in to bit 32 is result ^ src1 ^ src2. 414 * We already have the src xor term in Z, from computation of V. 415 */ 416 tcg_gen_xor_tl(cpu_icc_C, cpu_cc_Z, cpu_cc_N); 417 tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N); 418 } 419 tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N); 420 tcg_gen_mov_tl(dst, cpu_cc_N); 421 } 422 423 static void gen_op_addcc(TCGv dst, TCGv src1, TCGv src2) 424 { 425 gen_op_addcc_int(dst, src1, src2, NULL); 426 } 427 428 static void gen_op_taddcc(TCGv dst, TCGv src1, TCGv src2) 429 { 430 TCGv t = tcg_temp_new(); 431 432 /* Save the tag bits around modification of dst. */ 433 tcg_gen_or_tl(t, src1, src2); 434 435 gen_op_addcc(dst, src1, src2); 436 437 /* Incorprate tag bits into icc.V */ 438 tcg_gen_andi_tl(t, t, 3); 439 tcg_gen_neg_tl(t, t); 440 tcg_gen_ext32u_tl(t, t); 441 tcg_gen_or_tl(cpu_cc_V, cpu_cc_V, t); 442 } 443 444 static void gen_op_addc(TCGv dst, TCGv src1, TCGv src2) 445 { 446 tcg_gen_add_tl(dst, src1, src2); 447 tcg_gen_add_tl(dst, dst, gen_carry32()); 448 } 449 450 static void gen_op_addccc(TCGv dst, TCGv src1, TCGv src2) 451 { 452 gen_op_addcc_int(dst, src1, src2, gen_carry32()); 453 } 454 455 static void gen_op_addxc(TCGv dst, TCGv src1, TCGv src2) 456 { 457 tcg_gen_add_tl(dst, src1, src2); 458 tcg_gen_add_tl(dst, dst, cpu_cc_C); 459 } 460 461 static void gen_op_addxccc(TCGv dst, TCGv src1, TCGv src2) 462 { 463 gen_op_addcc_int(dst, src1, src2, cpu_cc_C); 464 } 465 466 static void gen_op_subcc_int(TCGv dst, TCGv src1, TCGv src2, TCGv cin) 467 { 468 TCGv z = tcg_constant_tl(0); 469 470 if (cin) { 471 tcg_gen_sub2_tl(cpu_cc_N, cpu_cc_C, src1, z, cin, z); 472 tcg_gen_sub2_tl(cpu_cc_N, cpu_cc_C, cpu_cc_N, cpu_cc_C, src2, z); 473 } else { 474 tcg_gen_sub2_tl(cpu_cc_N, cpu_cc_C, src1, z, src2, z); 475 } 476 tcg_gen_neg_tl(cpu_cc_C, cpu_cc_C); 477 tcg_gen_xor_tl(cpu_cc_Z, src1, src2); 478 tcg_gen_xor_tl(cpu_cc_V, cpu_cc_N, src1); 479 tcg_gen_and_tl(cpu_cc_V, cpu_cc_V, cpu_cc_Z); 480 #ifdef TARGET_SPARC64 481 tcg_gen_xor_tl(cpu_icc_C, cpu_cc_Z, cpu_cc_N); 482 tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N); 483 #endif 484 tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N); 485 tcg_gen_mov_tl(dst, cpu_cc_N); 486 } 487 488 static void gen_op_subcc(TCGv dst, TCGv src1, TCGv src2) 489 { 490 gen_op_subcc_int(dst, src1, src2, NULL); 491 } 492 493 static void gen_op_tsubcc(TCGv dst, TCGv src1, TCGv src2) 494 { 495 TCGv t = tcg_temp_new(); 496 497 /* Save the tag bits around modification of dst. */ 498 tcg_gen_or_tl(t, src1, src2); 499 500 gen_op_subcc(dst, src1, src2); 501 502 /* Incorprate tag bits into icc.V */ 503 tcg_gen_andi_tl(t, t, 3); 504 tcg_gen_neg_tl(t, t); 505 tcg_gen_ext32u_tl(t, t); 506 tcg_gen_or_tl(cpu_cc_V, cpu_cc_V, t); 507 } 508 509 static void gen_op_subc(TCGv dst, TCGv src1, TCGv src2) 510 { 511 tcg_gen_sub_tl(dst, src1, src2); 512 tcg_gen_sub_tl(dst, dst, gen_carry32()); 513 } 514 515 static void gen_op_subccc(TCGv dst, TCGv src1, TCGv src2) 516 { 517 gen_op_subcc_int(dst, src1, src2, gen_carry32()); 518 } 519 520 static void gen_op_subxc(TCGv dst, TCGv src1, TCGv src2) 521 { 522 tcg_gen_sub_tl(dst, src1, src2); 523 tcg_gen_sub_tl(dst, dst, cpu_cc_C); 524 } 525 526 static void gen_op_subxccc(TCGv dst, TCGv src1, TCGv src2) 527 { 528 gen_op_subcc_int(dst, src1, src2, cpu_cc_C); 529 } 530 531 static void gen_op_mulscc(TCGv dst, TCGv src1, TCGv src2) 532 { 533 TCGv zero = tcg_constant_tl(0); 534 TCGv one = tcg_constant_tl(1); 535 TCGv t_src1 = tcg_temp_new(); 536 TCGv t_src2 = tcg_temp_new(); 537 TCGv t0 = tcg_temp_new(); 538 539 tcg_gen_ext32u_tl(t_src1, src1); 540 tcg_gen_ext32u_tl(t_src2, src2); 541 542 /* 543 * if (!(env->y & 1)) 544 * src2 = 0; 545 */ 546 tcg_gen_movcond_tl(TCG_COND_TSTEQ, t_src2, cpu_y, one, zero, t_src2); 547 548 /* 549 * b2 = src1 & 1; 550 * y = (b2 << 31) | (y >> 1); 551 */ 552 tcg_gen_extract_tl(t0, cpu_y, 1, 31); 553 tcg_gen_deposit_tl(cpu_y, t0, src1, 31, 1); 554 555 // b1 = N ^ V; 556 tcg_gen_xor_tl(t0, cpu_cc_N, cpu_cc_V); 557 558 /* 559 * src1 = (b1 << 31) | (src1 >> 1) 560 */ 561 tcg_gen_andi_tl(t0, t0, 1u << 31); 562 tcg_gen_shri_tl(t_src1, t_src1, 1); 563 tcg_gen_or_tl(t_src1, t_src1, t0); 564 565 gen_op_addcc(dst, t_src1, t_src2); 566 } 567 568 static void gen_op_multiply(TCGv dst, TCGv src1, TCGv src2, int sign_ext) 569 { 570 #if TARGET_LONG_BITS == 32 571 if (sign_ext) { 572 tcg_gen_muls2_tl(dst, cpu_y, src1, src2); 573 } else { 574 tcg_gen_mulu2_tl(dst, cpu_y, src1, src2); 575 } 576 #else 577 TCGv t0 = tcg_temp_new_i64(); 578 TCGv t1 = tcg_temp_new_i64(); 579 580 if (sign_ext) { 581 tcg_gen_ext32s_i64(t0, src1); 582 tcg_gen_ext32s_i64(t1, src2); 583 } else { 584 tcg_gen_ext32u_i64(t0, src1); 585 tcg_gen_ext32u_i64(t1, src2); 586 } 587 588 tcg_gen_mul_i64(dst, t0, t1); 589 tcg_gen_shri_i64(cpu_y, dst, 32); 590 #endif 591 } 592 593 static void gen_op_umul(TCGv dst, TCGv src1, TCGv src2) 594 { 595 /* zero-extend truncated operands before multiplication */ 596 gen_op_multiply(dst, src1, src2, 0); 597 } 598 599 static void gen_op_smul(TCGv dst, TCGv src1, TCGv src2) 600 { 601 /* sign-extend truncated operands before multiplication */ 602 gen_op_multiply(dst, src1, src2, 1); 603 } 604 605 static void gen_op_umulxhi(TCGv dst, TCGv src1, TCGv src2) 606 { 607 TCGv discard = tcg_temp_new(); 608 tcg_gen_mulu2_tl(discard, dst, src1, src2); 609 } 610 611 static void gen_op_fpmaddx(TCGv_i64 dst, TCGv_i64 src1, 612 TCGv_i64 src2, TCGv_i64 src3) 613 { 614 TCGv_i64 t = tcg_temp_new_i64(); 615 616 tcg_gen_mul_i64(t, src1, src2); 617 tcg_gen_add_i64(dst, src3, t); 618 } 619 620 static void gen_op_fpmaddxhi(TCGv_i64 dst, TCGv_i64 src1, 621 TCGv_i64 src2, TCGv_i64 src3) 622 { 623 TCGv_i64 l = tcg_temp_new_i64(); 624 TCGv_i64 h = tcg_temp_new_i64(); 625 TCGv_i64 z = tcg_constant_i64(0); 626 627 tcg_gen_mulu2_i64(l, h, src1, src2); 628 tcg_gen_add2_i64(l, dst, l, h, src3, z); 629 } 630 631 static void gen_op_sdiv(TCGv dst, TCGv src1, TCGv src2) 632 { 633 #ifdef TARGET_SPARC64 634 gen_helper_sdiv(dst, tcg_env, src1, src2); 635 tcg_gen_ext32s_tl(dst, dst); 636 #else 637 TCGv_i64 t64 = tcg_temp_new_i64(); 638 gen_helper_sdiv(t64, tcg_env, src1, src2); 639 tcg_gen_trunc_i64_tl(dst, t64); 640 #endif 641 } 642 643 static void gen_op_udivcc(TCGv dst, TCGv src1, TCGv src2) 644 { 645 TCGv_i64 t64; 646 647 #ifdef TARGET_SPARC64 648 t64 = cpu_cc_V; 649 #else 650 t64 = tcg_temp_new_i64(); 651 #endif 652 653 gen_helper_udiv(t64, tcg_env, src1, src2); 654 655 #ifdef TARGET_SPARC64 656 tcg_gen_ext32u_tl(cpu_cc_N, t64); 657 tcg_gen_shri_tl(cpu_cc_V, t64, 32); 658 tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N); 659 tcg_gen_movi_tl(cpu_icc_C, 0); 660 #else 661 tcg_gen_extr_i64_tl(cpu_cc_N, cpu_cc_V, t64); 662 #endif 663 tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N); 664 tcg_gen_movi_tl(cpu_cc_C, 0); 665 tcg_gen_mov_tl(dst, cpu_cc_N); 666 } 667 668 static void gen_op_sdivcc(TCGv dst, TCGv src1, TCGv src2) 669 { 670 TCGv_i64 t64; 671 672 #ifdef TARGET_SPARC64 673 t64 = cpu_cc_V; 674 #else 675 t64 = tcg_temp_new_i64(); 676 #endif 677 678 gen_helper_sdiv(t64, tcg_env, src1, src2); 679 680 #ifdef TARGET_SPARC64 681 tcg_gen_ext32s_tl(cpu_cc_N, t64); 682 tcg_gen_shri_tl(cpu_cc_V, t64, 32); 683 tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N); 684 tcg_gen_movi_tl(cpu_icc_C, 0); 685 #else 686 tcg_gen_extr_i64_tl(cpu_cc_N, cpu_cc_V, t64); 687 #endif 688 tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N); 689 tcg_gen_movi_tl(cpu_cc_C, 0); 690 tcg_gen_mov_tl(dst, cpu_cc_N); 691 } 692 693 static void gen_op_taddcctv(TCGv dst, TCGv src1, TCGv src2) 694 { 695 gen_helper_taddcctv(dst, tcg_env, src1, src2); 696 } 697 698 static void gen_op_tsubcctv(TCGv dst, TCGv src1, TCGv src2) 699 { 700 gen_helper_tsubcctv(dst, tcg_env, src1, src2); 701 } 702 703 static void gen_op_popc(TCGv dst, TCGv src1, TCGv src2) 704 { 705 tcg_gen_ctpop_tl(dst, src2); 706 } 707 708 static void gen_op_lzcnt(TCGv dst, TCGv src) 709 { 710 tcg_gen_clzi_tl(dst, src, TARGET_LONG_BITS); 711 } 712 713 #ifndef TARGET_SPARC64 714 static void gen_helper_array8(TCGv dst, TCGv src1, TCGv src2) 715 { 716 g_assert_not_reached(); 717 } 718 #endif 719 720 static void gen_op_array16(TCGv dst, TCGv src1, TCGv src2) 721 { 722 gen_helper_array8(dst, src1, src2); 723 tcg_gen_shli_tl(dst, dst, 1); 724 } 725 726 static void gen_op_array32(TCGv dst, TCGv src1, TCGv src2) 727 { 728 gen_helper_array8(dst, src1, src2); 729 tcg_gen_shli_tl(dst, dst, 2); 730 } 731 732 static void gen_op_fpack16(TCGv_i32 dst, TCGv_i64 src) 733 { 734 #ifdef TARGET_SPARC64 735 gen_helper_fpack16(dst, cpu_gsr, src); 736 #else 737 g_assert_not_reached(); 738 #endif 739 } 740 741 static void gen_op_fpackfix(TCGv_i32 dst, TCGv_i64 src) 742 { 743 #ifdef TARGET_SPARC64 744 gen_helper_fpackfix(dst, cpu_gsr, src); 745 #else 746 g_assert_not_reached(); 747 #endif 748 } 749 750 static void gen_op_fpack32(TCGv_i64 dst, TCGv_i64 src1, TCGv_i64 src2) 751 { 752 #ifdef TARGET_SPARC64 753 gen_helper_fpack32(dst, cpu_gsr, src1, src2); 754 #else 755 g_assert_not_reached(); 756 #endif 757 } 758 759 static void gen_op_fpadds16s(TCGv_i32 d, TCGv_i32 src1, TCGv_i32 src2) 760 { 761 TCGv_i32 t[2]; 762 763 for (int i = 0; i < 2; i++) { 764 TCGv_i32 u = tcg_temp_new_i32(); 765 TCGv_i32 v = tcg_temp_new_i32(); 766 767 tcg_gen_sextract_i32(u, src1, i * 16, 16); 768 tcg_gen_sextract_i32(v, src2, i * 16, 16); 769 tcg_gen_add_i32(u, u, v); 770 tcg_gen_smax_i32(u, u, tcg_constant_i32(INT16_MIN)); 771 tcg_gen_smin_i32(u, u, tcg_constant_i32(INT16_MAX)); 772 t[i] = u; 773 } 774 tcg_gen_deposit_i32(d, t[0], t[1], 16, 16); 775 } 776 777 static void gen_op_fpsubs16s(TCGv_i32 d, TCGv_i32 src1, TCGv_i32 src2) 778 { 779 TCGv_i32 t[2]; 780 781 for (int i = 0; i < 2; i++) { 782 TCGv_i32 u = tcg_temp_new_i32(); 783 TCGv_i32 v = tcg_temp_new_i32(); 784 785 tcg_gen_sextract_i32(u, src1, i * 16, 16); 786 tcg_gen_sextract_i32(v, src2, i * 16, 16); 787 tcg_gen_sub_i32(u, u, v); 788 tcg_gen_smax_i32(u, u, tcg_constant_i32(INT16_MIN)); 789 tcg_gen_smin_i32(u, u, tcg_constant_i32(INT16_MAX)); 790 t[i] = u; 791 } 792 tcg_gen_deposit_i32(d, t[0], t[1], 16, 16); 793 } 794 795 static void gen_op_fpadds32s(TCGv_i32 d, TCGv_i32 src1, TCGv_i32 src2) 796 { 797 TCGv_i32 r = tcg_temp_new_i32(); 798 TCGv_i32 t = tcg_temp_new_i32(); 799 TCGv_i32 v = tcg_temp_new_i32(); 800 TCGv_i32 z = tcg_constant_i32(0); 801 802 tcg_gen_add_i32(r, src1, src2); 803 tcg_gen_xor_i32(t, src1, src2); 804 tcg_gen_xor_i32(v, r, src2); 805 tcg_gen_andc_i32(v, v, t); 806 807 tcg_gen_setcond_i32(TCG_COND_GE, t, r, z); 808 tcg_gen_addi_i32(t, t, INT32_MAX); 809 810 tcg_gen_movcond_i32(TCG_COND_LT, d, v, z, t, r); 811 } 812 813 static void gen_op_fpsubs32s(TCGv_i32 d, TCGv_i32 src1, TCGv_i32 src2) 814 { 815 TCGv_i32 r = tcg_temp_new_i32(); 816 TCGv_i32 t = tcg_temp_new_i32(); 817 TCGv_i32 v = tcg_temp_new_i32(); 818 TCGv_i32 z = tcg_constant_i32(0); 819 820 tcg_gen_sub_i32(r, src1, src2); 821 tcg_gen_xor_i32(t, src1, src2); 822 tcg_gen_xor_i32(v, r, src1); 823 tcg_gen_and_i32(v, v, t); 824 825 tcg_gen_setcond_i32(TCG_COND_GE, t, r, z); 826 tcg_gen_addi_i32(t, t, INT32_MAX); 827 828 tcg_gen_movcond_i32(TCG_COND_LT, d, v, z, t, r); 829 } 830 831 static void gen_op_faligndata_i(TCGv_i64 dst, TCGv_i64 s1, 832 TCGv_i64 s2, TCGv gsr) 833 { 834 #ifdef TARGET_SPARC64 835 TCGv t1, t2, shift; 836 837 t1 = tcg_temp_new(); 838 t2 = tcg_temp_new(); 839 shift = tcg_temp_new(); 840 841 tcg_gen_andi_tl(shift, gsr, 7); 842 tcg_gen_shli_tl(shift, shift, 3); 843 tcg_gen_shl_tl(t1, s1, shift); 844 845 /* 846 * A shift of 64 does not produce 0 in TCG. Divide this into a 847 * shift of (up to 63) followed by a constant shift of 1. 848 */ 849 tcg_gen_xori_tl(shift, shift, 63); 850 tcg_gen_shr_tl(t2, s2, shift); 851 tcg_gen_shri_tl(t2, t2, 1); 852 853 tcg_gen_or_tl(dst, t1, t2); 854 #else 855 g_assert_not_reached(); 856 #endif 857 } 858 859 static void gen_op_faligndata_g(TCGv_i64 dst, TCGv_i64 s1, TCGv_i64 s2) 860 { 861 gen_op_faligndata_i(dst, s1, s2, cpu_gsr); 862 } 863 864 static void gen_op_bshuffle(TCGv_i64 dst, TCGv_i64 src1, TCGv_i64 src2) 865 { 866 #ifdef TARGET_SPARC64 867 gen_helper_bshuffle(dst, cpu_gsr, src1, src2); 868 #else 869 g_assert_not_reached(); 870 #endif 871 } 872 873 static void gen_op_pdistn(TCGv dst, TCGv_i64 src1, TCGv_i64 src2) 874 { 875 #ifdef TARGET_SPARC64 876 gen_helper_pdist(dst, tcg_constant_i64(0), src1, src2); 877 #else 878 g_assert_not_reached(); 879 #endif 880 } 881 882 static void gen_op_fmul8x16al(TCGv_i64 dst, TCGv_i32 src1, TCGv_i32 src2) 883 { 884 tcg_gen_ext16s_i32(src2, src2); 885 gen_helper_fmul8x16a(dst, src1, src2); 886 } 887 888 static void gen_op_fmul8x16au(TCGv_i64 dst, TCGv_i32 src1, TCGv_i32 src2) 889 { 890 tcg_gen_sari_i32(src2, src2, 16); 891 gen_helper_fmul8x16a(dst, src1, src2); 892 } 893 894 static void gen_op_fmuld8ulx16(TCGv_i64 dst, TCGv_i32 src1, TCGv_i32 src2) 895 { 896 TCGv_i32 t0 = tcg_temp_new_i32(); 897 TCGv_i32 t1 = tcg_temp_new_i32(); 898 TCGv_i32 t2 = tcg_temp_new_i32(); 899 900 tcg_gen_ext8u_i32(t0, src1); 901 tcg_gen_ext16s_i32(t1, src2); 902 tcg_gen_mul_i32(t0, t0, t1); 903 904 tcg_gen_extract_i32(t1, src1, 16, 8); 905 tcg_gen_sextract_i32(t2, src2, 16, 16); 906 tcg_gen_mul_i32(t1, t1, t2); 907 908 tcg_gen_concat_i32_i64(dst, t0, t1); 909 } 910 911 static void gen_op_fmuld8sux16(TCGv_i64 dst, TCGv_i32 src1, TCGv_i32 src2) 912 { 913 TCGv_i32 t0 = tcg_temp_new_i32(); 914 TCGv_i32 t1 = tcg_temp_new_i32(); 915 TCGv_i32 t2 = tcg_temp_new_i32(); 916 917 /* 918 * The insn description talks about extracting the upper 8 bits 919 * of the signed 16-bit input rs1, performing the multiply, then 920 * shifting left by 8 bits. Instead, zap the lower 8 bits of 921 * the rs1 input, which avoids the need for two shifts. 922 */ 923 tcg_gen_ext16s_i32(t0, src1); 924 tcg_gen_andi_i32(t0, t0, ~0xff); 925 tcg_gen_ext16s_i32(t1, src2); 926 tcg_gen_mul_i32(t0, t0, t1); 927 928 tcg_gen_sextract_i32(t1, src1, 16, 16); 929 tcg_gen_andi_i32(t1, t1, ~0xff); 930 tcg_gen_sextract_i32(t2, src2, 16, 16); 931 tcg_gen_mul_i32(t1, t1, t2); 932 933 tcg_gen_concat_i32_i64(dst, t0, t1); 934 } 935 936 #ifdef TARGET_SPARC64 937 static void gen_vec_fchksm16(unsigned vece, TCGv_vec dst, 938 TCGv_vec src1, TCGv_vec src2) 939 { 940 TCGv_vec a = tcg_temp_new_vec_matching(dst); 941 TCGv_vec c = tcg_temp_new_vec_matching(dst); 942 943 tcg_gen_add_vec(vece, a, src1, src2); 944 tcg_gen_cmp_vec(TCG_COND_LTU, vece, c, a, src1); 945 /* Vector cmp produces -1 for true, so subtract to add carry. */ 946 tcg_gen_sub_vec(vece, dst, a, c); 947 } 948 949 static void gen_op_fchksm16(unsigned vece, uint32_t dofs, uint32_t aofs, 950 uint32_t bofs, uint32_t oprsz, uint32_t maxsz) 951 { 952 static const TCGOpcode vecop_list[] = { 953 INDEX_op_cmp_vec, INDEX_op_add_vec, INDEX_op_sub_vec, 954 }; 955 static const GVecGen3 op = { 956 .fni8 = gen_helper_fchksm16, 957 .fniv = gen_vec_fchksm16, 958 .opt_opc = vecop_list, 959 .vece = MO_16, 960 }; 961 tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &op); 962 } 963 964 static void gen_vec_fmean16(unsigned vece, TCGv_vec dst, 965 TCGv_vec src1, TCGv_vec src2) 966 { 967 TCGv_vec t = tcg_temp_new_vec_matching(dst); 968 969 tcg_gen_or_vec(vece, t, src1, src2); 970 tcg_gen_and_vec(vece, t, t, tcg_constant_vec_matching(dst, vece, 1)); 971 tcg_gen_sari_vec(vece, src1, src1, 1); 972 tcg_gen_sari_vec(vece, src2, src2, 1); 973 tcg_gen_add_vec(vece, dst, src1, src2); 974 tcg_gen_add_vec(vece, dst, dst, t); 975 } 976 977 static void gen_op_fmean16(unsigned vece, uint32_t dofs, uint32_t aofs, 978 uint32_t bofs, uint32_t oprsz, uint32_t maxsz) 979 { 980 static const TCGOpcode vecop_list[] = { 981 INDEX_op_add_vec, INDEX_op_sari_vec, 982 }; 983 static const GVecGen3 op = { 984 .fni8 = gen_helper_fmean16, 985 .fniv = gen_vec_fmean16, 986 .opt_opc = vecop_list, 987 .vece = MO_16, 988 }; 989 tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &op); 990 } 991 #else 992 #define gen_op_fchksm16 ({ qemu_build_not_reached(); NULL; }) 993 #define gen_op_fmean16 ({ qemu_build_not_reached(); NULL; }) 994 #endif 995 996 static void finishing_insn(DisasContext *dc) 997 { 998 /* 999 * From here, there is no future path through an unwinding exception. 1000 * If the current insn cannot raise an exception, the computation of 1001 * cpu_cond may be able to be elided. 1002 */ 1003 if (dc->cpu_cond_live) { 1004 tcg_gen_discard_tl(cpu_cond); 1005 dc->cpu_cond_live = false; 1006 } 1007 } 1008 1009 static void gen_generic_branch(DisasContext *dc) 1010 { 1011 TCGv npc0 = tcg_constant_tl(dc->jump_pc[0]); 1012 TCGv npc1 = tcg_constant_tl(dc->jump_pc[1]); 1013 TCGv c2 = tcg_constant_tl(dc->jump.c2); 1014 1015 tcg_gen_movcond_tl(dc->jump.cond, cpu_npc, dc->jump.c1, c2, npc0, npc1); 1016 } 1017 1018 /* call this function before using the condition register as it may 1019 have been set for a jump */ 1020 static void flush_cond(DisasContext *dc) 1021 { 1022 if (dc->npc == JUMP_PC) { 1023 gen_generic_branch(dc); 1024 dc->npc = DYNAMIC_PC_LOOKUP; 1025 } 1026 } 1027 1028 static void save_npc(DisasContext *dc) 1029 { 1030 if (dc->npc & 3) { 1031 switch (dc->npc) { 1032 case JUMP_PC: 1033 gen_generic_branch(dc); 1034 dc->npc = DYNAMIC_PC_LOOKUP; 1035 break; 1036 case DYNAMIC_PC: 1037 case DYNAMIC_PC_LOOKUP: 1038 break; 1039 default: 1040 g_assert_not_reached(); 1041 } 1042 } else { 1043 tcg_gen_movi_tl(cpu_npc, dc->npc); 1044 } 1045 } 1046 1047 static void save_state(DisasContext *dc) 1048 { 1049 tcg_gen_movi_tl(cpu_pc, dc->pc); 1050 save_npc(dc); 1051 } 1052 1053 static void gen_exception(DisasContext *dc, int which) 1054 { 1055 finishing_insn(dc); 1056 save_state(dc); 1057 gen_helper_raise_exception(tcg_env, tcg_constant_i32(which)); 1058 dc->base.is_jmp = DISAS_NORETURN; 1059 } 1060 1061 static TCGLabel *delay_exceptionv(DisasContext *dc, TCGv_i32 excp) 1062 { 1063 DisasDelayException *e = g_new0(DisasDelayException, 1); 1064 1065 e->next = dc->delay_excp_list; 1066 dc->delay_excp_list = e; 1067 1068 e->lab = gen_new_label(); 1069 e->excp = excp; 1070 e->pc = dc->pc; 1071 /* Caller must have used flush_cond before branch. */ 1072 assert(e->npc != JUMP_PC); 1073 e->npc = dc->npc; 1074 1075 return e->lab; 1076 } 1077 1078 static TCGLabel *delay_exception(DisasContext *dc, int excp) 1079 { 1080 return delay_exceptionv(dc, tcg_constant_i32(excp)); 1081 } 1082 1083 static void gen_check_align(DisasContext *dc, TCGv addr, int mask) 1084 { 1085 TCGv t = tcg_temp_new(); 1086 TCGLabel *lab; 1087 1088 tcg_gen_andi_tl(t, addr, mask); 1089 1090 flush_cond(dc); 1091 lab = delay_exception(dc, TT_UNALIGNED); 1092 tcg_gen_brcondi_tl(TCG_COND_NE, t, 0, lab); 1093 } 1094 1095 static void gen_mov_pc_npc(DisasContext *dc) 1096 { 1097 finishing_insn(dc); 1098 1099 if (dc->npc & 3) { 1100 switch (dc->npc) { 1101 case JUMP_PC: 1102 gen_generic_branch(dc); 1103 tcg_gen_mov_tl(cpu_pc, cpu_npc); 1104 dc->pc = DYNAMIC_PC_LOOKUP; 1105 break; 1106 case DYNAMIC_PC: 1107 case DYNAMIC_PC_LOOKUP: 1108 tcg_gen_mov_tl(cpu_pc, cpu_npc); 1109 dc->pc = dc->npc; 1110 break; 1111 default: 1112 g_assert_not_reached(); 1113 } 1114 } else { 1115 dc->pc = dc->npc; 1116 } 1117 } 1118 1119 static void gen_compare(DisasCompare *cmp, bool xcc, unsigned int cond, 1120 DisasContext *dc) 1121 { 1122 TCGv t1; 1123 1124 cmp->c1 = t1 = tcg_temp_new(); 1125 cmp->c2 = 0; 1126 1127 switch (cond & 7) { 1128 case 0x0: /* never */ 1129 cmp->cond = TCG_COND_NEVER; 1130 cmp->c1 = tcg_constant_tl(0); 1131 break; 1132 1133 case 0x1: /* eq: Z */ 1134 cmp->cond = TCG_COND_EQ; 1135 if (TARGET_LONG_BITS == 32 || xcc) { 1136 tcg_gen_mov_tl(t1, cpu_cc_Z); 1137 } else { 1138 tcg_gen_ext32u_tl(t1, cpu_icc_Z); 1139 } 1140 break; 1141 1142 case 0x2: /* le: Z | (N ^ V) */ 1143 /* 1144 * Simplify: 1145 * cc_Z || (N ^ V) < 0 NE 1146 * cc_Z && !((N ^ V) < 0) EQ 1147 * cc_Z & ~((N ^ V) >> TLB) EQ 1148 */ 1149 cmp->cond = TCG_COND_EQ; 1150 tcg_gen_xor_tl(t1, cpu_cc_N, cpu_cc_V); 1151 tcg_gen_sextract_tl(t1, t1, xcc ? 63 : 31, 1); 1152 tcg_gen_andc_tl(t1, xcc ? cpu_cc_Z : cpu_icc_Z, t1); 1153 if (TARGET_LONG_BITS == 64 && !xcc) { 1154 tcg_gen_ext32u_tl(t1, t1); 1155 } 1156 break; 1157 1158 case 0x3: /* lt: N ^ V */ 1159 cmp->cond = TCG_COND_LT; 1160 tcg_gen_xor_tl(t1, cpu_cc_N, cpu_cc_V); 1161 if (TARGET_LONG_BITS == 64 && !xcc) { 1162 tcg_gen_ext32s_tl(t1, t1); 1163 } 1164 break; 1165 1166 case 0x4: /* leu: Z | C */ 1167 /* 1168 * Simplify: 1169 * cc_Z == 0 || cc_C != 0 NE 1170 * cc_Z != 0 && cc_C == 0 EQ 1171 * cc_Z & (cc_C ? 0 : -1) EQ 1172 * cc_Z & (cc_C - 1) EQ 1173 */ 1174 cmp->cond = TCG_COND_EQ; 1175 if (TARGET_LONG_BITS == 32 || xcc) { 1176 tcg_gen_subi_tl(t1, cpu_cc_C, 1); 1177 tcg_gen_and_tl(t1, t1, cpu_cc_Z); 1178 } else { 1179 tcg_gen_extract_tl(t1, cpu_icc_C, 32, 1); 1180 tcg_gen_subi_tl(t1, t1, 1); 1181 tcg_gen_and_tl(t1, t1, cpu_icc_Z); 1182 tcg_gen_ext32u_tl(t1, t1); 1183 } 1184 break; 1185 1186 case 0x5: /* ltu: C */ 1187 cmp->cond = TCG_COND_NE; 1188 if (TARGET_LONG_BITS == 32 || xcc) { 1189 tcg_gen_mov_tl(t1, cpu_cc_C); 1190 } else { 1191 tcg_gen_extract_tl(t1, cpu_icc_C, 32, 1); 1192 } 1193 break; 1194 1195 case 0x6: /* neg: N */ 1196 cmp->cond = TCG_COND_LT; 1197 if (TARGET_LONG_BITS == 32 || xcc) { 1198 tcg_gen_mov_tl(t1, cpu_cc_N); 1199 } else { 1200 tcg_gen_ext32s_tl(t1, cpu_cc_N); 1201 } 1202 break; 1203 1204 case 0x7: /* vs: V */ 1205 cmp->cond = TCG_COND_LT; 1206 if (TARGET_LONG_BITS == 32 || xcc) { 1207 tcg_gen_mov_tl(t1, cpu_cc_V); 1208 } else { 1209 tcg_gen_ext32s_tl(t1, cpu_cc_V); 1210 } 1211 break; 1212 } 1213 if (cond & 8) { 1214 cmp->cond = tcg_invert_cond(cmp->cond); 1215 } 1216 } 1217 1218 static void gen_fcompare(DisasCompare *cmp, unsigned int cc, unsigned int cond) 1219 { 1220 TCGv_i32 fcc = cpu_fcc[cc]; 1221 TCGv_i32 c1 = fcc; 1222 int c2 = 0; 1223 TCGCond tcond; 1224 1225 /* 1226 * FCC values: 1227 * 0 = 1228 * 1 < 1229 * 2 > 1230 * 3 unordered 1231 */ 1232 switch (cond & 7) { 1233 case 0x0: /* fbn */ 1234 tcond = TCG_COND_NEVER; 1235 break; 1236 case 0x1: /* fbne : !0 */ 1237 tcond = TCG_COND_NE; 1238 break; 1239 case 0x2: /* fblg : 1 or 2 */ 1240 /* fcc in {1,2} - 1 -> fcc in {0,1} */ 1241 c1 = tcg_temp_new_i32(); 1242 tcg_gen_addi_i32(c1, fcc, -1); 1243 c2 = 1; 1244 tcond = TCG_COND_LEU; 1245 break; 1246 case 0x3: /* fbul : 1 or 3 */ 1247 c1 = tcg_temp_new_i32(); 1248 tcg_gen_andi_i32(c1, fcc, 1); 1249 tcond = TCG_COND_NE; 1250 break; 1251 case 0x4: /* fbl : 1 */ 1252 c2 = 1; 1253 tcond = TCG_COND_EQ; 1254 break; 1255 case 0x5: /* fbug : 2 or 3 */ 1256 c2 = 2; 1257 tcond = TCG_COND_GEU; 1258 break; 1259 case 0x6: /* fbg : 2 */ 1260 c2 = 2; 1261 tcond = TCG_COND_EQ; 1262 break; 1263 case 0x7: /* fbu : 3 */ 1264 c2 = 3; 1265 tcond = TCG_COND_EQ; 1266 break; 1267 } 1268 if (cond & 8) { 1269 tcond = tcg_invert_cond(tcond); 1270 } 1271 1272 cmp->cond = tcond; 1273 cmp->c2 = c2; 1274 cmp->c1 = tcg_temp_new(); 1275 tcg_gen_extu_i32_tl(cmp->c1, c1); 1276 } 1277 1278 static bool gen_compare_reg(DisasCompare *cmp, int cond, TCGv r_src) 1279 { 1280 static const TCGCond cond_reg[4] = { 1281 TCG_COND_NEVER, /* reserved */ 1282 TCG_COND_EQ, 1283 TCG_COND_LE, 1284 TCG_COND_LT, 1285 }; 1286 TCGCond tcond; 1287 1288 if ((cond & 3) == 0) { 1289 return false; 1290 } 1291 tcond = cond_reg[cond & 3]; 1292 if (cond & 4) { 1293 tcond = tcg_invert_cond(tcond); 1294 } 1295 1296 cmp->cond = tcond; 1297 cmp->c1 = tcg_temp_new(); 1298 cmp->c2 = 0; 1299 tcg_gen_mov_tl(cmp->c1, r_src); 1300 return true; 1301 } 1302 1303 static void gen_op_clear_ieee_excp_and_FTT(void) 1304 { 1305 tcg_gen_st_i32(tcg_constant_i32(0), tcg_env, 1306 offsetof(CPUSPARCState, fsr_cexc_ftt)); 1307 } 1308 1309 static void gen_op_fmovs(TCGv_i32 dst, TCGv_i32 src) 1310 { 1311 gen_op_clear_ieee_excp_and_FTT(); 1312 tcg_gen_mov_i32(dst, src); 1313 } 1314 1315 static void gen_op_fnegs(TCGv_i32 dst, TCGv_i32 src) 1316 { 1317 gen_op_clear_ieee_excp_and_FTT(); 1318 tcg_gen_xori_i32(dst, src, 1u << 31); 1319 } 1320 1321 static void gen_op_fabss(TCGv_i32 dst, TCGv_i32 src) 1322 { 1323 gen_op_clear_ieee_excp_and_FTT(); 1324 tcg_gen_andi_i32(dst, src, ~(1u << 31)); 1325 } 1326 1327 static void gen_op_fmovd(TCGv_i64 dst, TCGv_i64 src) 1328 { 1329 gen_op_clear_ieee_excp_and_FTT(); 1330 tcg_gen_mov_i64(dst, src); 1331 } 1332 1333 static void gen_op_fnegd(TCGv_i64 dst, TCGv_i64 src) 1334 { 1335 gen_op_clear_ieee_excp_and_FTT(); 1336 tcg_gen_xori_i64(dst, src, 1ull << 63); 1337 } 1338 1339 static void gen_op_fabsd(TCGv_i64 dst, TCGv_i64 src) 1340 { 1341 gen_op_clear_ieee_excp_and_FTT(); 1342 tcg_gen_andi_i64(dst, src, ~(1ull << 63)); 1343 } 1344 1345 static void gen_op_fnegq(TCGv_i128 dst, TCGv_i128 src) 1346 { 1347 TCGv_i64 l = tcg_temp_new_i64(); 1348 TCGv_i64 h = tcg_temp_new_i64(); 1349 1350 tcg_gen_extr_i128_i64(l, h, src); 1351 tcg_gen_xori_i64(h, h, 1ull << 63); 1352 tcg_gen_concat_i64_i128(dst, l, h); 1353 } 1354 1355 static void gen_op_fabsq(TCGv_i128 dst, TCGv_i128 src) 1356 { 1357 TCGv_i64 l = tcg_temp_new_i64(); 1358 TCGv_i64 h = tcg_temp_new_i64(); 1359 1360 tcg_gen_extr_i128_i64(l, h, src); 1361 tcg_gen_andi_i64(h, h, ~(1ull << 63)); 1362 tcg_gen_concat_i64_i128(dst, l, h); 1363 } 1364 1365 static void gen_op_fmadds(TCGv_i32 d, TCGv_i32 s1, TCGv_i32 s2, TCGv_i32 s3) 1366 { 1367 gen_helper_fmadds(d, tcg_env, s1, s2, s3, tcg_constant_i32(0)); 1368 } 1369 1370 static void gen_op_fmaddd(TCGv_i64 d, TCGv_i64 s1, TCGv_i64 s2, TCGv_i64 s3) 1371 { 1372 gen_helper_fmaddd(d, tcg_env, s1, s2, s3, tcg_constant_i32(0)); 1373 } 1374 1375 static void gen_op_fmsubs(TCGv_i32 d, TCGv_i32 s1, TCGv_i32 s2, TCGv_i32 s3) 1376 { 1377 int op = float_muladd_negate_c; 1378 gen_helper_fmadds(d, tcg_env, s1, s2, s3, tcg_constant_i32(op)); 1379 } 1380 1381 static void gen_op_fmsubd(TCGv_i64 d, TCGv_i64 s1, TCGv_i64 s2, TCGv_i64 s3) 1382 { 1383 int op = float_muladd_negate_c; 1384 gen_helper_fmaddd(d, tcg_env, s1, s2, s3, tcg_constant_i32(op)); 1385 } 1386 1387 static void gen_op_fnmsubs(TCGv_i32 d, TCGv_i32 s1, TCGv_i32 s2, TCGv_i32 s3) 1388 { 1389 int op = float_muladd_negate_c | float_muladd_negate_result; 1390 gen_helper_fmadds(d, tcg_env, s1, s2, s3, tcg_constant_i32(op)); 1391 } 1392 1393 static void gen_op_fnmsubd(TCGv_i64 d, TCGv_i64 s1, TCGv_i64 s2, TCGv_i64 s3) 1394 { 1395 int op = float_muladd_negate_c | float_muladd_negate_result; 1396 gen_helper_fmaddd(d, tcg_env, s1, s2, s3, tcg_constant_i32(op)); 1397 } 1398 1399 static void gen_op_fnmadds(TCGv_i32 d, TCGv_i32 s1, TCGv_i32 s2, TCGv_i32 s3) 1400 { 1401 int op = float_muladd_negate_result; 1402 gen_helper_fmadds(d, tcg_env, s1, s2, s3, tcg_constant_i32(op)); 1403 } 1404 1405 static void gen_op_fnmaddd(TCGv_i64 d, TCGv_i64 s1, TCGv_i64 s2, TCGv_i64 s3) 1406 { 1407 int op = float_muladd_negate_result; 1408 gen_helper_fmaddd(d, tcg_env, s1, s2, s3, tcg_constant_i32(op)); 1409 } 1410 1411 /* Use muladd to compute (1 * src1) + src2 / 2 with one rounding. */ 1412 static void gen_op_fhadds(TCGv_i32 d, TCGv_i32 s1, TCGv_i32 s2) 1413 { 1414 TCGv_i32 one = tcg_constant_i32(float32_one); 1415 int op = float_muladd_halve_result; 1416 gen_helper_fmadds(d, tcg_env, one, s1, s2, tcg_constant_i32(op)); 1417 } 1418 1419 static void gen_op_fhaddd(TCGv_i64 d, TCGv_i64 s1, TCGv_i64 s2) 1420 { 1421 TCGv_i64 one = tcg_constant_i64(float64_one); 1422 int op = float_muladd_halve_result; 1423 gen_helper_fmaddd(d, tcg_env, one, s1, s2, tcg_constant_i32(op)); 1424 } 1425 1426 /* Use muladd to compute (1 * src1) - src2 / 2 with one rounding. */ 1427 static void gen_op_fhsubs(TCGv_i32 d, TCGv_i32 s1, TCGv_i32 s2) 1428 { 1429 TCGv_i32 one = tcg_constant_i32(float32_one); 1430 int op = float_muladd_negate_c | float_muladd_halve_result; 1431 gen_helper_fmadds(d, tcg_env, one, s1, s2, tcg_constant_i32(op)); 1432 } 1433 1434 static void gen_op_fhsubd(TCGv_i64 d, TCGv_i64 s1, TCGv_i64 s2) 1435 { 1436 TCGv_i64 one = tcg_constant_i64(float64_one); 1437 int op = float_muladd_negate_c | float_muladd_halve_result; 1438 gen_helper_fmaddd(d, tcg_env, one, s1, s2, tcg_constant_i32(op)); 1439 } 1440 1441 /* Use muladd to compute -((1 * src1) + src2 / 2) with one rounding. */ 1442 static void gen_op_fnhadds(TCGv_i32 d, TCGv_i32 s1, TCGv_i32 s2) 1443 { 1444 TCGv_i32 one = tcg_constant_i32(float32_one); 1445 int op = float_muladd_negate_result | float_muladd_halve_result; 1446 gen_helper_fmadds(d, tcg_env, one, s1, s2, tcg_constant_i32(op)); 1447 } 1448 1449 static void gen_op_fnhaddd(TCGv_i64 d, TCGv_i64 s1, TCGv_i64 s2) 1450 { 1451 TCGv_i64 one = tcg_constant_i64(float64_one); 1452 int op = float_muladd_negate_result | float_muladd_halve_result; 1453 gen_helper_fmaddd(d, tcg_env, one, s1, s2, tcg_constant_i32(op)); 1454 } 1455 1456 static void gen_op_fpexception_im(DisasContext *dc, int ftt) 1457 { 1458 /* 1459 * CEXC is only set when succesfully completing an FPop, 1460 * or when raising FSR_FTT_IEEE_EXCP, i.e. check_ieee_exception. 1461 * Thus we can simply store FTT into this field. 1462 */ 1463 tcg_gen_st_i32(tcg_constant_i32(ftt), tcg_env, 1464 offsetof(CPUSPARCState, fsr_cexc_ftt)); 1465 gen_exception(dc, TT_FP_EXCP); 1466 } 1467 1468 static bool gen_trap_ifnofpu(DisasContext *dc) 1469 { 1470 #if !defined(CONFIG_USER_ONLY) 1471 if (!dc->fpu_enabled) { 1472 gen_exception(dc, TT_NFPU_INSN); 1473 return true; 1474 } 1475 #endif 1476 return false; 1477 } 1478 1479 static bool gen_trap_iffpexception(DisasContext *dc) 1480 { 1481 #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) 1482 /* 1483 * There are 3 states for the sparc32 fpu: 1484 * Normally the fpu is in fp_execute, and all insns are allowed. 1485 * When an exception is signaled, it moves to fp_exception_pending state. 1486 * Upon seeing the next FPop, the fpu moves to fp_exception state, 1487 * populates the FQ, and generates an fp_exception trap. 1488 * The fpu remains in fp_exception state until FQ becomes empty 1489 * after execution of a STDFQ instruction. While the fpu is in 1490 * fp_exception state, and FPop, fp load or fp branch insn will 1491 * return to fp_exception_pending state, set FSR.FTT to sequence_error, 1492 * and the insn will not be entered into the FQ. 1493 * 1494 * In QEMU, we do not model the fp_exception_pending state and 1495 * instead populate FQ and raise the exception immediately. 1496 * But we can still honor fp_exception state by noticing when 1497 * the FQ is not empty. 1498 */ 1499 if (dc->fsr_qne) { 1500 gen_op_fpexception_im(dc, FSR_FTT_SEQ_ERROR); 1501 return true; 1502 } 1503 #endif 1504 return false; 1505 } 1506 1507 static bool gen_trap_if_nofpu_fpexception(DisasContext *dc) 1508 { 1509 return gen_trap_ifnofpu(dc) || gen_trap_iffpexception(dc); 1510 } 1511 1512 /* asi moves */ 1513 typedef enum { 1514 GET_ASI_HELPER, 1515 GET_ASI_EXCP, 1516 GET_ASI_DIRECT, 1517 GET_ASI_DTWINX, 1518 GET_ASI_CODE, 1519 GET_ASI_BLOCK, 1520 GET_ASI_SHORT, 1521 GET_ASI_BCOPY, 1522 GET_ASI_BFILL, 1523 } ASIType; 1524 1525 typedef struct { 1526 ASIType type; 1527 int asi; 1528 int mem_idx; 1529 MemOp memop; 1530 } DisasASI; 1531 1532 /* 1533 * Build DisasASI. 1534 * For asi == -1, treat as non-asi. 1535 * For ask == -2, treat as immediate offset (v8 error, v9 %asi). 1536 */ 1537 static DisasASI resolve_asi(DisasContext *dc, int asi, MemOp memop) 1538 { 1539 ASIType type = GET_ASI_HELPER; 1540 int mem_idx = dc->mem_idx; 1541 1542 if (asi == -1) { 1543 /* Artificial "non-asi" case. */ 1544 type = GET_ASI_DIRECT; 1545 goto done; 1546 } 1547 1548 #ifndef TARGET_SPARC64 1549 /* Before v9, all asis are immediate and privileged. */ 1550 if (asi < 0) { 1551 gen_exception(dc, TT_ILL_INSN); 1552 type = GET_ASI_EXCP; 1553 } else if (supervisor(dc) 1554 /* Note that LEON accepts ASI_USERDATA in user mode, for 1555 use with CASA. Also note that previous versions of 1556 QEMU allowed (and old versions of gcc emitted) ASI_P 1557 for LEON, which is incorrect. */ 1558 || (asi == ASI_USERDATA 1559 && (dc->def->features & CPU_FEATURE_CASA))) { 1560 switch (asi) { 1561 case ASI_USERDATA: /* User data access */ 1562 mem_idx = MMU_USER_IDX; 1563 type = GET_ASI_DIRECT; 1564 break; 1565 case ASI_KERNELDATA: /* Supervisor data access */ 1566 mem_idx = MMU_KERNEL_IDX; 1567 type = GET_ASI_DIRECT; 1568 break; 1569 case ASI_USERTXT: /* User text access */ 1570 mem_idx = MMU_USER_IDX; 1571 type = GET_ASI_CODE; 1572 break; 1573 case ASI_KERNELTXT: /* Supervisor text access */ 1574 mem_idx = MMU_KERNEL_IDX; 1575 type = GET_ASI_CODE; 1576 break; 1577 case ASI_M_BYPASS: /* MMU passthrough */ 1578 case ASI_LEON_BYPASS: /* LEON MMU passthrough */ 1579 mem_idx = MMU_PHYS_IDX; 1580 type = GET_ASI_DIRECT; 1581 break; 1582 case ASI_M_BCOPY: /* Block copy, sta access */ 1583 mem_idx = MMU_KERNEL_IDX; 1584 type = GET_ASI_BCOPY; 1585 break; 1586 case ASI_M_BFILL: /* Block fill, stda access */ 1587 mem_idx = MMU_KERNEL_IDX; 1588 type = GET_ASI_BFILL; 1589 break; 1590 } 1591 1592 /* MMU_PHYS_IDX is used when the MMU is disabled to passthrough the 1593 * permissions check in get_physical_address(..). 1594 */ 1595 mem_idx = (dc->mem_idx == MMU_PHYS_IDX) ? MMU_PHYS_IDX : mem_idx; 1596 } else { 1597 gen_exception(dc, TT_PRIV_INSN); 1598 type = GET_ASI_EXCP; 1599 } 1600 #else 1601 if (asi < 0) { 1602 asi = dc->asi; 1603 } 1604 /* With v9, all asis below 0x80 are privileged. */ 1605 /* ??? We ought to check cpu_has_hypervisor, but we didn't copy 1606 down that bit into DisasContext. For the moment that's ok, 1607 since the direct implementations below doesn't have any ASIs 1608 in the restricted [0x30, 0x7f] range, and the check will be 1609 done properly in the helper. */ 1610 if (!supervisor(dc) && asi < 0x80) { 1611 gen_exception(dc, TT_PRIV_ACT); 1612 type = GET_ASI_EXCP; 1613 } else { 1614 switch (asi) { 1615 case ASI_REAL: /* Bypass */ 1616 case ASI_REAL_IO: /* Bypass, non-cacheable */ 1617 case ASI_REAL_L: /* Bypass LE */ 1618 case ASI_REAL_IO_L: /* Bypass, non-cacheable LE */ 1619 case ASI_TWINX_REAL: /* Real address, twinx */ 1620 case ASI_TWINX_REAL_L: /* Real address, twinx, LE */ 1621 case ASI_QUAD_LDD_PHYS: 1622 case ASI_QUAD_LDD_PHYS_L: 1623 mem_idx = MMU_PHYS_IDX; 1624 break; 1625 case ASI_N: /* Nucleus */ 1626 case ASI_NL: /* Nucleus LE */ 1627 case ASI_TWINX_N: 1628 case ASI_TWINX_NL: 1629 case ASI_NUCLEUS_QUAD_LDD: 1630 case ASI_NUCLEUS_QUAD_LDD_L: 1631 if (hypervisor(dc)) { 1632 mem_idx = MMU_PHYS_IDX; 1633 } else { 1634 mem_idx = MMU_NUCLEUS_IDX; 1635 } 1636 break; 1637 case ASI_AIUP: /* As if user primary */ 1638 case ASI_AIUPL: /* As if user primary LE */ 1639 case ASI_TWINX_AIUP: 1640 case ASI_TWINX_AIUP_L: 1641 case ASI_BLK_AIUP_4V: 1642 case ASI_BLK_AIUP_L_4V: 1643 case ASI_BLK_AIUP: 1644 case ASI_BLK_AIUPL: 1645 case ASI_MON_AIUP: 1646 mem_idx = MMU_USER_IDX; 1647 break; 1648 case ASI_AIUS: /* As if user secondary */ 1649 case ASI_AIUSL: /* As if user secondary LE */ 1650 case ASI_TWINX_AIUS: 1651 case ASI_TWINX_AIUS_L: 1652 case ASI_BLK_AIUS_4V: 1653 case ASI_BLK_AIUS_L_4V: 1654 case ASI_BLK_AIUS: 1655 case ASI_BLK_AIUSL: 1656 case ASI_MON_AIUS: 1657 mem_idx = MMU_USER_SECONDARY_IDX; 1658 break; 1659 case ASI_S: /* Secondary */ 1660 case ASI_SL: /* Secondary LE */ 1661 case ASI_TWINX_S: 1662 case ASI_TWINX_SL: 1663 case ASI_BLK_COMMIT_S: 1664 case ASI_BLK_S: 1665 case ASI_BLK_SL: 1666 case ASI_FL8_S: 1667 case ASI_FL8_SL: 1668 case ASI_FL16_S: 1669 case ASI_FL16_SL: 1670 case ASI_MON_S: 1671 if (mem_idx == MMU_USER_IDX) { 1672 mem_idx = MMU_USER_SECONDARY_IDX; 1673 } else if (mem_idx == MMU_KERNEL_IDX) { 1674 mem_idx = MMU_KERNEL_SECONDARY_IDX; 1675 } 1676 break; 1677 case ASI_P: /* Primary */ 1678 case ASI_PL: /* Primary LE */ 1679 case ASI_TWINX_P: 1680 case ASI_TWINX_PL: 1681 case ASI_BLK_COMMIT_P: 1682 case ASI_BLK_P: 1683 case ASI_BLK_PL: 1684 case ASI_FL8_P: 1685 case ASI_FL8_PL: 1686 case ASI_FL16_P: 1687 case ASI_FL16_PL: 1688 case ASI_MON_P: 1689 break; 1690 } 1691 switch (asi) { 1692 case ASI_REAL: 1693 case ASI_REAL_IO: 1694 case ASI_REAL_L: 1695 case ASI_REAL_IO_L: 1696 case ASI_N: 1697 case ASI_NL: 1698 case ASI_AIUP: 1699 case ASI_AIUPL: 1700 case ASI_AIUS: 1701 case ASI_AIUSL: 1702 case ASI_S: 1703 case ASI_SL: 1704 case ASI_P: 1705 case ASI_PL: 1706 case ASI_MON_P: 1707 case ASI_MON_S: 1708 case ASI_MON_AIUP: 1709 case ASI_MON_AIUS: 1710 type = GET_ASI_DIRECT; 1711 break; 1712 case ASI_TWINX_REAL: 1713 case ASI_TWINX_REAL_L: 1714 case ASI_TWINX_N: 1715 case ASI_TWINX_NL: 1716 case ASI_TWINX_AIUP: 1717 case ASI_TWINX_AIUP_L: 1718 case ASI_TWINX_AIUS: 1719 case ASI_TWINX_AIUS_L: 1720 case ASI_TWINX_P: 1721 case ASI_TWINX_PL: 1722 case ASI_TWINX_S: 1723 case ASI_TWINX_SL: 1724 case ASI_QUAD_LDD_PHYS: 1725 case ASI_QUAD_LDD_PHYS_L: 1726 case ASI_NUCLEUS_QUAD_LDD: 1727 case ASI_NUCLEUS_QUAD_LDD_L: 1728 type = GET_ASI_DTWINX; 1729 break; 1730 case ASI_BLK_COMMIT_P: 1731 case ASI_BLK_COMMIT_S: 1732 case ASI_BLK_AIUP_4V: 1733 case ASI_BLK_AIUP_L_4V: 1734 case ASI_BLK_AIUP: 1735 case ASI_BLK_AIUPL: 1736 case ASI_BLK_AIUS_4V: 1737 case ASI_BLK_AIUS_L_4V: 1738 case ASI_BLK_AIUS: 1739 case ASI_BLK_AIUSL: 1740 case ASI_BLK_S: 1741 case ASI_BLK_SL: 1742 case ASI_BLK_P: 1743 case ASI_BLK_PL: 1744 type = GET_ASI_BLOCK; 1745 break; 1746 case ASI_FL8_S: 1747 case ASI_FL8_SL: 1748 case ASI_FL8_P: 1749 case ASI_FL8_PL: 1750 memop = MO_UB; 1751 type = GET_ASI_SHORT; 1752 break; 1753 case ASI_FL16_S: 1754 case ASI_FL16_SL: 1755 case ASI_FL16_P: 1756 case ASI_FL16_PL: 1757 memop = MO_TEUW; 1758 type = GET_ASI_SHORT; 1759 break; 1760 } 1761 /* The little-endian asis all have bit 3 set. */ 1762 if (asi & 8) { 1763 memop ^= MO_BSWAP; 1764 } 1765 } 1766 #endif 1767 1768 done: 1769 return (DisasASI){ type, asi, mem_idx, memop }; 1770 } 1771 1772 #if defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64) 1773 static void gen_helper_ld_asi(TCGv_i64 r, TCGv_env e, TCGv a, 1774 TCGv_i32 asi, TCGv_i32 mop) 1775 { 1776 g_assert_not_reached(); 1777 } 1778 1779 static void gen_helper_st_asi(TCGv_env e, TCGv a, TCGv_i64 r, 1780 TCGv_i32 asi, TCGv_i32 mop) 1781 { 1782 g_assert_not_reached(); 1783 } 1784 #endif 1785 1786 static void gen_ld_asi(DisasContext *dc, DisasASI *da, TCGv dst, TCGv addr) 1787 { 1788 switch (da->type) { 1789 case GET_ASI_EXCP: 1790 break; 1791 case GET_ASI_DTWINX: /* Reserved for ldda. */ 1792 gen_exception(dc, TT_ILL_INSN); 1793 break; 1794 case GET_ASI_DIRECT: 1795 tcg_gen_qemu_ld_tl(dst, addr, da->mem_idx, da->memop | MO_ALIGN); 1796 break; 1797 1798 case GET_ASI_CODE: 1799 #if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64) 1800 { 1801 MemOpIdx oi = make_memop_idx(da->memop, da->mem_idx); 1802 TCGv_i64 t64 = tcg_temp_new_i64(); 1803 1804 gen_helper_ld_code(t64, tcg_env, addr, tcg_constant_i32(oi)); 1805 tcg_gen_trunc_i64_tl(dst, t64); 1806 } 1807 break; 1808 #else 1809 g_assert_not_reached(); 1810 #endif 1811 1812 default: 1813 { 1814 TCGv_i32 r_asi = tcg_constant_i32(da->asi); 1815 TCGv_i32 r_mop = tcg_constant_i32(da->memop | MO_ALIGN); 1816 1817 save_state(dc); 1818 #ifdef TARGET_SPARC64 1819 gen_helper_ld_asi(dst, tcg_env, addr, r_asi, r_mop); 1820 #else 1821 { 1822 TCGv_i64 t64 = tcg_temp_new_i64(); 1823 gen_helper_ld_asi(t64, tcg_env, addr, r_asi, r_mop); 1824 tcg_gen_trunc_i64_tl(dst, t64); 1825 } 1826 #endif 1827 } 1828 break; 1829 } 1830 } 1831 1832 static void gen_st_asi(DisasContext *dc, DisasASI *da, TCGv src, TCGv addr) 1833 { 1834 switch (da->type) { 1835 case GET_ASI_EXCP: 1836 break; 1837 1838 case GET_ASI_DTWINX: /* Reserved for stda. */ 1839 if (TARGET_LONG_BITS == 32) { 1840 gen_exception(dc, TT_ILL_INSN); 1841 break; 1842 } else if (!(dc->def->features & CPU_FEATURE_HYPV)) { 1843 /* Pre OpenSPARC CPUs don't have these */ 1844 gen_exception(dc, TT_ILL_INSN); 1845 break; 1846 } 1847 /* In OpenSPARC T1+ CPUs TWINX ASIs in store are ST_BLKINIT_ ASIs */ 1848 /* fall through */ 1849 1850 case GET_ASI_DIRECT: 1851 tcg_gen_qemu_st_tl(src, addr, da->mem_idx, da->memop | MO_ALIGN); 1852 break; 1853 1854 case GET_ASI_BCOPY: 1855 assert(TARGET_LONG_BITS == 32); 1856 /* 1857 * Copy 32 bytes from the address in SRC to ADDR. 1858 * 1859 * From Ross RT625 hyperSPARC manual, section 4.6: 1860 * "Block Copy and Block Fill will work only on cache line boundaries." 1861 * 1862 * It does not specify if an unaliged address is truncated or trapped. 1863 * Previous qemu behaviour was to truncate to 4 byte alignment, which 1864 * is obviously wrong. The only place I can see this used is in the 1865 * Linux kernel which begins with page alignment, advancing by 32, 1866 * so is always aligned. Assume truncation as the simpler option. 1867 * 1868 * Since the loads and stores are paired, allow the copy to happen 1869 * in the host endianness. The copy need not be atomic. 1870 */ 1871 { 1872 MemOp mop = MO_128 | MO_ATOM_IFALIGN_PAIR; 1873 TCGv saddr = tcg_temp_new(); 1874 TCGv daddr = tcg_temp_new(); 1875 TCGv_i128 tmp = tcg_temp_new_i128(); 1876 1877 tcg_gen_andi_tl(saddr, src, -32); 1878 tcg_gen_andi_tl(daddr, addr, -32); 1879 tcg_gen_qemu_ld_i128(tmp, saddr, da->mem_idx, mop); 1880 tcg_gen_qemu_st_i128(tmp, daddr, da->mem_idx, mop); 1881 tcg_gen_addi_tl(saddr, saddr, 16); 1882 tcg_gen_addi_tl(daddr, daddr, 16); 1883 tcg_gen_qemu_ld_i128(tmp, saddr, da->mem_idx, mop); 1884 tcg_gen_qemu_st_i128(tmp, daddr, da->mem_idx, mop); 1885 } 1886 break; 1887 1888 default: 1889 { 1890 TCGv_i32 r_asi = tcg_constant_i32(da->asi); 1891 TCGv_i32 r_mop = tcg_constant_i32(da->memop | MO_ALIGN); 1892 1893 save_state(dc); 1894 #ifdef TARGET_SPARC64 1895 gen_helper_st_asi(tcg_env, addr, src, r_asi, r_mop); 1896 #else 1897 { 1898 TCGv_i64 t64 = tcg_temp_new_i64(); 1899 tcg_gen_extu_tl_i64(t64, src); 1900 gen_helper_st_asi(tcg_env, addr, t64, r_asi, r_mop); 1901 } 1902 #endif 1903 1904 /* A write to a TLB register may alter page maps. End the TB. */ 1905 dc->npc = DYNAMIC_PC; 1906 } 1907 break; 1908 } 1909 } 1910 1911 static void gen_swap_asi(DisasContext *dc, DisasASI *da, 1912 TCGv dst, TCGv src, TCGv addr) 1913 { 1914 switch (da->type) { 1915 case GET_ASI_EXCP: 1916 break; 1917 case GET_ASI_DIRECT: 1918 tcg_gen_atomic_xchg_tl(dst, addr, src, 1919 da->mem_idx, da->memop | MO_ALIGN); 1920 break; 1921 default: 1922 /* ??? Should be DAE_invalid_asi. */ 1923 gen_exception(dc, TT_DATA_ACCESS); 1924 break; 1925 } 1926 } 1927 1928 static void gen_cas_asi(DisasContext *dc, DisasASI *da, 1929 TCGv oldv, TCGv newv, TCGv cmpv, TCGv addr) 1930 { 1931 switch (da->type) { 1932 case GET_ASI_EXCP: 1933 return; 1934 case GET_ASI_DIRECT: 1935 tcg_gen_atomic_cmpxchg_tl(oldv, addr, cmpv, newv, 1936 da->mem_idx, da->memop | MO_ALIGN); 1937 break; 1938 default: 1939 /* ??? Should be DAE_invalid_asi. */ 1940 gen_exception(dc, TT_DATA_ACCESS); 1941 break; 1942 } 1943 } 1944 1945 static void gen_ldstub_asi(DisasContext *dc, DisasASI *da, TCGv dst, TCGv addr) 1946 { 1947 switch (da->type) { 1948 case GET_ASI_EXCP: 1949 break; 1950 case GET_ASI_DIRECT: 1951 tcg_gen_atomic_xchg_tl(dst, addr, tcg_constant_tl(0xff), 1952 da->mem_idx, MO_UB); 1953 break; 1954 default: 1955 /* ??? In theory, this should be raise DAE_invalid_asi. 1956 But the SS-20 roms do ldstuba [%l0] #ASI_M_CTL, %o1. */ 1957 if (tb_cflags(dc->base.tb) & CF_PARALLEL) { 1958 gen_helper_exit_atomic(tcg_env); 1959 } else { 1960 TCGv_i32 r_asi = tcg_constant_i32(da->asi); 1961 TCGv_i32 r_mop = tcg_constant_i32(MO_UB); 1962 TCGv_i64 s64, t64; 1963 1964 save_state(dc); 1965 t64 = tcg_temp_new_i64(); 1966 gen_helper_ld_asi(t64, tcg_env, addr, r_asi, r_mop); 1967 1968 s64 = tcg_constant_i64(0xff); 1969 gen_helper_st_asi(tcg_env, addr, s64, r_asi, r_mop); 1970 1971 tcg_gen_trunc_i64_tl(dst, t64); 1972 1973 /* End the TB. */ 1974 dc->npc = DYNAMIC_PC; 1975 } 1976 break; 1977 } 1978 } 1979 1980 static void gen_ldf_asi(DisasContext *dc, DisasASI *da, MemOp orig_size, 1981 TCGv addr, int rd) 1982 { 1983 MemOp memop = da->memop; 1984 MemOp size = memop & MO_SIZE; 1985 TCGv_i32 d32; 1986 TCGv_i64 d64, l64; 1987 TCGv addr_tmp; 1988 1989 /* TODO: Use 128-bit load/store below. */ 1990 if (size == MO_128) { 1991 memop = (memop & ~MO_SIZE) | MO_64; 1992 } 1993 1994 switch (da->type) { 1995 case GET_ASI_EXCP: 1996 break; 1997 1998 case GET_ASI_DIRECT: 1999 memop |= MO_ALIGN_4; 2000 switch (size) { 2001 case MO_32: 2002 d32 = tcg_temp_new_i32(); 2003 tcg_gen_qemu_ld_i32(d32, addr, da->mem_idx, memop); 2004 gen_store_fpr_F(dc, rd, d32); 2005 break; 2006 2007 case MO_64: 2008 d64 = tcg_temp_new_i64(); 2009 tcg_gen_qemu_ld_i64(d64, addr, da->mem_idx, memop); 2010 gen_store_fpr_D(dc, rd, d64); 2011 break; 2012 2013 case MO_128: 2014 d64 = tcg_temp_new_i64(); 2015 l64 = tcg_temp_new_i64(); 2016 tcg_gen_qemu_ld_i64(d64, addr, da->mem_idx, memop); 2017 addr_tmp = tcg_temp_new(); 2018 tcg_gen_addi_tl(addr_tmp, addr, 8); 2019 tcg_gen_qemu_ld_i64(l64, addr_tmp, da->mem_idx, memop); 2020 gen_store_fpr_D(dc, rd, d64); 2021 gen_store_fpr_D(dc, rd + 2, l64); 2022 break; 2023 default: 2024 g_assert_not_reached(); 2025 } 2026 break; 2027 2028 case GET_ASI_BLOCK: 2029 /* Valid for lddfa on aligned registers only. */ 2030 if (orig_size == MO_64 && (rd & 7) == 0) { 2031 /* The first operation checks required alignment. */ 2032 addr_tmp = tcg_temp_new(); 2033 d64 = tcg_temp_new_i64(); 2034 for (int i = 0; ; ++i) { 2035 tcg_gen_qemu_ld_i64(d64, addr, da->mem_idx, 2036 memop | (i == 0 ? MO_ALIGN_64 : 0)); 2037 gen_store_fpr_D(dc, rd + 2 * i, d64); 2038 if (i == 7) { 2039 break; 2040 } 2041 tcg_gen_addi_tl(addr_tmp, addr, 8); 2042 addr = addr_tmp; 2043 } 2044 } else { 2045 gen_exception(dc, TT_ILL_INSN); 2046 } 2047 break; 2048 2049 case GET_ASI_SHORT: 2050 /* Valid for lddfa only. */ 2051 if (orig_size == MO_64) { 2052 d64 = tcg_temp_new_i64(); 2053 tcg_gen_qemu_ld_i64(d64, addr, da->mem_idx, memop | MO_ALIGN); 2054 gen_store_fpr_D(dc, rd, d64); 2055 } else { 2056 gen_exception(dc, TT_ILL_INSN); 2057 } 2058 break; 2059 2060 default: 2061 { 2062 TCGv_i32 r_asi = tcg_constant_i32(da->asi); 2063 TCGv_i32 r_mop = tcg_constant_i32(memop | MO_ALIGN); 2064 2065 save_state(dc); 2066 /* According to the table in the UA2011 manual, the only 2067 other asis that are valid for ldfa/lddfa/ldqfa are 2068 the NO_FAULT asis. We still need a helper for these, 2069 but we can just use the integer asi helper for them. */ 2070 switch (size) { 2071 case MO_32: 2072 d64 = tcg_temp_new_i64(); 2073 gen_helper_ld_asi(d64, tcg_env, addr, r_asi, r_mop); 2074 d32 = tcg_temp_new_i32(); 2075 tcg_gen_extrl_i64_i32(d32, d64); 2076 gen_store_fpr_F(dc, rd, d32); 2077 break; 2078 case MO_64: 2079 d64 = tcg_temp_new_i64(); 2080 gen_helper_ld_asi(d64, tcg_env, addr, r_asi, r_mop); 2081 gen_store_fpr_D(dc, rd, d64); 2082 break; 2083 case MO_128: 2084 d64 = tcg_temp_new_i64(); 2085 l64 = tcg_temp_new_i64(); 2086 gen_helper_ld_asi(d64, tcg_env, addr, r_asi, r_mop); 2087 addr_tmp = tcg_temp_new(); 2088 tcg_gen_addi_tl(addr_tmp, addr, 8); 2089 gen_helper_ld_asi(l64, tcg_env, addr_tmp, r_asi, r_mop); 2090 gen_store_fpr_D(dc, rd, d64); 2091 gen_store_fpr_D(dc, rd + 2, l64); 2092 break; 2093 default: 2094 g_assert_not_reached(); 2095 } 2096 } 2097 break; 2098 } 2099 } 2100 2101 static void gen_stf_asi(DisasContext *dc, DisasASI *da, MemOp orig_size, 2102 TCGv addr, int rd) 2103 { 2104 MemOp memop = da->memop; 2105 MemOp size = memop & MO_SIZE; 2106 TCGv_i32 d32; 2107 TCGv_i64 d64; 2108 TCGv addr_tmp; 2109 2110 /* TODO: Use 128-bit load/store below. */ 2111 if (size == MO_128) { 2112 memop = (memop & ~MO_SIZE) | MO_64; 2113 } 2114 2115 switch (da->type) { 2116 case GET_ASI_EXCP: 2117 break; 2118 2119 case GET_ASI_DIRECT: 2120 memop |= MO_ALIGN_4; 2121 switch (size) { 2122 case MO_32: 2123 d32 = gen_load_fpr_F(dc, rd); 2124 tcg_gen_qemu_st_i32(d32, addr, da->mem_idx, memop | MO_ALIGN); 2125 break; 2126 case MO_64: 2127 d64 = gen_load_fpr_D(dc, rd); 2128 tcg_gen_qemu_st_i64(d64, addr, da->mem_idx, memop | MO_ALIGN_4); 2129 break; 2130 case MO_128: 2131 /* Only 4-byte alignment required. However, it is legal for the 2132 cpu to signal the alignment fault, and the OS trap handler is 2133 required to fix it up. Requiring 16-byte alignment here avoids 2134 having to probe the second page before performing the first 2135 write. */ 2136 d64 = gen_load_fpr_D(dc, rd); 2137 tcg_gen_qemu_st_i64(d64, addr, da->mem_idx, memop | MO_ALIGN_16); 2138 addr_tmp = tcg_temp_new(); 2139 tcg_gen_addi_tl(addr_tmp, addr, 8); 2140 d64 = gen_load_fpr_D(dc, rd + 2); 2141 tcg_gen_qemu_st_i64(d64, addr_tmp, da->mem_idx, memop); 2142 break; 2143 default: 2144 g_assert_not_reached(); 2145 } 2146 break; 2147 2148 case GET_ASI_BLOCK: 2149 /* Valid for stdfa on aligned registers only. */ 2150 if (orig_size == MO_64 && (rd & 7) == 0) { 2151 /* The first operation checks required alignment. */ 2152 addr_tmp = tcg_temp_new(); 2153 for (int i = 0; ; ++i) { 2154 d64 = gen_load_fpr_D(dc, rd + 2 * i); 2155 tcg_gen_qemu_st_i64(d64, addr, da->mem_idx, 2156 memop | (i == 0 ? MO_ALIGN_64 : 0)); 2157 if (i == 7) { 2158 break; 2159 } 2160 tcg_gen_addi_tl(addr_tmp, addr, 8); 2161 addr = addr_tmp; 2162 } 2163 } else { 2164 gen_exception(dc, TT_ILL_INSN); 2165 } 2166 break; 2167 2168 case GET_ASI_SHORT: 2169 /* Valid for stdfa only. */ 2170 if (orig_size == MO_64) { 2171 d64 = gen_load_fpr_D(dc, rd); 2172 tcg_gen_qemu_st_i64(d64, addr, da->mem_idx, memop | MO_ALIGN); 2173 } else { 2174 gen_exception(dc, TT_ILL_INSN); 2175 } 2176 break; 2177 2178 default: 2179 /* According to the table in the UA2011 manual, the only 2180 other asis that are valid for ldfa/lddfa/ldqfa are 2181 the PST* asis, which aren't currently handled. */ 2182 gen_exception(dc, TT_ILL_INSN); 2183 break; 2184 } 2185 } 2186 2187 static void gen_ldda_asi(DisasContext *dc, DisasASI *da, TCGv addr, int rd) 2188 { 2189 TCGv hi = gen_dest_gpr(dc, rd); 2190 TCGv lo = gen_dest_gpr(dc, rd + 1); 2191 2192 switch (da->type) { 2193 case GET_ASI_EXCP: 2194 return; 2195 2196 case GET_ASI_DTWINX: 2197 #ifdef TARGET_SPARC64 2198 { 2199 MemOp mop = (da->memop & MO_BSWAP) | MO_128 | MO_ALIGN_16; 2200 TCGv_i128 t = tcg_temp_new_i128(); 2201 2202 tcg_gen_qemu_ld_i128(t, addr, da->mem_idx, mop); 2203 /* 2204 * Note that LE twinx acts as if each 64-bit register result is 2205 * byte swapped. We perform one 128-bit LE load, so must swap 2206 * the order of the writebacks. 2207 */ 2208 if ((mop & MO_BSWAP) == MO_TE) { 2209 tcg_gen_extr_i128_i64(lo, hi, t); 2210 } else { 2211 tcg_gen_extr_i128_i64(hi, lo, t); 2212 } 2213 } 2214 break; 2215 #else 2216 g_assert_not_reached(); 2217 #endif 2218 2219 case GET_ASI_DIRECT: 2220 { 2221 TCGv_i64 tmp = tcg_temp_new_i64(); 2222 2223 tcg_gen_qemu_ld_i64(tmp, addr, da->mem_idx, da->memop | MO_ALIGN); 2224 2225 /* Note that LE ldda acts as if each 32-bit register 2226 result is byte swapped. Having just performed one 2227 64-bit bswap, we need now to swap the writebacks. */ 2228 if ((da->memop & MO_BSWAP) == MO_TE) { 2229 tcg_gen_extr_i64_tl(lo, hi, tmp); 2230 } else { 2231 tcg_gen_extr_i64_tl(hi, lo, tmp); 2232 } 2233 } 2234 break; 2235 2236 case GET_ASI_CODE: 2237 #if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64) 2238 { 2239 MemOpIdx oi = make_memop_idx(da->memop, da->mem_idx); 2240 TCGv_i64 tmp = tcg_temp_new_i64(); 2241 2242 gen_helper_ld_code(tmp, tcg_env, addr, tcg_constant_i32(oi)); 2243 2244 /* See above. */ 2245 if ((da->memop & MO_BSWAP) == MO_TE) { 2246 tcg_gen_extr_i64_tl(lo, hi, tmp); 2247 } else { 2248 tcg_gen_extr_i64_tl(hi, lo, tmp); 2249 } 2250 } 2251 break; 2252 #else 2253 g_assert_not_reached(); 2254 #endif 2255 2256 default: 2257 /* ??? In theory we've handled all of the ASIs that are valid 2258 for ldda, and this should raise DAE_invalid_asi. However, 2259 real hardware allows others. This can be seen with e.g. 2260 FreeBSD 10.3 wrt ASI_IC_TAG. */ 2261 { 2262 TCGv_i32 r_asi = tcg_constant_i32(da->asi); 2263 TCGv_i32 r_mop = tcg_constant_i32(da->memop); 2264 TCGv_i64 tmp = tcg_temp_new_i64(); 2265 2266 save_state(dc); 2267 gen_helper_ld_asi(tmp, tcg_env, addr, r_asi, r_mop); 2268 2269 /* See above. */ 2270 if ((da->memop & MO_BSWAP) == MO_TE) { 2271 tcg_gen_extr_i64_tl(lo, hi, tmp); 2272 } else { 2273 tcg_gen_extr_i64_tl(hi, lo, tmp); 2274 } 2275 } 2276 break; 2277 } 2278 2279 gen_store_gpr(dc, rd, hi); 2280 gen_store_gpr(dc, rd + 1, lo); 2281 } 2282 2283 static void gen_stda_asi(DisasContext *dc, DisasASI *da, TCGv addr, int rd) 2284 { 2285 TCGv hi = gen_load_gpr(dc, rd); 2286 TCGv lo = gen_load_gpr(dc, rd + 1); 2287 2288 switch (da->type) { 2289 case GET_ASI_EXCP: 2290 break; 2291 2292 case GET_ASI_DTWINX: 2293 #ifdef TARGET_SPARC64 2294 { 2295 MemOp mop = (da->memop & MO_BSWAP) | MO_128 | MO_ALIGN_16; 2296 TCGv_i128 t = tcg_temp_new_i128(); 2297 2298 /* 2299 * Note that LE twinx acts as if each 64-bit register result is 2300 * byte swapped. We perform one 128-bit LE store, so must swap 2301 * the order of the construction. 2302 */ 2303 if ((mop & MO_BSWAP) == MO_TE) { 2304 tcg_gen_concat_i64_i128(t, lo, hi); 2305 } else { 2306 tcg_gen_concat_i64_i128(t, hi, lo); 2307 } 2308 tcg_gen_qemu_st_i128(t, addr, da->mem_idx, mop); 2309 } 2310 break; 2311 #else 2312 g_assert_not_reached(); 2313 #endif 2314 2315 case GET_ASI_DIRECT: 2316 { 2317 TCGv_i64 t64 = tcg_temp_new_i64(); 2318 2319 /* Note that LE stda acts as if each 32-bit register result is 2320 byte swapped. We will perform one 64-bit LE store, so now 2321 we must swap the order of the construction. */ 2322 if ((da->memop & MO_BSWAP) == MO_TE) { 2323 tcg_gen_concat_tl_i64(t64, lo, hi); 2324 } else { 2325 tcg_gen_concat_tl_i64(t64, hi, lo); 2326 } 2327 tcg_gen_qemu_st_i64(t64, addr, da->mem_idx, da->memop | MO_ALIGN); 2328 } 2329 break; 2330 2331 case GET_ASI_BFILL: 2332 assert(TARGET_LONG_BITS == 32); 2333 /* 2334 * Store 32 bytes of [rd:rd+1] to ADDR. 2335 * See comments for GET_ASI_COPY above. 2336 */ 2337 { 2338 MemOp mop = MO_TE | MO_128 | MO_ATOM_IFALIGN_PAIR; 2339 TCGv_i64 t8 = tcg_temp_new_i64(); 2340 TCGv_i128 t16 = tcg_temp_new_i128(); 2341 TCGv daddr = tcg_temp_new(); 2342 2343 tcg_gen_concat_tl_i64(t8, lo, hi); 2344 tcg_gen_concat_i64_i128(t16, t8, t8); 2345 tcg_gen_andi_tl(daddr, addr, -32); 2346 tcg_gen_qemu_st_i128(t16, daddr, da->mem_idx, mop); 2347 tcg_gen_addi_tl(daddr, daddr, 16); 2348 tcg_gen_qemu_st_i128(t16, daddr, da->mem_idx, mop); 2349 } 2350 break; 2351 2352 default: 2353 /* ??? In theory we've handled all of the ASIs that are valid 2354 for stda, and this should raise DAE_invalid_asi. */ 2355 { 2356 TCGv_i32 r_asi = tcg_constant_i32(da->asi); 2357 TCGv_i32 r_mop = tcg_constant_i32(da->memop); 2358 TCGv_i64 t64 = tcg_temp_new_i64(); 2359 2360 /* See above. */ 2361 if ((da->memop & MO_BSWAP) == MO_TE) { 2362 tcg_gen_concat_tl_i64(t64, lo, hi); 2363 } else { 2364 tcg_gen_concat_tl_i64(t64, hi, lo); 2365 } 2366 2367 save_state(dc); 2368 gen_helper_st_asi(tcg_env, addr, t64, r_asi, r_mop); 2369 } 2370 break; 2371 } 2372 } 2373 2374 static void gen_fmovs(DisasContext *dc, DisasCompare *cmp, int rd, int rs) 2375 { 2376 #ifdef TARGET_SPARC64 2377 TCGv_i32 c32, zero, dst, s1, s2; 2378 TCGv_i64 c64 = tcg_temp_new_i64(); 2379 2380 /* We have two choices here: extend the 32 bit data and use movcond_i64, 2381 or fold the comparison down to 32 bits and use movcond_i32. Choose 2382 the later. */ 2383 c32 = tcg_temp_new_i32(); 2384 tcg_gen_setcondi_i64(cmp->cond, c64, cmp->c1, cmp->c2); 2385 tcg_gen_extrl_i64_i32(c32, c64); 2386 2387 s1 = gen_load_fpr_F(dc, rs); 2388 s2 = gen_load_fpr_F(dc, rd); 2389 dst = tcg_temp_new_i32(); 2390 zero = tcg_constant_i32(0); 2391 2392 tcg_gen_movcond_i32(TCG_COND_NE, dst, c32, zero, s1, s2); 2393 2394 gen_store_fpr_F(dc, rd, dst); 2395 #else 2396 qemu_build_not_reached(); 2397 #endif 2398 } 2399 2400 static void gen_fmovd(DisasContext *dc, DisasCompare *cmp, int rd, int rs) 2401 { 2402 #ifdef TARGET_SPARC64 2403 TCGv_i64 dst = tcg_temp_new_i64(); 2404 tcg_gen_movcond_i64(cmp->cond, dst, cmp->c1, tcg_constant_tl(cmp->c2), 2405 gen_load_fpr_D(dc, rs), 2406 gen_load_fpr_D(dc, rd)); 2407 gen_store_fpr_D(dc, rd, dst); 2408 #else 2409 qemu_build_not_reached(); 2410 #endif 2411 } 2412 2413 static void gen_fmovq(DisasContext *dc, DisasCompare *cmp, int rd, int rs) 2414 { 2415 #ifdef TARGET_SPARC64 2416 TCGv c2 = tcg_constant_tl(cmp->c2); 2417 TCGv_i64 h = tcg_temp_new_i64(); 2418 TCGv_i64 l = tcg_temp_new_i64(); 2419 2420 tcg_gen_movcond_i64(cmp->cond, h, cmp->c1, c2, 2421 gen_load_fpr_D(dc, rs), 2422 gen_load_fpr_D(dc, rd)); 2423 tcg_gen_movcond_i64(cmp->cond, l, cmp->c1, c2, 2424 gen_load_fpr_D(dc, rs + 2), 2425 gen_load_fpr_D(dc, rd + 2)); 2426 gen_store_fpr_D(dc, rd, h); 2427 gen_store_fpr_D(dc, rd + 2, l); 2428 #else 2429 qemu_build_not_reached(); 2430 #endif 2431 } 2432 2433 #ifdef TARGET_SPARC64 2434 static void gen_load_trap_state_at_tl(TCGv_ptr r_tsptr) 2435 { 2436 TCGv_i32 r_tl = tcg_temp_new_i32(); 2437 2438 /* load env->tl into r_tl */ 2439 tcg_gen_ld_i32(r_tl, tcg_env, offsetof(CPUSPARCState, tl)); 2440 2441 /* tl = [0 ... MAXTL_MASK] where MAXTL_MASK must be power of 2 */ 2442 tcg_gen_andi_i32(r_tl, r_tl, MAXTL_MASK); 2443 2444 /* calculate offset to current trap state from env->ts, reuse r_tl */ 2445 tcg_gen_muli_i32(r_tl, r_tl, sizeof (trap_state)); 2446 tcg_gen_addi_ptr(r_tsptr, tcg_env, offsetof(CPUSPARCState, ts)); 2447 2448 /* tsptr = env->ts[env->tl & MAXTL_MASK] */ 2449 { 2450 TCGv_ptr r_tl_tmp = tcg_temp_new_ptr(); 2451 tcg_gen_ext_i32_ptr(r_tl_tmp, r_tl); 2452 tcg_gen_add_ptr(r_tsptr, r_tsptr, r_tl_tmp); 2453 } 2454 } 2455 #endif 2456 2457 static int extract_dfpreg(DisasContext *dc, int x) 2458 { 2459 int r = x & 0x1e; 2460 #ifdef TARGET_SPARC64 2461 r |= (x & 1) << 5; 2462 #endif 2463 return r; 2464 } 2465 2466 static int extract_qfpreg(DisasContext *dc, int x) 2467 { 2468 int r = x & 0x1c; 2469 #ifdef TARGET_SPARC64 2470 r |= (x & 1) << 5; 2471 #endif 2472 return r; 2473 } 2474 2475 /* Include the auto-generated decoder. */ 2476 #include "decode-insns.c.inc" 2477 2478 #define TRANS(NAME, AVAIL, FUNC, ...) \ 2479 static bool trans_##NAME(DisasContext *dc, arg_##NAME *a) \ 2480 { return avail_##AVAIL(dc) && FUNC(dc, __VA_ARGS__); } 2481 2482 #define avail_ALL(C) true 2483 #ifdef TARGET_SPARC64 2484 # define avail_32(C) false 2485 # define avail_ASR17(C) false 2486 # define avail_CASA(C) true 2487 # define avail_DIV(C) true 2488 # define avail_MUL(C) true 2489 # define avail_POWERDOWN(C) false 2490 # define avail_64(C) true 2491 # define avail_FMAF(C) ((C)->def->features & CPU_FEATURE_FMAF) 2492 # define avail_GL(C) ((C)->def->features & CPU_FEATURE_GL) 2493 # define avail_HYPV(C) ((C)->def->features & CPU_FEATURE_HYPV) 2494 # define avail_IMA(C) ((C)->def->features & CPU_FEATURE_IMA) 2495 # define avail_VIS1(C) ((C)->def->features & CPU_FEATURE_VIS1) 2496 # define avail_VIS2(C) ((C)->def->features & CPU_FEATURE_VIS2) 2497 # define avail_VIS3(C) ((C)->def->features & CPU_FEATURE_VIS3) 2498 # define avail_VIS3B(C) avail_VIS3(C) 2499 # define avail_VIS4(C) ((C)->def->features & CPU_FEATURE_VIS4) 2500 #else 2501 # define avail_32(C) true 2502 # define avail_ASR17(C) ((C)->def->features & CPU_FEATURE_ASR17) 2503 # define avail_CASA(C) ((C)->def->features & CPU_FEATURE_CASA) 2504 # define avail_DIV(C) ((C)->def->features & CPU_FEATURE_DIV) 2505 # define avail_MUL(C) ((C)->def->features & CPU_FEATURE_MUL) 2506 # define avail_POWERDOWN(C) ((C)->def->features & CPU_FEATURE_POWERDOWN) 2507 # define avail_64(C) false 2508 # define avail_FMAF(C) false 2509 # define avail_GL(C) false 2510 # define avail_HYPV(C) false 2511 # define avail_IMA(C) false 2512 # define avail_VIS1(C) false 2513 # define avail_VIS2(C) false 2514 # define avail_VIS3(C) false 2515 # define avail_VIS3B(C) false 2516 # define avail_VIS4(C) false 2517 #endif 2518 2519 /* Default case for non jump instructions. */ 2520 static bool advance_pc(DisasContext *dc) 2521 { 2522 TCGLabel *l1; 2523 2524 finishing_insn(dc); 2525 2526 if (dc->npc & 3) { 2527 switch (dc->npc) { 2528 case DYNAMIC_PC: 2529 case DYNAMIC_PC_LOOKUP: 2530 dc->pc = dc->npc; 2531 tcg_gen_mov_tl(cpu_pc, cpu_npc); 2532 tcg_gen_addi_tl(cpu_npc, cpu_npc, 4); 2533 break; 2534 2535 case JUMP_PC: 2536 /* we can do a static jump */ 2537 l1 = gen_new_label(); 2538 tcg_gen_brcondi_tl(dc->jump.cond, dc->jump.c1, dc->jump.c2, l1); 2539 2540 /* jump not taken */ 2541 gen_goto_tb(dc, 1, dc->jump_pc[1], dc->jump_pc[1] + 4); 2542 2543 /* jump taken */ 2544 gen_set_label(l1); 2545 gen_goto_tb(dc, 0, dc->jump_pc[0], dc->jump_pc[0] + 4); 2546 2547 dc->base.is_jmp = DISAS_NORETURN; 2548 break; 2549 2550 default: 2551 g_assert_not_reached(); 2552 } 2553 } else { 2554 dc->pc = dc->npc; 2555 dc->npc = dc->npc + 4; 2556 } 2557 return true; 2558 } 2559 2560 /* 2561 * Major opcodes 00 and 01 -- branches, call, and sethi 2562 */ 2563 2564 static bool advance_jump_cond(DisasContext *dc, DisasCompare *cmp, 2565 bool annul, int disp) 2566 { 2567 target_ulong dest = address_mask_i(dc, dc->pc + disp * 4); 2568 target_ulong npc; 2569 2570 finishing_insn(dc); 2571 2572 if (cmp->cond == TCG_COND_ALWAYS) { 2573 if (annul) { 2574 dc->pc = dest; 2575 dc->npc = dest + 4; 2576 } else { 2577 gen_mov_pc_npc(dc); 2578 dc->npc = dest; 2579 } 2580 return true; 2581 } 2582 2583 if (cmp->cond == TCG_COND_NEVER) { 2584 npc = dc->npc; 2585 if (npc & 3) { 2586 gen_mov_pc_npc(dc); 2587 if (annul) { 2588 tcg_gen_addi_tl(cpu_pc, cpu_pc, 4); 2589 } 2590 tcg_gen_addi_tl(cpu_npc, cpu_pc, 4); 2591 } else { 2592 dc->pc = npc + (annul ? 4 : 0); 2593 dc->npc = dc->pc + 4; 2594 } 2595 return true; 2596 } 2597 2598 flush_cond(dc); 2599 npc = dc->npc; 2600 2601 if (annul) { 2602 TCGLabel *l1 = gen_new_label(); 2603 2604 tcg_gen_brcondi_tl(tcg_invert_cond(cmp->cond), cmp->c1, cmp->c2, l1); 2605 gen_goto_tb(dc, 0, npc, dest); 2606 gen_set_label(l1); 2607 gen_goto_tb(dc, 1, npc + 4, npc + 8); 2608 2609 dc->base.is_jmp = DISAS_NORETURN; 2610 } else { 2611 if (npc & 3) { 2612 switch (npc) { 2613 case DYNAMIC_PC: 2614 case DYNAMIC_PC_LOOKUP: 2615 tcg_gen_mov_tl(cpu_pc, cpu_npc); 2616 tcg_gen_addi_tl(cpu_npc, cpu_npc, 4); 2617 tcg_gen_movcond_tl(cmp->cond, cpu_npc, 2618 cmp->c1, tcg_constant_tl(cmp->c2), 2619 tcg_constant_tl(dest), cpu_npc); 2620 dc->pc = npc; 2621 break; 2622 default: 2623 g_assert_not_reached(); 2624 } 2625 } else { 2626 dc->pc = npc; 2627 dc->npc = JUMP_PC; 2628 dc->jump = *cmp; 2629 dc->jump_pc[0] = dest; 2630 dc->jump_pc[1] = npc + 4; 2631 2632 /* The condition for cpu_cond is always NE -- normalize. */ 2633 if (cmp->cond == TCG_COND_NE) { 2634 tcg_gen_xori_tl(cpu_cond, cmp->c1, cmp->c2); 2635 } else { 2636 tcg_gen_setcondi_tl(cmp->cond, cpu_cond, cmp->c1, cmp->c2); 2637 } 2638 dc->cpu_cond_live = true; 2639 } 2640 } 2641 return true; 2642 } 2643 2644 static bool raise_priv(DisasContext *dc) 2645 { 2646 gen_exception(dc, TT_PRIV_INSN); 2647 return true; 2648 } 2649 2650 static bool raise_unimpfpop(DisasContext *dc) 2651 { 2652 gen_op_fpexception_im(dc, FSR_FTT_UNIMPFPOP); 2653 return true; 2654 } 2655 2656 static bool gen_trap_float128(DisasContext *dc) 2657 { 2658 if (dc->def->features & CPU_FEATURE_FLOAT128) { 2659 return false; 2660 } 2661 return raise_unimpfpop(dc); 2662 } 2663 2664 static bool do_bpcc(DisasContext *dc, arg_bcc *a) 2665 { 2666 DisasCompare cmp; 2667 2668 gen_compare(&cmp, a->cc, a->cond, dc); 2669 return advance_jump_cond(dc, &cmp, a->a, a->i); 2670 } 2671 2672 TRANS(Bicc, ALL, do_bpcc, a) 2673 TRANS(BPcc, 64, do_bpcc, a) 2674 2675 static bool do_fbpfcc(DisasContext *dc, arg_bcc *a) 2676 { 2677 DisasCompare cmp; 2678 2679 if (gen_trap_if_nofpu_fpexception(dc)) { 2680 return true; 2681 } 2682 gen_fcompare(&cmp, a->cc, a->cond); 2683 return advance_jump_cond(dc, &cmp, a->a, a->i); 2684 } 2685 2686 TRANS(FBPfcc, 64, do_fbpfcc, a) 2687 TRANS(FBfcc, ALL, do_fbpfcc, a) 2688 2689 static bool trans_BPr(DisasContext *dc, arg_BPr *a) 2690 { 2691 DisasCompare cmp; 2692 2693 if (!avail_64(dc)) { 2694 return false; 2695 } 2696 if (!gen_compare_reg(&cmp, a->cond, gen_load_gpr(dc, a->rs1))) { 2697 return false; 2698 } 2699 return advance_jump_cond(dc, &cmp, a->a, a->i); 2700 } 2701 2702 static bool trans_CALL(DisasContext *dc, arg_CALL *a) 2703 { 2704 target_long target = address_mask_i(dc, dc->pc + a->i * 4); 2705 2706 gen_store_gpr(dc, 15, tcg_constant_tl(dc->pc)); 2707 gen_mov_pc_npc(dc); 2708 dc->npc = target; 2709 return true; 2710 } 2711 2712 static bool trans_NCP(DisasContext *dc, arg_NCP *a) 2713 { 2714 /* 2715 * For sparc32, always generate the no-coprocessor exception. 2716 * For sparc64, always generate illegal instruction. 2717 */ 2718 #ifdef TARGET_SPARC64 2719 return false; 2720 #else 2721 gen_exception(dc, TT_NCP_INSN); 2722 return true; 2723 #endif 2724 } 2725 2726 static bool trans_SETHI(DisasContext *dc, arg_SETHI *a) 2727 { 2728 /* Special-case %g0 because that's the canonical nop. */ 2729 if (a->rd) { 2730 gen_store_gpr(dc, a->rd, tcg_constant_tl((uint32_t)a->i << 10)); 2731 } 2732 return advance_pc(dc); 2733 } 2734 2735 /* 2736 * Major Opcode 10 -- integer, floating-point, vis, and system insns. 2737 */ 2738 2739 static bool do_tcc(DisasContext *dc, int cond, int cc, 2740 int rs1, bool imm, int rs2_or_imm) 2741 { 2742 int mask = ((dc->def->features & CPU_FEATURE_HYPV) && supervisor(dc) 2743 ? UA2005_HTRAP_MASK : V8_TRAP_MASK); 2744 DisasCompare cmp; 2745 TCGLabel *lab; 2746 TCGv_i32 trap; 2747 2748 /* Trap never. */ 2749 if (cond == 0) { 2750 return advance_pc(dc); 2751 } 2752 2753 /* 2754 * Immediate traps are the most common case. Since this value is 2755 * live across the branch, it really pays to evaluate the constant. 2756 */ 2757 if (rs1 == 0 && (imm || rs2_or_imm == 0)) { 2758 trap = tcg_constant_i32((rs2_or_imm & mask) + TT_TRAP); 2759 } else { 2760 trap = tcg_temp_new_i32(); 2761 tcg_gen_trunc_tl_i32(trap, gen_load_gpr(dc, rs1)); 2762 if (imm) { 2763 tcg_gen_addi_i32(trap, trap, rs2_or_imm); 2764 } else { 2765 TCGv_i32 t2 = tcg_temp_new_i32(); 2766 tcg_gen_trunc_tl_i32(t2, gen_load_gpr(dc, rs2_or_imm)); 2767 tcg_gen_add_i32(trap, trap, t2); 2768 } 2769 tcg_gen_andi_i32(trap, trap, mask); 2770 tcg_gen_addi_i32(trap, trap, TT_TRAP); 2771 } 2772 2773 finishing_insn(dc); 2774 2775 /* Trap always. */ 2776 if (cond == 8) { 2777 save_state(dc); 2778 gen_helper_raise_exception(tcg_env, trap); 2779 dc->base.is_jmp = DISAS_NORETURN; 2780 return true; 2781 } 2782 2783 /* Conditional trap. */ 2784 flush_cond(dc); 2785 lab = delay_exceptionv(dc, trap); 2786 gen_compare(&cmp, cc, cond, dc); 2787 tcg_gen_brcondi_tl(cmp.cond, cmp.c1, cmp.c2, lab); 2788 2789 return advance_pc(dc); 2790 } 2791 2792 static bool trans_Tcc_r(DisasContext *dc, arg_Tcc_r *a) 2793 { 2794 if (avail_32(dc) && a->cc) { 2795 return false; 2796 } 2797 return do_tcc(dc, a->cond, a->cc, a->rs1, false, a->rs2); 2798 } 2799 2800 static bool trans_Tcc_i_v7(DisasContext *dc, arg_Tcc_i_v7 *a) 2801 { 2802 if (avail_64(dc)) { 2803 return false; 2804 } 2805 return do_tcc(dc, a->cond, 0, a->rs1, true, a->i); 2806 } 2807 2808 static bool trans_Tcc_i_v9(DisasContext *dc, arg_Tcc_i_v9 *a) 2809 { 2810 if (avail_32(dc)) { 2811 return false; 2812 } 2813 return do_tcc(dc, a->cond, a->cc, a->rs1, true, a->i); 2814 } 2815 2816 static bool trans_STBAR(DisasContext *dc, arg_STBAR *a) 2817 { 2818 tcg_gen_mb(TCG_MO_ST_ST | TCG_BAR_SC); 2819 return advance_pc(dc); 2820 } 2821 2822 static bool trans_MEMBAR(DisasContext *dc, arg_MEMBAR *a) 2823 { 2824 if (avail_32(dc)) { 2825 return false; 2826 } 2827 if (a->mmask) { 2828 /* Note TCG_MO_* was modeled on sparc64, so mmask matches. */ 2829 tcg_gen_mb(a->mmask | TCG_BAR_SC); 2830 } 2831 if (a->cmask) { 2832 /* For #Sync, etc, end the TB to recognize interrupts. */ 2833 dc->base.is_jmp = DISAS_EXIT; 2834 } 2835 return advance_pc(dc); 2836 } 2837 2838 static bool do_rd_special(DisasContext *dc, bool priv, int rd, 2839 TCGv (*func)(DisasContext *, TCGv)) 2840 { 2841 if (!priv) { 2842 return raise_priv(dc); 2843 } 2844 gen_store_gpr(dc, rd, func(dc, gen_dest_gpr(dc, rd))); 2845 return advance_pc(dc); 2846 } 2847 2848 static TCGv do_rdy(DisasContext *dc, TCGv dst) 2849 { 2850 return cpu_y; 2851 } 2852 2853 static bool trans_RDY(DisasContext *dc, arg_RDY *a) 2854 { 2855 /* 2856 * TODO: Need a feature bit for sparcv8. In the meantime, treat all 2857 * 32-bit cpus like sparcv7, which ignores the rs1 field. 2858 * This matches after all other ASR, so Leon3 Asr17 is handled first. 2859 */ 2860 if (avail_64(dc) && a->rs1 != 0) { 2861 return false; 2862 } 2863 return do_rd_special(dc, true, a->rd, do_rdy); 2864 } 2865 2866 static TCGv do_rd_leon3_config(DisasContext *dc, TCGv dst) 2867 { 2868 gen_helper_rdasr17(dst, tcg_env); 2869 return dst; 2870 } 2871 2872 TRANS(RDASR17, ASR17, do_rd_special, true, a->rd, do_rd_leon3_config) 2873 2874 static TCGv do_rdccr(DisasContext *dc, TCGv dst) 2875 { 2876 gen_helper_rdccr(dst, tcg_env); 2877 return dst; 2878 } 2879 2880 TRANS(RDCCR, 64, do_rd_special, true, a->rd, do_rdccr) 2881 2882 static TCGv do_rdasi(DisasContext *dc, TCGv dst) 2883 { 2884 #ifdef TARGET_SPARC64 2885 return tcg_constant_tl(dc->asi); 2886 #else 2887 qemu_build_not_reached(); 2888 #endif 2889 } 2890 2891 TRANS(RDASI, 64, do_rd_special, true, a->rd, do_rdasi) 2892 2893 static TCGv do_rdtick(DisasContext *dc, TCGv dst) 2894 { 2895 TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 2896 2897 tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(tick)); 2898 if (translator_io_start(&dc->base)) { 2899 dc->base.is_jmp = DISAS_EXIT; 2900 } 2901 gen_helper_tick_get_count(dst, tcg_env, r_tickptr, 2902 tcg_constant_i32(dc->mem_idx)); 2903 return dst; 2904 } 2905 2906 /* TODO: non-priv access only allowed when enabled. */ 2907 TRANS(RDTICK, 64, do_rd_special, true, a->rd, do_rdtick) 2908 2909 static TCGv do_rdpc(DisasContext *dc, TCGv dst) 2910 { 2911 return tcg_constant_tl(address_mask_i(dc, dc->pc)); 2912 } 2913 2914 TRANS(RDPC, 64, do_rd_special, true, a->rd, do_rdpc) 2915 2916 static TCGv do_rdfprs(DisasContext *dc, TCGv dst) 2917 { 2918 tcg_gen_ext_i32_tl(dst, cpu_fprs); 2919 return dst; 2920 } 2921 2922 TRANS(RDFPRS, 64, do_rd_special, true, a->rd, do_rdfprs) 2923 2924 static TCGv do_rdgsr(DisasContext *dc, TCGv dst) 2925 { 2926 gen_trap_ifnofpu(dc); 2927 return cpu_gsr; 2928 } 2929 2930 TRANS(RDGSR, 64, do_rd_special, true, a->rd, do_rdgsr) 2931 2932 static TCGv do_rdsoftint(DisasContext *dc, TCGv dst) 2933 { 2934 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(softint)); 2935 return dst; 2936 } 2937 2938 TRANS(RDSOFTINT, 64, do_rd_special, supervisor(dc), a->rd, do_rdsoftint) 2939 2940 static TCGv do_rdtick_cmpr(DisasContext *dc, TCGv dst) 2941 { 2942 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(tick_cmpr)); 2943 return dst; 2944 } 2945 2946 /* TODO: non-priv access only allowed when enabled. */ 2947 TRANS(RDTICK_CMPR, 64, do_rd_special, true, a->rd, do_rdtick_cmpr) 2948 2949 static TCGv do_rdstick(DisasContext *dc, TCGv dst) 2950 { 2951 TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 2952 2953 tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(stick)); 2954 if (translator_io_start(&dc->base)) { 2955 dc->base.is_jmp = DISAS_EXIT; 2956 } 2957 gen_helper_tick_get_count(dst, tcg_env, r_tickptr, 2958 tcg_constant_i32(dc->mem_idx)); 2959 return dst; 2960 } 2961 2962 /* TODO: non-priv access only allowed when enabled. */ 2963 TRANS(RDSTICK, 64, do_rd_special, true, a->rd, do_rdstick) 2964 2965 static TCGv do_rdstick_cmpr(DisasContext *dc, TCGv dst) 2966 { 2967 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(stick_cmpr)); 2968 return dst; 2969 } 2970 2971 /* TODO: supervisor access only allowed when enabled by hypervisor. */ 2972 TRANS(RDSTICK_CMPR, 64, do_rd_special, supervisor(dc), a->rd, do_rdstick_cmpr) 2973 2974 /* 2975 * UltraSPARC-T1 Strand status. 2976 * HYPV check maybe not enough, UA2005 & UA2007 describe 2977 * this ASR as impl. dep 2978 */ 2979 static TCGv do_rdstrand_status(DisasContext *dc, TCGv dst) 2980 { 2981 return tcg_constant_tl(1); 2982 } 2983 2984 TRANS(RDSTRAND_STATUS, HYPV, do_rd_special, true, a->rd, do_rdstrand_status) 2985 2986 static TCGv do_rdpsr(DisasContext *dc, TCGv dst) 2987 { 2988 gen_helper_rdpsr(dst, tcg_env); 2989 return dst; 2990 } 2991 2992 TRANS(RDPSR, 32, do_rd_special, supervisor(dc), a->rd, do_rdpsr) 2993 2994 static TCGv do_rdhpstate(DisasContext *dc, TCGv dst) 2995 { 2996 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hpstate)); 2997 return dst; 2998 } 2999 3000 TRANS(RDHPR_hpstate, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhpstate) 3001 3002 static TCGv do_rdhtstate(DisasContext *dc, TCGv dst) 3003 { 3004 TCGv_i32 tl = tcg_temp_new_i32(); 3005 TCGv_ptr tp = tcg_temp_new_ptr(); 3006 3007 tcg_gen_ld_i32(tl, tcg_env, env64_field_offsetof(tl)); 3008 tcg_gen_andi_i32(tl, tl, MAXTL_MASK); 3009 tcg_gen_shli_i32(tl, tl, 3); 3010 tcg_gen_ext_i32_ptr(tp, tl); 3011 tcg_gen_add_ptr(tp, tp, tcg_env); 3012 3013 tcg_gen_ld_tl(dst, tp, env64_field_offsetof(htstate)); 3014 return dst; 3015 } 3016 3017 TRANS(RDHPR_htstate, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhtstate) 3018 3019 static TCGv do_rdhintp(DisasContext *dc, TCGv dst) 3020 { 3021 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hintp)); 3022 return dst; 3023 } 3024 3025 TRANS(RDHPR_hintp, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhintp) 3026 3027 static TCGv do_rdhtba(DisasContext *dc, TCGv dst) 3028 { 3029 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(htba)); 3030 return dst; 3031 } 3032 3033 TRANS(RDHPR_htba, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhtba) 3034 3035 static TCGv do_rdhver(DisasContext *dc, TCGv dst) 3036 { 3037 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hver)); 3038 return dst; 3039 } 3040 3041 TRANS(RDHPR_hver, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhver) 3042 3043 static TCGv do_rdhstick_cmpr(DisasContext *dc, TCGv dst) 3044 { 3045 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hstick_cmpr)); 3046 return dst; 3047 } 3048 3049 TRANS(RDHPR_hstick_cmpr, HYPV, do_rd_special, hypervisor(dc), a->rd, 3050 do_rdhstick_cmpr) 3051 3052 static TCGv do_rdwim(DisasContext *dc, TCGv dst) 3053 { 3054 tcg_gen_ld_tl(dst, tcg_env, env32_field_offsetof(wim)); 3055 return dst; 3056 } 3057 3058 TRANS(RDWIM, 32, do_rd_special, supervisor(dc), a->rd, do_rdwim) 3059 3060 static TCGv do_rdtpc(DisasContext *dc, TCGv dst) 3061 { 3062 #ifdef TARGET_SPARC64 3063 TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 3064 3065 gen_load_trap_state_at_tl(r_tsptr); 3066 tcg_gen_ld_tl(dst, r_tsptr, offsetof(trap_state, tpc)); 3067 return dst; 3068 #else 3069 qemu_build_not_reached(); 3070 #endif 3071 } 3072 3073 TRANS(RDPR_tpc, 64, do_rd_special, supervisor(dc), a->rd, do_rdtpc) 3074 3075 static TCGv do_rdtnpc(DisasContext *dc, TCGv dst) 3076 { 3077 #ifdef TARGET_SPARC64 3078 TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 3079 3080 gen_load_trap_state_at_tl(r_tsptr); 3081 tcg_gen_ld_tl(dst, r_tsptr, offsetof(trap_state, tnpc)); 3082 return dst; 3083 #else 3084 qemu_build_not_reached(); 3085 #endif 3086 } 3087 3088 TRANS(RDPR_tnpc, 64, do_rd_special, supervisor(dc), a->rd, do_rdtnpc) 3089 3090 static TCGv do_rdtstate(DisasContext *dc, TCGv dst) 3091 { 3092 #ifdef TARGET_SPARC64 3093 TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 3094 3095 gen_load_trap_state_at_tl(r_tsptr); 3096 tcg_gen_ld_tl(dst, r_tsptr, offsetof(trap_state, tstate)); 3097 return dst; 3098 #else 3099 qemu_build_not_reached(); 3100 #endif 3101 } 3102 3103 TRANS(RDPR_tstate, 64, do_rd_special, supervisor(dc), a->rd, do_rdtstate) 3104 3105 static TCGv do_rdtt(DisasContext *dc, TCGv dst) 3106 { 3107 #ifdef TARGET_SPARC64 3108 TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 3109 3110 gen_load_trap_state_at_tl(r_tsptr); 3111 tcg_gen_ld32s_tl(dst, r_tsptr, offsetof(trap_state, tt)); 3112 return dst; 3113 #else 3114 qemu_build_not_reached(); 3115 #endif 3116 } 3117 3118 TRANS(RDPR_tt, 64, do_rd_special, supervisor(dc), a->rd, do_rdtt) 3119 TRANS(RDPR_tick, 64, do_rd_special, supervisor(dc), a->rd, do_rdtick) 3120 3121 static TCGv do_rdtba(DisasContext *dc, TCGv dst) 3122 { 3123 return cpu_tbr; 3124 } 3125 3126 TRANS(RDTBR, 32, do_rd_special, supervisor(dc), a->rd, do_rdtba) 3127 TRANS(RDPR_tba, 64, do_rd_special, supervisor(dc), a->rd, do_rdtba) 3128 3129 static TCGv do_rdpstate(DisasContext *dc, TCGv dst) 3130 { 3131 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(pstate)); 3132 return dst; 3133 } 3134 3135 TRANS(RDPR_pstate, 64, do_rd_special, supervisor(dc), a->rd, do_rdpstate) 3136 3137 static TCGv do_rdtl(DisasContext *dc, TCGv dst) 3138 { 3139 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(tl)); 3140 return dst; 3141 } 3142 3143 TRANS(RDPR_tl, 64, do_rd_special, supervisor(dc), a->rd, do_rdtl) 3144 3145 static TCGv do_rdpil(DisasContext *dc, TCGv dst) 3146 { 3147 tcg_gen_ld32s_tl(dst, tcg_env, env_field_offsetof(psrpil)); 3148 return dst; 3149 } 3150 3151 TRANS(RDPR_pil, 64, do_rd_special, supervisor(dc), a->rd, do_rdpil) 3152 3153 static TCGv do_rdcwp(DisasContext *dc, TCGv dst) 3154 { 3155 gen_helper_rdcwp(dst, tcg_env); 3156 return dst; 3157 } 3158 3159 TRANS(RDPR_cwp, 64, do_rd_special, supervisor(dc), a->rd, do_rdcwp) 3160 3161 static TCGv do_rdcansave(DisasContext *dc, TCGv dst) 3162 { 3163 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(cansave)); 3164 return dst; 3165 } 3166 3167 TRANS(RDPR_cansave, 64, do_rd_special, supervisor(dc), a->rd, do_rdcansave) 3168 3169 static TCGv do_rdcanrestore(DisasContext *dc, TCGv dst) 3170 { 3171 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(canrestore)); 3172 return dst; 3173 } 3174 3175 TRANS(RDPR_canrestore, 64, do_rd_special, supervisor(dc), a->rd, 3176 do_rdcanrestore) 3177 3178 static TCGv do_rdcleanwin(DisasContext *dc, TCGv dst) 3179 { 3180 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(cleanwin)); 3181 return dst; 3182 } 3183 3184 TRANS(RDPR_cleanwin, 64, do_rd_special, supervisor(dc), a->rd, do_rdcleanwin) 3185 3186 static TCGv do_rdotherwin(DisasContext *dc, TCGv dst) 3187 { 3188 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(otherwin)); 3189 return dst; 3190 } 3191 3192 TRANS(RDPR_otherwin, 64, do_rd_special, supervisor(dc), a->rd, do_rdotherwin) 3193 3194 static TCGv do_rdwstate(DisasContext *dc, TCGv dst) 3195 { 3196 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(wstate)); 3197 return dst; 3198 } 3199 3200 TRANS(RDPR_wstate, 64, do_rd_special, supervisor(dc), a->rd, do_rdwstate) 3201 3202 static TCGv do_rdgl(DisasContext *dc, TCGv dst) 3203 { 3204 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(gl)); 3205 return dst; 3206 } 3207 3208 TRANS(RDPR_gl, GL, do_rd_special, supervisor(dc), a->rd, do_rdgl) 3209 3210 /* UA2005 strand status */ 3211 static TCGv do_rdssr(DisasContext *dc, TCGv dst) 3212 { 3213 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(ssr)); 3214 return dst; 3215 } 3216 3217 TRANS(RDPR_strand_status, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdssr) 3218 3219 static TCGv do_rdver(DisasContext *dc, TCGv dst) 3220 { 3221 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(version)); 3222 return dst; 3223 } 3224 3225 TRANS(RDPR_ver, 64, do_rd_special, supervisor(dc), a->rd, do_rdver) 3226 3227 static bool trans_FLUSHW(DisasContext *dc, arg_FLUSHW *a) 3228 { 3229 if (avail_64(dc)) { 3230 gen_helper_flushw(tcg_env); 3231 return advance_pc(dc); 3232 } 3233 return false; 3234 } 3235 3236 static bool do_wr_special(DisasContext *dc, arg_r_r_ri *a, bool priv, 3237 void (*func)(DisasContext *, TCGv)) 3238 { 3239 TCGv src; 3240 3241 /* For simplicity, we under-decoded the rs2 form. */ 3242 if (!a->imm && (a->rs2_or_imm & ~0x1f)) { 3243 return false; 3244 } 3245 if (!priv) { 3246 return raise_priv(dc); 3247 } 3248 3249 if (a->rs1 == 0 && (a->imm || a->rs2_or_imm == 0)) { 3250 src = tcg_constant_tl(a->rs2_or_imm); 3251 } else { 3252 TCGv src1 = gen_load_gpr(dc, a->rs1); 3253 if (a->rs2_or_imm == 0) { 3254 src = src1; 3255 } else { 3256 src = tcg_temp_new(); 3257 if (a->imm) { 3258 tcg_gen_xori_tl(src, src1, a->rs2_or_imm); 3259 } else { 3260 tcg_gen_xor_tl(src, src1, gen_load_gpr(dc, a->rs2_or_imm)); 3261 } 3262 } 3263 } 3264 func(dc, src); 3265 return advance_pc(dc); 3266 } 3267 3268 static void do_wry(DisasContext *dc, TCGv src) 3269 { 3270 tcg_gen_ext32u_tl(cpu_y, src); 3271 } 3272 3273 TRANS(WRY, ALL, do_wr_special, a, true, do_wry) 3274 3275 static void do_wrccr(DisasContext *dc, TCGv src) 3276 { 3277 gen_helper_wrccr(tcg_env, src); 3278 } 3279 3280 TRANS(WRCCR, 64, do_wr_special, a, true, do_wrccr) 3281 3282 static void do_wrasi(DisasContext *dc, TCGv src) 3283 { 3284 TCGv tmp = tcg_temp_new(); 3285 3286 tcg_gen_ext8u_tl(tmp, src); 3287 tcg_gen_st32_tl(tmp, tcg_env, env64_field_offsetof(asi)); 3288 /* End TB to notice changed ASI. */ 3289 dc->base.is_jmp = DISAS_EXIT; 3290 } 3291 3292 TRANS(WRASI, 64, do_wr_special, a, true, do_wrasi) 3293 3294 static void do_wrfprs(DisasContext *dc, TCGv src) 3295 { 3296 #ifdef TARGET_SPARC64 3297 tcg_gen_trunc_tl_i32(cpu_fprs, src); 3298 dc->fprs_dirty = 0; 3299 dc->base.is_jmp = DISAS_EXIT; 3300 #else 3301 qemu_build_not_reached(); 3302 #endif 3303 } 3304 3305 TRANS(WRFPRS, 64, do_wr_special, a, true, do_wrfprs) 3306 3307 static void do_wrgsr(DisasContext *dc, TCGv src) 3308 { 3309 gen_trap_ifnofpu(dc); 3310 tcg_gen_mov_tl(cpu_gsr, src); 3311 } 3312 3313 TRANS(WRGSR, 64, do_wr_special, a, true, do_wrgsr) 3314 3315 static void do_wrsoftint_set(DisasContext *dc, TCGv src) 3316 { 3317 gen_helper_set_softint(tcg_env, src); 3318 } 3319 3320 TRANS(WRSOFTINT_SET, 64, do_wr_special, a, supervisor(dc), do_wrsoftint_set) 3321 3322 static void do_wrsoftint_clr(DisasContext *dc, TCGv src) 3323 { 3324 gen_helper_clear_softint(tcg_env, src); 3325 } 3326 3327 TRANS(WRSOFTINT_CLR, 64, do_wr_special, a, supervisor(dc), do_wrsoftint_clr) 3328 3329 static void do_wrsoftint(DisasContext *dc, TCGv src) 3330 { 3331 gen_helper_write_softint(tcg_env, src); 3332 } 3333 3334 TRANS(WRSOFTINT, 64, do_wr_special, a, supervisor(dc), do_wrsoftint) 3335 3336 static void do_wrtick_cmpr(DisasContext *dc, TCGv src) 3337 { 3338 TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 3339 3340 tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(tick_cmpr)); 3341 tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(tick)); 3342 translator_io_start(&dc->base); 3343 gen_helper_tick_set_limit(r_tickptr, src); 3344 /* End TB to handle timer interrupt */ 3345 dc->base.is_jmp = DISAS_EXIT; 3346 } 3347 3348 TRANS(WRTICK_CMPR, 64, do_wr_special, a, supervisor(dc), do_wrtick_cmpr) 3349 3350 static void do_wrstick(DisasContext *dc, TCGv src) 3351 { 3352 #ifdef TARGET_SPARC64 3353 TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 3354 3355 tcg_gen_ld_ptr(r_tickptr, tcg_env, offsetof(CPUSPARCState, stick)); 3356 translator_io_start(&dc->base); 3357 gen_helper_tick_set_count(r_tickptr, src); 3358 /* End TB to handle timer interrupt */ 3359 dc->base.is_jmp = DISAS_EXIT; 3360 #else 3361 qemu_build_not_reached(); 3362 #endif 3363 } 3364 3365 TRANS(WRSTICK, 64, do_wr_special, a, supervisor(dc), do_wrstick) 3366 3367 static void do_wrstick_cmpr(DisasContext *dc, TCGv src) 3368 { 3369 TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 3370 3371 tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(stick_cmpr)); 3372 tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(stick)); 3373 translator_io_start(&dc->base); 3374 gen_helper_tick_set_limit(r_tickptr, src); 3375 /* End TB to handle timer interrupt */ 3376 dc->base.is_jmp = DISAS_EXIT; 3377 } 3378 3379 TRANS(WRSTICK_CMPR, 64, do_wr_special, a, supervisor(dc), do_wrstick_cmpr) 3380 3381 static void do_wrpowerdown(DisasContext *dc, TCGv src) 3382 { 3383 finishing_insn(dc); 3384 save_state(dc); 3385 gen_helper_power_down(tcg_env); 3386 } 3387 3388 TRANS(WRPOWERDOWN, POWERDOWN, do_wr_special, a, supervisor(dc), do_wrpowerdown) 3389 3390 static void do_wrmwait(DisasContext *dc, TCGv src) 3391 { 3392 /* 3393 * TODO: This is a stub version of mwait, which merely recognizes 3394 * interrupts immediately and does not wait. 3395 */ 3396 dc->base.is_jmp = DISAS_EXIT; 3397 } 3398 3399 TRANS(WRMWAIT, VIS4, do_wr_special, a, true, do_wrmwait) 3400 3401 static void do_wrpsr(DisasContext *dc, TCGv src) 3402 { 3403 gen_helper_wrpsr(tcg_env, src); 3404 dc->base.is_jmp = DISAS_EXIT; 3405 } 3406 3407 TRANS(WRPSR, 32, do_wr_special, a, supervisor(dc), do_wrpsr) 3408 3409 static void do_wrwim(DisasContext *dc, TCGv src) 3410 { 3411 target_ulong mask = MAKE_64BIT_MASK(0, dc->def->nwindows); 3412 TCGv tmp = tcg_temp_new(); 3413 3414 tcg_gen_andi_tl(tmp, src, mask); 3415 tcg_gen_st_tl(tmp, tcg_env, env32_field_offsetof(wim)); 3416 } 3417 3418 TRANS(WRWIM, 32, do_wr_special, a, supervisor(dc), do_wrwim) 3419 3420 static void do_wrtpc(DisasContext *dc, TCGv src) 3421 { 3422 #ifdef TARGET_SPARC64 3423 TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 3424 3425 gen_load_trap_state_at_tl(r_tsptr); 3426 tcg_gen_st_tl(src, r_tsptr, offsetof(trap_state, tpc)); 3427 #else 3428 qemu_build_not_reached(); 3429 #endif 3430 } 3431 3432 TRANS(WRPR_tpc, 64, do_wr_special, a, supervisor(dc), do_wrtpc) 3433 3434 static void do_wrtnpc(DisasContext *dc, TCGv src) 3435 { 3436 #ifdef TARGET_SPARC64 3437 TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 3438 3439 gen_load_trap_state_at_tl(r_tsptr); 3440 tcg_gen_st_tl(src, r_tsptr, offsetof(trap_state, tnpc)); 3441 #else 3442 qemu_build_not_reached(); 3443 #endif 3444 } 3445 3446 TRANS(WRPR_tnpc, 64, do_wr_special, a, supervisor(dc), do_wrtnpc) 3447 3448 static void do_wrtstate(DisasContext *dc, TCGv src) 3449 { 3450 #ifdef TARGET_SPARC64 3451 TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 3452 3453 gen_load_trap_state_at_tl(r_tsptr); 3454 tcg_gen_st_tl(src, r_tsptr, offsetof(trap_state, tstate)); 3455 #else 3456 qemu_build_not_reached(); 3457 #endif 3458 } 3459 3460 TRANS(WRPR_tstate, 64, do_wr_special, a, supervisor(dc), do_wrtstate) 3461 3462 static void do_wrtt(DisasContext *dc, TCGv src) 3463 { 3464 #ifdef TARGET_SPARC64 3465 TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 3466 3467 gen_load_trap_state_at_tl(r_tsptr); 3468 tcg_gen_st32_tl(src, r_tsptr, offsetof(trap_state, tt)); 3469 #else 3470 qemu_build_not_reached(); 3471 #endif 3472 } 3473 3474 TRANS(WRPR_tt, 64, do_wr_special, a, supervisor(dc), do_wrtt) 3475 3476 static void do_wrtick(DisasContext *dc, TCGv src) 3477 { 3478 TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 3479 3480 tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(tick)); 3481 translator_io_start(&dc->base); 3482 gen_helper_tick_set_count(r_tickptr, src); 3483 /* End TB to handle timer interrupt */ 3484 dc->base.is_jmp = DISAS_EXIT; 3485 } 3486 3487 TRANS(WRPR_tick, 64, do_wr_special, a, supervisor(dc), do_wrtick) 3488 3489 static void do_wrtba(DisasContext *dc, TCGv src) 3490 { 3491 tcg_gen_mov_tl(cpu_tbr, src); 3492 } 3493 3494 TRANS(WRPR_tba, 64, do_wr_special, a, supervisor(dc), do_wrtba) 3495 3496 static void do_wrpstate(DisasContext *dc, TCGv src) 3497 { 3498 save_state(dc); 3499 if (translator_io_start(&dc->base)) { 3500 dc->base.is_jmp = DISAS_EXIT; 3501 } 3502 gen_helper_wrpstate(tcg_env, src); 3503 dc->npc = DYNAMIC_PC; 3504 } 3505 3506 TRANS(WRPR_pstate, 64, do_wr_special, a, supervisor(dc), do_wrpstate) 3507 3508 static void do_wrtl(DisasContext *dc, TCGv src) 3509 { 3510 save_state(dc); 3511 tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(tl)); 3512 dc->npc = DYNAMIC_PC; 3513 } 3514 3515 TRANS(WRPR_tl, 64, do_wr_special, a, supervisor(dc), do_wrtl) 3516 3517 static void do_wrpil(DisasContext *dc, TCGv src) 3518 { 3519 if (translator_io_start(&dc->base)) { 3520 dc->base.is_jmp = DISAS_EXIT; 3521 } 3522 gen_helper_wrpil(tcg_env, src); 3523 } 3524 3525 TRANS(WRPR_pil, 64, do_wr_special, a, supervisor(dc), do_wrpil) 3526 3527 static void do_wrcwp(DisasContext *dc, TCGv src) 3528 { 3529 gen_helper_wrcwp(tcg_env, src); 3530 } 3531 3532 TRANS(WRPR_cwp, 64, do_wr_special, a, supervisor(dc), do_wrcwp) 3533 3534 static void do_wrcansave(DisasContext *dc, TCGv src) 3535 { 3536 tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(cansave)); 3537 } 3538 3539 TRANS(WRPR_cansave, 64, do_wr_special, a, supervisor(dc), do_wrcansave) 3540 3541 static void do_wrcanrestore(DisasContext *dc, TCGv src) 3542 { 3543 tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(canrestore)); 3544 } 3545 3546 TRANS(WRPR_canrestore, 64, do_wr_special, a, supervisor(dc), do_wrcanrestore) 3547 3548 static void do_wrcleanwin(DisasContext *dc, TCGv src) 3549 { 3550 tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(cleanwin)); 3551 } 3552 3553 TRANS(WRPR_cleanwin, 64, do_wr_special, a, supervisor(dc), do_wrcleanwin) 3554 3555 static void do_wrotherwin(DisasContext *dc, TCGv src) 3556 { 3557 tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(otherwin)); 3558 } 3559 3560 TRANS(WRPR_otherwin, 64, do_wr_special, a, supervisor(dc), do_wrotherwin) 3561 3562 static void do_wrwstate(DisasContext *dc, TCGv src) 3563 { 3564 tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(wstate)); 3565 } 3566 3567 TRANS(WRPR_wstate, 64, do_wr_special, a, supervisor(dc), do_wrwstate) 3568 3569 static void do_wrgl(DisasContext *dc, TCGv src) 3570 { 3571 gen_helper_wrgl(tcg_env, src); 3572 } 3573 3574 TRANS(WRPR_gl, GL, do_wr_special, a, supervisor(dc), do_wrgl) 3575 3576 /* UA2005 strand status */ 3577 static void do_wrssr(DisasContext *dc, TCGv src) 3578 { 3579 tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(ssr)); 3580 } 3581 3582 TRANS(WRPR_strand_status, HYPV, do_wr_special, a, hypervisor(dc), do_wrssr) 3583 3584 TRANS(WRTBR, 32, do_wr_special, a, supervisor(dc), do_wrtba) 3585 3586 static void do_wrhpstate(DisasContext *dc, TCGv src) 3587 { 3588 tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(hpstate)); 3589 dc->base.is_jmp = DISAS_EXIT; 3590 } 3591 3592 TRANS(WRHPR_hpstate, HYPV, do_wr_special, a, hypervisor(dc), do_wrhpstate) 3593 3594 static void do_wrhtstate(DisasContext *dc, TCGv src) 3595 { 3596 TCGv_i32 tl = tcg_temp_new_i32(); 3597 TCGv_ptr tp = tcg_temp_new_ptr(); 3598 3599 tcg_gen_ld_i32(tl, tcg_env, env64_field_offsetof(tl)); 3600 tcg_gen_andi_i32(tl, tl, MAXTL_MASK); 3601 tcg_gen_shli_i32(tl, tl, 3); 3602 tcg_gen_ext_i32_ptr(tp, tl); 3603 tcg_gen_add_ptr(tp, tp, tcg_env); 3604 3605 tcg_gen_st_tl(src, tp, env64_field_offsetof(htstate)); 3606 } 3607 3608 TRANS(WRHPR_htstate, HYPV, do_wr_special, a, hypervisor(dc), do_wrhtstate) 3609 3610 static void do_wrhintp(DisasContext *dc, TCGv src) 3611 { 3612 tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(hintp)); 3613 } 3614 3615 TRANS(WRHPR_hintp, HYPV, do_wr_special, a, hypervisor(dc), do_wrhintp) 3616 3617 static void do_wrhtba(DisasContext *dc, TCGv src) 3618 { 3619 tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(htba)); 3620 } 3621 3622 TRANS(WRHPR_htba, HYPV, do_wr_special, a, hypervisor(dc), do_wrhtba) 3623 3624 static void do_wrhstick_cmpr(DisasContext *dc, TCGv src) 3625 { 3626 TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 3627 3628 tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(hstick_cmpr)); 3629 tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(hstick)); 3630 translator_io_start(&dc->base); 3631 gen_helper_tick_set_limit(r_tickptr, src); 3632 /* End TB to handle timer interrupt */ 3633 dc->base.is_jmp = DISAS_EXIT; 3634 } 3635 3636 TRANS(WRHPR_hstick_cmpr, HYPV, do_wr_special, a, hypervisor(dc), 3637 do_wrhstick_cmpr) 3638 3639 static bool do_saved_restored(DisasContext *dc, bool saved) 3640 { 3641 if (!supervisor(dc)) { 3642 return raise_priv(dc); 3643 } 3644 if (saved) { 3645 gen_helper_saved(tcg_env); 3646 } else { 3647 gen_helper_restored(tcg_env); 3648 } 3649 return advance_pc(dc); 3650 } 3651 3652 TRANS(SAVED, 64, do_saved_restored, true) 3653 TRANS(RESTORED, 64, do_saved_restored, false) 3654 3655 static bool trans_NOP(DisasContext *dc, arg_NOP *a) 3656 { 3657 return advance_pc(dc); 3658 } 3659 3660 /* 3661 * TODO: Need a feature bit for sparcv8. 3662 * In the meantime, treat all 32-bit cpus like sparcv7. 3663 */ 3664 TRANS(NOP_v7, 32, trans_NOP, a) 3665 TRANS(NOP_v9, 64, trans_NOP, a) 3666 3667 static bool do_arith_int(DisasContext *dc, arg_r_r_ri_cc *a, 3668 void (*func)(TCGv, TCGv, TCGv), 3669 void (*funci)(TCGv, TCGv, target_long), 3670 bool logic_cc) 3671 { 3672 TCGv dst, src1; 3673 3674 /* For simplicity, we under-decoded the rs2 form. */ 3675 if (!a->imm && a->rs2_or_imm & ~0x1f) { 3676 return false; 3677 } 3678 3679 if (logic_cc) { 3680 dst = cpu_cc_N; 3681 } else { 3682 dst = gen_dest_gpr(dc, a->rd); 3683 } 3684 src1 = gen_load_gpr(dc, a->rs1); 3685 3686 if (a->imm || a->rs2_or_imm == 0) { 3687 if (funci) { 3688 funci(dst, src1, a->rs2_or_imm); 3689 } else { 3690 func(dst, src1, tcg_constant_tl(a->rs2_or_imm)); 3691 } 3692 } else { 3693 func(dst, src1, cpu_regs[a->rs2_or_imm]); 3694 } 3695 3696 if (logic_cc) { 3697 if (TARGET_LONG_BITS == 64) { 3698 tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N); 3699 tcg_gen_movi_tl(cpu_icc_C, 0); 3700 } 3701 tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N); 3702 tcg_gen_movi_tl(cpu_cc_C, 0); 3703 tcg_gen_movi_tl(cpu_cc_V, 0); 3704 } 3705 3706 gen_store_gpr(dc, a->rd, dst); 3707 return advance_pc(dc); 3708 } 3709 3710 static bool do_arith(DisasContext *dc, arg_r_r_ri_cc *a, 3711 void (*func)(TCGv, TCGv, TCGv), 3712 void (*funci)(TCGv, TCGv, target_long), 3713 void (*func_cc)(TCGv, TCGv, TCGv)) 3714 { 3715 if (a->cc) { 3716 return do_arith_int(dc, a, func_cc, NULL, false); 3717 } 3718 return do_arith_int(dc, a, func, funci, false); 3719 } 3720 3721 static bool do_logic(DisasContext *dc, arg_r_r_ri_cc *a, 3722 void (*func)(TCGv, TCGv, TCGv), 3723 void (*funci)(TCGv, TCGv, target_long)) 3724 { 3725 return do_arith_int(dc, a, func, funci, a->cc); 3726 } 3727 3728 TRANS(ADD, ALL, do_arith, a, tcg_gen_add_tl, tcg_gen_addi_tl, gen_op_addcc) 3729 TRANS(SUB, ALL, do_arith, a, tcg_gen_sub_tl, tcg_gen_subi_tl, gen_op_subcc) 3730 TRANS(ADDC, ALL, do_arith, a, gen_op_addc, NULL, gen_op_addccc) 3731 TRANS(SUBC, ALL, do_arith, a, gen_op_subc, NULL, gen_op_subccc) 3732 3733 TRANS(TADDcc, ALL, do_arith, a, NULL, NULL, gen_op_taddcc) 3734 TRANS(TSUBcc, ALL, do_arith, a, NULL, NULL, gen_op_tsubcc) 3735 TRANS(TADDccTV, ALL, do_arith, a, NULL, NULL, gen_op_taddcctv) 3736 TRANS(TSUBccTV, ALL, do_arith, a, NULL, NULL, gen_op_tsubcctv) 3737 3738 TRANS(AND, ALL, do_logic, a, tcg_gen_and_tl, tcg_gen_andi_tl) 3739 TRANS(XOR, ALL, do_logic, a, tcg_gen_xor_tl, tcg_gen_xori_tl) 3740 TRANS(ANDN, ALL, do_logic, a, tcg_gen_andc_tl, NULL) 3741 TRANS(ORN, ALL, do_logic, a, tcg_gen_orc_tl, NULL) 3742 TRANS(XORN, ALL, do_logic, a, tcg_gen_eqv_tl, NULL) 3743 3744 TRANS(MULX, 64, do_arith, a, tcg_gen_mul_tl, tcg_gen_muli_tl, NULL) 3745 TRANS(UMUL, MUL, do_logic, a, gen_op_umul, NULL) 3746 TRANS(SMUL, MUL, do_logic, a, gen_op_smul, NULL) 3747 TRANS(MULScc, ALL, do_arith, a, NULL, NULL, gen_op_mulscc) 3748 3749 TRANS(UDIVcc, DIV, do_arith, a, NULL, NULL, gen_op_udivcc) 3750 TRANS(SDIV, DIV, do_arith, a, gen_op_sdiv, NULL, gen_op_sdivcc) 3751 3752 /* TODO: Should have feature bit -- comes in with UltraSparc T2. */ 3753 TRANS(POPC, 64, do_arith, a, gen_op_popc, NULL, NULL) 3754 3755 static bool trans_OR(DisasContext *dc, arg_r_r_ri_cc *a) 3756 { 3757 /* OR with %g0 is the canonical alias for MOV. */ 3758 if (!a->cc && a->rs1 == 0) { 3759 if (a->imm || a->rs2_or_imm == 0) { 3760 gen_store_gpr(dc, a->rd, tcg_constant_tl(a->rs2_or_imm)); 3761 } else if (a->rs2_or_imm & ~0x1f) { 3762 /* For simplicity, we under-decoded the rs2 form. */ 3763 return false; 3764 } else { 3765 gen_store_gpr(dc, a->rd, cpu_regs[a->rs2_or_imm]); 3766 } 3767 return advance_pc(dc); 3768 } 3769 return do_logic(dc, a, tcg_gen_or_tl, tcg_gen_ori_tl); 3770 } 3771 3772 static bool trans_UDIV(DisasContext *dc, arg_r_r_ri *a) 3773 { 3774 TCGv_i64 t1, t2; 3775 TCGv dst; 3776 3777 if (!avail_DIV(dc)) { 3778 return false; 3779 } 3780 /* For simplicity, we under-decoded the rs2 form. */ 3781 if (!a->imm && a->rs2_or_imm & ~0x1f) { 3782 return false; 3783 } 3784 3785 if (unlikely(a->rs2_or_imm == 0)) { 3786 gen_exception(dc, TT_DIV_ZERO); 3787 return true; 3788 } 3789 3790 if (a->imm) { 3791 t2 = tcg_constant_i64((uint32_t)a->rs2_or_imm); 3792 } else { 3793 TCGLabel *lab; 3794 TCGv_i32 n2; 3795 3796 finishing_insn(dc); 3797 flush_cond(dc); 3798 3799 n2 = tcg_temp_new_i32(); 3800 tcg_gen_trunc_tl_i32(n2, cpu_regs[a->rs2_or_imm]); 3801 3802 lab = delay_exception(dc, TT_DIV_ZERO); 3803 tcg_gen_brcondi_i32(TCG_COND_EQ, n2, 0, lab); 3804 3805 t2 = tcg_temp_new_i64(); 3806 #ifdef TARGET_SPARC64 3807 tcg_gen_ext32u_i64(t2, cpu_regs[a->rs2_or_imm]); 3808 #else 3809 tcg_gen_extu_i32_i64(t2, cpu_regs[a->rs2_or_imm]); 3810 #endif 3811 } 3812 3813 t1 = tcg_temp_new_i64(); 3814 tcg_gen_concat_tl_i64(t1, gen_load_gpr(dc, a->rs1), cpu_y); 3815 3816 tcg_gen_divu_i64(t1, t1, t2); 3817 tcg_gen_umin_i64(t1, t1, tcg_constant_i64(UINT32_MAX)); 3818 3819 dst = gen_dest_gpr(dc, a->rd); 3820 tcg_gen_trunc_i64_tl(dst, t1); 3821 gen_store_gpr(dc, a->rd, dst); 3822 return advance_pc(dc); 3823 } 3824 3825 static bool trans_UDIVX(DisasContext *dc, arg_r_r_ri *a) 3826 { 3827 TCGv dst, src1, src2; 3828 3829 if (!avail_64(dc)) { 3830 return false; 3831 } 3832 /* For simplicity, we under-decoded the rs2 form. */ 3833 if (!a->imm && a->rs2_or_imm & ~0x1f) { 3834 return false; 3835 } 3836 3837 if (unlikely(a->rs2_or_imm == 0)) { 3838 gen_exception(dc, TT_DIV_ZERO); 3839 return true; 3840 } 3841 3842 if (a->imm) { 3843 src2 = tcg_constant_tl(a->rs2_or_imm); 3844 } else { 3845 TCGLabel *lab; 3846 3847 finishing_insn(dc); 3848 flush_cond(dc); 3849 3850 lab = delay_exception(dc, TT_DIV_ZERO); 3851 src2 = cpu_regs[a->rs2_or_imm]; 3852 tcg_gen_brcondi_tl(TCG_COND_EQ, src2, 0, lab); 3853 } 3854 3855 dst = gen_dest_gpr(dc, a->rd); 3856 src1 = gen_load_gpr(dc, a->rs1); 3857 3858 tcg_gen_divu_tl(dst, src1, src2); 3859 gen_store_gpr(dc, a->rd, dst); 3860 return advance_pc(dc); 3861 } 3862 3863 static bool trans_SDIVX(DisasContext *dc, arg_r_r_ri *a) 3864 { 3865 TCGv dst, src1, src2; 3866 3867 if (!avail_64(dc)) { 3868 return false; 3869 } 3870 /* For simplicity, we under-decoded the rs2 form. */ 3871 if (!a->imm && a->rs2_or_imm & ~0x1f) { 3872 return false; 3873 } 3874 3875 if (unlikely(a->rs2_or_imm == 0)) { 3876 gen_exception(dc, TT_DIV_ZERO); 3877 return true; 3878 } 3879 3880 dst = gen_dest_gpr(dc, a->rd); 3881 src1 = gen_load_gpr(dc, a->rs1); 3882 3883 if (a->imm) { 3884 if (unlikely(a->rs2_or_imm == -1)) { 3885 tcg_gen_neg_tl(dst, src1); 3886 gen_store_gpr(dc, a->rd, dst); 3887 return advance_pc(dc); 3888 } 3889 src2 = tcg_constant_tl(a->rs2_or_imm); 3890 } else { 3891 TCGLabel *lab; 3892 TCGv t1, t2; 3893 3894 finishing_insn(dc); 3895 flush_cond(dc); 3896 3897 lab = delay_exception(dc, TT_DIV_ZERO); 3898 src2 = cpu_regs[a->rs2_or_imm]; 3899 tcg_gen_brcondi_tl(TCG_COND_EQ, src2, 0, lab); 3900 3901 /* 3902 * Need to avoid INT64_MIN / -1, which will trap on x86 host. 3903 * Set SRC2 to 1 as a new divisor, to produce the correct result. 3904 */ 3905 t1 = tcg_temp_new(); 3906 t2 = tcg_temp_new(); 3907 tcg_gen_setcondi_tl(TCG_COND_EQ, t1, src1, (target_long)INT64_MIN); 3908 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, src2, -1); 3909 tcg_gen_and_tl(t1, t1, t2); 3910 tcg_gen_movcond_tl(TCG_COND_NE, t1, t1, tcg_constant_tl(0), 3911 tcg_constant_tl(1), src2); 3912 src2 = t1; 3913 } 3914 3915 tcg_gen_div_tl(dst, src1, src2); 3916 gen_store_gpr(dc, a->rd, dst); 3917 return advance_pc(dc); 3918 } 3919 3920 static bool gen_edge(DisasContext *dc, arg_r_r_r *a, 3921 int width, bool cc, bool little_endian) 3922 { 3923 TCGv dst, s1, s2, l, r, t, m; 3924 uint64_t amask = address_mask_i(dc, -8); 3925 3926 dst = gen_dest_gpr(dc, a->rd); 3927 s1 = gen_load_gpr(dc, a->rs1); 3928 s2 = gen_load_gpr(dc, a->rs2); 3929 3930 if (cc) { 3931 gen_op_subcc(cpu_cc_N, s1, s2); 3932 } 3933 3934 l = tcg_temp_new(); 3935 r = tcg_temp_new(); 3936 t = tcg_temp_new(); 3937 3938 switch (width) { 3939 case 8: 3940 tcg_gen_andi_tl(l, s1, 7); 3941 tcg_gen_andi_tl(r, s2, 7); 3942 tcg_gen_xori_tl(r, r, 7); 3943 m = tcg_constant_tl(0xff); 3944 break; 3945 case 16: 3946 tcg_gen_extract_tl(l, s1, 1, 2); 3947 tcg_gen_extract_tl(r, s2, 1, 2); 3948 tcg_gen_xori_tl(r, r, 3); 3949 m = tcg_constant_tl(0xf); 3950 break; 3951 case 32: 3952 tcg_gen_extract_tl(l, s1, 2, 1); 3953 tcg_gen_extract_tl(r, s2, 2, 1); 3954 tcg_gen_xori_tl(r, r, 1); 3955 m = tcg_constant_tl(0x3); 3956 break; 3957 default: 3958 abort(); 3959 } 3960 3961 /* Compute Left Edge */ 3962 if (little_endian) { 3963 tcg_gen_shl_tl(l, m, l); 3964 tcg_gen_and_tl(l, l, m); 3965 } else { 3966 tcg_gen_shr_tl(l, m, l); 3967 } 3968 /* Compute Right Edge */ 3969 if (little_endian) { 3970 tcg_gen_shr_tl(r, m, r); 3971 } else { 3972 tcg_gen_shl_tl(r, m, r); 3973 tcg_gen_and_tl(r, r, m); 3974 } 3975 3976 /* Compute dst = (s1 == s2 under amask ? l : l & r) */ 3977 tcg_gen_xor_tl(t, s1, s2); 3978 tcg_gen_and_tl(r, r, l); 3979 tcg_gen_movcond_tl(TCG_COND_TSTEQ, dst, t, tcg_constant_tl(amask), r, l); 3980 3981 gen_store_gpr(dc, a->rd, dst); 3982 return advance_pc(dc); 3983 } 3984 3985 TRANS(EDGE8cc, VIS1, gen_edge, a, 8, 1, 0) 3986 TRANS(EDGE8Lcc, VIS1, gen_edge, a, 8, 1, 1) 3987 TRANS(EDGE16cc, VIS1, gen_edge, a, 16, 1, 0) 3988 TRANS(EDGE16Lcc, VIS1, gen_edge, a, 16, 1, 1) 3989 TRANS(EDGE32cc, VIS1, gen_edge, a, 32, 1, 0) 3990 TRANS(EDGE32Lcc, VIS1, gen_edge, a, 32, 1, 1) 3991 3992 TRANS(EDGE8N, VIS2, gen_edge, a, 8, 0, 0) 3993 TRANS(EDGE8LN, VIS2, gen_edge, a, 8, 0, 1) 3994 TRANS(EDGE16N, VIS2, gen_edge, a, 16, 0, 0) 3995 TRANS(EDGE16LN, VIS2, gen_edge, a, 16, 0, 1) 3996 TRANS(EDGE32N, VIS2, gen_edge, a, 32, 0, 0) 3997 TRANS(EDGE32LN, VIS2, gen_edge, a, 32, 0, 1) 3998 3999 static bool do_rr(DisasContext *dc, arg_r_r *a, 4000 void (*func)(TCGv, TCGv)) 4001 { 4002 TCGv dst = gen_dest_gpr(dc, a->rd); 4003 TCGv src = gen_load_gpr(dc, a->rs); 4004 4005 func(dst, src); 4006 gen_store_gpr(dc, a->rd, dst); 4007 return advance_pc(dc); 4008 } 4009 4010 TRANS(LZCNT, VIS3, do_rr, a, gen_op_lzcnt) 4011 4012 static bool do_rrr(DisasContext *dc, arg_r_r_r *a, 4013 void (*func)(TCGv, TCGv, TCGv)) 4014 { 4015 TCGv dst = gen_dest_gpr(dc, a->rd); 4016 TCGv src1 = gen_load_gpr(dc, a->rs1); 4017 TCGv src2 = gen_load_gpr(dc, a->rs2); 4018 4019 func(dst, src1, src2); 4020 gen_store_gpr(dc, a->rd, dst); 4021 return advance_pc(dc); 4022 } 4023 4024 TRANS(ARRAY8, VIS1, do_rrr, a, gen_helper_array8) 4025 TRANS(ARRAY16, VIS1, do_rrr, a, gen_op_array16) 4026 TRANS(ARRAY32, VIS1, do_rrr, a, gen_op_array32) 4027 4028 TRANS(ADDXC, VIS3, do_rrr, a, gen_op_addxc) 4029 TRANS(ADDXCcc, VIS3, do_rrr, a, gen_op_addxccc) 4030 4031 TRANS(SUBXC, VIS4, do_rrr, a, gen_op_subxc) 4032 TRANS(SUBXCcc, VIS4, do_rrr, a, gen_op_subxccc) 4033 4034 TRANS(UMULXHI, VIS3, do_rrr, a, gen_op_umulxhi) 4035 4036 static void gen_op_alignaddr(TCGv dst, TCGv s1, TCGv s2) 4037 { 4038 #ifdef TARGET_SPARC64 4039 TCGv tmp = tcg_temp_new(); 4040 4041 tcg_gen_add_tl(tmp, s1, s2); 4042 tcg_gen_andi_tl(dst, tmp, -8); 4043 tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, tmp, 0, 3); 4044 #else 4045 g_assert_not_reached(); 4046 #endif 4047 } 4048 4049 static void gen_op_alignaddrl(TCGv dst, TCGv s1, TCGv s2) 4050 { 4051 #ifdef TARGET_SPARC64 4052 TCGv tmp = tcg_temp_new(); 4053 4054 tcg_gen_add_tl(tmp, s1, s2); 4055 tcg_gen_andi_tl(dst, tmp, -8); 4056 tcg_gen_neg_tl(tmp, tmp); 4057 tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, tmp, 0, 3); 4058 #else 4059 g_assert_not_reached(); 4060 #endif 4061 } 4062 4063 TRANS(ALIGNADDR, VIS1, do_rrr, a, gen_op_alignaddr) 4064 TRANS(ALIGNADDRL, VIS1, do_rrr, a, gen_op_alignaddrl) 4065 4066 static void gen_op_bmask(TCGv dst, TCGv s1, TCGv s2) 4067 { 4068 #ifdef TARGET_SPARC64 4069 tcg_gen_add_tl(dst, s1, s2); 4070 tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, dst, 32, 32); 4071 #else 4072 g_assert_not_reached(); 4073 #endif 4074 } 4075 4076 TRANS(BMASK, VIS2, do_rrr, a, gen_op_bmask) 4077 4078 static bool do_cmask(DisasContext *dc, int rs2, void (*func)(TCGv, TCGv, TCGv)) 4079 { 4080 func(cpu_gsr, cpu_gsr, gen_load_gpr(dc, rs2)); 4081 return true; 4082 } 4083 4084 TRANS(CMASK8, VIS3, do_cmask, a->rs2, gen_helper_cmask8) 4085 TRANS(CMASK16, VIS3, do_cmask, a->rs2, gen_helper_cmask16) 4086 TRANS(CMASK32, VIS3, do_cmask, a->rs2, gen_helper_cmask32) 4087 4088 static bool do_shift_r(DisasContext *dc, arg_shiftr *a, bool l, bool u) 4089 { 4090 TCGv dst, src1, src2; 4091 4092 /* Reject 64-bit shifts for sparc32. */ 4093 if (avail_32(dc) && a->x) { 4094 return false; 4095 } 4096 4097 src2 = tcg_temp_new(); 4098 tcg_gen_andi_tl(src2, gen_load_gpr(dc, a->rs2), a->x ? 63 : 31); 4099 src1 = gen_load_gpr(dc, a->rs1); 4100 dst = gen_dest_gpr(dc, a->rd); 4101 4102 if (l) { 4103 tcg_gen_shl_tl(dst, src1, src2); 4104 if (!a->x) { 4105 tcg_gen_ext32u_tl(dst, dst); 4106 } 4107 } else if (u) { 4108 if (!a->x) { 4109 tcg_gen_ext32u_tl(dst, src1); 4110 src1 = dst; 4111 } 4112 tcg_gen_shr_tl(dst, src1, src2); 4113 } else { 4114 if (!a->x) { 4115 tcg_gen_ext32s_tl(dst, src1); 4116 src1 = dst; 4117 } 4118 tcg_gen_sar_tl(dst, src1, src2); 4119 } 4120 gen_store_gpr(dc, a->rd, dst); 4121 return advance_pc(dc); 4122 } 4123 4124 TRANS(SLL_r, ALL, do_shift_r, a, true, true) 4125 TRANS(SRL_r, ALL, do_shift_r, a, false, true) 4126 TRANS(SRA_r, ALL, do_shift_r, a, false, false) 4127 4128 static bool do_shift_i(DisasContext *dc, arg_shifti *a, bool l, bool u) 4129 { 4130 TCGv dst, src1; 4131 4132 /* Reject 64-bit shifts for sparc32. */ 4133 if (avail_32(dc) && (a->x || a->i >= 32)) { 4134 return false; 4135 } 4136 4137 src1 = gen_load_gpr(dc, a->rs1); 4138 dst = gen_dest_gpr(dc, a->rd); 4139 4140 if (avail_32(dc) || a->x) { 4141 if (l) { 4142 tcg_gen_shli_tl(dst, src1, a->i); 4143 } else if (u) { 4144 tcg_gen_shri_tl(dst, src1, a->i); 4145 } else { 4146 tcg_gen_sari_tl(dst, src1, a->i); 4147 } 4148 } else { 4149 if (l) { 4150 tcg_gen_deposit_z_tl(dst, src1, a->i, 32 - a->i); 4151 } else if (u) { 4152 tcg_gen_extract_tl(dst, src1, a->i, 32 - a->i); 4153 } else { 4154 tcg_gen_sextract_tl(dst, src1, a->i, 32 - a->i); 4155 } 4156 } 4157 gen_store_gpr(dc, a->rd, dst); 4158 return advance_pc(dc); 4159 } 4160 4161 TRANS(SLL_i, ALL, do_shift_i, a, true, true) 4162 TRANS(SRL_i, ALL, do_shift_i, a, false, true) 4163 TRANS(SRA_i, ALL, do_shift_i, a, false, false) 4164 4165 static TCGv gen_rs2_or_imm(DisasContext *dc, bool imm, int rs2_or_imm) 4166 { 4167 /* For simplicity, we under-decoded the rs2 form. */ 4168 if (!imm && rs2_or_imm & ~0x1f) { 4169 return NULL; 4170 } 4171 if (imm || rs2_or_imm == 0) { 4172 return tcg_constant_tl(rs2_or_imm); 4173 } else { 4174 return cpu_regs[rs2_or_imm]; 4175 } 4176 } 4177 4178 static bool do_mov_cond(DisasContext *dc, DisasCompare *cmp, int rd, TCGv src2) 4179 { 4180 TCGv dst = gen_load_gpr(dc, rd); 4181 TCGv c2 = tcg_constant_tl(cmp->c2); 4182 4183 tcg_gen_movcond_tl(cmp->cond, dst, cmp->c1, c2, src2, dst); 4184 gen_store_gpr(dc, rd, dst); 4185 return advance_pc(dc); 4186 } 4187 4188 static bool trans_MOVcc(DisasContext *dc, arg_MOVcc *a) 4189 { 4190 TCGv src2 = gen_rs2_or_imm(dc, a->imm, a->rs2_or_imm); 4191 DisasCompare cmp; 4192 4193 if (src2 == NULL) { 4194 return false; 4195 } 4196 gen_compare(&cmp, a->cc, a->cond, dc); 4197 return do_mov_cond(dc, &cmp, a->rd, src2); 4198 } 4199 4200 static bool trans_MOVfcc(DisasContext *dc, arg_MOVfcc *a) 4201 { 4202 TCGv src2 = gen_rs2_or_imm(dc, a->imm, a->rs2_or_imm); 4203 DisasCompare cmp; 4204 4205 if (src2 == NULL) { 4206 return false; 4207 } 4208 gen_fcompare(&cmp, a->cc, a->cond); 4209 return do_mov_cond(dc, &cmp, a->rd, src2); 4210 } 4211 4212 static bool trans_MOVR(DisasContext *dc, arg_MOVR *a) 4213 { 4214 TCGv src2 = gen_rs2_or_imm(dc, a->imm, a->rs2_or_imm); 4215 DisasCompare cmp; 4216 4217 if (src2 == NULL) { 4218 return false; 4219 } 4220 if (!gen_compare_reg(&cmp, a->cond, gen_load_gpr(dc, a->rs1))) { 4221 return false; 4222 } 4223 return do_mov_cond(dc, &cmp, a->rd, src2); 4224 } 4225 4226 static bool do_add_special(DisasContext *dc, arg_r_r_ri *a, 4227 bool (*func)(DisasContext *dc, int rd, TCGv src)) 4228 { 4229 TCGv src1, sum; 4230 4231 /* For simplicity, we under-decoded the rs2 form. */ 4232 if (!a->imm && a->rs2_or_imm & ~0x1f) { 4233 return false; 4234 } 4235 4236 /* 4237 * Always load the sum into a new temporary. 4238 * This is required to capture the value across a window change, 4239 * e.g. SAVE and RESTORE, and may be optimized away otherwise. 4240 */ 4241 sum = tcg_temp_new(); 4242 src1 = gen_load_gpr(dc, a->rs1); 4243 if (a->imm || a->rs2_or_imm == 0) { 4244 tcg_gen_addi_tl(sum, src1, a->rs2_or_imm); 4245 } else { 4246 tcg_gen_add_tl(sum, src1, cpu_regs[a->rs2_or_imm]); 4247 } 4248 return func(dc, a->rd, sum); 4249 } 4250 4251 static bool do_jmpl(DisasContext *dc, int rd, TCGv src) 4252 { 4253 /* 4254 * Preserve pc across advance, so that we can delay 4255 * the writeback to rd until after src is consumed. 4256 */ 4257 target_ulong cur_pc = dc->pc; 4258 4259 gen_check_align(dc, src, 3); 4260 4261 gen_mov_pc_npc(dc); 4262 tcg_gen_mov_tl(cpu_npc, src); 4263 gen_address_mask(dc, cpu_npc); 4264 gen_store_gpr(dc, rd, tcg_constant_tl(cur_pc)); 4265 4266 dc->npc = DYNAMIC_PC_LOOKUP; 4267 return true; 4268 } 4269 4270 TRANS(JMPL, ALL, do_add_special, a, do_jmpl) 4271 4272 static bool do_rett(DisasContext *dc, int rd, TCGv src) 4273 { 4274 if (!supervisor(dc)) { 4275 return raise_priv(dc); 4276 } 4277 4278 gen_check_align(dc, src, 3); 4279 4280 gen_mov_pc_npc(dc); 4281 tcg_gen_mov_tl(cpu_npc, src); 4282 gen_helper_rett(tcg_env); 4283 4284 dc->npc = DYNAMIC_PC; 4285 return true; 4286 } 4287 4288 TRANS(RETT, 32, do_add_special, a, do_rett) 4289 4290 static bool do_return(DisasContext *dc, int rd, TCGv src) 4291 { 4292 gen_check_align(dc, src, 3); 4293 gen_helper_restore(tcg_env); 4294 4295 gen_mov_pc_npc(dc); 4296 tcg_gen_mov_tl(cpu_npc, src); 4297 gen_address_mask(dc, cpu_npc); 4298 4299 dc->npc = DYNAMIC_PC_LOOKUP; 4300 return true; 4301 } 4302 4303 TRANS(RETURN, 64, do_add_special, a, do_return) 4304 4305 static bool do_save(DisasContext *dc, int rd, TCGv src) 4306 { 4307 gen_helper_save(tcg_env); 4308 gen_store_gpr(dc, rd, src); 4309 return advance_pc(dc); 4310 } 4311 4312 TRANS(SAVE, ALL, do_add_special, a, do_save) 4313 4314 static bool do_restore(DisasContext *dc, int rd, TCGv src) 4315 { 4316 gen_helper_restore(tcg_env); 4317 gen_store_gpr(dc, rd, src); 4318 return advance_pc(dc); 4319 } 4320 4321 TRANS(RESTORE, ALL, do_add_special, a, do_restore) 4322 4323 static bool do_done_retry(DisasContext *dc, bool done) 4324 { 4325 if (!supervisor(dc)) { 4326 return raise_priv(dc); 4327 } 4328 dc->npc = DYNAMIC_PC; 4329 dc->pc = DYNAMIC_PC; 4330 translator_io_start(&dc->base); 4331 if (done) { 4332 gen_helper_done(tcg_env); 4333 } else { 4334 gen_helper_retry(tcg_env); 4335 } 4336 return true; 4337 } 4338 4339 TRANS(DONE, 64, do_done_retry, true) 4340 TRANS(RETRY, 64, do_done_retry, false) 4341 4342 /* 4343 * Major opcode 11 -- load and store instructions 4344 */ 4345 4346 static TCGv gen_ldst_addr(DisasContext *dc, int rs1, bool imm, int rs2_or_imm) 4347 { 4348 TCGv addr, tmp = NULL; 4349 4350 /* For simplicity, we under-decoded the rs2 form. */ 4351 if (!imm && rs2_or_imm & ~0x1f) { 4352 return NULL; 4353 } 4354 4355 addr = gen_load_gpr(dc, rs1); 4356 if (rs2_or_imm) { 4357 tmp = tcg_temp_new(); 4358 if (imm) { 4359 tcg_gen_addi_tl(tmp, addr, rs2_or_imm); 4360 } else { 4361 tcg_gen_add_tl(tmp, addr, cpu_regs[rs2_or_imm]); 4362 } 4363 addr = tmp; 4364 } 4365 if (AM_CHECK(dc)) { 4366 if (!tmp) { 4367 tmp = tcg_temp_new(); 4368 } 4369 tcg_gen_ext32u_tl(tmp, addr); 4370 addr = tmp; 4371 } 4372 return addr; 4373 } 4374 4375 static bool do_ld_gpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp mop) 4376 { 4377 TCGv reg, addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 4378 DisasASI da; 4379 4380 if (addr == NULL) { 4381 return false; 4382 } 4383 da = resolve_asi(dc, a->asi, mop); 4384 4385 reg = gen_dest_gpr(dc, a->rd); 4386 gen_ld_asi(dc, &da, reg, addr); 4387 gen_store_gpr(dc, a->rd, reg); 4388 return advance_pc(dc); 4389 } 4390 4391 TRANS(LDUW, ALL, do_ld_gpr, a, MO_TEUL) 4392 TRANS(LDUB, ALL, do_ld_gpr, a, MO_UB) 4393 TRANS(LDUH, ALL, do_ld_gpr, a, MO_TEUW) 4394 TRANS(LDSB, ALL, do_ld_gpr, a, MO_SB) 4395 TRANS(LDSH, ALL, do_ld_gpr, a, MO_TESW) 4396 TRANS(LDSW, 64, do_ld_gpr, a, MO_TESL) 4397 TRANS(LDX, 64, do_ld_gpr, a, MO_TEUQ) 4398 4399 static bool do_st_gpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp mop) 4400 { 4401 TCGv reg, addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 4402 DisasASI da; 4403 4404 if (addr == NULL) { 4405 return false; 4406 } 4407 da = resolve_asi(dc, a->asi, mop); 4408 4409 reg = gen_load_gpr(dc, a->rd); 4410 gen_st_asi(dc, &da, reg, addr); 4411 return advance_pc(dc); 4412 } 4413 4414 TRANS(STW, ALL, do_st_gpr, a, MO_TEUL) 4415 TRANS(STB, ALL, do_st_gpr, a, MO_UB) 4416 TRANS(STH, ALL, do_st_gpr, a, MO_TEUW) 4417 TRANS(STX, 64, do_st_gpr, a, MO_TEUQ) 4418 4419 static bool trans_LDD(DisasContext *dc, arg_r_r_ri_asi *a) 4420 { 4421 TCGv addr; 4422 DisasASI da; 4423 4424 if (a->rd & 1) { 4425 return false; 4426 } 4427 addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 4428 if (addr == NULL) { 4429 return false; 4430 } 4431 da = resolve_asi(dc, a->asi, MO_TEUQ); 4432 gen_ldda_asi(dc, &da, addr, a->rd); 4433 return advance_pc(dc); 4434 } 4435 4436 static bool trans_STD(DisasContext *dc, arg_r_r_ri_asi *a) 4437 { 4438 TCGv addr; 4439 DisasASI da; 4440 4441 if (a->rd & 1) { 4442 return false; 4443 } 4444 addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 4445 if (addr == NULL) { 4446 return false; 4447 } 4448 da = resolve_asi(dc, a->asi, MO_TEUQ); 4449 gen_stda_asi(dc, &da, addr, a->rd); 4450 return advance_pc(dc); 4451 } 4452 4453 static bool trans_LDSTUB(DisasContext *dc, arg_r_r_ri_asi *a) 4454 { 4455 TCGv addr, reg; 4456 DisasASI da; 4457 4458 addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 4459 if (addr == NULL) { 4460 return false; 4461 } 4462 da = resolve_asi(dc, a->asi, MO_UB); 4463 4464 reg = gen_dest_gpr(dc, a->rd); 4465 gen_ldstub_asi(dc, &da, reg, addr); 4466 gen_store_gpr(dc, a->rd, reg); 4467 return advance_pc(dc); 4468 } 4469 4470 static bool trans_SWAP(DisasContext *dc, arg_r_r_ri_asi *a) 4471 { 4472 TCGv addr, dst, src; 4473 DisasASI da; 4474 4475 addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 4476 if (addr == NULL) { 4477 return false; 4478 } 4479 da = resolve_asi(dc, a->asi, MO_TEUL); 4480 4481 dst = gen_dest_gpr(dc, a->rd); 4482 src = gen_load_gpr(dc, a->rd); 4483 gen_swap_asi(dc, &da, dst, src, addr); 4484 gen_store_gpr(dc, a->rd, dst); 4485 return advance_pc(dc); 4486 } 4487 4488 static bool do_casa(DisasContext *dc, arg_r_r_ri_asi *a, MemOp mop) 4489 { 4490 TCGv addr, o, n, c; 4491 DisasASI da; 4492 4493 addr = gen_ldst_addr(dc, a->rs1, true, 0); 4494 if (addr == NULL) { 4495 return false; 4496 } 4497 da = resolve_asi(dc, a->asi, mop); 4498 4499 o = gen_dest_gpr(dc, a->rd); 4500 n = gen_load_gpr(dc, a->rd); 4501 c = gen_load_gpr(dc, a->rs2_or_imm); 4502 gen_cas_asi(dc, &da, o, n, c, addr); 4503 gen_store_gpr(dc, a->rd, o); 4504 return advance_pc(dc); 4505 } 4506 4507 TRANS(CASA, CASA, do_casa, a, MO_TEUL) 4508 TRANS(CASXA, 64, do_casa, a, MO_TEUQ) 4509 4510 static bool do_ld_fpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp sz) 4511 { 4512 TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 4513 DisasASI da; 4514 4515 if (addr == NULL) { 4516 return false; 4517 } 4518 if (gen_trap_if_nofpu_fpexception(dc)) { 4519 return true; 4520 } 4521 if (sz == MO_128 && gen_trap_float128(dc)) { 4522 return true; 4523 } 4524 da = resolve_asi(dc, a->asi, MO_TE | sz); 4525 gen_ldf_asi(dc, &da, sz, addr, a->rd); 4526 gen_update_fprs_dirty(dc, a->rd); 4527 return advance_pc(dc); 4528 } 4529 4530 TRANS(LDF, ALL, do_ld_fpr, a, MO_32) 4531 TRANS(LDDF, ALL, do_ld_fpr, a, MO_64) 4532 TRANS(LDQF, ALL, do_ld_fpr, a, MO_128) 4533 4534 TRANS(LDFA, 64, do_ld_fpr, a, MO_32) 4535 TRANS(LDDFA, 64, do_ld_fpr, a, MO_64) 4536 TRANS(LDQFA, 64, do_ld_fpr, a, MO_128) 4537 4538 static bool do_st_fpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp sz) 4539 { 4540 TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 4541 DisasASI da; 4542 4543 if (addr == NULL) { 4544 return false; 4545 } 4546 /* Store insns are ok in fp_exception_pending state. */ 4547 if (gen_trap_ifnofpu(dc)) { 4548 return true; 4549 } 4550 if (sz == MO_128 && gen_trap_float128(dc)) { 4551 return true; 4552 } 4553 da = resolve_asi(dc, a->asi, MO_TE | sz); 4554 gen_stf_asi(dc, &da, sz, addr, a->rd); 4555 return advance_pc(dc); 4556 } 4557 4558 TRANS(STF, ALL, do_st_fpr, a, MO_32) 4559 TRANS(STDF, ALL, do_st_fpr, a, MO_64) 4560 TRANS(STQF, 64, do_st_fpr, a, MO_128) 4561 4562 TRANS(STFA, 64, do_st_fpr, a, MO_32) 4563 TRANS(STDFA, 64, do_st_fpr, a, MO_64) 4564 TRANS(STQFA, 64, do_st_fpr, a, MO_128) 4565 4566 static bool trans_STDFQ(DisasContext *dc, arg_STDFQ *a) 4567 { 4568 TCGv addr; 4569 4570 if (!avail_32(dc)) { 4571 return false; 4572 } 4573 addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 4574 if (addr == NULL) { 4575 return false; 4576 } 4577 if (!supervisor(dc)) { 4578 return raise_priv(dc); 4579 } 4580 #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) 4581 if (gen_trap_ifnofpu(dc)) { 4582 return true; 4583 } 4584 if (!dc->fsr_qne) { 4585 gen_op_fpexception_im(dc, FSR_FTT_SEQ_ERROR); 4586 return true; 4587 } 4588 4589 /* Store the single element from the queue. */ 4590 TCGv_i64 fq = tcg_temp_new_i64(); 4591 tcg_gen_ld_i64(fq, tcg_env, offsetof(CPUSPARCState, fq.d)); 4592 tcg_gen_qemu_st_i64(fq, addr, dc->mem_idx, MO_TEUQ | MO_ALIGN_4); 4593 4594 /* Mark the queue empty, transitioning to fp_execute state. */ 4595 tcg_gen_st_i32(tcg_constant_i32(0), tcg_env, 4596 offsetof(CPUSPARCState, fsr_qne)); 4597 dc->fsr_qne = 0; 4598 4599 return advance_pc(dc); 4600 #else 4601 qemu_build_not_reached(); 4602 #endif 4603 } 4604 4605 static bool trans_LDFSR(DisasContext *dc, arg_r_r_ri *a) 4606 { 4607 TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 4608 TCGv_i32 tmp; 4609 4610 if (addr == NULL) { 4611 return false; 4612 } 4613 if (gen_trap_if_nofpu_fpexception(dc)) { 4614 return true; 4615 } 4616 4617 tmp = tcg_temp_new_i32(); 4618 tcg_gen_qemu_ld_i32(tmp, addr, dc->mem_idx, MO_TEUL | MO_ALIGN); 4619 4620 tcg_gen_extract_i32(cpu_fcc[0], tmp, FSR_FCC0_SHIFT, 2); 4621 /* LDFSR does not change FCC[1-3]. */ 4622 4623 gen_helper_set_fsr_nofcc_noftt(tcg_env, tmp); 4624 return advance_pc(dc); 4625 } 4626 4627 static bool do_ldxfsr(DisasContext *dc, arg_r_r_ri *a, bool entire) 4628 { 4629 #ifdef TARGET_SPARC64 4630 TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 4631 TCGv_i64 t64; 4632 TCGv_i32 lo, hi; 4633 4634 if (addr == NULL) { 4635 return false; 4636 } 4637 if (gen_trap_if_nofpu_fpexception(dc)) { 4638 return true; 4639 } 4640 4641 t64 = tcg_temp_new_i64(); 4642 tcg_gen_qemu_ld_i64(t64, addr, dc->mem_idx, MO_TEUQ | MO_ALIGN); 4643 4644 lo = tcg_temp_new_i32(); 4645 hi = cpu_fcc[3]; 4646 tcg_gen_extr_i64_i32(lo, hi, t64); 4647 tcg_gen_extract_i32(cpu_fcc[0], lo, FSR_FCC0_SHIFT, 2); 4648 tcg_gen_extract_i32(cpu_fcc[1], hi, FSR_FCC1_SHIFT - 32, 2); 4649 tcg_gen_extract_i32(cpu_fcc[2], hi, FSR_FCC2_SHIFT - 32, 2); 4650 tcg_gen_extract_i32(cpu_fcc[3], hi, FSR_FCC3_SHIFT - 32, 2); 4651 4652 if (entire) { 4653 gen_helper_set_fsr_nofcc(tcg_env, lo); 4654 } else { 4655 gen_helper_set_fsr_nofcc_noftt(tcg_env, lo); 4656 } 4657 return advance_pc(dc); 4658 #else 4659 return false; 4660 #endif 4661 } 4662 4663 TRANS(LDXFSR, 64, do_ldxfsr, a, false) 4664 TRANS(LDXEFSR, VIS3B, do_ldxfsr, a, true) 4665 4666 static bool do_stfsr(DisasContext *dc, arg_r_r_ri *a, MemOp mop) 4667 { 4668 TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 4669 TCGv fsr; 4670 4671 if (addr == NULL) { 4672 return false; 4673 } 4674 /* Store insns are ok in fp_exception_pending state. */ 4675 if (gen_trap_ifnofpu(dc)) { 4676 return true; 4677 } 4678 4679 fsr = tcg_temp_new(); 4680 gen_helper_get_fsr(fsr, tcg_env); 4681 tcg_gen_qemu_st_tl(fsr, addr, dc->mem_idx, mop | MO_ALIGN); 4682 return advance_pc(dc); 4683 } 4684 4685 TRANS(STFSR, ALL, do_stfsr, a, MO_TEUL) 4686 TRANS(STXFSR, 64, do_stfsr, a, MO_TEUQ) 4687 4688 static bool do_fc(DisasContext *dc, int rd, int32_t c) 4689 { 4690 if (gen_trap_ifnofpu(dc)) { 4691 return true; 4692 } 4693 gen_store_fpr_F(dc, rd, tcg_constant_i32(c)); 4694 return advance_pc(dc); 4695 } 4696 4697 TRANS(FZEROs, VIS1, do_fc, a->rd, 0) 4698 TRANS(FONEs, VIS1, do_fc, a->rd, -1) 4699 4700 static bool do_dc(DisasContext *dc, int rd, int64_t c) 4701 { 4702 if (gen_trap_ifnofpu(dc)) { 4703 return true; 4704 } 4705 gen_store_fpr_D(dc, rd, tcg_constant_i64(c)); 4706 return advance_pc(dc); 4707 } 4708 4709 TRANS(FZEROd, VIS1, do_dc, a->rd, 0) 4710 TRANS(FONEd, VIS1, do_dc, a->rd, -1) 4711 4712 static bool do_ff(DisasContext *dc, arg_r_r *a, 4713 void (*func)(TCGv_i32, TCGv_i32)) 4714 { 4715 TCGv_i32 tmp; 4716 4717 if (gen_trap_if_nofpu_fpexception(dc)) { 4718 return true; 4719 } 4720 4721 tmp = gen_load_fpr_F(dc, a->rs); 4722 func(tmp, tmp); 4723 gen_store_fpr_F(dc, a->rd, tmp); 4724 return advance_pc(dc); 4725 } 4726 4727 TRANS(FMOVs, ALL, do_ff, a, gen_op_fmovs) 4728 TRANS(FNEGs, ALL, do_ff, a, gen_op_fnegs) 4729 TRANS(FABSs, ALL, do_ff, a, gen_op_fabss) 4730 TRANS(FSRCs, VIS1, do_ff, a, tcg_gen_mov_i32) 4731 TRANS(FNOTs, VIS1, do_ff, a, tcg_gen_not_i32) 4732 4733 static bool do_fd(DisasContext *dc, arg_r_r *a, 4734 void (*func)(TCGv_i32, TCGv_i64)) 4735 { 4736 TCGv_i32 dst; 4737 TCGv_i64 src; 4738 4739 if (gen_trap_ifnofpu(dc)) { 4740 return true; 4741 } 4742 4743 dst = tcg_temp_new_i32(); 4744 src = gen_load_fpr_D(dc, a->rs); 4745 func(dst, src); 4746 gen_store_fpr_F(dc, a->rd, dst); 4747 return advance_pc(dc); 4748 } 4749 4750 TRANS(FPACK16, VIS1, do_fd, a, gen_op_fpack16) 4751 TRANS(FPACKFIX, VIS1, do_fd, a, gen_op_fpackfix) 4752 4753 static bool do_env_ff(DisasContext *dc, arg_r_r *a, 4754 void (*func)(TCGv_i32, TCGv_env, TCGv_i32)) 4755 { 4756 TCGv_i32 tmp; 4757 4758 if (gen_trap_if_nofpu_fpexception(dc)) { 4759 return true; 4760 } 4761 4762 tmp = gen_load_fpr_F(dc, a->rs); 4763 func(tmp, tcg_env, tmp); 4764 gen_store_fpr_F(dc, a->rd, tmp); 4765 return advance_pc(dc); 4766 } 4767 4768 TRANS(FSQRTs, ALL, do_env_ff, a, gen_helper_fsqrts) 4769 TRANS(FiTOs, ALL, do_env_ff, a, gen_helper_fitos) 4770 TRANS(FsTOi, ALL, do_env_ff, a, gen_helper_fstoi) 4771 4772 static bool do_env_fd(DisasContext *dc, arg_r_r *a, 4773 void (*func)(TCGv_i32, TCGv_env, TCGv_i64)) 4774 { 4775 TCGv_i32 dst; 4776 TCGv_i64 src; 4777 4778 if (gen_trap_if_nofpu_fpexception(dc)) { 4779 return true; 4780 } 4781 4782 dst = tcg_temp_new_i32(); 4783 src = gen_load_fpr_D(dc, a->rs); 4784 func(dst, tcg_env, src); 4785 gen_store_fpr_F(dc, a->rd, dst); 4786 return advance_pc(dc); 4787 } 4788 4789 TRANS(FdTOs, ALL, do_env_fd, a, gen_helper_fdtos) 4790 TRANS(FdTOi, ALL, do_env_fd, a, gen_helper_fdtoi) 4791 TRANS(FxTOs, 64, do_env_fd, a, gen_helper_fxtos) 4792 4793 static bool do_dd(DisasContext *dc, arg_r_r *a, 4794 void (*func)(TCGv_i64, TCGv_i64)) 4795 { 4796 TCGv_i64 dst, src; 4797 4798 if (gen_trap_if_nofpu_fpexception(dc)) { 4799 return true; 4800 } 4801 4802 dst = tcg_temp_new_i64(); 4803 src = gen_load_fpr_D(dc, a->rs); 4804 func(dst, src); 4805 gen_store_fpr_D(dc, a->rd, dst); 4806 return advance_pc(dc); 4807 } 4808 4809 TRANS(FMOVd, 64, do_dd, a, gen_op_fmovd) 4810 TRANS(FNEGd, 64, do_dd, a, gen_op_fnegd) 4811 TRANS(FABSd, 64, do_dd, a, gen_op_fabsd) 4812 TRANS(FSRCd, VIS1, do_dd, a, tcg_gen_mov_i64) 4813 TRANS(FNOTd, VIS1, do_dd, a, tcg_gen_not_i64) 4814 4815 static bool do_env_dd(DisasContext *dc, arg_r_r *a, 4816 void (*func)(TCGv_i64, TCGv_env, TCGv_i64)) 4817 { 4818 TCGv_i64 dst, src; 4819 4820 if (gen_trap_if_nofpu_fpexception(dc)) { 4821 return true; 4822 } 4823 4824 dst = tcg_temp_new_i64(); 4825 src = gen_load_fpr_D(dc, a->rs); 4826 func(dst, tcg_env, src); 4827 gen_store_fpr_D(dc, a->rd, dst); 4828 return advance_pc(dc); 4829 } 4830 4831 TRANS(FSQRTd, ALL, do_env_dd, a, gen_helper_fsqrtd) 4832 TRANS(FxTOd, 64, do_env_dd, a, gen_helper_fxtod) 4833 TRANS(FdTOx, 64, do_env_dd, a, gen_helper_fdtox) 4834 4835 static bool do_df(DisasContext *dc, arg_r_r *a, 4836 void (*func)(TCGv_i64, TCGv_i32)) 4837 { 4838 TCGv_i64 dst; 4839 TCGv_i32 src; 4840 4841 if (gen_trap_ifnofpu(dc)) { 4842 return true; 4843 } 4844 4845 dst = tcg_temp_new_i64(); 4846 src = gen_load_fpr_F(dc, a->rs); 4847 func(dst, src); 4848 gen_store_fpr_D(dc, a->rd, dst); 4849 return advance_pc(dc); 4850 } 4851 4852 TRANS(FEXPAND, VIS1, do_df, a, gen_helper_fexpand) 4853 4854 static bool do_env_df(DisasContext *dc, arg_r_r *a, 4855 void (*func)(TCGv_i64, TCGv_env, TCGv_i32)) 4856 { 4857 TCGv_i64 dst; 4858 TCGv_i32 src; 4859 4860 if (gen_trap_if_nofpu_fpexception(dc)) { 4861 return true; 4862 } 4863 4864 dst = tcg_temp_new_i64(); 4865 src = gen_load_fpr_F(dc, a->rs); 4866 func(dst, tcg_env, src); 4867 gen_store_fpr_D(dc, a->rd, dst); 4868 return advance_pc(dc); 4869 } 4870 4871 TRANS(FiTOd, ALL, do_env_df, a, gen_helper_fitod) 4872 TRANS(FsTOd, ALL, do_env_df, a, gen_helper_fstod) 4873 TRANS(FsTOx, 64, do_env_df, a, gen_helper_fstox) 4874 4875 static bool do_qq(DisasContext *dc, arg_r_r *a, 4876 void (*func)(TCGv_i128, TCGv_i128)) 4877 { 4878 TCGv_i128 t; 4879 4880 if (gen_trap_ifnofpu(dc)) { 4881 return true; 4882 } 4883 if (gen_trap_float128(dc)) { 4884 return true; 4885 } 4886 4887 gen_op_clear_ieee_excp_and_FTT(); 4888 t = gen_load_fpr_Q(dc, a->rs); 4889 func(t, t); 4890 gen_store_fpr_Q(dc, a->rd, t); 4891 return advance_pc(dc); 4892 } 4893 4894 TRANS(FMOVq, 64, do_qq, a, tcg_gen_mov_i128) 4895 TRANS(FNEGq, 64, do_qq, a, gen_op_fnegq) 4896 TRANS(FABSq, 64, do_qq, a, gen_op_fabsq) 4897 4898 static bool do_env_qq(DisasContext *dc, arg_r_r *a, 4899 void (*func)(TCGv_i128, TCGv_env, TCGv_i128)) 4900 { 4901 TCGv_i128 t; 4902 4903 if (gen_trap_if_nofpu_fpexception(dc)) { 4904 return true; 4905 } 4906 if (gen_trap_float128(dc)) { 4907 return true; 4908 } 4909 4910 t = gen_load_fpr_Q(dc, a->rs); 4911 func(t, tcg_env, t); 4912 gen_store_fpr_Q(dc, a->rd, t); 4913 return advance_pc(dc); 4914 } 4915 4916 TRANS(FSQRTq, ALL, do_env_qq, a, gen_helper_fsqrtq) 4917 4918 static bool do_env_fq(DisasContext *dc, arg_r_r *a, 4919 void (*func)(TCGv_i32, TCGv_env, TCGv_i128)) 4920 { 4921 TCGv_i128 src; 4922 TCGv_i32 dst; 4923 4924 if (gen_trap_if_nofpu_fpexception(dc)) { 4925 return true; 4926 } 4927 if (gen_trap_float128(dc)) { 4928 return true; 4929 } 4930 4931 src = gen_load_fpr_Q(dc, a->rs); 4932 dst = tcg_temp_new_i32(); 4933 func(dst, tcg_env, src); 4934 gen_store_fpr_F(dc, a->rd, dst); 4935 return advance_pc(dc); 4936 } 4937 4938 TRANS(FqTOs, ALL, do_env_fq, a, gen_helper_fqtos) 4939 TRANS(FqTOi, ALL, do_env_fq, a, gen_helper_fqtoi) 4940 4941 static bool do_env_dq(DisasContext *dc, arg_r_r *a, 4942 void (*func)(TCGv_i64, TCGv_env, TCGv_i128)) 4943 { 4944 TCGv_i128 src; 4945 TCGv_i64 dst; 4946 4947 if (gen_trap_if_nofpu_fpexception(dc)) { 4948 return true; 4949 } 4950 if (gen_trap_float128(dc)) { 4951 return true; 4952 } 4953 4954 src = gen_load_fpr_Q(dc, a->rs); 4955 dst = tcg_temp_new_i64(); 4956 func(dst, tcg_env, src); 4957 gen_store_fpr_D(dc, a->rd, dst); 4958 return advance_pc(dc); 4959 } 4960 4961 TRANS(FqTOd, ALL, do_env_dq, a, gen_helper_fqtod) 4962 TRANS(FqTOx, 64, do_env_dq, a, gen_helper_fqtox) 4963 4964 static bool do_env_qf(DisasContext *dc, arg_r_r *a, 4965 void (*func)(TCGv_i128, TCGv_env, TCGv_i32)) 4966 { 4967 TCGv_i32 src; 4968 TCGv_i128 dst; 4969 4970 if (gen_trap_if_nofpu_fpexception(dc)) { 4971 return true; 4972 } 4973 if (gen_trap_float128(dc)) { 4974 return true; 4975 } 4976 4977 src = gen_load_fpr_F(dc, a->rs); 4978 dst = tcg_temp_new_i128(); 4979 func(dst, tcg_env, src); 4980 gen_store_fpr_Q(dc, a->rd, dst); 4981 return advance_pc(dc); 4982 } 4983 4984 TRANS(FiTOq, ALL, do_env_qf, a, gen_helper_fitoq) 4985 TRANS(FsTOq, ALL, do_env_qf, a, gen_helper_fstoq) 4986 4987 static bool do_env_qd(DisasContext *dc, arg_r_r *a, 4988 void (*func)(TCGv_i128, TCGv_env, TCGv_i64)) 4989 { 4990 TCGv_i64 src; 4991 TCGv_i128 dst; 4992 4993 if (gen_trap_if_nofpu_fpexception(dc)) { 4994 return true; 4995 } 4996 4997 src = gen_load_fpr_D(dc, a->rs); 4998 dst = tcg_temp_new_i128(); 4999 func(dst, tcg_env, src); 5000 gen_store_fpr_Q(dc, a->rd, dst); 5001 return advance_pc(dc); 5002 } 5003 5004 TRANS(FdTOq, ALL, do_env_qd, a, gen_helper_fdtoq) 5005 TRANS(FxTOq, 64, do_env_qd, a, gen_helper_fxtoq) 5006 5007 static bool do_fff(DisasContext *dc, arg_r_r_r *a, 5008 void (*func)(TCGv_i32, TCGv_i32, TCGv_i32)) 5009 { 5010 TCGv_i32 src1, src2; 5011 5012 if (gen_trap_ifnofpu(dc)) { 5013 return true; 5014 } 5015 5016 src1 = gen_load_fpr_F(dc, a->rs1); 5017 src2 = gen_load_fpr_F(dc, a->rs2); 5018 func(src1, src1, src2); 5019 gen_store_fpr_F(dc, a->rd, src1); 5020 return advance_pc(dc); 5021 } 5022 5023 TRANS(FPADD16s, VIS1, do_fff, a, tcg_gen_vec_add16_i32) 5024 TRANS(FPADD32s, VIS1, do_fff, a, tcg_gen_add_i32) 5025 TRANS(FPSUB16s, VIS1, do_fff, a, tcg_gen_vec_sub16_i32) 5026 TRANS(FPSUB32s, VIS1, do_fff, a, tcg_gen_sub_i32) 5027 TRANS(FNORs, VIS1, do_fff, a, tcg_gen_nor_i32) 5028 TRANS(FANDNOTs, VIS1, do_fff, a, tcg_gen_andc_i32) 5029 TRANS(FXORs, VIS1, do_fff, a, tcg_gen_xor_i32) 5030 TRANS(FNANDs, VIS1, do_fff, a, tcg_gen_nand_i32) 5031 TRANS(FANDs, VIS1, do_fff, a, tcg_gen_and_i32) 5032 TRANS(FXNORs, VIS1, do_fff, a, tcg_gen_eqv_i32) 5033 TRANS(FORNOTs, VIS1, do_fff, a, tcg_gen_orc_i32) 5034 TRANS(FORs, VIS1, do_fff, a, tcg_gen_or_i32) 5035 5036 TRANS(FHADDs, VIS3, do_fff, a, gen_op_fhadds) 5037 TRANS(FHSUBs, VIS3, do_fff, a, gen_op_fhsubs) 5038 TRANS(FNHADDs, VIS3, do_fff, a, gen_op_fnhadds) 5039 5040 TRANS(FPADDS16s, VIS3, do_fff, a, gen_op_fpadds16s) 5041 TRANS(FPSUBS16s, VIS3, do_fff, a, gen_op_fpsubs16s) 5042 TRANS(FPADDS32s, VIS3, do_fff, a, gen_op_fpadds32s) 5043 TRANS(FPSUBS32s, VIS3, do_fff, a, gen_op_fpsubs32s) 5044 5045 static bool do_env_fff(DisasContext *dc, arg_r_r_r *a, 5046 void (*func)(TCGv_i32, TCGv_env, TCGv_i32, TCGv_i32)) 5047 { 5048 TCGv_i32 src1, src2; 5049 5050 if (gen_trap_if_nofpu_fpexception(dc)) { 5051 return true; 5052 } 5053 5054 src1 = gen_load_fpr_F(dc, a->rs1); 5055 src2 = gen_load_fpr_F(dc, a->rs2); 5056 func(src1, tcg_env, src1, src2); 5057 gen_store_fpr_F(dc, a->rd, src1); 5058 return advance_pc(dc); 5059 } 5060 5061 TRANS(FADDs, ALL, do_env_fff, a, gen_helper_fadds) 5062 TRANS(FSUBs, ALL, do_env_fff, a, gen_helper_fsubs) 5063 TRANS(FMULs, ALL, do_env_fff, a, gen_helper_fmuls) 5064 TRANS(FDIVs, ALL, do_env_fff, a, gen_helper_fdivs) 5065 TRANS(FNADDs, VIS3, do_env_fff, a, gen_helper_fnadds) 5066 TRANS(FNMULs, VIS3, do_env_fff, a, gen_helper_fnmuls) 5067 5068 static bool do_dff(DisasContext *dc, arg_r_r_r *a, 5069 void (*func)(TCGv_i64, TCGv_i32, TCGv_i32)) 5070 { 5071 TCGv_i64 dst; 5072 TCGv_i32 src1, src2; 5073 5074 if (gen_trap_ifnofpu(dc)) { 5075 return true; 5076 } 5077 5078 dst = tcg_temp_new_i64(); 5079 src1 = gen_load_fpr_F(dc, a->rs1); 5080 src2 = gen_load_fpr_F(dc, a->rs2); 5081 func(dst, src1, src2); 5082 gen_store_fpr_D(dc, a->rd, dst); 5083 return advance_pc(dc); 5084 } 5085 5086 TRANS(FMUL8x16AU, VIS1, do_dff, a, gen_op_fmul8x16au) 5087 TRANS(FMUL8x16AL, VIS1, do_dff, a, gen_op_fmul8x16al) 5088 TRANS(FMULD8SUx16, VIS1, do_dff, a, gen_op_fmuld8sux16) 5089 TRANS(FMULD8ULx16, VIS1, do_dff, a, gen_op_fmuld8ulx16) 5090 TRANS(FPMERGE, VIS1, do_dff, a, gen_helper_fpmerge) 5091 5092 static bool do_dfd(DisasContext *dc, arg_r_r_r *a, 5093 void (*func)(TCGv_i64, TCGv_i32, TCGv_i64)) 5094 { 5095 TCGv_i64 dst, src2; 5096 TCGv_i32 src1; 5097 5098 if (gen_trap_ifnofpu(dc)) { 5099 return true; 5100 } 5101 5102 dst = tcg_temp_new_i64(); 5103 src1 = gen_load_fpr_F(dc, a->rs1); 5104 src2 = gen_load_fpr_D(dc, a->rs2); 5105 func(dst, src1, src2); 5106 gen_store_fpr_D(dc, a->rd, dst); 5107 return advance_pc(dc); 5108 } 5109 5110 TRANS(FMUL8x16, VIS1, do_dfd, a, gen_helper_fmul8x16) 5111 5112 static bool do_gvec_ddd(DisasContext *dc, arg_r_r_r *a, MemOp vece, 5113 void (*func)(unsigned, uint32_t, uint32_t, 5114 uint32_t, uint32_t, uint32_t)) 5115 { 5116 if (gen_trap_ifnofpu(dc)) { 5117 return true; 5118 } 5119 5120 func(vece, gen_offset_fpr_D(a->rd), gen_offset_fpr_D(a->rs1), 5121 gen_offset_fpr_D(a->rs2), 8, 8); 5122 return advance_pc(dc); 5123 } 5124 5125 TRANS(FPADD8, VIS4, do_gvec_ddd, a, MO_8, tcg_gen_gvec_add) 5126 TRANS(FPADD16, VIS1, do_gvec_ddd, a, MO_16, tcg_gen_gvec_add) 5127 TRANS(FPADD32, VIS1, do_gvec_ddd, a, MO_32, tcg_gen_gvec_add) 5128 5129 TRANS(FPSUB8, VIS4, do_gvec_ddd, a, MO_8, tcg_gen_gvec_sub) 5130 TRANS(FPSUB16, VIS1, do_gvec_ddd, a, MO_16, tcg_gen_gvec_sub) 5131 TRANS(FPSUB32, VIS1, do_gvec_ddd, a, MO_32, tcg_gen_gvec_sub) 5132 5133 TRANS(FCHKSM16, VIS3, do_gvec_ddd, a, MO_16, gen_op_fchksm16) 5134 TRANS(FMEAN16, VIS3, do_gvec_ddd, a, MO_16, gen_op_fmean16) 5135 5136 TRANS(FPADDS8, VIS4, do_gvec_ddd, a, MO_8, tcg_gen_gvec_ssadd) 5137 TRANS(FPADDS16, VIS3, do_gvec_ddd, a, MO_16, tcg_gen_gvec_ssadd) 5138 TRANS(FPADDS32, VIS3, do_gvec_ddd, a, MO_32, tcg_gen_gvec_ssadd) 5139 TRANS(FPADDUS8, VIS4, do_gvec_ddd, a, MO_8, tcg_gen_gvec_usadd) 5140 TRANS(FPADDUS16, VIS4, do_gvec_ddd, a, MO_16, tcg_gen_gvec_usadd) 5141 5142 TRANS(FPSUBS8, VIS4, do_gvec_ddd, a, MO_8, tcg_gen_gvec_sssub) 5143 TRANS(FPSUBS16, VIS3, do_gvec_ddd, a, MO_16, tcg_gen_gvec_sssub) 5144 TRANS(FPSUBS32, VIS3, do_gvec_ddd, a, MO_32, tcg_gen_gvec_sssub) 5145 TRANS(FPSUBUS8, VIS4, do_gvec_ddd, a, MO_8, tcg_gen_gvec_ussub) 5146 TRANS(FPSUBUS16, VIS4, do_gvec_ddd, a, MO_16, tcg_gen_gvec_ussub) 5147 5148 TRANS(FSLL16, VIS3, do_gvec_ddd, a, MO_16, tcg_gen_gvec_shlv) 5149 TRANS(FSLL32, VIS3, do_gvec_ddd, a, MO_32, tcg_gen_gvec_shlv) 5150 TRANS(FSRL16, VIS3, do_gvec_ddd, a, MO_16, tcg_gen_gvec_shrv) 5151 TRANS(FSRL32, VIS3, do_gvec_ddd, a, MO_32, tcg_gen_gvec_shrv) 5152 TRANS(FSRA16, VIS3, do_gvec_ddd, a, MO_16, tcg_gen_gvec_sarv) 5153 TRANS(FSRA32, VIS3, do_gvec_ddd, a, MO_32, tcg_gen_gvec_sarv) 5154 5155 TRANS(FPMIN8, VIS4, do_gvec_ddd, a, MO_8, tcg_gen_gvec_smin) 5156 TRANS(FPMIN16, VIS4, do_gvec_ddd, a, MO_16, tcg_gen_gvec_smin) 5157 TRANS(FPMIN32, VIS4, do_gvec_ddd, a, MO_32, tcg_gen_gvec_smin) 5158 TRANS(FPMINU8, VIS4, do_gvec_ddd, a, MO_8, tcg_gen_gvec_umin) 5159 TRANS(FPMINU16, VIS4, do_gvec_ddd, a, MO_16, tcg_gen_gvec_umin) 5160 TRANS(FPMINU32, VIS4, do_gvec_ddd, a, MO_32, tcg_gen_gvec_umin) 5161 5162 TRANS(FPMAX8, VIS4, do_gvec_ddd, a, MO_8, tcg_gen_gvec_smax) 5163 TRANS(FPMAX16, VIS4, do_gvec_ddd, a, MO_16, tcg_gen_gvec_smax) 5164 TRANS(FPMAX32, VIS4, do_gvec_ddd, a, MO_32, tcg_gen_gvec_smax) 5165 TRANS(FPMAXU8, VIS4, do_gvec_ddd, a, MO_8, tcg_gen_gvec_umax) 5166 TRANS(FPMAXU16, VIS4, do_gvec_ddd, a, MO_16, tcg_gen_gvec_umax) 5167 TRANS(FPMAXU32, VIS4, do_gvec_ddd, a, MO_32, tcg_gen_gvec_umax) 5168 5169 static bool do_ddd(DisasContext *dc, arg_r_r_r *a, 5170 void (*func)(TCGv_i64, TCGv_i64, TCGv_i64)) 5171 { 5172 TCGv_i64 dst, src1, src2; 5173 5174 if (gen_trap_ifnofpu(dc)) { 5175 return true; 5176 } 5177 5178 dst = tcg_temp_new_i64(); 5179 src1 = gen_load_fpr_D(dc, a->rs1); 5180 src2 = gen_load_fpr_D(dc, a->rs2); 5181 func(dst, src1, src2); 5182 gen_store_fpr_D(dc, a->rd, dst); 5183 return advance_pc(dc); 5184 } 5185 5186 TRANS(FMUL8SUx16, VIS1, do_ddd, a, gen_helper_fmul8sux16) 5187 TRANS(FMUL8ULx16, VIS1, do_ddd, a, gen_helper_fmul8ulx16) 5188 5189 TRANS(FNORd, VIS1, do_ddd, a, tcg_gen_nor_i64) 5190 TRANS(FANDNOTd, VIS1, do_ddd, a, tcg_gen_andc_i64) 5191 TRANS(FXORd, VIS1, do_ddd, a, tcg_gen_xor_i64) 5192 TRANS(FNANDd, VIS1, do_ddd, a, tcg_gen_nand_i64) 5193 TRANS(FANDd, VIS1, do_ddd, a, tcg_gen_and_i64) 5194 TRANS(FXNORd, VIS1, do_ddd, a, tcg_gen_eqv_i64) 5195 TRANS(FORNOTd, VIS1, do_ddd, a, tcg_gen_orc_i64) 5196 TRANS(FORd, VIS1, do_ddd, a, tcg_gen_or_i64) 5197 5198 TRANS(FPACK32, VIS1, do_ddd, a, gen_op_fpack32) 5199 TRANS(FALIGNDATAg, VIS1, do_ddd, a, gen_op_faligndata_g) 5200 TRANS(BSHUFFLE, VIS2, do_ddd, a, gen_op_bshuffle) 5201 5202 TRANS(FHADDd, VIS3, do_ddd, a, gen_op_fhaddd) 5203 TRANS(FHSUBd, VIS3, do_ddd, a, gen_op_fhsubd) 5204 TRANS(FNHADDd, VIS3, do_ddd, a, gen_op_fnhaddd) 5205 5206 TRANS(FPADD64, VIS3B, do_ddd, a, tcg_gen_add_i64) 5207 TRANS(FPSUB64, VIS3B, do_ddd, a, tcg_gen_sub_i64) 5208 TRANS(FSLAS16, VIS3, do_ddd, a, gen_helper_fslas16) 5209 TRANS(FSLAS32, VIS3, do_ddd, a, gen_helper_fslas32) 5210 5211 static bool do_rdd(DisasContext *dc, arg_r_r_r *a, 5212 void (*func)(TCGv, TCGv_i64, TCGv_i64)) 5213 { 5214 TCGv_i64 src1, src2; 5215 TCGv dst; 5216 5217 if (gen_trap_ifnofpu(dc)) { 5218 return true; 5219 } 5220 5221 dst = gen_dest_gpr(dc, a->rd); 5222 src1 = gen_load_fpr_D(dc, a->rs1); 5223 src2 = gen_load_fpr_D(dc, a->rs2); 5224 func(dst, src1, src2); 5225 gen_store_gpr(dc, a->rd, dst); 5226 return advance_pc(dc); 5227 } 5228 5229 TRANS(FPCMPLE16, VIS1, do_rdd, a, gen_helper_fcmple16) 5230 TRANS(FPCMPNE16, VIS1, do_rdd, a, gen_helper_fcmpne16) 5231 TRANS(FPCMPGT16, VIS1, do_rdd, a, gen_helper_fcmpgt16) 5232 TRANS(FPCMPEQ16, VIS1, do_rdd, a, gen_helper_fcmpeq16) 5233 TRANS(FPCMPULE16, VIS4, do_rdd, a, gen_helper_fcmpule16) 5234 TRANS(FPCMPUGT16, VIS4, do_rdd, a, gen_helper_fcmpugt16) 5235 5236 TRANS(FPCMPLE32, VIS1, do_rdd, a, gen_helper_fcmple32) 5237 TRANS(FPCMPNE32, VIS1, do_rdd, a, gen_helper_fcmpne32) 5238 TRANS(FPCMPGT32, VIS1, do_rdd, a, gen_helper_fcmpgt32) 5239 TRANS(FPCMPEQ32, VIS1, do_rdd, a, gen_helper_fcmpeq32) 5240 TRANS(FPCMPULE32, VIS4, do_rdd, a, gen_helper_fcmpule32) 5241 TRANS(FPCMPUGT32, VIS4, do_rdd, a, gen_helper_fcmpugt32) 5242 5243 TRANS(FPCMPEQ8, VIS3B, do_rdd, a, gen_helper_fcmpeq8) 5244 TRANS(FPCMPNE8, VIS3B, do_rdd, a, gen_helper_fcmpne8) 5245 TRANS(FPCMPULE8, VIS3B, do_rdd, a, gen_helper_fcmpule8) 5246 TRANS(FPCMPUGT8, VIS3B, do_rdd, a, gen_helper_fcmpugt8) 5247 TRANS(FPCMPLE8, VIS4, do_rdd, a, gen_helper_fcmple8) 5248 TRANS(FPCMPGT8, VIS4, do_rdd, a, gen_helper_fcmpgt8) 5249 5250 TRANS(PDISTN, VIS3, do_rdd, a, gen_op_pdistn) 5251 TRANS(XMULX, VIS3, do_rrr, a, gen_helper_xmulx) 5252 TRANS(XMULXHI, VIS3, do_rrr, a, gen_helper_xmulxhi) 5253 5254 static bool do_env_ddd(DisasContext *dc, arg_r_r_r *a, 5255 void (*func)(TCGv_i64, TCGv_env, TCGv_i64, TCGv_i64)) 5256 { 5257 TCGv_i64 dst, src1, src2; 5258 5259 if (gen_trap_if_nofpu_fpexception(dc)) { 5260 return true; 5261 } 5262 5263 dst = tcg_temp_new_i64(); 5264 src1 = gen_load_fpr_D(dc, a->rs1); 5265 src2 = gen_load_fpr_D(dc, a->rs2); 5266 func(dst, tcg_env, src1, src2); 5267 gen_store_fpr_D(dc, a->rd, dst); 5268 return advance_pc(dc); 5269 } 5270 5271 TRANS(FADDd, ALL, do_env_ddd, a, gen_helper_faddd) 5272 TRANS(FSUBd, ALL, do_env_ddd, a, gen_helper_fsubd) 5273 TRANS(FMULd, ALL, do_env_ddd, a, gen_helper_fmuld) 5274 TRANS(FDIVd, ALL, do_env_ddd, a, gen_helper_fdivd) 5275 TRANS(FNADDd, VIS3, do_env_ddd, a, gen_helper_fnaddd) 5276 TRANS(FNMULd, VIS3, do_env_ddd, a, gen_helper_fnmuld) 5277 5278 static bool trans_FsMULd(DisasContext *dc, arg_r_r_r *a) 5279 { 5280 TCGv_i64 dst; 5281 TCGv_i32 src1, src2; 5282 5283 if (gen_trap_if_nofpu_fpexception(dc)) { 5284 return true; 5285 } 5286 if (!(dc->def->features & CPU_FEATURE_FSMULD)) { 5287 return raise_unimpfpop(dc); 5288 } 5289 5290 dst = tcg_temp_new_i64(); 5291 src1 = gen_load_fpr_F(dc, a->rs1); 5292 src2 = gen_load_fpr_F(dc, a->rs2); 5293 gen_helper_fsmuld(dst, tcg_env, src1, src2); 5294 gen_store_fpr_D(dc, a->rd, dst); 5295 return advance_pc(dc); 5296 } 5297 5298 static bool trans_FNsMULd(DisasContext *dc, arg_r_r_r *a) 5299 { 5300 TCGv_i64 dst; 5301 TCGv_i32 src1, src2; 5302 5303 if (!avail_VIS3(dc)) { 5304 return false; 5305 } 5306 if (gen_trap_ifnofpu(dc)) { 5307 return true; 5308 } 5309 dst = tcg_temp_new_i64(); 5310 src1 = gen_load_fpr_F(dc, a->rs1); 5311 src2 = gen_load_fpr_F(dc, a->rs2); 5312 gen_helper_fnsmuld(dst, tcg_env, src1, src2); 5313 gen_store_fpr_D(dc, a->rd, dst); 5314 return advance_pc(dc); 5315 } 5316 5317 static bool do_ffff(DisasContext *dc, arg_r_r_r_r *a, 5318 void (*func)(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_i32)) 5319 { 5320 TCGv_i32 dst, src1, src2, src3; 5321 5322 if (gen_trap_ifnofpu(dc)) { 5323 return true; 5324 } 5325 5326 src1 = gen_load_fpr_F(dc, a->rs1); 5327 src2 = gen_load_fpr_F(dc, a->rs2); 5328 src3 = gen_load_fpr_F(dc, a->rs3); 5329 dst = tcg_temp_new_i32(); 5330 func(dst, src1, src2, src3); 5331 gen_store_fpr_F(dc, a->rd, dst); 5332 return advance_pc(dc); 5333 } 5334 5335 TRANS(FMADDs, FMAF, do_ffff, a, gen_op_fmadds) 5336 TRANS(FMSUBs, FMAF, do_ffff, a, gen_op_fmsubs) 5337 TRANS(FNMSUBs, FMAF, do_ffff, a, gen_op_fnmsubs) 5338 TRANS(FNMADDs, FMAF, do_ffff, a, gen_op_fnmadds) 5339 5340 static bool do_dddd(DisasContext *dc, arg_r_r_r_r *a, 5341 void (*func)(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_i64)) 5342 { 5343 TCGv_i64 dst, src1, src2, src3; 5344 5345 if (gen_trap_ifnofpu(dc)) { 5346 return true; 5347 } 5348 5349 dst = tcg_temp_new_i64(); 5350 src1 = gen_load_fpr_D(dc, a->rs1); 5351 src2 = gen_load_fpr_D(dc, a->rs2); 5352 src3 = gen_load_fpr_D(dc, a->rs3); 5353 func(dst, src1, src2, src3); 5354 gen_store_fpr_D(dc, a->rd, dst); 5355 return advance_pc(dc); 5356 } 5357 5358 TRANS(PDIST, VIS1, do_dddd, a, gen_helper_pdist) 5359 TRANS(FMADDd, FMAF, do_dddd, a, gen_op_fmaddd) 5360 TRANS(FMSUBd, FMAF, do_dddd, a, gen_op_fmsubd) 5361 TRANS(FNMSUBd, FMAF, do_dddd, a, gen_op_fnmsubd) 5362 TRANS(FNMADDd, FMAF, do_dddd, a, gen_op_fnmaddd) 5363 TRANS(FPMADDX, IMA, do_dddd, a, gen_op_fpmaddx) 5364 TRANS(FPMADDXHI, IMA, do_dddd, a, gen_op_fpmaddxhi) 5365 5366 static bool trans_FALIGNDATAi(DisasContext *dc, arg_r_r_r *a) 5367 { 5368 TCGv_i64 dst, src1, src2; 5369 TCGv src3; 5370 5371 if (!avail_VIS4(dc)) { 5372 return false; 5373 } 5374 if (gen_trap_ifnofpu(dc)) { 5375 return true; 5376 } 5377 5378 dst = tcg_temp_new_i64(); 5379 src1 = gen_load_fpr_D(dc, a->rd); 5380 src2 = gen_load_fpr_D(dc, a->rs2); 5381 src3 = gen_load_gpr(dc, a->rs1); 5382 gen_op_faligndata_i(dst, src1, src2, src3); 5383 gen_store_fpr_D(dc, a->rd, dst); 5384 return advance_pc(dc); 5385 } 5386 5387 static bool do_env_qqq(DisasContext *dc, arg_r_r_r *a, 5388 void (*func)(TCGv_i128, TCGv_env, TCGv_i128, TCGv_i128)) 5389 { 5390 TCGv_i128 src1, src2; 5391 5392 if (gen_trap_if_nofpu_fpexception(dc)) { 5393 return true; 5394 } 5395 if (gen_trap_float128(dc)) { 5396 return true; 5397 } 5398 5399 src1 = gen_load_fpr_Q(dc, a->rs1); 5400 src2 = gen_load_fpr_Q(dc, a->rs2); 5401 func(src1, tcg_env, src1, src2); 5402 gen_store_fpr_Q(dc, a->rd, src1); 5403 return advance_pc(dc); 5404 } 5405 5406 TRANS(FADDq, ALL, do_env_qqq, a, gen_helper_faddq) 5407 TRANS(FSUBq, ALL, do_env_qqq, a, gen_helper_fsubq) 5408 TRANS(FMULq, ALL, do_env_qqq, a, gen_helper_fmulq) 5409 TRANS(FDIVq, ALL, do_env_qqq, a, gen_helper_fdivq) 5410 5411 static bool trans_FdMULq(DisasContext *dc, arg_r_r_r *a) 5412 { 5413 TCGv_i64 src1, src2; 5414 TCGv_i128 dst; 5415 5416 if (gen_trap_if_nofpu_fpexception(dc)) { 5417 return true; 5418 } 5419 if (gen_trap_float128(dc)) { 5420 return true; 5421 } 5422 5423 src1 = gen_load_fpr_D(dc, a->rs1); 5424 src2 = gen_load_fpr_D(dc, a->rs2); 5425 dst = tcg_temp_new_i128(); 5426 gen_helper_fdmulq(dst, tcg_env, src1, src2); 5427 gen_store_fpr_Q(dc, a->rd, dst); 5428 return advance_pc(dc); 5429 } 5430 5431 static bool do_fmovr(DisasContext *dc, arg_FMOVRs *a, bool is_128, 5432 void (*func)(DisasContext *, DisasCompare *, int, int)) 5433 { 5434 DisasCompare cmp; 5435 5436 if (!gen_compare_reg(&cmp, a->cond, gen_load_gpr(dc, a->rs1))) { 5437 return false; 5438 } 5439 if (gen_trap_ifnofpu(dc)) { 5440 return true; 5441 } 5442 if (is_128 && gen_trap_float128(dc)) { 5443 return true; 5444 } 5445 5446 gen_op_clear_ieee_excp_and_FTT(); 5447 func(dc, &cmp, a->rd, a->rs2); 5448 return advance_pc(dc); 5449 } 5450 5451 TRANS(FMOVRs, 64, do_fmovr, a, false, gen_fmovs) 5452 TRANS(FMOVRd, 64, do_fmovr, a, false, gen_fmovd) 5453 TRANS(FMOVRq, 64, do_fmovr, a, true, gen_fmovq) 5454 5455 static bool do_fmovcc(DisasContext *dc, arg_FMOVscc *a, bool is_128, 5456 void (*func)(DisasContext *, DisasCompare *, int, int)) 5457 { 5458 DisasCompare cmp; 5459 5460 if (gen_trap_ifnofpu(dc)) { 5461 return true; 5462 } 5463 if (is_128 && gen_trap_float128(dc)) { 5464 return true; 5465 } 5466 5467 gen_op_clear_ieee_excp_and_FTT(); 5468 gen_compare(&cmp, a->cc, a->cond, dc); 5469 func(dc, &cmp, a->rd, a->rs2); 5470 return advance_pc(dc); 5471 } 5472 5473 TRANS(FMOVscc, 64, do_fmovcc, a, false, gen_fmovs) 5474 TRANS(FMOVdcc, 64, do_fmovcc, a, false, gen_fmovd) 5475 TRANS(FMOVqcc, 64, do_fmovcc, a, true, gen_fmovq) 5476 5477 static bool do_fmovfcc(DisasContext *dc, arg_FMOVsfcc *a, bool is_128, 5478 void (*func)(DisasContext *, DisasCompare *, int, int)) 5479 { 5480 DisasCompare cmp; 5481 5482 if (gen_trap_ifnofpu(dc)) { 5483 return true; 5484 } 5485 if (is_128 && gen_trap_float128(dc)) { 5486 return true; 5487 } 5488 5489 gen_op_clear_ieee_excp_and_FTT(); 5490 gen_fcompare(&cmp, a->cc, a->cond); 5491 func(dc, &cmp, a->rd, a->rs2); 5492 return advance_pc(dc); 5493 } 5494 5495 TRANS(FMOVsfcc, 64, do_fmovfcc, a, false, gen_fmovs) 5496 TRANS(FMOVdfcc, 64, do_fmovfcc, a, false, gen_fmovd) 5497 TRANS(FMOVqfcc, 64, do_fmovfcc, a, true, gen_fmovq) 5498 5499 static bool do_fcmps(DisasContext *dc, arg_FCMPs *a, bool e) 5500 { 5501 TCGv_i32 src1, src2; 5502 5503 if (avail_32(dc) && a->cc != 0) { 5504 return false; 5505 } 5506 if (gen_trap_if_nofpu_fpexception(dc)) { 5507 return true; 5508 } 5509 5510 src1 = gen_load_fpr_F(dc, a->rs1); 5511 src2 = gen_load_fpr_F(dc, a->rs2); 5512 if (e) { 5513 gen_helper_fcmpes(cpu_fcc[a->cc], tcg_env, src1, src2); 5514 } else { 5515 gen_helper_fcmps(cpu_fcc[a->cc], tcg_env, src1, src2); 5516 } 5517 return advance_pc(dc); 5518 } 5519 5520 TRANS(FCMPs, ALL, do_fcmps, a, false) 5521 TRANS(FCMPEs, ALL, do_fcmps, a, true) 5522 5523 static bool do_fcmpd(DisasContext *dc, arg_FCMPd *a, bool e) 5524 { 5525 TCGv_i64 src1, src2; 5526 5527 if (avail_32(dc) && a->cc != 0) { 5528 return false; 5529 } 5530 if (gen_trap_if_nofpu_fpexception(dc)) { 5531 return true; 5532 } 5533 5534 src1 = gen_load_fpr_D(dc, a->rs1); 5535 src2 = gen_load_fpr_D(dc, a->rs2); 5536 if (e) { 5537 gen_helper_fcmped(cpu_fcc[a->cc], tcg_env, src1, src2); 5538 } else { 5539 gen_helper_fcmpd(cpu_fcc[a->cc], tcg_env, src1, src2); 5540 } 5541 return advance_pc(dc); 5542 } 5543 5544 TRANS(FCMPd, ALL, do_fcmpd, a, false) 5545 TRANS(FCMPEd, ALL, do_fcmpd, a, true) 5546 5547 static bool do_fcmpq(DisasContext *dc, arg_FCMPq *a, bool e) 5548 { 5549 TCGv_i128 src1, src2; 5550 5551 if (avail_32(dc) && a->cc != 0) { 5552 return false; 5553 } 5554 if (gen_trap_if_nofpu_fpexception(dc)) { 5555 return true; 5556 } 5557 if (gen_trap_float128(dc)) { 5558 return true; 5559 } 5560 5561 src1 = gen_load_fpr_Q(dc, a->rs1); 5562 src2 = gen_load_fpr_Q(dc, a->rs2); 5563 if (e) { 5564 gen_helper_fcmpeq(cpu_fcc[a->cc], tcg_env, src1, src2); 5565 } else { 5566 gen_helper_fcmpq(cpu_fcc[a->cc], tcg_env, src1, src2); 5567 } 5568 return advance_pc(dc); 5569 } 5570 5571 TRANS(FCMPq, ALL, do_fcmpq, a, false) 5572 TRANS(FCMPEq, ALL, do_fcmpq, a, true) 5573 5574 static bool trans_FLCMPs(DisasContext *dc, arg_FLCMPs *a) 5575 { 5576 TCGv_i32 src1, src2; 5577 5578 if (!avail_VIS3(dc)) { 5579 return false; 5580 } 5581 if (gen_trap_ifnofpu(dc)) { 5582 return true; 5583 } 5584 5585 src1 = gen_load_fpr_F(dc, a->rs1); 5586 src2 = gen_load_fpr_F(dc, a->rs2); 5587 gen_helper_flcmps(cpu_fcc[a->cc], src1, src2); 5588 return advance_pc(dc); 5589 } 5590 5591 static bool trans_FLCMPd(DisasContext *dc, arg_FLCMPd *a) 5592 { 5593 TCGv_i64 src1, src2; 5594 5595 if (!avail_VIS3(dc)) { 5596 return false; 5597 } 5598 if (gen_trap_ifnofpu(dc)) { 5599 return true; 5600 } 5601 5602 src1 = gen_load_fpr_D(dc, a->rs1); 5603 src2 = gen_load_fpr_D(dc, a->rs2); 5604 gen_helper_flcmpd(cpu_fcc[a->cc], src1, src2); 5605 return advance_pc(dc); 5606 } 5607 5608 static bool do_movf2r(DisasContext *dc, arg_r_r *a, 5609 int (*offset)(unsigned int), 5610 void (*load)(TCGv, TCGv_ptr, tcg_target_long)) 5611 { 5612 TCGv dst; 5613 5614 if (gen_trap_ifnofpu(dc)) { 5615 return true; 5616 } 5617 dst = gen_dest_gpr(dc, a->rd); 5618 load(dst, tcg_env, offset(a->rs)); 5619 gen_store_gpr(dc, a->rd, dst); 5620 return advance_pc(dc); 5621 } 5622 5623 TRANS(MOVsTOsw, VIS3B, do_movf2r, a, gen_offset_fpr_F, tcg_gen_ld32s_tl) 5624 TRANS(MOVsTOuw, VIS3B, do_movf2r, a, gen_offset_fpr_F, tcg_gen_ld32u_tl) 5625 TRANS(MOVdTOx, VIS3B, do_movf2r, a, gen_offset_fpr_D, tcg_gen_ld_tl) 5626 5627 static bool do_movr2f(DisasContext *dc, arg_r_r *a, 5628 int (*offset)(unsigned int), 5629 void (*store)(TCGv, TCGv_ptr, tcg_target_long)) 5630 { 5631 TCGv src; 5632 5633 if (gen_trap_ifnofpu(dc)) { 5634 return true; 5635 } 5636 src = gen_load_gpr(dc, a->rs); 5637 store(src, tcg_env, offset(a->rd)); 5638 return advance_pc(dc); 5639 } 5640 5641 TRANS(MOVwTOs, VIS3B, do_movr2f, a, gen_offset_fpr_F, tcg_gen_st32_tl) 5642 TRANS(MOVxTOd, VIS3B, do_movr2f, a, gen_offset_fpr_D, tcg_gen_st_tl) 5643 5644 static void sparc_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) 5645 { 5646 DisasContext *dc = container_of(dcbase, DisasContext, base); 5647 int bound; 5648 5649 dc->pc = dc->base.pc_first; 5650 dc->npc = (target_ulong)dc->base.tb->cs_base; 5651 dc->mem_idx = dc->base.tb->flags & TB_FLAG_MMU_MASK; 5652 dc->def = &cpu_env(cs)->def; 5653 dc->fpu_enabled = tb_fpu_enabled(dc->base.tb->flags); 5654 dc->address_mask_32bit = tb_am_enabled(dc->base.tb->flags); 5655 #ifndef CONFIG_USER_ONLY 5656 dc->supervisor = (dc->base.tb->flags & TB_FLAG_SUPER) != 0; 5657 # ifdef TARGET_SPARC64 5658 dc->hypervisor = (dc->base.tb->flags & TB_FLAG_HYPER) != 0; 5659 # else 5660 dc->fsr_qne = (dc->base.tb->flags & TB_FLAG_FSR_QNE) != 0; 5661 # endif 5662 #endif 5663 #ifdef TARGET_SPARC64 5664 dc->fprs_dirty = 0; 5665 dc->asi = (dc->base.tb->flags >> TB_FLAG_ASI_SHIFT) & 0xff; 5666 #endif 5667 /* 5668 * if we reach a page boundary, we stop generation so that the 5669 * PC of a TT_TFAULT exception is always in the right page 5670 */ 5671 bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4; 5672 dc->base.max_insns = MIN(dc->base.max_insns, bound); 5673 } 5674 5675 static void sparc_tr_tb_start(DisasContextBase *db, CPUState *cs) 5676 { 5677 } 5678 5679 static void sparc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) 5680 { 5681 DisasContext *dc = container_of(dcbase, DisasContext, base); 5682 target_ulong npc = dc->npc; 5683 5684 if (npc & 3) { 5685 switch (npc) { 5686 case JUMP_PC: 5687 assert(dc->jump_pc[1] == dc->pc + 4); 5688 npc = dc->jump_pc[0] | JUMP_PC; 5689 break; 5690 case DYNAMIC_PC: 5691 case DYNAMIC_PC_LOOKUP: 5692 npc = DYNAMIC_PC; 5693 break; 5694 default: 5695 g_assert_not_reached(); 5696 } 5697 } 5698 tcg_gen_insn_start(dc->pc, npc); 5699 } 5700 5701 static void sparc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) 5702 { 5703 DisasContext *dc = container_of(dcbase, DisasContext, base); 5704 unsigned int insn; 5705 5706 insn = translator_ldl(cpu_env(cs), &dc->base, dc->pc); 5707 dc->base.pc_next += 4; 5708 5709 if (!decode(dc, insn)) { 5710 gen_exception(dc, TT_ILL_INSN); 5711 } 5712 5713 if (dc->base.is_jmp == DISAS_NORETURN) { 5714 return; 5715 } 5716 if (dc->pc != dc->base.pc_next) { 5717 dc->base.is_jmp = DISAS_TOO_MANY; 5718 } 5719 } 5720 5721 static void sparc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) 5722 { 5723 DisasContext *dc = container_of(dcbase, DisasContext, base); 5724 DisasDelayException *e, *e_next; 5725 bool may_lookup; 5726 5727 finishing_insn(dc); 5728 5729 switch (dc->base.is_jmp) { 5730 case DISAS_NEXT: 5731 case DISAS_TOO_MANY: 5732 if (((dc->pc | dc->npc) & 3) == 0) { 5733 /* static PC and NPC: we can use direct chaining */ 5734 gen_goto_tb(dc, 0, dc->pc, dc->npc); 5735 break; 5736 } 5737 5738 may_lookup = true; 5739 if (dc->pc & 3) { 5740 switch (dc->pc) { 5741 case DYNAMIC_PC_LOOKUP: 5742 break; 5743 case DYNAMIC_PC: 5744 may_lookup = false; 5745 break; 5746 default: 5747 g_assert_not_reached(); 5748 } 5749 } else { 5750 tcg_gen_movi_tl(cpu_pc, dc->pc); 5751 } 5752 5753 if (dc->npc & 3) { 5754 switch (dc->npc) { 5755 case JUMP_PC: 5756 gen_generic_branch(dc); 5757 break; 5758 case DYNAMIC_PC: 5759 may_lookup = false; 5760 break; 5761 case DYNAMIC_PC_LOOKUP: 5762 break; 5763 default: 5764 g_assert_not_reached(); 5765 } 5766 } else { 5767 tcg_gen_movi_tl(cpu_npc, dc->npc); 5768 } 5769 if (may_lookup) { 5770 tcg_gen_lookup_and_goto_ptr(); 5771 } else { 5772 tcg_gen_exit_tb(NULL, 0); 5773 } 5774 break; 5775 5776 case DISAS_NORETURN: 5777 break; 5778 5779 case DISAS_EXIT: 5780 /* Exit TB */ 5781 save_state(dc); 5782 tcg_gen_exit_tb(NULL, 0); 5783 break; 5784 5785 default: 5786 g_assert_not_reached(); 5787 } 5788 5789 for (e = dc->delay_excp_list; e ; e = e_next) { 5790 gen_set_label(e->lab); 5791 5792 tcg_gen_movi_tl(cpu_pc, e->pc); 5793 if (e->npc % 4 == 0) { 5794 tcg_gen_movi_tl(cpu_npc, e->npc); 5795 } 5796 gen_helper_raise_exception(tcg_env, e->excp); 5797 5798 e_next = e->next; 5799 g_free(e); 5800 } 5801 } 5802 5803 static const TranslatorOps sparc_tr_ops = { 5804 .init_disas_context = sparc_tr_init_disas_context, 5805 .tb_start = sparc_tr_tb_start, 5806 .insn_start = sparc_tr_insn_start, 5807 .translate_insn = sparc_tr_translate_insn, 5808 .tb_stop = sparc_tr_tb_stop, 5809 }; 5810 5811 void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int *max_insns, 5812 vaddr pc, void *host_pc) 5813 { 5814 DisasContext dc = {}; 5815 5816 translator_loop(cs, tb, max_insns, pc, host_pc, &sparc_tr_ops, &dc.base); 5817 } 5818 5819 void sparc_tcg_init(void) 5820 { 5821 static const char gregnames[32][4] = { 5822 "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7", 5823 "o0", "o1", "o2", "o3", "o4", "o5", "o6", "o7", 5824 "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7", 5825 "i0", "i1", "i2", "i3", "i4", "i5", "i6", "i7", 5826 }; 5827 5828 static const struct { TCGv_i32 *ptr; int off; const char *name; } r32[] = { 5829 #ifdef TARGET_SPARC64 5830 { &cpu_fprs, offsetof(CPUSPARCState, fprs), "fprs" }, 5831 { &cpu_fcc[0], offsetof(CPUSPARCState, fcc[0]), "fcc0" }, 5832 { &cpu_fcc[1], offsetof(CPUSPARCState, fcc[1]), "fcc1" }, 5833 { &cpu_fcc[2], offsetof(CPUSPARCState, fcc[2]), "fcc2" }, 5834 { &cpu_fcc[3], offsetof(CPUSPARCState, fcc[3]), "fcc3" }, 5835 #else 5836 { &cpu_fcc[0], offsetof(CPUSPARCState, fcc[0]), "fcc" }, 5837 #endif 5838 }; 5839 5840 static const struct { TCGv *ptr; int off; const char *name; } rtl[] = { 5841 #ifdef TARGET_SPARC64 5842 { &cpu_gsr, offsetof(CPUSPARCState, gsr), "gsr" }, 5843 { &cpu_xcc_Z, offsetof(CPUSPARCState, xcc_Z), "xcc_Z" }, 5844 { &cpu_xcc_C, offsetof(CPUSPARCState, xcc_C), "xcc_C" }, 5845 #endif 5846 { &cpu_cc_N, offsetof(CPUSPARCState, cc_N), "cc_N" }, 5847 { &cpu_cc_V, offsetof(CPUSPARCState, cc_V), "cc_V" }, 5848 { &cpu_icc_Z, offsetof(CPUSPARCState, icc_Z), "icc_Z" }, 5849 { &cpu_icc_C, offsetof(CPUSPARCState, icc_C), "icc_C" }, 5850 { &cpu_cond, offsetof(CPUSPARCState, cond), "cond" }, 5851 { &cpu_pc, offsetof(CPUSPARCState, pc), "pc" }, 5852 { &cpu_npc, offsetof(CPUSPARCState, npc), "npc" }, 5853 { &cpu_y, offsetof(CPUSPARCState, y), "y" }, 5854 { &cpu_tbr, offsetof(CPUSPARCState, tbr), "tbr" }, 5855 }; 5856 5857 unsigned int i; 5858 5859 cpu_regwptr = tcg_global_mem_new_ptr(tcg_env, 5860 offsetof(CPUSPARCState, regwptr), 5861 "regwptr"); 5862 5863 for (i = 0; i < ARRAY_SIZE(r32); ++i) { 5864 *r32[i].ptr = tcg_global_mem_new_i32(tcg_env, r32[i].off, r32[i].name); 5865 } 5866 5867 for (i = 0; i < ARRAY_SIZE(rtl); ++i) { 5868 *rtl[i].ptr = tcg_global_mem_new(tcg_env, rtl[i].off, rtl[i].name); 5869 } 5870 5871 cpu_regs[0] = NULL; 5872 for (i = 1; i < 8; ++i) { 5873 cpu_regs[i] = tcg_global_mem_new(tcg_env, 5874 offsetof(CPUSPARCState, gregs[i]), 5875 gregnames[i]); 5876 } 5877 5878 for (i = 8; i < 32; ++i) { 5879 cpu_regs[i] = tcg_global_mem_new(cpu_regwptr, 5880 (i - 8) * sizeof(target_ulong), 5881 gregnames[i]); 5882 } 5883 } 5884 5885 void sparc_restore_state_to_opc(CPUState *cs, 5886 const TranslationBlock *tb, 5887 const uint64_t *data) 5888 { 5889 CPUSPARCState *env = cpu_env(cs); 5890 target_ulong pc = data[0]; 5891 target_ulong npc = data[1]; 5892 5893 env->pc = pc; 5894 if (npc == DYNAMIC_PC) { 5895 /* dynamic NPC: already stored */ 5896 } else if (npc & JUMP_PC) { 5897 /* jump PC: use 'cond' and the jump targets of the translation */ 5898 if (env->cond) { 5899 env->npc = npc & ~3; 5900 } else { 5901 env->npc = pc + 4; 5902 } 5903 } else { 5904 env->npc = npc; 5905 } 5906 } 5907