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