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