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