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" 314fd71d19SRichard Henderson #include "fpu/softfloat.h" 32fcf5ef2aSThomas Huth #include "asi.h" 33fcf5ef2aSThomas Huth 34d53106c9SRichard Henderson #define HELPER_H "helper.h" 35d53106c9SRichard Henderson #include "exec/helper-info.c.inc" 36d53106c9SRichard Henderson #undef HELPER_H 37fcf5ef2aSThomas Huth 38668bb9b7SRichard Henderson #ifdef TARGET_SPARC64 39668bb9b7SRichard Henderson # define gen_helper_rdpsr(D, E) qemu_build_not_reached() 40c92948f2SClément Chigot # define gen_helper_rdasr17(D, E) qemu_build_not_reached() 4186b82fe0SRichard Henderson # define gen_helper_rett(E) qemu_build_not_reached() 420faef01bSRichard Henderson # define gen_helper_power_down(E) qemu_build_not_reached() 4325524734SRichard Henderson # define gen_helper_wrpsr(E, S) qemu_build_not_reached() 44668bb9b7SRichard Henderson #else 450faef01bSRichard Henderson # define gen_helper_clear_softint(E, S) qemu_build_not_reached() 468f75b8a4SRichard Henderson # define gen_helper_done(E) qemu_build_not_reached() 47e8325dc0SRichard Henderson # define gen_helper_flushw(E) qemu_build_not_reached() 48a859602cSRichard Henderson # define gen_helper_fmul8x16a(D, S1, S2) qemu_build_not_reached() 49af25071cSRichard Henderson # define gen_helper_rdccr(D, E) qemu_build_not_reached() 505d617bfbSRichard Henderson # define gen_helper_rdcwp(D, E) qemu_build_not_reached() 5125524734SRichard Henderson # define gen_helper_restored(E) qemu_build_not_reached() 528f75b8a4SRichard Henderson # define gen_helper_retry(E) qemu_build_not_reached() 5325524734SRichard Henderson # define gen_helper_saved(E) qemu_build_not_reached() 540faef01bSRichard Henderson # define gen_helper_set_softint(E, S) qemu_build_not_reached() 55af25071cSRichard Henderson # define gen_helper_tick_get_count(D, E, T, C) qemu_build_not_reached() 569422278eSRichard Henderson # define gen_helper_tick_set_count(P, S) qemu_build_not_reached() 57bb97f2f5SRichard Henderson # define gen_helper_tick_set_limit(P, S) qemu_build_not_reached() 580faef01bSRichard Henderson # define gen_helper_wrccr(E, S) qemu_build_not_reached() 599422278eSRichard Henderson # define gen_helper_wrcwp(E, S) qemu_build_not_reached() 609422278eSRichard Henderson # define gen_helper_wrgl(E, S) qemu_build_not_reached() 610faef01bSRichard Henderson # define gen_helper_write_softint(E, S) qemu_build_not_reached() 629422278eSRichard Henderson # define gen_helper_wrpil(E, S) qemu_build_not_reached() 639422278eSRichard Henderson # define gen_helper_wrpstate(E, S) qemu_build_not_reached() 64c973b4e8SRichard Henderson # define gen_helper_cmask8 ({ qemu_build_not_reached(); NULL; }) 65c973b4e8SRichard Henderson # define gen_helper_cmask16 ({ qemu_build_not_reached(); NULL; }) 66c973b4e8SRichard Henderson # define gen_helper_cmask32 ({ qemu_build_not_reached(); NULL; }) 67669e0774SRichard Henderson # define gen_helper_fcmpeq8 ({ qemu_build_not_reached(); NULL; }) 68e2fa6bd1SRichard Henderson # define gen_helper_fcmpeq16 ({ qemu_build_not_reached(); NULL; }) 69e2fa6bd1SRichard Henderson # define gen_helper_fcmpeq32 ({ qemu_build_not_reached(); NULL; }) 70b3c934ddSRichard Henderson # define gen_helper_fcmpgt8 ({ qemu_build_not_reached(); NULL; }) 71e2fa6bd1SRichard Henderson # define gen_helper_fcmpgt16 ({ qemu_build_not_reached(); NULL; }) 72e2fa6bd1SRichard Henderson # define gen_helper_fcmpgt32 ({ qemu_build_not_reached(); NULL; }) 73b3c934ddSRichard Henderson # define gen_helper_fcmple8 ({ qemu_build_not_reached(); NULL; }) 74e2fa6bd1SRichard Henderson # define gen_helper_fcmple16 ({ qemu_build_not_reached(); NULL; }) 75e2fa6bd1SRichard Henderson # define gen_helper_fcmple32 ({ qemu_build_not_reached(); NULL; }) 76669e0774SRichard Henderson # define gen_helper_fcmpne8 ({ qemu_build_not_reached(); NULL; }) 77e2fa6bd1SRichard Henderson # define gen_helper_fcmpne16 ({ qemu_build_not_reached(); NULL; }) 78e2fa6bd1SRichard Henderson # define gen_helper_fcmpne32 ({ qemu_build_not_reached(); NULL; }) 79669e0774SRichard Henderson # define gen_helper_fcmpule8 ({ qemu_build_not_reached(); NULL; }) 80b3c934ddSRichard Henderson # define gen_helper_fcmpule16 ({ qemu_build_not_reached(); NULL; }) 81b3c934ddSRichard Henderson # define gen_helper_fcmpule32 ({ qemu_build_not_reached(); NULL; }) 82669e0774SRichard Henderson # define gen_helper_fcmpugt8 ({ qemu_build_not_reached(); NULL; }) 83b3c934ddSRichard Henderson # define gen_helper_fcmpugt16 ({ qemu_build_not_reached(); NULL; }) 84b3c934ddSRichard Henderson # define gen_helper_fcmpugt32 ({ qemu_build_not_reached(); NULL; }) 858aa418b3SRichard Henderson # define gen_helper_fdtox ({ qemu_build_not_reached(); NULL; }) 86e06c9f83SRichard Henderson # define gen_helper_fexpand ({ qemu_build_not_reached(); NULL; }) 87e06c9f83SRichard Henderson # define gen_helper_fmul8sux16 ({ qemu_build_not_reached(); NULL; }) 88e06c9f83SRichard Henderson # define gen_helper_fmul8ulx16 ({ qemu_build_not_reached(); NULL; }) 89e06c9f83SRichard Henderson # define gen_helper_fmul8x16 ({ qemu_build_not_reached(); NULL; }) 90e06c9f83SRichard Henderson # define gen_helper_fpmerge ({ qemu_build_not_reached(); NULL; }) 911617586fSRichard Henderson # define gen_helper_fqtox ({ qemu_build_not_reached(); NULL; }) 92fbc5c8d4SRichard Henderson # define gen_helper_fslas16 ({ qemu_build_not_reached(); NULL; }) 93fbc5c8d4SRichard Henderson # define gen_helper_fslas32 ({ qemu_build_not_reached(); NULL; }) 94199d43efSRichard Henderson # define gen_helper_fstox ({ qemu_build_not_reached(); NULL; }) 958aa418b3SRichard Henderson # define gen_helper_fxtod ({ qemu_build_not_reached(); NULL; }) 967b8e3e1aSRichard Henderson # define gen_helper_fxtoq ({ qemu_build_not_reached(); NULL; }) 97f4e18df5SRichard Henderson # define gen_helper_fxtos ({ qemu_build_not_reached(); NULL; }) 98afb04344SRichard Henderson # define gen_helper_pdist ({ qemu_build_not_reached(); NULL; }) 99029b0283SRichard Henderson # define gen_helper_xmulx ({ qemu_build_not_reached(); NULL; }) 100029b0283SRichard Henderson # define gen_helper_xmulxhi ({ qemu_build_not_reached(); NULL; }) 101668bb9b7SRichard Henderson # define MAXTL_MASK 0 102af25071cSRichard Henderson #endif 103af25071cSRichard Henderson 104633c4283SRichard Henderson /* Dynamic PC, must exit to main loop. */ 105633c4283SRichard Henderson #define DYNAMIC_PC 1 106633c4283SRichard Henderson /* Dynamic PC, one of two values according to jump_pc[T2]. */ 107633c4283SRichard Henderson #define JUMP_PC 2 108633c4283SRichard Henderson /* Dynamic PC, may lookup next TB. */ 109633c4283SRichard Henderson #define DYNAMIC_PC_LOOKUP 3 110fcf5ef2aSThomas Huth 11146bb0137SMark Cave-Ayland #define DISAS_EXIT DISAS_TARGET_0 11246bb0137SMark Cave-Ayland 113fcf5ef2aSThomas Huth /* global register indexes */ 114fcf5ef2aSThomas Huth static TCGv_ptr cpu_regwptr; 115c9fa8e58SRichard Henderson static TCGv cpu_pc, cpu_npc; 116fcf5ef2aSThomas Huth static TCGv cpu_regs[32]; 117fcf5ef2aSThomas Huth static TCGv cpu_y; 118fcf5ef2aSThomas Huth static TCGv cpu_tbr; 119fcf5ef2aSThomas Huth static TCGv cpu_cond; 1202a1905c7SRichard Henderson static TCGv cpu_cc_N; 1212a1905c7SRichard Henderson static TCGv cpu_cc_V; 1222a1905c7SRichard Henderson static TCGv cpu_icc_Z; 1232a1905c7SRichard Henderson static TCGv cpu_icc_C; 124fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64 1252a1905c7SRichard Henderson static TCGv cpu_xcc_Z; 1262a1905c7SRichard Henderson static TCGv cpu_xcc_C; 1272a1905c7SRichard Henderson static TCGv_i32 cpu_fprs; 128fcf5ef2aSThomas Huth static TCGv cpu_gsr; 129fcf5ef2aSThomas Huth #else 130af25071cSRichard Henderson # define cpu_fprs ({ qemu_build_not_reached(); (TCGv)NULL; }) 131af25071cSRichard Henderson # define cpu_gsr ({ qemu_build_not_reached(); (TCGv)NULL; }) 132fcf5ef2aSThomas Huth #endif 1332a1905c7SRichard Henderson 1342a1905c7SRichard Henderson #ifdef TARGET_SPARC64 1352a1905c7SRichard Henderson #define cpu_cc_Z cpu_xcc_Z 1362a1905c7SRichard Henderson #define cpu_cc_C cpu_xcc_C 1372a1905c7SRichard Henderson #else 1382a1905c7SRichard Henderson #define cpu_cc_Z cpu_icc_Z 1392a1905c7SRichard Henderson #define cpu_cc_C cpu_icc_C 1402a1905c7SRichard Henderson #define cpu_xcc_Z ({ qemu_build_not_reached(); NULL; }) 1412a1905c7SRichard Henderson #define cpu_xcc_C ({ qemu_build_not_reached(); NULL; }) 1422a1905c7SRichard Henderson #endif 1432a1905c7SRichard Henderson 1441210a036SRichard Henderson /* Floating point comparison registers */ 145d8c5b92fSRichard Henderson static TCGv_i32 cpu_fcc[TARGET_FCCREGS]; 146fcf5ef2aSThomas Huth 147af25071cSRichard Henderson #define env_field_offsetof(X) offsetof(CPUSPARCState, X) 148af25071cSRichard Henderson #ifdef TARGET_SPARC64 149cd6269f7SRichard Henderson # define env32_field_offsetof(X) ({ qemu_build_not_reached(); 0; }) 150af25071cSRichard Henderson # define env64_field_offsetof(X) env_field_offsetof(X) 151af25071cSRichard Henderson #else 152cd6269f7SRichard Henderson # define env32_field_offsetof(X) env_field_offsetof(X) 153af25071cSRichard Henderson # define env64_field_offsetof(X) ({ qemu_build_not_reached(); 0; }) 154af25071cSRichard Henderson #endif 155af25071cSRichard Henderson 156533f042fSRichard Henderson typedef struct DisasCompare { 157533f042fSRichard Henderson TCGCond cond; 158533f042fSRichard Henderson TCGv c1; 159533f042fSRichard Henderson int c2; 160533f042fSRichard Henderson } DisasCompare; 161533f042fSRichard Henderson 162186e7890SRichard Henderson typedef struct DisasDelayException { 163186e7890SRichard Henderson struct DisasDelayException *next; 164186e7890SRichard Henderson TCGLabel *lab; 165186e7890SRichard Henderson TCGv_i32 excp; 166186e7890SRichard Henderson /* Saved state at parent insn. */ 167186e7890SRichard Henderson target_ulong pc; 168186e7890SRichard Henderson target_ulong npc; 169186e7890SRichard Henderson } DisasDelayException; 170186e7890SRichard Henderson 171fcf5ef2aSThomas Huth typedef struct DisasContext { 172af00be49SEmilio G. Cota DisasContextBase base; 173fcf5ef2aSThomas Huth target_ulong pc; /* current Program Counter: integer or DYNAMIC_PC */ 174fcf5ef2aSThomas Huth target_ulong npc; /* next PC: integer or DYNAMIC_PC or JUMP_PC */ 175533f042fSRichard Henderson 176533f042fSRichard Henderson /* Used when JUMP_PC value is used. */ 177533f042fSRichard Henderson DisasCompare jump; 178533f042fSRichard Henderson target_ulong jump_pc[2]; 179533f042fSRichard Henderson 180fcf5ef2aSThomas Huth int mem_idx; 18189527e3aSRichard Henderson bool cpu_cond_live; 182c9b459aaSArtyom Tarasenko bool fpu_enabled; 183c9b459aaSArtyom Tarasenko bool address_mask_32bit; 184c9b459aaSArtyom Tarasenko #ifndef CONFIG_USER_ONLY 185c9b459aaSArtyom Tarasenko bool supervisor; 186c9b459aaSArtyom Tarasenko #ifdef TARGET_SPARC64 187c9b459aaSArtyom Tarasenko bool hypervisor; 1885a165e26SRichard Henderson #else 1895a165e26SRichard Henderson bool fsr_qne; 190c9b459aaSArtyom Tarasenko #endif 191c9b459aaSArtyom Tarasenko #endif 192c9b459aaSArtyom Tarasenko 193fcf5ef2aSThomas Huth sparc_def_t *def; 194fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64 195fcf5ef2aSThomas Huth int fprs_dirty; 196fcf5ef2aSThomas Huth int asi; 197fcf5ef2aSThomas Huth #endif 198186e7890SRichard Henderson DisasDelayException *delay_excp_list; 199fcf5ef2aSThomas Huth } DisasContext; 200fcf5ef2aSThomas Huth 201fcf5ef2aSThomas Huth // This function uses non-native bit order 202fcf5ef2aSThomas Huth #define GET_FIELD(X, FROM, TO) \ 203fcf5ef2aSThomas Huth ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1)) 204fcf5ef2aSThomas Huth 205fcf5ef2aSThomas Huth // This function uses the order in the manuals, i.e. bit 0 is 2^0 206fcf5ef2aSThomas Huth #define GET_FIELD_SP(X, FROM, TO) \ 207fcf5ef2aSThomas Huth GET_FIELD(X, 31 - (TO), 31 - (FROM)) 208fcf5ef2aSThomas Huth 209fcf5ef2aSThomas Huth #define GET_FIELDs(x,a,b) sign_extend (GET_FIELD(x,a,b), (b) - (a) + 1) 210fcf5ef2aSThomas Huth #define GET_FIELD_SPs(x,a,b) sign_extend (GET_FIELD_SP(x,a,b), ((b) - (a) + 1)) 211fcf5ef2aSThomas Huth 212fcf5ef2aSThomas Huth #define UA2005_HTRAP_MASK 0xff 213fcf5ef2aSThomas Huth #define V8_TRAP_MASK 0x7f 214fcf5ef2aSThomas Huth 215fcf5ef2aSThomas Huth #define IS_IMM (insn & (1<<13)) 216fcf5ef2aSThomas Huth 2170c2e96c1SRichard Henderson static void gen_update_fprs_dirty(DisasContext *dc, int rd) 218fcf5ef2aSThomas Huth { 219fcf5ef2aSThomas Huth #if defined(TARGET_SPARC64) 220fcf5ef2aSThomas Huth int bit = (rd < 32) ? 1 : 2; 221fcf5ef2aSThomas Huth /* If we know we've already set this bit within the TB, 222fcf5ef2aSThomas Huth we can avoid setting it again. */ 223fcf5ef2aSThomas Huth if (!(dc->fprs_dirty & bit)) { 224fcf5ef2aSThomas Huth dc->fprs_dirty |= bit; 225fcf5ef2aSThomas Huth tcg_gen_ori_i32(cpu_fprs, cpu_fprs, bit); 226fcf5ef2aSThomas Huth } 227fcf5ef2aSThomas Huth #endif 228fcf5ef2aSThomas Huth } 229fcf5ef2aSThomas Huth 230fcf5ef2aSThomas Huth /* floating point registers moves */ 2311210a036SRichard Henderson 2321210a036SRichard Henderson static int gen_offset_fpr_F(unsigned int reg) 2331210a036SRichard Henderson { 2341210a036SRichard Henderson int ret; 2351210a036SRichard Henderson 2361210a036SRichard Henderson tcg_debug_assert(reg < 32); 2371210a036SRichard Henderson ret= offsetof(CPUSPARCState, fpr[reg / 2]); 2381210a036SRichard Henderson if (reg & 1) { 2391210a036SRichard Henderson ret += offsetof(CPU_DoubleU, l.lower); 2401210a036SRichard Henderson } else { 2411210a036SRichard Henderson ret += offsetof(CPU_DoubleU, l.upper); 2421210a036SRichard Henderson } 2431210a036SRichard Henderson return ret; 2441210a036SRichard Henderson } 2451210a036SRichard Henderson 246fcf5ef2aSThomas Huth static TCGv_i32 gen_load_fpr_F(DisasContext *dc, unsigned int src) 247fcf5ef2aSThomas Huth { 24836ab4623SRichard Henderson TCGv_i32 ret = tcg_temp_new_i32(); 2491210a036SRichard Henderson tcg_gen_ld_i32(ret, tcg_env, gen_offset_fpr_F(src)); 250dc41aa7dSRichard Henderson return ret; 251fcf5ef2aSThomas Huth } 252fcf5ef2aSThomas Huth 253fcf5ef2aSThomas Huth static void gen_store_fpr_F(DisasContext *dc, unsigned int dst, TCGv_i32 v) 254fcf5ef2aSThomas Huth { 2551210a036SRichard Henderson tcg_gen_st_i32(v, tcg_env, gen_offset_fpr_F(dst)); 256fcf5ef2aSThomas Huth gen_update_fprs_dirty(dc, dst); 257fcf5ef2aSThomas Huth } 258fcf5ef2aSThomas Huth 2591210a036SRichard Henderson static int gen_offset_fpr_D(unsigned int reg) 2601210a036SRichard Henderson { 2611210a036SRichard Henderson tcg_debug_assert(reg < 64); 2621210a036SRichard Henderson tcg_debug_assert(reg % 2 == 0); 2631210a036SRichard Henderson return offsetof(CPUSPARCState, fpr[reg / 2]); 2641210a036SRichard Henderson } 2651210a036SRichard Henderson 266fcf5ef2aSThomas Huth static TCGv_i64 gen_load_fpr_D(DisasContext *dc, unsigned int src) 267fcf5ef2aSThomas Huth { 2681210a036SRichard Henderson TCGv_i64 ret = tcg_temp_new_i64(); 2691210a036SRichard Henderson tcg_gen_ld_i64(ret, tcg_env, gen_offset_fpr_D(src)); 2701210a036SRichard Henderson return ret; 271fcf5ef2aSThomas Huth } 272fcf5ef2aSThomas Huth 273fcf5ef2aSThomas Huth static void gen_store_fpr_D(DisasContext *dc, unsigned int dst, TCGv_i64 v) 274fcf5ef2aSThomas Huth { 2751210a036SRichard Henderson tcg_gen_st_i64(v, tcg_env, gen_offset_fpr_D(dst)); 276fcf5ef2aSThomas Huth gen_update_fprs_dirty(dc, dst); 277fcf5ef2aSThomas Huth } 278fcf5ef2aSThomas Huth 27933ec4245SRichard Henderson static TCGv_i128 gen_load_fpr_Q(DisasContext *dc, unsigned int src) 28033ec4245SRichard Henderson { 28133ec4245SRichard Henderson TCGv_i128 ret = tcg_temp_new_i128(); 2821210a036SRichard Henderson TCGv_i64 h = gen_load_fpr_D(dc, src); 2831210a036SRichard Henderson TCGv_i64 l = gen_load_fpr_D(dc, src + 2); 28433ec4245SRichard Henderson 2851210a036SRichard Henderson tcg_gen_concat_i64_i128(ret, l, h); 28633ec4245SRichard Henderson return ret; 28733ec4245SRichard Henderson } 28833ec4245SRichard Henderson 28933ec4245SRichard Henderson static void gen_store_fpr_Q(DisasContext *dc, unsigned int dst, TCGv_i128 v) 29033ec4245SRichard Henderson { 2911210a036SRichard Henderson TCGv_i64 h = tcg_temp_new_i64(); 2921210a036SRichard Henderson TCGv_i64 l = tcg_temp_new_i64(); 2931210a036SRichard Henderson 2941210a036SRichard Henderson tcg_gen_extr_i128_i64(l, h, v); 2951210a036SRichard Henderson gen_store_fpr_D(dc, dst, h); 2961210a036SRichard Henderson gen_store_fpr_D(dc, dst + 2, l); 29733ec4245SRichard Henderson } 29833ec4245SRichard Henderson 299fcf5ef2aSThomas Huth /* moves */ 300fcf5ef2aSThomas Huth #ifdef CONFIG_USER_ONLY 301fcf5ef2aSThomas Huth #define supervisor(dc) 0 302fcf5ef2aSThomas Huth #define hypervisor(dc) 0 303fcf5ef2aSThomas Huth #else 304fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64 305c9b459aaSArtyom Tarasenko #define hypervisor(dc) (dc->hypervisor) 306c9b459aaSArtyom Tarasenko #define supervisor(dc) (dc->supervisor | dc->hypervisor) 307fcf5ef2aSThomas Huth #else 308c9b459aaSArtyom Tarasenko #define supervisor(dc) (dc->supervisor) 309668bb9b7SRichard Henderson #define hypervisor(dc) 0 310fcf5ef2aSThomas Huth #endif 311fcf5ef2aSThomas Huth #endif 312fcf5ef2aSThomas Huth 313b1bc09eaSRichard Henderson #if !defined(TARGET_SPARC64) 314b1bc09eaSRichard Henderson # define AM_CHECK(dc) false 315b1bc09eaSRichard Henderson #elif defined(TARGET_ABI32) 316b1bc09eaSRichard Henderson # define AM_CHECK(dc) true 317b1bc09eaSRichard Henderson #elif defined(CONFIG_USER_ONLY) 318b1bc09eaSRichard Henderson # define AM_CHECK(dc) false 319fcf5ef2aSThomas Huth #else 320b1bc09eaSRichard Henderson # define AM_CHECK(dc) ((dc)->address_mask_32bit) 321fcf5ef2aSThomas Huth #endif 322fcf5ef2aSThomas Huth 3230c2e96c1SRichard Henderson static void gen_address_mask(DisasContext *dc, TCGv addr) 324fcf5ef2aSThomas Huth { 325b1bc09eaSRichard Henderson if (AM_CHECK(dc)) { 326fcf5ef2aSThomas Huth tcg_gen_andi_tl(addr, addr, 0xffffffffULL); 327b1bc09eaSRichard Henderson } 328fcf5ef2aSThomas Huth } 329fcf5ef2aSThomas Huth 33023ada1b1SRichard Henderson static target_ulong address_mask_i(DisasContext *dc, target_ulong addr) 33123ada1b1SRichard Henderson { 33223ada1b1SRichard Henderson return AM_CHECK(dc) ? (uint32_t)addr : addr; 33323ada1b1SRichard Henderson } 33423ada1b1SRichard Henderson 3350c2e96c1SRichard Henderson static TCGv gen_load_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 TCGv t = tcg_temp_new(); 342fcf5ef2aSThomas Huth tcg_gen_movi_tl(t, 0); 343fcf5ef2aSThomas Huth return t; 344fcf5ef2aSThomas Huth } 345fcf5ef2aSThomas Huth } 346fcf5ef2aSThomas Huth 3470c2e96c1SRichard Henderson static void gen_store_gpr(DisasContext *dc, int reg, TCGv v) 348fcf5ef2aSThomas Huth { 349fcf5ef2aSThomas Huth if (reg > 0) { 350fcf5ef2aSThomas Huth assert(reg < 32); 351fcf5ef2aSThomas Huth tcg_gen_mov_tl(cpu_regs[reg], v); 352fcf5ef2aSThomas Huth } 353fcf5ef2aSThomas Huth } 354fcf5ef2aSThomas Huth 3550c2e96c1SRichard Henderson static TCGv gen_dest_gpr(DisasContext *dc, int reg) 356fcf5ef2aSThomas Huth { 357fcf5ef2aSThomas Huth if (reg > 0) { 358fcf5ef2aSThomas Huth assert(reg < 32); 359fcf5ef2aSThomas Huth return cpu_regs[reg]; 360fcf5ef2aSThomas Huth } else { 36152123f14SRichard Henderson return tcg_temp_new(); 362fcf5ef2aSThomas Huth } 363fcf5ef2aSThomas Huth } 364fcf5ef2aSThomas Huth 3655645aa2eSRichard Henderson static bool use_goto_tb(DisasContext *s, target_ulong pc, target_ulong npc) 366fcf5ef2aSThomas Huth { 3675645aa2eSRichard Henderson return translator_use_goto_tb(&s->base, pc) && 3685645aa2eSRichard Henderson translator_use_goto_tb(&s->base, npc); 369fcf5ef2aSThomas Huth } 370fcf5ef2aSThomas Huth 3715645aa2eSRichard Henderson static void gen_goto_tb(DisasContext *s, int tb_num, 372fcf5ef2aSThomas Huth target_ulong pc, target_ulong npc) 373fcf5ef2aSThomas Huth { 374fcf5ef2aSThomas Huth if (use_goto_tb(s, pc, npc)) { 375fcf5ef2aSThomas Huth /* jump to same page: we can use a direct jump */ 376fcf5ef2aSThomas Huth tcg_gen_goto_tb(tb_num); 377fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_pc, pc); 378fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_npc, npc); 37907ea28b4SRichard Henderson tcg_gen_exit_tb(s->base.tb, tb_num); 380fcf5ef2aSThomas Huth } else { 381f67ccb2fSRichard Henderson /* jump to another page: we can use an indirect jump */ 382fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_pc, pc); 383fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_npc, npc); 384f67ccb2fSRichard Henderson tcg_gen_lookup_and_goto_ptr(); 385fcf5ef2aSThomas Huth } 386fcf5ef2aSThomas Huth } 387fcf5ef2aSThomas Huth 388b989ce73SRichard Henderson static TCGv gen_carry32(void) 389fcf5ef2aSThomas Huth { 390b989ce73SRichard Henderson if (TARGET_LONG_BITS == 64) { 391b989ce73SRichard Henderson TCGv t = tcg_temp_new(); 392b989ce73SRichard Henderson tcg_gen_extract_tl(t, cpu_icc_C, 32, 1); 393b989ce73SRichard Henderson return t; 394b989ce73SRichard Henderson } 395b989ce73SRichard Henderson return cpu_icc_C; 396fcf5ef2aSThomas Huth } 397fcf5ef2aSThomas Huth 398b989ce73SRichard Henderson static void gen_op_addcc_int(TCGv dst, TCGv src1, TCGv src2, TCGv cin) 399fcf5ef2aSThomas Huth { 400b989ce73SRichard Henderson TCGv z = tcg_constant_tl(0); 401fcf5ef2aSThomas Huth 402b989ce73SRichard Henderson if (cin) { 403b989ce73SRichard Henderson tcg_gen_add2_tl(cpu_cc_N, cpu_cc_C, src1, z, cin, z); 404b989ce73SRichard Henderson tcg_gen_add2_tl(cpu_cc_N, cpu_cc_C, cpu_cc_N, cpu_cc_C, src2, z); 405b989ce73SRichard Henderson } else { 406b989ce73SRichard Henderson tcg_gen_add2_tl(cpu_cc_N, cpu_cc_C, src1, z, src2, z); 407b989ce73SRichard Henderson } 408b989ce73SRichard Henderson tcg_gen_xor_tl(cpu_cc_Z, src1, src2); 409b989ce73SRichard Henderson tcg_gen_xor_tl(cpu_cc_V, cpu_cc_N, src2); 410b989ce73SRichard Henderson tcg_gen_andc_tl(cpu_cc_V, cpu_cc_V, cpu_cc_Z); 411b989ce73SRichard Henderson if (TARGET_LONG_BITS == 64) { 412b989ce73SRichard Henderson /* 413b989ce73SRichard Henderson * Carry-in to bit 32 is result ^ src1 ^ src2. 414b989ce73SRichard Henderson * We already have the src xor term in Z, from computation of V. 415b989ce73SRichard Henderson */ 416b989ce73SRichard Henderson tcg_gen_xor_tl(cpu_icc_C, cpu_cc_Z, cpu_cc_N); 417b989ce73SRichard Henderson tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N); 418b989ce73SRichard Henderson } 419b989ce73SRichard Henderson tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N); 420b989ce73SRichard Henderson tcg_gen_mov_tl(dst, cpu_cc_N); 421b989ce73SRichard Henderson } 422fcf5ef2aSThomas Huth 423b989ce73SRichard Henderson static void gen_op_addcc(TCGv dst, TCGv src1, TCGv src2) 424b989ce73SRichard Henderson { 425b989ce73SRichard Henderson gen_op_addcc_int(dst, src1, src2, NULL); 426b989ce73SRichard Henderson } 427fcf5ef2aSThomas Huth 428b989ce73SRichard Henderson static void gen_op_taddcc(TCGv dst, TCGv src1, TCGv src2) 429b989ce73SRichard Henderson { 430b989ce73SRichard Henderson TCGv t = tcg_temp_new(); 431b989ce73SRichard Henderson 432b989ce73SRichard Henderson /* Save the tag bits around modification of dst. */ 433b989ce73SRichard Henderson tcg_gen_or_tl(t, src1, src2); 434b989ce73SRichard Henderson 435b989ce73SRichard Henderson gen_op_addcc(dst, src1, src2); 436b989ce73SRichard Henderson 437b989ce73SRichard Henderson /* Incorprate tag bits into icc.V */ 438b989ce73SRichard Henderson tcg_gen_andi_tl(t, t, 3); 439b989ce73SRichard Henderson tcg_gen_neg_tl(t, t); 440b989ce73SRichard Henderson tcg_gen_ext32u_tl(t, t); 441b989ce73SRichard Henderson tcg_gen_or_tl(cpu_cc_V, cpu_cc_V, t); 442b989ce73SRichard Henderson } 443b989ce73SRichard Henderson 444b989ce73SRichard Henderson static void gen_op_addc(TCGv dst, TCGv src1, TCGv src2) 445b989ce73SRichard Henderson { 446b989ce73SRichard Henderson tcg_gen_add_tl(dst, src1, src2); 447b989ce73SRichard Henderson tcg_gen_add_tl(dst, dst, gen_carry32()); 448b989ce73SRichard Henderson } 449b989ce73SRichard Henderson 450b989ce73SRichard Henderson static void gen_op_addccc(TCGv dst, TCGv src1, TCGv src2) 451b989ce73SRichard Henderson { 452b989ce73SRichard Henderson gen_op_addcc_int(dst, src1, src2, gen_carry32()); 453fcf5ef2aSThomas Huth } 454fcf5ef2aSThomas Huth 455015fc6fcSRichard Henderson static void gen_op_addxc(TCGv dst, TCGv src1, TCGv src2) 456015fc6fcSRichard Henderson { 457015fc6fcSRichard Henderson tcg_gen_add_tl(dst, src1, src2); 458015fc6fcSRichard Henderson tcg_gen_add_tl(dst, dst, cpu_cc_C); 459015fc6fcSRichard Henderson } 460015fc6fcSRichard Henderson 461015fc6fcSRichard Henderson static void gen_op_addxccc(TCGv dst, TCGv src1, TCGv src2) 462015fc6fcSRichard Henderson { 463015fc6fcSRichard Henderson gen_op_addcc_int(dst, src1, src2, cpu_cc_C); 464015fc6fcSRichard Henderson } 465015fc6fcSRichard Henderson 466f828df74SRichard Henderson static void gen_op_subcc_int(TCGv dst, TCGv src1, TCGv src2, TCGv cin) 467fcf5ef2aSThomas Huth { 468f828df74SRichard Henderson TCGv z = tcg_constant_tl(0); 469fcf5ef2aSThomas Huth 470f828df74SRichard Henderson if (cin) { 471f828df74SRichard Henderson tcg_gen_sub2_tl(cpu_cc_N, cpu_cc_C, src1, z, cin, z); 472f828df74SRichard Henderson tcg_gen_sub2_tl(cpu_cc_N, cpu_cc_C, cpu_cc_N, cpu_cc_C, src2, z); 473f828df74SRichard Henderson } else { 474f828df74SRichard Henderson tcg_gen_sub2_tl(cpu_cc_N, cpu_cc_C, src1, z, src2, z); 475f828df74SRichard Henderson } 476f828df74SRichard Henderson tcg_gen_neg_tl(cpu_cc_C, cpu_cc_C); 477f828df74SRichard Henderson tcg_gen_xor_tl(cpu_cc_Z, src1, src2); 478f828df74SRichard Henderson tcg_gen_xor_tl(cpu_cc_V, cpu_cc_N, src1); 479f828df74SRichard Henderson tcg_gen_and_tl(cpu_cc_V, cpu_cc_V, cpu_cc_Z); 480f828df74SRichard Henderson #ifdef TARGET_SPARC64 481f828df74SRichard Henderson tcg_gen_xor_tl(cpu_icc_C, cpu_cc_Z, cpu_cc_N); 482f828df74SRichard Henderson tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N); 483fcf5ef2aSThomas Huth #endif 484f828df74SRichard Henderson tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N); 485f828df74SRichard Henderson tcg_gen_mov_tl(dst, cpu_cc_N); 486fcf5ef2aSThomas Huth } 487fcf5ef2aSThomas Huth 488f828df74SRichard Henderson static void gen_op_subcc(TCGv dst, TCGv src1, TCGv src2) 489fcf5ef2aSThomas Huth { 490f828df74SRichard Henderson gen_op_subcc_int(dst, src1, src2, NULL); 491fcf5ef2aSThomas Huth } 492fcf5ef2aSThomas Huth 493f828df74SRichard Henderson static void gen_op_tsubcc(TCGv dst, TCGv src1, TCGv src2) 494fcf5ef2aSThomas Huth { 495f828df74SRichard Henderson TCGv t = tcg_temp_new(); 496fcf5ef2aSThomas Huth 497f828df74SRichard Henderson /* Save the tag bits around modification of dst. */ 498f828df74SRichard Henderson tcg_gen_or_tl(t, src1, src2); 499fcf5ef2aSThomas Huth 500f828df74SRichard Henderson gen_op_subcc(dst, src1, src2); 501f828df74SRichard Henderson 502f828df74SRichard Henderson /* Incorprate tag bits into icc.V */ 503f828df74SRichard Henderson tcg_gen_andi_tl(t, t, 3); 504f828df74SRichard Henderson tcg_gen_neg_tl(t, t); 505f828df74SRichard Henderson tcg_gen_ext32u_tl(t, t); 506f828df74SRichard Henderson tcg_gen_or_tl(cpu_cc_V, cpu_cc_V, t); 507f828df74SRichard Henderson } 508f828df74SRichard Henderson 509f828df74SRichard Henderson static void gen_op_subc(TCGv dst, TCGv src1, TCGv src2) 510f828df74SRichard Henderson { 511fcf5ef2aSThomas Huth tcg_gen_sub_tl(dst, src1, src2); 512f828df74SRichard Henderson tcg_gen_sub_tl(dst, dst, gen_carry32()); 513fcf5ef2aSThomas Huth } 514fcf5ef2aSThomas Huth 515f828df74SRichard Henderson static void gen_op_subccc(TCGv dst, TCGv src1, TCGv src2) 516dfebb950SRichard Henderson { 517f828df74SRichard Henderson gen_op_subcc_int(dst, src1, src2, gen_carry32()); 518dfebb950SRichard Henderson } 519dfebb950SRichard Henderson 52056f2ef9cSRichard Henderson static void gen_op_subxc(TCGv dst, TCGv src1, TCGv src2) 52156f2ef9cSRichard Henderson { 52256f2ef9cSRichard Henderson tcg_gen_sub_tl(dst, src1, src2); 52356f2ef9cSRichard Henderson tcg_gen_sub_tl(dst, dst, cpu_cc_C); 52456f2ef9cSRichard Henderson } 52556f2ef9cSRichard Henderson 52656f2ef9cSRichard Henderson static void gen_op_subxccc(TCGv dst, TCGv src1, TCGv src2) 52756f2ef9cSRichard Henderson { 52856f2ef9cSRichard Henderson gen_op_subcc_int(dst, src1, src2, cpu_cc_C); 52956f2ef9cSRichard Henderson } 53056f2ef9cSRichard Henderson 5310c2e96c1SRichard Henderson static void gen_op_mulscc(TCGv dst, TCGv src1, TCGv src2) 532fcf5ef2aSThomas Huth { 533b989ce73SRichard Henderson TCGv zero = tcg_constant_tl(0); 53450280618SRichard Henderson TCGv one = tcg_constant_tl(1); 535b989ce73SRichard Henderson TCGv t_src1 = tcg_temp_new(); 536b989ce73SRichard Henderson TCGv t_src2 = tcg_temp_new(); 537b989ce73SRichard Henderson TCGv t0 = tcg_temp_new(); 538fcf5ef2aSThomas Huth 539b989ce73SRichard Henderson tcg_gen_ext32u_tl(t_src1, src1); 540b989ce73SRichard Henderson tcg_gen_ext32u_tl(t_src2, src2); 541fcf5ef2aSThomas Huth 542b989ce73SRichard Henderson /* 543b989ce73SRichard Henderson * if (!(env->y & 1)) 544b989ce73SRichard Henderson * src2 = 0; 545fcf5ef2aSThomas Huth */ 54650280618SRichard Henderson tcg_gen_movcond_tl(TCG_COND_TSTEQ, t_src2, cpu_y, one, zero, t_src2); 547fcf5ef2aSThomas Huth 548b989ce73SRichard Henderson /* 549b989ce73SRichard Henderson * b2 = src1 & 1; 550b989ce73SRichard Henderson * y = (b2 << 31) | (y >> 1); 551b989ce73SRichard Henderson */ 5520b1183e3SPhilippe Mathieu-Daudé tcg_gen_extract_tl(t0, cpu_y, 1, 31); 553b989ce73SRichard Henderson tcg_gen_deposit_tl(cpu_y, t0, src1, 31, 1); 554fcf5ef2aSThomas Huth 555fcf5ef2aSThomas Huth // b1 = N ^ V; 5562a1905c7SRichard Henderson tcg_gen_xor_tl(t0, cpu_cc_N, cpu_cc_V); 557fcf5ef2aSThomas Huth 558b989ce73SRichard Henderson /* 559b989ce73SRichard Henderson * src1 = (b1 << 31) | (src1 >> 1) 560b989ce73SRichard Henderson */ 5612a1905c7SRichard Henderson tcg_gen_andi_tl(t0, t0, 1u << 31); 562b989ce73SRichard Henderson tcg_gen_shri_tl(t_src1, t_src1, 1); 563b989ce73SRichard Henderson tcg_gen_or_tl(t_src1, t_src1, t0); 564fcf5ef2aSThomas Huth 565b989ce73SRichard Henderson gen_op_addcc(dst, t_src1, t_src2); 566fcf5ef2aSThomas Huth } 567fcf5ef2aSThomas Huth 5680c2e96c1SRichard Henderson static void gen_op_multiply(TCGv dst, TCGv src1, TCGv src2, int sign_ext) 569fcf5ef2aSThomas Huth { 570fcf5ef2aSThomas Huth #if TARGET_LONG_BITS == 32 571fcf5ef2aSThomas Huth if (sign_ext) { 572fcf5ef2aSThomas Huth tcg_gen_muls2_tl(dst, cpu_y, src1, src2); 573fcf5ef2aSThomas Huth } else { 574fcf5ef2aSThomas Huth tcg_gen_mulu2_tl(dst, cpu_y, src1, src2); 575fcf5ef2aSThomas Huth } 576fcf5ef2aSThomas Huth #else 577fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new_i64(); 578fcf5ef2aSThomas Huth TCGv t1 = tcg_temp_new_i64(); 579fcf5ef2aSThomas Huth 580fcf5ef2aSThomas Huth if (sign_ext) { 581fcf5ef2aSThomas Huth tcg_gen_ext32s_i64(t0, src1); 582fcf5ef2aSThomas Huth tcg_gen_ext32s_i64(t1, src2); 583fcf5ef2aSThomas Huth } else { 584fcf5ef2aSThomas Huth tcg_gen_ext32u_i64(t0, src1); 585fcf5ef2aSThomas Huth tcg_gen_ext32u_i64(t1, src2); 586fcf5ef2aSThomas Huth } 587fcf5ef2aSThomas Huth 588fcf5ef2aSThomas Huth tcg_gen_mul_i64(dst, t0, t1); 589fcf5ef2aSThomas Huth tcg_gen_shri_i64(cpu_y, dst, 32); 590fcf5ef2aSThomas Huth #endif 591fcf5ef2aSThomas Huth } 592fcf5ef2aSThomas Huth 5930c2e96c1SRichard Henderson static void gen_op_umul(TCGv dst, TCGv src1, TCGv src2) 594fcf5ef2aSThomas Huth { 595fcf5ef2aSThomas Huth /* zero-extend truncated operands before multiplication */ 596fcf5ef2aSThomas Huth gen_op_multiply(dst, src1, src2, 0); 597fcf5ef2aSThomas Huth } 598fcf5ef2aSThomas Huth 5990c2e96c1SRichard Henderson static void gen_op_smul(TCGv dst, TCGv src1, TCGv src2) 600fcf5ef2aSThomas Huth { 601fcf5ef2aSThomas Huth /* sign-extend truncated operands before multiplication */ 602fcf5ef2aSThomas Huth gen_op_multiply(dst, src1, src2, 1); 603fcf5ef2aSThomas Huth } 604fcf5ef2aSThomas Huth 605680af1b4SRichard Henderson static void gen_op_umulxhi(TCGv dst, TCGv src1, TCGv src2) 606680af1b4SRichard Henderson { 607680af1b4SRichard Henderson TCGv discard = tcg_temp_new(); 608680af1b4SRichard Henderson tcg_gen_mulu2_tl(discard, dst, src1, src2); 609680af1b4SRichard Henderson } 610680af1b4SRichard Henderson 61168a414e9SRichard Henderson static void gen_op_fpmaddx(TCGv_i64 dst, TCGv_i64 src1, 61268a414e9SRichard Henderson TCGv_i64 src2, TCGv_i64 src3) 61368a414e9SRichard Henderson { 61468a414e9SRichard Henderson TCGv_i64 t = tcg_temp_new_i64(); 61568a414e9SRichard Henderson 61668a414e9SRichard Henderson tcg_gen_mul_i64(t, src1, src2); 61768a414e9SRichard Henderson tcg_gen_add_i64(dst, src3, t); 61868a414e9SRichard Henderson } 61968a414e9SRichard Henderson 62068a414e9SRichard Henderson static void gen_op_fpmaddxhi(TCGv_i64 dst, TCGv_i64 src1, 62168a414e9SRichard Henderson TCGv_i64 src2, TCGv_i64 src3) 62268a414e9SRichard Henderson { 62368a414e9SRichard Henderson TCGv_i64 l = tcg_temp_new_i64(); 62468a414e9SRichard Henderson TCGv_i64 h = tcg_temp_new_i64(); 62568a414e9SRichard Henderson TCGv_i64 z = tcg_constant_i64(0); 62668a414e9SRichard Henderson 62768a414e9SRichard Henderson tcg_gen_mulu2_i64(l, h, src1, src2); 62868a414e9SRichard Henderson tcg_gen_add2_i64(l, dst, l, h, src3, z); 62968a414e9SRichard Henderson } 63068a414e9SRichard Henderson 631c2636853SRichard Henderson static void gen_op_sdiv(TCGv dst, TCGv src1, TCGv src2) 632c2636853SRichard Henderson { 63313260103SRichard Henderson #ifdef TARGET_SPARC64 634c2636853SRichard Henderson gen_helper_sdiv(dst, tcg_env, src1, src2); 63513260103SRichard Henderson tcg_gen_ext32s_tl(dst, dst); 63613260103SRichard Henderson #else 63713260103SRichard Henderson TCGv_i64 t64 = tcg_temp_new_i64(); 63813260103SRichard Henderson gen_helper_sdiv(t64, tcg_env, src1, src2); 63913260103SRichard Henderson tcg_gen_trunc_i64_tl(dst, t64); 64013260103SRichard Henderson #endif 641c2636853SRichard Henderson } 642c2636853SRichard Henderson 643c2636853SRichard Henderson static void gen_op_udivcc(TCGv dst, TCGv src1, TCGv src2) 644c2636853SRichard Henderson { 64513260103SRichard Henderson TCGv_i64 t64; 64613260103SRichard Henderson 64713260103SRichard Henderson #ifdef TARGET_SPARC64 64813260103SRichard Henderson t64 = cpu_cc_V; 64913260103SRichard Henderson #else 65013260103SRichard Henderson t64 = tcg_temp_new_i64(); 65113260103SRichard Henderson #endif 65213260103SRichard Henderson 65313260103SRichard Henderson gen_helper_udiv(t64, tcg_env, src1, src2); 65413260103SRichard Henderson 65513260103SRichard Henderson #ifdef TARGET_SPARC64 65613260103SRichard Henderson tcg_gen_ext32u_tl(cpu_cc_N, t64); 65713260103SRichard Henderson tcg_gen_shri_tl(cpu_cc_V, t64, 32); 65813260103SRichard Henderson tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N); 65913260103SRichard Henderson tcg_gen_movi_tl(cpu_icc_C, 0); 66013260103SRichard Henderson #else 66113260103SRichard Henderson tcg_gen_extr_i64_tl(cpu_cc_N, cpu_cc_V, t64); 66213260103SRichard Henderson #endif 66313260103SRichard Henderson tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N); 66413260103SRichard Henderson tcg_gen_movi_tl(cpu_cc_C, 0); 66513260103SRichard Henderson tcg_gen_mov_tl(dst, cpu_cc_N); 666c2636853SRichard Henderson } 667c2636853SRichard Henderson 668c2636853SRichard Henderson static void gen_op_sdivcc(TCGv dst, TCGv src1, TCGv src2) 669c2636853SRichard Henderson { 67013260103SRichard Henderson TCGv_i64 t64; 67113260103SRichard Henderson 67213260103SRichard Henderson #ifdef TARGET_SPARC64 67313260103SRichard Henderson t64 = cpu_cc_V; 67413260103SRichard Henderson #else 67513260103SRichard Henderson t64 = tcg_temp_new_i64(); 67613260103SRichard Henderson #endif 67713260103SRichard Henderson 67813260103SRichard Henderson gen_helper_sdiv(t64, tcg_env, src1, src2); 67913260103SRichard Henderson 68013260103SRichard Henderson #ifdef TARGET_SPARC64 68113260103SRichard Henderson tcg_gen_ext32s_tl(cpu_cc_N, t64); 68213260103SRichard Henderson tcg_gen_shri_tl(cpu_cc_V, t64, 32); 68313260103SRichard Henderson tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N); 68413260103SRichard Henderson tcg_gen_movi_tl(cpu_icc_C, 0); 68513260103SRichard Henderson #else 68613260103SRichard Henderson tcg_gen_extr_i64_tl(cpu_cc_N, cpu_cc_V, t64); 68713260103SRichard Henderson #endif 68813260103SRichard Henderson tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N); 68913260103SRichard Henderson tcg_gen_movi_tl(cpu_cc_C, 0); 69013260103SRichard Henderson tcg_gen_mov_tl(dst, cpu_cc_N); 691c2636853SRichard Henderson } 692c2636853SRichard Henderson 693a9aba13dSRichard Henderson static void gen_op_taddcctv(TCGv dst, TCGv src1, TCGv src2) 694a9aba13dSRichard Henderson { 695a9aba13dSRichard Henderson gen_helper_taddcctv(dst, tcg_env, src1, src2); 696a9aba13dSRichard Henderson } 697a9aba13dSRichard Henderson 698a9aba13dSRichard Henderson static void gen_op_tsubcctv(TCGv dst, TCGv src1, TCGv src2) 699a9aba13dSRichard Henderson { 700a9aba13dSRichard Henderson gen_helper_tsubcctv(dst, tcg_env, src1, src2); 701a9aba13dSRichard Henderson } 702a9aba13dSRichard Henderson 7039c6ec5bcSRichard Henderson static void gen_op_popc(TCGv dst, TCGv src1, TCGv src2) 7049c6ec5bcSRichard Henderson { 7059c6ec5bcSRichard Henderson tcg_gen_ctpop_tl(dst, src2); 7069c6ec5bcSRichard Henderson } 7079c6ec5bcSRichard Henderson 708875ce392SRichard Henderson static void gen_op_lzcnt(TCGv dst, TCGv src) 709875ce392SRichard Henderson { 710875ce392SRichard Henderson tcg_gen_clzi_tl(dst, src, TARGET_LONG_BITS); 711875ce392SRichard Henderson } 712875ce392SRichard Henderson 71345bfed3bSRichard Henderson #ifndef TARGET_SPARC64 71445bfed3bSRichard Henderson static void gen_helper_array8(TCGv dst, TCGv src1, TCGv src2) 71545bfed3bSRichard Henderson { 71645bfed3bSRichard Henderson g_assert_not_reached(); 71745bfed3bSRichard Henderson } 71845bfed3bSRichard Henderson #endif 71945bfed3bSRichard Henderson 72045bfed3bSRichard Henderson static void gen_op_array16(TCGv dst, TCGv src1, TCGv src2) 72145bfed3bSRichard Henderson { 72245bfed3bSRichard Henderson gen_helper_array8(dst, src1, src2); 72345bfed3bSRichard Henderson tcg_gen_shli_tl(dst, dst, 1); 72445bfed3bSRichard Henderson } 72545bfed3bSRichard Henderson 72645bfed3bSRichard Henderson static void gen_op_array32(TCGv dst, TCGv src1, TCGv src2) 72745bfed3bSRichard Henderson { 72845bfed3bSRichard Henderson gen_helper_array8(dst, src1, src2); 72945bfed3bSRichard Henderson tcg_gen_shli_tl(dst, dst, 2); 73045bfed3bSRichard Henderson } 73145bfed3bSRichard Henderson 7322f722641SRichard Henderson static void gen_op_fpack16(TCGv_i32 dst, TCGv_i64 src) 7332f722641SRichard Henderson { 7342f722641SRichard Henderson #ifdef TARGET_SPARC64 7352f722641SRichard Henderson gen_helper_fpack16(dst, cpu_gsr, src); 7362f722641SRichard Henderson #else 7372f722641SRichard Henderson g_assert_not_reached(); 7382f722641SRichard Henderson #endif 7392f722641SRichard Henderson } 7402f722641SRichard Henderson 7412f722641SRichard Henderson static void gen_op_fpackfix(TCGv_i32 dst, TCGv_i64 src) 7422f722641SRichard Henderson { 7432f722641SRichard Henderson #ifdef TARGET_SPARC64 7442f722641SRichard Henderson gen_helper_fpackfix(dst, cpu_gsr, src); 7452f722641SRichard Henderson #else 7462f722641SRichard Henderson g_assert_not_reached(); 7472f722641SRichard Henderson #endif 7482f722641SRichard Henderson } 7492f722641SRichard Henderson 7504b6edc0aSRichard Henderson static void gen_op_fpack32(TCGv_i64 dst, TCGv_i64 src1, TCGv_i64 src2) 7514b6edc0aSRichard Henderson { 7524b6edc0aSRichard Henderson #ifdef TARGET_SPARC64 7534b6edc0aSRichard Henderson gen_helper_fpack32(dst, cpu_gsr, src1, src2); 7544b6edc0aSRichard Henderson #else 7554b6edc0aSRichard Henderson g_assert_not_reached(); 7564b6edc0aSRichard Henderson #endif 7574b6edc0aSRichard Henderson } 7584b6edc0aSRichard Henderson 7590d1d3aafSRichard Henderson static void gen_op_fpadds16s(TCGv_i32 d, TCGv_i32 src1, TCGv_i32 src2) 7600d1d3aafSRichard Henderson { 7610d1d3aafSRichard Henderson TCGv_i32 t[2]; 7620d1d3aafSRichard Henderson 7630d1d3aafSRichard Henderson for (int i = 0; i < 2; i++) { 7640d1d3aafSRichard Henderson TCGv_i32 u = tcg_temp_new_i32(); 7650d1d3aafSRichard Henderson TCGv_i32 v = tcg_temp_new_i32(); 7660d1d3aafSRichard Henderson 7670d1d3aafSRichard Henderson tcg_gen_sextract_i32(u, src1, i * 16, 16); 7680d1d3aafSRichard Henderson tcg_gen_sextract_i32(v, src2, i * 16, 16); 7690d1d3aafSRichard Henderson tcg_gen_add_i32(u, u, v); 7700d1d3aafSRichard Henderson tcg_gen_smax_i32(u, u, tcg_constant_i32(INT16_MIN)); 7710d1d3aafSRichard Henderson tcg_gen_smin_i32(u, u, tcg_constant_i32(INT16_MAX)); 7720d1d3aafSRichard Henderson t[i] = u; 7730d1d3aafSRichard Henderson } 7740d1d3aafSRichard Henderson tcg_gen_deposit_i32(d, t[0], t[1], 16, 16); 7750d1d3aafSRichard Henderson } 7760d1d3aafSRichard Henderson 7770d1d3aafSRichard Henderson static void gen_op_fpsubs16s(TCGv_i32 d, TCGv_i32 src1, TCGv_i32 src2) 7780d1d3aafSRichard Henderson { 7790d1d3aafSRichard Henderson TCGv_i32 t[2]; 7800d1d3aafSRichard Henderson 7810d1d3aafSRichard Henderson for (int i = 0; i < 2; i++) { 7820d1d3aafSRichard Henderson TCGv_i32 u = tcg_temp_new_i32(); 7830d1d3aafSRichard Henderson TCGv_i32 v = tcg_temp_new_i32(); 7840d1d3aafSRichard Henderson 7850d1d3aafSRichard Henderson tcg_gen_sextract_i32(u, src1, i * 16, 16); 7860d1d3aafSRichard Henderson tcg_gen_sextract_i32(v, src2, i * 16, 16); 7870d1d3aafSRichard Henderson tcg_gen_sub_i32(u, u, v); 7880d1d3aafSRichard Henderson tcg_gen_smax_i32(u, u, tcg_constant_i32(INT16_MIN)); 7890d1d3aafSRichard Henderson tcg_gen_smin_i32(u, u, tcg_constant_i32(INT16_MAX)); 7900d1d3aafSRichard Henderson t[i] = u; 7910d1d3aafSRichard Henderson } 7920d1d3aafSRichard Henderson tcg_gen_deposit_i32(d, t[0], t[1], 16, 16); 7930d1d3aafSRichard Henderson } 7940d1d3aafSRichard Henderson 7950d1d3aafSRichard Henderson static void gen_op_fpadds32s(TCGv_i32 d, TCGv_i32 src1, TCGv_i32 src2) 7960d1d3aafSRichard Henderson { 7970d1d3aafSRichard Henderson TCGv_i32 r = tcg_temp_new_i32(); 7980d1d3aafSRichard Henderson TCGv_i32 t = tcg_temp_new_i32(); 7990d1d3aafSRichard Henderson TCGv_i32 v = tcg_temp_new_i32(); 8000d1d3aafSRichard Henderson TCGv_i32 z = tcg_constant_i32(0); 8010d1d3aafSRichard Henderson 8020d1d3aafSRichard Henderson tcg_gen_add_i32(r, src1, src2); 8030d1d3aafSRichard Henderson tcg_gen_xor_i32(t, src1, src2); 8040d1d3aafSRichard Henderson tcg_gen_xor_i32(v, r, src2); 8050d1d3aafSRichard Henderson tcg_gen_andc_i32(v, v, t); 8060d1d3aafSRichard Henderson 8070d1d3aafSRichard Henderson tcg_gen_setcond_i32(TCG_COND_GE, t, r, z); 8080d1d3aafSRichard Henderson tcg_gen_addi_i32(t, t, INT32_MAX); 8090d1d3aafSRichard Henderson 8100d1d3aafSRichard Henderson tcg_gen_movcond_i32(TCG_COND_LT, d, v, z, t, r); 8110d1d3aafSRichard Henderson } 8120d1d3aafSRichard Henderson 8130d1d3aafSRichard Henderson static void gen_op_fpsubs32s(TCGv_i32 d, TCGv_i32 src1, TCGv_i32 src2) 8140d1d3aafSRichard Henderson { 8150d1d3aafSRichard Henderson TCGv_i32 r = tcg_temp_new_i32(); 8160d1d3aafSRichard Henderson TCGv_i32 t = tcg_temp_new_i32(); 8170d1d3aafSRichard Henderson TCGv_i32 v = tcg_temp_new_i32(); 8180d1d3aafSRichard Henderson TCGv_i32 z = tcg_constant_i32(0); 8190d1d3aafSRichard Henderson 8200d1d3aafSRichard Henderson tcg_gen_sub_i32(r, src1, src2); 8210d1d3aafSRichard Henderson tcg_gen_xor_i32(t, src1, src2); 8220d1d3aafSRichard Henderson tcg_gen_xor_i32(v, r, src1); 8230d1d3aafSRichard Henderson tcg_gen_and_i32(v, v, t); 8240d1d3aafSRichard Henderson 8250d1d3aafSRichard Henderson tcg_gen_setcond_i32(TCG_COND_GE, t, r, z); 8260d1d3aafSRichard Henderson tcg_gen_addi_i32(t, t, INT32_MAX); 8270d1d3aafSRichard Henderson 8280d1d3aafSRichard Henderson tcg_gen_movcond_i32(TCG_COND_LT, d, v, z, t, r); 8290d1d3aafSRichard Henderson } 8300d1d3aafSRichard Henderson 831b2b48493SRichard Henderson static void gen_op_faligndata_i(TCGv_i64 dst, TCGv_i64 s1, 832b2b48493SRichard Henderson TCGv_i64 s2, TCGv gsr) 8334b6edc0aSRichard Henderson { 8344b6edc0aSRichard Henderson #ifdef TARGET_SPARC64 8354b6edc0aSRichard Henderson TCGv t1, t2, shift; 8364b6edc0aSRichard Henderson 8374b6edc0aSRichard Henderson t1 = tcg_temp_new(); 8384b6edc0aSRichard Henderson t2 = tcg_temp_new(); 8394b6edc0aSRichard Henderson shift = tcg_temp_new(); 8404b6edc0aSRichard Henderson 841b2b48493SRichard Henderson tcg_gen_andi_tl(shift, gsr, 7); 8424b6edc0aSRichard Henderson tcg_gen_shli_tl(shift, shift, 3); 8434b6edc0aSRichard Henderson tcg_gen_shl_tl(t1, s1, shift); 8444b6edc0aSRichard Henderson 8454b6edc0aSRichard Henderson /* 8464b6edc0aSRichard Henderson * A shift of 64 does not produce 0 in TCG. Divide this into a 8474b6edc0aSRichard Henderson * shift of (up to 63) followed by a constant shift of 1. 8484b6edc0aSRichard Henderson */ 8494b6edc0aSRichard Henderson tcg_gen_xori_tl(shift, shift, 63); 8504b6edc0aSRichard Henderson tcg_gen_shr_tl(t2, s2, shift); 8514b6edc0aSRichard Henderson tcg_gen_shri_tl(t2, t2, 1); 8524b6edc0aSRichard Henderson 8534b6edc0aSRichard Henderson tcg_gen_or_tl(dst, t1, t2); 8544b6edc0aSRichard Henderson #else 8554b6edc0aSRichard Henderson g_assert_not_reached(); 8564b6edc0aSRichard Henderson #endif 8574b6edc0aSRichard Henderson } 8584b6edc0aSRichard Henderson 859b2b48493SRichard Henderson static void gen_op_faligndata_g(TCGv_i64 dst, TCGv_i64 s1, TCGv_i64 s2) 860b2b48493SRichard Henderson { 861b2b48493SRichard Henderson gen_op_faligndata_i(dst, s1, s2, cpu_gsr); 862b2b48493SRichard Henderson } 863b2b48493SRichard Henderson 8644b6edc0aSRichard Henderson static void gen_op_bshuffle(TCGv_i64 dst, TCGv_i64 src1, TCGv_i64 src2) 8654b6edc0aSRichard Henderson { 8664b6edc0aSRichard Henderson #ifdef TARGET_SPARC64 8674b6edc0aSRichard Henderson gen_helper_bshuffle(dst, cpu_gsr, src1, src2); 8684b6edc0aSRichard Henderson #else 8694b6edc0aSRichard Henderson g_assert_not_reached(); 8704b6edc0aSRichard Henderson #endif 8714b6edc0aSRichard Henderson } 8724b6edc0aSRichard Henderson 8737d5ebd8fSRichard Henderson static void gen_op_pdistn(TCGv dst, TCGv_i64 src1, TCGv_i64 src2) 8747d5ebd8fSRichard Henderson { 8757d5ebd8fSRichard Henderson #ifdef TARGET_SPARC64 8767d5ebd8fSRichard Henderson gen_helper_pdist(dst, tcg_constant_i64(0), src1, src2); 8777d5ebd8fSRichard Henderson #else 8787d5ebd8fSRichard Henderson g_assert_not_reached(); 8797d5ebd8fSRichard Henderson #endif 8807d5ebd8fSRichard Henderson } 8817d5ebd8fSRichard Henderson 882a859602cSRichard Henderson static void gen_op_fmul8x16al(TCGv_i64 dst, TCGv_i32 src1, TCGv_i32 src2) 883a859602cSRichard Henderson { 884a859602cSRichard Henderson tcg_gen_ext16s_i32(src2, src2); 885a859602cSRichard Henderson gen_helper_fmul8x16a(dst, src1, src2); 886a859602cSRichard Henderson } 887a859602cSRichard Henderson 888a859602cSRichard Henderson static void gen_op_fmul8x16au(TCGv_i64 dst, TCGv_i32 src1, TCGv_i32 src2) 889a859602cSRichard Henderson { 890a859602cSRichard Henderson tcg_gen_sari_i32(src2, src2, 16); 891a859602cSRichard Henderson gen_helper_fmul8x16a(dst, src1, src2); 892a859602cSRichard Henderson } 893a859602cSRichard Henderson 894be8998e0SRichard Henderson static void gen_op_fmuld8ulx16(TCGv_i64 dst, TCGv_i32 src1, TCGv_i32 src2) 895be8998e0SRichard Henderson { 896be8998e0SRichard Henderson TCGv_i32 t0 = tcg_temp_new_i32(); 897be8998e0SRichard Henderson TCGv_i32 t1 = tcg_temp_new_i32(); 898be8998e0SRichard Henderson TCGv_i32 t2 = tcg_temp_new_i32(); 899be8998e0SRichard Henderson 900be8998e0SRichard Henderson tcg_gen_ext8u_i32(t0, src1); 901be8998e0SRichard Henderson tcg_gen_ext16s_i32(t1, src2); 902be8998e0SRichard Henderson tcg_gen_mul_i32(t0, t0, t1); 903be8998e0SRichard Henderson 904be8998e0SRichard Henderson tcg_gen_extract_i32(t1, src1, 16, 8); 905be8998e0SRichard Henderson tcg_gen_sextract_i32(t2, src2, 16, 16); 906be8998e0SRichard Henderson tcg_gen_mul_i32(t1, t1, t2); 907be8998e0SRichard Henderson 908be8998e0SRichard Henderson tcg_gen_concat_i32_i64(dst, t0, t1); 909be8998e0SRichard Henderson } 910be8998e0SRichard Henderson 911be8998e0SRichard Henderson static void gen_op_fmuld8sux16(TCGv_i64 dst, TCGv_i32 src1, TCGv_i32 src2) 912be8998e0SRichard Henderson { 913be8998e0SRichard Henderson TCGv_i32 t0 = tcg_temp_new_i32(); 914be8998e0SRichard Henderson TCGv_i32 t1 = tcg_temp_new_i32(); 915be8998e0SRichard Henderson TCGv_i32 t2 = tcg_temp_new_i32(); 916be8998e0SRichard Henderson 917be8998e0SRichard Henderson /* 918be8998e0SRichard Henderson * The insn description talks about extracting the upper 8 bits 919be8998e0SRichard Henderson * of the signed 16-bit input rs1, performing the multiply, then 920be8998e0SRichard Henderson * shifting left by 8 bits. Instead, zap the lower 8 bits of 921be8998e0SRichard Henderson * the rs1 input, which avoids the need for two shifts. 922be8998e0SRichard Henderson */ 923be8998e0SRichard Henderson tcg_gen_ext16s_i32(t0, src1); 924be8998e0SRichard Henderson tcg_gen_andi_i32(t0, t0, ~0xff); 925be8998e0SRichard Henderson tcg_gen_ext16s_i32(t1, src2); 926be8998e0SRichard Henderson tcg_gen_mul_i32(t0, t0, t1); 927be8998e0SRichard Henderson 928be8998e0SRichard Henderson tcg_gen_sextract_i32(t1, src1, 16, 16); 929be8998e0SRichard Henderson tcg_gen_andi_i32(t1, t1, ~0xff); 930be8998e0SRichard Henderson tcg_gen_sextract_i32(t2, src2, 16, 16); 931be8998e0SRichard Henderson tcg_gen_mul_i32(t1, t1, t2); 932be8998e0SRichard Henderson 933be8998e0SRichard Henderson tcg_gen_concat_i32_i64(dst, t0, t1); 934be8998e0SRichard Henderson } 935be8998e0SRichard Henderson 9367837185eSRichard Henderson #ifdef TARGET_SPARC64 9377837185eSRichard Henderson static void gen_vec_fchksm16(unsigned vece, TCGv_vec dst, 9387837185eSRichard Henderson TCGv_vec src1, TCGv_vec src2) 9397837185eSRichard Henderson { 9407837185eSRichard Henderson TCGv_vec a = tcg_temp_new_vec_matching(dst); 9417837185eSRichard Henderson TCGv_vec c = tcg_temp_new_vec_matching(dst); 9427837185eSRichard Henderson 9437837185eSRichard Henderson tcg_gen_add_vec(vece, a, src1, src2); 9447837185eSRichard Henderson tcg_gen_cmp_vec(TCG_COND_LTU, vece, c, a, src1); 9457837185eSRichard Henderson /* Vector cmp produces -1 for true, so subtract to add carry. */ 9467837185eSRichard Henderson tcg_gen_sub_vec(vece, dst, a, c); 9477837185eSRichard Henderson } 9487837185eSRichard Henderson 9497837185eSRichard Henderson static void gen_op_fchksm16(unsigned vece, uint32_t dofs, uint32_t aofs, 9507837185eSRichard Henderson uint32_t bofs, uint32_t oprsz, uint32_t maxsz) 9517837185eSRichard Henderson { 9527837185eSRichard Henderson static const TCGOpcode vecop_list[] = { 9537837185eSRichard Henderson INDEX_op_cmp_vec, INDEX_op_add_vec, INDEX_op_sub_vec, 9547837185eSRichard Henderson }; 9557837185eSRichard Henderson static const GVecGen3 op = { 9567837185eSRichard Henderson .fni8 = gen_helper_fchksm16, 9577837185eSRichard Henderson .fniv = gen_vec_fchksm16, 9587837185eSRichard Henderson .opt_opc = vecop_list, 9597837185eSRichard Henderson .vece = MO_16, 9607837185eSRichard Henderson }; 9617837185eSRichard Henderson tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &op); 9627837185eSRichard Henderson } 963d6ff1ccbSRichard Henderson 964d6ff1ccbSRichard Henderson static void gen_vec_fmean16(unsigned vece, TCGv_vec dst, 965d6ff1ccbSRichard Henderson TCGv_vec src1, TCGv_vec src2) 966d6ff1ccbSRichard Henderson { 967d6ff1ccbSRichard Henderson TCGv_vec t = tcg_temp_new_vec_matching(dst); 968d6ff1ccbSRichard Henderson 969d6ff1ccbSRichard Henderson tcg_gen_or_vec(vece, t, src1, src2); 970d6ff1ccbSRichard Henderson tcg_gen_and_vec(vece, t, t, tcg_constant_vec_matching(dst, vece, 1)); 971d6ff1ccbSRichard Henderson tcg_gen_sari_vec(vece, src1, src1, 1); 972d6ff1ccbSRichard Henderson tcg_gen_sari_vec(vece, src2, src2, 1); 973d6ff1ccbSRichard Henderson tcg_gen_add_vec(vece, dst, src1, src2); 974d6ff1ccbSRichard Henderson tcg_gen_add_vec(vece, dst, dst, t); 975d6ff1ccbSRichard Henderson } 976d6ff1ccbSRichard Henderson 977d6ff1ccbSRichard Henderson static void gen_op_fmean16(unsigned vece, uint32_t dofs, uint32_t aofs, 978d6ff1ccbSRichard Henderson uint32_t bofs, uint32_t oprsz, uint32_t maxsz) 979d6ff1ccbSRichard Henderson { 980d6ff1ccbSRichard Henderson static const TCGOpcode vecop_list[] = { 981d6ff1ccbSRichard Henderson INDEX_op_add_vec, INDEX_op_sari_vec, 982d6ff1ccbSRichard Henderson }; 983d6ff1ccbSRichard Henderson static const GVecGen3 op = { 984d6ff1ccbSRichard Henderson .fni8 = gen_helper_fmean16, 985d6ff1ccbSRichard Henderson .fniv = gen_vec_fmean16, 986d6ff1ccbSRichard Henderson .opt_opc = vecop_list, 987d6ff1ccbSRichard Henderson .vece = MO_16, 988d6ff1ccbSRichard Henderson }; 989d6ff1ccbSRichard Henderson tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &op); 990d6ff1ccbSRichard Henderson } 9917837185eSRichard Henderson #else 9927837185eSRichard Henderson #define gen_op_fchksm16 ({ qemu_build_not_reached(); NULL; }) 993d6ff1ccbSRichard Henderson #define gen_op_fmean16 ({ qemu_build_not_reached(); NULL; }) 9947837185eSRichard Henderson #endif 9957837185eSRichard Henderson 99689527e3aSRichard Henderson static void finishing_insn(DisasContext *dc) 99789527e3aSRichard Henderson { 99889527e3aSRichard Henderson /* 99989527e3aSRichard Henderson * From here, there is no future path through an unwinding exception. 100089527e3aSRichard Henderson * If the current insn cannot raise an exception, the computation of 100189527e3aSRichard Henderson * cpu_cond may be able to be elided. 100289527e3aSRichard Henderson */ 100389527e3aSRichard Henderson if (dc->cpu_cond_live) { 100489527e3aSRichard Henderson tcg_gen_discard_tl(cpu_cond); 100589527e3aSRichard Henderson dc->cpu_cond_live = false; 100689527e3aSRichard Henderson } 100789527e3aSRichard Henderson } 100889527e3aSRichard Henderson 10090c2e96c1SRichard Henderson static void gen_generic_branch(DisasContext *dc) 1010fcf5ef2aSThomas Huth { 101100ab7e61SRichard Henderson TCGv npc0 = tcg_constant_tl(dc->jump_pc[0]); 101200ab7e61SRichard Henderson TCGv npc1 = tcg_constant_tl(dc->jump_pc[1]); 1013533f042fSRichard Henderson TCGv c2 = tcg_constant_tl(dc->jump.c2); 1014fcf5ef2aSThomas Huth 1015533f042fSRichard Henderson tcg_gen_movcond_tl(dc->jump.cond, cpu_npc, dc->jump.c1, c2, npc0, npc1); 1016fcf5ef2aSThomas Huth } 1017fcf5ef2aSThomas Huth 1018fcf5ef2aSThomas Huth /* call this function before using the condition register as it may 1019fcf5ef2aSThomas Huth have been set for a jump */ 10200c2e96c1SRichard Henderson static void flush_cond(DisasContext *dc) 1021fcf5ef2aSThomas Huth { 1022fcf5ef2aSThomas Huth if (dc->npc == JUMP_PC) { 1023fcf5ef2aSThomas Huth gen_generic_branch(dc); 102499c82c47SRichard Henderson dc->npc = DYNAMIC_PC_LOOKUP; 1025fcf5ef2aSThomas Huth } 1026fcf5ef2aSThomas Huth } 1027fcf5ef2aSThomas Huth 10280c2e96c1SRichard Henderson static void save_npc(DisasContext *dc) 1029fcf5ef2aSThomas Huth { 1030633c4283SRichard Henderson if (dc->npc & 3) { 1031633c4283SRichard Henderson switch (dc->npc) { 1032633c4283SRichard Henderson case JUMP_PC: 1033fcf5ef2aSThomas Huth gen_generic_branch(dc); 103499c82c47SRichard Henderson dc->npc = DYNAMIC_PC_LOOKUP; 1035633c4283SRichard Henderson break; 1036633c4283SRichard Henderson case DYNAMIC_PC: 1037633c4283SRichard Henderson case DYNAMIC_PC_LOOKUP: 1038633c4283SRichard Henderson break; 1039633c4283SRichard Henderson default: 1040633c4283SRichard Henderson g_assert_not_reached(); 1041633c4283SRichard Henderson } 1042633c4283SRichard Henderson } else { 1043fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_npc, dc->npc); 1044fcf5ef2aSThomas Huth } 1045fcf5ef2aSThomas Huth } 1046fcf5ef2aSThomas Huth 10470c2e96c1SRichard Henderson static void save_state(DisasContext *dc) 1048fcf5ef2aSThomas Huth { 1049fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_pc, dc->pc); 1050fcf5ef2aSThomas Huth save_npc(dc); 1051fcf5ef2aSThomas Huth } 1052fcf5ef2aSThomas Huth 1053fcf5ef2aSThomas Huth static void gen_exception(DisasContext *dc, int which) 1054fcf5ef2aSThomas Huth { 105589527e3aSRichard Henderson finishing_insn(dc); 1056fcf5ef2aSThomas Huth save_state(dc); 1057ad75a51eSRichard Henderson gen_helper_raise_exception(tcg_env, tcg_constant_i32(which)); 1058af00be49SEmilio G. Cota dc->base.is_jmp = DISAS_NORETURN; 1059fcf5ef2aSThomas Huth } 1060fcf5ef2aSThomas Huth 1061186e7890SRichard Henderson static TCGLabel *delay_exceptionv(DisasContext *dc, TCGv_i32 excp) 1062fcf5ef2aSThomas Huth { 1063186e7890SRichard Henderson DisasDelayException *e = g_new0(DisasDelayException, 1); 1064186e7890SRichard Henderson 1065186e7890SRichard Henderson e->next = dc->delay_excp_list; 1066186e7890SRichard Henderson dc->delay_excp_list = e; 1067186e7890SRichard Henderson 1068186e7890SRichard Henderson e->lab = gen_new_label(); 1069186e7890SRichard Henderson e->excp = excp; 1070186e7890SRichard Henderson e->pc = dc->pc; 1071186e7890SRichard Henderson /* Caller must have used flush_cond before branch. */ 1072186e7890SRichard Henderson assert(e->npc != JUMP_PC); 1073186e7890SRichard Henderson e->npc = dc->npc; 1074186e7890SRichard Henderson 1075186e7890SRichard Henderson return e->lab; 1076186e7890SRichard Henderson } 1077186e7890SRichard Henderson 1078186e7890SRichard Henderson static TCGLabel *delay_exception(DisasContext *dc, int excp) 1079186e7890SRichard Henderson { 1080186e7890SRichard Henderson return delay_exceptionv(dc, tcg_constant_i32(excp)); 1081186e7890SRichard Henderson } 1082186e7890SRichard Henderson 1083186e7890SRichard Henderson static void gen_check_align(DisasContext *dc, TCGv addr, int mask) 1084186e7890SRichard Henderson { 1085186e7890SRichard Henderson TCGv t = tcg_temp_new(); 1086186e7890SRichard Henderson TCGLabel *lab; 1087186e7890SRichard Henderson 1088186e7890SRichard Henderson tcg_gen_andi_tl(t, addr, mask); 1089186e7890SRichard Henderson 1090186e7890SRichard Henderson flush_cond(dc); 1091186e7890SRichard Henderson lab = delay_exception(dc, TT_UNALIGNED); 1092186e7890SRichard Henderson tcg_gen_brcondi_tl(TCG_COND_NE, t, 0, lab); 1093fcf5ef2aSThomas Huth } 1094fcf5ef2aSThomas Huth 10950c2e96c1SRichard Henderson static void gen_mov_pc_npc(DisasContext *dc) 1096fcf5ef2aSThomas Huth { 109789527e3aSRichard Henderson finishing_insn(dc); 109889527e3aSRichard Henderson 1099633c4283SRichard Henderson if (dc->npc & 3) { 1100633c4283SRichard Henderson switch (dc->npc) { 1101633c4283SRichard Henderson case JUMP_PC: 1102fcf5ef2aSThomas Huth gen_generic_branch(dc); 1103fcf5ef2aSThomas Huth tcg_gen_mov_tl(cpu_pc, cpu_npc); 110499c82c47SRichard Henderson dc->pc = DYNAMIC_PC_LOOKUP; 1105633c4283SRichard Henderson break; 1106633c4283SRichard Henderson case DYNAMIC_PC: 1107633c4283SRichard Henderson case DYNAMIC_PC_LOOKUP: 1108fcf5ef2aSThomas Huth tcg_gen_mov_tl(cpu_pc, cpu_npc); 1109633c4283SRichard Henderson dc->pc = dc->npc; 1110633c4283SRichard Henderson break; 1111633c4283SRichard Henderson default: 1112633c4283SRichard Henderson g_assert_not_reached(); 1113633c4283SRichard Henderson } 1114fcf5ef2aSThomas Huth } else { 1115fcf5ef2aSThomas Huth dc->pc = dc->npc; 1116fcf5ef2aSThomas Huth } 1117fcf5ef2aSThomas Huth } 1118fcf5ef2aSThomas Huth 1119fcf5ef2aSThomas Huth static void gen_compare(DisasCompare *cmp, bool xcc, unsigned int cond, 1120fcf5ef2aSThomas Huth DisasContext *dc) 1121fcf5ef2aSThomas Huth { 1122b597eedcSRichard Henderson TCGv t1; 1123fcf5ef2aSThomas Huth 11242a1905c7SRichard Henderson cmp->c1 = t1 = tcg_temp_new(); 1125c8507ebfSRichard Henderson cmp->c2 = 0; 11262a1905c7SRichard Henderson 11272a1905c7SRichard Henderson switch (cond & 7) { 11282a1905c7SRichard Henderson case 0x0: /* never */ 11292a1905c7SRichard Henderson cmp->cond = TCG_COND_NEVER; 1130c8507ebfSRichard Henderson cmp->c1 = tcg_constant_tl(0); 1131fcf5ef2aSThomas Huth break; 11322a1905c7SRichard Henderson 11332a1905c7SRichard Henderson case 0x1: /* eq: Z */ 11342a1905c7SRichard Henderson cmp->cond = TCG_COND_EQ; 11352a1905c7SRichard Henderson if (TARGET_LONG_BITS == 32 || xcc) { 11362a1905c7SRichard Henderson tcg_gen_mov_tl(t1, cpu_cc_Z); 11372a1905c7SRichard Henderson } else { 11382a1905c7SRichard Henderson tcg_gen_ext32u_tl(t1, cpu_icc_Z); 11392a1905c7SRichard Henderson } 11402a1905c7SRichard Henderson break; 11412a1905c7SRichard Henderson 11422a1905c7SRichard Henderson case 0x2: /* le: Z | (N ^ V) */ 11432a1905c7SRichard Henderson /* 11442a1905c7SRichard Henderson * Simplify: 11452a1905c7SRichard Henderson * cc_Z || (N ^ V) < 0 NE 11462a1905c7SRichard Henderson * cc_Z && !((N ^ V) < 0) EQ 11472a1905c7SRichard Henderson * cc_Z & ~((N ^ V) >> TLB) EQ 11482a1905c7SRichard Henderson */ 11492a1905c7SRichard Henderson cmp->cond = TCG_COND_EQ; 11502a1905c7SRichard Henderson tcg_gen_xor_tl(t1, cpu_cc_N, cpu_cc_V); 11512a1905c7SRichard Henderson tcg_gen_sextract_tl(t1, t1, xcc ? 63 : 31, 1); 11522a1905c7SRichard Henderson tcg_gen_andc_tl(t1, xcc ? cpu_cc_Z : cpu_icc_Z, t1); 11532a1905c7SRichard Henderson if (TARGET_LONG_BITS == 64 && !xcc) { 11542a1905c7SRichard Henderson tcg_gen_ext32u_tl(t1, t1); 11552a1905c7SRichard Henderson } 11562a1905c7SRichard Henderson break; 11572a1905c7SRichard Henderson 11582a1905c7SRichard Henderson case 0x3: /* lt: N ^ V */ 11592a1905c7SRichard Henderson cmp->cond = TCG_COND_LT; 11602a1905c7SRichard Henderson tcg_gen_xor_tl(t1, cpu_cc_N, cpu_cc_V); 11612a1905c7SRichard Henderson if (TARGET_LONG_BITS == 64 && !xcc) { 11622a1905c7SRichard Henderson tcg_gen_ext32s_tl(t1, t1); 11632a1905c7SRichard Henderson } 11642a1905c7SRichard Henderson break; 11652a1905c7SRichard Henderson 11662a1905c7SRichard Henderson case 0x4: /* leu: Z | C */ 11672a1905c7SRichard Henderson /* 11682a1905c7SRichard Henderson * Simplify: 11692a1905c7SRichard Henderson * cc_Z == 0 || cc_C != 0 NE 11702a1905c7SRichard Henderson * cc_Z != 0 && cc_C == 0 EQ 11712a1905c7SRichard Henderson * cc_Z & (cc_C ? 0 : -1) EQ 11722a1905c7SRichard Henderson * cc_Z & (cc_C - 1) EQ 11732a1905c7SRichard Henderson */ 11742a1905c7SRichard Henderson cmp->cond = TCG_COND_EQ; 11752a1905c7SRichard Henderson if (TARGET_LONG_BITS == 32 || xcc) { 11762a1905c7SRichard Henderson tcg_gen_subi_tl(t1, cpu_cc_C, 1); 11772a1905c7SRichard Henderson tcg_gen_and_tl(t1, t1, cpu_cc_Z); 11782a1905c7SRichard Henderson } else { 11792a1905c7SRichard Henderson tcg_gen_extract_tl(t1, cpu_icc_C, 32, 1); 11802a1905c7SRichard Henderson tcg_gen_subi_tl(t1, t1, 1); 11812a1905c7SRichard Henderson tcg_gen_and_tl(t1, t1, cpu_icc_Z); 11822a1905c7SRichard Henderson tcg_gen_ext32u_tl(t1, t1); 11832a1905c7SRichard Henderson } 11842a1905c7SRichard Henderson break; 11852a1905c7SRichard Henderson 11862a1905c7SRichard Henderson case 0x5: /* ltu: C */ 11872a1905c7SRichard Henderson cmp->cond = TCG_COND_NE; 11882a1905c7SRichard Henderson if (TARGET_LONG_BITS == 32 || xcc) { 11892a1905c7SRichard Henderson tcg_gen_mov_tl(t1, cpu_cc_C); 11902a1905c7SRichard Henderson } else { 11912a1905c7SRichard Henderson tcg_gen_extract_tl(t1, cpu_icc_C, 32, 1); 11922a1905c7SRichard Henderson } 11932a1905c7SRichard Henderson break; 11942a1905c7SRichard Henderson 11952a1905c7SRichard Henderson case 0x6: /* neg: N */ 11962a1905c7SRichard Henderson cmp->cond = TCG_COND_LT; 11972a1905c7SRichard Henderson if (TARGET_LONG_BITS == 32 || xcc) { 11982a1905c7SRichard Henderson tcg_gen_mov_tl(t1, cpu_cc_N); 11992a1905c7SRichard Henderson } else { 12002a1905c7SRichard Henderson tcg_gen_ext32s_tl(t1, cpu_cc_N); 12012a1905c7SRichard Henderson } 12022a1905c7SRichard Henderson break; 12032a1905c7SRichard Henderson 12042a1905c7SRichard Henderson case 0x7: /* vs: V */ 12052a1905c7SRichard Henderson cmp->cond = TCG_COND_LT; 12062a1905c7SRichard Henderson if (TARGET_LONG_BITS == 32 || xcc) { 12072a1905c7SRichard Henderson tcg_gen_mov_tl(t1, cpu_cc_V); 12082a1905c7SRichard Henderson } else { 12092a1905c7SRichard Henderson tcg_gen_ext32s_tl(t1, cpu_cc_V); 12102a1905c7SRichard Henderson } 12112a1905c7SRichard Henderson break; 12122a1905c7SRichard Henderson } 12132a1905c7SRichard Henderson if (cond & 8) { 12142a1905c7SRichard Henderson cmp->cond = tcg_invert_cond(cmp->cond); 1215fcf5ef2aSThomas Huth } 1216fcf5ef2aSThomas Huth } 1217fcf5ef2aSThomas Huth 1218fcf5ef2aSThomas Huth static void gen_fcompare(DisasCompare *cmp, unsigned int cc, unsigned int cond) 1219fcf5ef2aSThomas Huth { 1220d8c5b92fSRichard Henderson TCGv_i32 fcc = cpu_fcc[cc]; 1221d8c5b92fSRichard Henderson TCGv_i32 c1 = fcc; 1222d8c5b92fSRichard Henderson int c2 = 0; 1223d8c5b92fSRichard Henderson TCGCond tcond; 1224fcf5ef2aSThomas Huth 1225d8c5b92fSRichard Henderson /* 1226d8c5b92fSRichard Henderson * FCC values: 1227d8c5b92fSRichard Henderson * 0 = 1228d8c5b92fSRichard Henderson * 1 < 1229d8c5b92fSRichard Henderson * 2 > 1230d8c5b92fSRichard Henderson * 3 unordered 1231d8c5b92fSRichard Henderson */ 1232d8c5b92fSRichard Henderson switch (cond & 7) { 1233d8c5b92fSRichard Henderson case 0x0: /* fbn */ 1234d8c5b92fSRichard Henderson tcond = TCG_COND_NEVER; 1235fcf5ef2aSThomas Huth break; 1236d8c5b92fSRichard Henderson case 0x1: /* fbne : !0 */ 1237d8c5b92fSRichard Henderson tcond = TCG_COND_NE; 1238fcf5ef2aSThomas Huth break; 1239d8c5b92fSRichard Henderson case 0x2: /* fblg : 1 or 2 */ 1240d8c5b92fSRichard Henderson /* fcc in {1,2} - 1 -> fcc in {0,1} */ 1241d8c5b92fSRichard Henderson c1 = tcg_temp_new_i32(); 1242d8c5b92fSRichard Henderson tcg_gen_addi_i32(c1, fcc, -1); 1243d8c5b92fSRichard Henderson c2 = 1; 1244d8c5b92fSRichard Henderson tcond = TCG_COND_LEU; 1245fcf5ef2aSThomas Huth break; 1246d8c5b92fSRichard Henderson case 0x3: /* fbul : 1 or 3 */ 1247d8c5b92fSRichard Henderson c1 = tcg_temp_new_i32(); 1248d8c5b92fSRichard Henderson tcg_gen_andi_i32(c1, fcc, 1); 1249d8c5b92fSRichard Henderson tcond = TCG_COND_NE; 1250d8c5b92fSRichard Henderson break; 1251d8c5b92fSRichard Henderson case 0x4: /* fbl : 1 */ 1252d8c5b92fSRichard Henderson c2 = 1; 1253d8c5b92fSRichard Henderson tcond = TCG_COND_EQ; 1254d8c5b92fSRichard Henderson break; 1255d8c5b92fSRichard Henderson case 0x5: /* fbug : 2 or 3 */ 1256d8c5b92fSRichard Henderson c2 = 2; 1257d8c5b92fSRichard Henderson tcond = TCG_COND_GEU; 1258d8c5b92fSRichard Henderson break; 1259d8c5b92fSRichard Henderson case 0x6: /* fbg : 2 */ 1260d8c5b92fSRichard Henderson c2 = 2; 1261d8c5b92fSRichard Henderson tcond = TCG_COND_EQ; 1262d8c5b92fSRichard Henderson break; 1263d8c5b92fSRichard Henderson case 0x7: /* fbu : 3 */ 1264d8c5b92fSRichard Henderson c2 = 3; 1265d8c5b92fSRichard Henderson tcond = TCG_COND_EQ; 1266fcf5ef2aSThomas Huth break; 1267fcf5ef2aSThomas Huth } 1268d8c5b92fSRichard Henderson if (cond & 8) { 1269d8c5b92fSRichard Henderson tcond = tcg_invert_cond(tcond); 1270fcf5ef2aSThomas Huth } 1271d8c5b92fSRichard Henderson 1272d8c5b92fSRichard Henderson cmp->cond = tcond; 1273d8c5b92fSRichard Henderson cmp->c2 = c2; 1274d8c5b92fSRichard Henderson cmp->c1 = tcg_temp_new(); 1275d8c5b92fSRichard Henderson tcg_gen_extu_i32_tl(cmp->c1, c1); 1276fcf5ef2aSThomas Huth } 1277fcf5ef2aSThomas Huth 12782c4f56c9SRichard Henderson static bool gen_compare_reg(DisasCompare *cmp, int cond, TCGv r_src) 12792c4f56c9SRichard Henderson { 12802c4f56c9SRichard Henderson static const TCGCond cond_reg[4] = { 1281ab9ffe98SRichard Henderson TCG_COND_NEVER, /* reserved */ 1282fcf5ef2aSThomas Huth TCG_COND_EQ, 1283fcf5ef2aSThomas Huth TCG_COND_LE, 1284fcf5ef2aSThomas Huth TCG_COND_LT, 1285fcf5ef2aSThomas Huth }; 12862c4f56c9SRichard Henderson TCGCond tcond; 1287fcf5ef2aSThomas Huth 12882c4f56c9SRichard Henderson if ((cond & 3) == 0) { 12892c4f56c9SRichard Henderson return false; 12902c4f56c9SRichard Henderson } 12912c4f56c9SRichard Henderson tcond = cond_reg[cond & 3]; 12922c4f56c9SRichard Henderson if (cond & 4) { 12932c4f56c9SRichard Henderson tcond = tcg_invert_cond(tcond); 12942c4f56c9SRichard Henderson } 12952c4f56c9SRichard Henderson 12962c4f56c9SRichard Henderson cmp->cond = tcond; 1297816f89b7SRichard Henderson cmp->c1 = tcg_temp_new(); 1298c8507ebfSRichard Henderson cmp->c2 = 0; 1299816f89b7SRichard Henderson tcg_gen_mov_tl(cmp->c1, r_src); 13002c4f56c9SRichard Henderson return true; 1301fcf5ef2aSThomas Huth } 1302fcf5ef2aSThomas Huth 1303baf3dbf2SRichard Henderson static void gen_op_clear_ieee_excp_and_FTT(void) 1304baf3dbf2SRichard Henderson { 13053590f01eSRichard Henderson tcg_gen_st_i32(tcg_constant_i32(0), tcg_env, 13063590f01eSRichard Henderson offsetof(CPUSPARCState, fsr_cexc_ftt)); 1307baf3dbf2SRichard Henderson } 1308baf3dbf2SRichard Henderson 1309baf3dbf2SRichard Henderson static void gen_op_fmovs(TCGv_i32 dst, TCGv_i32 src) 1310baf3dbf2SRichard Henderson { 1311baf3dbf2SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 1312baf3dbf2SRichard Henderson tcg_gen_mov_i32(dst, src); 1313baf3dbf2SRichard Henderson } 1314baf3dbf2SRichard Henderson 1315baf3dbf2SRichard Henderson static void gen_op_fnegs(TCGv_i32 dst, TCGv_i32 src) 1316baf3dbf2SRichard Henderson { 1317baf3dbf2SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 1318daf457d4SRichard Henderson tcg_gen_xori_i32(dst, src, 1u << 31); 1319baf3dbf2SRichard Henderson } 1320baf3dbf2SRichard Henderson 1321baf3dbf2SRichard Henderson static void gen_op_fabss(TCGv_i32 dst, TCGv_i32 src) 1322baf3dbf2SRichard Henderson { 1323baf3dbf2SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 1324daf457d4SRichard Henderson tcg_gen_andi_i32(dst, src, ~(1u << 31)); 1325baf3dbf2SRichard Henderson } 1326baf3dbf2SRichard Henderson 1327c6d83e4fSRichard Henderson static void gen_op_fmovd(TCGv_i64 dst, TCGv_i64 src) 1328c6d83e4fSRichard Henderson { 1329c6d83e4fSRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 1330c6d83e4fSRichard Henderson tcg_gen_mov_i64(dst, src); 1331c6d83e4fSRichard Henderson } 1332c6d83e4fSRichard Henderson 1333c6d83e4fSRichard Henderson static void gen_op_fnegd(TCGv_i64 dst, TCGv_i64 src) 1334c6d83e4fSRichard Henderson { 1335c6d83e4fSRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 1336daf457d4SRichard Henderson tcg_gen_xori_i64(dst, src, 1ull << 63); 1337c6d83e4fSRichard Henderson } 1338c6d83e4fSRichard Henderson 1339c6d83e4fSRichard Henderson static void gen_op_fabsd(TCGv_i64 dst, TCGv_i64 src) 1340c6d83e4fSRichard Henderson { 1341c6d83e4fSRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 1342daf457d4SRichard Henderson tcg_gen_andi_i64(dst, src, ~(1ull << 63)); 1343daf457d4SRichard Henderson } 1344daf457d4SRichard Henderson 1345daf457d4SRichard Henderson static void gen_op_fnegq(TCGv_i128 dst, TCGv_i128 src) 1346daf457d4SRichard Henderson { 1347daf457d4SRichard Henderson TCGv_i64 l = tcg_temp_new_i64(); 1348daf457d4SRichard Henderson TCGv_i64 h = tcg_temp_new_i64(); 1349daf457d4SRichard Henderson 1350daf457d4SRichard Henderson tcg_gen_extr_i128_i64(l, h, src); 1351daf457d4SRichard Henderson tcg_gen_xori_i64(h, h, 1ull << 63); 1352daf457d4SRichard Henderson tcg_gen_concat_i64_i128(dst, l, h); 1353daf457d4SRichard Henderson } 1354daf457d4SRichard Henderson 1355daf457d4SRichard Henderson static void gen_op_fabsq(TCGv_i128 dst, TCGv_i128 src) 1356daf457d4SRichard Henderson { 1357daf457d4SRichard Henderson TCGv_i64 l = tcg_temp_new_i64(); 1358daf457d4SRichard Henderson TCGv_i64 h = tcg_temp_new_i64(); 1359daf457d4SRichard Henderson 1360daf457d4SRichard Henderson tcg_gen_extr_i128_i64(l, h, src); 1361daf457d4SRichard Henderson tcg_gen_andi_i64(h, h, ~(1ull << 63)); 1362daf457d4SRichard Henderson tcg_gen_concat_i64_i128(dst, l, h); 1363c6d83e4fSRichard Henderson } 1364c6d83e4fSRichard Henderson 13654fd71d19SRichard Henderson static void gen_op_fmadds(TCGv_i32 d, TCGv_i32 s1, TCGv_i32 s2, TCGv_i32 s3) 13664fd71d19SRichard Henderson { 13674fd71d19SRichard Henderson gen_helper_fmadds(d, tcg_env, s1, s2, s3, tcg_constant_i32(0)); 13684fd71d19SRichard Henderson } 13694fd71d19SRichard Henderson 13704fd71d19SRichard Henderson static void gen_op_fmaddd(TCGv_i64 d, TCGv_i64 s1, TCGv_i64 s2, TCGv_i64 s3) 13714fd71d19SRichard Henderson { 13724fd71d19SRichard Henderson gen_helper_fmaddd(d, tcg_env, s1, s2, s3, tcg_constant_i32(0)); 13734fd71d19SRichard Henderson } 13744fd71d19SRichard Henderson 13754fd71d19SRichard Henderson static void gen_op_fmsubs(TCGv_i32 d, TCGv_i32 s1, TCGv_i32 s2, TCGv_i32 s3) 13764fd71d19SRichard Henderson { 13774fd71d19SRichard Henderson int op = float_muladd_negate_c; 13784fd71d19SRichard Henderson gen_helper_fmadds(d, tcg_env, s1, s2, s3, tcg_constant_i32(op)); 13794fd71d19SRichard Henderson } 13804fd71d19SRichard Henderson 13814fd71d19SRichard Henderson static void gen_op_fmsubd(TCGv_i64 d, TCGv_i64 s1, TCGv_i64 s2, TCGv_i64 s3) 13824fd71d19SRichard Henderson { 13834fd71d19SRichard Henderson int op = float_muladd_negate_c; 13844fd71d19SRichard Henderson gen_helper_fmaddd(d, tcg_env, s1, s2, s3, tcg_constant_i32(op)); 13854fd71d19SRichard Henderson } 13864fd71d19SRichard Henderson 13874fd71d19SRichard Henderson static void gen_op_fnmsubs(TCGv_i32 d, TCGv_i32 s1, TCGv_i32 s2, TCGv_i32 s3) 13884fd71d19SRichard Henderson { 13894fd71d19SRichard Henderson int op = float_muladd_negate_c | float_muladd_negate_result; 13904fd71d19SRichard Henderson gen_helper_fmadds(d, tcg_env, s1, s2, s3, tcg_constant_i32(op)); 13914fd71d19SRichard Henderson } 13924fd71d19SRichard Henderson 13934fd71d19SRichard Henderson static void gen_op_fnmsubd(TCGv_i64 d, TCGv_i64 s1, TCGv_i64 s2, TCGv_i64 s3) 13944fd71d19SRichard Henderson { 13954fd71d19SRichard Henderson int op = float_muladd_negate_c | float_muladd_negate_result; 13964fd71d19SRichard Henderson gen_helper_fmaddd(d, tcg_env, s1, s2, s3, tcg_constant_i32(op)); 13974fd71d19SRichard Henderson } 13984fd71d19SRichard Henderson 13994fd71d19SRichard Henderson static void gen_op_fnmadds(TCGv_i32 d, TCGv_i32 s1, TCGv_i32 s2, TCGv_i32 s3) 14004fd71d19SRichard Henderson { 14014fd71d19SRichard Henderson int op = float_muladd_negate_result; 14024fd71d19SRichard Henderson gen_helper_fmadds(d, tcg_env, s1, s2, s3, tcg_constant_i32(op)); 14034fd71d19SRichard Henderson } 14044fd71d19SRichard Henderson 14054fd71d19SRichard Henderson static void gen_op_fnmaddd(TCGv_i64 d, TCGv_i64 s1, TCGv_i64 s2, TCGv_i64 s3) 14064fd71d19SRichard Henderson { 14074fd71d19SRichard Henderson int op = float_muladd_negate_result; 14084fd71d19SRichard Henderson gen_helper_fmaddd(d, tcg_env, s1, s2, s3, tcg_constant_i32(op)); 14094fd71d19SRichard Henderson } 14104fd71d19SRichard Henderson 14113d50b728SRichard Henderson /* Use muladd to compute (1 * src1) + src2 / 2 with one rounding. */ 14123d50b728SRichard Henderson static void gen_op_fhadds(TCGv_i32 d, TCGv_i32 s1, TCGv_i32 s2) 14133d50b728SRichard Henderson { 14143d50b728SRichard Henderson TCGv_i32 one = tcg_constant_i32(float32_one); 14153d50b728SRichard Henderson int op = float_muladd_halve_result; 14163d50b728SRichard Henderson gen_helper_fmadds(d, tcg_env, one, s1, s2, tcg_constant_i32(op)); 14173d50b728SRichard Henderson } 14183d50b728SRichard Henderson 14193d50b728SRichard Henderson static void gen_op_fhaddd(TCGv_i64 d, TCGv_i64 s1, TCGv_i64 s2) 14203d50b728SRichard Henderson { 14213d50b728SRichard Henderson TCGv_i64 one = tcg_constant_i64(float64_one); 14223d50b728SRichard Henderson int op = float_muladd_halve_result; 14233d50b728SRichard Henderson gen_helper_fmaddd(d, tcg_env, one, s1, s2, tcg_constant_i32(op)); 14243d50b728SRichard Henderson } 14253d50b728SRichard Henderson 14263d50b728SRichard Henderson /* Use muladd to compute (1 * src1) - src2 / 2 with one rounding. */ 14273d50b728SRichard Henderson static void gen_op_fhsubs(TCGv_i32 d, TCGv_i32 s1, TCGv_i32 s2) 14283d50b728SRichard Henderson { 14293d50b728SRichard Henderson TCGv_i32 one = tcg_constant_i32(float32_one); 14303d50b728SRichard Henderson int op = float_muladd_negate_c | float_muladd_halve_result; 14313d50b728SRichard Henderson gen_helper_fmadds(d, tcg_env, one, s1, s2, tcg_constant_i32(op)); 14323d50b728SRichard Henderson } 14333d50b728SRichard Henderson 14343d50b728SRichard Henderson static void gen_op_fhsubd(TCGv_i64 d, TCGv_i64 s1, TCGv_i64 s2) 14353d50b728SRichard Henderson { 14363d50b728SRichard Henderson TCGv_i64 one = tcg_constant_i64(float64_one); 14373d50b728SRichard Henderson int op = float_muladd_negate_c | float_muladd_halve_result; 14383d50b728SRichard Henderson gen_helper_fmaddd(d, tcg_env, one, s1, s2, tcg_constant_i32(op)); 14393d50b728SRichard Henderson } 14403d50b728SRichard Henderson 14413d50b728SRichard Henderson /* Use muladd to compute -((1 * src1) + src2 / 2) with one rounding. */ 14423d50b728SRichard Henderson static void gen_op_fnhadds(TCGv_i32 d, TCGv_i32 s1, TCGv_i32 s2) 14433d50b728SRichard Henderson { 14443d50b728SRichard Henderson TCGv_i32 one = tcg_constant_i32(float32_one); 14453d50b728SRichard Henderson int op = float_muladd_negate_result | float_muladd_halve_result; 14463d50b728SRichard Henderson gen_helper_fmadds(d, tcg_env, one, s1, s2, tcg_constant_i32(op)); 14473d50b728SRichard Henderson } 14483d50b728SRichard Henderson 14493d50b728SRichard Henderson static void gen_op_fnhaddd(TCGv_i64 d, TCGv_i64 s1, TCGv_i64 s2) 14503d50b728SRichard Henderson { 14513d50b728SRichard Henderson TCGv_i64 one = tcg_constant_i64(float64_one); 14523d50b728SRichard Henderson int op = float_muladd_negate_result | float_muladd_halve_result; 14533d50b728SRichard Henderson gen_helper_fmaddd(d, tcg_env, one, s1, s2, tcg_constant_i32(op)); 14543d50b728SRichard Henderson } 14553d50b728SRichard Henderson 14563590f01eSRichard Henderson static void gen_op_fpexception_im(DisasContext *dc, int ftt) 1457fcf5ef2aSThomas Huth { 14583590f01eSRichard Henderson /* 14593590f01eSRichard Henderson * CEXC is only set when succesfully completing an FPop, 14603590f01eSRichard Henderson * or when raising FSR_FTT_IEEE_EXCP, i.e. check_ieee_exception. 14613590f01eSRichard Henderson * Thus we can simply store FTT into this field. 14623590f01eSRichard Henderson */ 14633590f01eSRichard Henderson tcg_gen_st_i32(tcg_constant_i32(ftt), tcg_env, 14643590f01eSRichard Henderson offsetof(CPUSPARCState, fsr_cexc_ftt)); 1465fcf5ef2aSThomas Huth gen_exception(dc, TT_FP_EXCP); 1466fcf5ef2aSThomas Huth } 1467fcf5ef2aSThomas Huth 1468fcf5ef2aSThomas Huth static int gen_trap_ifnofpu(DisasContext *dc) 1469fcf5ef2aSThomas Huth { 1470fcf5ef2aSThomas Huth #if !defined(CONFIG_USER_ONLY) 1471fcf5ef2aSThomas Huth if (!dc->fpu_enabled) { 1472fcf5ef2aSThomas Huth gen_exception(dc, TT_NFPU_INSN); 1473fcf5ef2aSThomas Huth return 1; 1474fcf5ef2aSThomas Huth } 1475fcf5ef2aSThomas Huth #endif 1476fcf5ef2aSThomas Huth return 0; 1477fcf5ef2aSThomas Huth } 1478fcf5ef2aSThomas Huth 1479fcf5ef2aSThomas Huth /* asi moves */ 1480fcf5ef2aSThomas Huth typedef enum { 1481fcf5ef2aSThomas Huth GET_ASI_HELPER, 1482fcf5ef2aSThomas Huth GET_ASI_EXCP, 1483fcf5ef2aSThomas Huth GET_ASI_DIRECT, 1484fcf5ef2aSThomas Huth GET_ASI_DTWINX, 14852786a3f8SRichard Henderson GET_ASI_CODE, 1486fcf5ef2aSThomas Huth GET_ASI_BLOCK, 1487fcf5ef2aSThomas Huth GET_ASI_SHORT, 1488fcf5ef2aSThomas Huth GET_ASI_BCOPY, 1489fcf5ef2aSThomas Huth GET_ASI_BFILL, 1490fcf5ef2aSThomas Huth } ASIType; 1491fcf5ef2aSThomas Huth 1492fcf5ef2aSThomas Huth typedef struct { 1493fcf5ef2aSThomas Huth ASIType type; 1494fcf5ef2aSThomas Huth int asi; 1495fcf5ef2aSThomas Huth int mem_idx; 149614776ab5STony Nguyen MemOp memop; 1497fcf5ef2aSThomas Huth } DisasASI; 1498fcf5ef2aSThomas Huth 1499811cc0b0SRichard Henderson /* 1500811cc0b0SRichard Henderson * Build DisasASI. 1501811cc0b0SRichard Henderson * For asi == -1, treat as non-asi. 1502811cc0b0SRichard Henderson * For ask == -2, treat as immediate offset (v8 error, v9 %asi). 1503811cc0b0SRichard Henderson */ 1504811cc0b0SRichard Henderson static DisasASI resolve_asi(DisasContext *dc, int asi, MemOp memop) 1505fcf5ef2aSThomas Huth { 1506fcf5ef2aSThomas Huth ASIType type = GET_ASI_HELPER; 1507fcf5ef2aSThomas Huth int mem_idx = dc->mem_idx; 1508fcf5ef2aSThomas Huth 1509811cc0b0SRichard Henderson if (asi == -1) { 1510811cc0b0SRichard Henderson /* Artificial "non-asi" case. */ 1511811cc0b0SRichard Henderson type = GET_ASI_DIRECT; 1512811cc0b0SRichard Henderson goto done; 1513811cc0b0SRichard Henderson } 1514811cc0b0SRichard Henderson 1515fcf5ef2aSThomas Huth #ifndef TARGET_SPARC64 1516fcf5ef2aSThomas Huth /* Before v9, all asis are immediate and privileged. */ 1517811cc0b0SRichard Henderson if (asi < 0) { 1518fcf5ef2aSThomas Huth gen_exception(dc, TT_ILL_INSN); 1519fcf5ef2aSThomas Huth type = GET_ASI_EXCP; 1520fcf5ef2aSThomas Huth } else if (supervisor(dc) 1521fcf5ef2aSThomas Huth /* Note that LEON accepts ASI_USERDATA in user mode, for 1522fcf5ef2aSThomas Huth use with CASA. Also note that previous versions of 1523fcf5ef2aSThomas Huth QEMU allowed (and old versions of gcc emitted) ASI_P 1524fcf5ef2aSThomas Huth for LEON, which is incorrect. */ 1525fcf5ef2aSThomas Huth || (asi == ASI_USERDATA 1526fcf5ef2aSThomas Huth && (dc->def->features & CPU_FEATURE_CASA))) { 1527fcf5ef2aSThomas Huth switch (asi) { 1528fcf5ef2aSThomas Huth case ASI_USERDATA: /* User data access */ 1529fcf5ef2aSThomas Huth mem_idx = MMU_USER_IDX; 1530fcf5ef2aSThomas Huth type = GET_ASI_DIRECT; 1531fcf5ef2aSThomas Huth break; 1532fcf5ef2aSThomas Huth case ASI_KERNELDATA: /* Supervisor data access */ 1533fcf5ef2aSThomas Huth mem_idx = MMU_KERNEL_IDX; 1534fcf5ef2aSThomas Huth type = GET_ASI_DIRECT; 1535fcf5ef2aSThomas Huth break; 15362786a3f8SRichard Henderson case ASI_USERTXT: /* User text access */ 15372786a3f8SRichard Henderson mem_idx = MMU_USER_IDX; 15382786a3f8SRichard Henderson type = GET_ASI_CODE; 15392786a3f8SRichard Henderson break; 15402786a3f8SRichard Henderson case ASI_KERNELTXT: /* Supervisor text access */ 15412786a3f8SRichard Henderson mem_idx = MMU_KERNEL_IDX; 15422786a3f8SRichard Henderson type = GET_ASI_CODE; 15432786a3f8SRichard Henderson break; 1544fcf5ef2aSThomas Huth case ASI_M_BYPASS: /* MMU passthrough */ 1545fcf5ef2aSThomas Huth case ASI_LEON_BYPASS: /* LEON MMU passthrough */ 1546fcf5ef2aSThomas Huth mem_idx = MMU_PHYS_IDX; 1547fcf5ef2aSThomas Huth type = GET_ASI_DIRECT; 1548fcf5ef2aSThomas Huth break; 1549fcf5ef2aSThomas Huth case ASI_M_BCOPY: /* Block copy, sta access */ 1550fcf5ef2aSThomas Huth mem_idx = MMU_KERNEL_IDX; 1551fcf5ef2aSThomas Huth type = GET_ASI_BCOPY; 1552fcf5ef2aSThomas Huth break; 1553fcf5ef2aSThomas Huth case ASI_M_BFILL: /* Block fill, stda access */ 1554fcf5ef2aSThomas Huth mem_idx = MMU_KERNEL_IDX; 1555fcf5ef2aSThomas Huth type = GET_ASI_BFILL; 1556fcf5ef2aSThomas Huth break; 1557fcf5ef2aSThomas Huth } 15586e10f37cSKONRAD Frederic 15596e10f37cSKONRAD Frederic /* MMU_PHYS_IDX is used when the MMU is disabled to passthrough the 15606e10f37cSKONRAD Frederic * permissions check in get_physical_address(..). 15616e10f37cSKONRAD Frederic */ 15626e10f37cSKONRAD Frederic mem_idx = (dc->mem_idx == MMU_PHYS_IDX) ? MMU_PHYS_IDX : mem_idx; 1563fcf5ef2aSThomas Huth } else { 1564fcf5ef2aSThomas Huth gen_exception(dc, TT_PRIV_INSN); 1565fcf5ef2aSThomas Huth type = GET_ASI_EXCP; 1566fcf5ef2aSThomas Huth } 1567fcf5ef2aSThomas Huth #else 1568811cc0b0SRichard Henderson if (asi < 0) { 1569fcf5ef2aSThomas Huth asi = dc->asi; 1570fcf5ef2aSThomas Huth } 1571fcf5ef2aSThomas Huth /* With v9, all asis below 0x80 are privileged. */ 1572fcf5ef2aSThomas Huth /* ??? We ought to check cpu_has_hypervisor, but we didn't copy 1573fcf5ef2aSThomas Huth down that bit into DisasContext. For the moment that's ok, 1574fcf5ef2aSThomas Huth since the direct implementations below doesn't have any ASIs 1575fcf5ef2aSThomas Huth in the restricted [0x30, 0x7f] range, and the check will be 1576fcf5ef2aSThomas Huth done properly in the helper. */ 1577fcf5ef2aSThomas Huth if (!supervisor(dc) && asi < 0x80) { 1578fcf5ef2aSThomas Huth gen_exception(dc, TT_PRIV_ACT); 1579fcf5ef2aSThomas Huth type = GET_ASI_EXCP; 1580fcf5ef2aSThomas Huth } else { 1581fcf5ef2aSThomas Huth switch (asi) { 1582fcf5ef2aSThomas Huth case ASI_REAL: /* Bypass */ 1583fcf5ef2aSThomas Huth case ASI_REAL_IO: /* Bypass, non-cacheable */ 1584fcf5ef2aSThomas Huth case ASI_REAL_L: /* Bypass LE */ 1585fcf5ef2aSThomas Huth case ASI_REAL_IO_L: /* Bypass, non-cacheable LE */ 1586fcf5ef2aSThomas Huth case ASI_TWINX_REAL: /* Real address, twinx */ 1587fcf5ef2aSThomas Huth case ASI_TWINX_REAL_L: /* Real address, twinx, LE */ 1588fcf5ef2aSThomas Huth case ASI_QUAD_LDD_PHYS: 1589fcf5ef2aSThomas Huth case ASI_QUAD_LDD_PHYS_L: 1590fcf5ef2aSThomas Huth mem_idx = MMU_PHYS_IDX; 1591fcf5ef2aSThomas Huth break; 1592fcf5ef2aSThomas Huth case ASI_N: /* Nucleus */ 1593fcf5ef2aSThomas Huth case ASI_NL: /* Nucleus LE */ 1594fcf5ef2aSThomas Huth case ASI_TWINX_N: 1595fcf5ef2aSThomas Huth case ASI_TWINX_NL: 1596fcf5ef2aSThomas Huth case ASI_NUCLEUS_QUAD_LDD: 1597fcf5ef2aSThomas Huth case ASI_NUCLEUS_QUAD_LDD_L: 15989a10756dSArtyom Tarasenko if (hypervisor(dc)) { 159984f8f587SArtyom Tarasenko mem_idx = MMU_PHYS_IDX; 16009a10756dSArtyom Tarasenko } else { 1601fcf5ef2aSThomas Huth mem_idx = MMU_NUCLEUS_IDX; 16029a10756dSArtyom Tarasenko } 1603fcf5ef2aSThomas Huth break; 1604fcf5ef2aSThomas Huth case ASI_AIUP: /* As if user primary */ 1605fcf5ef2aSThomas Huth case ASI_AIUPL: /* As if user primary LE */ 1606fcf5ef2aSThomas Huth case ASI_TWINX_AIUP: 1607fcf5ef2aSThomas Huth case ASI_TWINX_AIUP_L: 1608fcf5ef2aSThomas Huth case ASI_BLK_AIUP_4V: 1609fcf5ef2aSThomas Huth case ASI_BLK_AIUP_L_4V: 1610fcf5ef2aSThomas Huth case ASI_BLK_AIUP: 1611fcf5ef2aSThomas Huth case ASI_BLK_AIUPL: 1612eeb3f592SRichard Henderson case ASI_MON_AIUP: 1613fcf5ef2aSThomas Huth mem_idx = MMU_USER_IDX; 1614fcf5ef2aSThomas Huth break; 1615fcf5ef2aSThomas Huth case ASI_AIUS: /* As if user secondary */ 1616fcf5ef2aSThomas Huth case ASI_AIUSL: /* As if user secondary LE */ 1617fcf5ef2aSThomas Huth case ASI_TWINX_AIUS: 1618fcf5ef2aSThomas Huth case ASI_TWINX_AIUS_L: 1619fcf5ef2aSThomas Huth case ASI_BLK_AIUS_4V: 1620fcf5ef2aSThomas Huth case ASI_BLK_AIUS_L_4V: 1621fcf5ef2aSThomas Huth case ASI_BLK_AIUS: 1622fcf5ef2aSThomas Huth case ASI_BLK_AIUSL: 1623eeb3f592SRichard Henderson case ASI_MON_AIUS: 1624fcf5ef2aSThomas Huth mem_idx = MMU_USER_SECONDARY_IDX; 1625fcf5ef2aSThomas Huth break; 1626fcf5ef2aSThomas Huth case ASI_S: /* Secondary */ 1627fcf5ef2aSThomas Huth case ASI_SL: /* Secondary LE */ 1628fcf5ef2aSThomas Huth case ASI_TWINX_S: 1629fcf5ef2aSThomas Huth case ASI_TWINX_SL: 1630fcf5ef2aSThomas Huth case ASI_BLK_COMMIT_S: 1631fcf5ef2aSThomas Huth case ASI_BLK_S: 1632fcf5ef2aSThomas Huth case ASI_BLK_SL: 1633fcf5ef2aSThomas Huth case ASI_FL8_S: 1634fcf5ef2aSThomas Huth case ASI_FL8_SL: 1635fcf5ef2aSThomas Huth case ASI_FL16_S: 1636fcf5ef2aSThomas Huth case ASI_FL16_SL: 1637eeb3f592SRichard Henderson case ASI_MON_S: 1638fcf5ef2aSThomas Huth if (mem_idx == MMU_USER_IDX) { 1639fcf5ef2aSThomas Huth mem_idx = MMU_USER_SECONDARY_IDX; 1640fcf5ef2aSThomas Huth } else if (mem_idx == MMU_KERNEL_IDX) { 1641fcf5ef2aSThomas Huth mem_idx = MMU_KERNEL_SECONDARY_IDX; 1642fcf5ef2aSThomas Huth } 1643fcf5ef2aSThomas Huth break; 1644fcf5ef2aSThomas Huth case ASI_P: /* Primary */ 1645fcf5ef2aSThomas Huth case ASI_PL: /* Primary LE */ 1646fcf5ef2aSThomas Huth case ASI_TWINX_P: 1647fcf5ef2aSThomas Huth case ASI_TWINX_PL: 1648fcf5ef2aSThomas Huth case ASI_BLK_COMMIT_P: 1649fcf5ef2aSThomas Huth case ASI_BLK_P: 1650fcf5ef2aSThomas Huth case ASI_BLK_PL: 1651fcf5ef2aSThomas Huth case ASI_FL8_P: 1652fcf5ef2aSThomas Huth case ASI_FL8_PL: 1653fcf5ef2aSThomas Huth case ASI_FL16_P: 1654fcf5ef2aSThomas Huth case ASI_FL16_PL: 1655eeb3f592SRichard Henderson case ASI_MON_P: 1656fcf5ef2aSThomas Huth break; 1657fcf5ef2aSThomas Huth } 1658fcf5ef2aSThomas Huth switch (asi) { 1659fcf5ef2aSThomas Huth case ASI_REAL: 1660fcf5ef2aSThomas Huth case ASI_REAL_IO: 1661fcf5ef2aSThomas Huth case ASI_REAL_L: 1662fcf5ef2aSThomas Huth case ASI_REAL_IO_L: 1663fcf5ef2aSThomas Huth case ASI_N: 1664fcf5ef2aSThomas Huth case ASI_NL: 1665fcf5ef2aSThomas Huth case ASI_AIUP: 1666fcf5ef2aSThomas Huth case ASI_AIUPL: 1667fcf5ef2aSThomas Huth case ASI_AIUS: 1668fcf5ef2aSThomas Huth case ASI_AIUSL: 1669fcf5ef2aSThomas Huth case ASI_S: 1670fcf5ef2aSThomas Huth case ASI_SL: 1671fcf5ef2aSThomas Huth case ASI_P: 1672fcf5ef2aSThomas Huth case ASI_PL: 1673eeb3f592SRichard Henderson case ASI_MON_P: 1674eeb3f592SRichard Henderson case ASI_MON_S: 1675eeb3f592SRichard Henderson case ASI_MON_AIUP: 1676eeb3f592SRichard Henderson case ASI_MON_AIUS: 1677fcf5ef2aSThomas Huth type = GET_ASI_DIRECT; 1678fcf5ef2aSThomas Huth break; 1679fcf5ef2aSThomas Huth case ASI_TWINX_REAL: 1680fcf5ef2aSThomas Huth case ASI_TWINX_REAL_L: 1681fcf5ef2aSThomas Huth case ASI_TWINX_N: 1682fcf5ef2aSThomas Huth case ASI_TWINX_NL: 1683fcf5ef2aSThomas Huth case ASI_TWINX_AIUP: 1684fcf5ef2aSThomas Huth case ASI_TWINX_AIUP_L: 1685fcf5ef2aSThomas Huth case ASI_TWINX_AIUS: 1686fcf5ef2aSThomas Huth case ASI_TWINX_AIUS_L: 1687fcf5ef2aSThomas Huth case ASI_TWINX_P: 1688fcf5ef2aSThomas Huth case ASI_TWINX_PL: 1689fcf5ef2aSThomas Huth case ASI_TWINX_S: 1690fcf5ef2aSThomas Huth case ASI_TWINX_SL: 1691fcf5ef2aSThomas Huth case ASI_QUAD_LDD_PHYS: 1692fcf5ef2aSThomas Huth case ASI_QUAD_LDD_PHYS_L: 1693fcf5ef2aSThomas Huth case ASI_NUCLEUS_QUAD_LDD: 1694fcf5ef2aSThomas Huth case ASI_NUCLEUS_QUAD_LDD_L: 1695fcf5ef2aSThomas Huth type = GET_ASI_DTWINX; 1696fcf5ef2aSThomas Huth break; 1697fcf5ef2aSThomas Huth case ASI_BLK_COMMIT_P: 1698fcf5ef2aSThomas Huth case ASI_BLK_COMMIT_S: 1699fcf5ef2aSThomas Huth case ASI_BLK_AIUP_4V: 1700fcf5ef2aSThomas Huth case ASI_BLK_AIUP_L_4V: 1701fcf5ef2aSThomas Huth case ASI_BLK_AIUP: 1702fcf5ef2aSThomas Huth case ASI_BLK_AIUPL: 1703fcf5ef2aSThomas Huth case ASI_BLK_AIUS_4V: 1704fcf5ef2aSThomas Huth case ASI_BLK_AIUS_L_4V: 1705fcf5ef2aSThomas Huth case ASI_BLK_AIUS: 1706fcf5ef2aSThomas Huth case ASI_BLK_AIUSL: 1707fcf5ef2aSThomas Huth case ASI_BLK_S: 1708fcf5ef2aSThomas Huth case ASI_BLK_SL: 1709fcf5ef2aSThomas Huth case ASI_BLK_P: 1710fcf5ef2aSThomas Huth case ASI_BLK_PL: 1711fcf5ef2aSThomas Huth type = GET_ASI_BLOCK; 1712fcf5ef2aSThomas Huth break; 1713fcf5ef2aSThomas Huth case ASI_FL8_S: 1714fcf5ef2aSThomas Huth case ASI_FL8_SL: 1715fcf5ef2aSThomas Huth case ASI_FL8_P: 1716fcf5ef2aSThomas Huth case ASI_FL8_PL: 1717fcf5ef2aSThomas Huth memop = MO_UB; 1718fcf5ef2aSThomas Huth type = GET_ASI_SHORT; 1719fcf5ef2aSThomas Huth break; 1720fcf5ef2aSThomas Huth case ASI_FL16_S: 1721fcf5ef2aSThomas Huth case ASI_FL16_SL: 1722fcf5ef2aSThomas Huth case ASI_FL16_P: 1723fcf5ef2aSThomas Huth case ASI_FL16_PL: 1724fcf5ef2aSThomas Huth memop = MO_TEUW; 1725fcf5ef2aSThomas Huth type = GET_ASI_SHORT; 1726fcf5ef2aSThomas Huth break; 1727fcf5ef2aSThomas Huth } 1728fcf5ef2aSThomas Huth /* The little-endian asis all have bit 3 set. */ 1729fcf5ef2aSThomas Huth if (asi & 8) { 1730fcf5ef2aSThomas Huth memop ^= MO_BSWAP; 1731fcf5ef2aSThomas Huth } 1732fcf5ef2aSThomas Huth } 1733fcf5ef2aSThomas Huth #endif 1734fcf5ef2aSThomas Huth 1735811cc0b0SRichard Henderson done: 1736fcf5ef2aSThomas Huth return (DisasASI){ type, asi, mem_idx, memop }; 1737fcf5ef2aSThomas Huth } 1738fcf5ef2aSThomas Huth 1739a76779eeSRichard Henderson #if defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64) 1740a76779eeSRichard Henderson static void gen_helper_ld_asi(TCGv_i64 r, TCGv_env e, TCGv a, 1741a76779eeSRichard Henderson TCGv_i32 asi, TCGv_i32 mop) 1742a76779eeSRichard Henderson { 1743a76779eeSRichard Henderson g_assert_not_reached(); 1744a76779eeSRichard Henderson } 1745a76779eeSRichard Henderson 1746a76779eeSRichard Henderson static void gen_helper_st_asi(TCGv_env e, TCGv a, TCGv_i64 r, 1747a76779eeSRichard Henderson TCGv_i32 asi, TCGv_i32 mop) 1748a76779eeSRichard Henderson { 1749a76779eeSRichard Henderson g_assert_not_reached(); 1750a76779eeSRichard Henderson } 1751a76779eeSRichard Henderson #endif 1752a76779eeSRichard Henderson 175342071fc1SRichard Henderson static void gen_ld_asi(DisasContext *dc, DisasASI *da, TCGv dst, TCGv addr) 1754fcf5ef2aSThomas Huth { 1755c03a0fd1SRichard Henderson switch (da->type) { 1756fcf5ef2aSThomas Huth case GET_ASI_EXCP: 1757fcf5ef2aSThomas Huth break; 1758fcf5ef2aSThomas Huth case GET_ASI_DTWINX: /* Reserved for ldda. */ 1759fcf5ef2aSThomas Huth gen_exception(dc, TT_ILL_INSN); 1760fcf5ef2aSThomas Huth break; 1761fcf5ef2aSThomas Huth case GET_ASI_DIRECT: 1762c03a0fd1SRichard Henderson tcg_gen_qemu_ld_tl(dst, addr, da->mem_idx, da->memop | MO_ALIGN); 1763fcf5ef2aSThomas Huth break; 17642786a3f8SRichard Henderson 17652786a3f8SRichard Henderson case GET_ASI_CODE: 17662786a3f8SRichard Henderson #if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64) 17672786a3f8SRichard Henderson { 17682786a3f8SRichard Henderson MemOpIdx oi = make_memop_idx(da->memop, da->mem_idx); 17692786a3f8SRichard Henderson TCGv_i64 t64 = tcg_temp_new_i64(); 17702786a3f8SRichard Henderson 17712786a3f8SRichard Henderson gen_helper_ld_code(t64, tcg_env, addr, tcg_constant_i32(oi)); 17722786a3f8SRichard Henderson tcg_gen_trunc_i64_tl(dst, t64); 17732786a3f8SRichard Henderson } 17742786a3f8SRichard Henderson break; 17752786a3f8SRichard Henderson #else 17762786a3f8SRichard Henderson g_assert_not_reached(); 17772786a3f8SRichard Henderson #endif 17782786a3f8SRichard Henderson 1779fcf5ef2aSThomas Huth default: 1780fcf5ef2aSThomas Huth { 1781c03a0fd1SRichard Henderson TCGv_i32 r_asi = tcg_constant_i32(da->asi); 1782c03a0fd1SRichard Henderson TCGv_i32 r_mop = tcg_constant_i32(da->memop | MO_ALIGN); 1783fcf5ef2aSThomas Huth 1784fcf5ef2aSThomas Huth save_state(dc); 1785fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64 1786ad75a51eSRichard Henderson gen_helper_ld_asi(dst, tcg_env, addr, r_asi, r_mop); 1787fcf5ef2aSThomas Huth #else 1788fcf5ef2aSThomas Huth { 1789fcf5ef2aSThomas Huth TCGv_i64 t64 = tcg_temp_new_i64(); 1790ad75a51eSRichard Henderson gen_helper_ld_asi(t64, tcg_env, addr, r_asi, r_mop); 1791fcf5ef2aSThomas Huth tcg_gen_trunc_i64_tl(dst, t64); 1792fcf5ef2aSThomas Huth } 1793fcf5ef2aSThomas Huth #endif 1794fcf5ef2aSThomas Huth } 1795fcf5ef2aSThomas Huth break; 1796fcf5ef2aSThomas Huth } 1797fcf5ef2aSThomas Huth } 1798fcf5ef2aSThomas Huth 179942071fc1SRichard Henderson static void gen_st_asi(DisasContext *dc, DisasASI *da, TCGv src, TCGv addr) 1800c03a0fd1SRichard Henderson { 1801c03a0fd1SRichard Henderson switch (da->type) { 1802fcf5ef2aSThomas Huth case GET_ASI_EXCP: 1803fcf5ef2aSThomas Huth break; 1804c03a0fd1SRichard Henderson 1805fcf5ef2aSThomas Huth case GET_ASI_DTWINX: /* Reserved for stda. */ 1806c03a0fd1SRichard Henderson if (TARGET_LONG_BITS == 32) { 1807fcf5ef2aSThomas Huth gen_exception(dc, TT_ILL_INSN); 1808fcf5ef2aSThomas Huth break; 1809c03a0fd1SRichard Henderson } else if (!(dc->def->features & CPU_FEATURE_HYPV)) { 18103390537bSArtyom Tarasenko /* Pre OpenSPARC CPUs don't have these */ 18113390537bSArtyom Tarasenko gen_exception(dc, TT_ILL_INSN); 1812fcf5ef2aSThomas Huth break; 1813c03a0fd1SRichard Henderson } 1814c03a0fd1SRichard Henderson /* In OpenSPARC T1+ CPUs TWINX ASIs in store are ST_BLKINIT_ ASIs */ 1815c03a0fd1SRichard Henderson /* fall through */ 1816c03a0fd1SRichard Henderson 1817c03a0fd1SRichard Henderson case GET_ASI_DIRECT: 1818c03a0fd1SRichard Henderson tcg_gen_qemu_st_tl(src, addr, da->mem_idx, da->memop | MO_ALIGN); 1819c03a0fd1SRichard Henderson break; 1820c03a0fd1SRichard Henderson 1821fcf5ef2aSThomas Huth case GET_ASI_BCOPY: 1822c03a0fd1SRichard Henderson assert(TARGET_LONG_BITS == 32); 182398271007SRichard Henderson /* 182498271007SRichard Henderson * Copy 32 bytes from the address in SRC to ADDR. 182598271007SRichard Henderson * 182698271007SRichard Henderson * From Ross RT625 hyperSPARC manual, section 4.6: 182798271007SRichard Henderson * "Block Copy and Block Fill will work only on cache line boundaries." 182898271007SRichard Henderson * 182998271007SRichard Henderson * It does not specify if an unaliged address is truncated or trapped. 183098271007SRichard Henderson * Previous qemu behaviour was to truncate to 4 byte alignment, which 183198271007SRichard Henderson * is obviously wrong. The only place I can see this used is in the 183298271007SRichard Henderson * Linux kernel which begins with page alignment, advancing by 32, 183398271007SRichard Henderson * so is always aligned. Assume truncation as the simpler option. 183498271007SRichard Henderson * 183598271007SRichard Henderson * Since the loads and stores are paired, allow the copy to happen 183698271007SRichard Henderson * in the host endianness. The copy need not be atomic. 183798271007SRichard Henderson */ 1838fcf5ef2aSThomas Huth { 183998271007SRichard Henderson MemOp mop = MO_128 | MO_ATOM_IFALIGN_PAIR; 1840fcf5ef2aSThomas Huth TCGv saddr = tcg_temp_new(); 1841fcf5ef2aSThomas Huth TCGv daddr = tcg_temp_new(); 184298271007SRichard Henderson TCGv_i128 tmp = tcg_temp_new_i128(); 1843fcf5ef2aSThomas Huth 184498271007SRichard Henderson tcg_gen_andi_tl(saddr, src, -32); 184598271007SRichard Henderson tcg_gen_andi_tl(daddr, addr, -32); 184698271007SRichard Henderson tcg_gen_qemu_ld_i128(tmp, saddr, da->mem_idx, mop); 184798271007SRichard Henderson tcg_gen_qemu_st_i128(tmp, daddr, da->mem_idx, mop); 184898271007SRichard Henderson tcg_gen_addi_tl(saddr, saddr, 16); 184998271007SRichard Henderson tcg_gen_addi_tl(daddr, daddr, 16); 185098271007SRichard Henderson tcg_gen_qemu_ld_i128(tmp, saddr, da->mem_idx, mop); 185198271007SRichard Henderson tcg_gen_qemu_st_i128(tmp, daddr, da->mem_idx, mop); 1852fcf5ef2aSThomas Huth } 1853fcf5ef2aSThomas Huth break; 1854c03a0fd1SRichard Henderson 1855fcf5ef2aSThomas Huth default: 1856fcf5ef2aSThomas Huth { 1857c03a0fd1SRichard Henderson TCGv_i32 r_asi = tcg_constant_i32(da->asi); 1858c03a0fd1SRichard Henderson TCGv_i32 r_mop = tcg_constant_i32(da->memop | MO_ALIGN); 1859fcf5ef2aSThomas Huth 1860fcf5ef2aSThomas Huth save_state(dc); 1861fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64 1862ad75a51eSRichard Henderson gen_helper_st_asi(tcg_env, addr, src, r_asi, r_mop); 1863fcf5ef2aSThomas Huth #else 1864fcf5ef2aSThomas Huth { 1865fcf5ef2aSThomas Huth TCGv_i64 t64 = tcg_temp_new_i64(); 1866fcf5ef2aSThomas Huth tcg_gen_extu_tl_i64(t64, src); 1867ad75a51eSRichard Henderson gen_helper_st_asi(tcg_env, addr, t64, r_asi, r_mop); 1868fcf5ef2aSThomas Huth } 1869fcf5ef2aSThomas Huth #endif 1870fcf5ef2aSThomas Huth 1871fcf5ef2aSThomas Huth /* A write to a TLB register may alter page maps. End the TB. */ 1872fcf5ef2aSThomas Huth dc->npc = DYNAMIC_PC; 1873fcf5ef2aSThomas Huth } 1874fcf5ef2aSThomas Huth break; 1875fcf5ef2aSThomas Huth } 1876fcf5ef2aSThomas Huth } 1877fcf5ef2aSThomas Huth 1878dca544b9SRichard Henderson static void gen_swap_asi(DisasContext *dc, DisasASI *da, 1879c03a0fd1SRichard Henderson TCGv dst, TCGv src, TCGv addr) 1880c03a0fd1SRichard Henderson { 1881c03a0fd1SRichard Henderson switch (da->type) { 1882c03a0fd1SRichard Henderson case GET_ASI_EXCP: 1883c03a0fd1SRichard Henderson break; 1884c03a0fd1SRichard Henderson case GET_ASI_DIRECT: 1885dca544b9SRichard Henderson tcg_gen_atomic_xchg_tl(dst, addr, src, 1886dca544b9SRichard Henderson da->mem_idx, da->memop | MO_ALIGN); 1887c03a0fd1SRichard Henderson break; 1888c03a0fd1SRichard Henderson default: 1889c03a0fd1SRichard Henderson /* ??? Should be DAE_invalid_asi. */ 1890c03a0fd1SRichard Henderson gen_exception(dc, TT_DATA_ACCESS); 1891c03a0fd1SRichard Henderson break; 1892c03a0fd1SRichard Henderson } 1893c03a0fd1SRichard Henderson } 1894c03a0fd1SRichard Henderson 1895d0a11d25SRichard Henderson static void gen_cas_asi(DisasContext *dc, DisasASI *da, 1896c03a0fd1SRichard Henderson TCGv oldv, TCGv newv, TCGv cmpv, TCGv addr) 1897c03a0fd1SRichard Henderson { 1898c03a0fd1SRichard Henderson switch (da->type) { 1899fcf5ef2aSThomas Huth case GET_ASI_EXCP: 1900c03a0fd1SRichard Henderson return; 1901fcf5ef2aSThomas Huth case GET_ASI_DIRECT: 1902c03a0fd1SRichard Henderson tcg_gen_atomic_cmpxchg_tl(oldv, addr, cmpv, newv, 1903c03a0fd1SRichard Henderson da->mem_idx, da->memop | MO_ALIGN); 1904fcf5ef2aSThomas Huth break; 1905fcf5ef2aSThomas Huth default: 1906fcf5ef2aSThomas Huth /* ??? Should be DAE_invalid_asi. */ 1907fcf5ef2aSThomas Huth gen_exception(dc, TT_DATA_ACCESS); 1908fcf5ef2aSThomas Huth break; 1909fcf5ef2aSThomas Huth } 1910fcf5ef2aSThomas Huth } 1911fcf5ef2aSThomas Huth 1912cf07cd1eSRichard Henderson static void gen_ldstub_asi(DisasContext *dc, DisasASI *da, TCGv dst, TCGv addr) 1913c03a0fd1SRichard Henderson { 1914c03a0fd1SRichard Henderson switch (da->type) { 1915fcf5ef2aSThomas Huth case GET_ASI_EXCP: 1916fcf5ef2aSThomas Huth break; 1917fcf5ef2aSThomas Huth case GET_ASI_DIRECT: 1918cf07cd1eSRichard Henderson tcg_gen_atomic_xchg_tl(dst, addr, tcg_constant_tl(0xff), 1919cf07cd1eSRichard Henderson da->mem_idx, MO_UB); 1920fcf5ef2aSThomas Huth break; 1921fcf5ef2aSThomas Huth default: 19223db010c3SRichard Henderson /* ??? In theory, this should be raise DAE_invalid_asi. 19233db010c3SRichard Henderson But the SS-20 roms do ldstuba [%l0] #ASI_M_CTL, %o1. */ 1924af00be49SEmilio G. Cota if (tb_cflags(dc->base.tb) & CF_PARALLEL) { 1925ad75a51eSRichard Henderson gen_helper_exit_atomic(tcg_env); 19263db010c3SRichard Henderson } else { 1927c03a0fd1SRichard Henderson TCGv_i32 r_asi = tcg_constant_i32(da->asi); 192800ab7e61SRichard Henderson TCGv_i32 r_mop = tcg_constant_i32(MO_UB); 19293db010c3SRichard Henderson TCGv_i64 s64, t64; 19303db010c3SRichard Henderson 19313db010c3SRichard Henderson save_state(dc); 19323db010c3SRichard Henderson t64 = tcg_temp_new_i64(); 1933ad75a51eSRichard Henderson gen_helper_ld_asi(t64, tcg_env, addr, r_asi, r_mop); 19343db010c3SRichard Henderson 193500ab7e61SRichard Henderson s64 = tcg_constant_i64(0xff); 1936ad75a51eSRichard Henderson gen_helper_st_asi(tcg_env, addr, s64, r_asi, r_mop); 19373db010c3SRichard Henderson 19383db010c3SRichard Henderson tcg_gen_trunc_i64_tl(dst, t64); 19393db010c3SRichard Henderson 19403db010c3SRichard Henderson /* End the TB. */ 19413db010c3SRichard Henderson dc->npc = DYNAMIC_PC; 19423db010c3SRichard Henderson } 1943fcf5ef2aSThomas Huth break; 1944fcf5ef2aSThomas Huth } 1945fcf5ef2aSThomas Huth } 1946fcf5ef2aSThomas Huth 1947287b1152SRichard Henderson static void gen_ldf_asi(DisasContext *dc, DisasASI *da, MemOp orig_size, 19483259b9e2SRichard Henderson TCGv addr, int rd) 1949fcf5ef2aSThomas Huth { 19503259b9e2SRichard Henderson MemOp memop = da->memop; 19513259b9e2SRichard Henderson MemOp size = memop & MO_SIZE; 1952fcf5ef2aSThomas Huth TCGv_i32 d32; 19531210a036SRichard Henderson TCGv_i64 d64, l64; 1954287b1152SRichard Henderson TCGv addr_tmp; 1955fcf5ef2aSThomas Huth 19563259b9e2SRichard Henderson /* TODO: Use 128-bit load/store below. */ 19573259b9e2SRichard Henderson if (size == MO_128) { 19583259b9e2SRichard Henderson memop = (memop & ~MO_SIZE) | MO_64; 19593259b9e2SRichard Henderson } 19603259b9e2SRichard Henderson 19613259b9e2SRichard Henderson switch (da->type) { 1962fcf5ef2aSThomas Huth case GET_ASI_EXCP: 1963fcf5ef2aSThomas Huth break; 1964fcf5ef2aSThomas Huth 1965fcf5ef2aSThomas Huth case GET_ASI_DIRECT: 19663259b9e2SRichard Henderson memop |= MO_ALIGN_4; 1967fcf5ef2aSThomas Huth switch (size) { 19683259b9e2SRichard Henderson case MO_32: 1969388a6465SRichard Henderson d32 = tcg_temp_new_i32(); 19703259b9e2SRichard Henderson tcg_gen_qemu_ld_i32(d32, addr, da->mem_idx, memop); 1971fcf5ef2aSThomas Huth gen_store_fpr_F(dc, rd, d32); 1972fcf5ef2aSThomas Huth break; 19733259b9e2SRichard Henderson 19743259b9e2SRichard Henderson case MO_64: 19751210a036SRichard Henderson d64 = tcg_temp_new_i64(); 19761210a036SRichard Henderson tcg_gen_qemu_ld_i64(d64, addr, da->mem_idx, memop); 19771210a036SRichard Henderson gen_store_fpr_D(dc, rd, d64); 1978fcf5ef2aSThomas Huth break; 19793259b9e2SRichard Henderson 19803259b9e2SRichard Henderson case MO_128: 1981fcf5ef2aSThomas Huth d64 = tcg_temp_new_i64(); 19821210a036SRichard Henderson l64 = tcg_temp_new_i64(); 19833259b9e2SRichard Henderson tcg_gen_qemu_ld_i64(d64, addr, da->mem_idx, memop); 1984287b1152SRichard Henderson addr_tmp = tcg_temp_new(); 1985287b1152SRichard Henderson tcg_gen_addi_tl(addr_tmp, addr, 8); 19861210a036SRichard Henderson tcg_gen_qemu_ld_i64(l64, addr_tmp, da->mem_idx, memop); 19871210a036SRichard Henderson gen_store_fpr_D(dc, rd, d64); 19881210a036SRichard Henderson gen_store_fpr_D(dc, rd + 2, l64); 1989fcf5ef2aSThomas Huth break; 1990fcf5ef2aSThomas Huth default: 1991fcf5ef2aSThomas Huth g_assert_not_reached(); 1992fcf5ef2aSThomas Huth } 1993fcf5ef2aSThomas Huth break; 1994fcf5ef2aSThomas Huth 1995fcf5ef2aSThomas Huth case GET_ASI_BLOCK: 1996fcf5ef2aSThomas Huth /* Valid for lddfa on aligned registers only. */ 19973259b9e2SRichard Henderson if (orig_size == MO_64 && (rd & 7) == 0) { 1998fcf5ef2aSThomas Huth /* The first operation checks required alignment. */ 1999287b1152SRichard Henderson addr_tmp = tcg_temp_new(); 20001210a036SRichard Henderson d64 = tcg_temp_new_i64(); 2001287b1152SRichard Henderson for (int i = 0; ; ++i) { 20021210a036SRichard Henderson tcg_gen_qemu_ld_i64(d64, addr, da->mem_idx, 20033259b9e2SRichard Henderson memop | (i == 0 ? MO_ALIGN_64 : 0)); 20041210a036SRichard Henderson gen_store_fpr_D(dc, rd + 2 * i, d64); 2005fcf5ef2aSThomas Huth if (i == 7) { 2006fcf5ef2aSThomas Huth break; 2007fcf5ef2aSThomas Huth } 2008287b1152SRichard Henderson tcg_gen_addi_tl(addr_tmp, addr, 8); 2009287b1152SRichard Henderson addr = addr_tmp; 2010fcf5ef2aSThomas Huth } 2011fcf5ef2aSThomas Huth } else { 2012fcf5ef2aSThomas Huth gen_exception(dc, TT_ILL_INSN); 2013fcf5ef2aSThomas Huth } 2014fcf5ef2aSThomas Huth break; 2015fcf5ef2aSThomas Huth 2016fcf5ef2aSThomas Huth case GET_ASI_SHORT: 2017fcf5ef2aSThomas Huth /* Valid for lddfa only. */ 20183259b9e2SRichard Henderson if (orig_size == MO_64) { 20191210a036SRichard Henderson d64 = tcg_temp_new_i64(); 20201210a036SRichard Henderson tcg_gen_qemu_ld_i64(d64, addr, da->mem_idx, memop | MO_ALIGN); 20211210a036SRichard Henderson gen_store_fpr_D(dc, rd, d64); 2022fcf5ef2aSThomas Huth } else { 2023fcf5ef2aSThomas Huth gen_exception(dc, TT_ILL_INSN); 2024fcf5ef2aSThomas Huth } 2025fcf5ef2aSThomas Huth break; 2026fcf5ef2aSThomas Huth 2027fcf5ef2aSThomas Huth default: 2028fcf5ef2aSThomas Huth { 20293259b9e2SRichard Henderson TCGv_i32 r_asi = tcg_constant_i32(da->asi); 20303259b9e2SRichard Henderson TCGv_i32 r_mop = tcg_constant_i32(memop | MO_ALIGN); 2031fcf5ef2aSThomas Huth 2032fcf5ef2aSThomas Huth save_state(dc); 2033fcf5ef2aSThomas Huth /* According to the table in the UA2011 manual, the only 2034fcf5ef2aSThomas Huth other asis that are valid for ldfa/lddfa/ldqfa are 2035fcf5ef2aSThomas Huth the NO_FAULT asis. We still need a helper for these, 2036fcf5ef2aSThomas Huth but we can just use the integer asi helper for them. */ 2037fcf5ef2aSThomas Huth switch (size) { 20383259b9e2SRichard Henderson case MO_32: 2039fcf5ef2aSThomas Huth d64 = tcg_temp_new_i64(); 2040ad75a51eSRichard Henderson gen_helper_ld_asi(d64, tcg_env, addr, r_asi, r_mop); 2041388a6465SRichard Henderson d32 = tcg_temp_new_i32(); 2042fcf5ef2aSThomas Huth tcg_gen_extrl_i64_i32(d32, d64); 2043fcf5ef2aSThomas Huth gen_store_fpr_F(dc, rd, d32); 2044fcf5ef2aSThomas Huth break; 20453259b9e2SRichard Henderson case MO_64: 20461210a036SRichard Henderson d64 = tcg_temp_new_i64(); 20471210a036SRichard Henderson gen_helper_ld_asi(d64, tcg_env, addr, r_asi, r_mop); 20481210a036SRichard Henderson gen_store_fpr_D(dc, rd, d64); 2049fcf5ef2aSThomas Huth break; 20503259b9e2SRichard Henderson case MO_128: 2051fcf5ef2aSThomas Huth d64 = tcg_temp_new_i64(); 20521210a036SRichard Henderson l64 = tcg_temp_new_i64(); 2053ad75a51eSRichard Henderson gen_helper_ld_asi(d64, tcg_env, addr, r_asi, r_mop); 2054287b1152SRichard Henderson addr_tmp = tcg_temp_new(); 2055287b1152SRichard Henderson tcg_gen_addi_tl(addr_tmp, addr, 8); 20561210a036SRichard Henderson gen_helper_ld_asi(l64, tcg_env, addr_tmp, r_asi, r_mop); 20571210a036SRichard Henderson gen_store_fpr_D(dc, rd, d64); 20581210a036SRichard Henderson gen_store_fpr_D(dc, rd + 2, l64); 2059fcf5ef2aSThomas Huth break; 2060fcf5ef2aSThomas Huth default: 2061fcf5ef2aSThomas Huth g_assert_not_reached(); 2062fcf5ef2aSThomas Huth } 2063fcf5ef2aSThomas Huth } 2064fcf5ef2aSThomas Huth break; 2065fcf5ef2aSThomas Huth } 2066fcf5ef2aSThomas Huth } 2067fcf5ef2aSThomas Huth 2068287b1152SRichard Henderson static void gen_stf_asi(DisasContext *dc, DisasASI *da, MemOp orig_size, 20693259b9e2SRichard Henderson TCGv addr, int rd) 20703259b9e2SRichard Henderson { 20713259b9e2SRichard Henderson MemOp memop = da->memop; 20723259b9e2SRichard Henderson MemOp size = memop & MO_SIZE; 2073fcf5ef2aSThomas Huth TCGv_i32 d32; 20741210a036SRichard Henderson TCGv_i64 d64; 2075287b1152SRichard Henderson TCGv addr_tmp; 2076fcf5ef2aSThomas Huth 20773259b9e2SRichard Henderson /* TODO: Use 128-bit load/store below. */ 20783259b9e2SRichard Henderson if (size == MO_128) { 20793259b9e2SRichard Henderson memop = (memop & ~MO_SIZE) | MO_64; 20803259b9e2SRichard Henderson } 20813259b9e2SRichard Henderson 20823259b9e2SRichard Henderson switch (da->type) { 2083fcf5ef2aSThomas Huth case GET_ASI_EXCP: 2084fcf5ef2aSThomas Huth break; 2085fcf5ef2aSThomas Huth 2086fcf5ef2aSThomas Huth case GET_ASI_DIRECT: 20873259b9e2SRichard Henderson memop |= MO_ALIGN_4; 2088fcf5ef2aSThomas Huth switch (size) { 20893259b9e2SRichard Henderson case MO_32: 2090fcf5ef2aSThomas Huth d32 = gen_load_fpr_F(dc, rd); 20913259b9e2SRichard Henderson tcg_gen_qemu_st_i32(d32, addr, da->mem_idx, memop | MO_ALIGN); 2092fcf5ef2aSThomas Huth break; 20933259b9e2SRichard Henderson case MO_64: 20941210a036SRichard Henderson d64 = gen_load_fpr_D(dc, rd); 20951210a036SRichard Henderson tcg_gen_qemu_st_i64(d64, addr, da->mem_idx, memop | MO_ALIGN_4); 2096fcf5ef2aSThomas Huth break; 20973259b9e2SRichard Henderson case MO_128: 2098fcf5ef2aSThomas Huth /* Only 4-byte alignment required. However, it is legal for the 2099fcf5ef2aSThomas Huth cpu to signal the alignment fault, and the OS trap handler is 2100fcf5ef2aSThomas Huth required to fix it up. Requiring 16-byte alignment here avoids 2101fcf5ef2aSThomas Huth having to probe the second page before performing the first 2102fcf5ef2aSThomas Huth write. */ 21031210a036SRichard Henderson d64 = gen_load_fpr_D(dc, rd); 21041210a036SRichard Henderson tcg_gen_qemu_st_i64(d64, addr, da->mem_idx, memop | MO_ALIGN_16); 2105287b1152SRichard Henderson addr_tmp = tcg_temp_new(); 2106287b1152SRichard Henderson tcg_gen_addi_tl(addr_tmp, addr, 8); 21071210a036SRichard Henderson d64 = gen_load_fpr_D(dc, rd + 2); 21081210a036SRichard Henderson tcg_gen_qemu_st_i64(d64, addr_tmp, da->mem_idx, memop); 2109fcf5ef2aSThomas Huth break; 2110fcf5ef2aSThomas Huth default: 2111fcf5ef2aSThomas Huth g_assert_not_reached(); 2112fcf5ef2aSThomas Huth } 2113fcf5ef2aSThomas Huth break; 2114fcf5ef2aSThomas Huth 2115fcf5ef2aSThomas Huth case GET_ASI_BLOCK: 2116fcf5ef2aSThomas Huth /* Valid for stdfa on aligned registers only. */ 21173259b9e2SRichard Henderson if (orig_size == MO_64 && (rd & 7) == 0) { 2118fcf5ef2aSThomas Huth /* The first operation checks required alignment. */ 2119287b1152SRichard Henderson addr_tmp = tcg_temp_new(); 2120287b1152SRichard Henderson for (int i = 0; ; ++i) { 21211210a036SRichard Henderson d64 = gen_load_fpr_D(dc, rd + 2 * i); 21221210a036SRichard Henderson tcg_gen_qemu_st_i64(d64, addr, da->mem_idx, 21233259b9e2SRichard Henderson memop | (i == 0 ? MO_ALIGN_64 : 0)); 2124fcf5ef2aSThomas Huth if (i == 7) { 2125fcf5ef2aSThomas Huth break; 2126fcf5ef2aSThomas Huth } 2127287b1152SRichard Henderson tcg_gen_addi_tl(addr_tmp, addr, 8); 2128287b1152SRichard Henderson addr = addr_tmp; 2129fcf5ef2aSThomas Huth } 2130fcf5ef2aSThomas Huth } else { 2131fcf5ef2aSThomas Huth gen_exception(dc, TT_ILL_INSN); 2132fcf5ef2aSThomas Huth } 2133fcf5ef2aSThomas Huth break; 2134fcf5ef2aSThomas Huth 2135fcf5ef2aSThomas Huth case GET_ASI_SHORT: 2136fcf5ef2aSThomas Huth /* Valid for stdfa only. */ 21373259b9e2SRichard Henderson if (orig_size == MO_64) { 21381210a036SRichard Henderson d64 = gen_load_fpr_D(dc, rd); 21391210a036SRichard Henderson tcg_gen_qemu_st_i64(d64, addr, da->mem_idx, memop | MO_ALIGN); 2140fcf5ef2aSThomas Huth } else { 2141fcf5ef2aSThomas Huth gen_exception(dc, TT_ILL_INSN); 2142fcf5ef2aSThomas Huth } 2143fcf5ef2aSThomas Huth break; 2144fcf5ef2aSThomas Huth 2145fcf5ef2aSThomas Huth default: 2146fcf5ef2aSThomas Huth /* According to the table in the UA2011 manual, the only 2147fcf5ef2aSThomas Huth other asis that are valid for ldfa/lddfa/ldqfa are 2148fcf5ef2aSThomas Huth the PST* asis, which aren't currently handled. */ 2149fcf5ef2aSThomas Huth gen_exception(dc, TT_ILL_INSN); 2150fcf5ef2aSThomas Huth break; 2151fcf5ef2aSThomas Huth } 2152fcf5ef2aSThomas Huth } 2153fcf5ef2aSThomas Huth 215442071fc1SRichard Henderson static void gen_ldda_asi(DisasContext *dc, DisasASI *da, TCGv addr, int rd) 2155fcf5ef2aSThomas Huth { 2156a76779eeSRichard Henderson TCGv hi = gen_dest_gpr(dc, rd); 2157a76779eeSRichard Henderson TCGv lo = gen_dest_gpr(dc, rd + 1); 2158fcf5ef2aSThomas Huth 2159c03a0fd1SRichard Henderson switch (da->type) { 2160fcf5ef2aSThomas Huth case GET_ASI_EXCP: 2161fcf5ef2aSThomas Huth return; 2162fcf5ef2aSThomas Huth 2163fcf5ef2aSThomas Huth case GET_ASI_DTWINX: 2164ebbbec92SRichard Henderson #ifdef TARGET_SPARC64 2165ebbbec92SRichard Henderson { 2166ebbbec92SRichard Henderson MemOp mop = (da->memop & MO_BSWAP) | MO_128 | MO_ALIGN_16; 2167ebbbec92SRichard Henderson TCGv_i128 t = tcg_temp_new_i128(); 2168ebbbec92SRichard Henderson 2169ebbbec92SRichard Henderson tcg_gen_qemu_ld_i128(t, addr, da->mem_idx, mop); 2170ebbbec92SRichard Henderson /* 2171ebbbec92SRichard Henderson * Note that LE twinx acts as if each 64-bit register result is 2172ebbbec92SRichard Henderson * byte swapped. We perform one 128-bit LE load, so must swap 2173ebbbec92SRichard Henderson * the order of the writebacks. 2174ebbbec92SRichard Henderson */ 2175ebbbec92SRichard Henderson if ((mop & MO_BSWAP) == MO_TE) { 2176ebbbec92SRichard Henderson tcg_gen_extr_i128_i64(lo, hi, t); 2177ebbbec92SRichard Henderson } else { 2178ebbbec92SRichard Henderson tcg_gen_extr_i128_i64(hi, lo, t); 2179ebbbec92SRichard Henderson } 2180ebbbec92SRichard Henderson } 2181fcf5ef2aSThomas Huth break; 2182ebbbec92SRichard Henderson #else 2183ebbbec92SRichard Henderson g_assert_not_reached(); 2184ebbbec92SRichard Henderson #endif 2185fcf5ef2aSThomas Huth 2186fcf5ef2aSThomas Huth case GET_ASI_DIRECT: 2187fcf5ef2aSThomas Huth { 2188fcf5ef2aSThomas Huth TCGv_i64 tmp = tcg_temp_new_i64(); 2189fcf5ef2aSThomas Huth 2190c03a0fd1SRichard Henderson tcg_gen_qemu_ld_i64(tmp, addr, da->mem_idx, da->memop | MO_ALIGN); 2191fcf5ef2aSThomas Huth 2192fcf5ef2aSThomas Huth /* Note that LE ldda acts as if each 32-bit register 2193fcf5ef2aSThomas Huth result is byte swapped. Having just performed one 2194fcf5ef2aSThomas Huth 64-bit bswap, we need now to swap the writebacks. */ 2195c03a0fd1SRichard Henderson if ((da->memop & MO_BSWAP) == MO_TE) { 2196a76779eeSRichard Henderson tcg_gen_extr_i64_tl(lo, hi, tmp); 2197fcf5ef2aSThomas Huth } else { 2198a76779eeSRichard Henderson tcg_gen_extr_i64_tl(hi, lo, tmp); 2199fcf5ef2aSThomas Huth } 2200fcf5ef2aSThomas Huth } 2201fcf5ef2aSThomas Huth break; 2202fcf5ef2aSThomas Huth 22032786a3f8SRichard Henderson case GET_ASI_CODE: 22042786a3f8SRichard Henderson #if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64) 22052786a3f8SRichard Henderson { 22062786a3f8SRichard Henderson MemOpIdx oi = make_memop_idx(da->memop, da->mem_idx); 22072786a3f8SRichard Henderson TCGv_i64 tmp = tcg_temp_new_i64(); 22082786a3f8SRichard Henderson 22092786a3f8SRichard Henderson gen_helper_ld_code(tmp, tcg_env, addr, tcg_constant_i32(oi)); 22102786a3f8SRichard Henderson 22112786a3f8SRichard Henderson /* See above. */ 22122786a3f8SRichard Henderson if ((da->memop & MO_BSWAP) == MO_TE) { 22132786a3f8SRichard Henderson tcg_gen_extr_i64_tl(lo, hi, tmp); 22142786a3f8SRichard Henderson } else { 22152786a3f8SRichard Henderson tcg_gen_extr_i64_tl(hi, lo, tmp); 22162786a3f8SRichard Henderson } 22172786a3f8SRichard Henderson } 22182786a3f8SRichard Henderson break; 22192786a3f8SRichard Henderson #else 22202786a3f8SRichard Henderson g_assert_not_reached(); 22212786a3f8SRichard Henderson #endif 22222786a3f8SRichard Henderson 2223fcf5ef2aSThomas Huth default: 2224fcf5ef2aSThomas Huth /* ??? In theory we've handled all of the ASIs that are valid 2225fcf5ef2aSThomas Huth for ldda, and this should raise DAE_invalid_asi. However, 2226fcf5ef2aSThomas Huth real hardware allows others. This can be seen with e.g. 2227fcf5ef2aSThomas Huth FreeBSD 10.3 wrt ASI_IC_TAG. */ 2228fcf5ef2aSThomas Huth { 2229c03a0fd1SRichard Henderson TCGv_i32 r_asi = tcg_constant_i32(da->asi); 2230c03a0fd1SRichard Henderson TCGv_i32 r_mop = tcg_constant_i32(da->memop); 2231fcf5ef2aSThomas Huth TCGv_i64 tmp = tcg_temp_new_i64(); 2232fcf5ef2aSThomas Huth 2233fcf5ef2aSThomas Huth save_state(dc); 2234ad75a51eSRichard Henderson gen_helper_ld_asi(tmp, tcg_env, addr, r_asi, r_mop); 2235fcf5ef2aSThomas Huth 2236fcf5ef2aSThomas Huth /* See above. */ 2237c03a0fd1SRichard Henderson if ((da->memop & MO_BSWAP) == MO_TE) { 2238a76779eeSRichard Henderson tcg_gen_extr_i64_tl(lo, hi, tmp); 2239fcf5ef2aSThomas Huth } else { 2240a76779eeSRichard Henderson tcg_gen_extr_i64_tl(hi, lo, tmp); 2241fcf5ef2aSThomas Huth } 2242fcf5ef2aSThomas Huth } 2243fcf5ef2aSThomas Huth break; 2244fcf5ef2aSThomas Huth } 2245fcf5ef2aSThomas Huth 2246fcf5ef2aSThomas Huth gen_store_gpr(dc, rd, hi); 2247fcf5ef2aSThomas Huth gen_store_gpr(dc, rd + 1, lo); 2248fcf5ef2aSThomas Huth } 2249fcf5ef2aSThomas Huth 225042071fc1SRichard Henderson static void gen_stda_asi(DisasContext *dc, DisasASI *da, TCGv addr, int rd) 2251c03a0fd1SRichard Henderson { 2252c03a0fd1SRichard Henderson TCGv hi = gen_load_gpr(dc, rd); 2253fcf5ef2aSThomas Huth TCGv lo = gen_load_gpr(dc, rd + 1); 2254fcf5ef2aSThomas Huth 2255c03a0fd1SRichard Henderson switch (da->type) { 2256fcf5ef2aSThomas Huth case GET_ASI_EXCP: 2257fcf5ef2aSThomas Huth break; 2258fcf5ef2aSThomas Huth 2259fcf5ef2aSThomas Huth case GET_ASI_DTWINX: 2260ebbbec92SRichard Henderson #ifdef TARGET_SPARC64 2261ebbbec92SRichard Henderson { 2262ebbbec92SRichard Henderson MemOp mop = (da->memop & MO_BSWAP) | MO_128 | MO_ALIGN_16; 2263ebbbec92SRichard Henderson TCGv_i128 t = tcg_temp_new_i128(); 2264ebbbec92SRichard Henderson 2265ebbbec92SRichard Henderson /* 2266ebbbec92SRichard Henderson * Note that LE twinx acts as if each 64-bit register result is 2267ebbbec92SRichard Henderson * byte swapped. We perform one 128-bit LE store, so must swap 2268ebbbec92SRichard Henderson * the order of the construction. 2269ebbbec92SRichard Henderson */ 2270ebbbec92SRichard Henderson if ((mop & MO_BSWAP) == MO_TE) { 2271ebbbec92SRichard Henderson tcg_gen_concat_i64_i128(t, lo, hi); 2272ebbbec92SRichard Henderson } else { 2273ebbbec92SRichard Henderson tcg_gen_concat_i64_i128(t, hi, lo); 2274ebbbec92SRichard Henderson } 2275ebbbec92SRichard Henderson tcg_gen_qemu_st_i128(t, addr, da->mem_idx, mop); 2276ebbbec92SRichard Henderson } 2277fcf5ef2aSThomas Huth break; 2278ebbbec92SRichard Henderson #else 2279ebbbec92SRichard Henderson g_assert_not_reached(); 2280ebbbec92SRichard Henderson #endif 2281fcf5ef2aSThomas Huth 2282fcf5ef2aSThomas Huth case GET_ASI_DIRECT: 2283fcf5ef2aSThomas Huth { 2284fcf5ef2aSThomas Huth TCGv_i64 t64 = tcg_temp_new_i64(); 2285fcf5ef2aSThomas Huth 2286fcf5ef2aSThomas Huth /* Note that LE stda acts as if each 32-bit register result is 2287fcf5ef2aSThomas Huth byte swapped. We will perform one 64-bit LE store, so now 2288fcf5ef2aSThomas Huth we must swap the order of the construction. */ 2289c03a0fd1SRichard Henderson if ((da->memop & MO_BSWAP) == MO_TE) { 2290a76779eeSRichard Henderson tcg_gen_concat_tl_i64(t64, lo, hi); 2291fcf5ef2aSThomas Huth } else { 2292a76779eeSRichard Henderson tcg_gen_concat_tl_i64(t64, hi, lo); 2293fcf5ef2aSThomas Huth } 2294c03a0fd1SRichard Henderson tcg_gen_qemu_st_i64(t64, addr, da->mem_idx, da->memop | MO_ALIGN); 2295fcf5ef2aSThomas Huth } 2296fcf5ef2aSThomas Huth break; 2297fcf5ef2aSThomas Huth 2298a76779eeSRichard Henderson case GET_ASI_BFILL: 2299a76779eeSRichard Henderson assert(TARGET_LONG_BITS == 32); 230054c3e953SRichard Henderson /* 230154c3e953SRichard Henderson * Store 32 bytes of [rd:rd+1] to ADDR. 230254c3e953SRichard Henderson * See comments for GET_ASI_COPY above. 230354c3e953SRichard Henderson */ 2304a76779eeSRichard Henderson { 230554c3e953SRichard Henderson MemOp mop = MO_TE | MO_128 | MO_ATOM_IFALIGN_PAIR; 230654c3e953SRichard Henderson TCGv_i64 t8 = tcg_temp_new_i64(); 230754c3e953SRichard Henderson TCGv_i128 t16 = tcg_temp_new_i128(); 230854c3e953SRichard Henderson TCGv daddr = tcg_temp_new(); 2309a76779eeSRichard Henderson 231054c3e953SRichard Henderson tcg_gen_concat_tl_i64(t8, lo, hi); 231154c3e953SRichard Henderson tcg_gen_concat_i64_i128(t16, t8, t8); 231254c3e953SRichard Henderson tcg_gen_andi_tl(daddr, addr, -32); 231354c3e953SRichard Henderson tcg_gen_qemu_st_i128(t16, daddr, da->mem_idx, mop); 231454c3e953SRichard Henderson tcg_gen_addi_tl(daddr, daddr, 16); 231554c3e953SRichard Henderson tcg_gen_qemu_st_i128(t16, daddr, da->mem_idx, mop); 2316a76779eeSRichard Henderson } 2317a76779eeSRichard Henderson break; 2318a76779eeSRichard Henderson 2319fcf5ef2aSThomas Huth default: 2320fcf5ef2aSThomas Huth /* ??? In theory we've handled all of the ASIs that are valid 2321fcf5ef2aSThomas Huth for stda, and this should raise DAE_invalid_asi. */ 2322fcf5ef2aSThomas Huth { 2323c03a0fd1SRichard Henderson TCGv_i32 r_asi = tcg_constant_i32(da->asi); 2324c03a0fd1SRichard Henderson TCGv_i32 r_mop = tcg_constant_i32(da->memop); 2325fcf5ef2aSThomas Huth TCGv_i64 t64 = tcg_temp_new_i64(); 2326fcf5ef2aSThomas Huth 2327fcf5ef2aSThomas Huth /* See above. */ 2328c03a0fd1SRichard Henderson if ((da->memop & MO_BSWAP) == MO_TE) { 2329a76779eeSRichard Henderson tcg_gen_concat_tl_i64(t64, lo, hi); 2330fcf5ef2aSThomas Huth } else { 2331a76779eeSRichard Henderson tcg_gen_concat_tl_i64(t64, hi, lo); 2332fcf5ef2aSThomas Huth } 2333fcf5ef2aSThomas Huth 2334fcf5ef2aSThomas Huth save_state(dc); 2335ad75a51eSRichard Henderson gen_helper_st_asi(tcg_env, addr, t64, r_asi, r_mop); 2336fcf5ef2aSThomas Huth } 2337fcf5ef2aSThomas Huth break; 2338fcf5ef2aSThomas Huth } 2339fcf5ef2aSThomas Huth } 2340fcf5ef2aSThomas Huth 2341fcf5ef2aSThomas Huth static void gen_fmovs(DisasContext *dc, DisasCompare *cmp, int rd, int rs) 2342fcf5ef2aSThomas Huth { 2343f7ec8155SRichard Henderson #ifdef TARGET_SPARC64 2344fcf5ef2aSThomas Huth TCGv_i32 c32, zero, dst, s1, s2; 2345dd7dbfccSRichard Henderson TCGv_i64 c64 = tcg_temp_new_i64(); 2346fcf5ef2aSThomas Huth 2347fcf5ef2aSThomas Huth /* We have two choices here: extend the 32 bit data and use movcond_i64, 2348fcf5ef2aSThomas Huth or fold the comparison down to 32 bits and use movcond_i32. Choose 2349fcf5ef2aSThomas Huth the later. */ 2350fcf5ef2aSThomas Huth c32 = tcg_temp_new_i32(); 2351c8507ebfSRichard Henderson tcg_gen_setcondi_i64(cmp->cond, c64, cmp->c1, cmp->c2); 2352fcf5ef2aSThomas Huth tcg_gen_extrl_i64_i32(c32, c64); 2353fcf5ef2aSThomas Huth 2354fcf5ef2aSThomas Huth s1 = gen_load_fpr_F(dc, rs); 2355fcf5ef2aSThomas Huth s2 = gen_load_fpr_F(dc, rd); 2356388a6465SRichard Henderson dst = tcg_temp_new_i32(); 235700ab7e61SRichard Henderson zero = tcg_constant_i32(0); 2358fcf5ef2aSThomas Huth 2359fcf5ef2aSThomas Huth tcg_gen_movcond_i32(TCG_COND_NE, dst, c32, zero, s1, s2); 2360fcf5ef2aSThomas Huth 2361fcf5ef2aSThomas Huth gen_store_fpr_F(dc, rd, dst); 2362f7ec8155SRichard Henderson #else 2363f7ec8155SRichard Henderson qemu_build_not_reached(); 2364f7ec8155SRichard Henderson #endif 2365fcf5ef2aSThomas Huth } 2366fcf5ef2aSThomas Huth 2367fcf5ef2aSThomas Huth static void gen_fmovd(DisasContext *dc, DisasCompare *cmp, int rd, int rs) 2368fcf5ef2aSThomas Huth { 2369f7ec8155SRichard Henderson #ifdef TARGET_SPARC64 237052f46d46SRichard Henderson TCGv_i64 dst = tcg_temp_new_i64(); 2371c8507ebfSRichard Henderson tcg_gen_movcond_i64(cmp->cond, dst, cmp->c1, tcg_constant_tl(cmp->c2), 2372fcf5ef2aSThomas Huth gen_load_fpr_D(dc, rs), 2373fcf5ef2aSThomas Huth gen_load_fpr_D(dc, rd)); 2374fcf5ef2aSThomas Huth gen_store_fpr_D(dc, rd, dst); 2375f7ec8155SRichard Henderson #else 2376f7ec8155SRichard Henderson qemu_build_not_reached(); 2377f7ec8155SRichard Henderson #endif 2378fcf5ef2aSThomas Huth } 2379fcf5ef2aSThomas Huth 2380fcf5ef2aSThomas Huth static void gen_fmovq(DisasContext *dc, DisasCompare *cmp, int rd, int rs) 2381fcf5ef2aSThomas Huth { 2382f7ec8155SRichard Henderson #ifdef TARGET_SPARC64 2383c8507ebfSRichard Henderson TCGv c2 = tcg_constant_tl(cmp->c2); 23841210a036SRichard Henderson TCGv_i64 h = tcg_temp_new_i64(); 23851210a036SRichard Henderson TCGv_i64 l = tcg_temp_new_i64(); 2386fcf5ef2aSThomas Huth 23871210a036SRichard Henderson tcg_gen_movcond_i64(cmp->cond, h, cmp->c1, c2, 23881210a036SRichard Henderson gen_load_fpr_D(dc, rs), 23891210a036SRichard Henderson gen_load_fpr_D(dc, rd)); 23901210a036SRichard Henderson tcg_gen_movcond_i64(cmp->cond, l, cmp->c1, c2, 23911210a036SRichard Henderson gen_load_fpr_D(dc, rs + 2), 23921210a036SRichard Henderson gen_load_fpr_D(dc, rd + 2)); 23931210a036SRichard Henderson gen_store_fpr_D(dc, rd, h); 23941210a036SRichard Henderson gen_store_fpr_D(dc, rd + 2, l); 2395f7ec8155SRichard Henderson #else 2396f7ec8155SRichard Henderson qemu_build_not_reached(); 2397f7ec8155SRichard Henderson #endif 2398fcf5ef2aSThomas Huth } 2399fcf5ef2aSThomas Huth 2400f7ec8155SRichard Henderson #ifdef TARGET_SPARC64 24015d617bfbSRichard Henderson static void gen_load_trap_state_at_tl(TCGv_ptr r_tsptr) 2402fcf5ef2aSThomas Huth { 2403fcf5ef2aSThomas Huth TCGv_i32 r_tl = tcg_temp_new_i32(); 2404fcf5ef2aSThomas Huth 2405fcf5ef2aSThomas Huth /* load env->tl into r_tl */ 2406ad75a51eSRichard Henderson tcg_gen_ld_i32(r_tl, tcg_env, offsetof(CPUSPARCState, tl)); 2407fcf5ef2aSThomas Huth 2408fcf5ef2aSThomas Huth /* tl = [0 ... MAXTL_MASK] where MAXTL_MASK must be power of 2 */ 2409fcf5ef2aSThomas Huth tcg_gen_andi_i32(r_tl, r_tl, MAXTL_MASK); 2410fcf5ef2aSThomas Huth 2411fcf5ef2aSThomas Huth /* calculate offset to current trap state from env->ts, reuse r_tl */ 2412fcf5ef2aSThomas Huth tcg_gen_muli_i32(r_tl, r_tl, sizeof (trap_state)); 2413ad75a51eSRichard Henderson tcg_gen_addi_ptr(r_tsptr, tcg_env, offsetof(CPUSPARCState, ts)); 2414fcf5ef2aSThomas Huth 2415fcf5ef2aSThomas Huth /* tsptr = env->ts[env->tl & MAXTL_MASK] */ 2416fcf5ef2aSThomas Huth { 2417fcf5ef2aSThomas Huth TCGv_ptr r_tl_tmp = tcg_temp_new_ptr(); 2418fcf5ef2aSThomas Huth tcg_gen_ext_i32_ptr(r_tl_tmp, r_tl); 2419fcf5ef2aSThomas Huth tcg_gen_add_ptr(r_tsptr, r_tsptr, r_tl_tmp); 2420fcf5ef2aSThomas Huth } 2421fcf5ef2aSThomas Huth } 2422fcf5ef2aSThomas Huth #endif 2423fcf5ef2aSThomas Huth 242406c060d9SRichard Henderson static int extract_dfpreg(DisasContext *dc, int x) 242506c060d9SRichard Henderson { 24260bba7572SRichard Henderson int r = x & 0x1e; 24270bba7572SRichard Henderson #ifdef TARGET_SPARC64 24280bba7572SRichard Henderson r |= (x & 1) << 5; 24290bba7572SRichard Henderson #endif 24300bba7572SRichard Henderson return r; 243106c060d9SRichard Henderson } 243206c060d9SRichard Henderson 243306c060d9SRichard Henderson static int extract_qfpreg(DisasContext *dc, int x) 243406c060d9SRichard Henderson { 24350bba7572SRichard Henderson int r = x & 0x1c; 24360bba7572SRichard Henderson #ifdef TARGET_SPARC64 24370bba7572SRichard Henderson r |= (x & 1) << 5; 24380bba7572SRichard Henderson #endif 24390bba7572SRichard Henderson return r; 244006c060d9SRichard Henderson } 244106c060d9SRichard Henderson 2442878cc677SRichard Henderson /* Include the auto-generated decoder. */ 2443878cc677SRichard Henderson #include "decode-insns.c.inc" 2444878cc677SRichard Henderson 2445878cc677SRichard Henderson #define TRANS(NAME, AVAIL, FUNC, ...) \ 2446878cc677SRichard Henderson static bool trans_##NAME(DisasContext *dc, arg_##NAME *a) \ 2447878cc677SRichard Henderson { return avail_##AVAIL(dc) && FUNC(dc, __VA_ARGS__); } 2448878cc677SRichard Henderson 2449878cc677SRichard Henderson #define avail_ALL(C) true 2450878cc677SRichard Henderson #ifdef TARGET_SPARC64 2451878cc677SRichard Henderson # define avail_32(C) false 2452af25071cSRichard Henderson # define avail_ASR17(C) false 2453d0a11d25SRichard Henderson # define avail_CASA(C) true 2454c2636853SRichard Henderson # define avail_DIV(C) true 2455b5372650SRichard Henderson # define avail_MUL(C) true 24560faef01bSRichard Henderson # define avail_POWERDOWN(C) false 2457878cc677SRichard Henderson # define avail_64(C) true 24584fd71d19SRichard Henderson # define avail_FMAF(C) ((C)->def->features & CPU_FEATURE_FMAF) 24595d617bfbSRichard Henderson # define avail_GL(C) ((C)->def->features & CPU_FEATURE_GL) 2460af25071cSRichard Henderson # define avail_HYPV(C) ((C)->def->features & CPU_FEATURE_HYPV) 246168a414e9SRichard Henderson # define avail_IMA(C) ((C)->def->features & CPU_FEATURE_IMA) 2462b88ce6f2SRichard Henderson # define avail_VIS1(C) ((C)->def->features & CPU_FEATURE_VIS1) 2463b88ce6f2SRichard Henderson # define avail_VIS2(C) ((C)->def->features & CPU_FEATURE_VIS2) 24643335a048SRichard Henderson # define avail_VIS3(C) ((C)->def->features & CPU_FEATURE_VIS3) 24653335a048SRichard Henderson # define avail_VIS3B(C) avail_VIS3(C) 246690b1433dSRichard Henderson # define avail_VIS4(C) ((C)->def->features & CPU_FEATURE_VIS4) 2467878cc677SRichard Henderson #else 2468878cc677SRichard Henderson # define avail_32(C) true 2469af25071cSRichard Henderson # define avail_ASR17(C) ((C)->def->features & CPU_FEATURE_ASR17) 2470d0a11d25SRichard Henderson # define avail_CASA(C) ((C)->def->features & CPU_FEATURE_CASA) 2471c2636853SRichard Henderson # define avail_DIV(C) ((C)->def->features & CPU_FEATURE_DIV) 2472b5372650SRichard Henderson # define avail_MUL(C) ((C)->def->features & CPU_FEATURE_MUL) 24730faef01bSRichard Henderson # define avail_POWERDOWN(C) ((C)->def->features & CPU_FEATURE_POWERDOWN) 2474878cc677SRichard Henderson # define avail_64(C) false 24754fd71d19SRichard Henderson # define avail_FMAF(C) false 24765d617bfbSRichard Henderson # define avail_GL(C) false 2477af25071cSRichard Henderson # define avail_HYPV(C) false 247868a414e9SRichard Henderson # define avail_IMA(C) false 2479b88ce6f2SRichard Henderson # define avail_VIS1(C) false 2480b88ce6f2SRichard Henderson # define avail_VIS2(C) false 24813335a048SRichard Henderson # define avail_VIS3(C) false 24823335a048SRichard Henderson # define avail_VIS3B(C) false 248390b1433dSRichard Henderson # define avail_VIS4(C) false 2484878cc677SRichard Henderson #endif 2485878cc677SRichard Henderson 2486878cc677SRichard Henderson /* Default case for non jump instructions. */ 2487878cc677SRichard Henderson static bool advance_pc(DisasContext *dc) 2488878cc677SRichard Henderson { 24894a8d145dSRichard Henderson TCGLabel *l1; 24904a8d145dSRichard Henderson 249189527e3aSRichard Henderson finishing_insn(dc); 249289527e3aSRichard Henderson 2493878cc677SRichard Henderson if (dc->npc & 3) { 2494878cc677SRichard Henderson switch (dc->npc) { 2495878cc677SRichard Henderson case DYNAMIC_PC: 2496878cc677SRichard Henderson case DYNAMIC_PC_LOOKUP: 2497878cc677SRichard Henderson dc->pc = dc->npc; 2498444d8b30SRichard Henderson tcg_gen_mov_tl(cpu_pc, cpu_npc); 2499444d8b30SRichard Henderson tcg_gen_addi_tl(cpu_npc, cpu_npc, 4); 2500878cc677SRichard Henderson break; 25014a8d145dSRichard Henderson 2502878cc677SRichard Henderson case JUMP_PC: 2503878cc677SRichard Henderson /* we can do a static jump */ 25044a8d145dSRichard Henderson l1 = gen_new_label(); 2505533f042fSRichard Henderson tcg_gen_brcondi_tl(dc->jump.cond, dc->jump.c1, dc->jump.c2, l1); 25064a8d145dSRichard Henderson 25074a8d145dSRichard Henderson /* jump not taken */ 25084a8d145dSRichard Henderson gen_goto_tb(dc, 1, dc->jump_pc[1], dc->jump_pc[1] + 4); 25094a8d145dSRichard Henderson 25104a8d145dSRichard Henderson /* jump taken */ 25114a8d145dSRichard Henderson gen_set_label(l1); 25124a8d145dSRichard Henderson gen_goto_tb(dc, 0, dc->jump_pc[0], dc->jump_pc[0] + 4); 25134a8d145dSRichard Henderson 2514878cc677SRichard Henderson dc->base.is_jmp = DISAS_NORETURN; 2515878cc677SRichard Henderson break; 25164a8d145dSRichard Henderson 2517878cc677SRichard Henderson default: 2518878cc677SRichard Henderson g_assert_not_reached(); 2519878cc677SRichard Henderson } 2520878cc677SRichard Henderson } else { 2521878cc677SRichard Henderson dc->pc = dc->npc; 2522878cc677SRichard Henderson dc->npc = dc->npc + 4; 2523878cc677SRichard Henderson } 2524878cc677SRichard Henderson return true; 2525878cc677SRichard Henderson } 2526878cc677SRichard Henderson 25276d2a0768SRichard Henderson /* 25286d2a0768SRichard Henderson * Major opcodes 00 and 01 -- branches, call, and sethi 25296d2a0768SRichard Henderson */ 25306d2a0768SRichard Henderson 25319d4e2bc7SRichard Henderson static bool advance_jump_cond(DisasContext *dc, DisasCompare *cmp, 25323951b7a8SRichard Henderson bool annul, int disp) 2533276567aaSRichard Henderson { 25343951b7a8SRichard Henderson target_ulong dest = address_mask_i(dc, dc->pc + disp * 4); 2535c76c8045SRichard Henderson target_ulong npc; 2536c76c8045SRichard Henderson 253789527e3aSRichard Henderson finishing_insn(dc); 253889527e3aSRichard Henderson 25392d9bb237SRichard Henderson if (cmp->cond == TCG_COND_ALWAYS) { 25402d9bb237SRichard Henderson if (annul) { 25412d9bb237SRichard Henderson dc->pc = dest; 25422d9bb237SRichard Henderson dc->npc = dest + 4; 25432d9bb237SRichard Henderson } else { 25442d9bb237SRichard Henderson gen_mov_pc_npc(dc); 25452d9bb237SRichard Henderson dc->npc = dest; 25462d9bb237SRichard Henderson } 25472d9bb237SRichard Henderson return true; 25482d9bb237SRichard Henderson } 25492d9bb237SRichard Henderson 25502d9bb237SRichard Henderson if (cmp->cond == TCG_COND_NEVER) { 25512d9bb237SRichard Henderson npc = dc->npc; 25522d9bb237SRichard Henderson if (npc & 3) { 25532d9bb237SRichard Henderson gen_mov_pc_npc(dc); 25542d9bb237SRichard Henderson if (annul) { 25552d9bb237SRichard Henderson tcg_gen_addi_tl(cpu_pc, cpu_pc, 4); 25562d9bb237SRichard Henderson } 25572d9bb237SRichard Henderson tcg_gen_addi_tl(cpu_npc, cpu_pc, 4); 25582d9bb237SRichard Henderson } else { 25592d9bb237SRichard Henderson dc->pc = npc + (annul ? 4 : 0); 25602d9bb237SRichard Henderson dc->npc = dc->pc + 4; 25612d9bb237SRichard Henderson } 25622d9bb237SRichard Henderson return true; 25632d9bb237SRichard Henderson } 25642d9bb237SRichard Henderson 2565c76c8045SRichard Henderson flush_cond(dc); 2566c76c8045SRichard Henderson npc = dc->npc; 25676b3e4cc6SRichard Henderson 2568276567aaSRichard Henderson if (annul) { 25696b3e4cc6SRichard Henderson TCGLabel *l1 = gen_new_label(); 25706b3e4cc6SRichard Henderson 2571c8507ebfSRichard Henderson tcg_gen_brcondi_tl(tcg_invert_cond(cmp->cond), cmp->c1, cmp->c2, l1); 25726b3e4cc6SRichard Henderson gen_goto_tb(dc, 0, npc, dest); 25736b3e4cc6SRichard Henderson gen_set_label(l1); 25746b3e4cc6SRichard Henderson gen_goto_tb(dc, 1, npc + 4, npc + 8); 25756b3e4cc6SRichard Henderson 25766b3e4cc6SRichard Henderson dc->base.is_jmp = DISAS_NORETURN; 2577276567aaSRichard Henderson } else { 25786b3e4cc6SRichard Henderson if (npc & 3) { 25796b3e4cc6SRichard Henderson switch (npc) { 25806b3e4cc6SRichard Henderson case DYNAMIC_PC: 25816b3e4cc6SRichard Henderson case DYNAMIC_PC_LOOKUP: 25826b3e4cc6SRichard Henderson tcg_gen_mov_tl(cpu_pc, cpu_npc); 25836b3e4cc6SRichard Henderson tcg_gen_addi_tl(cpu_npc, cpu_npc, 4); 25849d4e2bc7SRichard Henderson tcg_gen_movcond_tl(cmp->cond, cpu_npc, 2585c8507ebfSRichard Henderson cmp->c1, tcg_constant_tl(cmp->c2), 25866b3e4cc6SRichard Henderson tcg_constant_tl(dest), cpu_npc); 25876b3e4cc6SRichard Henderson dc->pc = npc; 25886b3e4cc6SRichard Henderson break; 25896b3e4cc6SRichard Henderson default: 25906b3e4cc6SRichard Henderson g_assert_not_reached(); 25916b3e4cc6SRichard Henderson } 25926b3e4cc6SRichard Henderson } else { 25936b3e4cc6SRichard Henderson dc->pc = npc; 2594533f042fSRichard Henderson dc->npc = JUMP_PC; 2595533f042fSRichard Henderson dc->jump = *cmp; 25966b3e4cc6SRichard Henderson dc->jump_pc[0] = dest; 25976b3e4cc6SRichard Henderson dc->jump_pc[1] = npc + 4; 2598dd7dbfccSRichard Henderson 2599dd7dbfccSRichard Henderson /* The condition for cpu_cond is always NE -- normalize. */ 2600dd7dbfccSRichard Henderson if (cmp->cond == TCG_COND_NE) { 2601c8507ebfSRichard Henderson tcg_gen_xori_tl(cpu_cond, cmp->c1, cmp->c2); 26029d4e2bc7SRichard Henderson } else { 2603c8507ebfSRichard Henderson tcg_gen_setcondi_tl(cmp->cond, cpu_cond, cmp->c1, cmp->c2); 26049d4e2bc7SRichard Henderson } 260589527e3aSRichard Henderson dc->cpu_cond_live = true; 26066b3e4cc6SRichard Henderson } 2607276567aaSRichard Henderson } 2608276567aaSRichard Henderson return true; 2609276567aaSRichard Henderson } 2610276567aaSRichard Henderson 2611af25071cSRichard Henderson static bool raise_priv(DisasContext *dc) 2612af25071cSRichard Henderson { 2613af25071cSRichard Henderson gen_exception(dc, TT_PRIV_INSN); 2614af25071cSRichard Henderson return true; 2615af25071cSRichard Henderson } 2616af25071cSRichard Henderson 261706c060d9SRichard Henderson static bool raise_unimpfpop(DisasContext *dc) 261806c060d9SRichard Henderson { 261906c060d9SRichard Henderson gen_op_fpexception_im(dc, FSR_FTT_UNIMPFPOP); 262006c060d9SRichard Henderson return true; 262106c060d9SRichard Henderson } 262206c060d9SRichard Henderson 262306c060d9SRichard Henderson static bool gen_trap_float128(DisasContext *dc) 262406c060d9SRichard Henderson { 262506c060d9SRichard Henderson if (dc->def->features & CPU_FEATURE_FLOAT128) { 262606c060d9SRichard Henderson return false; 262706c060d9SRichard Henderson } 262806c060d9SRichard Henderson return raise_unimpfpop(dc); 262906c060d9SRichard Henderson } 263006c060d9SRichard Henderson 2631276567aaSRichard Henderson static bool do_bpcc(DisasContext *dc, arg_bcc *a) 2632276567aaSRichard Henderson { 26331ea9c62aSRichard Henderson DisasCompare cmp; 2634276567aaSRichard Henderson 26351ea9c62aSRichard Henderson gen_compare(&cmp, a->cc, a->cond, dc); 26363951b7a8SRichard Henderson return advance_jump_cond(dc, &cmp, a->a, a->i); 2637276567aaSRichard Henderson } 2638276567aaSRichard Henderson 2639276567aaSRichard Henderson TRANS(Bicc, ALL, do_bpcc, a) 2640276567aaSRichard Henderson TRANS(BPcc, 64, do_bpcc, a) 2641276567aaSRichard Henderson 264245196ea4SRichard Henderson static bool do_fbpfcc(DisasContext *dc, arg_bcc *a) 264345196ea4SRichard Henderson { 2644d5471936SRichard Henderson DisasCompare cmp; 264545196ea4SRichard Henderson 264645196ea4SRichard Henderson if (gen_trap_ifnofpu(dc)) { 264745196ea4SRichard Henderson return true; 264845196ea4SRichard Henderson } 2649d5471936SRichard Henderson gen_fcompare(&cmp, a->cc, a->cond); 26503951b7a8SRichard Henderson return advance_jump_cond(dc, &cmp, a->a, a->i); 265145196ea4SRichard Henderson } 265245196ea4SRichard Henderson 265345196ea4SRichard Henderson TRANS(FBPfcc, 64, do_fbpfcc, a) 265445196ea4SRichard Henderson TRANS(FBfcc, ALL, do_fbpfcc, a) 265545196ea4SRichard Henderson 2656ab9ffe98SRichard Henderson static bool trans_BPr(DisasContext *dc, arg_BPr *a) 2657ab9ffe98SRichard Henderson { 2658ab9ffe98SRichard Henderson DisasCompare cmp; 2659ab9ffe98SRichard Henderson 2660ab9ffe98SRichard Henderson if (!avail_64(dc)) { 2661ab9ffe98SRichard Henderson return false; 2662ab9ffe98SRichard Henderson } 26632c4f56c9SRichard Henderson if (!gen_compare_reg(&cmp, a->cond, gen_load_gpr(dc, a->rs1))) { 2664ab9ffe98SRichard Henderson return false; 2665ab9ffe98SRichard Henderson } 26663951b7a8SRichard Henderson return advance_jump_cond(dc, &cmp, a->a, a->i); 2667ab9ffe98SRichard Henderson } 2668ab9ffe98SRichard Henderson 266923ada1b1SRichard Henderson static bool trans_CALL(DisasContext *dc, arg_CALL *a) 267023ada1b1SRichard Henderson { 267123ada1b1SRichard Henderson target_long target = address_mask_i(dc, dc->pc + a->i * 4); 267223ada1b1SRichard Henderson 267323ada1b1SRichard Henderson gen_store_gpr(dc, 15, tcg_constant_tl(dc->pc)); 267423ada1b1SRichard Henderson gen_mov_pc_npc(dc); 267523ada1b1SRichard Henderson dc->npc = target; 267623ada1b1SRichard Henderson return true; 267723ada1b1SRichard Henderson } 267823ada1b1SRichard Henderson 267945196ea4SRichard Henderson static bool trans_NCP(DisasContext *dc, arg_NCP *a) 268045196ea4SRichard Henderson { 268145196ea4SRichard Henderson /* 268245196ea4SRichard Henderson * For sparc32, always generate the no-coprocessor exception. 268345196ea4SRichard Henderson * For sparc64, always generate illegal instruction. 268445196ea4SRichard Henderson */ 268545196ea4SRichard Henderson #ifdef TARGET_SPARC64 268645196ea4SRichard Henderson return false; 268745196ea4SRichard Henderson #else 268845196ea4SRichard Henderson gen_exception(dc, TT_NCP_INSN); 268945196ea4SRichard Henderson return true; 269045196ea4SRichard Henderson #endif 269145196ea4SRichard Henderson } 269245196ea4SRichard Henderson 26936d2a0768SRichard Henderson static bool trans_SETHI(DisasContext *dc, arg_SETHI *a) 26946d2a0768SRichard Henderson { 26956d2a0768SRichard Henderson /* Special-case %g0 because that's the canonical nop. */ 26966d2a0768SRichard Henderson if (a->rd) { 26976d2a0768SRichard Henderson gen_store_gpr(dc, a->rd, tcg_constant_tl((uint32_t)a->i << 10)); 26986d2a0768SRichard Henderson } 26996d2a0768SRichard Henderson return advance_pc(dc); 27006d2a0768SRichard Henderson } 27016d2a0768SRichard Henderson 27020faef01bSRichard Henderson /* 27030faef01bSRichard Henderson * Major Opcode 10 -- integer, floating-point, vis, and system insns. 27040faef01bSRichard Henderson */ 27050faef01bSRichard Henderson 270630376636SRichard Henderson static bool do_tcc(DisasContext *dc, int cond, int cc, 270730376636SRichard Henderson int rs1, bool imm, int rs2_or_imm) 270830376636SRichard Henderson { 270930376636SRichard Henderson int mask = ((dc->def->features & CPU_FEATURE_HYPV) && supervisor(dc) 271030376636SRichard Henderson ? UA2005_HTRAP_MASK : V8_TRAP_MASK); 271130376636SRichard Henderson DisasCompare cmp; 271230376636SRichard Henderson TCGLabel *lab; 271330376636SRichard Henderson TCGv_i32 trap; 271430376636SRichard Henderson 271530376636SRichard Henderson /* Trap never. */ 271630376636SRichard Henderson if (cond == 0) { 271730376636SRichard Henderson return advance_pc(dc); 271830376636SRichard Henderson } 271930376636SRichard Henderson 272030376636SRichard Henderson /* 272130376636SRichard Henderson * Immediate traps are the most common case. Since this value is 272230376636SRichard Henderson * live across the branch, it really pays to evaluate the constant. 272330376636SRichard Henderson */ 272430376636SRichard Henderson if (rs1 == 0 && (imm || rs2_or_imm == 0)) { 272530376636SRichard Henderson trap = tcg_constant_i32((rs2_or_imm & mask) + TT_TRAP); 272630376636SRichard Henderson } else { 272730376636SRichard Henderson trap = tcg_temp_new_i32(); 272830376636SRichard Henderson tcg_gen_trunc_tl_i32(trap, gen_load_gpr(dc, rs1)); 272930376636SRichard Henderson if (imm) { 273030376636SRichard Henderson tcg_gen_addi_i32(trap, trap, rs2_or_imm); 273130376636SRichard Henderson } else { 273230376636SRichard Henderson TCGv_i32 t2 = tcg_temp_new_i32(); 273330376636SRichard Henderson tcg_gen_trunc_tl_i32(t2, gen_load_gpr(dc, rs2_or_imm)); 273430376636SRichard Henderson tcg_gen_add_i32(trap, trap, t2); 273530376636SRichard Henderson } 273630376636SRichard Henderson tcg_gen_andi_i32(trap, trap, mask); 273730376636SRichard Henderson tcg_gen_addi_i32(trap, trap, TT_TRAP); 273830376636SRichard Henderson } 273930376636SRichard Henderson 274089527e3aSRichard Henderson finishing_insn(dc); 274189527e3aSRichard Henderson 274230376636SRichard Henderson /* Trap always. */ 274330376636SRichard Henderson if (cond == 8) { 274430376636SRichard Henderson save_state(dc); 274530376636SRichard Henderson gen_helper_raise_exception(tcg_env, trap); 274630376636SRichard Henderson dc->base.is_jmp = DISAS_NORETURN; 274730376636SRichard Henderson return true; 274830376636SRichard Henderson } 274930376636SRichard Henderson 275030376636SRichard Henderson /* Conditional trap. */ 275130376636SRichard Henderson flush_cond(dc); 275230376636SRichard Henderson lab = delay_exceptionv(dc, trap); 275330376636SRichard Henderson gen_compare(&cmp, cc, cond, dc); 2754c8507ebfSRichard Henderson tcg_gen_brcondi_tl(cmp.cond, cmp.c1, cmp.c2, lab); 275530376636SRichard Henderson 275630376636SRichard Henderson return advance_pc(dc); 275730376636SRichard Henderson } 275830376636SRichard Henderson 275930376636SRichard Henderson static bool trans_Tcc_r(DisasContext *dc, arg_Tcc_r *a) 276030376636SRichard Henderson { 276130376636SRichard Henderson if (avail_32(dc) && a->cc) { 276230376636SRichard Henderson return false; 276330376636SRichard Henderson } 276430376636SRichard Henderson return do_tcc(dc, a->cond, a->cc, a->rs1, false, a->rs2); 276530376636SRichard Henderson } 276630376636SRichard Henderson 276730376636SRichard Henderson static bool trans_Tcc_i_v7(DisasContext *dc, arg_Tcc_i_v7 *a) 276830376636SRichard Henderson { 276930376636SRichard Henderson if (avail_64(dc)) { 277030376636SRichard Henderson return false; 277130376636SRichard Henderson } 277230376636SRichard Henderson return do_tcc(dc, a->cond, 0, a->rs1, true, a->i); 277330376636SRichard Henderson } 277430376636SRichard Henderson 277530376636SRichard Henderson static bool trans_Tcc_i_v9(DisasContext *dc, arg_Tcc_i_v9 *a) 277630376636SRichard Henderson { 277730376636SRichard Henderson if (avail_32(dc)) { 277830376636SRichard Henderson return false; 277930376636SRichard Henderson } 278030376636SRichard Henderson return do_tcc(dc, a->cond, a->cc, a->rs1, true, a->i); 278130376636SRichard Henderson } 278230376636SRichard Henderson 2783af25071cSRichard Henderson static bool trans_STBAR(DisasContext *dc, arg_STBAR *a) 2784af25071cSRichard Henderson { 2785af25071cSRichard Henderson tcg_gen_mb(TCG_MO_ST_ST | TCG_BAR_SC); 2786af25071cSRichard Henderson return advance_pc(dc); 2787af25071cSRichard Henderson } 2788af25071cSRichard Henderson 2789af25071cSRichard Henderson static bool trans_MEMBAR(DisasContext *dc, arg_MEMBAR *a) 2790af25071cSRichard Henderson { 2791af25071cSRichard Henderson if (avail_32(dc)) { 2792af25071cSRichard Henderson return false; 2793af25071cSRichard Henderson } 2794af25071cSRichard Henderson if (a->mmask) { 2795af25071cSRichard Henderson /* Note TCG_MO_* was modeled on sparc64, so mmask matches. */ 2796af25071cSRichard Henderson tcg_gen_mb(a->mmask | TCG_BAR_SC); 2797af25071cSRichard Henderson } 2798af25071cSRichard Henderson if (a->cmask) { 2799af25071cSRichard Henderson /* For #Sync, etc, end the TB to recognize interrupts. */ 2800af25071cSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 2801af25071cSRichard Henderson } 2802af25071cSRichard Henderson return advance_pc(dc); 2803af25071cSRichard Henderson } 2804af25071cSRichard Henderson 2805af25071cSRichard Henderson static bool do_rd_special(DisasContext *dc, bool priv, int rd, 2806af25071cSRichard Henderson TCGv (*func)(DisasContext *, TCGv)) 2807af25071cSRichard Henderson { 2808af25071cSRichard Henderson if (!priv) { 2809af25071cSRichard Henderson return raise_priv(dc); 2810af25071cSRichard Henderson } 2811af25071cSRichard Henderson gen_store_gpr(dc, rd, func(dc, gen_dest_gpr(dc, rd))); 2812af25071cSRichard Henderson return advance_pc(dc); 2813af25071cSRichard Henderson } 2814af25071cSRichard Henderson 2815af25071cSRichard Henderson static TCGv do_rdy(DisasContext *dc, TCGv dst) 2816af25071cSRichard Henderson { 2817af25071cSRichard Henderson return cpu_y; 2818af25071cSRichard Henderson } 2819af25071cSRichard Henderson 2820af25071cSRichard Henderson static bool trans_RDY(DisasContext *dc, arg_RDY *a) 2821af25071cSRichard Henderson { 2822af25071cSRichard Henderson /* 2823af25071cSRichard Henderson * TODO: Need a feature bit for sparcv8. In the meantime, treat all 2824af25071cSRichard Henderson * 32-bit cpus like sparcv7, which ignores the rs1 field. 2825af25071cSRichard Henderson * This matches after all other ASR, so Leon3 Asr17 is handled first. 2826af25071cSRichard Henderson */ 2827af25071cSRichard Henderson if (avail_64(dc) && a->rs1 != 0) { 2828af25071cSRichard Henderson return false; 2829af25071cSRichard Henderson } 2830af25071cSRichard Henderson return do_rd_special(dc, true, a->rd, do_rdy); 2831af25071cSRichard Henderson } 2832af25071cSRichard Henderson 2833af25071cSRichard Henderson static TCGv do_rd_leon3_config(DisasContext *dc, TCGv dst) 2834af25071cSRichard Henderson { 2835c92948f2SClément Chigot gen_helper_rdasr17(dst, tcg_env); 2836c92948f2SClément Chigot return dst; 2837af25071cSRichard Henderson } 2838af25071cSRichard Henderson 2839af25071cSRichard Henderson TRANS(RDASR17, ASR17, do_rd_special, true, a->rd, do_rd_leon3_config) 2840af25071cSRichard Henderson 2841af25071cSRichard Henderson static TCGv do_rdccr(DisasContext *dc, TCGv dst) 2842af25071cSRichard Henderson { 2843af25071cSRichard Henderson gen_helper_rdccr(dst, tcg_env); 2844af25071cSRichard Henderson return dst; 2845af25071cSRichard Henderson } 2846af25071cSRichard Henderson 2847af25071cSRichard Henderson TRANS(RDCCR, 64, do_rd_special, true, a->rd, do_rdccr) 2848af25071cSRichard Henderson 2849af25071cSRichard Henderson static TCGv do_rdasi(DisasContext *dc, TCGv dst) 2850af25071cSRichard Henderson { 2851af25071cSRichard Henderson #ifdef TARGET_SPARC64 2852af25071cSRichard Henderson return tcg_constant_tl(dc->asi); 2853af25071cSRichard Henderson #else 2854af25071cSRichard Henderson qemu_build_not_reached(); 2855af25071cSRichard Henderson #endif 2856af25071cSRichard Henderson } 2857af25071cSRichard Henderson 2858af25071cSRichard Henderson TRANS(RDASI, 64, do_rd_special, true, a->rd, do_rdasi) 2859af25071cSRichard Henderson 2860af25071cSRichard Henderson static TCGv do_rdtick(DisasContext *dc, TCGv dst) 2861af25071cSRichard Henderson { 2862af25071cSRichard Henderson TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 2863af25071cSRichard Henderson 2864af25071cSRichard Henderson tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(tick)); 2865af25071cSRichard Henderson if (translator_io_start(&dc->base)) { 2866af25071cSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 2867af25071cSRichard Henderson } 2868af25071cSRichard Henderson gen_helper_tick_get_count(dst, tcg_env, r_tickptr, 2869af25071cSRichard Henderson tcg_constant_i32(dc->mem_idx)); 2870af25071cSRichard Henderson return dst; 2871af25071cSRichard Henderson } 2872af25071cSRichard Henderson 2873af25071cSRichard Henderson /* TODO: non-priv access only allowed when enabled. */ 2874af25071cSRichard Henderson TRANS(RDTICK, 64, do_rd_special, true, a->rd, do_rdtick) 2875af25071cSRichard Henderson 2876af25071cSRichard Henderson static TCGv do_rdpc(DisasContext *dc, TCGv dst) 2877af25071cSRichard Henderson { 2878af25071cSRichard Henderson return tcg_constant_tl(address_mask_i(dc, dc->pc)); 2879af25071cSRichard Henderson } 2880af25071cSRichard Henderson 2881af25071cSRichard Henderson TRANS(RDPC, 64, do_rd_special, true, a->rd, do_rdpc) 2882af25071cSRichard Henderson 2883af25071cSRichard Henderson static TCGv do_rdfprs(DisasContext *dc, TCGv dst) 2884af25071cSRichard Henderson { 2885af25071cSRichard Henderson tcg_gen_ext_i32_tl(dst, cpu_fprs); 2886af25071cSRichard Henderson return dst; 2887af25071cSRichard Henderson } 2888af25071cSRichard Henderson 2889af25071cSRichard Henderson TRANS(RDFPRS, 64, do_rd_special, true, a->rd, do_rdfprs) 2890af25071cSRichard Henderson 2891af25071cSRichard Henderson static TCGv do_rdgsr(DisasContext *dc, TCGv dst) 2892af25071cSRichard Henderson { 2893af25071cSRichard Henderson gen_trap_ifnofpu(dc); 2894af25071cSRichard Henderson return cpu_gsr; 2895af25071cSRichard Henderson } 2896af25071cSRichard Henderson 2897af25071cSRichard Henderson TRANS(RDGSR, 64, do_rd_special, true, a->rd, do_rdgsr) 2898af25071cSRichard Henderson 2899af25071cSRichard Henderson static TCGv do_rdsoftint(DisasContext *dc, TCGv dst) 2900af25071cSRichard Henderson { 2901af25071cSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(softint)); 2902af25071cSRichard Henderson return dst; 2903af25071cSRichard Henderson } 2904af25071cSRichard Henderson 2905af25071cSRichard Henderson TRANS(RDSOFTINT, 64, do_rd_special, supervisor(dc), a->rd, do_rdsoftint) 2906af25071cSRichard Henderson 2907af25071cSRichard Henderson static TCGv do_rdtick_cmpr(DisasContext *dc, TCGv dst) 2908af25071cSRichard Henderson { 2909577efa45SRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(tick_cmpr)); 2910577efa45SRichard Henderson return dst; 2911af25071cSRichard Henderson } 2912af25071cSRichard Henderson 2913af25071cSRichard Henderson /* TODO: non-priv access only allowed when enabled. */ 2914af25071cSRichard Henderson TRANS(RDTICK_CMPR, 64, do_rd_special, true, a->rd, do_rdtick_cmpr) 2915af25071cSRichard Henderson 2916af25071cSRichard Henderson static TCGv do_rdstick(DisasContext *dc, TCGv dst) 2917af25071cSRichard Henderson { 2918af25071cSRichard Henderson TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 2919af25071cSRichard Henderson 2920af25071cSRichard Henderson tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(stick)); 2921af25071cSRichard Henderson if (translator_io_start(&dc->base)) { 2922af25071cSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 2923af25071cSRichard Henderson } 2924af25071cSRichard Henderson gen_helper_tick_get_count(dst, tcg_env, r_tickptr, 2925af25071cSRichard Henderson tcg_constant_i32(dc->mem_idx)); 2926af25071cSRichard Henderson return dst; 2927af25071cSRichard Henderson } 2928af25071cSRichard Henderson 2929af25071cSRichard Henderson /* TODO: non-priv access only allowed when enabled. */ 2930af25071cSRichard Henderson TRANS(RDSTICK, 64, do_rd_special, true, a->rd, do_rdstick) 2931af25071cSRichard Henderson 2932af25071cSRichard Henderson static TCGv do_rdstick_cmpr(DisasContext *dc, TCGv dst) 2933af25071cSRichard Henderson { 2934577efa45SRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(stick_cmpr)); 2935577efa45SRichard Henderson return dst; 2936af25071cSRichard Henderson } 2937af25071cSRichard Henderson 2938af25071cSRichard Henderson /* TODO: supervisor access only allowed when enabled by hypervisor. */ 2939af25071cSRichard Henderson TRANS(RDSTICK_CMPR, 64, do_rd_special, supervisor(dc), a->rd, do_rdstick_cmpr) 2940af25071cSRichard Henderson 2941af25071cSRichard Henderson /* 2942af25071cSRichard Henderson * UltraSPARC-T1 Strand status. 2943af25071cSRichard Henderson * HYPV check maybe not enough, UA2005 & UA2007 describe 2944af25071cSRichard Henderson * this ASR as impl. dep 2945af25071cSRichard Henderson */ 2946af25071cSRichard Henderson static TCGv do_rdstrand_status(DisasContext *dc, TCGv dst) 2947af25071cSRichard Henderson { 2948af25071cSRichard Henderson return tcg_constant_tl(1); 2949af25071cSRichard Henderson } 2950af25071cSRichard Henderson 2951af25071cSRichard Henderson TRANS(RDSTRAND_STATUS, HYPV, do_rd_special, true, a->rd, do_rdstrand_status) 2952af25071cSRichard Henderson 2953668bb9b7SRichard Henderson static TCGv do_rdpsr(DisasContext *dc, TCGv dst) 2954668bb9b7SRichard Henderson { 2955668bb9b7SRichard Henderson gen_helper_rdpsr(dst, tcg_env); 2956668bb9b7SRichard Henderson return dst; 2957668bb9b7SRichard Henderson } 2958668bb9b7SRichard Henderson 2959668bb9b7SRichard Henderson TRANS(RDPSR, 32, do_rd_special, supervisor(dc), a->rd, do_rdpsr) 2960668bb9b7SRichard Henderson 2961668bb9b7SRichard Henderson static TCGv do_rdhpstate(DisasContext *dc, TCGv dst) 2962668bb9b7SRichard Henderson { 2963668bb9b7SRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hpstate)); 2964668bb9b7SRichard Henderson return dst; 2965668bb9b7SRichard Henderson } 2966668bb9b7SRichard Henderson 2967668bb9b7SRichard Henderson TRANS(RDHPR_hpstate, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhpstate) 2968668bb9b7SRichard Henderson 2969668bb9b7SRichard Henderson static TCGv do_rdhtstate(DisasContext *dc, TCGv dst) 2970668bb9b7SRichard Henderson { 2971668bb9b7SRichard Henderson TCGv_i32 tl = tcg_temp_new_i32(); 2972668bb9b7SRichard Henderson TCGv_ptr tp = tcg_temp_new_ptr(); 2973668bb9b7SRichard Henderson 2974668bb9b7SRichard Henderson tcg_gen_ld_i32(tl, tcg_env, env64_field_offsetof(tl)); 2975668bb9b7SRichard Henderson tcg_gen_andi_i32(tl, tl, MAXTL_MASK); 2976668bb9b7SRichard Henderson tcg_gen_shli_i32(tl, tl, 3); 2977668bb9b7SRichard Henderson tcg_gen_ext_i32_ptr(tp, tl); 2978668bb9b7SRichard Henderson tcg_gen_add_ptr(tp, tp, tcg_env); 2979668bb9b7SRichard Henderson 2980668bb9b7SRichard Henderson tcg_gen_ld_tl(dst, tp, env64_field_offsetof(htstate)); 2981668bb9b7SRichard Henderson return dst; 2982668bb9b7SRichard Henderson } 2983668bb9b7SRichard Henderson 2984668bb9b7SRichard Henderson TRANS(RDHPR_htstate, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhtstate) 2985668bb9b7SRichard Henderson 2986668bb9b7SRichard Henderson static TCGv do_rdhintp(DisasContext *dc, TCGv dst) 2987668bb9b7SRichard Henderson { 29882da789deSRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hintp)); 29892da789deSRichard Henderson return dst; 2990668bb9b7SRichard Henderson } 2991668bb9b7SRichard Henderson 2992668bb9b7SRichard Henderson TRANS(RDHPR_hintp, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhintp) 2993668bb9b7SRichard Henderson 2994668bb9b7SRichard Henderson static TCGv do_rdhtba(DisasContext *dc, TCGv dst) 2995668bb9b7SRichard Henderson { 29962da789deSRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(htba)); 29972da789deSRichard Henderson return dst; 2998668bb9b7SRichard Henderson } 2999668bb9b7SRichard Henderson 3000668bb9b7SRichard Henderson TRANS(RDHPR_htba, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhtba) 3001668bb9b7SRichard Henderson 3002668bb9b7SRichard Henderson static TCGv do_rdhver(DisasContext *dc, TCGv dst) 3003668bb9b7SRichard Henderson { 30042da789deSRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hver)); 30052da789deSRichard Henderson return dst; 3006668bb9b7SRichard Henderson } 3007668bb9b7SRichard Henderson 3008668bb9b7SRichard Henderson TRANS(RDHPR_hver, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhver) 3009668bb9b7SRichard Henderson 3010668bb9b7SRichard Henderson static TCGv do_rdhstick_cmpr(DisasContext *dc, TCGv dst) 3011668bb9b7SRichard Henderson { 3012577efa45SRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hstick_cmpr)); 3013577efa45SRichard Henderson return dst; 3014668bb9b7SRichard Henderson } 3015668bb9b7SRichard Henderson 3016668bb9b7SRichard Henderson TRANS(RDHPR_hstick_cmpr, HYPV, do_rd_special, hypervisor(dc), a->rd, 3017668bb9b7SRichard Henderson do_rdhstick_cmpr) 3018668bb9b7SRichard Henderson 30195d617bfbSRichard Henderson static TCGv do_rdwim(DisasContext *dc, TCGv dst) 30205d617bfbSRichard Henderson { 3021cd6269f7SRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env32_field_offsetof(wim)); 3022cd6269f7SRichard Henderson return dst; 30235d617bfbSRichard Henderson } 30245d617bfbSRichard Henderson 30255d617bfbSRichard Henderson TRANS(RDWIM, 32, do_rd_special, supervisor(dc), a->rd, do_rdwim) 30265d617bfbSRichard Henderson 30275d617bfbSRichard Henderson static TCGv do_rdtpc(DisasContext *dc, TCGv dst) 30285d617bfbSRichard Henderson { 30295d617bfbSRichard Henderson #ifdef TARGET_SPARC64 30305d617bfbSRichard Henderson TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 30315d617bfbSRichard Henderson 30325d617bfbSRichard Henderson gen_load_trap_state_at_tl(r_tsptr); 30335d617bfbSRichard Henderson tcg_gen_ld_tl(dst, r_tsptr, offsetof(trap_state, tpc)); 30345d617bfbSRichard Henderson return dst; 30355d617bfbSRichard Henderson #else 30365d617bfbSRichard Henderson qemu_build_not_reached(); 30375d617bfbSRichard Henderson #endif 30385d617bfbSRichard Henderson } 30395d617bfbSRichard Henderson 30405d617bfbSRichard Henderson TRANS(RDPR_tpc, 64, do_rd_special, supervisor(dc), a->rd, do_rdtpc) 30415d617bfbSRichard Henderson 30425d617bfbSRichard Henderson static TCGv do_rdtnpc(DisasContext *dc, TCGv dst) 30435d617bfbSRichard Henderson { 30445d617bfbSRichard Henderson #ifdef TARGET_SPARC64 30455d617bfbSRichard Henderson TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 30465d617bfbSRichard Henderson 30475d617bfbSRichard Henderson gen_load_trap_state_at_tl(r_tsptr); 30485d617bfbSRichard Henderson tcg_gen_ld_tl(dst, r_tsptr, offsetof(trap_state, tnpc)); 30495d617bfbSRichard Henderson return dst; 30505d617bfbSRichard Henderson #else 30515d617bfbSRichard Henderson qemu_build_not_reached(); 30525d617bfbSRichard Henderson #endif 30535d617bfbSRichard Henderson } 30545d617bfbSRichard Henderson 30555d617bfbSRichard Henderson TRANS(RDPR_tnpc, 64, do_rd_special, supervisor(dc), a->rd, do_rdtnpc) 30565d617bfbSRichard Henderson 30575d617bfbSRichard Henderson static TCGv do_rdtstate(DisasContext *dc, TCGv dst) 30585d617bfbSRichard Henderson { 30595d617bfbSRichard Henderson #ifdef TARGET_SPARC64 30605d617bfbSRichard Henderson TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 30615d617bfbSRichard Henderson 30625d617bfbSRichard Henderson gen_load_trap_state_at_tl(r_tsptr); 30635d617bfbSRichard Henderson tcg_gen_ld_tl(dst, r_tsptr, offsetof(trap_state, tstate)); 30645d617bfbSRichard Henderson return dst; 30655d617bfbSRichard Henderson #else 30665d617bfbSRichard Henderson qemu_build_not_reached(); 30675d617bfbSRichard Henderson #endif 30685d617bfbSRichard Henderson } 30695d617bfbSRichard Henderson 30705d617bfbSRichard Henderson TRANS(RDPR_tstate, 64, do_rd_special, supervisor(dc), a->rd, do_rdtstate) 30715d617bfbSRichard Henderson 30725d617bfbSRichard Henderson static TCGv do_rdtt(DisasContext *dc, TCGv dst) 30735d617bfbSRichard Henderson { 30745d617bfbSRichard Henderson #ifdef TARGET_SPARC64 30755d617bfbSRichard Henderson TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 30765d617bfbSRichard Henderson 30775d617bfbSRichard Henderson gen_load_trap_state_at_tl(r_tsptr); 30785d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, r_tsptr, offsetof(trap_state, tt)); 30795d617bfbSRichard Henderson return dst; 30805d617bfbSRichard Henderson #else 30815d617bfbSRichard Henderson qemu_build_not_reached(); 30825d617bfbSRichard Henderson #endif 30835d617bfbSRichard Henderson } 30845d617bfbSRichard Henderson 30855d617bfbSRichard Henderson TRANS(RDPR_tt, 64, do_rd_special, supervisor(dc), a->rd, do_rdtt) 30865d617bfbSRichard Henderson TRANS(RDPR_tick, 64, do_rd_special, supervisor(dc), a->rd, do_rdtick) 30875d617bfbSRichard Henderson 30885d617bfbSRichard Henderson static TCGv do_rdtba(DisasContext *dc, TCGv dst) 30895d617bfbSRichard Henderson { 30905d617bfbSRichard Henderson return cpu_tbr; 30915d617bfbSRichard Henderson } 30925d617bfbSRichard Henderson 3093e8325dc0SRichard Henderson TRANS(RDTBR, 32, do_rd_special, supervisor(dc), a->rd, do_rdtba) 30945d617bfbSRichard Henderson TRANS(RDPR_tba, 64, do_rd_special, supervisor(dc), a->rd, do_rdtba) 30955d617bfbSRichard Henderson 30965d617bfbSRichard Henderson static TCGv do_rdpstate(DisasContext *dc, TCGv dst) 30975d617bfbSRichard Henderson { 30985d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(pstate)); 30995d617bfbSRichard Henderson return dst; 31005d617bfbSRichard Henderson } 31015d617bfbSRichard Henderson 31025d617bfbSRichard Henderson TRANS(RDPR_pstate, 64, do_rd_special, supervisor(dc), a->rd, do_rdpstate) 31035d617bfbSRichard Henderson 31045d617bfbSRichard Henderson static TCGv do_rdtl(DisasContext *dc, TCGv dst) 31055d617bfbSRichard Henderson { 31065d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(tl)); 31075d617bfbSRichard Henderson return dst; 31085d617bfbSRichard Henderson } 31095d617bfbSRichard Henderson 31105d617bfbSRichard Henderson TRANS(RDPR_tl, 64, do_rd_special, supervisor(dc), a->rd, do_rdtl) 31115d617bfbSRichard Henderson 31125d617bfbSRichard Henderson static TCGv do_rdpil(DisasContext *dc, TCGv dst) 31135d617bfbSRichard Henderson { 31145d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env_field_offsetof(psrpil)); 31155d617bfbSRichard Henderson return dst; 31165d617bfbSRichard Henderson } 31175d617bfbSRichard Henderson 31185d617bfbSRichard Henderson TRANS(RDPR_pil, 64, do_rd_special, supervisor(dc), a->rd, do_rdpil) 31195d617bfbSRichard Henderson 31205d617bfbSRichard Henderson static TCGv do_rdcwp(DisasContext *dc, TCGv dst) 31215d617bfbSRichard Henderson { 31225d617bfbSRichard Henderson gen_helper_rdcwp(dst, tcg_env); 31235d617bfbSRichard Henderson return dst; 31245d617bfbSRichard Henderson } 31255d617bfbSRichard Henderson 31265d617bfbSRichard Henderson TRANS(RDPR_cwp, 64, do_rd_special, supervisor(dc), a->rd, do_rdcwp) 31275d617bfbSRichard Henderson 31285d617bfbSRichard Henderson static TCGv do_rdcansave(DisasContext *dc, TCGv dst) 31295d617bfbSRichard Henderson { 31305d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(cansave)); 31315d617bfbSRichard Henderson return dst; 31325d617bfbSRichard Henderson } 31335d617bfbSRichard Henderson 31345d617bfbSRichard Henderson TRANS(RDPR_cansave, 64, do_rd_special, supervisor(dc), a->rd, do_rdcansave) 31355d617bfbSRichard Henderson 31365d617bfbSRichard Henderson static TCGv do_rdcanrestore(DisasContext *dc, TCGv dst) 31375d617bfbSRichard Henderson { 31385d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(canrestore)); 31395d617bfbSRichard Henderson return dst; 31405d617bfbSRichard Henderson } 31415d617bfbSRichard Henderson 31425d617bfbSRichard Henderson TRANS(RDPR_canrestore, 64, do_rd_special, supervisor(dc), a->rd, 31435d617bfbSRichard Henderson do_rdcanrestore) 31445d617bfbSRichard Henderson 31455d617bfbSRichard Henderson static TCGv do_rdcleanwin(DisasContext *dc, TCGv dst) 31465d617bfbSRichard Henderson { 31475d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(cleanwin)); 31485d617bfbSRichard Henderson return dst; 31495d617bfbSRichard Henderson } 31505d617bfbSRichard Henderson 31515d617bfbSRichard Henderson TRANS(RDPR_cleanwin, 64, do_rd_special, supervisor(dc), a->rd, do_rdcleanwin) 31525d617bfbSRichard Henderson 31535d617bfbSRichard Henderson static TCGv do_rdotherwin(DisasContext *dc, TCGv dst) 31545d617bfbSRichard Henderson { 31555d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(otherwin)); 31565d617bfbSRichard Henderson return dst; 31575d617bfbSRichard Henderson } 31585d617bfbSRichard Henderson 31595d617bfbSRichard Henderson TRANS(RDPR_otherwin, 64, do_rd_special, supervisor(dc), a->rd, do_rdotherwin) 31605d617bfbSRichard Henderson 31615d617bfbSRichard Henderson static TCGv do_rdwstate(DisasContext *dc, TCGv dst) 31625d617bfbSRichard Henderson { 31635d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(wstate)); 31645d617bfbSRichard Henderson return dst; 31655d617bfbSRichard Henderson } 31665d617bfbSRichard Henderson 31675d617bfbSRichard Henderson TRANS(RDPR_wstate, 64, do_rd_special, supervisor(dc), a->rd, do_rdwstate) 31685d617bfbSRichard Henderson 31695d617bfbSRichard Henderson static TCGv do_rdgl(DisasContext *dc, TCGv dst) 31705d617bfbSRichard Henderson { 31715d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(gl)); 31725d617bfbSRichard Henderson return dst; 31735d617bfbSRichard Henderson } 31745d617bfbSRichard Henderson 31755d617bfbSRichard Henderson TRANS(RDPR_gl, GL, do_rd_special, supervisor(dc), a->rd, do_rdgl) 31765d617bfbSRichard Henderson 31775d617bfbSRichard Henderson /* UA2005 strand status */ 31785d617bfbSRichard Henderson static TCGv do_rdssr(DisasContext *dc, TCGv dst) 31795d617bfbSRichard Henderson { 31802da789deSRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(ssr)); 31812da789deSRichard Henderson return dst; 31825d617bfbSRichard Henderson } 31835d617bfbSRichard Henderson 31845d617bfbSRichard Henderson TRANS(RDPR_strand_status, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdssr) 31855d617bfbSRichard Henderson 31865d617bfbSRichard Henderson static TCGv do_rdver(DisasContext *dc, TCGv dst) 31875d617bfbSRichard Henderson { 31882da789deSRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(version)); 31892da789deSRichard Henderson return dst; 31905d617bfbSRichard Henderson } 31915d617bfbSRichard Henderson 31925d617bfbSRichard Henderson TRANS(RDPR_ver, 64, do_rd_special, supervisor(dc), a->rd, do_rdver) 31935d617bfbSRichard Henderson 3194e8325dc0SRichard Henderson static bool trans_FLUSHW(DisasContext *dc, arg_FLUSHW *a) 3195e8325dc0SRichard Henderson { 3196e8325dc0SRichard Henderson if (avail_64(dc)) { 3197e8325dc0SRichard Henderson gen_helper_flushw(tcg_env); 3198e8325dc0SRichard Henderson return advance_pc(dc); 3199e8325dc0SRichard Henderson } 3200e8325dc0SRichard Henderson return false; 3201e8325dc0SRichard Henderson } 3202e8325dc0SRichard Henderson 32030faef01bSRichard Henderson static bool do_wr_special(DisasContext *dc, arg_r_r_ri *a, bool priv, 32040faef01bSRichard Henderson void (*func)(DisasContext *, TCGv)) 32050faef01bSRichard Henderson { 32060faef01bSRichard Henderson TCGv src; 32070faef01bSRichard Henderson 32080faef01bSRichard Henderson /* For simplicity, we under-decoded the rs2 form. */ 32090faef01bSRichard Henderson if (!a->imm && (a->rs2_or_imm & ~0x1f)) { 32100faef01bSRichard Henderson return false; 32110faef01bSRichard Henderson } 32120faef01bSRichard Henderson if (!priv) { 32130faef01bSRichard Henderson return raise_priv(dc); 32140faef01bSRichard Henderson } 32150faef01bSRichard Henderson 32160faef01bSRichard Henderson if (a->rs1 == 0 && (a->imm || a->rs2_or_imm == 0)) { 32170faef01bSRichard Henderson src = tcg_constant_tl(a->rs2_or_imm); 32180faef01bSRichard Henderson } else { 32190faef01bSRichard Henderson TCGv src1 = gen_load_gpr(dc, a->rs1); 32200faef01bSRichard Henderson if (a->rs2_or_imm == 0) { 32210faef01bSRichard Henderson src = src1; 32220faef01bSRichard Henderson } else { 32230faef01bSRichard Henderson src = tcg_temp_new(); 32240faef01bSRichard Henderson if (a->imm) { 32250faef01bSRichard Henderson tcg_gen_xori_tl(src, src1, a->rs2_or_imm); 32260faef01bSRichard Henderson } else { 32270faef01bSRichard Henderson tcg_gen_xor_tl(src, src1, gen_load_gpr(dc, a->rs2_or_imm)); 32280faef01bSRichard Henderson } 32290faef01bSRichard Henderson } 32300faef01bSRichard Henderson } 32310faef01bSRichard Henderson func(dc, src); 32320faef01bSRichard Henderson return advance_pc(dc); 32330faef01bSRichard Henderson } 32340faef01bSRichard Henderson 32350faef01bSRichard Henderson static void do_wry(DisasContext *dc, TCGv src) 32360faef01bSRichard Henderson { 32370faef01bSRichard Henderson tcg_gen_ext32u_tl(cpu_y, src); 32380faef01bSRichard Henderson } 32390faef01bSRichard Henderson 32400faef01bSRichard Henderson TRANS(WRY, ALL, do_wr_special, a, true, do_wry) 32410faef01bSRichard Henderson 32420faef01bSRichard Henderson static void do_wrccr(DisasContext *dc, TCGv src) 32430faef01bSRichard Henderson { 32440faef01bSRichard Henderson gen_helper_wrccr(tcg_env, src); 32450faef01bSRichard Henderson } 32460faef01bSRichard Henderson 32470faef01bSRichard Henderson TRANS(WRCCR, 64, do_wr_special, a, true, do_wrccr) 32480faef01bSRichard Henderson 32490faef01bSRichard Henderson static void do_wrasi(DisasContext *dc, TCGv src) 32500faef01bSRichard Henderson { 32510faef01bSRichard Henderson TCGv tmp = tcg_temp_new(); 32520faef01bSRichard Henderson 32530faef01bSRichard Henderson tcg_gen_ext8u_tl(tmp, src); 32540faef01bSRichard Henderson tcg_gen_st32_tl(tmp, tcg_env, env64_field_offsetof(asi)); 32550faef01bSRichard Henderson /* End TB to notice changed ASI. */ 32560faef01bSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 32570faef01bSRichard Henderson } 32580faef01bSRichard Henderson 32590faef01bSRichard Henderson TRANS(WRASI, 64, do_wr_special, a, true, do_wrasi) 32600faef01bSRichard Henderson 32610faef01bSRichard Henderson static void do_wrfprs(DisasContext *dc, TCGv src) 32620faef01bSRichard Henderson { 32630faef01bSRichard Henderson #ifdef TARGET_SPARC64 32640faef01bSRichard Henderson tcg_gen_trunc_tl_i32(cpu_fprs, src); 32650faef01bSRichard Henderson dc->fprs_dirty = 0; 32660faef01bSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 32670faef01bSRichard Henderson #else 32680faef01bSRichard Henderson qemu_build_not_reached(); 32690faef01bSRichard Henderson #endif 32700faef01bSRichard Henderson } 32710faef01bSRichard Henderson 32720faef01bSRichard Henderson TRANS(WRFPRS, 64, do_wr_special, a, true, do_wrfprs) 32730faef01bSRichard Henderson 32740faef01bSRichard Henderson static void do_wrgsr(DisasContext *dc, TCGv src) 32750faef01bSRichard Henderson { 32760faef01bSRichard Henderson gen_trap_ifnofpu(dc); 32770faef01bSRichard Henderson tcg_gen_mov_tl(cpu_gsr, src); 32780faef01bSRichard Henderson } 32790faef01bSRichard Henderson 32800faef01bSRichard Henderson TRANS(WRGSR, 64, do_wr_special, a, true, do_wrgsr) 32810faef01bSRichard Henderson 32820faef01bSRichard Henderson static void do_wrsoftint_set(DisasContext *dc, TCGv src) 32830faef01bSRichard Henderson { 32840faef01bSRichard Henderson gen_helper_set_softint(tcg_env, src); 32850faef01bSRichard Henderson } 32860faef01bSRichard Henderson 32870faef01bSRichard Henderson TRANS(WRSOFTINT_SET, 64, do_wr_special, a, supervisor(dc), do_wrsoftint_set) 32880faef01bSRichard Henderson 32890faef01bSRichard Henderson static void do_wrsoftint_clr(DisasContext *dc, TCGv src) 32900faef01bSRichard Henderson { 32910faef01bSRichard Henderson gen_helper_clear_softint(tcg_env, src); 32920faef01bSRichard Henderson } 32930faef01bSRichard Henderson 32940faef01bSRichard Henderson TRANS(WRSOFTINT_CLR, 64, do_wr_special, a, supervisor(dc), do_wrsoftint_clr) 32950faef01bSRichard Henderson 32960faef01bSRichard Henderson static void do_wrsoftint(DisasContext *dc, TCGv src) 32970faef01bSRichard Henderson { 32980faef01bSRichard Henderson gen_helper_write_softint(tcg_env, src); 32990faef01bSRichard Henderson } 33000faef01bSRichard Henderson 33010faef01bSRichard Henderson TRANS(WRSOFTINT, 64, do_wr_special, a, supervisor(dc), do_wrsoftint) 33020faef01bSRichard Henderson 33030faef01bSRichard Henderson static void do_wrtick_cmpr(DisasContext *dc, TCGv src) 33040faef01bSRichard Henderson { 33050faef01bSRichard Henderson TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 33060faef01bSRichard Henderson 3307577efa45SRichard Henderson tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(tick_cmpr)); 3308577efa45SRichard Henderson tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(tick)); 33090faef01bSRichard Henderson translator_io_start(&dc->base); 3310577efa45SRichard Henderson gen_helper_tick_set_limit(r_tickptr, src); 33110faef01bSRichard Henderson /* End TB to handle timer interrupt */ 33120faef01bSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 33130faef01bSRichard Henderson } 33140faef01bSRichard Henderson 33150faef01bSRichard Henderson TRANS(WRTICK_CMPR, 64, do_wr_special, a, supervisor(dc), do_wrtick_cmpr) 33160faef01bSRichard Henderson 33170faef01bSRichard Henderson static void do_wrstick(DisasContext *dc, TCGv src) 33180faef01bSRichard Henderson { 33190faef01bSRichard Henderson #ifdef TARGET_SPARC64 33200faef01bSRichard Henderson TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 33210faef01bSRichard Henderson 33220faef01bSRichard Henderson tcg_gen_ld_ptr(r_tickptr, tcg_env, offsetof(CPUSPARCState, stick)); 33230faef01bSRichard Henderson translator_io_start(&dc->base); 33240faef01bSRichard Henderson gen_helper_tick_set_count(r_tickptr, src); 33250faef01bSRichard Henderson /* End TB to handle timer interrupt */ 33260faef01bSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 33270faef01bSRichard Henderson #else 33280faef01bSRichard Henderson qemu_build_not_reached(); 33290faef01bSRichard Henderson #endif 33300faef01bSRichard Henderson } 33310faef01bSRichard Henderson 33320faef01bSRichard Henderson TRANS(WRSTICK, 64, do_wr_special, a, supervisor(dc), do_wrstick) 33330faef01bSRichard Henderson 33340faef01bSRichard Henderson static void do_wrstick_cmpr(DisasContext *dc, TCGv src) 33350faef01bSRichard Henderson { 33360faef01bSRichard Henderson TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 33370faef01bSRichard Henderson 3338577efa45SRichard Henderson tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(stick_cmpr)); 3339577efa45SRichard Henderson tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(stick)); 33400faef01bSRichard Henderson translator_io_start(&dc->base); 3341577efa45SRichard Henderson gen_helper_tick_set_limit(r_tickptr, src); 33420faef01bSRichard Henderson /* End TB to handle timer interrupt */ 33430faef01bSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 33440faef01bSRichard Henderson } 33450faef01bSRichard Henderson 33460faef01bSRichard Henderson TRANS(WRSTICK_CMPR, 64, do_wr_special, a, supervisor(dc), do_wrstick_cmpr) 33470faef01bSRichard Henderson 33480faef01bSRichard Henderson static void do_wrpowerdown(DisasContext *dc, TCGv src) 33490faef01bSRichard Henderson { 335089527e3aSRichard Henderson finishing_insn(dc); 33510faef01bSRichard Henderson save_state(dc); 33520faef01bSRichard Henderson gen_helper_power_down(tcg_env); 33530faef01bSRichard Henderson } 33540faef01bSRichard Henderson 33550faef01bSRichard Henderson TRANS(WRPOWERDOWN, POWERDOWN, do_wr_special, a, supervisor(dc), do_wrpowerdown) 33560faef01bSRichard Henderson 33576fbc032cSRichard Henderson static void do_wrmwait(DisasContext *dc, TCGv src) 33586fbc032cSRichard Henderson { 33596fbc032cSRichard Henderson /* 33606fbc032cSRichard Henderson * TODO: This is a stub version of mwait, which merely recognizes 33616fbc032cSRichard Henderson * interrupts immediately and does not wait. 33626fbc032cSRichard Henderson */ 33636fbc032cSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 33646fbc032cSRichard Henderson } 33656fbc032cSRichard Henderson 33666fbc032cSRichard Henderson TRANS(WRMWAIT, VIS4, do_wr_special, a, true, do_wrmwait) 33676fbc032cSRichard Henderson 336825524734SRichard Henderson static void do_wrpsr(DisasContext *dc, TCGv src) 336925524734SRichard Henderson { 337025524734SRichard Henderson gen_helper_wrpsr(tcg_env, src); 337125524734SRichard Henderson dc->base.is_jmp = DISAS_EXIT; 337225524734SRichard Henderson } 337325524734SRichard Henderson 337425524734SRichard Henderson TRANS(WRPSR, 32, do_wr_special, a, supervisor(dc), do_wrpsr) 337525524734SRichard Henderson 33769422278eSRichard Henderson static void do_wrwim(DisasContext *dc, TCGv src) 33779422278eSRichard Henderson { 33789422278eSRichard Henderson target_ulong mask = MAKE_64BIT_MASK(0, dc->def->nwindows); 3379cd6269f7SRichard Henderson TCGv tmp = tcg_temp_new(); 3380cd6269f7SRichard Henderson 3381cd6269f7SRichard Henderson tcg_gen_andi_tl(tmp, src, mask); 3382cd6269f7SRichard Henderson tcg_gen_st_tl(tmp, tcg_env, env32_field_offsetof(wim)); 33839422278eSRichard Henderson } 33849422278eSRichard Henderson 33859422278eSRichard Henderson TRANS(WRWIM, 32, do_wr_special, a, supervisor(dc), do_wrwim) 33869422278eSRichard Henderson 33879422278eSRichard Henderson static void do_wrtpc(DisasContext *dc, TCGv src) 33889422278eSRichard Henderson { 33899422278eSRichard Henderson #ifdef TARGET_SPARC64 33909422278eSRichard Henderson TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 33919422278eSRichard Henderson 33929422278eSRichard Henderson gen_load_trap_state_at_tl(r_tsptr); 33939422278eSRichard Henderson tcg_gen_st_tl(src, r_tsptr, offsetof(trap_state, tpc)); 33949422278eSRichard Henderson #else 33959422278eSRichard Henderson qemu_build_not_reached(); 33969422278eSRichard Henderson #endif 33979422278eSRichard Henderson } 33989422278eSRichard Henderson 33999422278eSRichard Henderson TRANS(WRPR_tpc, 64, do_wr_special, a, supervisor(dc), do_wrtpc) 34009422278eSRichard Henderson 34019422278eSRichard Henderson static void do_wrtnpc(DisasContext *dc, TCGv src) 34029422278eSRichard Henderson { 34039422278eSRichard Henderson #ifdef TARGET_SPARC64 34049422278eSRichard Henderson TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 34059422278eSRichard Henderson 34069422278eSRichard Henderson gen_load_trap_state_at_tl(r_tsptr); 34079422278eSRichard Henderson tcg_gen_st_tl(src, r_tsptr, offsetof(trap_state, tnpc)); 34089422278eSRichard Henderson #else 34099422278eSRichard Henderson qemu_build_not_reached(); 34109422278eSRichard Henderson #endif 34119422278eSRichard Henderson } 34129422278eSRichard Henderson 34139422278eSRichard Henderson TRANS(WRPR_tnpc, 64, do_wr_special, a, supervisor(dc), do_wrtnpc) 34149422278eSRichard Henderson 34159422278eSRichard Henderson static void do_wrtstate(DisasContext *dc, TCGv src) 34169422278eSRichard Henderson { 34179422278eSRichard Henderson #ifdef TARGET_SPARC64 34189422278eSRichard Henderson TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 34199422278eSRichard Henderson 34209422278eSRichard Henderson gen_load_trap_state_at_tl(r_tsptr); 34219422278eSRichard Henderson tcg_gen_st_tl(src, r_tsptr, offsetof(trap_state, tstate)); 34229422278eSRichard Henderson #else 34239422278eSRichard Henderson qemu_build_not_reached(); 34249422278eSRichard Henderson #endif 34259422278eSRichard Henderson } 34269422278eSRichard Henderson 34279422278eSRichard Henderson TRANS(WRPR_tstate, 64, do_wr_special, a, supervisor(dc), do_wrtstate) 34289422278eSRichard Henderson 34299422278eSRichard Henderson static void do_wrtt(DisasContext *dc, TCGv src) 34309422278eSRichard Henderson { 34319422278eSRichard Henderson #ifdef TARGET_SPARC64 34329422278eSRichard Henderson TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 34339422278eSRichard Henderson 34349422278eSRichard Henderson gen_load_trap_state_at_tl(r_tsptr); 34359422278eSRichard Henderson tcg_gen_st32_tl(src, r_tsptr, offsetof(trap_state, tt)); 34369422278eSRichard Henderson #else 34379422278eSRichard Henderson qemu_build_not_reached(); 34389422278eSRichard Henderson #endif 34399422278eSRichard Henderson } 34409422278eSRichard Henderson 34419422278eSRichard Henderson TRANS(WRPR_tt, 64, do_wr_special, a, supervisor(dc), do_wrtt) 34429422278eSRichard Henderson 34439422278eSRichard Henderson static void do_wrtick(DisasContext *dc, TCGv src) 34449422278eSRichard Henderson { 34459422278eSRichard Henderson TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 34469422278eSRichard Henderson 34479422278eSRichard Henderson tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(tick)); 34489422278eSRichard Henderson translator_io_start(&dc->base); 34499422278eSRichard Henderson gen_helper_tick_set_count(r_tickptr, src); 34509422278eSRichard Henderson /* End TB to handle timer interrupt */ 34519422278eSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 34529422278eSRichard Henderson } 34539422278eSRichard Henderson 34549422278eSRichard Henderson TRANS(WRPR_tick, 64, do_wr_special, a, supervisor(dc), do_wrtick) 34559422278eSRichard Henderson 34569422278eSRichard Henderson static void do_wrtba(DisasContext *dc, TCGv src) 34579422278eSRichard Henderson { 34589422278eSRichard Henderson tcg_gen_mov_tl(cpu_tbr, src); 34599422278eSRichard Henderson } 34609422278eSRichard Henderson 34619422278eSRichard Henderson TRANS(WRPR_tba, 64, do_wr_special, a, supervisor(dc), do_wrtba) 34629422278eSRichard Henderson 34639422278eSRichard Henderson static void do_wrpstate(DisasContext *dc, TCGv src) 34649422278eSRichard Henderson { 34659422278eSRichard Henderson save_state(dc); 34669422278eSRichard Henderson if (translator_io_start(&dc->base)) { 34679422278eSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 34689422278eSRichard Henderson } 34699422278eSRichard Henderson gen_helper_wrpstate(tcg_env, src); 34709422278eSRichard Henderson dc->npc = DYNAMIC_PC; 34719422278eSRichard Henderson } 34729422278eSRichard Henderson 34739422278eSRichard Henderson TRANS(WRPR_pstate, 64, do_wr_special, a, supervisor(dc), do_wrpstate) 34749422278eSRichard Henderson 34759422278eSRichard Henderson static void do_wrtl(DisasContext *dc, TCGv src) 34769422278eSRichard Henderson { 34779422278eSRichard Henderson save_state(dc); 34789422278eSRichard Henderson tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(tl)); 34799422278eSRichard Henderson dc->npc = DYNAMIC_PC; 34809422278eSRichard Henderson } 34819422278eSRichard Henderson 34829422278eSRichard Henderson TRANS(WRPR_tl, 64, do_wr_special, a, supervisor(dc), do_wrtl) 34839422278eSRichard Henderson 34849422278eSRichard Henderson static void do_wrpil(DisasContext *dc, TCGv src) 34859422278eSRichard Henderson { 34869422278eSRichard Henderson if (translator_io_start(&dc->base)) { 34879422278eSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 34889422278eSRichard Henderson } 34899422278eSRichard Henderson gen_helper_wrpil(tcg_env, src); 34909422278eSRichard Henderson } 34919422278eSRichard Henderson 34929422278eSRichard Henderson TRANS(WRPR_pil, 64, do_wr_special, a, supervisor(dc), do_wrpil) 34939422278eSRichard Henderson 34949422278eSRichard Henderson static void do_wrcwp(DisasContext *dc, TCGv src) 34959422278eSRichard Henderson { 34969422278eSRichard Henderson gen_helper_wrcwp(tcg_env, src); 34979422278eSRichard Henderson } 34989422278eSRichard Henderson 34999422278eSRichard Henderson TRANS(WRPR_cwp, 64, do_wr_special, a, supervisor(dc), do_wrcwp) 35009422278eSRichard Henderson 35019422278eSRichard Henderson static void do_wrcansave(DisasContext *dc, TCGv src) 35029422278eSRichard Henderson { 35039422278eSRichard Henderson tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(cansave)); 35049422278eSRichard Henderson } 35059422278eSRichard Henderson 35069422278eSRichard Henderson TRANS(WRPR_cansave, 64, do_wr_special, a, supervisor(dc), do_wrcansave) 35079422278eSRichard Henderson 35089422278eSRichard Henderson static void do_wrcanrestore(DisasContext *dc, TCGv src) 35099422278eSRichard Henderson { 35109422278eSRichard Henderson tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(canrestore)); 35119422278eSRichard Henderson } 35129422278eSRichard Henderson 35139422278eSRichard Henderson TRANS(WRPR_canrestore, 64, do_wr_special, a, supervisor(dc), do_wrcanrestore) 35149422278eSRichard Henderson 35159422278eSRichard Henderson static void do_wrcleanwin(DisasContext *dc, TCGv src) 35169422278eSRichard Henderson { 35179422278eSRichard Henderson tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(cleanwin)); 35189422278eSRichard Henderson } 35199422278eSRichard Henderson 35209422278eSRichard Henderson TRANS(WRPR_cleanwin, 64, do_wr_special, a, supervisor(dc), do_wrcleanwin) 35219422278eSRichard Henderson 35229422278eSRichard Henderson static void do_wrotherwin(DisasContext *dc, TCGv src) 35239422278eSRichard Henderson { 35249422278eSRichard Henderson tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(otherwin)); 35259422278eSRichard Henderson } 35269422278eSRichard Henderson 35279422278eSRichard Henderson TRANS(WRPR_otherwin, 64, do_wr_special, a, supervisor(dc), do_wrotherwin) 35289422278eSRichard Henderson 35299422278eSRichard Henderson static void do_wrwstate(DisasContext *dc, TCGv src) 35309422278eSRichard Henderson { 35319422278eSRichard Henderson tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(wstate)); 35329422278eSRichard Henderson } 35339422278eSRichard Henderson 35349422278eSRichard Henderson TRANS(WRPR_wstate, 64, do_wr_special, a, supervisor(dc), do_wrwstate) 35359422278eSRichard Henderson 35369422278eSRichard Henderson static void do_wrgl(DisasContext *dc, TCGv src) 35379422278eSRichard Henderson { 35389422278eSRichard Henderson gen_helper_wrgl(tcg_env, src); 35399422278eSRichard Henderson } 35409422278eSRichard Henderson 35419422278eSRichard Henderson TRANS(WRPR_gl, GL, do_wr_special, a, supervisor(dc), do_wrgl) 35429422278eSRichard Henderson 35439422278eSRichard Henderson /* UA2005 strand status */ 35449422278eSRichard Henderson static void do_wrssr(DisasContext *dc, TCGv src) 35459422278eSRichard Henderson { 35462da789deSRichard Henderson tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(ssr)); 35479422278eSRichard Henderson } 35489422278eSRichard Henderson 35499422278eSRichard Henderson TRANS(WRPR_strand_status, HYPV, do_wr_special, a, hypervisor(dc), do_wrssr) 35509422278eSRichard Henderson 3551bb97f2f5SRichard Henderson TRANS(WRTBR, 32, do_wr_special, a, supervisor(dc), do_wrtba) 3552bb97f2f5SRichard Henderson 3553bb97f2f5SRichard Henderson static void do_wrhpstate(DisasContext *dc, TCGv src) 3554bb97f2f5SRichard Henderson { 3555bb97f2f5SRichard Henderson tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(hpstate)); 3556bb97f2f5SRichard Henderson dc->base.is_jmp = DISAS_EXIT; 3557bb97f2f5SRichard Henderson } 3558bb97f2f5SRichard Henderson 3559bb97f2f5SRichard Henderson TRANS(WRHPR_hpstate, HYPV, do_wr_special, a, hypervisor(dc), do_wrhpstate) 3560bb97f2f5SRichard Henderson 3561bb97f2f5SRichard Henderson static void do_wrhtstate(DisasContext *dc, TCGv src) 3562bb97f2f5SRichard Henderson { 3563bb97f2f5SRichard Henderson TCGv_i32 tl = tcg_temp_new_i32(); 3564bb97f2f5SRichard Henderson TCGv_ptr tp = tcg_temp_new_ptr(); 3565bb97f2f5SRichard Henderson 3566bb97f2f5SRichard Henderson tcg_gen_ld_i32(tl, tcg_env, env64_field_offsetof(tl)); 3567bb97f2f5SRichard Henderson tcg_gen_andi_i32(tl, tl, MAXTL_MASK); 3568bb97f2f5SRichard Henderson tcg_gen_shli_i32(tl, tl, 3); 3569bb97f2f5SRichard Henderson tcg_gen_ext_i32_ptr(tp, tl); 3570bb97f2f5SRichard Henderson tcg_gen_add_ptr(tp, tp, tcg_env); 3571bb97f2f5SRichard Henderson 3572bb97f2f5SRichard Henderson tcg_gen_st_tl(src, tp, env64_field_offsetof(htstate)); 3573bb97f2f5SRichard Henderson } 3574bb97f2f5SRichard Henderson 3575bb97f2f5SRichard Henderson TRANS(WRHPR_htstate, HYPV, do_wr_special, a, hypervisor(dc), do_wrhtstate) 3576bb97f2f5SRichard Henderson 3577bb97f2f5SRichard Henderson static void do_wrhintp(DisasContext *dc, TCGv src) 3578bb97f2f5SRichard Henderson { 35792da789deSRichard Henderson tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(hintp)); 3580bb97f2f5SRichard Henderson } 3581bb97f2f5SRichard Henderson 3582bb97f2f5SRichard Henderson TRANS(WRHPR_hintp, HYPV, do_wr_special, a, hypervisor(dc), do_wrhintp) 3583bb97f2f5SRichard Henderson 3584bb97f2f5SRichard Henderson static void do_wrhtba(DisasContext *dc, TCGv src) 3585bb97f2f5SRichard Henderson { 35862da789deSRichard Henderson tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(htba)); 3587bb97f2f5SRichard Henderson } 3588bb97f2f5SRichard Henderson 3589bb97f2f5SRichard Henderson TRANS(WRHPR_htba, HYPV, do_wr_special, a, hypervisor(dc), do_wrhtba) 3590bb97f2f5SRichard Henderson 3591bb97f2f5SRichard Henderson static void do_wrhstick_cmpr(DisasContext *dc, TCGv src) 3592bb97f2f5SRichard Henderson { 3593bb97f2f5SRichard Henderson TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 3594bb97f2f5SRichard Henderson 3595577efa45SRichard Henderson tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(hstick_cmpr)); 3596bb97f2f5SRichard Henderson tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(hstick)); 3597bb97f2f5SRichard Henderson translator_io_start(&dc->base); 3598577efa45SRichard Henderson gen_helper_tick_set_limit(r_tickptr, src); 3599bb97f2f5SRichard Henderson /* End TB to handle timer interrupt */ 3600bb97f2f5SRichard Henderson dc->base.is_jmp = DISAS_EXIT; 3601bb97f2f5SRichard Henderson } 3602bb97f2f5SRichard Henderson 3603bb97f2f5SRichard Henderson TRANS(WRHPR_hstick_cmpr, HYPV, do_wr_special, a, hypervisor(dc), 3604bb97f2f5SRichard Henderson do_wrhstick_cmpr) 3605bb97f2f5SRichard Henderson 360625524734SRichard Henderson static bool do_saved_restored(DisasContext *dc, bool saved) 360725524734SRichard Henderson { 360825524734SRichard Henderson if (!supervisor(dc)) { 360925524734SRichard Henderson return raise_priv(dc); 361025524734SRichard Henderson } 361125524734SRichard Henderson if (saved) { 361225524734SRichard Henderson gen_helper_saved(tcg_env); 361325524734SRichard Henderson } else { 361425524734SRichard Henderson gen_helper_restored(tcg_env); 361525524734SRichard Henderson } 361625524734SRichard Henderson return advance_pc(dc); 361725524734SRichard Henderson } 361825524734SRichard Henderson 361925524734SRichard Henderson TRANS(SAVED, 64, do_saved_restored, true) 362025524734SRichard Henderson TRANS(RESTORED, 64, do_saved_restored, false) 362125524734SRichard Henderson 3622d3825800SRichard Henderson static bool trans_NOP(DisasContext *dc, arg_NOP *a) 3623d3825800SRichard Henderson { 3624d3825800SRichard Henderson return advance_pc(dc); 3625d3825800SRichard Henderson } 3626d3825800SRichard Henderson 36270faef01bSRichard Henderson /* 36280faef01bSRichard Henderson * TODO: Need a feature bit for sparcv8. 36290faef01bSRichard Henderson * In the meantime, treat all 32-bit cpus like sparcv7. 36300faef01bSRichard Henderson */ 36315458fd31SRichard Henderson TRANS(NOP_v7, 32, trans_NOP, a) 36325458fd31SRichard Henderson TRANS(NOP_v9, 64, trans_NOP, a) 36330faef01bSRichard Henderson 3634b597eedcSRichard Henderson static bool do_arith_int(DisasContext *dc, arg_r_r_ri_cc *a, 3635428881deSRichard Henderson void (*func)(TCGv, TCGv, TCGv), 36362a45b736SRichard Henderson void (*funci)(TCGv, TCGv, target_long), 36372a45b736SRichard Henderson bool logic_cc) 3638428881deSRichard Henderson { 3639428881deSRichard Henderson TCGv dst, src1; 3640428881deSRichard Henderson 3641428881deSRichard Henderson /* For simplicity, we under-decoded the rs2 form. */ 3642428881deSRichard Henderson if (!a->imm && a->rs2_or_imm & ~0x1f) { 3643428881deSRichard Henderson return false; 3644428881deSRichard Henderson } 3645428881deSRichard Henderson 36462a45b736SRichard Henderson if (logic_cc) { 36472a45b736SRichard Henderson dst = cpu_cc_N; 3648428881deSRichard Henderson } else { 3649428881deSRichard Henderson dst = gen_dest_gpr(dc, a->rd); 3650428881deSRichard Henderson } 3651428881deSRichard Henderson src1 = gen_load_gpr(dc, a->rs1); 3652428881deSRichard Henderson 3653428881deSRichard Henderson if (a->imm || a->rs2_or_imm == 0) { 3654428881deSRichard Henderson if (funci) { 3655428881deSRichard Henderson funci(dst, src1, a->rs2_or_imm); 3656428881deSRichard Henderson } else { 3657428881deSRichard Henderson func(dst, src1, tcg_constant_tl(a->rs2_or_imm)); 3658428881deSRichard Henderson } 3659428881deSRichard Henderson } else { 3660428881deSRichard Henderson func(dst, src1, cpu_regs[a->rs2_or_imm]); 3661428881deSRichard Henderson } 36622a45b736SRichard Henderson 36632a45b736SRichard Henderson if (logic_cc) { 36642a45b736SRichard Henderson if (TARGET_LONG_BITS == 64) { 36652a45b736SRichard Henderson tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N); 36662a45b736SRichard Henderson tcg_gen_movi_tl(cpu_icc_C, 0); 36672a45b736SRichard Henderson } 36682a45b736SRichard Henderson tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N); 36692a45b736SRichard Henderson tcg_gen_movi_tl(cpu_cc_C, 0); 36702a45b736SRichard Henderson tcg_gen_movi_tl(cpu_cc_V, 0); 36712a45b736SRichard Henderson } 36722a45b736SRichard Henderson 3673428881deSRichard Henderson gen_store_gpr(dc, a->rd, dst); 3674428881deSRichard Henderson return advance_pc(dc); 3675428881deSRichard Henderson } 3676428881deSRichard Henderson 3677b597eedcSRichard Henderson static bool do_arith(DisasContext *dc, arg_r_r_ri_cc *a, 3678428881deSRichard Henderson void (*func)(TCGv, TCGv, TCGv), 3679428881deSRichard Henderson void (*funci)(TCGv, TCGv, target_long), 3680428881deSRichard Henderson void (*func_cc)(TCGv, TCGv, TCGv)) 3681428881deSRichard Henderson { 3682428881deSRichard Henderson if (a->cc) { 3683b597eedcSRichard Henderson return do_arith_int(dc, a, func_cc, NULL, false); 3684428881deSRichard Henderson } 3685b597eedcSRichard Henderson return do_arith_int(dc, a, func, funci, false); 3686428881deSRichard Henderson } 3687428881deSRichard Henderson 3688428881deSRichard Henderson static bool do_logic(DisasContext *dc, arg_r_r_ri_cc *a, 3689428881deSRichard Henderson void (*func)(TCGv, TCGv, TCGv), 3690428881deSRichard Henderson void (*funci)(TCGv, TCGv, target_long)) 3691428881deSRichard Henderson { 3692b597eedcSRichard Henderson return do_arith_int(dc, a, func, funci, a->cc); 3693428881deSRichard Henderson } 3694428881deSRichard Henderson 3695b597eedcSRichard Henderson TRANS(ADD, ALL, do_arith, a, tcg_gen_add_tl, tcg_gen_addi_tl, gen_op_addcc) 3696b597eedcSRichard Henderson TRANS(SUB, ALL, do_arith, a, tcg_gen_sub_tl, tcg_gen_subi_tl, gen_op_subcc) 3697b597eedcSRichard Henderson TRANS(ADDC, ALL, do_arith, a, gen_op_addc, NULL, gen_op_addccc) 3698b597eedcSRichard Henderson TRANS(SUBC, ALL, do_arith, a, gen_op_subc, NULL, gen_op_subccc) 3699428881deSRichard Henderson 3700b597eedcSRichard Henderson TRANS(TADDcc, ALL, do_arith, a, NULL, NULL, gen_op_taddcc) 3701b597eedcSRichard Henderson TRANS(TSUBcc, ALL, do_arith, a, NULL, NULL, gen_op_tsubcc) 3702b597eedcSRichard Henderson TRANS(TADDccTV, ALL, do_arith, a, NULL, NULL, gen_op_taddcctv) 3703b597eedcSRichard Henderson TRANS(TSUBccTV, ALL, do_arith, a, NULL, NULL, gen_op_tsubcctv) 3704a9aba13dSRichard Henderson 3705428881deSRichard Henderson TRANS(AND, ALL, do_logic, a, tcg_gen_and_tl, tcg_gen_andi_tl) 3706428881deSRichard Henderson TRANS(XOR, ALL, do_logic, a, tcg_gen_xor_tl, tcg_gen_xori_tl) 3707428881deSRichard Henderson TRANS(ANDN, ALL, do_logic, a, tcg_gen_andc_tl, NULL) 3708428881deSRichard Henderson TRANS(ORN, ALL, do_logic, a, tcg_gen_orc_tl, NULL) 3709428881deSRichard Henderson TRANS(XORN, ALL, do_logic, a, tcg_gen_eqv_tl, NULL) 3710428881deSRichard Henderson 3711b597eedcSRichard Henderson TRANS(MULX, 64, do_arith, a, tcg_gen_mul_tl, tcg_gen_muli_tl, NULL) 3712b5372650SRichard Henderson TRANS(UMUL, MUL, do_logic, a, gen_op_umul, NULL) 3713b5372650SRichard Henderson TRANS(SMUL, MUL, do_logic, a, gen_op_smul, NULL) 3714b597eedcSRichard Henderson TRANS(MULScc, ALL, do_arith, a, NULL, NULL, gen_op_mulscc) 371522188d7dSRichard Henderson 37163a6b8de3SRichard Henderson TRANS(UDIVcc, DIV, do_arith, a, NULL, NULL, gen_op_udivcc) 3717b597eedcSRichard Henderson TRANS(SDIV, DIV, do_arith, a, gen_op_sdiv, NULL, gen_op_sdivcc) 37184ee85ea9SRichard Henderson 37199c6ec5bcSRichard Henderson /* TODO: Should have feature bit -- comes in with UltraSparc T2. */ 3720b597eedcSRichard Henderson TRANS(POPC, 64, do_arith, a, gen_op_popc, NULL, NULL) 37219c6ec5bcSRichard Henderson 3722428881deSRichard Henderson static bool trans_OR(DisasContext *dc, arg_r_r_ri_cc *a) 3723428881deSRichard Henderson { 3724428881deSRichard Henderson /* OR with %g0 is the canonical alias for MOV. */ 3725428881deSRichard Henderson if (!a->cc && a->rs1 == 0) { 3726428881deSRichard Henderson if (a->imm || a->rs2_or_imm == 0) { 3727428881deSRichard Henderson gen_store_gpr(dc, a->rd, tcg_constant_tl(a->rs2_or_imm)); 3728428881deSRichard Henderson } else if (a->rs2_or_imm & ~0x1f) { 3729428881deSRichard Henderson /* For simplicity, we under-decoded the rs2 form. */ 3730428881deSRichard Henderson return false; 3731428881deSRichard Henderson } else { 3732428881deSRichard Henderson gen_store_gpr(dc, a->rd, cpu_regs[a->rs2_or_imm]); 3733428881deSRichard Henderson } 3734428881deSRichard Henderson return advance_pc(dc); 3735428881deSRichard Henderson } 3736428881deSRichard Henderson return do_logic(dc, a, tcg_gen_or_tl, tcg_gen_ori_tl); 3737428881deSRichard Henderson } 3738428881deSRichard Henderson 37393a6b8de3SRichard Henderson static bool trans_UDIV(DisasContext *dc, arg_r_r_ri *a) 37403a6b8de3SRichard Henderson { 37413a6b8de3SRichard Henderson TCGv_i64 t1, t2; 37423a6b8de3SRichard Henderson TCGv dst; 37433a6b8de3SRichard Henderson 37443a6b8de3SRichard Henderson if (!avail_DIV(dc)) { 37453a6b8de3SRichard Henderson return false; 37463a6b8de3SRichard Henderson } 37473a6b8de3SRichard Henderson /* For simplicity, we under-decoded the rs2 form. */ 37483a6b8de3SRichard Henderson if (!a->imm && a->rs2_or_imm & ~0x1f) { 37493a6b8de3SRichard Henderson return false; 37503a6b8de3SRichard Henderson } 37513a6b8de3SRichard Henderson 37523a6b8de3SRichard Henderson if (unlikely(a->rs2_or_imm == 0)) { 37533a6b8de3SRichard Henderson gen_exception(dc, TT_DIV_ZERO); 37543a6b8de3SRichard Henderson return true; 37553a6b8de3SRichard Henderson } 37563a6b8de3SRichard Henderson 37573a6b8de3SRichard Henderson if (a->imm) { 37583a6b8de3SRichard Henderson t2 = tcg_constant_i64((uint32_t)a->rs2_or_imm); 37593a6b8de3SRichard Henderson } else { 37603a6b8de3SRichard Henderson TCGLabel *lab; 37613a6b8de3SRichard Henderson TCGv_i32 n2; 37623a6b8de3SRichard Henderson 37633a6b8de3SRichard Henderson finishing_insn(dc); 37643a6b8de3SRichard Henderson flush_cond(dc); 37653a6b8de3SRichard Henderson 37663a6b8de3SRichard Henderson n2 = tcg_temp_new_i32(); 37673a6b8de3SRichard Henderson tcg_gen_trunc_tl_i32(n2, cpu_regs[a->rs2_or_imm]); 37683a6b8de3SRichard Henderson 37693a6b8de3SRichard Henderson lab = delay_exception(dc, TT_DIV_ZERO); 37703a6b8de3SRichard Henderson tcg_gen_brcondi_i32(TCG_COND_EQ, n2, 0, lab); 37713a6b8de3SRichard Henderson 37723a6b8de3SRichard Henderson t2 = tcg_temp_new_i64(); 37733a6b8de3SRichard Henderson #ifdef TARGET_SPARC64 37743a6b8de3SRichard Henderson tcg_gen_ext32u_i64(t2, cpu_regs[a->rs2_or_imm]); 37753a6b8de3SRichard Henderson #else 37763a6b8de3SRichard Henderson tcg_gen_extu_i32_i64(t2, cpu_regs[a->rs2_or_imm]); 37773a6b8de3SRichard Henderson #endif 37783a6b8de3SRichard Henderson } 37793a6b8de3SRichard Henderson 37803a6b8de3SRichard Henderson t1 = tcg_temp_new_i64(); 37813a6b8de3SRichard Henderson tcg_gen_concat_tl_i64(t1, gen_load_gpr(dc, a->rs1), cpu_y); 37823a6b8de3SRichard Henderson 37833a6b8de3SRichard Henderson tcg_gen_divu_i64(t1, t1, t2); 37843a6b8de3SRichard Henderson tcg_gen_umin_i64(t1, t1, tcg_constant_i64(UINT32_MAX)); 37853a6b8de3SRichard Henderson 37863a6b8de3SRichard Henderson dst = gen_dest_gpr(dc, a->rd); 37873a6b8de3SRichard Henderson tcg_gen_trunc_i64_tl(dst, t1); 37883a6b8de3SRichard Henderson gen_store_gpr(dc, a->rd, dst); 37893a6b8de3SRichard Henderson return advance_pc(dc); 37903a6b8de3SRichard Henderson } 37913a6b8de3SRichard Henderson 3792f3141174SRichard Henderson static bool trans_UDIVX(DisasContext *dc, arg_r_r_ri *a) 3793f3141174SRichard Henderson { 3794f3141174SRichard Henderson TCGv dst, src1, src2; 3795f3141174SRichard Henderson 3796f3141174SRichard Henderson if (!avail_64(dc)) { 3797f3141174SRichard Henderson return false; 3798f3141174SRichard Henderson } 3799f3141174SRichard Henderson /* For simplicity, we under-decoded the rs2 form. */ 3800f3141174SRichard Henderson if (!a->imm && a->rs2_or_imm & ~0x1f) { 3801f3141174SRichard Henderson return false; 3802f3141174SRichard Henderson } 3803f3141174SRichard Henderson 3804f3141174SRichard Henderson if (unlikely(a->rs2_or_imm == 0)) { 3805f3141174SRichard Henderson gen_exception(dc, TT_DIV_ZERO); 3806f3141174SRichard Henderson return true; 3807f3141174SRichard Henderson } 3808f3141174SRichard Henderson 3809f3141174SRichard Henderson if (a->imm) { 3810f3141174SRichard Henderson src2 = tcg_constant_tl(a->rs2_or_imm); 3811f3141174SRichard Henderson } else { 3812f3141174SRichard Henderson TCGLabel *lab; 3813f3141174SRichard Henderson 3814f3141174SRichard Henderson finishing_insn(dc); 3815f3141174SRichard Henderson flush_cond(dc); 3816f3141174SRichard Henderson 3817f3141174SRichard Henderson lab = delay_exception(dc, TT_DIV_ZERO); 3818f3141174SRichard Henderson src2 = cpu_regs[a->rs2_or_imm]; 3819f3141174SRichard Henderson tcg_gen_brcondi_tl(TCG_COND_EQ, src2, 0, lab); 3820f3141174SRichard Henderson } 3821f3141174SRichard Henderson 3822f3141174SRichard Henderson dst = gen_dest_gpr(dc, a->rd); 3823f3141174SRichard Henderson src1 = gen_load_gpr(dc, a->rs1); 3824f3141174SRichard Henderson 3825f3141174SRichard Henderson tcg_gen_divu_tl(dst, src1, src2); 3826f3141174SRichard Henderson gen_store_gpr(dc, a->rd, dst); 3827f3141174SRichard Henderson return advance_pc(dc); 3828f3141174SRichard Henderson } 3829f3141174SRichard Henderson 3830f3141174SRichard Henderson static bool trans_SDIVX(DisasContext *dc, arg_r_r_ri *a) 3831f3141174SRichard Henderson { 3832f3141174SRichard Henderson TCGv dst, src1, src2; 3833f3141174SRichard Henderson 3834f3141174SRichard Henderson if (!avail_64(dc)) { 3835f3141174SRichard Henderson return false; 3836f3141174SRichard Henderson } 3837f3141174SRichard Henderson /* For simplicity, we under-decoded the rs2 form. */ 3838f3141174SRichard Henderson if (!a->imm && a->rs2_or_imm & ~0x1f) { 3839f3141174SRichard Henderson return false; 3840f3141174SRichard Henderson } 3841f3141174SRichard Henderson 3842f3141174SRichard Henderson if (unlikely(a->rs2_or_imm == 0)) { 3843f3141174SRichard Henderson gen_exception(dc, TT_DIV_ZERO); 3844f3141174SRichard Henderson return true; 3845f3141174SRichard Henderson } 3846f3141174SRichard Henderson 3847f3141174SRichard Henderson dst = gen_dest_gpr(dc, a->rd); 3848f3141174SRichard Henderson src1 = gen_load_gpr(dc, a->rs1); 3849f3141174SRichard Henderson 3850f3141174SRichard Henderson if (a->imm) { 3851f3141174SRichard Henderson if (unlikely(a->rs2_or_imm == -1)) { 3852f3141174SRichard Henderson tcg_gen_neg_tl(dst, src1); 3853f3141174SRichard Henderson gen_store_gpr(dc, a->rd, dst); 3854f3141174SRichard Henderson return advance_pc(dc); 3855f3141174SRichard Henderson } 3856f3141174SRichard Henderson src2 = tcg_constant_tl(a->rs2_or_imm); 3857f3141174SRichard Henderson } else { 3858f3141174SRichard Henderson TCGLabel *lab; 3859f3141174SRichard Henderson TCGv t1, t2; 3860f3141174SRichard Henderson 3861f3141174SRichard Henderson finishing_insn(dc); 3862f3141174SRichard Henderson flush_cond(dc); 3863f3141174SRichard Henderson 3864f3141174SRichard Henderson lab = delay_exception(dc, TT_DIV_ZERO); 3865f3141174SRichard Henderson src2 = cpu_regs[a->rs2_or_imm]; 3866f3141174SRichard Henderson tcg_gen_brcondi_tl(TCG_COND_EQ, src2, 0, lab); 3867f3141174SRichard Henderson 3868f3141174SRichard Henderson /* 3869f3141174SRichard Henderson * Need to avoid INT64_MIN / -1, which will trap on x86 host. 3870f3141174SRichard Henderson * Set SRC2 to 1 as a new divisor, to produce the correct result. 3871f3141174SRichard Henderson */ 3872f3141174SRichard Henderson t1 = tcg_temp_new(); 3873f3141174SRichard Henderson t2 = tcg_temp_new(); 3874f3141174SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_EQ, t1, src1, (target_long)INT64_MIN); 3875f3141174SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_EQ, t2, src2, -1); 3876f3141174SRichard Henderson tcg_gen_and_tl(t1, t1, t2); 3877f3141174SRichard Henderson tcg_gen_movcond_tl(TCG_COND_NE, t1, t1, tcg_constant_tl(0), 3878f3141174SRichard Henderson tcg_constant_tl(1), src2); 3879f3141174SRichard Henderson src2 = t1; 3880f3141174SRichard Henderson } 3881f3141174SRichard Henderson 3882f3141174SRichard Henderson tcg_gen_div_tl(dst, src1, src2); 3883f3141174SRichard Henderson gen_store_gpr(dc, a->rd, dst); 3884f3141174SRichard Henderson return advance_pc(dc); 3885f3141174SRichard Henderson } 3886f3141174SRichard Henderson 3887b88ce6f2SRichard Henderson static bool gen_edge(DisasContext *dc, arg_r_r_r *a, 388843db5838SRichard Henderson int width, bool cc, bool little_endian) 3889b88ce6f2SRichard Henderson { 389043db5838SRichard Henderson TCGv dst, s1, s2, l, r, t, m; 389143db5838SRichard Henderson uint64_t amask = address_mask_i(dc, -8); 3892b88ce6f2SRichard Henderson 3893b88ce6f2SRichard Henderson dst = gen_dest_gpr(dc, a->rd); 3894b88ce6f2SRichard Henderson s1 = gen_load_gpr(dc, a->rs1); 3895b88ce6f2SRichard Henderson s2 = gen_load_gpr(dc, a->rs2); 3896b88ce6f2SRichard Henderson 3897b88ce6f2SRichard Henderson if (cc) { 3898f828df74SRichard Henderson gen_op_subcc(cpu_cc_N, s1, s2); 3899b88ce6f2SRichard Henderson } 3900b88ce6f2SRichard Henderson 390143db5838SRichard Henderson l = tcg_temp_new(); 390243db5838SRichard Henderson r = tcg_temp_new(); 390343db5838SRichard Henderson t = tcg_temp_new(); 390443db5838SRichard Henderson 3905b88ce6f2SRichard Henderson switch (width) { 3906b88ce6f2SRichard Henderson case 8: 390743db5838SRichard Henderson tcg_gen_andi_tl(l, s1, 7); 390843db5838SRichard Henderson tcg_gen_andi_tl(r, s2, 7); 390943db5838SRichard Henderson tcg_gen_xori_tl(r, r, 7); 391043db5838SRichard Henderson m = tcg_constant_tl(0xff); 3911b88ce6f2SRichard Henderson break; 3912b88ce6f2SRichard Henderson case 16: 391343db5838SRichard Henderson tcg_gen_extract_tl(l, s1, 1, 2); 391443db5838SRichard Henderson tcg_gen_extract_tl(r, s2, 1, 2); 391543db5838SRichard Henderson tcg_gen_xori_tl(r, r, 3); 391643db5838SRichard Henderson m = tcg_constant_tl(0xf); 3917b88ce6f2SRichard Henderson break; 3918b88ce6f2SRichard Henderson case 32: 391943db5838SRichard Henderson tcg_gen_extract_tl(l, s1, 2, 1); 392043db5838SRichard Henderson tcg_gen_extract_tl(r, s2, 2, 1); 392143db5838SRichard Henderson tcg_gen_xori_tl(r, r, 1); 392243db5838SRichard Henderson m = tcg_constant_tl(0x3); 3923b88ce6f2SRichard Henderson break; 3924b88ce6f2SRichard Henderson default: 3925b88ce6f2SRichard Henderson abort(); 3926b88ce6f2SRichard Henderson } 3927b88ce6f2SRichard Henderson 392843db5838SRichard Henderson /* Compute Left Edge */ 392943db5838SRichard Henderson if (little_endian) { 393043db5838SRichard Henderson tcg_gen_shl_tl(l, m, l); 393143db5838SRichard Henderson tcg_gen_and_tl(l, l, m); 393243db5838SRichard Henderson } else { 393343db5838SRichard Henderson tcg_gen_shr_tl(l, m, l); 393443db5838SRichard Henderson } 393543db5838SRichard Henderson /* Compute Right Edge */ 393643db5838SRichard Henderson if (little_endian) { 393743db5838SRichard Henderson tcg_gen_shr_tl(r, m, r); 393843db5838SRichard Henderson } else { 393943db5838SRichard Henderson tcg_gen_shl_tl(r, m, r); 394043db5838SRichard Henderson tcg_gen_and_tl(r, r, m); 394143db5838SRichard Henderson } 3942b88ce6f2SRichard Henderson 394343db5838SRichard Henderson /* Compute dst = (s1 == s2 under amask ? l : l & r) */ 394443db5838SRichard Henderson tcg_gen_xor_tl(t, s1, s2); 394543db5838SRichard Henderson tcg_gen_and_tl(r, r, l); 394643db5838SRichard Henderson tcg_gen_movcond_tl(TCG_COND_TSTEQ, dst, t, tcg_constant_tl(amask), r, l); 3947b88ce6f2SRichard Henderson 3948b88ce6f2SRichard Henderson gen_store_gpr(dc, a->rd, dst); 3949b88ce6f2SRichard Henderson return advance_pc(dc); 3950b88ce6f2SRichard Henderson } 3951b88ce6f2SRichard Henderson 3952b88ce6f2SRichard Henderson TRANS(EDGE8cc, VIS1, gen_edge, a, 8, 1, 0) 3953b88ce6f2SRichard Henderson TRANS(EDGE8Lcc, VIS1, gen_edge, a, 8, 1, 1) 3954b88ce6f2SRichard Henderson TRANS(EDGE16cc, VIS1, gen_edge, a, 16, 1, 0) 3955b88ce6f2SRichard Henderson TRANS(EDGE16Lcc, VIS1, gen_edge, a, 16, 1, 1) 3956b88ce6f2SRichard Henderson TRANS(EDGE32cc, VIS1, gen_edge, a, 32, 1, 0) 3957b88ce6f2SRichard Henderson TRANS(EDGE32Lcc, VIS1, gen_edge, a, 32, 1, 1) 3958b88ce6f2SRichard Henderson 3959b88ce6f2SRichard Henderson TRANS(EDGE8N, VIS2, gen_edge, a, 8, 0, 0) 3960b88ce6f2SRichard Henderson TRANS(EDGE8LN, VIS2, gen_edge, a, 8, 0, 1) 3961b88ce6f2SRichard Henderson TRANS(EDGE16N, VIS2, gen_edge, a, 16, 0, 0) 3962b88ce6f2SRichard Henderson TRANS(EDGE16LN, VIS2, gen_edge, a, 16, 0, 1) 3963b88ce6f2SRichard Henderson TRANS(EDGE32N, VIS2, gen_edge, a, 32, 0, 0) 3964b88ce6f2SRichard Henderson TRANS(EDGE32LN, VIS2, gen_edge, a, 32, 0, 1) 3965b88ce6f2SRichard Henderson 3966875ce392SRichard Henderson static bool do_rr(DisasContext *dc, arg_r_r *a, 3967875ce392SRichard Henderson void (*func)(TCGv, TCGv)) 3968875ce392SRichard Henderson { 3969875ce392SRichard Henderson TCGv dst = gen_dest_gpr(dc, a->rd); 3970875ce392SRichard Henderson TCGv src = gen_load_gpr(dc, a->rs); 3971875ce392SRichard Henderson 3972875ce392SRichard Henderson func(dst, src); 3973875ce392SRichard Henderson gen_store_gpr(dc, a->rd, dst); 3974875ce392SRichard Henderson return advance_pc(dc); 3975875ce392SRichard Henderson } 3976875ce392SRichard Henderson 3977875ce392SRichard Henderson TRANS(LZCNT, VIS3, do_rr, a, gen_op_lzcnt) 3978875ce392SRichard Henderson 397945bfed3bSRichard Henderson static bool do_rrr(DisasContext *dc, arg_r_r_r *a, 398045bfed3bSRichard Henderson void (*func)(TCGv, TCGv, TCGv)) 398145bfed3bSRichard Henderson { 398245bfed3bSRichard Henderson TCGv dst = gen_dest_gpr(dc, a->rd); 398345bfed3bSRichard Henderson TCGv src1 = gen_load_gpr(dc, a->rs1); 398445bfed3bSRichard Henderson TCGv src2 = gen_load_gpr(dc, a->rs2); 398545bfed3bSRichard Henderson 398645bfed3bSRichard Henderson func(dst, src1, src2); 398745bfed3bSRichard Henderson gen_store_gpr(dc, a->rd, dst); 398845bfed3bSRichard Henderson return advance_pc(dc); 398945bfed3bSRichard Henderson } 399045bfed3bSRichard Henderson 399145bfed3bSRichard Henderson TRANS(ARRAY8, VIS1, do_rrr, a, gen_helper_array8) 399245bfed3bSRichard Henderson TRANS(ARRAY16, VIS1, do_rrr, a, gen_op_array16) 399345bfed3bSRichard Henderson TRANS(ARRAY32, VIS1, do_rrr, a, gen_op_array32) 399445bfed3bSRichard Henderson 3995015fc6fcSRichard Henderson TRANS(ADDXC, VIS3, do_rrr, a, gen_op_addxc) 3996015fc6fcSRichard Henderson TRANS(ADDXCcc, VIS3, do_rrr, a, gen_op_addxccc) 3997015fc6fcSRichard Henderson 399856f2ef9cSRichard Henderson TRANS(SUBXC, VIS4, do_rrr, a, gen_op_subxc) 399956f2ef9cSRichard Henderson TRANS(SUBXCcc, VIS4, do_rrr, a, gen_op_subxccc) 400056f2ef9cSRichard Henderson 4001680af1b4SRichard Henderson TRANS(UMULXHI, VIS3, do_rrr, a, gen_op_umulxhi) 4002680af1b4SRichard Henderson 40039e20ca94SRichard Henderson static void gen_op_alignaddr(TCGv dst, TCGv s1, TCGv s2) 40049e20ca94SRichard Henderson { 40059e20ca94SRichard Henderson #ifdef TARGET_SPARC64 40069e20ca94SRichard Henderson TCGv tmp = tcg_temp_new(); 40079e20ca94SRichard Henderson 40089e20ca94SRichard Henderson tcg_gen_add_tl(tmp, s1, s2); 40099e20ca94SRichard Henderson tcg_gen_andi_tl(dst, tmp, -8); 40109e20ca94SRichard Henderson tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, tmp, 0, 3); 40119e20ca94SRichard Henderson #else 40129e20ca94SRichard Henderson g_assert_not_reached(); 40139e20ca94SRichard Henderson #endif 40149e20ca94SRichard Henderson } 40159e20ca94SRichard Henderson 40169e20ca94SRichard Henderson static void gen_op_alignaddrl(TCGv dst, TCGv s1, TCGv s2) 40179e20ca94SRichard Henderson { 40189e20ca94SRichard Henderson #ifdef TARGET_SPARC64 40199e20ca94SRichard Henderson TCGv tmp = tcg_temp_new(); 40209e20ca94SRichard Henderson 40219e20ca94SRichard Henderson tcg_gen_add_tl(tmp, s1, s2); 40229e20ca94SRichard Henderson tcg_gen_andi_tl(dst, tmp, -8); 40239e20ca94SRichard Henderson tcg_gen_neg_tl(tmp, tmp); 40249e20ca94SRichard Henderson tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, tmp, 0, 3); 40259e20ca94SRichard Henderson #else 40269e20ca94SRichard Henderson g_assert_not_reached(); 40279e20ca94SRichard Henderson #endif 40289e20ca94SRichard Henderson } 40299e20ca94SRichard Henderson 40309e20ca94SRichard Henderson TRANS(ALIGNADDR, VIS1, do_rrr, a, gen_op_alignaddr) 40319e20ca94SRichard Henderson TRANS(ALIGNADDRL, VIS1, do_rrr, a, gen_op_alignaddrl) 40329e20ca94SRichard Henderson 403339ca3490SRichard Henderson static void gen_op_bmask(TCGv dst, TCGv s1, TCGv s2) 403439ca3490SRichard Henderson { 403539ca3490SRichard Henderson #ifdef TARGET_SPARC64 403639ca3490SRichard Henderson tcg_gen_add_tl(dst, s1, s2); 403739ca3490SRichard Henderson tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, dst, 32, 32); 403839ca3490SRichard Henderson #else 403939ca3490SRichard Henderson g_assert_not_reached(); 404039ca3490SRichard Henderson #endif 404139ca3490SRichard Henderson } 404239ca3490SRichard Henderson 404339ca3490SRichard Henderson TRANS(BMASK, VIS2, do_rrr, a, gen_op_bmask) 404439ca3490SRichard Henderson 4045c973b4e8SRichard Henderson static bool do_cmask(DisasContext *dc, int rs2, void (*func)(TCGv, TCGv, TCGv)) 4046c973b4e8SRichard Henderson { 4047c973b4e8SRichard Henderson func(cpu_gsr, cpu_gsr, gen_load_gpr(dc, rs2)); 4048c973b4e8SRichard Henderson return true; 4049c973b4e8SRichard Henderson } 4050c973b4e8SRichard Henderson 4051c973b4e8SRichard Henderson TRANS(CMASK8, VIS3, do_cmask, a->rs2, gen_helper_cmask8) 4052c973b4e8SRichard Henderson TRANS(CMASK16, VIS3, do_cmask, a->rs2, gen_helper_cmask16) 4053c973b4e8SRichard Henderson TRANS(CMASK32, VIS3, do_cmask, a->rs2, gen_helper_cmask32) 4054c973b4e8SRichard Henderson 40555fc546eeSRichard Henderson static bool do_shift_r(DisasContext *dc, arg_shiftr *a, bool l, bool u) 40565fc546eeSRichard Henderson { 40575fc546eeSRichard Henderson TCGv dst, src1, src2; 40585fc546eeSRichard Henderson 40595fc546eeSRichard Henderson /* Reject 64-bit shifts for sparc32. */ 40605fc546eeSRichard Henderson if (avail_32(dc) && a->x) { 40615fc546eeSRichard Henderson return false; 40625fc546eeSRichard Henderson } 40635fc546eeSRichard Henderson 40645fc546eeSRichard Henderson src2 = tcg_temp_new(); 40655fc546eeSRichard Henderson tcg_gen_andi_tl(src2, gen_load_gpr(dc, a->rs2), a->x ? 63 : 31); 40665fc546eeSRichard Henderson src1 = gen_load_gpr(dc, a->rs1); 40675fc546eeSRichard Henderson dst = gen_dest_gpr(dc, a->rd); 40685fc546eeSRichard Henderson 40695fc546eeSRichard Henderson if (l) { 40705fc546eeSRichard Henderson tcg_gen_shl_tl(dst, src1, src2); 40715fc546eeSRichard Henderson if (!a->x) { 40725fc546eeSRichard Henderson tcg_gen_ext32u_tl(dst, dst); 40735fc546eeSRichard Henderson } 40745fc546eeSRichard Henderson } else if (u) { 40755fc546eeSRichard Henderson if (!a->x) { 40765fc546eeSRichard Henderson tcg_gen_ext32u_tl(dst, src1); 40775fc546eeSRichard Henderson src1 = dst; 40785fc546eeSRichard Henderson } 40795fc546eeSRichard Henderson tcg_gen_shr_tl(dst, src1, src2); 40805fc546eeSRichard Henderson } else { 40815fc546eeSRichard Henderson if (!a->x) { 40825fc546eeSRichard Henderson tcg_gen_ext32s_tl(dst, src1); 40835fc546eeSRichard Henderson src1 = dst; 40845fc546eeSRichard Henderson } 40855fc546eeSRichard Henderson tcg_gen_sar_tl(dst, src1, src2); 40865fc546eeSRichard Henderson } 40875fc546eeSRichard Henderson gen_store_gpr(dc, a->rd, dst); 40885fc546eeSRichard Henderson return advance_pc(dc); 40895fc546eeSRichard Henderson } 40905fc546eeSRichard Henderson 40915fc546eeSRichard Henderson TRANS(SLL_r, ALL, do_shift_r, a, true, true) 40925fc546eeSRichard Henderson TRANS(SRL_r, ALL, do_shift_r, a, false, true) 40935fc546eeSRichard Henderson TRANS(SRA_r, ALL, do_shift_r, a, false, false) 40945fc546eeSRichard Henderson 40955fc546eeSRichard Henderson static bool do_shift_i(DisasContext *dc, arg_shifti *a, bool l, bool u) 40965fc546eeSRichard Henderson { 40975fc546eeSRichard Henderson TCGv dst, src1; 40985fc546eeSRichard Henderson 40995fc546eeSRichard Henderson /* Reject 64-bit shifts for sparc32. */ 41005fc546eeSRichard Henderson if (avail_32(dc) && (a->x || a->i >= 32)) { 41015fc546eeSRichard Henderson return false; 41025fc546eeSRichard Henderson } 41035fc546eeSRichard Henderson 41045fc546eeSRichard Henderson src1 = gen_load_gpr(dc, a->rs1); 41055fc546eeSRichard Henderson dst = gen_dest_gpr(dc, a->rd); 41065fc546eeSRichard Henderson 41075fc546eeSRichard Henderson if (avail_32(dc) || a->x) { 41085fc546eeSRichard Henderson if (l) { 41095fc546eeSRichard Henderson tcg_gen_shli_tl(dst, src1, a->i); 41105fc546eeSRichard Henderson } else if (u) { 41115fc546eeSRichard Henderson tcg_gen_shri_tl(dst, src1, a->i); 41125fc546eeSRichard Henderson } else { 41135fc546eeSRichard Henderson tcg_gen_sari_tl(dst, src1, a->i); 41145fc546eeSRichard Henderson } 41155fc546eeSRichard Henderson } else { 41165fc546eeSRichard Henderson if (l) { 41175fc546eeSRichard Henderson tcg_gen_deposit_z_tl(dst, src1, a->i, 32 - a->i); 41185fc546eeSRichard Henderson } else if (u) { 41195fc546eeSRichard Henderson tcg_gen_extract_tl(dst, src1, a->i, 32 - a->i); 41205fc546eeSRichard Henderson } else { 41215fc546eeSRichard Henderson tcg_gen_sextract_tl(dst, src1, a->i, 32 - a->i); 41225fc546eeSRichard Henderson } 41235fc546eeSRichard Henderson } 41245fc546eeSRichard Henderson gen_store_gpr(dc, a->rd, dst); 41255fc546eeSRichard Henderson return advance_pc(dc); 41265fc546eeSRichard Henderson } 41275fc546eeSRichard Henderson 41285fc546eeSRichard Henderson TRANS(SLL_i, ALL, do_shift_i, a, true, true) 41295fc546eeSRichard Henderson TRANS(SRL_i, ALL, do_shift_i, a, false, true) 41305fc546eeSRichard Henderson TRANS(SRA_i, ALL, do_shift_i, a, false, false) 41315fc546eeSRichard Henderson 4132fb4ed7aaSRichard Henderson static TCGv gen_rs2_or_imm(DisasContext *dc, bool imm, int rs2_or_imm) 4133fb4ed7aaSRichard Henderson { 4134fb4ed7aaSRichard Henderson /* For simplicity, we under-decoded the rs2 form. */ 4135fb4ed7aaSRichard Henderson if (!imm && rs2_or_imm & ~0x1f) { 4136fb4ed7aaSRichard Henderson return NULL; 4137fb4ed7aaSRichard Henderson } 4138fb4ed7aaSRichard Henderson if (imm || rs2_or_imm == 0) { 4139fb4ed7aaSRichard Henderson return tcg_constant_tl(rs2_or_imm); 4140fb4ed7aaSRichard Henderson } else { 4141fb4ed7aaSRichard Henderson return cpu_regs[rs2_or_imm]; 4142fb4ed7aaSRichard Henderson } 4143fb4ed7aaSRichard Henderson } 4144fb4ed7aaSRichard Henderson 4145fb4ed7aaSRichard Henderson static bool do_mov_cond(DisasContext *dc, DisasCompare *cmp, int rd, TCGv src2) 4146fb4ed7aaSRichard Henderson { 4147fb4ed7aaSRichard Henderson TCGv dst = gen_load_gpr(dc, rd); 4148c8507ebfSRichard Henderson TCGv c2 = tcg_constant_tl(cmp->c2); 4149fb4ed7aaSRichard Henderson 4150c8507ebfSRichard Henderson tcg_gen_movcond_tl(cmp->cond, dst, cmp->c1, c2, src2, dst); 4151fb4ed7aaSRichard Henderson gen_store_gpr(dc, rd, dst); 4152fb4ed7aaSRichard Henderson return advance_pc(dc); 4153fb4ed7aaSRichard Henderson } 4154fb4ed7aaSRichard Henderson 4155fb4ed7aaSRichard Henderson static bool trans_MOVcc(DisasContext *dc, arg_MOVcc *a) 4156fb4ed7aaSRichard Henderson { 4157fb4ed7aaSRichard Henderson TCGv src2 = gen_rs2_or_imm(dc, a->imm, a->rs2_or_imm); 4158fb4ed7aaSRichard Henderson DisasCompare cmp; 4159fb4ed7aaSRichard Henderson 4160fb4ed7aaSRichard Henderson if (src2 == NULL) { 4161fb4ed7aaSRichard Henderson return false; 4162fb4ed7aaSRichard Henderson } 4163fb4ed7aaSRichard Henderson gen_compare(&cmp, a->cc, a->cond, dc); 4164fb4ed7aaSRichard Henderson return do_mov_cond(dc, &cmp, a->rd, src2); 4165fb4ed7aaSRichard Henderson } 4166fb4ed7aaSRichard Henderson 4167fb4ed7aaSRichard Henderson static bool trans_MOVfcc(DisasContext *dc, arg_MOVfcc *a) 4168fb4ed7aaSRichard Henderson { 4169fb4ed7aaSRichard Henderson TCGv src2 = gen_rs2_or_imm(dc, a->imm, a->rs2_or_imm); 4170fb4ed7aaSRichard Henderson DisasCompare cmp; 4171fb4ed7aaSRichard Henderson 4172fb4ed7aaSRichard Henderson if (src2 == NULL) { 4173fb4ed7aaSRichard Henderson return false; 4174fb4ed7aaSRichard Henderson } 4175fb4ed7aaSRichard Henderson gen_fcompare(&cmp, a->cc, a->cond); 4176fb4ed7aaSRichard Henderson return do_mov_cond(dc, &cmp, a->rd, src2); 4177fb4ed7aaSRichard Henderson } 4178fb4ed7aaSRichard Henderson 4179fb4ed7aaSRichard Henderson static bool trans_MOVR(DisasContext *dc, arg_MOVR *a) 4180fb4ed7aaSRichard Henderson { 4181fb4ed7aaSRichard Henderson TCGv src2 = gen_rs2_or_imm(dc, a->imm, a->rs2_or_imm); 4182fb4ed7aaSRichard Henderson DisasCompare cmp; 4183fb4ed7aaSRichard Henderson 4184fb4ed7aaSRichard Henderson if (src2 == NULL) { 4185fb4ed7aaSRichard Henderson return false; 4186fb4ed7aaSRichard Henderson } 41872c4f56c9SRichard Henderson if (!gen_compare_reg(&cmp, a->cond, gen_load_gpr(dc, a->rs1))) { 41882c4f56c9SRichard Henderson return false; 41892c4f56c9SRichard Henderson } 4190fb4ed7aaSRichard Henderson return do_mov_cond(dc, &cmp, a->rd, src2); 4191fb4ed7aaSRichard Henderson } 4192fb4ed7aaSRichard Henderson 419386b82fe0SRichard Henderson static bool do_add_special(DisasContext *dc, arg_r_r_ri *a, 419486b82fe0SRichard Henderson bool (*func)(DisasContext *dc, int rd, TCGv src)) 419586b82fe0SRichard Henderson { 419686b82fe0SRichard Henderson TCGv src1, sum; 419786b82fe0SRichard Henderson 419886b82fe0SRichard Henderson /* For simplicity, we under-decoded the rs2 form. */ 419986b82fe0SRichard Henderson if (!a->imm && a->rs2_or_imm & ~0x1f) { 420086b82fe0SRichard Henderson return false; 420186b82fe0SRichard Henderson } 420286b82fe0SRichard Henderson 420386b82fe0SRichard Henderson /* 420486b82fe0SRichard Henderson * Always load the sum into a new temporary. 420586b82fe0SRichard Henderson * This is required to capture the value across a window change, 420686b82fe0SRichard Henderson * e.g. SAVE and RESTORE, and may be optimized away otherwise. 420786b82fe0SRichard Henderson */ 420886b82fe0SRichard Henderson sum = tcg_temp_new(); 420986b82fe0SRichard Henderson src1 = gen_load_gpr(dc, a->rs1); 421086b82fe0SRichard Henderson if (a->imm || a->rs2_or_imm == 0) { 421186b82fe0SRichard Henderson tcg_gen_addi_tl(sum, src1, a->rs2_or_imm); 421286b82fe0SRichard Henderson } else { 421386b82fe0SRichard Henderson tcg_gen_add_tl(sum, src1, cpu_regs[a->rs2_or_imm]); 421486b82fe0SRichard Henderson } 421586b82fe0SRichard Henderson return func(dc, a->rd, sum); 421686b82fe0SRichard Henderson } 421786b82fe0SRichard Henderson 421886b82fe0SRichard Henderson static bool do_jmpl(DisasContext *dc, int rd, TCGv src) 421986b82fe0SRichard Henderson { 422086b82fe0SRichard Henderson /* 422186b82fe0SRichard Henderson * Preserve pc across advance, so that we can delay 422286b82fe0SRichard Henderson * the writeback to rd until after src is consumed. 422386b82fe0SRichard Henderson */ 422486b82fe0SRichard Henderson target_ulong cur_pc = dc->pc; 422586b82fe0SRichard Henderson 422686b82fe0SRichard Henderson gen_check_align(dc, src, 3); 422786b82fe0SRichard Henderson 422886b82fe0SRichard Henderson gen_mov_pc_npc(dc); 422986b82fe0SRichard Henderson tcg_gen_mov_tl(cpu_npc, src); 423086b82fe0SRichard Henderson gen_address_mask(dc, cpu_npc); 423186b82fe0SRichard Henderson gen_store_gpr(dc, rd, tcg_constant_tl(cur_pc)); 423286b82fe0SRichard Henderson 423386b82fe0SRichard Henderson dc->npc = DYNAMIC_PC_LOOKUP; 423486b82fe0SRichard Henderson return true; 423586b82fe0SRichard Henderson } 423686b82fe0SRichard Henderson 423786b82fe0SRichard Henderson TRANS(JMPL, ALL, do_add_special, a, do_jmpl) 423886b82fe0SRichard Henderson 423986b82fe0SRichard Henderson static bool do_rett(DisasContext *dc, int rd, TCGv src) 424086b82fe0SRichard Henderson { 424186b82fe0SRichard Henderson if (!supervisor(dc)) { 424286b82fe0SRichard Henderson return raise_priv(dc); 424386b82fe0SRichard Henderson } 424486b82fe0SRichard Henderson 424586b82fe0SRichard Henderson gen_check_align(dc, src, 3); 424686b82fe0SRichard Henderson 424786b82fe0SRichard Henderson gen_mov_pc_npc(dc); 424886b82fe0SRichard Henderson tcg_gen_mov_tl(cpu_npc, src); 424986b82fe0SRichard Henderson gen_helper_rett(tcg_env); 425086b82fe0SRichard Henderson 425186b82fe0SRichard Henderson dc->npc = DYNAMIC_PC; 425286b82fe0SRichard Henderson return true; 425386b82fe0SRichard Henderson } 425486b82fe0SRichard Henderson 425586b82fe0SRichard Henderson TRANS(RETT, 32, do_add_special, a, do_rett) 425686b82fe0SRichard Henderson 425786b82fe0SRichard Henderson static bool do_return(DisasContext *dc, int rd, TCGv src) 425886b82fe0SRichard Henderson { 425986b82fe0SRichard Henderson gen_check_align(dc, src, 3); 42600dfae4f9SRichard Henderson gen_helper_restore(tcg_env); 426186b82fe0SRichard Henderson 426286b82fe0SRichard Henderson gen_mov_pc_npc(dc); 426386b82fe0SRichard Henderson tcg_gen_mov_tl(cpu_npc, src); 426486b82fe0SRichard Henderson gen_address_mask(dc, cpu_npc); 426586b82fe0SRichard Henderson 426686b82fe0SRichard Henderson dc->npc = DYNAMIC_PC_LOOKUP; 426786b82fe0SRichard Henderson return true; 426886b82fe0SRichard Henderson } 426986b82fe0SRichard Henderson 427086b82fe0SRichard Henderson TRANS(RETURN, 64, do_add_special, a, do_return) 427186b82fe0SRichard Henderson 4272d3825800SRichard Henderson static bool do_save(DisasContext *dc, int rd, TCGv src) 4273d3825800SRichard Henderson { 4274d3825800SRichard Henderson gen_helper_save(tcg_env); 4275d3825800SRichard Henderson gen_store_gpr(dc, rd, src); 4276d3825800SRichard Henderson return advance_pc(dc); 4277d3825800SRichard Henderson } 4278d3825800SRichard Henderson 4279d3825800SRichard Henderson TRANS(SAVE, ALL, do_add_special, a, do_save) 4280d3825800SRichard Henderson 4281d3825800SRichard Henderson static bool do_restore(DisasContext *dc, int rd, TCGv src) 4282d3825800SRichard Henderson { 4283d3825800SRichard Henderson gen_helper_restore(tcg_env); 4284d3825800SRichard Henderson gen_store_gpr(dc, rd, src); 4285d3825800SRichard Henderson return advance_pc(dc); 4286d3825800SRichard Henderson } 4287d3825800SRichard Henderson 4288d3825800SRichard Henderson TRANS(RESTORE, ALL, do_add_special, a, do_restore) 4289d3825800SRichard Henderson 42908f75b8a4SRichard Henderson static bool do_done_retry(DisasContext *dc, bool done) 42918f75b8a4SRichard Henderson { 42928f75b8a4SRichard Henderson if (!supervisor(dc)) { 42938f75b8a4SRichard Henderson return raise_priv(dc); 42948f75b8a4SRichard Henderson } 42958f75b8a4SRichard Henderson dc->npc = DYNAMIC_PC; 42968f75b8a4SRichard Henderson dc->pc = DYNAMIC_PC; 42978f75b8a4SRichard Henderson translator_io_start(&dc->base); 42988f75b8a4SRichard Henderson if (done) { 42998f75b8a4SRichard Henderson gen_helper_done(tcg_env); 43008f75b8a4SRichard Henderson } else { 43018f75b8a4SRichard Henderson gen_helper_retry(tcg_env); 43028f75b8a4SRichard Henderson } 43038f75b8a4SRichard Henderson return true; 43048f75b8a4SRichard Henderson } 43058f75b8a4SRichard Henderson 43068f75b8a4SRichard Henderson TRANS(DONE, 64, do_done_retry, true) 43078f75b8a4SRichard Henderson TRANS(RETRY, 64, do_done_retry, false) 43088f75b8a4SRichard Henderson 43090880d20bSRichard Henderson /* 43100880d20bSRichard Henderson * Major opcode 11 -- load and store instructions 43110880d20bSRichard Henderson */ 43120880d20bSRichard Henderson 43130880d20bSRichard Henderson static TCGv gen_ldst_addr(DisasContext *dc, int rs1, bool imm, int rs2_or_imm) 43140880d20bSRichard Henderson { 43150880d20bSRichard Henderson TCGv addr, tmp = NULL; 43160880d20bSRichard Henderson 43170880d20bSRichard Henderson /* For simplicity, we under-decoded the rs2 form. */ 43180880d20bSRichard Henderson if (!imm && rs2_or_imm & ~0x1f) { 43190880d20bSRichard Henderson return NULL; 43200880d20bSRichard Henderson } 43210880d20bSRichard Henderson 43220880d20bSRichard Henderson addr = gen_load_gpr(dc, rs1); 43230880d20bSRichard Henderson if (rs2_or_imm) { 43240880d20bSRichard Henderson tmp = tcg_temp_new(); 43250880d20bSRichard Henderson if (imm) { 43260880d20bSRichard Henderson tcg_gen_addi_tl(tmp, addr, rs2_or_imm); 43270880d20bSRichard Henderson } else { 43280880d20bSRichard Henderson tcg_gen_add_tl(tmp, addr, cpu_regs[rs2_or_imm]); 43290880d20bSRichard Henderson } 43300880d20bSRichard Henderson addr = tmp; 43310880d20bSRichard Henderson } 43320880d20bSRichard Henderson if (AM_CHECK(dc)) { 43330880d20bSRichard Henderson if (!tmp) { 43340880d20bSRichard Henderson tmp = tcg_temp_new(); 43350880d20bSRichard Henderson } 43360880d20bSRichard Henderson tcg_gen_ext32u_tl(tmp, addr); 43370880d20bSRichard Henderson addr = tmp; 43380880d20bSRichard Henderson } 43390880d20bSRichard Henderson return addr; 43400880d20bSRichard Henderson } 43410880d20bSRichard Henderson 43420880d20bSRichard Henderson static bool do_ld_gpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp mop) 43430880d20bSRichard Henderson { 43440880d20bSRichard Henderson TCGv reg, addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 43450880d20bSRichard Henderson DisasASI da; 43460880d20bSRichard Henderson 43470880d20bSRichard Henderson if (addr == NULL) { 43480880d20bSRichard Henderson return false; 43490880d20bSRichard Henderson } 43500880d20bSRichard Henderson da = resolve_asi(dc, a->asi, mop); 43510880d20bSRichard Henderson 43520880d20bSRichard Henderson reg = gen_dest_gpr(dc, a->rd); 435342071fc1SRichard Henderson gen_ld_asi(dc, &da, reg, addr); 43540880d20bSRichard Henderson gen_store_gpr(dc, a->rd, reg); 43550880d20bSRichard Henderson return advance_pc(dc); 43560880d20bSRichard Henderson } 43570880d20bSRichard Henderson 43580880d20bSRichard Henderson TRANS(LDUW, ALL, do_ld_gpr, a, MO_TEUL) 43590880d20bSRichard Henderson TRANS(LDUB, ALL, do_ld_gpr, a, MO_UB) 43600880d20bSRichard Henderson TRANS(LDUH, ALL, do_ld_gpr, a, MO_TEUW) 43610880d20bSRichard Henderson TRANS(LDSB, ALL, do_ld_gpr, a, MO_SB) 43620880d20bSRichard Henderson TRANS(LDSH, ALL, do_ld_gpr, a, MO_TESW) 43630880d20bSRichard Henderson TRANS(LDSW, 64, do_ld_gpr, a, MO_TESL) 43640880d20bSRichard Henderson TRANS(LDX, 64, do_ld_gpr, a, MO_TEUQ) 43650880d20bSRichard Henderson 43660880d20bSRichard Henderson static bool do_st_gpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp mop) 43670880d20bSRichard Henderson { 43680880d20bSRichard Henderson TCGv reg, addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 43690880d20bSRichard Henderson DisasASI da; 43700880d20bSRichard Henderson 43710880d20bSRichard Henderson if (addr == NULL) { 43720880d20bSRichard Henderson return false; 43730880d20bSRichard Henderson } 43740880d20bSRichard Henderson da = resolve_asi(dc, a->asi, mop); 43750880d20bSRichard Henderson 43760880d20bSRichard Henderson reg = gen_load_gpr(dc, a->rd); 437742071fc1SRichard Henderson gen_st_asi(dc, &da, reg, addr); 43780880d20bSRichard Henderson return advance_pc(dc); 43790880d20bSRichard Henderson } 43800880d20bSRichard Henderson 43810880d20bSRichard Henderson TRANS(STW, ALL, do_st_gpr, a, MO_TEUL) 43820880d20bSRichard Henderson TRANS(STB, ALL, do_st_gpr, a, MO_UB) 43830880d20bSRichard Henderson TRANS(STH, ALL, do_st_gpr, a, MO_TEUW) 43840880d20bSRichard Henderson TRANS(STX, 64, do_st_gpr, a, MO_TEUQ) 43850880d20bSRichard Henderson 43860880d20bSRichard Henderson static bool trans_LDD(DisasContext *dc, arg_r_r_ri_asi *a) 43870880d20bSRichard Henderson { 43880880d20bSRichard Henderson TCGv addr; 43890880d20bSRichard Henderson DisasASI da; 43900880d20bSRichard Henderson 43910880d20bSRichard Henderson if (a->rd & 1) { 43920880d20bSRichard Henderson return false; 43930880d20bSRichard Henderson } 43940880d20bSRichard Henderson addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 43950880d20bSRichard Henderson if (addr == NULL) { 43960880d20bSRichard Henderson return false; 43970880d20bSRichard Henderson } 43980880d20bSRichard Henderson da = resolve_asi(dc, a->asi, MO_TEUQ); 439942071fc1SRichard Henderson gen_ldda_asi(dc, &da, addr, a->rd); 44000880d20bSRichard Henderson return advance_pc(dc); 44010880d20bSRichard Henderson } 44020880d20bSRichard Henderson 44030880d20bSRichard Henderson static bool trans_STD(DisasContext *dc, arg_r_r_ri_asi *a) 44040880d20bSRichard Henderson { 44050880d20bSRichard Henderson TCGv addr; 44060880d20bSRichard Henderson DisasASI da; 44070880d20bSRichard Henderson 44080880d20bSRichard Henderson if (a->rd & 1) { 44090880d20bSRichard Henderson return false; 44100880d20bSRichard Henderson } 44110880d20bSRichard Henderson addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 44120880d20bSRichard Henderson if (addr == NULL) { 44130880d20bSRichard Henderson return false; 44140880d20bSRichard Henderson } 44150880d20bSRichard Henderson da = resolve_asi(dc, a->asi, MO_TEUQ); 441642071fc1SRichard Henderson gen_stda_asi(dc, &da, addr, a->rd); 44170880d20bSRichard Henderson return advance_pc(dc); 44180880d20bSRichard Henderson } 44190880d20bSRichard Henderson 4420cf07cd1eSRichard Henderson static bool trans_LDSTUB(DisasContext *dc, arg_r_r_ri_asi *a) 4421cf07cd1eSRichard Henderson { 4422cf07cd1eSRichard Henderson TCGv addr, reg; 4423cf07cd1eSRichard Henderson DisasASI da; 4424cf07cd1eSRichard Henderson 4425cf07cd1eSRichard Henderson addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 4426cf07cd1eSRichard Henderson if (addr == NULL) { 4427cf07cd1eSRichard Henderson return false; 4428cf07cd1eSRichard Henderson } 4429cf07cd1eSRichard Henderson da = resolve_asi(dc, a->asi, MO_UB); 4430cf07cd1eSRichard Henderson 4431cf07cd1eSRichard Henderson reg = gen_dest_gpr(dc, a->rd); 4432cf07cd1eSRichard Henderson gen_ldstub_asi(dc, &da, reg, addr); 4433cf07cd1eSRichard Henderson gen_store_gpr(dc, a->rd, reg); 4434cf07cd1eSRichard Henderson return advance_pc(dc); 4435cf07cd1eSRichard Henderson } 4436cf07cd1eSRichard Henderson 4437dca544b9SRichard Henderson static bool trans_SWAP(DisasContext *dc, arg_r_r_ri_asi *a) 4438dca544b9SRichard Henderson { 4439dca544b9SRichard Henderson TCGv addr, dst, src; 4440dca544b9SRichard Henderson DisasASI da; 4441dca544b9SRichard Henderson 4442dca544b9SRichard Henderson addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 4443dca544b9SRichard Henderson if (addr == NULL) { 4444dca544b9SRichard Henderson return false; 4445dca544b9SRichard Henderson } 4446dca544b9SRichard Henderson da = resolve_asi(dc, a->asi, MO_TEUL); 4447dca544b9SRichard Henderson 4448dca544b9SRichard Henderson dst = gen_dest_gpr(dc, a->rd); 4449dca544b9SRichard Henderson src = gen_load_gpr(dc, a->rd); 4450dca544b9SRichard Henderson gen_swap_asi(dc, &da, dst, src, addr); 4451dca544b9SRichard Henderson gen_store_gpr(dc, a->rd, dst); 4452dca544b9SRichard Henderson return advance_pc(dc); 4453dca544b9SRichard Henderson } 4454dca544b9SRichard Henderson 4455d0a11d25SRichard Henderson static bool do_casa(DisasContext *dc, arg_r_r_ri_asi *a, MemOp mop) 4456d0a11d25SRichard Henderson { 4457d0a11d25SRichard Henderson TCGv addr, o, n, c; 4458d0a11d25SRichard Henderson DisasASI da; 4459d0a11d25SRichard Henderson 4460d0a11d25SRichard Henderson addr = gen_ldst_addr(dc, a->rs1, true, 0); 4461d0a11d25SRichard Henderson if (addr == NULL) { 4462d0a11d25SRichard Henderson return false; 4463d0a11d25SRichard Henderson } 4464d0a11d25SRichard Henderson da = resolve_asi(dc, a->asi, mop); 4465d0a11d25SRichard Henderson 4466d0a11d25SRichard Henderson o = gen_dest_gpr(dc, a->rd); 4467d0a11d25SRichard Henderson n = gen_load_gpr(dc, a->rd); 4468d0a11d25SRichard Henderson c = gen_load_gpr(dc, a->rs2_or_imm); 4469d0a11d25SRichard Henderson gen_cas_asi(dc, &da, o, n, c, addr); 4470d0a11d25SRichard Henderson gen_store_gpr(dc, a->rd, o); 4471d0a11d25SRichard Henderson return advance_pc(dc); 4472d0a11d25SRichard Henderson } 4473d0a11d25SRichard Henderson 4474d0a11d25SRichard Henderson TRANS(CASA, CASA, do_casa, a, MO_TEUL) 4475d0a11d25SRichard Henderson TRANS(CASXA, 64, do_casa, a, MO_TEUQ) 4476d0a11d25SRichard Henderson 447706c060d9SRichard Henderson static bool do_ld_fpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp sz) 447806c060d9SRichard Henderson { 447906c060d9SRichard Henderson TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 448006c060d9SRichard Henderson DisasASI da; 448106c060d9SRichard Henderson 448206c060d9SRichard Henderson if (addr == NULL) { 448306c060d9SRichard Henderson return false; 448406c060d9SRichard Henderson } 448506c060d9SRichard Henderson if (gen_trap_ifnofpu(dc)) { 448606c060d9SRichard Henderson return true; 448706c060d9SRichard Henderson } 448806c060d9SRichard Henderson if (sz == MO_128 && gen_trap_float128(dc)) { 448906c060d9SRichard Henderson return true; 449006c060d9SRichard Henderson } 449106c060d9SRichard Henderson da = resolve_asi(dc, a->asi, MO_TE | sz); 4492287b1152SRichard Henderson gen_ldf_asi(dc, &da, sz, addr, a->rd); 449306c060d9SRichard Henderson gen_update_fprs_dirty(dc, a->rd); 449406c060d9SRichard Henderson return advance_pc(dc); 449506c060d9SRichard Henderson } 449606c060d9SRichard Henderson 449706c060d9SRichard Henderson TRANS(LDF, ALL, do_ld_fpr, a, MO_32) 449806c060d9SRichard Henderson TRANS(LDDF, ALL, do_ld_fpr, a, MO_64) 449906c060d9SRichard Henderson TRANS(LDQF, ALL, do_ld_fpr, a, MO_128) 450006c060d9SRichard Henderson 4501287b1152SRichard Henderson TRANS(LDFA, 64, do_ld_fpr, a, MO_32) 4502287b1152SRichard Henderson TRANS(LDDFA, 64, do_ld_fpr, a, MO_64) 4503287b1152SRichard Henderson TRANS(LDQFA, 64, do_ld_fpr, a, MO_128) 4504287b1152SRichard Henderson 450506c060d9SRichard Henderson static bool do_st_fpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp sz) 450606c060d9SRichard Henderson { 450706c060d9SRichard Henderson TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 450806c060d9SRichard Henderson DisasASI da; 450906c060d9SRichard Henderson 451006c060d9SRichard Henderson if (addr == NULL) { 451106c060d9SRichard Henderson return false; 451206c060d9SRichard Henderson } 451306c060d9SRichard Henderson if (gen_trap_ifnofpu(dc)) { 451406c060d9SRichard Henderson return true; 451506c060d9SRichard Henderson } 451606c060d9SRichard Henderson if (sz == MO_128 && gen_trap_float128(dc)) { 451706c060d9SRichard Henderson return true; 451806c060d9SRichard Henderson } 451906c060d9SRichard Henderson da = resolve_asi(dc, a->asi, MO_TE | sz); 4520287b1152SRichard Henderson gen_stf_asi(dc, &da, sz, addr, a->rd); 452106c060d9SRichard Henderson return advance_pc(dc); 452206c060d9SRichard Henderson } 452306c060d9SRichard Henderson 452406c060d9SRichard Henderson TRANS(STF, ALL, do_st_fpr, a, MO_32) 452506c060d9SRichard Henderson TRANS(STDF, ALL, do_st_fpr, a, MO_64) 452612d36294SRichard Henderson TRANS(STQF, 64, do_st_fpr, a, MO_128) 452706c060d9SRichard Henderson 4528287b1152SRichard Henderson TRANS(STFA, 64, do_st_fpr, a, MO_32) 4529287b1152SRichard Henderson TRANS(STDFA, 64, do_st_fpr, a, MO_64) 4530287b1152SRichard Henderson TRANS(STQFA, 64, do_st_fpr, a, MO_128) 4531287b1152SRichard Henderson 453206c060d9SRichard Henderson static bool trans_STDFQ(DisasContext *dc, arg_STDFQ *a) 453306c060d9SRichard Henderson { 4534*29b99802SRichard Henderson TCGv addr; 4535*29b99802SRichard Henderson 453606c060d9SRichard Henderson if (!avail_32(dc)) { 453706c060d9SRichard Henderson return false; 453806c060d9SRichard Henderson } 4539*29b99802SRichard Henderson addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 4540*29b99802SRichard Henderson if (addr == NULL) { 4541*29b99802SRichard Henderson return false; 4542*29b99802SRichard Henderson } 454306c060d9SRichard Henderson if (!supervisor(dc)) { 454406c060d9SRichard Henderson return raise_priv(dc); 454506c060d9SRichard Henderson } 4546*29b99802SRichard Henderson #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) 454706c060d9SRichard Henderson if (gen_trap_ifnofpu(dc)) { 454806c060d9SRichard Henderson return true; 454906c060d9SRichard Henderson } 4550*29b99802SRichard Henderson if (!dc->fsr_qne) { 455106c060d9SRichard Henderson gen_op_fpexception_im(dc, FSR_FTT_SEQ_ERROR); 455206c060d9SRichard Henderson return true; 455306c060d9SRichard Henderson } 455406c060d9SRichard Henderson 4555*29b99802SRichard Henderson /* Store the single element from the queue. */ 4556*29b99802SRichard Henderson TCGv_i64 fq = tcg_temp_new_i64(); 4557*29b99802SRichard Henderson tcg_gen_ld_i64(fq, tcg_env, offsetof(CPUSPARCState, fq.d)); 4558*29b99802SRichard Henderson tcg_gen_qemu_st_i64(fq, addr, dc->mem_idx, MO_TEUQ | MO_ALIGN_4); 4559*29b99802SRichard Henderson 4560*29b99802SRichard Henderson /* Mark the queue empty, transitioning to fp_execute state. */ 4561*29b99802SRichard Henderson tcg_gen_st_i32(tcg_constant_i32(0), tcg_env, 4562*29b99802SRichard Henderson offsetof(CPUSPARCState, fsr_qne)); 4563*29b99802SRichard Henderson dc->fsr_qne = 0; 4564*29b99802SRichard Henderson 4565*29b99802SRichard Henderson return advance_pc(dc); 4566*29b99802SRichard Henderson #else 4567*29b99802SRichard Henderson qemu_build_not_reached(); 4568*29b99802SRichard Henderson #endif 4569*29b99802SRichard Henderson } 4570*29b99802SRichard Henderson 4571d8c5b92fSRichard Henderson static bool trans_LDFSR(DisasContext *dc, arg_r_r_ri *a) 45723d3c0673SRichard Henderson { 45733590f01eSRichard Henderson TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 4574d8c5b92fSRichard Henderson TCGv_i32 tmp; 45753590f01eSRichard Henderson 45763d3c0673SRichard Henderson if (addr == NULL) { 45773d3c0673SRichard Henderson return false; 45783d3c0673SRichard Henderson } 45793d3c0673SRichard Henderson if (gen_trap_ifnofpu(dc)) { 45803d3c0673SRichard Henderson return true; 45813d3c0673SRichard Henderson } 4582d8c5b92fSRichard Henderson 4583d8c5b92fSRichard Henderson tmp = tcg_temp_new_i32(); 4584d8c5b92fSRichard Henderson tcg_gen_qemu_ld_i32(tmp, addr, dc->mem_idx, MO_TEUL | MO_ALIGN); 4585d8c5b92fSRichard Henderson 4586d8c5b92fSRichard Henderson tcg_gen_extract_i32(cpu_fcc[0], tmp, FSR_FCC0_SHIFT, 2); 4587d8c5b92fSRichard Henderson /* LDFSR does not change FCC[1-3]. */ 4588d8c5b92fSRichard Henderson 4589d8c5b92fSRichard Henderson gen_helper_set_fsr_nofcc_noftt(tcg_env, tmp); 45903d3c0673SRichard Henderson return advance_pc(dc); 45913d3c0673SRichard Henderson } 45923d3c0673SRichard Henderson 4593298c52f7SRichard Henderson static bool do_ldxfsr(DisasContext *dc, arg_r_r_ri *a, bool entire) 4594d8c5b92fSRichard Henderson { 4595d8c5b92fSRichard Henderson #ifdef TARGET_SPARC64 4596d8c5b92fSRichard Henderson TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 4597d8c5b92fSRichard Henderson TCGv_i64 t64; 4598d8c5b92fSRichard Henderson TCGv_i32 lo, hi; 4599d8c5b92fSRichard Henderson 4600d8c5b92fSRichard Henderson if (addr == NULL) { 4601d8c5b92fSRichard Henderson return false; 4602d8c5b92fSRichard Henderson } 4603d8c5b92fSRichard Henderson if (gen_trap_ifnofpu(dc)) { 4604d8c5b92fSRichard Henderson return true; 4605d8c5b92fSRichard Henderson } 4606d8c5b92fSRichard Henderson 4607d8c5b92fSRichard Henderson t64 = tcg_temp_new_i64(); 4608d8c5b92fSRichard Henderson tcg_gen_qemu_ld_i64(t64, addr, dc->mem_idx, MO_TEUQ | MO_ALIGN); 4609d8c5b92fSRichard Henderson 4610d8c5b92fSRichard Henderson lo = tcg_temp_new_i32(); 4611d8c5b92fSRichard Henderson hi = cpu_fcc[3]; 4612d8c5b92fSRichard Henderson tcg_gen_extr_i64_i32(lo, hi, t64); 4613d8c5b92fSRichard Henderson tcg_gen_extract_i32(cpu_fcc[0], lo, FSR_FCC0_SHIFT, 2); 4614d8c5b92fSRichard Henderson tcg_gen_extract_i32(cpu_fcc[1], hi, FSR_FCC1_SHIFT - 32, 2); 4615d8c5b92fSRichard Henderson tcg_gen_extract_i32(cpu_fcc[2], hi, FSR_FCC2_SHIFT - 32, 2); 4616d8c5b92fSRichard Henderson tcg_gen_extract_i32(cpu_fcc[3], hi, FSR_FCC3_SHIFT - 32, 2); 4617d8c5b92fSRichard Henderson 4618298c52f7SRichard Henderson if (entire) { 4619298c52f7SRichard Henderson gen_helper_set_fsr_nofcc(tcg_env, lo); 4620298c52f7SRichard Henderson } else { 4621d8c5b92fSRichard Henderson gen_helper_set_fsr_nofcc_noftt(tcg_env, lo); 4622298c52f7SRichard Henderson } 4623d8c5b92fSRichard Henderson return advance_pc(dc); 4624d8c5b92fSRichard Henderson #else 4625d8c5b92fSRichard Henderson return false; 4626d8c5b92fSRichard Henderson #endif 4627d8c5b92fSRichard Henderson } 46283d3c0673SRichard Henderson 4629298c52f7SRichard Henderson TRANS(LDXFSR, 64, do_ldxfsr, a, false) 4630298c52f7SRichard Henderson TRANS(LDXEFSR, VIS3B, do_ldxfsr, a, true) 4631298c52f7SRichard Henderson 46323d3c0673SRichard Henderson static bool do_stfsr(DisasContext *dc, arg_r_r_ri *a, MemOp mop) 46333d3c0673SRichard Henderson { 46343d3c0673SRichard Henderson TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 46351ccd6e13SRichard Henderson TCGv fsr; 46361ccd6e13SRichard Henderson 46373d3c0673SRichard Henderson if (addr == NULL) { 46383d3c0673SRichard Henderson return false; 46393d3c0673SRichard Henderson } 46403d3c0673SRichard Henderson if (gen_trap_ifnofpu(dc)) { 46413d3c0673SRichard Henderson return true; 46423d3c0673SRichard Henderson } 46431ccd6e13SRichard Henderson 46441ccd6e13SRichard Henderson fsr = tcg_temp_new(); 46451ccd6e13SRichard Henderson gen_helper_get_fsr(fsr, tcg_env); 46461ccd6e13SRichard Henderson tcg_gen_qemu_st_tl(fsr, addr, dc->mem_idx, mop | MO_ALIGN); 46473d3c0673SRichard Henderson return advance_pc(dc); 46483d3c0673SRichard Henderson } 46493d3c0673SRichard Henderson 46503d3c0673SRichard Henderson TRANS(STFSR, ALL, do_stfsr, a, MO_TEUL) 46513d3c0673SRichard Henderson TRANS(STXFSR, 64, do_stfsr, a, MO_TEUQ) 46523d3c0673SRichard Henderson 46531210a036SRichard Henderson static bool do_fc(DisasContext *dc, int rd, int32_t c) 46543a38260eSRichard Henderson { 46553a38260eSRichard Henderson if (gen_trap_ifnofpu(dc)) { 46563a38260eSRichard Henderson return true; 46573a38260eSRichard Henderson } 46581210a036SRichard Henderson gen_store_fpr_F(dc, rd, tcg_constant_i32(c)); 46593a38260eSRichard Henderson return advance_pc(dc); 46603a38260eSRichard Henderson } 46613a38260eSRichard Henderson 46623a38260eSRichard Henderson TRANS(FZEROs, VIS1, do_fc, a->rd, 0) 46631210a036SRichard Henderson TRANS(FONEs, VIS1, do_fc, a->rd, -1) 46643a38260eSRichard Henderson 46653a38260eSRichard Henderson static bool do_dc(DisasContext *dc, int rd, int64_t c) 46663a38260eSRichard Henderson { 46673a38260eSRichard Henderson if (gen_trap_ifnofpu(dc)) { 46683a38260eSRichard Henderson return true; 46693a38260eSRichard Henderson } 46701210a036SRichard Henderson gen_store_fpr_D(dc, rd, tcg_constant_i64(c)); 46713a38260eSRichard Henderson return advance_pc(dc); 46723a38260eSRichard Henderson } 46733a38260eSRichard Henderson 46743a38260eSRichard Henderson TRANS(FZEROd, VIS1, do_dc, a->rd, 0) 46753a38260eSRichard Henderson TRANS(FONEd, VIS1, do_dc, a->rd, -1) 46763a38260eSRichard Henderson 4677baf3dbf2SRichard Henderson static bool do_ff(DisasContext *dc, arg_r_r *a, 4678baf3dbf2SRichard Henderson void (*func)(TCGv_i32, TCGv_i32)) 4679baf3dbf2SRichard Henderson { 4680baf3dbf2SRichard Henderson TCGv_i32 tmp; 4681baf3dbf2SRichard Henderson 4682baf3dbf2SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4683baf3dbf2SRichard Henderson return true; 4684baf3dbf2SRichard Henderson } 4685baf3dbf2SRichard Henderson 4686baf3dbf2SRichard Henderson tmp = gen_load_fpr_F(dc, a->rs); 4687baf3dbf2SRichard Henderson func(tmp, tmp); 4688baf3dbf2SRichard Henderson gen_store_fpr_F(dc, a->rd, tmp); 4689baf3dbf2SRichard Henderson return advance_pc(dc); 4690baf3dbf2SRichard Henderson } 4691baf3dbf2SRichard Henderson 4692baf3dbf2SRichard Henderson TRANS(FMOVs, ALL, do_ff, a, gen_op_fmovs) 4693baf3dbf2SRichard Henderson TRANS(FNEGs, ALL, do_ff, a, gen_op_fnegs) 4694baf3dbf2SRichard Henderson TRANS(FABSs, ALL, do_ff, a, gen_op_fabss) 4695baf3dbf2SRichard Henderson TRANS(FSRCs, VIS1, do_ff, a, tcg_gen_mov_i32) 4696baf3dbf2SRichard Henderson TRANS(FNOTs, VIS1, do_ff, a, tcg_gen_not_i32) 4697baf3dbf2SRichard Henderson 46982f722641SRichard Henderson static bool do_fd(DisasContext *dc, arg_r_r *a, 46992f722641SRichard Henderson void (*func)(TCGv_i32, TCGv_i64)) 47002f722641SRichard Henderson { 47012f722641SRichard Henderson TCGv_i32 dst; 47022f722641SRichard Henderson TCGv_i64 src; 47032f722641SRichard Henderson 47042f722641SRichard Henderson if (gen_trap_ifnofpu(dc)) { 47052f722641SRichard Henderson return true; 47062f722641SRichard Henderson } 47072f722641SRichard Henderson 4708388a6465SRichard Henderson dst = tcg_temp_new_i32(); 47092f722641SRichard Henderson src = gen_load_fpr_D(dc, a->rs); 47102f722641SRichard Henderson func(dst, src); 47112f722641SRichard Henderson gen_store_fpr_F(dc, a->rd, dst); 47122f722641SRichard Henderson return advance_pc(dc); 47132f722641SRichard Henderson } 47142f722641SRichard Henderson 47152f722641SRichard Henderson TRANS(FPACK16, VIS1, do_fd, a, gen_op_fpack16) 47162f722641SRichard Henderson TRANS(FPACKFIX, VIS1, do_fd, a, gen_op_fpackfix) 47172f722641SRichard Henderson 4718119cb94fSRichard Henderson static bool do_env_ff(DisasContext *dc, arg_r_r *a, 4719119cb94fSRichard Henderson void (*func)(TCGv_i32, TCGv_env, TCGv_i32)) 4720119cb94fSRichard Henderson { 4721119cb94fSRichard Henderson TCGv_i32 tmp; 4722119cb94fSRichard Henderson 4723119cb94fSRichard Henderson if (gen_trap_ifnofpu(dc)) { 4724119cb94fSRichard Henderson return true; 4725119cb94fSRichard Henderson } 4726119cb94fSRichard Henderson 4727119cb94fSRichard Henderson tmp = gen_load_fpr_F(dc, a->rs); 4728119cb94fSRichard Henderson func(tmp, tcg_env, tmp); 4729119cb94fSRichard Henderson gen_store_fpr_F(dc, a->rd, tmp); 4730119cb94fSRichard Henderson return advance_pc(dc); 4731119cb94fSRichard Henderson } 4732119cb94fSRichard Henderson 4733119cb94fSRichard Henderson TRANS(FSQRTs, ALL, do_env_ff, a, gen_helper_fsqrts) 4734119cb94fSRichard Henderson TRANS(FiTOs, ALL, do_env_ff, a, gen_helper_fitos) 4735119cb94fSRichard Henderson TRANS(FsTOi, ALL, do_env_ff, a, gen_helper_fstoi) 4736119cb94fSRichard Henderson 47378c94bcd8SRichard Henderson static bool do_env_fd(DisasContext *dc, arg_r_r *a, 47388c94bcd8SRichard Henderson void (*func)(TCGv_i32, TCGv_env, TCGv_i64)) 47398c94bcd8SRichard Henderson { 47408c94bcd8SRichard Henderson TCGv_i32 dst; 47418c94bcd8SRichard Henderson TCGv_i64 src; 47428c94bcd8SRichard Henderson 47438c94bcd8SRichard Henderson if (gen_trap_ifnofpu(dc)) { 47448c94bcd8SRichard Henderson return true; 47458c94bcd8SRichard Henderson } 47468c94bcd8SRichard Henderson 4747388a6465SRichard Henderson dst = tcg_temp_new_i32(); 47488c94bcd8SRichard Henderson src = gen_load_fpr_D(dc, a->rs); 47498c94bcd8SRichard Henderson func(dst, tcg_env, src); 47508c94bcd8SRichard Henderson gen_store_fpr_F(dc, a->rd, dst); 47518c94bcd8SRichard Henderson return advance_pc(dc); 47528c94bcd8SRichard Henderson } 47538c94bcd8SRichard Henderson 47548c94bcd8SRichard Henderson TRANS(FdTOs, ALL, do_env_fd, a, gen_helper_fdtos) 47558c94bcd8SRichard Henderson TRANS(FdTOi, ALL, do_env_fd, a, gen_helper_fdtoi) 47568c94bcd8SRichard Henderson TRANS(FxTOs, 64, do_env_fd, a, gen_helper_fxtos) 47578c94bcd8SRichard Henderson 4758c6d83e4fSRichard Henderson static bool do_dd(DisasContext *dc, arg_r_r *a, 4759c6d83e4fSRichard Henderson void (*func)(TCGv_i64, TCGv_i64)) 4760c6d83e4fSRichard Henderson { 4761c6d83e4fSRichard Henderson TCGv_i64 dst, src; 4762c6d83e4fSRichard Henderson 4763c6d83e4fSRichard Henderson if (gen_trap_ifnofpu(dc)) { 4764c6d83e4fSRichard Henderson return true; 4765c6d83e4fSRichard Henderson } 4766c6d83e4fSRichard Henderson 476752f46d46SRichard Henderson dst = tcg_temp_new_i64(); 4768c6d83e4fSRichard Henderson src = gen_load_fpr_D(dc, a->rs); 4769c6d83e4fSRichard Henderson func(dst, src); 4770c6d83e4fSRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 4771c6d83e4fSRichard Henderson return advance_pc(dc); 4772c6d83e4fSRichard Henderson } 4773c6d83e4fSRichard Henderson 4774c6d83e4fSRichard Henderson TRANS(FMOVd, 64, do_dd, a, gen_op_fmovd) 4775c6d83e4fSRichard Henderson TRANS(FNEGd, 64, do_dd, a, gen_op_fnegd) 4776c6d83e4fSRichard Henderson TRANS(FABSd, 64, do_dd, a, gen_op_fabsd) 4777c6d83e4fSRichard Henderson TRANS(FSRCd, VIS1, do_dd, a, tcg_gen_mov_i64) 4778c6d83e4fSRichard Henderson TRANS(FNOTd, VIS1, do_dd, a, tcg_gen_not_i64) 4779c6d83e4fSRichard Henderson 47808aa418b3SRichard Henderson static bool do_env_dd(DisasContext *dc, arg_r_r *a, 47818aa418b3SRichard Henderson void (*func)(TCGv_i64, TCGv_env, TCGv_i64)) 47828aa418b3SRichard Henderson { 47838aa418b3SRichard Henderson TCGv_i64 dst, src; 47848aa418b3SRichard Henderson 47858aa418b3SRichard Henderson if (gen_trap_ifnofpu(dc)) { 47868aa418b3SRichard Henderson return true; 47878aa418b3SRichard Henderson } 47888aa418b3SRichard Henderson 478952f46d46SRichard Henderson dst = tcg_temp_new_i64(); 47908aa418b3SRichard Henderson src = gen_load_fpr_D(dc, a->rs); 47918aa418b3SRichard Henderson func(dst, tcg_env, src); 47928aa418b3SRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 47938aa418b3SRichard Henderson return advance_pc(dc); 47948aa418b3SRichard Henderson } 47958aa418b3SRichard Henderson 47968aa418b3SRichard Henderson TRANS(FSQRTd, ALL, do_env_dd, a, gen_helper_fsqrtd) 47978aa418b3SRichard Henderson TRANS(FxTOd, 64, do_env_dd, a, gen_helper_fxtod) 47988aa418b3SRichard Henderson TRANS(FdTOx, 64, do_env_dd, a, gen_helper_fdtox) 47998aa418b3SRichard Henderson 48007b616f36SRichard Henderson static bool do_df(DisasContext *dc, arg_r_r *a, 48017b616f36SRichard Henderson void (*func)(TCGv_i64, TCGv_i32)) 48027b616f36SRichard Henderson { 48037b616f36SRichard Henderson TCGv_i64 dst; 48047b616f36SRichard Henderson TCGv_i32 src; 48057b616f36SRichard Henderson 48067b616f36SRichard Henderson if (gen_trap_ifnofpu(dc)) { 48077b616f36SRichard Henderson return true; 48087b616f36SRichard Henderson } 48097b616f36SRichard Henderson 48107b616f36SRichard Henderson dst = tcg_temp_new_i64(); 48117b616f36SRichard Henderson src = gen_load_fpr_F(dc, a->rs); 48127b616f36SRichard Henderson func(dst, src); 48137b616f36SRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 48147b616f36SRichard Henderson return advance_pc(dc); 48157b616f36SRichard Henderson } 48167b616f36SRichard Henderson 48177b616f36SRichard Henderson TRANS(FEXPAND, VIS1, do_df, a, gen_helper_fexpand) 48187b616f36SRichard Henderson 4819199d43efSRichard Henderson static bool do_env_df(DisasContext *dc, arg_r_r *a, 4820199d43efSRichard Henderson void (*func)(TCGv_i64, TCGv_env, TCGv_i32)) 4821199d43efSRichard Henderson { 4822199d43efSRichard Henderson TCGv_i64 dst; 4823199d43efSRichard Henderson TCGv_i32 src; 4824199d43efSRichard Henderson 4825199d43efSRichard Henderson if (gen_trap_ifnofpu(dc)) { 4826199d43efSRichard Henderson return true; 4827199d43efSRichard Henderson } 4828199d43efSRichard Henderson 482952f46d46SRichard Henderson dst = tcg_temp_new_i64(); 4830199d43efSRichard Henderson src = gen_load_fpr_F(dc, a->rs); 4831199d43efSRichard Henderson func(dst, tcg_env, src); 4832199d43efSRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 4833199d43efSRichard Henderson return advance_pc(dc); 4834199d43efSRichard Henderson } 4835199d43efSRichard Henderson 4836199d43efSRichard Henderson TRANS(FiTOd, ALL, do_env_df, a, gen_helper_fitod) 4837199d43efSRichard Henderson TRANS(FsTOd, ALL, do_env_df, a, gen_helper_fstod) 4838199d43efSRichard Henderson TRANS(FsTOx, 64, do_env_df, a, gen_helper_fstox) 4839199d43efSRichard Henderson 4840daf457d4SRichard Henderson static bool do_qq(DisasContext *dc, arg_r_r *a, 4841daf457d4SRichard Henderson void (*func)(TCGv_i128, TCGv_i128)) 4842f4e18df5SRichard Henderson { 484333ec4245SRichard Henderson TCGv_i128 t; 4844f4e18df5SRichard Henderson 4845f4e18df5SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4846f4e18df5SRichard Henderson return true; 4847f4e18df5SRichard Henderson } 4848f4e18df5SRichard Henderson if (gen_trap_float128(dc)) { 4849f4e18df5SRichard Henderson return true; 4850f4e18df5SRichard Henderson } 4851f4e18df5SRichard Henderson 4852f4e18df5SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 485333ec4245SRichard Henderson t = gen_load_fpr_Q(dc, a->rs); 4854daf457d4SRichard Henderson func(t, t); 485533ec4245SRichard Henderson gen_store_fpr_Q(dc, a->rd, t); 4856f4e18df5SRichard Henderson return advance_pc(dc); 4857f4e18df5SRichard Henderson } 4858f4e18df5SRichard Henderson 4859daf457d4SRichard Henderson TRANS(FMOVq, 64, do_qq, a, tcg_gen_mov_i128) 4860daf457d4SRichard Henderson TRANS(FNEGq, 64, do_qq, a, gen_op_fnegq) 4861daf457d4SRichard Henderson TRANS(FABSq, 64, do_qq, a, gen_op_fabsq) 4862f4e18df5SRichard Henderson 4863c995216bSRichard Henderson static bool do_env_qq(DisasContext *dc, arg_r_r *a, 4864e41716beSRichard Henderson void (*func)(TCGv_i128, TCGv_env, TCGv_i128)) 4865c995216bSRichard Henderson { 4866e41716beSRichard Henderson TCGv_i128 t; 4867e41716beSRichard Henderson 4868c995216bSRichard Henderson if (gen_trap_ifnofpu(dc)) { 4869c995216bSRichard Henderson return true; 4870c995216bSRichard Henderson } 4871c995216bSRichard Henderson if (gen_trap_float128(dc)) { 4872c995216bSRichard Henderson return true; 4873c995216bSRichard Henderson } 4874c995216bSRichard Henderson 4875e41716beSRichard Henderson t = gen_load_fpr_Q(dc, a->rs); 4876e41716beSRichard Henderson func(t, tcg_env, t); 4877e41716beSRichard Henderson gen_store_fpr_Q(dc, a->rd, t); 4878c995216bSRichard Henderson return advance_pc(dc); 4879c995216bSRichard Henderson } 4880c995216bSRichard Henderson 4881c995216bSRichard Henderson TRANS(FSQRTq, ALL, do_env_qq, a, gen_helper_fsqrtq) 4882c995216bSRichard Henderson 4883bd9c5c42SRichard Henderson static bool do_env_fq(DisasContext *dc, arg_r_r *a, 4884d81e3efeSRichard Henderson void (*func)(TCGv_i32, TCGv_env, TCGv_i128)) 4885bd9c5c42SRichard Henderson { 4886d81e3efeSRichard Henderson TCGv_i128 src; 4887bd9c5c42SRichard Henderson TCGv_i32 dst; 4888bd9c5c42SRichard Henderson 4889bd9c5c42SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4890bd9c5c42SRichard Henderson return true; 4891bd9c5c42SRichard Henderson } 4892bd9c5c42SRichard Henderson if (gen_trap_float128(dc)) { 4893bd9c5c42SRichard Henderson return true; 4894bd9c5c42SRichard Henderson } 4895bd9c5c42SRichard Henderson 4896d81e3efeSRichard Henderson src = gen_load_fpr_Q(dc, a->rs); 4897388a6465SRichard Henderson dst = tcg_temp_new_i32(); 4898d81e3efeSRichard Henderson func(dst, tcg_env, src); 4899bd9c5c42SRichard Henderson gen_store_fpr_F(dc, a->rd, dst); 4900bd9c5c42SRichard Henderson return advance_pc(dc); 4901bd9c5c42SRichard Henderson } 4902bd9c5c42SRichard Henderson 4903bd9c5c42SRichard Henderson TRANS(FqTOs, ALL, do_env_fq, a, gen_helper_fqtos) 4904bd9c5c42SRichard Henderson TRANS(FqTOi, ALL, do_env_fq, a, gen_helper_fqtoi) 4905bd9c5c42SRichard Henderson 49061617586fSRichard Henderson static bool do_env_dq(DisasContext *dc, arg_r_r *a, 490725a5769eSRichard Henderson void (*func)(TCGv_i64, TCGv_env, TCGv_i128)) 49081617586fSRichard Henderson { 490925a5769eSRichard Henderson TCGv_i128 src; 49101617586fSRichard Henderson TCGv_i64 dst; 49111617586fSRichard Henderson 49121617586fSRichard Henderson if (gen_trap_ifnofpu(dc)) { 49131617586fSRichard Henderson return true; 49141617586fSRichard Henderson } 49151617586fSRichard Henderson if (gen_trap_float128(dc)) { 49161617586fSRichard Henderson return true; 49171617586fSRichard Henderson } 49181617586fSRichard Henderson 491925a5769eSRichard Henderson src = gen_load_fpr_Q(dc, a->rs); 492052f46d46SRichard Henderson dst = tcg_temp_new_i64(); 492125a5769eSRichard Henderson func(dst, tcg_env, src); 49221617586fSRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 49231617586fSRichard Henderson return advance_pc(dc); 49241617586fSRichard Henderson } 49251617586fSRichard Henderson 49261617586fSRichard Henderson TRANS(FqTOd, ALL, do_env_dq, a, gen_helper_fqtod) 49271617586fSRichard Henderson TRANS(FqTOx, 64, do_env_dq, a, gen_helper_fqtox) 49281617586fSRichard Henderson 492913ebcc77SRichard Henderson static bool do_env_qf(DisasContext *dc, arg_r_r *a, 49300b2a61ccSRichard Henderson void (*func)(TCGv_i128, TCGv_env, TCGv_i32)) 493113ebcc77SRichard Henderson { 493213ebcc77SRichard Henderson TCGv_i32 src; 49330b2a61ccSRichard Henderson TCGv_i128 dst; 493413ebcc77SRichard Henderson 493513ebcc77SRichard Henderson if (gen_trap_ifnofpu(dc)) { 493613ebcc77SRichard Henderson return true; 493713ebcc77SRichard Henderson } 493813ebcc77SRichard Henderson if (gen_trap_float128(dc)) { 493913ebcc77SRichard Henderson return true; 494013ebcc77SRichard Henderson } 494113ebcc77SRichard Henderson 494213ebcc77SRichard Henderson src = gen_load_fpr_F(dc, a->rs); 49430b2a61ccSRichard Henderson dst = tcg_temp_new_i128(); 49440b2a61ccSRichard Henderson func(dst, tcg_env, src); 49450b2a61ccSRichard Henderson gen_store_fpr_Q(dc, a->rd, dst); 494613ebcc77SRichard Henderson return advance_pc(dc); 494713ebcc77SRichard Henderson } 494813ebcc77SRichard Henderson 494913ebcc77SRichard Henderson TRANS(FiTOq, ALL, do_env_qf, a, gen_helper_fitoq) 495013ebcc77SRichard Henderson TRANS(FsTOq, ALL, do_env_qf, a, gen_helper_fstoq) 495113ebcc77SRichard Henderson 49527b8e3e1aSRichard Henderson static bool do_env_qd(DisasContext *dc, arg_r_r *a, 4953fdc50716SRichard Henderson void (*func)(TCGv_i128, TCGv_env, TCGv_i64)) 49547b8e3e1aSRichard Henderson { 49557b8e3e1aSRichard Henderson TCGv_i64 src; 4956fdc50716SRichard Henderson TCGv_i128 dst; 49577b8e3e1aSRichard Henderson 49587b8e3e1aSRichard Henderson if (gen_trap_ifnofpu(dc)) { 49597b8e3e1aSRichard Henderson return true; 49607b8e3e1aSRichard Henderson } 49617b8e3e1aSRichard Henderson if (gen_trap_float128(dc)) { 49627b8e3e1aSRichard Henderson return true; 49637b8e3e1aSRichard Henderson } 49647b8e3e1aSRichard Henderson 49657b8e3e1aSRichard Henderson src = gen_load_fpr_D(dc, a->rs); 4966fdc50716SRichard Henderson dst = tcg_temp_new_i128(); 4967fdc50716SRichard Henderson func(dst, tcg_env, src); 4968fdc50716SRichard Henderson gen_store_fpr_Q(dc, a->rd, dst); 49697b8e3e1aSRichard Henderson return advance_pc(dc); 49707b8e3e1aSRichard Henderson } 49717b8e3e1aSRichard Henderson 49727b8e3e1aSRichard Henderson TRANS(FdTOq, ALL, do_env_qd, a, gen_helper_fdtoq) 49737b8e3e1aSRichard Henderson TRANS(FxTOq, 64, do_env_qd, a, gen_helper_fxtoq) 49747b8e3e1aSRichard Henderson 49757f10b52fSRichard Henderson static bool do_fff(DisasContext *dc, arg_r_r_r *a, 49767f10b52fSRichard Henderson void (*func)(TCGv_i32, TCGv_i32, TCGv_i32)) 49777f10b52fSRichard Henderson { 49787f10b52fSRichard Henderson TCGv_i32 src1, src2; 49797f10b52fSRichard Henderson 49807f10b52fSRichard Henderson if (gen_trap_ifnofpu(dc)) { 49817f10b52fSRichard Henderson return true; 49827f10b52fSRichard Henderson } 49837f10b52fSRichard Henderson 49847f10b52fSRichard Henderson src1 = gen_load_fpr_F(dc, a->rs1); 49857f10b52fSRichard Henderson src2 = gen_load_fpr_F(dc, a->rs2); 49867f10b52fSRichard Henderson func(src1, src1, src2); 49877f10b52fSRichard Henderson gen_store_fpr_F(dc, a->rd, src1); 49887f10b52fSRichard Henderson return advance_pc(dc); 49897f10b52fSRichard Henderson } 49907f10b52fSRichard Henderson 49917f10b52fSRichard Henderson TRANS(FPADD16s, VIS1, do_fff, a, tcg_gen_vec_add16_i32) 49927f10b52fSRichard Henderson TRANS(FPADD32s, VIS1, do_fff, a, tcg_gen_add_i32) 49937f10b52fSRichard Henderson TRANS(FPSUB16s, VIS1, do_fff, a, tcg_gen_vec_sub16_i32) 49947f10b52fSRichard Henderson TRANS(FPSUB32s, VIS1, do_fff, a, tcg_gen_sub_i32) 49957f10b52fSRichard Henderson TRANS(FNORs, VIS1, do_fff, a, tcg_gen_nor_i32) 49967f10b52fSRichard Henderson TRANS(FANDNOTs, VIS1, do_fff, a, tcg_gen_andc_i32) 49977f10b52fSRichard Henderson TRANS(FXORs, VIS1, do_fff, a, tcg_gen_xor_i32) 49987f10b52fSRichard Henderson TRANS(FNANDs, VIS1, do_fff, a, tcg_gen_nand_i32) 49997f10b52fSRichard Henderson TRANS(FANDs, VIS1, do_fff, a, tcg_gen_and_i32) 50007f10b52fSRichard Henderson TRANS(FXNORs, VIS1, do_fff, a, tcg_gen_eqv_i32) 50017f10b52fSRichard Henderson TRANS(FORNOTs, VIS1, do_fff, a, tcg_gen_orc_i32) 50027f10b52fSRichard Henderson TRANS(FORs, VIS1, do_fff, a, tcg_gen_or_i32) 50037f10b52fSRichard Henderson 50043d50b728SRichard Henderson TRANS(FHADDs, VIS3, do_fff, a, gen_op_fhadds) 50053d50b728SRichard Henderson TRANS(FHSUBs, VIS3, do_fff, a, gen_op_fhsubs) 50063d50b728SRichard Henderson TRANS(FNHADDs, VIS3, do_fff, a, gen_op_fnhadds) 50073d50b728SRichard Henderson 50080d1d3aafSRichard Henderson TRANS(FPADDS16s, VIS3, do_fff, a, gen_op_fpadds16s) 50090d1d3aafSRichard Henderson TRANS(FPSUBS16s, VIS3, do_fff, a, gen_op_fpsubs16s) 50100d1d3aafSRichard Henderson TRANS(FPADDS32s, VIS3, do_fff, a, gen_op_fpadds32s) 50110d1d3aafSRichard Henderson TRANS(FPSUBS32s, VIS3, do_fff, a, gen_op_fpsubs32s) 50120d1d3aafSRichard Henderson 5013c1514961SRichard Henderson static bool do_env_fff(DisasContext *dc, arg_r_r_r *a, 5014c1514961SRichard Henderson void (*func)(TCGv_i32, TCGv_env, TCGv_i32, TCGv_i32)) 5015c1514961SRichard Henderson { 5016c1514961SRichard Henderson TCGv_i32 src1, src2; 5017c1514961SRichard Henderson 5018c1514961SRichard Henderson if (gen_trap_ifnofpu(dc)) { 5019c1514961SRichard Henderson return true; 5020c1514961SRichard Henderson } 5021c1514961SRichard Henderson 5022c1514961SRichard Henderson src1 = gen_load_fpr_F(dc, a->rs1); 5023c1514961SRichard Henderson src2 = gen_load_fpr_F(dc, a->rs2); 5024c1514961SRichard Henderson func(src1, tcg_env, src1, src2); 5025c1514961SRichard Henderson gen_store_fpr_F(dc, a->rd, src1); 5026c1514961SRichard Henderson return advance_pc(dc); 5027c1514961SRichard Henderson } 5028c1514961SRichard Henderson 5029c1514961SRichard Henderson TRANS(FADDs, ALL, do_env_fff, a, gen_helper_fadds) 5030c1514961SRichard Henderson TRANS(FSUBs, ALL, do_env_fff, a, gen_helper_fsubs) 5031c1514961SRichard Henderson TRANS(FMULs, ALL, do_env_fff, a, gen_helper_fmuls) 5032c1514961SRichard Henderson TRANS(FDIVs, ALL, do_env_fff, a, gen_helper_fdivs) 50333d50b728SRichard Henderson TRANS(FNADDs, VIS3, do_env_fff, a, gen_helper_fnadds) 50343d50b728SRichard Henderson TRANS(FNMULs, VIS3, do_env_fff, a, gen_helper_fnmuls) 5035c1514961SRichard Henderson 5036a859602cSRichard Henderson static bool do_dff(DisasContext *dc, arg_r_r_r *a, 5037a859602cSRichard Henderson void (*func)(TCGv_i64, TCGv_i32, TCGv_i32)) 5038a859602cSRichard Henderson { 5039a859602cSRichard Henderson TCGv_i64 dst; 5040a859602cSRichard Henderson TCGv_i32 src1, src2; 5041a859602cSRichard Henderson 5042a859602cSRichard Henderson if (gen_trap_ifnofpu(dc)) { 5043a859602cSRichard Henderson return true; 5044a859602cSRichard Henderson } 5045a859602cSRichard Henderson 504652f46d46SRichard Henderson dst = tcg_temp_new_i64(); 5047a859602cSRichard Henderson src1 = gen_load_fpr_F(dc, a->rs1); 5048a859602cSRichard Henderson src2 = gen_load_fpr_F(dc, a->rs2); 5049a859602cSRichard Henderson func(dst, src1, src2); 5050a859602cSRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 5051a859602cSRichard Henderson return advance_pc(dc); 5052a859602cSRichard Henderson } 5053a859602cSRichard Henderson 5054a859602cSRichard Henderson TRANS(FMUL8x16AU, VIS1, do_dff, a, gen_op_fmul8x16au) 5055a859602cSRichard Henderson TRANS(FMUL8x16AL, VIS1, do_dff, a, gen_op_fmul8x16al) 5056be8998e0SRichard Henderson TRANS(FMULD8SUx16, VIS1, do_dff, a, gen_op_fmuld8sux16) 5057be8998e0SRichard Henderson TRANS(FMULD8ULx16, VIS1, do_dff, a, gen_op_fmuld8ulx16) 5058d3ef26afSRichard Henderson TRANS(FPMERGE, VIS1, do_dff, a, gen_helper_fpmerge) 5059a859602cSRichard Henderson 50609157dcccSRichard Henderson static bool do_dfd(DisasContext *dc, arg_r_r_r *a, 50619157dcccSRichard Henderson void (*func)(TCGv_i64, TCGv_i32, TCGv_i64)) 50629157dcccSRichard Henderson { 50639157dcccSRichard Henderson TCGv_i64 dst, src2; 50649157dcccSRichard Henderson TCGv_i32 src1; 50659157dcccSRichard Henderson 50669157dcccSRichard Henderson if (gen_trap_ifnofpu(dc)) { 50679157dcccSRichard Henderson return true; 50689157dcccSRichard Henderson } 50699157dcccSRichard Henderson 507052f46d46SRichard Henderson dst = tcg_temp_new_i64(); 50719157dcccSRichard Henderson src1 = gen_load_fpr_F(dc, a->rs1); 50729157dcccSRichard Henderson src2 = gen_load_fpr_D(dc, a->rs2); 50739157dcccSRichard Henderson func(dst, src1, src2); 50749157dcccSRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 50759157dcccSRichard Henderson return advance_pc(dc); 50769157dcccSRichard Henderson } 50779157dcccSRichard Henderson 50789157dcccSRichard Henderson TRANS(FMUL8x16, VIS1, do_dfd, a, gen_helper_fmul8x16) 50799157dcccSRichard Henderson 508028c131a3SRichard Henderson static bool do_gvec_ddd(DisasContext *dc, arg_r_r_r *a, MemOp vece, 508128c131a3SRichard Henderson void (*func)(unsigned, uint32_t, uint32_t, 508228c131a3SRichard Henderson uint32_t, uint32_t, uint32_t)) 508328c131a3SRichard Henderson { 508428c131a3SRichard Henderson if (gen_trap_ifnofpu(dc)) { 508528c131a3SRichard Henderson return true; 508628c131a3SRichard Henderson } 508728c131a3SRichard Henderson 508828c131a3SRichard Henderson func(vece, gen_offset_fpr_D(a->rd), gen_offset_fpr_D(a->rs1), 508928c131a3SRichard Henderson gen_offset_fpr_D(a->rs2), 8, 8); 509028c131a3SRichard Henderson return advance_pc(dc); 509128c131a3SRichard Henderson } 509228c131a3SRichard Henderson 5093b99c1bbdSRichard Henderson TRANS(FPADD8, VIS4, do_gvec_ddd, a, MO_8, tcg_gen_gvec_add) 509428c131a3SRichard Henderson TRANS(FPADD16, VIS1, do_gvec_ddd, a, MO_16, tcg_gen_gvec_add) 509528c131a3SRichard Henderson TRANS(FPADD32, VIS1, do_gvec_ddd, a, MO_32, tcg_gen_gvec_add) 5096b99c1bbdSRichard Henderson 5097b99c1bbdSRichard Henderson TRANS(FPSUB8, VIS4, do_gvec_ddd, a, MO_8, tcg_gen_gvec_sub) 509828c131a3SRichard Henderson TRANS(FPSUB16, VIS1, do_gvec_ddd, a, MO_16, tcg_gen_gvec_sub) 509928c131a3SRichard Henderson TRANS(FPSUB32, VIS1, do_gvec_ddd, a, MO_32, tcg_gen_gvec_sub) 5100b99c1bbdSRichard Henderson 51017837185eSRichard Henderson TRANS(FCHKSM16, VIS3, do_gvec_ddd, a, MO_16, gen_op_fchksm16) 5102d6ff1ccbSRichard Henderson TRANS(FMEAN16, VIS3, do_gvec_ddd, a, MO_16, gen_op_fmean16) 510328c131a3SRichard Henderson 5104b99c1bbdSRichard Henderson TRANS(FPADDS8, VIS4, do_gvec_ddd, a, MO_8, tcg_gen_gvec_ssadd) 51050d1d3aafSRichard Henderson TRANS(FPADDS16, VIS3, do_gvec_ddd, a, MO_16, tcg_gen_gvec_ssadd) 51060d1d3aafSRichard Henderson TRANS(FPADDS32, VIS3, do_gvec_ddd, a, MO_32, tcg_gen_gvec_ssadd) 5107b99c1bbdSRichard Henderson TRANS(FPADDUS8, VIS4, do_gvec_ddd, a, MO_8, tcg_gen_gvec_usadd) 5108b99c1bbdSRichard Henderson TRANS(FPADDUS16, VIS4, do_gvec_ddd, a, MO_16, tcg_gen_gvec_usadd) 5109b99c1bbdSRichard Henderson 5110b99c1bbdSRichard Henderson TRANS(FPSUBS8, VIS4, do_gvec_ddd, a, MO_8, tcg_gen_gvec_sssub) 51110d1d3aafSRichard Henderson TRANS(FPSUBS16, VIS3, do_gvec_ddd, a, MO_16, tcg_gen_gvec_sssub) 51120d1d3aafSRichard Henderson TRANS(FPSUBS32, VIS3, do_gvec_ddd, a, MO_32, tcg_gen_gvec_sssub) 5113b99c1bbdSRichard Henderson TRANS(FPSUBUS8, VIS4, do_gvec_ddd, a, MO_8, tcg_gen_gvec_ussub) 5114b99c1bbdSRichard Henderson TRANS(FPSUBUS16, VIS4, do_gvec_ddd, a, MO_16, tcg_gen_gvec_ussub) 51150d1d3aafSRichard Henderson 5116fbc5c8d4SRichard Henderson TRANS(FSLL16, VIS3, do_gvec_ddd, a, MO_16, tcg_gen_gvec_shlv) 5117fbc5c8d4SRichard Henderson TRANS(FSLL32, VIS3, do_gvec_ddd, a, MO_32, tcg_gen_gvec_shlv) 5118fbc5c8d4SRichard Henderson TRANS(FSRL16, VIS3, do_gvec_ddd, a, MO_16, tcg_gen_gvec_shrv) 5119fbc5c8d4SRichard Henderson TRANS(FSRL32, VIS3, do_gvec_ddd, a, MO_32, tcg_gen_gvec_shrv) 5120fbc5c8d4SRichard Henderson TRANS(FSRA16, VIS3, do_gvec_ddd, a, MO_16, tcg_gen_gvec_sarv) 5121fbc5c8d4SRichard Henderson TRANS(FSRA32, VIS3, do_gvec_ddd, a, MO_32, tcg_gen_gvec_sarv) 5122fbc5c8d4SRichard Henderson 5123db11dfeaSRichard Henderson TRANS(FPMIN8, VIS4, do_gvec_ddd, a, MO_8, tcg_gen_gvec_smin) 5124db11dfeaSRichard Henderson TRANS(FPMIN16, VIS4, do_gvec_ddd, a, MO_16, tcg_gen_gvec_smin) 5125db11dfeaSRichard Henderson TRANS(FPMIN32, VIS4, do_gvec_ddd, a, MO_32, tcg_gen_gvec_smin) 5126db11dfeaSRichard Henderson TRANS(FPMINU8, VIS4, do_gvec_ddd, a, MO_8, tcg_gen_gvec_umin) 5127db11dfeaSRichard Henderson TRANS(FPMINU16, VIS4, do_gvec_ddd, a, MO_16, tcg_gen_gvec_umin) 5128db11dfeaSRichard Henderson TRANS(FPMINU32, VIS4, do_gvec_ddd, a, MO_32, tcg_gen_gvec_umin) 5129db11dfeaSRichard Henderson 5130db11dfeaSRichard Henderson TRANS(FPMAX8, VIS4, do_gvec_ddd, a, MO_8, tcg_gen_gvec_smax) 5131db11dfeaSRichard Henderson TRANS(FPMAX16, VIS4, do_gvec_ddd, a, MO_16, tcg_gen_gvec_smax) 5132db11dfeaSRichard Henderson TRANS(FPMAX32, VIS4, do_gvec_ddd, a, MO_32, tcg_gen_gvec_smax) 5133db11dfeaSRichard Henderson TRANS(FPMAXU8, VIS4, do_gvec_ddd, a, MO_8, tcg_gen_gvec_umax) 5134db11dfeaSRichard Henderson TRANS(FPMAXU16, VIS4, do_gvec_ddd, a, MO_16, tcg_gen_gvec_umax) 5135db11dfeaSRichard Henderson TRANS(FPMAXU32, VIS4, do_gvec_ddd, a, MO_32, tcg_gen_gvec_umax) 5136db11dfeaSRichard Henderson 5137e06c9f83SRichard Henderson static bool do_ddd(DisasContext *dc, arg_r_r_r *a, 5138e06c9f83SRichard Henderson void (*func)(TCGv_i64, TCGv_i64, TCGv_i64)) 5139e06c9f83SRichard Henderson { 5140e06c9f83SRichard Henderson TCGv_i64 dst, src1, src2; 5141e06c9f83SRichard Henderson 5142e06c9f83SRichard Henderson if (gen_trap_ifnofpu(dc)) { 5143e06c9f83SRichard Henderson return true; 5144e06c9f83SRichard Henderson } 5145e06c9f83SRichard Henderson 514652f46d46SRichard Henderson dst = tcg_temp_new_i64(); 5147e06c9f83SRichard Henderson src1 = gen_load_fpr_D(dc, a->rs1); 5148e06c9f83SRichard Henderson src2 = gen_load_fpr_D(dc, a->rs2); 5149e06c9f83SRichard Henderson func(dst, src1, src2); 5150e06c9f83SRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 5151e06c9f83SRichard Henderson return advance_pc(dc); 5152e06c9f83SRichard Henderson } 5153e06c9f83SRichard Henderson 5154e06c9f83SRichard Henderson TRANS(FMUL8SUx16, VIS1, do_ddd, a, gen_helper_fmul8sux16) 5155e06c9f83SRichard Henderson TRANS(FMUL8ULx16, VIS1, do_ddd, a, gen_helper_fmul8ulx16) 5156e06c9f83SRichard Henderson 5157e06c9f83SRichard Henderson TRANS(FNORd, VIS1, do_ddd, a, tcg_gen_nor_i64) 5158e06c9f83SRichard Henderson TRANS(FANDNOTd, VIS1, do_ddd, a, tcg_gen_andc_i64) 5159e06c9f83SRichard Henderson TRANS(FXORd, VIS1, do_ddd, a, tcg_gen_xor_i64) 5160e06c9f83SRichard Henderson TRANS(FNANDd, VIS1, do_ddd, a, tcg_gen_nand_i64) 5161e06c9f83SRichard Henderson TRANS(FANDd, VIS1, do_ddd, a, tcg_gen_and_i64) 5162e06c9f83SRichard Henderson TRANS(FXNORd, VIS1, do_ddd, a, tcg_gen_eqv_i64) 5163e06c9f83SRichard Henderson TRANS(FORNOTd, VIS1, do_ddd, a, tcg_gen_orc_i64) 5164e06c9f83SRichard Henderson TRANS(FORd, VIS1, do_ddd, a, tcg_gen_or_i64) 5165e06c9f83SRichard Henderson 51664b6edc0aSRichard Henderson TRANS(FPACK32, VIS1, do_ddd, a, gen_op_fpack32) 5167b2b48493SRichard Henderson TRANS(FALIGNDATAg, VIS1, do_ddd, a, gen_op_faligndata_g) 51684b6edc0aSRichard Henderson TRANS(BSHUFFLE, VIS2, do_ddd, a, gen_op_bshuffle) 51694b6edc0aSRichard Henderson 51703d50b728SRichard Henderson TRANS(FHADDd, VIS3, do_ddd, a, gen_op_fhaddd) 51713d50b728SRichard Henderson TRANS(FHSUBd, VIS3, do_ddd, a, gen_op_fhsubd) 51723d50b728SRichard Henderson TRANS(FNHADDd, VIS3, do_ddd, a, gen_op_fnhaddd) 51733d50b728SRichard Henderson 5174bc3f14a9SRichard Henderson TRANS(FPADD64, VIS3B, do_ddd, a, tcg_gen_add_i64) 5175bc3f14a9SRichard Henderson TRANS(FPSUB64, VIS3B, do_ddd, a, tcg_gen_sub_i64) 5176fbc5c8d4SRichard Henderson TRANS(FSLAS16, VIS3, do_ddd, a, gen_helper_fslas16) 5177fbc5c8d4SRichard Henderson TRANS(FSLAS32, VIS3, do_ddd, a, gen_helper_fslas32) 5178bc3f14a9SRichard Henderson 5179e2fa6bd1SRichard Henderson static bool do_rdd(DisasContext *dc, arg_r_r_r *a, 5180e2fa6bd1SRichard Henderson void (*func)(TCGv, TCGv_i64, TCGv_i64)) 5181e2fa6bd1SRichard Henderson { 5182e2fa6bd1SRichard Henderson TCGv_i64 src1, src2; 5183e2fa6bd1SRichard Henderson TCGv dst; 5184e2fa6bd1SRichard Henderson 5185e2fa6bd1SRichard Henderson if (gen_trap_ifnofpu(dc)) { 5186e2fa6bd1SRichard Henderson return true; 5187e2fa6bd1SRichard Henderson } 5188e2fa6bd1SRichard Henderson 5189e2fa6bd1SRichard Henderson dst = gen_dest_gpr(dc, a->rd); 5190e2fa6bd1SRichard Henderson src1 = gen_load_fpr_D(dc, a->rs1); 5191e2fa6bd1SRichard Henderson src2 = gen_load_fpr_D(dc, a->rs2); 5192e2fa6bd1SRichard Henderson func(dst, src1, src2); 5193e2fa6bd1SRichard Henderson gen_store_gpr(dc, a->rd, dst); 5194e2fa6bd1SRichard Henderson return advance_pc(dc); 5195e2fa6bd1SRichard Henderson } 5196e2fa6bd1SRichard Henderson 5197e2fa6bd1SRichard Henderson TRANS(FPCMPLE16, VIS1, do_rdd, a, gen_helper_fcmple16) 5198e2fa6bd1SRichard Henderson TRANS(FPCMPNE16, VIS1, do_rdd, a, gen_helper_fcmpne16) 5199e2fa6bd1SRichard Henderson TRANS(FPCMPGT16, VIS1, do_rdd, a, gen_helper_fcmpgt16) 5200e2fa6bd1SRichard Henderson TRANS(FPCMPEQ16, VIS1, do_rdd, a, gen_helper_fcmpeq16) 5201b3c934ddSRichard Henderson TRANS(FPCMPULE16, VIS4, do_rdd, a, gen_helper_fcmpule16) 5202b3c934ddSRichard Henderson TRANS(FPCMPUGT16, VIS4, do_rdd, a, gen_helper_fcmpugt16) 5203e2fa6bd1SRichard Henderson 5204e2fa6bd1SRichard Henderson TRANS(FPCMPLE32, VIS1, do_rdd, a, gen_helper_fcmple32) 5205e2fa6bd1SRichard Henderson TRANS(FPCMPNE32, VIS1, do_rdd, a, gen_helper_fcmpne32) 5206e2fa6bd1SRichard Henderson TRANS(FPCMPGT32, VIS1, do_rdd, a, gen_helper_fcmpgt32) 5207e2fa6bd1SRichard Henderson TRANS(FPCMPEQ32, VIS1, do_rdd, a, gen_helper_fcmpeq32) 5208b3c934ddSRichard Henderson TRANS(FPCMPULE32, VIS4, do_rdd, a, gen_helper_fcmpule32) 5209b3c934ddSRichard Henderson TRANS(FPCMPUGT32, VIS4, do_rdd, a, gen_helper_fcmpugt32) 5210e2fa6bd1SRichard Henderson 5211669e0774SRichard Henderson TRANS(FPCMPEQ8, VIS3B, do_rdd, a, gen_helper_fcmpeq8) 5212669e0774SRichard Henderson TRANS(FPCMPNE8, VIS3B, do_rdd, a, gen_helper_fcmpne8) 5213669e0774SRichard Henderson TRANS(FPCMPULE8, VIS3B, do_rdd, a, gen_helper_fcmpule8) 5214669e0774SRichard Henderson TRANS(FPCMPUGT8, VIS3B, do_rdd, a, gen_helper_fcmpugt8) 5215b3c934ddSRichard Henderson TRANS(FPCMPLE8, VIS4, do_rdd, a, gen_helper_fcmple8) 5216b3c934ddSRichard Henderson TRANS(FPCMPGT8, VIS4, do_rdd, a, gen_helper_fcmpgt8) 5217669e0774SRichard Henderson 52187d5ebd8fSRichard Henderson TRANS(PDISTN, VIS3, do_rdd, a, gen_op_pdistn) 5219029b0283SRichard Henderson TRANS(XMULX, VIS3, do_rrr, a, gen_helper_xmulx) 5220029b0283SRichard Henderson TRANS(XMULXHI, VIS3, do_rrr, a, gen_helper_xmulxhi) 52217d5ebd8fSRichard Henderson 5222f2a59b0aSRichard Henderson static bool do_env_ddd(DisasContext *dc, arg_r_r_r *a, 5223f2a59b0aSRichard Henderson void (*func)(TCGv_i64, TCGv_env, TCGv_i64, TCGv_i64)) 5224f2a59b0aSRichard Henderson { 5225f2a59b0aSRichard Henderson TCGv_i64 dst, src1, src2; 5226f2a59b0aSRichard Henderson 5227f2a59b0aSRichard Henderson if (gen_trap_ifnofpu(dc)) { 5228f2a59b0aSRichard Henderson return true; 5229f2a59b0aSRichard Henderson } 5230f2a59b0aSRichard Henderson 523152f46d46SRichard Henderson dst = tcg_temp_new_i64(); 5232f2a59b0aSRichard Henderson src1 = gen_load_fpr_D(dc, a->rs1); 5233f2a59b0aSRichard Henderson src2 = gen_load_fpr_D(dc, a->rs2); 5234f2a59b0aSRichard Henderson func(dst, tcg_env, src1, src2); 5235f2a59b0aSRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 5236f2a59b0aSRichard Henderson return advance_pc(dc); 5237f2a59b0aSRichard Henderson } 5238f2a59b0aSRichard Henderson 5239f2a59b0aSRichard Henderson TRANS(FADDd, ALL, do_env_ddd, a, gen_helper_faddd) 5240f2a59b0aSRichard Henderson TRANS(FSUBd, ALL, do_env_ddd, a, gen_helper_fsubd) 5241f2a59b0aSRichard Henderson TRANS(FMULd, ALL, do_env_ddd, a, gen_helper_fmuld) 5242f2a59b0aSRichard Henderson TRANS(FDIVd, ALL, do_env_ddd, a, gen_helper_fdivd) 52433d50b728SRichard Henderson TRANS(FNADDd, VIS3, do_env_ddd, a, gen_helper_fnaddd) 52443d50b728SRichard Henderson TRANS(FNMULd, VIS3, do_env_ddd, a, gen_helper_fnmuld) 5245f2a59b0aSRichard Henderson 5246ff4c711bSRichard Henderson static bool trans_FsMULd(DisasContext *dc, arg_r_r_r *a) 5247ff4c711bSRichard Henderson { 5248ff4c711bSRichard Henderson TCGv_i64 dst; 5249ff4c711bSRichard Henderson TCGv_i32 src1, src2; 5250ff4c711bSRichard Henderson 5251ff4c711bSRichard Henderson if (gen_trap_ifnofpu(dc)) { 5252ff4c711bSRichard Henderson return true; 5253ff4c711bSRichard Henderson } 5254ff4c711bSRichard Henderson if (!(dc->def->features & CPU_FEATURE_FSMULD)) { 5255ff4c711bSRichard Henderson return raise_unimpfpop(dc); 5256ff4c711bSRichard Henderson } 5257ff4c711bSRichard Henderson 525852f46d46SRichard Henderson dst = tcg_temp_new_i64(); 5259ff4c711bSRichard Henderson src1 = gen_load_fpr_F(dc, a->rs1); 5260ff4c711bSRichard Henderson src2 = gen_load_fpr_F(dc, a->rs2); 5261ff4c711bSRichard Henderson gen_helper_fsmuld(dst, tcg_env, src1, src2); 5262ff4c711bSRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 5263ff4c711bSRichard Henderson return advance_pc(dc); 5264ff4c711bSRichard Henderson } 5265ff4c711bSRichard Henderson 52663d50b728SRichard Henderson static bool trans_FNsMULd(DisasContext *dc, arg_r_r_r *a) 52673d50b728SRichard Henderson { 52683d50b728SRichard Henderson TCGv_i64 dst; 52693d50b728SRichard Henderson TCGv_i32 src1, src2; 52703d50b728SRichard Henderson 52713d50b728SRichard Henderson if (!avail_VIS3(dc)) { 52723d50b728SRichard Henderson return false; 52733d50b728SRichard Henderson } 52743d50b728SRichard Henderson if (gen_trap_ifnofpu(dc)) { 52753d50b728SRichard Henderson return true; 52763d50b728SRichard Henderson } 52773d50b728SRichard Henderson dst = tcg_temp_new_i64(); 52783d50b728SRichard Henderson src1 = gen_load_fpr_F(dc, a->rs1); 52793d50b728SRichard Henderson src2 = gen_load_fpr_F(dc, a->rs2); 52803d50b728SRichard Henderson gen_helper_fnsmuld(dst, tcg_env, src1, src2); 52813d50b728SRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 52823d50b728SRichard Henderson return advance_pc(dc); 52833d50b728SRichard Henderson } 52843d50b728SRichard Henderson 52854fd71d19SRichard Henderson static bool do_ffff(DisasContext *dc, arg_r_r_r_r *a, 52864fd71d19SRichard Henderson void (*func)(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_i32)) 52874fd71d19SRichard Henderson { 52884fd71d19SRichard Henderson TCGv_i32 dst, src1, src2, src3; 52894fd71d19SRichard Henderson 52904fd71d19SRichard Henderson if (gen_trap_ifnofpu(dc)) { 52914fd71d19SRichard Henderson return true; 52924fd71d19SRichard Henderson } 52934fd71d19SRichard Henderson 52944fd71d19SRichard Henderson src1 = gen_load_fpr_F(dc, a->rs1); 52954fd71d19SRichard Henderson src2 = gen_load_fpr_F(dc, a->rs2); 52964fd71d19SRichard Henderson src3 = gen_load_fpr_F(dc, a->rs3); 52974fd71d19SRichard Henderson dst = tcg_temp_new_i32(); 52984fd71d19SRichard Henderson func(dst, src1, src2, src3); 52994fd71d19SRichard Henderson gen_store_fpr_F(dc, a->rd, dst); 53004fd71d19SRichard Henderson return advance_pc(dc); 53014fd71d19SRichard Henderson } 53024fd71d19SRichard Henderson 53034fd71d19SRichard Henderson TRANS(FMADDs, FMAF, do_ffff, a, gen_op_fmadds) 53044fd71d19SRichard Henderson TRANS(FMSUBs, FMAF, do_ffff, a, gen_op_fmsubs) 53054fd71d19SRichard Henderson TRANS(FNMSUBs, FMAF, do_ffff, a, gen_op_fnmsubs) 53064fd71d19SRichard Henderson TRANS(FNMADDs, FMAF, do_ffff, a, gen_op_fnmadds) 53074fd71d19SRichard Henderson 53084fd71d19SRichard Henderson static bool do_dddd(DisasContext *dc, arg_r_r_r_r *a, 5309afb04344SRichard Henderson void (*func)(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_i64)) 5310afb04344SRichard Henderson { 53114fd71d19SRichard Henderson TCGv_i64 dst, src1, src2, src3; 5312afb04344SRichard Henderson 5313afb04344SRichard Henderson if (gen_trap_ifnofpu(dc)) { 5314afb04344SRichard Henderson return true; 5315afb04344SRichard Henderson } 5316afb04344SRichard Henderson 531752f46d46SRichard Henderson dst = tcg_temp_new_i64(); 5318afb04344SRichard Henderson src1 = gen_load_fpr_D(dc, a->rs1); 5319afb04344SRichard Henderson src2 = gen_load_fpr_D(dc, a->rs2); 53204fd71d19SRichard Henderson src3 = gen_load_fpr_D(dc, a->rs3); 53214fd71d19SRichard Henderson func(dst, src1, src2, src3); 5322afb04344SRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 5323afb04344SRichard Henderson return advance_pc(dc); 5324afb04344SRichard Henderson } 5325afb04344SRichard Henderson 5326afb04344SRichard Henderson TRANS(PDIST, VIS1, do_dddd, a, gen_helper_pdist) 53274fd71d19SRichard Henderson TRANS(FMADDd, FMAF, do_dddd, a, gen_op_fmaddd) 53284fd71d19SRichard Henderson TRANS(FMSUBd, FMAF, do_dddd, a, gen_op_fmsubd) 53294fd71d19SRichard Henderson TRANS(FNMSUBd, FMAF, do_dddd, a, gen_op_fnmsubd) 53304fd71d19SRichard Henderson TRANS(FNMADDd, FMAF, do_dddd, a, gen_op_fnmaddd) 533168a414e9SRichard Henderson TRANS(FPMADDX, IMA, do_dddd, a, gen_op_fpmaddx) 533268a414e9SRichard Henderson TRANS(FPMADDXHI, IMA, do_dddd, a, gen_op_fpmaddxhi) 5333afb04344SRichard Henderson 5334b2b48493SRichard Henderson static bool trans_FALIGNDATAi(DisasContext *dc, arg_r_r_r *a) 5335b2b48493SRichard Henderson { 5336b2b48493SRichard Henderson TCGv_i64 dst, src1, src2; 5337b2b48493SRichard Henderson TCGv src3; 5338b2b48493SRichard Henderson 5339b2b48493SRichard Henderson if (!avail_VIS4(dc)) { 5340b2b48493SRichard Henderson return false; 5341b2b48493SRichard Henderson } 5342b2b48493SRichard Henderson if (gen_trap_ifnofpu(dc)) { 5343b2b48493SRichard Henderson return true; 5344b2b48493SRichard Henderson } 5345b2b48493SRichard Henderson 5346b2b48493SRichard Henderson dst = tcg_temp_new_i64(); 5347b2b48493SRichard Henderson src1 = gen_load_fpr_D(dc, a->rd); 5348b2b48493SRichard Henderson src2 = gen_load_fpr_D(dc, a->rs2); 5349b2b48493SRichard Henderson src3 = gen_load_gpr(dc, a->rs1); 5350b2b48493SRichard Henderson gen_op_faligndata_i(dst, src1, src2, src3); 5351b2b48493SRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 5352b2b48493SRichard Henderson return advance_pc(dc); 5353b2b48493SRichard Henderson } 5354b2b48493SRichard Henderson 5355a4056239SRichard Henderson static bool do_env_qqq(DisasContext *dc, arg_r_r_r *a, 535616bedf89SRichard Henderson void (*func)(TCGv_i128, TCGv_env, TCGv_i128, TCGv_i128)) 5357a4056239SRichard Henderson { 535816bedf89SRichard Henderson TCGv_i128 src1, src2; 535916bedf89SRichard Henderson 5360a4056239SRichard Henderson if (gen_trap_ifnofpu(dc)) { 5361a4056239SRichard Henderson return true; 5362a4056239SRichard Henderson } 5363a4056239SRichard Henderson if (gen_trap_float128(dc)) { 5364a4056239SRichard Henderson return true; 5365a4056239SRichard Henderson } 5366a4056239SRichard Henderson 536716bedf89SRichard Henderson src1 = gen_load_fpr_Q(dc, a->rs1); 536816bedf89SRichard Henderson src2 = gen_load_fpr_Q(dc, a->rs2); 536916bedf89SRichard Henderson func(src1, tcg_env, src1, src2); 537016bedf89SRichard Henderson gen_store_fpr_Q(dc, a->rd, src1); 5371a4056239SRichard Henderson return advance_pc(dc); 5372a4056239SRichard Henderson } 5373a4056239SRichard Henderson 5374a4056239SRichard Henderson TRANS(FADDq, ALL, do_env_qqq, a, gen_helper_faddq) 5375a4056239SRichard Henderson TRANS(FSUBq, ALL, do_env_qqq, a, gen_helper_fsubq) 5376a4056239SRichard Henderson TRANS(FMULq, ALL, do_env_qqq, a, gen_helper_fmulq) 5377a4056239SRichard Henderson TRANS(FDIVq, ALL, do_env_qqq, a, gen_helper_fdivq) 5378a4056239SRichard Henderson 53795e3b17bbSRichard Henderson static bool trans_FdMULq(DisasContext *dc, arg_r_r_r *a) 53805e3b17bbSRichard Henderson { 53815e3b17bbSRichard Henderson TCGv_i64 src1, src2; 5382ba21dc99SRichard Henderson TCGv_i128 dst; 53835e3b17bbSRichard Henderson 53845e3b17bbSRichard Henderson if (gen_trap_ifnofpu(dc)) { 53855e3b17bbSRichard Henderson return true; 53865e3b17bbSRichard Henderson } 53875e3b17bbSRichard Henderson if (gen_trap_float128(dc)) { 53885e3b17bbSRichard Henderson return true; 53895e3b17bbSRichard Henderson } 53905e3b17bbSRichard Henderson 53915e3b17bbSRichard Henderson src1 = gen_load_fpr_D(dc, a->rs1); 53925e3b17bbSRichard Henderson src2 = gen_load_fpr_D(dc, a->rs2); 5393ba21dc99SRichard Henderson dst = tcg_temp_new_i128(); 5394ba21dc99SRichard Henderson gen_helper_fdmulq(dst, tcg_env, src1, src2); 5395ba21dc99SRichard Henderson gen_store_fpr_Q(dc, a->rd, dst); 53965e3b17bbSRichard Henderson return advance_pc(dc); 53975e3b17bbSRichard Henderson } 53985e3b17bbSRichard Henderson 5399f7ec8155SRichard Henderson static bool do_fmovr(DisasContext *dc, arg_FMOVRs *a, bool is_128, 5400f7ec8155SRichard Henderson void (*func)(DisasContext *, DisasCompare *, int, int)) 5401f7ec8155SRichard Henderson { 5402f7ec8155SRichard Henderson DisasCompare cmp; 5403f7ec8155SRichard Henderson 54042c4f56c9SRichard Henderson if (!gen_compare_reg(&cmp, a->cond, gen_load_gpr(dc, a->rs1))) { 54052c4f56c9SRichard Henderson return false; 54062c4f56c9SRichard Henderson } 5407f7ec8155SRichard Henderson if (gen_trap_ifnofpu(dc)) { 5408f7ec8155SRichard Henderson return true; 5409f7ec8155SRichard Henderson } 5410f7ec8155SRichard Henderson if (is_128 && gen_trap_float128(dc)) { 5411f7ec8155SRichard Henderson return true; 5412f7ec8155SRichard Henderson } 5413f7ec8155SRichard Henderson 5414f7ec8155SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 5415f7ec8155SRichard Henderson func(dc, &cmp, a->rd, a->rs2); 5416f7ec8155SRichard Henderson return advance_pc(dc); 5417f7ec8155SRichard Henderson } 5418f7ec8155SRichard Henderson 5419f7ec8155SRichard Henderson TRANS(FMOVRs, 64, do_fmovr, a, false, gen_fmovs) 5420f7ec8155SRichard Henderson TRANS(FMOVRd, 64, do_fmovr, a, false, gen_fmovd) 5421f7ec8155SRichard Henderson TRANS(FMOVRq, 64, do_fmovr, a, true, gen_fmovq) 5422f7ec8155SRichard Henderson 5423f7ec8155SRichard Henderson static bool do_fmovcc(DisasContext *dc, arg_FMOVscc *a, bool is_128, 5424f7ec8155SRichard Henderson void (*func)(DisasContext *, DisasCompare *, int, int)) 5425f7ec8155SRichard Henderson { 5426f7ec8155SRichard Henderson DisasCompare cmp; 5427f7ec8155SRichard Henderson 5428f7ec8155SRichard Henderson if (gen_trap_ifnofpu(dc)) { 5429f7ec8155SRichard Henderson return true; 5430f7ec8155SRichard Henderson } 5431f7ec8155SRichard Henderson if (is_128 && gen_trap_float128(dc)) { 5432f7ec8155SRichard Henderson return true; 5433f7ec8155SRichard Henderson } 5434f7ec8155SRichard Henderson 5435f7ec8155SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 5436f7ec8155SRichard Henderson gen_compare(&cmp, a->cc, a->cond, dc); 5437f7ec8155SRichard Henderson func(dc, &cmp, a->rd, a->rs2); 5438f7ec8155SRichard Henderson return advance_pc(dc); 5439f7ec8155SRichard Henderson } 5440f7ec8155SRichard Henderson 5441f7ec8155SRichard Henderson TRANS(FMOVscc, 64, do_fmovcc, a, false, gen_fmovs) 5442f7ec8155SRichard Henderson TRANS(FMOVdcc, 64, do_fmovcc, a, false, gen_fmovd) 5443f7ec8155SRichard Henderson TRANS(FMOVqcc, 64, do_fmovcc, a, true, gen_fmovq) 5444f7ec8155SRichard Henderson 5445f7ec8155SRichard Henderson static bool do_fmovfcc(DisasContext *dc, arg_FMOVsfcc *a, bool is_128, 5446f7ec8155SRichard Henderson void (*func)(DisasContext *, DisasCompare *, int, int)) 5447f7ec8155SRichard Henderson { 5448f7ec8155SRichard Henderson DisasCompare cmp; 5449f7ec8155SRichard Henderson 5450f7ec8155SRichard Henderson if (gen_trap_ifnofpu(dc)) { 5451f7ec8155SRichard Henderson return true; 5452f7ec8155SRichard Henderson } 5453f7ec8155SRichard Henderson if (is_128 && gen_trap_float128(dc)) { 5454f7ec8155SRichard Henderson return true; 5455f7ec8155SRichard Henderson } 5456f7ec8155SRichard Henderson 5457f7ec8155SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 5458f7ec8155SRichard Henderson gen_fcompare(&cmp, a->cc, a->cond); 5459f7ec8155SRichard Henderson func(dc, &cmp, a->rd, a->rs2); 5460f7ec8155SRichard Henderson return advance_pc(dc); 5461f7ec8155SRichard Henderson } 5462f7ec8155SRichard Henderson 5463f7ec8155SRichard Henderson TRANS(FMOVsfcc, 64, do_fmovfcc, a, false, gen_fmovs) 5464f7ec8155SRichard Henderson TRANS(FMOVdfcc, 64, do_fmovfcc, a, false, gen_fmovd) 5465f7ec8155SRichard Henderson TRANS(FMOVqfcc, 64, do_fmovfcc, a, true, gen_fmovq) 5466f7ec8155SRichard Henderson 546740f9ad21SRichard Henderson static bool do_fcmps(DisasContext *dc, arg_FCMPs *a, bool e) 546840f9ad21SRichard Henderson { 546940f9ad21SRichard Henderson TCGv_i32 src1, src2; 547040f9ad21SRichard Henderson 547140f9ad21SRichard Henderson if (avail_32(dc) && a->cc != 0) { 547240f9ad21SRichard Henderson return false; 547340f9ad21SRichard Henderson } 547440f9ad21SRichard Henderson if (gen_trap_ifnofpu(dc)) { 547540f9ad21SRichard Henderson return true; 547640f9ad21SRichard Henderson } 547740f9ad21SRichard Henderson 547840f9ad21SRichard Henderson src1 = gen_load_fpr_F(dc, a->rs1); 547940f9ad21SRichard Henderson src2 = gen_load_fpr_F(dc, a->rs2); 548040f9ad21SRichard Henderson if (e) { 5481d8c5b92fSRichard Henderson gen_helper_fcmpes(cpu_fcc[a->cc], tcg_env, src1, src2); 548240f9ad21SRichard Henderson } else { 5483d8c5b92fSRichard Henderson gen_helper_fcmps(cpu_fcc[a->cc], tcg_env, src1, src2); 548440f9ad21SRichard Henderson } 548540f9ad21SRichard Henderson return advance_pc(dc); 548640f9ad21SRichard Henderson } 548740f9ad21SRichard Henderson 548840f9ad21SRichard Henderson TRANS(FCMPs, ALL, do_fcmps, a, false) 548940f9ad21SRichard Henderson TRANS(FCMPEs, ALL, do_fcmps, a, true) 549040f9ad21SRichard Henderson 549140f9ad21SRichard Henderson static bool do_fcmpd(DisasContext *dc, arg_FCMPd *a, bool e) 549240f9ad21SRichard Henderson { 549340f9ad21SRichard Henderson TCGv_i64 src1, src2; 549440f9ad21SRichard Henderson 549540f9ad21SRichard Henderson if (avail_32(dc) && a->cc != 0) { 549640f9ad21SRichard Henderson return false; 549740f9ad21SRichard Henderson } 549840f9ad21SRichard Henderson if (gen_trap_ifnofpu(dc)) { 549940f9ad21SRichard Henderson return true; 550040f9ad21SRichard Henderson } 550140f9ad21SRichard Henderson 550240f9ad21SRichard Henderson src1 = gen_load_fpr_D(dc, a->rs1); 550340f9ad21SRichard Henderson src2 = gen_load_fpr_D(dc, a->rs2); 550440f9ad21SRichard Henderson if (e) { 5505d8c5b92fSRichard Henderson gen_helper_fcmped(cpu_fcc[a->cc], tcg_env, src1, src2); 550640f9ad21SRichard Henderson } else { 5507d8c5b92fSRichard Henderson gen_helper_fcmpd(cpu_fcc[a->cc], tcg_env, src1, src2); 550840f9ad21SRichard Henderson } 550940f9ad21SRichard Henderson return advance_pc(dc); 551040f9ad21SRichard Henderson } 551140f9ad21SRichard Henderson 551240f9ad21SRichard Henderson TRANS(FCMPd, ALL, do_fcmpd, a, false) 551340f9ad21SRichard Henderson TRANS(FCMPEd, ALL, do_fcmpd, a, true) 551440f9ad21SRichard Henderson 551540f9ad21SRichard Henderson static bool do_fcmpq(DisasContext *dc, arg_FCMPq *a, bool e) 551640f9ad21SRichard Henderson { 5517f3ceafadSRichard Henderson TCGv_i128 src1, src2; 5518f3ceafadSRichard Henderson 551940f9ad21SRichard Henderson if (avail_32(dc) && a->cc != 0) { 552040f9ad21SRichard Henderson return false; 552140f9ad21SRichard Henderson } 552240f9ad21SRichard Henderson if (gen_trap_ifnofpu(dc)) { 552340f9ad21SRichard Henderson return true; 552440f9ad21SRichard Henderson } 552540f9ad21SRichard Henderson if (gen_trap_float128(dc)) { 552640f9ad21SRichard Henderson return true; 552740f9ad21SRichard Henderson } 552840f9ad21SRichard Henderson 5529f3ceafadSRichard Henderson src1 = gen_load_fpr_Q(dc, a->rs1); 5530f3ceafadSRichard Henderson src2 = gen_load_fpr_Q(dc, a->rs2); 553140f9ad21SRichard Henderson if (e) { 5532d8c5b92fSRichard Henderson gen_helper_fcmpeq(cpu_fcc[a->cc], tcg_env, src1, src2); 553340f9ad21SRichard Henderson } else { 5534d8c5b92fSRichard Henderson gen_helper_fcmpq(cpu_fcc[a->cc], tcg_env, src1, src2); 553540f9ad21SRichard Henderson } 553640f9ad21SRichard Henderson return advance_pc(dc); 553740f9ad21SRichard Henderson } 553840f9ad21SRichard Henderson 553940f9ad21SRichard Henderson TRANS(FCMPq, ALL, do_fcmpq, a, false) 554040f9ad21SRichard Henderson TRANS(FCMPEq, ALL, do_fcmpq, a, true) 554140f9ad21SRichard Henderson 55421d3ed3d7SRichard Henderson static bool trans_FLCMPs(DisasContext *dc, arg_FLCMPs *a) 55431d3ed3d7SRichard Henderson { 55441d3ed3d7SRichard Henderson TCGv_i32 src1, src2; 55451d3ed3d7SRichard Henderson 55461d3ed3d7SRichard Henderson if (!avail_VIS3(dc)) { 55471d3ed3d7SRichard Henderson return false; 55481d3ed3d7SRichard Henderson } 55491d3ed3d7SRichard Henderson if (gen_trap_ifnofpu(dc)) { 55501d3ed3d7SRichard Henderson return true; 55511d3ed3d7SRichard Henderson } 55521d3ed3d7SRichard Henderson 55531d3ed3d7SRichard Henderson src1 = gen_load_fpr_F(dc, a->rs1); 55541d3ed3d7SRichard Henderson src2 = gen_load_fpr_F(dc, a->rs2); 55551d3ed3d7SRichard Henderson gen_helper_flcmps(cpu_fcc[a->cc], src1, src2); 55561d3ed3d7SRichard Henderson return advance_pc(dc); 55571d3ed3d7SRichard Henderson } 55581d3ed3d7SRichard Henderson 55591d3ed3d7SRichard Henderson static bool trans_FLCMPd(DisasContext *dc, arg_FLCMPd *a) 55601d3ed3d7SRichard Henderson { 55611d3ed3d7SRichard Henderson TCGv_i64 src1, src2; 55621d3ed3d7SRichard Henderson 55631d3ed3d7SRichard Henderson if (!avail_VIS3(dc)) { 55641d3ed3d7SRichard Henderson return false; 55651d3ed3d7SRichard Henderson } 55661d3ed3d7SRichard Henderson if (gen_trap_ifnofpu(dc)) { 55671d3ed3d7SRichard Henderson return true; 55681d3ed3d7SRichard Henderson } 55691d3ed3d7SRichard Henderson 55701d3ed3d7SRichard Henderson src1 = gen_load_fpr_D(dc, a->rs1); 55711d3ed3d7SRichard Henderson src2 = gen_load_fpr_D(dc, a->rs2); 55721d3ed3d7SRichard Henderson gen_helper_flcmpd(cpu_fcc[a->cc], src1, src2); 55731d3ed3d7SRichard Henderson return advance_pc(dc); 55741d3ed3d7SRichard Henderson } 55751d3ed3d7SRichard Henderson 557609b157e6SRichard Henderson static bool do_movf2r(DisasContext *dc, arg_r_r *a, 557709b157e6SRichard Henderson int (*offset)(unsigned int), 557809b157e6SRichard Henderson void (*load)(TCGv, TCGv_ptr, tcg_target_long)) 557909b157e6SRichard Henderson { 558009b157e6SRichard Henderson TCGv dst; 558109b157e6SRichard Henderson 558209b157e6SRichard Henderson if (gen_trap_ifnofpu(dc)) { 558309b157e6SRichard Henderson return true; 558409b157e6SRichard Henderson } 558509b157e6SRichard Henderson dst = gen_dest_gpr(dc, a->rd); 558609b157e6SRichard Henderson load(dst, tcg_env, offset(a->rs)); 558709b157e6SRichard Henderson gen_store_gpr(dc, a->rd, dst); 558809b157e6SRichard Henderson return advance_pc(dc); 558909b157e6SRichard Henderson } 559009b157e6SRichard Henderson 559109b157e6SRichard Henderson TRANS(MOVsTOsw, VIS3B, do_movf2r, a, gen_offset_fpr_F, tcg_gen_ld32s_tl) 559209b157e6SRichard Henderson TRANS(MOVsTOuw, VIS3B, do_movf2r, a, gen_offset_fpr_F, tcg_gen_ld32u_tl) 559309b157e6SRichard Henderson TRANS(MOVdTOx, VIS3B, do_movf2r, a, gen_offset_fpr_D, tcg_gen_ld_tl) 559409b157e6SRichard Henderson 559509b157e6SRichard Henderson static bool do_movr2f(DisasContext *dc, arg_r_r *a, 559609b157e6SRichard Henderson int (*offset)(unsigned int), 559709b157e6SRichard Henderson void (*store)(TCGv, TCGv_ptr, tcg_target_long)) 559809b157e6SRichard Henderson { 559909b157e6SRichard Henderson TCGv src; 560009b157e6SRichard Henderson 560109b157e6SRichard Henderson if (gen_trap_ifnofpu(dc)) { 560209b157e6SRichard Henderson return true; 560309b157e6SRichard Henderson } 560409b157e6SRichard Henderson src = gen_load_gpr(dc, a->rs); 560509b157e6SRichard Henderson store(src, tcg_env, offset(a->rd)); 560609b157e6SRichard Henderson return advance_pc(dc); 560709b157e6SRichard Henderson } 560809b157e6SRichard Henderson 560909b157e6SRichard Henderson TRANS(MOVwTOs, VIS3B, do_movr2f, a, gen_offset_fpr_F, tcg_gen_st32_tl) 561009b157e6SRichard Henderson TRANS(MOVxTOd, VIS3B, do_movr2f, a, gen_offset_fpr_D, tcg_gen_st_tl) 561109b157e6SRichard Henderson 56126e61bc94SEmilio G. Cota static void sparc_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) 5613fcf5ef2aSThomas Huth { 56146e61bc94SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 56156e61bc94SEmilio G. Cota int bound; 5616af00be49SEmilio G. Cota 5617af00be49SEmilio G. Cota dc->pc = dc->base.pc_first; 56186e61bc94SEmilio G. Cota dc->npc = (target_ulong)dc->base.tb->cs_base; 56196e61bc94SEmilio G. Cota dc->mem_idx = dc->base.tb->flags & TB_FLAG_MMU_MASK; 562077976769SPhilippe Mathieu-Daudé dc->def = &cpu_env(cs)->def; 56216e61bc94SEmilio G. Cota dc->fpu_enabled = tb_fpu_enabled(dc->base.tb->flags); 56226e61bc94SEmilio G. Cota dc->address_mask_32bit = tb_am_enabled(dc->base.tb->flags); 5623c9b459aaSArtyom Tarasenko #ifndef CONFIG_USER_ONLY 56246e61bc94SEmilio G. Cota dc->supervisor = (dc->base.tb->flags & TB_FLAG_SUPER) != 0; 56255a165e26SRichard Henderson # ifdef TARGET_SPARC64 56265a165e26SRichard Henderson dc->hypervisor = (dc->base.tb->flags & TB_FLAG_HYPER) != 0; 56275a165e26SRichard Henderson # else 56285a165e26SRichard Henderson dc->fsr_qne = (dc->base.tb->flags & TB_FLAG_FSR_QNE) != 0; 56295a165e26SRichard Henderson # endif 5630c9b459aaSArtyom Tarasenko #endif 5631fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64 5632fcf5ef2aSThomas Huth dc->fprs_dirty = 0; 56336e61bc94SEmilio G. Cota dc->asi = (dc->base.tb->flags >> TB_FLAG_ASI_SHIFT) & 0xff; 5634fcf5ef2aSThomas Huth #endif 56356e61bc94SEmilio G. Cota /* 56366e61bc94SEmilio G. Cota * if we reach a page boundary, we stop generation so that the 56376e61bc94SEmilio G. Cota * PC of a TT_TFAULT exception is always in the right page 56386e61bc94SEmilio G. Cota */ 56396e61bc94SEmilio G. Cota bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4; 56406e61bc94SEmilio G. Cota dc->base.max_insns = MIN(dc->base.max_insns, bound); 5641af00be49SEmilio G. Cota } 5642fcf5ef2aSThomas Huth 56436e61bc94SEmilio G. Cota static void sparc_tr_tb_start(DisasContextBase *db, CPUState *cs) 56446e61bc94SEmilio G. Cota { 56456e61bc94SEmilio G. Cota } 56466e61bc94SEmilio G. Cota 56476e61bc94SEmilio G. Cota static void sparc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) 56486e61bc94SEmilio G. Cota { 56496e61bc94SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 5650633c4283SRichard Henderson target_ulong npc = dc->npc; 56516e61bc94SEmilio G. Cota 5652633c4283SRichard Henderson if (npc & 3) { 5653633c4283SRichard Henderson switch (npc) { 5654633c4283SRichard Henderson case JUMP_PC: 5655fcf5ef2aSThomas Huth assert(dc->jump_pc[1] == dc->pc + 4); 5656633c4283SRichard Henderson npc = dc->jump_pc[0] | JUMP_PC; 5657633c4283SRichard Henderson break; 5658633c4283SRichard Henderson case DYNAMIC_PC: 5659633c4283SRichard Henderson case DYNAMIC_PC_LOOKUP: 5660633c4283SRichard Henderson npc = DYNAMIC_PC; 5661633c4283SRichard Henderson break; 5662633c4283SRichard Henderson default: 5663633c4283SRichard Henderson g_assert_not_reached(); 5664fcf5ef2aSThomas Huth } 56656e61bc94SEmilio G. Cota } 5666633c4283SRichard Henderson tcg_gen_insn_start(dc->pc, npc); 5667633c4283SRichard Henderson } 5668fcf5ef2aSThomas Huth 56696e61bc94SEmilio G. Cota static void sparc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) 56706e61bc94SEmilio G. Cota { 56716e61bc94SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 56726e61bc94SEmilio G. Cota unsigned int insn; 5673fcf5ef2aSThomas Huth 567477976769SPhilippe Mathieu-Daudé insn = translator_ldl(cpu_env(cs), &dc->base, dc->pc); 5675af00be49SEmilio G. Cota dc->base.pc_next += 4; 5676878cc677SRichard Henderson 5677878cc677SRichard Henderson if (!decode(dc, insn)) { 5678ba9c09b4SRichard Henderson gen_exception(dc, TT_ILL_INSN); 5679878cc677SRichard Henderson } 5680fcf5ef2aSThomas Huth 5681af00be49SEmilio G. Cota if (dc->base.is_jmp == DISAS_NORETURN) { 56826e61bc94SEmilio G. Cota return; 5683c5e6ccdfSEmilio G. Cota } 5684af00be49SEmilio G. Cota if (dc->pc != dc->base.pc_next) { 56856e61bc94SEmilio G. Cota dc->base.is_jmp = DISAS_TOO_MANY; 5686af00be49SEmilio G. Cota } 56876e61bc94SEmilio G. Cota } 5688fcf5ef2aSThomas Huth 56896e61bc94SEmilio G. Cota static void sparc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) 56906e61bc94SEmilio G. Cota { 56916e61bc94SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 5692186e7890SRichard Henderson DisasDelayException *e, *e_next; 5693633c4283SRichard Henderson bool may_lookup; 56946e61bc94SEmilio G. Cota 569589527e3aSRichard Henderson finishing_insn(dc); 569689527e3aSRichard Henderson 569746bb0137SMark Cave-Ayland switch (dc->base.is_jmp) { 569846bb0137SMark Cave-Ayland case DISAS_NEXT: 569946bb0137SMark Cave-Ayland case DISAS_TOO_MANY: 5700633c4283SRichard Henderson if (((dc->pc | dc->npc) & 3) == 0) { 5701fcf5ef2aSThomas Huth /* static PC and NPC: we can use direct chaining */ 5702fcf5ef2aSThomas Huth gen_goto_tb(dc, 0, dc->pc, dc->npc); 5703633c4283SRichard Henderson break; 5704fcf5ef2aSThomas Huth } 5705633c4283SRichard Henderson 5706930f1865SRichard Henderson may_lookup = true; 5707633c4283SRichard Henderson if (dc->pc & 3) { 5708633c4283SRichard Henderson switch (dc->pc) { 5709633c4283SRichard Henderson case DYNAMIC_PC_LOOKUP: 5710633c4283SRichard Henderson break; 5711633c4283SRichard Henderson case DYNAMIC_PC: 5712633c4283SRichard Henderson may_lookup = false; 5713633c4283SRichard Henderson break; 5714633c4283SRichard Henderson default: 5715633c4283SRichard Henderson g_assert_not_reached(); 5716633c4283SRichard Henderson } 5717633c4283SRichard Henderson } else { 5718633c4283SRichard Henderson tcg_gen_movi_tl(cpu_pc, dc->pc); 5719633c4283SRichard Henderson } 5720633c4283SRichard Henderson 5721930f1865SRichard Henderson if (dc->npc & 3) { 5722930f1865SRichard Henderson switch (dc->npc) { 5723930f1865SRichard Henderson case JUMP_PC: 5724930f1865SRichard Henderson gen_generic_branch(dc); 5725930f1865SRichard Henderson break; 5726930f1865SRichard Henderson case DYNAMIC_PC: 5727930f1865SRichard Henderson may_lookup = false; 5728930f1865SRichard Henderson break; 5729930f1865SRichard Henderson case DYNAMIC_PC_LOOKUP: 5730930f1865SRichard Henderson break; 5731930f1865SRichard Henderson default: 5732930f1865SRichard Henderson g_assert_not_reached(); 5733930f1865SRichard Henderson } 5734930f1865SRichard Henderson } else { 5735930f1865SRichard Henderson tcg_gen_movi_tl(cpu_npc, dc->npc); 5736930f1865SRichard Henderson } 5737633c4283SRichard Henderson if (may_lookup) { 5738633c4283SRichard Henderson tcg_gen_lookup_and_goto_ptr(); 5739633c4283SRichard Henderson } else { 574007ea28b4SRichard Henderson tcg_gen_exit_tb(NULL, 0); 5741fcf5ef2aSThomas Huth } 574246bb0137SMark Cave-Ayland break; 574346bb0137SMark Cave-Ayland 574446bb0137SMark Cave-Ayland case DISAS_NORETURN: 574546bb0137SMark Cave-Ayland break; 574646bb0137SMark Cave-Ayland 574746bb0137SMark Cave-Ayland case DISAS_EXIT: 574846bb0137SMark Cave-Ayland /* Exit TB */ 574946bb0137SMark Cave-Ayland save_state(dc); 575046bb0137SMark Cave-Ayland tcg_gen_exit_tb(NULL, 0); 575146bb0137SMark Cave-Ayland break; 575246bb0137SMark Cave-Ayland 575346bb0137SMark Cave-Ayland default: 575446bb0137SMark Cave-Ayland g_assert_not_reached(); 5755fcf5ef2aSThomas Huth } 5756186e7890SRichard Henderson 5757186e7890SRichard Henderson for (e = dc->delay_excp_list; e ; e = e_next) { 5758186e7890SRichard Henderson gen_set_label(e->lab); 5759186e7890SRichard Henderson 5760186e7890SRichard Henderson tcg_gen_movi_tl(cpu_pc, e->pc); 5761186e7890SRichard Henderson if (e->npc % 4 == 0) { 5762186e7890SRichard Henderson tcg_gen_movi_tl(cpu_npc, e->npc); 5763186e7890SRichard Henderson } 5764186e7890SRichard Henderson gen_helper_raise_exception(tcg_env, e->excp); 5765186e7890SRichard Henderson 5766186e7890SRichard Henderson e_next = e->next; 5767186e7890SRichard Henderson g_free(e); 5768186e7890SRichard Henderson } 5769fcf5ef2aSThomas Huth } 57706e61bc94SEmilio G. Cota 57716e61bc94SEmilio G. Cota static const TranslatorOps sparc_tr_ops = { 57726e61bc94SEmilio G. Cota .init_disas_context = sparc_tr_init_disas_context, 57736e61bc94SEmilio G. Cota .tb_start = sparc_tr_tb_start, 57746e61bc94SEmilio G. Cota .insn_start = sparc_tr_insn_start, 57756e61bc94SEmilio G. Cota .translate_insn = sparc_tr_translate_insn, 57766e61bc94SEmilio G. Cota .tb_stop = sparc_tr_tb_stop, 57776e61bc94SEmilio G. Cota }; 57786e61bc94SEmilio G. Cota 5779597f9b2dSRichard Henderson void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int *max_insns, 578032f0c394SAnton Johansson vaddr pc, void *host_pc) 57816e61bc94SEmilio G. Cota { 57826e61bc94SEmilio G. Cota DisasContext dc = {}; 57836e61bc94SEmilio G. Cota 5784306c8721SRichard Henderson translator_loop(cs, tb, max_insns, pc, host_pc, &sparc_tr_ops, &dc.base); 5785fcf5ef2aSThomas Huth } 5786fcf5ef2aSThomas Huth 578755c3ceefSRichard Henderson void sparc_tcg_init(void) 5788fcf5ef2aSThomas Huth { 5789fcf5ef2aSThomas Huth static const char gregnames[32][4] = { 5790fcf5ef2aSThomas Huth "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7", 5791fcf5ef2aSThomas Huth "o0", "o1", "o2", "o3", "o4", "o5", "o6", "o7", 5792fcf5ef2aSThomas Huth "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7", 5793fcf5ef2aSThomas Huth "i0", "i1", "i2", "i3", "i4", "i5", "i6", "i7", 5794fcf5ef2aSThomas Huth }; 5795fcf5ef2aSThomas Huth 5796d8c5b92fSRichard Henderson static const struct { TCGv_i32 *ptr; int off; const char *name; } r32[] = { 5797d8c5b92fSRichard Henderson #ifdef TARGET_SPARC64 5798d8c5b92fSRichard Henderson { &cpu_fprs, offsetof(CPUSPARCState, fprs), "fprs" }, 5799d8c5b92fSRichard Henderson { &cpu_fcc[0], offsetof(CPUSPARCState, fcc[0]), "fcc0" }, 5800d8c5b92fSRichard Henderson { &cpu_fcc[1], offsetof(CPUSPARCState, fcc[1]), "fcc1" }, 5801d8c5b92fSRichard Henderson { &cpu_fcc[2], offsetof(CPUSPARCState, fcc[2]), "fcc2" }, 5802d8c5b92fSRichard Henderson { &cpu_fcc[3], offsetof(CPUSPARCState, fcc[3]), "fcc3" }, 5803d8c5b92fSRichard Henderson #else 5804d8c5b92fSRichard Henderson { &cpu_fcc[0], offsetof(CPUSPARCState, fcc[0]), "fcc" }, 5805d8c5b92fSRichard Henderson #endif 5806d8c5b92fSRichard Henderson }; 5807d8c5b92fSRichard Henderson 5808fcf5ef2aSThomas Huth static const struct { TCGv *ptr; int off; const char *name; } rtl[] = { 5809fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64 5810fcf5ef2aSThomas Huth { &cpu_gsr, offsetof(CPUSPARCState, gsr), "gsr" }, 58112a1905c7SRichard Henderson { &cpu_xcc_Z, offsetof(CPUSPARCState, xcc_Z), "xcc_Z" }, 58122a1905c7SRichard Henderson { &cpu_xcc_C, offsetof(CPUSPARCState, xcc_C), "xcc_C" }, 5813fcf5ef2aSThomas Huth #endif 58142a1905c7SRichard Henderson { &cpu_cc_N, offsetof(CPUSPARCState, cc_N), "cc_N" }, 58152a1905c7SRichard Henderson { &cpu_cc_V, offsetof(CPUSPARCState, cc_V), "cc_V" }, 58162a1905c7SRichard Henderson { &cpu_icc_Z, offsetof(CPUSPARCState, icc_Z), "icc_Z" }, 58172a1905c7SRichard Henderson { &cpu_icc_C, offsetof(CPUSPARCState, icc_C), "icc_C" }, 5818fcf5ef2aSThomas Huth { &cpu_cond, offsetof(CPUSPARCState, cond), "cond" }, 5819fcf5ef2aSThomas Huth { &cpu_pc, offsetof(CPUSPARCState, pc), "pc" }, 5820fcf5ef2aSThomas Huth { &cpu_npc, offsetof(CPUSPARCState, npc), "npc" }, 5821fcf5ef2aSThomas Huth { &cpu_y, offsetof(CPUSPARCState, y), "y" }, 5822fcf5ef2aSThomas Huth { &cpu_tbr, offsetof(CPUSPARCState, tbr), "tbr" }, 5823fcf5ef2aSThomas Huth }; 5824fcf5ef2aSThomas Huth 5825fcf5ef2aSThomas Huth unsigned int i; 5826fcf5ef2aSThomas Huth 5827ad75a51eSRichard Henderson cpu_regwptr = tcg_global_mem_new_ptr(tcg_env, 5828fcf5ef2aSThomas Huth offsetof(CPUSPARCState, regwptr), 5829fcf5ef2aSThomas Huth "regwptr"); 5830fcf5ef2aSThomas Huth 5831d8c5b92fSRichard Henderson for (i = 0; i < ARRAY_SIZE(r32); ++i) { 5832d8c5b92fSRichard Henderson *r32[i].ptr = tcg_global_mem_new_i32(tcg_env, r32[i].off, r32[i].name); 5833d8c5b92fSRichard Henderson } 5834d8c5b92fSRichard Henderson 5835fcf5ef2aSThomas Huth for (i = 0; i < ARRAY_SIZE(rtl); ++i) { 5836ad75a51eSRichard Henderson *rtl[i].ptr = tcg_global_mem_new(tcg_env, rtl[i].off, rtl[i].name); 5837fcf5ef2aSThomas Huth } 5838fcf5ef2aSThomas Huth 5839f764718dSRichard Henderson cpu_regs[0] = NULL; 5840fcf5ef2aSThomas Huth for (i = 1; i < 8; ++i) { 5841ad75a51eSRichard Henderson cpu_regs[i] = tcg_global_mem_new(tcg_env, 5842fcf5ef2aSThomas Huth offsetof(CPUSPARCState, gregs[i]), 5843fcf5ef2aSThomas Huth gregnames[i]); 5844fcf5ef2aSThomas Huth } 5845fcf5ef2aSThomas Huth 5846fcf5ef2aSThomas Huth for (i = 8; i < 32; ++i) { 5847fcf5ef2aSThomas Huth cpu_regs[i] = tcg_global_mem_new(cpu_regwptr, 5848fcf5ef2aSThomas Huth (i - 8) * sizeof(target_ulong), 5849fcf5ef2aSThomas Huth gregnames[i]); 5850fcf5ef2aSThomas Huth } 5851fcf5ef2aSThomas Huth } 5852fcf5ef2aSThomas Huth 5853f36aaa53SRichard Henderson void sparc_restore_state_to_opc(CPUState *cs, 5854f36aaa53SRichard Henderson const TranslationBlock *tb, 5855f36aaa53SRichard Henderson const uint64_t *data) 5856fcf5ef2aSThomas Huth { 585777976769SPhilippe Mathieu-Daudé CPUSPARCState *env = cpu_env(cs); 5858fcf5ef2aSThomas Huth target_ulong pc = data[0]; 5859fcf5ef2aSThomas Huth target_ulong npc = data[1]; 5860fcf5ef2aSThomas Huth 5861fcf5ef2aSThomas Huth env->pc = pc; 5862fcf5ef2aSThomas Huth if (npc == DYNAMIC_PC) { 5863fcf5ef2aSThomas Huth /* dynamic NPC: already stored */ 5864fcf5ef2aSThomas Huth } else if (npc & JUMP_PC) { 5865fcf5ef2aSThomas Huth /* jump PC: use 'cond' and the jump targets of the translation */ 5866fcf5ef2aSThomas Huth if (env->cond) { 5867fcf5ef2aSThomas Huth env->npc = npc & ~3; 5868fcf5ef2aSThomas Huth } else { 5869fcf5ef2aSThomas Huth env->npc = pc + 4; 5870fcf5ef2aSThomas Huth } 5871fcf5ef2aSThomas Huth } else { 5872fcf5ef2aSThomas Huth env->npc = npc; 5873fcf5ef2aSThomas Huth } 5874fcf5ef2aSThomas Huth } 5875