1fcf5ef2aSThomas Huth /* 2fcf5ef2aSThomas Huth SPARC translation 3fcf5ef2aSThomas Huth 4fcf5ef2aSThomas Huth Copyright (C) 2003 Thomas M. Ogrisegg <tom@fnord.at> 5fcf5ef2aSThomas Huth Copyright (C) 2003-2005 Fabrice Bellard 6fcf5ef2aSThomas Huth 7fcf5ef2aSThomas Huth This library is free software; you can redistribute it and/or 8fcf5ef2aSThomas Huth modify it under the terms of the GNU Lesser General Public 9fcf5ef2aSThomas Huth License as published by the Free Software Foundation; either 105650b549SChetan Pant version 2.1 of the License, or (at your option) any later version. 11fcf5ef2aSThomas Huth 12fcf5ef2aSThomas Huth This library is distributed in the hope that it will be useful, 13fcf5ef2aSThomas Huth but WITHOUT ANY WARRANTY; without even the implied warranty of 14fcf5ef2aSThomas Huth MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15fcf5ef2aSThomas Huth Lesser General Public License for more details. 16fcf5ef2aSThomas Huth 17fcf5ef2aSThomas Huth You should have received a copy of the GNU Lesser General Public 18fcf5ef2aSThomas Huth License along with this library; if not, see <http://www.gnu.org/licenses/>. 19fcf5ef2aSThomas Huth */ 20fcf5ef2aSThomas Huth 21fcf5ef2aSThomas Huth #include "qemu/osdep.h" 22fcf5ef2aSThomas Huth 23fcf5ef2aSThomas Huth #include "cpu.h" 24fcf5ef2aSThomas Huth #include "exec/helper-proto.h" 25fcf5ef2aSThomas Huth #include "exec/exec-all.h" 26dcb32f1dSPhilippe Mathieu-Daudé #include "tcg/tcg-op.h" 27fafba1bbSRichard Henderson #include "tcg/tcg-op-gvec.h" 28fcf5ef2aSThomas Huth #include "exec/helper-gen.h" 29c5e6ccdfSEmilio G. Cota #include "exec/translator.h" 30fcf5ef2aSThomas Huth #include "exec/log.h" 31fcf5ef2aSThomas Huth #include "asi.h" 32fcf5ef2aSThomas Huth 33d53106c9SRichard Henderson #define HELPER_H "helper.h" 34d53106c9SRichard Henderson #include "exec/helper-info.c.inc" 35d53106c9SRichard Henderson #undef HELPER_H 36fcf5ef2aSThomas Huth 37668bb9b7SRichard Henderson #ifdef TARGET_SPARC64 38668bb9b7SRichard Henderson # define gen_helper_rdpsr(D, E) qemu_build_not_reached() 39c92948f2SClément Chigot # define gen_helper_rdasr17(D, E) qemu_build_not_reached() 4086b82fe0SRichard Henderson # define gen_helper_rett(E) qemu_build_not_reached() 410faef01bSRichard Henderson # define gen_helper_power_down(E) qemu_build_not_reached() 4225524734SRichard Henderson # define gen_helper_wrpsr(E, S) qemu_build_not_reached() 43668bb9b7SRichard Henderson #else 440faef01bSRichard Henderson # define gen_helper_clear_softint(E, S) qemu_build_not_reached() 458f75b8a4SRichard Henderson # define gen_helper_done(E) qemu_build_not_reached() 46e8325dc0SRichard Henderson # define gen_helper_flushw(E) qemu_build_not_reached() 47a859602cSRichard Henderson # define gen_helper_fmul8x16a(D, S1, S2) qemu_build_not_reached() 48af25071cSRichard Henderson # define gen_helper_rdccr(D, E) qemu_build_not_reached() 495d617bfbSRichard Henderson # define gen_helper_rdcwp(D, E) qemu_build_not_reached() 5025524734SRichard Henderson # define gen_helper_restored(E) qemu_build_not_reached() 518f75b8a4SRichard Henderson # define gen_helper_retry(E) qemu_build_not_reached() 5225524734SRichard Henderson # define gen_helper_saved(E) qemu_build_not_reached() 530faef01bSRichard Henderson # define gen_helper_set_softint(E, S) qemu_build_not_reached() 54af25071cSRichard Henderson # define gen_helper_tick_get_count(D, E, T, C) qemu_build_not_reached() 559422278eSRichard Henderson # define gen_helper_tick_set_count(P, S) qemu_build_not_reached() 56bb97f2f5SRichard Henderson # define gen_helper_tick_set_limit(P, S) qemu_build_not_reached() 570faef01bSRichard Henderson # define gen_helper_wrccr(E, S) qemu_build_not_reached() 589422278eSRichard Henderson # define gen_helper_wrcwp(E, S) qemu_build_not_reached() 599422278eSRichard Henderson # define gen_helper_wrgl(E, S) qemu_build_not_reached() 600faef01bSRichard Henderson # define gen_helper_write_softint(E, S) qemu_build_not_reached() 619422278eSRichard Henderson # define gen_helper_wrpil(E, S) qemu_build_not_reached() 629422278eSRichard Henderson # define gen_helper_wrpstate(E, S) qemu_build_not_reached() 63e2fa6bd1SRichard Henderson # define gen_helper_fcmpeq16 ({ qemu_build_not_reached(); NULL; }) 64e2fa6bd1SRichard Henderson # define gen_helper_fcmpeq32 ({ qemu_build_not_reached(); NULL; }) 65e2fa6bd1SRichard Henderson # define gen_helper_fcmpgt16 ({ qemu_build_not_reached(); NULL; }) 66e2fa6bd1SRichard Henderson # define gen_helper_fcmpgt32 ({ qemu_build_not_reached(); NULL; }) 67e2fa6bd1SRichard Henderson # define gen_helper_fcmple16 ({ qemu_build_not_reached(); NULL; }) 68e2fa6bd1SRichard Henderson # define gen_helper_fcmple32 ({ qemu_build_not_reached(); NULL; }) 69e2fa6bd1SRichard Henderson # define gen_helper_fcmpne16 ({ qemu_build_not_reached(); NULL; }) 70e2fa6bd1SRichard Henderson # define gen_helper_fcmpne32 ({ qemu_build_not_reached(); NULL; }) 718aa418b3SRichard Henderson # define gen_helper_fdtox ({ qemu_build_not_reached(); NULL; }) 72e06c9f83SRichard Henderson # define gen_helper_fexpand ({ qemu_build_not_reached(); NULL; }) 73e06c9f83SRichard Henderson # define gen_helper_fmul8sux16 ({ qemu_build_not_reached(); NULL; }) 74e06c9f83SRichard Henderson # define gen_helper_fmul8ulx16 ({ qemu_build_not_reached(); NULL; }) 75e06c9f83SRichard Henderson # define gen_helper_fmul8x16 ({ qemu_build_not_reached(); NULL; }) 76e06c9f83SRichard Henderson # define gen_helper_fpmerge ({ qemu_build_not_reached(); NULL; }) 771617586fSRichard Henderson # define gen_helper_fqtox ({ qemu_build_not_reached(); NULL; }) 78199d43efSRichard Henderson # define gen_helper_fstox ({ qemu_build_not_reached(); NULL; }) 798aa418b3SRichard Henderson # define gen_helper_fxtod ({ qemu_build_not_reached(); NULL; }) 807b8e3e1aSRichard Henderson # define gen_helper_fxtoq ({ qemu_build_not_reached(); NULL; }) 81f4e18df5SRichard Henderson # define gen_helper_fxtos ({ qemu_build_not_reached(); NULL; }) 82afb04344SRichard Henderson # define gen_helper_pdist ({ qemu_build_not_reached(); NULL; }) 83668bb9b7SRichard Henderson # define MAXTL_MASK 0 84af25071cSRichard Henderson #endif 85af25071cSRichard Henderson 86633c4283SRichard Henderson /* Dynamic PC, must exit to main loop. */ 87633c4283SRichard Henderson #define DYNAMIC_PC 1 88633c4283SRichard Henderson /* Dynamic PC, one of two values according to jump_pc[T2]. */ 89633c4283SRichard Henderson #define JUMP_PC 2 90633c4283SRichard Henderson /* Dynamic PC, may lookup next TB. */ 91633c4283SRichard Henderson #define DYNAMIC_PC_LOOKUP 3 92fcf5ef2aSThomas Huth 9346bb0137SMark Cave-Ayland #define DISAS_EXIT DISAS_TARGET_0 9446bb0137SMark Cave-Ayland 95fcf5ef2aSThomas Huth /* global register indexes */ 96fcf5ef2aSThomas Huth static TCGv_ptr cpu_regwptr; 97c9fa8e58SRichard Henderson static TCGv cpu_pc, cpu_npc; 98fcf5ef2aSThomas Huth static TCGv cpu_regs[32]; 99fcf5ef2aSThomas Huth static TCGv cpu_y; 100fcf5ef2aSThomas Huth static TCGv cpu_tbr; 101fcf5ef2aSThomas Huth static TCGv cpu_cond; 1022a1905c7SRichard Henderson static TCGv cpu_cc_N; 1032a1905c7SRichard Henderson static TCGv cpu_cc_V; 1042a1905c7SRichard Henderson static TCGv cpu_icc_Z; 1052a1905c7SRichard Henderson static TCGv cpu_icc_C; 106fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64 1072a1905c7SRichard Henderson static TCGv cpu_xcc_Z; 1082a1905c7SRichard Henderson static TCGv cpu_xcc_C; 1092a1905c7SRichard Henderson static TCGv_i32 cpu_fprs; 110fcf5ef2aSThomas Huth static TCGv cpu_gsr; 111fcf5ef2aSThomas Huth #else 112af25071cSRichard Henderson # define cpu_fprs ({ qemu_build_not_reached(); (TCGv)NULL; }) 113af25071cSRichard Henderson # define cpu_gsr ({ qemu_build_not_reached(); (TCGv)NULL; }) 114fcf5ef2aSThomas Huth #endif 1152a1905c7SRichard Henderson 1162a1905c7SRichard Henderson #ifdef TARGET_SPARC64 1172a1905c7SRichard Henderson #define cpu_cc_Z cpu_xcc_Z 1182a1905c7SRichard Henderson #define cpu_cc_C cpu_xcc_C 1192a1905c7SRichard Henderson #else 1202a1905c7SRichard Henderson #define cpu_cc_Z cpu_icc_Z 1212a1905c7SRichard Henderson #define cpu_cc_C cpu_icc_C 1222a1905c7SRichard Henderson #define cpu_xcc_Z ({ qemu_build_not_reached(); NULL; }) 1232a1905c7SRichard Henderson #define cpu_xcc_C ({ qemu_build_not_reached(); NULL; }) 1242a1905c7SRichard Henderson #endif 1252a1905c7SRichard Henderson 1261210a036SRichard Henderson /* Floating point comparison registers */ 127d8c5b92fSRichard Henderson static TCGv_i32 cpu_fcc[TARGET_FCCREGS]; 128fcf5ef2aSThomas Huth 129af25071cSRichard Henderson #define env_field_offsetof(X) offsetof(CPUSPARCState, X) 130af25071cSRichard Henderson #ifdef TARGET_SPARC64 131cd6269f7SRichard Henderson # define env32_field_offsetof(X) ({ qemu_build_not_reached(); 0; }) 132af25071cSRichard Henderson # define env64_field_offsetof(X) env_field_offsetof(X) 133af25071cSRichard Henderson #else 134cd6269f7SRichard Henderson # define env32_field_offsetof(X) env_field_offsetof(X) 135af25071cSRichard Henderson # define env64_field_offsetof(X) ({ qemu_build_not_reached(); 0; }) 136af25071cSRichard Henderson #endif 137af25071cSRichard Henderson 138533f042fSRichard Henderson typedef struct DisasCompare { 139533f042fSRichard Henderson TCGCond cond; 140533f042fSRichard Henderson TCGv c1; 141533f042fSRichard Henderson int c2; 142533f042fSRichard Henderson } DisasCompare; 143533f042fSRichard Henderson 144186e7890SRichard Henderson typedef struct DisasDelayException { 145186e7890SRichard Henderson struct DisasDelayException *next; 146186e7890SRichard Henderson TCGLabel *lab; 147186e7890SRichard Henderson TCGv_i32 excp; 148186e7890SRichard Henderson /* Saved state at parent insn. */ 149186e7890SRichard Henderson target_ulong pc; 150186e7890SRichard Henderson target_ulong npc; 151186e7890SRichard Henderson } DisasDelayException; 152186e7890SRichard Henderson 153fcf5ef2aSThomas Huth typedef struct DisasContext { 154af00be49SEmilio G. Cota DisasContextBase base; 155fcf5ef2aSThomas Huth target_ulong pc; /* current Program Counter: integer or DYNAMIC_PC */ 156fcf5ef2aSThomas Huth target_ulong npc; /* next PC: integer or DYNAMIC_PC or JUMP_PC */ 157533f042fSRichard Henderson 158533f042fSRichard Henderson /* Used when JUMP_PC value is used. */ 159533f042fSRichard Henderson DisasCompare jump; 160533f042fSRichard Henderson target_ulong jump_pc[2]; 161533f042fSRichard Henderson 162fcf5ef2aSThomas Huth int mem_idx; 16389527e3aSRichard Henderson bool cpu_cond_live; 164c9b459aaSArtyom Tarasenko bool fpu_enabled; 165c9b459aaSArtyom Tarasenko bool address_mask_32bit; 166c9b459aaSArtyom Tarasenko #ifndef CONFIG_USER_ONLY 167c9b459aaSArtyom Tarasenko bool supervisor; 168c9b459aaSArtyom Tarasenko #ifdef TARGET_SPARC64 169c9b459aaSArtyom Tarasenko bool hypervisor; 170c9b459aaSArtyom Tarasenko #endif 171c9b459aaSArtyom Tarasenko #endif 172c9b459aaSArtyom Tarasenko 173fcf5ef2aSThomas Huth sparc_def_t *def; 174fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64 175fcf5ef2aSThomas Huth int fprs_dirty; 176fcf5ef2aSThomas Huth int asi; 177fcf5ef2aSThomas Huth #endif 178186e7890SRichard Henderson DisasDelayException *delay_excp_list; 179fcf5ef2aSThomas Huth } DisasContext; 180fcf5ef2aSThomas Huth 181fcf5ef2aSThomas Huth // This function uses non-native bit order 182fcf5ef2aSThomas Huth #define GET_FIELD(X, FROM, TO) \ 183fcf5ef2aSThomas Huth ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1)) 184fcf5ef2aSThomas Huth 185fcf5ef2aSThomas Huth // This function uses the order in the manuals, i.e. bit 0 is 2^0 186fcf5ef2aSThomas Huth #define GET_FIELD_SP(X, FROM, TO) \ 187fcf5ef2aSThomas Huth GET_FIELD(X, 31 - (TO), 31 - (FROM)) 188fcf5ef2aSThomas Huth 189fcf5ef2aSThomas Huth #define GET_FIELDs(x,a,b) sign_extend (GET_FIELD(x,a,b), (b) - (a) + 1) 190fcf5ef2aSThomas Huth #define GET_FIELD_SPs(x,a,b) sign_extend (GET_FIELD_SP(x,a,b), ((b) - (a) + 1)) 191fcf5ef2aSThomas Huth 192fcf5ef2aSThomas Huth #define UA2005_HTRAP_MASK 0xff 193fcf5ef2aSThomas Huth #define V8_TRAP_MASK 0x7f 194fcf5ef2aSThomas Huth 195fcf5ef2aSThomas Huth #define IS_IMM (insn & (1<<13)) 196fcf5ef2aSThomas Huth 1970c2e96c1SRichard Henderson static void gen_update_fprs_dirty(DisasContext *dc, int rd) 198fcf5ef2aSThomas Huth { 199fcf5ef2aSThomas Huth #if defined(TARGET_SPARC64) 200fcf5ef2aSThomas Huth int bit = (rd < 32) ? 1 : 2; 201fcf5ef2aSThomas Huth /* If we know we've already set this bit within the TB, 202fcf5ef2aSThomas Huth we can avoid setting it again. */ 203fcf5ef2aSThomas Huth if (!(dc->fprs_dirty & bit)) { 204fcf5ef2aSThomas Huth dc->fprs_dirty |= bit; 205fcf5ef2aSThomas Huth tcg_gen_ori_i32(cpu_fprs, cpu_fprs, bit); 206fcf5ef2aSThomas Huth } 207fcf5ef2aSThomas Huth #endif 208fcf5ef2aSThomas Huth } 209fcf5ef2aSThomas Huth 210fcf5ef2aSThomas Huth /* floating point registers moves */ 2111210a036SRichard Henderson 2121210a036SRichard Henderson static int gen_offset_fpr_F(unsigned int reg) 2131210a036SRichard Henderson { 2141210a036SRichard Henderson int ret; 2151210a036SRichard Henderson 2161210a036SRichard Henderson tcg_debug_assert(reg < 32); 2171210a036SRichard Henderson ret= offsetof(CPUSPARCState, fpr[reg / 2]); 2181210a036SRichard Henderson if (reg & 1) { 2191210a036SRichard Henderson ret += offsetof(CPU_DoubleU, l.lower); 2201210a036SRichard Henderson } else { 2211210a036SRichard Henderson ret += offsetof(CPU_DoubleU, l.upper); 2221210a036SRichard Henderson } 2231210a036SRichard Henderson return ret; 2241210a036SRichard Henderson } 2251210a036SRichard Henderson 226fcf5ef2aSThomas Huth static TCGv_i32 gen_load_fpr_F(DisasContext *dc, unsigned int src) 227fcf5ef2aSThomas Huth { 22836ab4623SRichard Henderson TCGv_i32 ret = tcg_temp_new_i32(); 2291210a036SRichard Henderson tcg_gen_ld_i32(ret, tcg_env, gen_offset_fpr_F(src)); 230dc41aa7dSRichard Henderson return ret; 231fcf5ef2aSThomas Huth } 232fcf5ef2aSThomas Huth 233fcf5ef2aSThomas Huth static void gen_store_fpr_F(DisasContext *dc, unsigned int dst, TCGv_i32 v) 234fcf5ef2aSThomas Huth { 2351210a036SRichard Henderson tcg_gen_st_i32(v, tcg_env, gen_offset_fpr_F(dst)); 236fcf5ef2aSThomas Huth gen_update_fprs_dirty(dc, dst); 237fcf5ef2aSThomas Huth } 238fcf5ef2aSThomas Huth 2391210a036SRichard Henderson static int gen_offset_fpr_D(unsigned int reg) 2401210a036SRichard Henderson { 2411210a036SRichard Henderson tcg_debug_assert(reg < 64); 2421210a036SRichard Henderson tcg_debug_assert(reg % 2 == 0); 2431210a036SRichard Henderson return offsetof(CPUSPARCState, fpr[reg / 2]); 2441210a036SRichard Henderson } 2451210a036SRichard Henderson 246fcf5ef2aSThomas Huth static TCGv_i64 gen_load_fpr_D(DisasContext *dc, unsigned int src) 247fcf5ef2aSThomas Huth { 2481210a036SRichard Henderson TCGv_i64 ret = tcg_temp_new_i64(); 2491210a036SRichard Henderson tcg_gen_ld_i64(ret, tcg_env, gen_offset_fpr_D(src)); 2501210a036SRichard Henderson return ret; 251fcf5ef2aSThomas Huth } 252fcf5ef2aSThomas Huth 253fcf5ef2aSThomas Huth static void gen_store_fpr_D(DisasContext *dc, unsigned int dst, TCGv_i64 v) 254fcf5ef2aSThomas Huth { 2551210a036SRichard Henderson tcg_gen_st_i64(v, tcg_env, gen_offset_fpr_D(dst)); 256fcf5ef2aSThomas Huth gen_update_fprs_dirty(dc, dst); 257fcf5ef2aSThomas Huth } 258fcf5ef2aSThomas Huth 25933ec4245SRichard Henderson static TCGv_i128 gen_load_fpr_Q(DisasContext *dc, unsigned int src) 26033ec4245SRichard Henderson { 26133ec4245SRichard Henderson TCGv_i128 ret = tcg_temp_new_i128(); 2621210a036SRichard Henderson TCGv_i64 h = gen_load_fpr_D(dc, src); 2631210a036SRichard Henderson TCGv_i64 l = gen_load_fpr_D(dc, src + 2); 26433ec4245SRichard Henderson 2651210a036SRichard Henderson tcg_gen_concat_i64_i128(ret, l, h); 26633ec4245SRichard Henderson return ret; 26733ec4245SRichard Henderson } 26833ec4245SRichard Henderson 26933ec4245SRichard Henderson static void gen_store_fpr_Q(DisasContext *dc, unsigned int dst, TCGv_i128 v) 27033ec4245SRichard Henderson { 2711210a036SRichard Henderson TCGv_i64 h = tcg_temp_new_i64(); 2721210a036SRichard Henderson TCGv_i64 l = tcg_temp_new_i64(); 2731210a036SRichard Henderson 2741210a036SRichard Henderson tcg_gen_extr_i128_i64(l, h, v); 2751210a036SRichard Henderson gen_store_fpr_D(dc, dst, h); 2761210a036SRichard Henderson gen_store_fpr_D(dc, dst + 2, l); 27733ec4245SRichard Henderson } 27833ec4245SRichard Henderson 279fcf5ef2aSThomas Huth /* moves */ 280fcf5ef2aSThomas Huth #ifdef CONFIG_USER_ONLY 281fcf5ef2aSThomas Huth #define supervisor(dc) 0 282fcf5ef2aSThomas Huth #define hypervisor(dc) 0 283fcf5ef2aSThomas Huth #else 284fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64 285c9b459aaSArtyom Tarasenko #define hypervisor(dc) (dc->hypervisor) 286c9b459aaSArtyom Tarasenko #define supervisor(dc) (dc->supervisor | dc->hypervisor) 287fcf5ef2aSThomas Huth #else 288c9b459aaSArtyom Tarasenko #define supervisor(dc) (dc->supervisor) 289668bb9b7SRichard Henderson #define hypervisor(dc) 0 290fcf5ef2aSThomas Huth #endif 291fcf5ef2aSThomas Huth #endif 292fcf5ef2aSThomas Huth 293b1bc09eaSRichard Henderson #if !defined(TARGET_SPARC64) 294b1bc09eaSRichard Henderson # define AM_CHECK(dc) false 295b1bc09eaSRichard Henderson #elif defined(TARGET_ABI32) 296b1bc09eaSRichard Henderson # define AM_CHECK(dc) true 297b1bc09eaSRichard Henderson #elif defined(CONFIG_USER_ONLY) 298b1bc09eaSRichard Henderson # define AM_CHECK(dc) false 299fcf5ef2aSThomas Huth #else 300b1bc09eaSRichard Henderson # define AM_CHECK(dc) ((dc)->address_mask_32bit) 301fcf5ef2aSThomas Huth #endif 302fcf5ef2aSThomas Huth 3030c2e96c1SRichard Henderson static void gen_address_mask(DisasContext *dc, TCGv addr) 304fcf5ef2aSThomas Huth { 305b1bc09eaSRichard Henderson if (AM_CHECK(dc)) { 306fcf5ef2aSThomas Huth tcg_gen_andi_tl(addr, addr, 0xffffffffULL); 307b1bc09eaSRichard Henderson } 308fcf5ef2aSThomas Huth } 309fcf5ef2aSThomas Huth 31023ada1b1SRichard Henderson static target_ulong address_mask_i(DisasContext *dc, target_ulong addr) 31123ada1b1SRichard Henderson { 31223ada1b1SRichard Henderson return AM_CHECK(dc) ? (uint32_t)addr : addr; 31323ada1b1SRichard Henderson } 31423ada1b1SRichard Henderson 3150c2e96c1SRichard Henderson static TCGv gen_load_gpr(DisasContext *dc, int reg) 316fcf5ef2aSThomas Huth { 317fcf5ef2aSThomas Huth if (reg > 0) { 318fcf5ef2aSThomas Huth assert(reg < 32); 319fcf5ef2aSThomas Huth return cpu_regs[reg]; 320fcf5ef2aSThomas Huth } else { 32152123f14SRichard Henderson TCGv t = tcg_temp_new(); 322fcf5ef2aSThomas Huth tcg_gen_movi_tl(t, 0); 323fcf5ef2aSThomas Huth return t; 324fcf5ef2aSThomas Huth } 325fcf5ef2aSThomas Huth } 326fcf5ef2aSThomas Huth 3270c2e96c1SRichard Henderson static void gen_store_gpr(DisasContext *dc, int reg, TCGv v) 328fcf5ef2aSThomas Huth { 329fcf5ef2aSThomas Huth if (reg > 0) { 330fcf5ef2aSThomas Huth assert(reg < 32); 331fcf5ef2aSThomas Huth tcg_gen_mov_tl(cpu_regs[reg], v); 332fcf5ef2aSThomas Huth } 333fcf5ef2aSThomas Huth } 334fcf5ef2aSThomas Huth 3350c2e96c1SRichard Henderson static TCGv gen_dest_gpr(DisasContext *dc, int reg) 336fcf5ef2aSThomas Huth { 337fcf5ef2aSThomas Huth if (reg > 0) { 338fcf5ef2aSThomas Huth assert(reg < 32); 339fcf5ef2aSThomas Huth return cpu_regs[reg]; 340fcf5ef2aSThomas Huth } else { 34152123f14SRichard Henderson return tcg_temp_new(); 342fcf5ef2aSThomas Huth } 343fcf5ef2aSThomas Huth } 344fcf5ef2aSThomas Huth 3455645aa2eSRichard Henderson static bool use_goto_tb(DisasContext *s, target_ulong pc, target_ulong npc) 346fcf5ef2aSThomas Huth { 3475645aa2eSRichard Henderson return translator_use_goto_tb(&s->base, pc) && 3485645aa2eSRichard Henderson translator_use_goto_tb(&s->base, npc); 349fcf5ef2aSThomas Huth } 350fcf5ef2aSThomas Huth 3515645aa2eSRichard Henderson static void gen_goto_tb(DisasContext *s, int tb_num, 352fcf5ef2aSThomas Huth target_ulong pc, target_ulong npc) 353fcf5ef2aSThomas Huth { 354fcf5ef2aSThomas Huth if (use_goto_tb(s, pc, npc)) { 355fcf5ef2aSThomas Huth /* jump to same page: we can use a direct jump */ 356fcf5ef2aSThomas Huth tcg_gen_goto_tb(tb_num); 357fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_pc, pc); 358fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_npc, npc); 35907ea28b4SRichard Henderson tcg_gen_exit_tb(s->base.tb, tb_num); 360fcf5ef2aSThomas Huth } else { 361f67ccb2fSRichard Henderson /* jump to another page: we can use an indirect jump */ 362fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_pc, pc); 363fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_npc, npc); 364f67ccb2fSRichard Henderson tcg_gen_lookup_and_goto_ptr(); 365fcf5ef2aSThomas Huth } 366fcf5ef2aSThomas Huth } 367fcf5ef2aSThomas Huth 368b989ce73SRichard Henderson static TCGv gen_carry32(void) 369fcf5ef2aSThomas Huth { 370b989ce73SRichard Henderson if (TARGET_LONG_BITS == 64) { 371b989ce73SRichard Henderson TCGv t = tcg_temp_new(); 372b989ce73SRichard Henderson tcg_gen_extract_tl(t, cpu_icc_C, 32, 1); 373b989ce73SRichard Henderson return t; 374b989ce73SRichard Henderson } 375b989ce73SRichard Henderson return cpu_icc_C; 376fcf5ef2aSThomas Huth } 377fcf5ef2aSThomas Huth 378b989ce73SRichard Henderson static void gen_op_addcc_int(TCGv dst, TCGv src1, TCGv src2, TCGv cin) 379fcf5ef2aSThomas Huth { 380b989ce73SRichard Henderson TCGv z = tcg_constant_tl(0); 381fcf5ef2aSThomas Huth 382b989ce73SRichard Henderson if (cin) { 383b989ce73SRichard Henderson tcg_gen_add2_tl(cpu_cc_N, cpu_cc_C, src1, z, cin, z); 384b989ce73SRichard Henderson tcg_gen_add2_tl(cpu_cc_N, cpu_cc_C, cpu_cc_N, cpu_cc_C, src2, z); 385b989ce73SRichard Henderson } else { 386b989ce73SRichard Henderson tcg_gen_add2_tl(cpu_cc_N, cpu_cc_C, src1, z, src2, z); 387b989ce73SRichard Henderson } 388b989ce73SRichard Henderson tcg_gen_xor_tl(cpu_cc_Z, src1, src2); 389b989ce73SRichard Henderson tcg_gen_xor_tl(cpu_cc_V, cpu_cc_N, src2); 390b989ce73SRichard Henderson tcg_gen_andc_tl(cpu_cc_V, cpu_cc_V, cpu_cc_Z); 391b989ce73SRichard Henderson if (TARGET_LONG_BITS == 64) { 392b989ce73SRichard Henderson /* 393b989ce73SRichard Henderson * Carry-in to bit 32 is result ^ src1 ^ src2. 394b989ce73SRichard Henderson * We already have the src xor term in Z, from computation of V. 395b989ce73SRichard Henderson */ 396b989ce73SRichard Henderson tcg_gen_xor_tl(cpu_icc_C, cpu_cc_Z, cpu_cc_N); 397b989ce73SRichard Henderson tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N); 398b989ce73SRichard Henderson } 399b989ce73SRichard Henderson tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N); 400b989ce73SRichard Henderson tcg_gen_mov_tl(dst, cpu_cc_N); 401b989ce73SRichard Henderson } 402fcf5ef2aSThomas Huth 403b989ce73SRichard Henderson static void gen_op_addcc(TCGv dst, TCGv src1, TCGv src2) 404b989ce73SRichard Henderson { 405b989ce73SRichard Henderson gen_op_addcc_int(dst, src1, src2, NULL); 406b989ce73SRichard Henderson } 407fcf5ef2aSThomas Huth 408b989ce73SRichard Henderson static void gen_op_taddcc(TCGv dst, TCGv src1, TCGv src2) 409b989ce73SRichard Henderson { 410b989ce73SRichard Henderson TCGv t = tcg_temp_new(); 411b989ce73SRichard Henderson 412b989ce73SRichard Henderson /* Save the tag bits around modification of dst. */ 413b989ce73SRichard Henderson tcg_gen_or_tl(t, src1, src2); 414b989ce73SRichard Henderson 415b989ce73SRichard Henderson gen_op_addcc(dst, src1, src2); 416b989ce73SRichard Henderson 417b989ce73SRichard Henderson /* Incorprate tag bits into icc.V */ 418b989ce73SRichard Henderson tcg_gen_andi_tl(t, t, 3); 419b989ce73SRichard Henderson tcg_gen_neg_tl(t, t); 420b989ce73SRichard Henderson tcg_gen_ext32u_tl(t, t); 421b989ce73SRichard Henderson tcg_gen_or_tl(cpu_cc_V, cpu_cc_V, t); 422b989ce73SRichard Henderson } 423b989ce73SRichard Henderson 424b989ce73SRichard Henderson static void gen_op_addc(TCGv dst, TCGv src1, TCGv src2) 425b989ce73SRichard Henderson { 426b989ce73SRichard Henderson tcg_gen_add_tl(dst, src1, src2); 427b989ce73SRichard Henderson tcg_gen_add_tl(dst, dst, gen_carry32()); 428b989ce73SRichard Henderson } 429b989ce73SRichard Henderson 430b989ce73SRichard Henderson static void gen_op_addccc(TCGv dst, TCGv src1, TCGv src2) 431b989ce73SRichard Henderson { 432b989ce73SRichard Henderson gen_op_addcc_int(dst, src1, src2, gen_carry32()); 433fcf5ef2aSThomas Huth } 434fcf5ef2aSThomas Huth 435f828df74SRichard Henderson static void gen_op_subcc_int(TCGv dst, TCGv src1, TCGv src2, TCGv cin) 436fcf5ef2aSThomas Huth { 437f828df74SRichard Henderson TCGv z = tcg_constant_tl(0); 438fcf5ef2aSThomas Huth 439f828df74SRichard Henderson if (cin) { 440f828df74SRichard Henderson tcg_gen_sub2_tl(cpu_cc_N, cpu_cc_C, src1, z, cin, z); 441f828df74SRichard Henderson tcg_gen_sub2_tl(cpu_cc_N, cpu_cc_C, cpu_cc_N, cpu_cc_C, src2, z); 442f828df74SRichard Henderson } else { 443f828df74SRichard Henderson tcg_gen_sub2_tl(cpu_cc_N, cpu_cc_C, src1, z, src2, z); 444f828df74SRichard Henderson } 445f828df74SRichard Henderson tcg_gen_neg_tl(cpu_cc_C, cpu_cc_C); 446f828df74SRichard Henderson tcg_gen_xor_tl(cpu_cc_Z, src1, src2); 447f828df74SRichard Henderson tcg_gen_xor_tl(cpu_cc_V, cpu_cc_N, src1); 448f828df74SRichard Henderson tcg_gen_and_tl(cpu_cc_V, cpu_cc_V, cpu_cc_Z); 449f828df74SRichard Henderson #ifdef TARGET_SPARC64 450f828df74SRichard Henderson tcg_gen_xor_tl(cpu_icc_C, cpu_cc_Z, cpu_cc_N); 451f828df74SRichard Henderson tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N); 452fcf5ef2aSThomas Huth #endif 453f828df74SRichard Henderson tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N); 454f828df74SRichard Henderson tcg_gen_mov_tl(dst, cpu_cc_N); 455fcf5ef2aSThomas Huth } 456fcf5ef2aSThomas Huth 457f828df74SRichard Henderson static void gen_op_subcc(TCGv dst, TCGv src1, TCGv src2) 458fcf5ef2aSThomas Huth { 459f828df74SRichard Henderson gen_op_subcc_int(dst, src1, src2, NULL); 460fcf5ef2aSThomas Huth } 461fcf5ef2aSThomas Huth 462f828df74SRichard Henderson static void gen_op_tsubcc(TCGv dst, TCGv src1, TCGv src2) 463fcf5ef2aSThomas Huth { 464f828df74SRichard Henderson TCGv t = tcg_temp_new(); 465fcf5ef2aSThomas Huth 466f828df74SRichard Henderson /* Save the tag bits around modification of dst. */ 467f828df74SRichard Henderson tcg_gen_or_tl(t, src1, src2); 468fcf5ef2aSThomas Huth 469f828df74SRichard Henderson gen_op_subcc(dst, src1, src2); 470f828df74SRichard Henderson 471f828df74SRichard Henderson /* Incorprate tag bits into icc.V */ 472f828df74SRichard Henderson tcg_gen_andi_tl(t, t, 3); 473f828df74SRichard Henderson tcg_gen_neg_tl(t, t); 474f828df74SRichard Henderson tcg_gen_ext32u_tl(t, t); 475f828df74SRichard Henderson tcg_gen_or_tl(cpu_cc_V, cpu_cc_V, t); 476f828df74SRichard Henderson } 477f828df74SRichard Henderson 478f828df74SRichard Henderson static void gen_op_subc(TCGv dst, TCGv src1, TCGv src2) 479f828df74SRichard Henderson { 480fcf5ef2aSThomas Huth tcg_gen_sub_tl(dst, src1, src2); 481f828df74SRichard Henderson tcg_gen_sub_tl(dst, dst, gen_carry32()); 482fcf5ef2aSThomas Huth } 483fcf5ef2aSThomas Huth 484f828df74SRichard Henderson static void gen_op_subccc(TCGv dst, TCGv src1, TCGv src2) 485dfebb950SRichard Henderson { 486f828df74SRichard Henderson gen_op_subcc_int(dst, src1, src2, gen_carry32()); 487dfebb950SRichard Henderson } 488dfebb950SRichard Henderson 4890c2e96c1SRichard Henderson static void gen_op_mulscc(TCGv dst, TCGv src1, TCGv src2) 490fcf5ef2aSThomas Huth { 491b989ce73SRichard Henderson TCGv zero = tcg_constant_tl(0); 49250280618SRichard Henderson TCGv one = tcg_constant_tl(1); 493b989ce73SRichard Henderson TCGv t_src1 = tcg_temp_new(); 494b989ce73SRichard Henderson TCGv t_src2 = tcg_temp_new(); 495b989ce73SRichard Henderson TCGv t0 = tcg_temp_new(); 496fcf5ef2aSThomas Huth 497b989ce73SRichard Henderson tcg_gen_ext32u_tl(t_src1, src1); 498b989ce73SRichard Henderson tcg_gen_ext32u_tl(t_src2, src2); 499fcf5ef2aSThomas Huth 500b989ce73SRichard Henderson /* 501b989ce73SRichard Henderson * if (!(env->y & 1)) 502b989ce73SRichard Henderson * src2 = 0; 503fcf5ef2aSThomas Huth */ 50450280618SRichard Henderson tcg_gen_movcond_tl(TCG_COND_TSTEQ, t_src2, cpu_y, one, zero, t_src2); 505fcf5ef2aSThomas Huth 506b989ce73SRichard Henderson /* 507b989ce73SRichard Henderson * b2 = src1 & 1; 508b989ce73SRichard Henderson * y = (b2 << 31) | (y >> 1); 509b989ce73SRichard Henderson */ 5100b1183e3SPhilippe Mathieu-Daudé tcg_gen_extract_tl(t0, cpu_y, 1, 31); 511b989ce73SRichard Henderson tcg_gen_deposit_tl(cpu_y, t0, src1, 31, 1); 512fcf5ef2aSThomas Huth 513fcf5ef2aSThomas Huth // b1 = N ^ V; 5142a1905c7SRichard Henderson tcg_gen_xor_tl(t0, cpu_cc_N, cpu_cc_V); 515fcf5ef2aSThomas Huth 516b989ce73SRichard Henderson /* 517b989ce73SRichard Henderson * src1 = (b1 << 31) | (src1 >> 1) 518b989ce73SRichard Henderson */ 5192a1905c7SRichard Henderson tcg_gen_andi_tl(t0, t0, 1u << 31); 520b989ce73SRichard Henderson tcg_gen_shri_tl(t_src1, t_src1, 1); 521b989ce73SRichard Henderson tcg_gen_or_tl(t_src1, t_src1, t0); 522fcf5ef2aSThomas Huth 523b989ce73SRichard Henderson gen_op_addcc(dst, t_src1, t_src2); 524fcf5ef2aSThomas Huth } 525fcf5ef2aSThomas Huth 5260c2e96c1SRichard Henderson static void gen_op_multiply(TCGv dst, TCGv src1, TCGv src2, int sign_ext) 527fcf5ef2aSThomas Huth { 528fcf5ef2aSThomas Huth #if TARGET_LONG_BITS == 32 529fcf5ef2aSThomas Huth if (sign_ext) { 530fcf5ef2aSThomas Huth tcg_gen_muls2_tl(dst, cpu_y, src1, src2); 531fcf5ef2aSThomas Huth } else { 532fcf5ef2aSThomas Huth tcg_gen_mulu2_tl(dst, cpu_y, src1, src2); 533fcf5ef2aSThomas Huth } 534fcf5ef2aSThomas Huth #else 535fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new_i64(); 536fcf5ef2aSThomas Huth TCGv t1 = tcg_temp_new_i64(); 537fcf5ef2aSThomas Huth 538fcf5ef2aSThomas Huth if (sign_ext) { 539fcf5ef2aSThomas Huth tcg_gen_ext32s_i64(t0, src1); 540fcf5ef2aSThomas Huth tcg_gen_ext32s_i64(t1, src2); 541fcf5ef2aSThomas Huth } else { 542fcf5ef2aSThomas Huth tcg_gen_ext32u_i64(t0, src1); 543fcf5ef2aSThomas Huth tcg_gen_ext32u_i64(t1, src2); 544fcf5ef2aSThomas Huth } 545fcf5ef2aSThomas Huth 546fcf5ef2aSThomas Huth tcg_gen_mul_i64(dst, t0, t1); 547fcf5ef2aSThomas Huth tcg_gen_shri_i64(cpu_y, dst, 32); 548fcf5ef2aSThomas Huth #endif 549fcf5ef2aSThomas Huth } 550fcf5ef2aSThomas Huth 5510c2e96c1SRichard Henderson static void gen_op_umul(TCGv dst, TCGv src1, TCGv src2) 552fcf5ef2aSThomas Huth { 553fcf5ef2aSThomas Huth /* zero-extend truncated operands before multiplication */ 554fcf5ef2aSThomas Huth gen_op_multiply(dst, src1, src2, 0); 555fcf5ef2aSThomas Huth } 556fcf5ef2aSThomas Huth 5570c2e96c1SRichard Henderson static void gen_op_smul(TCGv dst, TCGv src1, TCGv src2) 558fcf5ef2aSThomas Huth { 559fcf5ef2aSThomas Huth /* sign-extend truncated operands before multiplication */ 560fcf5ef2aSThomas Huth gen_op_multiply(dst, src1, src2, 1); 561fcf5ef2aSThomas Huth } 562fcf5ef2aSThomas Huth 563c2636853SRichard Henderson static void gen_op_sdiv(TCGv dst, TCGv src1, TCGv src2) 564c2636853SRichard Henderson { 56513260103SRichard Henderson #ifdef TARGET_SPARC64 566c2636853SRichard Henderson gen_helper_sdiv(dst, tcg_env, src1, src2); 56713260103SRichard Henderson tcg_gen_ext32s_tl(dst, dst); 56813260103SRichard Henderson #else 56913260103SRichard Henderson TCGv_i64 t64 = tcg_temp_new_i64(); 57013260103SRichard Henderson gen_helper_sdiv(t64, tcg_env, src1, src2); 57113260103SRichard Henderson tcg_gen_trunc_i64_tl(dst, t64); 57213260103SRichard Henderson #endif 573c2636853SRichard Henderson } 574c2636853SRichard Henderson 575c2636853SRichard Henderson static void gen_op_udivcc(TCGv dst, TCGv src1, TCGv src2) 576c2636853SRichard Henderson { 57713260103SRichard Henderson TCGv_i64 t64; 57813260103SRichard Henderson 57913260103SRichard Henderson #ifdef TARGET_SPARC64 58013260103SRichard Henderson t64 = cpu_cc_V; 58113260103SRichard Henderson #else 58213260103SRichard Henderson t64 = tcg_temp_new_i64(); 58313260103SRichard Henderson #endif 58413260103SRichard Henderson 58513260103SRichard Henderson gen_helper_udiv(t64, tcg_env, src1, src2); 58613260103SRichard Henderson 58713260103SRichard Henderson #ifdef TARGET_SPARC64 58813260103SRichard Henderson tcg_gen_ext32u_tl(cpu_cc_N, t64); 58913260103SRichard Henderson tcg_gen_shri_tl(cpu_cc_V, t64, 32); 59013260103SRichard Henderson tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N); 59113260103SRichard Henderson tcg_gen_movi_tl(cpu_icc_C, 0); 59213260103SRichard Henderson #else 59313260103SRichard Henderson tcg_gen_extr_i64_tl(cpu_cc_N, cpu_cc_V, t64); 59413260103SRichard Henderson #endif 59513260103SRichard Henderson tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N); 59613260103SRichard Henderson tcg_gen_movi_tl(cpu_cc_C, 0); 59713260103SRichard Henderson tcg_gen_mov_tl(dst, cpu_cc_N); 598c2636853SRichard Henderson } 599c2636853SRichard Henderson 600c2636853SRichard Henderson static void gen_op_sdivcc(TCGv dst, TCGv src1, TCGv src2) 601c2636853SRichard Henderson { 60213260103SRichard Henderson TCGv_i64 t64; 60313260103SRichard Henderson 60413260103SRichard Henderson #ifdef TARGET_SPARC64 60513260103SRichard Henderson t64 = cpu_cc_V; 60613260103SRichard Henderson #else 60713260103SRichard Henderson t64 = tcg_temp_new_i64(); 60813260103SRichard Henderson #endif 60913260103SRichard Henderson 61013260103SRichard Henderson gen_helper_sdiv(t64, tcg_env, src1, src2); 61113260103SRichard Henderson 61213260103SRichard Henderson #ifdef TARGET_SPARC64 61313260103SRichard Henderson tcg_gen_ext32s_tl(cpu_cc_N, t64); 61413260103SRichard Henderson tcg_gen_shri_tl(cpu_cc_V, t64, 32); 61513260103SRichard Henderson tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N); 61613260103SRichard Henderson tcg_gen_movi_tl(cpu_icc_C, 0); 61713260103SRichard Henderson #else 61813260103SRichard Henderson tcg_gen_extr_i64_tl(cpu_cc_N, cpu_cc_V, t64); 61913260103SRichard Henderson #endif 62013260103SRichard Henderson tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N); 62113260103SRichard Henderson tcg_gen_movi_tl(cpu_cc_C, 0); 62213260103SRichard Henderson tcg_gen_mov_tl(dst, cpu_cc_N); 623c2636853SRichard Henderson } 624c2636853SRichard Henderson 625a9aba13dSRichard Henderson static void gen_op_taddcctv(TCGv dst, TCGv src1, TCGv src2) 626a9aba13dSRichard Henderson { 627a9aba13dSRichard Henderson gen_helper_taddcctv(dst, tcg_env, src1, src2); 628a9aba13dSRichard Henderson } 629a9aba13dSRichard Henderson 630a9aba13dSRichard Henderson static void gen_op_tsubcctv(TCGv dst, TCGv src1, TCGv src2) 631a9aba13dSRichard Henderson { 632a9aba13dSRichard Henderson gen_helper_tsubcctv(dst, tcg_env, src1, src2); 633a9aba13dSRichard Henderson } 634a9aba13dSRichard Henderson 6359c6ec5bcSRichard Henderson static void gen_op_popc(TCGv dst, TCGv src1, TCGv src2) 6369c6ec5bcSRichard Henderson { 6379c6ec5bcSRichard Henderson tcg_gen_ctpop_tl(dst, src2); 6389c6ec5bcSRichard Henderson } 6399c6ec5bcSRichard Henderson 64045bfed3bSRichard Henderson #ifndef TARGET_SPARC64 64145bfed3bSRichard Henderson static void gen_helper_array8(TCGv dst, TCGv src1, TCGv src2) 64245bfed3bSRichard Henderson { 64345bfed3bSRichard Henderson g_assert_not_reached(); 64445bfed3bSRichard Henderson } 64545bfed3bSRichard Henderson #endif 64645bfed3bSRichard Henderson 64745bfed3bSRichard Henderson static void gen_op_array16(TCGv dst, TCGv src1, TCGv src2) 64845bfed3bSRichard Henderson { 64945bfed3bSRichard Henderson gen_helper_array8(dst, src1, src2); 65045bfed3bSRichard Henderson tcg_gen_shli_tl(dst, dst, 1); 65145bfed3bSRichard Henderson } 65245bfed3bSRichard Henderson 65345bfed3bSRichard Henderson static void gen_op_array32(TCGv dst, TCGv src1, TCGv src2) 65445bfed3bSRichard Henderson { 65545bfed3bSRichard Henderson gen_helper_array8(dst, src1, src2); 65645bfed3bSRichard Henderson tcg_gen_shli_tl(dst, dst, 2); 65745bfed3bSRichard Henderson } 65845bfed3bSRichard Henderson 6592f722641SRichard Henderson static void gen_op_fpack16(TCGv_i32 dst, TCGv_i64 src) 6602f722641SRichard Henderson { 6612f722641SRichard Henderson #ifdef TARGET_SPARC64 6622f722641SRichard Henderson gen_helper_fpack16(dst, cpu_gsr, src); 6632f722641SRichard Henderson #else 6642f722641SRichard Henderson g_assert_not_reached(); 6652f722641SRichard Henderson #endif 6662f722641SRichard Henderson } 6672f722641SRichard Henderson 6682f722641SRichard Henderson static void gen_op_fpackfix(TCGv_i32 dst, TCGv_i64 src) 6692f722641SRichard Henderson { 6702f722641SRichard Henderson #ifdef TARGET_SPARC64 6712f722641SRichard Henderson gen_helper_fpackfix(dst, cpu_gsr, src); 6722f722641SRichard Henderson #else 6732f722641SRichard Henderson g_assert_not_reached(); 6742f722641SRichard Henderson #endif 6752f722641SRichard Henderson } 6762f722641SRichard Henderson 6774b6edc0aSRichard Henderson static void gen_op_fpack32(TCGv_i64 dst, TCGv_i64 src1, TCGv_i64 src2) 6784b6edc0aSRichard Henderson { 6794b6edc0aSRichard Henderson #ifdef TARGET_SPARC64 6804b6edc0aSRichard Henderson gen_helper_fpack32(dst, cpu_gsr, src1, src2); 6814b6edc0aSRichard Henderson #else 6824b6edc0aSRichard Henderson g_assert_not_reached(); 6834b6edc0aSRichard Henderson #endif 6844b6edc0aSRichard Henderson } 6854b6edc0aSRichard Henderson 6864b6edc0aSRichard Henderson static void gen_op_faligndata(TCGv_i64 dst, TCGv_i64 s1, TCGv_i64 s2) 6874b6edc0aSRichard Henderson { 6884b6edc0aSRichard Henderson #ifdef TARGET_SPARC64 6894b6edc0aSRichard Henderson TCGv t1, t2, shift; 6904b6edc0aSRichard Henderson 6914b6edc0aSRichard Henderson t1 = tcg_temp_new(); 6924b6edc0aSRichard Henderson t2 = tcg_temp_new(); 6934b6edc0aSRichard Henderson shift = tcg_temp_new(); 6944b6edc0aSRichard Henderson 6954b6edc0aSRichard Henderson tcg_gen_andi_tl(shift, cpu_gsr, 7); 6964b6edc0aSRichard Henderson tcg_gen_shli_tl(shift, shift, 3); 6974b6edc0aSRichard Henderson tcg_gen_shl_tl(t1, s1, shift); 6984b6edc0aSRichard Henderson 6994b6edc0aSRichard Henderson /* 7004b6edc0aSRichard Henderson * A shift of 64 does not produce 0 in TCG. Divide this into a 7014b6edc0aSRichard Henderson * shift of (up to 63) followed by a constant shift of 1. 7024b6edc0aSRichard Henderson */ 7034b6edc0aSRichard Henderson tcg_gen_xori_tl(shift, shift, 63); 7044b6edc0aSRichard Henderson tcg_gen_shr_tl(t2, s2, shift); 7054b6edc0aSRichard Henderson tcg_gen_shri_tl(t2, t2, 1); 7064b6edc0aSRichard Henderson 7074b6edc0aSRichard Henderson tcg_gen_or_tl(dst, t1, t2); 7084b6edc0aSRichard Henderson #else 7094b6edc0aSRichard Henderson g_assert_not_reached(); 7104b6edc0aSRichard Henderson #endif 7114b6edc0aSRichard Henderson } 7124b6edc0aSRichard Henderson 7134b6edc0aSRichard Henderson static void gen_op_bshuffle(TCGv_i64 dst, TCGv_i64 src1, TCGv_i64 src2) 7144b6edc0aSRichard Henderson { 7154b6edc0aSRichard Henderson #ifdef TARGET_SPARC64 7164b6edc0aSRichard Henderson gen_helper_bshuffle(dst, cpu_gsr, src1, src2); 7174b6edc0aSRichard Henderson #else 7184b6edc0aSRichard Henderson g_assert_not_reached(); 7194b6edc0aSRichard Henderson #endif 7204b6edc0aSRichard Henderson } 7214b6edc0aSRichard Henderson 722a859602cSRichard Henderson static void gen_op_fmul8x16al(TCGv_i64 dst, TCGv_i32 src1, TCGv_i32 src2) 723a859602cSRichard Henderson { 724a859602cSRichard Henderson tcg_gen_ext16s_i32(src2, src2); 725a859602cSRichard Henderson gen_helper_fmul8x16a(dst, src1, src2); 726a859602cSRichard Henderson } 727a859602cSRichard Henderson 728a859602cSRichard Henderson static void gen_op_fmul8x16au(TCGv_i64 dst, TCGv_i32 src1, TCGv_i32 src2) 729a859602cSRichard Henderson { 730a859602cSRichard Henderson tcg_gen_sari_i32(src2, src2, 16); 731a859602cSRichard Henderson gen_helper_fmul8x16a(dst, src1, src2); 732a859602cSRichard Henderson } 733a859602cSRichard Henderson 734be8998e0SRichard Henderson static void gen_op_fmuld8ulx16(TCGv_i64 dst, TCGv_i32 src1, TCGv_i32 src2) 735be8998e0SRichard Henderson { 736be8998e0SRichard Henderson TCGv_i32 t0 = tcg_temp_new_i32(); 737be8998e0SRichard Henderson TCGv_i32 t1 = tcg_temp_new_i32(); 738be8998e0SRichard Henderson TCGv_i32 t2 = tcg_temp_new_i32(); 739be8998e0SRichard Henderson 740be8998e0SRichard Henderson tcg_gen_ext8u_i32(t0, src1); 741be8998e0SRichard Henderson tcg_gen_ext16s_i32(t1, src2); 742be8998e0SRichard Henderson tcg_gen_mul_i32(t0, t0, t1); 743be8998e0SRichard Henderson 744be8998e0SRichard Henderson tcg_gen_extract_i32(t1, src1, 16, 8); 745be8998e0SRichard Henderson tcg_gen_sextract_i32(t2, src2, 16, 16); 746be8998e0SRichard Henderson tcg_gen_mul_i32(t1, t1, t2); 747be8998e0SRichard Henderson 748be8998e0SRichard Henderson tcg_gen_concat_i32_i64(dst, t0, t1); 749be8998e0SRichard Henderson } 750be8998e0SRichard Henderson 751be8998e0SRichard Henderson static void gen_op_fmuld8sux16(TCGv_i64 dst, TCGv_i32 src1, TCGv_i32 src2) 752be8998e0SRichard Henderson { 753be8998e0SRichard Henderson TCGv_i32 t0 = tcg_temp_new_i32(); 754be8998e0SRichard Henderson TCGv_i32 t1 = tcg_temp_new_i32(); 755be8998e0SRichard Henderson TCGv_i32 t2 = tcg_temp_new_i32(); 756be8998e0SRichard Henderson 757be8998e0SRichard Henderson /* 758be8998e0SRichard Henderson * The insn description talks about extracting the upper 8 bits 759be8998e0SRichard Henderson * of the signed 16-bit input rs1, performing the multiply, then 760be8998e0SRichard Henderson * shifting left by 8 bits. Instead, zap the lower 8 bits of 761be8998e0SRichard Henderson * the rs1 input, which avoids the need for two shifts. 762be8998e0SRichard Henderson */ 763be8998e0SRichard Henderson tcg_gen_ext16s_i32(t0, src1); 764be8998e0SRichard Henderson tcg_gen_andi_i32(t0, t0, ~0xff); 765be8998e0SRichard Henderson tcg_gen_ext16s_i32(t1, src2); 766be8998e0SRichard Henderson tcg_gen_mul_i32(t0, t0, t1); 767be8998e0SRichard Henderson 768be8998e0SRichard Henderson tcg_gen_sextract_i32(t1, src1, 16, 16); 769be8998e0SRichard Henderson tcg_gen_andi_i32(t1, t1, ~0xff); 770be8998e0SRichard Henderson tcg_gen_sextract_i32(t2, src2, 16, 16); 771be8998e0SRichard Henderson tcg_gen_mul_i32(t1, t1, t2); 772be8998e0SRichard Henderson 773be8998e0SRichard Henderson tcg_gen_concat_i32_i64(dst, t0, t1); 774be8998e0SRichard Henderson } 775be8998e0SRichard Henderson 77689527e3aSRichard Henderson static void finishing_insn(DisasContext *dc) 77789527e3aSRichard Henderson { 77889527e3aSRichard Henderson /* 77989527e3aSRichard Henderson * From here, there is no future path through an unwinding exception. 78089527e3aSRichard Henderson * If the current insn cannot raise an exception, the computation of 78189527e3aSRichard Henderson * cpu_cond may be able to be elided. 78289527e3aSRichard Henderson */ 78389527e3aSRichard Henderson if (dc->cpu_cond_live) { 78489527e3aSRichard Henderson tcg_gen_discard_tl(cpu_cond); 78589527e3aSRichard Henderson dc->cpu_cond_live = false; 78689527e3aSRichard Henderson } 78789527e3aSRichard Henderson } 78889527e3aSRichard Henderson 7890c2e96c1SRichard Henderson static void gen_generic_branch(DisasContext *dc) 790fcf5ef2aSThomas Huth { 79100ab7e61SRichard Henderson TCGv npc0 = tcg_constant_tl(dc->jump_pc[0]); 79200ab7e61SRichard Henderson TCGv npc1 = tcg_constant_tl(dc->jump_pc[1]); 793533f042fSRichard Henderson TCGv c2 = tcg_constant_tl(dc->jump.c2); 794fcf5ef2aSThomas Huth 795533f042fSRichard Henderson tcg_gen_movcond_tl(dc->jump.cond, cpu_npc, dc->jump.c1, c2, npc0, npc1); 796fcf5ef2aSThomas Huth } 797fcf5ef2aSThomas Huth 798fcf5ef2aSThomas Huth /* call this function before using the condition register as it may 799fcf5ef2aSThomas Huth have been set for a jump */ 8000c2e96c1SRichard Henderson static void flush_cond(DisasContext *dc) 801fcf5ef2aSThomas Huth { 802fcf5ef2aSThomas Huth if (dc->npc == JUMP_PC) { 803fcf5ef2aSThomas Huth gen_generic_branch(dc); 80499c82c47SRichard Henderson dc->npc = DYNAMIC_PC_LOOKUP; 805fcf5ef2aSThomas Huth } 806fcf5ef2aSThomas Huth } 807fcf5ef2aSThomas Huth 8080c2e96c1SRichard Henderson static void save_npc(DisasContext *dc) 809fcf5ef2aSThomas Huth { 810633c4283SRichard Henderson if (dc->npc & 3) { 811633c4283SRichard Henderson switch (dc->npc) { 812633c4283SRichard Henderson case JUMP_PC: 813fcf5ef2aSThomas Huth gen_generic_branch(dc); 81499c82c47SRichard Henderson dc->npc = DYNAMIC_PC_LOOKUP; 815633c4283SRichard Henderson break; 816633c4283SRichard Henderson case DYNAMIC_PC: 817633c4283SRichard Henderson case DYNAMIC_PC_LOOKUP: 818633c4283SRichard Henderson break; 819633c4283SRichard Henderson default: 820633c4283SRichard Henderson g_assert_not_reached(); 821633c4283SRichard Henderson } 822633c4283SRichard Henderson } else { 823fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_npc, dc->npc); 824fcf5ef2aSThomas Huth } 825fcf5ef2aSThomas Huth } 826fcf5ef2aSThomas Huth 8270c2e96c1SRichard Henderson static void save_state(DisasContext *dc) 828fcf5ef2aSThomas Huth { 829fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_pc, dc->pc); 830fcf5ef2aSThomas Huth save_npc(dc); 831fcf5ef2aSThomas Huth } 832fcf5ef2aSThomas Huth 833fcf5ef2aSThomas Huth static void gen_exception(DisasContext *dc, int which) 834fcf5ef2aSThomas Huth { 83589527e3aSRichard Henderson finishing_insn(dc); 836fcf5ef2aSThomas Huth save_state(dc); 837ad75a51eSRichard Henderson gen_helper_raise_exception(tcg_env, tcg_constant_i32(which)); 838af00be49SEmilio G. Cota dc->base.is_jmp = DISAS_NORETURN; 839fcf5ef2aSThomas Huth } 840fcf5ef2aSThomas Huth 841186e7890SRichard Henderson static TCGLabel *delay_exceptionv(DisasContext *dc, TCGv_i32 excp) 842fcf5ef2aSThomas Huth { 843186e7890SRichard Henderson DisasDelayException *e = g_new0(DisasDelayException, 1); 844186e7890SRichard Henderson 845186e7890SRichard Henderson e->next = dc->delay_excp_list; 846186e7890SRichard Henderson dc->delay_excp_list = e; 847186e7890SRichard Henderson 848186e7890SRichard Henderson e->lab = gen_new_label(); 849186e7890SRichard Henderson e->excp = excp; 850186e7890SRichard Henderson e->pc = dc->pc; 851186e7890SRichard Henderson /* Caller must have used flush_cond before branch. */ 852186e7890SRichard Henderson assert(e->npc != JUMP_PC); 853186e7890SRichard Henderson e->npc = dc->npc; 854186e7890SRichard Henderson 855186e7890SRichard Henderson return e->lab; 856186e7890SRichard Henderson } 857186e7890SRichard Henderson 858186e7890SRichard Henderson static TCGLabel *delay_exception(DisasContext *dc, int excp) 859186e7890SRichard Henderson { 860186e7890SRichard Henderson return delay_exceptionv(dc, tcg_constant_i32(excp)); 861186e7890SRichard Henderson } 862186e7890SRichard Henderson 863186e7890SRichard Henderson static void gen_check_align(DisasContext *dc, TCGv addr, int mask) 864186e7890SRichard Henderson { 865186e7890SRichard Henderson TCGv t = tcg_temp_new(); 866186e7890SRichard Henderson TCGLabel *lab; 867186e7890SRichard Henderson 868186e7890SRichard Henderson tcg_gen_andi_tl(t, addr, mask); 869186e7890SRichard Henderson 870186e7890SRichard Henderson flush_cond(dc); 871186e7890SRichard Henderson lab = delay_exception(dc, TT_UNALIGNED); 872186e7890SRichard Henderson tcg_gen_brcondi_tl(TCG_COND_NE, t, 0, lab); 873fcf5ef2aSThomas Huth } 874fcf5ef2aSThomas Huth 8750c2e96c1SRichard Henderson static void gen_mov_pc_npc(DisasContext *dc) 876fcf5ef2aSThomas Huth { 87789527e3aSRichard Henderson finishing_insn(dc); 87889527e3aSRichard Henderson 879633c4283SRichard Henderson if (dc->npc & 3) { 880633c4283SRichard Henderson switch (dc->npc) { 881633c4283SRichard Henderson case JUMP_PC: 882fcf5ef2aSThomas Huth gen_generic_branch(dc); 883fcf5ef2aSThomas Huth tcg_gen_mov_tl(cpu_pc, cpu_npc); 88499c82c47SRichard Henderson dc->pc = DYNAMIC_PC_LOOKUP; 885633c4283SRichard Henderson break; 886633c4283SRichard Henderson case DYNAMIC_PC: 887633c4283SRichard Henderson case DYNAMIC_PC_LOOKUP: 888fcf5ef2aSThomas Huth tcg_gen_mov_tl(cpu_pc, cpu_npc); 889633c4283SRichard Henderson dc->pc = dc->npc; 890633c4283SRichard Henderson break; 891633c4283SRichard Henderson default: 892633c4283SRichard Henderson g_assert_not_reached(); 893633c4283SRichard Henderson } 894fcf5ef2aSThomas Huth } else { 895fcf5ef2aSThomas Huth dc->pc = dc->npc; 896fcf5ef2aSThomas Huth } 897fcf5ef2aSThomas Huth } 898fcf5ef2aSThomas Huth 899fcf5ef2aSThomas Huth static void gen_compare(DisasCompare *cmp, bool xcc, unsigned int cond, 900fcf5ef2aSThomas Huth DisasContext *dc) 901fcf5ef2aSThomas Huth { 902b597eedcSRichard Henderson TCGv t1; 903fcf5ef2aSThomas Huth 9042a1905c7SRichard Henderson cmp->c1 = t1 = tcg_temp_new(); 905c8507ebfSRichard Henderson cmp->c2 = 0; 9062a1905c7SRichard Henderson 9072a1905c7SRichard Henderson switch (cond & 7) { 9082a1905c7SRichard Henderson case 0x0: /* never */ 9092a1905c7SRichard Henderson cmp->cond = TCG_COND_NEVER; 910c8507ebfSRichard Henderson cmp->c1 = tcg_constant_tl(0); 911fcf5ef2aSThomas Huth break; 9122a1905c7SRichard Henderson 9132a1905c7SRichard Henderson case 0x1: /* eq: Z */ 9142a1905c7SRichard Henderson cmp->cond = TCG_COND_EQ; 9152a1905c7SRichard Henderson if (TARGET_LONG_BITS == 32 || xcc) { 9162a1905c7SRichard Henderson tcg_gen_mov_tl(t1, cpu_cc_Z); 9172a1905c7SRichard Henderson } else { 9182a1905c7SRichard Henderson tcg_gen_ext32u_tl(t1, cpu_icc_Z); 9192a1905c7SRichard Henderson } 9202a1905c7SRichard Henderson break; 9212a1905c7SRichard Henderson 9222a1905c7SRichard Henderson case 0x2: /* le: Z | (N ^ V) */ 9232a1905c7SRichard Henderson /* 9242a1905c7SRichard Henderson * Simplify: 9252a1905c7SRichard Henderson * cc_Z || (N ^ V) < 0 NE 9262a1905c7SRichard Henderson * cc_Z && !((N ^ V) < 0) EQ 9272a1905c7SRichard Henderson * cc_Z & ~((N ^ V) >> TLB) EQ 9282a1905c7SRichard Henderson */ 9292a1905c7SRichard Henderson cmp->cond = TCG_COND_EQ; 9302a1905c7SRichard Henderson tcg_gen_xor_tl(t1, cpu_cc_N, cpu_cc_V); 9312a1905c7SRichard Henderson tcg_gen_sextract_tl(t1, t1, xcc ? 63 : 31, 1); 9322a1905c7SRichard Henderson tcg_gen_andc_tl(t1, xcc ? cpu_cc_Z : cpu_icc_Z, t1); 9332a1905c7SRichard Henderson if (TARGET_LONG_BITS == 64 && !xcc) { 9342a1905c7SRichard Henderson tcg_gen_ext32u_tl(t1, t1); 9352a1905c7SRichard Henderson } 9362a1905c7SRichard Henderson break; 9372a1905c7SRichard Henderson 9382a1905c7SRichard Henderson case 0x3: /* lt: N ^ V */ 9392a1905c7SRichard Henderson cmp->cond = TCG_COND_LT; 9402a1905c7SRichard Henderson tcg_gen_xor_tl(t1, cpu_cc_N, cpu_cc_V); 9412a1905c7SRichard Henderson if (TARGET_LONG_BITS == 64 && !xcc) { 9422a1905c7SRichard Henderson tcg_gen_ext32s_tl(t1, t1); 9432a1905c7SRichard Henderson } 9442a1905c7SRichard Henderson break; 9452a1905c7SRichard Henderson 9462a1905c7SRichard Henderson case 0x4: /* leu: Z | C */ 9472a1905c7SRichard Henderson /* 9482a1905c7SRichard Henderson * Simplify: 9492a1905c7SRichard Henderson * cc_Z == 0 || cc_C != 0 NE 9502a1905c7SRichard Henderson * cc_Z != 0 && cc_C == 0 EQ 9512a1905c7SRichard Henderson * cc_Z & (cc_C ? 0 : -1) EQ 9522a1905c7SRichard Henderson * cc_Z & (cc_C - 1) EQ 9532a1905c7SRichard Henderson */ 9542a1905c7SRichard Henderson cmp->cond = TCG_COND_EQ; 9552a1905c7SRichard Henderson if (TARGET_LONG_BITS == 32 || xcc) { 9562a1905c7SRichard Henderson tcg_gen_subi_tl(t1, cpu_cc_C, 1); 9572a1905c7SRichard Henderson tcg_gen_and_tl(t1, t1, cpu_cc_Z); 9582a1905c7SRichard Henderson } else { 9592a1905c7SRichard Henderson tcg_gen_extract_tl(t1, cpu_icc_C, 32, 1); 9602a1905c7SRichard Henderson tcg_gen_subi_tl(t1, t1, 1); 9612a1905c7SRichard Henderson tcg_gen_and_tl(t1, t1, cpu_icc_Z); 9622a1905c7SRichard Henderson tcg_gen_ext32u_tl(t1, t1); 9632a1905c7SRichard Henderson } 9642a1905c7SRichard Henderson break; 9652a1905c7SRichard Henderson 9662a1905c7SRichard Henderson case 0x5: /* ltu: C */ 9672a1905c7SRichard Henderson cmp->cond = TCG_COND_NE; 9682a1905c7SRichard Henderson if (TARGET_LONG_BITS == 32 || xcc) { 9692a1905c7SRichard Henderson tcg_gen_mov_tl(t1, cpu_cc_C); 9702a1905c7SRichard Henderson } else { 9712a1905c7SRichard Henderson tcg_gen_extract_tl(t1, cpu_icc_C, 32, 1); 9722a1905c7SRichard Henderson } 9732a1905c7SRichard Henderson break; 9742a1905c7SRichard Henderson 9752a1905c7SRichard Henderson case 0x6: /* neg: N */ 9762a1905c7SRichard Henderson cmp->cond = TCG_COND_LT; 9772a1905c7SRichard Henderson if (TARGET_LONG_BITS == 32 || xcc) { 9782a1905c7SRichard Henderson tcg_gen_mov_tl(t1, cpu_cc_N); 9792a1905c7SRichard Henderson } else { 9802a1905c7SRichard Henderson tcg_gen_ext32s_tl(t1, cpu_cc_N); 9812a1905c7SRichard Henderson } 9822a1905c7SRichard Henderson break; 9832a1905c7SRichard Henderson 9842a1905c7SRichard Henderson case 0x7: /* vs: V */ 9852a1905c7SRichard Henderson cmp->cond = TCG_COND_LT; 9862a1905c7SRichard Henderson if (TARGET_LONG_BITS == 32 || xcc) { 9872a1905c7SRichard Henderson tcg_gen_mov_tl(t1, cpu_cc_V); 9882a1905c7SRichard Henderson } else { 9892a1905c7SRichard Henderson tcg_gen_ext32s_tl(t1, cpu_cc_V); 9902a1905c7SRichard Henderson } 9912a1905c7SRichard Henderson break; 9922a1905c7SRichard Henderson } 9932a1905c7SRichard Henderson if (cond & 8) { 9942a1905c7SRichard Henderson cmp->cond = tcg_invert_cond(cmp->cond); 995fcf5ef2aSThomas Huth } 996fcf5ef2aSThomas Huth } 997fcf5ef2aSThomas Huth 998fcf5ef2aSThomas Huth static void gen_fcompare(DisasCompare *cmp, unsigned int cc, unsigned int cond) 999fcf5ef2aSThomas Huth { 1000d8c5b92fSRichard Henderson TCGv_i32 fcc = cpu_fcc[cc]; 1001d8c5b92fSRichard Henderson TCGv_i32 c1 = fcc; 1002d8c5b92fSRichard Henderson int c2 = 0; 1003d8c5b92fSRichard Henderson TCGCond tcond; 1004fcf5ef2aSThomas Huth 1005d8c5b92fSRichard Henderson /* 1006d8c5b92fSRichard Henderson * FCC values: 1007d8c5b92fSRichard Henderson * 0 = 1008d8c5b92fSRichard Henderson * 1 < 1009d8c5b92fSRichard Henderson * 2 > 1010d8c5b92fSRichard Henderson * 3 unordered 1011d8c5b92fSRichard Henderson */ 1012d8c5b92fSRichard Henderson switch (cond & 7) { 1013d8c5b92fSRichard Henderson case 0x0: /* fbn */ 1014d8c5b92fSRichard Henderson tcond = TCG_COND_NEVER; 1015fcf5ef2aSThomas Huth break; 1016d8c5b92fSRichard Henderson case 0x1: /* fbne : !0 */ 1017d8c5b92fSRichard Henderson tcond = TCG_COND_NE; 1018fcf5ef2aSThomas Huth break; 1019d8c5b92fSRichard Henderson case 0x2: /* fblg : 1 or 2 */ 1020d8c5b92fSRichard Henderson /* fcc in {1,2} - 1 -> fcc in {0,1} */ 1021d8c5b92fSRichard Henderson c1 = tcg_temp_new_i32(); 1022d8c5b92fSRichard Henderson tcg_gen_addi_i32(c1, fcc, -1); 1023d8c5b92fSRichard Henderson c2 = 1; 1024d8c5b92fSRichard Henderson tcond = TCG_COND_LEU; 1025fcf5ef2aSThomas Huth break; 1026d8c5b92fSRichard Henderson case 0x3: /* fbul : 1 or 3 */ 1027d8c5b92fSRichard Henderson c1 = tcg_temp_new_i32(); 1028d8c5b92fSRichard Henderson tcg_gen_andi_i32(c1, fcc, 1); 1029d8c5b92fSRichard Henderson tcond = TCG_COND_NE; 1030d8c5b92fSRichard Henderson break; 1031d8c5b92fSRichard Henderson case 0x4: /* fbl : 1 */ 1032d8c5b92fSRichard Henderson c2 = 1; 1033d8c5b92fSRichard Henderson tcond = TCG_COND_EQ; 1034d8c5b92fSRichard Henderson break; 1035d8c5b92fSRichard Henderson case 0x5: /* fbug : 2 or 3 */ 1036d8c5b92fSRichard Henderson c2 = 2; 1037d8c5b92fSRichard Henderson tcond = TCG_COND_GEU; 1038d8c5b92fSRichard Henderson break; 1039d8c5b92fSRichard Henderson case 0x6: /* fbg : 2 */ 1040d8c5b92fSRichard Henderson c2 = 2; 1041d8c5b92fSRichard Henderson tcond = TCG_COND_EQ; 1042d8c5b92fSRichard Henderson break; 1043d8c5b92fSRichard Henderson case 0x7: /* fbu : 3 */ 1044d8c5b92fSRichard Henderson c2 = 3; 1045d8c5b92fSRichard Henderson tcond = TCG_COND_EQ; 1046fcf5ef2aSThomas Huth break; 1047fcf5ef2aSThomas Huth } 1048d8c5b92fSRichard Henderson if (cond & 8) { 1049d8c5b92fSRichard Henderson tcond = tcg_invert_cond(tcond); 1050fcf5ef2aSThomas Huth } 1051d8c5b92fSRichard Henderson 1052d8c5b92fSRichard Henderson cmp->cond = tcond; 1053d8c5b92fSRichard Henderson cmp->c2 = c2; 1054d8c5b92fSRichard Henderson cmp->c1 = tcg_temp_new(); 1055d8c5b92fSRichard Henderson tcg_gen_extu_i32_tl(cmp->c1, c1); 1056fcf5ef2aSThomas Huth } 1057fcf5ef2aSThomas Huth 10582c4f56c9SRichard Henderson static bool gen_compare_reg(DisasCompare *cmp, int cond, TCGv r_src) 10592c4f56c9SRichard Henderson { 10602c4f56c9SRichard Henderson static const TCGCond cond_reg[4] = { 1061ab9ffe98SRichard Henderson TCG_COND_NEVER, /* reserved */ 1062fcf5ef2aSThomas Huth TCG_COND_EQ, 1063fcf5ef2aSThomas Huth TCG_COND_LE, 1064fcf5ef2aSThomas Huth TCG_COND_LT, 1065fcf5ef2aSThomas Huth }; 10662c4f56c9SRichard Henderson TCGCond tcond; 1067fcf5ef2aSThomas Huth 10682c4f56c9SRichard Henderson if ((cond & 3) == 0) { 10692c4f56c9SRichard Henderson return false; 10702c4f56c9SRichard Henderson } 10712c4f56c9SRichard Henderson tcond = cond_reg[cond & 3]; 10722c4f56c9SRichard Henderson if (cond & 4) { 10732c4f56c9SRichard Henderson tcond = tcg_invert_cond(tcond); 10742c4f56c9SRichard Henderson } 10752c4f56c9SRichard Henderson 10762c4f56c9SRichard Henderson cmp->cond = tcond; 1077816f89b7SRichard Henderson cmp->c1 = tcg_temp_new(); 1078c8507ebfSRichard Henderson cmp->c2 = 0; 1079816f89b7SRichard Henderson tcg_gen_mov_tl(cmp->c1, r_src); 10802c4f56c9SRichard Henderson return true; 1081fcf5ef2aSThomas Huth } 1082fcf5ef2aSThomas Huth 1083baf3dbf2SRichard Henderson static void gen_op_clear_ieee_excp_and_FTT(void) 1084baf3dbf2SRichard Henderson { 10853590f01eSRichard Henderson tcg_gen_st_i32(tcg_constant_i32(0), tcg_env, 10863590f01eSRichard Henderson offsetof(CPUSPARCState, fsr_cexc_ftt)); 1087baf3dbf2SRichard Henderson } 1088baf3dbf2SRichard Henderson 1089baf3dbf2SRichard Henderson static void gen_op_fmovs(TCGv_i32 dst, TCGv_i32 src) 1090baf3dbf2SRichard Henderson { 1091baf3dbf2SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 1092baf3dbf2SRichard Henderson tcg_gen_mov_i32(dst, src); 1093baf3dbf2SRichard Henderson } 1094baf3dbf2SRichard Henderson 1095baf3dbf2SRichard Henderson static void gen_op_fnegs(TCGv_i32 dst, TCGv_i32 src) 1096baf3dbf2SRichard Henderson { 1097baf3dbf2SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 1098daf457d4SRichard Henderson tcg_gen_xori_i32(dst, src, 1u << 31); 1099baf3dbf2SRichard Henderson } 1100baf3dbf2SRichard Henderson 1101baf3dbf2SRichard Henderson static void gen_op_fabss(TCGv_i32 dst, TCGv_i32 src) 1102baf3dbf2SRichard Henderson { 1103baf3dbf2SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 1104daf457d4SRichard Henderson tcg_gen_andi_i32(dst, src, ~(1u << 31)); 1105baf3dbf2SRichard Henderson } 1106baf3dbf2SRichard Henderson 1107c6d83e4fSRichard Henderson static void gen_op_fmovd(TCGv_i64 dst, TCGv_i64 src) 1108c6d83e4fSRichard Henderson { 1109c6d83e4fSRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 1110c6d83e4fSRichard Henderson tcg_gen_mov_i64(dst, src); 1111c6d83e4fSRichard Henderson } 1112c6d83e4fSRichard Henderson 1113c6d83e4fSRichard Henderson static void gen_op_fnegd(TCGv_i64 dst, TCGv_i64 src) 1114c6d83e4fSRichard Henderson { 1115c6d83e4fSRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 1116daf457d4SRichard Henderson tcg_gen_xori_i64(dst, src, 1ull << 63); 1117c6d83e4fSRichard Henderson } 1118c6d83e4fSRichard Henderson 1119c6d83e4fSRichard Henderson static void gen_op_fabsd(TCGv_i64 dst, TCGv_i64 src) 1120c6d83e4fSRichard Henderson { 1121c6d83e4fSRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 1122daf457d4SRichard Henderson tcg_gen_andi_i64(dst, src, ~(1ull << 63)); 1123daf457d4SRichard Henderson } 1124daf457d4SRichard Henderson 1125daf457d4SRichard Henderson static void gen_op_fnegq(TCGv_i128 dst, TCGv_i128 src) 1126daf457d4SRichard Henderson { 1127daf457d4SRichard Henderson TCGv_i64 l = tcg_temp_new_i64(); 1128daf457d4SRichard Henderson TCGv_i64 h = tcg_temp_new_i64(); 1129daf457d4SRichard Henderson 1130daf457d4SRichard Henderson tcg_gen_extr_i128_i64(l, h, src); 1131daf457d4SRichard Henderson tcg_gen_xori_i64(h, h, 1ull << 63); 1132daf457d4SRichard Henderson tcg_gen_concat_i64_i128(dst, l, h); 1133daf457d4SRichard Henderson } 1134daf457d4SRichard Henderson 1135daf457d4SRichard Henderson static void gen_op_fabsq(TCGv_i128 dst, TCGv_i128 src) 1136daf457d4SRichard Henderson { 1137daf457d4SRichard Henderson TCGv_i64 l = tcg_temp_new_i64(); 1138daf457d4SRichard Henderson TCGv_i64 h = tcg_temp_new_i64(); 1139daf457d4SRichard Henderson 1140daf457d4SRichard Henderson tcg_gen_extr_i128_i64(l, h, src); 1141daf457d4SRichard Henderson tcg_gen_andi_i64(h, h, ~(1ull << 63)); 1142daf457d4SRichard Henderson tcg_gen_concat_i64_i128(dst, l, h); 1143c6d83e4fSRichard Henderson } 1144c6d83e4fSRichard Henderson 11453590f01eSRichard Henderson static void gen_op_fpexception_im(DisasContext *dc, int ftt) 1146fcf5ef2aSThomas Huth { 11473590f01eSRichard Henderson /* 11483590f01eSRichard Henderson * CEXC is only set when succesfully completing an FPop, 11493590f01eSRichard Henderson * or when raising FSR_FTT_IEEE_EXCP, i.e. check_ieee_exception. 11503590f01eSRichard Henderson * Thus we can simply store FTT into this field. 11513590f01eSRichard Henderson */ 11523590f01eSRichard Henderson tcg_gen_st_i32(tcg_constant_i32(ftt), tcg_env, 11533590f01eSRichard Henderson offsetof(CPUSPARCState, fsr_cexc_ftt)); 1154fcf5ef2aSThomas Huth gen_exception(dc, TT_FP_EXCP); 1155fcf5ef2aSThomas Huth } 1156fcf5ef2aSThomas Huth 1157fcf5ef2aSThomas Huth static int gen_trap_ifnofpu(DisasContext *dc) 1158fcf5ef2aSThomas Huth { 1159fcf5ef2aSThomas Huth #if !defined(CONFIG_USER_ONLY) 1160fcf5ef2aSThomas Huth if (!dc->fpu_enabled) { 1161fcf5ef2aSThomas Huth gen_exception(dc, TT_NFPU_INSN); 1162fcf5ef2aSThomas Huth return 1; 1163fcf5ef2aSThomas Huth } 1164fcf5ef2aSThomas Huth #endif 1165fcf5ef2aSThomas Huth return 0; 1166fcf5ef2aSThomas Huth } 1167fcf5ef2aSThomas Huth 1168fcf5ef2aSThomas Huth /* asi moves */ 1169fcf5ef2aSThomas Huth typedef enum { 1170fcf5ef2aSThomas Huth GET_ASI_HELPER, 1171fcf5ef2aSThomas Huth GET_ASI_EXCP, 1172fcf5ef2aSThomas Huth GET_ASI_DIRECT, 1173fcf5ef2aSThomas Huth GET_ASI_DTWINX, 11742786a3f8SRichard Henderson GET_ASI_CODE, 1175fcf5ef2aSThomas Huth GET_ASI_BLOCK, 1176fcf5ef2aSThomas Huth GET_ASI_SHORT, 1177fcf5ef2aSThomas Huth GET_ASI_BCOPY, 1178fcf5ef2aSThomas Huth GET_ASI_BFILL, 1179fcf5ef2aSThomas Huth } ASIType; 1180fcf5ef2aSThomas Huth 1181fcf5ef2aSThomas Huth typedef struct { 1182fcf5ef2aSThomas Huth ASIType type; 1183fcf5ef2aSThomas Huth int asi; 1184fcf5ef2aSThomas Huth int mem_idx; 118514776ab5STony Nguyen MemOp memop; 1186fcf5ef2aSThomas Huth } DisasASI; 1187fcf5ef2aSThomas Huth 1188811cc0b0SRichard Henderson /* 1189811cc0b0SRichard Henderson * Build DisasASI. 1190811cc0b0SRichard Henderson * For asi == -1, treat as non-asi. 1191811cc0b0SRichard Henderson * For ask == -2, treat as immediate offset (v8 error, v9 %asi). 1192811cc0b0SRichard Henderson */ 1193811cc0b0SRichard Henderson static DisasASI resolve_asi(DisasContext *dc, int asi, MemOp memop) 1194fcf5ef2aSThomas Huth { 1195fcf5ef2aSThomas Huth ASIType type = GET_ASI_HELPER; 1196fcf5ef2aSThomas Huth int mem_idx = dc->mem_idx; 1197fcf5ef2aSThomas Huth 1198811cc0b0SRichard Henderson if (asi == -1) { 1199811cc0b0SRichard Henderson /* Artificial "non-asi" case. */ 1200811cc0b0SRichard Henderson type = GET_ASI_DIRECT; 1201811cc0b0SRichard Henderson goto done; 1202811cc0b0SRichard Henderson } 1203811cc0b0SRichard Henderson 1204fcf5ef2aSThomas Huth #ifndef TARGET_SPARC64 1205fcf5ef2aSThomas Huth /* Before v9, all asis are immediate and privileged. */ 1206811cc0b0SRichard Henderson if (asi < 0) { 1207fcf5ef2aSThomas Huth gen_exception(dc, TT_ILL_INSN); 1208fcf5ef2aSThomas Huth type = GET_ASI_EXCP; 1209fcf5ef2aSThomas Huth } else if (supervisor(dc) 1210fcf5ef2aSThomas Huth /* Note that LEON accepts ASI_USERDATA in user mode, for 1211fcf5ef2aSThomas Huth use with CASA. Also note that previous versions of 1212fcf5ef2aSThomas Huth QEMU allowed (and old versions of gcc emitted) ASI_P 1213fcf5ef2aSThomas Huth for LEON, which is incorrect. */ 1214fcf5ef2aSThomas Huth || (asi == ASI_USERDATA 1215fcf5ef2aSThomas Huth && (dc->def->features & CPU_FEATURE_CASA))) { 1216fcf5ef2aSThomas Huth switch (asi) { 1217fcf5ef2aSThomas Huth case ASI_USERDATA: /* User data access */ 1218fcf5ef2aSThomas Huth mem_idx = MMU_USER_IDX; 1219fcf5ef2aSThomas Huth type = GET_ASI_DIRECT; 1220fcf5ef2aSThomas Huth break; 1221fcf5ef2aSThomas Huth case ASI_KERNELDATA: /* Supervisor data access */ 1222fcf5ef2aSThomas Huth mem_idx = MMU_KERNEL_IDX; 1223fcf5ef2aSThomas Huth type = GET_ASI_DIRECT; 1224fcf5ef2aSThomas Huth break; 12252786a3f8SRichard Henderson case ASI_USERTXT: /* User text access */ 12262786a3f8SRichard Henderson mem_idx = MMU_USER_IDX; 12272786a3f8SRichard Henderson type = GET_ASI_CODE; 12282786a3f8SRichard Henderson break; 12292786a3f8SRichard Henderson case ASI_KERNELTXT: /* Supervisor text access */ 12302786a3f8SRichard Henderson mem_idx = MMU_KERNEL_IDX; 12312786a3f8SRichard Henderson type = GET_ASI_CODE; 12322786a3f8SRichard Henderson break; 1233fcf5ef2aSThomas Huth case ASI_M_BYPASS: /* MMU passthrough */ 1234fcf5ef2aSThomas Huth case ASI_LEON_BYPASS: /* LEON MMU passthrough */ 1235fcf5ef2aSThomas Huth mem_idx = MMU_PHYS_IDX; 1236fcf5ef2aSThomas Huth type = GET_ASI_DIRECT; 1237fcf5ef2aSThomas Huth break; 1238fcf5ef2aSThomas Huth case ASI_M_BCOPY: /* Block copy, sta access */ 1239fcf5ef2aSThomas Huth mem_idx = MMU_KERNEL_IDX; 1240fcf5ef2aSThomas Huth type = GET_ASI_BCOPY; 1241fcf5ef2aSThomas Huth break; 1242fcf5ef2aSThomas Huth case ASI_M_BFILL: /* Block fill, stda access */ 1243fcf5ef2aSThomas Huth mem_idx = MMU_KERNEL_IDX; 1244fcf5ef2aSThomas Huth type = GET_ASI_BFILL; 1245fcf5ef2aSThomas Huth break; 1246fcf5ef2aSThomas Huth } 12476e10f37cSKONRAD Frederic 12486e10f37cSKONRAD Frederic /* MMU_PHYS_IDX is used when the MMU is disabled to passthrough the 12496e10f37cSKONRAD Frederic * permissions check in get_physical_address(..). 12506e10f37cSKONRAD Frederic */ 12516e10f37cSKONRAD Frederic mem_idx = (dc->mem_idx == MMU_PHYS_IDX) ? MMU_PHYS_IDX : mem_idx; 1252fcf5ef2aSThomas Huth } else { 1253fcf5ef2aSThomas Huth gen_exception(dc, TT_PRIV_INSN); 1254fcf5ef2aSThomas Huth type = GET_ASI_EXCP; 1255fcf5ef2aSThomas Huth } 1256fcf5ef2aSThomas Huth #else 1257811cc0b0SRichard Henderson if (asi < 0) { 1258fcf5ef2aSThomas Huth asi = dc->asi; 1259fcf5ef2aSThomas Huth } 1260fcf5ef2aSThomas Huth /* With v9, all asis below 0x80 are privileged. */ 1261fcf5ef2aSThomas Huth /* ??? We ought to check cpu_has_hypervisor, but we didn't copy 1262fcf5ef2aSThomas Huth down that bit into DisasContext. For the moment that's ok, 1263fcf5ef2aSThomas Huth since the direct implementations below doesn't have any ASIs 1264fcf5ef2aSThomas Huth in the restricted [0x30, 0x7f] range, and the check will be 1265fcf5ef2aSThomas Huth done properly in the helper. */ 1266fcf5ef2aSThomas Huth if (!supervisor(dc) && asi < 0x80) { 1267fcf5ef2aSThomas Huth gen_exception(dc, TT_PRIV_ACT); 1268fcf5ef2aSThomas Huth type = GET_ASI_EXCP; 1269fcf5ef2aSThomas Huth } else { 1270fcf5ef2aSThomas Huth switch (asi) { 1271fcf5ef2aSThomas Huth case ASI_REAL: /* Bypass */ 1272fcf5ef2aSThomas Huth case ASI_REAL_IO: /* Bypass, non-cacheable */ 1273fcf5ef2aSThomas Huth case ASI_REAL_L: /* Bypass LE */ 1274fcf5ef2aSThomas Huth case ASI_REAL_IO_L: /* Bypass, non-cacheable LE */ 1275fcf5ef2aSThomas Huth case ASI_TWINX_REAL: /* Real address, twinx */ 1276fcf5ef2aSThomas Huth case ASI_TWINX_REAL_L: /* Real address, twinx, LE */ 1277fcf5ef2aSThomas Huth case ASI_QUAD_LDD_PHYS: 1278fcf5ef2aSThomas Huth case ASI_QUAD_LDD_PHYS_L: 1279fcf5ef2aSThomas Huth mem_idx = MMU_PHYS_IDX; 1280fcf5ef2aSThomas Huth break; 1281fcf5ef2aSThomas Huth case ASI_N: /* Nucleus */ 1282fcf5ef2aSThomas Huth case ASI_NL: /* Nucleus LE */ 1283fcf5ef2aSThomas Huth case ASI_TWINX_N: 1284fcf5ef2aSThomas Huth case ASI_TWINX_NL: 1285fcf5ef2aSThomas Huth case ASI_NUCLEUS_QUAD_LDD: 1286fcf5ef2aSThomas Huth case ASI_NUCLEUS_QUAD_LDD_L: 12879a10756dSArtyom Tarasenko if (hypervisor(dc)) { 128884f8f587SArtyom Tarasenko mem_idx = MMU_PHYS_IDX; 12899a10756dSArtyom Tarasenko } else { 1290fcf5ef2aSThomas Huth mem_idx = MMU_NUCLEUS_IDX; 12919a10756dSArtyom Tarasenko } 1292fcf5ef2aSThomas Huth break; 1293fcf5ef2aSThomas Huth case ASI_AIUP: /* As if user primary */ 1294fcf5ef2aSThomas Huth case ASI_AIUPL: /* As if user primary LE */ 1295fcf5ef2aSThomas Huth case ASI_TWINX_AIUP: 1296fcf5ef2aSThomas Huth case ASI_TWINX_AIUP_L: 1297fcf5ef2aSThomas Huth case ASI_BLK_AIUP_4V: 1298fcf5ef2aSThomas Huth case ASI_BLK_AIUP_L_4V: 1299fcf5ef2aSThomas Huth case ASI_BLK_AIUP: 1300fcf5ef2aSThomas Huth case ASI_BLK_AIUPL: 1301fcf5ef2aSThomas Huth mem_idx = MMU_USER_IDX; 1302fcf5ef2aSThomas Huth break; 1303fcf5ef2aSThomas Huth case ASI_AIUS: /* As if user secondary */ 1304fcf5ef2aSThomas Huth case ASI_AIUSL: /* As if user secondary LE */ 1305fcf5ef2aSThomas Huth case ASI_TWINX_AIUS: 1306fcf5ef2aSThomas Huth case ASI_TWINX_AIUS_L: 1307fcf5ef2aSThomas Huth case ASI_BLK_AIUS_4V: 1308fcf5ef2aSThomas Huth case ASI_BLK_AIUS_L_4V: 1309fcf5ef2aSThomas Huth case ASI_BLK_AIUS: 1310fcf5ef2aSThomas Huth case ASI_BLK_AIUSL: 1311fcf5ef2aSThomas Huth mem_idx = MMU_USER_SECONDARY_IDX; 1312fcf5ef2aSThomas Huth break; 1313fcf5ef2aSThomas Huth case ASI_S: /* Secondary */ 1314fcf5ef2aSThomas Huth case ASI_SL: /* Secondary LE */ 1315fcf5ef2aSThomas Huth case ASI_TWINX_S: 1316fcf5ef2aSThomas Huth case ASI_TWINX_SL: 1317fcf5ef2aSThomas Huth case ASI_BLK_COMMIT_S: 1318fcf5ef2aSThomas Huth case ASI_BLK_S: 1319fcf5ef2aSThomas Huth case ASI_BLK_SL: 1320fcf5ef2aSThomas Huth case ASI_FL8_S: 1321fcf5ef2aSThomas Huth case ASI_FL8_SL: 1322fcf5ef2aSThomas Huth case ASI_FL16_S: 1323fcf5ef2aSThomas Huth case ASI_FL16_SL: 1324fcf5ef2aSThomas Huth if (mem_idx == MMU_USER_IDX) { 1325fcf5ef2aSThomas Huth mem_idx = MMU_USER_SECONDARY_IDX; 1326fcf5ef2aSThomas Huth } else if (mem_idx == MMU_KERNEL_IDX) { 1327fcf5ef2aSThomas Huth mem_idx = MMU_KERNEL_SECONDARY_IDX; 1328fcf5ef2aSThomas Huth } 1329fcf5ef2aSThomas Huth break; 1330fcf5ef2aSThomas Huth case ASI_P: /* Primary */ 1331fcf5ef2aSThomas Huth case ASI_PL: /* Primary LE */ 1332fcf5ef2aSThomas Huth case ASI_TWINX_P: 1333fcf5ef2aSThomas Huth case ASI_TWINX_PL: 1334fcf5ef2aSThomas Huth case ASI_BLK_COMMIT_P: 1335fcf5ef2aSThomas Huth case ASI_BLK_P: 1336fcf5ef2aSThomas Huth case ASI_BLK_PL: 1337fcf5ef2aSThomas Huth case ASI_FL8_P: 1338fcf5ef2aSThomas Huth case ASI_FL8_PL: 1339fcf5ef2aSThomas Huth case ASI_FL16_P: 1340fcf5ef2aSThomas Huth case ASI_FL16_PL: 1341fcf5ef2aSThomas Huth break; 1342fcf5ef2aSThomas Huth } 1343fcf5ef2aSThomas Huth switch (asi) { 1344fcf5ef2aSThomas Huth case ASI_REAL: 1345fcf5ef2aSThomas Huth case ASI_REAL_IO: 1346fcf5ef2aSThomas Huth case ASI_REAL_L: 1347fcf5ef2aSThomas Huth case ASI_REAL_IO_L: 1348fcf5ef2aSThomas Huth case ASI_N: 1349fcf5ef2aSThomas Huth case ASI_NL: 1350fcf5ef2aSThomas Huth case ASI_AIUP: 1351fcf5ef2aSThomas Huth case ASI_AIUPL: 1352fcf5ef2aSThomas Huth case ASI_AIUS: 1353fcf5ef2aSThomas Huth case ASI_AIUSL: 1354fcf5ef2aSThomas Huth case ASI_S: 1355fcf5ef2aSThomas Huth case ASI_SL: 1356fcf5ef2aSThomas Huth case ASI_P: 1357fcf5ef2aSThomas Huth case ASI_PL: 1358fcf5ef2aSThomas Huth type = GET_ASI_DIRECT; 1359fcf5ef2aSThomas Huth break; 1360fcf5ef2aSThomas Huth case ASI_TWINX_REAL: 1361fcf5ef2aSThomas Huth case ASI_TWINX_REAL_L: 1362fcf5ef2aSThomas Huth case ASI_TWINX_N: 1363fcf5ef2aSThomas Huth case ASI_TWINX_NL: 1364fcf5ef2aSThomas Huth case ASI_TWINX_AIUP: 1365fcf5ef2aSThomas Huth case ASI_TWINX_AIUP_L: 1366fcf5ef2aSThomas Huth case ASI_TWINX_AIUS: 1367fcf5ef2aSThomas Huth case ASI_TWINX_AIUS_L: 1368fcf5ef2aSThomas Huth case ASI_TWINX_P: 1369fcf5ef2aSThomas Huth case ASI_TWINX_PL: 1370fcf5ef2aSThomas Huth case ASI_TWINX_S: 1371fcf5ef2aSThomas Huth case ASI_TWINX_SL: 1372fcf5ef2aSThomas Huth case ASI_QUAD_LDD_PHYS: 1373fcf5ef2aSThomas Huth case ASI_QUAD_LDD_PHYS_L: 1374fcf5ef2aSThomas Huth case ASI_NUCLEUS_QUAD_LDD: 1375fcf5ef2aSThomas Huth case ASI_NUCLEUS_QUAD_LDD_L: 1376fcf5ef2aSThomas Huth type = GET_ASI_DTWINX; 1377fcf5ef2aSThomas Huth break; 1378fcf5ef2aSThomas Huth case ASI_BLK_COMMIT_P: 1379fcf5ef2aSThomas Huth case ASI_BLK_COMMIT_S: 1380fcf5ef2aSThomas Huth case ASI_BLK_AIUP_4V: 1381fcf5ef2aSThomas Huth case ASI_BLK_AIUP_L_4V: 1382fcf5ef2aSThomas Huth case ASI_BLK_AIUP: 1383fcf5ef2aSThomas Huth case ASI_BLK_AIUPL: 1384fcf5ef2aSThomas Huth case ASI_BLK_AIUS_4V: 1385fcf5ef2aSThomas Huth case ASI_BLK_AIUS_L_4V: 1386fcf5ef2aSThomas Huth case ASI_BLK_AIUS: 1387fcf5ef2aSThomas Huth case ASI_BLK_AIUSL: 1388fcf5ef2aSThomas Huth case ASI_BLK_S: 1389fcf5ef2aSThomas Huth case ASI_BLK_SL: 1390fcf5ef2aSThomas Huth case ASI_BLK_P: 1391fcf5ef2aSThomas Huth case ASI_BLK_PL: 1392fcf5ef2aSThomas Huth type = GET_ASI_BLOCK; 1393fcf5ef2aSThomas Huth break; 1394fcf5ef2aSThomas Huth case ASI_FL8_S: 1395fcf5ef2aSThomas Huth case ASI_FL8_SL: 1396fcf5ef2aSThomas Huth case ASI_FL8_P: 1397fcf5ef2aSThomas Huth case ASI_FL8_PL: 1398fcf5ef2aSThomas Huth memop = MO_UB; 1399fcf5ef2aSThomas Huth type = GET_ASI_SHORT; 1400fcf5ef2aSThomas Huth break; 1401fcf5ef2aSThomas Huth case ASI_FL16_S: 1402fcf5ef2aSThomas Huth case ASI_FL16_SL: 1403fcf5ef2aSThomas Huth case ASI_FL16_P: 1404fcf5ef2aSThomas Huth case ASI_FL16_PL: 1405fcf5ef2aSThomas Huth memop = MO_TEUW; 1406fcf5ef2aSThomas Huth type = GET_ASI_SHORT; 1407fcf5ef2aSThomas Huth break; 1408fcf5ef2aSThomas Huth } 1409fcf5ef2aSThomas Huth /* The little-endian asis all have bit 3 set. */ 1410fcf5ef2aSThomas Huth if (asi & 8) { 1411fcf5ef2aSThomas Huth memop ^= MO_BSWAP; 1412fcf5ef2aSThomas Huth } 1413fcf5ef2aSThomas Huth } 1414fcf5ef2aSThomas Huth #endif 1415fcf5ef2aSThomas Huth 1416811cc0b0SRichard Henderson done: 1417fcf5ef2aSThomas Huth return (DisasASI){ type, asi, mem_idx, memop }; 1418fcf5ef2aSThomas Huth } 1419fcf5ef2aSThomas Huth 1420a76779eeSRichard Henderson #if defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64) 1421a76779eeSRichard Henderson static void gen_helper_ld_asi(TCGv_i64 r, TCGv_env e, TCGv a, 1422a76779eeSRichard Henderson TCGv_i32 asi, TCGv_i32 mop) 1423a76779eeSRichard Henderson { 1424a76779eeSRichard Henderson g_assert_not_reached(); 1425a76779eeSRichard Henderson } 1426a76779eeSRichard Henderson 1427a76779eeSRichard Henderson static void gen_helper_st_asi(TCGv_env e, TCGv a, TCGv_i64 r, 1428a76779eeSRichard Henderson TCGv_i32 asi, TCGv_i32 mop) 1429a76779eeSRichard Henderson { 1430a76779eeSRichard Henderson g_assert_not_reached(); 1431a76779eeSRichard Henderson } 1432a76779eeSRichard Henderson #endif 1433a76779eeSRichard Henderson 143442071fc1SRichard Henderson static void gen_ld_asi(DisasContext *dc, DisasASI *da, TCGv dst, TCGv addr) 1435fcf5ef2aSThomas Huth { 1436c03a0fd1SRichard Henderson switch (da->type) { 1437fcf5ef2aSThomas Huth case GET_ASI_EXCP: 1438fcf5ef2aSThomas Huth break; 1439fcf5ef2aSThomas Huth case GET_ASI_DTWINX: /* Reserved for ldda. */ 1440fcf5ef2aSThomas Huth gen_exception(dc, TT_ILL_INSN); 1441fcf5ef2aSThomas Huth break; 1442fcf5ef2aSThomas Huth case GET_ASI_DIRECT: 1443c03a0fd1SRichard Henderson tcg_gen_qemu_ld_tl(dst, addr, da->mem_idx, da->memop | MO_ALIGN); 1444fcf5ef2aSThomas Huth break; 14452786a3f8SRichard Henderson 14462786a3f8SRichard Henderson case GET_ASI_CODE: 14472786a3f8SRichard Henderson #if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64) 14482786a3f8SRichard Henderson { 14492786a3f8SRichard Henderson MemOpIdx oi = make_memop_idx(da->memop, da->mem_idx); 14502786a3f8SRichard Henderson TCGv_i64 t64 = tcg_temp_new_i64(); 14512786a3f8SRichard Henderson 14522786a3f8SRichard Henderson gen_helper_ld_code(t64, tcg_env, addr, tcg_constant_i32(oi)); 14532786a3f8SRichard Henderson tcg_gen_trunc_i64_tl(dst, t64); 14542786a3f8SRichard Henderson } 14552786a3f8SRichard Henderson break; 14562786a3f8SRichard Henderson #else 14572786a3f8SRichard Henderson g_assert_not_reached(); 14582786a3f8SRichard Henderson #endif 14592786a3f8SRichard Henderson 1460fcf5ef2aSThomas Huth default: 1461fcf5ef2aSThomas Huth { 1462c03a0fd1SRichard Henderson TCGv_i32 r_asi = tcg_constant_i32(da->asi); 1463c03a0fd1SRichard Henderson TCGv_i32 r_mop = tcg_constant_i32(da->memop | MO_ALIGN); 1464fcf5ef2aSThomas Huth 1465fcf5ef2aSThomas Huth save_state(dc); 1466fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64 1467ad75a51eSRichard Henderson gen_helper_ld_asi(dst, tcg_env, addr, r_asi, r_mop); 1468fcf5ef2aSThomas Huth #else 1469fcf5ef2aSThomas Huth { 1470fcf5ef2aSThomas Huth TCGv_i64 t64 = tcg_temp_new_i64(); 1471ad75a51eSRichard Henderson gen_helper_ld_asi(t64, tcg_env, addr, r_asi, r_mop); 1472fcf5ef2aSThomas Huth tcg_gen_trunc_i64_tl(dst, t64); 1473fcf5ef2aSThomas Huth } 1474fcf5ef2aSThomas Huth #endif 1475fcf5ef2aSThomas Huth } 1476fcf5ef2aSThomas Huth break; 1477fcf5ef2aSThomas Huth } 1478fcf5ef2aSThomas Huth } 1479fcf5ef2aSThomas Huth 148042071fc1SRichard Henderson static void gen_st_asi(DisasContext *dc, DisasASI *da, TCGv src, TCGv addr) 1481c03a0fd1SRichard Henderson { 1482c03a0fd1SRichard Henderson switch (da->type) { 1483fcf5ef2aSThomas Huth case GET_ASI_EXCP: 1484fcf5ef2aSThomas Huth break; 1485c03a0fd1SRichard Henderson 1486fcf5ef2aSThomas Huth case GET_ASI_DTWINX: /* Reserved for stda. */ 1487c03a0fd1SRichard Henderson if (TARGET_LONG_BITS == 32) { 1488fcf5ef2aSThomas Huth gen_exception(dc, TT_ILL_INSN); 1489fcf5ef2aSThomas Huth break; 1490c03a0fd1SRichard Henderson } else if (!(dc->def->features & CPU_FEATURE_HYPV)) { 14913390537bSArtyom Tarasenko /* Pre OpenSPARC CPUs don't have these */ 14923390537bSArtyom Tarasenko gen_exception(dc, TT_ILL_INSN); 1493fcf5ef2aSThomas Huth break; 1494c03a0fd1SRichard Henderson } 1495c03a0fd1SRichard Henderson /* In OpenSPARC T1+ CPUs TWINX ASIs in store are ST_BLKINIT_ ASIs */ 1496c03a0fd1SRichard Henderson /* fall through */ 1497c03a0fd1SRichard Henderson 1498c03a0fd1SRichard Henderson case GET_ASI_DIRECT: 1499c03a0fd1SRichard Henderson tcg_gen_qemu_st_tl(src, addr, da->mem_idx, da->memop | MO_ALIGN); 1500c03a0fd1SRichard Henderson break; 1501c03a0fd1SRichard Henderson 1502fcf5ef2aSThomas Huth case GET_ASI_BCOPY: 1503c03a0fd1SRichard Henderson assert(TARGET_LONG_BITS == 32); 150498271007SRichard Henderson /* 150598271007SRichard Henderson * Copy 32 bytes from the address in SRC to ADDR. 150698271007SRichard Henderson * 150798271007SRichard Henderson * From Ross RT625 hyperSPARC manual, section 4.6: 150898271007SRichard Henderson * "Block Copy and Block Fill will work only on cache line boundaries." 150998271007SRichard Henderson * 151098271007SRichard Henderson * It does not specify if an unaliged address is truncated or trapped. 151198271007SRichard Henderson * Previous qemu behaviour was to truncate to 4 byte alignment, which 151298271007SRichard Henderson * is obviously wrong. The only place I can see this used is in the 151398271007SRichard Henderson * Linux kernel which begins with page alignment, advancing by 32, 151498271007SRichard Henderson * so is always aligned. Assume truncation as the simpler option. 151598271007SRichard Henderson * 151698271007SRichard Henderson * Since the loads and stores are paired, allow the copy to happen 151798271007SRichard Henderson * in the host endianness. The copy need not be atomic. 151898271007SRichard Henderson */ 1519fcf5ef2aSThomas Huth { 152098271007SRichard Henderson MemOp mop = MO_128 | MO_ATOM_IFALIGN_PAIR; 1521fcf5ef2aSThomas Huth TCGv saddr = tcg_temp_new(); 1522fcf5ef2aSThomas Huth TCGv daddr = tcg_temp_new(); 152398271007SRichard Henderson TCGv_i128 tmp = tcg_temp_new_i128(); 1524fcf5ef2aSThomas Huth 152598271007SRichard Henderson tcg_gen_andi_tl(saddr, src, -32); 152698271007SRichard Henderson tcg_gen_andi_tl(daddr, addr, -32); 152798271007SRichard Henderson tcg_gen_qemu_ld_i128(tmp, saddr, da->mem_idx, mop); 152898271007SRichard Henderson tcg_gen_qemu_st_i128(tmp, daddr, da->mem_idx, mop); 152998271007SRichard Henderson tcg_gen_addi_tl(saddr, saddr, 16); 153098271007SRichard Henderson tcg_gen_addi_tl(daddr, daddr, 16); 153198271007SRichard Henderson tcg_gen_qemu_ld_i128(tmp, saddr, da->mem_idx, mop); 153298271007SRichard Henderson tcg_gen_qemu_st_i128(tmp, daddr, da->mem_idx, mop); 1533fcf5ef2aSThomas Huth } 1534fcf5ef2aSThomas Huth break; 1535c03a0fd1SRichard Henderson 1536fcf5ef2aSThomas Huth default: 1537fcf5ef2aSThomas Huth { 1538c03a0fd1SRichard Henderson TCGv_i32 r_asi = tcg_constant_i32(da->asi); 1539c03a0fd1SRichard Henderson TCGv_i32 r_mop = tcg_constant_i32(da->memop | MO_ALIGN); 1540fcf5ef2aSThomas Huth 1541fcf5ef2aSThomas Huth save_state(dc); 1542fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64 1543ad75a51eSRichard Henderson gen_helper_st_asi(tcg_env, addr, src, r_asi, r_mop); 1544fcf5ef2aSThomas Huth #else 1545fcf5ef2aSThomas Huth { 1546fcf5ef2aSThomas Huth TCGv_i64 t64 = tcg_temp_new_i64(); 1547fcf5ef2aSThomas Huth tcg_gen_extu_tl_i64(t64, src); 1548ad75a51eSRichard Henderson gen_helper_st_asi(tcg_env, addr, t64, r_asi, r_mop); 1549fcf5ef2aSThomas Huth } 1550fcf5ef2aSThomas Huth #endif 1551fcf5ef2aSThomas Huth 1552fcf5ef2aSThomas Huth /* A write to a TLB register may alter page maps. End the TB. */ 1553fcf5ef2aSThomas Huth dc->npc = DYNAMIC_PC; 1554fcf5ef2aSThomas Huth } 1555fcf5ef2aSThomas Huth break; 1556fcf5ef2aSThomas Huth } 1557fcf5ef2aSThomas Huth } 1558fcf5ef2aSThomas Huth 1559dca544b9SRichard Henderson static void gen_swap_asi(DisasContext *dc, DisasASI *da, 1560c03a0fd1SRichard Henderson TCGv dst, TCGv src, TCGv addr) 1561c03a0fd1SRichard Henderson { 1562c03a0fd1SRichard Henderson switch (da->type) { 1563c03a0fd1SRichard Henderson case GET_ASI_EXCP: 1564c03a0fd1SRichard Henderson break; 1565c03a0fd1SRichard Henderson case GET_ASI_DIRECT: 1566dca544b9SRichard Henderson tcg_gen_atomic_xchg_tl(dst, addr, src, 1567dca544b9SRichard Henderson da->mem_idx, da->memop | MO_ALIGN); 1568c03a0fd1SRichard Henderson break; 1569c03a0fd1SRichard Henderson default: 1570c03a0fd1SRichard Henderson /* ??? Should be DAE_invalid_asi. */ 1571c03a0fd1SRichard Henderson gen_exception(dc, TT_DATA_ACCESS); 1572c03a0fd1SRichard Henderson break; 1573c03a0fd1SRichard Henderson } 1574c03a0fd1SRichard Henderson } 1575c03a0fd1SRichard Henderson 1576d0a11d25SRichard Henderson static void gen_cas_asi(DisasContext *dc, DisasASI *da, 1577c03a0fd1SRichard Henderson TCGv oldv, TCGv newv, TCGv cmpv, TCGv addr) 1578c03a0fd1SRichard Henderson { 1579c03a0fd1SRichard Henderson switch (da->type) { 1580fcf5ef2aSThomas Huth case GET_ASI_EXCP: 1581c03a0fd1SRichard Henderson return; 1582fcf5ef2aSThomas Huth case GET_ASI_DIRECT: 1583c03a0fd1SRichard Henderson tcg_gen_atomic_cmpxchg_tl(oldv, addr, cmpv, newv, 1584c03a0fd1SRichard Henderson da->mem_idx, da->memop | MO_ALIGN); 1585fcf5ef2aSThomas Huth break; 1586fcf5ef2aSThomas Huth default: 1587fcf5ef2aSThomas Huth /* ??? Should be DAE_invalid_asi. */ 1588fcf5ef2aSThomas Huth gen_exception(dc, TT_DATA_ACCESS); 1589fcf5ef2aSThomas Huth break; 1590fcf5ef2aSThomas Huth } 1591fcf5ef2aSThomas Huth } 1592fcf5ef2aSThomas Huth 1593cf07cd1eSRichard Henderson static void gen_ldstub_asi(DisasContext *dc, DisasASI *da, TCGv dst, TCGv addr) 1594c03a0fd1SRichard Henderson { 1595c03a0fd1SRichard Henderson switch (da->type) { 1596fcf5ef2aSThomas Huth case GET_ASI_EXCP: 1597fcf5ef2aSThomas Huth break; 1598fcf5ef2aSThomas Huth case GET_ASI_DIRECT: 1599cf07cd1eSRichard Henderson tcg_gen_atomic_xchg_tl(dst, addr, tcg_constant_tl(0xff), 1600cf07cd1eSRichard Henderson da->mem_idx, MO_UB); 1601fcf5ef2aSThomas Huth break; 1602fcf5ef2aSThomas Huth default: 16033db010c3SRichard Henderson /* ??? In theory, this should be raise DAE_invalid_asi. 16043db010c3SRichard Henderson But the SS-20 roms do ldstuba [%l0] #ASI_M_CTL, %o1. */ 1605af00be49SEmilio G. Cota if (tb_cflags(dc->base.tb) & CF_PARALLEL) { 1606ad75a51eSRichard Henderson gen_helper_exit_atomic(tcg_env); 16073db010c3SRichard Henderson } else { 1608c03a0fd1SRichard Henderson TCGv_i32 r_asi = tcg_constant_i32(da->asi); 160900ab7e61SRichard Henderson TCGv_i32 r_mop = tcg_constant_i32(MO_UB); 16103db010c3SRichard Henderson TCGv_i64 s64, t64; 16113db010c3SRichard Henderson 16123db010c3SRichard Henderson save_state(dc); 16133db010c3SRichard Henderson t64 = tcg_temp_new_i64(); 1614ad75a51eSRichard Henderson gen_helper_ld_asi(t64, tcg_env, addr, r_asi, r_mop); 16153db010c3SRichard Henderson 161600ab7e61SRichard Henderson s64 = tcg_constant_i64(0xff); 1617ad75a51eSRichard Henderson gen_helper_st_asi(tcg_env, addr, s64, r_asi, r_mop); 16183db010c3SRichard Henderson 16193db010c3SRichard Henderson tcg_gen_trunc_i64_tl(dst, t64); 16203db010c3SRichard Henderson 16213db010c3SRichard Henderson /* End the TB. */ 16223db010c3SRichard Henderson dc->npc = DYNAMIC_PC; 16233db010c3SRichard Henderson } 1624fcf5ef2aSThomas Huth break; 1625fcf5ef2aSThomas Huth } 1626fcf5ef2aSThomas Huth } 1627fcf5ef2aSThomas Huth 1628287b1152SRichard Henderson static void gen_ldf_asi(DisasContext *dc, DisasASI *da, MemOp orig_size, 16293259b9e2SRichard Henderson TCGv addr, int rd) 1630fcf5ef2aSThomas Huth { 16313259b9e2SRichard Henderson MemOp memop = da->memop; 16323259b9e2SRichard Henderson MemOp size = memop & MO_SIZE; 1633fcf5ef2aSThomas Huth TCGv_i32 d32; 16341210a036SRichard Henderson TCGv_i64 d64, l64; 1635287b1152SRichard Henderson TCGv addr_tmp; 1636fcf5ef2aSThomas Huth 16373259b9e2SRichard Henderson /* TODO: Use 128-bit load/store below. */ 16383259b9e2SRichard Henderson if (size == MO_128) { 16393259b9e2SRichard Henderson memop = (memop & ~MO_SIZE) | MO_64; 16403259b9e2SRichard Henderson } 16413259b9e2SRichard Henderson 16423259b9e2SRichard Henderson switch (da->type) { 1643fcf5ef2aSThomas Huth case GET_ASI_EXCP: 1644fcf5ef2aSThomas Huth break; 1645fcf5ef2aSThomas Huth 1646fcf5ef2aSThomas Huth case GET_ASI_DIRECT: 16473259b9e2SRichard Henderson memop |= MO_ALIGN_4; 1648fcf5ef2aSThomas Huth switch (size) { 16493259b9e2SRichard Henderson case MO_32: 1650388a6465SRichard Henderson d32 = tcg_temp_new_i32(); 16513259b9e2SRichard Henderson tcg_gen_qemu_ld_i32(d32, addr, da->mem_idx, memop); 1652fcf5ef2aSThomas Huth gen_store_fpr_F(dc, rd, d32); 1653fcf5ef2aSThomas Huth break; 16543259b9e2SRichard Henderson 16553259b9e2SRichard Henderson case MO_64: 16561210a036SRichard Henderson d64 = tcg_temp_new_i64(); 16571210a036SRichard Henderson tcg_gen_qemu_ld_i64(d64, addr, da->mem_idx, memop); 16581210a036SRichard Henderson gen_store_fpr_D(dc, rd, d64); 1659fcf5ef2aSThomas Huth break; 16603259b9e2SRichard Henderson 16613259b9e2SRichard Henderson case MO_128: 1662fcf5ef2aSThomas Huth d64 = tcg_temp_new_i64(); 16631210a036SRichard Henderson l64 = tcg_temp_new_i64(); 16643259b9e2SRichard Henderson tcg_gen_qemu_ld_i64(d64, addr, da->mem_idx, memop); 1665287b1152SRichard Henderson addr_tmp = tcg_temp_new(); 1666287b1152SRichard Henderson tcg_gen_addi_tl(addr_tmp, addr, 8); 16671210a036SRichard Henderson tcg_gen_qemu_ld_i64(l64, addr_tmp, da->mem_idx, memop); 16681210a036SRichard Henderson gen_store_fpr_D(dc, rd, d64); 16691210a036SRichard Henderson gen_store_fpr_D(dc, rd + 2, l64); 1670fcf5ef2aSThomas Huth break; 1671fcf5ef2aSThomas Huth default: 1672fcf5ef2aSThomas Huth g_assert_not_reached(); 1673fcf5ef2aSThomas Huth } 1674fcf5ef2aSThomas Huth break; 1675fcf5ef2aSThomas Huth 1676fcf5ef2aSThomas Huth case GET_ASI_BLOCK: 1677fcf5ef2aSThomas Huth /* Valid for lddfa on aligned registers only. */ 16783259b9e2SRichard Henderson if (orig_size == MO_64 && (rd & 7) == 0) { 1679fcf5ef2aSThomas Huth /* The first operation checks required alignment. */ 1680287b1152SRichard Henderson addr_tmp = tcg_temp_new(); 16811210a036SRichard Henderson d64 = tcg_temp_new_i64(); 1682287b1152SRichard Henderson for (int i = 0; ; ++i) { 16831210a036SRichard Henderson tcg_gen_qemu_ld_i64(d64, addr, da->mem_idx, 16843259b9e2SRichard Henderson memop | (i == 0 ? MO_ALIGN_64 : 0)); 16851210a036SRichard Henderson gen_store_fpr_D(dc, rd + 2 * i, d64); 1686fcf5ef2aSThomas Huth if (i == 7) { 1687fcf5ef2aSThomas Huth break; 1688fcf5ef2aSThomas Huth } 1689287b1152SRichard Henderson tcg_gen_addi_tl(addr_tmp, addr, 8); 1690287b1152SRichard Henderson addr = addr_tmp; 1691fcf5ef2aSThomas Huth } 1692fcf5ef2aSThomas Huth } else { 1693fcf5ef2aSThomas Huth gen_exception(dc, TT_ILL_INSN); 1694fcf5ef2aSThomas Huth } 1695fcf5ef2aSThomas Huth break; 1696fcf5ef2aSThomas Huth 1697fcf5ef2aSThomas Huth case GET_ASI_SHORT: 1698fcf5ef2aSThomas Huth /* Valid for lddfa only. */ 16993259b9e2SRichard Henderson if (orig_size == MO_64) { 17001210a036SRichard Henderson d64 = tcg_temp_new_i64(); 17011210a036SRichard Henderson tcg_gen_qemu_ld_i64(d64, addr, da->mem_idx, memop | MO_ALIGN); 17021210a036SRichard Henderson gen_store_fpr_D(dc, rd, d64); 1703fcf5ef2aSThomas Huth } else { 1704fcf5ef2aSThomas Huth gen_exception(dc, TT_ILL_INSN); 1705fcf5ef2aSThomas Huth } 1706fcf5ef2aSThomas Huth break; 1707fcf5ef2aSThomas Huth 1708fcf5ef2aSThomas Huth default: 1709fcf5ef2aSThomas Huth { 17103259b9e2SRichard Henderson TCGv_i32 r_asi = tcg_constant_i32(da->asi); 17113259b9e2SRichard Henderson TCGv_i32 r_mop = tcg_constant_i32(memop | MO_ALIGN); 1712fcf5ef2aSThomas Huth 1713fcf5ef2aSThomas Huth save_state(dc); 1714fcf5ef2aSThomas Huth /* According to the table in the UA2011 manual, the only 1715fcf5ef2aSThomas Huth other asis that are valid for ldfa/lddfa/ldqfa are 1716fcf5ef2aSThomas Huth the NO_FAULT asis. We still need a helper for these, 1717fcf5ef2aSThomas Huth but we can just use the integer asi helper for them. */ 1718fcf5ef2aSThomas Huth switch (size) { 17193259b9e2SRichard Henderson case MO_32: 1720fcf5ef2aSThomas Huth d64 = tcg_temp_new_i64(); 1721ad75a51eSRichard Henderson gen_helper_ld_asi(d64, tcg_env, addr, r_asi, r_mop); 1722388a6465SRichard Henderson d32 = tcg_temp_new_i32(); 1723fcf5ef2aSThomas Huth tcg_gen_extrl_i64_i32(d32, d64); 1724fcf5ef2aSThomas Huth gen_store_fpr_F(dc, rd, d32); 1725fcf5ef2aSThomas Huth break; 17263259b9e2SRichard Henderson case MO_64: 17271210a036SRichard Henderson d64 = tcg_temp_new_i64(); 17281210a036SRichard Henderson gen_helper_ld_asi(d64, tcg_env, addr, r_asi, r_mop); 17291210a036SRichard Henderson gen_store_fpr_D(dc, rd, d64); 1730fcf5ef2aSThomas Huth break; 17313259b9e2SRichard Henderson case MO_128: 1732fcf5ef2aSThomas Huth d64 = tcg_temp_new_i64(); 17331210a036SRichard Henderson l64 = tcg_temp_new_i64(); 1734ad75a51eSRichard Henderson gen_helper_ld_asi(d64, tcg_env, addr, r_asi, r_mop); 1735287b1152SRichard Henderson addr_tmp = tcg_temp_new(); 1736287b1152SRichard Henderson tcg_gen_addi_tl(addr_tmp, addr, 8); 17371210a036SRichard Henderson gen_helper_ld_asi(l64, tcg_env, addr_tmp, r_asi, r_mop); 17381210a036SRichard Henderson gen_store_fpr_D(dc, rd, d64); 17391210a036SRichard Henderson gen_store_fpr_D(dc, rd + 2, l64); 1740fcf5ef2aSThomas Huth break; 1741fcf5ef2aSThomas Huth default: 1742fcf5ef2aSThomas Huth g_assert_not_reached(); 1743fcf5ef2aSThomas Huth } 1744fcf5ef2aSThomas Huth } 1745fcf5ef2aSThomas Huth break; 1746fcf5ef2aSThomas Huth } 1747fcf5ef2aSThomas Huth } 1748fcf5ef2aSThomas Huth 1749287b1152SRichard Henderson static void gen_stf_asi(DisasContext *dc, DisasASI *da, MemOp orig_size, 17503259b9e2SRichard Henderson TCGv addr, int rd) 17513259b9e2SRichard Henderson { 17523259b9e2SRichard Henderson MemOp memop = da->memop; 17533259b9e2SRichard Henderson MemOp size = memop & MO_SIZE; 1754fcf5ef2aSThomas Huth TCGv_i32 d32; 17551210a036SRichard Henderson TCGv_i64 d64; 1756287b1152SRichard Henderson TCGv addr_tmp; 1757fcf5ef2aSThomas Huth 17583259b9e2SRichard Henderson /* TODO: Use 128-bit load/store below. */ 17593259b9e2SRichard Henderson if (size == MO_128) { 17603259b9e2SRichard Henderson memop = (memop & ~MO_SIZE) | MO_64; 17613259b9e2SRichard Henderson } 17623259b9e2SRichard Henderson 17633259b9e2SRichard Henderson switch (da->type) { 1764fcf5ef2aSThomas Huth case GET_ASI_EXCP: 1765fcf5ef2aSThomas Huth break; 1766fcf5ef2aSThomas Huth 1767fcf5ef2aSThomas Huth case GET_ASI_DIRECT: 17683259b9e2SRichard Henderson memop |= MO_ALIGN_4; 1769fcf5ef2aSThomas Huth switch (size) { 17703259b9e2SRichard Henderson case MO_32: 1771fcf5ef2aSThomas Huth d32 = gen_load_fpr_F(dc, rd); 17723259b9e2SRichard Henderson tcg_gen_qemu_st_i32(d32, addr, da->mem_idx, memop | MO_ALIGN); 1773fcf5ef2aSThomas Huth break; 17743259b9e2SRichard Henderson case MO_64: 17751210a036SRichard Henderson d64 = gen_load_fpr_D(dc, rd); 17761210a036SRichard Henderson tcg_gen_qemu_st_i64(d64, addr, da->mem_idx, memop | MO_ALIGN_4); 1777fcf5ef2aSThomas Huth break; 17783259b9e2SRichard Henderson case MO_128: 1779fcf5ef2aSThomas Huth /* Only 4-byte alignment required. However, it is legal for the 1780fcf5ef2aSThomas Huth cpu to signal the alignment fault, and the OS trap handler is 1781fcf5ef2aSThomas Huth required to fix it up. Requiring 16-byte alignment here avoids 1782fcf5ef2aSThomas Huth having to probe the second page before performing the first 1783fcf5ef2aSThomas Huth write. */ 17841210a036SRichard Henderson d64 = gen_load_fpr_D(dc, rd); 17851210a036SRichard Henderson tcg_gen_qemu_st_i64(d64, addr, da->mem_idx, memop | MO_ALIGN_16); 1786287b1152SRichard Henderson addr_tmp = tcg_temp_new(); 1787287b1152SRichard Henderson tcg_gen_addi_tl(addr_tmp, addr, 8); 17881210a036SRichard Henderson d64 = gen_load_fpr_D(dc, rd + 2); 17891210a036SRichard Henderson tcg_gen_qemu_st_i64(d64, addr_tmp, da->mem_idx, memop); 1790fcf5ef2aSThomas Huth break; 1791fcf5ef2aSThomas Huth default: 1792fcf5ef2aSThomas Huth g_assert_not_reached(); 1793fcf5ef2aSThomas Huth } 1794fcf5ef2aSThomas Huth break; 1795fcf5ef2aSThomas Huth 1796fcf5ef2aSThomas Huth case GET_ASI_BLOCK: 1797fcf5ef2aSThomas Huth /* Valid for stdfa on aligned registers only. */ 17983259b9e2SRichard Henderson if (orig_size == MO_64 && (rd & 7) == 0) { 1799fcf5ef2aSThomas Huth /* The first operation checks required alignment. */ 1800287b1152SRichard Henderson addr_tmp = tcg_temp_new(); 1801287b1152SRichard Henderson for (int i = 0; ; ++i) { 18021210a036SRichard Henderson d64 = gen_load_fpr_D(dc, rd + 2 * i); 18031210a036SRichard Henderson tcg_gen_qemu_st_i64(d64, addr, da->mem_idx, 18043259b9e2SRichard Henderson memop | (i == 0 ? MO_ALIGN_64 : 0)); 1805fcf5ef2aSThomas Huth if (i == 7) { 1806fcf5ef2aSThomas Huth break; 1807fcf5ef2aSThomas Huth } 1808287b1152SRichard Henderson tcg_gen_addi_tl(addr_tmp, addr, 8); 1809287b1152SRichard Henderson addr = addr_tmp; 1810fcf5ef2aSThomas Huth } 1811fcf5ef2aSThomas Huth } else { 1812fcf5ef2aSThomas Huth gen_exception(dc, TT_ILL_INSN); 1813fcf5ef2aSThomas Huth } 1814fcf5ef2aSThomas Huth break; 1815fcf5ef2aSThomas Huth 1816fcf5ef2aSThomas Huth case GET_ASI_SHORT: 1817fcf5ef2aSThomas Huth /* Valid for stdfa only. */ 18183259b9e2SRichard Henderson if (orig_size == MO_64) { 18191210a036SRichard Henderson d64 = gen_load_fpr_D(dc, rd); 18201210a036SRichard Henderson tcg_gen_qemu_st_i64(d64, addr, da->mem_idx, memop | MO_ALIGN); 1821fcf5ef2aSThomas Huth } else { 1822fcf5ef2aSThomas Huth gen_exception(dc, TT_ILL_INSN); 1823fcf5ef2aSThomas Huth } 1824fcf5ef2aSThomas Huth break; 1825fcf5ef2aSThomas Huth 1826fcf5ef2aSThomas Huth default: 1827fcf5ef2aSThomas Huth /* According to the table in the UA2011 manual, the only 1828fcf5ef2aSThomas Huth other asis that are valid for ldfa/lddfa/ldqfa are 1829fcf5ef2aSThomas Huth the PST* asis, which aren't currently handled. */ 1830fcf5ef2aSThomas Huth gen_exception(dc, TT_ILL_INSN); 1831fcf5ef2aSThomas Huth break; 1832fcf5ef2aSThomas Huth } 1833fcf5ef2aSThomas Huth } 1834fcf5ef2aSThomas Huth 183542071fc1SRichard Henderson static void gen_ldda_asi(DisasContext *dc, DisasASI *da, TCGv addr, int rd) 1836fcf5ef2aSThomas Huth { 1837a76779eeSRichard Henderson TCGv hi = gen_dest_gpr(dc, rd); 1838a76779eeSRichard Henderson TCGv lo = gen_dest_gpr(dc, rd + 1); 1839fcf5ef2aSThomas Huth 1840c03a0fd1SRichard Henderson switch (da->type) { 1841fcf5ef2aSThomas Huth case GET_ASI_EXCP: 1842fcf5ef2aSThomas Huth return; 1843fcf5ef2aSThomas Huth 1844fcf5ef2aSThomas Huth case GET_ASI_DTWINX: 1845ebbbec92SRichard Henderson #ifdef TARGET_SPARC64 1846ebbbec92SRichard Henderson { 1847ebbbec92SRichard Henderson MemOp mop = (da->memop & MO_BSWAP) | MO_128 | MO_ALIGN_16; 1848ebbbec92SRichard Henderson TCGv_i128 t = tcg_temp_new_i128(); 1849ebbbec92SRichard Henderson 1850ebbbec92SRichard Henderson tcg_gen_qemu_ld_i128(t, addr, da->mem_idx, mop); 1851ebbbec92SRichard Henderson /* 1852ebbbec92SRichard Henderson * Note that LE twinx acts as if each 64-bit register result is 1853ebbbec92SRichard Henderson * byte swapped. We perform one 128-bit LE load, so must swap 1854ebbbec92SRichard Henderson * the order of the writebacks. 1855ebbbec92SRichard Henderson */ 1856ebbbec92SRichard Henderson if ((mop & MO_BSWAP) == MO_TE) { 1857ebbbec92SRichard Henderson tcg_gen_extr_i128_i64(lo, hi, t); 1858ebbbec92SRichard Henderson } else { 1859ebbbec92SRichard Henderson tcg_gen_extr_i128_i64(hi, lo, t); 1860ebbbec92SRichard Henderson } 1861ebbbec92SRichard Henderson } 1862fcf5ef2aSThomas Huth break; 1863ebbbec92SRichard Henderson #else 1864ebbbec92SRichard Henderson g_assert_not_reached(); 1865ebbbec92SRichard Henderson #endif 1866fcf5ef2aSThomas Huth 1867fcf5ef2aSThomas Huth case GET_ASI_DIRECT: 1868fcf5ef2aSThomas Huth { 1869fcf5ef2aSThomas Huth TCGv_i64 tmp = tcg_temp_new_i64(); 1870fcf5ef2aSThomas Huth 1871c03a0fd1SRichard Henderson tcg_gen_qemu_ld_i64(tmp, addr, da->mem_idx, da->memop | MO_ALIGN); 1872fcf5ef2aSThomas Huth 1873fcf5ef2aSThomas Huth /* Note that LE ldda acts as if each 32-bit register 1874fcf5ef2aSThomas Huth result is byte swapped. Having just performed one 1875fcf5ef2aSThomas Huth 64-bit bswap, we need now to swap the writebacks. */ 1876c03a0fd1SRichard Henderson if ((da->memop & MO_BSWAP) == MO_TE) { 1877a76779eeSRichard Henderson tcg_gen_extr_i64_tl(lo, hi, tmp); 1878fcf5ef2aSThomas Huth } else { 1879a76779eeSRichard Henderson tcg_gen_extr_i64_tl(hi, lo, tmp); 1880fcf5ef2aSThomas Huth } 1881fcf5ef2aSThomas Huth } 1882fcf5ef2aSThomas Huth break; 1883fcf5ef2aSThomas Huth 18842786a3f8SRichard Henderson case GET_ASI_CODE: 18852786a3f8SRichard Henderson #if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64) 18862786a3f8SRichard Henderson { 18872786a3f8SRichard Henderson MemOpIdx oi = make_memop_idx(da->memop, da->mem_idx); 18882786a3f8SRichard Henderson TCGv_i64 tmp = tcg_temp_new_i64(); 18892786a3f8SRichard Henderson 18902786a3f8SRichard Henderson gen_helper_ld_code(tmp, tcg_env, addr, tcg_constant_i32(oi)); 18912786a3f8SRichard Henderson 18922786a3f8SRichard Henderson /* See above. */ 18932786a3f8SRichard Henderson if ((da->memop & MO_BSWAP) == MO_TE) { 18942786a3f8SRichard Henderson tcg_gen_extr_i64_tl(lo, hi, tmp); 18952786a3f8SRichard Henderson } else { 18962786a3f8SRichard Henderson tcg_gen_extr_i64_tl(hi, lo, tmp); 18972786a3f8SRichard Henderson } 18982786a3f8SRichard Henderson } 18992786a3f8SRichard Henderson break; 19002786a3f8SRichard Henderson #else 19012786a3f8SRichard Henderson g_assert_not_reached(); 19022786a3f8SRichard Henderson #endif 19032786a3f8SRichard Henderson 1904fcf5ef2aSThomas Huth default: 1905fcf5ef2aSThomas Huth /* ??? In theory we've handled all of the ASIs that are valid 1906fcf5ef2aSThomas Huth for ldda, and this should raise DAE_invalid_asi. However, 1907fcf5ef2aSThomas Huth real hardware allows others. This can be seen with e.g. 1908fcf5ef2aSThomas Huth FreeBSD 10.3 wrt ASI_IC_TAG. */ 1909fcf5ef2aSThomas Huth { 1910c03a0fd1SRichard Henderson TCGv_i32 r_asi = tcg_constant_i32(da->asi); 1911c03a0fd1SRichard Henderson TCGv_i32 r_mop = tcg_constant_i32(da->memop); 1912fcf5ef2aSThomas Huth TCGv_i64 tmp = tcg_temp_new_i64(); 1913fcf5ef2aSThomas Huth 1914fcf5ef2aSThomas Huth save_state(dc); 1915ad75a51eSRichard Henderson gen_helper_ld_asi(tmp, tcg_env, addr, r_asi, r_mop); 1916fcf5ef2aSThomas Huth 1917fcf5ef2aSThomas Huth /* See above. */ 1918c03a0fd1SRichard Henderson if ((da->memop & MO_BSWAP) == MO_TE) { 1919a76779eeSRichard Henderson tcg_gen_extr_i64_tl(lo, hi, tmp); 1920fcf5ef2aSThomas Huth } else { 1921a76779eeSRichard Henderson tcg_gen_extr_i64_tl(hi, lo, tmp); 1922fcf5ef2aSThomas Huth } 1923fcf5ef2aSThomas Huth } 1924fcf5ef2aSThomas Huth break; 1925fcf5ef2aSThomas Huth } 1926fcf5ef2aSThomas Huth 1927fcf5ef2aSThomas Huth gen_store_gpr(dc, rd, hi); 1928fcf5ef2aSThomas Huth gen_store_gpr(dc, rd + 1, lo); 1929fcf5ef2aSThomas Huth } 1930fcf5ef2aSThomas Huth 193142071fc1SRichard Henderson static void gen_stda_asi(DisasContext *dc, DisasASI *da, TCGv addr, int rd) 1932c03a0fd1SRichard Henderson { 1933c03a0fd1SRichard Henderson TCGv hi = gen_load_gpr(dc, rd); 1934fcf5ef2aSThomas Huth TCGv lo = gen_load_gpr(dc, rd + 1); 1935fcf5ef2aSThomas Huth 1936c03a0fd1SRichard Henderson switch (da->type) { 1937fcf5ef2aSThomas Huth case GET_ASI_EXCP: 1938fcf5ef2aSThomas Huth break; 1939fcf5ef2aSThomas Huth 1940fcf5ef2aSThomas Huth case GET_ASI_DTWINX: 1941ebbbec92SRichard Henderson #ifdef TARGET_SPARC64 1942ebbbec92SRichard Henderson { 1943ebbbec92SRichard Henderson MemOp mop = (da->memop & MO_BSWAP) | MO_128 | MO_ALIGN_16; 1944ebbbec92SRichard Henderson TCGv_i128 t = tcg_temp_new_i128(); 1945ebbbec92SRichard Henderson 1946ebbbec92SRichard Henderson /* 1947ebbbec92SRichard Henderson * Note that LE twinx acts as if each 64-bit register result is 1948ebbbec92SRichard Henderson * byte swapped. We perform one 128-bit LE store, so must swap 1949ebbbec92SRichard Henderson * the order of the construction. 1950ebbbec92SRichard Henderson */ 1951ebbbec92SRichard Henderson if ((mop & MO_BSWAP) == MO_TE) { 1952ebbbec92SRichard Henderson tcg_gen_concat_i64_i128(t, lo, hi); 1953ebbbec92SRichard Henderson } else { 1954ebbbec92SRichard Henderson tcg_gen_concat_i64_i128(t, hi, lo); 1955ebbbec92SRichard Henderson } 1956ebbbec92SRichard Henderson tcg_gen_qemu_st_i128(t, addr, da->mem_idx, mop); 1957ebbbec92SRichard Henderson } 1958fcf5ef2aSThomas Huth break; 1959ebbbec92SRichard Henderson #else 1960ebbbec92SRichard Henderson g_assert_not_reached(); 1961ebbbec92SRichard Henderson #endif 1962fcf5ef2aSThomas Huth 1963fcf5ef2aSThomas Huth case GET_ASI_DIRECT: 1964fcf5ef2aSThomas Huth { 1965fcf5ef2aSThomas Huth TCGv_i64 t64 = tcg_temp_new_i64(); 1966fcf5ef2aSThomas Huth 1967fcf5ef2aSThomas Huth /* Note that LE stda acts as if each 32-bit register result is 1968fcf5ef2aSThomas Huth byte swapped. We will perform one 64-bit LE store, so now 1969fcf5ef2aSThomas Huth we must swap the order of the construction. */ 1970c03a0fd1SRichard Henderson if ((da->memop & MO_BSWAP) == MO_TE) { 1971a76779eeSRichard Henderson tcg_gen_concat_tl_i64(t64, lo, hi); 1972fcf5ef2aSThomas Huth } else { 1973a76779eeSRichard Henderson tcg_gen_concat_tl_i64(t64, hi, lo); 1974fcf5ef2aSThomas Huth } 1975c03a0fd1SRichard Henderson tcg_gen_qemu_st_i64(t64, addr, da->mem_idx, da->memop | MO_ALIGN); 1976fcf5ef2aSThomas Huth } 1977fcf5ef2aSThomas Huth break; 1978fcf5ef2aSThomas Huth 1979a76779eeSRichard Henderson case GET_ASI_BFILL: 1980a76779eeSRichard Henderson assert(TARGET_LONG_BITS == 32); 198154c3e953SRichard Henderson /* 198254c3e953SRichard Henderson * Store 32 bytes of [rd:rd+1] to ADDR. 198354c3e953SRichard Henderson * See comments for GET_ASI_COPY above. 198454c3e953SRichard Henderson */ 1985a76779eeSRichard Henderson { 198654c3e953SRichard Henderson MemOp mop = MO_TE | MO_128 | MO_ATOM_IFALIGN_PAIR; 198754c3e953SRichard Henderson TCGv_i64 t8 = tcg_temp_new_i64(); 198854c3e953SRichard Henderson TCGv_i128 t16 = tcg_temp_new_i128(); 198954c3e953SRichard Henderson TCGv daddr = tcg_temp_new(); 1990a76779eeSRichard Henderson 199154c3e953SRichard Henderson tcg_gen_concat_tl_i64(t8, lo, hi); 199254c3e953SRichard Henderson tcg_gen_concat_i64_i128(t16, t8, t8); 199354c3e953SRichard Henderson tcg_gen_andi_tl(daddr, addr, -32); 199454c3e953SRichard Henderson tcg_gen_qemu_st_i128(t16, daddr, da->mem_idx, mop); 199554c3e953SRichard Henderson tcg_gen_addi_tl(daddr, daddr, 16); 199654c3e953SRichard Henderson tcg_gen_qemu_st_i128(t16, daddr, da->mem_idx, mop); 1997a76779eeSRichard Henderson } 1998a76779eeSRichard Henderson break; 1999a76779eeSRichard Henderson 2000fcf5ef2aSThomas Huth default: 2001fcf5ef2aSThomas Huth /* ??? In theory we've handled all of the ASIs that are valid 2002fcf5ef2aSThomas Huth for stda, and this should raise DAE_invalid_asi. */ 2003fcf5ef2aSThomas Huth { 2004c03a0fd1SRichard Henderson TCGv_i32 r_asi = tcg_constant_i32(da->asi); 2005c03a0fd1SRichard Henderson TCGv_i32 r_mop = tcg_constant_i32(da->memop); 2006fcf5ef2aSThomas Huth TCGv_i64 t64 = tcg_temp_new_i64(); 2007fcf5ef2aSThomas Huth 2008fcf5ef2aSThomas Huth /* See above. */ 2009c03a0fd1SRichard Henderson if ((da->memop & MO_BSWAP) == MO_TE) { 2010a76779eeSRichard Henderson tcg_gen_concat_tl_i64(t64, lo, hi); 2011fcf5ef2aSThomas Huth } else { 2012a76779eeSRichard Henderson tcg_gen_concat_tl_i64(t64, hi, lo); 2013fcf5ef2aSThomas Huth } 2014fcf5ef2aSThomas Huth 2015fcf5ef2aSThomas Huth save_state(dc); 2016ad75a51eSRichard Henderson gen_helper_st_asi(tcg_env, addr, t64, r_asi, r_mop); 2017fcf5ef2aSThomas Huth } 2018fcf5ef2aSThomas Huth break; 2019fcf5ef2aSThomas Huth } 2020fcf5ef2aSThomas Huth } 2021fcf5ef2aSThomas Huth 2022fcf5ef2aSThomas Huth static void gen_fmovs(DisasContext *dc, DisasCompare *cmp, int rd, int rs) 2023fcf5ef2aSThomas Huth { 2024f7ec8155SRichard Henderson #ifdef TARGET_SPARC64 2025fcf5ef2aSThomas Huth TCGv_i32 c32, zero, dst, s1, s2; 2026dd7dbfccSRichard Henderson TCGv_i64 c64 = tcg_temp_new_i64(); 2027fcf5ef2aSThomas Huth 2028fcf5ef2aSThomas Huth /* We have two choices here: extend the 32 bit data and use movcond_i64, 2029fcf5ef2aSThomas Huth or fold the comparison down to 32 bits and use movcond_i32. Choose 2030fcf5ef2aSThomas Huth the later. */ 2031fcf5ef2aSThomas Huth c32 = tcg_temp_new_i32(); 2032c8507ebfSRichard Henderson tcg_gen_setcondi_i64(cmp->cond, c64, cmp->c1, cmp->c2); 2033fcf5ef2aSThomas Huth tcg_gen_extrl_i64_i32(c32, c64); 2034fcf5ef2aSThomas Huth 2035fcf5ef2aSThomas Huth s1 = gen_load_fpr_F(dc, rs); 2036fcf5ef2aSThomas Huth s2 = gen_load_fpr_F(dc, rd); 2037388a6465SRichard Henderson dst = tcg_temp_new_i32(); 203800ab7e61SRichard Henderson zero = tcg_constant_i32(0); 2039fcf5ef2aSThomas Huth 2040fcf5ef2aSThomas Huth tcg_gen_movcond_i32(TCG_COND_NE, dst, c32, zero, s1, s2); 2041fcf5ef2aSThomas Huth 2042fcf5ef2aSThomas Huth gen_store_fpr_F(dc, rd, dst); 2043f7ec8155SRichard Henderson #else 2044f7ec8155SRichard Henderson qemu_build_not_reached(); 2045f7ec8155SRichard Henderson #endif 2046fcf5ef2aSThomas Huth } 2047fcf5ef2aSThomas Huth 2048fcf5ef2aSThomas Huth static void gen_fmovd(DisasContext *dc, DisasCompare *cmp, int rd, int rs) 2049fcf5ef2aSThomas Huth { 2050f7ec8155SRichard Henderson #ifdef TARGET_SPARC64 205152f46d46SRichard Henderson TCGv_i64 dst = tcg_temp_new_i64(); 2052c8507ebfSRichard Henderson tcg_gen_movcond_i64(cmp->cond, dst, cmp->c1, tcg_constant_tl(cmp->c2), 2053fcf5ef2aSThomas Huth gen_load_fpr_D(dc, rs), 2054fcf5ef2aSThomas Huth gen_load_fpr_D(dc, rd)); 2055fcf5ef2aSThomas Huth gen_store_fpr_D(dc, rd, dst); 2056f7ec8155SRichard Henderson #else 2057f7ec8155SRichard Henderson qemu_build_not_reached(); 2058f7ec8155SRichard Henderson #endif 2059fcf5ef2aSThomas Huth } 2060fcf5ef2aSThomas Huth 2061fcf5ef2aSThomas Huth static void gen_fmovq(DisasContext *dc, DisasCompare *cmp, int rd, int rs) 2062fcf5ef2aSThomas Huth { 2063f7ec8155SRichard Henderson #ifdef TARGET_SPARC64 2064c8507ebfSRichard Henderson TCGv c2 = tcg_constant_tl(cmp->c2); 20651210a036SRichard Henderson TCGv_i64 h = tcg_temp_new_i64(); 20661210a036SRichard Henderson TCGv_i64 l = tcg_temp_new_i64(); 2067fcf5ef2aSThomas Huth 20681210a036SRichard Henderson tcg_gen_movcond_i64(cmp->cond, h, cmp->c1, c2, 20691210a036SRichard Henderson gen_load_fpr_D(dc, rs), 20701210a036SRichard Henderson gen_load_fpr_D(dc, rd)); 20711210a036SRichard Henderson tcg_gen_movcond_i64(cmp->cond, l, cmp->c1, c2, 20721210a036SRichard Henderson gen_load_fpr_D(dc, rs + 2), 20731210a036SRichard Henderson gen_load_fpr_D(dc, rd + 2)); 20741210a036SRichard Henderson gen_store_fpr_D(dc, rd, h); 20751210a036SRichard Henderson gen_store_fpr_D(dc, rd + 2, l); 2076f7ec8155SRichard Henderson #else 2077f7ec8155SRichard Henderson qemu_build_not_reached(); 2078f7ec8155SRichard Henderson #endif 2079fcf5ef2aSThomas Huth } 2080fcf5ef2aSThomas Huth 2081f7ec8155SRichard Henderson #ifdef TARGET_SPARC64 20825d617bfbSRichard Henderson static void gen_load_trap_state_at_tl(TCGv_ptr r_tsptr) 2083fcf5ef2aSThomas Huth { 2084fcf5ef2aSThomas Huth TCGv_i32 r_tl = tcg_temp_new_i32(); 2085fcf5ef2aSThomas Huth 2086fcf5ef2aSThomas Huth /* load env->tl into r_tl */ 2087ad75a51eSRichard Henderson tcg_gen_ld_i32(r_tl, tcg_env, offsetof(CPUSPARCState, tl)); 2088fcf5ef2aSThomas Huth 2089fcf5ef2aSThomas Huth /* tl = [0 ... MAXTL_MASK] where MAXTL_MASK must be power of 2 */ 2090fcf5ef2aSThomas Huth tcg_gen_andi_i32(r_tl, r_tl, MAXTL_MASK); 2091fcf5ef2aSThomas Huth 2092fcf5ef2aSThomas Huth /* calculate offset to current trap state from env->ts, reuse r_tl */ 2093fcf5ef2aSThomas Huth tcg_gen_muli_i32(r_tl, r_tl, sizeof (trap_state)); 2094ad75a51eSRichard Henderson tcg_gen_addi_ptr(r_tsptr, tcg_env, offsetof(CPUSPARCState, ts)); 2095fcf5ef2aSThomas Huth 2096fcf5ef2aSThomas Huth /* tsptr = env->ts[env->tl & MAXTL_MASK] */ 2097fcf5ef2aSThomas Huth { 2098fcf5ef2aSThomas Huth TCGv_ptr r_tl_tmp = tcg_temp_new_ptr(); 2099fcf5ef2aSThomas Huth tcg_gen_ext_i32_ptr(r_tl_tmp, r_tl); 2100fcf5ef2aSThomas Huth tcg_gen_add_ptr(r_tsptr, r_tsptr, r_tl_tmp); 2101fcf5ef2aSThomas Huth } 2102fcf5ef2aSThomas Huth } 2103fcf5ef2aSThomas Huth #endif 2104fcf5ef2aSThomas Huth 210506c060d9SRichard Henderson static int extract_dfpreg(DisasContext *dc, int x) 210606c060d9SRichard Henderson { 21070bba7572SRichard Henderson int r = x & 0x1e; 21080bba7572SRichard Henderson #ifdef TARGET_SPARC64 21090bba7572SRichard Henderson r |= (x & 1) << 5; 21100bba7572SRichard Henderson #endif 21110bba7572SRichard Henderson return r; 211206c060d9SRichard Henderson } 211306c060d9SRichard Henderson 211406c060d9SRichard Henderson static int extract_qfpreg(DisasContext *dc, int x) 211506c060d9SRichard Henderson { 21160bba7572SRichard Henderson int r = x & 0x1c; 21170bba7572SRichard Henderson #ifdef TARGET_SPARC64 21180bba7572SRichard Henderson r |= (x & 1) << 5; 21190bba7572SRichard Henderson #endif 21200bba7572SRichard Henderson return r; 212106c060d9SRichard Henderson } 212206c060d9SRichard Henderson 2123878cc677SRichard Henderson /* Include the auto-generated decoder. */ 2124878cc677SRichard Henderson #include "decode-insns.c.inc" 2125878cc677SRichard Henderson 2126878cc677SRichard Henderson #define TRANS(NAME, AVAIL, FUNC, ...) \ 2127878cc677SRichard Henderson static bool trans_##NAME(DisasContext *dc, arg_##NAME *a) \ 2128878cc677SRichard Henderson { return avail_##AVAIL(dc) && FUNC(dc, __VA_ARGS__); } 2129878cc677SRichard Henderson 2130878cc677SRichard Henderson #define avail_ALL(C) true 2131878cc677SRichard Henderson #ifdef TARGET_SPARC64 2132878cc677SRichard Henderson # define avail_32(C) false 2133af25071cSRichard Henderson # define avail_ASR17(C) false 2134d0a11d25SRichard Henderson # define avail_CASA(C) true 2135c2636853SRichard Henderson # define avail_DIV(C) true 2136b5372650SRichard Henderson # define avail_MUL(C) true 21370faef01bSRichard Henderson # define avail_POWERDOWN(C) false 2138878cc677SRichard Henderson # define avail_64(C) true 21395d617bfbSRichard Henderson # define avail_GL(C) ((C)->def->features & CPU_FEATURE_GL) 2140af25071cSRichard Henderson # define avail_HYPV(C) ((C)->def->features & CPU_FEATURE_HYPV) 2141b88ce6f2SRichard Henderson # define avail_VIS1(C) ((C)->def->features & CPU_FEATURE_VIS1) 2142b88ce6f2SRichard Henderson # define avail_VIS2(C) ((C)->def->features & CPU_FEATURE_VIS2) 2143878cc677SRichard Henderson #else 2144878cc677SRichard Henderson # define avail_32(C) true 2145af25071cSRichard Henderson # define avail_ASR17(C) ((C)->def->features & CPU_FEATURE_ASR17) 2146d0a11d25SRichard Henderson # define avail_CASA(C) ((C)->def->features & CPU_FEATURE_CASA) 2147c2636853SRichard Henderson # define avail_DIV(C) ((C)->def->features & CPU_FEATURE_DIV) 2148b5372650SRichard Henderson # define avail_MUL(C) ((C)->def->features & CPU_FEATURE_MUL) 21490faef01bSRichard Henderson # define avail_POWERDOWN(C) ((C)->def->features & CPU_FEATURE_POWERDOWN) 2150878cc677SRichard Henderson # define avail_64(C) false 21515d617bfbSRichard Henderson # define avail_GL(C) false 2152af25071cSRichard Henderson # define avail_HYPV(C) false 2153b88ce6f2SRichard Henderson # define avail_VIS1(C) false 2154b88ce6f2SRichard Henderson # define avail_VIS2(C) false 2155878cc677SRichard Henderson #endif 2156878cc677SRichard Henderson 2157878cc677SRichard Henderson /* Default case for non jump instructions. */ 2158878cc677SRichard Henderson static bool advance_pc(DisasContext *dc) 2159878cc677SRichard Henderson { 21604a8d145dSRichard Henderson TCGLabel *l1; 21614a8d145dSRichard Henderson 216289527e3aSRichard Henderson finishing_insn(dc); 216389527e3aSRichard Henderson 2164878cc677SRichard Henderson if (dc->npc & 3) { 2165878cc677SRichard Henderson switch (dc->npc) { 2166878cc677SRichard Henderson case DYNAMIC_PC: 2167878cc677SRichard Henderson case DYNAMIC_PC_LOOKUP: 2168878cc677SRichard Henderson dc->pc = dc->npc; 2169444d8b30SRichard Henderson tcg_gen_mov_tl(cpu_pc, cpu_npc); 2170444d8b30SRichard Henderson tcg_gen_addi_tl(cpu_npc, cpu_npc, 4); 2171878cc677SRichard Henderson break; 21724a8d145dSRichard Henderson 2173878cc677SRichard Henderson case JUMP_PC: 2174878cc677SRichard Henderson /* we can do a static jump */ 21754a8d145dSRichard Henderson l1 = gen_new_label(); 2176533f042fSRichard Henderson tcg_gen_brcondi_tl(dc->jump.cond, dc->jump.c1, dc->jump.c2, l1); 21774a8d145dSRichard Henderson 21784a8d145dSRichard Henderson /* jump not taken */ 21794a8d145dSRichard Henderson gen_goto_tb(dc, 1, dc->jump_pc[1], dc->jump_pc[1] + 4); 21804a8d145dSRichard Henderson 21814a8d145dSRichard Henderson /* jump taken */ 21824a8d145dSRichard Henderson gen_set_label(l1); 21834a8d145dSRichard Henderson gen_goto_tb(dc, 0, dc->jump_pc[0], dc->jump_pc[0] + 4); 21844a8d145dSRichard Henderson 2185878cc677SRichard Henderson dc->base.is_jmp = DISAS_NORETURN; 2186878cc677SRichard Henderson break; 21874a8d145dSRichard Henderson 2188878cc677SRichard Henderson default: 2189878cc677SRichard Henderson g_assert_not_reached(); 2190878cc677SRichard Henderson } 2191878cc677SRichard Henderson } else { 2192878cc677SRichard Henderson dc->pc = dc->npc; 2193878cc677SRichard Henderson dc->npc = dc->npc + 4; 2194878cc677SRichard Henderson } 2195878cc677SRichard Henderson return true; 2196878cc677SRichard Henderson } 2197878cc677SRichard Henderson 21986d2a0768SRichard Henderson /* 21996d2a0768SRichard Henderson * Major opcodes 00 and 01 -- branches, call, and sethi 22006d2a0768SRichard Henderson */ 22016d2a0768SRichard Henderson 22029d4e2bc7SRichard Henderson static bool advance_jump_cond(DisasContext *dc, DisasCompare *cmp, 22033951b7a8SRichard Henderson bool annul, int disp) 2204276567aaSRichard Henderson { 22053951b7a8SRichard Henderson target_ulong dest = address_mask_i(dc, dc->pc + disp * 4); 2206c76c8045SRichard Henderson target_ulong npc; 2207c76c8045SRichard Henderson 220889527e3aSRichard Henderson finishing_insn(dc); 220989527e3aSRichard Henderson 22102d9bb237SRichard Henderson if (cmp->cond == TCG_COND_ALWAYS) { 22112d9bb237SRichard Henderson if (annul) { 22122d9bb237SRichard Henderson dc->pc = dest; 22132d9bb237SRichard Henderson dc->npc = dest + 4; 22142d9bb237SRichard Henderson } else { 22152d9bb237SRichard Henderson gen_mov_pc_npc(dc); 22162d9bb237SRichard Henderson dc->npc = dest; 22172d9bb237SRichard Henderson } 22182d9bb237SRichard Henderson return true; 22192d9bb237SRichard Henderson } 22202d9bb237SRichard Henderson 22212d9bb237SRichard Henderson if (cmp->cond == TCG_COND_NEVER) { 22222d9bb237SRichard Henderson npc = dc->npc; 22232d9bb237SRichard Henderson if (npc & 3) { 22242d9bb237SRichard Henderson gen_mov_pc_npc(dc); 22252d9bb237SRichard Henderson if (annul) { 22262d9bb237SRichard Henderson tcg_gen_addi_tl(cpu_pc, cpu_pc, 4); 22272d9bb237SRichard Henderson } 22282d9bb237SRichard Henderson tcg_gen_addi_tl(cpu_npc, cpu_pc, 4); 22292d9bb237SRichard Henderson } else { 22302d9bb237SRichard Henderson dc->pc = npc + (annul ? 4 : 0); 22312d9bb237SRichard Henderson dc->npc = dc->pc + 4; 22322d9bb237SRichard Henderson } 22332d9bb237SRichard Henderson return true; 22342d9bb237SRichard Henderson } 22352d9bb237SRichard Henderson 2236c76c8045SRichard Henderson flush_cond(dc); 2237c76c8045SRichard Henderson npc = dc->npc; 22386b3e4cc6SRichard Henderson 2239276567aaSRichard Henderson if (annul) { 22406b3e4cc6SRichard Henderson TCGLabel *l1 = gen_new_label(); 22416b3e4cc6SRichard Henderson 2242c8507ebfSRichard Henderson tcg_gen_brcondi_tl(tcg_invert_cond(cmp->cond), cmp->c1, cmp->c2, l1); 22436b3e4cc6SRichard Henderson gen_goto_tb(dc, 0, npc, dest); 22446b3e4cc6SRichard Henderson gen_set_label(l1); 22456b3e4cc6SRichard Henderson gen_goto_tb(dc, 1, npc + 4, npc + 8); 22466b3e4cc6SRichard Henderson 22476b3e4cc6SRichard Henderson dc->base.is_jmp = DISAS_NORETURN; 2248276567aaSRichard Henderson } else { 22496b3e4cc6SRichard Henderson if (npc & 3) { 22506b3e4cc6SRichard Henderson switch (npc) { 22516b3e4cc6SRichard Henderson case DYNAMIC_PC: 22526b3e4cc6SRichard Henderson case DYNAMIC_PC_LOOKUP: 22536b3e4cc6SRichard Henderson tcg_gen_mov_tl(cpu_pc, cpu_npc); 22546b3e4cc6SRichard Henderson tcg_gen_addi_tl(cpu_npc, cpu_npc, 4); 22559d4e2bc7SRichard Henderson tcg_gen_movcond_tl(cmp->cond, cpu_npc, 2256c8507ebfSRichard Henderson cmp->c1, tcg_constant_tl(cmp->c2), 22576b3e4cc6SRichard Henderson tcg_constant_tl(dest), cpu_npc); 22586b3e4cc6SRichard Henderson dc->pc = npc; 22596b3e4cc6SRichard Henderson break; 22606b3e4cc6SRichard Henderson default: 22616b3e4cc6SRichard Henderson g_assert_not_reached(); 22626b3e4cc6SRichard Henderson } 22636b3e4cc6SRichard Henderson } else { 22646b3e4cc6SRichard Henderson dc->pc = npc; 2265533f042fSRichard Henderson dc->npc = JUMP_PC; 2266533f042fSRichard Henderson dc->jump = *cmp; 22676b3e4cc6SRichard Henderson dc->jump_pc[0] = dest; 22686b3e4cc6SRichard Henderson dc->jump_pc[1] = npc + 4; 2269dd7dbfccSRichard Henderson 2270dd7dbfccSRichard Henderson /* The condition for cpu_cond is always NE -- normalize. */ 2271dd7dbfccSRichard Henderson if (cmp->cond == TCG_COND_NE) { 2272c8507ebfSRichard Henderson tcg_gen_xori_tl(cpu_cond, cmp->c1, cmp->c2); 22739d4e2bc7SRichard Henderson } else { 2274c8507ebfSRichard Henderson tcg_gen_setcondi_tl(cmp->cond, cpu_cond, cmp->c1, cmp->c2); 22759d4e2bc7SRichard Henderson } 227689527e3aSRichard Henderson dc->cpu_cond_live = true; 22776b3e4cc6SRichard Henderson } 2278276567aaSRichard Henderson } 2279276567aaSRichard Henderson return true; 2280276567aaSRichard Henderson } 2281276567aaSRichard Henderson 2282af25071cSRichard Henderson static bool raise_priv(DisasContext *dc) 2283af25071cSRichard Henderson { 2284af25071cSRichard Henderson gen_exception(dc, TT_PRIV_INSN); 2285af25071cSRichard Henderson return true; 2286af25071cSRichard Henderson } 2287af25071cSRichard Henderson 228806c060d9SRichard Henderson static bool raise_unimpfpop(DisasContext *dc) 228906c060d9SRichard Henderson { 229006c060d9SRichard Henderson gen_op_fpexception_im(dc, FSR_FTT_UNIMPFPOP); 229106c060d9SRichard Henderson return true; 229206c060d9SRichard Henderson } 229306c060d9SRichard Henderson 229406c060d9SRichard Henderson static bool gen_trap_float128(DisasContext *dc) 229506c060d9SRichard Henderson { 229606c060d9SRichard Henderson if (dc->def->features & CPU_FEATURE_FLOAT128) { 229706c060d9SRichard Henderson return false; 229806c060d9SRichard Henderson } 229906c060d9SRichard Henderson return raise_unimpfpop(dc); 230006c060d9SRichard Henderson } 230106c060d9SRichard Henderson 2302276567aaSRichard Henderson static bool do_bpcc(DisasContext *dc, arg_bcc *a) 2303276567aaSRichard Henderson { 23041ea9c62aSRichard Henderson DisasCompare cmp; 2305276567aaSRichard Henderson 23061ea9c62aSRichard Henderson gen_compare(&cmp, a->cc, a->cond, dc); 23073951b7a8SRichard Henderson return advance_jump_cond(dc, &cmp, a->a, a->i); 2308276567aaSRichard Henderson } 2309276567aaSRichard Henderson 2310276567aaSRichard Henderson TRANS(Bicc, ALL, do_bpcc, a) 2311276567aaSRichard Henderson TRANS(BPcc, 64, do_bpcc, a) 2312276567aaSRichard Henderson 231345196ea4SRichard Henderson static bool do_fbpfcc(DisasContext *dc, arg_bcc *a) 231445196ea4SRichard Henderson { 2315d5471936SRichard Henderson DisasCompare cmp; 231645196ea4SRichard Henderson 231745196ea4SRichard Henderson if (gen_trap_ifnofpu(dc)) { 231845196ea4SRichard Henderson return true; 231945196ea4SRichard Henderson } 2320d5471936SRichard Henderson gen_fcompare(&cmp, a->cc, a->cond); 23213951b7a8SRichard Henderson return advance_jump_cond(dc, &cmp, a->a, a->i); 232245196ea4SRichard Henderson } 232345196ea4SRichard Henderson 232445196ea4SRichard Henderson TRANS(FBPfcc, 64, do_fbpfcc, a) 232545196ea4SRichard Henderson TRANS(FBfcc, ALL, do_fbpfcc, a) 232645196ea4SRichard Henderson 2327ab9ffe98SRichard Henderson static bool trans_BPr(DisasContext *dc, arg_BPr *a) 2328ab9ffe98SRichard Henderson { 2329ab9ffe98SRichard Henderson DisasCompare cmp; 2330ab9ffe98SRichard Henderson 2331ab9ffe98SRichard Henderson if (!avail_64(dc)) { 2332ab9ffe98SRichard Henderson return false; 2333ab9ffe98SRichard Henderson } 23342c4f56c9SRichard Henderson if (!gen_compare_reg(&cmp, a->cond, gen_load_gpr(dc, a->rs1))) { 2335ab9ffe98SRichard Henderson return false; 2336ab9ffe98SRichard Henderson } 23373951b7a8SRichard Henderson return advance_jump_cond(dc, &cmp, a->a, a->i); 2338ab9ffe98SRichard Henderson } 2339ab9ffe98SRichard Henderson 234023ada1b1SRichard Henderson static bool trans_CALL(DisasContext *dc, arg_CALL *a) 234123ada1b1SRichard Henderson { 234223ada1b1SRichard Henderson target_long target = address_mask_i(dc, dc->pc + a->i * 4); 234323ada1b1SRichard Henderson 234423ada1b1SRichard Henderson gen_store_gpr(dc, 15, tcg_constant_tl(dc->pc)); 234523ada1b1SRichard Henderson gen_mov_pc_npc(dc); 234623ada1b1SRichard Henderson dc->npc = target; 234723ada1b1SRichard Henderson return true; 234823ada1b1SRichard Henderson } 234923ada1b1SRichard Henderson 235045196ea4SRichard Henderson static bool trans_NCP(DisasContext *dc, arg_NCP *a) 235145196ea4SRichard Henderson { 235245196ea4SRichard Henderson /* 235345196ea4SRichard Henderson * For sparc32, always generate the no-coprocessor exception. 235445196ea4SRichard Henderson * For sparc64, always generate illegal instruction. 235545196ea4SRichard Henderson */ 235645196ea4SRichard Henderson #ifdef TARGET_SPARC64 235745196ea4SRichard Henderson return false; 235845196ea4SRichard Henderson #else 235945196ea4SRichard Henderson gen_exception(dc, TT_NCP_INSN); 236045196ea4SRichard Henderson return true; 236145196ea4SRichard Henderson #endif 236245196ea4SRichard Henderson } 236345196ea4SRichard Henderson 23646d2a0768SRichard Henderson static bool trans_SETHI(DisasContext *dc, arg_SETHI *a) 23656d2a0768SRichard Henderson { 23666d2a0768SRichard Henderson /* Special-case %g0 because that's the canonical nop. */ 23676d2a0768SRichard Henderson if (a->rd) { 23686d2a0768SRichard Henderson gen_store_gpr(dc, a->rd, tcg_constant_tl((uint32_t)a->i << 10)); 23696d2a0768SRichard Henderson } 23706d2a0768SRichard Henderson return advance_pc(dc); 23716d2a0768SRichard Henderson } 23726d2a0768SRichard Henderson 23730faef01bSRichard Henderson /* 23740faef01bSRichard Henderson * Major Opcode 10 -- integer, floating-point, vis, and system insns. 23750faef01bSRichard Henderson */ 23760faef01bSRichard Henderson 237730376636SRichard Henderson static bool do_tcc(DisasContext *dc, int cond, int cc, 237830376636SRichard Henderson int rs1, bool imm, int rs2_or_imm) 237930376636SRichard Henderson { 238030376636SRichard Henderson int mask = ((dc->def->features & CPU_FEATURE_HYPV) && supervisor(dc) 238130376636SRichard Henderson ? UA2005_HTRAP_MASK : V8_TRAP_MASK); 238230376636SRichard Henderson DisasCompare cmp; 238330376636SRichard Henderson TCGLabel *lab; 238430376636SRichard Henderson TCGv_i32 trap; 238530376636SRichard Henderson 238630376636SRichard Henderson /* Trap never. */ 238730376636SRichard Henderson if (cond == 0) { 238830376636SRichard Henderson return advance_pc(dc); 238930376636SRichard Henderson } 239030376636SRichard Henderson 239130376636SRichard Henderson /* 239230376636SRichard Henderson * Immediate traps are the most common case. Since this value is 239330376636SRichard Henderson * live across the branch, it really pays to evaluate the constant. 239430376636SRichard Henderson */ 239530376636SRichard Henderson if (rs1 == 0 && (imm || rs2_or_imm == 0)) { 239630376636SRichard Henderson trap = tcg_constant_i32((rs2_or_imm & mask) + TT_TRAP); 239730376636SRichard Henderson } else { 239830376636SRichard Henderson trap = tcg_temp_new_i32(); 239930376636SRichard Henderson tcg_gen_trunc_tl_i32(trap, gen_load_gpr(dc, rs1)); 240030376636SRichard Henderson if (imm) { 240130376636SRichard Henderson tcg_gen_addi_i32(trap, trap, rs2_or_imm); 240230376636SRichard Henderson } else { 240330376636SRichard Henderson TCGv_i32 t2 = tcg_temp_new_i32(); 240430376636SRichard Henderson tcg_gen_trunc_tl_i32(t2, gen_load_gpr(dc, rs2_or_imm)); 240530376636SRichard Henderson tcg_gen_add_i32(trap, trap, t2); 240630376636SRichard Henderson } 240730376636SRichard Henderson tcg_gen_andi_i32(trap, trap, mask); 240830376636SRichard Henderson tcg_gen_addi_i32(trap, trap, TT_TRAP); 240930376636SRichard Henderson } 241030376636SRichard Henderson 241189527e3aSRichard Henderson finishing_insn(dc); 241289527e3aSRichard Henderson 241330376636SRichard Henderson /* Trap always. */ 241430376636SRichard Henderson if (cond == 8) { 241530376636SRichard Henderson save_state(dc); 241630376636SRichard Henderson gen_helper_raise_exception(tcg_env, trap); 241730376636SRichard Henderson dc->base.is_jmp = DISAS_NORETURN; 241830376636SRichard Henderson return true; 241930376636SRichard Henderson } 242030376636SRichard Henderson 242130376636SRichard Henderson /* Conditional trap. */ 242230376636SRichard Henderson flush_cond(dc); 242330376636SRichard Henderson lab = delay_exceptionv(dc, trap); 242430376636SRichard Henderson gen_compare(&cmp, cc, cond, dc); 2425c8507ebfSRichard Henderson tcg_gen_brcondi_tl(cmp.cond, cmp.c1, cmp.c2, lab); 242630376636SRichard Henderson 242730376636SRichard Henderson return advance_pc(dc); 242830376636SRichard Henderson } 242930376636SRichard Henderson 243030376636SRichard Henderson static bool trans_Tcc_r(DisasContext *dc, arg_Tcc_r *a) 243130376636SRichard Henderson { 243230376636SRichard Henderson if (avail_32(dc) && a->cc) { 243330376636SRichard Henderson return false; 243430376636SRichard Henderson } 243530376636SRichard Henderson return do_tcc(dc, a->cond, a->cc, a->rs1, false, a->rs2); 243630376636SRichard Henderson } 243730376636SRichard Henderson 243830376636SRichard Henderson static bool trans_Tcc_i_v7(DisasContext *dc, arg_Tcc_i_v7 *a) 243930376636SRichard Henderson { 244030376636SRichard Henderson if (avail_64(dc)) { 244130376636SRichard Henderson return false; 244230376636SRichard Henderson } 244330376636SRichard Henderson return do_tcc(dc, a->cond, 0, a->rs1, true, a->i); 244430376636SRichard Henderson } 244530376636SRichard Henderson 244630376636SRichard Henderson static bool trans_Tcc_i_v9(DisasContext *dc, arg_Tcc_i_v9 *a) 244730376636SRichard Henderson { 244830376636SRichard Henderson if (avail_32(dc)) { 244930376636SRichard Henderson return false; 245030376636SRichard Henderson } 245130376636SRichard Henderson return do_tcc(dc, a->cond, a->cc, a->rs1, true, a->i); 245230376636SRichard Henderson } 245330376636SRichard Henderson 2454af25071cSRichard Henderson static bool trans_STBAR(DisasContext *dc, arg_STBAR *a) 2455af25071cSRichard Henderson { 2456af25071cSRichard Henderson tcg_gen_mb(TCG_MO_ST_ST | TCG_BAR_SC); 2457af25071cSRichard Henderson return advance_pc(dc); 2458af25071cSRichard Henderson } 2459af25071cSRichard Henderson 2460af25071cSRichard Henderson static bool trans_MEMBAR(DisasContext *dc, arg_MEMBAR *a) 2461af25071cSRichard Henderson { 2462af25071cSRichard Henderson if (avail_32(dc)) { 2463af25071cSRichard Henderson return false; 2464af25071cSRichard Henderson } 2465af25071cSRichard Henderson if (a->mmask) { 2466af25071cSRichard Henderson /* Note TCG_MO_* was modeled on sparc64, so mmask matches. */ 2467af25071cSRichard Henderson tcg_gen_mb(a->mmask | TCG_BAR_SC); 2468af25071cSRichard Henderson } 2469af25071cSRichard Henderson if (a->cmask) { 2470af25071cSRichard Henderson /* For #Sync, etc, end the TB to recognize interrupts. */ 2471af25071cSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 2472af25071cSRichard Henderson } 2473af25071cSRichard Henderson return advance_pc(dc); 2474af25071cSRichard Henderson } 2475af25071cSRichard Henderson 2476af25071cSRichard Henderson static bool do_rd_special(DisasContext *dc, bool priv, int rd, 2477af25071cSRichard Henderson TCGv (*func)(DisasContext *, TCGv)) 2478af25071cSRichard Henderson { 2479af25071cSRichard Henderson if (!priv) { 2480af25071cSRichard Henderson return raise_priv(dc); 2481af25071cSRichard Henderson } 2482af25071cSRichard Henderson gen_store_gpr(dc, rd, func(dc, gen_dest_gpr(dc, rd))); 2483af25071cSRichard Henderson return advance_pc(dc); 2484af25071cSRichard Henderson } 2485af25071cSRichard Henderson 2486af25071cSRichard Henderson static TCGv do_rdy(DisasContext *dc, TCGv dst) 2487af25071cSRichard Henderson { 2488af25071cSRichard Henderson return cpu_y; 2489af25071cSRichard Henderson } 2490af25071cSRichard Henderson 2491af25071cSRichard Henderson static bool trans_RDY(DisasContext *dc, arg_RDY *a) 2492af25071cSRichard Henderson { 2493af25071cSRichard Henderson /* 2494af25071cSRichard Henderson * TODO: Need a feature bit for sparcv8. In the meantime, treat all 2495af25071cSRichard Henderson * 32-bit cpus like sparcv7, which ignores the rs1 field. 2496af25071cSRichard Henderson * This matches after all other ASR, so Leon3 Asr17 is handled first. 2497af25071cSRichard Henderson */ 2498af25071cSRichard Henderson if (avail_64(dc) && a->rs1 != 0) { 2499af25071cSRichard Henderson return false; 2500af25071cSRichard Henderson } 2501af25071cSRichard Henderson return do_rd_special(dc, true, a->rd, do_rdy); 2502af25071cSRichard Henderson } 2503af25071cSRichard Henderson 2504af25071cSRichard Henderson static TCGv do_rd_leon3_config(DisasContext *dc, TCGv dst) 2505af25071cSRichard Henderson { 2506c92948f2SClément Chigot gen_helper_rdasr17(dst, tcg_env); 2507c92948f2SClément Chigot return dst; 2508af25071cSRichard Henderson } 2509af25071cSRichard Henderson 2510af25071cSRichard Henderson TRANS(RDASR17, ASR17, do_rd_special, true, a->rd, do_rd_leon3_config) 2511af25071cSRichard Henderson 2512af25071cSRichard Henderson static TCGv do_rdccr(DisasContext *dc, TCGv dst) 2513af25071cSRichard Henderson { 2514af25071cSRichard Henderson gen_helper_rdccr(dst, tcg_env); 2515af25071cSRichard Henderson return dst; 2516af25071cSRichard Henderson } 2517af25071cSRichard Henderson 2518af25071cSRichard Henderson TRANS(RDCCR, 64, do_rd_special, true, a->rd, do_rdccr) 2519af25071cSRichard Henderson 2520af25071cSRichard Henderson static TCGv do_rdasi(DisasContext *dc, TCGv dst) 2521af25071cSRichard Henderson { 2522af25071cSRichard Henderson #ifdef TARGET_SPARC64 2523af25071cSRichard Henderson return tcg_constant_tl(dc->asi); 2524af25071cSRichard Henderson #else 2525af25071cSRichard Henderson qemu_build_not_reached(); 2526af25071cSRichard Henderson #endif 2527af25071cSRichard Henderson } 2528af25071cSRichard Henderson 2529af25071cSRichard Henderson TRANS(RDASI, 64, do_rd_special, true, a->rd, do_rdasi) 2530af25071cSRichard Henderson 2531af25071cSRichard Henderson static TCGv do_rdtick(DisasContext *dc, TCGv dst) 2532af25071cSRichard Henderson { 2533af25071cSRichard Henderson TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 2534af25071cSRichard Henderson 2535af25071cSRichard Henderson tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(tick)); 2536af25071cSRichard Henderson if (translator_io_start(&dc->base)) { 2537af25071cSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 2538af25071cSRichard Henderson } 2539af25071cSRichard Henderson gen_helper_tick_get_count(dst, tcg_env, r_tickptr, 2540af25071cSRichard Henderson tcg_constant_i32(dc->mem_idx)); 2541af25071cSRichard Henderson return dst; 2542af25071cSRichard Henderson } 2543af25071cSRichard Henderson 2544af25071cSRichard Henderson /* TODO: non-priv access only allowed when enabled. */ 2545af25071cSRichard Henderson TRANS(RDTICK, 64, do_rd_special, true, a->rd, do_rdtick) 2546af25071cSRichard Henderson 2547af25071cSRichard Henderson static TCGv do_rdpc(DisasContext *dc, TCGv dst) 2548af25071cSRichard Henderson { 2549af25071cSRichard Henderson return tcg_constant_tl(address_mask_i(dc, dc->pc)); 2550af25071cSRichard Henderson } 2551af25071cSRichard Henderson 2552af25071cSRichard Henderson TRANS(RDPC, 64, do_rd_special, true, a->rd, do_rdpc) 2553af25071cSRichard Henderson 2554af25071cSRichard Henderson static TCGv do_rdfprs(DisasContext *dc, TCGv dst) 2555af25071cSRichard Henderson { 2556af25071cSRichard Henderson tcg_gen_ext_i32_tl(dst, cpu_fprs); 2557af25071cSRichard Henderson return dst; 2558af25071cSRichard Henderson } 2559af25071cSRichard Henderson 2560af25071cSRichard Henderson TRANS(RDFPRS, 64, do_rd_special, true, a->rd, do_rdfprs) 2561af25071cSRichard Henderson 2562af25071cSRichard Henderson static TCGv do_rdgsr(DisasContext *dc, TCGv dst) 2563af25071cSRichard Henderson { 2564af25071cSRichard Henderson gen_trap_ifnofpu(dc); 2565af25071cSRichard Henderson return cpu_gsr; 2566af25071cSRichard Henderson } 2567af25071cSRichard Henderson 2568af25071cSRichard Henderson TRANS(RDGSR, 64, do_rd_special, true, a->rd, do_rdgsr) 2569af25071cSRichard Henderson 2570af25071cSRichard Henderson static TCGv do_rdsoftint(DisasContext *dc, TCGv dst) 2571af25071cSRichard Henderson { 2572af25071cSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(softint)); 2573af25071cSRichard Henderson return dst; 2574af25071cSRichard Henderson } 2575af25071cSRichard Henderson 2576af25071cSRichard Henderson TRANS(RDSOFTINT, 64, do_rd_special, supervisor(dc), a->rd, do_rdsoftint) 2577af25071cSRichard Henderson 2578af25071cSRichard Henderson static TCGv do_rdtick_cmpr(DisasContext *dc, TCGv dst) 2579af25071cSRichard Henderson { 2580577efa45SRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(tick_cmpr)); 2581577efa45SRichard Henderson return dst; 2582af25071cSRichard Henderson } 2583af25071cSRichard Henderson 2584af25071cSRichard Henderson /* TODO: non-priv access only allowed when enabled. */ 2585af25071cSRichard Henderson TRANS(RDTICK_CMPR, 64, do_rd_special, true, a->rd, do_rdtick_cmpr) 2586af25071cSRichard Henderson 2587af25071cSRichard Henderson static TCGv do_rdstick(DisasContext *dc, TCGv dst) 2588af25071cSRichard Henderson { 2589af25071cSRichard Henderson TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 2590af25071cSRichard Henderson 2591af25071cSRichard Henderson tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(stick)); 2592af25071cSRichard Henderson if (translator_io_start(&dc->base)) { 2593af25071cSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 2594af25071cSRichard Henderson } 2595af25071cSRichard Henderson gen_helper_tick_get_count(dst, tcg_env, r_tickptr, 2596af25071cSRichard Henderson tcg_constant_i32(dc->mem_idx)); 2597af25071cSRichard Henderson return dst; 2598af25071cSRichard Henderson } 2599af25071cSRichard Henderson 2600af25071cSRichard Henderson /* TODO: non-priv access only allowed when enabled. */ 2601af25071cSRichard Henderson TRANS(RDSTICK, 64, do_rd_special, true, a->rd, do_rdstick) 2602af25071cSRichard Henderson 2603af25071cSRichard Henderson static TCGv do_rdstick_cmpr(DisasContext *dc, TCGv dst) 2604af25071cSRichard Henderson { 2605577efa45SRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(stick_cmpr)); 2606577efa45SRichard Henderson return dst; 2607af25071cSRichard Henderson } 2608af25071cSRichard Henderson 2609af25071cSRichard Henderson /* TODO: supervisor access only allowed when enabled by hypervisor. */ 2610af25071cSRichard Henderson TRANS(RDSTICK_CMPR, 64, do_rd_special, supervisor(dc), a->rd, do_rdstick_cmpr) 2611af25071cSRichard Henderson 2612af25071cSRichard Henderson /* 2613af25071cSRichard Henderson * UltraSPARC-T1 Strand status. 2614af25071cSRichard Henderson * HYPV check maybe not enough, UA2005 & UA2007 describe 2615af25071cSRichard Henderson * this ASR as impl. dep 2616af25071cSRichard Henderson */ 2617af25071cSRichard Henderson static TCGv do_rdstrand_status(DisasContext *dc, TCGv dst) 2618af25071cSRichard Henderson { 2619af25071cSRichard Henderson return tcg_constant_tl(1); 2620af25071cSRichard Henderson } 2621af25071cSRichard Henderson 2622af25071cSRichard Henderson TRANS(RDSTRAND_STATUS, HYPV, do_rd_special, true, a->rd, do_rdstrand_status) 2623af25071cSRichard Henderson 2624668bb9b7SRichard Henderson static TCGv do_rdpsr(DisasContext *dc, TCGv dst) 2625668bb9b7SRichard Henderson { 2626668bb9b7SRichard Henderson gen_helper_rdpsr(dst, tcg_env); 2627668bb9b7SRichard Henderson return dst; 2628668bb9b7SRichard Henderson } 2629668bb9b7SRichard Henderson 2630668bb9b7SRichard Henderson TRANS(RDPSR, 32, do_rd_special, supervisor(dc), a->rd, do_rdpsr) 2631668bb9b7SRichard Henderson 2632668bb9b7SRichard Henderson static TCGv do_rdhpstate(DisasContext *dc, TCGv dst) 2633668bb9b7SRichard Henderson { 2634668bb9b7SRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hpstate)); 2635668bb9b7SRichard Henderson return dst; 2636668bb9b7SRichard Henderson } 2637668bb9b7SRichard Henderson 2638668bb9b7SRichard Henderson TRANS(RDHPR_hpstate, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhpstate) 2639668bb9b7SRichard Henderson 2640668bb9b7SRichard Henderson static TCGv do_rdhtstate(DisasContext *dc, TCGv dst) 2641668bb9b7SRichard Henderson { 2642668bb9b7SRichard Henderson TCGv_i32 tl = tcg_temp_new_i32(); 2643668bb9b7SRichard Henderson TCGv_ptr tp = tcg_temp_new_ptr(); 2644668bb9b7SRichard Henderson 2645668bb9b7SRichard Henderson tcg_gen_ld_i32(tl, tcg_env, env64_field_offsetof(tl)); 2646668bb9b7SRichard Henderson tcg_gen_andi_i32(tl, tl, MAXTL_MASK); 2647668bb9b7SRichard Henderson tcg_gen_shli_i32(tl, tl, 3); 2648668bb9b7SRichard Henderson tcg_gen_ext_i32_ptr(tp, tl); 2649668bb9b7SRichard Henderson tcg_gen_add_ptr(tp, tp, tcg_env); 2650668bb9b7SRichard Henderson 2651668bb9b7SRichard Henderson tcg_gen_ld_tl(dst, tp, env64_field_offsetof(htstate)); 2652668bb9b7SRichard Henderson return dst; 2653668bb9b7SRichard Henderson } 2654668bb9b7SRichard Henderson 2655668bb9b7SRichard Henderson TRANS(RDHPR_htstate, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhtstate) 2656668bb9b7SRichard Henderson 2657668bb9b7SRichard Henderson static TCGv do_rdhintp(DisasContext *dc, TCGv dst) 2658668bb9b7SRichard Henderson { 26592da789deSRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hintp)); 26602da789deSRichard Henderson return dst; 2661668bb9b7SRichard Henderson } 2662668bb9b7SRichard Henderson 2663668bb9b7SRichard Henderson TRANS(RDHPR_hintp, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhintp) 2664668bb9b7SRichard Henderson 2665668bb9b7SRichard Henderson static TCGv do_rdhtba(DisasContext *dc, TCGv dst) 2666668bb9b7SRichard Henderson { 26672da789deSRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(htba)); 26682da789deSRichard Henderson return dst; 2669668bb9b7SRichard Henderson } 2670668bb9b7SRichard Henderson 2671668bb9b7SRichard Henderson TRANS(RDHPR_htba, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhtba) 2672668bb9b7SRichard Henderson 2673668bb9b7SRichard Henderson static TCGv do_rdhver(DisasContext *dc, TCGv dst) 2674668bb9b7SRichard Henderson { 26752da789deSRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hver)); 26762da789deSRichard Henderson return dst; 2677668bb9b7SRichard Henderson } 2678668bb9b7SRichard Henderson 2679668bb9b7SRichard Henderson TRANS(RDHPR_hver, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhver) 2680668bb9b7SRichard Henderson 2681668bb9b7SRichard Henderson static TCGv do_rdhstick_cmpr(DisasContext *dc, TCGv dst) 2682668bb9b7SRichard Henderson { 2683577efa45SRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hstick_cmpr)); 2684577efa45SRichard Henderson return dst; 2685668bb9b7SRichard Henderson } 2686668bb9b7SRichard Henderson 2687668bb9b7SRichard Henderson TRANS(RDHPR_hstick_cmpr, HYPV, do_rd_special, hypervisor(dc), a->rd, 2688668bb9b7SRichard Henderson do_rdhstick_cmpr) 2689668bb9b7SRichard Henderson 26905d617bfbSRichard Henderson static TCGv do_rdwim(DisasContext *dc, TCGv dst) 26915d617bfbSRichard Henderson { 2692cd6269f7SRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env32_field_offsetof(wim)); 2693cd6269f7SRichard Henderson return dst; 26945d617bfbSRichard Henderson } 26955d617bfbSRichard Henderson 26965d617bfbSRichard Henderson TRANS(RDWIM, 32, do_rd_special, supervisor(dc), a->rd, do_rdwim) 26975d617bfbSRichard Henderson 26985d617bfbSRichard Henderson static TCGv do_rdtpc(DisasContext *dc, TCGv dst) 26995d617bfbSRichard Henderson { 27005d617bfbSRichard Henderson #ifdef TARGET_SPARC64 27015d617bfbSRichard Henderson TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 27025d617bfbSRichard Henderson 27035d617bfbSRichard Henderson gen_load_trap_state_at_tl(r_tsptr); 27045d617bfbSRichard Henderson tcg_gen_ld_tl(dst, r_tsptr, offsetof(trap_state, tpc)); 27055d617bfbSRichard Henderson return dst; 27065d617bfbSRichard Henderson #else 27075d617bfbSRichard Henderson qemu_build_not_reached(); 27085d617bfbSRichard Henderson #endif 27095d617bfbSRichard Henderson } 27105d617bfbSRichard Henderson 27115d617bfbSRichard Henderson TRANS(RDPR_tpc, 64, do_rd_special, supervisor(dc), a->rd, do_rdtpc) 27125d617bfbSRichard Henderson 27135d617bfbSRichard Henderson static TCGv do_rdtnpc(DisasContext *dc, TCGv dst) 27145d617bfbSRichard Henderson { 27155d617bfbSRichard Henderson #ifdef TARGET_SPARC64 27165d617bfbSRichard Henderson TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 27175d617bfbSRichard Henderson 27185d617bfbSRichard Henderson gen_load_trap_state_at_tl(r_tsptr); 27195d617bfbSRichard Henderson tcg_gen_ld_tl(dst, r_tsptr, offsetof(trap_state, tnpc)); 27205d617bfbSRichard Henderson return dst; 27215d617bfbSRichard Henderson #else 27225d617bfbSRichard Henderson qemu_build_not_reached(); 27235d617bfbSRichard Henderson #endif 27245d617bfbSRichard Henderson } 27255d617bfbSRichard Henderson 27265d617bfbSRichard Henderson TRANS(RDPR_tnpc, 64, do_rd_special, supervisor(dc), a->rd, do_rdtnpc) 27275d617bfbSRichard Henderson 27285d617bfbSRichard Henderson static TCGv do_rdtstate(DisasContext *dc, TCGv dst) 27295d617bfbSRichard Henderson { 27305d617bfbSRichard Henderson #ifdef TARGET_SPARC64 27315d617bfbSRichard Henderson TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 27325d617bfbSRichard Henderson 27335d617bfbSRichard Henderson gen_load_trap_state_at_tl(r_tsptr); 27345d617bfbSRichard Henderson tcg_gen_ld_tl(dst, r_tsptr, offsetof(trap_state, tstate)); 27355d617bfbSRichard Henderson return dst; 27365d617bfbSRichard Henderson #else 27375d617bfbSRichard Henderson qemu_build_not_reached(); 27385d617bfbSRichard Henderson #endif 27395d617bfbSRichard Henderson } 27405d617bfbSRichard Henderson 27415d617bfbSRichard Henderson TRANS(RDPR_tstate, 64, do_rd_special, supervisor(dc), a->rd, do_rdtstate) 27425d617bfbSRichard Henderson 27435d617bfbSRichard Henderson static TCGv do_rdtt(DisasContext *dc, TCGv dst) 27445d617bfbSRichard Henderson { 27455d617bfbSRichard Henderson #ifdef TARGET_SPARC64 27465d617bfbSRichard Henderson TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 27475d617bfbSRichard Henderson 27485d617bfbSRichard Henderson gen_load_trap_state_at_tl(r_tsptr); 27495d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, r_tsptr, offsetof(trap_state, tt)); 27505d617bfbSRichard Henderson return dst; 27515d617bfbSRichard Henderson #else 27525d617bfbSRichard Henderson qemu_build_not_reached(); 27535d617bfbSRichard Henderson #endif 27545d617bfbSRichard Henderson } 27555d617bfbSRichard Henderson 27565d617bfbSRichard Henderson TRANS(RDPR_tt, 64, do_rd_special, supervisor(dc), a->rd, do_rdtt) 27575d617bfbSRichard Henderson TRANS(RDPR_tick, 64, do_rd_special, supervisor(dc), a->rd, do_rdtick) 27585d617bfbSRichard Henderson 27595d617bfbSRichard Henderson static TCGv do_rdtba(DisasContext *dc, TCGv dst) 27605d617bfbSRichard Henderson { 27615d617bfbSRichard Henderson return cpu_tbr; 27625d617bfbSRichard Henderson } 27635d617bfbSRichard Henderson 2764e8325dc0SRichard Henderson TRANS(RDTBR, 32, do_rd_special, supervisor(dc), a->rd, do_rdtba) 27655d617bfbSRichard Henderson TRANS(RDPR_tba, 64, do_rd_special, supervisor(dc), a->rd, do_rdtba) 27665d617bfbSRichard Henderson 27675d617bfbSRichard Henderson static TCGv do_rdpstate(DisasContext *dc, TCGv dst) 27685d617bfbSRichard Henderson { 27695d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(pstate)); 27705d617bfbSRichard Henderson return dst; 27715d617bfbSRichard Henderson } 27725d617bfbSRichard Henderson 27735d617bfbSRichard Henderson TRANS(RDPR_pstate, 64, do_rd_special, supervisor(dc), a->rd, do_rdpstate) 27745d617bfbSRichard Henderson 27755d617bfbSRichard Henderson static TCGv do_rdtl(DisasContext *dc, TCGv dst) 27765d617bfbSRichard Henderson { 27775d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(tl)); 27785d617bfbSRichard Henderson return dst; 27795d617bfbSRichard Henderson } 27805d617bfbSRichard Henderson 27815d617bfbSRichard Henderson TRANS(RDPR_tl, 64, do_rd_special, supervisor(dc), a->rd, do_rdtl) 27825d617bfbSRichard Henderson 27835d617bfbSRichard Henderson static TCGv do_rdpil(DisasContext *dc, TCGv dst) 27845d617bfbSRichard Henderson { 27855d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env_field_offsetof(psrpil)); 27865d617bfbSRichard Henderson return dst; 27875d617bfbSRichard Henderson } 27885d617bfbSRichard Henderson 27895d617bfbSRichard Henderson TRANS(RDPR_pil, 64, do_rd_special, supervisor(dc), a->rd, do_rdpil) 27905d617bfbSRichard Henderson 27915d617bfbSRichard Henderson static TCGv do_rdcwp(DisasContext *dc, TCGv dst) 27925d617bfbSRichard Henderson { 27935d617bfbSRichard Henderson gen_helper_rdcwp(dst, tcg_env); 27945d617bfbSRichard Henderson return dst; 27955d617bfbSRichard Henderson } 27965d617bfbSRichard Henderson 27975d617bfbSRichard Henderson TRANS(RDPR_cwp, 64, do_rd_special, supervisor(dc), a->rd, do_rdcwp) 27985d617bfbSRichard Henderson 27995d617bfbSRichard Henderson static TCGv do_rdcansave(DisasContext *dc, TCGv dst) 28005d617bfbSRichard Henderson { 28015d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(cansave)); 28025d617bfbSRichard Henderson return dst; 28035d617bfbSRichard Henderson } 28045d617bfbSRichard Henderson 28055d617bfbSRichard Henderson TRANS(RDPR_cansave, 64, do_rd_special, supervisor(dc), a->rd, do_rdcansave) 28065d617bfbSRichard Henderson 28075d617bfbSRichard Henderson static TCGv do_rdcanrestore(DisasContext *dc, TCGv dst) 28085d617bfbSRichard Henderson { 28095d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(canrestore)); 28105d617bfbSRichard Henderson return dst; 28115d617bfbSRichard Henderson } 28125d617bfbSRichard Henderson 28135d617bfbSRichard Henderson TRANS(RDPR_canrestore, 64, do_rd_special, supervisor(dc), a->rd, 28145d617bfbSRichard Henderson do_rdcanrestore) 28155d617bfbSRichard Henderson 28165d617bfbSRichard Henderson static TCGv do_rdcleanwin(DisasContext *dc, TCGv dst) 28175d617bfbSRichard Henderson { 28185d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(cleanwin)); 28195d617bfbSRichard Henderson return dst; 28205d617bfbSRichard Henderson } 28215d617bfbSRichard Henderson 28225d617bfbSRichard Henderson TRANS(RDPR_cleanwin, 64, do_rd_special, supervisor(dc), a->rd, do_rdcleanwin) 28235d617bfbSRichard Henderson 28245d617bfbSRichard Henderson static TCGv do_rdotherwin(DisasContext *dc, TCGv dst) 28255d617bfbSRichard Henderson { 28265d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(otherwin)); 28275d617bfbSRichard Henderson return dst; 28285d617bfbSRichard Henderson } 28295d617bfbSRichard Henderson 28305d617bfbSRichard Henderson TRANS(RDPR_otherwin, 64, do_rd_special, supervisor(dc), a->rd, do_rdotherwin) 28315d617bfbSRichard Henderson 28325d617bfbSRichard Henderson static TCGv do_rdwstate(DisasContext *dc, TCGv dst) 28335d617bfbSRichard Henderson { 28345d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(wstate)); 28355d617bfbSRichard Henderson return dst; 28365d617bfbSRichard Henderson } 28375d617bfbSRichard Henderson 28385d617bfbSRichard Henderson TRANS(RDPR_wstate, 64, do_rd_special, supervisor(dc), a->rd, do_rdwstate) 28395d617bfbSRichard Henderson 28405d617bfbSRichard Henderson static TCGv do_rdgl(DisasContext *dc, TCGv dst) 28415d617bfbSRichard Henderson { 28425d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(gl)); 28435d617bfbSRichard Henderson return dst; 28445d617bfbSRichard Henderson } 28455d617bfbSRichard Henderson 28465d617bfbSRichard Henderson TRANS(RDPR_gl, GL, do_rd_special, supervisor(dc), a->rd, do_rdgl) 28475d617bfbSRichard Henderson 28485d617bfbSRichard Henderson /* UA2005 strand status */ 28495d617bfbSRichard Henderson static TCGv do_rdssr(DisasContext *dc, TCGv dst) 28505d617bfbSRichard Henderson { 28512da789deSRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(ssr)); 28522da789deSRichard Henderson return dst; 28535d617bfbSRichard Henderson } 28545d617bfbSRichard Henderson 28555d617bfbSRichard Henderson TRANS(RDPR_strand_status, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdssr) 28565d617bfbSRichard Henderson 28575d617bfbSRichard Henderson static TCGv do_rdver(DisasContext *dc, TCGv dst) 28585d617bfbSRichard Henderson { 28592da789deSRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(version)); 28602da789deSRichard Henderson return dst; 28615d617bfbSRichard Henderson } 28625d617bfbSRichard Henderson 28635d617bfbSRichard Henderson TRANS(RDPR_ver, 64, do_rd_special, supervisor(dc), a->rd, do_rdver) 28645d617bfbSRichard Henderson 2865e8325dc0SRichard Henderson static bool trans_FLUSHW(DisasContext *dc, arg_FLUSHW *a) 2866e8325dc0SRichard Henderson { 2867e8325dc0SRichard Henderson if (avail_64(dc)) { 2868e8325dc0SRichard Henderson gen_helper_flushw(tcg_env); 2869e8325dc0SRichard Henderson return advance_pc(dc); 2870e8325dc0SRichard Henderson } 2871e8325dc0SRichard Henderson return false; 2872e8325dc0SRichard Henderson } 2873e8325dc0SRichard Henderson 28740faef01bSRichard Henderson static bool do_wr_special(DisasContext *dc, arg_r_r_ri *a, bool priv, 28750faef01bSRichard Henderson void (*func)(DisasContext *, TCGv)) 28760faef01bSRichard Henderson { 28770faef01bSRichard Henderson TCGv src; 28780faef01bSRichard Henderson 28790faef01bSRichard Henderson /* For simplicity, we under-decoded the rs2 form. */ 28800faef01bSRichard Henderson if (!a->imm && (a->rs2_or_imm & ~0x1f)) { 28810faef01bSRichard Henderson return false; 28820faef01bSRichard Henderson } 28830faef01bSRichard Henderson if (!priv) { 28840faef01bSRichard Henderson return raise_priv(dc); 28850faef01bSRichard Henderson } 28860faef01bSRichard Henderson 28870faef01bSRichard Henderson if (a->rs1 == 0 && (a->imm || a->rs2_or_imm == 0)) { 28880faef01bSRichard Henderson src = tcg_constant_tl(a->rs2_or_imm); 28890faef01bSRichard Henderson } else { 28900faef01bSRichard Henderson TCGv src1 = gen_load_gpr(dc, a->rs1); 28910faef01bSRichard Henderson if (a->rs2_or_imm == 0) { 28920faef01bSRichard Henderson src = src1; 28930faef01bSRichard Henderson } else { 28940faef01bSRichard Henderson src = tcg_temp_new(); 28950faef01bSRichard Henderson if (a->imm) { 28960faef01bSRichard Henderson tcg_gen_xori_tl(src, src1, a->rs2_or_imm); 28970faef01bSRichard Henderson } else { 28980faef01bSRichard Henderson tcg_gen_xor_tl(src, src1, gen_load_gpr(dc, a->rs2_or_imm)); 28990faef01bSRichard Henderson } 29000faef01bSRichard Henderson } 29010faef01bSRichard Henderson } 29020faef01bSRichard Henderson func(dc, src); 29030faef01bSRichard Henderson return advance_pc(dc); 29040faef01bSRichard Henderson } 29050faef01bSRichard Henderson 29060faef01bSRichard Henderson static void do_wry(DisasContext *dc, TCGv src) 29070faef01bSRichard Henderson { 29080faef01bSRichard Henderson tcg_gen_ext32u_tl(cpu_y, src); 29090faef01bSRichard Henderson } 29100faef01bSRichard Henderson 29110faef01bSRichard Henderson TRANS(WRY, ALL, do_wr_special, a, true, do_wry) 29120faef01bSRichard Henderson 29130faef01bSRichard Henderson static void do_wrccr(DisasContext *dc, TCGv src) 29140faef01bSRichard Henderson { 29150faef01bSRichard Henderson gen_helper_wrccr(tcg_env, src); 29160faef01bSRichard Henderson } 29170faef01bSRichard Henderson 29180faef01bSRichard Henderson TRANS(WRCCR, 64, do_wr_special, a, true, do_wrccr) 29190faef01bSRichard Henderson 29200faef01bSRichard Henderson static void do_wrasi(DisasContext *dc, TCGv src) 29210faef01bSRichard Henderson { 29220faef01bSRichard Henderson TCGv tmp = tcg_temp_new(); 29230faef01bSRichard Henderson 29240faef01bSRichard Henderson tcg_gen_ext8u_tl(tmp, src); 29250faef01bSRichard Henderson tcg_gen_st32_tl(tmp, tcg_env, env64_field_offsetof(asi)); 29260faef01bSRichard Henderson /* End TB to notice changed ASI. */ 29270faef01bSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 29280faef01bSRichard Henderson } 29290faef01bSRichard Henderson 29300faef01bSRichard Henderson TRANS(WRASI, 64, do_wr_special, a, true, do_wrasi) 29310faef01bSRichard Henderson 29320faef01bSRichard Henderson static void do_wrfprs(DisasContext *dc, TCGv src) 29330faef01bSRichard Henderson { 29340faef01bSRichard Henderson #ifdef TARGET_SPARC64 29350faef01bSRichard Henderson tcg_gen_trunc_tl_i32(cpu_fprs, src); 29360faef01bSRichard Henderson dc->fprs_dirty = 0; 29370faef01bSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 29380faef01bSRichard Henderson #else 29390faef01bSRichard Henderson qemu_build_not_reached(); 29400faef01bSRichard Henderson #endif 29410faef01bSRichard Henderson } 29420faef01bSRichard Henderson 29430faef01bSRichard Henderson TRANS(WRFPRS, 64, do_wr_special, a, true, do_wrfprs) 29440faef01bSRichard Henderson 29450faef01bSRichard Henderson static void do_wrgsr(DisasContext *dc, TCGv src) 29460faef01bSRichard Henderson { 29470faef01bSRichard Henderson gen_trap_ifnofpu(dc); 29480faef01bSRichard Henderson tcg_gen_mov_tl(cpu_gsr, src); 29490faef01bSRichard Henderson } 29500faef01bSRichard Henderson 29510faef01bSRichard Henderson TRANS(WRGSR, 64, do_wr_special, a, true, do_wrgsr) 29520faef01bSRichard Henderson 29530faef01bSRichard Henderson static void do_wrsoftint_set(DisasContext *dc, TCGv src) 29540faef01bSRichard Henderson { 29550faef01bSRichard Henderson gen_helper_set_softint(tcg_env, src); 29560faef01bSRichard Henderson } 29570faef01bSRichard Henderson 29580faef01bSRichard Henderson TRANS(WRSOFTINT_SET, 64, do_wr_special, a, supervisor(dc), do_wrsoftint_set) 29590faef01bSRichard Henderson 29600faef01bSRichard Henderson static void do_wrsoftint_clr(DisasContext *dc, TCGv src) 29610faef01bSRichard Henderson { 29620faef01bSRichard Henderson gen_helper_clear_softint(tcg_env, src); 29630faef01bSRichard Henderson } 29640faef01bSRichard Henderson 29650faef01bSRichard Henderson TRANS(WRSOFTINT_CLR, 64, do_wr_special, a, supervisor(dc), do_wrsoftint_clr) 29660faef01bSRichard Henderson 29670faef01bSRichard Henderson static void do_wrsoftint(DisasContext *dc, TCGv src) 29680faef01bSRichard Henderson { 29690faef01bSRichard Henderson gen_helper_write_softint(tcg_env, src); 29700faef01bSRichard Henderson } 29710faef01bSRichard Henderson 29720faef01bSRichard Henderson TRANS(WRSOFTINT, 64, do_wr_special, a, supervisor(dc), do_wrsoftint) 29730faef01bSRichard Henderson 29740faef01bSRichard Henderson static void do_wrtick_cmpr(DisasContext *dc, TCGv src) 29750faef01bSRichard Henderson { 29760faef01bSRichard Henderson TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 29770faef01bSRichard Henderson 2978577efa45SRichard Henderson tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(tick_cmpr)); 2979577efa45SRichard Henderson tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(tick)); 29800faef01bSRichard Henderson translator_io_start(&dc->base); 2981577efa45SRichard Henderson gen_helper_tick_set_limit(r_tickptr, src); 29820faef01bSRichard Henderson /* End TB to handle timer interrupt */ 29830faef01bSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 29840faef01bSRichard Henderson } 29850faef01bSRichard Henderson 29860faef01bSRichard Henderson TRANS(WRTICK_CMPR, 64, do_wr_special, a, supervisor(dc), do_wrtick_cmpr) 29870faef01bSRichard Henderson 29880faef01bSRichard Henderson static void do_wrstick(DisasContext *dc, TCGv src) 29890faef01bSRichard Henderson { 29900faef01bSRichard Henderson #ifdef TARGET_SPARC64 29910faef01bSRichard Henderson TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 29920faef01bSRichard Henderson 29930faef01bSRichard Henderson tcg_gen_ld_ptr(r_tickptr, tcg_env, offsetof(CPUSPARCState, stick)); 29940faef01bSRichard Henderson translator_io_start(&dc->base); 29950faef01bSRichard Henderson gen_helper_tick_set_count(r_tickptr, src); 29960faef01bSRichard Henderson /* End TB to handle timer interrupt */ 29970faef01bSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 29980faef01bSRichard Henderson #else 29990faef01bSRichard Henderson qemu_build_not_reached(); 30000faef01bSRichard Henderson #endif 30010faef01bSRichard Henderson } 30020faef01bSRichard Henderson 30030faef01bSRichard Henderson TRANS(WRSTICK, 64, do_wr_special, a, supervisor(dc), do_wrstick) 30040faef01bSRichard Henderson 30050faef01bSRichard Henderson static void do_wrstick_cmpr(DisasContext *dc, TCGv src) 30060faef01bSRichard Henderson { 30070faef01bSRichard Henderson TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 30080faef01bSRichard Henderson 3009577efa45SRichard Henderson tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(stick_cmpr)); 3010577efa45SRichard Henderson tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(stick)); 30110faef01bSRichard Henderson translator_io_start(&dc->base); 3012577efa45SRichard Henderson gen_helper_tick_set_limit(r_tickptr, src); 30130faef01bSRichard Henderson /* End TB to handle timer interrupt */ 30140faef01bSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 30150faef01bSRichard Henderson } 30160faef01bSRichard Henderson 30170faef01bSRichard Henderson TRANS(WRSTICK_CMPR, 64, do_wr_special, a, supervisor(dc), do_wrstick_cmpr) 30180faef01bSRichard Henderson 30190faef01bSRichard Henderson static void do_wrpowerdown(DisasContext *dc, TCGv src) 30200faef01bSRichard Henderson { 302189527e3aSRichard Henderson finishing_insn(dc); 30220faef01bSRichard Henderson save_state(dc); 30230faef01bSRichard Henderson gen_helper_power_down(tcg_env); 30240faef01bSRichard Henderson } 30250faef01bSRichard Henderson 30260faef01bSRichard Henderson TRANS(WRPOWERDOWN, POWERDOWN, do_wr_special, a, supervisor(dc), do_wrpowerdown) 30270faef01bSRichard Henderson 302825524734SRichard Henderson static void do_wrpsr(DisasContext *dc, TCGv src) 302925524734SRichard Henderson { 303025524734SRichard Henderson gen_helper_wrpsr(tcg_env, src); 303125524734SRichard Henderson dc->base.is_jmp = DISAS_EXIT; 303225524734SRichard Henderson } 303325524734SRichard Henderson 303425524734SRichard Henderson TRANS(WRPSR, 32, do_wr_special, a, supervisor(dc), do_wrpsr) 303525524734SRichard Henderson 30369422278eSRichard Henderson static void do_wrwim(DisasContext *dc, TCGv src) 30379422278eSRichard Henderson { 30389422278eSRichard Henderson target_ulong mask = MAKE_64BIT_MASK(0, dc->def->nwindows); 3039cd6269f7SRichard Henderson TCGv tmp = tcg_temp_new(); 3040cd6269f7SRichard Henderson 3041cd6269f7SRichard Henderson tcg_gen_andi_tl(tmp, src, mask); 3042cd6269f7SRichard Henderson tcg_gen_st_tl(tmp, tcg_env, env32_field_offsetof(wim)); 30439422278eSRichard Henderson } 30449422278eSRichard Henderson 30459422278eSRichard Henderson TRANS(WRWIM, 32, do_wr_special, a, supervisor(dc), do_wrwim) 30469422278eSRichard Henderson 30479422278eSRichard Henderson static void do_wrtpc(DisasContext *dc, TCGv src) 30489422278eSRichard Henderson { 30499422278eSRichard Henderson #ifdef TARGET_SPARC64 30509422278eSRichard Henderson TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 30519422278eSRichard Henderson 30529422278eSRichard Henderson gen_load_trap_state_at_tl(r_tsptr); 30539422278eSRichard Henderson tcg_gen_st_tl(src, r_tsptr, offsetof(trap_state, tpc)); 30549422278eSRichard Henderson #else 30559422278eSRichard Henderson qemu_build_not_reached(); 30569422278eSRichard Henderson #endif 30579422278eSRichard Henderson } 30589422278eSRichard Henderson 30599422278eSRichard Henderson TRANS(WRPR_tpc, 64, do_wr_special, a, supervisor(dc), do_wrtpc) 30609422278eSRichard Henderson 30619422278eSRichard Henderson static void do_wrtnpc(DisasContext *dc, TCGv src) 30629422278eSRichard Henderson { 30639422278eSRichard Henderson #ifdef TARGET_SPARC64 30649422278eSRichard Henderson TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 30659422278eSRichard Henderson 30669422278eSRichard Henderson gen_load_trap_state_at_tl(r_tsptr); 30679422278eSRichard Henderson tcg_gen_st_tl(src, r_tsptr, offsetof(trap_state, tnpc)); 30689422278eSRichard Henderson #else 30699422278eSRichard Henderson qemu_build_not_reached(); 30709422278eSRichard Henderson #endif 30719422278eSRichard Henderson } 30729422278eSRichard Henderson 30739422278eSRichard Henderson TRANS(WRPR_tnpc, 64, do_wr_special, a, supervisor(dc), do_wrtnpc) 30749422278eSRichard Henderson 30759422278eSRichard Henderson static void do_wrtstate(DisasContext *dc, TCGv src) 30769422278eSRichard Henderson { 30779422278eSRichard Henderson #ifdef TARGET_SPARC64 30789422278eSRichard Henderson TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 30799422278eSRichard Henderson 30809422278eSRichard Henderson gen_load_trap_state_at_tl(r_tsptr); 30819422278eSRichard Henderson tcg_gen_st_tl(src, r_tsptr, offsetof(trap_state, tstate)); 30829422278eSRichard Henderson #else 30839422278eSRichard Henderson qemu_build_not_reached(); 30849422278eSRichard Henderson #endif 30859422278eSRichard Henderson } 30869422278eSRichard Henderson 30879422278eSRichard Henderson TRANS(WRPR_tstate, 64, do_wr_special, a, supervisor(dc), do_wrtstate) 30889422278eSRichard Henderson 30899422278eSRichard Henderson static void do_wrtt(DisasContext *dc, TCGv src) 30909422278eSRichard Henderson { 30919422278eSRichard Henderson #ifdef TARGET_SPARC64 30929422278eSRichard Henderson TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 30939422278eSRichard Henderson 30949422278eSRichard Henderson gen_load_trap_state_at_tl(r_tsptr); 30959422278eSRichard Henderson tcg_gen_st32_tl(src, r_tsptr, offsetof(trap_state, tt)); 30969422278eSRichard Henderson #else 30979422278eSRichard Henderson qemu_build_not_reached(); 30989422278eSRichard Henderson #endif 30999422278eSRichard Henderson } 31009422278eSRichard Henderson 31019422278eSRichard Henderson TRANS(WRPR_tt, 64, do_wr_special, a, supervisor(dc), do_wrtt) 31029422278eSRichard Henderson 31039422278eSRichard Henderson static void do_wrtick(DisasContext *dc, TCGv src) 31049422278eSRichard Henderson { 31059422278eSRichard Henderson TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 31069422278eSRichard Henderson 31079422278eSRichard Henderson tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(tick)); 31089422278eSRichard Henderson translator_io_start(&dc->base); 31099422278eSRichard Henderson gen_helper_tick_set_count(r_tickptr, src); 31109422278eSRichard Henderson /* End TB to handle timer interrupt */ 31119422278eSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 31129422278eSRichard Henderson } 31139422278eSRichard Henderson 31149422278eSRichard Henderson TRANS(WRPR_tick, 64, do_wr_special, a, supervisor(dc), do_wrtick) 31159422278eSRichard Henderson 31169422278eSRichard Henderson static void do_wrtba(DisasContext *dc, TCGv src) 31179422278eSRichard Henderson { 31189422278eSRichard Henderson tcg_gen_mov_tl(cpu_tbr, src); 31199422278eSRichard Henderson } 31209422278eSRichard Henderson 31219422278eSRichard Henderson TRANS(WRPR_tba, 64, do_wr_special, a, supervisor(dc), do_wrtba) 31229422278eSRichard Henderson 31239422278eSRichard Henderson static void do_wrpstate(DisasContext *dc, TCGv src) 31249422278eSRichard Henderson { 31259422278eSRichard Henderson save_state(dc); 31269422278eSRichard Henderson if (translator_io_start(&dc->base)) { 31279422278eSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 31289422278eSRichard Henderson } 31299422278eSRichard Henderson gen_helper_wrpstate(tcg_env, src); 31309422278eSRichard Henderson dc->npc = DYNAMIC_PC; 31319422278eSRichard Henderson } 31329422278eSRichard Henderson 31339422278eSRichard Henderson TRANS(WRPR_pstate, 64, do_wr_special, a, supervisor(dc), do_wrpstate) 31349422278eSRichard Henderson 31359422278eSRichard Henderson static void do_wrtl(DisasContext *dc, TCGv src) 31369422278eSRichard Henderson { 31379422278eSRichard Henderson save_state(dc); 31389422278eSRichard Henderson tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(tl)); 31399422278eSRichard Henderson dc->npc = DYNAMIC_PC; 31409422278eSRichard Henderson } 31419422278eSRichard Henderson 31429422278eSRichard Henderson TRANS(WRPR_tl, 64, do_wr_special, a, supervisor(dc), do_wrtl) 31439422278eSRichard Henderson 31449422278eSRichard Henderson static void do_wrpil(DisasContext *dc, TCGv src) 31459422278eSRichard Henderson { 31469422278eSRichard Henderson if (translator_io_start(&dc->base)) { 31479422278eSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 31489422278eSRichard Henderson } 31499422278eSRichard Henderson gen_helper_wrpil(tcg_env, src); 31509422278eSRichard Henderson } 31519422278eSRichard Henderson 31529422278eSRichard Henderson TRANS(WRPR_pil, 64, do_wr_special, a, supervisor(dc), do_wrpil) 31539422278eSRichard Henderson 31549422278eSRichard Henderson static void do_wrcwp(DisasContext *dc, TCGv src) 31559422278eSRichard Henderson { 31569422278eSRichard Henderson gen_helper_wrcwp(tcg_env, src); 31579422278eSRichard Henderson } 31589422278eSRichard Henderson 31599422278eSRichard Henderson TRANS(WRPR_cwp, 64, do_wr_special, a, supervisor(dc), do_wrcwp) 31609422278eSRichard Henderson 31619422278eSRichard Henderson static void do_wrcansave(DisasContext *dc, TCGv src) 31629422278eSRichard Henderson { 31639422278eSRichard Henderson tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(cansave)); 31649422278eSRichard Henderson } 31659422278eSRichard Henderson 31669422278eSRichard Henderson TRANS(WRPR_cansave, 64, do_wr_special, a, supervisor(dc), do_wrcansave) 31679422278eSRichard Henderson 31689422278eSRichard Henderson static void do_wrcanrestore(DisasContext *dc, TCGv src) 31699422278eSRichard Henderson { 31709422278eSRichard Henderson tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(canrestore)); 31719422278eSRichard Henderson } 31729422278eSRichard Henderson 31739422278eSRichard Henderson TRANS(WRPR_canrestore, 64, do_wr_special, a, supervisor(dc), do_wrcanrestore) 31749422278eSRichard Henderson 31759422278eSRichard Henderson static void do_wrcleanwin(DisasContext *dc, TCGv src) 31769422278eSRichard Henderson { 31779422278eSRichard Henderson tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(cleanwin)); 31789422278eSRichard Henderson } 31799422278eSRichard Henderson 31809422278eSRichard Henderson TRANS(WRPR_cleanwin, 64, do_wr_special, a, supervisor(dc), do_wrcleanwin) 31819422278eSRichard Henderson 31829422278eSRichard Henderson static void do_wrotherwin(DisasContext *dc, TCGv src) 31839422278eSRichard Henderson { 31849422278eSRichard Henderson tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(otherwin)); 31859422278eSRichard Henderson } 31869422278eSRichard Henderson 31879422278eSRichard Henderson TRANS(WRPR_otherwin, 64, do_wr_special, a, supervisor(dc), do_wrotherwin) 31889422278eSRichard Henderson 31899422278eSRichard Henderson static void do_wrwstate(DisasContext *dc, TCGv src) 31909422278eSRichard Henderson { 31919422278eSRichard Henderson tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(wstate)); 31929422278eSRichard Henderson } 31939422278eSRichard Henderson 31949422278eSRichard Henderson TRANS(WRPR_wstate, 64, do_wr_special, a, supervisor(dc), do_wrwstate) 31959422278eSRichard Henderson 31969422278eSRichard Henderson static void do_wrgl(DisasContext *dc, TCGv src) 31979422278eSRichard Henderson { 31989422278eSRichard Henderson gen_helper_wrgl(tcg_env, src); 31999422278eSRichard Henderson } 32009422278eSRichard Henderson 32019422278eSRichard Henderson TRANS(WRPR_gl, GL, do_wr_special, a, supervisor(dc), do_wrgl) 32029422278eSRichard Henderson 32039422278eSRichard Henderson /* UA2005 strand status */ 32049422278eSRichard Henderson static void do_wrssr(DisasContext *dc, TCGv src) 32059422278eSRichard Henderson { 32062da789deSRichard Henderson tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(ssr)); 32079422278eSRichard Henderson } 32089422278eSRichard Henderson 32099422278eSRichard Henderson TRANS(WRPR_strand_status, HYPV, do_wr_special, a, hypervisor(dc), do_wrssr) 32109422278eSRichard Henderson 3211bb97f2f5SRichard Henderson TRANS(WRTBR, 32, do_wr_special, a, supervisor(dc), do_wrtba) 3212bb97f2f5SRichard Henderson 3213bb97f2f5SRichard Henderson static void do_wrhpstate(DisasContext *dc, TCGv src) 3214bb97f2f5SRichard Henderson { 3215bb97f2f5SRichard Henderson tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(hpstate)); 3216bb97f2f5SRichard Henderson dc->base.is_jmp = DISAS_EXIT; 3217bb97f2f5SRichard Henderson } 3218bb97f2f5SRichard Henderson 3219bb97f2f5SRichard Henderson TRANS(WRHPR_hpstate, HYPV, do_wr_special, a, hypervisor(dc), do_wrhpstate) 3220bb97f2f5SRichard Henderson 3221bb97f2f5SRichard Henderson static void do_wrhtstate(DisasContext *dc, TCGv src) 3222bb97f2f5SRichard Henderson { 3223bb97f2f5SRichard Henderson TCGv_i32 tl = tcg_temp_new_i32(); 3224bb97f2f5SRichard Henderson TCGv_ptr tp = tcg_temp_new_ptr(); 3225bb97f2f5SRichard Henderson 3226bb97f2f5SRichard Henderson tcg_gen_ld_i32(tl, tcg_env, env64_field_offsetof(tl)); 3227bb97f2f5SRichard Henderson tcg_gen_andi_i32(tl, tl, MAXTL_MASK); 3228bb97f2f5SRichard Henderson tcg_gen_shli_i32(tl, tl, 3); 3229bb97f2f5SRichard Henderson tcg_gen_ext_i32_ptr(tp, tl); 3230bb97f2f5SRichard Henderson tcg_gen_add_ptr(tp, tp, tcg_env); 3231bb97f2f5SRichard Henderson 3232bb97f2f5SRichard Henderson tcg_gen_st_tl(src, tp, env64_field_offsetof(htstate)); 3233bb97f2f5SRichard Henderson } 3234bb97f2f5SRichard Henderson 3235bb97f2f5SRichard Henderson TRANS(WRHPR_htstate, HYPV, do_wr_special, a, hypervisor(dc), do_wrhtstate) 3236bb97f2f5SRichard Henderson 3237bb97f2f5SRichard Henderson static void do_wrhintp(DisasContext *dc, TCGv src) 3238bb97f2f5SRichard Henderson { 32392da789deSRichard Henderson tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(hintp)); 3240bb97f2f5SRichard Henderson } 3241bb97f2f5SRichard Henderson 3242bb97f2f5SRichard Henderson TRANS(WRHPR_hintp, HYPV, do_wr_special, a, hypervisor(dc), do_wrhintp) 3243bb97f2f5SRichard Henderson 3244bb97f2f5SRichard Henderson static void do_wrhtba(DisasContext *dc, TCGv src) 3245bb97f2f5SRichard Henderson { 32462da789deSRichard Henderson tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(htba)); 3247bb97f2f5SRichard Henderson } 3248bb97f2f5SRichard Henderson 3249bb97f2f5SRichard Henderson TRANS(WRHPR_htba, HYPV, do_wr_special, a, hypervisor(dc), do_wrhtba) 3250bb97f2f5SRichard Henderson 3251bb97f2f5SRichard Henderson static void do_wrhstick_cmpr(DisasContext *dc, TCGv src) 3252bb97f2f5SRichard Henderson { 3253bb97f2f5SRichard Henderson TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 3254bb97f2f5SRichard Henderson 3255577efa45SRichard Henderson tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(hstick_cmpr)); 3256bb97f2f5SRichard Henderson tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(hstick)); 3257bb97f2f5SRichard Henderson translator_io_start(&dc->base); 3258577efa45SRichard Henderson gen_helper_tick_set_limit(r_tickptr, src); 3259bb97f2f5SRichard Henderson /* End TB to handle timer interrupt */ 3260bb97f2f5SRichard Henderson dc->base.is_jmp = DISAS_EXIT; 3261bb97f2f5SRichard Henderson } 3262bb97f2f5SRichard Henderson 3263bb97f2f5SRichard Henderson TRANS(WRHPR_hstick_cmpr, HYPV, do_wr_special, a, hypervisor(dc), 3264bb97f2f5SRichard Henderson do_wrhstick_cmpr) 3265bb97f2f5SRichard Henderson 326625524734SRichard Henderson static bool do_saved_restored(DisasContext *dc, bool saved) 326725524734SRichard Henderson { 326825524734SRichard Henderson if (!supervisor(dc)) { 326925524734SRichard Henderson return raise_priv(dc); 327025524734SRichard Henderson } 327125524734SRichard Henderson if (saved) { 327225524734SRichard Henderson gen_helper_saved(tcg_env); 327325524734SRichard Henderson } else { 327425524734SRichard Henderson gen_helper_restored(tcg_env); 327525524734SRichard Henderson } 327625524734SRichard Henderson return advance_pc(dc); 327725524734SRichard Henderson } 327825524734SRichard Henderson 327925524734SRichard Henderson TRANS(SAVED, 64, do_saved_restored, true) 328025524734SRichard Henderson TRANS(RESTORED, 64, do_saved_restored, false) 328125524734SRichard Henderson 3282d3825800SRichard Henderson static bool trans_NOP(DisasContext *dc, arg_NOP *a) 3283d3825800SRichard Henderson { 3284d3825800SRichard Henderson return advance_pc(dc); 3285d3825800SRichard Henderson } 3286d3825800SRichard Henderson 32870faef01bSRichard Henderson /* 32880faef01bSRichard Henderson * TODO: Need a feature bit for sparcv8. 32890faef01bSRichard Henderson * In the meantime, treat all 32-bit cpus like sparcv7. 32900faef01bSRichard Henderson */ 32915458fd31SRichard Henderson TRANS(NOP_v7, 32, trans_NOP, a) 32925458fd31SRichard Henderson TRANS(NOP_v9, 64, trans_NOP, a) 32930faef01bSRichard Henderson 3294b597eedcSRichard Henderson static bool do_arith_int(DisasContext *dc, arg_r_r_ri_cc *a, 3295428881deSRichard Henderson void (*func)(TCGv, TCGv, TCGv), 32962a45b736SRichard Henderson void (*funci)(TCGv, TCGv, target_long), 32972a45b736SRichard Henderson bool logic_cc) 3298428881deSRichard Henderson { 3299428881deSRichard Henderson TCGv dst, src1; 3300428881deSRichard Henderson 3301428881deSRichard Henderson /* For simplicity, we under-decoded the rs2 form. */ 3302428881deSRichard Henderson if (!a->imm && a->rs2_or_imm & ~0x1f) { 3303428881deSRichard Henderson return false; 3304428881deSRichard Henderson } 3305428881deSRichard Henderson 33062a45b736SRichard Henderson if (logic_cc) { 33072a45b736SRichard Henderson dst = cpu_cc_N; 3308428881deSRichard Henderson } else { 3309428881deSRichard Henderson dst = gen_dest_gpr(dc, a->rd); 3310428881deSRichard Henderson } 3311428881deSRichard Henderson src1 = gen_load_gpr(dc, a->rs1); 3312428881deSRichard Henderson 3313428881deSRichard Henderson if (a->imm || a->rs2_or_imm == 0) { 3314428881deSRichard Henderson if (funci) { 3315428881deSRichard Henderson funci(dst, src1, a->rs2_or_imm); 3316428881deSRichard Henderson } else { 3317428881deSRichard Henderson func(dst, src1, tcg_constant_tl(a->rs2_or_imm)); 3318428881deSRichard Henderson } 3319428881deSRichard Henderson } else { 3320428881deSRichard Henderson func(dst, src1, cpu_regs[a->rs2_or_imm]); 3321428881deSRichard Henderson } 33222a45b736SRichard Henderson 33232a45b736SRichard Henderson if (logic_cc) { 33242a45b736SRichard Henderson if (TARGET_LONG_BITS == 64) { 33252a45b736SRichard Henderson tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N); 33262a45b736SRichard Henderson tcg_gen_movi_tl(cpu_icc_C, 0); 33272a45b736SRichard Henderson } 33282a45b736SRichard Henderson tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N); 33292a45b736SRichard Henderson tcg_gen_movi_tl(cpu_cc_C, 0); 33302a45b736SRichard Henderson tcg_gen_movi_tl(cpu_cc_V, 0); 33312a45b736SRichard Henderson } 33322a45b736SRichard Henderson 3333428881deSRichard Henderson gen_store_gpr(dc, a->rd, dst); 3334428881deSRichard Henderson return advance_pc(dc); 3335428881deSRichard Henderson } 3336428881deSRichard Henderson 3337b597eedcSRichard Henderson static bool do_arith(DisasContext *dc, arg_r_r_ri_cc *a, 3338428881deSRichard Henderson void (*func)(TCGv, TCGv, TCGv), 3339428881deSRichard Henderson void (*funci)(TCGv, TCGv, target_long), 3340428881deSRichard Henderson void (*func_cc)(TCGv, TCGv, TCGv)) 3341428881deSRichard Henderson { 3342428881deSRichard Henderson if (a->cc) { 3343b597eedcSRichard Henderson return do_arith_int(dc, a, func_cc, NULL, false); 3344428881deSRichard Henderson } 3345b597eedcSRichard Henderson return do_arith_int(dc, a, func, funci, false); 3346428881deSRichard Henderson } 3347428881deSRichard Henderson 3348428881deSRichard Henderson static bool do_logic(DisasContext *dc, arg_r_r_ri_cc *a, 3349428881deSRichard Henderson void (*func)(TCGv, TCGv, TCGv), 3350428881deSRichard Henderson void (*funci)(TCGv, TCGv, target_long)) 3351428881deSRichard Henderson { 3352b597eedcSRichard Henderson return do_arith_int(dc, a, func, funci, a->cc); 3353428881deSRichard Henderson } 3354428881deSRichard Henderson 3355b597eedcSRichard Henderson TRANS(ADD, ALL, do_arith, a, tcg_gen_add_tl, tcg_gen_addi_tl, gen_op_addcc) 3356b597eedcSRichard Henderson TRANS(SUB, ALL, do_arith, a, tcg_gen_sub_tl, tcg_gen_subi_tl, gen_op_subcc) 3357b597eedcSRichard Henderson TRANS(ADDC, ALL, do_arith, a, gen_op_addc, NULL, gen_op_addccc) 3358b597eedcSRichard Henderson TRANS(SUBC, ALL, do_arith, a, gen_op_subc, NULL, gen_op_subccc) 3359428881deSRichard Henderson 3360b597eedcSRichard Henderson TRANS(TADDcc, ALL, do_arith, a, NULL, NULL, gen_op_taddcc) 3361b597eedcSRichard Henderson TRANS(TSUBcc, ALL, do_arith, a, NULL, NULL, gen_op_tsubcc) 3362b597eedcSRichard Henderson TRANS(TADDccTV, ALL, do_arith, a, NULL, NULL, gen_op_taddcctv) 3363b597eedcSRichard Henderson TRANS(TSUBccTV, ALL, do_arith, a, NULL, NULL, gen_op_tsubcctv) 3364a9aba13dSRichard Henderson 3365428881deSRichard Henderson TRANS(AND, ALL, do_logic, a, tcg_gen_and_tl, tcg_gen_andi_tl) 3366428881deSRichard Henderson TRANS(XOR, ALL, do_logic, a, tcg_gen_xor_tl, tcg_gen_xori_tl) 3367428881deSRichard Henderson TRANS(ANDN, ALL, do_logic, a, tcg_gen_andc_tl, NULL) 3368428881deSRichard Henderson TRANS(ORN, ALL, do_logic, a, tcg_gen_orc_tl, NULL) 3369428881deSRichard Henderson TRANS(XORN, ALL, do_logic, a, tcg_gen_eqv_tl, NULL) 3370428881deSRichard Henderson 3371b597eedcSRichard Henderson TRANS(MULX, 64, do_arith, a, tcg_gen_mul_tl, tcg_gen_muli_tl, NULL) 3372b5372650SRichard Henderson TRANS(UMUL, MUL, do_logic, a, gen_op_umul, NULL) 3373b5372650SRichard Henderson TRANS(SMUL, MUL, do_logic, a, gen_op_smul, NULL) 3374b597eedcSRichard Henderson TRANS(MULScc, ALL, do_arith, a, NULL, NULL, gen_op_mulscc) 337522188d7dSRichard Henderson 33763a6b8de3SRichard Henderson TRANS(UDIVcc, DIV, do_arith, a, NULL, NULL, gen_op_udivcc) 3377b597eedcSRichard Henderson TRANS(SDIV, DIV, do_arith, a, gen_op_sdiv, NULL, gen_op_sdivcc) 33784ee85ea9SRichard Henderson 33799c6ec5bcSRichard Henderson /* TODO: Should have feature bit -- comes in with UltraSparc T2. */ 3380b597eedcSRichard Henderson TRANS(POPC, 64, do_arith, a, gen_op_popc, NULL, NULL) 33819c6ec5bcSRichard Henderson 3382428881deSRichard Henderson static bool trans_OR(DisasContext *dc, arg_r_r_ri_cc *a) 3383428881deSRichard Henderson { 3384428881deSRichard Henderson /* OR with %g0 is the canonical alias for MOV. */ 3385428881deSRichard Henderson if (!a->cc && a->rs1 == 0) { 3386428881deSRichard Henderson if (a->imm || a->rs2_or_imm == 0) { 3387428881deSRichard Henderson gen_store_gpr(dc, a->rd, tcg_constant_tl(a->rs2_or_imm)); 3388428881deSRichard Henderson } else if (a->rs2_or_imm & ~0x1f) { 3389428881deSRichard Henderson /* For simplicity, we under-decoded the rs2 form. */ 3390428881deSRichard Henderson return false; 3391428881deSRichard Henderson } else { 3392428881deSRichard Henderson gen_store_gpr(dc, a->rd, cpu_regs[a->rs2_or_imm]); 3393428881deSRichard Henderson } 3394428881deSRichard Henderson return advance_pc(dc); 3395428881deSRichard Henderson } 3396428881deSRichard Henderson return do_logic(dc, a, tcg_gen_or_tl, tcg_gen_ori_tl); 3397428881deSRichard Henderson } 3398428881deSRichard Henderson 33993a6b8de3SRichard Henderson static bool trans_UDIV(DisasContext *dc, arg_r_r_ri *a) 34003a6b8de3SRichard Henderson { 34013a6b8de3SRichard Henderson TCGv_i64 t1, t2; 34023a6b8de3SRichard Henderson TCGv dst; 34033a6b8de3SRichard Henderson 34043a6b8de3SRichard Henderson if (!avail_DIV(dc)) { 34053a6b8de3SRichard Henderson return false; 34063a6b8de3SRichard Henderson } 34073a6b8de3SRichard Henderson /* For simplicity, we under-decoded the rs2 form. */ 34083a6b8de3SRichard Henderson if (!a->imm && a->rs2_or_imm & ~0x1f) { 34093a6b8de3SRichard Henderson return false; 34103a6b8de3SRichard Henderson } 34113a6b8de3SRichard Henderson 34123a6b8de3SRichard Henderson if (unlikely(a->rs2_or_imm == 0)) { 34133a6b8de3SRichard Henderson gen_exception(dc, TT_DIV_ZERO); 34143a6b8de3SRichard Henderson return true; 34153a6b8de3SRichard Henderson } 34163a6b8de3SRichard Henderson 34173a6b8de3SRichard Henderson if (a->imm) { 34183a6b8de3SRichard Henderson t2 = tcg_constant_i64((uint32_t)a->rs2_or_imm); 34193a6b8de3SRichard Henderson } else { 34203a6b8de3SRichard Henderson TCGLabel *lab; 34213a6b8de3SRichard Henderson TCGv_i32 n2; 34223a6b8de3SRichard Henderson 34233a6b8de3SRichard Henderson finishing_insn(dc); 34243a6b8de3SRichard Henderson flush_cond(dc); 34253a6b8de3SRichard Henderson 34263a6b8de3SRichard Henderson n2 = tcg_temp_new_i32(); 34273a6b8de3SRichard Henderson tcg_gen_trunc_tl_i32(n2, cpu_regs[a->rs2_or_imm]); 34283a6b8de3SRichard Henderson 34293a6b8de3SRichard Henderson lab = delay_exception(dc, TT_DIV_ZERO); 34303a6b8de3SRichard Henderson tcg_gen_brcondi_i32(TCG_COND_EQ, n2, 0, lab); 34313a6b8de3SRichard Henderson 34323a6b8de3SRichard Henderson t2 = tcg_temp_new_i64(); 34333a6b8de3SRichard Henderson #ifdef TARGET_SPARC64 34343a6b8de3SRichard Henderson tcg_gen_ext32u_i64(t2, cpu_regs[a->rs2_or_imm]); 34353a6b8de3SRichard Henderson #else 34363a6b8de3SRichard Henderson tcg_gen_extu_i32_i64(t2, cpu_regs[a->rs2_or_imm]); 34373a6b8de3SRichard Henderson #endif 34383a6b8de3SRichard Henderson } 34393a6b8de3SRichard Henderson 34403a6b8de3SRichard Henderson t1 = tcg_temp_new_i64(); 34413a6b8de3SRichard Henderson tcg_gen_concat_tl_i64(t1, gen_load_gpr(dc, a->rs1), cpu_y); 34423a6b8de3SRichard Henderson 34433a6b8de3SRichard Henderson tcg_gen_divu_i64(t1, t1, t2); 34443a6b8de3SRichard Henderson tcg_gen_umin_i64(t1, t1, tcg_constant_i64(UINT32_MAX)); 34453a6b8de3SRichard Henderson 34463a6b8de3SRichard Henderson dst = gen_dest_gpr(dc, a->rd); 34473a6b8de3SRichard Henderson tcg_gen_trunc_i64_tl(dst, t1); 34483a6b8de3SRichard Henderson gen_store_gpr(dc, a->rd, dst); 34493a6b8de3SRichard Henderson return advance_pc(dc); 34503a6b8de3SRichard Henderson } 34513a6b8de3SRichard Henderson 3452f3141174SRichard Henderson static bool trans_UDIVX(DisasContext *dc, arg_r_r_ri *a) 3453f3141174SRichard Henderson { 3454f3141174SRichard Henderson TCGv dst, src1, src2; 3455f3141174SRichard Henderson 3456f3141174SRichard Henderson if (!avail_64(dc)) { 3457f3141174SRichard Henderson return false; 3458f3141174SRichard Henderson } 3459f3141174SRichard Henderson /* For simplicity, we under-decoded the rs2 form. */ 3460f3141174SRichard Henderson if (!a->imm && a->rs2_or_imm & ~0x1f) { 3461f3141174SRichard Henderson return false; 3462f3141174SRichard Henderson } 3463f3141174SRichard Henderson 3464f3141174SRichard Henderson if (unlikely(a->rs2_or_imm == 0)) { 3465f3141174SRichard Henderson gen_exception(dc, TT_DIV_ZERO); 3466f3141174SRichard Henderson return true; 3467f3141174SRichard Henderson } 3468f3141174SRichard Henderson 3469f3141174SRichard Henderson if (a->imm) { 3470f3141174SRichard Henderson src2 = tcg_constant_tl(a->rs2_or_imm); 3471f3141174SRichard Henderson } else { 3472f3141174SRichard Henderson TCGLabel *lab; 3473f3141174SRichard Henderson 3474f3141174SRichard Henderson finishing_insn(dc); 3475f3141174SRichard Henderson flush_cond(dc); 3476f3141174SRichard Henderson 3477f3141174SRichard Henderson lab = delay_exception(dc, TT_DIV_ZERO); 3478f3141174SRichard Henderson src2 = cpu_regs[a->rs2_or_imm]; 3479f3141174SRichard Henderson tcg_gen_brcondi_tl(TCG_COND_EQ, src2, 0, lab); 3480f3141174SRichard Henderson } 3481f3141174SRichard Henderson 3482f3141174SRichard Henderson dst = gen_dest_gpr(dc, a->rd); 3483f3141174SRichard Henderson src1 = gen_load_gpr(dc, a->rs1); 3484f3141174SRichard Henderson 3485f3141174SRichard Henderson tcg_gen_divu_tl(dst, src1, src2); 3486f3141174SRichard Henderson gen_store_gpr(dc, a->rd, dst); 3487f3141174SRichard Henderson return advance_pc(dc); 3488f3141174SRichard Henderson } 3489f3141174SRichard Henderson 3490f3141174SRichard Henderson static bool trans_SDIVX(DisasContext *dc, arg_r_r_ri *a) 3491f3141174SRichard Henderson { 3492f3141174SRichard Henderson TCGv dst, src1, src2; 3493f3141174SRichard Henderson 3494f3141174SRichard Henderson if (!avail_64(dc)) { 3495f3141174SRichard Henderson return false; 3496f3141174SRichard Henderson } 3497f3141174SRichard Henderson /* For simplicity, we under-decoded the rs2 form. */ 3498f3141174SRichard Henderson if (!a->imm && a->rs2_or_imm & ~0x1f) { 3499f3141174SRichard Henderson return false; 3500f3141174SRichard Henderson } 3501f3141174SRichard Henderson 3502f3141174SRichard Henderson if (unlikely(a->rs2_or_imm == 0)) { 3503f3141174SRichard Henderson gen_exception(dc, TT_DIV_ZERO); 3504f3141174SRichard Henderson return true; 3505f3141174SRichard Henderson } 3506f3141174SRichard Henderson 3507f3141174SRichard Henderson dst = gen_dest_gpr(dc, a->rd); 3508f3141174SRichard Henderson src1 = gen_load_gpr(dc, a->rs1); 3509f3141174SRichard Henderson 3510f3141174SRichard Henderson if (a->imm) { 3511f3141174SRichard Henderson if (unlikely(a->rs2_or_imm == -1)) { 3512f3141174SRichard Henderson tcg_gen_neg_tl(dst, src1); 3513f3141174SRichard Henderson gen_store_gpr(dc, a->rd, dst); 3514f3141174SRichard Henderson return advance_pc(dc); 3515f3141174SRichard Henderson } 3516f3141174SRichard Henderson src2 = tcg_constant_tl(a->rs2_or_imm); 3517f3141174SRichard Henderson } else { 3518f3141174SRichard Henderson TCGLabel *lab; 3519f3141174SRichard Henderson TCGv t1, t2; 3520f3141174SRichard Henderson 3521f3141174SRichard Henderson finishing_insn(dc); 3522f3141174SRichard Henderson flush_cond(dc); 3523f3141174SRichard Henderson 3524f3141174SRichard Henderson lab = delay_exception(dc, TT_DIV_ZERO); 3525f3141174SRichard Henderson src2 = cpu_regs[a->rs2_or_imm]; 3526f3141174SRichard Henderson tcg_gen_brcondi_tl(TCG_COND_EQ, src2, 0, lab); 3527f3141174SRichard Henderson 3528f3141174SRichard Henderson /* 3529f3141174SRichard Henderson * Need to avoid INT64_MIN / -1, which will trap on x86 host. 3530f3141174SRichard Henderson * Set SRC2 to 1 as a new divisor, to produce the correct result. 3531f3141174SRichard Henderson */ 3532f3141174SRichard Henderson t1 = tcg_temp_new(); 3533f3141174SRichard Henderson t2 = tcg_temp_new(); 3534f3141174SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_EQ, t1, src1, (target_long)INT64_MIN); 3535f3141174SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_EQ, t2, src2, -1); 3536f3141174SRichard Henderson tcg_gen_and_tl(t1, t1, t2); 3537f3141174SRichard Henderson tcg_gen_movcond_tl(TCG_COND_NE, t1, t1, tcg_constant_tl(0), 3538f3141174SRichard Henderson tcg_constant_tl(1), src2); 3539f3141174SRichard Henderson src2 = t1; 3540f3141174SRichard Henderson } 3541f3141174SRichard Henderson 3542f3141174SRichard Henderson tcg_gen_div_tl(dst, src1, src2); 3543f3141174SRichard Henderson gen_store_gpr(dc, a->rd, dst); 3544f3141174SRichard Henderson return advance_pc(dc); 3545f3141174SRichard Henderson } 3546f3141174SRichard Henderson 3547b88ce6f2SRichard Henderson static bool gen_edge(DisasContext *dc, arg_r_r_r *a, 354843db5838SRichard Henderson int width, bool cc, bool little_endian) 3549b88ce6f2SRichard Henderson { 355043db5838SRichard Henderson TCGv dst, s1, s2, l, r, t, m; 355143db5838SRichard Henderson uint64_t amask = address_mask_i(dc, -8); 3552b88ce6f2SRichard Henderson 3553b88ce6f2SRichard Henderson dst = gen_dest_gpr(dc, a->rd); 3554b88ce6f2SRichard Henderson s1 = gen_load_gpr(dc, a->rs1); 3555b88ce6f2SRichard Henderson s2 = gen_load_gpr(dc, a->rs2); 3556b88ce6f2SRichard Henderson 3557b88ce6f2SRichard Henderson if (cc) { 3558f828df74SRichard Henderson gen_op_subcc(cpu_cc_N, s1, s2); 3559b88ce6f2SRichard Henderson } 3560b88ce6f2SRichard Henderson 356143db5838SRichard Henderson l = tcg_temp_new(); 356243db5838SRichard Henderson r = tcg_temp_new(); 356343db5838SRichard Henderson t = tcg_temp_new(); 356443db5838SRichard Henderson 3565b88ce6f2SRichard Henderson switch (width) { 3566b88ce6f2SRichard Henderson case 8: 356743db5838SRichard Henderson tcg_gen_andi_tl(l, s1, 7); 356843db5838SRichard Henderson tcg_gen_andi_tl(r, s2, 7); 356943db5838SRichard Henderson tcg_gen_xori_tl(r, r, 7); 357043db5838SRichard Henderson m = tcg_constant_tl(0xff); 3571b88ce6f2SRichard Henderson break; 3572b88ce6f2SRichard Henderson case 16: 357343db5838SRichard Henderson tcg_gen_extract_tl(l, s1, 1, 2); 357443db5838SRichard Henderson tcg_gen_extract_tl(r, s2, 1, 2); 357543db5838SRichard Henderson tcg_gen_xori_tl(r, r, 3); 357643db5838SRichard Henderson m = tcg_constant_tl(0xf); 3577b88ce6f2SRichard Henderson break; 3578b88ce6f2SRichard Henderson case 32: 357943db5838SRichard Henderson tcg_gen_extract_tl(l, s1, 2, 1); 358043db5838SRichard Henderson tcg_gen_extract_tl(r, s2, 2, 1); 358143db5838SRichard Henderson tcg_gen_xori_tl(r, r, 1); 358243db5838SRichard Henderson m = tcg_constant_tl(0x3); 3583b88ce6f2SRichard Henderson break; 3584b88ce6f2SRichard Henderson default: 3585b88ce6f2SRichard Henderson abort(); 3586b88ce6f2SRichard Henderson } 3587b88ce6f2SRichard Henderson 358843db5838SRichard Henderson /* Compute Left Edge */ 358943db5838SRichard Henderson if (little_endian) { 359043db5838SRichard Henderson tcg_gen_shl_tl(l, m, l); 359143db5838SRichard Henderson tcg_gen_and_tl(l, l, m); 359243db5838SRichard Henderson } else { 359343db5838SRichard Henderson tcg_gen_shr_tl(l, m, l); 359443db5838SRichard Henderson } 359543db5838SRichard Henderson /* Compute Right Edge */ 359643db5838SRichard Henderson if (little_endian) { 359743db5838SRichard Henderson tcg_gen_shr_tl(r, m, r); 359843db5838SRichard Henderson } else { 359943db5838SRichard Henderson tcg_gen_shl_tl(r, m, r); 360043db5838SRichard Henderson tcg_gen_and_tl(r, r, m); 360143db5838SRichard Henderson } 3602b88ce6f2SRichard Henderson 360343db5838SRichard Henderson /* Compute dst = (s1 == s2 under amask ? l : l & r) */ 360443db5838SRichard Henderson tcg_gen_xor_tl(t, s1, s2); 360543db5838SRichard Henderson tcg_gen_and_tl(r, r, l); 360643db5838SRichard Henderson tcg_gen_movcond_tl(TCG_COND_TSTEQ, dst, t, tcg_constant_tl(amask), r, l); 3607b88ce6f2SRichard Henderson 3608b88ce6f2SRichard Henderson gen_store_gpr(dc, a->rd, dst); 3609b88ce6f2SRichard Henderson return advance_pc(dc); 3610b88ce6f2SRichard Henderson } 3611b88ce6f2SRichard Henderson 3612b88ce6f2SRichard Henderson TRANS(EDGE8cc, VIS1, gen_edge, a, 8, 1, 0) 3613b88ce6f2SRichard Henderson TRANS(EDGE8Lcc, VIS1, gen_edge, a, 8, 1, 1) 3614b88ce6f2SRichard Henderson TRANS(EDGE16cc, VIS1, gen_edge, a, 16, 1, 0) 3615b88ce6f2SRichard Henderson TRANS(EDGE16Lcc, VIS1, gen_edge, a, 16, 1, 1) 3616b88ce6f2SRichard Henderson TRANS(EDGE32cc, VIS1, gen_edge, a, 32, 1, 0) 3617b88ce6f2SRichard Henderson TRANS(EDGE32Lcc, VIS1, gen_edge, a, 32, 1, 1) 3618b88ce6f2SRichard Henderson 3619b88ce6f2SRichard Henderson TRANS(EDGE8N, VIS2, gen_edge, a, 8, 0, 0) 3620b88ce6f2SRichard Henderson TRANS(EDGE8LN, VIS2, gen_edge, a, 8, 0, 1) 3621b88ce6f2SRichard Henderson TRANS(EDGE16N, VIS2, gen_edge, a, 16, 0, 0) 3622b88ce6f2SRichard Henderson TRANS(EDGE16LN, VIS2, gen_edge, a, 16, 0, 1) 3623b88ce6f2SRichard Henderson TRANS(EDGE32N, VIS2, gen_edge, a, 32, 0, 0) 3624b88ce6f2SRichard Henderson TRANS(EDGE32LN, VIS2, gen_edge, a, 32, 0, 1) 3625b88ce6f2SRichard Henderson 362645bfed3bSRichard Henderson static bool do_rrr(DisasContext *dc, arg_r_r_r *a, 362745bfed3bSRichard Henderson void (*func)(TCGv, TCGv, TCGv)) 362845bfed3bSRichard Henderson { 362945bfed3bSRichard Henderson TCGv dst = gen_dest_gpr(dc, a->rd); 363045bfed3bSRichard Henderson TCGv src1 = gen_load_gpr(dc, a->rs1); 363145bfed3bSRichard Henderson TCGv src2 = gen_load_gpr(dc, a->rs2); 363245bfed3bSRichard Henderson 363345bfed3bSRichard Henderson func(dst, src1, src2); 363445bfed3bSRichard Henderson gen_store_gpr(dc, a->rd, dst); 363545bfed3bSRichard Henderson return advance_pc(dc); 363645bfed3bSRichard Henderson } 363745bfed3bSRichard Henderson 363845bfed3bSRichard Henderson TRANS(ARRAY8, VIS1, do_rrr, a, gen_helper_array8) 363945bfed3bSRichard Henderson TRANS(ARRAY16, VIS1, do_rrr, a, gen_op_array16) 364045bfed3bSRichard Henderson TRANS(ARRAY32, VIS1, do_rrr, a, gen_op_array32) 364145bfed3bSRichard Henderson 36429e20ca94SRichard Henderson static void gen_op_alignaddr(TCGv dst, TCGv s1, TCGv s2) 36439e20ca94SRichard Henderson { 36449e20ca94SRichard Henderson #ifdef TARGET_SPARC64 36459e20ca94SRichard Henderson TCGv tmp = tcg_temp_new(); 36469e20ca94SRichard Henderson 36479e20ca94SRichard Henderson tcg_gen_add_tl(tmp, s1, s2); 36489e20ca94SRichard Henderson tcg_gen_andi_tl(dst, tmp, -8); 36499e20ca94SRichard Henderson tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, tmp, 0, 3); 36509e20ca94SRichard Henderson #else 36519e20ca94SRichard Henderson g_assert_not_reached(); 36529e20ca94SRichard Henderson #endif 36539e20ca94SRichard Henderson } 36549e20ca94SRichard Henderson 36559e20ca94SRichard Henderson static void gen_op_alignaddrl(TCGv dst, TCGv s1, TCGv s2) 36569e20ca94SRichard Henderson { 36579e20ca94SRichard Henderson #ifdef TARGET_SPARC64 36589e20ca94SRichard Henderson TCGv tmp = tcg_temp_new(); 36599e20ca94SRichard Henderson 36609e20ca94SRichard Henderson tcg_gen_add_tl(tmp, s1, s2); 36619e20ca94SRichard Henderson tcg_gen_andi_tl(dst, tmp, -8); 36629e20ca94SRichard Henderson tcg_gen_neg_tl(tmp, tmp); 36639e20ca94SRichard Henderson tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, tmp, 0, 3); 36649e20ca94SRichard Henderson #else 36659e20ca94SRichard Henderson g_assert_not_reached(); 36669e20ca94SRichard Henderson #endif 36679e20ca94SRichard Henderson } 36689e20ca94SRichard Henderson 36699e20ca94SRichard Henderson TRANS(ALIGNADDR, VIS1, do_rrr, a, gen_op_alignaddr) 36709e20ca94SRichard Henderson TRANS(ALIGNADDRL, VIS1, do_rrr, a, gen_op_alignaddrl) 36719e20ca94SRichard Henderson 367239ca3490SRichard Henderson static void gen_op_bmask(TCGv dst, TCGv s1, TCGv s2) 367339ca3490SRichard Henderson { 367439ca3490SRichard Henderson #ifdef TARGET_SPARC64 367539ca3490SRichard Henderson tcg_gen_add_tl(dst, s1, s2); 367639ca3490SRichard Henderson tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, dst, 32, 32); 367739ca3490SRichard Henderson #else 367839ca3490SRichard Henderson g_assert_not_reached(); 367939ca3490SRichard Henderson #endif 368039ca3490SRichard Henderson } 368139ca3490SRichard Henderson 368239ca3490SRichard Henderson TRANS(BMASK, VIS2, do_rrr, a, gen_op_bmask) 368339ca3490SRichard Henderson 36845fc546eeSRichard Henderson static bool do_shift_r(DisasContext *dc, arg_shiftr *a, bool l, bool u) 36855fc546eeSRichard Henderson { 36865fc546eeSRichard Henderson TCGv dst, src1, src2; 36875fc546eeSRichard Henderson 36885fc546eeSRichard Henderson /* Reject 64-bit shifts for sparc32. */ 36895fc546eeSRichard Henderson if (avail_32(dc) && a->x) { 36905fc546eeSRichard Henderson return false; 36915fc546eeSRichard Henderson } 36925fc546eeSRichard Henderson 36935fc546eeSRichard Henderson src2 = tcg_temp_new(); 36945fc546eeSRichard Henderson tcg_gen_andi_tl(src2, gen_load_gpr(dc, a->rs2), a->x ? 63 : 31); 36955fc546eeSRichard Henderson src1 = gen_load_gpr(dc, a->rs1); 36965fc546eeSRichard Henderson dst = gen_dest_gpr(dc, a->rd); 36975fc546eeSRichard Henderson 36985fc546eeSRichard Henderson if (l) { 36995fc546eeSRichard Henderson tcg_gen_shl_tl(dst, src1, src2); 37005fc546eeSRichard Henderson if (!a->x) { 37015fc546eeSRichard Henderson tcg_gen_ext32u_tl(dst, dst); 37025fc546eeSRichard Henderson } 37035fc546eeSRichard Henderson } else if (u) { 37045fc546eeSRichard Henderson if (!a->x) { 37055fc546eeSRichard Henderson tcg_gen_ext32u_tl(dst, src1); 37065fc546eeSRichard Henderson src1 = dst; 37075fc546eeSRichard Henderson } 37085fc546eeSRichard Henderson tcg_gen_shr_tl(dst, src1, src2); 37095fc546eeSRichard Henderson } else { 37105fc546eeSRichard Henderson if (!a->x) { 37115fc546eeSRichard Henderson tcg_gen_ext32s_tl(dst, src1); 37125fc546eeSRichard Henderson src1 = dst; 37135fc546eeSRichard Henderson } 37145fc546eeSRichard Henderson tcg_gen_sar_tl(dst, src1, src2); 37155fc546eeSRichard Henderson } 37165fc546eeSRichard Henderson gen_store_gpr(dc, a->rd, dst); 37175fc546eeSRichard Henderson return advance_pc(dc); 37185fc546eeSRichard Henderson } 37195fc546eeSRichard Henderson 37205fc546eeSRichard Henderson TRANS(SLL_r, ALL, do_shift_r, a, true, true) 37215fc546eeSRichard Henderson TRANS(SRL_r, ALL, do_shift_r, a, false, true) 37225fc546eeSRichard Henderson TRANS(SRA_r, ALL, do_shift_r, a, false, false) 37235fc546eeSRichard Henderson 37245fc546eeSRichard Henderson static bool do_shift_i(DisasContext *dc, arg_shifti *a, bool l, bool u) 37255fc546eeSRichard Henderson { 37265fc546eeSRichard Henderson TCGv dst, src1; 37275fc546eeSRichard Henderson 37285fc546eeSRichard Henderson /* Reject 64-bit shifts for sparc32. */ 37295fc546eeSRichard Henderson if (avail_32(dc) && (a->x || a->i >= 32)) { 37305fc546eeSRichard Henderson return false; 37315fc546eeSRichard Henderson } 37325fc546eeSRichard Henderson 37335fc546eeSRichard Henderson src1 = gen_load_gpr(dc, a->rs1); 37345fc546eeSRichard Henderson dst = gen_dest_gpr(dc, a->rd); 37355fc546eeSRichard Henderson 37365fc546eeSRichard Henderson if (avail_32(dc) || a->x) { 37375fc546eeSRichard Henderson if (l) { 37385fc546eeSRichard Henderson tcg_gen_shli_tl(dst, src1, a->i); 37395fc546eeSRichard Henderson } else if (u) { 37405fc546eeSRichard Henderson tcg_gen_shri_tl(dst, src1, a->i); 37415fc546eeSRichard Henderson } else { 37425fc546eeSRichard Henderson tcg_gen_sari_tl(dst, src1, a->i); 37435fc546eeSRichard Henderson } 37445fc546eeSRichard Henderson } else { 37455fc546eeSRichard Henderson if (l) { 37465fc546eeSRichard Henderson tcg_gen_deposit_z_tl(dst, src1, a->i, 32 - a->i); 37475fc546eeSRichard Henderson } else if (u) { 37485fc546eeSRichard Henderson tcg_gen_extract_tl(dst, src1, a->i, 32 - a->i); 37495fc546eeSRichard Henderson } else { 37505fc546eeSRichard Henderson tcg_gen_sextract_tl(dst, src1, a->i, 32 - a->i); 37515fc546eeSRichard Henderson } 37525fc546eeSRichard Henderson } 37535fc546eeSRichard Henderson gen_store_gpr(dc, a->rd, dst); 37545fc546eeSRichard Henderson return advance_pc(dc); 37555fc546eeSRichard Henderson } 37565fc546eeSRichard Henderson 37575fc546eeSRichard Henderson TRANS(SLL_i, ALL, do_shift_i, a, true, true) 37585fc546eeSRichard Henderson TRANS(SRL_i, ALL, do_shift_i, a, false, true) 37595fc546eeSRichard Henderson TRANS(SRA_i, ALL, do_shift_i, a, false, false) 37605fc546eeSRichard Henderson 3761fb4ed7aaSRichard Henderson static TCGv gen_rs2_or_imm(DisasContext *dc, bool imm, int rs2_or_imm) 3762fb4ed7aaSRichard Henderson { 3763fb4ed7aaSRichard Henderson /* For simplicity, we under-decoded the rs2 form. */ 3764fb4ed7aaSRichard Henderson if (!imm && rs2_or_imm & ~0x1f) { 3765fb4ed7aaSRichard Henderson return NULL; 3766fb4ed7aaSRichard Henderson } 3767fb4ed7aaSRichard Henderson if (imm || rs2_or_imm == 0) { 3768fb4ed7aaSRichard Henderson return tcg_constant_tl(rs2_or_imm); 3769fb4ed7aaSRichard Henderson } else { 3770fb4ed7aaSRichard Henderson return cpu_regs[rs2_or_imm]; 3771fb4ed7aaSRichard Henderson } 3772fb4ed7aaSRichard Henderson } 3773fb4ed7aaSRichard Henderson 3774fb4ed7aaSRichard Henderson static bool do_mov_cond(DisasContext *dc, DisasCompare *cmp, int rd, TCGv src2) 3775fb4ed7aaSRichard Henderson { 3776fb4ed7aaSRichard Henderson TCGv dst = gen_load_gpr(dc, rd); 3777c8507ebfSRichard Henderson TCGv c2 = tcg_constant_tl(cmp->c2); 3778fb4ed7aaSRichard Henderson 3779c8507ebfSRichard Henderson tcg_gen_movcond_tl(cmp->cond, dst, cmp->c1, c2, src2, dst); 3780fb4ed7aaSRichard Henderson gen_store_gpr(dc, rd, dst); 3781fb4ed7aaSRichard Henderson return advance_pc(dc); 3782fb4ed7aaSRichard Henderson } 3783fb4ed7aaSRichard Henderson 3784fb4ed7aaSRichard Henderson static bool trans_MOVcc(DisasContext *dc, arg_MOVcc *a) 3785fb4ed7aaSRichard Henderson { 3786fb4ed7aaSRichard Henderson TCGv src2 = gen_rs2_or_imm(dc, a->imm, a->rs2_or_imm); 3787fb4ed7aaSRichard Henderson DisasCompare cmp; 3788fb4ed7aaSRichard Henderson 3789fb4ed7aaSRichard Henderson if (src2 == NULL) { 3790fb4ed7aaSRichard Henderson return false; 3791fb4ed7aaSRichard Henderson } 3792fb4ed7aaSRichard Henderson gen_compare(&cmp, a->cc, a->cond, dc); 3793fb4ed7aaSRichard Henderson return do_mov_cond(dc, &cmp, a->rd, src2); 3794fb4ed7aaSRichard Henderson } 3795fb4ed7aaSRichard Henderson 3796fb4ed7aaSRichard Henderson static bool trans_MOVfcc(DisasContext *dc, arg_MOVfcc *a) 3797fb4ed7aaSRichard Henderson { 3798fb4ed7aaSRichard Henderson TCGv src2 = gen_rs2_or_imm(dc, a->imm, a->rs2_or_imm); 3799fb4ed7aaSRichard Henderson DisasCompare cmp; 3800fb4ed7aaSRichard Henderson 3801fb4ed7aaSRichard Henderson if (src2 == NULL) { 3802fb4ed7aaSRichard Henderson return false; 3803fb4ed7aaSRichard Henderson } 3804fb4ed7aaSRichard Henderson gen_fcompare(&cmp, a->cc, a->cond); 3805fb4ed7aaSRichard Henderson return do_mov_cond(dc, &cmp, a->rd, src2); 3806fb4ed7aaSRichard Henderson } 3807fb4ed7aaSRichard Henderson 3808fb4ed7aaSRichard Henderson static bool trans_MOVR(DisasContext *dc, arg_MOVR *a) 3809fb4ed7aaSRichard Henderson { 3810fb4ed7aaSRichard Henderson TCGv src2 = gen_rs2_or_imm(dc, a->imm, a->rs2_or_imm); 3811fb4ed7aaSRichard Henderson DisasCompare cmp; 3812fb4ed7aaSRichard Henderson 3813fb4ed7aaSRichard Henderson if (src2 == NULL) { 3814fb4ed7aaSRichard Henderson return false; 3815fb4ed7aaSRichard Henderson } 38162c4f56c9SRichard Henderson if (!gen_compare_reg(&cmp, a->cond, gen_load_gpr(dc, a->rs1))) { 38172c4f56c9SRichard Henderson return false; 38182c4f56c9SRichard Henderson } 3819fb4ed7aaSRichard Henderson return do_mov_cond(dc, &cmp, a->rd, src2); 3820fb4ed7aaSRichard Henderson } 3821fb4ed7aaSRichard Henderson 382286b82fe0SRichard Henderson static bool do_add_special(DisasContext *dc, arg_r_r_ri *a, 382386b82fe0SRichard Henderson bool (*func)(DisasContext *dc, int rd, TCGv src)) 382486b82fe0SRichard Henderson { 382586b82fe0SRichard Henderson TCGv src1, sum; 382686b82fe0SRichard Henderson 382786b82fe0SRichard Henderson /* For simplicity, we under-decoded the rs2 form. */ 382886b82fe0SRichard Henderson if (!a->imm && a->rs2_or_imm & ~0x1f) { 382986b82fe0SRichard Henderson return false; 383086b82fe0SRichard Henderson } 383186b82fe0SRichard Henderson 383286b82fe0SRichard Henderson /* 383386b82fe0SRichard Henderson * Always load the sum into a new temporary. 383486b82fe0SRichard Henderson * This is required to capture the value across a window change, 383586b82fe0SRichard Henderson * e.g. SAVE and RESTORE, and may be optimized away otherwise. 383686b82fe0SRichard Henderson */ 383786b82fe0SRichard Henderson sum = tcg_temp_new(); 383886b82fe0SRichard Henderson src1 = gen_load_gpr(dc, a->rs1); 383986b82fe0SRichard Henderson if (a->imm || a->rs2_or_imm == 0) { 384086b82fe0SRichard Henderson tcg_gen_addi_tl(sum, src1, a->rs2_or_imm); 384186b82fe0SRichard Henderson } else { 384286b82fe0SRichard Henderson tcg_gen_add_tl(sum, src1, cpu_regs[a->rs2_or_imm]); 384386b82fe0SRichard Henderson } 384486b82fe0SRichard Henderson return func(dc, a->rd, sum); 384586b82fe0SRichard Henderson } 384686b82fe0SRichard Henderson 384786b82fe0SRichard Henderson static bool do_jmpl(DisasContext *dc, int rd, TCGv src) 384886b82fe0SRichard Henderson { 384986b82fe0SRichard Henderson /* 385086b82fe0SRichard Henderson * Preserve pc across advance, so that we can delay 385186b82fe0SRichard Henderson * the writeback to rd until after src is consumed. 385286b82fe0SRichard Henderson */ 385386b82fe0SRichard Henderson target_ulong cur_pc = dc->pc; 385486b82fe0SRichard Henderson 385586b82fe0SRichard Henderson gen_check_align(dc, src, 3); 385686b82fe0SRichard Henderson 385786b82fe0SRichard Henderson gen_mov_pc_npc(dc); 385886b82fe0SRichard Henderson tcg_gen_mov_tl(cpu_npc, src); 385986b82fe0SRichard Henderson gen_address_mask(dc, cpu_npc); 386086b82fe0SRichard Henderson gen_store_gpr(dc, rd, tcg_constant_tl(cur_pc)); 386186b82fe0SRichard Henderson 386286b82fe0SRichard Henderson dc->npc = DYNAMIC_PC_LOOKUP; 386386b82fe0SRichard Henderson return true; 386486b82fe0SRichard Henderson } 386586b82fe0SRichard Henderson 386686b82fe0SRichard Henderson TRANS(JMPL, ALL, do_add_special, a, do_jmpl) 386786b82fe0SRichard Henderson 386886b82fe0SRichard Henderson static bool do_rett(DisasContext *dc, int rd, TCGv src) 386986b82fe0SRichard Henderson { 387086b82fe0SRichard Henderson if (!supervisor(dc)) { 387186b82fe0SRichard Henderson return raise_priv(dc); 387286b82fe0SRichard Henderson } 387386b82fe0SRichard Henderson 387486b82fe0SRichard Henderson gen_check_align(dc, src, 3); 387586b82fe0SRichard Henderson 387686b82fe0SRichard Henderson gen_mov_pc_npc(dc); 387786b82fe0SRichard Henderson tcg_gen_mov_tl(cpu_npc, src); 387886b82fe0SRichard Henderson gen_helper_rett(tcg_env); 387986b82fe0SRichard Henderson 388086b82fe0SRichard Henderson dc->npc = DYNAMIC_PC; 388186b82fe0SRichard Henderson return true; 388286b82fe0SRichard Henderson } 388386b82fe0SRichard Henderson 388486b82fe0SRichard Henderson TRANS(RETT, 32, do_add_special, a, do_rett) 388586b82fe0SRichard Henderson 388686b82fe0SRichard Henderson static bool do_return(DisasContext *dc, int rd, TCGv src) 388786b82fe0SRichard Henderson { 388886b82fe0SRichard Henderson gen_check_align(dc, src, 3); 38890dfae4f9SRichard Henderson gen_helper_restore(tcg_env); 389086b82fe0SRichard Henderson 389186b82fe0SRichard Henderson gen_mov_pc_npc(dc); 389286b82fe0SRichard Henderson tcg_gen_mov_tl(cpu_npc, src); 389386b82fe0SRichard Henderson gen_address_mask(dc, cpu_npc); 389486b82fe0SRichard Henderson 389586b82fe0SRichard Henderson dc->npc = DYNAMIC_PC_LOOKUP; 389686b82fe0SRichard Henderson return true; 389786b82fe0SRichard Henderson } 389886b82fe0SRichard Henderson 389986b82fe0SRichard Henderson TRANS(RETURN, 64, do_add_special, a, do_return) 390086b82fe0SRichard Henderson 3901d3825800SRichard Henderson static bool do_save(DisasContext *dc, int rd, TCGv src) 3902d3825800SRichard Henderson { 3903d3825800SRichard Henderson gen_helper_save(tcg_env); 3904d3825800SRichard Henderson gen_store_gpr(dc, rd, src); 3905d3825800SRichard Henderson return advance_pc(dc); 3906d3825800SRichard Henderson } 3907d3825800SRichard Henderson 3908d3825800SRichard Henderson TRANS(SAVE, ALL, do_add_special, a, do_save) 3909d3825800SRichard Henderson 3910d3825800SRichard Henderson static bool do_restore(DisasContext *dc, int rd, TCGv src) 3911d3825800SRichard Henderson { 3912d3825800SRichard Henderson gen_helper_restore(tcg_env); 3913d3825800SRichard Henderson gen_store_gpr(dc, rd, src); 3914d3825800SRichard Henderson return advance_pc(dc); 3915d3825800SRichard Henderson } 3916d3825800SRichard Henderson 3917d3825800SRichard Henderson TRANS(RESTORE, ALL, do_add_special, a, do_restore) 3918d3825800SRichard Henderson 39198f75b8a4SRichard Henderson static bool do_done_retry(DisasContext *dc, bool done) 39208f75b8a4SRichard Henderson { 39218f75b8a4SRichard Henderson if (!supervisor(dc)) { 39228f75b8a4SRichard Henderson return raise_priv(dc); 39238f75b8a4SRichard Henderson } 39248f75b8a4SRichard Henderson dc->npc = DYNAMIC_PC; 39258f75b8a4SRichard Henderson dc->pc = DYNAMIC_PC; 39268f75b8a4SRichard Henderson translator_io_start(&dc->base); 39278f75b8a4SRichard Henderson if (done) { 39288f75b8a4SRichard Henderson gen_helper_done(tcg_env); 39298f75b8a4SRichard Henderson } else { 39308f75b8a4SRichard Henderson gen_helper_retry(tcg_env); 39318f75b8a4SRichard Henderson } 39328f75b8a4SRichard Henderson return true; 39338f75b8a4SRichard Henderson } 39348f75b8a4SRichard Henderson 39358f75b8a4SRichard Henderson TRANS(DONE, 64, do_done_retry, true) 39368f75b8a4SRichard Henderson TRANS(RETRY, 64, do_done_retry, false) 39378f75b8a4SRichard Henderson 39380880d20bSRichard Henderson /* 39390880d20bSRichard Henderson * Major opcode 11 -- load and store instructions 39400880d20bSRichard Henderson */ 39410880d20bSRichard Henderson 39420880d20bSRichard Henderson static TCGv gen_ldst_addr(DisasContext *dc, int rs1, bool imm, int rs2_or_imm) 39430880d20bSRichard Henderson { 39440880d20bSRichard Henderson TCGv addr, tmp = NULL; 39450880d20bSRichard Henderson 39460880d20bSRichard Henderson /* For simplicity, we under-decoded the rs2 form. */ 39470880d20bSRichard Henderson if (!imm && rs2_or_imm & ~0x1f) { 39480880d20bSRichard Henderson return NULL; 39490880d20bSRichard Henderson } 39500880d20bSRichard Henderson 39510880d20bSRichard Henderson addr = gen_load_gpr(dc, rs1); 39520880d20bSRichard Henderson if (rs2_or_imm) { 39530880d20bSRichard Henderson tmp = tcg_temp_new(); 39540880d20bSRichard Henderson if (imm) { 39550880d20bSRichard Henderson tcg_gen_addi_tl(tmp, addr, rs2_or_imm); 39560880d20bSRichard Henderson } else { 39570880d20bSRichard Henderson tcg_gen_add_tl(tmp, addr, cpu_regs[rs2_or_imm]); 39580880d20bSRichard Henderson } 39590880d20bSRichard Henderson addr = tmp; 39600880d20bSRichard Henderson } 39610880d20bSRichard Henderson if (AM_CHECK(dc)) { 39620880d20bSRichard Henderson if (!tmp) { 39630880d20bSRichard Henderson tmp = tcg_temp_new(); 39640880d20bSRichard Henderson } 39650880d20bSRichard Henderson tcg_gen_ext32u_tl(tmp, addr); 39660880d20bSRichard Henderson addr = tmp; 39670880d20bSRichard Henderson } 39680880d20bSRichard Henderson return addr; 39690880d20bSRichard Henderson } 39700880d20bSRichard Henderson 39710880d20bSRichard Henderson static bool do_ld_gpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp mop) 39720880d20bSRichard Henderson { 39730880d20bSRichard Henderson TCGv reg, addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 39740880d20bSRichard Henderson DisasASI da; 39750880d20bSRichard Henderson 39760880d20bSRichard Henderson if (addr == NULL) { 39770880d20bSRichard Henderson return false; 39780880d20bSRichard Henderson } 39790880d20bSRichard Henderson da = resolve_asi(dc, a->asi, mop); 39800880d20bSRichard Henderson 39810880d20bSRichard Henderson reg = gen_dest_gpr(dc, a->rd); 398242071fc1SRichard Henderson gen_ld_asi(dc, &da, reg, addr); 39830880d20bSRichard Henderson gen_store_gpr(dc, a->rd, reg); 39840880d20bSRichard Henderson return advance_pc(dc); 39850880d20bSRichard Henderson } 39860880d20bSRichard Henderson 39870880d20bSRichard Henderson TRANS(LDUW, ALL, do_ld_gpr, a, MO_TEUL) 39880880d20bSRichard Henderson TRANS(LDUB, ALL, do_ld_gpr, a, MO_UB) 39890880d20bSRichard Henderson TRANS(LDUH, ALL, do_ld_gpr, a, MO_TEUW) 39900880d20bSRichard Henderson TRANS(LDSB, ALL, do_ld_gpr, a, MO_SB) 39910880d20bSRichard Henderson TRANS(LDSH, ALL, do_ld_gpr, a, MO_TESW) 39920880d20bSRichard Henderson TRANS(LDSW, 64, do_ld_gpr, a, MO_TESL) 39930880d20bSRichard Henderson TRANS(LDX, 64, do_ld_gpr, a, MO_TEUQ) 39940880d20bSRichard Henderson 39950880d20bSRichard Henderson static bool do_st_gpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp mop) 39960880d20bSRichard Henderson { 39970880d20bSRichard Henderson TCGv reg, addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 39980880d20bSRichard Henderson DisasASI da; 39990880d20bSRichard Henderson 40000880d20bSRichard Henderson if (addr == NULL) { 40010880d20bSRichard Henderson return false; 40020880d20bSRichard Henderson } 40030880d20bSRichard Henderson da = resolve_asi(dc, a->asi, mop); 40040880d20bSRichard Henderson 40050880d20bSRichard Henderson reg = gen_load_gpr(dc, a->rd); 400642071fc1SRichard Henderson gen_st_asi(dc, &da, reg, addr); 40070880d20bSRichard Henderson return advance_pc(dc); 40080880d20bSRichard Henderson } 40090880d20bSRichard Henderson 40100880d20bSRichard Henderson TRANS(STW, ALL, do_st_gpr, a, MO_TEUL) 40110880d20bSRichard Henderson TRANS(STB, ALL, do_st_gpr, a, MO_UB) 40120880d20bSRichard Henderson TRANS(STH, ALL, do_st_gpr, a, MO_TEUW) 40130880d20bSRichard Henderson TRANS(STX, 64, do_st_gpr, a, MO_TEUQ) 40140880d20bSRichard Henderson 40150880d20bSRichard Henderson static bool trans_LDD(DisasContext *dc, arg_r_r_ri_asi *a) 40160880d20bSRichard Henderson { 40170880d20bSRichard Henderson TCGv addr; 40180880d20bSRichard Henderson DisasASI da; 40190880d20bSRichard Henderson 40200880d20bSRichard Henderson if (a->rd & 1) { 40210880d20bSRichard Henderson return false; 40220880d20bSRichard Henderson } 40230880d20bSRichard Henderson addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 40240880d20bSRichard Henderson if (addr == NULL) { 40250880d20bSRichard Henderson return false; 40260880d20bSRichard Henderson } 40270880d20bSRichard Henderson da = resolve_asi(dc, a->asi, MO_TEUQ); 402842071fc1SRichard Henderson gen_ldda_asi(dc, &da, addr, a->rd); 40290880d20bSRichard Henderson return advance_pc(dc); 40300880d20bSRichard Henderson } 40310880d20bSRichard Henderson 40320880d20bSRichard Henderson static bool trans_STD(DisasContext *dc, arg_r_r_ri_asi *a) 40330880d20bSRichard Henderson { 40340880d20bSRichard Henderson TCGv addr; 40350880d20bSRichard Henderson DisasASI da; 40360880d20bSRichard Henderson 40370880d20bSRichard Henderson if (a->rd & 1) { 40380880d20bSRichard Henderson return false; 40390880d20bSRichard Henderson } 40400880d20bSRichard Henderson addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 40410880d20bSRichard Henderson if (addr == NULL) { 40420880d20bSRichard Henderson return false; 40430880d20bSRichard Henderson } 40440880d20bSRichard Henderson da = resolve_asi(dc, a->asi, MO_TEUQ); 404542071fc1SRichard Henderson gen_stda_asi(dc, &da, addr, a->rd); 40460880d20bSRichard Henderson return advance_pc(dc); 40470880d20bSRichard Henderson } 40480880d20bSRichard Henderson 4049cf07cd1eSRichard Henderson static bool trans_LDSTUB(DisasContext *dc, arg_r_r_ri_asi *a) 4050cf07cd1eSRichard Henderson { 4051cf07cd1eSRichard Henderson TCGv addr, reg; 4052cf07cd1eSRichard Henderson DisasASI da; 4053cf07cd1eSRichard Henderson 4054cf07cd1eSRichard Henderson addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 4055cf07cd1eSRichard Henderson if (addr == NULL) { 4056cf07cd1eSRichard Henderson return false; 4057cf07cd1eSRichard Henderson } 4058cf07cd1eSRichard Henderson da = resolve_asi(dc, a->asi, MO_UB); 4059cf07cd1eSRichard Henderson 4060cf07cd1eSRichard Henderson reg = gen_dest_gpr(dc, a->rd); 4061cf07cd1eSRichard Henderson gen_ldstub_asi(dc, &da, reg, addr); 4062cf07cd1eSRichard Henderson gen_store_gpr(dc, a->rd, reg); 4063cf07cd1eSRichard Henderson return advance_pc(dc); 4064cf07cd1eSRichard Henderson } 4065cf07cd1eSRichard Henderson 4066dca544b9SRichard Henderson static bool trans_SWAP(DisasContext *dc, arg_r_r_ri_asi *a) 4067dca544b9SRichard Henderson { 4068dca544b9SRichard Henderson TCGv addr, dst, src; 4069dca544b9SRichard Henderson DisasASI da; 4070dca544b9SRichard Henderson 4071dca544b9SRichard Henderson addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 4072dca544b9SRichard Henderson if (addr == NULL) { 4073dca544b9SRichard Henderson return false; 4074dca544b9SRichard Henderson } 4075dca544b9SRichard Henderson da = resolve_asi(dc, a->asi, MO_TEUL); 4076dca544b9SRichard Henderson 4077dca544b9SRichard Henderson dst = gen_dest_gpr(dc, a->rd); 4078dca544b9SRichard Henderson src = gen_load_gpr(dc, a->rd); 4079dca544b9SRichard Henderson gen_swap_asi(dc, &da, dst, src, addr); 4080dca544b9SRichard Henderson gen_store_gpr(dc, a->rd, dst); 4081dca544b9SRichard Henderson return advance_pc(dc); 4082dca544b9SRichard Henderson } 4083dca544b9SRichard Henderson 4084d0a11d25SRichard Henderson static bool do_casa(DisasContext *dc, arg_r_r_ri_asi *a, MemOp mop) 4085d0a11d25SRichard Henderson { 4086d0a11d25SRichard Henderson TCGv addr, o, n, c; 4087d0a11d25SRichard Henderson DisasASI da; 4088d0a11d25SRichard Henderson 4089d0a11d25SRichard Henderson addr = gen_ldst_addr(dc, a->rs1, true, 0); 4090d0a11d25SRichard Henderson if (addr == NULL) { 4091d0a11d25SRichard Henderson return false; 4092d0a11d25SRichard Henderson } 4093d0a11d25SRichard Henderson da = resolve_asi(dc, a->asi, mop); 4094d0a11d25SRichard Henderson 4095d0a11d25SRichard Henderson o = gen_dest_gpr(dc, a->rd); 4096d0a11d25SRichard Henderson n = gen_load_gpr(dc, a->rd); 4097d0a11d25SRichard Henderson c = gen_load_gpr(dc, a->rs2_or_imm); 4098d0a11d25SRichard Henderson gen_cas_asi(dc, &da, o, n, c, addr); 4099d0a11d25SRichard Henderson gen_store_gpr(dc, a->rd, o); 4100d0a11d25SRichard Henderson return advance_pc(dc); 4101d0a11d25SRichard Henderson } 4102d0a11d25SRichard Henderson 4103d0a11d25SRichard Henderson TRANS(CASA, CASA, do_casa, a, MO_TEUL) 4104d0a11d25SRichard Henderson TRANS(CASXA, 64, do_casa, a, MO_TEUQ) 4105d0a11d25SRichard Henderson 410606c060d9SRichard Henderson static bool do_ld_fpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp sz) 410706c060d9SRichard Henderson { 410806c060d9SRichard Henderson TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 410906c060d9SRichard Henderson DisasASI da; 411006c060d9SRichard Henderson 411106c060d9SRichard Henderson if (addr == NULL) { 411206c060d9SRichard Henderson return false; 411306c060d9SRichard Henderson } 411406c060d9SRichard Henderson if (gen_trap_ifnofpu(dc)) { 411506c060d9SRichard Henderson return true; 411606c060d9SRichard Henderson } 411706c060d9SRichard Henderson if (sz == MO_128 && gen_trap_float128(dc)) { 411806c060d9SRichard Henderson return true; 411906c060d9SRichard Henderson } 412006c060d9SRichard Henderson da = resolve_asi(dc, a->asi, MO_TE | sz); 4121287b1152SRichard Henderson gen_ldf_asi(dc, &da, sz, addr, a->rd); 412206c060d9SRichard Henderson gen_update_fprs_dirty(dc, a->rd); 412306c060d9SRichard Henderson return advance_pc(dc); 412406c060d9SRichard Henderson } 412506c060d9SRichard Henderson 412606c060d9SRichard Henderson TRANS(LDF, ALL, do_ld_fpr, a, MO_32) 412706c060d9SRichard Henderson TRANS(LDDF, ALL, do_ld_fpr, a, MO_64) 412806c060d9SRichard Henderson TRANS(LDQF, ALL, do_ld_fpr, a, MO_128) 412906c060d9SRichard Henderson 4130287b1152SRichard Henderson TRANS(LDFA, 64, do_ld_fpr, a, MO_32) 4131287b1152SRichard Henderson TRANS(LDDFA, 64, do_ld_fpr, a, MO_64) 4132287b1152SRichard Henderson TRANS(LDQFA, 64, do_ld_fpr, a, MO_128) 4133287b1152SRichard Henderson 413406c060d9SRichard Henderson static bool do_st_fpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp sz) 413506c060d9SRichard Henderson { 413606c060d9SRichard Henderson TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 413706c060d9SRichard Henderson DisasASI da; 413806c060d9SRichard Henderson 413906c060d9SRichard Henderson if (addr == NULL) { 414006c060d9SRichard Henderson return false; 414106c060d9SRichard Henderson } 414206c060d9SRichard Henderson if (gen_trap_ifnofpu(dc)) { 414306c060d9SRichard Henderson return true; 414406c060d9SRichard Henderson } 414506c060d9SRichard Henderson if (sz == MO_128 && gen_trap_float128(dc)) { 414606c060d9SRichard Henderson return true; 414706c060d9SRichard Henderson } 414806c060d9SRichard Henderson da = resolve_asi(dc, a->asi, MO_TE | sz); 4149287b1152SRichard Henderson gen_stf_asi(dc, &da, sz, addr, a->rd); 415006c060d9SRichard Henderson return advance_pc(dc); 415106c060d9SRichard Henderson } 415206c060d9SRichard Henderson 415306c060d9SRichard Henderson TRANS(STF, ALL, do_st_fpr, a, MO_32) 415406c060d9SRichard Henderson TRANS(STDF, ALL, do_st_fpr, a, MO_64) 415506c060d9SRichard Henderson TRANS(STQF, ALL, do_st_fpr, a, MO_128) 415606c060d9SRichard Henderson 4157287b1152SRichard Henderson TRANS(STFA, 64, do_st_fpr, a, MO_32) 4158287b1152SRichard Henderson TRANS(STDFA, 64, do_st_fpr, a, MO_64) 4159287b1152SRichard Henderson TRANS(STQFA, 64, do_st_fpr, a, MO_128) 4160287b1152SRichard Henderson 416106c060d9SRichard Henderson static bool trans_STDFQ(DisasContext *dc, arg_STDFQ *a) 416206c060d9SRichard Henderson { 416306c060d9SRichard Henderson if (!avail_32(dc)) { 416406c060d9SRichard Henderson return false; 416506c060d9SRichard Henderson } 416606c060d9SRichard Henderson if (!supervisor(dc)) { 416706c060d9SRichard Henderson return raise_priv(dc); 416806c060d9SRichard Henderson } 416906c060d9SRichard Henderson if (gen_trap_ifnofpu(dc)) { 417006c060d9SRichard Henderson return true; 417106c060d9SRichard Henderson } 417206c060d9SRichard Henderson gen_op_fpexception_im(dc, FSR_FTT_SEQ_ERROR); 417306c060d9SRichard Henderson return true; 417406c060d9SRichard Henderson } 417506c060d9SRichard Henderson 4176d8c5b92fSRichard Henderson static bool trans_LDFSR(DisasContext *dc, arg_r_r_ri *a) 41773d3c0673SRichard Henderson { 41783590f01eSRichard Henderson TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 4179d8c5b92fSRichard Henderson TCGv_i32 tmp; 41803590f01eSRichard Henderson 41813d3c0673SRichard Henderson if (addr == NULL) { 41823d3c0673SRichard Henderson return false; 41833d3c0673SRichard Henderson } 41843d3c0673SRichard Henderson if (gen_trap_ifnofpu(dc)) { 41853d3c0673SRichard Henderson return true; 41863d3c0673SRichard Henderson } 4187d8c5b92fSRichard Henderson 4188d8c5b92fSRichard Henderson tmp = tcg_temp_new_i32(); 4189d8c5b92fSRichard Henderson tcg_gen_qemu_ld_i32(tmp, addr, dc->mem_idx, MO_TEUL | MO_ALIGN); 4190d8c5b92fSRichard Henderson 4191d8c5b92fSRichard Henderson tcg_gen_extract_i32(cpu_fcc[0], tmp, FSR_FCC0_SHIFT, 2); 4192d8c5b92fSRichard Henderson /* LDFSR does not change FCC[1-3]. */ 4193d8c5b92fSRichard Henderson 4194d8c5b92fSRichard Henderson gen_helper_set_fsr_nofcc_noftt(tcg_env, tmp); 41953d3c0673SRichard Henderson return advance_pc(dc); 41963d3c0673SRichard Henderson } 41973d3c0673SRichard Henderson 4198d8c5b92fSRichard Henderson static bool trans_LDXFSR(DisasContext *dc, arg_r_r_ri *a) 4199d8c5b92fSRichard Henderson { 4200d8c5b92fSRichard Henderson #ifdef TARGET_SPARC64 4201d8c5b92fSRichard Henderson TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 4202d8c5b92fSRichard Henderson TCGv_i64 t64; 4203d8c5b92fSRichard Henderson TCGv_i32 lo, hi; 4204d8c5b92fSRichard Henderson 4205d8c5b92fSRichard Henderson if (addr == NULL) { 4206d8c5b92fSRichard Henderson return false; 4207d8c5b92fSRichard Henderson } 4208d8c5b92fSRichard Henderson if (gen_trap_ifnofpu(dc)) { 4209d8c5b92fSRichard Henderson return true; 4210d8c5b92fSRichard Henderson } 4211d8c5b92fSRichard Henderson 4212d8c5b92fSRichard Henderson t64 = tcg_temp_new_i64(); 4213d8c5b92fSRichard Henderson tcg_gen_qemu_ld_i64(t64, addr, dc->mem_idx, MO_TEUQ | MO_ALIGN); 4214d8c5b92fSRichard Henderson 4215d8c5b92fSRichard Henderson lo = tcg_temp_new_i32(); 4216d8c5b92fSRichard Henderson hi = cpu_fcc[3]; 4217d8c5b92fSRichard Henderson tcg_gen_extr_i64_i32(lo, hi, t64); 4218d8c5b92fSRichard Henderson tcg_gen_extract_i32(cpu_fcc[0], lo, FSR_FCC0_SHIFT, 2); 4219d8c5b92fSRichard Henderson tcg_gen_extract_i32(cpu_fcc[1], hi, FSR_FCC1_SHIFT - 32, 2); 4220d8c5b92fSRichard Henderson tcg_gen_extract_i32(cpu_fcc[2], hi, FSR_FCC2_SHIFT - 32, 2); 4221d8c5b92fSRichard Henderson tcg_gen_extract_i32(cpu_fcc[3], hi, FSR_FCC3_SHIFT - 32, 2); 4222d8c5b92fSRichard Henderson 4223d8c5b92fSRichard Henderson gen_helper_set_fsr_nofcc_noftt(tcg_env, lo); 4224d8c5b92fSRichard Henderson return advance_pc(dc); 4225d8c5b92fSRichard Henderson #else 4226d8c5b92fSRichard Henderson return false; 4227d8c5b92fSRichard Henderson #endif 4228d8c5b92fSRichard Henderson } 42293d3c0673SRichard Henderson 42303d3c0673SRichard Henderson static bool do_stfsr(DisasContext *dc, arg_r_r_ri *a, MemOp mop) 42313d3c0673SRichard Henderson { 42323d3c0673SRichard Henderson TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 42331ccd6e13SRichard Henderson TCGv fsr; 42341ccd6e13SRichard Henderson 42353d3c0673SRichard Henderson if (addr == NULL) { 42363d3c0673SRichard Henderson return false; 42373d3c0673SRichard Henderson } 42383d3c0673SRichard Henderson if (gen_trap_ifnofpu(dc)) { 42393d3c0673SRichard Henderson return true; 42403d3c0673SRichard Henderson } 42411ccd6e13SRichard Henderson 42421ccd6e13SRichard Henderson fsr = tcg_temp_new(); 42431ccd6e13SRichard Henderson gen_helper_get_fsr(fsr, tcg_env); 42441ccd6e13SRichard Henderson tcg_gen_qemu_st_tl(fsr, addr, dc->mem_idx, mop | MO_ALIGN); 42453d3c0673SRichard Henderson return advance_pc(dc); 42463d3c0673SRichard Henderson } 42473d3c0673SRichard Henderson 42483d3c0673SRichard Henderson TRANS(STFSR, ALL, do_stfsr, a, MO_TEUL) 42493d3c0673SRichard Henderson TRANS(STXFSR, 64, do_stfsr, a, MO_TEUQ) 42503d3c0673SRichard Henderson 42511210a036SRichard Henderson static bool do_fc(DisasContext *dc, int rd, int32_t c) 42523a38260eSRichard Henderson { 42533a38260eSRichard Henderson if (gen_trap_ifnofpu(dc)) { 42543a38260eSRichard Henderson return true; 42553a38260eSRichard Henderson } 42561210a036SRichard Henderson gen_store_fpr_F(dc, rd, tcg_constant_i32(c)); 42573a38260eSRichard Henderson return advance_pc(dc); 42583a38260eSRichard Henderson } 42593a38260eSRichard Henderson 42603a38260eSRichard Henderson TRANS(FZEROs, VIS1, do_fc, a->rd, 0) 42611210a036SRichard Henderson TRANS(FONEs, VIS1, do_fc, a->rd, -1) 42623a38260eSRichard Henderson 42633a38260eSRichard Henderson static bool do_dc(DisasContext *dc, int rd, int64_t c) 42643a38260eSRichard Henderson { 42653a38260eSRichard Henderson if (gen_trap_ifnofpu(dc)) { 42663a38260eSRichard Henderson return true; 42673a38260eSRichard Henderson } 42681210a036SRichard Henderson gen_store_fpr_D(dc, rd, tcg_constant_i64(c)); 42693a38260eSRichard Henderson return advance_pc(dc); 42703a38260eSRichard Henderson } 42713a38260eSRichard Henderson 42723a38260eSRichard Henderson TRANS(FZEROd, VIS1, do_dc, a->rd, 0) 42733a38260eSRichard Henderson TRANS(FONEd, VIS1, do_dc, a->rd, -1) 42743a38260eSRichard Henderson 4275baf3dbf2SRichard Henderson static bool do_ff(DisasContext *dc, arg_r_r *a, 4276baf3dbf2SRichard Henderson void (*func)(TCGv_i32, TCGv_i32)) 4277baf3dbf2SRichard Henderson { 4278baf3dbf2SRichard Henderson TCGv_i32 tmp; 4279baf3dbf2SRichard Henderson 4280baf3dbf2SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4281baf3dbf2SRichard Henderson return true; 4282baf3dbf2SRichard Henderson } 4283baf3dbf2SRichard Henderson 4284baf3dbf2SRichard Henderson tmp = gen_load_fpr_F(dc, a->rs); 4285baf3dbf2SRichard Henderson func(tmp, tmp); 4286baf3dbf2SRichard Henderson gen_store_fpr_F(dc, a->rd, tmp); 4287baf3dbf2SRichard Henderson return advance_pc(dc); 4288baf3dbf2SRichard Henderson } 4289baf3dbf2SRichard Henderson 4290baf3dbf2SRichard Henderson TRANS(FMOVs, ALL, do_ff, a, gen_op_fmovs) 4291baf3dbf2SRichard Henderson TRANS(FNEGs, ALL, do_ff, a, gen_op_fnegs) 4292baf3dbf2SRichard Henderson TRANS(FABSs, ALL, do_ff, a, gen_op_fabss) 4293baf3dbf2SRichard Henderson TRANS(FSRCs, VIS1, do_ff, a, tcg_gen_mov_i32) 4294baf3dbf2SRichard Henderson TRANS(FNOTs, VIS1, do_ff, a, tcg_gen_not_i32) 4295baf3dbf2SRichard Henderson 42962f722641SRichard Henderson static bool do_fd(DisasContext *dc, arg_r_r *a, 42972f722641SRichard Henderson void (*func)(TCGv_i32, TCGv_i64)) 42982f722641SRichard Henderson { 42992f722641SRichard Henderson TCGv_i32 dst; 43002f722641SRichard Henderson TCGv_i64 src; 43012f722641SRichard Henderson 43022f722641SRichard Henderson if (gen_trap_ifnofpu(dc)) { 43032f722641SRichard Henderson return true; 43042f722641SRichard Henderson } 43052f722641SRichard Henderson 4306388a6465SRichard Henderson dst = tcg_temp_new_i32(); 43072f722641SRichard Henderson src = gen_load_fpr_D(dc, a->rs); 43082f722641SRichard Henderson func(dst, src); 43092f722641SRichard Henderson gen_store_fpr_F(dc, a->rd, dst); 43102f722641SRichard Henderson return advance_pc(dc); 43112f722641SRichard Henderson } 43122f722641SRichard Henderson 43132f722641SRichard Henderson TRANS(FPACK16, VIS1, do_fd, a, gen_op_fpack16) 43142f722641SRichard Henderson TRANS(FPACKFIX, VIS1, do_fd, a, gen_op_fpackfix) 43152f722641SRichard Henderson 4316119cb94fSRichard Henderson static bool do_env_ff(DisasContext *dc, arg_r_r *a, 4317119cb94fSRichard Henderson void (*func)(TCGv_i32, TCGv_env, TCGv_i32)) 4318119cb94fSRichard Henderson { 4319119cb94fSRichard Henderson TCGv_i32 tmp; 4320119cb94fSRichard Henderson 4321119cb94fSRichard Henderson if (gen_trap_ifnofpu(dc)) { 4322119cb94fSRichard Henderson return true; 4323119cb94fSRichard Henderson } 4324119cb94fSRichard Henderson 4325119cb94fSRichard Henderson tmp = gen_load_fpr_F(dc, a->rs); 4326119cb94fSRichard Henderson func(tmp, tcg_env, tmp); 4327119cb94fSRichard Henderson gen_store_fpr_F(dc, a->rd, tmp); 4328119cb94fSRichard Henderson return advance_pc(dc); 4329119cb94fSRichard Henderson } 4330119cb94fSRichard Henderson 4331119cb94fSRichard Henderson TRANS(FSQRTs, ALL, do_env_ff, a, gen_helper_fsqrts) 4332119cb94fSRichard Henderson TRANS(FiTOs, ALL, do_env_ff, a, gen_helper_fitos) 4333119cb94fSRichard Henderson TRANS(FsTOi, ALL, do_env_ff, a, gen_helper_fstoi) 4334119cb94fSRichard Henderson 43358c94bcd8SRichard Henderson static bool do_env_fd(DisasContext *dc, arg_r_r *a, 43368c94bcd8SRichard Henderson void (*func)(TCGv_i32, TCGv_env, TCGv_i64)) 43378c94bcd8SRichard Henderson { 43388c94bcd8SRichard Henderson TCGv_i32 dst; 43398c94bcd8SRichard Henderson TCGv_i64 src; 43408c94bcd8SRichard Henderson 43418c94bcd8SRichard Henderson if (gen_trap_ifnofpu(dc)) { 43428c94bcd8SRichard Henderson return true; 43438c94bcd8SRichard Henderson } 43448c94bcd8SRichard Henderson 4345388a6465SRichard Henderson dst = tcg_temp_new_i32(); 43468c94bcd8SRichard Henderson src = gen_load_fpr_D(dc, a->rs); 43478c94bcd8SRichard Henderson func(dst, tcg_env, src); 43488c94bcd8SRichard Henderson gen_store_fpr_F(dc, a->rd, dst); 43498c94bcd8SRichard Henderson return advance_pc(dc); 43508c94bcd8SRichard Henderson } 43518c94bcd8SRichard Henderson 43528c94bcd8SRichard Henderson TRANS(FdTOs, ALL, do_env_fd, a, gen_helper_fdtos) 43538c94bcd8SRichard Henderson TRANS(FdTOi, ALL, do_env_fd, a, gen_helper_fdtoi) 43548c94bcd8SRichard Henderson TRANS(FxTOs, 64, do_env_fd, a, gen_helper_fxtos) 43558c94bcd8SRichard Henderson 4356c6d83e4fSRichard Henderson static bool do_dd(DisasContext *dc, arg_r_r *a, 4357c6d83e4fSRichard Henderson void (*func)(TCGv_i64, TCGv_i64)) 4358c6d83e4fSRichard Henderson { 4359c6d83e4fSRichard Henderson TCGv_i64 dst, src; 4360c6d83e4fSRichard Henderson 4361c6d83e4fSRichard Henderson if (gen_trap_ifnofpu(dc)) { 4362c6d83e4fSRichard Henderson return true; 4363c6d83e4fSRichard Henderson } 4364c6d83e4fSRichard Henderson 436552f46d46SRichard Henderson dst = tcg_temp_new_i64(); 4366c6d83e4fSRichard Henderson src = gen_load_fpr_D(dc, a->rs); 4367c6d83e4fSRichard Henderson func(dst, src); 4368c6d83e4fSRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 4369c6d83e4fSRichard Henderson return advance_pc(dc); 4370c6d83e4fSRichard Henderson } 4371c6d83e4fSRichard Henderson 4372c6d83e4fSRichard Henderson TRANS(FMOVd, 64, do_dd, a, gen_op_fmovd) 4373c6d83e4fSRichard Henderson TRANS(FNEGd, 64, do_dd, a, gen_op_fnegd) 4374c6d83e4fSRichard Henderson TRANS(FABSd, 64, do_dd, a, gen_op_fabsd) 4375c6d83e4fSRichard Henderson TRANS(FSRCd, VIS1, do_dd, a, tcg_gen_mov_i64) 4376c6d83e4fSRichard Henderson TRANS(FNOTd, VIS1, do_dd, a, tcg_gen_not_i64) 4377c6d83e4fSRichard Henderson 43788aa418b3SRichard Henderson static bool do_env_dd(DisasContext *dc, arg_r_r *a, 43798aa418b3SRichard Henderson void (*func)(TCGv_i64, TCGv_env, TCGv_i64)) 43808aa418b3SRichard Henderson { 43818aa418b3SRichard Henderson TCGv_i64 dst, src; 43828aa418b3SRichard Henderson 43838aa418b3SRichard Henderson if (gen_trap_ifnofpu(dc)) { 43848aa418b3SRichard Henderson return true; 43858aa418b3SRichard Henderson } 43868aa418b3SRichard Henderson 438752f46d46SRichard Henderson dst = tcg_temp_new_i64(); 43888aa418b3SRichard Henderson src = gen_load_fpr_D(dc, a->rs); 43898aa418b3SRichard Henderson func(dst, tcg_env, src); 43908aa418b3SRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 43918aa418b3SRichard Henderson return advance_pc(dc); 43928aa418b3SRichard Henderson } 43938aa418b3SRichard Henderson 43948aa418b3SRichard Henderson TRANS(FSQRTd, ALL, do_env_dd, a, gen_helper_fsqrtd) 43958aa418b3SRichard Henderson TRANS(FxTOd, 64, do_env_dd, a, gen_helper_fxtod) 43968aa418b3SRichard Henderson TRANS(FdTOx, 64, do_env_dd, a, gen_helper_fdtox) 43978aa418b3SRichard Henderson 43987b616f36SRichard Henderson static bool do_df(DisasContext *dc, arg_r_r *a, 43997b616f36SRichard Henderson void (*func)(TCGv_i64, TCGv_i32)) 44007b616f36SRichard Henderson { 44017b616f36SRichard Henderson TCGv_i64 dst; 44027b616f36SRichard Henderson TCGv_i32 src; 44037b616f36SRichard Henderson 44047b616f36SRichard Henderson if (gen_trap_ifnofpu(dc)) { 44057b616f36SRichard Henderson return true; 44067b616f36SRichard Henderson } 44077b616f36SRichard Henderson 44087b616f36SRichard Henderson dst = tcg_temp_new_i64(); 44097b616f36SRichard Henderson src = gen_load_fpr_F(dc, a->rs); 44107b616f36SRichard Henderson func(dst, src); 44117b616f36SRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 44127b616f36SRichard Henderson return advance_pc(dc); 44137b616f36SRichard Henderson } 44147b616f36SRichard Henderson 44157b616f36SRichard Henderson TRANS(FEXPAND, VIS1, do_df, a, gen_helper_fexpand) 44167b616f36SRichard Henderson 4417199d43efSRichard Henderson static bool do_env_df(DisasContext *dc, arg_r_r *a, 4418199d43efSRichard Henderson void (*func)(TCGv_i64, TCGv_env, TCGv_i32)) 4419199d43efSRichard Henderson { 4420199d43efSRichard Henderson TCGv_i64 dst; 4421199d43efSRichard Henderson TCGv_i32 src; 4422199d43efSRichard Henderson 4423199d43efSRichard Henderson if (gen_trap_ifnofpu(dc)) { 4424199d43efSRichard Henderson return true; 4425199d43efSRichard Henderson } 4426199d43efSRichard Henderson 442752f46d46SRichard Henderson dst = tcg_temp_new_i64(); 4428199d43efSRichard Henderson src = gen_load_fpr_F(dc, a->rs); 4429199d43efSRichard Henderson func(dst, tcg_env, src); 4430199d43efSRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 4431199d43efSRichard Henderson return advance_pc(dc); 4432199d43efSRichard Henderson } 4433199d43efSRichard Henderson 4434199d43efSRichard Henderson TRANS(FiTOd, ALL, do_env_df, a, gen_helper_fitod) 4435199d43efSRichard Henderson TRANS(FsTOd, ALL, do_env_df, a, gen_helper_fstod) 4436199d43efSRichard Henderson TRANS(FsTOx, 64, do_env_df, a, gen_helper_fstox) 4437199d43efSRichard Henderson 4438daf457d4SRichard Henderson static bool do_qq(DisasContext *dc, arg_r_r *a, 4439daf457d4SRichard Henderson void (*func)(TCGv_i128, TCGv_i128)) 4440f4e18df5SRichard Henderson { 444133ec4245SRichard Henderson TCGv_i128 t; 4442f4e18df5SRichard Henderson 4443f4e18df5SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4444f4e18df5SRichard Henderson return true; 4445f4e18df5SRichard Henderson } 4446f4e18df5SRichard Henderson if (gen_trap_float128(dc)) { 4447f4e18df5SRichard Henderson return true; 4448f4e18df5SRichard Henderson } 4449f4e18df5SRichard Henderson 4450f4e18df5SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 445133ec4245SRichard Henderson t = gen_load_fpr_Q(dc, a->rs); 4452daf457d4SRichard Henderson func(t, t); 445333ec4245SRichard Henderson gen_store_fpr_Q(dc, a->rd, t); 4454f4e18df5SRichard Henderson return advance_pc(dc); 4455f4e18df5SRichard Henderson } 4456f4e18df5SRichard Henderson 4457daf457d4SRichard Henderson TRANS(FMOVq, 64, do_qq, a, tcg_gen_mov_i128) 4458daf457d4SRichard Henderson TRANS(FNEGq, 64, do_qq, a, gen_op_fnegq) 4459daf457d4SRichard Henderson TRANS(FABSq, 64, do_qq, a, gen_op_fabsq) 4460f4e18df5SRichard Henderson 4461c995216bSRichard Henderson static bool do_env_qq(DisasContext *dc, arg_r_r *a, 4462e41716beSRichard Henderson void (*func)(TCGv_i128, TCGv_env, TCGv_i128)) 4463c995216bSRichard Henderson { 4464e41716beSRichard Henderson TCGv_i128 t; 4465e41716beSRichard Henderson 4466c995216bSRichard Henderson if (gen_trap_ifnofpu(dc)) { 4467c995216bSRichard Henderson return true; 4468c995216bSRichard Henderson } 4469c995216bSRichard Henderson if (gen_trap_float128(dc)) { 4470c995216bSRichard Henderson return true; 4471c995216bSRichard Henderson } 4472c995216bSRichard Henderson 4473e41716beSRichard Henderson t = gen_load_fpr_Q(dc, a->rs); 4474e41716beSRichard Henderson func(t, tcg_env, t); 4475e41716beSRichard Henderson gen_store_fpr_Q(dc, a->rd, t); 4476c995216bSRichard Henderson return advance_pc(dc); 4477c995216bSRichard Henderson } 4478c995216bSRichard Henderson 4479c995216bSRichard Henderson TRANS(FSQRTq, ALL, do_env_qq, a, gen_helper_fsqrtq) 4480c995216bSRichard Henderson 4481bd9c5c42SRichard Henderson static bool do_env_fq(DisasContext *dc, arg_r_r *a, 4482d81e3efeSRichard Henderson void (*func)(TCGv_i32, TCGv_env, TCGv_i128)) 4483bd9c5c42SRichard Henderson { 4484d81e3efeSRichard Henderson TCGv_i128 src; 4485bd9c5c42SRichard Henderson TCGv_i32 dst; 4486bd9c5c42SRichard Henderson 4487bd9c5c42SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4488bd9c5c42SRichard Henderson return true; 4489bd9c5c42SRichard Henderson } 4490bd9c5c42SRichard Henderson if (gen_trap_float128(dc)) { 4491bd9c5c42SRichard Henderson return true; 4492bd9c5c42SRichard Henderson } 4493bd9c5c42SRichard Henderson 4494d81e3efeSRichard Henderson src = gen_load_fpr_Q(dc, a->rs); 4495388a6465SRichard Henderson dst = tcg_temp_new_i32(); 4496d81e3efeSRichard Henderson func(dst, tcg_env, src); 4497bd9c5c42SRichard Henderson gen_store_fpr_F(dc, a->rd, dst); 4498bd9c5c42SRichard Henderson return advance_pc(dc); 4499bd9c5c42SRichard Henderson } 4500bd9c5c42SRichard Henderson 4501bd9c5c42SRichard Henderson TRANS(FqTOs, ALL, do_env_fq, a, gen_helper_fqtos) 4502bd9c5c42SRichard Henderson TRANS(FqTOi, ALL, do_env_fq, a, gen_helper_fqtoi) 4503bd9c5c42SRichard Henderson 45041617586fSRichard Henderson static bool do_env_dq(DisasContext *dc, arg_r_r *a, 450525a5769eSRichard Henderson void (*func)(TCGv_i64, TCGv_env, TCGv_i128)) 45061617586fSRichard Henderson { 450725a5769eSRichard Henderson TCGv_i128 src; 45081617586fSRichard Henderson TCGv_i64 dst; 45091617586fSRichard Henderson 45101617586fSRichard Henderson if (gen_trap_ifnofpu(dc)) { 45111617586fSRichard Henderson return true; 45121617586fSRichard Henderson } 45131617586fSRichard Henderson if (gen_trap_float128(dc)) { 45141617586fSRichard Henderson return true; 45151617586fSRichard Henderson } 45161617586fSRichard Henderson 451725a5769eSRichard Henderson src = gen_load_fpr_Q(dc, a->rs); 451852f46d46SRichard Henderson dst = tcg_temp_new_i64(); 451925a5769eSRichard Henderson func(dst, tcg_env, src); 45201617586fSRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 45211617586fSRichard Henderson return advance_pc(dc); 45221617586fSRichard Henderson } 45231617586fSRichard Henderson 45241617586fSRichard Henderson TRANS(FqTOd, ALL, do_env_dq, a, gen_helper_fqtod) 45251617586fSRichard Henderson TRANS(FqTOx, 64, do_env_dq, a, gen_helper_fqtox) 45261617586fSRichard Henderson 452713ebcc77SRichard Henderson static bool do_env_qf(DisasContext *dc, arg_r_r *a, 45280b2a61ccSRichard Henderson void (*func)(TCGv_i128, TCGv_env, TCGv_i32)) 452913ebcc77SRichard Henderson { 453013ebcc77SRichard Henderson TCGv_i32 src; 45310b2a61ccSRichard Henderson TCGv_i128 dst; 453213ebcc77SRichard Henderson 453313ebcc77SRichard Henderson if (gen_trap_ifnofpu(dc)) { 453413ebcc77SRichard Henderson return true; 453513ebcc77SRichard Henderson } 453613ebcc77SRichard Henderson if (gen_trap_float128(dc)) { 453713ebcc77SRichard Henderson return true; 453813ebcc77SRichard Henderson } 453913ebcc77SRichard Henderson 454013ebcc77SRichard Henderson src = gen_load_fpr_F(dc, a->rs); 45410b2a61ccSRichard Henderson dst = tcg_temp_new_i128(); 45420b2a61ccSRichard Henderson func(dst, tcg_env, src); 45430b2a61ccSRichard Henderson gen_store_fpr_Q(dc, a->rd, dst); 454413ebcc77SRichard Henderson return advance_pc(dc); 454513ebcc77SRichard Henderson } 454613ebcc77SRichard Henderson 454713ebcc77SRichard Henderson TRANS(FiTOq, ALL, do_env_qf, a, gen_helper_fitoq) 454813ebcc77SRichard Henderson TRANS(FsTOq, ALL, do_env_qf, a, gen_helper_fstoq) 454913ebcc77SRichard Henderson 45507b8e3e1aSRichard Henderson static bool do_env_qd(DisasContext *dc, arg_r_r *a, 4551fdc50716SRichard Henderson void (*func)(TCGv_i128, TCGv_env, TCGv_i64)) 45527b8e3e1aSRichard Henderson { 45537b8e3e1aSRichard Henderson TCGv_i64 src; 4554fdc50716SRichard Henderson TCGv_i128 dst; 45557b8e3e1aSRichard Henderson 45567b8e3e1aSRichard Henderson if (gen_trap_ifnofpu(dc)) { 45577b8e3e1aSRichard Henderson return true; 45587b8e3e1aSRichard Henderson } 45597b8e3e1aSRichard Henderson if (gen_trap_float128(dc)) { 45607b8e3e1aSRichard Henderson return true; 45617b8e3e1aSRichard Henderson } 45627b8e3e1aSRichard Henderson 45637b8e3e1aSRichard Henderson src = gen_load_fpr_D(dc, a->rs); 4564fdc50716SRichard Henderson dst = tcg_temp_new_i128(); 4565fdc50716SRichard Henderson func(dst, tcg_env, src); 4566fdc50716SRichard Henderson gen_store_fpr_Q(dc, a->rd, dst); 45677b8e3e1aSRichard Henderson return advance_pc(dc); 45687b8e3e1aSRichard Henderson } 45697b8e3e1aSRichard Henderson 45707b8e3e1aSRichard Henderson TRANS(FdTOq, ALL, do_env_qd, a, gen_helper_fdtoq) 45717b8e3e1aSRichard Henderson TRANS(FxTOq, 64, do_env_qd, a, gen_helper_fxtoq) 45727b8e3e1aSRichard Henderson 45737f10b52fSRichard Henderson static bool do_fff(DisasContext *dc, arg_r_r_r *a, 45747f10b52fSRichard Henderson void (*func)(TCGv_i32, TCGv_i32, TCGv_i32)) 45757f10b52fSRichard Henderson { 45767f10b52fSRichard Henderson TCGv_i32 src1, src2; 45777f10b52fSRichard Henderson 45787f10b52fSRichard Henderson if (gen_trap_ifnofpu(dc)) { 45797f10b52fSRichard Henderson return true; 45807f10b52fSRichard Henderson } 45817f10b52fSRichard Henderson 45827f10b52fSRichard Henderson src1 = gen_load_fpr_F(dc, a->rs1); 45837f10b52fSRichard Henderson src2 = gen_load_fpr_F(dc, a->rs2); 45847f10b52fSRichard Henderson func(src1, src1, src2); 45857f10b52fSRichard Henderson gen_store_fpr_F(dc, a->rd, src1); 45867f10b52fSRichard Henderson return advance_pc(dc); 45877f10b52fSRichard Henderson } 45887f10b52fSRichard Henderson 45897f10b52fSRichard Henderson TRANS(FPADD16s, VIS1, do_fff, a, tcg_gen_vec_add16_i32) 45907f10b52fSRichard Henderson TRANS(FPADD32s, VIS1, do_fff, a, tcg_gen_add_i32) 45917f10b52fSRichard Henderson TRANS(FPSUB16s, VIS1, do_fff, a, tcg_gen_vec_sub16_i32) 45927f10b52fSRichard Henderson TRANS(FPSUB32s, VIS1, do_fff, a, tcg_gen_sub_i32) 45937f10b52fSRichard Henderson TRANS(FNORs, VIS1, do_fff, a, tcg_gen_nor_i32) 45947f10b52fSRichard Henderson TRANS(FANDNOTs, VIS1, do_fff, a, tcg_gen_andc_i32) 45957f10b52fSRichard Henderson TRANS(FXORs, VIS1, do_fff, a, tcg_gen_xor_i32) 45967f10b52fSRichard Henderson TRANS(FNANDs, VIS1, do_fff, a, tcg_gen_nand_i32) 45977f10b52fSRichard Henderson TRANS(FANDs, VIS1, do_fff, a, tcg_gen_and_i32) 45987f10b52fSRichard Henderson TRANS(FXNORs, VIS1, do_fff, a, tcg_gen_eqv_i32) 45997f10b52fSRichard Henderson TRANS(FORNOTs, VIS1, do_fff, a, tcg_gen_orc_i32) 46007f10b52fSRichard Henderson TRANS(FORs, VIS1, do_fff, a, tcg_gen_or_i32) 46017f10b52fSRichard Henderson 4602c1514961SRichard Henderson static bool do_env_fff(DisasContext *dc, arg_r_r_r *a, 4603c1514961SRichard Henderson void (*func)(TCGv_i32, TCGv_env, TCGv_i32, TCGv_i32)) 4604c1514961SRichard Henderson { 4605c1514961SRichard Henderson TCGv_i32 src1, src2; 4606c1514961SRichard Henderson 4607c1514961SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4608c1514961SRichard Henderson return true; 4609c1514961SRichard Henderson } 4610c1514961SRichard Henderson 4611c1514961SRichard Henderson src1 = gen_load_fpr_F(dc, a->rs1); 4612c1514961SRichard Henderson src2 = gen_load_fpr_F(dc, a->rs2); 4613c1514961SRichard Henderson func(src1, tcg_env, src1, src2); 4614c1514961SRichard Henderson gen_store_fpr_F(dc, a->rd, src1); 4615c1514961SRichard Henderson return advance_pc(dc); 4616c1514961SRichard Henderson } 4617c1514961SRichard Henderson 4618c1514961SRichard Henderson TRANS(FADDs, ALL, do_env_fff, a, gen_helper_fadds) 4619c1514961SRichard Henderson TRANS(FSUBs, ALL, do_env_fff, a, gen_helper_fsubs) 4620c1514961SRichard Henderson TRANS(FMULs, ALL, do_env_fff, a, gen_helper_fmuls) 4621c1514961SRichard Henderson TRANS(FDIVs, ALL, do_env_fff, a, gen_helper_fdivs) 4622c1514961SRichard Henderson 4623a859602cSRichard Henderson static bool do_dff(DisasContext *dc, arg_r_r_r *a, 4624a859602cSRichard Henderson void (*func)(TCGv_i64, TCGv_i32, TCGv_i32)) 4625a859602cSRichard Henderson { 4626a859602cSRichard Henderson TCGv_i64 dst; 4627a859602cSRichard Henderson TCGv_i32 src1, src2; 4628a859602cSRichard Henderson 4629a859602cSRichard Henderson if (gen_trap_ifnofpu(dc)) { 4630a859602cSRichard Henderson return true; 4631a859602cSRichard Henderson } 4632a859602cSRichard Henderson 463352f46d46SRichard Henderson dst = tcg_temp_new_i64(); 4634a859602cSRichard Henderson src1 = gen_load_fpr_F(dc, a->rs1); 4635a859602cSRichard Henderson src2 = gen_load_fpr_F(dc, a->rs2); 4636a859602cSRichard Henderson func(dst, src1, src2); 4637a859602cSRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 4638a859602cSRichard Henderson return advance_pc(dc); 4639a859602cSRichard Henderson } 4640a859602cSRichard Henderson 4641a859602cSRichard Henderson TRANS(FMUL8x16AU, VIS1, do_dff, a, gen_op_fmul8x16au) 4642a859602cSRichard Henderson TRANS(FMUL8x16AL, VIS1, do_dff, a, gen_op_fmul8x16al) 4643be8998e0SRichard Henderson TRANS(FMULD8SUx16, VIS1, do_dff, a, gen_op_fmuld8sux16) 4644be8998e0SRichard Henderson TRANS(FMULD8ULx16, VIS1, do_dff, a, gen_op_fmuld8ulx16) 4645d3ef26afSRichard Henderson TRANS(FPMERGE, VIS1, do_dff, a, gen_helper_fpmerge) 4646a859602cSRichard Henderson 46479157dcccSRichard Henderson static bool do_dfd(DisasContext *dc, arg_r_r_r *a, 46489157dcccSRichard Henderson void (*func)(TCGv_i64, TCGv_i32, TCGv_i64)) 46499157dcccSRichard Henderson { 46509157dcccSRichard Henderson TCGv_i64 dst, src2; 46519157dcccSRichard Henderson TCGv_i32 src1; 46529157dcccSRichard Henderson 46539157dcccSRichard Henderson if (gen_trap_ifnofpu(dc)) { 46549157dcccSRichard Henderson return true; 46559157dcccSRichard Henderson } 46569157dcccSRichard Henderson 465752f46d46SRichard Henderson dst = tcg_temp_new_i64(); 46589157dcccSRichard Henderson src1 = gen_load_fpr_F(dc, a->rs1); 46599157dcccSRichard Henderson src2 = gen_load_fpr_D(dc, a->rs2); 46609157dcccSRichard Henderson func(dst, src1, src2); 46619157dcccSRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 46629157dcccSRichard Henderson return advance_pc(dc); 46639157dcccSRichard Henderson } 46649157dcccSRichard Henderson 46659157dcccSRichard Henderson TRANS(FMUL8x16, VIS1, do_dfd, a, gen_helper_fmul8x16) 46669157dcccSRichard Henderson 4667*28c131a3SRichard Henderson static bool do_gvec_ddd(DisasContext *dc, arg_r_r_r *a, MemOp vece, 4668*28c131a3SRichard Henderson void (*func)(unsigned, uint32_t, uint32_t, 4669*28c131a3SRichard Henderson uint32_t, uint32_t, uint32_t)) 4670*28c131a3SRichard Henderson { 4671*28c131a3SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4672*28c131a3SRichard Henderson return true; 4673*28c131a3SRichard Henderson } 4674*28c131a3SRichard Henderson 4675*28c131a3SRichard Henderson func(vece, gen_offset_fpr_D(a->rd), gen_offset_fpr_D(a->rs1), 4676*28c131a3SRichard Henderson gen_offset_fpr_D(a->rs2), 8, 8); 4677*28c131a3SRichard Henderson return advance_pc(dc); 4678*28c131a3SRichard Henderson } 4679*28c131a3SRichard Henderson 4680*28c131a3SRichard Henderson TRANS(FPADD16, VIS1, do_gvec_ddd, a, MO_16, tcg_gen_gvec_add) 4681*28c131a3SRichard Henderson TRANS(FPADD32, VIS1, do_gvec_ddd, a, MO_32, tcg_gen_gvec_add) 4682*28c131a3SRichard Henderson TRANS(FPSUB16, VIS1, do_gvec_ddd, a, MO_16, tcg_gen_gvec_sub) 4683*28c131a3SRichard Henderson TRANS(FPSUB32, VIS1, do_gvec_ddd, a, MO_32, tcg_gen_gvec_sub) 4684*28c131a3SRichard Henderson 4685e06c9f83SRichard Henderson static bool do_ddd(DisasContext *dc, arg_r_r_r *a, 4686e06c9f83SRichard Henderson void (*func)(TCGv_i64, TCGv_i64, TCGv_i64)) 4687e06c9f83SRichard Henderson { 4688e06c9f83SRichard Henderson TCGv_i64 dst, src1, src2; 4689e06c9f83SRichard Henderson 4690e06c9f83SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4691e06c9f83SRichard Henderson return true; 4692e06c9f83SRichard Henderson } 4693e06c9f83SRichard Henderson 469452f46d46SRichard Henderson dst = tcg_temp_new_i64(); 4695e06c9f83SRichard Henderson src1 = gen_load_fpr_D(dc, a->rs1); 4696e06c9f83SRichard Henderson src2 = gen_load_fpr_D(dc, a->rs2); 4697e06c9f83SRichard Henderson func(dst, src1, src2); 4698e06c9f83SRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 4699e06c9f83SRichard Henderson return advance_pc(dc); 4700e06c9f83SRichard Henderson } 4701e06c9f83SRichard Henderson 4702e06c9f83SRichard Henderson TRANS(FMUL8SUx16, VIS1, do_ddd, a, gen_helper_fmul8sux16) 4703e06c9f83SRichard Henderson TRANS(FMUL8ULx16, VIS1, do_ddd, a, gen_helper_fmul8ulx16) 4704e06c9f83SRichard Henderson 4705e06c9f83SRichard Henderson TRANS(FNORd, VIS1, do_ddd, a, tcg_gen_nor_i64) 4706e06c9f83SRichard Henderson TRANS(FANDNOTd, VIS1, do_ddd, a, tcg_gen_andc_i64) 4707e06c9f83SRichard Henderson TRANS(FXORd, VIS1, do_ddd, a, tcg_gen_xor_i64) 4708e06c9f83SRichard Henderson TRANS(FNANDd, VIS1, do_ddd, a, tcg_gen_nand_i64) 4709e06c9f83SRichard Henderson TRANS(FANDd, VIS1, do_ddd, a, tcg_gen_and_i64) 4710e06c9f83SRichard Henderson TRANS(FXNORd, VIS1, do_ddd, a, tcg_gen_eqv_i64) 4711e06c9f83SRichard Henderson TRANS(FORNOTd, VIS1, do_ddd, a, tcg_gen_orc_i64) 4712e06c9f83SRichard Henderson TRANS(FORd, VIS1, do_ddd, a, tcg_gen_or_i64) 4713e06c9f83SRichard Henderson 47144b6edc0aSRichard Henderson TRANS(FPACK32, VIS1, do_ddd, a, gen_op_fpack32) 47154b6edc0aSRichard Henderson TRANS(FALIGNDATAg, VIS1, do_ddd, a, gen_op_faligndata) 47164b6edc0aSRichard Henderson TRANS(BSHUFFLE, VIS2, do_ddd, a, gen_op_bshuffle) 47174b6edc0aSRichard Henderson 4718e2fa6bd1SRichard Henderson static bool do_rdd(DisasContext *dc, arg_r_r_r *a, 4719e2fa6bd1SRichard Henderson void (*func)(TCGv, TCGv_i64, TCGv_i64)) 4720e2fa6bd1SRichard Henderson { 4721e2fa6bd1SRichard Henderson TCGv_i64 src1, src2; 4722e2fa6bd1SRichard Henderson TCGv dst; 4723e2fa6bd1SRichard Henderson 4724e2fa6bd1SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4725e2fa6bd1SRichard Henderson return true; 4726e2fa6bd1SRichard Henderson } 4727e2fa6bd1SRichard Henderson 4728e2fa6bd1SRichard Henderson dst = gen_dest_gpr(dc, a->rd); 4729e2fa6bd1SRichard Henderson src1 = gen_load_fpr_D(dc, a->rs1); 4730e2fa6bd1SRichard Henderson src2 = gen_load_fpr_D(dc, a->rs2); 4731e2fa6bd1SRichard Henderson func(dst, src1, src2); 4732e2fa6bd1SRichard Henderson gen_store_gpr(dc, a->rd, dst); 4733e2fa6bd1SRichard Henderson return advance_pc(dc); 4734e2fa6bd1SRichard Henderson } 4735e2fa6bd1SRichard Henderson 4736e2fa6bd1SRichard Henderson TRANS(FPCMPLE16, VIS1, do_rdd, a, gen_helper_fcmple16) 4737e2fa6bd1SRichard Henderson TRANS(FPCMPNE16, VIS1, do_rdd, a, gen_helper_fcmpne16) 4738e2fa6bd1SRichard Henderson TRANS(FPCMPGT16, VIS1, do_rdd, a, gen_helper_fcmpgt16) 4739e2fa6bd1SRichard Henderson TRANS(FPCMPEQ16, VIS1, do_rdd, a, gen_helper_fcmpeq16) 4740e2fa6bd1SRichard Henderson 4741e2fa6bd1SRichard Henderson TRANS(FPCMPLE32, VIS1, do_rdd, a, gen_helper_fcmple32) 4742e2fa6bd1SRichard Henderson TRANS(FPCMPNE32, VIS1, do_rdd, a, gen_helper_fcmpne32) 4743e2fa6bd1SRichard Henderson TRANS(FPCMPGT32, VIS1, do_rdd, a, gen_helper_fcmpgt32) 4744e2fa6bd1SRichard Henderson TRANS(FPCMPEQ32, VIS1, do_rdd, a, gen_helper_fcmpeq32) 4745e2fa6bd1SRichard Henderson 4746f2a59b0aSRichard Henderson static bool do_env_ddd(DisasContext *dc, arg_r_r_r *a, 4747f2a59b0aSRichard Henderson void (*func)(TCGv_i64, TCGv_env, TCGv_i64, TCGv_i64)) 4748f2a59b0aSRichard Henderson { 4749f2a59b0aSRichard Henderson TCGv_i64 dst, src1, src2; 4750f2a59b0aSRichard Henderson 4751f2a59b0aSRichard Henderson if (gen_trap_ifnofpu(dc)) { 4752f2a59b0aSRichard Henderson return true; 4753f2a59b0aSRichard Henderson } 4754f2a59b0aSRichard Henderson 475552f46d46SRichard Henderson dst = tcg_temp_new_i64(); 4756f2a59b0aSRichard Henderson src1 = gen_load_fpr_D(dc, a->rs1); 4757f2a59b0aSRichard Henderson src2 = gen_load_fpr_D(dc, a->rs2); 4758f2a59b0aSRichard Henderson func(dst, tcg_env, src1, src2); 4759f2a59b0aSRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 4760f2a59b0aSRichard Henderson return advance_pc(dc); 4761f2a59b0aSRichard Henderson } 4762f2a59b0aSRichard Henderson 4763f2a59b0aSRichard Henderson TRANS(FADDd, ALL, do_env_ddd, a, gen_helper_faddd) 4764f2a59b0aSRichard Henderson TRANS(FSUBd, ALL, do_env_ddd, a, gen_helper_fsubd) 4765f2a59b0aSRichard Henderson TRANS(FMULd, ALL, do_env_ddd, a, gen_helper_fmuld) 4766f2a59b0aSRichard Henderson TRANS(FDIVd, ALL, do_env_ddd, a, gen_helper_fdivd) 4767f2a59b0aSRichard Henderson 4768ff4c711bSRichard Henderson static bool trans_FsMULd(DisasContext *dc, arg_r_r_r *a) 4769ff4c711bSRichard Henderson { 4770ff4c711bSRichard Henderson TCGv_i64 dst; 4771ff4c711bSRichard Henderson TCGv_i32 src1, src2; 4772ff4c711bSRichard Henderson 4773ff4c711bSRichard Henderson if (gen_trap_ifnofpu(dc)) { 4774ff4c711bSRichard Henderson return true; 4775ff4c711bSRichard Henderson } 4776ff4c711bSRichard Henderson if (!(dc->def->features & CPU_FEATURE_FSMULD)) { 4777ff4c711bSRichard Henderson return raise_unimpfpop(dc); 4778ff4c711bSRichard Henderson } 4779ff4c711bSRichard Henderson 478052f46d46SRichard Henderson dst = tcg_temp_new_i64(); 4781ff4c711bSRichard Henderson src1 = gen_load_fpr_F(dc, a->rs1); 4782ff4c711bSRichard Henderson src2 = gen_load_fpr_F(dc, a->rs2); 4783ff4c711bSRichard Henderson gen_helper_fsmuld(dst, tcg_env, src1, src2); 4784ff4c711bSRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 4785ff4c711bSRichard Henderson return advance_pc(dc); 4786ff4c711bSRichard Henderson } 4787ff4c711bSRichard Henderson 4788afb04344SRichard Henderson static bool do_dddd(DisasContext *dc, arg_r_r_r *a, 4789afb04344SRichard Henderson void (*func)(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_i64)) 4790afb04344SRichard Henderson { 4791afb04344SRichard Henderson TCGv_i64 dst, src0, src1, src2; 4792afb04344SRichard Henderson 4793afb04344SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4794afb04344SRichard Henderson return true; 4795afb04344SRichard Henderson } 4796afb04344SRichard Henderson 479752f46d46SRichard Henderson dst = tcg_temp_new_i64(); 4798afb04344SRichard Henderson src0 = gen_load_fpr_D(dc, a->rd); 4799afb04344SRichard Henderson src1 = gen_load_fpr_D(dc, a->rs1); 4800afb04344SRichard Henderson src2 = gen_load_fpr_D(dc, a->rs2); 4801afb04344SRichard Henderson func(dst, src0, src1, src2); 4802afb04344SRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 4803afb04344SRichard Henderson return advance_pc(dc); 4804afb04344SRichard Henderson } 4805afb04344SRichard Henderson 4806afb04344SRichard Henderson TRANS(PDIST, VIS1, do_dddd, a, gen_helper_pdist) 4807afb04344SRichard Henderson 4808a4056239SRichard Henderson static bool do_env_qqq(DisasContext *dc, arg_r_r_r *a, 480916bedf89SRichard Henderson void (*func)(TCGv_i128, TCGv_env, TCGv_i128, TCGv_i128)) 4810a4056239SRichard Henderson { 481116bedf89SRichard Henderson TCGv_i128 src1, src2; 481216bedf89SRichard Henderson 4813a4056239SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4814a4056239SRichard Henderson return true; 4815a4056239SRichard Henderson } 4816a4056239SRichard Henderson if (gen_trap_float128(dc)) { 4817a4056239SRichard Henderson return true; 4818a4056239SRichard Henderson } 4819a4056239SRichard Henderson 482016bedf89SRichard Henderson src1 = gen_load_fpr_Q(dc, a->rs1); 482116bedf89SRichard Henderson src2 = gen_load_fpr_Q(dc, a->rs2); 482216bedf89SRichard Henderson func(src1, tcg_env, src1, src2); 482316bedf89SRichard Henderson gen_store_fpr_Q(dc, a->rd, src1); 4824a4056239SRichard Henderson return advance_pc(dc); 4825a4056239SRichard Henderson } 4826a4056239SRichard Henderson 4827a4056239SRichard Henderson TRANS(FADDq, ALL, do_env_qqq, a, gen_helper_faddq) 4828a4056239SRichard Henderson TRANS(FSUBq, ALL, do_env_qqq, a, gen_helper_fsubq) 4829a4056239SRichard Henderson TRANS(FMULq, ALL, do_env_qqq, a, gen_helper_fmulq) 4830a4056239SRichard Henderson TRANS(FDIVq, ALL, do_env_qqq, a, gen_helper_fdivq) 4831a4056239SRichard Henderson 48325e3b17bbSRichard Henderson static bool trans_FdMULq(DisasContext *dc, arg_r_r_r *a) 48335e3b17bbSRichard Henderson { 48345e3b17bbSRichard Henderson TCGv_i64 src1, src2; 4835ba21dc99SRichard Henderson TCGv_i128 dst; 48365e3b17bbSRichard Henderson 48375e3b17bbSRichard Henderson if (gen_trap_ifnofpu(dc)) { 48385e3b17bbSRichard Henderson return true; 48395e3b17bbSRichard Henderson } 48405e3b17bbSRichard Henderson if (gen_trap_float128(dc)) { 48415e3b17bbSRichard Henderson return true; 48425e3b17bbSRichard Henderson } 48435e3b17bbSRichard Henderson 48445e3b17bbSRichard Henderson src1 = gen_load_fpr_D(dc, a->rs1); 48455e3b17bbSRichard Henderson src2 = gen_load_fpr_D(dc, a->rs2); 4846ba21dc99SRichard Henderson dst = tcg_temp_new_i128(); 4847ba21dc99SRichard Henderson gen_helper_fdmulq(dst, tcg_env, src1, src2); 4848ba21dc99SRichard Henderson gen_store_fpr_Q(dc, a->rd, dst); 48495e3b17bbSRichard Henderson return advance_pc(dc); 48505e3b17bbSRichard Henderson } 48515e3b17bbSRichard Henderson 4852f7ec8155SRichard Henderson static bool do_fmovr(DisasContext *dc, arg_FMOVRs *a, bool is_128, 4853f7ec8155SRichard Henderson void (*func)(DisasContext *, DisasCompare *, int, int)) 4854f7ec8155SRichard Henderson { 4855f7ec8155SRichard Henderson DisasCompare cmp; 4856f7ec8155SRichard Henderson 48572c4f56c9SRichard Henderson if (!gen_compare_reg(&cmp, a->cond, gen_load_gpr(dc, a->rs1))) { 48582c4f56c9SRichard Henderson return false; 48592c4f56c9SRichard Henderson } 4860f7ec8155SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4861f7ec8155SRichard Henderson return true; 4862f7ec8155SRichard Henderson } 4863f7ec8155SRichard Henderson if (is_128 && gen_trap_float128(dc)) { 4864f7ec8155SRichard Henderson return true; 4865f7ec8155SRichard Henderson } 4866f7ec8155SRichard Henderson 4867f7ec8155SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 4868f7ec8155SRichard Henderson func(dc, &cmp, a->rd, a->rs2); 4869f7ec8155SRichard Henderson return advance_pc(dc); 4870f7ec8155SRichard Henderson } 4871f7ec8155SRichard Henderson 4872f7ec8155SRichard Henderson TRANS(FMOVRs, 64, do_fmovr, a, false, gen_fmovs) 4873f7ec8155SRichard Henderson TRANS(FMOVRd, 64, do_fmovr, a, false, gen_fmovd) 4874f7ec8155SRichard Henderson TRANS(FMOVRq, 64, do_fmovr, a, true, gen_fmovq) 4875f7ec8155SRichard Henderson 4876f7ec8155SRichard Henderson static bool do_fmovcc(DisasContext *dc, arg_FMOVscc *a, bool is_128, 4877f7ec8155SRichard Henderson void (*func)(DisasContext *, DisasCompare *, int, int)) 4878f7ec8155SRichard Henderson { 4879f7ec8155SRichard Henderson DisasCompare cmp; 4880f7ec8155SRichard Henderson 4881f7ec8155SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4882f7ec8155SRichard Henderson return true; 4883f7ec8155SRichard Henderson } 4884f7ec8155SRichard Henderson if (is_128 && gen_trap_float128(dc)) { 4885f7ec8155SRichard Henderson return true; 4886f7ec8155SRichard Henderson } 4887f7ec8155SRichard Henderson 4888f7ec8155SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 4889f7ec8155SRichard Henderson gen_compare(&cmp, a->cc, a->cond, dc); 4890f7ec8155SRichard Henderson func(dc, &cmp, a->rd, a->rs2); 4891f7ec8155SRichard Henderson return advance_pc(dc); 4892f7ec8155SRichard Henderson } 4893f7ec8155SRichard Henderson 4894f7ec8155SRichard Henderson TRANS(FMOVscc, 64, do_fmovcc, a, false, gen_fmovs) 4895f7ec8155SRichard Henderson TRANS(FMOVdcc, 64, do_fmovcc, a, false, gen_fmovd) 4896f7ec8155SRichard Henderson TRANS(FMOVqcc, 64, do_fmovcc, a, true, gen_fmovq) 4897f7ec8155SRichard Henderson 4898f7ec8155SRichard Henderson static bool do_fmovfcc(DisasContext *dc, arg_FMOVsfcc *a, bool is_128, 4899f7ec8155SRichard Henderson void (*func)(DisasContext *, DisasCompare *, int, int)) 4900f7ec8155SRichard Henderson { 4901f7ec8155SRichard Henderson DisasCompare cmp; 4902f7ec8155SRichard Henderson 4903f7ec8155SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4904f7ec8155SRichard Henderson return true; 4905f7ec8155SRichard Henderson } 4906f7ec8155SRichard Henderson if (is_128 && gen_trap_float128(dc)) { 4907f7ec8155SRichard Henderson return true; 4908f7ec8155SRichard Henderson } 4909f7ec8155SRichard Henderson 4910f7ec8155SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 4911f7ec8155SRichard Henderson gen_fcompare(&cmp, a->cc, a->cond); 4912f7ec8155SRichard Henderson func(dc, &cmp, a->rd, a->rs2); 4913f7ec8155SRichard Henderson return advance_pc(dc); 4914f7ec8155SRichard Henderson } 4915f7ec8155SRichard Henderson 4916f7ec8155SRichard Henderson TRANS(FMOVsfcc, 64, do_fmovfcc, a, false, gen_fmovs) 4917f7ec8155SRichard Henderson TRANS(FMOVdfcc, 64, do_fmovfcc, a, false, gen_fmovd) 4918f7ec8155SRichard Henderson TRANS(FMOVqfcc, 64, do_fmovfcc, a, true, gen_fmovq) 4919f7ec8155SRichard Henderson 492040f9ad21SRichard Henderson static bool do_fcmps(DisasContext *dc, arg_FCMPs *a, bool e) 492140f9ad21SRichard Henderson { 492240f9ad21SRichard Henderson TCGv_i32 src1, src2; 492340f9ad21SRichard Henderson 492440f9ad21SRichard Henderson if (avail_32(dc) && a->cc != 0) { 492540f9ad21SRichard Henderson return false; 492640f9ad21SRichard Henderson } 492740f9ad21SRichard Henderson if (gen_trap_ifnofpu(dc)) { 492840f9ad21SRichard Henderson return true; 492940f9ad21SRichard Henderson } 493040f9ad21SRichard Henderson 493140f9ad21SRichard Henderson src1 = gen_load_fpr_F(dc, a->rs1); 493240f9ad21SRichard Henderson src2 = gen_load_fpr_F(dc, a->rs2); 493340f9ad21SRichard Henderson if (e) { 4934d8c5b92fSRichard Henderson gen_helper_fcmpes(cpu_fcc[a->cc], tcg_env, src1, src2); 493540f9ad21SRichard Henderson } else { 4936d8c5b92fSRichard Henderson gen_helper_fcmps(cpu_fcc[a->cc], tcg_env, src1, src2); 493740f9ad21SRichard Henderson } 493840f9ad21SRichard Henderson return advance_pc(dc); 493940f9ad21SRichard Henderson } 494040f9ad21SRichard Henderson 494140f9ad21SRichard Henderson TRANS(FCMPs, ALL, do_fcmps, a, false) 494240f9ad21SRichard Henderson TRANS(FCMPEs, ALL, do_fcmps, a, true) 494340f9ad21SRichard Henderson 494440f9ad21SRichard Henderson static bool do_fcmpd(DisasContext *dc, arg_FCMPd *a, bool e) 494540f9ad21SRichard Henderson { 494640f9ad21SRichard Henderson TCGv_i64 src1, src2; 494740f9ad21SRichard Henderson 494840f9ad21SRichard Henderson if (avail_32(dc) && a->cc != 0) { 494940f9ad21SRichard Henderson return false; 495040f9ad21SRichard Henderson } 495140f9ad21SRichard Henderson if (gen_trap_ifnofpu(dc)) { 495240f9ad21SRichard Henderson return true; 495340f9ad21SRichard Henderson } 495440f9ad21SRichard Henderson 495540f9ad21SRichard Henderson src1 = gen_load_fpr_D(dc, a->rs1); 495640f9ad21SRichard Henderson src2 = gen_load_fpr_D(dc, a->rs2); 495740f9ad21SRichard Henderson if (e) { 4958d8c5b92fSRichard Henderson gen_helper_fcmped(cpu_fcc[a->cc], tcg_env, src1, src2); 495940f9ad21SRichard Henderson } else { 4960d8c5b92fSRichard Henderson gen_helper_fcmpd(cpu_fcc[a->cc], tcg_env, src1, src2); 496140f9ad21SRichard Henderson } 496240f9ad21SRichard Henderson return advance_pc(dc); 496340f9ad21SRichard Henderson } 496440f9ad21SRichard Henderson 496540f9ad21SRichard Henderson TRANS(FCMPd, ALL, do_fcmpd, a, false) 496640f9ad21SRichard Henderson TRANS(FCMPEd, ALL, do_fcmpd, a, true) 496740f9ad21SRichard Henderson 496840f9ad21SRichard Henderson static bool do_fcmpq(DisasContext *dc, arg_FCMPq *a, bool e) 496940f9ad21SRichard Henderson { 4970f3ceafadSRichard Henderson TCGv_i128 src1, src2; 4971f3ceafadSRichard Henderson 497240f9ad21SRichard Henderson if (avail_32(dc) && a->cc != 0) { 497340f9ad21SRichard Henderson return false; 497440f9ad21SRichard Henderson } 497540f9ad21SRichard Henderson if (gen_trap_ifnofpu(dc)) { 497640f9ad21SRichard Henderson return true; 497740f9ad21SRichard Henderson } 497840f9ad21SRichard Henderson if (gen_trap_float128(dc)) { 497940f9ad21SRichard Henderson return true; 498040f9ad21SRichard Henderson } 498140f9ad21SRichard Henderson 4982f3ceafadSRichard Henderson src1 = gen_load_fpr_Q(dc, a->rs1); 4983f3ceafadSRichard Henderson src2 = gen_load_fpr_Q(dc, a->rs2); 498440f9ad21SRichard Henderson if (e) { 4985d8c5b92fSRichard Henderson gen_helper_fcmpeq(cpu_fcc[a->cc], tcg_env, src1, src2); 498640f9ad21SRichard Henderson } else { 4987d8c5b92fSRichard Henderson gen_helper_fcmpq(cpu_fcc[a->cc], tcg_env, src1, src2); 498840f9ad21SRichard Henderson } 498940f9ad21SRichard Henderson return advance_pc(dc); 499040f9ad21SRichard Henderson } 499140f9ad21SRichard Henderson 499240f9ad21SRichard Henderson TRANS(FCMPq, ALL, do_fcmpq, a, false) 499340f9ad21SRichard Henderson TRANS(FCMPEq, ALL, do_fcmpq, a, true) 499440f9ad21SRichard Henderson 49956e61bc94SEmilio G. Cota static void sparc_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) 4996fcf5ef2aSThomas Huth { 49976e61bc94SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 49986e61bc94SEmilio G. Cota int bound; 4999af00be49SEmilio G. Cota 5000af00be49SEmilio G. Cota dc->pc = dc->base.pc_first; 50016e61bc94SEmilio G. Cota dc->npc = (target_ulong)dc->base.tb->cs_base; 50026e61bc94SEmilio G. Cota dc->mem_idx = dc->base.tb->flags & TB_FLAG_MMU_MASK; 500377976769SPhilippe Mathieu-Daudé dc->def = &cpu_env(cs)->def; 50046e61bc94SEmilio G. Cota dc->fpu_enabled = tb_fpu_enabled(dc->base.tb->flags); 50056e61bc94SEmilio G. Cota dc->address_mask_32bit = tb_am_enabled(dc->base.tb->flags); 5006c9b459aaSArtyom Tarasenko #ifndef CONFIG_USER_ONLY 50076e61bc94SEmilio G. Cota dc->supervisor = (dc->base.tb->flags & TB_FLAG_SUPER) != 0; 5008c9b459aaSArtyom Tarasenko #endif 5009fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64 5010fcf5ef2aSThomas Huth dc->fprs_dirty = 0; 50116e61bc94SEmilio G. Cota dc->asi = (dc->base.tb->flags >> TB_FLAG_ASI_SHIFT) & 0xff; 5012c9b459aaSArtyom Tarasenko #ifndef CONFIG_USER_ONLY 50136e61bc94SEmilio G. Cota dc->hypervisor = (dc->base.tb->flags & TB_FLAG_HYPER) != 0; 5014c9b459aaSArtyom Tarasenko #endif 5015fcf5ef2aSThomas Huth #endif 50166e61bc94SEmilio G. Cota /* 50176e61bc94SEmilio G. Cota * if we reach a page boundary, we stop generation so that the 50186e61bc94SEmilio G. Cota * PC of a TT_TFAULT exception is always in the right page 50196e61bc94SEmilio G. Cota */ 50206e61bc94SEmilio G. Cota bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4; 50216e61bc94SEmilio G. Cota dc->base.max_insns = MIN(dc->base.max_insns, bound); 5022af00be49SEmilio G. Cota } 5023fcf5ef2aSThomas Huth 50246e61bc94SEmilio G. Cota static void sparc_tr_tb_start(DisasContextBase *db, CPUState *cs) 50256e61bc94SEmilio G. Cota { 50266e61bc94SEmilio G. Cota } 50276e61bc94SEmilio G. Cota 50286e61bc94SEmilio G. Cota static void sparc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) 50296e61bc94SEmilio G. Cota { 50306e61bc94SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 5031633c4283SRichard Henderson target_ulong npc = dc->npc; 50326e61bc94SEmilio G. Cota 5033633c4283SRichard Henderson if (npc & 3) { 5034633c4283SRichard Henderson switch (npc) { 5035633c4283SRichard Henderson case JUMP_PC: 5036fcf5ef2aSThomas Huth assert(dc->jump_pc[1] == dc->pc + 4); 5037633c4283SRichard Henderson npc = dc->jump_pc[0] | JUMP_PC; 5038633c4283SRichard Henderson break; 5039633c4283SRichard Henderson case DYNAMIC_PC: 5040633c4283SRichard Henderson case DYNAMIC_PC_LOOKUP: 5041633c4283SRichard Henderson npc = DYNAMIC_PC; 5042633c4283SRichard Henderson break; 5043633c4283SRichard Henderson default: 5044633c4283SRichard Henderson g_assert_not_reached(); 5045fcf5ef2aSThomas Huth } 50466e61bc94SEmilio G. Cota } 5047633c4283SRichard Henderson tcg_gen_insn_start(dc->pc, npc); 5048633c4283SRichard Henderson } 5049fcf5ef2aSThomas Huth 50506e61bc94SEmilio G. Cota static void sparc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) 50516e61bc94SEmilio G. Cota { 50526e61bc94SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 50536e61bc94SEmilio G. Cota unsigned int insn; 5054fcf5ef2aSThomas Huth 505577976769SPhilippe Mathieu-Daudé insn = translator_ldl(cpu_env(cs), &dc->base, dc->pc); 5056af00be49SEmilio G. Cota dc->base.pc_next += 4; 5057878cc677SRichard Henderson 5058878cc677SRichard Henderson if (!decode(dc, insn)) { 5059ba9c09b4SRichard Henderson gen_exception(dc, TT_ILL_INSN); 5060878cc677SRichard Henderson } 5061fcf5ef2aSThomas Huth 5062af00be49SEmilio G. Cota if (dc->base.is_jmp == DISAS_NORETURN) { 50636e61bc94SEmilio G. Cota return; 5064c5e6ccdfSEmilio G. Cota } 5065af00be49SEmilio G. Cota if (dc->pc != dc->base.pc_next) { 50666e61bc94SEmilio G. Cota dc->base.is_jmp = DISAS_TOO_MANY; 5067af00be49SEmilio G. Cota } 50686e61bc94SEmilio G. Cota } 5069fcf5ef2aSThomas Huth 50706e61bc94SEmilio G. Cota static void sparc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) 50716e61bc94SEmilio G. Cota { 50726e61bc94SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 5073186e7890SRichard Henderson DisasDelayException *e, *e_next; 5074633c4283SRichard Henderson bool may_lookup; 50756e61bc94SEmilio G. Cota 507689527e3aSRichard Henderson finishing_insn(dc); 507789527e3aSRichard Henderson 507846bb0137SMark Cave-Ayland switch (dc->base.is_jmp) { 507946bb0137SMark Cave-Ayland case DISAS_NEXT: 508046bb0137SMark Cave-Ayland case DISAS_TOO_MANY: 5081633c4283SRichard Henderson if (((dc->pc | dc->npc) & 3) == 0) { 5082fcf5ef2aSThomas Huth /* static PC and NPC: we can use direct chaining */ 5083fcf5ef2aSThomas Huth gen_goto_tb(dc, 0, dc->pc, dc->npc); 5084633c4283SRichard Henderson break; 5085fcf5ef2aSThomas Huth } 5086633c4283SRichard Henderson 5087930f1865SRichard Henderson may_lookup = true; 5088633c4283SRichard Henderson if (dc->pc & 3) { 5089633c4283SRichard Henderson switch (dc->pc) { 5090633c4283SRichard Henderson case DYNAMIC_PC_LOOKUP: 5091633c4283SRichard Henderson break; 5092633c4283SRichard Henderson case DYNAMIC_PC: 5093633c4283SRichard Henderson may_lookup = false; 5094633c4283SRichard Henderson break; 5095633c4283SRichard Henderson default: 5096633c4283SRichard Henderson g_assert_not_reached(); 5097633c4283SRichard Henderson } 5098633c4283SRichard Henderson } else { 5099633c4283SRichard Henderson tcg_gen_movi_tl(cpu_pc, dc->pc); 5100633c4283SRichard Henderson } 5101633c4283SRichard Henderson 5102930f1865SRichard Henderson if (dc->npc & 3) { 5103930f1865SRichard Henderson switch (dc->npc) { 5104930f1865SRichard Henderson case JUMP_PC: 5105930f1865SRichard Henderson gen_generic_branch(dc); 5106930f1865SRichard Henderson break; 5107930f1865SRichard Henderson case DYNAMIC_PC: 5108930f1865SRichard Henderson may_lookup = false; 5109930f1865SRichard Henderson break; 5110930f1865SRichard Henderson case DYNAMIC_PC_LOOKUP: 5111930f1865SRichard Henderson break; 5112930f1865SRichard Henderson default: 5113930f1865SRichard Henderson g_assert_not_reached(); 5114930f1865SRichard Henderson } 5115930f1865SRichard Henderson } else { 5116930f1865SRichard Henderson tcg_gen_movi_tl(cpu_npc, dc->npc); 5117930f1865SRichard Henderson } 5118633c4283SRichard Henderson if (may_lookup) { 5119633c4283SRichard Henderson tcg_gen_lookup_and_goto_ptr(); 5120633c4283SRichard Henderson } else { 512107ea28b4SRichard Henderson tcg_gen_exit_tb(NULL, 0); 5122fcf5ef2aSThomas Huth } 512346bb0137SMark Cave-Ayland break; 512446bb0137SMark Cave-Ayland 512546bb0137SMark Cave-Ayland case DISAS_NORETURN: 512646bb0137SMark Cave-Ayland break; 512746bb0137SMark Cave-Ayland 512846bb0137SMark Cave-Ayland case DISAS_EXIT: 512946bb0137SMark Cave-Ayland /* Exit TB */ 513046bb0137SMark Cave-Ayland save_state(dc); 513146bb0137SMark Cave-Ayland tcg_gen_exit_tb(NULL, 0); 513246bb0137SMark Cave-Ayland break; 513346bb0137SMark Cave-Ayland 513446bb0137SMark Cave-Ayland default: 513546bb0137SMark Cave-Ayland g_assert_not_reached(); 5136fcf5ef2aSThomas Huth } 5137186e7890SRichard Henderson 5138186e7890SRichard Henderson for (e = dc->delay_excp_list; e ; e = e_next) { 5139186e7890SRichard Henderson gen_set_label(e->lab); 5140186e7890SRichard Henderson 5141186e7890SRichard Henderson tcg_gen_movi_tl(cpu_pc, e->pc); 5142186e7890SRichard Henderson if (e->npc % 4 == 0) { 5143186e7890SRichard Henderson tcg_gen_movi_tl(cpu_npc, e->npc); 5144186e7890SRichard Henderson } 5145186e7890SRichard Henderson gen_helper_raise_exception(tcg_env, e->excp); 5146186e7890SRichard Henderson 5147186e7890SRichard Henderson e_next = e->next; 5148186e7890SRichard Henderson g_free(e); 5149186e7890SRichard Henderson } 5150fcf5ef2aSThomas Huth } 51516e61bc94SEmilio G. Cota 51526e61bc94SEmilio G. Cota static const TranslatorOps sparc_tr_ops = { 51536e61bc94SEmilio G. Cota .init_disas_context = sparc_tr_init_disas_context, 51546e61bc94SEmilio G. Cota .tb_start = sparc_tr_tb_start, 51556e61bc94SEmilio G. Cota .insn_start = sparc_tr_insn_start, 51566e61bc94SEmilio G. Cota .translate_insn = sparc_tr_translate_insn, 51576e61bc94SEmilio G. Cota .tb_stop = sparc_tr_tb_stop, 51586e61bc94SEmilio G. Cota }; 51596e61bc94SEmilio G. Cota 5160597f9b2dSRichard Henderson void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int *max_insns, 516132f0c394SAnton Johansson vaddr pc, void *host_pc) 51626e61bc94SEmilio G. Cota { 51636e61bc94SEmilio G. Cota DisasContext dc = {}; 51646e61bc94SEmilio G. Cota 5165306c8721SRichard Henderson translator_loop(cs, tb, max_insns, pc, host_pc, &sparc_tr_ops, &dc.base); 5166fcf5ef2aSThomas Huth } 5167fcf5ef2aSThomas Huth 516855c3ceefSRichard Henderson void sparc_tcg_init(void) 5169fcf5ef2aSThomas Huth { 5170fcf5ef2aSThomas Huth static const char gregnames[32][4] = { 5171fcf5ef2aSThomas Huth "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7", 5172fcf5ef2aSThomas Huth "o0", "o1", "o2", "o3", "o4", "o5", "o6", "o7", 5173fcf5ef2aSThomas Huth "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7", 5174fcf5ef2aSThomas Huth "i0", "i1", "i2", "i3", "i4", "i5", "i6", "i7", 5175fcf5ef2aSThomas Huth }; 5176fcf5ef2aSThomas Huth 5177d8c5b92fSRichard Henderson static const struct { TCGv_i32 *ptr; int off; const char *name; } r32[] = { 5178d8c5b92fSRichard Henderson #ifdef TARGET_SPARC64 5179d8c5b92fSRichard Henderson { &cpu_fprs, offsetof(CPUSPARCState, fprs), "fprs" }, 5180d8c5b92fSRichard Henderson { &cpu_fcc[0], offsetof(CPUSPARCState, fcc[0]), "fcc0" }, 5181d8c5b92fSRichard Henderson { &cpu_fcc[1], offsetof(CPUSPARCState, fcc[1]), "fcc1" }, 5182d8c5b92fSRichard Henderson { &cpu_fcc[2], offsetof(CPUSPARCState, fcc[2]), "fcc2" }, 5183d8c5b92fSRichard Henderson { &cpu_fcc[3], offsetof(CPUSPARCState, fcc[3]), "fcc3" }, 5184d8c5b92fSRichard Henderson #else 5185d8c5b92fSRichard Henderson { &cpu_fcc[0], offsetof(CPUSPARCState, fcc[0]), "fcc" }, 5186d8c5b92fSRichard Henderson #endif 5187d8c5b92fSRichard Henderson }; 5188d8c5b92fSRichard Henderson 5189fcf5ef2aSThomas Huth static const struct { TCGv *ptr; int off; const char *name; } rtl[] = { 5190fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64 5191fcf5ef2aSThomas Huth { &cpu_gsr, offsetof(CPUSPARCState, gsr), "gsr" }, 51922a1905c7SRichard Henderson { &cpu_xcc_Z, offsetof(CPUSPARCState, xcc_Z), "xcc_Z" }, 51932a1905c7SRichard Henderson { &cpu_xcc_C, offsetof(CPUSPARCState, xcc_C), "xcc_C" }, 5194fcf5ef2aSThomas Huth #endif 51952a1905c7SRichard Henderson { &cpu_cc_N, offsetof(CPUSPARCState, cc_N), "cc_N" }, 51962a1905c7SRichard Henderson { &cpu_cc_V, offsetof(CPUSPARCState, cc_V), "cc_V" }, 51972a1905c7SRichard Henderson { &cpu_icc_Z, offsetof(CPUSPARCState, icc_Z), "icc_Z" }, 51982a1905c7SRichard Henderson { &cpu_icc_C, offsetof(CPUSPARCState, icc_C), "icc_C" }, 5199fcf5ef2aSThomas Huth { &cpu_cond, offsetof(CPUSPARCState, cond), "cond" }, 5200fcf5ef2aSThomas Huth { &cpu_pc, offsetof(CPUSPARCState, pc), "pc" }, 5201fcf5ef2aSThomas Huth { &cpu_npc, offsetof(CPUSPARCState, npc), "npc" }, 5202fcf5ef2aSThomas Huth { &cpu_y, offsetof(CPUSPARCState, y), "y" }, 5203fcf5ef2aSThomas Huth { &cpu_tbr, offsetof(CPUSPARCState, tbr), "tbr" }, 5204fcf5ef2aSThomas Huth }; 5205fcf5ef2aSThomas Huth 5206fcf5ef2aSThomas Huth unsigned int i; 5207fcf5ef2aSThomas Huth 5208ad75a51eSRichard Henderson cpu_regwptr = tcg_global_mem_new_ptr(tcg_env, 5209fcf5ef2aSThomas Huth offsetof(CPUSPARCState, regwptr), 5210fcf5ef2aSThomas Huth "regwptr"); 5211fcf5ef2aSThomas Huth 5212d8c5b92fSRichard Henderson for (i = 0; i < ARRAY_SIZE(r32); ++i) { 5213d8c5b92fSRichard Henderson *r32[i].ptr = tcg_global_mem_new_i32(tcg_env, r32[i].off, r32[i].name); 5214d8c5b92fSRichard Henderson } 5215d8c5b92fSRichard Henderson 5216fcf5ef2aSThomas Huth for (i = 0; i < ARRAY_SIZE(rtl); ++i) { 5217ad75a51eSRichard Henderson *rtl[i].ptr = tcg_global_mem_new(tcg_env, rtl[i].off, rtl[i].name); 5218fcf5ef2aSThomas Huth } 5219fcf5ef2aSThomas Huth 5220f764718dSRichard Henderson cpu_regs[0] = NULL; 5221fcf5ef2aSThomas Huth for (i = 1; i < 8; ++i) { 5222ad75a51eSRichard Henderson cpu_regs[i] = tcg_global_mem_new(tcg_env, 5223fcf5ef2aSThomas Huth offsetof(CPUSPARCState, gregs[i]), 5224fcf5ef2aSThomas Huth gregnames[i]); 5225fcf5ef2aSThomas Huth } 5226fcf5ef2aSThomas Huth 5227fcf5ef2aSThomas Huth for (i = 8; i < 32; ++i) { 5228fcf5ef2aSThomas Huth cpu_regs[i] = tcg_global_mem_new(cpu_regwptr, 5229fcf5ef2aSThomas Huth (i - 8) * sizeof(target_ulong), 5230fcf5ef2aSThomas Huth gregnames[i]); 5231fcf5ef2aSThomas Huth } 5232fcf5ef2aSThomas Huth } 5233fcf5ef2aSThomas Huth 5234f36aaa53SRichard Henderson void sparc_restore_state_to_opc(CPUState *cs, 5235f36aaa53SRichard Henderson const TranslationBlock *tb, 5236f36aaa53SRichard Henderson const uint64_t *data) 5237fcf5ef2aSThomas Huth { 523877976769SPhilippe Mathieu-Daudé CPUSPARCState *env = cpu_env(cs); 5239fcf5ef2aSThomas Huth target_ulong pc = data[0]; 5240fcf5ef2aSThomas Huth target_ulong npc = data[1]; 5241fcf5ef2aSThomas Huth 5242fcf5ef2aSThomas Huth env->pc = pc; 5243fcf5ef2aSThomas Huth if (npc == DYNAMIC_PC) { 5244fcf5ef2aSThomas Huth /* dynamic NPC: already stored */ 5245fcf5ef2aSThomas Huth } else if (npc & JUMP_PC) { 5246fcf5ef2aSThomas Huth /* jump PC: use 'cond' and the jump targets of the translation */ 5247fcf5ef2aSThomas Huth if (env->cond) { 5248fcf5ef2aSThomas Huth env->npc = npc & ~3; 5249fcf5ef2aSThomas Huth } else { 5250fcf5ef2aSThomas Huth env->npc = pc + 4; 5251fcf5ef2aSThomas Huth } 5252fcf5ef2aSThomas Huth } else { 5253fcf5ef2aSThomas Huth env->npc = npc; 5254fcf5ef2aSThomas Huth } 5255fcf5ef2aSThomas Huth } 5256