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 int 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 1; 1474 } 1475 #endif 1476 return 0; 1477 } 1478 1479 /* asi moves */ 1480 typedef enum { 1481 GET_ASI_HELPER, 1482 GET_ASI_EXCP, 1483 GET_ASI_DIRECT, 1484 GET_ASI_DTWINX, 1485 GET_ASI_CODE, 1486 GET_ASI_BLOCK, 1487 GET_ASI_SHORT, 1488 GET_ASI_BCOPY, 1489 GET_ASI_BFILL, 1490 } ASIType; 1491 1492 typedef struct { 1493 ASIType type; 1494 int asi; 1495 int mem_idx; 1496 MemOp memop; 1497 } DisasASI; 1498 1499 /* 1500 * Build DisasASI. 1501 * For asi == -1, treat as non-asi. 1502 * For ask == -2, treat as immediate offset (v8 error, v9 %asi). 1503 */ 1504 static DisasASI resolve_asi(DisasContext *dc, int asi, MemOp memop) 1505 { 1506 ASIType type = GET_ASI_HELPER; 1507 int mem_idx = dc->mem_idx; 1508 1509 if (asi == -1) { 1510 /* Artificial "non-asi" case. */ 1511 type = GET_ASI_DIRECT; 1512 goto done; 1513 } 1514 1515 #ifndef TARGET_SPARC64 1516 /* Before v9, all asis are immediate and privileged. */ 1517 if (asi < 0) { 1518 gen_exception(dc, TT_ILL_INSN); 1519 type = GET_ASI_EXCP; 1520 } else if (supervisor(dc) 1521 /* Note that LEON accepts ASI_USERDATA in user mode, for 1522 use with CASA. Also note that previous versions of 1523 QEMU allowed (and old versions of gcc emitted) ASI_P 1524 for LEON, which is incorrect. */ 1525 || (asi == ASI_USERDATA 1526 && (dc->def->features & CPU_FEATURE_CASA))) { 1527 switch (asi) { 1528 case ASI_USERDATA: /* User data access */ 1529 mem_idx = MMU_USER_IDX; 1530 type = GET_ASI_DIRECT; 1531 break; 1532 case ASI_KERNELDATA: /* Supervisor data access */ 1533 mem_idx = MMU_KERNEL_IDX; 1534 type = GET_ASI_DIRECT; 1535 break; 1536 case ASI_USERTXT: /* User text access */ 1537 mem_idx = MMU_USER_IDX; 1538 type = GET_ASI_CODE; 1539 break; 1540 case ASI_KERNELTXT: /* Supervisor text access */ 1541 mem_idx = MMU_KERNEL_IDX; 1542 type = GET_ASI_CODE; 1543 break; 1544 case ASI_M_BYPASS: /* MMU passthrough */ 1545 case ASI_LEON_BYPASS: /* LEON MMU passthrough */ 1546 mem_idx = MMU_PHYS_IDX; 1547 type = GET_ASI_DIRECT; 1548 break; 1549 case ASI_M_BCOPY: /* Block copy, sta access */ 1550 mem_idx = MMU_KERNEL_IDX; 1551 type = GET_ASI_BCOPY; 1552 break; 1553 case ASI_M_BFILL: /* Block fill, stda access */ 1554 mem_idx = MMU_KERNEL_IDX; 1555 type = GET_ASI_BFILL; 1556 break; 1557 } 1558 1559 /* MMU_PHYS_IDX is used when the MMU is disabled to passthrough the 1560 * permissions check in get_physical_address(..). 1561 */ 1562 mem_idx = (dc->mem_idx == MMU_PHYS_IDX) ? MMU_PHYS_IDX : mem_idx; 1563 } else { 1564 gen_exception(dc, TT_PRIV_INSN); 1565 type = GET_ASI_EXCP; 1566 } 1567 #else 1568 if (asi < 0) { 1569 asi = dc->asi; 1570 } 1571 /* With v9, all asis below 0x80 are privileged. */ 1572 /* ??? We ought to check cpu_has_hypervisor, but we didn't copy 1573 down that bit into DisasContext. For the moment that's ok, 1574 since the direct implementations below doesn't have any ASIs 1575 in the restricted [0x30, 0x7f] range, and the check will be 1576 done properly in the helper. */ 1577 if (!supervisor(dc) && asi < 0x80) { 1578 gen_exception(dc, TT_PRIV_ACT); 1579 type = GET_ASI_EXCP; 1580 } else { 1581 switch (asi) { 1582 case ASI_REAL: /* Bypass */ 1583 case ASI_REAL_IO: /* Bypass, non-cacheable */ 1584 case ASI_REAL_L: /* Bypass LE */ 1585 case ASI_REAL_IO_L: /* Bypass, non-cacheable LE */ 1586 case ASI_TWINX_REAL: /* Real address, twinx */ 1587 case ASI_TWINX_REAL_L: /* Real address, twinx, LE */ 1588 case ASI_QUAD_LDD_PHYS: 1589 case ASI_QUAD_LDD_PHYS_L: 1590 mem_idx = MMU_PHYS_IDX; 1591 break; 1592 case ASI_N: /* Nucleus */ 1593 case ASI_NL: /* Nucleus LE */ 1594 case ASI_TWINX_N: 1595 case ASI_TWINX_NL: 1596 case ASI_NUCLEUS_QUAD_LDD: 1597 case ASI_NUCLEUS_QUAD_LDD_L: 1598 if (hypervisor(dc)) { 1599 mem_idx = MMU_PHYS_IDX; 1600 } else { 1601 mem_idx = MMU_NUCLEUS_IDX; 1602 } 1603 break; 1604 case ASI_AIUP: /* As if user primary */ 1605 case ASI_AIUPL: /* As if user primary LE */ 1606 case ASI_TWINX_AIUP: 1607 case ASI_TWINX_AIUP_L: 1608 case ASI_BLK_AIUP_4V: 1609 case ASI_BLK_AIUP_L_4V: 1610 case ASI_BLK_AIUP: 1611 case ASI_BLK_AIUPL: 1612 case ASI_MON_AIUP: 1613 mem_idx = MMU_USER_IDX; 1614 break; 1615 case ASI_AIUS: /* As if user secondary */ 1616 case ASI_AIUSL: /* As if user secondary LE */ 1617 case ASI_TWINX_AIUS: 1618 case ASI_TWINX_AIUS_L: 1619 case ASI_BLK_AIUS_4V: 1620 case ASI_BLK_AIUS_L_4V: 1621 case ASI_BLK_AIUS: 1622 case ASI_BLK_AIUSL: 1623 case ASI_MON_AIUS: 1624 mem_idx = MMU_USER_SECONDARY_IDX; 1625 break; 1626 case ASI_S: /* Secondary */ 1627 case ASI_SL: /* Secondary LE */ 1628 case ASI_TWINX_S: 1629 case ASI_TWINX_SL: 1630 case ASI_BLK_COMMIT_S: 1631 case ASI_BLK_S: 1632 case ASI_BLK_SL: 1633 case ASI_FL8_S: 1634 case ASI_FL8_SL: 1635 case ASI_FL16_S: 1636 case ASI_FL16_SL: 1637 case ASI_MON_S: 1638 if (mem_idx == MMU_USER_IDX) { 1639 mem_idx = MMU_USER_SECONDARY_IDX; 1640 } else if (mem_idx == MMU_KERNEL_IDX) { 1641 mem_idx = MMU_KERNEL_SECONDARY_IDX; 1642 } 1643 break; 1644 case ASI_P: /* Primary */ 1645 case ASI_PL: /* Primary LE */ 1646 case ASI_TWINX_P: 1647 case ASI_TWINX_PL: 1648 case ASI_BLK_COMMIT_P: 1649 case ASI_BLK_P: 1650 case ASI_BLK_PL: 1651 case ASI_FL8_P: 1652 case ASI_FL8_PL: 1653 case ASI_FL16_P: 1654 case ASI_FL16_PL: 1655 case ASI_MON_P: 1656 break; 1657 } 1658 switch (asi) { 1659 case ASI_REAL: 1660 case ASI_REAL_IO: 1661 case ASI_REAL_L: 1662 case ASI_REAL_IO_L: 1663 case ASI_N: 1664 case ASI_NL: 1665 case ASI_AIUP: 1666 case ASI_AIUPL: 1667 case ASI_AIUS: 1668 case ASI_AIUSL: 1669 case ASI_S: 1670 case ASI_SL: 1671 case ASI_P: 1672 case ASI_PL: 1673 case ASI_MON_P: 1674 case ASI_MON_S: 1675 case ASI_MON_AIUP: 1676 case ASI_MON_AIUS: 1677 type = GET_ASI_DIRECT; 1678 break; 1679 case ASI_TWINX_REAL: 1680 case ASI_TWINX_REAL_L: 1681 case ASI_TWINX_N: 1682 case ASI_TWINX_NL: 1683 case ASI_TWINX_AIUP: 1684 case ASI_TWINX_AIUP_L: 1685 case ASI_TWINX_AIUS: 1686 case ASI_TWINX_AIUS_L: 1687 case ASI_TWINX_P: 1688 case ASI_TWINX_PL: 1689 case ASI_TWINX_S: 1690 case ASI_TWINX_SL: 1691 case ASI_QUAD_LDD_PHYS: 1692 case ASI_QUAD_LDD_PHYS_L: 1693 case ASI_NUCLEUS_QUAD_LDD: 1694 case ASI_NUCLEUS_QUAD_LDD_L: 1695 type = GET_ASI_DTWINX; 1696 break; 1697 case ASI_BLK_COMMIT_P: 1698 case ASI_BLK_COMMIT_S: 1699 case ASI_BLK_AIUP_4V: 1700 case ASI_BLK_AIUP_L_4V: 1701 case ASI_BLK_AIUP: 1702 case ASI_BLK_AIUPL: 1703 case ASI_BLK_AIUS_4V: 1704 case ASI_BLK_AIUS_L_4V: 1705 case ASI_BLK_AIUS: 1706 case ASI_BLK_AIUSL: 1707 case ASI_BLK_S: 1708 case ASI_BLK_SL: 1709 case ASI_BLK_P: 1710 case ASI_BLK_PL: 1711 type = GET_ASI_BLOCK; 1712 break; 1713 case ASI_FL8_S: 1714 case ASI_FL8_SL: 1715 case ASI_FL8_P: 1716 case ASI_FL8_PL: 1717 memop = MO_UB; 1718 type = GET_ASI_SHORT; 1719 break; 1720 case ASI_FL16_S: 1721 case ASI_FL16_SL: 1722 case ASI_FL16_P: 1723 case ASI_FL16_PL: 1724 memop = MO_TEUW; 1725 type = GET_ASI_SHORT; 1726 break; 1727 } 1728 /* The little-endian asis all have bit 3 set. */ 1729 if (asi & 8) { 1730 memop ^= MO_BSWAP; 1731 } 1732 } 1733 #endif 1734 1735 done: 1736 return (DisasASI){ type, asi, mem_idx, memop }; 1737 } 1738 1739 #if defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64) 1740 static void gen_helper_ld_asi(TCGv_i64 r, TCGv_env e, TCGv a, 1741 TCGv_i32 asi, TCGv_i32 mop) 1742 { 1743 g_assert_not_reached(); 1744 } 1745 1746 static void gen_helper_st_asi(TCGv_env e, TCGv a, TCGv_i64 r, 1747 TCGv_i32 asi, TCGv_i32 mop) 1748 { 1749 g_assert_not_reached(); 1750 } 1751 #endif 1752 1753 static void gen_ld_asi(DisasContext *dc, DisasASI *da, TCGv dst, TCGv addr) 1754 { 1755 switch (da->type) { 1756 case GET_ASI_EXCP: 1757 break; 1758 case GET_ASI_DTWINX: /* Reserved for ldda. */ 1759 gen_exception(dc, TT_ILL_INSN); 1760 break; 1761 case GET_ASI_DIRECT: 1762 tcg_gen_qemu_ld_tl(dst, addr, da->mem_idx, da->memop | MO_ALIGN); 1763 break; 1764 1765 case GET_ASI_CODE: 1766 #if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64) 1767 { 1768 MemOpIdx oi = make_memop_idx(da->memop, da->mem_idx); 1769 TCGv_i64 t64 = tcg_temp_new_i64(); 1770 1771 gen_helper_ld_code(t64, tcg_env, addr, tcg_constant_i32(oi)); 1772 tcg_gen_trunc_i64_tl(dst, t64); 1773 } 1774 break; 1775 #else 1776 g_assert_not_reached(); 1777 #endif 1778 1779 default: 1780 { 1781 TCGv_i32 r_asi = tcg_constant_i32(da->asi); 1782 TCGv_i32 r_mop = tcg_constant_i32(da->memop | MO_ALIGN); 1783 1784 save_state(dc); 1785 #ifdef TARGET_SPARC64 1786 gen_helper_ld_asi(dst, tcg_env, addr, r_asi, r_mop); 1787 #else 1788 { 1789 TCGv_i64 t64 = tcg_temp_new_i64(); 1790 gen_helper_ld_asi(t64, tcg_env, addr, r_asi, r_mop); 1791 tcg_gen_trunc_i64_tl(dst, t64); 1792 } 1793 #endif 1794 } 1795 break; 1796 } 1797 } 1798 1799 static void gen_st_asi(DisasContext *dc, DisasASI *da, TCGv src, TCGv addr) 1800 { 1801 switch (da->type) { 1802 case GET_ASI_EXCP: 1803 break; 1804 1805 case GET_ASI_DTWINX: /* Reserved for stda. */ 1806 if (TARGET_LONG_BITS == 32) { 1807 gen_exception(dc, TT_ILL_INSN); 1808 break; 1809 } else if (!(dc->def->features & CPU_FEATURE_HYPV)) { 1810 /* Pre OpenSPARC CPUs don't have these */ 1811 gen_exception(dc, TT_ILL_INSN); 1812 break; 1813 } 1814 /* In OpenSPARC T1+ CPUs TWINX ASIs in store are ST_BLKINIT_ ASIs */ 1815 /* fall through */ 1816 1817 case GET_ASI_DIRECT: 1818 tcg_gen_qemu_st_tl(src, addr, da->mem_idx, da->memop | MO_ALIGN); 1819 break; 1820 1821 case GET_ASI_BCOPY: 1822 assert(TARGET_LONG_BITS == 32); 1823 /* 1824 * Copy 32 bytes from the address in SRC to ADDR. 1825 * 1826 * From Ross RT625 hyperSPARC manual, section 4.6: 1827 * "Block Copy and Block Fill will work only on cache line boundaries." 1828 * 1829 * It does not specify if an unaliged address is truncated or trapped. 1830 * Previous qemu behaviour was to truncate to 4 byte alignment, which 1831 * is obviously wrong. The only place I can see this used is in the 1832 * Linux kernel which begins with page alignment, advancing by 32, 1833 * so is always aligned. Assume truncation as the simpler option. 1834 * 1835 * Since the loads and stores are paired, allow the copy to happen 1836 * in the host endianness. The copy need not be atomic. 1837 */ 1838 { 1839 MemOp mop = MO_128 | MO_ATOM_IFALIGN_PAIR; 1840 TCGv saddr = tcg_temp_new(); 1841 TCGv daddr = tcg_temp_new(); 1842 TCGv_i128 tmp = tcg_temp_new_i128(); 1843 1844 tcg_gen_andi_tl(saddr, src, -32); 1845 tcg_gen_andi_tl(daddr, addr, -32); 1846 tcg_gen_qemu_ld_i128(tmp, saddr, da->mem_idx, mop); 1847 tcg_gen_qemu_st_i128(tmp, daddr, da->mem_idx, mop); 1848 tcg_gen_addi_tl(saddr, saddr, 16); 1849 tcg_gen_addi_tl(daddr, daddr, 16); 1850 tcg_gen_qemu_ld_i128(tmp, saddr, da->mem_idx, mop); 1851 tcg_gen_qemu_st_i128(tmp, daddr, da->mem_idx, mop); 1852 } 1853 break; 1854 1855 default: 1856 { 1857 TCGv_i32 r_asi = tcg_constant_i32(da->asi); 1858 TCGv_i32 r_mop = tcg_constant_i32(da->memop | MO_ALIGN); 1859 1860 save_state(dc); 1861 #ifdef TARGET_SPARC64 1862 gen_helper_st_asi(tcg_env, addr, src, r_asi, r_mop); 1863 #else 1864 { 1865 TCGv_i64 t64 = tcg_temp_new_i64(); 1866 tcg_gen_extu_tl_i64(t64, src); 1867 gen_helper_st_asi(tcg_env, addr, t64, r_asi, r_mop); 1868 } 1869 #endif 1870 1871 /* A write to a TLB register may alter page maps. End the TB. */ 1872 dc->npc = DYNAMIC_PC; 1873 } 1874 break; 1875 } 1876 } 1877 1878 static void gen_swap_asi(DisasContext *dc, DisasASI *da, 1879 TCGv dst, TCGv src, TCGv addr) 1880 { 1881 switch (da->type) { 1882 case GET_ASI_EXCP: 1883 break; 1884 case GET_ASI_DIRECT: 1885 tcg_gen_atomic_xchg_tl(dst, addr, src, 1886 da->mem_idx, da->memop | MO_ALIGN); 1887 break; 1888 default: 1889 /* ??? Should be DAE_invalid_asi. */ 1890 gen_exception(dc, TT_DATA_ACCESS); 1891 break; 1892 } 1893 } 1894 1895 static void gen_cas_asi(DisasContext *dc, DisasASI *da, 1896 TCGv oldv, TCGv newv, TCGv cmpv, TCGv addr) 1897 { 1898 switch (da->type) { 1899 case GET_ASI_EXCP: 1900 return; 1901 case GET_ASI_DIRECT: 1902 tcg_gen_atomic_cmpxchg_tl(oldv, addr, cmpv, newv, 1903 da->mem_idx, da->memop | MO_ALIGN); 1904 break; 1905 default: 1906 /* ??? Should be DAE_invalid_asi. */ 1907 gen_exception(dc, TT_DATA_ACCESS); 1908 break; 1909 } 1910 } 1911 1912 static void gen_ldstub_asi(DisasContext *dc, DisasASI *da, TCGv dst, 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, tcg_constant_tl(0xff), 1919 da->mem_idx, MO_UB); 1920 break; 1921 default: 1922 /* ??? In theory, this should be raise DAE_invalid_asi. 1923 But the SS-20 roms do ldstuba [%l0] #ASI_M_CTL, %o1. */ 1924 if (tb_cflags(dc->base.tb) & CF_PARALLEL) { 1925 gen_helper_exit_atomic(tcg_env); 1926 } else { 1927 TCGv_i32 r_asi = tcg_constant_i32(da->asi); 1928 TCGv_i32 r_mop = tcg_constant_i32(MO_UB); 1929 TCGv_i64 s64, t64; 1930 1931 save_state(dc); 1932 t64 = tcg_temp_new_i64(); 1933 gen_helper_ld_asi(t64, tcg_env, addr, r_asi, r_mop); 1934 1935 s64 = tcg_constant_i64(0xff); 1936 gen_helper_st_asi(tcg_env, addr, s64, r_asi, r_mop); 1937 1938 tcg_gen_trunc_i64_tl(dst, t64); 1939 1940 /* End the TB. */ 1941 dc->npc = DYNAMIC_PC; 1942 } 1943 break; 1944 } 1945 } 1946 1947 static void gen_ldf_asi(DisasContext *dc, DisasASI *da, MemOp orig_size, 1948 TCGv addr, int rd) 1949 { 1950 MemOp memop = da->memop; 1951 MemOp size = memop & MO_SIZE; 1952 TCGv_i32 d32; 1953 TCGv_i64 d64, l64; 1954 TCGv addr_tmp; 1955 1956 /* TODO: Use 128-bit load/store below. */ 1957 if (size == MO_128) { 1958 memop = (memop & ~MO_SIZE) | MO_64; 1959 } 1960 1961 switch (da->type) { 1962 case GET_ASI_EXCP: 1963 break; 1964 1965 case GET_ASI_DIRECT: 1966 memop |= MO_ALIGN_4; 1967 switch (size) { 1968 case MO_32: 1969 d32 = tcg_temp_new_i32(); 1970 tcg_gen_qemu_ld_i32(d32, addr, da->mem_idx, memop); 1971 gen_store_fpr_F(dc, rd, d32); 1972 break; 1973 1974 case MO_64: 1975 d64 = tcg_temp_new_i64(); 1976 tcg_gen_qemu_ld_i64(d64, addr, da->mem_idx, memop); 1977 gen_store_fpr_D(dc, rd, d64); 1978 break; 1979 1980 case MO_128: 1981 d64 = tcg_temp_new_i64(); 1982 l64 = tcg_temp_new_i64(); 1983 tcg_gen_qemu_ld_i64(d64, addr, da->mem_idx, memop); 1984 addr_tmp = tcg_temp_new(); 1985 tcg_gen_addi_tl(addr_tmp, addr, 8); 1986 tcg_gen_qemu_ld_i64(l64, addr_tmp, da->mem_idx, memop); 1987 gen_store_fpr_D(dc, rd, d64); 1988 gen_store_fpr_D(dc, rd + 2, l64); 1989 break; 1990 default: 1991 g_assert_not_reached(); 1992 } 1993 break; 1994 1995 case GET_ASI_BLOCK: 1996 /* Valid for lddfa on aligned registers only. */ 1997 if (orig_size == MO_64 && (rd & 7) == 0) { 1998 /* The first operation checks required alignment. */ 1999 addr_tmp = tcg_temp_new(); 2000 d64 = tcg_temp_new_i64(); 2001 for (int i = 0; ; ++i) { 2002 tcg_gen_qemu_ld_i64(d64, addr, da->mem_idx, 2003 memop | (i == 0 ? MO_ALIGN_64 : 0)); 2004 gen_store_fpr_D(dc, rd + 2 * i, d64); 2005 if (i == 7) { 2006 break; 2007 } 2008 tcg_gen_addi_tl(addr_tmp, addr, 8); 2009 addr = addr_tmp; 2010 } 2011 } else { 2012 gen_exception(dc, TT_ILL_INSN); 2013 } 2014 break; 2015 2016 case GET_ASI_SHORT: 2017 /* Valid for lddfa only. */ 2018 if (orig_size == MO_64) { 2019 d64 = tcg_temp_new_i64(); 2020 tcg_gen_qemu_ld_i64(d64, addr, da->mem_idx, memop | MO_ALIGN); 2021 gen_store_fpr_D(dc, rd, d64); 2022 } else { 2023 gen_exception(dc, TT_ILL_INSN); 2024 } 2025 break; 2026 2027 default: 2028 { 2029 TCGv_i32 r_asi = tcg_constant_i32(da->asi); 2030 TCGv_i32 r_mop = tcg_constant_i32(memop | MO_ALIGN); 2031 2032 save_state(dc); 2033 /* According to the table in the UA2011 manual, the only 2034 other asis that are valid for ldfa/lddfa/ldqfa are 2035 the NO_FAULT asis. We still need a helper for these, 2036 but we can just use the integer asi helper for them. */ 2037 switch (size) { 2038 case MO_32: 2039 d64 = tcg_temp_new_i64(); 2040 gen_helper_ld_asi(d64, tcg_env, addr, r_asi, r_mop); 2041 d32 = tcg_temp_new_i32(); 2042 tcg_gen_extrl_i64_i32(d32, d64); 2043 gen_store_fpr_F(dc, rd, d32); 2044 break; 2045 case MO_64: 2046 d64 = tcg_temp_new_i64(); 2047 gen_helper_ld_asi(d64, tcg_env, addr, r_asi, r_mop); 2048 gen_store_fpr_D(dc, rd, d64); 2049 break; 2050 case MO_128: 2051 d64 = tcg_temp_new_i64(); 2052 l64 = tcg_temp_new_i64(); 2053 gen_helper_ld_asi(d64, tcg_env, addr, r_asi, r_mop); 2054 addr_tmp = tcg_temp_new(); 2055 tcg_gen_addi_tl(addr_tmp, addr, 8); 2056 gen_helper_ld_asi(l64, tcg_env, addr_tmp, r_asi, r_mop); 2057 gen_store_fpr_D(dc, rd, d64); 2058 gen_store_fpr_D(dc, rd + 2, l64); 2059 break; 2060 default: 2061 g_assert_not_reached(); 2062 } 2063 } 2064 break; 2065 } 2066 } 2067 2068 static void gen_stf_asi(DisasContext *dc, DisasASI *da, MemOp orig_size, 2069 TCGv addr, int rd) 2070 { 2071 MemOp memop = da->memop; 2072 MemOp size = memop & MO_SIZE; 2073 TCGv_i32 d32; 2074 TCGv_i64 d64; 2075 TCGv addr_tmp; 2076 2077 /* TODO: Use 128-bit load/store below. */ 2078 if (size == MO_128) { 2079 memop = (memop & ~MO_SIZE) | MO_64; 2080 } 2081 2082 switch (da->type) { 2083 case GET_ASI_EXCP: 2084 break; 2085 2086 case GET_ASI_DIRECT: 2087 memop |= MO_ALIGN_4; 2088 switch (size) { 2089 case MO_32: 2090 d32 = gen_load_fpr_F(dc, rd); 2091 tcg_gen_qemu_st_i32(d32, addr, da->mem_idx, memop | MO_ALIGN); 2092 break; 2093 case MO_64: 2094 d64 = gen_load_fpr_D(dc, rd); 2095 tcg_gen_qemu_st_i64(d64, addr, da->mem_idx, memop | MO_ALIGN_4); 2096 break; 2097 case MO_128: 2098 /* Only 4-byte alignment required. However, it is legal for the 2099 cpu to signal the alignment fault, and the OS trap handler is 2100 required to fix it up. Requiring 16-byte alignment here avoids 2101 having to probe the second page before performing the first 2102 write. */ 2103 d64 = gen_load_fpr_D(dc, rd); 2104 tcg_gen_qemu_st_i64(d64, addr, da->mem_idx, memop | MO_ALIGN_16); 2105 addr_tmp = tcg_temp_new(); 2106 tcg_gen_addi_tl(addr_tmp, addr, 8); 2107 d64 = gen_load_fpr_D(dc, rd + 2); 2108 tcg_gen_qemu_st_i64(d64, addr_tmp, da->mem_idx, memop); 2109 break; 2110 default: 2111 g_assert_not_reached(); 2112 } 2113 break; 2114 2115 case GET_ASI_BLOCK: 2116 /* Valid for stdfa on aligned registers only. */ 2117 if (orig_size == MO_64 && (rd & 7) == 0) { 2118 /* The first operation checks required alignment. */ 2119 addr_tmp = tcg_temp_new(); 2120 for (int i = 0; ; ++i) { 2121 d64 = gen_load_fpr_D(dc, rd + 2 * i); 2122 tcg_gen_qemu_st_i64(d64, addr, da->mem_idx, 2123 memop | (i == 0 ? MO_ALIGN_64 : 0)); 2124 if (i == 7) { 2125 break; 2126 } 2127 tcg_gen_addi_tl(addr_tmp, addr, 8); 2128 addr = addr_tmp; 2129 } 2130 } else { 2131 gen_exception(dc, TT_ILL_INSN); 2132 } 2133 break; 2134 2135 case GET_ASI_SHORT: 2136 /* Valid for stdfa only. */ 2137 if (orig_size == MO_64) { 2138 d64 = gen_load_fpr_D(dc, rd); 2139 tcg_gen_qemu_st_i64(d64, addr, da->mem_idx, memop | MO_ALIGN); 2140 } else { 2141 gen_exception(dc, TT_ILL_INSN); 2142 } 2143 break; 2144 2145 default: 2146 /* According to the table in the UA2011 manual, the only 2147 other asis that are valid for ldfa/lddfa/ldqfa are 2148 the PST* asis, which aren't currently handled. */ 2149 gen_exception(dc, TT_ILL_INSN); 2150 break; 2151 } 2152 } 2153 2154 static void gen_ldda_asi(DisasContext *dc, DisasASI *da, TCGv addr, int rd) 2155 { 2156 TCGv hi = gen_dest_gpr(dc, rd); 2157 TCGv lo = gen_dest_gpr(dc, rd + 1); 2158 2159 switch (da->type) { 2160 case GET_ASI_EXCP: 2161 return; 2162 2163 case GET_ASI_DTWINX: 2164 #ifdef TARGET_SPARC64 2165 { 2166 MemOp mop = (da->memop & MO_BSWAP) | MO_128 | MO_ALIGN_16; 2167 TCGv_i128 t = tcg_temp_new_i128(); 2168 2169 tcg_gen_qemu_ld_i128(t, addr, da->mem_idx, mop); 2170 /* 2171 * Note that LE twinx acts as if each 64-bit register result is 2172 * byte swapped. We perform one 128-bit LE load, so must swap 2173 * the order of the writebacks. 2174 */ 2175 if ((mop & MO_BSWAP) == MO_TE) { 2176 tcg_gen_extr_i128_i64(lo, hi, t); 2177 } else { 2178 tcg_gen_extr_i128_i64(hi, lo, t); 2179 } 2180 } 2181 break; 2182 #else 2183 g_assert_not_reached(); 2184 #endif 2185 2186 case GET_ASI_DIRECT: 2187 { 2188 TCGv_i64 tmp = tcg_temp_new_i64(); 2189 2190 tcg_gen_qemu_ld_i64(tmp, addr, da->mem_idx, da->memop | MO_ALIGN); 2191 2192 /* Note that LE ldda acts as if each 32-bit register 2193 result is byte swapped. Having just performed one 2194 64-bit bswap, we need now to swap the writebacks. */ 2195 if ((da->memop & MO_BSWAP) == MO_TE) { 2196 tcg_gen_extr_i64_tl(lo, hi, tmp); 2197 } else { 2198 tcg_gen_extr_i64_tl(hi, lo, tmp); 2199 } 2200 } 2201 break; 2202 2203 case GET_ASI_CODE: 2204 #if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64) 2205 { 2206 MemOpIdx oi = make_memop_idx(da->memop, da->mem_idx); 2207 TCGv_i64 tmp = tcg_temp_new_i64(); 2208 2209 gen_helper_ld_code(tmp, tcg_env, addr, tcg_constant_i32(oi)); 2210 2211 /* See above. */ 2212 if ((da->memop & MO_BSWAP) == MO_TE) { 2213 tcg_gen_extr_i64_tl(lo, hi, tmp); 2214 } else { 2215 tcg_gen_extr_i64_tl(hi, lo, tmp); 2216 } 2217 } 2218 break; 2219 #else 2220 g_assert_not_reached(); 2221 #endif 2222 2223 default: 2224 /* ??? In theory we've handled all of the ASIs that are valid 2225 for ldda, and this should raise DAE_invalid_asi. However, 2226 real hardware allows others. This can be seen with e.g. 2227 FreeBSD 10.3 wrt ASI_IC_TAG. */ 2228 { 2229 TCGv_i32 r_asi = tcg_constant_i32(da->asi); 2230 TCGv_i32 r_mop = tcg_constant_i32(da->memop); 2231 TCGv_i64 tmp = tcg_temp_new_i64(); 2232 2233 save_state(dc); 2234 gen_helper_ld_asi(tmp, tcg_env, addr, r_asi, r_mop); 2235 2236 /* See above. */ 2237 if ((da->memop & MO_BSWAP) == MO_TE) { 2238 tcg_gen_extr_i64_tl(lo, hi, tmp); 2239 } else { 2240 tcg_gen_extr_i64_tl(hi, lo, tmp); 2241 } 2242 } 2243 break; 2244 } 2245 2246 gen_store_gpr(dc, rd, hi); 2247 gen_store_gpr(dc, rd + 1, lo); 2248 } 2249 2250 static void gen_stda_asi(DisasContext *dc, DisasASI *da, TCGv addr, int rd) 2251 { 2252 TCGv hi = gen_load_gpr(dc, rd); 2253 TCGv lo = gen_load_gpr(dc, rd + 1); 2254 2255 switch (da->type) { 2256 case GET_ASI_EXCP: 2257 break; 2258 2259 case GET_ASI_DTWINX: 2260 #ifdef TARGET_SPARC64 2261 { 2262 MemOp mop = (da->memop & MO_BSWAP) | MO_128 | MO_ALIGN_16; 2263 TCGv_i128 t = tcg_temp_new_i128(); 2264 2265 /* 2266 * Note that LE twinx acts as if each 64-bit register result is 2267 * byte swapped. We perform one 128-bit LE store, so must swap 2268 * the order of the construction. 2269 */ 2270 if ((mop & MO_BSWAP) == MO_TE) { 2271 tcg_gen_concat_i64_i128(t, lo, hi); 2272 } else { 2273 tcg_gen_concat_i64_i128(t, hi, lo); 2274 } 2275 tcg_gen_qemu_st_i128(t, addr, da->mem_idx, mop); 2276 } 2277 break; 2278 #else 2279 g_assert_not_reached(); 2280 #endif 2281 2282 case GET_ASI_DIRECT: 2283 { 2284 TCGv_i64 t64 = tcg_temp_new_i64(); 2285 2286 /* Note that LE stda acts as if each 32-bit register result is 2287 byte swapped. We will perform one 64-bit LE store, so now 2288 we must swap the order of the construction. */ 2289 if ((da->memop & MO_BSWAP) == MO_TE) { 2290 tcg_gen_concat_tl_i64(t64, lo, hi); 2291 } else { 2292 tcg_gen_concat_tl_i64(t64, hi, lo); 2293 } 2294 tcg_gen_qemu_st_i64(t64, addr, da->mem_idx, da->memop | MO_ALIGN); 2295 } 2296 break; 2297 2298 case GET_ASI_BFILL: 2299 assert(TARGET_LONG_BITS == 32); 2300 /* 2301 * Store 32 bytes of [rd:rd+1] to ADDR. 2302 * See comments for GET_ASI_COPY above. 2303 */ 2304 { 2305 MemOp mop = MO_TE | MO_128 | MO_ATOM_IFALIGN_PAIR; 2306 TCGv_i64 t8 = tcg_temp_new_i64(); 2307 TCGv_i128 t16 = tcg_temp_new_i128(); 2308 TCGv daddr = tcg_temp_new(); 2309 2310 tcg_gen_concat_tl_i64(t8, lo, hi); 2311 tcg_gen_concat_i64_i128(t16, t8, t8); 2312 tcg_gen_andi_tl(daddr, addr, -32); 2313 tcg_gen_qemu_st_i128(t16, daddr, da->mem_idx, mop); 2314 tcg_gen_addi_tl(daddr, daddr, 16); 2315 tcg_gen_qemu_st_i128(t16, daddr, da->mem_idx, mop); 2316 } 2317 break; 2318 2319 default: 2320 /* ??? In theory we've handled all of the ASIs that are valid 2321 for stda, and this should raise DAE_invalid_asi. */ 2322 { 2323 TCGv_i32 r_asi = tcg_constant_i32(da->asi); 2324 TCGv_i32 r_mop = tcg_constant_i32(da->memop); 2325 TCGv_i64 t64 = tcg_temp_new_i64(); 2326 2327 /* See above. */ 2328 if ((da->memop & MO_BSWAP) == MO_TE) { 2329 tcg_gen_concat_tl_i64(t64, lo, hi); 2330 } else { 2331 tcg_gen_concat_tl_i64(t64, hi, lo); 2332 } 2333 2334 save_state(dc); 2335 gen_helper_st_asi(tcg_env, addr, t64, r_asi, r_mop); 2336 } 2337 break; 2338 } 2339 } 2340 2341 static void gen_fmovs(DisasContext *dc, DisasCompare *cmp, int rd, int rs) 2342 { 2343 #ifdef TARGET_SPARC64 2344 TCGv_i32 c32, zero, dst, s1, s2; 2345 TCGv_i64 c64 = tcg_temp_new_i64(); 2346 2347 /* We have two choices here: extend the 32 bit data and use movcond_i64, 2348 or fold the comparison down to 32 bits and use movcond_i32. Choose 2349 the later. */ 2350 c32 = tcg_temp_new_i32(); 2351 tcg_gen_setcondi_i64(cmp->cond, c64, cmp->c1, cmp->c2); 2352 tcg_gen_extrl_i64_i32(c32, c64); 2353 2354 s1 = gen_load_fpr_F(dc, rs); 2355 s2 = gen_load_fpr_F(dc, rd); 2356 dst = tcg_temp_new_i32(); 2357 zero = tcg_constant_i32(0); 2358 2359 tcg_gen_movcond_i32(TCG_COND_NE, dst, c32, zero, s1, s2); 2360 2361 gen_store_fpr_F(dc, rd, dst); 2362 #else 2363 qemu_build_not_reached(); 2364 #endif 2365 } 2366 2367 static void gen_fmovd(DisasContext *dc, DisasCompare *cmp, int rd, int rs) 2368 { 2369 #ifdef TARGET_SPARC64 2370 TCGv_i64 dst = tcg_temp_new_i64(); 2371 tcg_gen_movcond_i64(cmp->cond, dst, cmp->c1, tcg_constant_tl(cmp->c2), 2372 gen_load_fpr_D(dc, rs), 2373 gen_load_fpr_D(dc, rd)); 2374 gen_store_fpr_D(dc, rd, dst); 2375 #else 2376 qemu_build_not_reached(); 2377 #endif 2378 } 2379 2380 static void gen_fmovq(DisasContext *dc, DisasCompare *cmp, int rd, int rs) 2381 { 2382 #ifdef TARGET_SPARC64 2383 TCGv c2 = tcg_constant_tl(cmp->c2); 2384 TCGv_i64 h = tcg_temp_new_i64(); 2385 TCGv_i64 l = tcg_temp_new_i64(); 2386 2387 tcg_gen_movcond_i64(cmp->cond, h, cmp->c1, c2, 2388 gen_load_fpr_D(dc, rs), 2389 gen_load_fpr_D(dc, rd)); 2390 tcg_gen_movcond_i64(cmp->cond, l, cmp->c1, c2, 2391 gen_load_fpr_D(dc, rs + 2), 2392 gen_load_fpr_D(dc, rd + 2)); 2393 gen_store_fpr_D(dc, rd, h); 2394 gen_store_fpr_D(dc, rd + 2, l); 2395 #else 2396 qemu_build_not_reached(); 2397 #endif 2398 } 2399 2400 #ifdef TARGET_SPARC64 2401 static void gen_load_trap_state_at_tl(TCGv_ptr r_tsptr) 2402 { 2403 TCGv_i32 r_tl = tcg_temp_new_i32(); 2404 2405 /* load env->tl into r_tl */ 2406 tcg_gen_ld_i32(r_tl, tcg_env, offsetof(CPUSPARCState, tl)); 2407 2408 /* tl = [0 ... MAXTL_MASK] where MAXTL_MASK must be power of 2 */ 2409 tcg_gen_andi_i32(r_tl, r_tl, MAXTL_MASK); 2410 2411 /* calculate offset to current trap state from env->ts, reuse r_tl */ 2412 tcg_gen_muli_i32(r_tl, r_tl, sizeof (trap_state)); 2413 tcg_gen_addi_ptr(r_tsptr, tcg_env, offsetof(CPUSPARCState, ts)); 2414 2415 /* tsptr = env->ts[env->tl & MAXTL_MASK] */ 2416 { 2417 TCGv_ptr r_tl_tmp = tcg_temp_new_ptr(); 2418 tcg_gen_ext_i32_ptr(r_tl_tmp, r_tl); 2419 tcg_gen_add_ptr(r_tsptr, r_tsptr, r_tl_tmp); 2420 } 2421 } 2422 #endif 2423 2424 static int extract_dfpreg(DisasContext *dc, int x) 2425 { 2426 int r = x & 0x1e; 2427 #ifdef TARGET_SPARC64 2428 r |= (x & 1) << 5; 2429 #endif 2430 return r; 2431 } 2432 2433 static int extract_qfpreg(DisasContext *dc, int x) 2434 { 2435 int r = x & 0x1c; 2436 #ifdef TARGET_SPARC64 2437 r |= (x & 1) << 5; 2438 #endif 2439 return r; 2440 } 2441 2442 /* Include the auto-generated decoder. */ 2443 #include "decode-insns.c.inc" 2444 2445 #define TRANS(NAME, AVAIL, FUNC, ...) \ 2446 static bool trans_##NAME(DisasContext *dc, arg_##NAME *a) \ 2447 { return avail_##AVAIL(dc) && FUNC(dc, __VA_ARGS__); } 2448 2449 #define avail_ALL(C) true 2450 #ifdef TARGET_SPARC64 2451 # define avail_32(C) false 2452 # define avail_ASR17(C) false 2453 # define avail_CASA(C) true 2454 # define avail_DIV(C) true 2455 # define avail_MUL(C) true 2456 # define avail_POWERDOWN(C) false 2457 # define avail_64(C) true 2458 # define avail_FMAF(C) ((C)->def->features & CPU_FEATURE_FMAF) 2459 # define avail_GL(C) ((C)->def->features & CPU_FEATURE_GL) 2460 # define avail_HYPV(C) ((C)->def->features & CPU_FEATURE_HYPV) 2461 # define avail_IMA(C) ((C)->def->features & CPU_FEATURE_IMA) 2462 # define avail_VIS1(C) ((C)->def->features & CPU_FEATURE_VIS1) 2463 # define avail_VIS2(C) ((C)->def->features & CPU_FEATURE_VIS2) 2464 # define avail_VIS3(C) ((C)->def->features & CPU_FEATURE_VIS3) 2465 # define avail_VIS3B(C) avail_VIS3(C) 2466 # define avail_VIS4(C) ((C)->def->features & CPU_FEATURE_VIS4) 2467 #else 2468 # define avail_32(C) true 2469 # define avail_ASR17(C) ((C)->def->features & CPU_FEATURE_ASR17) 2470 # define avail_CASA(C) ((C)->def->features & CPU_FEATURE_CASA) 2471 # define avail_DIV(C) ((C)->def->features & CPU_FEATURE_DIV) 2472 # define avail_MUL(C) ((C)->def->features & CPU_FEATURE_MUL) 2473 # define avail_POWERDOWN(C) ((C)->def->features & CPU_FEATURE_POWERDOWN) 2474 # define avail_64(C) false 2475 # define avail_FMAF(C) false 2476 # define avail_GL(C) false 2477 # define avail_HYPV(C) false 2478 # define avail_IMA(C) false 2479 # define avail_VIS1(C) false 2480 # define avail_VIS2(C) false 2481 # define avail_VIS3(C) false 2482 # define avail_VIS3B(C) false 2483 # define avail_VIS4(C) false 2484 #endif 2485 2486 /* Default case for non jump instructions. */ 2487 static bool advance_pc(DisasContext *dc) 2488 { 2489 TCGLabel *l1; 2490 2491 finishing_insn(dc); 2492 2493 if (dc->npc & 3) { 2494 switch (dc->npc) { 2495 case DYNAMIC_PC: 2496 case DYNAMIC_PC_LOOKUP: 2497 dc->pc = dc->npc; 2498 tcg_gen_mov_tl(cpu_pc, cpu_npc); 2499 tcg_gen_addi_tl(cpu_npc, cpu_npc, 4); 2500 break; 2501 2502 case JUMP_PC: 2503 /* we can do a static jump */ 2504 l1 = gen_new_label(); 2505 tcg_gen_brcondi_tl(dc->jump.cond, dc->jump.c1, dc->jump.c2, l1); 2506 2507 /* jump not taken */ 2508 gen_goto_tb(dc, 1, dc->jump_pc[1], dc->jump_pc[1] + 4); 2509 2510 /* jump taken */ 2511 gen_set_label(l1); 2512 gen_goto_tb(dc, 0, dc->jump_pc[0], dc->jump_pc[0] + 4); 2513 2514 dc->base.is_jmp = DISAS_NORETURN; 2515 break; 2516 2517 default: 2518 g_assert_not_reached(); 2519 } 2520 } else { 2521 dc->pc = dc->npc; 2522 dc->npc = dc->npc + 4; 2523 } 2524 return true; 2525 } 2526 2527 /* 2528 * Major opcodes 00 and 01 -- branches, call, and sethi 2529 */ 2530 2531 static bool advance_jump_cond(DisasContext *dc, DisasCompare *cmp, 2532 bool annul, int disp) 2533 { 2534 target_ulong dest = address_mask_i(dc, dc->pc + disp * 4); 2535 target_ulong npc; 2536 2537 finishing_insn(dc); 2538 2539 if (cmp->cond == TCG_COND_ALWAYS) { 2540 if (annul) { 2541 dc->pc = dest; 2542 dc->npc = dest + 4; 2543 } else { 2544 gen_mov_pc_npc(dc); 2545 dc->npc = dest; 2546 } 2547 return true; 2548 } 2549 2550 if (cmp->cond == TCG_COND_NEVER) { 2551 npc = dc->npc; 2552 if (npc & 3) { 2553 gen_mov_pc_npc(dc); 2554 if (annul) { 2555 tcg_gen_addi_tl(cpu_pc, cpu_pc, 4); 2556 } 2557 tcg_gen_addi_tl(cpu_npc, cpu_pc, 4); 2558 } else { 2559 dc->pc = npc + (annul ? 4 : 0); 2560 dc->npc = dc->pc + 4; 2561 } 2562 return true; 2563 } 2564 2565 flush_cond(dc); 2566 npc = dc->npc; 2567 2568 if (annul) { 2569 TCGLabel *l1 = gen_new_label(); 2570 2571 tcg_gen_brcondi_tl(tcg_invert_cond(cmp->cond), cmp->c1, cmp->c2, l1); 2572 gen_goto_tb(dc, 0, npc, dest); 2573 gen_set_label(l1); 2574 gen_goto_tb(dc, 1, npc + 4, npc + 8); 2575 2576 dc->base.is_jmp = DISAS_NORETURN; 2577 } else { 2578 if (npc & 3) { 2579 switch (npc) { 2580 case DYNAMIC_PC: 2581 case DYNAMIC_PC_LOOKUP: 2582 tcg_gen_mov_tl(cpu_pc, cpu_npc); 2583 tcg_gen_addi_tl(cpu_npc, cpu_npc, 4); 2584 tcg_gen_movcond_tl(cmp->cond, cpu_npc, 2585 cmp->c1, tcg_constant_tl(cmp->c2), 2586 tcg_constant_tl(dest), cpu_npc); 2587 dc->pc = npc; 2588 break; 2589 default: 2590 g_assert_not_reached(); 2591 } 2592 } else { 2593 dc->pc = npc; 2594 dc->npc = JUMP_PC; 2595 dc->jump = *cmp; 2596 dc->jump_pc[0] = dest; 2597 dc->jump_pc[1] = npc + 4; 2598 2599 /* The condition for cpu_cond is always NE -- normalize. */ 2600 if (cmp->cond == TCG_COND_NE) { 2601 tcg_gen_xori_tl(cpu_cond, cmp->c1, cmp->c2); 2602 } else { 2603 tcg_gen_setcondi_tl(cmp->cond, cpu_cond, cmp->c1, cmp->c2); 2604 } 2605 dc->cpu_cond_live = true; 2606 } 2607 } 2608 return true; 2609 } 2610 2611 static bool raise_priv(DisasContext *dc) 2612 { 2613 gen_exception(dc, TT_PRIV_INSN); 2614 return true; 2615 } 2616 2617 static bool raise_unimpfpop(DisasContext *dc) 2618 { 2619 gen_op_fpexception_im(dc, FSR_FTT_UNIMPFPOP); 2620 return true; 2621 } 2622 2623 static bool gen_trap_float128(DisasContext *dc) 2624 { 2625 if (dc->def->features & CPU_FEATURE_FLOAT128) { 2626 return false; 2627 } 2628 return raise_unimpfpop(dc); 2629 } 2630 2631 static bool do_bpcc(DisasContext *dc, arg_bcc *a) 2632 { 2633 DisasCompare cmp; 2634 2635 gen_compare(&cmp, a->cc, a->cond, dc); 2636 return advance_jump_cond(dc, &cmp, a->a, a->i); 2637 } 2638 2639 TRANS(Bicc, ALL, do_bpcc, a) 2640 TRANS(BPcc, 64, do_bpcc, a) 2641 2642 static bool do_fbpfcc(DisasContext *dc, arg_bcc *a) 2643 { 2644 DisasCompare cmp; 2645 2646 if (gen_trap_ifnofpu(dc)) { 2647 return true; 2648 } 2649 gen_fcompare(&cmp, a->cc, a->cond); 2650 return advance_jump_cond(dc, &cmp, a->a, a->i); 2651 } 2652 2653 TRANS(FBPfcc, 64, do_fbpfcc, a) 2654 TRANS(FBfcc, ALL, do_fbpfcc, a) 2655 2656 static bool trans_BPr(DisasContext *dc, arg_BPr *a) 2657 { 2658 DisasCompare cmp; 2659 2660 if (!avail_64(dc)) { 2661 return false; 2662 } 2663 if (!gen_compare_reg(&cmp, a->cond, gen_load_gpr(dc, a->rs1))) { 2664 return false; 2665 } 2666 return advance_jump_cond(dc, &cmp, a->a, a->i); 2667 } 2668 2669 static bool trans_CALL(DisasContext *dc, arg_CALL *a) 2670 { 2671 target_long target = address_mask_i(dc, dc->pc + a->i * 4); 2672 2673 gen_store_gpr(dc, 15, tcg_constant_tl(dc->pc)); 2674 gen_mov_pc_npc(dc); 2675 dc->npc = target; 2676 return true; 2677 } 2678 2679 static bool trans_NCP(DisasContext *dc, arg_NCP *a) 2680 { 2681 /* 2682 * For sparc32, always generate the no-coprocessor exception. 2683 * For sparc64, always generate illegal instruction. 2684 */ 2685 #ifdef TARGET_SPARC64 2686 return false; 2687 #else 2688 gen_exception(dc, TT_NCP_INSN); 2689 return true; 2690 #endif 2691 } 2692 2693 static bool trans_SETHI(DisasContext *dc, arg_SETHI *a) 2694 { 2695 /* Special-case %g0 because that's the canonical nop. */ 2696 if (a->rd) { 2697 gen_store_gpr(dc, a->rd, tcg_constant_tl((uint32_t)a->i << 10)); 2698 } 2699 return advance_pc(dc); 2700 } 2701 2702 /* 2703 * Major Opcode 10 -- integer, floating-point, vis, and system insns. 2704 */ 2705 2706 static bool do_tcc(DisasContext *dc, int cond, int cc, 2707 int rs1, bool imm, int rs2_or_imm) 2708 { 2709 int mask = ((dc->def->features & CPU_FEATURE_HYPV) && supervisor(dc) 2710 ? UA2005_HTRAP_MASK : V8_TRAP_MASK); 2711 DisasCompare cmp; 2712 TCGLabel *lab; 2713 TCGv_i32 trap; 2714 2715 /* Trap never. */ 2716 if (cond == 0) { 2717 return advance_pc(dc); 2718 } 2719 2720 /* 2721 * Immediate traps are the most common case. Since this value is 2722 * live across the branch, it really pays to evaluate the constant. 2723 */ 2724 if (rs1 == 0 && (imm || rs2_or_imm == 0)) { 2725 trap = tcg_constant_i32((rs2_or_imm & mask) + TT_TRAP); 2726 } else { 2727 trap = tcg_temp_new_i32(); 2728 tcg_gen_trunc_tl_i32(trap, gen_load_gpr(dc, rs1)); 2729 if (imm) { 2730 tcg_gen_addi_i32(trap, trap, rs2_or_imm); 2731 } else { 2732 TCGv_i32 t2 = tcg_temp_new_i32(); 2733 tcg_gen_trunc_tl_i32(t2, gen_load_gpr(dc, rs2_or_imm)); 2734 tcg_gen_add_i32(trap, trap, t2); 2735 } 2736 tcg_gen_andi_i32(trap, trap, mask); 2737 tcg_gen_addi_i32(trap, trap, TT_TRAP); 2738 } 2739 2740 finishing_insn(dc); 2741 2742 /* Trap always. */ 2743 if (cond == 8) { 2744 save_state(dc); 2745 gen_helper_raise_exception(tcg_env, trap); 2746 dc->base.is_jmp = DISAS_NORETURN; 2747 return true; 2748 } 2749 2750 /* Conditional trap. */ 2751 flush_cond(dc); 2752 lab = delay_exceptionv(dc, trap); 2753 gen_compare(&cmp, cc, cond, dc); 2754 tcg_gen_brcondi_tl(cmp.cond, cmp.c1, cmp.c2, lab); 2755 2756 return advance_pc(dc); 2757 } 2758 2759 static bool trans_Tcc_r(DisasContext *dc, arg_Tcc_r *a) 2760 { 2761 if (avail_32(dc) && a->cc) { 2762 return false; 2763 } 2764 return do_tcc(dc, a->cond, a->cc, a->rs1, false, a->rs2); 2765 } 2766 2767 static bool trans_Tcc_i_v7(DisasContext *dc, arg_Tcc_i_v7 *a) 2768 { 2769 if (avail_64(dc)) { 2770 return false; 2771 } 2772 return do_tcc(dc, a->cond, 0, a->rs1, true, a->i); 2773 } 2774 2775 static bool trans_Tcc_i_v9(DisasContext *dc, arg_Tcc_i_v9 *a) 2776 { 2777 if (avail_32(dc)) { 2778 return false; 2779 } 2780 return do_tcc(dc, a->cond, a->cc, a->rs1, true, a->i); 2781 } 2782 2783 static bool trans_STBAR(DisasContext *dc, arg_STBAR *a) 2784 { 2785 tcg_gen_mb(TCG_MO_ST_ST | TCG_BAR_SC); 2786 return advance_pc(dc); 2787 } 2788 2789 static bool trans_MEMBAR(DisasContext *dc, arg_MEMBAR *a) 2790 { 2791 if (avail_32(dc)) { 2792 return false; 2793 } 2794 if (a->mmask) { 2795 /* Note TCG_MO_* was modeled on sparc64, so mmask matches. */ 2796 tcg_gen_mb(a->mmask | TCG_BAR_SC); 2797 } 2798 if (a->cmask) { 2799 /* For #Sync, etc, end the TB to recognize interrupts. */ 2800 dc->base.is_jmp = DISAS_EXIT; 2801 } 2802 return advance_pc(dc); 2803 } 2804 2805 static bool do_rd_special(DisasContext *dc, bool priv, int rd, 2806 TCGv (*func)(DisasContext *, TCGv)) 2807 { 2808 if (!priv) { 2809 return raise_priv(dc); 2810 } 2811 gen_store_gpr(dc, rd, func(dc, gen_dest_gpr(dc, rd))); 2812 return advance_pc(dc); 2813 } 2814 2815 static TCGv do_rdy(DisasContext *dc, TCGv dst) 2816 { 2817 return cpu_y; 2818 } 2819 2820 static bool trans_RDY(DisasContext *dc, arg_RDY *a) 2821 { 2822 /* 2823 * TODO: Need a feature bit for sparcv8. In the meantime, treat all 2824 * 32-bit cpus like sparcv7, which ignores the rs1 field. 2825 * This matches after all other ASR, so Leon3 Asr17 is handled first. 2826 */ 2827 if (avail_64(dc) && a->rs1 != 0) { 2828 return false; 2829 } 2830 return do_rd_special(dc, true, a->rd, do_rdy); 2831 } 2832 2833 static TCGv do_rd_leon3_config(DisasContext *dc, TCGv dst) 2834 { 2835 gen_helper_rdasr17(dst, tcg_env); 2836 return dst; 2837 } 2838 2839 TRANS(RDASR17, ASR17, do_rd_special, true, a->rd, do_rd_leon3_config) 2840 2841 static TCGv do_rdccr(DisasContext *dc, TCGv dst) 2842 { 2843 gen_helper_rdccr(dst, tcg_env); 2844 return dst; 2845 } 2846 2847 TRANS(RDCCR, 64, do_rd_special, true, a->rd, do_rdccr) 2848 2849 static TCGv do_rdasi(DisasContext *dc, TCGv dst) 2850 { 2851 #ifdef TARGET_SPARC64 2852 return tcg_constant_tl(dc->asi); 2853 #else 2854 qemu_build_not_reached(); 2855 #endif 2856 } 2857 2858 TRANS(RDASI, 64, do_rd_special, true, a->rd, do_rdasi) 2859 2860 static TCGv do_rdtick(DisasContext *dc, TCGv dst) 2861 { 2862 TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 2863 2864 tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(tick)); 2865 if (translator_io_start(&dc->base)) { 2866 dc->base.is_jmp = DISAS_EXIT; 2867 } 2868 gen_helper_tick_get_count(dst, tcg_env, r_tickptr, 2869 tcg_constant_i32(dc->mem_idx)); 2870 return dst; 2871 } 2872 2873 /* TODO: non-priv access only allowed when enabled. */ 2874 TRANS(RDTICK, 64, do_rd_special, true, a->rd, do_rdtick) 2875 2876 static TCGv do_rdpc(DisasContext *dc, TCGv dst) 2877 { 2878 return tcg_constant_tl(address_mask_i(dc, dc->pc)); 2879 } 2880 2881 TRANS(RDPC, 64, do_rd_special, true, a->rd, do_rdpc) 2882 2883 static TCGv do_rdfprs(DisasContext *dc, TCGv dst) 2884 { 2885 tcg_gen_ext_i32_tl(dst, cpu_fprs); 2886 return dst; 2887 } 2888 2889 TRANS(RDFPRS, 64, do_rd_special, true, a->rd, do_rdfprs) 2890 2891 static TCGv do_rdgsr(DisasContext *dc, TCGv dst) 2892 { 2893 gen_trap_ifnofpu(dc); 2894 return cpu_gsr; 2895 } 2896 2897 TRANS(RDGSR, 64, do_rd_special, true, a->rd, do_rdgsr) 2898 2899 static TCGv do_rdsoftint(DisasContext *dc, TCGv dst) 2900 { 2901 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(softint)); 2902 return dst; 2903 } 2904 2905 TRANS(RDSOFTINT, 64, do_rd_special, supervisor(dc), a->rd, do_rdsoftint) 2906 2907 static TCGv do_rdtick_cmpr(DisasContext *dc, TCGv dst) 2908 { 2909 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(tick_cmpr)); 2910 return dst; 2911 } 2912 2913 /* TODO: non-priv access only allowed when enabled. */ 2914 TRANS(RDTICK_CMPR, 64, do_rd_special, true, a->rd, do_rdtick_cmpr) 2915 2916 static TCGv do_rdstick(DisasContext *dc, TCGv dst) 2917 { 2918 TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 2919 2920 tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(stick)); 2921 if (translator_io_start(&dc->base)) { 2922 dc->base.is_jmp = DISAS_EXIT; 2923 } 2924 gen_helper_tick_get_count(dst, tcg_env, r_tickptr, 2925 tcg_constant_i32(dc->mem_idx)); 2926 return dst; 2927 } 2928 2929 /* TODO: non-priv access only allowed when enabled. */ 2930 TRANS(RDSTICK, 64, do_rd_special, true, a->rd, do_rdstick) 2931 2932 static TCGv do_rdstick_cmpr(DisasContext *dc, TCGv dst) 2933 { 2934 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(stick_cmpr)); 2935 return dst; 2936 } 2937 2938 /* TODO: supervisor access only allowed when enabled by hypervisor. */ 2939 TRANS(RDSTICK_CMPR, 64, do_rd_special, supervisor(dc), a->rd, do_rdstick_cmpr) 2940 2941 /* 2942 * UltraSPARC-T1 Strand status. 2943 * HYPV check maybe not enough, UA2005 & UA2007 describe 2944 * this ASR as impl. dep 2945 */ 2946 static TCGv do_rdstrand_status(DisasContext *dc, TCGv dst) 2947 { 2948 return tcg_constant_tl(1); 2949 } 2950 2951 TRANS(RDSTRAND_STATUS, HYPV, do_rd_special, true, a->rd, do_rdstrand_status) 2952 2953 static TCGv do_rdpsr(DisasContext *dc, TCGv dst) 2954 { 2955 gen_helper_rdpsr(dst, tcg_env); 2956 return dst; 2957 } 2958 2959 TRANS(RDPSR, 32, do_rd_special, supervisor(dc), a->rd, do_rdpsr) 2960 2961 static TCGv do_rdhpstate(DisasContext *dc, TCGv dst) 2962 { 2963 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hpstate)); 2964 return dst; 2965 } 2966 2967 TRANS(RDHPR_hpstate, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhpstate) 2968 2969 static TCGv do_rdhtstate(DisasContext *dc, TCGv dst) 2970 { 2971 TCGv_i32 tl = tcg_temp_new_i32(); 2972 TCGv_ptr tp = tcg_temp_new_ptr(); 2973 2974 tcg_gen_ld_i32(tl, tcg_env, env64_field_offsetof(tl)); 2975 tcg_gen_andi_i32(tl, tl, MAXTL_MASK); 2976 tcg_gen_shli_i32(tl, tl, 3); 2977 tcg_gen_ext_i32_ptr(tp, tl); 2978 tcg_gen_add_ptr(tp, tp, tcg_env); 2979 2980 tcg_gen_ld_tl(dst, tp, env64_field_offsetof(htstate)); 2981 return dst; 2982 } 2983 2984 TRANS(RDHPR_htstate, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhtstate) 2985 2986 static TCGv do_rdhintp(DisasContext *dc, TCGv dst) 2987 { 2988 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hintp)); 2989 return dst; 2990 } 2991 2992 TRANS(RDHPR_hintp, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhintp) 2993 2994 static TCGv do_rdhtba(DisasContext *dc, TCGv dst) 2995 { 2996 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(htba)); 2997 return dst; 2998 } 2999 3000 TRANS(RDHPR_htba, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhtba) 3001 3002 static TCGv do_rdhver(DisasContext *dc, TCGv dst) 3003 { 3004 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hver)); 3005 return dst; 3006 } 3007 3008 TRANS(RDHPR_hver, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhver) 3009 3010 static TCGv do_rdhstick_cmpr(DisasContext *dc, TCGv dst) 3011 { 3012 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hstick_cmpr)); 3013 return dst; 3014 } 3015 3016 TRANS(RDHPR_hstick_cmpr, HYPV, do_rd_special, hypervisor(dc), a->rd, 3017 do_rdhstick_cmpr) 3018 3019 static TCGv do_rdwim(DisasContext *dc, TCGv dst) 3020 { 3021 tcg_gen_ld_tl(dst, tcg_env, env32_field_offsetof(wim)); 3022 return dst; 3023 } 3024 3025 TRANS(RDWIM, 32, do_rd_special, supervisor(dc), a->rd, do_rdwim) 3026 3027 static TCGv do_rdtpc(DisasContext *dc, TCGv dst) 3028 { 3029 #ifdef TARGET_SPARC64 3030 TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 3031 3032 gen_load_trap_state_at_tl(r_tsptr); 3033 tcg_gen_ld_tl(dst, r_tsptr, offsetof(trap_state, tpc)); 3034 return dst; 3035 #else 3036 qemu_build_not_reached(); 3037 #endif 3038 } 3039 3040 TRANS(RDPR_tpc, 64, do_rd_special, supervisor(dc), a->rd, do_rdtpc) 3041 3042 static TCGv do_rdtnpc(DisasContext *dc, TCGv dst) 3043 { 3044 #ifdef TARGET_SPARC64 3045 TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 3046 3047 gen_load_trap_state_at_tl(r_tsptr); 3048 tcg_gen_ld_tl(dst, r_tsptr, offsetof(trap_state, tnpc)); 3049 return dst; 3050 #else 3051 qemu_build_not_reached(); 3052 #endif 3053 } 3054 3055 TRANS(RDPR_tnpc, 64, do_rd_special, supervisor(dc), a->rd, do_rdtnpc) 3056 3057 static TCGv do_rdtstate(DisasContext *dc, TCGv dst) 3058 { 3059 #ifdef TARGET_SPARC64 3060 TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 3061 3062 gen_load_trap_state_at_tl(r_tsptr); 3063 tcg_gen_ld_tl(dst, r_tsptr, offsetof(trap_state, tstate)); 3064 return dst; 3065 #else 3066 qemu_build_not_reached(); 3067 #endif 3068 } 3069 3070 TRANS(RDPR_tstate, 64, do_rd_special, supervisor(dc), a->rd, do_rdtstate) 3071 3072 static TCGv do_rdtt(DisasContext *dc, TCGv dst) 3073 { 3074 #ifdef TARGET_SPARC64 3075 TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 3076 3077 gen_load_trap_state_at_tl(r_tsptr); 3078 tcg_gen_ld32s_tl(dst, r_tsptr, offsetof(trap_state, tt)); 3079 return dst; 3080 #else 3081 qemu_build_not_reached(); 3082 #endif 3083 } 3084 3085 TRANS(RDPR_tt, 64, do_rd_special, supervisor(dc), a->rd, do_rdtt) 3086 TRANS(RDPR_tick, 64, do_rd_special, supervisor(dc), a->rd, do_rdtick) 3087 3088 static TCGv do_rdtba(DisasContext *dc, TCGv dst) 3089 { 3090 return cpu_tbr; 3091 } 3092 3093 TRANS(RDTBR, 32, do_rd_special, supervisor(dc), a->rd, do_rdtba) 3094 TRANS(RDPR_tba, 64, do_rd_special, supervisor(dc), a->rd, do_rdtba) 3095 3096 static TCGv do_rdpstate(DisasContext *dc, TCGv dst) 3097 { 3098 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(pstate)); 3099 return dst; 3100 } 3101 3102 TRANS(RDPR_pstate, 64, do_rd_special, supervisor(dc), a->rd, do_rdpstate) 3103 3104 static TCGv do_rdtl(DisasContext *dc, TCGv dst) 3105 { 3106 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(tl)); 3107 return dst; 3108 } 3109 3110 TRANS(RDPR_tl, 64, do_rd_special, supervisor(dc), a->rd, do_rdtl) 3111 3112 static TCGv do_rdpil(DisasContext *dc, TCGv dst) 3113 { 3114 tcg_gen_ld32s_tl(dst, tcg_env, env_field_offsetof(psrpil)); 3115 return dst; 3116 } 3117 3118 TRANS(RDPR_pil, 64, do_rd_special, supervisor(dc), a->rd, do_rdpil) 3119 3120 static TCGv do_rdcwp(DisasContext *dc, TCGv dst) 3121 { 3122 gen_helper_rdcwp(dst, tcg_env); 3123 return dst; 3124 } 3125 3126 TRANS(RDPR_cwp, 64, do_rd_special, supervisor(dc), a->rd, do_rdcwp) 3127 3128 static TCGv do_rdcansave(DisasContext *dc, TCGv dst) 3129 { 3130 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(cansave)); 3131 return dst; 3132 } 3133 3134 TRANS(RDPR_cansave, 64, do_rd_special, supervisor(dc), a->rd, do_rdcansave) 3135 3136 static TCGv do_rdcanrestore(DisasContext *dc, TCGv dst) 3137 { 3138 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(canrestore)); 3139 return dst; 3140 } 3141 3142 TRANS(RDPR_canrestore, 64, do_rd_special, supervisor(dc), a->rd, 3143 do_rdcanrestore) 3144 3145 static TCGv do_rdcleanwin(DisasContext *dc, TCGv dst) 3146 { 3147 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(cleanwin)); 3148 return dst; 3149 } 3150 3151 TRANS(RDPR_cleanwin, 64, do_rd_special, supervisor(dc), a->rd, do_rdcleanwin) 3152 3153 static TCGv do_rdotherwin(DisasContext *dc, TCGv dst) 3154 { 3155 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(otherwin)); 3156 return dst; 3157 } 3158 3159 TRANS(RDPR_otherwin, 64, do_rd_special, supervisor(dc), a->rd, do_rdotherwin) 3160 3161 static TCGv do_rdwstate(DisasContext *dc, TCGv dst) 3162 { 3163 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(wstate)); 3164 return dst; 3165 } 3166 3167 TRANS(RDPR_wstate, 64, do_rd_special, supervisor(dc), a->rd, do_rdwstate) 3168 3169 static TCGv do_rdgl(DisasContext *dc, TCGv dst) 3170 { 3171 tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(gl)); 3172 return dst; 3173 } 3174 3175 TRANS(RDPR_gl, GL, do_rd_special, supervisor(dc), a->rd, do_rdgl) 3176 3177 /* UA2005 strand status */ 3178 static TCGv do_rdssr(DisasContext *dc, TCGv dst) 3179 { 3180 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(ssr)); 3181 return dst; 3182 } 3183 3184 TRANS(RDPR_strand_status, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdssr) 3185 3186 static TCGv do_rdver(DisasContext *dc, TCGv dst) 3187 { 3188 tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(version)); 3189 return dst; 3190 } 3191 3192 TRANS(RDPR_ver, 64, do_rd_special, supervisor(dc), a->rd, do_rdver) 3193 3194 static bool trans_FLUSHW(DisasContext *dc, arg_FLUSHW *a) 3195 { 3196 if (avail_64(dc)) { 3197 gen_helper_flushw(tcg_env); 3198 return advance_pc(dc); 3199 } 3200 return false; 3201 } 3202 3203 static bool do_wr_special(DisasContext *dc, arg_r_r_ri *a, bool priv, 3204 void (*func)(DisasContext *, TCGv)) 3205 { 3206 TCGv src; 3207 3208 /* For simplicity, we under-decoded the rs2 form. */ 3209 if (!a->imm && (a->rs2_or_imm & ~0x1f)) { 3210 return false; 3211 } 3212 if (!priv) { 3213 return raise_priv(dc); 3214 } 3215 3216 if (a->rs1 == 0 && (a->imm || a->rs2_or_imm == 0)) { 3217 src = tcg_constant_tl(a->rs2_or_imm); 3218 } else { 3219 TCGv src1 = gen_load_gpr(dc, a->rs1); 3220 if (a->rs2_or_imm == 0) { 3221 src = src1; 3222 } else { 3223 src = tcg_temp_new(); 3224 if (a->imm) { 3225 tcg_gen_xori_tl(src, src1, a->rs2_or_imm); 3226 } else { 3227 tcg_gen_xor_tl(src, src1, gen_load_gpr(dc, a->rs2_or_imm)); 3228 } 3229 } 3230 } 3231 func(dc, src); 3232 return advance_pc(dc); 3233 } 3234 3235 static void do_wry(DisasContext *dc, TCGv src) 3236 { 3237 tcg_gen_ext32u_tl(cpu_y, src); 3238 } 3239 3240 TRANS(WRY, ALL, do_wr_special, a, true, do_wry) 3241 3242 static void do_wrccr(DisasContext *dc, TCGv src) 3243 { 3244 gen_helper_wrccr(tcg_env, src); 3245 } 3246 3247 TRANS(WRCCR, 64, do_wr_special, a, true, do_wrccr) 3248 3249 static void do_wrasi(DisasContext *dc, TCGv src) 3250 { 3251 TCGv tmp = tcg_temp_new(); 3252 3253 tcg_gen_ext8u_tl(tmp, src); 3254 tcg_gen_st32_tl(tmp, tcg_env, env64_field_offsetof(asi)); 3255 /* End TB to notice changed ASI. */ 3256 dc->base.is_jmp = DISAS_EXIT; 3257 } 3258 3259 TRANS(WRASI, 64, do_wr_special, a, true, do_wrasi) 3260 3261 static void do_wrfprs(DisasContext *dc, TCGv src) 3262 { 3263 #ifdef TARGET_SPARC64 3264 tcg_gen_trunc_tl_i32(cpu_fprs, src); 3265 dc->fprs_dirty = 0; 3266 dc->base.is_jmp = DISAS_EXIT; 3267 #else 3268 qemu_build_not_reached(); 3269 #endif 3270 } 3271 3272 TRANS(WRFPRS, 64, do_wr_special, a, true, do_wrfprs) 3273 3274 static void do_wrgsr(DisasContext *dc, TCGv src) 3275 { 3276 gen_trap_ifnofpu(dc); 3277 tcg_gen_mov_tl(cpu_gsr, src); 3278 } 3279 3280 TRANS(WRGSR, 64, do_wr_special, a, true, do_wrgsr) 3281 3282 static void do_wrsoftint_set(DisasContext *dc, TCGv src) 3283 { 3284 gen_helper_set_softint(tcg_env, src); 3285 } 3286 3287 TRANS(WRSOFTINT_SET, 64, do_wr_special, a, supervisor(dc), do_wrsoftint_set) 3288 3289 static void do_wrsoftint_clr(DisasContext *dc, TCGv src) 3290 { 3291 gen_helper_clear_softint(tcg_env, src); 3292 } 3293 3294 TRANS(WRSOFTINT_CLR, 64, do_wr_special, a, supervisor(dc), do_wrsoftint_clr) 3295 3296 static void do_wrsoftint(DisasContext *dc, TCGv src) 3297 { 3298 gen_helper_write_softint(tcg_env, src); 3299 } 3300 3301 TRANS(WRSOFTINT, 64, do_wr_special, a, supervisor(dc), do_wrsoftint) 3302 3303 static void do_wrtick_cmpr(DisasContext *dc, TCGv src) 3304 { 3305 TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 3306 3307 tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(tick_cmpr)); 3308 tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(tick)); 3309 translator_io_start(&dc->base); 3310 gen_helper_tick_set_limit(r_tickptr, src); 3311 /* End TB to handle timer interrupt */ 3312 dc->base.is_jmp = DISAS_EXIT; 3313 } 3314 3315 TRANS(WRTICK_CMPR, 64, do_wr_special, a, supervisor(dc), do_wrtick_cmpr) 3316 3317 static void do_wrstick(DisasContext *dc, TCGv src) 3318 { 3319 #ifdef TARGET_SPARC64 3320 TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 3321 3322 tcg_gen_ld_ptr(r_tickptr, tcg_env, offsetof(CPUSPARCState, stick)); 3323 translator_io_start(&dc->base); 3324 gen_helper_tick_set_count(r_tickptr, src); 3325 /* End TB to handle timer interrupt */ 3326 dc->base.is_jmp = DISAS_EXIT; 3327 #else 3328 qemu_build_not_reached(); 3329 #endif 3330 } 3331 3332 TRANS(WRSTICK, 64, do_wr_special, a, supervisor(dc), do_wrstick) 3333 3334 static void do_wrstick_cmpr(DisasContext *dc, TCGv src) 3335 { 3336 TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 3337 3338 tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(stick_cmpr)); 3339 tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(stick)); 3340 translator_io_start(&dc->base); 3341 gen_helper_tick_set_limit(r_tickptr, src); 3342 /* End TB to handle timer interrupt */ 3343 dc->base.is_jmp = DISAS_EXIT; 3344 } 3345 3346 TRANS(WRSTICK_CMPR, 64, do_wr_special, a, supervisor(dc), do_wrstick_cmpr) 3347 3348 static void do_wrpowerdown(DisasContext *dc, TCGv src) 3349 { 3350 finishing_insn(dc); 3351 save_state(dc); 3352 gen_helper_power_down(tcg_env); 3353 } 3354 3355 TRANS(WRPOWERDOWN, POWERDOWN, do_wr_special, a, supervisor(dc), do_wrpowerdown) 3356 3357 static void do_wrmwait(DisasContext *dc, TCGv src) 3358 { 3359 /* 3360 * TODO: This is a stub version of mwait, which merely recognizes 3361 * interrupts immediately and does not wait. 3362 */ 3363 dc->base.is_jmp = DISAS_EXIT; 3364 } 3365 3366 TRANS(WRMWAIT, VIS4, do_wr_special, a, true, do_wrmwait) 3367 3368 static void do_wrpsr(DisasContext *dc, TCGv src) 3369 { 3370 gen_helper_wrpsr(tcg_env, src); 3371 dc->base.is_jmp = DISAS_EXIT; 3372 } 3373 3374 TRANS(WRPSR, 32, do_wr_special, a, supervisor(dc), do_wrpsr) 3375 3376 static void do_wrwim(DisasContext *dc, TCGv src) 3377 { 3378 target_ulong mask = MAKE_64BIT_MASK(0, dc->def->nwindows); 3379 TCGv tmp = tcg_temp_new(); 3380 3381 tcg_gen_andi_tl(tmp, src, mask); 3382 tcg_gen_st_tl(tmp, tcg_env, env32_field_offsetof(wim)); 3383 } 3384 3385 TRANS(WRWIM, 32, do_wr_special, a, supervisor(dc), do_wrwim) 3386 3387 static void do_wrtpc(DisasContext *dc, TCGv src) 3388 { 3389 #ifdef TARGET_SPARC64 3390 TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 3391 3392 gen_load_trap_state_at_tl(r_tsptr); 3393 tcg_gen_st_tl(src, r_tsptr, offsetof(trap_state, tpc)); 3394 #else 3395 qemu_build_not_reached(); 3396 #endif 3397 } 3398 3399 TRANS(WRPR_tpc, 64, do_wr_special, a, supervisor(dc), do_wrtpc) 3400 3401 static void do_wrtnpc(DisasContext *dc, TCGv src) 3402 { 3403 #ifdef TARGET_SPARC64 3404 TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 3405 3406 gen_load_trap_state_at_tl(r_tsptr); 3407 tcg_gen_st_tl(src, r_tsptr, offsetof(trap_state, tnpc)); 3408 #else 3409 qemu_build_not_reached(); 3410 #endif 3411 } 3412 3413 TRANS(WRPR_tnpc, 64, do_wr_special, a, supervisor(dc), do_wrtnpc) 3414 3415 static void do_wrtstate(DisasContext *dc, TCGv src) 3416 { 3417 #ifdef TARGET_SPARC64 3418 TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 3419 3420 gen_load_trap_state_at_tl(r_tsptr); 3421 tcg_gen_st_tl(src, r_tsptr, offsetof(trap_state, tstate)); 3422 #else 3423 qemu_build_not_reached(); 3424 #endif 3425 } 3426 3427 TRANS(WRPR_tstate, 64, do_wr_special, a, supervisor(dc), do_wrtstate) 3428 3429 static void do_wrtt(DisasContext *dc, TCGv src) 3430 { 3431 #ifdef TARGET_SPARC64 3432 TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 3433 3434 gen_load_trap_state_at_tl(r_tsptr); 3435 tcg_gen_st32_tl(src, r_tsptr, offsetof(trap_state, tt)); 3436 #else 3437 qemu_build_not_reached(); 3438 #endif 3439 } 3440 3441 TRANS(WRPR_tt, 64, do_wr_special, a, supervisor(dc), do_wrtt) 3442 3443 static void do_wrtick(DisasContext *dc, TCGv src) 3444 { 3445 TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 3446 3447 tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(tick)); 3448 translator_io_start(&dc->base); 3449 gen_helper_tick_set_count(r_tickptr, src); 3450 /* End TB to handle timer interrupt */ 3451 dc->base.is_jmp = DISAS_EXIT; 3452 } 3453 3454 TRANS(WRPR_tick, 64, do_wr_special, a, supervisor(dc), do_wrtick) 3455 3456 static void do_wrtba(DisasContext *dc, TCGv src) 3457 { 3458 tcg_gen_mov_tl(cpu_tbr, src); 3459 } 3460 3461 TRANS(WRPR_tba, 64, do_wr_special, a, supervisor(dc), do_wrtba) 3462 3463 static void do_wrpstate(DisasContext *dc, TCGv src) 3464 { 3465 save_state(dc); 3466 if (translator_io_start(&dc->base)) { 3467 dc->base.is_jmp = DISAS_EXIT; 3468 } 3469 gen_helper_wrpstate(tcg_env, src); 3470 dc->npc = DYNAMIC_PC; 3471 } 3472 3473 TRANS(WRPR_pstate, 64, do_wr_special, a, supervisor(dc), do_wrpstate) 3474 3475 static void do_wrtl(DisasContext *dc, TCGv src) 3476 { 3477 save_state(dc); 3478 tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(tl)); 3479 dc->npc = DYNAMIC_PC; 3480 } 3481 3482 TRANS(WRPR_tl, 64, do_wr_special, a, supervisor(dc), do_wrtl) 3483 3484 static void do_wrpil(DisasContext *dc, TCGv src) 3485 { 3486 if (translator_io_start(&dc->base)) { 3487 dc->base.is_jmp = DISAS_EXIT; 3488 } 3489 gen_helper_wrpil(tcg_env, src); 3490 } 3491 3492 TRANS(WRPR_pil, 64, do_wr_special, a, supervisor(dc), do_wrpil) 3493 3494 static void do_wrcwp(DisasContext *dc, TCGv src) 3495 { 3496 gen_helper_wrcwp(tcg_env, src); 3497 } 3498 3499 TRANS(WRPR_cwp, 64, do_wr_special, a, supervisor(dc), do_wrcwp) 3500 3501 static void do_wrcansave(DisasContext *dc, TCGv src) 3502 { 3503 tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(cansave)); 3504 } 3505 3506 TRANS(WRPR_cansave, 64, do_wr_special, a, supervisor(dc), do_wrcansave) 3507 3508 static void do_wrcanrestore(DisasContext *dc, TCGv src) 3509 { 3510 tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(canrestore)); 3511 } 3512 3513 TRANS(WRPR_canrestore, 64, do_wr_special, a, supervisor(dc), do_wrcanrestore) 3514 3515 static void do_wrcleanwin(DisasContext *dc, TCGv src) 3516 { 3517 tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(cleanwin)); 3518 } 3519 3520 TRANS(WRPR_cleanwin, 64, do_wr_special, a, supervisor(dc), do_wrcleanwin) 3521 3522 static void do_wrotherwin(DisasContext *dc, TCGv src) 3523 { 3524 tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(otherwin)); 3525 } 3526 3527 TRANS(WRPR_otherwin, 64, do_wr_special, a, supervisor(dc), do_wrotherwin) 3528 3529 static void do_wrwstate(DisasContext *dc, TCGv src) 3530 { 3531 tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(wstate)); 3532 } 3533 3534 TRANS(WRPR_wstate, 64, do_wr_special, a, supervisor(dc), do_wrwstate) 3535 3536 static void do_wrgl(DisasContext *dc, TCGv src) 3537 { 3538 gen_helper_wrgl(tcg_env, src); 3539 } 3540 3541 TRANS(WRPR_gl, GL, do_wr_special, a, supervisor(dc), do_wrgl) 3542 3543 /* UA2005 strand status */ 3544 static void do_wrssr(DisasContext *dc, TCGv src) 3545 { 3546 tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(ssr)); 3547 } 3548 3549 TRANS(WRPR_strand_status, HYPV, do_wr_special, a, hypervisor(dc), do_wrssr) 3550 3551 TRANS(WRTBR, 32, do_wr_special, a, supervisor(dc), do_wrtba) 3552 3553 static void do_wrhpstate(DisasContext *dc, TCGv src) 3554 { 3555 tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(hpstate)); 3556 dc->base.is_jmp = DISAS_EXIT; 3557 } 3558 3559 TRANS(WRHPR_hpstate, HYPV, do_wr_special, a, hypervisor(dc), do_wrhpstate) 3560 3561 static void do_wrhtstate(DisasContext *dc, TCGv src) 3562 { 3563 TCGv_i32 tl = tcg_temp_new_i32(); 3564 TCGv_ptr tp = tcg_temp_new_ptr(); 3565 3566 tcg_gen_ld_i32(tl, tcg_env, env64_field_offsetof(tl)); 3567 tcg_gen_andi_i32(tl, tl, MAXTL_MASK); 3568 tcg_gen_shli_i32(tl, tl, 3); 3569 tcg_gen_ext_i32_ptr(tp, tl); 3570 tcg_gen_add_ptr(tp, tp, tcg_env); 3571 3572 tcg_gen_st_tl(src, tp, env64_field_offsetof(htstate)); 3573 } 3574 3575 TRANS(WRHPR_htstate, HYPV, do_wr_special, a, hypervisor(dc), do_wrhtstate) 3576 3577 static void do_wrhintp(DisasContext *dc, TCGv src) 3578 { 3579 tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(hintp)); 3580 } 3581 3582 TRANS(WRHPR_hintp, HYPV, do_wr_special, a, hypervisor(dc), do_wrhintp) 3583 3584 static void do_wrhtba(DisasContext *dc, TCGv src) 3585 { 3586 tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(htba)); 3587 } 3588 3589 TRANS(WRHPR_htba, HYPV, do_wr_special, a, hypervisor(dc), do_wrhtba) 3590 3591 static void do_wrhstick_cmpr(DisasContext *dc, TCGv src) 3592 { 3593 TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 3594 3595 tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(hstick_cmpr)); 3596 tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(hstick)); 3597 translator_io_start(&dc->base); 3598 gen_helper_tick_set_limit(r_tickptr, src); 3599 /* End TB to handle timer interrupt */ 3600 dc->base.is_jmp = DISAS_EXIT; 3601 } 3602 3603 TRANS(WRHPR_hstick_cmpr, HYPV, do_wr_special, a, hypervisor(dc), 3604 do_wrhstick_cmpr) 3605 3606 static bool do_saved_restored(DisasContext *dc, bool saved) 3607 { 3608 if (!supervisor(dc)) { 3609 return raise_priv(dc); 3610 } 3611 if (saved) { 3612 gen_helper_saved(tcg_env); 3613 } else { 3614 gen_helper_restored(tcg_env); 3615 } 3616 return advance_pc(dc); 3617 } 3618 3619 TRANS(SAVED, 64, do_saved_restored, true) 3620 TRANS(RESTORED, 64, do_saved_restored, false) 3621 3622 static bool trans_NOP(DisasContext *dc, arg_NOP *a) 3623 { 3624 return advance_pc(dc); 3625 } 3626 3627 /* 3628 * TODO: Need a feature bit for sparcv8. 3629 * In the meantime, treat all 32-bit cpus like sparcv7. 3630 */ 3631 TRANS(NOP_v7, 32, trans_NOP, a) 3632 TRANS(NOP_v9, 64, trans_NOP, a) 3633 3634 static bool do_arith_int(DisasContext *dc, arg_r_r_ri_cc *a, 3635 void (*func)(TCGv, TCGv, TCGv), 3636 void (*funci)(TCGv, TCGv, target_long), 3637 bool logic_cc) 3638 { 3639 TCGv dst, src1; 3640 3641 /* For simplicity, we under-decoded the rs2 form. */ 3642 if (!a->imm && a->rs2_or_imm & ~0x1f) { 3643 return false; 3644 } 3645 3646 if (logic_cc) { 3647 dst = cpu_cc_N; 3648 } else { 3649 dst = gen_dest_gpr(dc, a->rd); 3650 } 3651 src1 = gen_load_gpr(dc, a->rs1); 3652 3653 if (a->imm || a->rs2_or_imm == 0) { 3654 if (funci) { 3655 funci(dst, src1, a->rs2_or_imm); 3656 } else { 3657 func(dst, src1, tcg_constant_tl(a->rs2_or_imm)); 3658 } 3659 } else { 3660 func(dst, src1, cpu_regs[a->rs2_or_imm]); 3661 } 3662 3663 if (logic_cc) { 3664 if (TARGET_LONG_BITS == 64) { 3665 tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N); 3666 tcg_gen_movi_tl(cpu_icc_C, 0); 3667 } 3668 tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N); 3669 tcg_gen_movi_tl(cpu_cc_C, 0); 3670 tcg_gen_movi_tl(cpu_cc_V, 0); 3671 } 3672 3673 gen_store_gpr(dc, a->rd, dst); 3674 return advance_pc(dc); 3675 } 3676 3677 static bool do_arith(DisasContext *dc, arg_r_r_ri_cc *a, 3678 void (*func)(TCGv, TCGv, TCGv), 3679 void (*funci)(TCGv, TCGv, target_long), 3680 void (*func_cc)(TCGv, TCGv, TCGv)) 3681 { 3682 if (a->cc) { 3683 return do_arith_int(dc, a, func_cc, NULL, false); 3684 } 3685 return do_arith_int(dc, a, func, funci, false); 3686 } 3687 3688 static bool do_logic(DisasContext *dc, arg_r_r_ri_cc *a, 3689 void (*func)(TCGv, TCGv, TCGv), 3690 void (*funci)(TCGv, TCGv, target_long)) 3691 { 3692 return do_arith_int(dc, a, func, funci, a->cc); 3693 } 3694 3695 TRANS(ADD, ALL, do_arith, a, tcg_gen_add_tl, tcg_gen_addi_tl, gen_op_addcc) 3696 TRANS(SUB, ALL, do_arith, a, tcg_gen_sub_tl, tcg_gen_subi_tl, gen_op_subcc) 3697 TRANS(ADDC, ALL, do_arith, a, gen_op_addc, NULL, gen_op_addccc) 3698 TRANS(SUBC, ALL, do_arith, a, gen_op_subc, NULL, gen_op_subccc) 3699 3700 TRANS(TADDcc, ALL, do_arith, a, NULL, NULL, gen_op_taddcc) 3701 TRANS(TSUBcc, ALL, do_arith, a, NULL, NULL, gen_op_tsubcc) 3702 TRANS(TADDccTV, ALL, do_arith, a, NULL, NULL, gen_op_taddcctv) 3703 TRANS(TSUBccTV, ALL, do_arith, a, NULL, NULL, gen_op_tsubcctv) 3704 3705 TRANS(AND, ALL, do_logic, a, tcg_gen_and_tl, tcg_gen_andi_tl) 3706 TRANS(XOR, ALL, do_logic, a, tcg_gen_xor_tl, tcg_gen_xori_tl) 3707 TRANS(ANDN, ALL, do_logic, a, tcg_gen_andc_tl, NULL) 3708 TRANS(ORN, ALL, do_logic, a, tcg_gen_orc_tl, NULL) 3709 TRANS(XORN, ALL, do_logic, a, tcg_gen_eqv_tl, NULL) 3710 3711 TRANS(MULX, 64, do_arith, a, tcg_gen_mul_tl, tcg_gen_muli_tl, NULL) 3712 TRANS(UMUL, MUL, do_logic, a, gen_op_umul, NULL) 3713 TRANS(SMUL, MUL, do_logic, a, gen_op_smul, NULL) 3714 TRANS(MULScc, ALL, do_arith, a, NULL, NULL, gen_op_mulscc) 3715 3716 TRANS(UDIVcc, DIV, do_arith, a, NULL, NULL, gen_op_udivcc) 3717 TRANS(SDIV, DIV, do_arith, a, gen_op_sdiv, NULL, gen_op_sdivcc) 3718 3719 /* TODO: Should have feature bit -- comes in with UltraSparc T2. */ 3720 TRANS(POPC, 64, do_arith, a, gen_op_popc, NULL, NULL) 3721 3722 static bool trans_OR(DisasContext *dc, arg_r_r_ri_cc *a) 3723 { 3724 /* OR with %g0 is the canonical alias for MOV. */ 3725 if (!a->cc && a->rs1 == 0) { 3726 if (a->imm || a->rs2_or_imm == 0) { 3727 gen_store_gpr(dc, a->rd, tcg_constant_tl(a->rs2_or_imm)); 3728 } else if (a->rs2_or_imm & ~0x1f) { 3729 /* For simplicity, we under-decoded the rs2 form. */ 3730 return false; 3731 } else { 3732 gen_store_gpr(dc, a->rd, cpu_regs[a->rs2_or_imm]); 3733 } 3734 return advance_pc(dc); 3735 } 3736 return do_logic(dc, a, tcg_gen_or_tl, tcg_gen_ori_tl); 3737 } 3738 3739 static bool trans_UDIV(DisasContext *dc, arg_r_r_ri *a) 3740 { 3741 TCGv_i64 t1, t2; 3742 TCGv dst; 3743 3744 if (!avail_DIV(dc)) { 3745 return false; 3746 } 3747 /* For simplicity, we under-decoded the rs2 form. */ 3748 if (!a->imm && a->rs2_or_imm & ~0x1f) { 3749 return false; 3750 } 3751 3752 if (unlikely(a->rs2_or_imm == 0)) { 3753 gen_exception(dc, TT_DIV_ZERO); 3754 return true; 3755 } 3756 3757 if (a->imm) { 3758 t2 = tcg_constant_i64((uint32_t)a->rs2_or_imm); 3759 } else { 3760 TCGLabel *lab; 3761 TCGv_i32 n2; 3762 3763 finishing_insn(dc); 3764 flush_cond(dc); 3765 3766 n2 = tcg_temp_new_i32(); 3767 tcg_gen_trunc_tl_i32(n2, cpu_regs[a->rs2_or_imm]); 3768 3769 lab = delay_exception(dc, TT_DIV_ZERO); 3770 tcg_gen_brcondi_i32(TCG_COND_EQ, n2, 0, lab); 3771 3772 t2 = tcg_temp_new_i64(); 3773 #ifdef TARGET_SPARC64 3774 tcg_gen_ext32u_i64(t2, cpu_regs[a->rs2_or_imm]); 3775 #else 3776 tcg_gen_extu_i32_i64(t2, cpu_regs[a->rs2_or_imm]); 3777 #endif 3778 } 3779 3780 t1 = tcg_temp_new_i64(); 3781 tcg_gen_concat_tl_i64(t1, gen_load_gpr(dc, a->rs1), cpu_y); 3782 3783 tcg_gen_divu_i64(t1, t1, t2); 3784 tcg_gen_umin_i64(t1, t1, tcg_constant_i64(UINT32_MAX)); 3785 3786 dst = gen_dest_gpr(dc, a->rd); 3787 tcg_gen_trunc_i64_tl(dst, t1); 3788 gen_store_gpr(dc, a->rd, dst); 3789 return advance_pc(dc); 3790 } 3791 3792 static bool trans_UDIVX(DisasContext *dc, arg_r_r_ri *a) 3793 { 3794 TCGv dst, src1, src2; 3795 3796 if (!avail_64(dc)) { 3797 return false; 3798 } 3799 /* For simplicity, we under-decoded the rs2 form. */ 3800 if (!a->imm && a->rs2_or_imm & ~0x1f) { 3801 return false; 3802 } 3803 3804 if (unlikely(a->rs2_or_imm == 0)) { 3805 gen_exception(dc, TT_DIV_ZERO); 3806 return true; 3807 } 3808 3809 if (a->imm) { 3810 src2 = tcg_constant_tl(a->rs2_or_imm); 3811 } else { 3812 TCGLabel *lab; 3813 3814 finishing_insn(dc); 3815 flush_cond(dc); 3816 3817 lab = delay_exception(dc, TT_DIV_ZERO); 3818 src2 = cpu_regs[a->rs2_or_imm]; 3819 tcg_gen_brcondi_tl(TCG_COND_EQ, src2, 0, lab); 3820 } 3821 3822 dst = gen_dest_gpr(dc, a->rd); 3823 src1 = gen_load_gpr(dc, a->rs1); 3824 3825 tcg_gen_divu_tl(dst, src1, src2); 3826 gen_store_gpr(dc, a->rd, dst); 3827 return advance_pc(dc); 3828 } 3829 3830 static bool trans_SDIVX(DisasContext *dc, arg_r_r_ri *a) 3831 { 3832 TCGv dst, src1, src2; 3833 3834 if (!avail_64(dc)) { 3835 return false; 3836 } 3837 /* For simplicity, we under-decoded the rs2 form. */ 3838 if (!a->imm && a->rs2_or_imm & ~0x1f) { 3839 return false; 3840 } 3841 3842 if (unlikely(a->rs2_or_imm == 0)) { 3843 gen_exception(dc, TT_DIV_ZERO); 3844 return true; 3845 } 3846 3847 dst = gen_dest_gpr(dc, a->rd); 3848 src1 = gen_load_gpr(dc, a->rs1); 3849 3850 if (a->imm) { 3851 if (unlikely(a->rs2_or_imm == -1)) { 3852 tcg_gen_neg_tl(dst, src1); 3853 gen_store_gpr(dc, a->rd, dst); 3854 return advance_pc(dc); 3855 } 3856 src2 = tcg_constant_tl(a->rs2_or_imm); 3857 } else { 3858 TCGLabel *lab; 3859 TCGv t1, t2; 3860 3861 finishing_insn(dc); 3862 flush_cond(dc); 3863 3864 lab = delay_exception(dc, TT_DIV_ZERO); 3865 src2 = cpu_regs[a->rs2_or_imm]; 3866 tcg_gen_brcondi_tl(TCG_COND_EQ, src2, 0, lab); 3867 3868 /* 3869 * Need to avoid INT64_MIN / -1, which will trap on x86 host. 3870 * Set SRC2 to 1 as a new divisor, to produce the correct result. 3871 */ 3872 t1 = tcg_temp_new(); 3873 t2 = tcg_temp_new(); 3874 tcg_gen_setcondi_tl(TCG_COND_EQ, t1, src1, (target_long)INT64_MIN); 3875 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, src2, -1); 3876 tcg_gen_and_tl(t1, t1, t2); 3877 tcg_gen_movcond_tl(TCG_COND_NE, t1, t1, tcg_constant_tl(0), 3878 tcg_constant_tl(1), src2); 3879 src2 = t1; 3880 } 3881 3882 tcg_gen_div_tl(dst, src1, src2); 3883 gen_store_gpr(dc, a->rd, dst); 3884 return advance_pc(dc); 3885 } 3886 3887 static bool gen_edge(DisasContext *dc, arg_r_r_r *a, 3888 int width, bool cc, bool little_endian) 3889 { 3890 TCGv dst, s1, s2, l, r, t, m; 3891 uint64_t amask = address_mask_i(dc, -8); 3892 3893 dst = gen_dest_gpr(dc, a->rd); 3894 s1 = gen_load_gpr(dc, a->rs1); 3895 s2 = gen_load_gpr(dc, a->rs2); 3896 3897 if (cc) { 3898 gen_op_subcc(cpu_cc_N, s1, s2); 3899 } 3900 3901 l = tcg_temp_new(); 3902 r = tcg_temp_new(); 3903 t = tcg_temp_new(); 3904 3905 switch (width) { 3906 case 8: 3907 tcg_gen_andi_tl(l, s1, 7); 3908 tcg_gen_andi_tl(r, s2, 7); 3909 tcg_gen_xori_tl(r, r, 7); 3910 m = tcg_constant_tl(0xff); 3911 break; 3912 case 16: 3913 tcg_gen_extract_tl(l, s1, 1, 2); 3914 tcg_gen_extract_tl(r, s2, 1, 2); 3915 tcg_gen_xori_tl(r, r, 3); 3916 m = tcg_constant_tl(0xf); 3917 break; 3918 case 32: 3919 tcg_gen_extract_tl(l, s1, 2, 1); 3920 tcg_gen_extract_tl(r, s2, 2, 1); 3921 tcg_gen_xori_tl(r, r, 1); 3922 m = tcg_constant_tl(0x3); 3923 break; 3924 default: 3925 abort(); 3926 } 3927 3928 /* Compute Left Edge */ 3929 if (little_endian) { 3930 tcg_gen_shl_tl(l, m, l); 3931 tcg_gen_and_tl(l, l, m); 3932 } else { 3933 tcg_gen_shr_tl(l, m, l); 3934 } 3935 /* Compute Right Edge */ 3936 if (little_endian) { 3937 tcg_gen_shr_tl(r, m, r); 3938 } else { 3939 tcg_gen_shl_tl(r, m, r); 3940 tcg_gen_and_tl(r, r, m); 3941 } 3942 3943 /* Compute dst = (s1 == s2 under amask ? l : l & r) */ 3944 tcg_gen_xor_tl(t, s1, s2); 3945 tcg_gen_and_tl(r, r, l); 3946 tcg_gen_movcond_tl(TCG_COND_TSTEQ, dst, t, tcg_constant_tl(amask), r, l); 3947 3948 gen_store_gpr(dc, a->rd, dst); 3949 return advance_pc(dc); 3950 } 3951 3952 TRANS(EDGE8cc, VIS1, gen_edge, a, 8, 1, 0) 3953 TRANS(EDGE8Lcc, VIS1, gen_edge, a, 8, 1, 1) 3954 TRANS(EDGE16cc, VIS1, gen_edge, a, 16, 1, 0) 3955 TRANS(EDGE16Lcc, VIS1, gen_edge, a, 16, 1, 1) 3956 TRANS(EDGE32cc, VIS1, gen_edge, a, 32, 1, 0) 3957 TRANS(EDGE32Lcc, VIS1, gen_edge, a, 32, 1, 1) 3958 3959 TRANS(EDGE8N, VIS2, gen_edge, a, 8, 0, 0) 3960 TRANS(EDGE8LN, VIS2, gen_edge, a, 8, 0, 1) 3961 TRANS(EDGE16N, VIS2, gen_edge, a, 16, 0, 0) 3962 TRANS(EDGE16LN, VIS2, gen_edge, a, 16, 0, 1) 3963 TRANS(EDGE32N, VIS2, gen_edge, a, 32, 0, 0) 3964 TRANS(EDGE32LN, VIS2, gen_edge, a, 32, 0, 1) 3965 3966 static bool do_rr(DisasContext *dc, arg_r_r *a, 3967 void (*func)(TCGv, TCGv)) 3968 { 3969 TCGv dst = gen_dest_gpr(dc, a->rd); 3970 TCGv src = gen_load_gpr(dc, a->rs); 3971 3972 func(dst, src); 3973 gen_store_gpr(dc, a->rd, dst); 3974 return advance_pc(dc); 3975 } 3976 3977 TRANS(LZCNT, VIS3, do_rr, a, gen_op_lzcnt) 3978 3979 static bool do_rrr(DisasContext *dc, arg_r_r_r *a, 3980 void (*func)(TCGv, TCGv, TCGv)) 3981 { 3982 TCGv dst = gen_dest_gpr(dc, a->rd); 3983 TCGv src1 = gen_load_gpr(dc, a->rs1); 3984 TCGv src2 = gen_load_gpr(dc, a->rs2); 3985 3986 func(dst, src1, src2); 3987 gen_store_gpr(dc, a->rd, dst); 3988 return advance_pc(dc); 3989 } 3990 3991 TRANS(ARRAY8, VIS1, do_rrr, a, gen_helper_array8) 3992 TRANS(ARRAY16, VIS1, do_rrr, a, gen_op_array16) 3993 TRANS(ARRAY32, VIS1, do_rrr, a, gen_op_array32) 3994 3995 TRANS(ADDXC, VIS3, do_rrr, a, gen_op_addxc) 3996 TRANS(ADDXCcc, VIS3, do_rrr, a, gen_op_addxccc) 3997 3998 TRANS(SUBXC, VIS4, do_rrr, a, gen_op_subxc) 3999 TRANS(SUBXCcc, VIS4, do_rrr, a, gen_op_subxccc) 4000 4001 TRANS(UMULXHI, VIS3, do_rrr, a, gen_op_umulxhi) 4002 4003 static void gen_op_alignaddr(TCGv dst, TCGv s1, TCGv s2) 4004 { 4005 #ifdef TARGET_SPARC64 4006 TCGv tmp = tcg_temp_new(); 4007 4008 tcg_gen_add_tl(tmp, s1, s2); 4009 tcg_gen_andi_tl(dst, tmp, -8); 4010 tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, tmp, 0, 3); 4011 #else 4012 g_assert_not_reached(); 4013 #endif 4014 } 4015 4016 static void gen_op_alignaddrl(TCGv dst, TCGv s1, TCGv s2) 4017 { 4018 #ifdef TARGET_SPARC64 4019 TCGv tmp = tcg_temp_new(); 4020 4021 tcg_gen_add_tl(tmp, s1, s2); 4022 tcg_gen_andi_tl(dst, tmp, -8); 4023 tcg_gen_neg_tl(tmp, tmp); 4024 tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, tmp, 0, 3); 4025 #else 4026 g_assert_not_reached(); 4027 #endif 4028 } 4029 4030 TRANS(ALIGNADDR, VIS1, do_rrr, a, gen_op_alignaddr) 4031 TRANS(ALIGNADDRL, VIS1, do_rrr, a, gen_op_alignaddrl) 4032 4033 static void gen_op_bmask(TCGv dst, TCGv s1, TCGv s2) 4034 { 4035 #ifdef TARGET_SPARC64 4036 tcg_gen_add_tl(dst, s1, s2); 4037 tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, dst, 32, 32); 4038 #else 4039 g_assert_not_reached(); 4040 #endif 4041 } 4042 4043 TRANS(BMASK, VIS2, do_rrr, a, gen_op_bmask) 4044 4045 static bool do_cmask(DisasContext *dc, int rs2, void (*func)(TCGv, TCGv, TCGv)) 4046 { 4047 func(cpu_gsr, cpu_gsr, gen_load_gpr(dc, rs2)); 4048 return true; 4049 } 4050 4051 TRANS(CMASK8, VIS3, do_cmask, a->rs2, gen_helper_cmask8) 4052 TRANS(CMASK16, VIS3, do_cmask, a->rs2, gen_helper_cmask16) 4053 TRANS(CMASK32, VIS3, do_cmask, a->rs2, gen_helper_cmask32) 4054 4055 static bool do_shift_r(DisasContext *dc, arg_shiftr *a, bool l, bool u) 4056 { 4057 TCGv dst, src1, src2; 4058 4059 /* Reject 64-bit shifts for sparc32. */ 4060 if (avail_32(dc) && a->x) { 4061 return false; 4062 } 4063 4064 src2 = tcg_temp_new(); 4065 tcg_gen_andi_tl(src2, gen_load_gpr(dc, a->rs2), a->x ? 63 : 31); 4066 src1 = gen_load_gpr(dc, a->rs1); 4067 dst = gen_dest_gpr(dc, a->rd); 4068 4069 if (l) { 4070 tcg_gen_shl_tl(dst, src1, src2); 4071 if (!a->x) { 4072 tcg_gen_ext32u_tl(dst, dst); 4073 } 4074 } else if (u) { 4075 if (!a->x) { 4076 tcg_gen_ext32u_tl(dst, src1); 4077 src1 = dst; 4078 } 4079 tcg_gen_shr_tl(dst, src1, src2); 4080 } else { 4081 if (!a->x) { 4082 tcg_gen_ext32s_tl(dst, src1); 4083 src1 = dst; 4084 } 4085 tcg_gen_sar_tl(dst, src1, src2); 4086 } 4087 gen_store_gpr(dc, a->rd, dst); 4088 return advance_pc(dc); 4089 } 4090 4091 TRANS(SLL_r, ALL, do_shift_r, a, true, true) 4092 TRANS(SRL_r, ALL, do_shift_r, a, false, true) 4093 TRANS(SRA_r, ALL, do_shift_r, a, false, false) 4094 4095 static bool do_shift_i(DisasContext *dc, arg_shifti *a, bool l, bool u) 4096 { 4097 TCGv dst, src1; 4098 4099 /* Reject 64-bit shifts for sparc32. */ 4100 if (avail_32(dc) && (a->x || a->i >= 32)) { 4101 return false; 4102 } 4103 4104 src1 = gen_load_gpr(dc, a->rs1); 4105 dst = gen_dest_gpr(dc, a->rd); 4106 4107 if (avail_32(dc) || a->x) { 4108 if (l) { 4109 tcg_gen_shli_tl(dst, src1, a->i); 4110 } else if (u) { 4111 tcg_gen_shri_tl(dst, src1, a->i); 4112 } else { 4113 tcg_gen_sari_tl(dst, src1, a->i); 4114 } 4115 } else { 4116 if (l) { 4117 tcg_gen_deposit_z_tl(dst, src1, a->i, 32 - a->i); 4118 } else if (u) { 4119 tcg_gen_extract_tl(dst, src1, a->i, 32 - a->i); 4120 } else { 4121 tcg_gen_sextract_tl(dst, src1, a->i, 32 - a->i); 4122 } 4123 } 4124 gen_store_gpr(dc, a->rd, dst); 4125 return advance_pc(dc); 4126 } 4127 4128 TRANS(SLL_i, ALL, do_shift_i, a, true, true) 4129 TRANS(SRL_i, ALL, do_shift_i, a, false, true) 4130 TRANS(SRA_i, ALL, do_shift_i, a, false, false) 4131 4132 static TCGv gen_rs2_or_imm(DisasContext *dc, bool imm, int rs2_or_imm) 4133 { 4134 /* For simplicity, we under-decoded the rs2 form. */ 4135 if (!imm && rs2_or_imm & ~0x1f) { 4136 return NULL; 4137 } 4138 if (imm || rs2_or_imm == 0) { 4139 return tcg_constant_tl(rs2_or_imm); 4140 } else { 4141 return cpu_regs[rs2_or_imm]; 4142 } 4143 } 4144 4145 static bool do_mov_cond(DisasContext *dc, DisasCompare *cmp, int rd, TCGv src2) 4146 { 4147 TCGv dst = gen_load_gpr(dc, rd); 4148 TCGv c2 = tcg_constant_tl(cmp->c2); 4149 4150 tcg_gen_movcond_tl(cmp->cond, dst, cmp->c1, c2, src2, dst); 4151 gen_store_gpr(dc, rd, dst); 4152 return advance_pc(dc); 4153 } 4154 4155 static bool trans_MOVcc(DisasContext *dc, arg_MOVcc *a) 4156 { 4157 TCGv src2 = gen_rs2_or_imm(dc, a->imm, a->rs2_or_imm); 4158 DisasCompare cmp; 4159 4160 if (src2 == NULL) { 4161 return false; 4162 } 4163 gen_compare(&cmp, a->cc, a->cond, dc); 4164 return do_mov_cond(dc, &cmp, a->rd, src2); 4165 } 4166 4167 static bool trans_MOVfcc(DisasContext *dc, arg_MOVfcc *a) 4168 { 4169 TCGv src2 = gen_rs2_or_imm(dc, a->imm, a->rs2_or_imm); 4170 DisasCompare cmp; 4171 4172 if (src2 == NULL) { 4173 return false; 4174 } 4175 gen_fcompare(&cmp, a->cc, a->cond); 4176 return do_mov_cond(dc, &cmp, a->rd, src2); 4177 } 4178 4179 static bool trans_MOVR(DisasContext *dc, arg_MOVR *a) 4180 { 4181 TCGv src2 = gen_rs2_or_imm(dc, a->imm, a->rs2_or_imm); 4182 DisasCompare cmp; 4183 4184 if (src2 == NULL) { 4185 return false; 4186 } 4187 if (!gen_compare_reg(&cmp, a->cond, gen_load_gpr(dc, a->rs1))) { 4188 return false; 4189 } 4190 return do_mov_cond(dc, &cmp, a->rd, src2); 4191 } 4192 4193 static bool do_add_special(DisasContext *dc, arg_r_r_ri *a, 4194 bool (*func)(DisasContext *dc, int rd, TCGv src)) 4195 { 4196 TCGv src1, sum; 4197 4198 /* For simplicity, we under-decoded the rs2 form. */ 4199 if (!a->imm && a->rs2_or_imm & ~0x1f) { 4200 return false; 4201 } 4202 4203 /* 4204 * Always load the sum into a new temporary. 4205 * This is required to capture the value across a window change, 4206 * e.g. SAVE and RESTORE, and may be optimized away otherwise. 4207 */ 4208 sum = tcg_temp_new(); 4209 src1 = gen_load_gpr(dc, a->rs1); 4210 if (a->imm || a->rs2_or_imm == 0) { 4211 tcg_gen_addi_tl(sum, src1, a->rs2_or_imm); 4212 } else { 4213 tcg_gen_add_tl(sum, src1, cpu_regs[a->rs2_or_imm]); 4214 } 4215 return func(dc, a->rd, sum); 4216 } 4217 4218 static bool do_jmpl(DisasContext *dc, int rd, TCGv src) 4219 { 4220 /* 4221 * Preserve pc across advance, so that we can delay 4222 * the writeback to rd until after src is consumed. 4223 */ 4224 target_ulong cur_pc = dc->pc; 4225 4226 gen_check_align(dc, src, 3); 4227 4228 gen_mov_pc_npc(dc); 4229 tcg_gen_mov_tl(cpu_npc, src); 4230 gen_address_mask(dc, cpu_npc); 4231 gen_store_gpr(dc, rd, tcg_constant_tl(cur_pc)); 4232 4233 dc->npc = DYNAMIC_PC_LOOKUP; 4234 return true; 4235 } 4236 4237 TRANS(JMPL, ALL, do_add_special, a, do_jmpl) 4238 4239 static bool do_rett(DisasContext *dc, int rd, TCGv src) 4240 { 4241 if (!supervisor(dc)) { 4242 return raise_priv(dc); 4243 } 4244 4245 gen_check_align(dc, src, 3); 4246 4247 gen_mov_pc_npc(dc); 4248 tcg_gen_mov_tl(cpu_npc, src); 4249 gen_helper_rett(tcg_env); 4250 4251 dc->npc = DYNAMIC_PC; 4252 return true; 4253 } 4254 4255 TRANS(RETT, 32, do_add_special, a, do_rett) 4256 4257 static bool do_return(DisasContext *dc, int rd, TCGv src) 4258 { 4259 gen_check_align(dc, src, 3); 4260 gen_helper_restore(tcg_env); 4261 4262 gen_mov_pc_npc(dc); 4263 tcg_gen_mov_tl(cpu_npc, src); 4264 gen_address_mask(dc, cpu_npc); 4265 4266 dc->npc = DYNAMIC_PC_LOOKUP; 4267 return true; 4268 } 4269 4270 TRANS(RETURN, 64, do_add_special, a, do_return) 4271 4272 static bool do_save(DisasContext *dc, int rd, TCGv src) 4273 { 4274 gen_helper_save(tcg_env); 4275 gen_store_gpr(dc, rd, src); 4276 return advance_pc(dc); 4277 } 4278 4279 TRANS(SAVE, ALL, do_add_special, a, do_save) 4280 4281 static bool do_restore(DisasContext *dc, int rd, TCGv src) 4282 { 4283 gen_helper_restore(tcg_env); 4284 gen_store_gpr(dc, rd, src); 4285 return advance_pc(dc); 4286 } 4287 4288 TRANS(RESTORE, ALL, do_add_special, a, do_restore) 4289 4290 static bool do_done_retry(DisasContext *dc, bool done) 4291 { 4292 if (!supervisor(dc)) { 4293 return raise_priv(dc); 4294 } 4295 dc->npc = DYNAMIC_PC; 4296 dc->pc = DYNAMIC_PC; 4297 translator_io_start(&dc->base); 4298 if (done) { 4299 gen_helper_done(tcg_env); 4300 } else { 4301 gen_helper_retry(tcg_env); 4302 } 4303 return true; 4304 } 4305 4306 TRANS(DONE, 64, do_done_retry, true) 4307 TRANS(RETRY, 64, do_done_retry, false) 4308 4309 /* 4310 * Major opcode 11 -- load and store instructions 4311 */ 4312 4313 static TCGv gen_ldst_addr(DisasContext *dc, int rs1, bool imm, int rs2_or_imm) 4314 { 4315 TCGv addr, tmp = NULL; 4316 4317 /* For simplicity, we under-decoded the rs2 form. */ 4318 if (!imm && rs2_or_imm & ~0x1f) { 4319 return NULL; 4320 } 4321 4322 addr = gen_load_gpr(dc, rs1); 4323 if (rs2_or_imm) { 4324 tmp = tcg_temp_new(); 4325 if (imm) { 4326 tcg_gen_addi_tl(tmp, addr, rs2_or_imm); 4327 } else { 4328 tcg_gen_add_tl(tmp, addr, cpu_regs[rs2_or_imm]); 4329 } 4330 addr = tmp; 4331 } 4332 if (AM_CHECK(dc)) { 4333 if (!tmp) { 4334 tmp = tcg_temp_new(); 4335 } 4336 tcg_gen_ext32u_tl(tmp, addr); 4337 addr = tmp; 4338 } 4339 return addr; 4340 } 4341 4342 static bool do_ld_gpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp mop) 4343 { 4344 TCGv reg, addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 4345 DisasASI da; 4346 4347 if (addr == NULL) { 4348 return false; 4349 } 4350 da = resolve_asi(dc, a->asi, mop); 4351 4352 reg = gen_dest_gpr(dc, a->rd); 4353 gen_ld_asi(dc, &da, reg, addr); 4354 gen_store_gpr(dc, a->rd, reg); 4355 return advance_pc(dc); 4356 } 4357 4358 TRANS(LDUW, ALL, do_ld_gpr, a, MO_TEUL) 4359 TRANS(LDUB, ALL, do_ld_gpr, a, MO_UB) 4360 TRANS(LDUH, ALL, do_ld_gpr, a, MO_TEUW) 4361 TRANS(LDSB, ALL, do_ld_gpr, a, MO_SB) 4362 TRANS(LDSH, ALL, do_ld_gpr, a, MO_TESW) 4363 TRANS(LDSW, 64, do_ld_gpr, a, MO_TESL) 4364 TRANS(LDX, 64, do_ld_gpr, a, MO_TEUQ) 4365 4366 static bool do_st_gpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp mop) 4367 { 4368 TCGv reg, addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 4369 DisasASI da; 4370 4371 if (addr == NULL) { 4372 return false; 4373 } 4374 da = resolve_asi(dc, a->asi, mop); 4375 4376 reg = gen_load_gpr(dc, a->rd); 4377 gen_st_asi(dc, &da, reg, addr); 4378 return advance_pc(dc); 4379 } 4380 4381 TRANS(STW, ALL, do_st_gpr, a, MO_TEUL) 4382 TRANS(STB, ALL, do_st_gpr, a, MO_UB) 4383 TRANS(STH, ALL, do_st_gpr, a, MO_TEUW) 4384 TRANS(STX, 64, do_st_gpr, a, MO_TEUQ) 4385 4386 static bool trans_LDD(DisasContext *dc, arg_r_r_ri_asi *a) 4387 { 4388 TCGv addr; 4389 DisasASI da; 4390 4391 if (a->rd & 1) { 4392 return false; 4393 } 4394 addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 4395 if (addr == NULL) { 4396 return false; 4397 } 4398 da = resolve_asi(dc, a->asi, MO_TEUQ); 4399 gen_ldda_asi(dc, &da, addr, a->rd); 4400 return advance_pc(dc); 4401 } 4402 4403 static bool trans_STD(DisasContext *dc, arg_r_r_ri_asi *a) 4404 { 4405 TCGv addr; 4406 DisasASI da; 4407 4408 if (a->rd & 1) { 4409 return false; 4410 } 4411 addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 4412 if (addr == NULL) { 4413 return false; 4414 } 4415 da = resolve_asi(dc, a->asi, MO_TEUQ); 4416 gen_stda_asi(dc, &da, addr, a->rd); 4417 return advance_pc(dc); 4418 } 4419 4420 static bool trans_LDSTUB(DisasContext *dc, arg_r_r_ri_asi *a) 4421 { 4422 TCGv addr, reg; 4423 DisasASI da; 4424 4425 addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 4426 if (addr == NULL) { 4427 return false; 4428 } 4429 da = resolve_asi(dc, a->asi, MO_UB); 4430 4431 reg = gen_dest_gpr(dc, a->rd); 4432 gen_ldstub_asi(dc, &da, reg, addr); 4433 gen_store_gpr(dc, a->rd, reg); 4434 return advance_pc(dc); 4435 } 4436 4437 static bool trans_SWAP(DisasContext *dc, arg_r_r_ri_asi *a) 4438 { 4439 TCGv addr, dst, src; 4440 DisasASI da; 4441 4442 addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 4443 if (addr == NULL) { 4444 return false; 4445 } 4446 da = resolve_asi(dc, a->asi, MO_TEUL); 4447 4448 dst = gen_dest_gpr(dc, a->rd); 4449 src = gen_load_gpr(dc, a->rd); 4450 gen_swap_asi(dc, &da, dst, src, addr); 4451 gen_store_gpr(dc, a->rd, dst); 4452 return advance_pc(dc); 4453 } 4454 4455 static bool do_casa(DisasContext *dc, arg_r_r_ri_asi *a, MemOp mop) 4456 { 4457 TCGv addr, o, n, c; 4458 DisasASI da; 4459 4460 addr = gen_ldst_addr(dc, a->rs1, true, 0); 4461 if (addr == NULL) { 4462 return false; 4463 } 4464 da = resolve_asi(dc, a->asi, mop); 4465 4466 o = gen_dest_gpr(dc, a->rd); 4467 n = gen_load_gpr(dc, a->rd); 4468 c = gen_load_gpr(dc, a->rs2_or_imm); 4469 gen_cas_asi(dc, &da, o, n, c, addr); 4470 gen_store_gpr(dc, a->rd, o); 4471 return advance_pc(dc); 4472 } 4473 4474 TRANS(CASA, CASA, do_casa, a, MO_TEUL) 4475 TRANS(CASXA, 64, do_casa, a, MO_TEUQ) 4476 4477 static bool do_ld_fpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp sz) 4478 { 4479 TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 4480 DisasASI da; 4481 4482 if (addr == NULL) { 4483 return false; 4484 } 4485 if (gen_trap_ifnofpu(dc)) { 4486 return true; 4487 } 4488 if (sz == MO_128 && gen_trap_float128(dc)) { 4489 return true; 4490 } 4491 da = resolve_asi(dc, a->asi, MO_TE | sz); 4492 gen_ldf_asi(dc, &da, sz, addr, a->rd); 4493 gen_update_fprs_dirty(dc, a->rd); 4494 return advance_pc(dc); 4495 } 4496 4497 TRANS(LDF, ALL, do_ld_fpr, a, MO_32) 4498 TRANS(LDDF, ALL, do_ld_fpr, a, MO_64) 4499 TRANS(LDQF, ALL, do_ld_fpr, a, MO_128) 4500 4501 TRANS(LDFA, 64, do_ld_fpr, a, MO_32) 4502 TRANS(LDDFA, 64, do_ld_fpr, a, MO_64) 4503 TRANS(LDQFA, 64, do_ld_fpr, a, MO_128) 4504 4505 static bool do_st_fpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp sz) 4506 { 4507 TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 4508 DisasASI da; 4509 4510 if (addr == NULL) { 4511 return false; 4512 } 4513 if (gen_trap_ifnofpu(dc)) { 4514 return true; 4515 } 4516 if (sz == MO_128 && gen_trap_float128(dc)) { 4517 return true; 4518 } 4519 da = resolve_asi(dc, a->asi, MO_TE | sz); 4520 gen_stf_asi(dc, &da, sz, addr, a->rd); 4521 return advance_pc(dc); 4522 } 4523 4524 TRANS(STF, ALL, do_st_fpr, a, MO_32) 4525 TRANS(STDF, ALL, do_st_fpr, a, MO_64) 4526 TRANS(STQF, 64, do_st_fpr, a, MO_128) 4527 4528 TRANS(STFA, 64, do_st_fpr, a, MO_32) 4529 TRANS(STDFA, 64, do_st_fpr, a, MO_64) 4530 TRANS(STQFA, 64, do_st_fpr, a, MO_128) 4531 4532 static bool trans_STDFQ(DisasContext *dc, arg_STDFQ *a) 4533 { 4534 TCGv addr; 4535 4536 if (!avail_32(dc)) { 4537 return false; 4538 } 4539 addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 4540 if (addr == NULL) { 4541 return false; 4542 } 4543 if (!supervisor(dc)) { 4544 return raise_priv(dc); 4545 } 4546 #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) 4547 if (gen_trap_ifnofpu(dc)) { 4548 return true; 4549 } 4550 if (!dc->fsr_qne) { 4551 gen_op_fpexception_im(dc, FSR_FTT_SEQ_ERROR); 4552 return true; 4553 } 4554 4555 /* Store the single element from the queue. */ 4556 TCGv_i64 fq = tcg_temp_new_i64(); 4557 tcg_gen_ld_i64(fq, tcg_env, offsetof(CPUSPARCState, fq.d)); 4558 tcg_gen_qemu_st_i64(fq, addr, dc->mem_idx, MO_TEUQ | MO_ALIGN_4); 4559 4560 /* Mark the queue empty, transitioning to fp_execute state. */ 4561 tcg_gen_st_i32(tcg_constant_i32(0), tcg_env, 4562 offsetof(CPUSPARCState, fsr_qne)); 4563 dc->fsr_qne = 0; 4564 4565 return advance_pc(dc); 4566 #else 4567 qemu_build_not_reached(); 4568 #endif 4569 } 4570 4571 static bool trans_LDFSR(DisasContext *dc, arg_r_r_ri *a) 4572 { 4573 TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 4574 TCGv_i32 tmp; 4575 4576 if (addr == NULL) { 4577 return false; 4578 } 4579 if (gen_trap_ifnofpu(dc)) { 4580 return true; 4581 } 4582 4583 tmp = tcg_temp_new_i32(); 4584 tcg_gen_qemu_ld_i32(tmp, addr, dc->mem_idx, MO_TEUL | MO_ALIGN); 4585 4586 tcg_gen_extract_i32(cpu_fcc[0], tmp, FSR_FCC0_SHIFT, 2); 4587 /* LDFSR does not change FCC[1-3]. */ 4588 4589 gen_helper_set_fsr_nofcc_noftt(tcg_env, tmp); 4590 return advance_pc(dc); 4591 } 4592 4593 static bool do_ldxfsr(DisasContext *dc, arg_r_r_ri *a, bool entire) 4594 { 4595 #ifdef TARGET_SPARC64 4596 TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 4597 TCGv_i64 t64; 4598 TCGv_i32 lo, hi; 4599 4600 if (addr == NULL) { 4601 return false; 4602 } 4603 if (gen_trap_ifnofpu(dc)) { 4604 return true; 4605 } 4606 4607 t64 = tcg_temp_new_i64(); 4608 tcg_gen_qemu_ld_i64(t64, addr, dc->mem_idx, MO_TEUQ | MO_ALIGN); 4609 4610 lo = tcg_temp_new_i32(); 4611 hi = cpu_fcc[3]; 4612 tcg_gen_extr_i64_i32(lo, hi, t64); 4613 tcg_gen_extract_i32(cpu_fcc[0], lo, FSR_FCC0_SHIFT, 2); 4614 tcg_gen_extract_i32(cpu_fcc[1], hi, FSR_FCC1_SHIFT - 32, 2); 4615 tcg_gen_extract_i32(cpu_fcc[2], hi, FSR_FCC2_SHIFT - 32, 2); 4616 tcg_gen_extract_i32(cpu_fcc[3], hi, FSR_FCC3_SHIFT - 32, 2); 4617 4618 if (entire) { 4619 gen_helper_set_fsr_nofcc(tcg_env, lo); 4620 } else { 4621 gen_helper_set_fsr_nofcc_noftt(tcg_env, lo); 4622 } 4623 return advance_pc(dc); 4624 #else 4625 return false; 4626 #endif 4627 } 4628 4629 TRANS(LDXFSR, 64, do_ldxfsr, a, false) 4630 TRANS(LDXEFSR, VIS3B, do_ldxfsr, a, true) 4631 4632 static bool do_stfsr(DisasContext *dc, arg_r_r_ri *a, MemOp mop) 4633 { 4634 TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 4635 TCGv fsr; 4636 4637 if (addr == NULL) { 4638 return false; 4639 } 4640 if (gen_trap_ifnofpu(dc)) { 4641 return true; 4642 } 4643 4644 fsr = tcg_temp_new(); 4645 gen_helper_get_fsr(fsr, tcg_env); 4646 tcg_gen_qemu_st_tl(fsr, addr, dc->mem_idx, mop | MO_ALIGN); 4647 return advance_pc(dc); 4648 } 4649 4650 TRANS(STFSR, ALL, do_stfsr, a, MO_TEUL) 4651 TRANS(STXFSR, 64, do_stfsr, a, MO_TEUQ) 4652 4653 static bool do_fc(DisasContext *dc, int rd, int32_t c) 4654 { 4655 if (gen_trap_ifnofpu(dc)) { 4656 return true; 4657 } 4658 gen_store_fpr_F(dc, rd, tcg_constant_i32(c)); 4659 return advance_pc(dc); 4660 } 4661 4662 TRANS(FZEROs, VIS1, do_fc, a->rd, 0) 4663 TRANS(FONEs, VIS1, do_fc, a->rd, -1) 4664 4665 static bool do_dc(DisasContext *dc, int rd, int64_t c) 4666 { 4667 if (gen_trap_ifnofpu(dc)) { 4668 return true; 4669 } 4670 gen_store_fpr_D(dc, rd, tcg_constant_i64(c)); 4671 return advance_pc(dc); 4672 } 4673 4674 TRANS(FZEROd, VIS1, do_dc, a->rd, 0) 4675 TRANS(FONEd, VIS1, do_dc, a->rd, -1) 4676 4677 static bool do_ff(DisasContext *dc, arg_r_r *a, 4678 void (*func)(TCGv_i32, TCGv_i32)) 4679 { 4680 TCGv_i32 tmp; 4681 4682 if (gen_trap_ifnofpu(dc)) { 4683 return true; 4684 } 4685 4686 tmp = gen_load_fpr_F(dc, a->rs); 4687 func(tmp, tmp); 4688 gen_store_fpr_F(dc, a->rd, tmp); 4689 return advance_pc(dc); 4690 } 4691 4692 TRANS(FMOVs, ALL, do_ff, a, gen_op_fmovs) 4693 TRANS(FNEGs, ALL, do_ff, a, gen_op_fnegs) 4694 TRANS(FABSs, ALL, do_ff, a, gen_op_fabss) 4695 TRANS(FSRCs, VIS1, do_ff, a, tcg_gen_mov_i32) 4696 TRANS(FNOTs, VIS1, do_ff, a, tcg_gen_not_i32) 4697 4698 static bool do_fd(DisasContext *dc, arg_r_r *a, 4699 void (*func)(TCGv_i32, TCGv_i64)) 4700 { 4701 TCGv_i32 dst; 4702 TCGv_i64 src; 4703 4704 if (gen_trap_ifnofpu(dc)) { 4705 return true; 4706 } 4707 4708 dst = tcg_temp_new_i32(); 4709 src = gen_load_fpr_D(dc, a->rs); 4710 func(dst, src); 4711 gen_store_fpr_F(dc, a->rd, dst); 4712 return advance_pc(dc); 4713 } 4714 4715 TRANS(FPACK16, VIS1, do_fd, a, gen_op_fpack16) 4716 TRANS(FPACKFIX, VIS1, do_fd, a, gen_op_fpackfix) 4717 4718 static bool do_env_ff(DisasContext *dc, arg_r_r *a, 4719 void (*func)(TCGv_i32, TCGv_env, TCGv_i32)) 4720 { 4721 TCGv_i32 tmp; 4722 4723 if (gen_trap_ifnofpu(dc)) { 4724 return true; 4725 } 4726 4727 tmp = gen_load_fpr_F(dc, a->rs); 4728 func(tmp, tcg_env, tmp); 4729 gen_store_fpr_F(dc, a->rd, tmp); 4730 return advance_pc(dc); 4731 } 4732 4733 TRANS(FSQRTs, ALL, do_env_ff, a, gen_helper_fsqrts) 4734 TRANS(FiTOs, ALL, do_env_ff, a, gen_helper_fitos) 4735 TRANS(FsTOi, ALL, do_env_ff, a, gen_helper_fstoi) 4736 4737 static bool do_env_fd(DisasContext *dc, arg_r_r *a, 4738 void (*func)(TCGv_i32, TCGv_env, TCGv_i64)) 4739 { 4740 TCGv_i32 dst; 4741 TCGv_i64 src; 4742 4743 if (gen_trap_ifnofpu(dc)) { 4744 return true; 4745 } 4746 4747 dst = tcg_temp_new_i32(); 4748 src = gen_load_fpr_D(dc, a->rs); 4749 func(dst, tcg_env, src); 4750 gen_store_fpr_F(dc, a->rd, dst); 4751 return advance_pc(dc); 4752 } 4753 4754 TRANS(FdTOs, ALL, do_env_fd, a, gen_helper_fdtos) 4755 TRANS(FdTOi, ALL, do_env_fd, a, gen_helper_fdtoi) 4756 TRANS(FxTOs, 64, do_env_fd, a, gen_helper_fxtos) 4757 4758 static bool do_dd(DisasContext *dc, arg_r_r *a, 4759 void (*func)(TCGv_i64, TCGv_i64)) 4760 { 4761 TCGv_i64 dst, src; 4762 4763 if (gen_trap_ifnofpu(dc)) { 4764 return true; 4765 } 4766 4767 dst = tcg_temp_new_i64(); 4768 src = gen_load_fpr_D(dc, a->rs); 4769 func(dst, src); 4770 gen_store_fpr_D(dc, a->rd, dst); 4771 return advance_pc(dc); 4772 } 4773 4774 TRANS(FMOVd, 64, do_dd, a, gen_op_fmovd) 4775 TRANS(FNEGd, 64, do_dd, a, gen_op_fnegd) 4776 TRANS(FABSd, 64, do_dd, a, gen_op_fabsd) 4777 TRANS(FSRCd, VIS1, do_dd, a, tcg_gen_mov_i64) 4778 TRANS(FNOTd, VIS1, do_dd, a, tcg_gen_not_i64) 4779 4780 static bool do_env_dd(DisasContext *dc, arg_r_r *a, 4781 void (*func)(TCGv_i64, TCGv_env, TCGv_i64)) 4782 { 4783 TCGv_i64 dst, src; 4784 4785 if (gen_trap_ifnofpu(dc)) { 4786 return true; 4787 } 4788 4789 dst = tcg_temp_new_i64(); 4790 src = gen_load_fpr_D(dc, a->rs); 4791 func(dst, tcg_env, src); 4792 gen_store_fpr_D(dc, a->rd, dst); 4793 return advance_pc(dc); 4794 } 4795 4796 TRANS(FSQRTd, ALL, do_env_dd, a, gen_helper_fsqrtd) 4797 TRANS(FxTOd, 64, do_env_dd, a, gen_helper_fxtod) 4798 TRANS(FdTOx, 64, do_env_dd, a, gen_helper_fdtox) 4799 4800 static bool do_df(DisasContext *dc, arg_r_r *a, 4801 void (*func)(TCGv_i64, TCGv_i32)) 4802 { 4803 TCGv_i64 dst; 4804 TCGv_i32 src; 4805 4806 if (gen_trap_ifnofpu(dc)) { 4807 return true; 4808 } 4809 4810 dst = tcg_temp_new_i64(); 4811 src = gen_load_fpr_F(dc, a->rs); 4812 func(dst, src); 4813 gen_store_fpr_D(dc, a->rd, dst); 4814 return advance_pc(dc); 4815 } 4816 4817 TRANS(FEXPAND, VIS1, do_df, a, gen_helper_fexpand) 4818 4819 static bool do_env_df(DisasContext *dc, arg_r_r *a, 4820 void (*func)(TCGv_i64, TCGv_env, TCGv_i32)) 4821 { 4822 TCGv_i64 dst; 4823 TCGv_i32 src; 4824 4825 if (gen_trap_ifnofpu(dc)) { 4826 return true; 4827 } 4828 4829 dst = tcg_temp_new_i64(); 4830 src = gen_load_fpr_F(dc, a->rs); 4831 func(dst, tcg_env, src); 4832 gen_store_fpr_D(dc, a->rd, dst); 4833 return advance_pc(dc); 4834 } 4835 4836 TRANS(FiTOd, ALL, do_env_df, a, gen_helper_fitod) 4837 TRANS(FsTOd, ALL, do_env_df, a, gen_helper_fstod) 4838 TRANS(FsTOx, 64, do_env_df, a, gen_helper_fstox) 4839 4840 static bool do_qq(DisasContext *dc, arg_r_r *a, 4841 void (*func)(TCGv_i128, TCGv_i128)) 4842 { 4843 TCGv_i128 t; 4844 4845 if (gen_trap_ifnofpu(dc)) { 4846 return true; 4847 } 4848 if (gen_trap_float128(dc)) { 4849 return true; 4850 } 4851 4852 gen_op_clear_ieee_excp_and_FTT(); 4853 t = gen_load_fpr_Q(dc, a->rs); 4854 func(t, t); 4855 gen_store_fpr_Q(dc, a->rd, t); 4856 return advance_pc(dc); 4857 } 4858 4859 TRANS(FMOVq, 64, do_qq, a, tcg_gen_mov_i128) 4860 TRANS(FNEGq, 64, do_qq, a, gen_op_fnegq) 4861 TRANS(FABSq, 64, do_qq, a, gen_op_fabsq) 4862 4863 static bool do_env_qq(DisasContext *dc, arg_r_r *a, 4864 void (*func)(TCGv_i128, TCGv_env, TCGv_i128)) 4865 { 4866 TCGv_i128 t; 4867 4868 if (gen_trap_ifnofpu(dc)) { 4869 return true; 4870 } 4871 if (gen_trap_float128(dc)) { 4872 return true; 4873 } 4874 4875 t = gen_load_fpr_Q(dc, a->rs); 4876 func(t, tcg_env, t); 4877 gen_store_fpr_Q(dc, a->rd, t); 4878 return advance_pc(dc); 4879 } 4880 4881 TRANS(FSQRTq, ALL, do_env_qq, a, gen_helper_fsqrtq) 4882 4883 static bool do_env_fq(DisasContext *dc, arg_r_r *a, 4884 void (*func)(TCGv_i32, TCGv_env, TCGv_i128)) 4885 { 4886 TCGv_i128 src; 4887 TCGv_i32 dst; 4888 4889 if (gen_trap_ifnofpu(dc)) { 4890 return true; 4891 } 4892 if (gen_trap_float128(dc)) { 4893 return true; 4894 } 4895 4896 src = gen_load_fpr_Q(dc, a->rs); 4897 dst = tcg_temp_new_i32(); 4898 func(dst, tcg_env, src); 4899 gen_store_fpr_F(dc, a->rd, dst); 4900 return advance_pc(dc); 4901 } 4902 4903 TRANS(FqTOs, ALL, do_env_fq, a, gen_helper_fqtos) 4904 TRANS(FqTOi, ALL, do_env_fq, a, gen_helper_fqtoi) 4905 4906 static bool do_env_dq(DisasContext *dc, arg_r_r *a, 4907 void (*func)(TCGv_i64, TCGv_env, TCGv_i128)) 4908 { 4909 TCGv_i128 src; 4910 TCGv_i64 dst; 4911 4912 if (gen_trap_ifnofpu(dc)) { 4913 return true; 4914 } 4915 if (gen_trap_float128(dc)) { 4916 return true; 4917 } 4918 4919 src = gen_load_fpr_Q(dc, a->rs); 4920 dst = tcg_temp_new_i64(); 4921 func(dst, tcg_env, src); 4922 gen_store_fpr_D(dc, a->rd, dst); 4923 return advance_pc(dc); 4924 } 4925 4926 TRANS(FqTOd, ALL, do_env_dq, a, gen_helper_fqtod) 4927 TRANS(FqTOx, 64, do_env_dq, a, gen_helper_fqtox) 4928 4929 static bool do_env_qf(DisasContext *dc, arg_r_r *a, 4930 void (*func)(TCGv_i128, TCGv_env, TCGv_i32)) 4931 { 4932 TCGv_i32 src; 4933 TCGv_i128 dst; 4934 4935 if (gen_trap_ifnofpu(dc)) { 4936 return true; 4937 } 4938 if (gen_trap_float128(dc)) { 4939 return true; 4940 } 4941 4942 src = gen_load_fpr_F(dc, a->rs); 4943 dst = tcg_temp_new_i128(); 4944 func(dst, tcg_env, src); 4945 gen_store_fpr_Q(dc, a->rd, dst); 4946 return advance_pc(dc); 4947 } 4948 4949 TRANS(FiTOq, ALL, do_env_qf, a, gen_helper_fitoq) 4950 TRANS(FsTOq, ALL, do_env_qf, a, gen_helper_fstoq) 4951 4952 static bool do_env_qd(DisasContext *dc, arg_r_r *a, 4953 void (*func)(TCGv_i128, TCGv_env, TCGv_i64)) 4954 { 4955 TCGv_i64 src; 4956 TCGv_i128 dst; 4957 4958 if (gen_trap_ifnofpu(dc)) { 4959 return true; 4960 } 4961 if (gen_trap_float128(dc)) { 4962 return true; 4963 } 4964 4965 src = gen_load_fpr_D(dc, a->rs); 4966 dst = tcg_temp_new_i128(); 4967 func(dst, tcg_env, src); 4968 gen_store_fpr_Q(dc, a->rd, dst); 4969 return advance_pc(dc); 4970 } 4971 4972 TRANS(FdTOq, ALL, do_env_qd, a, gen_helper_fdtoq) 4973 TRANS(FxTOq, 64, do_env_qd, a, gen_helper_fxtoq) 4974 4975 static bool do_fff(DisasContext *dc, arg_r_r_r *a, 4976 void (*func)(TCGv_i32, TCGv_i32, TCGv_i32)) 4977 { 4978 TCGv_i32 src1, src2; 4979 4980 if (gen_trap_ifnofpu(dc)) { 4981 return true; 4982 } 4983 4984 src1 = gen_load_fpr_F(dc, a->rs1); 4985 src2 = gen_load_fpr_F(dc, a->rs2); 4986 func(src1, src1, src2); 4987 gen_store_fpr_F(dc, a->rd, src1); 4988 return advance_pc(dc); 4989 } 4990 4991 TRANS(FPADD16s, VIS1, do_fff, a, tcg_gen_vec_add16_i32) 4992 TRANS(FPADD32s, VIS1, do_fff, a, tcg_gen_add_i32) 4993 TRANS(FPSUB16s, VIS1, do_fff, a, tcg_gen_vec_sub16_i32) 4994 TRANS(FPSUB32s, VIS1, do_fff, a, tcg_gen_sub_i32) 4995 TRANS(FNORs, VIS1, do_fff, a, tcg_gen_nor_i32) 4996 TRANS(FANDNOTs, VIS1, do_fff, a, tcg_gen_andc_i32) 4997 TRANS(FXORs, VIS1, do_fff, a, tcg_gen_xor_i32) 4998 TRANS(FNANDs, VIS1, do_fff, a, tcg_gen_nand_i32) 4999 TRANS(FANDs, VIS1, do_fff, a, tcg_gen_and_i32) 5000 TRANS(FXNORs, VIS1, do_fff, a, tcg_gen_eqv_i32) 5001 TRANS(FORNOTs, VIS1, do_fff, a, tcg_gen_orc_i32) 5002 TRANS(FORs, VIS1, do_fff, a, tcg_gen_or_i32) 5003 5004 TRANS(FHADDs, VIS3, do_fff, a, gen_op_fhadds) 5005 TRANS(FHSUBs, VIS3, do_fff, a, gen_op_fhsubs) 5006 TRANS(FNHADDs, VIS3, do_fff, a, gen_op_fnhadds) 5007 5008 TRANS(FPADDS16s, VIS3, do_fff, a, gen_op_fpadds16s) 5009 TRANS(FPSUBS16s, VIS3, do_fff, a, gen_op_fpsubs16s) 5010 TRANS(FPADDS32s, VIS3, do_fff, a, gen_op_fpadds32s) 5011 TRANS(FPSUBS32s, VIS3, do_fff, a, gen_op_fpsubs32s) 5012 5013 static bool do_env_fff(DisasContext *dc, arg_r_r_r *a, 5014 void (*func)(TCGv_i32, TCGv_env, TCGv_i32, TCGv_i32)) 5015 { 5016 TCGv_i32 src1, src2; 5017 5018 if (gen_trap_ifnofpu(dc)) { 5019 return true; 5020 } 5021 5022 src1 = gen_load_fpr_F(dc, a->rs1); 5023 src2 = gen_load_fpr_F(dc, a->rs2); 5024 func(src1, tcg_env, src1, src2); 5025 gen_store_fpr_F(dc, a->rd, src1); 5026 return advance_pc(dc); 5027 } 5028 5029 TRANS(FADDs, ALL, do_env_fff, a, gen_helper_fadds) 5030 TRANS(FSUBs, ALL, do_env_fff, a, gen_helper_fsubs) 5031 TRANS(FMULs, ALL, do_env_fff, a, gen_helper_fmuls) 5032 TRANS(FDIVs, ALL, do_env_fff, a, gen_helper_fdivs) 5033 TRANS(FNADDs, VIS3, do_env_fff, a, gen_helper_fnadds) 5034 TRANS(FNMULs, VIS3, do_env_fff, a, gen_helper_fnmuls) 5035 5036 static bool do_dff(DisasContext *dc, arg_r_r_r *a, 5037 void (*func)(TCGv_i64, TCGv_i32, TCGv_i32)) 5038 { 5039 TCGv_i64 dst; 5040 TCGv_i32 src1, src2; 5041 5042 if (gen_trap_ifnofpu(dc)) { 5043 return true; 5044 } 5045 5046 dst = tcg_temp_new_i64(); 5047 src1 = gen_load_fpr_F(dc, a->rs1); 5048 src2 = gen_load_fpr_F(dc, a->rs2); 5049 func(dst, src1, src2); 5050 gen_store_fpr_D(dc, a->rd, dst); 5051 return advance_pc(dc); 5052 } 5053 5054 TRANS(FMUL8x16AU, VIS1, do_dff, a, gen_op_fmul8x16au) 5055 TRANS(FMUL8x16AL, VIS1, do_dff, a, gen_op_fmul8x16al) 5056 TRANS(FMULD8SUx16, VIS1, do_dff, a, gen_op_fmuld8sux16) 5057 TRANS(FMULD8ULx16, VIS1, do_dff, a, gen_op_fmuld8ulx16) 5058 TRANS(FPMERGE, VIS1, do_dff, a, gen_helper_fpmerge) 5059 5060 static bool do_dfd(DisasContext *dc, arg_r_r_r *a, 5061 void (*func)(TCGv_i64, TCGv_i32, TCGv_i64)) 5062 { 5063 TCGv_i64 dst, src2; 5064 TCGv_i32 src1; 5065 5066 if (gen_trap_ifnofpu(dc)) { 5067 return true; 5068 } 5069 5070 dst = tcg_temp_new_i64(); 5071 src1 = gen_load_fpr_F(dc, a->rs1); 5072 src2 = gen_load_fpr_D(dc, a->rs2); 5073 func(dst, src1, src2); 5074 gen_store_fpr_D(dc, a->rd, dst); 5075 return advance_pc(dc); 5076 } 5077 5078 TRANS(FMUL8x16, VIS1, do_dfd, a, gen_helper_fmul8x16) 5079 5080 static bool do_gvec_ddd(DisasContext *dc, arg_r_r_r *a, MemOp vece, 5081 void (*func)(unsigned, uint32_t, uint32_t, 5082 uint32_t, uint32_t, uint32_t)) 5083 { 5084 if (gen_trap_ifnofpu(dc)) { 5085 return true; 5086 } 5087 5088 func(vece, gen_offset_fpr_D(a->rd), gen_offset_fpr_D(a->rs1), 5089 gen_offset_fpr_D(a->rs2), 8, 8); 5090 return advance_pc(dc); 5091 } 5092 5093 TRANS(FPADD8, VIS4, do_gvec_ddd, a, MO_8, tcg_gen_gvec_add) 5094 TRANS(FPADD16, VIS1, do_gvec_ddd, a, MO_16, tcg_gen_gvec_add) 5095 TRANS(FPADD32, VIS1, do_gvec_ddd, a, MO_32, tcg_gen_gvec_add) 5096 5097 TRANS(FPSUB8, VIS4, do_gvec_ddd, a, MO_8, tcg_gen_gvec_sub) 5098 TRANS(FPSUB16, VIS1, do_gvec_ddd, a, MO_16, tcg_gen_gvec_sub) 5099 TRANS(FPSUB32, VIS1, do_gvec_ddd, a, MO_32, tcg_gen_gvec_sub) 5100 5101 TRANS(FCHKSM16, VIS3, do_gvec_ddd, a, MO_16, gen_op_fchksm16) 5102 TRANS(FMEAN16, VIS3, do_gvec_ddd, a, MO_16, gen_op_fmean16) 5103 5104 TRANS(FPADDS8, VIS4, do_gvec_ddd, a, MO_8, tcg_gen_gvec_ssadd) 5105 TRANS(FPADDS16, VIS3, do_gvec_ddd, a, MO_16, tcg_gen_gvec_ssadd) 5106 TRANS(FPADDS32, VIS3, do_gvec_ddd, a, MO_32, tcg_gen_gvec_ssadd) 5107 TRANS(FPADDUS8, VIS4, do_gvec_ddd, a, MO_8, tcg_gen_gvec_usadd) 5108 TRANS(FPADDUS16, VIS4, do_gvec_ddd, a, MO_16, tcg_gen_gvec_usadd) 5109 5110 TRANS(FPSUBS8, VIS4, do_gvec_ddd, a, MO_8, tcg_gen_gvec_sssub) 5111 TRANS(FPSUBS16, VIS3, do_gvec_ddd, a, MO_16, tcg_gen_gvec_sssub) 5112 TRANS(FPSUBS32, VIS3, do_gvec_ddd, a, MO_32, tcg_gen_gvec_sssub) 5113 TRANS(FPSUBUS8, VIS4, do_gvec_ddd, a, MO_8, tcg_gen_gvec_ussub) 5114 TRANS(FPSUBUS16, VIS4, do_gvec_ddd, a, MO_16, tcg_gen_gvec_ussub) 5115 5116 TRANS(FSLL16, VIS3, do_gvec_ddd, a, MO_16, tcg_gen_gvec_shlv) 5117 TRANS(FSLL32, VIS3, do_gvec_ddd, a, MO_32, tcg_gen_gvec_shlv) 5118 TRANS(FSRL16, VIS3, do_gvec_ddd, a, MO_16, tcg_gen_gvec_shrv) 5119 TRANS(FSRL32, VIS3, do_gvec_ddd, a, MO_32, tcg_gen_gvec_shrv) 5120 TRANS(FSRA16, VIS3, do_gvec_ddd, a, MO_16, tcg_gen_gvec_sarv) 5121 TRANS(FSRA32, VIS3, do_gvec_ddd, a, MO_32, tcg_gen_gvec_sarv) 5122 5123 TRANS(FPMIN8, VIS4, do_gvec_ddd, a, MO_8, tcg_gen_gvec_smin) 5124 TRANS(FPMIN16, VIS4, do_gvec_ddd, a, MO_16, tcg_gen_gvec_smin) 5125 TRANS(FPMIN32, VIS4, do_gvec_ddd, a, MO_32, tcg_gen_gvec_smin) 5126 TRANS(FPMINU8, VIS4, do_gvec_ddd, a, MO_8, tcg_gen_gvec_umin) 5127 TRANS(FPMINU16, VIS4, do_gvec_ddd, a, MO_16, tcg_gen_gvec_umin) 5128 TRANS(FPMINU32, VIS4, do_gvec_ddd, a, MO_32, tcg_gen_gvec_umin) 5129 5130 TRANS(FPMAX8, VIS4, do_gvec_ddd, a, MO_8, tcg_gen_gvec_smax) 5131 TRANS(FPMAX16, VIS4, do_gvec_ddd, a, MO_16, tcg_gen_gvec_smax) 5132 TRANS(FPMAX32, VIS4, do_gvec_ddd, a, MO_32, tcg_gen_gvec_smax) 5133 TRANS(FPMAXU8, VIS4, do_gvec_ddd, a, MO_8, tcg_gen_gvec_umax) 5134 TRANS(FPMAXU16, VIS4, do_gvec_ddd, a, MO_16, tcg_gen_gvec_umax) 5135 TRANS(FPMAXU32, VIS4, do_gvec_ddd, a, MO_32, tcg_gen_gvec_umax) 5136 5137 static bool do_ddd(DisasContext *dc, arg_r_r_r *a, 5138 void (*func)(TCGv_i64, TCGv_i64, TCGv_i64)) 5139 { 5140 TCGv_i64 dst, src1, src2; 5141 5142 if (gen_trap_ifnofpu(dc)) { 5143 return true; 5144 } 5145 5146 dst = tcg_temp_new_i64(); 5147 src1 = gen_load_fpr_D(dc, a->rs1); 5148 src2 = gen_load_fpr_D(dc, a->rs2); 5149 func(dst, src1, src2); 5150 gen_store_fpr_D(dc, a->rd, dst); 5151 return advance_pc(dc); 5152 } 5153 5154 TRANS(FMUL8SUx16, VIS1, do_ddd, a, gen_helper_fmul8sux16) 5155 TRANS(FMUL8ULx16, VIS1, do_ddd, a, gen_helper_fmul8ulx16) 5156 5157 TRANS(FNORd, VIS1, do_ddd, a, tcg_gen_nor_i64) 5158 TRANS(FANDNOTd, VIS1, do_ddd, a, tcg_gen_andc_i64) 5159 TRANS(FXORd, VIS1, do_ddd, a, tcg_gen_xor_i64) 5160 TRANS(FNANDd, VIS1, do_ddd, a, tcg_gen_nand_i64) 5161 TRANS(FANDd, VIS1, do_ddd, a, tcg_gen_and_i64) 5162 TRANS(FXNORd, VIS1, do_ddd, a, tcg_gen_eqv_i64) 5163 TRANS(FORNOTd, VIS1, do_ddd, a, tcg_gen_orc_i64) 5164 TRANS(FORd, VIS1, do_ddd, a, tcg_gen_or_i64) 5165 5166 TRANS(FPACK32, VIS1, do_ddd, a, gen_op_fpack32) 5167 TRANS(FALIGNDATAg, VIS1, do_ddd, a, gen_op_faligndata_g) 5168 TRANS(BSHUFFLE, VIS2, do_ddd, a, gen_op_bshuffle) 5169 5170 TRANS(FHADDd, VIS3, do_ddd, a, gen_op_fhaddd) 5171 TRANS(FHSUBd, VIS3, do_ddd, a, gen_op_fhsubd) 5172 TRANS(FNHADDd, VIS3, do_ddd, a, gen_op_fnhaddd) 5173 5174 TRANS(FPADD64, VIS3B, do_ddd, a, tcg_gen_add_i64) 5175 TRANS(FPSUB64, VIS3B, do_ddd, a, tcg_gen_sub_i64) 5176 TRANS(FSLAS16, VIS3, do_ddd, a, gen_helper_fslas16) 5177 TRANS(FSLAS32, VIS3, do_ddd, a, gen_helper_fslas32) 5178 5179 static bool do_rdd(DisasContext *dc, arg_r_r_r *a, 5180 void (*func)(TCGv, TCGv_i64, TCGv_i64)) 5181 { 5182 TCGv_i64 src1, src2; 5183 TCGv dst; 5184 5185 if (gen_trap_ifnofpu(dc)) { 5186 return true; 5187 } 5188 5189 dst = gen_dest_gpr(dc, a->rd); 5190 src1 = gen_load_fpr_D(dc, a->rs1); 5191 src2 = gen_load_fpr_D(dc, a->rs2); 5192 func(dst, src1, src2); 5193 gen_store_gpr(dc, a->rd, dst); 5194 return advance_pc(dc); 5195 } 5196 5197 TRANS(FPCMPLE16, VIS1, do_rdd, a, gen_helper_fcmple16) 5198 TRANS(FPCMPNE16, VIS1, do_rdd, a, gen_helper_fcmpne16) 5199 TRANS(FPCMPGT16, VIS1, do_rdd, a, gen_helper_fcmpgt16) 5200 TRANS(FPCMPEQ16, VIS1, do_rdd, a, gen_helper_fcmpeq16) 5201 TRANS(FPCMPULE16, VIS4, do_rdd, a, gen_helper_fcmpule16) 5202 TRANS(FPCMPUGT16, VIS4, do_rdd, a, gen_helper_fcmpugt16) 5203 5204 TRANS(FPCMPLE32, VIS1, do_rdd, a, gen_helper_fcmple32) 5205 TRANS(FPCMPNE32, VIS1, do_rdd, a, gen_helper_fcmpne32) 5206 TRANS(FPCMPGT32, VIS1, do_rdd, a, gen_helper_fcmpgt32) 5207 TRANS(FPCMPEQ32, VIS1, do_rdd, a, gen_helper_fcmpeq32) 5208 TRANS(FPCMPULE32, VIS4, do_rdd, a, gen_helper_fcmpule32) 5209 TRANS(FPCMPUGT32, VIS4, do_rdd, a, gen_helper_fcmpugt32) 5210 5211 TRANS(FPCMPEQ8, VIS3B, do_rdd, a, gen_helper_fcmpeq8) 5212 TRANS(FPCMPNE8, VIS3B, do_rdd, a, gen_helper_fcmpne8) 5213 TRANS(FPCMPULE8, VIS3B, do_rdd, a, gen_helper_fcmpule8) 5214 TRANS(FPCMPUGT8, VIS3B, do_rdd, a, gen_helper_fcmpugt8) 5215 TRANS(FPCMPLE8, VIS4, do_rdd, a, gen_helper_fcmple8) 5216 TRANS(FPCMPGT8, VIS4, do_rdd, a, gen_helper_fcmpgt8) 5217 5218 TRANS(PDISTN, VIS3, do_rdd, a, gen_op_pdistn) 5219 TRANS(XMULX, VIS3, do_rrr, a, gen_helper_xmulx) 5220 TRANS(XMULXHI, VIS3, do_rrr, a, gen_helper_xmulxhi) 5221 5222 static bool do_env_ddd(DisasContext *dc, arg_r_r_r *a, 5223 void (*func)(TCGv_i64, TCGv_env, TCGv_i64, TCGv_i64)) 5224 { 5225 TCGv_i64 dst, src1, src2; 5226 5227 if (gen_trap_ifnofpu(dc)) { 5228 return true; 5229 } 5230 5231 dst = tcg_temp_new_i64(); 5232 src1 = gen_load_fpr_D(dc, a->rs1); 5233 src2 = gen_load_fpr_D(dc, a->rs2); 5234 func(dst, tcg_env, src1, src2); 5235 gen_store_fpr_D(dc, a->rd, dst); 5236 return advance_pc(dc); 5237 } 5238 5239 TRANS(FADDd, ALL, do_env_ddd, a, gen_helper_faddd) 5240 TRANS(FSUBd, ALL, do_env_ddd, a, gen_helper_fsubd) 5241 TRANS(FMULd, ALL, do_env_ddd, a, gen_helper_fmuld) 5242 TRANS(FDIVd, ALL, do_env_ddd, a, gen_helper_fdivd) 5243 TRANS(FNADDd, VIS3, do_env_ddd, a, gen_helper_fnaddd) 5244 TRANS(FNMULd, VIS3, do_env_ddd, a, gen_helper_fnmuld) 5245 5246 static bool trans_FsMULd(DisasContext *dc, arg_r_r_r *a) 5247 { 5248 TCGv_i64 dst; 5249 TCGv_i32 src1, src2; 5250 5251 if (gen_trap_ifnofpu(dc)) { 5252 return true; 5253 } 5254 if (!(dc->def->features & CPU_FEATURE_FSMULD)) { 5255 return raise_unimpfpop(dc); 5256 } 5257 5258 dst = tcg_temp_new_i64(); 5259 src1 = gen_load_fpr_F(dc, a->rs1); 5260 src2 = gen_load_fpr_F(dc, a->rs2); 5261 gen_helper_fsmuld(dst, tcg_env, src1, src2); 5262 gen_store_fpr_D(dc, a->rd, dst); 5263 return advance_pc(dc); 5264 } 5265 5266 static bool trans_FNsMULd(DisasContext *dc, arg_r_r_r *a) 5267 { 5268 TCGv_i64 dst; 5269 TCGv_i32 src1, src2; 5270 5271 if (!avail_VIS3(dc)) { 5272 return false; 5273 } 5274 if (gen_trap_ifnofpu(dc)) { 5275 return true; 5276 } 5277 dst = tcg_temp_new_i64(); 5278 src1 = gen_load_fpr_F(dc, a->rs1); 5279 src2 = gen_load_fpr_F(dc, a->rs2); 5280 gen_helper_fnsmuld(dst, tcg_env, src1, src2); 5281 gen_store_fpr_D(dc, a->rd, dst); 5282 return advance_pc(dc); 5283 } 5284 5285 static bool do_ffff(DisasContext *dc, arg_r_r_r_r *a, 5286 void (*func)(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_i32)) 5287 { 5288 TCGv_i32 dst, src1, src2, src3; 5289 5290 if (gen_trap_ifnofpu(dc)) { 5291 return true; 5292 } 5293 5294 src1 = gen_load_fpr_F(dc, a->rs1); 5295 src2 = gen_load_fpr_F(dc, a->rs2); 5296 src3 = gen_load_fpr_F(dc, a->rs3); 5297 dst = tcg_temp_new_i32(); 5298 func(dst, src1, src2, src3); 5299 gen_store_fpr_F(dc, a->rd, dst); 5300 return advance_pc(dc); 5301 } 5302 5303 TRANS(FMADDs, FMAF, do_ffff, a, gen_op_fmadds) 5304 TRANS(FMSUBs, FMAF, do_ffff, a, gen_op_fmsubs) 5305 TRANS(FNMSUBs, FMAF, do_ffff, a, gen_op_fnmsubs) 5306 TRANS(FNMADDs, FMAF, do_ffff, a, gen_op_fnmadds) 5307 5308 static bool do_dddd(DisasContext *dc, arg_r_r_r_r *a, 5309 void (*func)(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_i64)) 5310 { 5311 TCGv_i64 dst, src1, src2, src3; 5312 5313 if (gen_trap_ifnofpu(dc)) { 5314 return true; 5315 } 5316 5317 dst = tcg_temp_new_i64(); 5318 src1 = gen_load_fpr_D(dc, a->rs1); 5319 src2 = gen_load_fpr_D(dc, a->rs2); 5320 src3 = gen_load_fpr_D(dc, a->rs3); 5321 func(dst, src1, src2, src3); 5322 gen_store_fpr_D(dc, a->rd, dst); 5323 return advance_pc(dc); 5324 } 5325 5326 TRANS(PDIST, VIS1, do_dddd, a, gen_helper_pdist) 5327 TRANS(FMADDd, FMAF, do_dddd, a, gen_op_fmaddd) 5328 TRANS(FMSUBd, FMAF, do_dddd, a, gen_op_fmsubd) 5329 TRANS(FNMSUBd, FMAF, do_dddd, a, gen_op_fnmsubd) 5330 TRANS(FNMADDd, FMAF, do_dddd, a, gen_op_fnmaddd) 5331 TRANS(FPMADDX, IMA, do_dddd, a, gen_op_fpmaddx) 5332 TRANS(FPMADDXHI, IMA, do_dddd, a, gen_op_fpmaddxhi) 5333 5334 static bool trans_FALIGNDATAi(DisasContext *dc, arg_r_r_r *a) 5335 { 5336 TCGv_i64 dst, src1, src2; 5337 TCGv src3; 5338 5339 if (!avail_VIS4(dc)) { 5340 return false; 5341 } 5342 if (gen_trap_ifnofpu(dc)) { 5343 return true; 5344 } 5345 5346 dst = tcg_temp_new_i64(); 5347 src1 = gen_load_fpr_D(dc, a->rd); 5348 src2 = gen_load_fpr_D(dc, a->rs2); 5349 src3 = gen_load_gpr(dc, a->rs1); 5350 gen_op_faligndata_i(dst, src1, src2, src3); 5351 gen_store_fpr_D(dc, a->rd, dst); 5352 return advance_pc(dc); 5353 } 5354 5355 static bool do_env_qqq(DisasContext *dc, arg_r_r_r *a, 5356 void (*func)(TCGv_i128, TCGv_env, TCGv_i128, TCGv_i128)) 5357 { 5358 TCGv_i128 src1, src2; 5359 5360 if (gen_trap_ifnofpu(dc)) { 5361 return true; 5362 } 5363 if (gen_trap_float128(dc)) { 5364 return true; 5365 } 5366 5367 src1 = gen_load_fpr_Q(dc, a->rs1); 5368 src2 = gen_load_fpr_Q(dc, a->rs2); 5369 func(src1, tcg_env, src1, src2); 5370 gen_store_fpr_Q(dc, a->rd, src1); 5371 return advance_pc(dc); 5372 } 5373 5374 TRANS(FADDq, ALL, do_env_qqq, a, gen_helper_faddq) 5375 TRANS(FSUBq, ALL, do_env_qqq, a, gen_helper_fsubq) 5376 TRANS(FMULq, ALL, do_env_qqq, a, gen_helper_fmulq) 5377 TRANS(FDIVq, ALL, do_env_qqq, a, gen_helper_fdivq) 5378 5379 static bool trans_FdMULq(DisasContext *dc, arg_r_r_r *a) 5380 { 5381 TCGv_i64 src1, src2; 5382 TCGv_i128 dst; 5383 5384 if (gen_trap_ifnofpu(dc)) { 5385 return true; 5386 } 5387 if (gen_trap_float128(dc)) { 5388 return true; 5389 } 5390 5391 src1 = gen_load_fpr_D(dc, a->rs1); 5392 src2 = gen_load_fpr_D(dc, a->rs2); 5393 dst = tcg_temp_new_i128(); 5394 gen_helper_fdmulq(dst, tcg_env, src1, src2); 5395 gen_store_fpr_Q(dc, a->rd, dst); 5396 return advance_pc(dc); 5397 } 5398 5399 static bool do_fmovr(DisasContext *dc, arg_FMOVRs *a, bool is_128, 5400 void (*func)(DisasContext *, DisasCompare *, int, int)) 5401 { 5402 DisasCompare cmp; 5403 5404 if (!gen_compare_reg(&cmp, a->cond, gen_load_gpr(dc, a->rs1))) { 5405 return false; 5406 } 5407 if (gen_trap_ifnofpu(dc)) { 5408 return true; 5409 } 5410 if (is_128 && gen_trap_float128(dc)) { 5411 return true; 5412 } 5413 5414 gen_op_clear_ieee_excp_and_FTT(); 5415 func(dc, &cmp, a->rd, a->rs2); 5416 return advance_pc(dc); 5417 } 5418 5419 TRANS(FMOVRs, 64, do_fmovr, a, false, gen_fmovs) 5420 TRANS(FMOVRd, 64, do_fmovr, a, false, gen_fmovd) 5421 TRANS(FMOVRq, 64, do_fmovr, a, true, gen_fmovq) 5422 5423 static bool do_fmovcc(DisasContext *dc, arg_FMOVscc *a, bool is_128, 5424 void (*func)(DisasContext *, DisasCompare *, int, int)) 5425 { 5426 DisasCompare cmp; 5427 5428 if (gen_trap_ifnofpu(dc)) { 5429 return true; 5430 } 5431 if (is_128 && gen_trap_float128(dc)) { 5432 return true; 5433 } 5434 5435 gen_op_clear_ieee_excp_and_FTT(); 5436 gen_compare(&cmp, a->cc, a->cond, dc); 5437 func(dc, &cmp, a->rd, a->rs2); 5438 return advance_pc(dc); 5439 } 5440 5441 TRANS(FMOVscc, 64, do_fmovcc, a, false, gen_fmovs) 5442 TRANS(FMOVdcc, 64, do_fmovcc, a, false, gen_fmovd) 5443 TRANS(FMOVqcc, 64, do_fmovcc, a, true, gen_fmovq) 5444 5445 static bool do_fmovfcc(DisasContext *dc, arg_FMOVsfcc *a, bool is_128, 5446 void (*func)(DisasContext *, DisasCompare *, int, int)) 5447 { 5448 DisasCompare cmp; 5449 5450 if (gen_trap_ifnofpu(dc)) { 5451 return true; 5452 } 5453 if (is_128 && gen_trap_float128(dc)) { 5454 return true; 5455 } 5456 5457 gen_op_clear_ieee_excp_and_FTT(); 5458 gen_fcompare(&cmp, a->cc, a->cond); 5459 func(dc, &cmp, a->rd, a->rs2); 5460 return advance_pc(dc); 5461 } 5462 5463 TRANS(FMOVsfcc, 64, do_fmovfcc, a, false, gen_fmovs) 5464 TRANS(FMOVdfcc, 64, do_fmovfcc, a, false, gen_fmovd) 5465 TRANS(FMOVqfcc, 64, do_fmovfcc, a, true, gen_fmovq) 5466 5467 static bool do_fcmps(DisasContext *dc, arg_FCMPs *a, bool e) 5468 { 5469 TCGv_i32 src1, src2; 5470 5471 if (avail_32(dc) && a->cc != 0) { 5472 return false; 5473 } 5474 if (gen_trap_ifnofpu(dc)) { 5475 return true; 5476 } 5477 5478 src1 = gen_load_fpr_F(dc, a->rs1); 5479 src2 = gen_load_fpr_F(dc, a->rs2); 5480 if (e) { 5481 gen_helper_fcmpes(cpu_fcc[a->cc], tcg_env, src1, src2); 5482 } else { 5483 gen_helper_fcmps(cpu_fcc[a->cc], tcg_env, src1, src2); 5484 } 5485 return advance_pc(dc); 5486 } 5487 5488 TRANS(FCMPs, ALL, do_fcmps, a, false) 5489 TRANS(FCMPEs, ALL, do_fcmps, a, true) 5490 5491 static bool do_fcmpd(DisasContext *dc, arg_FCMPd *a, bool e) 5492 { 5493 TCGv_i64 src1, src2; 5494 5495 if (avail_32(dc) && a->cc != 0) { 5496 return false; 5497 } 5498 if (gen_trap_ifnofpu(dc)) { 5499 return true; 5500 } 5501 5502 src1 = gen_load_fpr_D(dc, a->rs1); 5503 src2 = gen_load_fpr_D(dc, a->rs2); 5504 if (e) { 5505 gen_helper_fcmped(cpu_fcc[a->cc], tcg_env, src1, src2); 5506 } else { 5507 gen_helper_fcmpd(cpu_fcc[a->cc], tcg_env, src1, src2); 5508 } 5509 return advance_pc(dc); 5510 } 5511 5512 TRANS(FCMPd, ALL, do_fcmpd, a, false) 5513 TRANS(FCMPEd, ALL, do_fcmpd, a, true) 5514 5515 static bool do_fcmpq(DisasContext *dc, arg_FCMPq *a, bool e) 5516 { 5517 TCGv_i128 src1, src2; 5518 5519 if (avail_32(dc) && a->cc != 0) { 5520 return false; 5521 } 5522 if (gen_trap_ifnofpu(dc)) { 5523 return true; 5524 } 5525 if (gen_trap_float128(dc)) { 5526 return true; 5527 } 5528 5529 src1 = gen_load_fpr_Q(dc, a->rs1); 5530 src2 = gen_load_fpr_Q(dc, a->rs2); 5531 if (e) { 5532 gen_helper_fcmpeq(cpu_fcc[a->cc], tcg_env, src1, src2); 5533 } else { 5534 gen_helper_fcmpq(cpu_fcc[a->cc], tcg_env, src1, src2); 5535 } 5536 return advance_pc(dc); 5537 } 5538 5539 TRANS(FCMPq, ALL, do_fcmpq, a, false) 5540 TRANS(FCMPEq, ALL, do_fcmpq, a, true) 5541 5542 static bool trans_FLCMPs(DisasContext *dc, arg_FLCMPs *a) 5543 { 5544 TCGv_i32 src1, src2; 5545 5546 if (!avail_VIS3(dc)) { 5547 return false; 5548 } 5549 if (gen_trap_ifnofpu(dc)) { 5550 return true; 5551 } 5552 5553 src1 = gen_load_fpr_F(dc, a->rs1); 5554 src2 = gen_load_fpr_F(dc, a->rs2); 5555 gen_helper_flcmps(cpu_fcc[a->cc], src1, src2); 5556 return advance_pc(dc); 5557 } 5558 5559 static bool trans_FLCMPd(DisasContext *dc, arg_FLCMPd *a) 5560 { 5561 TCGv_i64 src1, src2; 5562 5563 if (!avail_VIS3(dc)) { 5564 return false; 5565 } 5566 if (gen_trap_ifnofpu(dc)) { 5567 return true; 5568 } 5569 5570 src1 = gen_load_fpr_D(dc, a->rs1); 5571 src2 = gen_load_fpr_D(dc, a->rs2); 5572 gen_helper_flcmpd(cpu_fcc[a->cc], src1, src2); 5573 return advance_pc(dc); 5574 } 5575 5576 static bool do_movf2r(DisasContext *dc, arg_r_r *a, 5577 int (*offset)(unsigned int), 5578 void (*load)(TCGv, TCGv_ptr, tcg_target_long)) 5579 { 5580 TCGv dst; 5581 5582 if (gen_trap_ifnofpu(dc)) { 5583 return true; 5584 } 5585 dst = gen_dest_gpr(dc, a->rd); 5586 load(dst, tcg_env, offset(a->rs)); 5587 gen_store_gpr(dc, a->rd, dst); 5588 return advance_pc(dc); 5589 } 5590 5591 TRANS(MOVsTOsw, VIS3B, do_movf2r, a, gen_offset_fpr_F, tcg_gen_ld32s_tl) 5592 TRANS(MOVsTOuw, VIS3B, do_movf2r, a, gen_offset_fpr_F, tcg_gen_ld32u_tl) 5593 TRANS(MOVdTOx, VIS3B, do_movf2r, a, gen_offset_fpr_D, tcg_gen_ld_tl) 5594 5595 static bool do_movr2f(DisasContext *dc, arg_r_r *a, 5596 int (*offset)(unsigned int), 5597 void (*store)(TCGv, TCGv_ptr, tcg_target_long)) 5598 { 5599 TCGv src; 5600 5601 if (gen_trap_ifnofpu(dc)) { 5602 return true; 5603 } 5604 src = gen_load_gpr(dc, a->rs); 5605 store(src, tcg_env, offset(a->rd)); 5606 return advance_pc(dc); 5607 } 5608 5609 TRANS(MOVwTOs, VIS3B, do_movr2f, a, gen_offset_fpr_F, tcg_gen_st32_tl) 5610 TRANS(MOVxTOd, VIS3B, do_movr2f, a, gen_offset_fpr_D, tcg_gen_st_tl) 5611 5612 static void sparc_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) 5613 { 5614 DisasContext *dc = container_of(dcbase, DisasContext, base); 5615 int bound; 5616 5617 dc->pc = dc->base.pc_first; 5618 dc->npc = (target_ulong)dc->base.tb->cs_base; 5619 dc->mem_idx = dc->base.tb->flags & TB_FLAG_MMU_MASK; 5620 dc->def = &cpu_env(cs)->def; 5621 dc->fpu_enabled = tb_fpu_enabled(dc->base.tb->flags); 5622 dc->address_mask_32bit = tb_am_enabled(dc->base.tb->flags); 5623 #ifndef CONFIG_USER_ONLY 5624 dc->supervisor = (dc->base.tb->flags & TB_FLAG_SUPER) != 0; 5625 # ifdef TARGET_SPARC64 5626 dc->hypervisor = (dc->base.tb->flags & TB_FLAG_HYPER) != 0; 5627 # else 5628 dc->fsr_qne = (dc->base.tb->flags & TB_FLAG_FSR_QNE) != 0; 5629 # endif 5630 #endif 5631 #ifdef TARGET_SPARC64 5632 dc->fprs_dirty = 0; 5633 dc->asi = (dc->base.tb->flags >> TB_FLAG_ASI_SHIFT) & 0xff; 5634 #endif 5635 /* 5636 * if we reach a page boundary, we stop generation so that the 5637 * PC of a TT_TFAULT exception is always in the right page 5638 */ 5639 bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4; 5640 dc->base.max_insns = MIN(dc->base.max_insns, bound); 5641 } 5642 5643 static void sparc_tr_tb_start(DisasContextBase *db, CPUState *cs) 5644 { 5645 } 5646 5647 static void sparc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) 5648 { 5649 DisasContext *dc = container_of(dcbase, DisasContext, base); 5650 target_ulong npc = dc->npc; 5651 5652 if (npc & 3) { 5653 switch (npc) { 5654 case JUMP_PC: 5655 assert(dc->jump_pc[1] == dc->pc + 4); 5656 npc = dc->jump_pc[0] | JUMP_PC; 5657 break; 5658 case DYNAMIC_PC: 5659 case DYNAMIC_PC_LOOKUP: 5660 npc = DYNAMIC_PC; 5661 break; 5662 default: 5663 g_assert_not_reached(); 5664 } 5665 } 5666 tcg_gen_insn_start(dc->pc, npc); 5667 } 5668 5669 static void sparc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) 5670 { 5671 DisasContext *dc = container_of(dcbase, DisasContext, base); 5672 unsigned int insn; 5673 5674 insn = translator_ldl(cpu_env(cs), &dc->base, dc->pc); 5675 dc->base.pc_next += 4; 5676 5677 if (!decode(dc, insn)) { 5678 gen_exception(dc, TT_ILL_INSN); 5679 } 5680 5681 if (dc->base.is_jmp == DISAS_NORETURN) { 5682 return; 5683 } 5684 if (dc->pc != dc->base.pc_next) { 5685 dc->base.is_jmp = DISAS_TOO_MANY; 5686 } 5687 } 5688 5689 static void sparc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) 5690 { 5691 DisasContext *dc = container_of(dcbase, DisasContext, base); 5692 DisasDelayException *e, *e_next; 5693 bool may_lookup; 5694 5695 finishing_insn(dc); 5696 5697 switch (dc->base.is_jmp) { 5698 case DISAS_NEXT: 5699 case DISAS_TOO_MANY: 5700 if (((dc->pc | dc->npc) & 3) == 0) { 5701 /* static PC and NPC: we can use direct chaining */ 5702 gen_goto_tb(dc, 0, dc->pc, dc->npc); 5703 break; 5704 } 5705 5706 may_lookup = true; 5707 if (dc->pc & 3) { 5708 switch (dc->pc) { 5709 case DYNAMIC_PC_LOOKUP: 5710 break; 5711 case DYNAMIC_PC: 5712 may_lookup = false; 5713 break; 5714 default: 5715 g_assert_not_reached(); 5716 } 5717 } else { 5718 tcg_gen_movi_tl(cpu_pc, dc->pc); 5719 } 5720 5721 if (dc->npc & 3) { 5722 switch (dc->npc) { 5723 case JUMP_PC: 5724 gen_generic_branch(dc); 5725 break; 5726 case DYNAMIC_PC: 5727 may_lookup = false; 5728 break; 5729 case DYNAMIC_PC_LOOKUP: 5730 break; 5731 default: 5732 g_assert_not_reached(); 5733 } 5734 } else { 5735 tcg_gen_movi_tl(cpu_npc, dc->npc); 5736 } 5737 if (may_lookup) { 5738 tcg_gen_lookup_and_goto_ptr(); 5739 } else { 5740 tcg_gen_exit_tb(NULL, 0); 5741 } 5742 break; 5743 5744 case DISAS_NORETURN: 5745 break; 5746 5747 case DISAS_EXIT: 5748 /* Exit TB */ 5749 save_state(dc); 5750 tcg_gen_exit_tb(NULL, 0); 5751 break; 5752 5753 default: 5754 g_assert_not_reached(); 5755 } 5756 5757 for (e = dc->delay_excp_list; e ; e = e_next) { 5758 gen_set_label(e->lab); 5759 5760 tcg_gen_movi_tl(cpu_pc, e->pc); 5761 if (e->npc % 4 == 0) { 5762 tcg_gen_movi_tl(cpu_npc, e->npc); 5763 } 5764 gen_helper_raise_exception(tcg_env, e->excp); 5765 5766 e_next = e->next; 5767 g_free(e); 5768 } 5769 } 5770 5771 static const TranslatorOps sparc_tr_ops = { 5772 .init_disas_context = sparc_tr_init_disas_context, 5773 .tb_start = sparc_tr_tb_start, 5774 .insn_start = sparc_tr_insn_start, 5775 .translate_insn = sparc_tr_translate_insn, 5776 .tb_stop = sparc_tr_tb_stop, 5777 }; 5778 5779 void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int *max_insns, 5780 vaddr pc, void *host_pc) 5781 { 5782 DisasContext dc = {}; 5783 5784 translator_loop(cs, tb, max_insns, pc, host_pc, &sparc_tr_ops, &dc.base); 5785 } 5786 5787 void sparc_tcg_init(void) 5788 { 5789 static const char gregnames[32][4] = { 5790 "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7", 5791 "o0", "o1", "o2", "o3", "o4", "o5", "o6", "o7", 5792 "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7", 5793 "i0", "i1", "i2", "i3", "i4", "i5", "i6", "i7", 5794 }; 5795 5796 static const struct { TCGv_i32 *ptr; int off; const char *name; } r32[] = { 5797 #ifdef TARGET_SPARC64 5798 { &cpu_fprs, offsetof(CPUSPARCState, fprs), "fprs" }, 5799 { &cpu_fcc[0], offsetof(CPUSPARCState, fcc[0]), "fcc0" }, 5800 { &cpu_fcc[1], offsetof(CPUSPARCState, fcc[1]), "fcc1" }, 5801 { &cpu_fcc[2], offsetof(CPUSPARCState, fcc[2]), "fcc2" }, 5802 { &cpu_fcc[3], offsetof(CPUSPARCState, fcc[3]), "fcc3" }, 5803 #else 5804 { &cpu_fcc[0], offsetof(CPUSPARCState, fcc[0]), "fcc" }, 5805 #endif 5806 }; 5807 5808 static const struct { TCGv *ptr; int off; const char *name; } rtl[] = { 5809 #ifdef TARGET_SPARC64 5810 { &cpu_gsr, offsetof(CPUSPARCState, gsr), "gsr" }, 5811 { &cpu_xcc_Z, offsetof(CPUSPARCState, xcc_Z), "xcc_Z" }, 5812 { &cpu_xcc_C, offsetof(CPUSPARCState, xcc_C), "xcc_C" }, 5813 #endif 5814 { &cpu_cc_N, offsetof(CPUSPARCState, cc_N), "cc_N" }, 5815 { &cpu_cc_V, offsetof(CPUSPARCState, cc_V), "cc_V" }, 5816 { &cpu_icc_Z, offsetof(CPUSPARCState, icc_Z), "icc_Z" }, 5817 { &cpu_icc_C, offsetof(CPUSPARCState, icc_C), "icc_C" }, 5818 { &cpu_cond, offsetof(CPUSPARCState, cond), "cond" }, 5819 { &cpu_pc, offsetof(CPUSPARCState, pc), "pc" }, 5820 { &cpu_npc, offsetof(CPUSPARCState, npc), "npc" }, 5821 { &cpu_y, offsetof(CPUSPARCState, y), "y" }, 5822 { &cpu_tbr, offsetof(CPUSPARCState, tbr), "tbr" }, 5823 }; 5824 5825 unsigned int i; 5826 5827 cpu_regwptr = tcg_global_mem_new_ptr(tcg_env, 5828 offsetof(CPUSPARCState, regwptr), 5829 "regwptr"); 5830 5831 for (i = 0; i < ARRAY_SIZE(r32); ++i) { 5832 *r32[i].ptr = tcg_global_mem_new_i32(tcg_env, r32[i].off, r32[i].name); 5833 } 5834 5835 for (i = 0; i < ARRAY_SIZE(rtl); ++i) { 5836 *rtl[i].ptr = tcg_global_mem_new(tcg_env, rtl[i].off, rtl[i].name); 5837 } 5838 5839 cpu_regs[0] = NULL; 5840 for (i = 1; i < 8; ++i) { 5841 cpu_regs[i] = tcg_global_mem_new(tcg_env, 5842 offsetof(CPUSPARCState, gregs[i]), 5843 gregnames[i]); 5844 } 5845 5846 for (i = 8; i < 32; ++i) { 5847 cpu_regs[i] = tcg_global_mem_new(cpu_regwptr, 5848 (i - 8) * sizeof(target_ulong), 5849 gregnames[i]); 5850 } 5851 } 5852 5853 void sparc_restore_state_to_opc(CPUState *cs, 5854 const TranslationBlock *tb, 5855 const uint64_t *data) 5856 { 5857 CPUSPARCState *env = cpu_env(cs); 5858 target_ulong pc = data[0]; 5859 target_ulong npc = data[1]; 5860 5861 env->pc = pc; 5862 if (npc == DYNAMIC_PC) { 5863 /* dynamic NPC: already stored */ 5864 } else if (npc & JUMP_PC) { 5865 /* jump PC: use 'cond' and the jump targets of the translation */ 5866 if (env->cond) { 5867 env->npc = npc & ~3; 5868 } else { 5869 env->npc = pc + 4; 5870 } 5871 } else { 5872 env->npc = npc; 5873 } 5874 } 5875