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