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