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