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 "exec/cpu_ldst.h" 29 30 #include "exec/helper-gen.h" 31 32 #include "exec/translator.h" 33 #include "exec/log.h" 34 #include "asi.h" 35 36 #define HELPER_H "helper.h" 37 #include "exec/helper-info.c.inc" 38 #undef HELPER_H 39 40 #define DYNAMIC_PC 1 /* dynamic pc value */ 41 #define JUMP_PC 2 /* dynamic pc value which takes only two values 42 according to jump_pc[T2] */ 43 44 #define DISAS_EXIT DISAS_TARGET_0 45 46 /* global register indexes */ 47 static TCGv_ptr cpu_regwptr; 48 static TCGv cpu_cc_src, cpu_cc_src2, cpu_cc_dst; 49 static TCGv_i32 cpu_cc_op; 50 static TCGv_i32 cpu_psr; 51 static TCGv cpu_fsr, cpu_pc, cpu_npc; 52 static TCGv cpu_regs[32]; 53 static TCGv cpu_y; 54 #ifndef CONFIG_USER_ONLY 55 static TCGv cpu_tbr; 56 #endif 57 static TCGv cpu_cond; 58 #ifdef TARGET_SPARC64 59 static TCGv_i32 cpu_xcc, cpu_fprs; 60 static TCGv cpu_gsr; 61 static TCGv cpu_tick_cmpr, cpu_stick_cmpr, cpu_hstick_cmpr; 62 static TCGv cpu_hintp, cpu_htba, cpu_hver, cpu_ssr, cpu_ver; 63 #else 64 static TCGv cpu_wim; 65 #endif 66 /* Floating point registers */ 67 static TCGv_i64 cpu_fpr[TARGET_DPREGS]; 68 69 typedef struct DisasContext { 70 DisasContextBase base; 71 target_ulong pc; /* current Program Counter: integer or DYNAMIC_PC */ 72 target_ulong npc; /* next PC: integer or DYNAMIC_PC or JUMP_PC */ 73 target_ulong jump_pc[2]; /* used when JUMP_PC pc value is used */ 74 int mem_idx; 75 bool fpu_enabled; 76 bool address_mask_32bit; 77 #ifndef CONFIG_USER_ONLY 78 bool supervisor; 79 #ifdef TARGET_SPARC64 80 bool hypervisor; 81 #endif 82 #endif 83 84 uint32_t cc_op; /* current CC operation */ 85 sparc_def_t *def; 86 #ifdef TARGET_SPARC64 87 int fprs_dirty; 88 int asi; 89 #endif 90 } DisasContext; 91 92 typedef struct { 93 TCGCond cond; 94 bool is_bool; 95 TCGv c1, c2; 96 } DisasCompare; 97 98 // This function uses non-native bit order 99 #define GET_FIELD(X, FROM, TO) \ 100 ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1)) 101 102 // This function uses the order in the manuals, i.e. bit 0 is 2^0 103 #define GET_FIELD_SP(X, FROM, TO) \ 104 GET_FIELD(X, 31 - (TO), 31 - (FROM)) 105 106 #define GET_FIELDs(x,a,b) sign_extend (GET_FIELD(x,a,b), (b) - (a) + 1) 107 #define GET_FIELD_SPs(x,a,b) sign_extend (GET_FIELD_SP(x,a,b), ((b) - (a) + 1)) 108 109 #ifdef TARGET_SPARC64 110 #define DFPREG(r) (((r & 1) << 5) | (r & 0x1e)) 111 #define QFPREG(r) (((r & 1) << 5) | (r & 0x1c)) 112 #else 113 #define DFPREG(r) (r & 0x1e) 114 #define QFPREG(r) (r & 0x1c) 115 #endif 116 117 #define UA2005_HTRAP_MASK 0xff 118 #define V8_TRAP_MASK 0x7f 119 120 static int sign_extend(int x, int len) 121 { 122 len = 32 - len; 123 return (x << len) >> len; 124 } 125 126 #define IS_IMM (insn & (1<<13)) 127 128 static inline void gen_update_fprs_dirty(DisasContext *dc, int rd) 129 { 130 #if defined(TARGET_SPARC64) 131 int bit = (rd < 32) ? 1 : 2; 132 /* If we know we've already set this bit within the TB, 133 we can avoid setting it again. */ 134 if (!(dc->fprs_dirty & bit)) { 135 dc->fprs_dirty |= bit; 136 tcg_gen_ori_i32(cpu_fprs, cpu_fprs, bit); 137 } 138 #endif 139 } 140 141 /* floating point registers moves */ 142 static TCGv_i32 gen_load_fpr_F(DisasContext *dc, unsigned int src) 143 { 144 TCGv_i32 ret = tcg_temp_new_i32(); 145 if (src & 1) { 146 tcg_gen_extrl_i64_i32(ret, cpu_fpr[src / 2]); 147 } else { 148 tcg_gen_extrh_i64_i32(ret, cpu_fpr[src / 2]); 149 } 150 return ret; 151 } 152 153 static void gen_store_fpr_F(DisasContext *dc, unsigned int dst, TCGv_i32 v) 154 { 155 TCGv_i64 t = tcg_temp_new_i64(); 156 157 tcg_gen_extu_i32_i64(t, v); 158 tcg_gen_deposit_i64(cpu_fpr[dst / 2], cpu_fpr[dst / 2], t, 159 (dst & 1 ? 0 : 32), 32); 160 gen_update_fprs_dirty(dc, dst); 161 } 162 163 static TCGv_i32 gen_dest_fpr_F(DisasContext *dc) 164 { 165 return tcg_temp_new_i32(); 166 } 167 168 static TCGv_i64 gen_load_fpr_D(DisasContext *dc, unsigned int src) 169 { 170 src = DFPREG(src); 171 return cpu_fpr[src / 2]; 172 } 173 174 static void gen_store_fpr_D(DisasContext *dc, unsigned int dst, TCGv_i64 v) 175 { 176 dst = DFPREG(dst); 177 tcg_gen_mov_i64(cpu_fpr[dst / 2], v); 178 gen_update_fprs_dirty(dc, dst); 179 } 180 181 static TCGv_i64 gen_dest_fpr_D(DisasContext *dc, unsigned int dst) 182 { 183 return cpu_fpr[DFPREG(dst) / 2]; 184 } 185 186 static void gen_op_load_fpr_QT0(unsigned int src) 187 { 188 tcg_gen_st_i64(cpu_fpr[src / 2], cpu_env, offsetof(CPUSPARCState, qt0) + 189 offsetof(CPU_QuadU, ll.upper)); 190 tcg_gen_st_i64(cpu_fpr[src/2 + 1], cpu_env, offsetof(CPUSPARCState, qt0) + 191 offsetof(CPU_QuadU, ll.lower)); 192 } 193 194 static void gen_op_load_fpr_QT1(unsigned int src) 195 { 196 tcg_gen_st_i64(cpu_fpr[src / 2], cpu_env, offsetof(CPUSPARCState, qt1) + 197 offsetof(CPU_QuadU, ll.upper)); 198 tcg_gen_st_i64(cpu_fpr[src/2 + 1], cpu_env, offsetof(CPUSPARCState, qt1) + 199 offsetof(CPU_QuadU, ll.lower)); 200 } 201 202 static void gen_op_store_QT0_fpr(unsigned int dst) 203 { 204 tcg_gen_ld_i64(cpu_fpr[dst / 2], cpu_env, offsetof(CPUSPARCState, qt0) + 205 offsetof(CPU_QuadU, ll.upper)); 206 tcg_gen_ld_i64(cpu_fpr[dst/2 + 1], cpu_env, offsetof(CPUSPARCState, qt0) + 207 offsetof(CPU_QuadU, ll.lower)); 208 } 209 210 static void gen_store_fpr_Q(DisasContext *dc, unsigned int dst, 211 TCGv_i64 v1, TCGv_i64 v2) 212 { 213 dst = QFPREG(dst); 214 215 tcg_gen_mov_i64(cpu_fpr[dst / 2], v1); 216 tcg_gen_mov_i64(cpu_fpr[dst / 2 + 1], v2); 217 gen_update_fprs_dirty(dc, dst); 218 } 219 220 #ifdef TARGET_SPARC64 221 static TCGv_i64 gen_load_fpr_Q0(DisasContext *dc, unsigned int src) 222 { 223 src = QFPREG(src); 224 return cpu_fpr[src / 2]; 225 } 226 227 static TCGv_i64 gen_load_fpr_Q1(DisasContext *dc, unsigned int src) 228 { 229 src = QFPREG(src); 230 return cpu_fpr[src / 2 + 1]; 231 } 232 233 static void gen_move_Q(DisasContext *dc, unsigned int rd, unsigned int rs) 234 { 235 rd = QFPREG(rd); 236 rs = QFPREG(rs); 237 238 tcg_gen_mov_i64(cpu_fpr[rd / 2], cpu_fpr[rs / 2]); 239 tcg_gen_mov_i64(cpu_fpr[rd / 2 + 1], cpu_fpr[rs / 2 + 1]); 240 gen_update_fprs_dirty(dc, rd); 241 } 242 #endif 243 244 /* moves */ 245 #ifdef CONFIG_USER_ONLY 246 #define supervisor(dc) 0 247 #ifdef TARGET_SPARC64 248 #define hypervisor(dc) 0 249 #endif 250 #else 251 #ifdef TARGET_SPARC64 252 #define hypervisor(dc) (dc->hypervisor) 253 #define supervisor(dc) (dc->supervisor | dc->hypervisor) 254 #else 255 #define supervisor(dc) (dc->supervisor) 256 #endif 257 #endif 258 259 #ifdef TARGET_SPARC64 260 #ifndef TARGET_ABI32 261 #define AM_CHECK(dc) ((dc)->address_mask_32bit) 262 #else 263 #define AM_CHECK(dc) (1) 264 #endif 265 #endif 266 267 static inline void gen_address_mask(DisasContext *dc, TCGv addr) 268 { 269 #ifdef TARGET_SPARC64 270 if (AM_CHECK(dc)) 271 tcg_gen_andi_tl(addr, addr, 0xffffffffULL); 272 #endif 273 } 274 275 static inline TCGv gen_load_gpr(DisasContext *dc, int reg) 276 { 277 if (reg > 0) { 278 assert(reg < 32); 279 return cpu_regs[reg]; 280 } else { 281 TCGv t = tcg_temp_new(); 282 tcg_gen_movi_tl(t, 0); 283 return t; 284 } 285 } 286 287 static inline void gen_store_gpr(DisasContext *dc, int reg, TCGv v) 288 { 289 if (reg > 0) { 290 assert(reg < 32); 291 tcg_gen_mov_tl(cpu_regs[reg], v); 292 } 293 } 294 295 static inline TCGv gen_dest_gpr(DisasContext *dc, int reg) 296 { 297 if (reg > 0) { 298 assert(reg < 32); 299 return cpu_regs[reg]; 300 } else { 301 return tcg_temp_new(); 302 } 303 } 304 305 static bool use_goto_tb(DisasContext *s, target_ulong pc, target_ulong npc) 306 { 307 return translator_use_goto_tb(&s->base, pc) && 308 translator_use_goto_tb(&s->base, npc); 309 } 310 311 static void gen_goto_tb(DisasContext *s, int tb_num, 312 target_ulong pc, target_ulong npc) 313 { 314 if (use_goto_tb(s, pc, npc)) { 315 /* jump to same page: we can use a direct jump */ 316 tcg_gen_goto_tb(tb_num); 317 tcg_gen_movi_tl(cpu_pc, pc); 318 tcg_gen_movi_tl(cpu_npc, npc); 319 tcg_gen_exit_tb(s->base.tb, tb_num); 320 } else { 321 /* jump to another page: currently not optimized */ 322 tcg_gen_movi_tl(cpu_pc, pc); 323 tcg_gen_movi_tl(cpu_npc, npc); 324 tcg_gen_exit_tb(NULL, 0); 325 } 326 } 327 328 // XXX suboptimal 329 static inline void gen_mov_reg_N(TCGv reg, TCGv_i32 src) 330 { 331 tcg_gen_extu_i32_tl(reg, src); 332 tcg_gen_extract_tl(reg, reg, PSR_NEG_SHIFT, 1); 333 } 334 335 static inline void gen_mov_reg_Z(TCGv reg, TCGv_i32 src) 336 { 337 tcg_gen_extu_i32_tl(reg, src); 338 tcg_gen_extract_tl(reg, reg, PSR_ZERO_SHIFT, 1); 339 } 340 341 static inline void gen_mov_reg_V(TCGv reg, TCGv_i32 src) 342 { 343 tcg_gen_extu_i32_tl(reg, src); 344 tcg_gen_extract_tl(reg, reg, PSR_OVF_SHIFT, 1); 345 } 346 347 static inline void gen_mov_reg_C(TCGv reg, TCGv_i32 src) 348 { 349 tcg_gen_extu_i32_tl(reg, src); 350 tcg_gen_extract_tl(reg, reg, PSR_CARRY_SHIFT, 1); 351 } 352 353 static inline void gen_op_add_cc(TCGv dst, TCGv src1, TCGv src2) 354 { 355 tcg_gen_mov_tl(cpu_cc_src, src1); 356 tcg_gen_mov_tl(cpu_cc_src2, src2); 357 tcg_gen_add_tl(cpu_cc_dst, cpu_cc_src, cpu_cc_src2); 358 tcg_gen_mov_tl(dst, cpu_cc_dst); 359 } 360 361 static TCGv_i32 gen_add32_carry32(void) 362 { 363 TCGv_i32 carry_32, cc_src1_32, cc_src2_32; 364 365 /* Carry is computed from a previous add: (dst < src) */ 366 #if TARGET_LONG_BITS == 64 367 cc_src1_32 = tcg_temp_new_i32(); 368 cc_src2_32 = tcg_temp_new_i32(); 369 tcg_gen_extrl_i64_i32(cc_src1_32, cpu_cc_dst); 370 tcg_gen_extrl_i64_i32(cc_src2_32, cpu_cc_src); 371 #else 372 cc_src1_32 = cpu_cc_dst; 373 cc_src2_32 = cpu_cc_src; 374 #endif 375 376 carry_32 = tcg_temp_new_i32(); 377 tcg_gen_setcond_i32(TCG_COND_LTU, carry_32, cc_src1_32, cc_src2_32); 378 379 return carry_32; 380 } 381 382 static TCGv_i32 gen_sub32_carry32(void) 383 { 384 TCGv_i32 carry_32, cc_src1_32, cc_src2_32; 385 386 /* Carry is computed from a previous borrow: (src1 < src2) */ 387 #if TARGET_LONG_BITS == 64 388 cc_src1_32 = tcg_temp_new_i32(); 389 cc_src2_32 = tcg_temp_new_i32(); 390 tcg_gen_extrl_i64_i32(cc_src1_32, cpu_cc_src); 391 tcg_gen_extrl_i64_i32(cc_src2_32, cpu_cc_src2); 392 #else 393 cc_src1_32 = cpu_cc_src; 394 cc_src2_32 = cpu_cc_src2; 395 #endif 396 397 carry_32 = tcg_temp_new_i32(); 398 tcg_gen_setcond_i32(TCG_COND_LTU, carry_32, cc_src1_32, cc_src2_32); 399 400 return carry_32; 401 } 402 403 static void gen_op_addx_int(DisasContext *dc, TCGv dst, TCGv src1, 404 TCGv src2, int update_cc) 405 { 406 TCGv_i32 carry_32; 407 TCGv carry; 408 409 switch (dc->cc_op) { 410 case CC_OP_DIV: 411 case CC_OP_LOGIC: 412 /* Carry is known to be zero. Fall back to plain ADD. */ 413 if (update_cc) { 414 gen_op_add_cc(dst, src1, src2); 415 } else { 416 tcg_gen_add_tl(dst, src1, src2); 417 } 418 return; 419 420 case CC_OP_ADD: 421 case CC_OP_TADD: 422 case CC_OP_TADDTV: 423 if (TARGET_LONG_BITS == 32) { 424 /* We can re-use the host's hardware carry generation by using 425 an ADD2 opcode. We discard the low part of the output. 426 Ideally we'd combine this operation with the add that 427 generated the carry in the first place. */ 428 carry = tcg_temp_new(); 429 tcg_gen_add2_tl(carry, dst, cpu_cc_src, src1, cpu_cc_src2, src2); 430 goto add_done; 431 } 432 carry_32 = gen_add32_carry32(); 433 break; 434 435 case CC_OP_SUB: 436 case CC_OP_TSUB: 437 case CC_OP_TSUBTV: 438 carry_32 = gen_sub32_carry32(); 439 break; 440 441 default: 442 /* We need external help to produce the carry. */ 443 carry_32 = tcg_temp_new_i32(); 444 gen_helper_compute_C_icc(carry_32, cpu_env); 445 break; 446 } 447 448 #if TARGET_LONG_BITS == 64 449 carry = tcg_temp_new(); 450 tcg_gen_extu_i32_i64(carry, carry_32); 451 #else 452 carry = carry_32; 453 #endif 454 455 tcg_gen_add_tl(dst, src1, src2); 456 tcg_gen_add_tl(dst, dst, carry); 457 458 add_done: 459 if (update_cc) { 460 tcg_gen_mov_tl(cpu_cc_src, src1); 461 tcg_gen_mov_tl(cpu_cc_src2, src2); 462 tcg_gen_mov_tl(cpu_cc_dst, dst); 463 tcg_gen_movi_i32(cpu_cc_op, CC_OP_ADDX); 464 dc->cc_op = CC_OP_ADDX; 465 } 466 } 467 468 static inline void gen_op_sub_cc(TCGv dst, TCGv src1, TCGv src2) 469 { 470 tcg_gen_mov_tl(cpu_cc_src, src1); 471 tcg_gen_mov_tl(cpu_cc_src2, src2); 472 tcg_gen_sub_tl(cpu_cc_dst, cpu_cc_src, cpu_cc_src2); 473 tcg_gen_mov_tl(dst, cpu_cc_dst); 474 } 475 476 static void gen_op_subx_int(DisasContext *dc, TCGv dst, TCGv src1, 477 TCGv src2, int update_cc) 478 { 479 TCGv_i32 carry_32; 480 TCGv carry; 481 482 switch (dc->cc_op) { 483 case CC_OP_DIV: 484 case CC_OP_LOGIC: 485 /* Carry is known to be zero. Fall back to plain SUB. */ 486 if (update_cc) { 487 gen_op_sub_cc(dst, src1, src2); 488 } else { 489 tcg_gen_sub_tl(dst, src1, src2); 490 } 491 return; 492 493 case CC_OP_ADD: 494 case CC_OP_TADD: 495 case CC_OP_TADDTV: 496 carry_32 = gen_add32_carry32(); 497 break; 498 499 case CC_OP_SUB: 500 case CC_OP_TSUB: 501 case CC_OP_TSUBTV: 502 if (TARGET_LONG_BITS == 32) { 503 /* We can re-use the host's hardware carry generation by using 504 a SUB2 opcode. We discard the low part of the output. 505 Ideally we'd combine this operation with the add that 506 generated the carry in the first place. */ 507 carry = tcg_temp_new(); 508 tcg_gen_sub2_tl(carry, dst, cpu_cc_src, src1, cpu_cc_src2, src2); 509 goto sub_done; 510 } 511 carry_32 = gen_sub32_carry32(); 512 break; 513 514 default: 515 /* We need external help to produce the carry. */ 516 carry_32 = tcg_temp_new_i32(); 517 gen_helper_compute_C_icc(carry_32, cpu_env); 518 break; 519 } 520 521 #if TARGET_LONG_BITS == 64 522 carry = tcg_temp_new(); 523 tcg_gen_extu_i32_i64(carry, carry_32); 524 #else 525 carry = carry_32; 526 #endif 527 528 tcg_gen_sub_tl(dst, src1, src2); 529 tcg_gen_sub_tl(dst, dst, carry); 530 531 sub_done: 532 if (update_cc) { 533 tcg_gen_mov_tl(cpu_cc_src, src1); 534 tcg_gen_mov_tl(cpu_cc_src2, src2); 535 tcg_gen_mov_tl(cpu_cc_dst, dst); 536 tcg_gen_movi_i32(cpu_cc_op, CC_OP_SUBX); 537 dc->cc_op = CC_OP_SUBX; 538 } 539 } 540 541 static inline void gen_op_mulscc(TCGv dst, TCGv src1, TCGv src2) 542 { 543 TCGv r_temp, zero, t0; 544 545 r_temp = tcg_temp_new(); 546 t0 = tcg_temp_new(); 547 548 /* old op: 549 if (!(env->y & 1)) 550 T1 = 0; 551 */ 552 zero = tcg_constant_tl(0); 553 tcg_gen_andi_tl(cpu_cc_src, src1, 0xffffffff); 554 tcg_gen_andi_tl(r_temp, cpu_y, 0x1); 555 tcg_gen_andi_tl(cpu_cc_src2, src2, 0xffffffff); 556 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_cc_src2, r_temp, zero, 557 zero, cpu_cc_src2); 558 559 // b2 = T0 & 1; 560 // env->y = (b2 << 31) | (env->y >> 1); 561 tcg_gen_extract_tl(t0, cpu_y, 1, 31); 562 tcg_gen_deposit_tl(cpu_y, t0, cpu_cc_src, 31, 1); 563 564 // b1 = N ^ V; 565 gen_mov_reg_N(t0, cpu_psr); 566 gen_mov_reg_V(r_temp, cpu_psr); 567 tcg_gen_xor_tl(t0, t0, r_temp); 568 569 // T0 = (b1 << 31) | (T0 >> 1); 570 // src1 = T0; 571 tcg_gen_shli_tl(t0, t0, 31); 572 tcg_gen_shri_tl(cpu_cc_src, cpu_cc_src, 1); 573 tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, t0); 574 575 tcg_gen_add_tl(cpu_cc_dst, cpu_cc_src, cpu_cc_src2); 576 577 tcg_gen_mov_tl(dst, cpu_cc_dst); 578 } 579 580 static inline void gen_op_multiply(TCGv dst, TCGv src1, TCGv src2, int sign_ext) 581 { 582 #if TARGET_LONG_BITS == 32 583 if (sign_ext) { 584 tcg_gen_muls2_tl(dst, cpu_y, src1, src2); 585 } else { 586 tcg_gen_mulu2_tl(dst, cpu_y, src1, src2); 587 } 588 #else 589 TCGv t0 = tcg_temp_new_i64(); 590 TCGv t1 = tcg_temp_new_i64(); 591 592 if (sign_ext) { 593 tcg_gen_ext32s_i64(t0, src1); 594 tcg_gen_ext32s_i64(t1, src2); 595 } else { 596 tcg_gen_ext32u_i64(t0, src1); 597 tcg_gen_ext32u_i64(t1, src2); 598 } 599 600 tcg_gen_mul_i64(dst, t0, t1); 601 tcg_gen_shri_i64(cpu_y, dst, 32); 602 #endif 603 } 604 605 static inline void gen_op_umul(TCGv dst, TCGv src1, TCGv src2) 606 { 607 /* zero-extend truncated operands before multiplication */ 608 gen_op_multiply(dst, src1, src2, 0); 609 } 610 611 static inline void gen_op_smul(TCGv dst, TCGv src1, TCGv src2) 612 { 613 /* sign-extend truncated operands before multiplication */ 614 gen_op_multiply(dst, src1, src2, 1); 615 } 616 617 // 1 618 static inline void gen_op_eval_ba(TCGv dst) 619 { 620 tcg_gen_movi_tl(dst, 1); 621 } 622 623 // Z 624 static inline void gen_op_eval_be(TCGv dst, TCGv_i32 src) 625 { 626 gen_mov_reg_Z(dst, src); 627 } 628 629 // Z | (N ^ V) 630 static inline void gen_op_eval_ble(TCGv dst, TCGv_i32 src) 631 { 632 TCGv t0 = tcg_temp_new(); 633 gen_mov_reg_N(t0, src); 634 gen_mov_reg_V(dst, src); 635 tcg_gen_xor_tl(dst, dst, t0); 636 gen_mov_reg_Z(t0, src); 637 tcg_gen_or_tl(dst, dst, t0); 638 } 639 640 // N ^ V 641 static inline void gen_op_eval_bl(TCGv dst, TCGv_i32 src) 642 { 643 TCGv t0 = tcg_temp_new(); 644 gen_mov_reg_V(t0, src); 645 gen_mov_reg_N(dst, src); 646 tcg_gen_xor_tl(dst, dst, t0); 647 } 648 649 // C | Z 650 static inline void gen_op_eval_bleu(TCGv dst, TCGv_i32 src) 651 { 652 TCGv t0 = tcg_temp_new(); 653 gen_mov_reg_Z(t0, src); 654 gen_mov_reg_C(dst, src); 655 tcg_gen_or_tl(dst, dst, t0); 656 } 657 658 // C 659 static inline void gen_op_eval_bcs(TCGv dst, TCGv_i32 src) 660 { 661 gen_mov_reg_C(dst, src); 662 } 663 664 // V 665 static inline void gen_op_eval_bvs(TCGv dst, TCGv_i32 src) 666 { 667 gen_mov_reg_V(dst, src); 668 } 669 670 // 0 671 static inline void gen_op_eval_bn(TCGv dst) 672 { 673 tcg_gen_movi_tl(dst, 0); 674 } 675 676 // N 677 static inline void gen_op_eval_bneg(TCGv dst, TCGv_i32 src) 678 { 679 gen_mov_reg_N(dst, src); 680 } 681 682 // !Z 683 static inline void gen_op_eval_bne(TCGv dst, TCGv_i32 src) 684 { 685 gen_mov_reg_Z(dst, src); 686 tcg_gen_xori_tl(dst, dst, 0x1); 687 } 688 689 // !(Z | (N ^ V)) 690 static inline void gen_op_eval_bg(TCGv dst, TCGv_i32 src) 691 { 692 gen_op_eval_ble(dst, src); 693 tcg_gen_xori_tl(dst, dst, 0x1); 694 } 695 696 // !(N ^ V) 697 static inline void gen_op_eval_bge(TCGv dst, TCGv_i32 src) 698 { 699 gen_op_eval_bl(dst, src); 700 tcg_gen_xori_tl(dst, dst, 0x1); 701 } 702 703 // !(C | Z) 704 static inline void gen_op_eval_bgu(TCGv dst, TCGv_i32 src) 705 { 706 gen_op_eval_bleu(dst, src); 707 tcg_gen_xori_tl(dst, dst, 0x1); 708 } 709 710 // !C 711 static inline void gen_op_eval_bcc(TCGv dst, TCGv_i32 src) 712 { 713 gen_mov_reg_C(dst, src); 714 tcg_gen_xori_tl(dst, dst, 0x1); 715 } 716 717 // !N 718 static inline void gen_op_eval_bpos(TCGv dst, TCGv_i32 src) 719 { 720 gen_mov_reg_N(dst, src); 721 tcg_gen_xori_tl(dst, dst, 0x1); 722 } 723 724 // !V 725 static inline void gen_op_eval_bvc(TCGv dst, TCGv_i32 src) 726 { 727 gen_mov_reg_V(dst, src); 728 tcg_gen_xori_tl(dst, dst, 0x1); 729 } 730 731 /* 732 FPSR bit field FCC1 | FCC0: 733 0 = 734 1 < 735 2 > 736 3 unordered 737 */ 738 static inline void gen_mov_reg_FCC0(TCGv reg, TCGv src, 739 unsigned int fcc_offset) 740 { 741 tcg_gen_shri_tl(reg, src, FSR_FCC0_SHIFT + fcc_offset); 742 tcg_gen_andi_tl(reg, reg, 0x1); 743 } 744 745 static inline void gen_mov_reg_FCC1(TCGv reg, TCGv src, 746 unsigned int fcc_offset) 747 { 748 tcg_gen_shri_tl(reg, src, FSR_FCC1_SHIFT + fcc_offset); 749 tcg_gen_andi_tl(reg, reg, 0x1); 750 } 751 752 // !0: FCC0 | FCC1 753 static inline void gen_op_eval_fbne(TCGv dst, TCGv src, 754 unsigned int fcc_offset) 755 { 756 TCGv t0 = tcg_temp_new(); 757 gen_mov_reg_FCC0(dst, src, fcc_offset); 758 gen_mov_reg_FCC1(t0, src, fcc_offset); 759 tcg_gen_or_tl(dst, dst, t0); 760 } 761 762 // 1 or 2: FCC0 ^ FCC1 763 static inline void gen_op_eval_fblg(TCGv dst, TCGv src, 764 unsigned int fcc_offset) 765 { 766 TCGv t0 = tcg_temp_new(); 767 gen_mov_reg_FCC0(dst, src, fcc_offset); 768 gen_mov_reg_FCC1(t0, src, fcc_offset); 769 tcg_gen_xor_tl(dst, dst, t0); 770 } 771 772 // 1 or 3: FCC0 773 static inline void gen_op_eval_fbul(TCGv dst, TCGv src, 774 unsigned int fcc_offset) 775 { 776 gen_mov_reg_FCC0(dst, src, fcc_offset); 777 } 778 779 // 1: FCC0 & !FCC1 780 static inline void gen_op_eval_fbl(TCGv dst, TCGv src, 781 unsigned int fcc_offset) 782 { 783 TCGv t0 = tcg_temp_new(); 784 gen_mov_reg_FCC0(dst, src, fcc_offset); 785 gen_mov_reg_FCC1(t0, src, fcc_offset); 786 tcg_gen_andc_tl(dst, dst, t0); 787 } 788 789 // 2 or 3: FCC1 790 static inline void gen_op_eval_fbug(TCGv dst, TCGv src, 791 unsigned int fcc_offset) 792 { 793 gen_mov_reg_FCC1(dst, src, fcc_offset); 794 } 795 796 // 2: !FCC0 & FCC1 797 static inline void gen_op_eval_fbg(TCGv dst, TCGv src, 798 unsigned int fcc_offset) 799 { 800 TCGv t0 = tcg_temp_new(); 801 gen_mov_reg_FCC0(dst, src, fcc_offset); 802 gen_mov_reg_FCC1(t0, src, fcc_offset); 803 tcg_gen_andc_tl(dst, t0, dst); 804 } 805 806 // 3: FCC0 & FCC1 807 static inline void gen_op_eval_fbu(TCGv dst, TCGv src, 808 unsigned int fcc_offset) 809 { 810 TCGv t0 = tcg_temp_new(); 811 gen_mov_reg_FCC0(dst, src, fcc_offset); 812 gen_mov_reg_FCC1(t0, src, fcc_offset); 813 tcg_gen_and_tl(dst, dst, t0); 814 } 815 816 // 0: !(FCC0 | FCC1) 817 static inline void gen_op_eval_fbe(TCGv dst, TCGv src, 818 unsigned int fcc_offset) 819 { 820 TCGv t0 = tcg_temp_new(); 821 gen_mov_reg_FCC0(dst, src, fcc_offset); 822 gen_mov_reg_FCC1(t0, src, fcc_offset); 823 tcg_gen_or_tl(dst, dst, t0); 824 tcg_gen_xori_tl(dst, dst, 0x1); 825 } 826 827 // 0 or 3: !(FCC0 ^ FCC1) 828 static inline void gen_op_eval_fbue(TCGv dst, TCGv src, 829 unsigned int fcc_offset) 830 { 831 TCGv t0 = tcg_temp_new(); 832 gen_mov_reg_FCC0(dst, src, fcc_offset); 833 gen_mov_reg_FCC1(t0, src, fcc_offset); 834 tcg_gen_xor_tl(dst, dst, t0); 835 tcg_gen_xori_tl(dst, dst, 0x1); 836 } 837 838 // 0 or 2: !FCC0 839 static inline void gen_op_eval_fbge(TCGv dst, TCGv src, 840 unsigned int fcc_offset) 841 { 842 gen_mov_reg_FCC0(dst, src, fcc_offset); 843 tcg_gen_xori_tl(dst, dst, 0x1); 844 } 845 846 // !1: !(FCC0 & !FCC1) 847 static inline void gen_op_eval_fbuge(TCGv dst, TCGv src, 848 unsigned int fcc_offset) 849 { 850 TCGv t0 = tcg_temp_new(); 851 gen_mov_reg_FCC0(dst, src, fcc_offset); 852 gen_mov_reg_FCC1(t0, src, fcc_offset); 853 tcg_gen_andc_tl(dst, dst, t0); 854 tcg_gen_xori_tl(dst, dst, 0x1); 855 } 856 857 // 0 or 1: !FCC1 858 static inline void gen_op_eval_fble(TCGv dst, TCGv src, 859 unsigned int fcc_offset) 860 { 861 gen_mov_reg_FCC1(dst, src, fcc_offset); 862 tcg_gen_xori_tl(dst, dst, 0x1); 863 } 864 865 // !2: !(!FCC0 & FCC1) 866 static inline void gen_op_eval_fbule(TCGv dst, TCGv src, 867 unsigned int fcc_offset) 868 { 869 TCGv t0 = tcg_temp_new(); 870 gen_mov_reg_FCC0(dst, src, fcc_offset); 871 gen_mov_reg_FCC1(t0, src, fcc_offset); 872 tcg_gen_andc_tl(dst, t0, dst); 873 tcg_gen_xori_tl(dst, dst, 0x1); 874 } 875 876 // !3: !(FCC0 & FCC1) 877 static inline void gen_op_eval_fbo(TCGv dst, TCGv src, 878 unsigned int fcc_offset) 879 { 880 TCGv t0 = tcg_temp_new(); 881 gen_mov_reg_FCC0(dst, src, fcc_offset); 882 gen_mov_reg_FCC1(t0, src, fcc_offset); 883 tcg_gen_and_tl(dst, dst, t0); 884 tcg_gen_xori_tl(dst, dst, 0x1); 885 } 886 887 static inline void gen_branch2(DisasContext *dc, target_ulong pc1, 888 target_ulong pc2, TCGv r_cond) 889 { 890 TCGLabel *l1 = gen_new_label(); 891 892 tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, 0, l1); 893 894 gen_goto_tb(dc, 0, pc1, pc1 + 4); 895 896 gen_set_label(l1); 897 gen_goto_tb(dc, 1, pc2, pc2 + 4); 898 } 899 900 static void gen_branch_a(DisasContext *dc, target_ulong pc1) 901 { 902 TCGLabel *l1 = gen_new_label(); 903 target_ulong npc = dc->npc; 904 905 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_cond, 0, l1); 906 907 gen_goto_tb(dc, 0, npc, pc1); 908 909 gen_set_label(l1); 910 gen_goto_tb(dc, 1, npc + 4, npc + 8); 911 912 dc->base.is_jmp = DISAS_NORETURN; 913 } 914 915 static void gen_branch_n(DisasContext *dc, target_ulong pc1) 916 { 917 target_ulong npc = dc->npc; 918 919 if (likely(npc != DYNAMIC_PC)) { 920 dc->pc = npc; 921 dc->jump_pc[0] = pc1; 922 dc->jump_pc[1] = npc + 4; 923 dc->npc = JUMP_PC; 924 } else { 925 TCGv t, z; 926 927 tcg_gen_mov_tl(cpu_pc, cpu_npc); 928 929 tcg_gen_addi_tl(cpu_npc, cpu_npc, 4); 930 t = tcg_constant_tl(pc1); 931 z = tcg_constant_tl(0); 932 tcg_gen_movcond_tl(TCG_COND_NE, cpu_npc, cpu_cond, z, t, cpu_npc); 933 934 dc->pc = DYNAMIC_PC; 935 } 936 } 937 938 static inline void gen_generic_branch(DisasContext *dc) 939 { 940 TCGv npc0 = tcg_constant_tl(dc->jump_pc[0]); 941 TCGv npc1 = tcg_constant_tl(dc->jump_pc[1]); 942 TCGv zero = tcg_constant_tl(0); 943 944 tcg_gen_movcond_tl(TCG_COND_NE, cpu_npc, cpu_cond, zero, npc0, npc1); 945 } 946 947 /* call this function before using the condition register as it may 948 have been set for a jump */ 949 static inline void flush_cond(DisasContext *dc) 950 { 951 if (dc->npc == JUMP_PC) { 952 gen_generic_branch(dc); 953 dc->npc = DYNAMIC_PC; 954 } 955 } 956 957 static inline void save_npc(DisasContext *dc) 958 { 959 if (dc->npc == JUMP_PC) { 960 gen_generic_branch(dc); 961 dc->npc = DYNAMIC_PC; 962 } else if (dc->npc != DYNAMIC_PC) { 963 tcg_gen_movi_tl(cpu_npc, dc->npc); 964 } 965 } 966 967 static inline void update_psr(DisasContext *dc) 968 { 969 if (dc->cc_op != CC_OP_FLAGS) { 970 dc->cc_op = CC_OP_FLAGS; 971 gen_helper_compute_psr(cpu_env); 972 } 973 } 974 975 static inline void save_state(DisasContext *dc) 976 { 977 tcg_gen_movi_tl(cpu_pc, dc->pc); 978 save_npc(dc); 979 } 980 981 static void gen_exception(DisasContext *dc, int which) 982 { 983 save_state(dc); 984 gen_helper_raise_exception(cpu_env, tcg_constant_i32(which)); 985 dc->base.is_jmp = DISAS_NORETURN; 986 } 987 988 static void gen_check_align(TCGv addr, int mask) 989 { 990 gen_helper_check_align(cpu_env, addr, tcg_constant_i32(mask)); 991 } 992 993 static inline void gen_mov_pc_npc(DisasContext *dc) 994 { 995 if (dc->npc == JUMP_PC) { 996 gen_generic_branch(dc); 997 tcg_gen_mov_tl(cpu_pc, cpu_npc); 998 dc->pc = DYNAMIC_PC; 999 } else if (dc->npc == DYNAMIC_PC) { 1000 tcg_gen_mov_tl(cpu_pc, cpu_npc); 1001 dc->pc = DYNAMIC_PC; 1002 } else { 1003 dc->pc = dc->npc; 1004 } 1005 } 1006 1007 static inline void gen_op_next_insn(void) 1008 { 1009 tcg_gen_mov_tl(cpu_pc, cpu_npc); 1010 tcg_gen_addi_tl(cpu_npc, cpu_npc, 4); 1011 } 1012 1013 static void gen_compare(DisasCompare *cmp, bool xcc, unsigned int cond, 1014 DisasContext *dc) 1015 { 1016 static int subcc_cond[16] = { 1017 TCG_COND_NEVER, 1018 TCG_COND_EQ, 1019 TCG_COND_LE, 1020 TCG_COND_LT, 1021 TCG_COND_LEU, 1022 TCG_COND_LTU, 1023 -1, /* neg */ 1024 -1, /* overflow */ 1025 TCG_COND_ALWAYS, 1026 TCG_COND_NE, 1027 TCG_COND_GT, 1028 TCG_COND_GE, 1029 TCG_COND_GTU, 1030 TCG_COND_GEU, 1031 -1, /* pos */ 1032 -1, /* no overflow */ 1033 }; 1034 1035 static int logic_cond[16] = { 1036 TCG_COND_NEVER, 1037 TCG_COND_EQ, /* eq: Z */ 1038 TCG_COND_LE, /* le: Z | (N ^ V) -> Z | N */ 1039 TCG_COND_LT, /* lt: N ^ V -> N */ 1040 TCG_COND_EQ, /* leu: C | Z -> Z */ 1041 TCG_COND_NEVER, /* ltu: C -> 0 */ 1042 TCG_COND_LT, /* neg: N */ 1043 TCG_COND_NEVER, /* vs: V -> 0 */ 1044 TCG_COND_ALWAYS, 1045 TCG_COND_NE, /* ne: !Z */ 1046 TCG_COND_GT, /* gt: !(Z | (N ^ V)) -> !(Z | N) */ 1047 TCG_COND_GE, /* ge: !(N ^ V) -> !N */ 1048 TCG_COND_NE, /* gtu: !(C | Z) -> !Z */ 1049 TCG_COND_ALWAYS, /* geu: !C -> 1 */ 1050 TCG_COND_GE, /* pos: !N */ 1051 TCG_COND_ALWAYS, /* vc: !V -> 1 */ 1052 }; 1053 1054 TCGv_i32 r_src; 1055 TCGv r_dst; 1056 1057 #ifdef TARGET_SPARC64 1058 if (xcc) { 1059 r_src = cpu_xcc; 1060 } else { 1061 r_src = cpu_psr; 1062 } 1063 #else 1064 r_src = cpu_psr; 1065 #endif 1066 1067 switch (dc->cc_op) { 1068 case CC_OP_LOGIC: 1069 cmp->cond = logic_cond[cond]; 1070 do_compare_dst_0: 1071 cmp->is_bool = false; 1072 cmp->c2 = tcg_constant_tl(0); 1073 #ifdef TARGET_SPARC64 1074 if (!xcc) { 1075 cmp->c1 = tcg_temp_new(); 1076 tcg_gen_ext32s_tl(cmp->c1, cpu_cc_dst); 1077 break; 1078 } 1079 #endif 1080 cmp->c1 = cpu_cc_dst; 1081 break; 1082 1083 case CC_OP_SUB: 1084 switch (cond) { 1085 case 6: /* neg */ 1086 case 14: /* pos */ 1087 cmp->cond = (cond == 6 ? TCG_COND_LT : TCG_COND_GE); 1088 goto do_compare_dst_0; 1089 1090 case 7: /* overflow */ 1091 case 15: /* !overflow */ 1092 goto do_dynamic; 1093 1094 default: 1095 cmp->cond = subcc_cond[cond]; 1096 cmp->is_bool = false; 1097 #ifdef TARGET_SPARC64 1098 if (!xcc) { 1099 /* Note that sign-extension works for unsigned compares as 1100 long as both operands are sign-extended. */ 1101 cmp->c1 = tcg_temp_new(); 1102 cmp->c2 = tcg_temp_new(); 1103 tcg_gen_ext32s_tl(cmp->c1, cpu_cc_src); 1104 tcg_gen_ext32s_tl(cmp->c2, cpu_cc_src2); 1105 break; 1106 } 1107 #endif 1108 cmp->c1 = cpu_cc_src; 1109 cmp->c2 = cpu_cc_src2; 1110 break; 1111 } 1112 break; 1113 1114 default: 1115 do_dynamic: 1116 gen_helper_compute_psr(cpu_env); 1117 dc->cc_op = CC_OP_FLAGS; 1118 /* FALLTHRU */ 1119 1120 case CC_OP_FLAGS: 1121 /* We're going to generate a boolean result. */ 1122 cmp->cond = TCG_COND_NE; 1123 cmp->is_bool = true; 1124 cmp->c1 = r_dst = tcg_temp_new(); 1125 cmp->c2 = tcg_constant_tl(0); 1126 1127 switch (cond) { 1128 case 0x0: 1129 gen_op_eval_bn(r_dst); 1130 break; 1131 case 0x1: 1132 gen_op_eval_be(r_dst, r_src); 1133 break; 1134 case 0x2: 1135 gen_op_eval_ble(r_dst, r_src); 1136 break; 1137 case 0x3: 1138 gen_op_eval_bl(r_dst, r_src); 1139 break; 1140 case 0x4: 1141 gen_op_eval_bleu(r_dst, r_src); 1142 break; 1143 case 0x5: 1144 gen_op_eval_bcs(r_dst, r_src); 1145 break; 1146 case 0x6: 1147 gen_op_eval_bneg(r_dst, r_src); 1148 break; 1149 case 0x7: 1150 gen_op_eval_bvs(r_dst, r_src); 1151 break; 1152 case 0x8: 1153 gen_op_eval_ba(r_dst); 1154 break; 1155 case 0x9: 1156 gen_op_eval_bne(r_dst, r_src); 1157 break; 1158 case 0xa: 1159 gen_op_eval_bg(r_dst, r_src); 1160 break; 1161 case 0xb: 1162 gen_op_eval_bge(r_dst, r_src); 1163 break; 1164 case 0xc: 1165 gen_op_eval_bgu(r_dst, r_src); 1166 break; 1167 case 0xd: 1168 gen_op_eval_bcc(r_dst, r_src); 1169 break; 1170 case 0xe: 1171 gen_op_eval_bpos(r_dst, r_src); 1172 break; 1173 case 0xf: 1174 gen_op_eval_bvc(r_dst, r_src); 1175 break; 1176 } 1177 break; 1178 } 1179 } 1180 1181 static void gen_fcompare(DisasCompare *cmp, unsigned int cc, unsigned int cond) 1182 { 1183 unsigned int offset; 1184 TCGv r_dst; 1185 1186 /* For now we still generate a straight boolean result. */ 1187 cmp->cond = TCG_COND_NE; 1188 cmp->is_bool = true; 1189 cmp->c1 = r_dst = tcg_temp_new(); 1190 cmp->c2 = tcg_constant_tl(0); 1191 1192 switch (cc) { 1193 default: 1194 case 0x0: 1195 offset = 0; 1196 break; 1197 case 0x1: 1198 offset = 32 - 10; 1199 break; 1200 case 0x2: 1201 offset = 34 - 10; 1202 break; 1203 case 0x3: 1204 offset = 36 - 10; 1205 break; 1206 } 1207 1208 switch (cond) { 1209 case 0x0: 1210 gen_op_eval_bn(r_dst); 1211 break; 1212 case 0x1: 1213 gen_op_eval_fbne(r_dst, cpu_fsr, offset); 1214 break; 1215 case 0x2: 1216 gen_op_eval_fblg(r_dst, cpu_fsr, offset); 1217 break; 1218 case 0x3: 1219 gen_op_eval_fbul(r_dst, cpu_fsr, offset); 1220 break; 1221 case 0x4: 1222 gen_op_eval_fbl(r_dst, cpu_fsr, offset); 1223 break; 1224 case 0x5: 1225 gen_op_eval_fbug(r_dst, cpu_fsr, offset); 1226 break; 1227 case 0x6: 1228 gen_op_eval_fbg(r_dst, cpu_fsr, offset); 1229 break; 1230 case 0x7: 1231 gen_op_eval_fbu(r_dst, cpu_fsr, offset); 1232 break; 1233 case 0x8: 1234 gen_op_eval_ba(r_dst); 1235 break; 1236 case 0x9: 1237 gen_op_eval_fbe(r_dst, cpu_fsr, offset); 1238 break; 1239 case 0xa: 1240 gen_op_eval_fbue(r_dst, cpu_fsr, offset); 1241 break; 1242 case 0xb: 1243 gen_op_eval_fbge(r_dst, cpu_fsr, offset); 1244 break; 1245 case 0xc: 1246 gen_op_eval_fbuge(r_dst, cpu_fsr, offset); 1247 break; 1248 case 0xd: 1249 gen_op_eval_fble(r_dst, cpu_fsr, offset); 1250 break; 1251 case 0xe: 1252 gen_op_eval_fbule(r_dst, cpu_fsr, offset); 1253 break; 1254 case 0xf: 1255 gen_op_eval_fbo(r_dst, cpu_fsr, offset); 1256 break; 1257 } 1258 } 1259 1260 static void gen_cond(TCGv r_dst, unsigned int cc, unsigned int cond, 1261 DisasContext *dc) 1262 { 1263 DisasCompare cmp; 1264 gen_compare(&cmp, cc, cond, dc); 1265 1266 /* The interface is to return a boolean in r_dst. */ 1267 if (cmp.is_bool) { 1268 tcg_gen_mov_tl(r_dst, cmp.c1); 1269 } else { 1270 tcg_gen_setcond_tl(cmp.cond, r_dst, cmp.c1, cmp.c2); 1271 } 1272 } 1273 1274 static void gen_fcond(TCGv r_dst, unsigned int cc, unsigned int cond) 1275 { 1276 DisasCompare cmp; 1277 gen_fcompare(&cmp, cc, cond); 1278 1279 /* The interface is to return a boolean in r_dst. */ 1280 if (cmp.is_bool) { 1281 tcg_gen_mov_tl(r_dst, cmp.c1); 1282 } else { 1283 tcg_gen_setcond_tl(cmp.cond, r_dst, cmp.c1, cmp.c2); 1284 } 1285 } 1286 1287 #ifdef TARGET_SPARC64 1288 // Inverted logic 1289 static const int gen_tcg_cond_reg[8] = { 1290 -1, 1291 TCG_COND_NE, 1292 TCG_COND_GT, 1293 TCG_COND_GE, 1294 -1, 1295 TCG_COND_EQ, 1296 TCG_COND_LE, 1297 TCG_COND_LT, 1298 }; 1299 1300 static void gen_compare_reg(DisasCompare *cmp, int cond, TCGv r_src) 1301 { 1302 cmp->cond = tcg_invert_cond(gen_tcg_cond_reg[cond]); 1303 cmp->is_bool = false; 1304 cmp->c1 = r_src; 1305 cmp->c2 = tcg_constant_tl(0); 1306 } 1307 1308 static inline void gen_cond_reg(TCGv r_dst, int cond, TCGv r_src) 1309 { 1310 DisasCompare cmp; 1311 gen_compare_reg(&cmp, cond, r_src); 1312 1313 /* The interface is to return a boolean in r_dst. */ 1314 tcg_gen_setcond_tl(cmp.cond, r_dst, cmp.c1, cmp.c2); 1315 } 1316 #endif 1317 1318 static void do_branch(DisasContext *dc, int32_t offset, uint32_t insn, int cc) 1319 { 1320 unsigned int cond = GET_FIELD(insn, 3, 6), a = (insn & (1 << 29)); 1321 target_ulong target = dc->pc + offset; 1322 1323 #ifdef TARGET_SPARC64 1324 if (unlikely(AM_CHECK(dc))) { 1325 target &= 0xffffffffULL; 1326 } 1327 #endif 1328 if (cond == 0x0) { 1329 /* unconditional not taken */ 1330 if (a) { 1331 dc->pc = dc->npc + 4; 1332 dc->npc = dc->pc + 4; 1333 } else { 1334 dc->pc = dc->npc; 1335 dc->npc = dc->pc + 4; 1336 } 1337 } else if (cond == 0x8) { 1338 /* unconditional taken */ 1339 if (a) { 1340 dc->pc = target; 1341 dc->npc = dc->pc + 4; 1342 } else { 1343 dc->pc = dc->npc; 1344 dc->npc = target; 1345 tcg_gen_mov_tl(cpu_pc, cpu_npc); 1346 } 1347 } else { 1348 flush_cond(dc); 1349 gen_cond(cpu_cond, cc, cond, dc); 1350 if (a) { 1351 gen_branch_a(dc, target); 1352 } else { 1353 gen_branch_n(dc, target); 1354 } 1355 } 1356 } 1357 1358 static void do_fbranch(DisasContext *dc, int32_t offset, uint32_t insn, int cc) 1359 { 1360 unsigned int cond = GET_FIELD(insn, 3, 6), a = (insn & (1 << 29)); 1361 target_ulong target = dc->pc + offset; 1362 1363 #ifdef TARGET_SPARC64 1364 if (unlikely(AM_CHECK(dc))) { 1365 target &= 0xffffffffULL; 1366 } 1367 #endif 1368 if (cond == 0x0) { 1369 /* unconditional not taken */ 1370 if (a) { 1371 dc->pc = dc->npc + 4; 1372 dc->npc = dc->pc + 4; 1373 } else { 1374 dc->pc = dc->npc; 1375 dc->npc = dc->pc + 4; 1376 } 1377 } else if (cond == 0x8) { 1378 /* unconditional taken */ 1379 if (a) { 1380 dc->pc = target; 1381 dc->npc = dc->pc + 4; 1382 } else { 1383 dc->pc = dc->npc; 1384 dc->npc = target; 1385 tcg_gen_mov_tl(cpu_pc, cpu_npc); 1386 } 1387 } else { 1388 flush_cond(dc); 1389 gen_fcond(cpu_cond, cc, cond); 1390 if (a) { 1391 gen_branch_a(dc, target); 1392 } else { 1393 gen_branch_n(dc, target); 1394 } 1395 } 1396 } 1397 1398 #ifdef TARGET_SPARC64 1399 static void do_branch_reg(DisasContext *dc, int32_t offset, uint32_t insn, 1400 TCGv r_reg) 1401 { 1402 unsigned int cond = GET_FIELD_SP(insn, 25, 27), a = (insn & (1 << 29)); 1403 target_ulong target = dc->pc + offset; 1404 1405 if (unlikely(AM_CHECK(dc))) { 1406 target &= 0xffffffffULL; 1407 } 1408 flush_cond(dc); 1409 gen_cond_reg(cpu_cond, cond, r_reg); 1410 if (a) { 1411 gen_branch_a(dc, target); 1412 } else { 1413 gen_branch_n(dc, target); 1414 } 1415 } 1416 1417 static inline void gen_op_fcmps(int fccno, TCGv_i32 r_rs1, TCGv_i32 r_rs2) 1418 { 1419 switch (fccno) { 1420 case 0: 1421 gen_helper_fcmps(cpu_fsr, cpu_env, r_rs1, r_rs2); 1422 break; 1423 case 1: 1424 gen_helper_fcmps_fcc1(cpu_fsr, cpu_env, r_rs1, r_rs2); 1425 break; 1426 case 2: 1427 gen_helper_fcmps_fcc2(cpu_fsr, cpu_env, r_rs1, r_rs2); 1428 break; 1429 case 3: 1430 gen_helper_fcmps_fcc3(cpu_fsr, cpu_env, r_rs1, r_rs2); 1431 break; 1432 } 1433 } 1434 1435 static inline void gen_op_fcmpd(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2) 1436 { 1437 switch (fccno) { 1438 case 0: 1439 gen_helper_fcmpd(cpu_fsr, cpu_env, r_rs1, r_rs2); 1440 break; 1441 case 1: 1442 gen_helper_fcmpd_fcc1(cpu_fsr, cpu_env, r_rs1, r_rs2); 1443 break; 1444 case 2: 1445 gen_helper_fcmpd_fcc2(cpu_fsr, cpu_env, r_rs1, r_rs2); 1446 break; 1447 case 3: 1448 gen_helper_fcmpd_fcc3(cpu_fsr, cpu_env, r_rs1, r_rs2); 1449 break; 1450 } 1451 } 1452 1453 static inline void gen_op_fcmpq(int fccno) 1454 { 1455 switch (fccno) { 1456 case 0: 1457 gen_helper_fcmpq(cpu_fsr, cpu_env); 1458 break; 1459 case 1: 1460 gen_helper_fcmpq_fcc1(cpu_fsr, cpu_env); 1461 break; 1462 case 2: 1463 gen_helper_fcmpq_fcc2(cpu_fsr, cpu_env); 1464 break; 1465 case 3: 1466 gen_helper_fcmpq_fcc3(cpu_fsr, cpu_env); 1467 break; 1468 } 1469 } 1470 1471 static inline void gen_op_fcmpes(int fccno, TCGv_i32 r_rs1, TCGv_i32 r_rs2) 1472 { 1473 switch (fccno) { 1474 case 0: 1475 gen_helper_fcmpes(cpu_fsr, cpu_env, r_rs1, r_rs2); 1476 break; 1477 case 1: 1478 gen_helper_fcmpes_fcc1(cpu_fsr, cpu_env, r_rs1, r_rs2); 1479 break; 1480 case 2: 1481 gen_helper_fcmpes_fcc2(cpu_fsr, cpu_env, r_rs1, r_rs2); 1482 break; 1483 case 3: 1484 gen_helper_fcmpes_fcc3(cpu_fsr, cpu_env, r_rs1, r_rs2); 1485 break; 1486 } 1487 } 1488 1489 static inline void gen_op_fcmped(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2) 1490 { 1491 switch (fccno) { 1492 case 0: 1493 gen_helper_fcmped(cpu_fsr, cpu_env, r_rs1, r_rs2); 1494 break; 1495 case 1: 1496 gen_helper_fcmped_fcc1(cpu_fsr, cpu_env, r_rs1, r_rs2); 1497 break; 1498 case 2: 1499 gen_helper_fcmped_fcc2(cpu_fsr, cpu_env, r_rs1, r_rs2); 1500 break; 1501 case 3: 1502 gen_helper_fcmped_fcc3(cpu_fsr, cpu_env, r_rs1, r_rs2); 1503 break; 1504 } 1505 } 1506 1507 static inline void gen_op_fcmpeq(int fccno) 1508 { 1509 switch (fccno) { 1510 case 0: 1511 gen_helper_fcmpeq(cpu_fsr, cpu_env); 1512 break; 1513 case 1: 1514 gen_helper_fcmpeq_fcc1(cpu_fsr, cpu_env); 1515 break; 1516 case 2: 1517 gen_helper_fcmpeq_fcc2(cpu_fsr, cpu_env); 1518 break; 1519 case 3: 1520 gen_helper_fcmpeq_fcc3(cpu_fsr, cpu_env); 1521 break; 1522 } 1523 } 1524 1525 #else 1526 1527 static inline void gen_op_fcmps(int fccno, TCGv r_rs1, TCGv r_rs2) 1528 { 1529 gen_helper_fcmps(cpu_fsr, cpu_env, r_rs1, r_rs2); 1530 } 1531 1532 static inline void gen_op_fcmpd(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2) 1533 { 1534 gen_helper_fcmpd(cpu_fsr, cpu_env, r_rs1, r_rs2); 1535 } 1536 1537 static inline void gen_op_fcmpq(int fccno) 1538 { 1539 gen_helper_fcmpq(cpu_fsr, cpu_env); 1540 } 1541 1542 static inline void gen_op_fcmpes(int fccno, TCGv r_rs1, TCGv r_rs2) 1543 { 1544 gen_helper_fcmpes(cpu_fsr, cpu_env, r_rs1, r_rs2); 1545 } 1546 1547 static inline void gen_op_fcmped(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2) 1548 { 1549 gen_helper_fcmped(cpu_fsr, cpu_env, r_rs1, r_rs2); 1550 } 1551 1552 static inline void gen_op_fcmpeq(int fccno) 1553 { 1554 gen_helper_fcmpeq(cpu_fsr, cpu_env); 1555 } 1556 #endif 1557 1558 static void gen_op_fpexception_im(DisasContext *dc, int fsr_flags) 1559 { 1560 tcg_gen_andi_tl(cpu_fsr, cpu_fsr, FSR_FTT_NMASK); 1561 tcg_gen_ori_tl(cpu_fsr, cpu_fsr, fsr_flags); 1562 gen_exception(dc, TT_FP_EXCP); 1563 } 1564 1565 static int gen_trap_ifnofpu(DisasContext *dc) 1566 { 1567 #if !defined(CONFIG_USER_ONLY) 1568 if (!dc->fpu_enabled) { 1569 gen_exception(dc, TT_NFPU_INSN); 1570 return 1; 1571 } 1572 #endif 1573 return 0; 1574 } 1575 1576 static inline void gen_op_clear_ieee_excp_and_FTT(void) 1577 { 1578 tcg_gen_andi_tl(cpu_fsr, cpu_fsr, FSR_FTT_CEXC_NMASK); 1579 } 1580 1581 static inline void gen_fop_FF(DisasContext *dc, int rd, int rs, 1582 void (*gen)(TCGv_i32, TCGv_ptr, TCGv_i32)) 1583 { 1584 TCGv_i32 dst, src; 1585 1586 src = gen_load_fpr_F(dc, rs); 1587 dst = gen_dest_fpr_F(dc); 1588 1589 gen(dst, cpu_env, src); 1590 gen_helper_check_ieee_exceptions(cpu_fsr, cpu_env); 1591 1592 gen_store_fpr_F(dc, rd, dst); 1593 } 1594 1595 static inline void gen_ne_fop_FF(DisasContext *dc, int rd, int rs, 1596 void (*gen)(TCGv_i32, TCGv_i32)) 1597 { 1598 TCGv_i32 dst, src; 1599 1600 src = gen_load_fpr_F(dc, rs); 1601 dst = gen_dest_fpr_F(dc); 1602 1603 gen(dst, src); 1604 1605 gen_store_fpr_F(dc, rd, dst); 1606 } 1607 1608 static inline void gen_fop_FFF(DisasContext *dc, int rd, int rs1, int rs2, 1609 void (*gen)(TCGv_i32, TCGv_ptr, TCGv_i32, TCGv_i32)) 1610 { 1611 TCGv_i32 dst, src1, src2; 1612 1613 src1 = gen_load_fpr_F(dc, rs1); 1614 src2 = gen_load_fpr_F(dc, rs2); 1615 dst = gen_dest_fpr_F(dc); 1616 1617 gen(dst, cpu_env, src1, src2); 1618 gen_helper_check_ieee_exceptions(cpu_fsr, cpu_env); 1619 1620 gen_store_fpr_F(dc, rd, dst); 1621 } 1622 1623 #ifdef TARGET_SPARC64 1624 static inline void gen_ne_fop_FFF(DisasContext *dc, int rd, int rs1, int rs2, 1625 void (*gen)(TCGv_i32, TCGv_i32, TCGv_i32)) 1626 { 1627 TCGv_i32 dst, src1, src2; 1628 1629 src1 = gen_load_fpr_F(dc, rs1); 1630 src2 = gen_load_fpr_F(dc, rs2); 1631 dst = gen_dest_fpr_F(dc); 1632 1633 gen(dst, src1, src2); 1634 1635 gen_store_fpr_F(dc, rd, dst); 1636 } 1637 #endif 1638 1639 static inline void gen_fop_DD(DisasContext *dc, int rd, int rs, 1640 void (*gen)(TCGv_i64, TCGv_ptr, TCGv_i64)) 1641 { 1642 TCGv_i64 dst, src; 1643 1644 src = gen_load_fpr_D(dc, rs); 1645 dst = gen_dest_fpr_D(dc, rd); 1646 1647 gen(dst, cpu_env, src); 1648 gen_helper_check_ieee_exceptions(cpu_fsr, cpu_env); 1649 1650 gen_store_fpr_D(dc, rd, dst); 1651 } 1652 1653 #ifdef TARGET_SPARC64 1654 static inline void gen_ne_fop_DD(DisasContext *dc, int rd, int rs, 1655 void (*gen)(TCGv_i64, TCGv_i64)) 1656 { 1657 TCGv_i64 dst, src; 1658 1659 src = gen_load_fpr_D(dc, rs); 1660 dst = gen_dest_fpr_D(dc, rd); 1661 1662 gen(dst, src); 1663 1664 gen_store_fpr_D(dc, rd, dst); 1665 } 1666 #endif 1667 1668 static inline void gen_fop_DDD(DisasContext *dc, int rd, int rs1, int rs2, 1669 void (*gen)(TCGv_i64, TCGv_ptr, TCGv_i64, TCGv_i64)) 1670 { 1671 TCGv_i64 dst, src1, src2; 1672 1673 src1 = gen_load_fpr_D(dc, rs1); 1674 src2 = gen_load_fpr_D(dc, rs2); 1675 dst = gen_dest_fpr_D(dc, rd); 1676 1677 gen(dst, cpu_env, src1, src2); 1678 gen_helper_check_ieee_exceptions(cpu_fsr, cpu_env); 1679 1680 gen_store_fpr_D(dc, rd, dst); 1681 } 1682 1683 #ifdef TARGET_SPARC64 1684 static inline void gen_ne_fop_DDD(DisasContext *dc, int rd, int rs1, int rs2, 1685 void (*gen)(TCGv_i64, TCGv_i64, TCGv_i64)) 1686 { 1687 TCGv_i64 dst, src1, src2; 1688 1689 src1 = gen_load_fpr_D(dc, rs1); 1690 src2 = gen_load_fpr_D(dc, rs2); 1691 dst = gen_dest_fpr_D(dc, rd); 1692 1693 gen(dst, src1, src2); 1694 1695 gen_store_fpr_D(dc, rd, dst); 1696 } 1697 1698 static inline void gen_gsr_fop_DDD(DisasContext *dc, int rd, int rs1, int rs2, 1699 void (*gen)(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_i64)) 1700 { 1701 TCGv_i64 dst, src1, src2; 1702 1703 src1 = gen_load_fpr_D(dc, rs1); 1704 src2 = gen_load_fpr_D(dc, rs2); 1705 dst = gen_dest_fpr_D(dc, rd); 1706 1707 gen(dst, cpu_gsr, src1, src2); 1708 1709 gen_store_fpr_D(dc, rd, dst); 1710 } 1711 1712 static inline void gen_ne_fop_DDDD(DisasContext *dc, int rd, int rs1, int rs2, 1713 void (*gen)(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_i64)) 1714 { 1715 TCGv_i64 dst, src0, src1, src2; 1716 1717 src1 = gen_load_fpr_D(dc, rs1); 1718 src2 = gen_load_fpr_D(dc, rs2); 1719 src0 = gen_load_fpr_D(dc, rd); 1720 dst = gen_dest_fpr_D(dc, rd); 1721 1722 gen(dst, src0, src1, src2); 1723 1724 gen_store_fpr_D(dc, rd, dst); 1725 } 1726 #endif 1727 1728 static inline void gen_fop_QQ(DisasContext *dc, int rd, int rs, 1729 void (*gen)(TCGv_ptr)) 1730 { 1731 gen_op_load_fpr_QT1(QFPREG(rs)); 1732 1733 gen(cpu_env); 1734 gen_helper_check_ieee_exceptions(cpu_fsr, cpu_env); 1735 1736 gen_op_store_QT0_fpr(QFPREG(rd)); 1737 gen_update_fprs_dirty(dc, QFPREG(rd)); 1738 } 1739 1740 #ifdef TARGET_SPARC64 1741 static inline void gen_ne_fop_QQ(DisasContext *dc, int rd, int rs, 1742 void (*gen)(TCGv_ptr)) 1743 { 1744 gen_op_load_fpr_QT1(QFPREG(rs)); 1745 1746 gen(cpu_env); 1747 1748 gen_op_store_QT0_fpr(QFPREG(rd)); 1749 gen_update_fprs_dirty(dc, QFPREG(rd)); 1750 } 1751 #endif 1752 1753 static inline void gen_fop_QQQ(DisasContext *dc, int rd, int rs1, int rs2, 1754 void (*gen)(TCGv_ptr)) 1755 { 1756 gen_op_load_fpr_QT0(QFPREG(rs1)); 1757 gen_op_load_fpr_QT1(QFPREG(rs2)); 1758 1759 gen(cpu_env); 1760 gen_helper_check_ieee_exceptions(cpu_fsr, cpu_env); 1761 1762 gen_op_store_QT0_fpr(QFPREG(rd)); 1763 gen_update_fprs_dirty(dc, QFPREG(rd)); 1764 } 1765 1766 static inline void gen_fop_DFF(DisasContext *dc, int rd, int rs1, int rs2, 1767 void (*gen)(TCGv_i64, TCGv_ptr, TCGv_i32, TCGv_i32)) 1768 { 1769 TCGv_i64 dst; 1770 TCGv_i32 src1, src2; 1771 1772 src1 = gen_load_fpr_F(dc, rs1); 1773 src2 = gen_load_fpr_F(dc, rs2); 1774 dst = gen_dest_fpr_D(dc, rd); 1775 1776 gen(dst, cpu_env, src1, src2); 1777 gen_helper_check_ieee_exceptions(cpu_fsr, cpu_env); 1778 1779 gen_store_fpr_D(dc, rd, dst); 1780 } 1781 1782 static inline void gen_fop_QDD(DisasContext *dc, int rd, int rs1, int rs2, 1783 void (*gen)(TCGv_ptr, TCGv_i64, TCGv_i64)) 1784 { 1785 TCGv_i64 src1, src2; 1786 1787 src1 = gen_load_fpr_D(dc, rs1); 1788 src2 = gen_load_fpr_D(dc, rs2); 1789 1790 gen(cpu_env, src1, src2); 1791 gen_helper_check_ieee_exceptions(cpu_fsr, cpu_env); 1792 1793 gen_op_store_QT0_fpr(QFPREG(rd)); 1794 gen_update_fprs_dirty(dc, QFPREG(rd)); 1795 } 1796 1797 #ifdef TARGET_SPARC64 1798 static inline void gen_fop_DF(DisasContext *dc, int rd, int rs, 1799 void (*gen)(TCGv_i64, TCGv_ptr, TCGv_i32)) 1800 { 1801 TCGv_i64 dst; 1802 TCGv_i32 src; 1803 1804 src = gen_load_fpr_F(dc, rs); 1805 dst = gen_dest_fpr_D(dc, rd); 1806 1807 gen(dst, cpu_env, src); 1808 gen_helper_check_ieee_exceptions(cpu_fsr, cpu_env); 1809 1810 gen_store_fpr_D(dc, rd, dst); 1811 } 1812 #endif 1813 1814 static inline void gen_ne_fop_DF(DisasContext *dc, int rd, int rs, 1815 void (*gen)(TCGv_i64, TCGv_ptr, TCGv_i32)) 1816 { 1817 TCGv_i64 dst; 1818 TCGv_i32 src; 1819 1820 src = gen_load_fpr_F(dc, rs); 1821 dst = gen_dest_fpr_D(dc, rd); 1822 1823 gen(dst, cpu_env, src); 1824 1825 gen_store_fpr_D(dc, rd, dst); 1826 } 1827 1828 static inline void gen_fop_FD(DisasContext *dc, int rd, int rs, 1829 void (*gen)(TCGv_i32, TCGv_ptr, TCGv_i64)) 1830 { 1831 TCGv_i32 dst; 1832 TCGv_i64 src; 1833 1834 src = gen_load_fpr_D(dc, rs); 1835 dst = gen_dest_fpr_F(dc); 1836 1837 gen(dst, cpu_env, src); 1838 gen_helper_check_ieee_exceptions(cpu_fsr, cpu_env); 1839 1840 gen_store_fpr_F(dc, rd, dst); 1841 } 1842 1843 static inline void gen_fop_FQ(DisasContext *dc, int rd, int rs, 1844 void (*gen)(TCGv_i32, TCGv_ptr)) 1845 { 1846 TCGv_i32 dst; 1847 1848 gen_op_load_fpr_QT1(QFPREG(rs)); 1849 dst = gen_dest_fpr_F(dc); 1850 1851 gen(dst, cpu_env); 1852 gen_helper_check_ieee_exceptions(cpu_fsr, cpu_env); 1853 1854 gen_store_fpr_F(dc, rd, dst); 1855 } 1856 1857 static inline void gen_fop_DQ(DisasContext *dc, int rd, int rs, 1858 void (*gen)(TCGv_i64, TCGv_ptr)) 1859 { 1860 TCGv_i64 dst; 1861 1862 gen_op_load_fpr_QT1(QFPREG(rs)); 1863 dst = gen_dest_fpr_D(dc, rd); 1864 1865 gen(dst, cpu_env); 1866 gen_helper_check_ieee_exceptions(cpu_fsr, cpu_env); 1867 1868 gen_store_fpr_D(dc, rd, dst); 1869 } 1870 1871 static inline void gen_ne_fop_QF(DisasContext *dc, int rd, int rs, 1872 void (*gen)(TCGv_ptr, TCGv_i32)) 1873 { 1874 TCGv_i32 src; 1875 1876 src = gen_load_fpr_F(dc, rs); 1877 1878 gen(cpu_env, src); 1879 1880 gen_op_store_QT0_fpr(QFPREG(rd)); 1881 gen_update_fprs_dirty(dc, QFPREG(rd)); 1882 } 1883 1884 static inline void gen_ne_fop_QD(DisasContext *dc, int rd, int rs, 1885 void (*gen)(TCGv_ptr, TCGv_i64)) 1886 { 1887 TCGv_i64 src; 1888 1889 src = gen_load_fpr_D(dc, rs); 1890 1891 gen(cpu_env, src); 1892 1893 gen_op_store_QT0_fpr(QFPREG(rd)); 1894 gen_update_fprs_dirty(dc, QFPREG(rd)); 1895 } 1896 1897 static void gen_swap(DisasContext *dc, TCGv dst, TCGv src, 1898 TCGv addr, int mmu_idx, MemOp memop) 1899 { 1900 gen_address_mask(dc, addr); 1901 tcg_gen_atomic_xchg_tl(dst, addr, src, mmu_idx, memop | MO_ALIGN); 1902 } 1903 1904 static void gen_ldstub(DisasContext *dc, TCGv dst, TCGv addr, int mmu_idx) 1905 { 1906 TCGv m1 = tcg_constant_tl(0xff); 1907 gen_address_mask(dc, addr); 1908 tcg_gen_atomic_xchg_tl(dst, addr, m1, mmu_idx, MO_UB); 1909 } 1910 1911 /* asi moves */ 1912 #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64) 1913 typedef enum { 1914 GET_ASI_HELPER, 1915 GET_ASI_EXCP, 1916 GET_ASI_DIRECT, 1917 GET_ASI_DTWINX, 1918 GET_ASI_BLOCK, 1919 GET_ASI_SHORT, 1920 GET_ASI_BCOPY, 1921 GET_ASI_BFILL, 1922 } ASIType; 1923 1924 typedef struct { 1925 ASIType type; 1926 int asi; 1927 int mem_idx; 1928 MemOp memop; 1929 } DisasASI; 1930 1931 static DisasASI get_asi(DisasContext *dc, int insn, MemOp memop) 1932 { 1933 int asi = GET_FIELD(insn, 19, 26); 1934 ASIType type = GET_ASI_HELPER; 1935 int mem_idx = dc->mem_idx; 1936 1937 #ifndef TARGET_SPARC64 1938 /* Before v9, all asis are immediate and privileged. */ 1939 if (IS_IMM) { 1940 gen_exception(dc, TT_ILL_INSN); 1941 type = GET_ASI_EXCP; 1942 } else if (supervisor(dc) 1943 /* Note that LEON accepts ASI_USERDATA in user mode, for 1944 use with CASA. Also note that previous versions of 1945 QEMU allowed (and old versions of gcc emitted) ASI_P 1946 for LEON, which is incorrect. */ 1947 || (asi == ASI_USERDATA 1948 && (dc->def->features & CPU_FEATURE_CASA))) { 1949 switch (asi) { 1950 case ASI_USERDATA: /* User data access */ 1951 mem_idx = MMU_USER_IDX; 1952 type = GET_ASI_DIRECT; 1953 break; 1954 case ASI_KERNELDATA: /* Supervisor data access */ 1955 mem_idx = MMU_KERNEL_IDX; 1956 type = GET_ASI_DIRECT; 1957 break; 1958 case ASI_M_BYPASS: /* MMU passthrough */ 1959 case ASI_LEON_BYPASS: /* LEON MMU passthrough */ 1960 mem_idx = MMU_PHYS_IDX; 1961 type = GET_ASI_DIRECT; 1962 break; 1963 case ASI_M_BCOPY: /* Block copy, sta access */ 1964 mem_idx = MMU_KERNEL_IDX; 1965 type = GET_ASI_BCOPY; 1966 break; 1967 case ASI_M_BFILL: /* Block fill, stda access */ 1968 mem_idx = MMU_KERNEL_IDX; 1969 type = GET_ASI_BFILL; 1970 break; 1971 } 1972 1973 /* MMU_PHYS_IDX is used when the MMU is disabled to passthrough the 1974 * permissions check in get_physical_address(..). 1975 */ 1976 mem_idx = (dc->mem_idx == MMU_PHYS_IDX) ? MMU_PHYS_IDX : mem_idx; 1977 } else { 1978 gen_exception(dc, TT_PRIV_INSN); 1979 type = GET_ASI_EXCP; 1980 } 1981 #else 1982 if (IS_IMM) { 1983 asi = dc->asi; 1984 } 1985 /* With v9, all asis below 0x80 are privileged. */ 1986 /* ??? We ought to check cpu_has_hypervisor, but we didn't copy 1987 down that bit into DisasContext. For the moment that's ok, 1988 since the direct implementations below doesn't have any ASIs 1989 in the restricted [0x30, 0x7f] range, and the check will be 1990 done properly in the helper. */ 1991 if (!supervisor(dc) && asi < 0x80) { 1992 gen_exception(dc, TT_PRIV_ACT); 1993 type = GET_ASI_EXCP; 1994 } else { 1995 switch (asi) { 1996 case ASI_REAL: /* Bypass */ 1997 case ASI_REAL_IO: /* Bypass, non-cacheable */ 1998 case ASI_REAL_L: /* Bypass LE */ 1999 case ASI_REAL_IO_L: /* Bypass, non-cacheable LE */ 2000 case ASI_TWINX_REAL: /* Real address, twinx */ 2001 case ASI_TWINX_REAL_L: /* Real address, twinx, LE */ 2002 case ASI_QUAD_LDD_PHYS: 2003 case ASI_QUAD_LDD_PHYS_L: 2004 mem_idx = MMU_PHYS_IDX; 2005 break; 2006 case ASI_N: /* Nucleus */ 2007 case ASI_NL: /* Nucleus LE */ 2008 case ASI_TWINX_N: 2009 case ASI_TWINX_NL: 2010 case ASI_NUCLEUS_QUAD_LDD: 2011 case ASI_NUCLEUS_QUAD_LDD_L: 2012 if (hypervisor(dc)) { 2013 mem_idx = MMU_PHYS_IDX; 2014 } else { 2015 mem_idx = MMU_NUCLEUS_IDX; 2016 } 2017 break; 2018 case ASI_AIUP: /* As if user primary */ 2019 case ASI_AIUPL: /* As if user primary LE */ 2020 case ASI_TWINX_AIUP: 2021 case ASI_TWINX_AIUP_L: 2022 case ASI_BLK_AIUP_4V: 2023 case ASI_BLK_AIUP_L_4V: 2024 case ASI_BLK_AIUP: 2025 case ASI_BLK_AIUPL: 2026 mem_idx = MMU_USER_IDX; 2027 break; 2028 case ASI_AIUS: /* As if user secondary */ 2029 case ASI_AIUSL: /* As if user secondary LE */ 2030 case ASI_TWINX_AIUS: 2031 case ASI_TWINX_AIUS_L: 2032 case ASI_BLK_AIUS_4V: 2033 case ASI_BLK_AIUS_L_4V: 2034 case ASI_BLK_AIUS: 2035 case ASI_BLK_AIUSL: 2036 mem_idx = MMU_USER_SECONDARY_IDX; 2037 break; 2038 case ASI_S: /* Secondary */ 2039 case ASI_SL: /* Secondary LE */ 2040 case ASI_TWINX_S: 2041 case ASI_TWINX_SL: 2042 case ASI_BLK_COMMIT_S: 2043 case ASI_BLK_S: 2044 case ASI_BLK_SL: 2045 case ASI_FL8_S: 2046 case ASI_FL8_SL: 2047 case ASI_FL16_S: 2048 case ASI_FL16_SL: 2049 if (mem_idx == MMU_USER_IDX) { 2050 mem_idx = MMU_USER_SECONDARY_IDX; 2051 } else if (mem_idx == MMU_KERNEL_IDX) { 2052 mem_idx = MMU_KERNEL_SECONDARY_IDX; 2053 } 2054 break; 2055 case ASI_P: /* Primary */ 2056 case ASI_PL: /* Primary LE */ 2057 case ASI_TWINX_P: 2058 case ASI_TWINX_PL: 2059 case ASI_BLK_COMMIT_P: 2060 case ASI_BLK_P: 2061 case ASI_BLK_PL: 2062 case ASI_FL8_P: 2063 case ASI_FL8_PL: 2064 case ASI_FL16_P: 2065 case ASI_FL16_PL: 2066 break; 2067 } 2068 switch (asi) { 2069 case ASI_REAL: 2070 case ASI_REAL_IO: 2071 case ASI_REAL_L: 2072 case ASI_REAL_IO_L: 2073 case ASI_N: 2074 case ASI_NL: 2075 case ASI_AIUP: 2076 case ASI_AIUPL: 2077 case ASI_AIUS: 2078 case ASI_AIUSL: 2079 case ASI_S: 2080 case ASI_SL: 2081 case ASI_P: 2082 case ASI_PL: 2083 type = GET_ASI_DIRECT; 2084 break; 2085 case ASI_TWINX_REAL: 2086 case ASI_TWINX_REAL_L: 2087 case ASI_TWINX_N: 2088 case ASI_TWINX_NL: 2089 case ASI_TWINX_AIUP: 2090 case ASI_TWINX_AIUP_L: 2091 case ASI_TWINX_AIUS: 2092 case ASI_TWINX_AIUS_L: 2093 case ASI_TWINX_P: 2094 case ASI_TWINX_PL: 2095 case ASI_TWINX_S: 2096 case ASI_TWINX_SL: 2097 case ASI_QUAD_LDD_PHYS: 2098 case ASI_QUAD_LDD_PHYS_L: 2099 case ASI_NUCLEUS_QUAD_LDD: 2100 case ASI_NUCLEUS_QUAD_LDD_L: 2101 type = GET_ASI_DTWINX; 2102 break; 2103 case ASI_BLK_COMMIT_P: 2104 case ASI_BLK_COMMIT_S: 2105 case ASI_BLK_AIUP_4V: 2106 case ASI_BLK_AIUP_L_4V: 2107 case ASI_BLK_AIUP: 2108 case ASI_BLK_AIUPL: 2109 case ASI_BLK_AIUS_4V: 2110 case ASI_BLK_AIUS_L_4V: 2111 case ASI_BLK_AIUS: 2112 case ASI_BLK_AIUSL: 2113 case ASI_BLK_S: 2114 case ASI_BLK_SL: 2115 case ASI_BLK_P: 2116 case ASI_BLK_PL: 2117 type = GET_ASI_BLOCK; 2118 break; 2119 case ASI_FL8_S: 2120 case ASI_FL8_SL: 2121 case ASI_FL8_P: 2122 case ASI_FL8_PL: 2123 memop = MO_UB; 2124 type = GET_ASI_SHORT; 2125 break; 2126 case ASI_FL16_S: 2127 case ASI_FL16_SL: 2128 case ASI_FL16_P: 2129 case ASI_FL16_PL: 2130 memop = MO_TEUW; 2131 type = GET_ASI_SHORT; 2132 break; 2133 } 2134 /* The little-endian asis all have bit 3 set. */ 2135 if (asi & 8) { 2136 memop ^= MO_BSWAP; 2137 } 2138 } 2139 #endif 2140 2141 return (DisasASI){ type, asi, mem_idx, memop }; 2142 } 2143 2144 static void gen_ld_asi(DisasContext *dc, TCGv dst, TCGv addr, 2145 int insn, MemOp memop) 2146 { 2147 DisasASI da = get_asi(dc, insn, memop); 2148 2149 switch (da.type) { 2150 case GET_ASI_EXCP: 2151 break; 2152 case GET_ASI_DTWINX: /* Reserved for ldda. */ 2153 gen_exception(dc, TT_ILL_INSN); 2154 break; 2155 case GET_ASI_DIRECT: 2156 gen_address_mask(dc, addr); 2157 tcg_gen_qemu_ld_tl(dst, addr, da.mem_idx, da.memop | MO_ALIGN); 2158 break; 2159 default: 2160 { 2161 TCGv_i32 r_asi = tcg_constant_i32(da.asi); 2162 TCGv_i32 r_mop = tcg_constant_i32(memop | MO_ALIGN); 2163 2164 save_state(dc); 2165 #ifdef TARGET_SPARC64 2166 gen_helper_ld_asi(dst, cpu_env, addr, r_asi, r_mop); 2167 #else 2168 { 2169 TCGv_i64 t64 = tcg_temp_new_i64(); 2170 gen_helper_ld_asi(t64, cpu_env, addr, r_asi, r_mop); 2171 tcg_gen_trunc_i64_tl(dst, t64); 2172 } 2173 #endif 2174 } 2175 break; 2176 } 2177 } 2178 2179 static void gen_st_asi(DisasContext *dc, TCGv src, TCGv addr, 2180 int insn, MemOp memop) 2181 { 2182 DisasASI da = get_asi(dc, insn, memop); 2183 2184 switch (da.type) { 2185 case GET_ASI_EXCP: 2186 break; 2187 case GET_ASI_DTWINX: /* Reserved for stda. */ 2188 #ifndef TARGET_SPARC64 2189 gen_exception(dc, TT_ILL_INSN); 2190 break; 2191 #else 2192 if (!(dc->def->features & CPU_FEATURE_HYPV)) { 2193 /* Pre OpenSPARC CPUs don't have these */ 2194 gen_exception(dc, TT_ILL_INSN); 2195 return; 2196 } 2197 /* in OpenSPARC T1+ CPUs TWINX ASIs in store instructions 2198 * are ST_BLKINIT_ ASIs */ 2199 #endif 2200 /* fall through */ 2201 case GET_ASI_DIRECT: 2202 gen_address_mask(dc, addr); 2203 tcg_gen_qemu_st_tl(src, addr, da.mem_idx, da.memop | MO_ALIGN); 2204 break; 2205 #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) 2206 case GET_ASI_BCOPY: 2207 /* Copy 32 bytes from the address in SRC to ADDR. */ 2208 /* ??? The original qemu code suggests 4-byte alignment, dropping 2209 the low bits, but the only place I can see this used is in the 2210 Linux kernel with 32 byte alignment, which would make more sense 2211 as a cacheline-style operation. */ 2212 { 2213 TCGv saddr = tcg_temp_new(); 2214 TCGv daddr = tcg_temp_new(); 2215 TCGv four = tcg_constant_tl(4); 2216 TCGv_i32 tmp = tcg_temp_new_i32(); 2217 int i; 2218 2219 tcg_gen_andi_tl(saddr, src, -4); 2220 tcg_gen_andi_tl(daddr, addr, -4); 2221 for (i = 0; i < 32; i += 4) { 2222 /* Since the loads and stores are paired, allow the 2223 copy to happen in the host endianness. */ 2224 tcg_gen_qemu_ld_i32(tmp, saddr, da.mem_idx, MO_UL); 2225 tcg_gen_qemu_st_i32(tmp, daddr, da.mem_idx, MO_UL); 2226 tcg_gen_add_tl(saddr, saddr, four); 2227 tcg_gen_add_tl(daddr, daddr, four); 2228 } 2229 } 2230 break; 2231 #endif 2232 default: 2233 { 2234 TCGv_i32 r_asi = tcg_constant_i32(da.asi); 2235 TCGv_i32 r_mop = tcg_constant_i32(memop | MO_ALIGN); 2236 2237 save_state(dc); 2238 #ifdef TARGET_SPARC64 2239 gen_helper_st_asi(cpu_env, addr, src, r_asi, r_mop); 2240 #else 2241 { 2242 TCGv_i64 t64 = tcg_temp_new_i64(); 2243 tcg_gen_extu_tl_i64(t64, src); 2244 gen_helper_st_asi(cpu_env, addr, t64, r_asi, r_mop); 2245 } 2246 #endif 2247 2248 /* A write to a TLB register may alter page maps. End the TB. */ 2249 dc->npc = DYNAMIC_PC; 2250 } 2251 break; 2252 } 2253 } 2254 2255 static void gen_swap_asi(DisasContext *dc, TCGv dst, TCGv src, 2256 TCGv addr, int insn) 2257 { 2258 DisasASI da = get_asi(dc, insn, MO_TEUL); 2259 2260 switch (da.type) { 2261 case GET_ASI_EXCP: 2262 break; 2263 case GET_ASI_DIRECT: 2264 gen_swap(dc, dst, src, addr, da.mem_idx, da.memop); 2265 break; 2266 default: 2267 /* ??? Should be DAE_invalid_asi. */ 2268 gen_exception(dc, TT_DATA_ACCESS); 2269 break; 2270 } 2271 } 2272 2273 static void gen_cas_asi(DisasContext *dc, TCGv addr, TCGv cmpv, 2274 int insn, int rd) 2275 { 2276 DisasASI da = get_asi(dc, insn, MO_TEUL); 2277 TCGv oldv; 2278 2279 switch (da.type) { 2280 case GET_ASI_EXCP: 2281 return; 2282 case GET_ASI_DIRECT: 2283 oldv = tcg_temp_new(); 2284 tcg_gen_atomic_cmpxchg_tl(oldv, addr, cmpv, gen_load_gpr(dc, rd), 2285 da.mem_idx, da.memop | MO_ALIGN); 2286 gen_store_gpr(dc, rd, oldv); 2287 break; 2288 default: 2289 /* ??? Should be DAE_invalid_asi. */ 2290 gen_exception(dc, TT_DATA_ACCESS); 2291 break; 2292 } 2293 } 2294 2295 static void gen_ldstub_asi(DisasContext *dc, TCGv dst, TCGv addr, int insn) 2296 { 2297 DisasASI da = get_asi(dc, insn, MO_UB); 2298 2299 switch (da.type) { 2300 case GET_ASI_EXCP: 2301 break; 2302 case GET_ASI_DIRECT: 2303 gen_ldstub(dc, dst, addr, da.mem_idx); 2304 break; 2305 default: 2306 /* ??? In theory, this should be raise DAE_invalid_asi. 2307 But the SS-20 roms do ldstuba [%l0] #ASI_M_CTL, %o1. */ 2308 if (tb_cflags(dc->base.tb) & CF_PARALLEL) { 2309 gen_helper_exit_atomic(cpu_env); 2310 } else { 2311 TCGv_i32 r_asi = tcg_constant_i32(da.asi); 2312 TCGv_i32 r_mop = tcg_constant_i32(MO_UB); 2313 TCGv_i64 s64, t64; 2314 2315 save_state(dc); 2316 t64 = tcg_temp_new_i64(); 2317 gen_helper_ld_asi(t64, cpu_env, addr, r_asi, r_mop); 2318 2319 s64 = tcg_constant_i64(0xff); 2320 gen_helper_st_asi(cpu_env, addr, s64, r_asi, r_mop); 2321 2322 tcg_gen_trunc_i64_tl(dst, t64); 2323 2324 /* End the TB. */ 2325 dc->npc = DYNAMIC_PC; 2326 } 2327 break; 2328 } 2329 } 2330 #endif 2331 2332 #ifdef TARGET_SPARC64 2333 static void gen_ldf_asi(DisasContext *dc, TCGv addr, 2334 int insn, int size, int rd) 2335 { 2336 DisasASI da = get_asi(dc, insn, (size == 4 ? MO_TEUL : MO_TEUQ)); 2337 TCGv_i32 d32; 2338 TCGv_i64 d64; 2339 2340 switch (da.type) { 2341 case GET_ASI_EXCP: 2342 break; 2343 2344 case GET_ASI_DIRECT: 2345 gen_address_mask(dc, addr); 2346 switch (size) { 2347 case 4: 2348 d32 = gen_dest_fpr_F(dc); 2349 tcg_gen_qemu_ld_i32(d32, addr, da.mem_idx, da.memop | MO_ALIGN); 2350 gen_store_fpr_F(dc, rd, d32); 2351 break; 2352 case 8: 2353 tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2], addr, da.mem_idx, 2354 da.memop | MO_ALIGN_4); 2355 break; 2356 case 16: 2357 d64 = tcg_temp_new_i64(); 2358 tcg_gen_qemu_ld_i64(d64, addr, da.mem_idx, da.memop | MO_ALIGN_4); 2359 tcg_gen_addi_tl(addr, addr, 8); 2360 tcg_gen_qemu_ld_i64(cpu_fpr[rd/2+1], addr, da.mem_idx, 2361 da.memop | MO_ALIGN_4); 2362 tcg_gen_mov_i64(cpu_fpr[rd / 2], d64); 2363 break; 2364 default: 2365 g_assert_not_reached(); 2366 } 2367 break; 2368 2369 case GET_ASI_BLOCK: 2370 /* Valid for lddfa on aligned registers only. */ 2371 if (size == 8 && (rd & 7) == 0) { 2372 MemOp memop; 2373 TCGv eight; 2374 int i; 2375 2376 gen_address_mask(dc, addr); 2377 2378 /* The first operation checks required alignment. */ 2379 memop = da.memop | MO_ALIGN_64; 2380 eight = tcg_constant_tl(8); 2381 for (i = 0; ; ++i) { 2382 tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2 + i], addr, 2383 da.mem_idx, memop); 2384 if (i == 7) { 2385 break; 2386 } 2387 tcg_gen_add_tl(addr, addr, eight); 2388 memop = da.memop; 2389 } 2390 } else { 2391 gen_exception(dc, TT_ILL_INSN); 2392 } 2393 break; 2394 2395 case GET_ASI_SHORT: 2396 /* Valid for lddfa only. */ 2397 if (size == 8) { 2398 gen_address_mask(dc, addr); 2399 tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2], addr, da.mem_idx, 2400 da.memop | MO_ALIGN); 2401 } else { 2402 gen_exception(dc, TT_ILL_INSN); 2403 } 2404 break; 2405 2406 default: 2407 { 2408 TCGv_i32 r_asi = tcg_constant_i32(da.asi); 2409 TCGv_i32 r_mop = tcg_constant_i32(da.memop | MO_ALIGN); 2410 2411 save_state(dc); 2412 /* According to the table in the UA2011 manual, the only 2413 other asis that are valid for ldfa/lddfa/ldqfa are 2414 the NO_FAULT asis. We still need a helper for these, 2415 but we can just use the integer asi helper for them. */ 2416 switch (size) { 2417 case 4: 2418 d64 = tcg_temp_new_i64(); 2419 gen_helper_ld_asi(d64, cpu_env, addr, r_asi, r_mop); 2420 d32 = gen_dest_fpr_F(dc); 2421 tcg_gen_extrl_i64_i32(d32, d64); 2422 gen_store_fpr_F(dc, rd, d32); 2423 break; 2424 case 8: 2425 gen_helper_ld_asi(cpu_fpr[rd / 2], cpu_env, addr, r_asi, r_mop); 2426 break; 2427 case 16: 2428 d64 = tcg_temp_new_i64(); 2429 gen_helper_ld_asi(d64, cpu_env, addr, r_asi, r_mop); 2430 tcg_gen_addi_tl(addr, addr, 8); 2431 gen_helper_ld_asi(cpu_fpr[rd/2+1], cpu_env, addr, r_asi, r_mop); 2432 tcg_gen_mov_i64(cpu_fpr[rd / 2], d64); 2433 break; 2434 default: 2435 g_assert_not_reached(); 2436 } 2437 } 2438 break; 2439 } 2440 } 2441 2442 static void gen_stf_asi(DisasContext *dc, TCGv addr, 2443 int insn, int size, int rd) 2444 { 2445 DisasASI da = get_asi(dc, insn, (size == 4 ? MO_TEUL : MO_TEUQ)); 2446 TCGv_i32 d32; 2447 2448 switch (da.type) { 2449 case GET_ASI_EXCP: 2450 break; 2451 2452 case GET_ASI_DIRECT: 2453 gen_address_mask(dc, addr); 2454 switch (size) { 2455 case 4: 2456 d32 = gen_load_fpr_F(dc, rd); 2457 tcg_gen_qemu_st_i32(d32, addr, da.mem_idx, da.memop | MO_ALIGN); 2458 break; 2459 case 8: 2460 tcg_gen_qemu_st_i64(cpu_fpr[rd / 2], addr, da.mem_idx, 2461 da.memop | MO_ALIGN_4); 2462 break; 2463 case 16: 2464 /* Only 4-byte alignment required. However, it is legal for the 2465 cpu to signal the alignment fault, and the OS trap handler is 2466 required to fix it up. Requiring 16-byte alignment here avoids 2467 having to probe the second page before performing the first 2468 write. */ 2469 tcg_gen_qemu_st_i64(cpu_fpr[rd / 2], addr, da.mem_idx, 2470 da.memop | MO_ALIGN_16); 2471 tcg_gen_addi_tl(addr, addr, 8); 2472 tcg_gen_qemu_st_i64(cpu_fpr[rd/2+1], addr, da.mem_idx, da.memop); 2473 break; 2474 default: 2475 g_assert_not_reached(); 2476 } 2477 break; 2478 2479 case GET_ASI_BLOCK: 2480 /* Valid for stdfa on aligned registers only. */ 2481 if (size == 8 && (rd & 7) == 0) { 2482 MemOp memop; 2483 TCGv eight; 2484 int i; 2485 2486 gen_address_mask(dc, addr); 2487 2488 /* The first operation checks required alignment. */ 2489 memop = da.memop | MO_ALIGN_64; 2490 eight = tcg_constant_tl(8); 2491 for (i = 0; ; ++i) { 2492 tcg_gen_qemu_st_i64(cpu_fpr[rd / 2 + i], addr, 2493 da.mem_idx, memop); 2494 if (i == 7) { 2495 break; 2496 } 2497 tcg_gen_add_tl(addr, addr, eight); 2498 memop = da.memop; 2499 } 2500 } else { 2501 gen_exception(dc, TT_ILL_INSN); 2502 } 2503 break; 2504 2505 case GET_ASI_SHORT: 2506 /* Valid for stdfa only. */ 2507 if (size == 8) { 2508 gen_address_mask(dc, addr); 2509 tcg_gen_qemu_st_i64(cpu_fpr[rd / 2], addr, da.mem_idx, 2510 da.memop | MO_ALIGN); 2511 } else { 2512 gen_exception(dc, TT_ILL_INSN); 2513 } 2514 break; 2515 2516 default: 2517 /* According to the table in the UA2011 manual, the only 2518 other asis that are valid for ldfa/lddfa/ldqfa are 2519 the PST* asis, which aren't currently handled. */ 2520 gen_exception(dc, TT_ILL_INSN); 2521 break; 2522 } 2523 } 2524 2525 static void gen_ldda_asi(DisasContext *dc, TCGv addr, int insn, int rd) 2526 { 2527 DisasASI da = get_asi(dc, insn, MO_TEUQ); 2528 TCGv_i64 hi = gen_dest_gpr(dc, rd); 2529 TCGv_i64 lo = gen_dest_gpr(dc, rd + 1); 2530 2531 switch (da.type) { 2532 case GET_ASI_EXCP: 2533 return; 2534 2535 case GET_ASI_DTWINX: 2536 gen_address_mask(dc, addr); 2537 tcg_gen_qemu_ld_i64(hi, addr, da.mem_idx, da.memop | MO_ALIGN_16); 2538 tcg_gen_addi_tl(addr, addr, 8); 2539 tcg_gen_qemu_ld_i64(lo, addr, da.mem_idx, da.memop); 2540 break; 2541 2542 case GET_ASI_DIRECT: 2543 { 2544 TCGv_i64 tmp = tcg_temp_new_i64(); 2545 2546 gen_address_mask(dc, addr); 2547 tcg_gen_qemu_ld_i64(tmp, addr, da.mem_idx, da.memop | MO_ALIGN); 2548 2549 /* Note that LE ldda acts as if each 32-bit register 2550 result is byte swapped. Having just performed one 2551 64-bit bswap, we need now to swap the writebacks. */ 2552 if ((da.memop & MO_BSWAP) == MO_TE) { 2553 tcg_gen_extr32_i64(lo, hi, tmp); 2554 } else { 2555 tcg_gen_extr32_i64(hi, lo, tmp); 2556 } 2557 } 2558 break; 2559 2560 default: 2561 /* ??? In theory we've handled all of the ASIs that are valid 2562 for ldda, and this should raise DAE_invalid_asi. However, 2563 real hardware allows others. This can be seen with e.g. 2564 FreeBSD 10.3 wrt ASI_IC_TAG. */ 2565 { 2566 TCGv_i32 r_asi = tcg_constant_i32(da.asi); 2567 TCGv_i32 r_mop = tcg_constant_i32(da.memop); 2568 TCGv_i64 tmp = tcg_temp_new_i64(); 2569 2570 save_state(dc); 2571 gen_helper_ld_asi(tmp, cpu_env, addr, r_asi, r_mop); 2572 2573 /* See above. */ 2574 if ((da.memop & MO_BSWAP) == MO_TE) { 2575 tcg_gen_extr32_i64(lo, hi, tmp); 2576 } else { 2577 tcg_gen_extr32_i64(hi, lo, tmp); 2578 } 2579 } 2580 break; 2581 } 2582 2583 gen_store_gpr(dc, rd, hi); 2584 gen_store_gpr(dc, rd + 1, lo); 2585 } 2586 2587 static void gen_stda_asi(DisasContext *dc, TCGv hi, TCGv addr, 2588 int insn, int rd) 2589 { 2590 DisasASI da = get_asi(dc, insn, MO_TEUQ); 2591 TCGv lo = gen_load_gpr(dc, rd + 1); 2592 2593 switch (da.type) { 2594 case GET_ASI_EXCP: 2595 break; 2596 2597 case GET_ASI_DTWINX: 2598 gen_address_mask(dc, addr); 2599 tcg_gen_qemu_st_i64(hi, addr, da.mem_idx, da.memop | MO_ALIGN_16); 2600 tcg_gen_addi_tl(addr, addr, 8); 2601 tcg_gen_qemu_st_i64(lo, addr, da.mem_idx, da.memop); 2602 break; 2603 2604 case GET_ASI_DIRECT: 2605 { 2606 TCGv_i64 t64 = tcg_temp_new_i64(); 2607 2608 /* Note that LE stda acts as if each 32-bit register result is 2609 byte swapped. We will perform one 64-bit LE store, so now 2610 we must swap the order of the construction. */ 2611 if ((da.memop & MO_BSWAP) == MO_TE) { 2612 tcg_gen_concat32_i64(t64, lo, hi); 2613 } else { 2614 tcg_gen_concat32_i64(t64, hi, lo); 2615 } 2616 gen_address_mask(dc, addr); 2617 tcg_gen_qemu_st_i64(t64, addr, da.mem_idx, da.memop | MO_ALIGN); 2618 } 2619 break; 2620 2621 default: 2622 /* ??? In theory we've handled all of the ASIs that are valid 2623 for stda, and this should raise DAE_invalid_asi. */ 2624 { 2625 TCGv_i32 r_asi = tcg_constant_i32(da.asi); 2626 TCGv_i32 r_mop = tcg_constant_i32(da.memop); 2627 TCGv_i64 t64 = tcg_temp_new_i64(); 2628 2629 /* See above. */ 2630 if ((da.memop & MO_BSWAP) == MO_TE) { 2631 tcg_gen_concat32_i64(t64, lo, hi); 2632 } else { 2633 tcg_gen_concat32_i64(t64, hi, lo); 2634 } 2635 2636 save_state(dc); 2637 gen_helper_st_asi(cpu_env, addr, t64, r_asi, r_mop); 2638 } 2639 break; 2640 } 2641 } 2642 2643 static void gen_casx_asi(DisasContext *dc, TCGv addr, TCGv cmpv, 2644 int insn, int rd) 2645 { 2646 DisasASI da = get_asi(dc, insn, MO_TEUQ); 2647 TCGv oldv; 2648 2649 switch (da.type) { 2650 case GET_ASI_EXCP: 2651 return; 2652 case GET_ASI_DIRECT: 2653 oldv = tcg_temp_new(); 2654 tcg_gen_atomic_cmpxchg_tl(oldv, addr, cmpv, gen_load_gpr(dc, rd), 2655 da.mem_idx, da.memop | MO_ALIGN); 2656 gen_store_gpr(dc, rd, oldv); 2657 break; 2658 default: 2659 /* ??? Should be DAE_invalid_asi. */ 2660 gen_exception(dc, TT_DATA_ACCESS); 2661 break; 2662 } 2663 } 2664 2665 #elif !defined(CONFIG_USER_ONLY) 2666 static void gen_ldda_asi(DisasContext *dc, TCGv addr, int insn, int rd) 2667 { 2668 /* ??? Work around an apparent bug in Ubuntu gcc 4.8.2-10ubuntu2+12, 2669 whereby "rd + 1" elicits "error: array subscript is above array". 2670 Since we have already asserted that rd is even, the semantics 2671 are unchanged. */ 2672 TCGv lo = gen_dest_gpr(dc, rd | 1); 2673 TCGv hi = gen_dest_gpr(dc, rd); 2674 TCGv_i64 t64 = tcg_temp_new_i64(); 2675 DisasASI da = get_asi(dc, insn, MO_TEUQ); 2676 2677 switch (da.type) { 2678 case GET_ASI_EXCP: 2679 return; 2680 case GET_ASI_DIRECT: 2681 gen_address_mask(dc, addr); 2682 tcg_gen_qemu_ld_i64(t64, addr, da.mem_idx, da.memop | MO_ALIGN); 2683 break; 2684 default: 2685 { 2686 TCGv_i32 r_asi = tcg_constant_i32(da.asi); 2687 TCGv_i32 r_mop = tcg_constant_i32(MO_UQ); 2688 2689 save_state(dc); 2690 gen_helper_ld_asi(t64, cpu_env, addr, r_asi, r_mop); 2691 } 2692 break; 2693 } 2694 2695 tcg_gen_extr_i64_i32(lo, hi, t64); 2696 gen_store_gpr(dc, rd | 1, lo); 2697 gen_store_gpr(dc, rd, hi); 2698 } 2699 2700 static void gen_stda_asi(DisasContext *dc, TCGv hi, TCGv addr, 2701 int insn, int rd) 2702 { 2703 DisasASI da = get_asi(dc, insn, MO_TEUQ); 2704 TCGv lo = gen_load_gpr(dc, rd + 1); 2705 TCGv_i64 t64 = tcg_temp_new_i64(); 2706 2707 tcg_gen_concat_tl_i64(t64, lo, hi); 2708 2709 switch (da.type) { 2710 case GET_ASI_EXCP: 2711 break; 2712 case GET_ASI_DIRECT: 2713 gen_address_mask(dc, addr); 2714 tcg_gen_qemu_st_i64(t64, addr, da.mem_idx, da.memop | MO_ALIGN); 2715 break; 2716 case GET_ASI_BFILL: 2717 /* Store 32 bytes of T64 to ADDR. */ 2718 /* ??? The original qemu code suggests 8-byte alignment, dropping 2719 the low bits, but the only place I can see this used is in the 2720 Linux kernel with 32 byte alignment, which would make more sense 2721 as a cacheline-style operation. */ 2722 { 2723 TCGv d_addr = tcg_temp_new(); 2724 TCGv eight = tcg_constant_tl(8); 2725 int i; 2726 2727 tcg_gen_andi_tl(d_addr, addr, -8); 2728 for (i = 0; i < 32; i += 8) { 2729 tcg_gen_qemu_st_i64(t64, d_addr, da.mem_idx, da.memop); 2730 tcg_gen_add_tl(d_addr, d_addr, eight); 2731 } 2732 } 2733 break; 2734 default: 2735 { 2736 TCGv_i32 r_asi = tcg_constant_i32(da.asi); 2737 TCGv_i32 r_mop = tcg_constant_i32(MO_UQ); 2738 2739 save_state(dc); 2740 gen_helper_st_asi(cpu_env, addr, t64, r_asi, r_mop); 2741 } 2742 break; 2743 } 2744 } 2745 #endif 2746 2747 static TCGv get_src1(DisasContext *dc, unsigned int insn) 2748 { 2749 unsigned int rs1 = GET_FIELD(insn, 13, 17); 2750 return gen_load_gpr(dc, rs1); 2751 } 2752 2753 static TCGv get_src2(DisasContext *dc, unsigned int insn) 2754 { 2755 if (IS_IMM) { /* immediate */ 2756 target_long simm = GET_FIELDs(insn, 19, 31); 2757 TCGv t = tcg_temp_new(); 2758 tcg_gen_movi_tl(t, simm); 2759 return t; 2760 } else { /* register */ 2761 unsigned int rs2 = GET_FIELD(insn, 27, 31); 2762 return gen_load_gpr(dc, rs2); 2763 } 2764 } 2765 2766 #ifdef TARGET_SPARC64 2767 static void gen_fmovs(DisasContext *dc, DisasCompare *cmp, int rd, int rs) 2768 { 2769 TCGv_i32 c32, zero, dst, s1, s2; 2770 2771 /* We have two choices here: extend the 32 bit data and use movcond_i64, 2772 or fold the comparison down to 32 bits and use movcond_i32. Choose 2773 the later. */ 2774 c32 = tcg_temp_new_i32(); 2775 if (cmp->is_bool) { 2776 tcg_gen_extrl_i64_i32(c32, cmp->c1); 2777 } else { 2778 TCGv_i64 c64 = tcg_temp_new_i64(); 2779 tcg_gen_setcond_i64(cmp->cond, c64, cmp->c1, cmp->c2); 2780 tcg_gen_extrl_i64_i32(c32, c64); 2781 } 2782 2783 s1 = gen_load_fpr_F(dc, rs); 2784 s2 = gen_load_fpr_F(dc, rd); 2785 dst = gen_dest_fpr_F(dc); 2786 zero = tcg_constant_i32(0); 2787 2788 tcg_gen_movcond_i32(TCG_COND_NE, dst, c32, zero, s1, s2); 2789 2790 gen_store_fpr_F(dc, rd, dst); 2791 } 2792 2793 static void gen_fmovd(DisasContext *dc, DisasCompare *cmp, int rd, int rs) 2794 { 2795 TCGv_i64 dst = gen_dest_fpr_D(dc, rd); 2796 tcg_gen_movcond_i64(cmp->cond, dst, cmp->c1, cmp->c2, 2797 gen_load_fpr_D(dc, rs), 2798 gen_load_fpr_D(dc, rd)); 2799 gen_store_fpr_D(dc, rd, dst); 2800 } 2801 2802 static void gen_fmovq(DisasContext *dc, DisasCompare *cmp, int rd, int rs) 2803 { 2804 int qd = QFPREG(rd); 2805 int qs = QFPREG(rs); 2806 2807 tcg_gen_movcond_i64(cmp->cond, cpu_fpr[qd / 2], cmp->c1, cmp->c2, 2808 cpu_fpr[qs / 2], cpu_fpr[qd / 2]); 2809 tcg_gen_movcond_i64(cmp->cond, cpu_fpr[qd / 2 + 1], cmp->c1, cmp->c2, 2810 cpu_fpr[qs / 2 + 1], cpu_fpr[qd / 2 + 1]); 2811 2812 gen_update_fprs_dirty(dc, qd); 2813 } 2814 2815 #ifndef CONFIG_USER_ONLY 2816 static inline void gen_load_trap_state_at_tl(TCGv_ptr r_tsptr, TCGv_env cpu_env) 2817 { 2818 TCGv_i32 r_tl = tcg_temp_new_i32(); 2819 2820 /* load env->tl into r_tl */ 2821 tcg_gen_ld_i32(r_tl, cpu_env, offsetof(CPUSPARCState, tl)); 2822 2823 /* tl = [0 ... MAXTL_MASK] where MAXTL_MASK must be power of 2 */ 2824 tcg_gen_andi_i32(r_tl, r_tl, MAXTL_MASK); 2825 2826 /* calculate offset to current trap state from env->ts, reuse r_tl */ 2827 tcg_gen_muli_i32(r_tl, r_tl, sizeof (trap_state)); 2828 tcg_gen_addi_ptr(r_tsptr, cpu_env, offsetof(CPUSPARCState, ts)); 2829 2830 /* tsptr = env->ts[env->tl & MAXTL_MASK] */ 2831 { 2832 TCGv_ptr r_tl_tmp = tcg_temp_new_ptr(); 2833 tcg_gen_ext_i32_ptr(r_tl_tmp, r_tl); 2834 tcg_gen_add_ptr(r_tsptr, r_tsptr, r_tl_tmp); 2835 } 2836 } 2837 #endif 2838 2839 static void gen_edge(DisasContext *dc, TCGv dst, TCGv s1, TCGv s2, 2840 int width, bool cc, bool left) 2841 { 2842 TCGv lo1, lo2; 2843 uint64_t amask, tabl, tabr; 2844 int shift, imask, omask; 2845 2846 if (cc) { 2847 tcg_gen_mov_tl(cpu_cc_src, s1); 2848 tcg_gen_mov_tl(cpu_cc_src2, s2); 2849 tcg_gen_sub_tl(cpu_cc_dst, s1, s2); 2850 tcg_gen_movi_i32(cpu_cc_op, CC_OP_SUB); 2851 dc->cc_op = CC_OP_SUB; 2852 } 2853 2854 /* Theory of operation: there are two tables, left and right (not to 2855 be confused with the left and right versions of the opcode). These 2856 are indexed by the low 3 bits of the inputs. To make things "easy", 2857 these tables are loaded into two constants, TABL and TABR below. 2858 The operation index = (input & imask) << shift calculates the index 2859 into the constant, while val = (table >> index) & omask calculates 2860 the value we're looking for. */ 2861 switch (width) { 2862 case 8: 2863 imask = 0x7; 2864 shift = 3; 2865 omask = 0xff; 2866 if (left) { 2867 tabl = 0x80c0e0f0f8fcfeffULL; 2868 tabr = 0xff7f3f1f0f070301ULL; 2869 } else { 2870 tabl = 0x0103070f1f3f7fffULL; 2871 tabr = 0xfffefcf8f0e0c080ULL; 2872 } 2873 break; 2874 case 16: 2875 imask = 0x6; 2876 shift = 1; 2877 omask = 0xf; 2878 if (left) { 2879 tabl = 0x8cef; 2880 tabr = 0xf731; 2881 } else { 2882 tabl = 0x137f; 2883 tabr = 0xfec8; 2884 } 2885 break; 2886 case 32: 2887 imask = 0x4; 2888 shift = 0; 2889 omask = 0x3; 2890 if (left) { 2891 tabl = (2 << 2) | 3; 2892 tabr = (3 << 2) | 1; 2893 } else { 2894 tabl = (1 << 2) | 3; 2895 tabr = (3 << 2) | 2; 2896 } 2897 break; 2898 default: 2899 abort(); 2900 } 2901 2902 lo1 = tcg_temp_new(); 2903 lo2 = tcg_temp_new(); 2904 tcg_gen_andi_tl(lo1, s1, imask); 2905 tcg_gen_andi_tl(lo2, s2, imask); 2906 tcg_gen_shli_tl(lo1, lo1, shift); 2907 tcg_gen_shli_tl(lo2, lo2, shift); 2908 2909 tcg_gen_shr_tl(lo1, tcg_constant_tl(tabl), lo1); 2910 tcg_gen_shr_tl(lo2, tcg_constant_tl(tabr), lo2); 2911 tcg_gen_andi_tl(dst, lo1, omask); 2912 tcg_gen_andi_tl(lo2, lo2, omask); 2913 2914 amask = -8; 2915 if (AM_CHECK(dc)) { 2916 amask &= 0xffffffffULL; 2917 } 2918 tcg_gen_andi_tl(s1, s1, amask); 2919 tcg_gen_andi_tl(s2, s2, amask); 2920 2921 /* We want to compute 2922 dst = (s1 == s2 ? lo1 : lo1 & lo2). 2923 We've already done dst = lo1, so this reduces to 2924 dst &= (s1 == s2 ? -1 : lo2) 2925 Which we perform by 2926 lo2 |= -(s1 == s2) 2927 dst &= lo2 2928 */ 2929 tcg_gen_setcond_tl(TCG_COND_EQ, lo1, s1, s2); 2930 tcg_gen_neg_tl(lo1, lo1); 2931 tcg_gen_or_tl(lo2, lo2, lo1); 2932 tcg_gen_and_tl(dst, dst, lo2); 2933 } 2934 2935 static void gen_alignaddr(TCGv dst, TCGv s1, TCGv s2, bool left) 2936 { 2937 TCGv tmp = tcg_temp_new(); 2938 2939 tcg_gen_add_tl(tmp, s1, s2); 2940 tcg_gen_andi_tl(dst, tmp, -8); 2941 if (left) { 2942 tcg_gen_neg_tl(tmp, tmp); 2943 } 2944 tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, tmp, 0, 3); 2945 } 2946 2947 static void gen_faligndata(TCGv dst, TCGv gsr, TCGv s1, TCGv s2) 2948 { 2949 TCGv t1, t2, shift; 2950 2951 t1 = tcg_temp_new(); 2952 t2 = tcg_temp_new(); 2953 shift = tcg_temp_new(); 2954 2955 tcg_gen_andi_tl(shift, gsr, 7); 2956 tcg_gen_shli_tl(shift, shift, 3); 2957 tcg_gen_shl_tl(t1, s1, shift); 2958 2959 /* A shift of 64 does not produce 0 in TCG. Divide this into a 2960 shift of (up to 63) followed by a constant shift of 1. */ 2961 tcg_gen_xori_tl(shift, shift, 63); 2962 tcg_gen_shr_tl(t2, s2, shift); 2963 tcg_gen_shri_tl(t2, t2, 1); 2964 2965 tcg_gen_or_tl(dst, t1, t2); 2966 } 2967 #endif 2968 2969 #define CHECK_IU_FEATURE(dc, FEATURE) \ 2970 if (!((dc)->def->features & CPU_FEATURE_ ## FEATURE)) \ 2971 goto illegal_insn; 2972 #define CHECK_FPU_FEATURE(dc, FEATURE) \ 2973 if (!((dc)->def->features & CPU_FEATURE_ ## FEATURE)) \ 2974 goto nfpu_insn; 2975 2976 /* before an instruction, dc->pc must be static */ 2977 static void disas_sparc_insn(DisasContext * dc, unsigned int insn) 2978 { 2979 unsigned int opc, rs1, rs2, rd; 2980 TCGv cpu_src1, cpu_src2; 2981 TCGv_i32 cpu_src1_32, cpu_src2_32, cpu_dst_32; 2982 TCGv_i64 cpu_src1_64, cpu_src2_64, cpu_dst_64; 2983 target_long simm; 2984 2985 opc = GET_FIELD(insn, 0, 1); 2986 rd = GET_FIELD(insn, 2, 6); 2987 2988 switch (opc) { 2989 case 0: /* branches/sethi */ 2990 { 2991 unsigned int xop = GET_FIELD(insn, 7, 9); 2992 int32_t target; 2993 switch (xop) { 2994 #ifdef TARGET_SPARC64 2995 case 0x1: /* V9 BPcc */ 2996 { 2997 int cc; 2998 2999 target = GET_FIELD_SP(insn, 0, 18); 3000 target = sign_extend(target, 19); 3001 target <<= 2; 3002 cc = GET_FIELD_SP(insn, 20, 21); 3003 if (cc == 0) 3004 do_branch(dc, target, insn, 0); 3005 else if (cc == 2) 3006 do_branch(dc, target, insn, 1); 3007 else 3008 goto illegal_insn; 3009 goto jmp_insn; 3010 } 3011 case 0x3: /* V9 BPr */ 3012 { 3013 target = GET_FIELD_SP(insn, 0, 13) | 3014 (GET_FIELD_SP(insn, 20, 21) << 14); 3015 target = sign_extend(target, 16); 3016 target <<= 2; 3017 cpu_src1 = get_src1(dc, insn); 3018 do_branch_reg(dc, target, insn, cpu_src1); 3019 goto jmp_insn; 3020 } 3021 case 0x5: /* V9 FBPcc */ 3022 { 3023 int cc = GET_FIELD_SP(insn, 20, 21); 3024 if (gen_trap_ifnofpu(dc)) { 3025 goto jmp_insn; 3026 } 3027 target = GET_FIELD_SP(insn, 0, 18); 3028 target = sign_extend(target, 19); 3029 target <<= 2; 3030 do_fbranch(dc, target, insn, cc); 3031 goto jmp_insn; 3032 } 3033 #else 3034 case 0x7: /* CBN+x */ 3035 { 3036 goto ncp_insn; 3037 } 3038 #endif 3039 case 0x2: /* BN+x */ 3040 { 3041 target = GET_FIELD(insn, 10, 31); 3042 target = sign_extend(target, 22); 3043 target <<= 2; 3044 do_branch(dc, target, insn, 0); 3045 goto jmp_insn; 3046 } 3047 case 0x6: /* FBN+x */ 3048 { 3049 if (gen_trap_ifnofpu(dc)) { 3050 goto jmp_insn; 3051 } 3052 target = GET_FIELD(insn, 10, 31); 3053 target = sign_extend(target, 22); 3054 target <<= 2; 3055 do_fbranch(dc, target, insn, 0); 3056 goto jmp_insn; 3057 } 3058 case 0x4: /* SETHI */ 3059 /* Special-case %g0 because that's the canonical nop. */ 3060 if (rd) { 3061 uint32_t value = GET_FIELD(insn, 10, 31); 3062 TCGv t = gen_dest_gpr(dc, rd); 3063 tcg_gen_movi_tl(t, value << 10); 3064 gen_store_gpr(dc, rd, t); 3065 } 3066 break; 3067 case 0x0: /* UNIMPL */ 3068 default: 3069 goto illegal_insn; 3070 } 3071 break; 3072 } 3073 break; 3074 case 1: /*CALL*/ 3075 { 3076 target_long target = GET_FIELDs(insn, 2, 31) << 2; 3077 TCGv o7 = gen_dest_gpr(dc, 15); 3078 3079 tcg_gen_movi_tl(o7, dc->pc); 3080 gen_store_gpr(dc, 15, o7); 3081 target += dc->pc; 3082 gen_mov_pc_npc(dc); 3083 #ifdef TARGET_SPARC64 3084 if (unlikely(AM_CHECK(dc))) { 3085 target &= 0xffffffffULL; 3086 } 3087 #endif 3088 dc->npc = target; 3089 } 3090 goto jmp_insn; 3091 case 2: /* FPU & Logical Operations */ 3092 { 3093 unsigned int xop = GET_FIELD(insn, 7, 12); 3094 TCGv cpu_dst = tcg_temp_new(); 3095 TCGv cpu_tmp0; 3096 3097 if (xop == 0x3a) { /* generate trap */ 3098 int cond = GET_FIELD(insn, 3, 6); 3099 TCGv_i32 trap; 3100 TCGLabel *l1 = NULL; 3101 int mask; 3102 3103 if (cond == 0) { 3104 /* Trap never. */ 3105 break; 3106 } 3107 3108 save_state(dc); 3109 3110 if (cond != 8) { 3111 /* Conditional trap. */ 3112 DisasCompare cmp; 3113 #ifdef TARGET_SPARC64 3114 /* V9 icc/xcc */ 3115 int cc = GET_FIELD_SP(insn, 11, 12); 3116 if (cc == 0) { 3117 gen_compare(&cmp, 0, cond, dc); 3118 } else if (cc == 2) { 3119 gen_compare(&cmp, 1, cond, dc); 3120 } else { 3121 goto illegal_insn; 3122 } 3123 #else 3124 gen_compare(&cmp, 0, cond, dc); 3125 #endif 3126 l1 = gen_new_label(); 3127 tcg_gen_brcond_tl(tcg_invert_cond(cmp.cond), 3128 cmp.c1, cmp.c2, l1); 3129 } 3130 3131 mask = ((dc->def->features & CPU_FEATURE_HYPV) && supervisor(dc) 3132 ? UA2005_HTRAP_MASK : V8_TRAP_MASK); 3133 3134 /* Don't use the normal temporaries, as they may well have 3135 gone out of scope with the branch above. While we're 3136 doing that we might as well pre-truncate to 32-bit. */ 3137 trap = tcg_temp_new_i32(); 3138 3139 rs1 = GET_FIELD_SP(insn, 14, 18); 3140 if (IS_IMM) { 3141 rs2 = GET_FIELD_SP(insn, 0, 7); 3142 if (rs1 == 0) { 3143 tcg_gen_movi_i32(trap, (rs2 & mask) + TT_TRAP); 3144 /* Signal that the trap value is fully constant. */ 3145 mask = 0; 3146 } else { 3147 TCGv t1 = gen_load_gpr(dc, rs1); 3148 tcg_gen_trunc_tl_i32(trap, t1); 3149 tcg_gen_addi_i32(trap, trap, rs2); 3150 } 3151 } else { 3152 TCGv t1, t2; 3153 rs2 = GET_FIELD_SP(insn, 0, 4); 3154 t1 = gen_load_gpr(dc, rs1); 3155 t2 = gen_load_gpr(dc, rs2); 3156 tcg_gen_add_tl(t1, t1, t2); 3157 tcg_gen_trunc_tl_i32(trap, t1); 3158 } 3159 if (mask != 0) { 3160 tcg_gen_andi_i32(trap, trap, mask); 3161 tcg_gen_addi_i32(trap, trap, TT_TRAP); 3162 } 3163 3164 gen_helper_raise_exception(cpu_env, trap); 3165 3166 if (cond == 8) { 3167 /* An unconditional trap ends the TB. */ 3168 dc->base.is_jmp = DISAS_NORETURN; 3169 goto jmp_insn; 3170 } else { 3171 /* A conditional trap falls through to the next insn. */ 3172 gen_set_label(l1); 3173 break; 3174 } 3175 } else if (xop == 0x28) { 3176 rs1 = GET_FIELD(insn, 13, 17); 3177 switch(rs1) { 3178 case 0: /* rdy */ 3179 #ifndef TARGET_SPARC64 3180 case 0x01 ... 0x0e: /* undefined in the SPARCv8 3181 manual, rdy on the microSPARC 3182 II */ 3183 case 0x0f: /* stbar in the SPARCv8 manual, 3184 rdy on the microSPARC II */ 3185 case 0x10 ... 0x1f: /* implementation-dependent in the 3186 SPARCv8 manual, rdy on the 3187 microSPARC II */ 3188 /* Read Asr17 */ 3189 if (rs1 == 0x11 && dc->def->features & CPU_FEATURE_ASR17) { 3190 TCGv t = gen_dest_gpr(dc, rd); 3191 /* Read Asr17 for a Leon3 monoprocessor */ 3192 tcg_gen_movi_tl(t, (1 << 8) | (dc->def->nwindows - 1)); 3193 gen_store_gpr(dc, rd, t); 3194 break; 3195 } 3196 #endif 3197 gen_store_gpr(dc, rd, cpu_y); 3198 break; 3199 #ifdef TARGET_SPARC64 3200 case 0x2: /* V9 rdccr */ 3201 update_psr(dc); 3202 gen_helper_rdccr(cpu_dst, cpu_env); 3203 gen_store_gpr(dc, rd, cpu_dst); 3204 break; 3205 case 0x3: /* V9 rdasi */ 3206 tcg_gen_movi_tl(cpu_dst, dc->asi); 3207 gen_store_gpr(dc, rd, cpu_dst); 3208 break; 3209 case 0x4: /* V9 rdtick */ 3210 { 3211 TCGv_ptr r_tickptr; 3212 TCGv_i32 r_const; 3213 3214 r_tickptr = tcg_temp_new_ptr(); 3215 r_const = tcg_constant_i32(dc->mem_idx); 3216 tcg_gen_ld_ptr(r_tickptr, cpu_env, 3217 offsetof(CPUSPARCState, tick)); 3218 if (translator_io_start(&dc->base)) { 3219 dc->base.is_jmp = DISAS_EXIT; 3220 } 3221 gen_helper_tick_get_count(cpu_dst, cpu_env, r_tickptr, 3222 r_const); 3223 gen_store_gpr(dc, rd, cpu_dst); 3224 } 3225 break; 3226 case 0x5: /* V9 rdpc */ 3227 { 3228 TCGv t = gen_dest_gpr(dc, rd); 3229 if (unlikely(AM_CHECK(dc))) { 3230 tcg_gen_movi_tl(t, dc->pc & 0xffffffffULL); 3231 } else { 3232 tcg_gen_movi_tl(t, dc->pc); 3233 } 3234 gen_store_gpr(dc, rd, t); 3235 } 3236 break; 3237 case 0x6: /* V9 rdfprs */ 3238 tcg_gen_ext_i32_tl(cpu_dst, cpu_fprs); 3239 gen_store_gpr(dc, rd, cpu_dst); 3240 break; 3241 case 0xf: /* V9 membar */ 3242 break; /* no effect */ 3243 case 0x13: /* Graphics Status */ 3244 if (gen_trap_ifnofpu(dc)) { 3245 goto jmp_insn; 3246 } 3247 gen_store_gpr(dc, rd, cpu_gsr); 3248 break; 3249 case 0x16: /* Softint */ 3250 tcg_gen_ld32s_tl(cpu_dst, cpu_env, 3251 offsetof(CPUSPARCState, softint)); 3252 gen_store_gpr(dc, rd, cpu_dst); 3253 break; 3254 case 0x17: /* Tick compare */ 3255 gen_store_gpr(dc, rd, cpu_tick_cmpr); 3256 break; 3257 case 0x18: /* System tick */ 3258 { 3259 TCGv_ptr r_tickptr; 3260 TCGv_i32 r_const; 3261 3262 r_tickptr = tcg_temp_new_ptr(); 3263 r_const = tcg_constant_i32(dc->mem_idx); 3264 tcg_gen_ld_ptr(r_tickptr, cpu_env, 3265 offsetof(CPUSPARCState, stick)); 3266 if (translator_io_start(&dc->base)) { 3267 dc->base.is_jmp = DISAS_EXIT; 3268 } 3269 gen_helper_tick_get_count(cpu_dst, cpu_env, r_tickptr, 3270 r_const); 3271 gen_store_gpr(dc, rd, cpu_dst); 3272 } 3273 break; 3274 case 0x19: /* System tick compare */ 3275 gen_store_gpr(dc, rd, cpu_stick_cmpr); 3276 break; 3277 case 0x1a: /* UltraSPARC-T1 Strand status */ 3278 /* XXX HYPV check maybe not enough, UA2005 & UA2007 describe 3279 * this ASR as impl. dep 3280 */ 3281 CHECK_IU_FEATURE(dc, HYPV); 3282 { 3283 TCGv t = gen_dest_gpr(dc, rd); 3284 tcg_gen_movi_tl(t, 1UL); 3285 gen_store_gpr(dc, rd, t); 3286 } 3287 break; 3288 case 0x10: /* Performance Control */ 3289 case 0x11: /* Performance Instrumentation Counter */ 3290 case 0x12: /* Dispatch Control */ 3291 case 0x14: /* Softint set, WO */ 3292 case 0x15: /* Softint clear, WO */ 3293 #endif 3294 default: 3295 goto illegal_insn; 3296 } 3297 #if !defined(CONFIG_USER_ONLY) 3298 } else if (xop == 0x29) { /* rdpsr / UA2005 rdhpr */ 3299 #ifndef TARGET_SPARC64 3300 if (!supervisor(dc)) { 3301 goto priv_insn; 3302 } 3303 update_psr(dc); 3304 gen_helper_rdpsr(cpu_dst, cpu_env); 3305 #else 3306 CHECK_IU_FEATURE(dc, HYPV); 3307 if (!hypervisor(dc)) 3308 goto priv_insn; 3309 rs1 = GET_FIELD(insn, 13, 17); 3310 switch (rs1) { 3311 case 0: // hpstate 3312 tcg_gen_ld_i64(cpu_dst, cpu_env, 3313 offsetof(CPUSPARCState, hpstate)); 3314 break; 3315 case 1: // htstate 3316 // gen_op_rdhtstate(); 3317 break; 3318 case 3: // hintp 3319 tcg_gen_mov_tl(cpu_dst, cpu_hintp); 3320 break; 3321 case 5: // htba 3322 tcg_gen_mov_tl(cpu_dst, cpu_htba); 3323 break; 3324 case 6: // hver 3325 tcg_gen_mov_tl(cpu_dst, cpu_hver); 3326 break; 3327 case 31: // hstick_cmpr 3328 tcg_gen_mov_tl(cpu_dst, cpu_hstick_cmpr); 3329 break; 3330 default: 3331 goto illegal_insn; 3332 } 3333 #endif 3334 gen_store_gpr(dc, rd, cpu_dst); 3335 break; 3336 } else if (xop == 0x2a) { /* rdwim / V9 rdpr */ 3337 if (!supervisor(dc)) { 3338 goto priv_insn; 3339 } 3340 cpu_tmp0 = tcg_temp_new(); 3341 #ifdef TARGET_SPARC64 3342 rs1 = GET_FIELD(insn, 13, 17); 3343 switch (rs1) { 3344 case 0: // tpc 3345 { 3346 TCGv_ptr r_tsptr; 3347 3348 r_tsptr = tcg_temp_new_ptr(); 3349 gen_load_trap_state_at_tl(r_tsptr, cpu_env); 3350 tcg_gen_ld_tl(cpu_tmp0, r_tsptr, 3351 offsetof(trap_state, tpc)); 3352 } 3353 break; 3354 case 1: // tnpc 3355 { 3356 TCGv_ptr r_tsptr; 3357 3358 r_tsptr = tcg_temp_new_ptr(); 3359 gen_load_trap_state_at_tl(r_tsptr, cpu_env); 3360 tcg_gen_ld_tl(cpu_tmp0, r_tsptr, 3361 offsetof(trap_state, tnpc)); 3362 } 3363 break; 3364 case 2: // tstate 3365 { 3366 TCGv_ptr r_tsptr; 3367 3368 r_tsptr = tcg_temp_new_ptr(); 3369 gen_load_trap_state_at_tl(r_tsptr, cpu_env); 3370 tcg_gen_ld_tl(cpu_tmp0, r_tsptr, 3371 offsetof(trap_state, tstate)); 3372 } 3373 break; 3374 case 3: // tt 3375 { 3376 TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 3377 3378 gen_load_trap_state_at_tl(r_tsptr, cpu_env); 3379 tcg_gen_ld32s_tl(cpu_tmp0, r_tsptr, 3380 offsetof(trap_state, tt)); 3381 } 3382 break; 3383 case 4: // tick 3384 { 3385 TCGv_ptr r_tickptr; 3386 TCGv_i32 r_const; 3387 3388 r_tickptr = tcg_temp_new_ptr(); 3389 r_const = tcg_constant_i32(dc->mem_idx); 3390 tcg_gen_ld_ptr(r_tickptr, cpu_env, 3391 offsetof(CPUSPARCState, tick)); 3392 if (translator_io_start(&dc->base)) { 3393 dc->base.is_jmp = DISAS_EXIT; 3394 } 3395 gen_helper_tick_get_count(cpu_tmp0, cpu_env, 3396 r_tickptr, r_const); 3397 } 3398 break; 3399 case 5: // tba 3400 tcg_gen_mov_tl(cpu_tmp0, cpu_tbr); 3401 break; 3402 case 6: // pstate 3403 tcg_gen_ld32s_tl(cpu_tmp0, cpu_env, 3404 offsetof(CPUSPARCState, pstate)); 3405 break; 3406 case 7: // tl 3407 tcg_gen_ld32s_tl(cpu_tmp0, cpu_env, 3408 offsetof(CPUSPARCState, tl)); 3409 break; 3410 case 8: // pil 3411 tcg_gen_ld32s_tl(cpu_tmp0, cpu_env, 3412 offsetof(CPUSPARCState, psrpil)); 3413 break; 3414 case 9: // cwp 3415 gen_helper_rdcwp(cpu_tmp0, cpu_env); 3416 break; 3417 case 10: // cansave 3418 tcg_gen_ld32s_tl(cpu_tmp0, cpu_env, 3419 offsetof(CPUSPARCState, cansave)); 3420 break; 3421 case 11: // canrestore 3422 tcg_gen_ld32s_tl(cpu_tmp0, cpu_env, 3423 offsetof(CPUSPARCState, canrestore)); 3424 break; 3425 case 12: // cleanwin 3426 tcg_gen_ld32s_tl(cpu_tmp0, cpu_env, 3427 offsetof(CPUSPARCState, cleanwin)); 3428 break; 3429 case 13: // otherwin 3430 tcg_gen_ld32s_tl(cpu_tmp0, cpu_env, 3431 offsetof(CPUSPARCState, otherwin)); 3432 break; 3433 case 14: // wstate 3434 tcg_gen_ld32s_tl(cpu_tmp0, cpu_env, 3435 offsetof(CPUSPARCState, wstate)); 3436 break; 3437 case 16: // UA2005 gl 3438 CHECK_IU_FEATURE(dc, GL); 3439 tcg_gen_ld32s_tl(cpu_tmp0, cpu_env, 3440 offsetof(CPUSPARCState, gl)); 3441 break; 3442 case 26: // UA2005 strand status 3443 CHECK_IU_FEATURE(dc, HYPV); 3444 if (!hypervisor(dc)) 3445 goto priv_insn; 3446 tcg_gen_mov_tl(cpu_tmp0, cpu_ssr); 3447 break; 3448 case 31: // ver 3449 tcg_gen_mov_tl(cpu_tmp0, cpu_ver); 3450 break; 3451 case 15: // fq 3452 default: 3453 goto illegal_insn; 3454 } 3455 #else 3456 tcg_gen_ext_i32_tl(cpu_tmp0, cpu_wim); 3457 #endif 3458 gen_store_gpr(dc, rd, cpu_tmp0); 3459 break; 3460 #endif 3461 #if defined(TARGET_SPARC64) || !defined(CONFIG_USER_ONLY) 3462 } else if (xop == 0x2b) { /* rdtbr / V9 flushw */ 3463 #ifdef TARGET_SPARC64 3464 gen_helper_flushw(cpu_env); 3465 #else 3466 if (!supervisor(dc)) 3467 goto priv_insn; 3468 gen_store_gpr(dc, rd, cpu_tbr); 3469 #endif 3470 break; 3471 #endif 3472 } else if (xop == 0x34) { /* FPU Operations */ 3473 if (gen_trap_ifnofpu(dc)) { 3474 goto jmp_insn; 3475 } 3476 gen_op_clear_ieee_excp_and_FTT(); 3477 rs1 = GET_FIELD(insn, 13, 17); 3478 rs2 = GET_FIELD(insn, 27, 31); 3479 xop = GET_FIELD(insn, 18, 26); 3480 3481 switch (xop) { 3482 case 0x1: /* fmovs */ 3483 cpu_src1_32 = gen_load_fpr_F(dc, rs2); 3484 gen_store_fpr_F(dc, rd, cpu_src1_32); 3485 break; 3486 case 0x5: /* fnegs */ 3487 gen_ne_fop_FF(dc, rd, rs2, gen_helper_fnegs); 3488 break; 3489 case 0x9: /* fabss */ 3490 gen_ne_fop_FF(dc, rd, rs2, gen_helper_fabss); 3491 break; 3492 case 0x29: /* fsqrts */ 3493 CHECK_FPU_FEATURE(dc, FSQRT); 3494 gen_fop_FF(dc, rd, rs2, gen_helper_fsqrts); 3495 break; 3496 case 0x2a: /* fsqrtd */ 3497 CHECK_FPU_FEATURE(dc, FSQRT); 3498 gen_fop_DD(dc, rd, rs2, gen_helper_fsqrtd); 3499 break; 3500 case 0x2b: /* fsqrtq */ 3501 CHECK_FPU_FEATURE(dc, FLOAT128); 3502 gen_fop_QQ(dc, rd, rs2, gen_helper_fsqrtq); 3503 break; 3504 case 0x41: /* fadds */ 3505 gen_fop_FFF(dc, rd, rs1, rs2, gen_helper_fadds); 3506 break; 3507 case 0x42: /* faddd */ 3508 gen_fop_DDD(dc, rd, rs1, rs2, gen_helper_faddd); 3509 break; 3510 case 0x43: /* faddq */ 3511 CHECK_FPU_FEATURE(dc, FLOAT128); 3512 gen_fop_QQQ(dc, rd, rs1, rs2, gen_helper_faddq); 3513 break; 3514 case 0x45: /* fsubs */ 3515 gen_fop_FFF(dc, rd, rs1, rs2, gen_helper_fsubs); 3516 break; 3517 case 0x46: /* fsubd */ 3518 gen_fop_DDD(dc, rd, rs1, rs2, gen_helper_fsubd); 3519 break; 3520 case 0x47: /* fsubq */ 3521 CHECK_FPU_FEATURE(dc, FLOAT128); 3522 gen_fop_QQQ(dc, rd, rs1, rs2, gen_helper_fsubq); 3523 break; 3524 case 0x49: /* fmuls */ 3525 CHECK_FPU_FEATURE(dc, FMUL); 3526 gen_fop_FFF(dc, rd, rs1, rs2, gen_helper_fmuls); 3527 break; 3528 case 0x4a: /* fmuld */ 3529 CHECK_FPU_FEATURE(dc, FMUL); 3530 gen_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmuld); 3531 break; 3532 case 0x4b: /* fmulq */ 3533 CHECK_FPU_FEATURE(dc, FLOAT128); 3534 CHECK_FPU_FEATURE(dc, FMUL); 3535 gen_fop_QQQ(dc, rd, rs1, rs2, gen_helper_fmulq); 3536 break; 3537 case 0x4d: /* fdivs */ 3538 gen_fop_FFF(dc, rd, rs1, rs2, gen_helper_fdivs); 3539 break; 3540 case 0x4e: /* fdivd */ 3541 gen_fop_DDD(dc, rd, rs1, rs2, gen_helper_fdivd); 3542 break; 3543 case 0x4f: /* fdivq */ 3544 CHECK_FPU_FEATURE(dc, FLOAT128); 3545 gen_fop_QQQ(dc, rd, rs1, rs2, gen_helper_fdivq); 3546 break; 3547 case 0x69: /* fsmuld */ 3548 CHECK_FPU_FEATURE(dc, FSMULD); 3549 gen_fop_DFF(dc, rd, rs1, rs2, gen_helper_fsmuld); 3550 break; 3551 case 0x6e: /* fdmulq */ 3552 CHECK_FPU_FEATURE(dc, FLOAT128); 3553 gen_fop_QDD(dc, rd, rs1, rs2, gen_helper_fdmulq); 3554 break; 3555 case 0xc4: /* fitos */ 3556 gen_fop_FF(dc, rd, rs2, gen_helper_fitos); 3557 break; 3558 case 0xc6: /* fdtos */ 3559 gen_fop_FD(dc, rd, rs2, gen_helper_fdtos); 3560 break; 3561 case 0xc7: /* fqtos */ 3562 CHECK_FPU_FEATURE(dc, FLOAT128); 3563 gen_fop_FQ(dc, rd, rs2, gen_helper_fqtos); 3564 break; 3565 case 0xc8: /* fitod */ 3566 gen_ne_fop_DF(dc, rd, rs2, gen_helper_fitod); 3567 break; 3568 case 0xc9: /* fstod */ 3569 gen_ne_fop_DF(dc, rd, rs2, gen_helper_fstod); 3570 break; 3571 case 0xcb: /* fqtod */ 3572 CHECK_FPU_FEATURE(dc, FLOAT128); 3573 gen_fop_DQ(dc, rd, rs2, gen_helper_fqtod); 3574 break; 3575 case 0xcc: /* fitoq */ 3576 CHECK_FPU_FEATURE(dc, FLOAT128); 3577 gen_ne_fop_QF(dc, rd, rs2, gen_helper_fitoq); 3578 break; 3579 case 0xcd: /* fstoq */ 3580 CHECK_FPU_FEATURE(dc, FLOAT128); 3581 gen_ne_fop_QF(dc, rd, rs2, gen_helper_fstoq); 3582 break; 3583 case 0xce: /* fdtoq */ 3584 CHECK_FPU_FEATURE(dc, FLOAT128); 3585 gen_ne_fop_QD(dc, rd, rs2, gen_helper_fdtoq); 3586 break; 3587 case 0xd1: /* fstoi */ 3588 gen_fop_FF(dc, rd, rs2, gen_helper_fstoi); 3589 break; 3590 case 0xd2: /* fdtoi */ 3591 gen_fop_FD(dc, rd, rs2, gen_helper_fdtoi); 3592 break; 3593 case 0xd3: /* fqtoi */ 3594 CHECK_FPU_FEATURE(dc, FLOAT128); 3595 gen_fop_FQ(dc, rd, rs2, gen_helper_fqtoi); 3596 break; 3597 #ifdef TARGET_SPARC64 3598 case 0x2: /* V9 fmovd */ 3599 cpu_src1_64 = gen_load_fpr_D(dc, rs2); 3600 gen_store_fpr_D(dc, rd, cpu_src1_64); 3601 break; 3602 case 0x3: /* V9 fmovq */ 3603 CHECK_FPU_FEATURE(dc, FLOAT128); 3604 gen_move_Q(dc, rd, rs2); 3605 break; 3606 case 0x6: /* V9 fnegd */ 3607 gen_ne_fop_DD(dc, rd, rs2, gen_helper_fnegd); 3608 break; 3609 case 0x7: /* V9 fnegq */ 3610 CHECK_FPU_FEATURE(dc, FLOAT128); 3611 gen_ne_fop_QQ(dc, rd, rs2, gen_helper_fnegq); 3612 break; 3613 case 0xa: /* V9 fabsd */ 3614 gen_ne_fop_DD(dc, rd, rs2, gen_helper_fabsd); 3615 break; 3616 case 0xb: /* V9 fabsq */ 3617 CHECK_FPU_FEATURE(dc, FLOAT128); 3618 gen_ne_fop_QQ(dc, rd, rs2, gen_helper_fabsq); 3619 break; 3620 case 0x81: /* V9 fstox */ 3621 gen_fop_DF(dc, rd, rs2, gen_helper_fstox); 3622 break; 3623 case 0x82: /* V9 fdtox */ 3624 gen_fop_DD(dc, rd, rs2, gen_helper_fdtox); 3625 break; 3626 case 0x83: /* V9 fqtox */ 3627 CHECK_FPU_FEATURE(dc, FLOAT128); 3628 gen_fop_DQ(dc, rd, rs2, gen_helper_fqtox); 3629 break; 3630 case 0x84: /* V9 fxtos */ 3631 gen_fop_FD(dc, rd, rs2, gen_helper_fxtos); 3632 break; 3633 case 0x88: /* V9 fxtod */ 3634 gen_fop_DD(dc, rd, rs2, gen_helper_fxtod); 3635 break; 3636 case 0x8c: /* V9 fxtoq */ 3637 CHECK_FPU_FEATURE(dc, FLOAT128); 3638 gen_ne_fop_QD(dc, rd, rs2, gen_helper_fxtoq); 3639 break; 3640 #endif 3641 default: 3642 goto illegal_insn; 3643 } 3644 } else if (xop == 0x35) { /* FPU Operations */ 3645 #ifdef TARGET_SPARC64 3646 int cond; 3647 #endif 3648 if (gen_trap_ifnofpu(dc)) { 3649 goto jmp_insn; 3650 } 3651 gen_op_clear_ieee_excp_and_FTT(); 3652 rs1 = GET_FIELD(insn, 13, 17); 3653 rs2 = GET_FIELD(insn, 27, 31); 3654 xop = GET_FIELD(insn, 18, 26); 3655 3656 #ifdef TARGET_SPARC64 3657 #define FMOVR(sz) \ 3658 do { \ 3659 DisasCompare cmp; \ 3660 cond = GET_FIELD_SP(insn, 10, 12); \ 3661 cpu_src1 = get_src1(dc, insn); \ 3662 gen_compare_reg(&cmp, cond, cpu_src1); \ 3663 gen_fmov##sz(dc, &cmp, rd, rs2); \ 3664 } while (0) 3665 3666 if ((xop & 0x11f) == 0x005) { /* V9 fmovsr */ 3667 FMOVR(s); 3668 break; 3669 } else if ((xop & 0x11f) == 0x006) { // V9 fmovdr 3670 FMOVR(d); 3671 break; 3672 } else if ((xop & 0x11f) == 0x007) { // V9 fmovqr 3673 CHECK_FPU_FEATURE(dc, FLOAT128); 3674 FMOVR(q); 3675 break; 3676 } 3677 #undef FMOVR 3678 #endif 3679 switch (xop) { 3680 #ifdef TARGET_SPARC64 3681 #define FMOVCC(fcc, sz) \ 3682 do { \ 3683 DisasCompare cmp; \ 3684 cond = GET_FIELD_SP(insn, 14, 17); \ 3685 gen_fcompare(&cmp, fcc, cond); \ 3686 gen_fmov##sz(dc, &cmp, rd, rs2); \ 3687 } while (0) 3688 3689 case 0x001: /* V9 fmovscc %fcc0 */ 3690 FMOVCC(0, s); 3691 break; 3692 case 0x002: /* V9 fmovdcc %fcc0 */ 3693 FMOVCC(0, d); 3694 break; 3695 case 0x003: /* V9 fmovqcc %fcc0 */ 3696 CHECK_FPU_FEATURE(dc, FLOAT128); 3697 FMOVCC(0, q); 3698 break; 3699 case 0x041: /* V9 fmovscc %fcc1 */ 3700 FMOVCC(1, s); 3701 break; 3702 case 0x042: /* V9 fmovdcc %fcc1 */ 3703 FMOVCC(1, d); 3704 break; 3705 case 0x043: /* V9 fmovqcc %fcc1 */ 3706 CHECK_FPU_FEATURE(dc, FLOAT128); 3707 FMOVCC(1, q); 3708 break; 3709 case 0x081: /* V9 fmovscc %fcc2 */ 3710 FMOVCC(2, s); 3711 break; 3712 case 0x082: /* V9 fmovdcc %fcc2 */ 3713 FMOVCC(2, d); 3714 break; 3715 case 0x083: /* V9 fmovqcc %fcc2 */ 3716 CHECK_FPU_FEATURE(dc, FLOAT128); 3717 FMOVCC(2, q); 3718 break; 3719 case 0x0c1: /* V9 fmovscc %fcc3 */ 3720 FMOVCC(3, s); 3721 break; 3722 case 0x0c2: /* V9 fmovdcc %fcc3 */ 3723 FMOVCC(3, d); 3724 break; 3725 case 0x0c3: /* V9 fmovqcc %fcc3 */ 3726 CHECK_FPU_FEATURE(dc, FLOAT128); 3727 FMOVCC(3, q); 3728 break; 3729 #undef FMOVCC 3730 #define FMOVCC(xcc, sz) \ 3731 do { \ 3732 DisasCompare cmp; \ 3733 cond = GET_FIELD_SP(insn, 14, 17); \ 3734 gen_compare(&cmp, xcc, cond, dc); \ 3735 gen_fmov##sz(dc, &cmp, rd, rs2); \ 3736 } while (0) 3737 3738 case 0x101: /* V9 fmovscc %icc */ 3739 FMOVCC(0, s); 3740 break; 3741 case 0x102: /* V9 fmovdcc %icc */ 3742 FMOVCC(0, d); 3743 break; 3744 case 0x103: /* V9 fmovqcc %icc */ 3745 CHECK_FPU_FEATURE(dc, FLOAT128); 3746 FMOVCC(0, q); 3747 break; 3748 case 0x181: /* V9 fmovscc %xcc */ 3749 FMOVCC(1, s); 3750 break; 3751 case 0x182: /* V9 fmovdcc %xcc */ 3752 FMOVCC(1, d); 3753 break; 3754 case 0x183: /* V9 fmovqcc %xcc */ 3755 CHECK_FPU_FEATURE(dc, FLOAT128); 3756 FMOVCC(1, q); 3757 break; 3758 #undef FMOVCC 3759 #endif 3760 case 0x51: /* fcmps, V9 %fcc */ 3761 cpu_src1_32 = gen_load_fpr_F(dc, rs1); 3762 cpu_src2_32 = gen_load_fpr_F(dc, rs2); 3763 gen_op_fcmps(rd & 3, cpu_src1_32, cpu_src2_32); 3764 break; 3765 case 0x52: /* fcmpd, V9 %fcc */ 3766 cpu_src1_64 = gen_load_fpr_D(dc, rs1); 3767 cpu_src2_64 = gen_load_fpr_D(dc, rs2); 3768 gen_op_fcmpd(rd & 3, cpu_src1_64, cpu_src2_64); 3769 break; 3770 case 0x53: /* fcmpq, V9 %fcc */ 3771 CHECK_FPU_FEATURE(dc, FLOAT128); 3772 gen_op_load_fpr_QT0(QFPREG(rs1)); 3773 gen_op_load_fpr_QT1(QFPREG(rs2)); 3774 gen_op_fcmpq(rd & 3); 3775 break; 3776 case 0x55: /* fcmpes, V9 %fcc */ 3777 cpu_src1_32 = gen_load_fpr_F(dc, rs1); 3778 cpu_src2_32 = gen_load_fpr_F(dc, rs2); 3779 gen_op_fcmpes(rd & 3, cpu_src1_32, cpu_src2_32); 3780 break; 3781 case 0x56: /* fcmped, V9 %fcc */ 3782 cpu_src1_64 = gen_load_fpr_D(dc, rs1); 3783 cpu_src2_64 = gen_load_fpr_D(dc, rs2); 3784 gen_op_fcmped(rd & 3, cpu_src1_64, cpu_src2_64); 3785 break; 3786 case 0x57: /* fcmpeq, V9 %fcc */ 3787 CHECK_FPU_FEATURE(dc, FLOAT128); 3788 gen_op_load_fpr_QT0(QFPREG(rs1)); 3789 gen_op_load_fpr_QT1(QFPREG(rs2)); 3790 gen_op_fcmpeq(rd & 3); 3791 break; 3792 default: 3793 goto illegal_insn; 3794 } 3795 } else if (xop == 0x2) { 3796 TCGv dst = gen_dest_gpr(dc, rd); 3797 rs1 = GET_FIELD(insn, 13, 17); 3798 if (rs1 == 0) { 3799 /* clr/mov shortcut : or %g0, x, y -> mov x, y */ 3800 if (IS_IMM) { /* immediate */ 3801 simm = GET_FIELDs(insn, 19, 31); 3802 tcg_gen_movi_tl(dst, simm); 3803 gen_store_gpr(dc, rd, dst); 3804 } else { /* register */ 3805 rs2 = GET_FIELD(insn, 27, 31); 3806 if (rs2 == 0) { 3807 tcg_gen_movi_tl(dst, 0); 3808 gen_store_gpr(dc, rd, dst); 3809 } else { 3810 cpu_src2 = gen_load_gpr(dc, rs2); 3811 gen_store_gpr(dc, rd, cpu_src2); 3812 } 3813 } 3814 } else { 3815 cpu_src1 = get_src1(dc, insn); 3816 if (IS_IMM) { /* immediate */ 3817 simm = GET_FIELDs(insn, 19, 31); 3818 tcg_gen_ori_tl(dst, cpu_src1, simm); 3819 gen_store_gpr(dc, rd, dst); 3820 } else { /* register */ 3821 rs2 = GET_FIELD(insn, 27, 31); 3822 if (rs2 == 0) { 3823 /* mov shortcut: or x, %g0, y -> mov x, y */ 3824 gen_store_gpr(dc, rd, cpu_src1); 3825 } else { 3826 cpu_src2 = gen_load_gpr(dc, rs2); 3827 tcg_gen_or_tl(dst, cpu_src1, cpu_src2); 3828 gen_store_gpr(dc, rd, dst); 3829 } 3830 } 3831 } 3832 #ifdef TARGET_SPARC64 3833 } else if (xop == 0x25) { /* sll, V9 sllx */ 3834 cpu_src1 = get_src1(dc, insn); 3835 if (IS_IMM) { /* immediate */ 3836 simm = GET_FIELDs(insn, 20, 31); 3837 if (insn & (1 << 12)) { 3838 tcg_gen_shli_i64(cpu_dst, cpu_src1, simm & 0x3f); 3839 } else { 3840 tcg_gen_shli_i64(cpu_dst, cpu_src1, simm & 0x1f); 3841 } 3842 } else { /* register */ 3843 rs2 = GET_FIELD(insn, 27, 31); 3844 cpu_src2 = gen_load_gpr(dc, rs2); 3845 cpu_tmp0 = tcg_temp_new(); 3846 if (insn & (1 << 12)) { 3847 tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x3f); 3848 } else { 3849 tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x1f); 3850 } 3851 tcg_gen_shl_i64(cpu_dst, cpu_src1, cpu_tmp0); 3852 } 3853 gen_store_gpr(dc, rd, cpu_dst); 3854 } else if (xop == 0x26) { /* srl, V9 srlx */ 3855 cpu_src1 = get_src1(dc, insn); 3856 if (IS_IMM) { /* immediate */ 3857 simm = GET_FIELDs(insn, 20, 31); 3858 if (insn & (1 << 12)) { 3859 tcg_gen_shri_i64(cpu_dst, cpu_src1, simm & 0x3f); 3860 } else { 3861 tcg_gen_andi_i64(cpu_dst, cpu_src1, 0xffffffffULL); 3862 tcg_gen_shri_i64(cpu_dst, cpu_dst, simm & 0x1f); 3863 } 3864 } else { /* register */ 3865 rs2 = GET_FIELD(insn, 27, 31); 3866 cpu_src2 = gen_load_gpr(dc, rs2); 3867 cpu_tmp0 = tcg_temp_new(); 3868 if (insn & (1 << 12)) { 3869 tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x3f); 3870 tcg_gen_shr_i64(cpu_dst, cpu_src1, cpu_tmp0); 3871 } else { 3872 tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x1f); 3873 tcg_gen_andi_i64(cpu_dst, cpu_src1, 0xffffffffULL); 3874 tcg_gen_shr_i64(cpu_dst, cpu_dst, cpu_tmp0); 3875 } 3876 } 3877 gen_store_gpr(dc, rd, cpu_dst); 3878 } else if (xop == 0x27) { /* sra, V9 srax */ 3879 cpu_src1 = get_src1(dc, insn); 3880 if (IS_IMM) { /* immediate */ 3881 simm = GET_FIELDs(insn, 20, 31); 3882 if (insn & (1 << 12)) { 3883 tcg_gen_sari_i64(cpu_dst, cpu_src1, simm & 0x3f); 3884 } else { 3885 tcg_gen_ext32s_i64(cpu_dst, cpu_src1); 3886 tcg_gen_sari_i64(cpu_dst, cpu_dst, simm & 0x1f); 3887 } 3888 } else { /* register */ 3889 rs2 = GET_FIELD(insn, 27, 31); 3890 cpu_src2 = gen_load_gpr(dc, rs2); 3891 cpu_tmp0 = tcg_temp_new(); 3892 if (insn & (1 << 12)) { 3893 tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x3f); 3894 tcg_gen_sar_i64(cpu_dst, cpu_src1, cpu_tmp0); 3895 } else { 3896 tcg_gen_andi_i64(cpu_tmp0, cpu_src2, 0x1f); 3897 tcg_gen_ext32s_i64(cpu_dst, cpu_src1); 3898 tcg_gen_sar_i64(cpu_dst, cpu_dst, cpu_tmp0); 3899 } 3900 } 3901 gen_store_gpr(dc, rd, cpu_dst); 3902 #endif 3903 } else if (xop < 0x36) { 3904 if (xop < 0x20) { 3905 cpu_src1 = get_src1(dc, insn); 3906 cpu_src2 = get_src2(dc, insn); 3907 switch (xop & ~0x10) { 3908 case 0x0: /* add */ 3909 if (xop & 0x10) { 3910 gen_op_add_cc(cpu_dst, cpu_src1, cpu_src2); 3911 tcg_gen_movi_i32(cpu_cc_op, CC_OP_ADD); 3912 dc->cc_op = CC_OP_ADD; 3913 } else { 3914 tcg_gen_add_tl(cpu_dst, cpu_src1, cpu_src2); 3915 } 3916 break; 3917 case 0x1: /* and */ 3918 tcg_gen_and_tl(cpu_dst, cpu_src1, cpu_src2); 3919 if (xop & 0x10) { 3920 tcg_gen_mov_tl(cpu_cc_dst, cpu_dst); 3921 tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC); 3922 dc->cc_op = CC_OP_LOGIC; 3923 } 3924 break; 3925 case 0x2: /* or */ 3926 tcg_gen_or_tl(cpu_dst, cpu_src1, cpu_src2); 3927 if (xop & 0x10) { 3928 tcg_gen_mov_tl(cpu_cc_dst, cpu_dst); 3929 tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC); 3930 dc->cc_op = CC_OP_LOGIC; 3931 } 3932 break; 3933 case 0x3: /* xor */ 3934 tcg_gen_xor_tl(cpu_dst, cpu_src1, cpu_src2); 3935 if (xop & 0x10) { 3936 tcg_gen_mov_tl(cpu_cc_dst, cpu_dst); 3937 tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC); 3938 dc->cc_op = CC_OP_LOGIC; 3939 } 3940 break; 3941 case 0x4: /* sub */ 3942 if (xop & 0x10) { 3943 gen_op_sub_cc(cpu_dst, cpu_src1, cpu_src2); 3944 tcg_gen_movi_i32(cpu_cc_op, CC_OP_SUB); 3945 dc->cc_op = CC_OP_SUB; 3946 } else { 3947 tcg_gen_sub_tl(cpu_dst, cpu_src1, cpu_src2); 3948 } 3949 break; 3950 case 0x5: /* andn */ 3951 tcg_gen_andc_tl(cpu_dst, cpu_src1, cpu_src2); 3952 if (xop & 0x10) { 3953 tcg_gen_mov_tl(cpu_cc_dst, cpu_dst); 3954 tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC); 3955 dc->cc_op = CC_OP_LOGIC; 3956 } 3957 break; 3958 case 0x6: /* orn */ 3959 tcg_gen_orc_tl(cpu_dst, cpu_src1, cpu_src2); 3960 if (xop & 0x10) { 3961 tcg_gen_mov_tl(cpu_cc_dst, cpu_dst); 3962 tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC); 3963 dc->cc_op = CC_OP_LOGIC; 3964 } 3965 break; 3966 case 0x7: /* xorn */ 3967 tcg_gen_eqv_tl(cpu_dst, cpu_src1, cpu_src2); 3968 if (xop & 0x10) { 3969 tcg_gen_mov_tl(cpu_cc_dst, cpu_dst); 3970 tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC); 3971 dc->cc_op = CC_OP_LOGIC; 3972 } 3973 break; 3974 case 0x8: /* addx, V9 addc */ 3975 gen_op_addx_int(dc, cpu_dst, cpu_src1, cpu_src2, 3976 (xop & 0x10)); 3977 break; 3978 #ifdef TARGET_SPARC64 3979 case 0x9: /* V9 mulx */ 3980 tcg_gen_mul_i64(cpu_dst, cpu_src1, cpu_src2); 3981 break; 3982 #endif 3983 case 0xa: /* umul */ 3984 CHECK_IU_FEATURE(dc, MUL); 3985 gen_op_umul(cpu_dst, cpu_src1, cpu_src2); 3986 if (xop & 0x10) { 3987 tcg_gen_mov_tl(cpu_cc_dst, cpu_dst); 3988 tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC); 3989 dc->cc_op = CC_OP_LOGIC; 3990 } 3991 break; 3992 case 0xb: /* smul */ 3993 CHECK_IU_FEATURE(dc, MUL); 3994 gen_op_smul(cpu_dst, cpu_src1, cpu_src2); 3995 if (xop & 0x10) { 3996 tcg_gen_mov_tl(cpu_cc_dst, cpu_dst); 3997 tcg_gen_movi_i32(cpu_cc_op, CC_OP_LOGIC); 3998 dc->cc_op = CC_OP_LOGIC; 3999 } 4000 break; 4001 case 0xc: /* subx, V9 subc */ 4002 gen_op_subx_int(dc, cpu_dst, cpu_src1, cpu_src2, 4003 (xop & 0x10)); 4004 break; 4005 #ifdef TARGET_SPARC64 4006 case 0xd: /* V9 udivx */ 4007 gen_helper_udivx(cpu_dst, cpu_env, cpu_src1, cpu_src2); 4008 break; 4009 #endif 4010 case 0xe: /* udiv */ 4011 CHECK_IU_FEATURE(dc, DIV); 4012 if (xop & 0x10) { 4013 gen_helper_udiv_cc(cpu_dst, cpu_env, cpu_src1, 4014 cpu_src2); 4015 dc->cc_op = CC_OP_DIV; 4016 } else { 4017 gen_helper_udiv(cpu_dst, cpu_env, cpu_src1, 4018 cpu_src2); 4019 } 4020 break; 4021 case 0xf: /* sdiv */ 4022 CHECK_IU_FEATURE(dc, DIV); 4023 if (xop & 0x10) { 4024 gen_helper_sdiv_cc(cpu_dst, cpu_env, cpu_src1, 4025 cpu_src2); 4026 dc->cc_op = CC_OP_DIV; 4027 } else { 4028 gen_helper_sdiv(cpu_dst, cpu_env, cpu_src1, 4029 cpu_src2); 4030 } 4031 break; 4032 default: 4033 goto illegal_insn; 4034 } 4035 gen_store_gpr(dc, rd, cpu_dst); 4036 } else { 4037 cpu_src1 = get_src1(dc, insn); 4038 cpu_src2 = get_src2(dc, insn); 4039 switch (xop) { 4040 case 0x20: /* taddcc */ 4041 gen_op_add_cc(cpu_dst, cpu_src1, cpu_src2); 4042 gen_store_gpr(dc, rd, cpu_dst); 4043 tcg_gen_movi_i32(cpu_cc_op, CC_OP_TADD); 4044 dc->cc_op = CC_OP_TADD; 4045 break; 4046 case 0x21: /* tsubcc */ 4047 gen_op_sub_cc(cpu_dst, cpu_src1, cpu_src2); 4048 gen_store_gpr(dc, rd, cpu_dst); 4049 tcg_gen_movi_i32(cpu_cc_op, CC_OP_TSUB); 4050 dc->cc_op = CC_OP_TSUB; 4051 break; 4052 case 0x22: /* taddcctv */ 4053 gen_helper_taddcctv(cpu_dst, cpu_env, 4054 cpu_src1, cpu_src2); 4055 gen_store_gpr(dc, rd, cpu_dst); 4056 dc->cc_op = CC_OP_TADDTV; 4057 break; 4058 case 0x23: /* tsubcctv */ 4059 gen_helper_tsubcctv(cpu_dst, cpu_env, 4060 cpu_src1, cpu_src2); 4061 gen_store_gpr(dc, rd, cpu_dst); 4062 dc->cc_op = CC_OP_TSUBTV; 4063 break; 4064 case 0x24: /* mulscc */ 4065 update_psr(dc); 4066 gen_op_mulscc(cpu_dst, cpu_src1, cpu_src2); 4067 gen_store_gpr(dc, rd, cpu_dst); 4068 tcg_gen_movi_i32(cpu_cc_op, CC_OP_ADD); 4069 dc->cc_op = CC_OP_ADD; 4070 break; 4071 #ifndef TARGET_SPARC64 4072 case 0x25: /* sll */ 4073 if (IS_IMM) { /* immediate */ 4074 simm = GET_FIELDs(insn, 20, 31); 4075 tcg_gen_shli_tl(cpu_dst, cpu_src1, simm & 0x1f); 4076 } else { /* register */ 4077 cpu_tmp0 = tcg_temp_new(); 4078 tcg_gen_andi_tl(cpu_tmp0, cpu_src2, 0x1f); 4079 tcg_gen_shl_tl(cpu_dst, cpu_src1, cpu_tmp0); 4080 } 4081 gen_store_gpr(dc, rd, cpu_dst); 4082 break; 4083 case 0x26: /* srl */ 4084 if (IS_IMM) { /* immediate */ 4085 simm = GET_FIELDs(insn, 20, 31); 4086 tcg_gen_shri_tl(cpu_dst, cpu_src1, simm & 0x1f); 4087 } else { /* register */ 4088 cpu_tmp0 = tcg_temp_new(); 4089 tcg_gen_andi_tl(cpu_tmp0, cpu_src2, 0x1f); 4090 tcg_gen_shr_tl(cpu_dst, cpu_src1, cpu_tmp0); 4091 } 4092 gen_store_gpr(dc, rd, cpu_dst); 4093 break; 4094 case 0x27: /* sra */ 4095 if (IS_IMM) { /* immediate */ 4096 simm = GET_FIELDs(insn, 20, 31); 4097 tcg_gen_sari_tl(cpu_dst, cpu_src1, simm & 0x1f); 4098 } else { /* register */ 4099 cpu_tmp0 = tcg_temp_new(); 4100 tcg_gen_andi_tl(cpu_tmp0, cpu_src2, 0x1f); 4101 tcg_gen_sar_tl(cpu_dst, cpu_src1, cpu_tmp0); 4102 } 4103 gen_store_gpr(dc, rd, cpu_dst); 4104 break; 4105 #endif 4106 case 0x30: 4107 { 4108 cpu_tmp0 = tcg_temp_new(); 4109 switch(rd) { 4110 case 0: /* wry */ 4111 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2); 4112 tcg_gen_andi_tl(cpu_y, cpu_tmp0, 0xffffffff); 4113 break; 4114 #ifndef TARGET_SPARC64 4115 case 0x01 ... 0x0f: /* undefined in the 4116 SPARCv8 manual, nop 4117 on the microSPARC 4118 II */ 4119 case 0x10 ... 0x1f: /* implementation-dependent 4120 in the SPARCv8 4121 manual, nop on the 4122 microSPARC II */ 4123 if ((rd == 0x13) && (dc->def->features & 4124 CPU_FEATURE_POWERDOWN)) { 4125 /* LEON3 power-down */ 4126 save_state(dc); 4127 gen_helper_power_down(cpu_env); 4128 } 4129 break; 4130 #else 4131 case 0x2: /* V9 wrccr */ 4132 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2); 4133 gen_helper_wrccr(cpu_env, cpu_tmp0); 4134 tcg_gen_movi_i32(cpu_cc_op, CC_OP_FLAGS); 4135 dc->cc_op = CC_OP_FLAGS; 4136 break; 4137 case 0x3: /* V9 wrasi */ 4138 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2); 4139 tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, 0xff); 4140 tcg_gen_st32_tl(cpu_tmp0, cpu_env, 4141 offsetof(CPUSPARCState, asi)); 4142 /* End TB to notice changed ASI. */ 4143 save_state(dc); 4144 gen_op_next_insn(); 4145 tcg_gen_exit_tb(NULL, 0); 4146 dc->base.is_jmp = DISAS_NORETURN; 4147 break; 4148 case 0x6: /* V9 wrfprs */ 4149 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2); 4150 tcg_gen_trunc_tl_i32(cpu_fprs, cpu_tmp0); 4151 dc->fprs_dirty = 0; 4152 save_state(dc); 4153 gen_op_next_insn(); 4154 tcg_gen_exit_tb(NULL, 0); 4155 dc->base.is_jmp = DISAS_NORETURN; 4156 break; 4157 case 0xf: /* V9 sir, nop if user */ 4158 #if !defined(CONFIG_USER_ONLY) 4159 if (supervisor(dc)) { 4160 ; // XXX 4161 } 4162 #endif 4163 break; 4164 case 0x13: /* Graphics Status */ 4165 if (gen_trap_ifnofpu(dc)) { 4166 goto jmp_insn; 4167 } 4168 tcg_gen_xor_tl(cpu_gsr, cpu_src1, cpu_src2); 4169 break; 4170 case 0x14: /* Softint set */ 4171 if (!supervisor(dc)) 4172 goto illegal_insn; 4173 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2); 4174 gen_helper_set_softint(cpu_env, cpu_tmp0); 4175 break; 4176 case 0x15: /* Softint clear */ 4177 if (!supervisor(dc)) 4178 goto illegal_insn; 4179 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2); 4180 gen_helper_clear_softint(cpu_env, cpu_tmp0); 4181 break; 4182 case 0x16: /* Softint write */ 4183 if (!supervisor(dc)) 4184 goto illegal_insn; 4185 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2); 4186 gen_helper_write_softint(cpu_env, cpu_tmp0); 4187 break; 4188 case 0x17: /* Tick compare */ 4189 #if !defined(CONFIG_USER_ONLY) 4190 if (!supervisor(dc)) 4191 goto illegal_insn; 4192 #endif 4193 { 4194 TCGv_ptr r_tickptr; 4195 4196 tcg_gen_xor_tl(cpu_tick_cmpr, cpu_src1, 4197 cpu_src2); 4198 r_tickptr = tcg_temp_new_ptr(); 4199 tcg_gen_ld_ptr(r_tickptr, cpu_env, 4200 offsetof(CPUSPARCState, tick)); 4201 translator_io_start(&dc->base); 4202 gen_helper_tick_set_limit(r_tickptr, 4203 cpu_tick_cmpr); 4204 /* End TB to handle timer interrupt */ 4205 dc->base.is_jmp = DISAS_EXIT; 4206 } 4207 break; 4208 case 0x18: /* System tick */ 4209 #if !defined(CONFIG_USER_ONLY) 4210 if (!supervisor(dc)) 4211 goto illegal_insn; 4212 #endif 4213 { 4214 TCGv_ptr r_tickptr; 4215 4216 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, 4217 cpu_src2); 4218 r_tickptr = tcg_temp_new_ptr(); 4219 tcg_gen_ld_ptr(r_tickptr, cpu_env, 4220 offsetof(CPUSPARCState, stick)); 4221 translator_io_start(&dc->base); 4222 gen_helper_tick_set_count(r_tickptr, 4223 cpu_tmp0); 4224 /* End TB to handle timer interrupt */ 4225 dc->base.is_jmp = DISAS_EXIT; 4226 } 4227 break; 4228 case 0x19: /* System tick compare */ 4229 #if !defined(CONFIG_USER_ONLY) 4230 if (!supervisor(dc)) 4231 goto illegal_insn; 4232 #endif 4233 { 4234 TCGv_ptr r_tickptr; 4235 4236 tcg_gen_xor_tl(cpu_stick_cmpr, cpu_src1, 4237 cpu_src2); 4238 r_tickptr = tcg_temp_new_ptr(); 4239 tcg_gen_ld_ptr(r_tickptr, cpu_env, 4240 offsetof(CPUSPARCState, stick)); 4241 translator_io_start(&dc->base); 4242 gen_helper_tick_set_limit(r_tickptr, 4243 cpu_stick_cmpr); 4244 /* End TB to handle timer interrupt */ 4245 dc->base.is_jmp = DISAS_EXIT; 4246 } 4247 break; 4248 4249 case 0x10: /* Performance Control */ 4250 case 0x11: /* Performance Instrumentation 4251 Counter */ 4252 case 0x12: /* Dispatch Control */ 4253 #endif 4254 default: 4255 goto illegal_insn; 4256 } 4257 } 4258 break; 4259 #if !defined(CONFIG_USER_ONLY) 4260 case 0x31: /* wrpsr, V9 saved, restored */ 4261 { 4262 if (!supervisor(dc)) 4263 goto priv_insn; 4264 #ifdef TARGET_SPARC64 4265 switch (rd) { 4266 case 0: 4267 gen_helper_saved(cpu_env); 4268 break; 4269 case 1: 4270 gen_helper_restored(cpu_env); 4271 break; 4272 case 2: /* UA2005 allclean */ 4273 case 3: /* UA2005 otherw */ 4274 case 4: /* UA2005 normalw */ 4275 case 5: /* UA2005 invalw */ 4276 // XXX 4277 default: 4278 goto illegal_insn; 4279 } 4280 #else 4281 cpu_tmp0 = tcg_temp_new(); 4282 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2); 4283 gen_helper_wrpsr(cpu_env, cpu_tmp0); 4284 tcg_gen_movi_i32(cpu_cc_op, CC_OP_FLAGS); 4285 dc->cc_op = CC_OP_FLAGS; 4286 save_state(dc); 4287 gen_op_next_insn(); 4288 tcg_gen_exit_tb(NULL, 0); 4289 dc->base.is_jmp = DISAS_NORETURN; 4290 #endif 4291 } 4292 break; 4293 case 0x32: /* wrwim, V9 wrpr */ 4294 { 4295 if (!supervisor(dc)) 4296 goto priv_insn; 4297 cpu_tmp0 = tcg_temp_new(); 4298 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2); 4299 #ifdef TARGET_SPARC64 4300 switch (rd) { 4301 case 0: // tpc 4302 { 4303 TCGv_ptr r_tsptr; 4304 4305 r_tsptr = tcg_temp_new_ptr(); 4306 gen_load_trap_state_at_tl(r_tsptr, cpu_env); 4307 tcg_gen_st_tl(cpu_tmp0, r_tsptr, 4308 offsetof(trap_state, tpc)); 4309 } 4310 break; 4311 case 1: // tnpc 4312 { 4313 TCGv_ptr r_tsptr; 4314 4315 r_tsptr = tcg_temp_new_ptr(); 4316 gen_load_trap_state_at_tl(r_tsptr, cpu_env); 4317 tcg_gen_st_tl(cpu_tmp0, r_tsptr, 4318 offsetof(trap_state, tnpc)); 4319 } 4320 break; 4321 case 2: // tstate 4322 { 4323 TCGv_ptr r_tsptr; 4324 4325 r_tsptr = tcg_temp_new_ptr(); 4326 gen_load_trap_state_at_tl(r_tsptr, cpu_env); 4327 tcg_gen_st_tl(cpu_tmp0, r_tsptr, 4328 offsetof(trap_state, 4329 tstate)); 4330 } 4331 break; 4332 case 3: // tt 4333 { 4334 TCGv_ptr r_tsptr; 4335 4336 r_tsptr = tcg_temp_new_ptr(); 4337 gen_load_trap_state_at_tl(r_tsptr, cpu_env); 4338 tcg_gen_st32_tl(cpu_tmp0, r_tsptr, 4339 offsetof(trap_state, tt)); 4340 } 4341 break; 4342 case 4: // tick 4343 { 4344 TCGv_ptr r_tickptr; 4345 4346 r_tickptr = tcg_temp_new_ptr(); 4347 tcg_gen_ld_ptr(r_tickptr, cpu_env, 4348 offsetof(CPUSPARCState, tick)); 4349 translator_io_start(&dc->base); 4350 gen_helper_tick_set_count(r_tickptr, 4351 cpu_tmp0); 4352 /* End TB to handle timer interrupt */ 4353 dc->base.is_jmp = DISAS_EXIT; 4354 } 4355 break; 4356 case 5: // tba 4357 tcg_gen_mov_tl(cpu_tbr, cpu_tmp0); 4358 break; 4359 case 6: // pstate 4360 save_state(dc); 4361 if (translator_io_start(&dc->base)) { 4362 dc->base.is_jmp = DISAS_EXIT; 4363 } 4364 gen_helper_wrpstate(cpu_env, cpu_tmp0); 4365 dc->npc = DYNAMIC_PC; 4366 break; 4367 case 7: // tl 4368 save_state(dc); 4369 tcg_gen_st32_tl(cpu_tmp0, cpu_env, 4370 offsetof(CPUSPARCState, tl)); 4371 dc->npc = DYNAMIC_PC; 4372 break; 4373 case 8: // pil 4374 if (translator_io_start(&dc->base)) { 4375 dc->base.is_jmp = DISAS_EXIT; 4376 } 4377 gen_helper_wrpil(cpu_env, cpu_tmp0); 4378 break; 4379 case 9: // cwp 4380 gen_helper_wrcwp(cpu_env, cpu_tmp0); 4381 break; 4382 case 10: // cansave 4383 tcg_gen_st32_tl(cpu_tmp0, cpu_env, 4384 offsetof(CPUSPARCState, 4385 cansave)); 4386 break; 4387 case 11: // canrestore 4388 tcg_gen_st32_tl(cpu_tmp0, cpu_env, 4389 offsetof(CPUSPARCState, 4390 canrestore)); 4391 break; 4392 case 12: // cleanwin 4393 tcg_gen_st32_tl(cpu_tmp0, cpu_env, 4394 offsetof(CPUSPARCState, 4395 cleanwin)); 4396 break; 4397 case 13: // otherwin 4398 tcg_gen_st32_tl(cpu_tmp0, cpu_env, 4399 offsetof(CPUSPARCState, 4400 otherwin)); 4401 break; 4402 case 14: // wstate 4403 tcg_gen_st32_tl(cpu_tmp0, cpu_env, 4404 offsetof(CPUSPARCState, 4405 wstate)); 4406 break; 4407 case 16: // UA2005 gl 4408 CHECK_IU_FEATURE(dc, GL); 4409 gen_helper_wrgl(cpu_env, cpu_tmp0); 4410 break; 4411 case 26: // UA2005 strand status 4412 CHECK_IU_FEATURE(dc, HYPV); 4413 if (!hypervisor(dc)) 4414 goto priv_insn; 4415 tcg_gen_mov_tl(cpu_ssr, cpu_tmp0); 4416 break; 4417 default: 4418 goto illegal_insn; 4419 } 4420 #else 4421 tcg_gen_trunc_tl_i32(cpu_wim, cpu_tmp0); 4422 if (dc->def->nwindows != 32) { 4423 tcg_gen_andi_tl(cpu_wim, cpu_wim, 4424 (1 << dc->def->nwindows) - 1); 4425 } 4426 #endif 4427 } 4428 break; 4429 case 0x33: /* wrtbr, UA2005 wrhpr */ 4430 { 4431 #ifndef TARGET_SPARC64 4432 if (!supervisor(dc)) 4433 goto priv_insn; 4434 tcg_gen_xor_tl(cpu_tbr, cpu_src1, cpu_src2); 4435 #else 4436 CHECK_IU_FEATURE(dc, HYPV); 4437 if (!hypervisor(dc)) 4438 goto priv_insn; 4439 cpu_tmp0 = tcg_temp_new(); 4440 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2); 4441 switch (rd) { 4442 case 0: // hpstate 4443 tcg_gen_st_i64(cpu_tmp0, cpu_env, 4444 offsetof(CPUSPARCState, 4445 hpstate)); 4446 save_state(dc); 4447 gen_op_next_insn(); 4448 tcg_gen_exit_tb(NULL, 0); 4449 dc->base.is_jmp = DISAS_NORETURN; 4450 break; 4451 case 1: // htstate 4452 // XXX gen_op_wrhtstate(); 4453 break; 4454 case 3: // hintp 4455 tcg_gen_mov_tl(cpu_hintp, cpu_tmp0); 4456 break; 4457 case 5: // htba 4458 tcg_gen_mov_tl(cpu_htba, cpu_tmp0); 4459 break; 4460 case 31: // hstick_cmpr 4461 { 4462 TCGv_ptr r_tickptr; 4463 4464 tcg_gen_mov_tl(cpu_hstick_cmpr, cpu_tmp0); 4465 r_tickptr = tcg_temp_new_ptr(); 4466 tcg_gen_ld_ptr(r_tickptr, cpu_env, 4467 offsetof(CPUSPARCState, hstick)); 4468 translator_io_start(&dc->base); 4469 gen_helper_tick_set_limit(r_tickptr, 4470 cpu_hstick_cmpr); 4471 /* End TB to handle timer interrupt */ 4472 dc->base.is_jmp = DISAS_EXIT; 4473 } 4474 break; 4475 case 6: // hver readonly 4476 default: 4477 goto illegal_insn; 4478 } 4479 #endif 4480 } 4481 break; 4482 #endif 4483 #ifdef TARGET_SPARC64 4484 case 0x2c: /* V9 movcc */ 4485 { 4486 int cc = GET_FIELD_SP(insn, 11, 12); 4487 int cond = GET_FIELD_SP(insn, 14, 17); 4488 DisasCompare cmp; 4489 TCGv dst; 4490 4491 if (insn & (1 << 18)) { 4492 if (cc == 0) { 4493 gen_compare(&cmp, 0, cond, dc); 4494 } else if (cc == 2) { 4495 gen_compare(&cmp, 1, cond, dc); 4496 } else { 4497 goto illegal_insn; 4498 } 4499 } else { 4500 gen_fcompare(&cmp, cc, cond); 4501 } 4502 4503 /* The get_src2 above loaded the normal 13-bit 4504 immediate field, not the 11-bit field we have 4505 in movcc. But it did handle the reg case. */ 4506 if (IS_IMM) { 4507 simm = GET_FIELD_SPs(insn, 0, 10); 4508 tcg_gen_movi_tl(cpu_src2, simm); 4509 } 4510 4511 dst = gen_load_gpr(dc, rd); 4512 tcg_gen_movcond_tl(cmp.cond, dst, 4513 cmp.c1, cmp.c2, 4514 cpu_src2, dst); 4515 gen_store_gpr(dc, rd, dst); 4516 break; 4517 } 4518 case 0x2d: /* V9 sdivx */ 4519 gen_helper_sdivx(cpu_dst, cpu_env, cpu_src1, cpu_src2); 4520 gen_store_gpr(dc, rd, cpu_dst); 4521 break; 4522 case 0x2e: /* V9 popc */ 4523 tcg_gen_ctpop_tl(cpu_dst, cpu_src2); 4524 gen_store_gpr(dc, rd, cpu_dst); 4525 break; 4526 case 0x2f: /* V9 movr */ 4527 { 4528 int cond = GET_FIELD_SP(insn, 10, 12); 4529 DisasCompare cmp; 4530 TCGv dst; 4531 4532 gen_compare_reg(&cmp, cond, cpu_src1); 4533 4534 /* The get_src2 above loaded the normal 13-bit 4535 immediate field, not the 10-bit field we have 4536 in movr. But it did handle the reg case. */ 4537 if (IS_IMM) { 4538 simm = GET_FIELD_SPs(insn, 0, 9); 4539 tcg_gen_movi_tl(cpu_src2, simm); 4540 } 4541 4542 dst = gen_load_gpr(dc, rd); 4543 tcg_gen_movcond_tl(cmp.cond, dst, 4544 cmp.c1, cmp.c2, 4545 cpu_src2, dst); 4546 gen_store_gpr(dc, rd, dst); 4547 break; 4548 } 4549 #endif 4550 default: 4551 goto illegal_insn; 4552 } 4553 } 4554 } else if (xop == 0x36) { /* UltraSparc shutdown, VIS, V8 CPop1 */ 4555 #ifdef TARGET_SPARC64 4556 int opf = GET_FIELD_SP(insn, 5, 13); 4557 rs1 = GET_FIELD(insn, 13, 17); 4558 rs2 = GET_FIELD(insn, 27, 31); 4559 if (gen_trap_ifnofpu(dc)) { 4560 goto jmp_insn; 4561 } 4562 4563 switch (opf) { 4564 case 0x000: /* VIS I edge8cc */ 4565 CHECK_FPU_FEATURE(dc, VIS1); 4566 cpu_src1 = gen_load_gpr(dc, rs1); 4567 cpu_src2 = gen_load_gpr(dc, rs2); 4568 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 8, 1, 0); 4569 gen_store_gpr(dc, rd, cpu_dst); 4570 break; 4571 case 0x001: /* VIS II edge8n */ 4572 CHECK_FPU_FEATURE(dc, VIS2); 4573 cpu_src1 = gen_load_gpr(dc, rs1); 4574 cpu_src2 = gen_load_gpr(dc, rs2); 4575 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 8, 0, 0); 4576 gen_store_gpr(dc, rd, cpu_dst); 4577 break; 4578 case 0x002: /* VIS I edge8lcc */ 4579 CHECK_FPU_FEATURE(dc, VIS1); 4580 cpu_src1 = gen_load_gpr(dc, rs1); 4581 cpu_src2 = gen_load_gpr(dc, rs2); 4582 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 8, 1, 1); 4583 gen_store_gpr(dc, rd, cpu_dst); 4584 break; 4585 case 0x003: /* VIS II edge8ln */ 4586 CHECK_FPU_FEATURE(dc, VIS2); 4587 cpu_src1 = gen_load_gpr(dc, rs1); 4588 cpu_src2 = gen_load_gpr(dc, rs2); 4589 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 8, 0, 1); 4590 gen_store_gpr(dc, rd, cpu_dst); 4591 break; 4592 case 0x004: /* VIS I edge16cc */ 4593 CHECK_FPU_FEATURE(dc, VIS1); 4594 cpu_src1 = gen_load_gpr(dc, rs1); 4595 cpu_src2 = gen_load_gpr(dc, rs2); 4596 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 16, 1, 0); 4597 gen_store_gpr(dc, rd, cpu_dst); 4598 break; 4599 case 0x005: /* VIS II edge16n */ 4600 CHECK_FPU_FEATURE(dc, VIS2); 4601 cpu_src1 = gen_load_gpr(dc, rs1); 4602 cpu_src2 = gen_load_gpr(dc, rs2); 4603 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 16, 0, 0); 4604 gen_store_gpr(dc, rd, cpu_dst); 4605 break; 4606 case 0x006: /* VIS I edge16lcc */ 4607 CHECK_FPU_FEATURE(dc, VIS1); 4608 cpu_src1 = gen_load_gpr(dc, rs1); 4609 cpu_src2 = gen_load_gpr(dc, rs2); 4610 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 16, 1, 1); 4611 gen_store_gpr(dc, rd, cpu_dst); 4612 break; 4613 case 0x007: /* VIS II edge16ln */ 4614 CHECK_FPU_FEATURE(dc, VIS2); 4615 cpu_src1 = gen_load_gpr(dc, rs1); 4616 cpu_src2 = gen_load_gpr(dc, rs2); 4617 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 16, 0, 1); 4618 gen_store_gpr(dc, rd, cpu_dst); 4619 break; 4620 case 0x008: /* VIS I edge32cc */ 4621 CHECK_FPU_FEATURE(dc, VIS1); 4622 cpu_src1 = gen_load_gpr(dc, rs1); 4623 cpu_src2 = gen_load_gpr(dc, rs2); 4624 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 32, 1, 0); 4625 gen_store_gpr(dc, rd, cpu_dst); 4626 break; 4627 case 0x009: /* VIS II edge32n */ 4628 CHECK_FPU_FEATURE(dc, VIS2); 4629 cpu_src1 = gen_load_gpr(dc, rs1); 4630 cpu_src2 = gen_load_gpr(dc, rs2); 4631 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 32, 0, 0); 4632 gen_store_gpr(dc, rd, cpu_dst); 4633 break; 4634 case 0x00a: /* VIS I edge32lcc */ 4635 CHECK_FPU_FEATURE(dc, VIS1); 4636 cpu_src1 = gen_load_gpr(dc, rs1); 4637 cpu_src2 = gen_load_gpr(dc, rs2); 4638 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 32, 1, 1); 4639 gen_store_gpr(dc, rd, cpu_dst); 4640 break; 4641 case 0x00b: /* VIS II edge32ln */ 4642 CHECK_FPU_FEATURE(dc, VIS2); 4643 cpu_src1 = gen_load_gpr(dc, rs1); 4644 cpu_src2 = gen_load_gpr(dc, rs2); 4645 gen_edge(dc, cpu_dst, cpu_src1, cpu_src2, 32, 0, 1); 4646 gen_store_gpr(dc, rd, cpu_dst); 4647 break; 4648 case 0x010: /* VIS I array8 */ 4649 CHECK_FPU_FEATURE(dc, VIS1); 4650 cpu_src1 = gen_load_gpr(dc, rs1); 4651 cpu_src2 = gen_load_gpr(dc, rs2); 4652 gen_helper_array8(cpu_dst, cpu_src1, cpu_src2); 4653 gen_store_gpr(dc, rd, cpu_dst); 4654 break; 4655 case 0x012: /* VIS I array16 */ 4656 CHECK_FPU_FEATURE(dc, VIS1); 4657 cpu_src1 = gen_load_gpr(dc, rs1); 4658 cpu_src2 = gen_load_gpr(dc, rs2); 4659 gen_helper_array8(cpu_dst, cpu_src1, cpu_src2); 4660 tcg_gen_shli_i64(cpu_dst, cpu_dst, 1); 4661 gen_store_gpr(dc, rd, cpu_dst); 4662 break; 4663 case 0x014: /* VIS I array32 */ 4664 CHECK_FPU_FEATURE(dc, VIS1); 4665 cpu_src1 = gen_load_gpr(dc, rs1); 4666 cpu_src2 = gen_load_gpr(dc, rs2); 4667 gen_helper_array8(cpu_dst, cpu_src1, cpu_src2); 4668 tcg_gen_shli_i64(cpu_dst, cpu_dst, 2); 4669 gen_store_gpr(dc, rd, cpu_dst); 4670 break; 4671 case 0x018: /* VIS I alignaddr */ 4672 CHECK_FPU_FEATURE(dc, VIS1); 4673 cpu_src1 = gen_load_gpr(dc, rs1); 4674 cpu_src2 = gen_load_gpr(dc, rs2); 4675 gen_alignaddr(cpu_dst, cpu_src1, cpu_src2, 0); 4676 gen_store_gpr(dc, rd, cpu_dst); 4677 break; 4678 case 0x01a: /* VIS I alignaddrl */ 4679 CHECK_FPU_FEATURE(dc, VIS1); 4680 cpu_src1 = gen_load_gpr(dc, rs1); 4681 cpu_src2 = gen_load_gpr(dc, rs2); 4682 gen_alignaddr(cpu_dst, cpu_src1, cpu_src2, 1); 4683 gen_store_gpr(dc, rd, cpu_dst); 4684 break; 4685 case 0x019: /* VIS II bmask */ 4686 CHECK_FPU_FEATURE(dc, VIS2); 4687 cpu_src1 = gen_load_gpr(dc, rs1); 4688 cpu_src2 = gen_load_gpr(dc, rs2); 4689 tcg_gen_add_tl(cpu_dst, cpu_src1, cpu_src2); 4690 tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, cpu_dst, 32, 32); 4691 gen_store_gpr(dc, rd, cpu_dst); 4692 break; 4693 case 0x020: /* VIS I fcmple16 */ 4694 CHECK_FPU_FEATURE(dc, VIS1); 4695 cpu_src1_64 = gen_load_fpr_D(dc, rs1); 4696 cpu_src2_64 = gen_load_fpr_D(dc, rs2); 4697 gen_helper_fcmple16(cpu_dst, cpu_src1_64, cpu_src2_64); 4698 gen_store_gpr(dc, rd, cpu_dst); 4699 break; 4700 case 0x022: /* VIS I fcmpne16 */ 4701 CHECK_FPU_FEATURE(dc, VIS1); 4702 cpu_src1_64 = gen_load_fpr_D(dc, rs1); 4703 cpu_src2_64 = gen_load_fpr_D(dc, rs2); 4704 gen_helper_fcmpne16(cpu_dst, cpu_src1_64, cpu_src2_64); 4705 gen_store_gpr(dc, rd, cpu_dst); 4706 break; 4707 case 0x024: /* VIS I fcmple32 */ 4708 CHECK_FPU_FEATURE(dc, VIS1); 4709 cpu_src1_64 = gen_load_fpr_D(dc, rs1); 4710 cpu_src2_64 = gen_load_fpr_D(dc, rs2); 4711 gen_helper_fcmple32(cpu_dst, cpu_src1_64, cpu_src2_64); 4712 gen_store_gpr(dc, rd, cpu_dst); 4713 break; 4714 case 0x026: /* VIS I fcmpne32 */ 4715 CHECK_FPU_FEATURE(dc, VIS1); 4716 cpu_src1_64 = gen_load_fpr_D(dc, rs1); 4717 cpu_src2_64 = gen_load_fpr_D(dc, rs2); 4718 gen_helper_fcmpne32(cpu_dst, cpu_src1_64, cpu_src2_64); 4719 gen_store_gpr(dc, rd, cpu_dst); 4720 break; 4721 case 0x028: /* VIS I fcmpgt16 */ 4722 CHECK_FPU_FEATURE(dc, VIS1); 4723 cpu_src1_64 = gen_load_fpr_D(dc, rs1); 4724 cpu_src2_64 = gen_load_fpr_D(dc, rs2); 4725 gen_helper_fcmpgt16(cpu_dst, cpu_src1_64, cpu_src2_64); 4726 gen_store_gpr(dc, rd, cpu_dst); 4727 break; 4728 case 0x02a: /* VIS I fcmpeq16 */ 4729 CHECK_FPU_FEATURE(dc, VIS1); 4730 cpu_src1_64 = gen_load_fpr_D(dc, rs1); 4731 cpu_src2_64 = gen_load_fpr_D(dc, rs2); 4732 gen_helper_fcmpeq16(cpu_dst, cpu_src1_64, cpu_src2_64); 4733 gen_store_gpr(dc, rd, cpu_dst); 4734 break; 4735 case 0x02c: /* VIS I fcmpgt32 */ 4736 CHECK_FPU_FEATURE(dc, VIS1); 4737 cpu_src1_64 = gen_load_fpr_D(dc, rs1); 4738 cpu_src2_64 = gen_load_fpr_D(dc, rs2); 4739 gen_helper_fcmpgt32(cpu_dst, cpu_src1_64, cpu_src2_64); 4740 gen_store_gpr(dc, rd, cpu_dst); 4741 break; 4742 case 0x02e: /* VIS I fcmpeq32 */ 4743 CHECK_FPU_FEATURE(dc, VIS1); 4744 cpu_src1_64 = gen_load_fpr_D(dc, rs1); 4745 cpu_src2_64 = gen_load_fpr_D(dc, rs2); 4746 gen_helper_fcmpeq32(cpu_dst, cpu_src1_64, cpu_src2_64); 4747 gen_store_gpr(dc, rd, cpu_dst); 4748 break; 4749 case 0x031: /* VIS I fmul8x16 */ 4750 CHECK_FPU_FEATURE(dc, VIS1); 4751 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmul8x16); 4752 break; 4753 case 0x033: /* VIS I fmul8x16au */ 4754 CHECK_FPU_FEATURE(dc, VIS1); 4755 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmul8x16au); 4756 break; 4757 case 0x035: /* VIS I fmul8x16al */ 4758 CHECK_FPU_FEATURE(dc, VIS1); 4759 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmul8x16al); 4760 break; 4761 case 0x036: /* VIS I fmul8sux16 */ 4762 CHECK_FPU_FEATURE(dc, VIS1); 4763 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmul8sux16); 4764 break; 4765 case 0x037: /* VIS I fmul8ulx16 */ 4766 CHECK_FPU_FEATURE(dc, VIS1); 4767 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmul8ulx16); 4768 break; 4769 case 0x038: /* VIS I fmuld8sux16 */ 4770 CHECK_FPU_FEATURE(dc, VIS1); 4771 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmuld8sux16); 4772 break; 4773 case 0x039: /* VIS I fmuld8ulx16 */ 4774 CHECK_FPU_FEATURE(dc, VIS1); 4775 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fmuld8ulx16); 4776 break; 4777 case 0x03a: /* VIS I fpack32 */ 4778 CHECK_FPU_FEATURE(dc, VIS1); 4779 gen_gsr_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpack32); 4780 break; 4781 case 0x03b: /* VIS I fpack16 */ 4782 CHECK_FPU_FEATURE(dc, VIS1); 4783 cpu_src1_64 = gen_load_fpr_D(dc, rs2); 4784 cpu_dst_32 = gen_dest_fpr_F(dc); 4785 gen_helper_fpack16(cpu_dst_32, cpu_gsr, cpu_src1_64); 4786 gen_store_fpr_F(dc, rd, cpu_dst_32); 4787 break; 4788 case 0x03d: /* VIS I fpackfix */ 4789 CHECK_FPU_FEATURE(dc, VIS1); 4790 cpu_src1_64 = gen_load_fpr_D(dc, rs2); 4791 cpu_dst_32 = gen_dest_fpr_F(dc); 4792 gen_helper_fpackfix(cpu_dst_32, cpu_gsr, cpu_src1_64); 4793 gen_store_fpr_F(dc, rd, cpu_dst_32); 4794 break; 4795 case 0x03e: /* VIS I pdist */ 4796 CHECK_FPU_FEATURE(dc, VIS1); 4797 gen_ne_fop_DDDD(dc, rd, rs1, rs2, gen_helper_pdist); 4798 break; 4799 case 0x048: /* VIS I faligndata */ 4800 CHECK_FPU_FEATURE(dc, VIS1); 4801 gen_gsr_fop_DDD(dc, rd, rs1, rs2, gen_faligndata); 4802 break; 4803 case 0x04b: /* VIS I fpmerge */ 4804 CHECK_FPU_FEATURE(dc, VIS1); 4805 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpmerge); 4806 break; 4807 case 0x04c: /* VIS II bshuffle */ 4808 CHECK_FPU_FEATURE(dc, VIS2); 4809 gen_gsr_fop_DDD(dc, rd, rs1, rs2, gen_helper_bshuffle); 4810 break; 4811 case 0x04d: /* VIS I fexpand */ 4812 CHECK_FPU_FEATURE(dc, VIS1); 4813 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fexpand); 4814 break; 4815 case 0x050: /* VIS I fpadd16 */ 4816 CHECK_FPU_FEATURE(dc, VIS1); 4817 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpadd16); 4818 break; 4819 case 0x051: /* VIS I fpadd16s */ 4820 CHECK_FPU_FEATURE(dc, VIS1); 4821 gen_ne_fop_FFF(dc, rd, rs1, rs2, gen_helper_fpadd16s); 4822 break; 4823 case 0x052: /* VIS I fpadd32 */ 4824 CHECK_FPU_FEATURE(dc, VIS1); 4825 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpadd32); 4826 break; 4827 case 0x053: /* VIS I fpadd32s */ 4828 CHECK_FPU_FEATURE(dc, VIS1); 4829 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_add_i32); 4830 break; 4831 case 0x054: /* VIS I fpsub16 */ 4832 CHECK_FPU_FEATURE(dc, VIS1); 4833 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpsub16); 4834 break; 4835 case 0x055: /* VIS I fpsub16s */ 4836 CHECK_FPU_FEATURE(dc, VIS1); 4837 gen_ne_fop_FFF(dc, rd, rs1, rs2, gen_helper_fpsub16s); 4838 break; 4839 case 0x056: /* VIS I fpsub32 */ 4840 CHECK_FPU_FEATURE(dc, VIS1); 4841 gen_ne_fop_DDD(dc, rd, rs1, rs2, gen_helper_fpsub32); 4842 break; 4843 case 0x057: /* VIS I fpsub32s */ 4844 CHECK_FPU_FEATURE(dc, VIS1); 4845 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_sub_i32); 4846 break; 4847 case 0x060: /* VIS I fzero */ 4848 CHECK_FPU_FEATURE(dc, VIS1); 4849 cpu_dst_64 = gen_dest_fpr_D(dc, rd); 4850 tcg_gen_movi_i64(cpu_dst_64, 0); 4851 gen_store_fpr_D(dc, rd, cpu_dst_64); 4852 break; 4853 case 0x061: /* VIS I fzeros */ 4854 CHECK_FPU_FEATURE(dc, VIS1); 4855 cpu_dst_32 = gen_dest_fpr_F(dc); 4856 tcg_gen_movi_i32(cpu_dst_32, 0); 4857 gen_store_fpr_F(dc, rd, cpu_dst_32); 4858 break; 4859 case 0x062: /* VIS I fnor */ 4860 CHECK_FPU_FEATURE(dc, VIS1); 4861 gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_nor_i64); 4862 break; 4863 case 0x063: /* VIS I fnors */ 4864 CHECK_FPU_FEATURE(dc, VIS1); 4865 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_nor_i32); 4866 break; 4867 case 0x064: /* VIS I fandnot2 */ 4868 CHECK_FPU_FEATURE(dc, VIS1); 4869 gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_andc_i64); 4870 break; 4871 case 0x065: /* VIS I fandnot2s */ 4872 CHECK_FPU_FEATURE(dc, VIS1); 4873 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_andc_i32); 4874 break; 4875 case 0x066: /* VIS I fnot2 */ 4876 CHECK_FPU_FEATURE(dc, VIS1); 4877 gen_ne_fop_DD(dc, rd, rs2, tcg_gen_not_i64); 4878 break; 4879 case 0x067: /* VIS I fnot2s */ 4880 CHECK_FPU_FEATURE(dc, VIS1); 4881 gen_ne_fop_FF(dc, rd, rs2, tcg_gen_not_i32); 4882 break; 4883 case 0x068: /* VIS I fandnot1 */ 4884 CHECK_FPU_FEATURE(dc, VIS1); 4885 gen_ne_fop_DDD(dc, rd, rs2, rs1, tcg_gen_andc_i64); 4886 break; 4887 case 0x069: /* VIS I fandnot1s */ 4888 CHECK_FPU_FEATURE(dc, VIS1); 4889 gen_ne_fop_FFF(dc, rd, rs2, rs1, tcg_gen_andc_i32); 4890 break; 4891 case 0x06a: /* VIS I fnot1 */ 4892 CHECK_FPU_FEATURE(dc, VIS1); 4893 gen_ne_fop_DD(dc, rd, rs1, tcg_gen_not_i64); 4894 break; 4895 case 0x06b: /* VIS I fnot1s */ 4896 CHECK_FPU_FEATURE(dc, VIS1); 4897 gen_ne_fop_FF(dc, rd, rs1, tcg_gen_not_i32); 4898 break; 4899 case 0x06c: /* VIS I fxor */ 4900 CHECK_FPU_FEATURE(dc, VIS1); 4901 gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_xor_i64); 4902 break; 4903 case 0x06d: /* VIS I fxors */ 4904 CHECK_FPU_FEATURE(dc, VIS1); 4905 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_xor_i32); 4906 break; 4907 case 0x06e: /* VIS I fnand */ 4908 CHECK_FPU_FEATURE(dc, VIS1); 4909 gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_nand_i64); 4910 break; 4911 case 0x06f: /* VIS I fnands */ 4912 CHECK_FPU_FEATURE(dc, VIS1); 4913 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_nand_i32); 4914 break; 4915 case 0x070: /* VIS I fand */ 4916 CHECK_FPU_FEATURE(dc, VIS1); 4917 gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_and_i64); 4918 break; 4919 case 0x071: /* VIS I fands */ 4920 CHECK_FPU_FEATURE(dc, VIS1); 4921 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_and_i32); 4922 break; 4923 case 0x072: /* VIS I fxnor */ 4924 CHECK_FPU_FEATURE(dc, VIS1); 4925 gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_eqv_i64); 4926 break; 4927 case 0x073: /* VIS I fxnors */ 4928 CHECK_FPU_FEATURE(dc, VIS1); 4929 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_eqv_i32); 4930 break; 4931 case 0x074: /* VIS I fsrc1 */ 4932 CHECK_FPU_FEATURE(dc, VIS1); 4933 cpu_src1_64 = gen_load_fpr_D(dc, rs1); 4934 gen_store_fpr_D(dc, rd, cpu_src1_64); 4935 break; 4936 case 0x075: /* VIS I fsrc1s */ 4937 CHECK_FPU_FEATURE(dc, VIS1); 4938 cpu_src1_32 = gen_load_fpr_F(dc, rs1); 4939 gen_store_fpr_F(dc, rd, cpu_src1_32); 4940 break; 4941 case 0x076: /* VIS I fornot2 */ 4942 CHECK_FPU_FEATURE(dc, VIS1); 4943 gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_orc_i64); 4944 break; 4945 case 0x077: /* VIS I fornot2s */ 4946 CHECK_FPU_FEATURE(dc, VIS1); 4947 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_orc_i32); 4948 break; 4949 case 0x078: /* VIS I fsrc2 */ 4950 CHECK_FPU_FEATURE(dc, VIS1); 4951 cpu_src1_64 = gen_load_fpr_D(dc, rs2); 4952 gen_store_fpr_D(dc, rd, cpu_src1_64); 4953 break; 4954 case 0x079: /* VIS I fsrc2s */ 4955 CHECK_FPU_FEATURE(dc, VIS1); 4956 cpu_src1_32 = gen_load_fpr_F(dc, rs2); 4957 gen_store_fpr_F(dc, rd, cpu_src1_32); 4958 break; 4959 case 0x07a: /* VIS I fornot1 */ 4960 CHECK_FPU_FEATURE(dc, VIS1); 4961 gen_ne_fop_DDD(dc, rd, rs2, rs1, tcg_gen_orc_i64); 4962 break; 4963 case 0x07b: /* VIS I fornot1s */ 4964 CHECK_FPU_FEATURE(dc, VIS1); 4965 gen_ne_fop_FFF(dc, rd, rs2, rs1, tcg_gen_orc_i32); 4966 break; 4967 case 0x07c: /* VIS I for */ 4968 CHECK_FPU_FEATURE(dc, VIS1); 4969 gen_ne_fop_DDD(dc, rd, rs1, rs2, tcg_gen_or_i64); 4970 break; 4971 case 0x07d: /* VIS I fors */ 4972 CHECK_FPU_FEATURE(dc, VIS1); 4973 gen_ne_fop_FFF(dc, rd, rs1, rs2, tcg_gen_or_i32); 4974 break; 4975 case 0x07e: /* VIS I fone */ 4976 CHECK_FPU_FEATURE(dc, VIS1); 4977 cpu_dst_64 = gen_dest_fpr_D(dc, rd); 4978 tcg_gen_movi_i64(cpu_dst_64, -1); 4979 gen_store_fpr_D(dc, rd, cpu_dst_64); 4980 break; 4981 case 0x07f: /* VIS I fones */ 4982 CHECK_FPU_FEATURE(dc, VIS1); 4983 cpu_dst_32 = gen_dest_fpr_F(dc); 4984 tcg_gen_movi_i32(cpu_dst_32, -1); 4985 gen_store_fpr_F(dc, rd, cpu_dst_32); 4986 break; 4987 case 0x080: /* VIS I shutdown */ 4988 case 0x081: /* VIS II siam */ 4989 // XXX 4990 goto illegal_insn; 4991 default: 4992 goto illegal_insn; 4993 } 4994 #else 4995 goto ncp_insn; 4996 #endif 4997 } else if (xop == 0x37) { /* V8 CPop2, V9 impdep2 */ 4998 #ifdef TARGET_SPARC64 4999 goto illegal_insn; 5000 #else 5001 goto ncp_insn; 5002 #endif 5003 #ifdef TARGET_SPARC64 5004 } else if (xop == 0x39) { /* V9 return */ 5005 save_state(dc); 5006 cpu_src1 = get_src1(dc, insn); 5007 cpu_tmp0 = tcg_temp_new(); 5008 if (IS_IMM) { /* immediate */ 5009 simm = GET_FIELDs(insn, 19, 31); 5010 tcg_gen_addi_tl(cpu_tmp0, cpu_src1, simm); 5011 } else { /* register */ 5012 rs2 = GET_FIELD(insn, 27, 31); 5013 if (rs2) { 5014 cpu_src2 = gen_load_gpr(dc, rs2); 5015 tcg_gen_add_tl(cpu_tmp0, cpu_src1, cpu_src2); 5016 } else { 5017 tcg_gen_mov_tl(cpu_tmp0, cpu_src1); 5018 } 5019 } 5020 gen_helper_restore(cpu_env); 5021 gen_mov_pc_npc(dc); 5022 gen_check_align(cpu_tmp0, 3); 5023 tcg_gen_mov_tl(cpu_npc, cpu_tmp0); 5024 dc->npc = DYNAMIC_PC; 5025 goto jmp_insn; 5026 #endif 5027 } else { 5028 cpu_src1 = get_src1(dc, insn); 5029 cpu_tmp0 = tcg_temp_new(); 5030 if (IS_IMM) { /* immediate */ 5031 simm = GET_FIELDs(insn, 19, 31); 5032 tcg_gen_addi_tl(cpu_tmp0, cpu_src1, simm); 5033 } else { /* register */ 5034 rs2 = GET_FIELD(insn, 27, 31); 5035 if (rs2) { 5036 cpu_src2 = gen_load_gpr(dc, rs2); 5037 tcg_gen_add_tl(cpu_tmp0, cpu_src1, cpu_src2); 5038 } else { 5039 tcg_gen_mov_tl(cpu_tmp0, cpu_src1); 5040 } 5041 } 5042 switch (xop) { 5043 case 0x38: /* jmpl */ 5044 { 5045 TCGv t = gen_dest_gpr(dc, rd); 5046 tcg_gen_movi_tl(t, dc->pc); 5047 gen_store_gpr(dc, rd, t); 5048 5049 gen_mov_pc_npc(dc); 5050 gen_check_align(cpu_tmp0, 3); 5051 gen_address_mask(dc, cpu_tmp0); 5052 tcg_gen_mov_tl(cpu_npc, cpu_tmp0); 5053 dc->npc = DYNAMIC_PC; 5054 } 5055 goto jmp_insn; 5056 #if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64) 5057 case 0x39: /* rett, V9 return */ 5058 { 5059 if (!supervisor(dc)) 5060 goto priv_insn; 5061 gen_mov_pc_npc(dc); 5062 gen_check_align(cpu_tmp0, 3); 5063 tcg_gen_mov_tl(cpu_npc, cpu_tmp0); 5064 dc->npc = DYNAMIC_PC; 5065 gen_helper_rett(cpu_env); 5066 } 5067 goto jmp_insn; 5068 #endif 5069 case 0x3b: /* flush */ 5070 if (!((dc)->def->features & CPU_FEATURE_FLUSH)) 5071 goto unimp_flush; 5072 /* nop */ 5073 break; 5074 case 0x3c: /* save */ 5075 gen_helper_save(cpu_env); 5076 gen_store_gpr(dc, rd, cpu_tmp0); 5077 break; 5078 case 0x3d: /* restore */ 5079 gen_helper_restore(cpu_env); 5080 gen_store_gpr(dc, rd, cpu_tmp0); 5081 break; 5082 #if !defined(CONFIG_USER_ONLY) && defined(TARGET_SPARC64) 5083 case 0x3e: /* V9 done/retry */ 5084 { 5085 switch (rd) { 5086 case 0: 5087 if (!supervisor(dc)) 5088 goto priv_insn; 5089 dc->npc = DYNAMIC_PC; 5090 dc->pc = DYNAMIC_PC; 5091 translator_io_start(&dc->base); 5092 gen_helper_done(cpu_env); 5093 goto jmp_insn; 5094 case 1: 5095 if (!supervisor(dc)) 5096 goto priv_insn; 5097 dc->npc = DYNAMIC_PC; 5098 dc->pc = DYNAMIC_PC; 5099 translator_io_start(&dc->base); 5100 gen_helper_retry(cpu_env); 5101 goto jmp_insn; 5102 default: 5103 goto illegal_insn; 5104 } 5105 } 5106 break; 5107 #endif 5108 default: 5109 goto illegal_insn; 5110 } 5111 } 5112 break; 5113 } 5114 break; 5115 case 3: /* load/store instructions */ 5116 { 5117 unsigned int xop = GET_FIELD(insn, 7, 12); 5118 /* ??? gen_address_mask prevents us from using a source 5119 register directly. Always generate a temporary. */ 5120 TCGv cpu_addr = tcg_temp_new(); 5121 5122 tcg_gen_mov_tl(cpu_addr, get_src1(dc, insn)); 5123 if (xop == 0x3c || xop == 0x3e) { 5124 /* V9 casa/casxa : no offset */ 5125 } else if (IS_IMM) { /* immediate */ 5126 simm = GET_FIELDs(insn, 19, 31); 5127 if (simm != 0) { 5128 tcg_gen_addi_tl(cpu_addr, cpu_addr, simm); 5129 } 5130 } else { /* register */ 5131 rs2 = GET_FIELD(insn, 27, 31); 5132 if (rs2 != 0) { 5133 tcg_gen_add_tl(cpu_addr, cpu_addr, gen_load_gpr(dc, rs2)); 5134 } 5135 } 5136 if (xop < 4 || (xop > 7 && xop < 0x14 && xop != 0x0e) || 5137 (xop > 0x17 && xop <= 0x1d ) || 5138 (xop > 0x2c && xop <= 0x33) || xop == 0x1f || xop == 0x3d) { 5139 TCGv cpu_val = gen_dest_gpr(dc, rd); 5140 5141 switch (xop) { 5142 case 0x0: /* ld, V9 lduw, load unsigned word */ 5143 gen_address_mask(dc, cpu_addr); 5144 tcg_gen_qemu_ld_tl(cpu_val, cpu_addr, 5145 dc->mem_idx, MO_TEUL | MO_ALIGN); 5146 break; 5147 case 0x1: /* ldub, load unsigned byte */ 5148 gen_address_mask(dc, cpu_addr); 5149 tcg_gen_qemu_ld_tl(cpu_val, cpu_addr, 5150 dc->mem_idx, MO_UB); 5151 break; 5152 case 0x2: /* lduh, load unsigned halfword */ 5153 gen_address_mask(dc, cpu_addr); 5154 tcg_gen_qemu_ld_tl(cpu_val, cpu_addr, 5155 dc->mem_idx, MO_TEUW | MO_ALIGN); 5156 break; 5157 case 0x3: /* ldd, load double word */ 5158 if (rd & 1) 5159 goto illegal_insn; 5160 else { 5161 TCGv_i64 t64; 5162 5163 gen_address_mask(dc, cpu_addr); 5164 t64 = tcg_temp_new_i64(); 5165 tcg_gen_qemu_ld_i64(t64, cpu_addr, 5166 dc->mem_idx, MO_TEUQ | MO_ALIGN); 5167 tcg_gen_trunc_i64_tl(cpu_val, t64); 5168 tcg_gen_ext32u_tl(cpu_val, cpu_val); 5169 gen_store_gpr(dc, rd + 1, cpu_val); 5170 tcg_gen_shri_i64(t64, t64, 32); 5171 tcg_gen_trunc_i64_tl(cpu_val, t64); 5172 tcg_gen_ext32u_tl(cpu_val, cpu_val); 5173 } 5174 break; 5175 case 0x9: /* ldsb, load signed byte */ 5176 gen_address_mask(dc, cpu_addr); 5177 tcg_gen_qemu_ld_tl(cpu_val, cpu_addr, dc->mem_idx, MO_SB); 5178 break; 5179 case 0xa: /* ldsh, load signed halfword */ 5180 gen_address_mask(dc, cpu_addr); 5181 tcg_gen_qemu_ld_tl(cpu_val, cpu_addr, 5182 dc->mem_idx, MO_TESW | MO_ALIGN); 5183 break; 5184 case 0xd: /* ldstub */ 5185 gen_ldstub(dc, cpu_val, cpu_addr, dc->mem_idx); 5186 break; 5187 case 0x0f: 5188 /* swap, swap register with memory. Also atomically */ 5189 CHECK_IU_FEATURE(dc, SWAP); 5190 cpu_src1 = gen_load_gpr(dc, rd); 5191 gen_swap(dc, cpu_val, cpu_src1, cpu_addr, 5192 dc->mem_idx, MO_TEUL); 5193 break; 5194 #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64) 5195 case 0x10: /* lda, V9 lduwa, load word alternate */ 5196 gen_ld_asi(dc, cpu_val, cpu_addr, insn, MO_TEUL); 5197 break; 5198 case 0x11: /* lduba, load unsigned byte alternate */ 5199 gen_ld_asi(dc, cpu_val, cpu_addr, insn, MO_UB); 5200 break; 5201 case 0x12: /* lduha, load unsigned halfword alternate */ 5202 gen_ld_asi(dc, cpu_val, cpu_addr, insn, MO_TEUW); 5203 break; 5204 case 0x13: /* ldda, load double word alternate */ 5205 if (rd & 1) { 5206 goto illegal_insn; 5207 } 5208 gen_ldda_asi(dc, cpu_addr, insn, rd); 5209 goto skip_move; 5210 case 0x19: /* ldsba, load signed byte alternate */ 5211 gen_ld_asi(dc, cpu_val, cpu_addr, insn, MO_SB); 5212 break; 5213 case 0x1a: /* ldsha, load signed halfword alternate */ 5214 gen_ld_asi(dc, cpu_val, cpu_addr, insn, MO_TESW); 5215 break; 5216 case 0x1d: /* ldstuba -- XXX: should be atomically */ 5217 gen_ldstub_asi(dc, cpu_val, cpu_addr, insn); 5218 break; 5219 case 0x1f: /* swapa, swap reg with alt. memory. Also 5220 atomically */ 5221 CHECK_IU_FEATURE(dc, SWAP); 5222 cpu_src1 = gen_load_gpr(dc, rd); 5223 gen_swap_asi(dc, cpu_val, cpu_src1, cpu_addr, insn); 5224 break; 5225 5226 #ifndef TARGET_SPARC64 5227 case 0x30: /* ldc */ 5228 case 0x31: /* ldcsr */ 5229 case 0x33: /* lddc */ 5230 goto ncp_insn; 5231 #endif 5232 #endif 5233 #ifdef TARGET_SPARC64 5234 case 0x08: /* V9 ldsw */ 5235 gen_address_mask(dc, cpu_addr); 5236 tcg_gen_qemu_ld_tl(cpu_val, cpu_addr, 5237 dc->mem_idx, MO_TESL | MO_ALIGN); 5238 break; 5239 case 0x0b: /* V9 ldx */ 5240 gen_address_mask(dc, cpu_addr); 5241 tcg_gen_qemu_ld_tl(cpu_val, cpu_addr, 5242 dc->mem_idx, MO_TEUQ | MO_ALIGN); 5243 break; 5244 case 0x18: /* V9 ldswa */ 5245 gen_ld_asi(dc, cpu_val, cpu_addr, insn, MO_TESL); 5246 break; 5247 case 0x1b: /* V9 ldxa */ 5248 gen_ld_asi(dc, cpu_val, cpu_addr, insn, MO_TEUQ); 5249 break; 5250 case 0x2d: /* V9 prefetch, no effect */ 5251 goto skip_move; 5252 case 0x30: /* V9 ldfa */ 5253 if (gen_trap_ifnofpu(dc)) { 5254 goto jmp_insn; 5255 } 5256 gen_ldf_asi(dc, cpu_addr, insn, 4, rd); 5257 gen_update_fprs_dirty(dc, rd); 5258 goto skip_move; 5259 case 0x33: /* V9 lddfa */ 5260 if (gen_trap_ifnofpu(dc)) { 5261 goto jmp_insn; 5262 } 5263 gen_ldf_asi(dc, cpu_addr, insn, 8, DFPREG(rd)); 5264 gen_update_fprs_dirty(dc, DFPREG(rd)); 5265 goto skip_move; 5266 case 0x3d: /* V9 prefetcha, no effect */ 5267 goto skip_move; 5268 case 0x32: /* V9 ldqfa */ 5269 CHECK_FPU_FEATURE(dc, FLOAT128); 5270 if (gen_trap_ifnofpu(dc)) { 5271 goto jmp_insn; 5272 } 5273 gen_ldf_asi(dc, cpu_addr, insn, 16, QFPREG(rd)); 5274 gen_update_fprs_dirty(dc, QFPREG(rd)); 5275 goto skip_move; 5276 #endif 5277 default: 5278 goto illegal_insn; 5279 } 5280 gen_store_gpr(dc, rd, cpu_val); 5281 #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64) 5282 skip_move: ; 5283 #endif 5284 } else if (xop >= 0x20 && xop < 0x24) { 5285 if (gen_trap_ifnofpu(dc)) { 5286 goto jmp_insn; 5287 } 5288 switch (xop) { 5289 case 0x20: /* ldf, load fpreg */ 5290 gen_address_mask(dc, cpu_addr); 5291 cpu_dst_32 = gen_dest_fpr_F(dc); 5292 tcg_gen_qemu_ld_i32(cpu_dst_32, cpu_addr, 5293 dc->mem_idx, MO_TEUL | MO_ALIGN); 5294 gen_store_fpr_F(dc, rd, cpu_dst_32); 5295 break; 5296 case 0x21: /* ldfsr, V9 ldxfsr */ 5297 #ifdef TARGET_SPARC64 5298 gen_address_mask(dc, cpu_addr); 5299 if (rd == 1) { 5300 TCGv_i64 t64 = tcg_temp_new_i64(); 5301 tcg_gen_qemu_ld_i64(t64, cpu_addr, 5302 dc->mem_idx, MO_TEUQ | MO_ALIGN); 5303 gen_helper_ldxfsr(cpu_fsr, cpu_env, cpu_fsr, t64); 5304 break; 5305 } 5306 #endif 5307 cpu_dst_32 = tcg_temp_new_i32(); 5308 tcg_gen_qemu_ld_i32(cpu_dst_32, cpu_addr, 5309 dc->mem_idx, MO_TEUL | MO_ALIGN); 5310 gen_helper_ldfsr(cpu_fsr, cpu_env, cpu_fsr, cpu_dst_32); 5311 break; 5312 case 0x22: /* ldqf, load quad fpreg */ 5313 CHECK_FPU_FEATURE(dc, FLOAT128); 5314 gen_address_mask(dc, cpu_addr); 5315 cpu_src1_64 = tcg_temp_new_i64(); 5316 tcg_gen_qemu_ld_i64(cpu_src1_64, cpu_addr, dc->mem_idx, 5317 MO_TEUQ | MO_ALIGN_4); 5318 tcg_gen_addi_tl(cpu_addr, cpu_addr, 8); 5319 cpu_src2_64 = tcg_temp_new_i64(); 5320 tcg_gen_qemu_ld_i64(cpu_src2_64, cpu_addr, dc->mem_idx, 5321 MO_TEUQ | MO_ALIGN_4); 5322 gen_store_fpr_Q(dc, rd, cpu_src1_64, cpu_src2_64); 5323 break; 5324 case 0x23: /* lddf, load double fpreg */ 5325 gen_address_mask(dc, cpu_addr); 5326 cpu_dst_64 = gen_dest_fpr_D(dc, rd); 5327 tcg_gen_qemu_ld_i64(cpu_dst_64, cpu_addr, dc->mem_idx, 5328 MO_TEUQ | MO_ALIGN_4); 5329 gen_store_fpr_D(dc, rd, cpu_dst_64); 5330 break; 5331 default: 5332 goto illegal_insn; 5333 } 5334 } else if (xop < 8 || (xop >= 0x14 && xop < 0x18) || 5335 xop == 0xe || xop == 0x1e) { 5336 TCGv cpu_val = gen_load_gpr(dc, rd); 5337 5338 switch (xop) { 5339 case 0x4: /* st, store word */ 5340 gen_address_mask(dc, cpu_addr); 5341 tcg_gen_qemu_st_tl(cpu_val, cpu_addr, 5342 dc->mem_idx, MO_TEUL | MO_ALIGN); 5343 break; 5344 case 0x5: /* stb, store byte */ 5345 gen_address_mask(dc, cpu_addr); 5346 tcg_gen_qemu_st_tl(cpu_val, cpu_addr, dc->mem_idx, MO_UB); 5347 break; 5348 case 0x6: /* sth, store halfword */ 5349 gen_address_mask(dc, cpu_addr); 5350 tcg_gen_qemu_st_tl(cpu_val, cpu_addr, 5351 dc->mem_idx, MO_TEUW | MO_ALIGN); 5352 break; 5353 case 0x7: /* std, store double word */ 5354 if (rd & 1) 5355 goto illegal_insn; 5356 else { 5357 TCGv_i64 t64; 5358 TCGv lo; 5359 5360 gen_address_mask(dc, cpu_addr); 5361 lo = gen_load_gpr(dc, rd + 1); 5362 t64 = tcg_temp_new_i64(); 5363 tcg_gen_concat_tl_i64(t64, lo, cpu_val); 5364 tcg_gen_qemu_st_i64(t64, cpu_addr, 5365 dc->mem_idx, MO_TEUQ | MO_ALIGN); 5366 } 5367 break; 5368 #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64) 5369 case 0x14: /* sta, V9 stwa, store word alternate */ 5370 gen_st_asi(dc, cpu_val, cpu_addr, insn, MO_TEUL); 5371 break; 5372 case 0x15: /* stba, store byte alternate */ 5373 gen_st_asi(dc, cpu_val, cpu_addr, insn, MO_UB); 5374 break; 5375 case 0x16: /* stha, store halfword alternate */ 5376 gen_st_asi(dc, cpu_val, cpu_addr, insn, MO_TEUW); 5377 break; 5378 case 0x17: /* stda, store double word alternate */ 5379 if (rd & 1) { 5380 goto illegal_insn; 5381 } 5382 gen_stda_asi(dc, cpu_val, cpu_addr, insn, rd); 5383 break; 5384 #endif 5385 #ifdef TARGET_SPARC64 5386 case 0x0e: /* V9 stx */ 5387 gen_address_mask(dc, cpu_addr); 5388 tcg_gen_qemu_st_tl(cpu_val, cpu_addr, 5389 dc->mem_idx, MO_TEUQ | MO_ALIGN); 5390 break; 5391 case 0x1e: /* V9 stxa */ 5392 gen_st_asi(dc, cpu_val, cpu_addr, insn, MO_TEUQ); 5393 break; 5394 #endif 5395 default: 5396 goto illegal_insn; 5397 } 5398 } else if (xop > 0x23 && xop < 0x28) { 5399 if (gen_trap_ifnofpu(dc)) { 5400 goto jmp_insn; 5401 } 5402 switch (xop) { 5403 case 0x24: /* stf, store fpreg */ 5404 gen_address_mask(dc, cpu_addr); 5405 cpu_src1_32 = gen_load_fpr_F(dc, rd); 5406 tcg_gen_qemu_st_i32(cpu_src1_32, cpu_addr, 5407 dc->mem_idx, MO_TEUL | MO_ALIGN); 5408 break; 5409 case 0x25: /* stfsr, V9 stxfsr */ 5410 { 5411 #ifdef TARGET_SPARC64 5412 gen_address_mask(dc, cpu_addr); 5413 if (rd == 1) { 5414 tcg_gen_qemu_st_tl(cpu_fsr, cpu_addr, 5415 dc->mem_idx, MO_TEUQ | MO_ALIGN); 5416 break; 5417 } 5418 #endif 5419 tcg_gen_qemu_st_tl(cpu_fsr, cpu_addr, 5420 dc->mem_idx, MO_TEUL | MO_ALIGN); 5421 } 5422 break; 5423 case 0x26: 5424 #ifdef TARGET_SPARC64 5425 /* V9 stqf, store quad fpreg */ 5426 CHECK_FPU_FEATURE(dc, FLOAT128); 5427 gen_address_mask(dc, cpu_addr); 5428 /* ??? While stqf only requires 4-byte alignment, it is 5429 legal for the cpu to signal the unaligned exception. 5430 The OS trap handler is then required to fix it up. 5431 For qemu, this avoids having to probe the second page 5432 before performing the first write. */ 5433 cpu_src1_64 = gen_load_fpr_Q0(dc, rd); 5434 tcg_gen_qemu_st_i64(cpu_src1_64, cpu_addr, 5435 dc->mem_idx, MO_TEUQ | MO_ALIGN_16); 5436 tcg_gen_addi_tl(cpu_addr, cpu_addr, 8); 5437 cpu_src2_64 = gen_load_fpr_Q1(dc, rd); 5438 tcg_gen_qemu_st_i64(cpu_src1_64, cpu_addr, 5439 dc->mem_idx, MO_TEUQ); 5440 break; 5441 #else /* !TARGET_SPARC64 */ 5442 /* stdfq, store floating point queue */ 5443 #if defined(CONFIG_USER_ONLY) 5444 goto illegal_insn; 5445 #else 5446 if (!supervisor(dc)) 5447 goto priv_insn; 5448 if (gen_trap_ifnofpu(dc)) { 5449 goto jmp_insn; 5450 } 5451 goto nfq_insn; 5452 #endif 5453 #endif 5454 case 0x27: /* stdf, store double fpreg */ 5455 gen_address_mask(dc, cpu_addr); 5456 cpu_src1_64 = gen_load_fpr_D(dc, rd); 5457 tcg_gen_qemu_st_i64(cpu_src1_64, cpu_addr, dc->mem_idx, 5458 MO_TEUQ | MO_ALIGN_4); 5459 break; 5460 default: 5461 goto illegal_insn; 5462 } 5463 } else if (xop > 0x33 && xop < 0x3f) { 5464 switch (xop) { 5465 #ifdef TARGET_SPARC64 5466 case 0x34: /* V9 stfa */ 5467 if (gen_trap_ifnofpu(dc)) { 5468 goto jmp_insn; 5469 } 5470 gen_stf_asi(dc, cpu_addr, insn, 4, rd); 5471 break; 5472 case 0x36: /* V9 stqfa */ 5473 { 5474 CHECK_FPU_FEATURE(dc, FLOAT128); 5475 if (gen_trap_ifnofpu(dc)) { 5476 goto jmp_insn; 5477 } 5478 gen_stf_asi(dc, cpu_addr, insn, 16, QFPREG(rd)); 5479 } 5480 break; 5481 case 0x37: /* V9 stdfa */ 5482 if (gen_trap_ifnofpu(dc)) { 5483 goto jmp_insn; 5484 } 5485 gen_stf_asi(dc, cpu_addr, insn, 8, DFPREG(rd)); 5486 break; 5487 case 0x3e: /* V9 casxa */ 5488 rs2 = GET_FIELD(insn, 27, 31); 5489 cpu_src2 = gen_load_gpr(dc, rs2); 5490 gen_casx_asi(dc, cpu_addr, cpu_src2, insn, rd); 5491 break; 5492 #else 5493 case 0x34: /* stc */ 5494 case 0x35: /* stcsr */ 5495 case 0x36: /* stdcq */ 5496 case 0x37: /* stdc */ 5497 goto ncp_insn; 5498 #endif 5499 #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64) 5500 case 0x3c: /* V9 or LEON3 casa */ 5501 #ifndef TARGET_SPARC64 5502 CHECK_IU_FEATURE(dc, CASA); 5503 #endif 5504 rs2 = GET_FIELD(insn, 27, 31); 5505 cpu_src2 = gen_load_gpr(dc, rs2); 5506 gen_cas_asi(dc, cpu_addr, cpu_src2, insn, rd); 5507 break; 5508 #endif 5509 default: 5510 goto illegal_insn; 5511 } 5512 } else { 5513 goto illegal_insn; 5514 } 5515 } 5516 break; 5517 } 5518 /* default case for non jump instructions */ 5519 if (dc->npc == DYNAMIC_PC) { 5520 dc->pc = DYNAMIC_PC; 5521 gen_op_next_insn(); 5522 } else if (dc->npc == JUMP_PC) { 5523 /* we can do a static jump */ 5524 gen_branch2(dc, dc->jump_pc[0], dc->jump_pc[1], cpu_cond); 5525 dc->base.is_jmp = DISAS_NORETURN; 5526 } else { 5527 dc->pc = dc->npc; 5528 dc->npc = dc->npc + 4; 5529 } 5530 jmp_insn: 5531 return; 5532 illegal_insn: 5533 gen_exception(dc, TT_ILL_INSN); 5534 return; 5535 unimp_flush: 5536 gen_exception(dc, TT_UNIMP_FLUSH); 5537 return; 5538 #if !defined(CONFIG_USER_ONLY) 5539 priv_insn: 5540 gen_exception(dc, TT_PRIV_INSN); 5541 return; 5542 #endif 5543 nfpu_insn: 5544 gen_op_fpexception_im(dc, FSR_FTT_UNIMPFPOP); 5545 return; 5546 #if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64) 5547 nfq_insn: 5548 gen_op_fpexception_im(dc, FSR_FTT_SEQ_ERROR); 5549 return; 5550 #endif 5551 #ifndef TARGET_SPARC64 5552 ncp_insn: 5553 gen_exception(dc, TT_NCP_INSN); 5554 return; 5555 #endif 5556 } 5557 5558 static void sparc_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) 5559 { 5560 DisasContext *dc = container_of(dcbase, DisasContext, base); 5561 CPUSPARCState *env = cs->env_ptr; 5562 int bound; 5563 5564 dc->pc = dc->base.pc_first; 5565 dc->npc = (target_ulong)dc->base.tb->cs_base; 5566 dc->cc_op = CC_OP_DYNAMIC; 5567 dc->mem_idx = dc->base.tb->flags & TB_FLAG_MMU_MASK; 5568 dc->def = &env->def; 5569 dc->fpu_enabled = tb_fpu_enabled(dc->base.tb->flags); 5570 dc->address_mask_32bit = tb_am_enabled(dc->base.tb->flags); 5571 #ifndef CONFIG_USER_ONLY 5572 dc->supervisor = (dc->base.tb->flags & TB_FLAG_SUPER) != 0; 5573 #endif 5574 #ifdef TARGET_SPARC64 5575 dc->fprs_dirty = 0; 5576 dc->asi = (dc->base.tb->flags >> TB_FLAG_ASI_SHIFT) & 0xff; 5577 #ifndef CONFIG_USER_ONLY 5578 dc->hypervisor = (dc->base.tb->flags & TB_FLAG_HYPER) != 0; 5579 #endif 5580 #endif 5581 /* 5582 * if we reach a page boundary, we stop generation so that the 5583 * PC of a TT_TFAULT exception is always in the right page 5584 */ 5585 bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4; 5586 dc->base.max_insns = MIN(dc->base.max_insns, bound); 5587 } 5588 5589 static void sparc_tr_tb_start(DisasContextBase *db, CPUState *cs) 5590 { 5591 } 5592 5593 static void sparc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) 5594 { 5595 DisasContext *dc = container_of(dcbase, DisasContext, base); 5596 5597 if (dc->npc & JUMP_PC) { 5598 assert(dc->jump_pc[1] == dc->pc + 4); 5599 tcg_gen_insn_start(dc->pc, dc->jump_pc[0] | JUMP_PC); 5600 } else { 5601 tcg_gen_insn_start(dc->pc, dc->npc); 5602 } 5603 } 5604 5605 static void sparc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) 5606 { 5607 DisasContext *dc = container_of(dcbase, DisasContext, base); 5608 CPUSPARCState *env = cs->env_ptr; 5609 unsigned int insn; 5610 5611 insn = translator_ldl(env, &dc->base, dc->pc); 5612 dc->base.pc_next += 4; 5613 disas_sparc_insn(dc, insn); 5614 5615 if (dc->base.is_jmp == DISAS_NORETURN) { 5616 return; 5617 } 5618 if (dc->pc != dc->base.pc_next) { 5619 dc->base.is_jmp = DISAS_TOO_MANY; 5620 } 5621 } 5622 5623 static void sparc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) 5624 { 5625 DisasContext *dc = container_of(dcbase, DisasContext, base); 5626 5627 switch (dc->base.is_jmp) { 5628 case DISAS_NEXT: 5629 case DISAS_TOO_MANY: 5630 if (dc->pc != DYNAMIC_PC && 5631 (dc->npc != DYNAMIC_PC && dc->npc != JUMP_PC)) { 5632 /* static PC and NPC: we can use direct chaining */ 5633 gen_goto_tb(dc, 0, dc->pc, dc->npc); 5634 } else { 5635 if (dc->pc != DYNAMIC_PC) { 5636 tcg_gen_movi_tl(cpu_pc, dc->pc); 5637 } 5638 save_npc(dc); 5639 tcg_gen_exit_tb(NULL, 0); 5640 } 5641 break; 5642 5643 case DISAS_NORETURN: 5644 break; 5645 5646 case DISAS_EXIT: 5647 /* Exit TB */ 5648 save_state(dc); 5649 tcg_gen_exit_tb(NULL, 0); 5650 break; 5651 5652 default: 5653 g_assert_not_reached(); 5654 } 5655 } 5656 5657 static void sparc_tr_disas_log(const DisasContextBase *dcbase, 5658 CPUState *cpu, FILE *logfile) 5659 { 5660 fprintf(logfile, "IN: %s\n", lookup_symbol(dcbase->pc_first)); 5661 target_disas(logfile, cpu, dcbase->pc_first, dcbase->tb->size); 5662 } 5663 5664 static const TranslatorOps sparc_tr_ops = { 5665 .init_disas_context = sparc_tr_init_disas_context, 5666 .tb_start = sparc_tr_tb_start, 5667 .insn_start = sparc_tr_insn_start, 5668 .translate_insn = sparc_tr_translate_insn, 5669 .tb_stop = sparc_tr_tb_stop, 5670 .disas_log = sparc_tr_disas_log, 5671 }; 5672 5673 void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int *max_insns, 5674 target_ulong pc, void *host_pc) 5675 { 5676 DisasContext dc = {}; 5677 5678 translator_loop(cs, tb, max_insns, pc, host_pc, &sparc_tr_ops, &dc.base); 5679 } 5680 5681 void sparc_tcg_init(void) 5682 { 5683 static const char gregnames[32][4] = { 5684 "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7", 5685 "o0", "o1", "o2", "o3", "o4", "o5", "o6", "o7", 5686 "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7", 5687 "i0", "i1", "i2", "i3", "i4", "i5", "i6", "i7", 5688 }; 5689 static const char fregnames[32][4] = { 5690 "f0", "f2", "f4", "f6", "f8", "f10", "f12", "f14", 5691 "f16", "f18", "f20", "f22", "f24", "f26", "f28", "f30", 5692 "f32", "f34", "f36", "f38", "f40", "f42", "f44", "f46", 5693 "f48", "f50", "f52", "f54", "f56", "f58", "f60", "f62", 5694 }; 5695 5696 static const struct { TCGv_i32 *ptr; int off; const char *name; } r32[] = { 5697 #ifdef TARGET_SPARC64 5698 { &cpu_xcc, offsetof(CPUSPARCState, xcc), "xcc" }, 5699 { &cpu_fprs, offsetof(CPUSPARCState, fprs), "fprs" }, 5700 #else 5701 { &cpu_wim, offsetof(CPUSPARCState, wim), "wim" }, 5702 #endif 5703 { &cpu_cc_op, offsetof(CPUSPARCState, cc_op), "cc_op" }, 5704 { &cpu_psr, offsetof(CPUSPARCState, psr), "psr" }, 5705 }; 5706 5707 static const struct { TCGv *ptr; int off; const char *name; } rtl[] = { 5708 #ifdef TARGET_SPARC64 5709 { &cpu_gsr, offsetof(CPUSPARCState, gsr), "gsr" }, 5710 { &cpu_tick_cmpr, offsetof(CPUSPARCState, tick_cmpr), "tick_cmpr" }, 5711 { &cpu_stick_cmpr, offsetof(CPUSPARCState, stick_cmpr), "stick_cmpr" }, 5712 { &cpu_hstick_cmpr, offsetof(CPUSPARCState, hstick_cmpr), 5713 "hstick_cmpr" }, 5714 { &cpu_hintp, offsetof(CPUSPARCState, hintp), "hintp" }, 5715 { &cpu_htba, offsetof(CPUSPARCState, htba), "htba" }, 5716 { &cpu_hver, offsetof(CPUSPARCState, hver), "hver" }, 5717 { &cpu_ssr, offsetof(CPUSPARCState, ssr), "ssr" }, 5718 { &cpu_ver, offsetof(CPUSPARCState, version), "ver" }, 5719 #endif 5720 { &cpu_cond, offsetof(CPUSPARCState, cond), "cond" }, 5721 { &cpu_cc_src, offsetof(CPUSPARCState, cc_src), "cc_src" }, 5722 { &cpu_cc_src2, offsetof(CPUSPARCState, cc_src2), "cc_src2" }, 5723 { &cpu_cc_dst, offsetof(CPUSPARCState, cc_dst), "cc_dst" }, 5724 { &cpu_fsr, offsetof(CPUSPARCState, fsr), "fsr" }, 5725 { &cpu_pc, offsetof(CPUSPARCState, pc), "pc" }, 5726 { &cpu_npc, offsetof(CPUSPARCState, npc), "npc" }, 5727 { &cpu_y, offsetof(CPUSPARCState, y), "y" }, 5728 #ifndef CONFIG_USER_ONLY 5729 { &cpu_tbr, offsetof(CPUSPARCState, tbr), "tbr" }, 5730 #endif 5731 }; 5732 5733 unsigned int i; 5734 5735 cpu_regwptr = tcg_global_mem_new_ptr(cpu_env, 5736 offsetof(CPUSPARCState, regwptr), 5737 "regwptr"); 5738 5739 for (i = 0; i < ARRAY_SIZE(r32); ++i) { 5740 *r32[i].ptr = tcg_global_mem_new_i32(cpu_env, r32[i].off, r32[i].name); 5741 } 5742 5743 for (i = 0; i < ARRAY_SIZE(rtl); ++i) { 5744 *rtl[i].ptr = tcg_global_mem_new(cpu_env, rtl[i].off, rtl[i].name); 5745 } 5746 5747 cpu_regs[0] = NULL; 5748 for (i = 1; i < 8; ++i) { 5749 cpu_regs[i] = tcg_global_mem_new(cpu_env, 5750 offsetof(CPUSPARCState, gregs[i]), 5751 gregnames[i]); 5752 } 5753 5754 for (i = 8; i < 32; ++i) { 5755 cpu_regs[i] = tcg_global_mem_new(cpu_regwptr, 5756 (i - 8) * sizeof(target_ulong), 5757 gregnames[i]); 5758 } 5759 5760 for (i = 0; i < TARGET_DPREGS; i++) { 5761 cpu_fpr[i] = tcg_global_mem_new_i64(cpu_env, 5762 offsetof(CPUSPARCState, fpr[i]), 5763 fregnames[i]); 5764 } 5765 } 5766 5767 void sparc_restore_state_to_opc(CPUState *cs, 5768 const TranslationBlock *tb, 5769 const uint64_t *data) 5770 { 5771 SPARCCPU *cpu = SPARC_CPU(cs); 5772 CPUSPARCState *env = &cpu->env; 5773 target_ulong pc = data[0]; 5774 target_ulong npc = data[1]; 5775 5776 env->pc = pc; 5777 if (npc == DYNAMIC_PC) { 5778 /* dynamic NPC: already stored */ 5779 } else if (npc & JUMP_PC) { 5780 /* jump PC: use 'cond' and the jump targets of the translation */ 5781 if (env->cond) { 5782 env->npc = npc & ~3; 5783 } else { 5784 env->npc = pc + 4; 5785 } 5786 } else { 5787 env->npc = npc; 5788 } 5789 } 5790