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" 31*4fd71d19SRichard 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() 64e2fa6bd1SRichard Henderson # define gen_helper_fcmpeq16 ({ qemu_build_not_reached(); NULL; }) 65e2fa6bd1SRichard Henderson # define gen_helper_fcmpeq32 ({ qemu_build_not_reached(); NULL; }) 66e2fa6bd1SRichard Henderson # define gen_helper_fcmpgt16 ({ qemu_build_not_reached(); NULL; }) 67e2fa6bd1SRichard Henderson # define gen_helper_fcmpgt32 ({ qemu_build_not_reached(); NULL; }) 68e2fa6bd1SRichard Henderson # define gen_helper_fcmple16 ({ qemu_build_not_reached(); NULL; }) 69e2fa6bd1SRichard Henderson # define gen_helper_fcmple32 ({ qemu_build_not_reached(); NULL; }) 70e2fa6bd1SRichard Henderson # define gen_helper_fcmpne16 ({ qemu_build_not_reached(); NULL; }) 71e2fa6bd1SRichard Henderson # define gen_helper_fcmpne32 ({ qemu_build_not_reached(); NULL; }) 728aa418b3SRichard Henderson # define gen_helper_fdtox ({ qemu_build_not_reached(); NULL; }) 73e06c9f83SRichard Henderson # define gen_helper_fexpand ({ qemu_build_not_reached(); NULL; }) 74e06c9f83SRichard Henderson # define gen_helper_fmul8sux16 ({ qemu_build_not_reached(); NULL; }) 75e06c9f83SRichard Henderson # define gen_helper_fmul8ulx16 ({ qemu_build_not_reached(); NULL; }) 76e06c9f83SRichard Henderson # define gen_helper_fmul8x16 ({ qemu_build_not_reached(); NULL; }) 77e06c9f83SRichard Henderson # define gen_helper_fpmerge ({ qemu_build_not_reached(); NULL; }) 781617586fSRichard Henderson # define gen_helper_fqtox ({ qemu_build_not_reached(); NULL; }) 79199d43efSRichard Henderson # define gen_helper_fstox ({ qemu_build_not_reached(); NULL; }) 808aa418b3SRichard Henderson # define gen_helper_fxtod ({ qemu_build_not_reached(); NULL; }) 817b8e3e1aSRichard Henderson # define gen_helper_fxtoq ({ qemu_build_not_reached(); NULL; }) 82f4e18df5SRichard Henderson # define gen_helper_fxtos ({ qemu_build_not_reached(); NULL; }) 83afb04344SRichard Henderson # define gen_helper_pdist ({ qemu_build_not_reached(); NULL; }) 84668bb9b7SRichard Henderson # define MAXTL_MASK 0 85af25071cSRichard Henderson #endif 86af25071cSRichard Henderson 87633c4283SRichard Henderson /* Dynamic PC, must exit to main loop. */ 88633c4283SRichard Henderson #define DYNAMIC_PC 1 89633c4283SRichard Henderson /* Dynamic PC, one of two values according to jump_pc[T2]. */ 90633c4283SRichard Henderson #define JUMP_PC 2 91633c4283SRichard Henderson /* Dynamic PC, may lookup next TB. */ 92633c4283SRichard Henderson #define DYNAMIC_PC_LOOKUP 3 93fcf5ef2aSThomas Huth 9446bb0137SMark Cave-Ayland #define DISAS_EXIT DISAS_TARGET_0 9546bb0137SMark Cave-Ayland 96fcf5ef2aSThomas Huth /* global register indexes */ 97fcf5ef2aSThomas Huth static TCGv_ptr cpu_regwptr; 98c9fa8e58SRichard Henderson static TCGv cpu_pc, cpu_npc; 99fcf5ef2aSThomas Huth static TCGv cpu_regs[32]; 100fcf5ef2aSThomas Huth static TCGv cpu_y; 101fcf5ef2aSThomas Huth static TCGv cpu_tbr; 102fcf5ef2aSThomas Huth static TCGv cpu_cond; 1032a1905c7SRichard Henderson static TCGv cpu_cc_N; 1042a1905c7SRichard Henderson static TCGv cpu_cc_V; 1052a1905c7SRichard Henderson static TCGv cpu_icc_Z; 1062a1905c7SRichard Henderson static TCGv cpu_icc_C; 107fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64 1082a1905c7SRichard Henderson static TCGv cpu_xcc_Z; 1092a1905c7SRichard Henderson static TCGv cpu_xcc_C; 1102a1905c7SRichard Henderson static TCGv_i32 cpu_fprs; 111fcf5ef2aSThomas Huth static TCGv cpu_gsr; 112fcf5ef2aSThomas Huth #else 113af25071cSRichard Henderson # define cpu_fprs ({ qemu_build_not_reached(); (TCGv)NULL; }) 114af25071cSRichard Henderson # define cpu_gsr ({ qemu_build_not_reached(); (TCGv)NULL; }) 115fcf5ef2aSThomas Huth #endif 1162a1905c7SRichard Henderson 1172a1905c7SRichard Henderson #ifdef TARGET_SPARC64 1182a1905c7SRichard Henderson #define cpu_cc_Z cpu_xcc_Z 1192a1905c7SRichard Henderson #define cpu_cc_C cpu_xcc_C 1202a1905c7SRichard Henderson #else 1212a1905c7SRichard Henderson #define cpu_cc_Z cpu_icc_Z 1222a1905c7SRichard Henderson #define cpu_cc_C cpu_icc_C 1232a1905c7SRichard Henderson #define cpu_xcc_Z ({ qemu_build_not_reached(); NULL; }) 1242a1905c7SRichard Henderson #define cpu_xcc_C ({ qemu_build_not_reached(); NULL; }) 1252a1905c7SRichard Henderson #endif 1262a1905c7SRichard Henderson 1271210a036SRichard Henderson /* Floating point comparison registers */ 128d8c5b92fSRichard Henderson static TCGv_i32 cpu_fcc[TARGET_FCCREGS]; 129fcf5ef2aSThomas Huth 130af25071cSRichard Henderson #define env_field_offsetof(X) offsetof(CPUSPARCState, X) 131af25071cSRichard Henderson #ifdef TARGET_SPARC64 132cd6269f7SRichard Henderson # define env32_field_offsetof(X) ({ qemu_build_not_reached(); 0; }) 133af25071cSRichard Henderson # define env64_field_offsetof(X) env_field_offsetof(X) 134af25071cSRichard Henderson #else 135cd6269f7SRichard Henderson # define env32_field_offsetof(X) env_field_offsetof(X) 136af25071cSRichard Henderson # define env64_field_offsetof(X) ({ qemu_build_not_reached(); 0; }) 137af25071cSRichard Henderson #endif 138af25071cSRichard Henderson 139533f042fSRichard Henderson typedef struct DisasCompare { 140533f042fSRichard Henderson TCGCond cond; 141533f042fSRichard Henderson TCGv c1; 142533f042fSRichard Henderson int c2; 143533f042fSRichard Henderson } DisasCompare; 144533f042fSRichard Henderson 145186e7890SRichard Henderson typedef struct DisasDelayException { 146186e7890SRichard Henderson struct DisasDelayException *next; 147186e7890SRichard Henderson TCGLabel *lab; 148186e7890SRichard Henderson TCGv_i32 excp; 149186e7890SRichard Henderson /* Saved state at parent insn. */ 150186e7890SRichard Henderson target_ulong pc; 151186e7890SRichard Henderson target_ulong npc; 152186e7890SRichard Henderson } DisasDelayException; 153186e7890SRichard Henderson 154fcf5ef2aSThomas Huth typedef struct DisasContext { 155af00be49SEmilio G. Cota DisasContextBase base; 156fcf5ef2aSThomas Huth target_ulong pc; /* current Program Counter: integer or DYNAMIC_PC */ 157fcf5ef2aSThomas Huth target_ulong npc; /* next PC: integer or DYNAMIC_PC or JUMP_PC */ 158533f042fSRichard Henderson 159533f042fSRichard Henderson /* Used when JUMP_PC value is used. */ 160533f042fSRichard Henderson DisasCompare jump; 161533f042fSRichard Henderson target_ulong jump_pc[2]; 162533f042fSRichard Henderson 163fcf5ef2aSThomas Huth int mem_idx; 16489527e3aSRichard Henderson bool cpu_cond_live; 165c9b459aaSArtyom Tarasenko bool fpu_enabled; 166c9b459aaSArtyom Tarasenko bool address_mask_32bit; 167c9b459aaSArtyom Tarasenko #ifndef CONFIG_USER_ONLY 168c9b459aaSArtyom Tarasenko bool supervisor; 169c9b459aaSArtyom Tarasenko #ifdef TARGET_SPARC64 170c9b459aaSArtyom Tarasenko bool hypervisor; 171c9b459aaSArtyom Tarasenko #endif 172c9b459aaSArtyom Tarasenko #endif 173c9b459aaSArtyom Tarasenko 174fcf5ef2aSThomas Huth sparc_def_t *def; 175fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64 176fcf5ef2aSThomas Huth int fprs_dirty; 177fcf5ef2aSThomas Huth int asi; 178fcf5ef2aSThomas Huth #endif 179186e7890SRichard Henderson DisasDelayException *delay_excp_list; 180fcf5ef2aSThomas Huth } DisasContext; 181fcf5ef2aSThomas Huth 182fcf5ef2aSThomas Huth // This function uses non-native bit order 183fcf5ef2aSThomas Huth #define GET_FIELD(X, FROM, TO) \ 184fcf5ef2aSThomas Huth ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1)) 185fcf5ef2aSThomas Huth 186fcf5ef2aSThomas Huth // This function uses the order in the manuals, i.e. bit 0 is 2^0 187fcf5ef2aSThomas Huth #define GET_FIELD_SP(X, FROM, TO) \ 188fcf5ef2aSThomas Huth GET_FIELD(X, 31 - (TO), 31 - (FROM)) 189fcf5ef2aSThomas Huth 190fcf5ef2aSThomas Huth #define GET_FIELDs(x,a,b) sign_extend (GET_FIELD(x,a,b), (b) - (a) + 1) 191fcf5ef2aSThomas Huth #define GET_FIELD_SPs(x,a,b) sign_extend (GET_FIELD_SP(x,a,b), ((b) - (a) + 1)) 192fcf5ef2aSThomas Huth 193fcf5ef2aSThomas Huth #define UA2005_HTRAP_MASK 0xff 194fcf5ef2aSThomas Huth #define V8_TRAP_MASK 0x7f 195fcf5ef2aSThomas Huth 196fcf5ef2aSThomas Huth #define IS_IMM (insn & (1<<13)) 197fcf5ef2aSThomas Huth 1980c2e96c1SRichard Henderson static void gen_update_fprs_dirty(DisasContext *dc, int rd) 199fcf5ef2aSThomas Huth { 200fcf5ef2aSThomas Huth #if defined(TARGET_SPARC64) 201fcf5ef2aSThomas Huth int bit = (rd < 32) ? 1 : 2; 202fcf5ef2aSThomas Huth /* If we know we've already set this bit within the TB, 203fcf5ef2aSThomas Huth we can avoid setting it again. */ 204fcf5ef2aSThomas Huth if (!(dc->fprs_dirty & bit)) { 205fcf5ef2aSThomas Huth dc->fprs_dirty |= bit; 206fcf5ef2aSThomas Huth tcg_gen_ori_i32(cpu_fprs, cpu_fprs, bit); 207fcf5ef2aSThomas Huth } 208fcf5ef2aSThomas Huth #endif 209fcf5ef2aSThomas Huth } 210fcf5ef2aSThomas Huth 211fcf5ef2aSThomas Huth /* floating point registers moves */ 2121210a036SRichard Henderson 2131210a036SRichard Henderson static int gen_offset_fpr_F(unsigned int reg) 2141210a036SRichard Henderson { 2151210a036SRichard Henderson int ret; 2161210a036SRichard Henderson 2171210a036SRichard Henderson tcg_debug_assert(reg < 32); 2181210a036SRichard Henderson ret= offsetof(CPUSPARCState, fpr[reg / 2]); 2191210a036SRichard Henderson if (reg & 1) { 2201210a036SRichard Henderson ret += offsetof(CPU_DoubleU, l.lower); 2211210a036SRichard Henderson } else { 2221210a036SRichard Henderson ret += offsetof(CPU_DoubleU, l.upper); 2231210a036SRichard Henderson } 2241210a036SRichard Henderson return ret; 2251210a036SRichard Henderson } 2261210a036SRichard Henderson 227fcf5ef2aSThomas Huth static TCGv_i32 gen_load_fpr_F(DisasContext *dc, unsigned int src) 228fcf5ef2aSThomas Huth { 22936ab4623SRichard Henderson TCGv_i32 ret = tcg_temp_new_i32(); 2301210a036SRichard Henderson tcg_gen_ld_i32(ret, tcg_env, gen_offset_fpr_F(src)); 231dc41aa7dSRichard Henderson return ret; 232fcf5ef2aSThomas Huth } 233fcf5ef2aSThomas Huth 234fcf5ef2aSThomas Huth static void gen_store_fpr_F(DisasContext *dc, unsigned int dst, TCGv_i32 v) 235fcf5ef2aSThomas Huth { 2361210a036SRichard Henderson tcg_gen_st_i32(v, tcg_env, gen_offset_fpr_F(dst)); 237fcf5ef2aSThomas Huth gen_update_fprs_dirty(dc, dst); 238fcf5ef2aSThomas Huth } 239fcf5ef2aSThomas Huth 2401210a036SRichard Henderson static int gen_offset_fpr_D(unsigned int reg) 2411210a036SRichard Henderson { 2421210a036SRichard Henderson tcg_debug_assert(reg < 64); 2431210a036SRichard Henderson tcg_debug_assert(reg % 2 == 0); 2441210a036SRichard Henderson return offsetof(CPUSPARCState, fpr[reg / 2]); 2451210a036SRichard Henderson } 2461210a036SRichard Henderson 247fcf5ef2aSThomas Huth static TCGv_i64 gen_load_fpr_D(DisasContext *dc, unsigned int src) 248fcf5ef2aSThomas Huth { 2491210a036SRichard Henderson TCGv_i64 ret = tcg_temp_new_i64(); 2501210a036SRichard Henderson tcg_gen_ld_i64(ret, tcg_env, gen_offset_fpr_D(src)); 2511210a036SRichard Henderson return ret; 252fcf5ef2aSThomas Huth } 253fcf5ef2aSThomas Huth 254fcf5ef2aSThomas Huth static void gen_store_fpr_D(DisasContext *dc, unsigned int dst, TCGv_i64 v) 255fcf5ef2aSThomas Huth { 2561210a036SRichard Henderson tcg_gen_st_i64(v, tcg_env, gen_offset_fpr_D(dst)); 257fcf5ef2aSThomas Huth gen_update_fprs_dirty(dc, dst); 258fcf5ef2aSThomas Huth } 259fcf5ef2aSThomas Huth 26033ec4245SRichard Henderson static TCGv_i128 gen_load_fpr_Q(DisasContext *dc, unsigned int src) 26133ec4245SRichard Henderson { 26233ec4245SRichard Henderson TCGv_i128 ret = tcg_temp_new_i128(); 2631210a036SRichard Henderson TCGv_i64 h = gen_load_fpr_D(dc, src); 2641210a036SRichard Henderson TCGv_i64 l = gen_load_fpr_D(dc, src + 2); 26533ec4245SRichard Henderson 2661210a036SRichard Henderson tcg_gen_concat_i64_i128(ret, l, h); 26733ec4245SRichard Henderson return ret; 26833ec4245SRichard Henderson } 26933ec4245SRichard Henderson 27033ec4245SRichard Henderson static void gen_store_fpr_Q(DisasContext *dc, unsigned int dst, TCGv_i128 v) 27133ec4245SRichard Henderson { 2721210a036SRichard Henderson TCGv_i64 h = tcg_temp_new_i64(); 2731210a036SRichard Henderson TCGv_i64 l = tcg_temp_new_i64(); 2741210a036SRichard Henderson 2751210a036SRichard Henderson tcg_gen_extr_i128_i64(l, h, v); 2761210a036SRichard Henderson gen_store_fpr_D(dc, dst, h); 2771210a036SRichard Henderson gen_store_fpr_D(dc, dst + 2, l); 27833ec4245SRichard Henderson } 27933ec4245SRichard Henderson 280fcf5ef2aSThomas Huth /* moves */ 281fcf5ef2aSThomas Huth #ifdef CONFIG_USER_ONLY 282fcf5ef2aSThomas Huth #define supervisor(dc) 0 283fcf5ef2aSThomas Huth #define hypervisor(dc) 0 284fcf5ef2aSThomas Huth #else 285fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64 286c9b459aaSArtyom Tarasenko #define hypervisor(dc) (dc->hypervisor) 287c9b459aaSArtyom Tarasenko #define supervisor(dc) (dc->supervisor | dc->hypervisor) 288fcf5ef2aSThomas Huth #else 289c9b459aaSArtyom Tarasenko #define supervisor(dc) (dc->supervisor) 290668bb9b7SRichard Henderson #define hypervisor(dc) 0 291fcf5ef2aSThomas Huth #endif 292fcf5ef2aSThomas Huth #endif 293fcf5ef2aSThomas Huth 294b1bc09eaSRichard Henderson #if !defined(TARGET_SPARC64) 295b1bc09eaSRichard Henderson # define AM_CHECK(dc) false 296b1bc09eaSRichard Henderson #elif defined(TARGET_ABI32) 297b1bc09eaSRichard Henderson # define AM_CHECK(dc) true 298b1bc09eaSRichard Henderson #elif defined(CONFIG_USER_ONLY) 299b1bc09eaSRichard Henderson # define AM_CHECK(dc) false 300fcf5ef2aSThomas Huth #else 301b1bc09eaSRichard Henderson # define AM_CHECK(dc) ((dc)->address_mask_32bit) 302fcf5ef2aSThomas Huth #endif 303fcf5ef2aSThomas Huth 3040c2e96c1SRichard Henderson static void gen_address_mask(DisasContext *dc, TCGv addr) 305fcf5ef2aSThomas Huth { 306b1bc09eaSRichard Henderson if (AM_CHECK(dc)) { 307fcf5ef2aSThomas Huth tcg_gen_andi_tl(addr, addr, 0xffffffffULL); 308b1bc09eaSRichard Henderson } 309fcf5ef2aSThomas Huth } 310fcf5ef2aSThomas Huth 31123ada1b1SRichard Henderson static target_ulong address_mask_i(DisasContext *dc, target_ulong addr) 31223ada1b1SRichard Henderson { 31323ada1b1SRichard Henderson return AM_CHECK(dc) ? (uint32_t)addr : addr; 31423ada1b1SRichard Henderson } 31523ada1b1SRichard Henderson 3160c2e96c1SRichard Henderson static TCGv gen_load_gpr(DisasContext *dc, int reg) 317fcf5ef2aSThomas Huth { 318fcf5ef2aSThomas Huth if (reg > 0) { 319fcf5ef2aSThomas Huth assert(reg < 32); 320fcf5ef2aSThomas Huth return cpu_regs[reg]; 321fcf5ef2aSThomas Huth } else { 32252123f14SRichard Henderson TCGv t = tcg_temp_new(); 323fcf5ef2aSThomas Huth tcg_gen_movi_tl(t, 0); 324fcf5ef2aSThomas Huth return t; 325fcf5ef2aSThomas Huth } 326fcf5ef2aSThomas Huth } 327fcf5ef2aSThomas Huth 3280c2e96c1SRichard Henderson static void gen_store_gpr(DisasContext *dc, int reg, TCGv v) 329fcf5ef2aSThomas Huth { 330fcf5ef2aSThomas Huth if (reg > 0) { 331fcf5ef2aSThomas Huth assert(reg < 32); 332fcf5ef2aSThomas Huth tcg_gen_mov_tl(cpu_regs[reg], v); 333fcf5ef2aSThomas Huth } 334fcf5ef2aSThomas Huth } 335fcf5ef2aSThomas Huth 3360c2e96c1SRichard Henderson static TCGv gen_dest_gpr(DisasContext *dc, int reg) 337fcf5ef2aSThomas Huth { 338fcf5ef2aSThomas Huth if (reg > 0) { 339fcf5ef2aSThomas Huth assert(reg < 32); 340fcf5ef2aSThomas Huth return cpu_regs[reg]; 341fcf5ef2aSThomas Huth } else { 34252123f14SRichard Henderson return tcg_temp_new(); 343fcf5ef2aSThomas Huth } 344fcf5ef2aSThomas Huth } 345fcf5ef2aSThomas Huth 3465645aa2eSRichard Henderson static bool use_goto_tb(DisasContext *s, target_ulong pc, target_ulong npc) 347fcf5ef2aSThomas Huth { 3485645aa2eSRichard Henderson return translator_use_goto_tb(&s->base, pc) && 3495645aa2eSRichard Henderson translator_use_goto_tb(&s->base, npc); 350fcf5ef2aSThomas Huth } 351fcf5ef2aSThomas Huth 3525645aa2eSRichard Henderson static void gen_goto_tb(DisasContext *s, int tb_num, 353fcf5ef2aSThomas Huth target_ulong pc, target_ulong npc) 354fcf5ef2aSThomas Huth { 355fcf5ef2aSThomas Huth if (use_goto_tb(s, pc, npc)) { 356fcf5ef2aSThomas Huth /* jump to same page: we can use a direct jump */ 357fcf5ef2aSThomas Huth tcg_gen_goto_tb(tb_num); 358fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_pc, pc); 359fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_npc, npc); 36007ea28b4SRichard Henderson tcg_gen_exit_tb(s->base.tb, tb_num); 361fcf5ef2aSThomas Huth } else { 362f67ccb2fSRichard Henderson /* jump to another page: we can use an indirect jump */ 363fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_pc, pc); 364fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_npc, npc); 365f67ccb2fSRichard Henderson tcg_gen_lookup_and_goto_ptr(); 366fcf5ef2aSThomas Huth } 367fcf5ef2aSThomas Huth } 368fcf5ef2aSThomas Huth 369b989ce73SRichard Henderson static TCGv gen_carry32(void) 370fcf5ef2aSThomas Huth { 371b989ce73SRichard Henderson if (TARGET_LONG_BITS == 64) { 372b989ce73SRichard Henderson TCGv t = tcg_temp_new(); 373b989ce73SRichard Henderson tcg_gen_extract_tl(t, cpu_icc_C, 32, 1); 374b989ce73SRichard Henderson return t; 375b989ce73SRichard Henderson } 376b989ce73SRichard Henderson return cpu_icc_C; 377fcf5ef2aSThomas Huth } 378fcf5ef2aSThomas Huth 379b989ce73SRichard Henderson static void gen_op_addcc_int(TCGv dst, TCGv src1, TCGv src2, TCGv cin) 380fcf5ef2aSThomas Huth { 381b989ce73SRichard Henderson TCGv z = tcg_constant_tl(0); 382fcf5ef2aSThomas Huth 383b989ce73SRichard Henderson if (cin) { 384b989ce73SRichard Henderson tcg_gen_add2_tl(cpu_cc_N, cpu_cc_C, src1, z, cin, z); 385b989ce73SRichard Henderson tcg_gen_add2_tl(cpu_cc_N, cpu_cc_C, cpu_cc_N, cpu_cc_C, src2, z); 386b989ce73SRichard Henderson } else { 387b989ce73SRichard Henderson tcg_gen_add2_tl(cpu_cc_N, cpu_cc_C, src1, z, src2, z); 388b989ce73SRichard Henderson } 389b989ce73SRichard Henderson tcg_gen_xor_tl(cpu_cc_Z, src1, src2); 390b989ce73SRichard Henderson tcg_gen_xor_tl(cpu_cc_V, cpu_cc_N, src2); 391b989ce73SRichard Henderson tcg_gen_andc_tl(cpu_cc_V, cpu_cc_V, cpu_cc_Z); 392b989ce73SRichard Henderson if (TARGET_LONG_BITS == 64) { 393b989ce73SRichard Henderson /* 394b989ce73SRichard Henderson * Carry-in to bit 32 is result ^ src1 ^ src2. 395b989ce73SRichard Henderson * We already have the src xor term in Z, from computation of V. 396b989ce73SRichard Henderson */ 397b989ce73SRichard Henderson tcg_gen_xor_tl(cpu_icc_C, cpu_cc_Z, cpu_cc_N); 398b989ce73SRichard Henderson tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N); 399b989ce73SRichard Henderson } 400b989ce73SRichard Henderson tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N); 401b989ce73SRichard Henderson tcg_gen_mov_tl(dst, cpu_cc_N); 402b989ce73SRichard Henderson } 403fcf5ef2aSThomas Huth 404b989ce73SRichard Henderson static void gen_op_addcc(TCGv dst, TCGv src1, TCGv src2) 405b989ce73SRichard Henderson { 406b989ce73SRichard Henderson gen_op_addcc_int(dst, src1, src2, NULL); 407b989ce73SRichard Henderson } 408fcf5ef2aSThomas Huth 409b989ce73SRichard Henderson static void gen_op_taddcc(TCGv dst, TCGv src1, TCGv src2) 410b989ce73SRichard Henderson { 411b989ce73SRichard Henderson TCGv t = tcg_temp_new(); 412b989ce73SRichard Henderson 413b989ce73SRichard Henderson /* Save the tag bits around modification of dst. */ 414b989ce73SRichard Henderson tcg_gen_or_tl(t, src1, src2); 415b989ce73SRichard Henderson 416b989ce73SRichard Henderson gen_op_addcc(dst, src1, src2); 417b989ce73SRichard Henderson 418b989ce73SRichard Henderson /* Incorprate tag bits into icc.V */ 419b989ce73SRichard Henderson tcg_gen_andi_tl(t, t, 3); 420b989ce73SRichard Henderson tcg_gen_neg_tl(t, t); 421b989ce73SRichard Henderson tcg_gen_ext32u_tl(t, t); 422b989ce73SRichard Henderson tcg_gen_or_tl(cpu_cc_V, cpu_cc_V, t); 423b989ce73SRichard Henderson } 424b989ce73SRichard Henderson 425b989ce73SRichard Henderson static void gen_op_addc(TCGv dst, TCGv src1, TCGv src2) 426b989ce73SRichard Henderson { 427b989ce73SRichard Henderson tcg_gen_add_tl(dst, src1, src2); 428b989ce73SRichard Henderson tcg_gen_add_tl(dst, dst, gen_carry32()); 429b989ce73SRichard Henderson } 430b989ce73SRichard Henderson 431b989ce73SRichard Henderson static void gen_op_addccc(TCGv dst, TCGv src1, TCGv src2) 432b989ce73SRichard Henderson { 433b989ce73SRichard Henderson gen_op_addcc_int(dst, src1, src2, gen_carry32()); 434fcf5ef2aSThomas Huth } 435fcf5ef2aSThomas Huth 436f828df74SRichard Henderson static void gen_op_subcc_int(TCGv dst, TCGv src1, TCGv src2, TCGv cin) 437fcf5ef2aSThomas Huth { 438f828df74SRichard Henderson TCGv z = tcg_constant_tl(0); 439fcf5ef2aSThomas Huth 440f828df74SRichard Henderson if (cin) { 441f828df74SRichard Henderson tcg_gen_sub2_tl(cpu_cc_N, cpu_cc_C, src1, z, cin, z); 442f828df74SRichard Henderson tcg_gen_sub2_tl(cpu_cc_N, cpu_cc_C, cpu_cc_N, cpu_cc_C, src2, z); 443f828df74SRichard Henderson } else { 444f828df74SRichard Henderson tcg_gen_sub2_tl(cpu_cc_N, cpu_cc_C, src1, z, src2, z); 445f828df74SRichard Henderson } 446f828df74SRichard Henderson tcg_gen_neg_tl(cpu_cc_C, cpu_cc_C); 447f828df74SRichard Henderson tcg_gen_xor_tl(cpu_cc_Z, src1, src2); 448f828df74SRichard Henderson tcg_gen_xor_tl(cpu_cc_V, cpu_cc_N, src1); 449f828df74SRichard Henderson tcg_gen_and_tl(cpu_cc_V, cpu_cc_V, cpu_cc_Z); 450f828df74SRichard Henderson #ifdef TARGET_SPARC64 451f828df74SRichard Henderson tcg_gen_xor_tl(cpu_icc_C, cpu_cc_Z, cpu_cc_N); 452f828df74SRichard Henderson tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N); 453fcf5ef2aSThomas Huth #endif 454f828df74SRichard Henderson tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N); 455f828df74SRichard Henderson tcg_gen_mov_tl(dst, cpu_cc_N); 456fcf5ef2aSThomas Huth } 457fcf5ef2aSThomas Huth 458f828df74SRichard Henderson static void gen_op_subcc(TCGv dst, TCGv src1, TCGv src2) 459fcf5ef2aSThomas Huth { 460f828df74SRichard Henderson gen_op_subcc_int(dst, src1, src2, NULL); 461fcf5ef2aSThomas Huth } 462fcf5ef2aSThomas Huth 463f828df74SRichard Henderson static void gen_op_tsubcc(TCGv dst, TCGv src1, TCGv src2) 464fcf5ef2aSThomas Huth { 465f828df74SRichard Henderson TCGv t = tcg_temp_new(); 466fcf5ef2aSThomas Huth 467f828df74SRichard Henderson /* Save the tag bits around modification of dst. */ 468f828df74SRichard Henderson tcg_gen_or_tl(t, src1, src2); 469fcf5ef2aSThomas Huth 470f828df74SRichard Henderson gen_op_subcc(dst, src1, src2); 471f828df74SRichard Henderson 472f828df74SRichard Henderson /* Incorprate tag bits into icc.V */ 473f828df74SRichard Henderson tcg_gen_andi_tl(t, t, 3); 474f828df74SRichard Henderson tcg_gen_neg_tl(t, t); 475f828df74SRichard Henderson tcg_gen_ext32u_tl(t, t); 476f828df74SRichard Henderson tcg_gen_or_tl(cpu_cc_V, cpu_cc_V, t); 477f828df74SRichard Henderson } 478f828df74SRichard Henderson 479f828df74SRichard Henderson static void gen_op_subc(TCGv dst, TCGv src1, TCGv src2) 480f828df74SRichard Henderson { 481fcf5ef2aSThomas Huth tcg_gen_sub_tl(dst, src1, src2); 482f828df74SRichard Henderson tcg_gen_sub_tl(dst, dst, gen_carry32()); 483fcf5ef2aSThomas Huth } 484fcf5ef2aSThomas Huth 485f828df74SRichard Henderson static void gen_op_subccc(TCGv dst, TCGv src1, TCGv src2) 486dfebb950SRichard Henderson { 487f828df74SRichard Henderson gen_op_subcc_int(dst, src1, src2, gen_carry32()); 488dfebb950SRichard Henderson } 489dfebb950SRichard Henderson 4900c2e96c1SRichard Henderson static void gen_op_mulscc(TCGv dst, TCGv src1, TCGv src2) 491fcf5ef2aSThomas Huth { 492b989ce73SRichard Henderson TCGv zero = tcg_constant_tl(0); 49350280618SRichard Henderson TCGv one = tcg_constant_tl(1); 494b989ce73SRichard Henderson TCGv t_src1 = tcg_temp_new(); 495b989ce73SRichard Henderson TCGv t_src2 = tcg_temp_new(); 496b989ce73SRichard Henderson TCGv t0 = tcg_temp_new(); 497fcf5ef2aSThomas Huth 498b989ce73SRichard Henderson tcg_gen_ext32u_tl(t_src1, src1); 499b989ce73SRichard Henderson tcg_gen_ext32u_tl(t_src2, src2); 500fcf5ef2aSThomas Huth 501b989ce73SRichard Henderson /* 502b989ce73SRichard Henderson * if (!(env->y & 1)) 503b989ce73SRichard Henderson * src2 = 0; 504fcf5ef2aSThomas Huth */ 50550280618SRichard Henderson tcg_gen_movcond_tl(TCG_COND_TSTEQ, t_src2, cpu_y, one, zero, t_src2); 506fcf5ef2aSThomas Huth 507b989ce73SRichard Henderson /* 508b989ce73SRichard Henderson * b2 = src1 & 1; 509b989ce73SRichard Henderson * y = (b2 << 31) | (y >> 1); 510b989ce73SRichard Henderson */ 5110b1183e3SPhilippe Mathieu-Daudé tcg_gen_extract_tl(t0, cpu_y, 1, 31); 512b989ce73SRichard Henderson tcg_gen_deposit_tl(cpu_y, t0, src1, 31, 1); 513fcf5ef2aSThomas Huth 514fcf5ef2aSThomas Huth // b1 = N ^ V; 5152a1905c7SRichard Henderson tcg_gen_xor_tl(t0, cpu_cc_N, cpu_cc_V); 516fcf5ef2aSThomas Huth 517b989ce73SRichard Henderson /* 518b989ce73SRichard Henderson * src1 = (b1 << 31) | (src1 >> 1) 519b989ce73SRichard Henderson */ 5202a1905c7SRichard Henderson tcg_gen_andi_tl(t0, t0, 1u << 31); 521b989ce73SRichard Henderson tcg_gen_shri_tl(t_src1, t_src1, 1); 522b989ce73SRichard Henderson tcg_gen_or_tl(t_src1, t_src1, t0); 523fcf5ef2aSThomas Huth 524b989ce73SRichard Henderson gen_op_addcc(dst, t_src1, t_src2); 525fcf5ef2aSThomas Huth } 526fcf5ef2aSThomas Huth 5270c2e96c1SRichard Henderson static void gen_op_multiply(TCGv dst, TCGv src1, TCGv src2, int sign_ext) 528fcf5ef2aSThomas Huth { 529fcf5ef2aSThomas Huth #if TARGET_LONG_BITS == 32 530fcf5ef2aSThomas Huth if (sign_ext) { 531fcf5ef2aSThomas Huth tcg_gen_muls2_tl(dst, cpu_y, src1, src2); 532fcf5ef2aSThomas Huth } else { 533fcf5ef2aSThomas Huth tcg_gen_mulu2_tl(dst, cpu_y, src1, src2); 534fcf5ef2aSThomas Huth } 535fcf5ef2aSThomas Huth #else 536fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new_i64(); 537fcf5ef2aSThomas Huth TCGv t1 = tcg_temp_new_i64(); 538fcf5ef2aSThomas Huth 539fcf5ef2aSThomas Huth if (sign_ext) { 540fcf5ef2aSThomas Huth tcg_gen_ext32s_i64(t0, src1); 541fcf5ef2aSThomas Huth tcg_gen_ext32s_i64(t1, src2); 542fcf5ef2aSThomas Huth } else { 543fcf5ef2aSThomas Huth tcg_gen_ext32u_i64(t0, src1); 544fcf5ef2aSThomas Huth tcg_gen_ext32u_i64(t1, src2); 545fcf5ef2aSThomas Huth } 546fcf5ef2aSThomas Huth 547fcf5ef2aSThomas Huth tcg_gen_mul_i64(dst, t0, t1); 548fcf5ef2aSThomas Huth tcg_gen_shri_i64(cpu_y, dst, 32); 549fcf5ef2aSThomas Huth #endif 550fcf5ef2aSThomas Huth } 551fcf5ef2aSThomas Huth 5520c2e96c1SRichard Henderson static void gen_op_umul(TCGv dst, TCGv src1, TCGv src2) 553fcf5ef2aSThomas Huth { 554fcf5ef2aSThomas Huth /* zero-extend truncated operands before multiplication */ 555fcf5ef2aSThomas Huth gen_op_multiply(dst, src1, src2, 0); 556fcf5ef2aSThomas Huth } 557fcf5ef2aSThomas Huth 5580c2e96c1SRichard Henderson static void gen_op_smul(TCGv dst, TCGv src1, TCGv src2) 559fcf5ef2aSThomas Huth { 560fcf5ef2aSThomas Huth /* sign-extend truncated operands before multiplication */ 561fcf5ef2aSThomas Huth gen_op_multiply(dst, src1, src2, 1); 562fcf5ef2aSThomas Huth } 563fcf5ef2aSThomas Huth 564c2636853SRichard Henderson static void gen_op_sdiv(TCGv dst, TCGv src1, TCGv src2) 565c2636853SRichard Henderson { 56613260103SRichard Henderson #ifdef TARGET_SPARC64 567c2636853SRichard Henderson gen_helper_sdiv(dst, tcg_env, src1, src2); 56813260103SRichard Henderson tcg_gen_ext32s_tl(dst, dst); 56913260103SRichard Henderson #else 57013260103SRichard Henderson TCGv_i64 t64 = tcg_temp_new_i64(); 57113260103SRichard Henderson gen_helper_sdiv(t64, tcg_env, src1, src2); 57213260103SRichard Henderson tcg_gen_trunc_i64_tl(dst, t64); 57313260103SRichard Henderson #endif 574c2636853SRichard Henderson } 575c2636853SRichard Henderson 576c2636853SRichard Henderson static void gen_op_udivcc(TCGv dst, TCGv src1, TCGv src2) 577c2636853SRichard Henderson { 57813260103SRichard Henderson TCGv_i64 t64; 57913260103SRichard Henderson 58013260103SRichard Henderson #ifdef TARGET_SPARC64 58113260103SRichard Henderson t64 = cpu_cc_V; 58213260103SRichard Henderson #else 58313260103SRichard Henderson t64 = tcg_temp_new_i64(); 58413260103SRichard Henderson #endif 58513260103SRichard Henderson 58613260103SRichard Henderson gen_helper_udiv(t64, tcg_env, src1, src2); 58713260103SRichard Henderson 58813260103SRichard Henderson #ifdef TARGET_SPARC64 58913260103SRichard Henderson tcg_gen_ext32u_tl(cpu_cc_N, t64); 59013260103SRichard Henderson tcg_gen_shri_tl(cpu_cc_V, t64, 32); 59113260103SRichard Henderson tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N); 59213260103SRichard Henderson tcg_gen_movi_tl(cpu_icc_C, 0); 59313260103SRichard Henderson #else 59413260103SRichard Henderson tcg_gen_extr_i64_tl(cpu_cc_N, cpu_cc_V, t64); 59513260103SRichard Henderson #endif 59613260103SRichard Henderson tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N); 59713260103SRichard Henderson tcg_gen_movi_tl(cpu_cc_C, 0); 59813260103SRichard Henderson tcg_gen_mov_tl(dst, cpu_cc_N); 599c2636853SRichard Henderson } 600c2636853SRichard Henderson 601c2636853SRichard Henderson static void gen_op_sdivcc(TCGv dst, TCGv src1, TCGv src2) 602c2636853SRichard Henderson { 60313260103SRichard Henderson TCGv_i64 t64; 60413260103SRichard Henderson 60513260103SRichard Henderson #ifdef TARGET_SPARC64 60613260103SRichard Henderson t64 = cpu_cc_V; 60713260103SRichard Henderson #else 60813260103SRichard Henderson t64 = tcg_temp_new_i64(); 60913260103SRichard Henderson #endif 61013260103SRichard Henderson 61113260103SRichard Henderson gen_helper_sdiv(t64, tcg_env, src1, src2); 61213260103SRichard Henderson 61313260103SRichard Henderson #ifdef TARGET_SPARC64 61413260103SRichard Henderson tcg_gen_ext32s_tl(cpu_cc_N, t64); 61513260103SRichard Henderson tcg_gen_shri_tl(cpu_cc_V, t64, 32); 61613260103SRichard Henderson tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N); 61713260103SRichard Henderson tcg_gen_movi_tl(cpu_icc_C, 0); 61813260103SRichard Henderson #else 61913260103SRichard Henderson tcg_gen_extr_i64_tl(cpu_cc_N, cpu_cc_V, t64); 62013260103SRichard Henderson #endif 62113260103SRichard Henderson tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N); 62213260103SRichard Henderson tcg_gen_movi_tl(cpu_cc_C, 0); 62313260103SRichard Henderson tcg_gen_mov_tl(dst, cpu_cc_N); 624c2636853SRichard Henderson } 625c2636853SRichard Henderson 626a9aba13dSRichard Henderson static void gen_op_taddcctv(TCGv dst, TCGv src1, TCGv src2) 627a9aba13dSRichard Henderson { 628a9aba13dSRichard Henderson gen_helper_taddcctv(dst, tcg_env, src1, src2); 629a9aba13dSRichard Henderson } 630a9aba13dSRichard Henderson 631a9aba13dSRichard Henderson static void gen_op_tsubcctv(TCGv dst, TCGv src1, TCGv src2) 632a9aba13dSRichard Henderson { 633a9aba13dSRichard Henderson gen_helper_tsubcctv(dst, tcg_env, src1, src2); 634a9aba13dSRichard Henderson } 635a9aba13dSRichard Henderson 6369c6ec5bcSRichard Henderson static void gen_op_popc(TCGv dst, TCGv src1, TCGv src2) 6379c6ec5bcSRichard Henderson { 6389c6ec5bcSRichard Henderson tcg_gen_ctpop_tl(dst, src2); 6399c6ec5bcSRichard Henderson } 6409c6ec5bcSRichard Henderson 64145bfed3bSRichard Henderson #ifndef TARGET_SPARC64 64245bfed3bSRichard Henderson static void gen_helper_array8(TCGv dst, TCGv src1, TCGv src2) 64345bfed3bSRichard Henderson { 64445bfed3bSRichard Henderson g_assert_not_reached(); 64545bfed3bSRichard Henderson } 64645bfed3bSRichard Henderson #endif 64745bfed3bSRichard Henderson 64845bfed3bSRichard Henderson static void gen_op_array16(TCGv dst, TCGv src1, TCGv src2) 64945bfed3bSRichard Henderson { 65045bfed3bSRichard Henderson gen_helper_array8(dst, src1, src2); 65145bfed3bSRichard Henderson tcg_gen_shli_tl(dst, dst, 1); 65245bfed3bSRichard Henderson } 65345bfed3bSRichard Henderson 65445bfed3bSRichard Henderson static void gen_op_array32(TCGv dst, TCGv src1, TCGv src2) 65545bfed3bSRichard Henderson { 65645bfed3bSRichard Henderson gen_helper_array8(dst, src1, src2); 65745bfed3bSRichard Henderson tcg_gen_shli_tl(dst, dst, 2); 65845bfed3bSRichard Henderson } 65945bfed3bSRichard Henderson 6602f722641SRichard Henderson static void gen_op_fpack16(TCGv_i32 dst, TCGv_i64 src) 6612f722641SRichard Henderson { 6622f722641SRichard Henderson #ifdef TARGET_SPARC64 6632f722641SRichard Henderson gen_helper_fpack16(dst, cpu_gsr, src); 6642f722641SRichard Henderson #else 6652f722641SRichard Henderson g_assert_not_reached(); 6662f722641SRichard Henderson #endif 6672f722641SRichard Henderson } 6682f722641SRichard Henderson 6692f722641SRichard Henderson static void gen_op_fpackfix(TCGv_i32 dst, TCGv_i64 src) 6702f722641SRichard Henderson { 6712f722641SRichard Henderson #ifdef TARGET_SPARC64 6722f722641SRichard Henderson gen_helper_fpackfix(dst, cpu_gsr, src); 6732f722641SRichard Henderson #else 6742f722641SRichard Henderson g_assert_not_reached(); 6752f722641SRichard Henderson #endif 6762f722641SRichard Henderson } 6772f722641SRichard Henderson 6784b6edc0aSRichard Henderson static void gen_op_fpack32(TCGv_i64 dst, TCGv_i64 src1, TCGv_i64 src2) 6794b6edc0aSRichard Henderson { 6804b6edc0aSRichard Henderson #ifdef TARGET_SPARC64 6814b6edc0aSRichard Henderson gen_helper_fpack32(dst, cpu_gsr, src1, src2); 6824b6edc0aSRichard Henderson #else 6834b6edc0aSRichard Henderson g_assert_not_reached(); 6844b6edc0aSRichard Henderson #endif 6854b6edc0aSRichard Henderson } 6864b6edc0aSRichard Henderson 6874b6edc0aSRichard Henderson static void gen_op_faligndata(TCGv_i64 dst, TCGv_i64 s1, TCGv_i64 s2) 6884b6edc0aSRichard Henderson { 6894b6edc0aSRichard Henderson #ifdef TARGET_SPARC64 6904b6edc0aSRichard Henderson TCGv t1, t2, shift; 6914b6edc0aSRichard Henderson 6924b6edc0aSRichard Henderson t1 = tcg_temp_new(); 6934b6edc0aSRichard Henderson t2 = tcg_temp_new(); 6944b6edc0aSRichard Henderson shift = tcg_temp_new(); 6954b6edc0aSRichard Henderson 6964b6edc0aSRichard Henderson tcg_gen_andi_tl(shift, cpu_gsr, 7); 6974b6edc0aSRichard Henderson tcg_gen_shli_tl(shift, shift, 3); 6984b6edc0aSRichard Henderson tcg_gen_shl_tl(t1, s1, shift); 6994b6edc0aSRichard Henderson 7004b6edc0aSRichard Henderson /* 7014b6edc0aSRichard Henderson * A shift of 64 does not produce 0 in TCG. Divide this into a 7024b6edc0aSRichard Henderson * shift of (up to 63) followed by a constant shift of 1. 7034b6edc0aSRichard Henderson */ 7044b6edc0aSRichard Henderson tcg_gen_xori_tl(shift, shift, 63); 7054b6edc0aSRichard Henderson tcg_gen_shr_tl(t2, s2, shift); 7064b6edc0aSRichard Henderson tcg_gen_shri_tl(t2, t2, 1); 7074b6edc0aSRichard Henderson 7084b6edc0aSRichard Henderson tcg_gen_or_tl(dst, t1, t2); 7094b6edc0aSRichard Henderson #else 7104b6edc0aSRichard Henderson g_assert_not_reached(); 7114b6edc0aSRichard Henderson #endif 7124b6edc0aSRichard Henderson } 7134b6edc0aSRichard Henderson 7144b6edc0aSRichard Henderson static void gen_op_bshuffle(TCGv_i64 dst, TCGv_i64 src1, TCGv_i64 src2) 7154b6edc0aSRichard Henderson { 7164b6edc0aSRichard Henderson #ifdef TARGET_SPARC64 7174b6edc0aSRichard Henderson gen_helper_bshuffle(dst, cpu_gsr, src1, src2); 7184b6edc0aSRichard Henderson #else 7194b6edc0aSRichard Henderson g_assert_not_reached(); 7204b6edc0aSRichard Henderson #endif 7214b6edc0aSRichard Henderson } 7224b6edc0aSRichard Henderson 723a859602cSRichard Henderson static void gen_op_fmul8x16al(TCGv_i64 dst, TCGv_i32 src1, TCGv_i32 src2) 724a859602cSRichard Henderson { 725a859602cSRichard Henderson tcg_gen_ext16s_i32(src2, src2); 726a859602cSRichard Henderson gen_helper_fmul8x16a(dst, src1, src2); 727a859602cSRichard Henderson } 728a859602cSRichard Henderson 729a859602cSRichard Henderson static void gen_op_fmul8x16au(TCGv_i64 dst, TCGv_i32 src1, TCGv_i32 src2) 730a859602cSRichard Henderson { 731a859602cSRichard Henderson tcg_gen_sari_i32(src2, src2, 16); 732a859602cSRichard Henderson gen_helper_fmul8x16a(dst, src1, src2); 733a859602cSRichard Henderson } 734a859602cSRichard Henderson 735be8998e0SRichard Henderson static void gen_op_fmuld8ulx16(TCGv_i64 dst, TCGv_i32 src1, TCGv_i32 src2) 736be8998e0SRichard Henderson { 737be8998e0SRichard Henderson TCGv_i32 t0 = tcg_temp_new_i32(); 738be8998e0SRichard Henderson TCGv_i32 t1 = tcg_temp_new_i32(); 739be8998e0SRichard Henderson TCGv_i32 t2 = tcg_temp_new_i32(); 740be8998e0SRichard Henderson 741be8998e0SRichard Henderson tcg_gen_ext8u_i32(t0, src1); 742be8998e0SRichard Henderson tcg_gen_ext16s_i32(t1, src2); 743be8998e0SRichard Henderson tcg_gen_mul_i32(t0, t0, t1); 744be8998e0SRichard Henderson 745be8998e0SRichard Henderson tcg_gen_extract_i32(t1, src1, 16, 8); 746be8998e0SRichard Henderson tcg_gen_sextract_i32(t2, src2, 16, 16); 747be8998e0SRichard Henderson tcg_gen_mul_i32(t1, t1, t2); 748be8998e0SRichard Henderson 749be8998e0SRichard Henderson tcg_gen_concat_i32_i64(dst, t0, t1); 750be8998e0SRichard Henderson } 751be8998e0SRichard Henderson 752be8998e0SRichard Henderson static void gen_op_fmuld8sux16(TCGv_i64 dst, TCGv_i32 src1, TCGv_i32 src2) 753be8998e0SRichard Henderson { 754be8998e0SRichard Henderson TCGv_i32 t0 = tcg_temp_new_i32(); 755be8998e0SRichard Henderson TCGv_i32 t1 = tcg_temp_new_i32(); 756be8998e0SRichard Henderson TCGv_i32 t2 = tcg_temp_new_i32(); 757be8998e0SRichard Henderson 758be8998e0SRichard Henderson /* 759be8998e0SRichard Henderson * The insn description talks about extracting the upper 8 bits 760be8998e0SRichard Henderson * of the signed 16-bit input rs1, performing the multiply, then 761be8998e0SRichard Henderson * shifting left by 8 bits. Instead, zap the lower 8 bits of 762be8998e0SRichard Henderson * the rs1 input, which avoids the need for two shifts. 763be8998e0SRichard Henderson */ 764be8998e0SRichard Henderson tcg_gen_ext16s_i32(t0, src1); 765be8998e0SRichard Henderson tcg_gen_andi_i32(t0, t0, ~0xff); 766be8998e0SRichard Henderson tcg_gen_ext16s_i32(t1, src2); 767be8998e0SRichard Henderson tcg_gen_mul_i32(t0, t0, t1); 768be8998e0SRichard Henderson 769be8998e0SRichard Henderson tcg_gen_sextract_i32(t1, src1, 16, 16); 770be8998e0SRichard Henderson tcg_gen_andi_i32(t1, t1, ~0xff); 771be8998e0SRichard Henderson tcg_gen_sextract_i32(t2, src2, 16, 16); 772be8998e0SRichard Henderson tcg_gen_mul_i32(t1, t1, t2); 773be8998e0SRichard Henderson 774be8998e0SRichard Henderson tcg_gen_concat_i32_i64(dst, t0, t1); 775be8998e0SRichard Henderson } 776be8998e0SRichard Henderson 77789527e3aSRichard Henderson static void finishing_insn(DisasContext *dc) 77889527e3aSRichard Henderson { 77989527e3aSRichard Henderson /* 78089527e3aSRichard Henderson * From here, there is no future path through an unwinding exception. 78189527e3aSRichard Henderson * If the current insn cannot raise an exception, the computation of 78289527e3aSRichard Henderson * cpu_cond may be able to be elided. 78389527e3aSRichard Henderson */ 78489527e3aSRichard Henderson if (dc->cpu_cond_live) { 78589527e3aSRichard Henderson tcg_gen_discard_tl(cpu_cond); 78689527e3aSRichard Henderson dc->cpu_cond_live = false; 78789527e3aSRichard Henderson } 78889527e3aSRichard Henderson } 78989527e3aSRichard Henderson 7900c2e96c1SRichard Henderson static void gen_generic_branch(DisasContext *dc) 791fcf5ef2aSThomas Huth { 79200ab7e61SRichard Henderson TCGv npc0 = tcg_constant_tl(dc->jump_pc[0]); 79300ab7e61SRichard Henderson TCGv npc1 = tcg_constant_tl(dc->jump_pc[1]); 794533f042fSRichard Henderson TCGv c2 = tcg_constant_tl(dc->jump.c2); 795fcf5ef2aSThomas Huth 796533f042fSRichard Henderson tcg_gen_movcond_tl(dc->jump.cond, cpu_npc, dc->jump.c1, c2, npc0, npc1); 797fcf5ef2aSThomas Huth } 798fcf5ef2aSThomas Huth 799fcf5ef2aSThomas Huth /* call this function before using the condition register as it may 800fcf5ef2aSThomas Huth have been set for a jump */ 8010c2e96c1SRichard Henderson static void flush_cond(DisasContext *dc) 802fcf5ef2aSThomas Huth { 803fcf5ef2aSThomas Huth if (dc->npc == JUMP_PC) { 804fcf5ef2aSThomas Huth gen_generic_branch(dc); 80599c82c47SRichard Henderson dc->npc = DYNAMIC_PC_LOOKUP; 806fcf5ef2aSThomas Huth } 807fcf5ef2aSThomas Huth } 808fcf5ef2aSThomas Huth 8090c2e96c1SRichard Henderson static void save_npc(DisasContext *dc) 810fcf5ef2aSThomas Huth { 811633c4283SRichard Henderson if (dc->npc & 3) { 812633c4283SRichard Henderson switch (dc->npc) { 813633c4283SRichard Henderson case JUMP_PC: 814fcf5ef2aSThomas Huth gen_generic_branch(dc); 81599c82c47SRichard Henderson dc->npc = DYNAMIC_PC_LOOKUP; 816633c4283SRichard Henderson break; 817633c4283SRichard Henderson case DYNAMIC_PC: 818633c4283SRichard Henderson case DYNAMIC_PC_LOOKUP: 819633c4283SRichard Henderson break; 820633c4283SRichard Henderson default: 821633c4283SRichard Henderson g_assert_not_reached(); 822633c4283SRichard Henderson } 823633c4283SRichard Henderson } else { 824fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_npc, dc->npc); 825fcf5ef2aSThomas Huth } 826fcf5ef2aSThomas Huth } 827fcf5ef2aSThomas Huth 8280c2e96c1SRichard Henderson static void save_state(DisasContext *dc) 829fcf5ef2aSThomas Huth { 830fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_pc, dc->pc); 831fcf5ef2aSThomas Huth save_npc(dc); 832fcf5ef2aSThomas Huth } 833fcf5ef2aSThomas Huth 834fcf5ef2aSThomas Huth static void gen_exception(DisasContext *dc, int which) 835fcf5ef2aSThomas Huth { 83689527e3aSRichard Henderson finishing_insn(dc); 837fcf5ef2aSThomas Huth save_state(dc); 838ad75a51eSRichard Henderson gen_helper_raise_exception(tcg_env, tcg_constant_i32(which)); 839af00be49SEmilio G. Cota dc->base.is_jmp = DISAS_NORETURN; 840fcf5ef2aSThomas Huth } 841fcf5ef2aSThomas Huth 842186e7890SRichard Henderson static TCGLabel *delay_exceptionv(DisasContext *dc, TCGv_i32 excp) 843fcf5ef2aSThomas Huth { 844186e7890SRichard Henderson DisasDelayException *e = g_new0(DisasDelayException, 1); 845186e7890SRichard Henderson 846186e7890SRichard Henderson e->next = dc->delay_excp_list; 847186e7890SRichard Henderson dc->delay_excp_list = e; 848186e7890SRichard Henderson 849186e7890SRichard Henderson e->lab = gen_new_label(); 850186e7890SRichard Henderson e->excp = excp; 851186e7890SRichard Henderson e->pc = dc->pc; 852186e7890SRichard Henderson /* Caller must have used flush_cond before branch. */ 853186e7890SRichard Henderson assert(e->npc != JUMP_PC); 854186e7890SRichard Henderson e->npc = dc->npc; 855186e7890SRichard Henderson 856186e7890SRichard Henderson return e->lab; 857186e7890SRichard Henderson } 858186e7890SRichard Henderson 859186e7890SRichard Henderson static TCGLabel *delay_exception(DisasContext *dc, int excp) 860186e7890SRichard Henderson { 861186e7890SRichard Henderson return delay_exceptionv(dc, tcg_constant_i32(excp)); 862186e7890SRichard Henderson } 863186e7890SRichard Henderson 864186e7890SRichard Henderson static void gen_check_align(DisasContext *dc, TCGv addr, int mask) 865186e7890SRichard Henderson { 866186e7890SRichard Henderson TCGv t = tcg_temp_new(); 867186e7890SRichard Henderson TCGLabel *lab; 868186e7890SRichard Henderson 869186e7890SRichard Henderson tcg_gen_andi_tl(t, addr, mask); 870186e7890SRichard Henderson 871186e7890SRichard Henderson flush_cond(dc); 872186e7890SRichard Henderson lab = delay_exception(dc, TT_UNALIGNED); 873186e7890SRichard Henderson tcg_gen_brcondi_tl(TCG_COND_NE, t, 0, lab); 874fcf5ef2aSThomas Huth } 875fcf5ef2aSThomas Huth 8760c2e96c1SRichard Henderson static void gen_mov_pc_npc(DisasContext *dc) 877fcf5ef2aSThomas Huth { 87889527e3aSRichard Henderson finishing_insn(dc); 87989527e3aSRichard Henderson 880633c4283SRichard Henderson if (dc->npc & 3) { 881633c4283SRichard Henderson switch (dc->npc) { 882633c4283SRichard Henderson case JUMP_PC: 883fcf5ef2aSThomas Huth gen_generic_branch(dc); 884fcf5ef2aSThomas Huth tcg_gen_mov_tl(cpu_pc, cpu_npc); 88599c82c47SRichard Henderson dc->pc = DYNAMIC_PC_LOOKUP; 886633c4283SRichard Henderson break; 887633c4283SRichard Henderson case DYNAMIC_PC: 888633c4283SRichard Henderson case DYNAMIC_PC_LOOKUP: 889fcf5ef2aSThomas Huth tcg_gen_mov_tl(cpu_pc, cpu_npc); 890633c4283SRichard Henderson dc->pc = dc->npc; 891633c4283SRichard Henderson break; 892633c4283SRichard Henderson default: 893633c4283SRichard Henderson g_assert_not_reached(); 894633c4283SRichard Henderson } 895fcf5ef2aSThomas Huth } else { 896fcf5ef2aSThomas Huth dc->pc = dc->npc; 897fcf5ef2aSThomas Huth } 898fcf5ef2aSThomas Huth } 899fcf5ef2aSThomas Huth 900fcf5ef2aSThomas Huth static void gen_compare(DisasCompare *cmp, bool xcc, unsigned int cond, 901fcf5ef2aSThomas Huth DisasContext *dc) 902fcf5ef2aSThomas Huth { 903b597eedcSRichard Henderson TCGv t1; 904fcf5ef2aSThomas Huth 9052a1905c7SRichard Henderson cmp->c1 = t1 = tcg_temp_new(); 906c8507ebfSRichard Henderson cmp->c2 = 0; 9072a1905c7SRichard Henderson 9082a1905c7SRichard Henderson switch (cond & 7) { 9092a1905c7SRichard Henderson case 0x0: /* never */ 9102a1905c7SRichard Henderson cmp->cond = TCG_COND_NEVER; 911c8507ebfSRichard Henderson cmp->c1 = tcg_constant_tl(0); 912fcf5ef2aSThomas Huth break; 9132a1905c7SRichard Henderson 9142a1905c7SRichard Henderson case 0x1: /* eq: Z */ 9152a1905c7SRichard Henderson cmp->cond = TCG_COND_EQ; 9162a1905c7SRichard Henderson if (TARGET_LONG_BITS == 32 || xcc) { 9172a1905c7SRichard Henderson tcg_gen_mov_tl(t1, cpu_cc_Z); 9182a1905c7SRichard Henderson } else { 9192a1905c7SRichard Henderson tcg_gen_ext32u_tl(t1, cpu_icc_Z); 9202a1905c7SRichard Henderson } 9212a1905c7SRichard Henderson break; 9222a1905c7SRichard Henderson 9232a1905c7SRichard Henderson case 0x2: /* le: Z | (N ^ V) */ 9242a1905c7SRichard Henderson /* 9252a1905c7SRichard Henderson * Simplify: 9262a1905c7SRichard Henderson * cc_Z || (N ^ V) < 0 NE 9272a1905c7SRichard Henderson * cc_Z && !((N ^ V) < 0) EQ 9282a1905c7SRichard Henderson * cc_Z & ~((N ^ V) >> TLB) EQ 9292a1905c7SRichard Henderson */ 9302a1905c7SRichard Henderson cmp->cond = TCG_COND_EQ; 9312a1905c7SRichard Henderson tcg_gen_xor_tl(t1, cpu_cc_N, cpu_cc_V); 9322a1905c7SRichard Henderson tcg_gen_sextract_tl(t1, t1, xcc ? 63 : 31, 1); 9332a1905c7SRichard Henderson tcg_gen_andc_tl(t1, xcc ? cpu_cc_Z : cpu_icc_Z, t1); 9342a1905c7SRichard Henderson if (TARGET_LONG_BITS == 64 && !xcc) { 9352a1905c7SRichard Henderson tcg_gen_ext32u_tl(t1, t1); 9362a1905c7SRichard Henderson } 9372a1905c7SRichard Henderson break; 9382a1905c7SRichard Henderson 9392a1905c7SRichard Henderson case 0x3: /* lt: N ^ V */ 9402a1905c7SRichard Henderson cmp->cond = TCG_COND_LT; 9412a1905c7SRichard Henderson tcg_gen_xor_tl(t1, cpu_cc_N, cpu_cc_V); 9422a1905c7SRichard Henderson if (TARGET_LONG_BITS == 64 && !xcc) { 9432a1905c7SRichard Henderson tcg_gen_ext32s_tl(t1, t1); 9442a1905c7SRichard Henderson } 9452a1905c7SRichard Henderson break; 9462a1905c7SRichard Henderson 9472a1905c7SRichard Henderson case 0x4: /* leu: Z | C */ 9482a1905c7SRichard Henderson /* 9492a1905c7SRichard Henderson * Simplify: 9502a1905c7SRichard Henderson * cc_Z == 0 || cc_C != 0 NE 9512a1905c7SRichard Henderson * cc_Z != 0 && cc_C == 0 EQ 9522a1905c7SRichard Henderson * cc_Z & (cc_C ? 0 : -1) EQ 9532a1905c7SRichard Henderson * cc_Z & (cc_C - 1) EQ 9542a1905c7SRichard Henderson */ 9552a1905c7SRichard Henderson cmp->cond = TCG_COND_EQ; 9562a1905c7SRichard Henderson if (TARGET_LONG_BITS == 32 || xcc) { 9572a1905c7SRichard Henderson tcg_gen_subi_tl(t1, cpu_cc_C, 1); 9582a1905c7SRichard Henderson tcg_gen_and_tl(t1, t1, cpu_cc_Z); 9592a1905c7SRichard Henderson } else { 9602a1905c7SRichard Henderson tcg_gen_extract_tl(t1, cpu_icc_C, 32, 1); 9612a1905c7SRichard Henderson tcg_gen_subi_tl(t1, t1, 1); 9622a1905c7SRichard Henderson tcg_gen_and_tl(t1, t1, cpu_icc_Z); 9632a1905c7SRichard Henderson tcg_gen_ext32u_tl(t1, t1); 9642a1905c7SRichard Henderson } 9652a1905c7SRichard Henderson break; 9662a1905c7SRichard Henderson 9672a1905c7SRichard Henderson case 0x5: /* ltu: C */ 9682a1905c7SRichard Henderson cmp->cond = TCG_COND_NE; 9692a1905c7SRichard Henderson if (TARGET_LONG_BITS == 32 || xcc) { 9702a1905c7SRichard Henderson tcg_gen_mov_tl(t1, cpu_cc_C); 9712a1905c7SRichard Henderson } else { 9722a1905c7SRichard Henderson tcg_gen_extract_tl(t1, cpu_icc_C, 32, 1); 9732a1905c7SRichard Henderson } 9742a1905c7SRichard Henderson break; 9752a1905c7SRichard Henderson 9762a1905c7SRichard Henderson case 0x6: /* neg: N */ 9772a1905c7SRichard Henderson cmp->cond = TCG_COND_LT; 9782a1905c7SRichard Henderson if (TARGET_LONG_BITS == 32 || xcc) { 9792a1905c7SRichard Henderson tcg_gen_mov_tl(t1, cpu_cc_N); 9802a1905c7SRichard Henderson } else { 9812a1905c7SRichard Henderson tcg_gen_ext32s_tl(t1, cpu_cc_N); 9822a1905c7SRichard Henderson } 9832a1905c7SRichard Henderson break; 9842a1905c7SRichard Henderson 9852a1905c7SRichard Henderson case 0x7: /* vs: V */ 9862a1905c7SRichard Henderson cmp->cond = TCG_COND_LT; 9872a1905c7SRichard Henderson if (TARGET_LONG_BITS == 32 || xcc) { 9882a1905c7SRichard Henderson tcg_gen_mov_tl(t1, cpu_cc_V); 9892a1905c7SRichard Henderson } else { 9902a1905c7SRichard Henderson tcg_gen_ext32s_tl(t1, cpu_cc_V); 9912a1905c7SRichard Henderson } 9922a1905c7SRichard Henderson break; 9932a1905c7SRichard Henderson } 9942a1905c7SRichard Henderson if (cond & 8) { 9952a1905c7SRichard Henderson cmp->cond = tcg_invert_cond(cmp->cond); 996fcf5ef2aSThomas Huth } 997fcf5ef2aSThomas Huth } 998fcf5ef2aSThomas Huth 999fcf5ef2aSThomas Huth static void gen_fcompare(DisasCompare *cmp, unsigned int cc, unsigned int cond) 1000fcf5ef2aSThomas Huth { 1001d8c5b92fSRichard Henderson TCGv_i32 fcc = cpu_fcc[cc]; 1002d8c5b92fSRichard Henderson TCGv_i32 c1 = fcc; 1003d8c5b92fSRichard Henderson int c2 = 0; 1004d8c5b92fSRichard Henderson TCGCond tcond; 1005fcf5ef2aSThomas Huth 1006d8c5b92fSRichard Henderson /* 1007d8c5b92fSRichard Henderson * FCC values: 1008d8c5b92fSRichard Henderson * 0 = 1009d8c5b92fSRichard Henderson * 1 < 1010d8c5b92fSRichard Henderson * 2 > 1011d8c5b92fSRichard Henderson * 3 unordered 1012d8c5b92fSRichard Henderson */ 1013d8c5b92fSRichard Henderson switch (cond & 7) { 1014d8c5b92fSRichard Henderson case 0x0: /* fbn */ 1015d8c5b92fSRichard Henderson tcond = TCG_COND_NEVER; 1016fcf5ef2aSThomas Huth break; 1017d8c5b92fSRichard Henderson case 0x1: /* fbne : !0 */ 1018d8c5b92fSRichard Henderson tcond = TCG_COND_NE; 1019fcf5ef2aSThomas Huth break; 1020d8c5b92fSRichard Henderson case 0x2: /* fblg : 1 or 2 */ 1021d8c5b92fSRichard Henderson /* fcc in {1,2} - 1 -> fcc in {0,1} */ 1022d8c5b92fSRichard Henderson c1 = tcg_temp_new_i32(); 1023d8c5b92fSRichard Henderson tcg_gen_addi_i32(c1, fcc, -1); 1024d8c5b92fSRichard Henderson c2 = 1; 1025d8c5b92fSRichard Henderson tcond = TCG_COND_LEU; 1026fcf5ef2aSThomas Huth break; 1027d8c5b92fSRichard Henderson case 0x3: /* fbul : 1 or 3 */ 1028d8c5b92fSRichard Henderson c1 = tcg_temp_new_i32(); 1029d8c5b92fSRichard Henderson tcg_gen_andi_i32(c1, fcc, 1); 1030d8c5b92fSRichard Henderson tcond = TCG_COND_NE; 1031d8c5b92fSRichard Henderson break; 1032d8c5b92fSRichard Henderson case 0x4: /* fbl : 1 */ 1033d8c5b92fSRichard Henderson c2 = 1; 1034d8c5b92fSRichard Henderson tcond = TCG_COND_EQ; 1035d8c5b92fSRichard Henderson break; 1036d8c5b92fSRichard Henderson case 0x5: /* fbug : 2 or 3 */ 1037d8c5b92fSRichard Henderson c2 = 2; 1038d8c5b92fSRichard Henderson tcond = TCG_COND_GEU; 1039d8c5b92fSRichard Henderson break; 1040d8c5b92fSRichard Henderson case 0x6: /* fbg : 2 */ 1041d8c5b92fSRichard Henderson c2 = 2; 1042d8c5b92fSRichard Henderson tcond = TCG_COND_EQ; 1043d8c5b92fSRichard Henderson break; 1044d8c5b92fSRichard Henderson case 0x7: /* fbu : 3 */ 1045d8c5b92fSRichard Henderson c2 = 3; 1046d8c5b92fSRichard Henderson tcond = TCG_COND_EQ; 1047fcf5ef2aSThomas Huth break; 1048fcf5ef2aSThomas Huth } 1049d8c5b92fSRichard Henderson if (cond & 8) { 1050d8c5b92fSRichard Henderson tcond = tcg_invert_cond(tcond); 1051fcf5ef2aSThomas Huth } 1052d8c5b92fSRichard Henderson 1053d8c5b92fSRichard Henderson cmp->cond = tcond; 1054d8c5b92fSRichard Henderson cmp->c2 = c2; 1055d8c5b92fSRichard Henderson cmp->c1 = tcg_temp_new(); 1056d8c5b92fSRichard Henderson tcg_gen_extu_i32_tl(cmp->c1, c1); 1057fcf5ef2aSThomas Huth } 1058fcf5ef2aSThomas Huth 10592c4f56c9SRichard Henderson static bool gen_compare_reg(DisasCompare *cmp, int cond, TCGv r_src) 10602c4f56c9SRichard Henderson { 10612c4f56c9SRichard Henderson static const TCGCond cond_reg[4] = { 1062ab9ffe98SRichard Henderson TCG_COND_NEVER, /* reserved */ 1063fcf5ef2aSThomas Huth TCG_COND_EQ, 1064fcf5ef2aSThomas Huth TCG_COND_LE, 1065fcf5ef2aSThomas Huth TCG_COND_LT, 1066fcf5ef2aSThomas Huth }; 10672c4f56c9SRichard Henderson TCGCond tcond; 1068fcf5ef2aSThomas Huth 10692c4f56c9SRichard Henderson if ((cond & 3) == 0) { 10702c4f56c9SRichard Henderson return false; 10712c4f56c9SRichard Henderson } 10722c4f56c9SRichard Henderson tcond = cond_reg[cond & 3]; 10732c4f56c9SRichard Henderson if (cond & 4) { 10742c4f56c9SRichard Henderson tcond = tcg_invert_cond(tcond); 10752c4f56c9SRichard Henderson } 10762c4f56c9SRichard Henderson 10772c4f56c9SRichard Henderson cmp->cond = tcond; 1078816f89b7SRichard Henderson cmp->c1 = tcg_temp_new(); 1079c8507ebfSRichard Henderson cmp->c2 = 0; 1080816f89b7SRichard Henderson tcg_gen_mov_tl(cmp->c1, r_src); 10812c4f56c9SRichard Henderson return true; 1082fcf5ef2aSThomas Huth } 1083fcf5ef2aSThomas Huth 1084baf3dbf2SRichard Henderson static void gen_op_clear_ieee_excp_and_FTT(void) 1085baf3dbf2SRichard Henderson { 10863590f01eSRichard Henderson tcg_gen_st_i32(tcg_constant_i32(0), tcg_env, 10873590f01eSRichard Henderson offsetof(CPUSPARCState, fsr_cexc_ftt)); 1088baf3dbf2SRichard Henderson } 1089baf3dbf2SRichard Henderson 1090baf3dbf2SRichard Henderson static void gen_op_fmovs(TCGv_i32 dst, TCGv_i32 src) 1091baf3dbf2SRichard Henderson { 1092baf3dbf2SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 1093baf3dbf2SRichard Henderson tcg_gen_mov_i32(dst, src); 1094baf3dbf2SRichard Henderson } 1095baf3dbf2SRichard Henderson 1096baf3dbf2SRichard Henderson static void gen_op_fnegs(TCGv_i32 dst, TCGv_i32 src) 1097baf3dbf2SRichard Henderson { 1098baf3dbf2SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 1099daf457d4SRichard Henderson tcg_gen_xori_i32(dst, src, 1u << 31); 1100baf3dbf2SRichard Henderson } 1101baf3dbf2SRichard Henderson 1102baf3dbf2SRichard Henderson static void gen_op_fabss(TCGv_i32 dst, TCGv_i32 src) 1103baf3dbf2SRichard Henderson { 1104baf3dbf2SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 1105daf457d4SRichard Henderson tcg_gen_andi_i32(dst, src, ~(1u << 31)); 1106baf3dbf2SRichard Henderson } 1107baf3dbf2SRichard Henderson 1108c6d83e4fSRichard Henderson static void gen_op_fmovd(TCGv_i64 dst, TCGv_i64 src) 1109c6d83e4fSRichard Henderson { 1110c6d83e4fSRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 1111c6d83e4fSRichard Henderson tcg_gen_mov_i64(dst, src); 1112c6d83e4fSRichard Henderson } 1113c6d83e4fSRichard Henderson 1114c6d83e4fSRichard Henderson static void gen_op_fnegd(TCGv_i64 dst, TCGv_i64 src) 1115c6d83e4fSRichard Henderson { 1116c6d83e4fSRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 1117daf457d4SRichard Henderson tcg_gen_xori_i64(dst, src, 1ull << 63); 1118c6d83e4fSRichard Henderson } 1119c6d83e4fSRichard Henderson 1120c6d83e4fSRichard Henderson static void gen_op_fabsd(TCGv_i64 dst, TCGv_i64 src) 1121c6d83e4fSRichard Henderson { 1122c6d83e4fSRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 1123daf457d4SRichard Henderson tcg_gen_andi_i64(dst, src, ~(1ull << 63)); 1124daf457d4SRichard Henderson } 1125daf457d4SRichard Henderson 1126daf457d4SRichard Henderson static void gen_op_fnegq(TCGv_i128 dst, TCGv_i128 src) 1127daf457d4SRichard Henderson { 1128daf457d4SRichard Henderson TCGv_i64 l = tcg_temp_new_i64(); 1129daf457d4SRichard Henderson TCGv_i64 h = tcg_temp_new_i64(); 1130daf457d4SRichard Henderson 1131daf457d4SRichard Henderson tcg_gen_extr_i128_i64(l, h, src); 1132daf457d4SRichard Henderson tcg_gen_xori_i64(h, h, 1ull << 63); 1133daf457d4SRichard Henderson tcg_gen_concat_i64_i128(dst, l, h); 1134daf457d4SRichard Henderson } 1135daf457d4SRichard Henderson 1136daf457d4SRichard Henderson static void gen_op_fabsq(TCGv_i128 dst, TCGv_i128 src) 1137daf457d4SRichard Henderson { 1138daf457d4SRichard Henderson TCGv_i64 l = tcg_temp_new_i64(); 1139daf457d4SRichard Henderson TCGv_i64 h = tcg_temp_new_i64(); 1140daf457d4SRichard Henderson 1141daf457d4SRichard Henderson tcg_gen_extr_i128_i64(l, h, src); 1142daf457d4SRichard Henderson tcg_gen_andi_i64(h, h, ~(1ull << 63)); 1143daf457d4SRichard Henderson tcg_gen_concat_i64_i128(dst, l, h); 1144c6d83e4fSRichard Henderson } 1145c6d83e4fSRichard Henderson 1146*4fd71d19SRichard Henderson static void gen_op_fmadds(TCGv_i32 d, TCGv_i32 s1, TCGv_i32 s2, TCGv_i32 s3) 1147*4fd71d19SRichard Henderson { 1148*4fd71d19SRichard Henderson gen_helper_fmadds(d, tcg_env, s1, s2, s3, tcg_constant_i32(0)); 1149*4fd71d19SRichard Henderson } 1150*4fd71d19SRichard Henderson 1151*4fd71d19SRichard Henderson static void gen_op_fmaddd(TCGv_i64 d, TCGv_i64 s1, TCGv_i64 s2, TCGv_i64 s3) 1152*4fd71d19SRichard Henderson { 1153*4fd71d19SRichard Henderson gen_helper_fmaddd(d, tcg_env, s1, s2, s3, tcg_constant_i32(0)); 1154*4fd71d19SRichard Henderson } 1155*4fd71d19SRichard Henderson 1156*4fd71d19SRichard Henderson static void gen_op_fmsubs(TCGv_i32 d, TCGv_i32 s1, TCGv_i32 s2, TCGv_i32 s3) 1157*4fd71d19SRichard Henderson { 1158*4fd71d19SRichard Henderson int op = float_muladd_negate_c; 1159*4fd71d19SRichard Henderson gen_helper_fmadds(d, tcg_env, s1, s2, s3, tcg_constant_i32(op)); 1160*4fd71d19SRichard Henderson } 1161*4fd71d19SRichard Henderson 1162*4fd71d19SRichard Henderson static void gen_op_fmsubd(TCGv_i64 d, TCGv_i64 s1, TCGv_i64 s2, TCGv_i64 s3) 1163*4fd71d19SRichard Henderson { 1164*4fd71d19SRichard Henderson int op = float_muladd_negate_c; 1165*4fd71d19SRichard Henderson gen_helper_fmaddd(d, tcg_env, s1, s2, s3, tcg_constant_i32(op)); 1166*4fd71d19SRichard Henderson } 1167*4fd71d19SRichard Henderson 1168*4fd71d19SRichard Henderson static void gen_op_fnmsubs(TCGv_i32 d, TCGv_i32 s1, TCGv_i32 s2, TCGv_i32 s3) 1169*4fd71d19SRichard Henderson { 1170*4fd71d19SRichard Henderson int op = float_muladd_negate_c | float_muladd_negate_result; 1171*4fd71d19SRichard Henderson gen_helper_fmadds(d, tcg_env, s1, s2, s3, tcg_constant_i32(op)); 1172*4fd71d19SRichard Henderson } 1173*4fd71d19SRichard Henderson 1174*4fd71d19SRichard Henderson static void gen_op_fnmsubd(TCGv_i64 d, TCGv_i64 s1, TCGv_i64 s2, TCGv_i64 s3) 1175*4fd71d19SRichard Henderson { 1176*4fd71d19SRichard Henderson int op = float_muladd_negate_c | float_muladd_negate_result; 1177*4fd71d19SRichard Henderson gen_helper_fmaddd(d, tcg_env, s1, s2, s3, tcg_constant_i32(op)); 1178*4fd71d19SRichard Henderson } 1179*4fd71d19SRichard Henderson 1180*4fd71d19SRichard Henderson static void gen_op_fnmadds(TCGv_i32 d, TCGv_i32 s1, TCGv_i32 s2, TCGv_i32 s3) 1181*4fd71d19SRichard Henderson { 1182*4fd71d19SRichard Henderson int op = float_muladd_negate_result; 1183*4fd71d19SRichard Henderson gen_helper_fmadds(d, tcg_env, s1, s2, s3, tcg_constant_i32(op)); 1184*4fd71d19SRichard Henderson } 1185*4fd71d19SRichard Henderson 1186*4fd71d19SRichard Henderson static void gen_op_fnmaddd(TCGv_i64 d, TCGv_i64 s1, TCGv_i64 s2, TCGv_i64 s3) 1187*4fd71d19SRichard Henderson { 1188*4fd71d19SRichard Henderson int op = float_muladd_negate_result; 1189*4fd71d19SRichard Henderson gen_helper_fmaddd(d, tcg_env, s1, s2, s3, tcg_constant_i32(op)); 1190*4fd71d19SRichard Henderson } 1191*4fd71d19SRichard Henderson 11923590f01eSRichard Henderson static void gen_op_fpexception_im(DisasContext *dc, int ftt) 1193fcf5ef2aSThomas Huth { 11943590f01eSRichard Henderson /* 11953590f01eSRichard Henderson * CEXC is only set when succesfully completing an FPop, 11963590f01eSRichard Henderson * or when raising FSR_FTT_IEEE_EXCP, i.e. check_ieee_exception. 11973590f01eSRichard Henderson * Thus we can simply store FTT into this field. 11983590f01eSRichard Henderson */ 11993590f01eSRichard Henderson tcg_gen_st_i32(tcg_constant_i32(ftt), tcg_env, 12003590f01eSRichard Henderson offsetof(CPUSPARCState, fsr_cexc_ftt)); 1201fcf5ef2aSThomas Huth gen_exception(dc, TT_FP_EXCP); 1202fcf5ef2aSThomas Huth } 1203fcf5ef2aSThomas Huth 1204fcf5ef2aSThomas Huth static int gen_trap_ifnofpu(DisasContext *dc) 1205fcf5ef2aSThomas Huth { 1206fcf5ef2aSThomas Huth #if !defined(CONFIG_USER_ONLY) 1207fcf5ef2aSThomas Huth if (!dc->fpu_enabled) { 1208fcf5ef2aSThomas Huth gen_exception(dc, TT_NFPU_INSN); 1209fcf5ef2aSThomas Huth return 1; 1210fcf5ef2aSThomas Huth } 1211fcf5ef2aSThomas Huth #endif 1212fcf5ef2aSThomas Huth return 0; 1213fcf5ef2aSThomas Huth } 1214fcf5ef2aSThomas Huth 1215fcf5ef2aSThomas Huth /* asi moves */ 1216fcf5ef2aSThomas Huth typedef enum { 1217fcf5ef2aSThomas Huth GET_ASI_HELPER, 1218fcf5ef2aSThomas Huth GET_ASI_EXCP, 1219fcf5ef2aSThomas Huth GET_ASI_DIRECT, 1220fcf5ef2aSThomas Huth GET_ASI_DTWINX, 12212786a3f8SRichard Henderson GET_ASI_CODE, 1222fcf5ef2aSThomas Huth GET_ASI_BLOCK, 1223fcf5ef2aSThomas Huth GET_ASI_SHORT, 1224fcf5ef2aSThomas Huth GET_ASI_BCOPY, 1225fcf5ef2aSThomas Huth GET_ASI_BFILL, 1226fcf5ef2aSThomas Huth } ASIType; 1227fcf5ef2aSThomas Huth 1228fcf5ef2aSThomas Huth typedef struct { 1229fcf5ef2aSThomas Huth ASIType type; 1230fcf5ef2aSThomas Huth int asi; 1231fcf5ef2aSThomas Huth int mem_idx; 123214776ab5STony Nguyen MemOp memop; 1233fcf5ef2aSThomas Huth } DisasASI; 1234fcf5ef2aSThomas Huth 1235811cc0b0SRichard Henderson /* 1236811cc0b0SRichard Henderson * Build DisasASI. 1237811cc0b0SRichard Henderson * For asi == -1, treat as non-asi. 1238811cc0b0SRichard Henderson * For ask == -2, treat as immediate offset (v8 error, v9 %asi). 1239811cc0b0SRichard Henderson */ 1240811cc0b0SRichard Henderson static DisasASI resolve_asi(DisasContext *dc, int asi, MemOp memop) 1241fcf5ef2aSThomas Huth { 1242fcf5ef2aSThomas Huth ASIType type = GET_ASI_HELPER; 1243fcf5ef2aSThomas Huth int mem_idx = dc->mem_idx; 1244fcf5ef2aSThomas Huth 1245811cc0b0SRichard Henderson if (asi == -1) { 1246811cc0b0SRichard Henderson /* Artificial "non-asi" case. */ 1247811cc0b0SRichard Henderson type = GET_ASI_DIRECT; 1248811cc0b0SRichard Henderson goto done; 1249811cc0b0SRichard Henderson } 1250811cc0b0SRichard Henderson 1251fcf5ef2aSThomas Huth #ifndef TARGET_SPARC64 1252fcf5ef2aSThomas Huth /* Before v9, all asis are immediate and privileged. */ 1253811cc0b0SRichard Henderson if (asi < 0) { 1254fcf5ef2aSThomas Huth gen_exception(dc, TT_ILL_INSN); 1255fcf5ef2aSThomas Huth type = GET_ASI_EXCP; 1256fcf5ef2aSThomas Huth } else if (supervisor(dc) 1257fcf5ef2aSThomas Huth /* Note that LEON accepts ASI_USERDATA in user mode, for 1258fcf5ef2aSThomas Huth use with CASA. Also note that previous versions of 1259fcf5ef2aSThomas Huth QEMU allowed (and old versions of gcc emitted) ASI_P 1260fcf5ef2aSThomas Huth for LEON, which is incorrect. */ 1261fcf5ef2aSThomas Huth || (asi == ASI_USERDATA 1262fcf5ef2aSThomas Huth && (dc->def->features & CPU_FEATURE_CASA))) { 1263fcf5ef2aSThomas Huth switch (asi) { 1264fcf5ef2aSThomas Huth case ASI_USERDATA: /* User data access */ 1265fcf5ef2aSThomas Huth mem_idx = MMU_USER_IDX; 1266fcf5ef2aSThomas Huth type = GET_ASI_DIRECT; 1267fcf5ef2aSThomas Huth break; 1268fcf5ef2aSThomas Huth case ASI_KERNELDATA: /* Supervisor data access */ 1269fcf5ef2aSThomas Huth mem_idx = MMU_KERNEL_IDX; 1270fcf5ef2aSThomas Huth type = GET_ASI_DIRECT; 1271fcf5ef2aSThomas Huth break; 12722786a3f8SRichard Henderson case ASI_USERTXT: /* User text access */ 12732786a3f8SRichard Henderson mem_idx = MMU_USER_IDX; 12742786a3f8SRichard Henderson type = GET_ASI_CODE; 12752786a3f8SRichard Henderson break; 12762786a3f8SRichard Henderson case ASI_KERNELTXT: /* Supervisor text access */ 12772786a3f8SRichard Henderson mem_idx = MMU_KERNEL_IDX; 12782786a3f8SRichard Henderson type = GET_ASI_CODE; 12792786a3f8SRichard Henderson break; 1280fcf5ef2aSThomas Huth case ASI_M_BYPASS: /* MMU passthrough */ 1281fcf5ef2aSThomas Huth case ASI_LEON_BYPASS: /* LEON MMU passthrough */ 1282fcf5ef2aSThomas Huth mem_idx = MMU_PHYS_IDX; 1283fcf5ef2aSThomas Huth type = GET_ASI_DIRECT; 1284fcf5ef2aSThomas Huth break; 1285fcf5ef2aSThomas Huth case ASI_M_BCOPY: /* Block copy, sta access */ 1286fcf5ef2aSThomas Huth mem_idx = MMU_KERNEL_IDX; 1287fcf5ef2aSThomas Huth type = GET_ASI_BCOPY; 1288fcf5ef2aSThomas Huth break; 1289fcf5ef2aSThomas Huth case ASI_M_BFILL: /* Block fill, stda access */ 1290fcf5ef2aSThomas Huth mem_idx = MMU_KERNEL_IDX; 1291fcf5ef2aSThomas Huth type = GET_ASI_BFILL; 1292fcf5ef2aSThomas Huth break; 1293fcf5ef2aSThomas Huth } 12946e10f37cSKONRAD Frederic 12956e10f37cSKONRAD Frederic /* MMU_PHYS_IDX is used when the MMU is disabled to passthrough the 12966e10f37cSKONRAD Frederic * permissions check in get_physical_address(..). 12976e10f37cSKONRAD Frederic */ 12986e10f37cSKONRAD Frederic mem_idx = (dc->mem_idx == MMU_PHYS_IDX) ? MMU_PHYS_IDX : mem_idx; 1299fcf5ef2aSThomas Huth } else { 1300fcf5ef2aSThomas Huth gen_exception(dc, TT_PRIV_INSN); 1301fcf5ef2aSThomas Huth type = GET_ASI_EXCP; 1302fcf5ef2aSThomas Huth } 1303fcf5ef2aSThomas Huth #else 1304811cc0b0SRichard Henderson if (asi < 0) { 1305fcf5ef2aSThomas Huth asi = dc->asi; 1306fcf5ef2aSThomas Huth } 1307fcf5ef2aSThomas Huth /* With v9, all asis below 0x80 are privileged. */ 1308fcf5ef2aSThomas Huth /* ??? We ought to check cpu_has_hypervisor, but we didn't copy 1309fcf5ef2aSThomas Huth down that bit into DisasContext. For the moment that's ok, 1310fcf5ef2aSThomas Huth since the direct implementations below doesn't have any ASIs 1311fcf5ef2aSThomas Huth in the restricted [0x30, 0x7f] range, and the check will be 1312fcf5ef2aSThomas Huth done properly in the helper. */ 1313fcf5ef2aSThomas Huth if (!supervisor(dc) && asi < 0x80) { 1314fcf5ef2aSThomas Huth gen_exception(dc, TT_PRIV_ACT); 1315fcf5ef2aSThomas Huth type = GET_ASI_EXCP; 1316fcf5ef2aSThomas Huth } else { 1317fcf5ef2aSThomas Huth switch (asi) { 1318fcf5ef2aSThomas Huth case ASI_REAL: /* Bypass */ 1319fcf5ef2aSThomas Huth case ASI_REAL_IO: /* Bypass, non-cacheable */ 1320fcf5ef2aSThomas Huth case ASI_REAL_L: /* Bypass LE */ 1321fcf5ef2aSThomas Huth case ASI_REAL_IO_L: /* Bypass, non-cacheable LE */ 1322fcf5ef2aSThomas Huth case ASI_TWINX_REAL: /* Real address, twinx */ 1323fcf5ef2aSThomas Huth case ASI_TWINX_REAL_L: /* Real address, twinx, LE */ 1324fcf5ef2aSThomas Huth case ASI_QUAD_LDD_PHYS: 1325fcf5ef2aSThomas Huth case ASI_QUAD_LDD_PHYS_L: 1326fcf5ef2aSThomas Huth mem_idx = MMU_PHYS_IDX; 1327fcf5ef2aSThomas Huth break; 1328fcf5ef2aSThomas Huth case ASI_N: /* Nucleus */ 1329fcf5ef2aSThomas Huth case ASI_NL: /* Nucleus LE */ 1330fcf5ef2aSThomas Huth case ASI_TWINX_N: 1331fcf5ef2aSThomas Huth case ASI_TWINX_NL: 1332fcf5ef2aSThomas Huth case ASI_NUCLEUS_QUAD_LDD: 1333fcf5ef2aSThomas Huth case ASI_NUCLEUS_QUAD_LDD_L: 13349a10756dSArtyom Tarasenko if (hypervisor(dc)) { 133584f8f587SArtyom Tarasenko mem_idx = MMU_PHYS_IDX; 13369a10756dSArtyom Tarasenko } else { 1337fcf5ef2aSThomas Huth mem_idx = MMU_NUCLEUS_IDX; 13389a10756dSArtyom Tarasenko } 1339fcf5ef2aSThomas Huth break; 1340fcf5ef2aSThomas Huth case ASI_AIUP: /* As if user primary */ 1341fcf5ef2aSThomas Huth case ASI_AIUPL: /* As if user primary LE */ 1342fcf5ef2aSThomas Huth case ASI_TWINX_AIUP: 1343fcf5ef2aSThomas Huth case ASI_TWINX_AIUP_L: 1344fcf5ef2aSThomas Huth case ASI_BLK_AIUP_4V: 1345fcf5ef2aSThomas Huth case ASI_BLK_AIUP_L_4V: 1346fcf5ef2aSThomas Huth case ASI_BLK_AIUP: 1347fcf5ef2aSThomas Huth case ASI_BLK_AIUPL: 1348fcf5ef2aSThomas Huth mem_idx = MMU_USER_IDX; 1349fcf5ef2aSThomas Huth break; 1350fcf5ef2aSThomas Huth case ASI_AIUS: /* As if user secondary */ 1351fcf5ef2aSThomas Huth case ASI_AIUSL: /* As if user secondary LE */ 1352fcf5ef2aSThomas Huth case ASI_TWINX_AIUS: 1353fcf5ef2aSThomas Huth case ASI_TWINX_AIUS_L: 1354fcf5ef2aSThomas Huth case ASI_BLK_AIUS_4V: 1355fcf5ef2aSThomas Huth case ASI_BLK_AIUS_L_4V: 1356fcf5ef2aSThomas Huth case ASI_BLK_AIUS: 1357fcf5ef2aSThomas Huth case ASI_BLK_AIUSL: 1358fcf5ef2aSThomas Huth mem_idx = MMU_USER_SECONDARY_IDX; 1359fcf5ef2aSThomas Huth break; 1360fcf5ef2aSThomas Huth case ASI_S: /* Secondary */ 1361fcf5ef2aSThomas Huth case ASI_SL: /* Secondary LE */ 1362fcf5ef2aSThomas Huth case ASI_TWINX_S: 1363fcf5ef2aSThomas Huth case ASI_TWINX_SL: 1364fcf5ef2aSThomas Huth case ASI_BLK_COMMIT_S: 1365fcf5ef2aSThomas Huth case ASI_BLK_S: 1366fcf5ef2aSThomas Huth case ASI_BLK_SL: 1367fcf5ef2aSThomas Huth case ASI_FL8_S: 1368fcf5ef2aSThomas Huth case ASI_FL8_SL: 1369fcf5ef2aSThomas Huth case ASI_FL16_S: 1370fcf5ef2aSThomas Huth case ASI_FL16_SL: 1371fcf5ef2aSThomas Huth if (mem_idx == MMU_USER_IDX) { 1372fcf5ef2aSThomas Huth mem_idx = MMU_USER_SECONDARY_IDX; 1373fcf5ef2aSThomas Huth } else if (mem_idx == MMU_KERNEL_IDX) { 1374fcf5ef2aSThomas Huth mem_idx = MMU_KERNEL_SECONDARY_IDX; 1375fcf5ef2aSThomas Huth } 1376fcf5ef2aSThomas Huth break; 1377fcf5ef2aSThomas Huth case ASI_P: /* Primary */ 1378fcf5ef2aSThomas Huth case ASI_PL: /* Primary LE */ 1379fcf5ef2aSThomas Huth case ASI_TWINX_P: 1380fcf5ef2aSThomas Huth case ASI_TWINX_PL: 1381fcf5ef2aSThomas Huth case ASI_BLK_COMMIT_P: 1382fcf5ef2aSThomas Huth case ASI_BLK_P: 1383fcf5ef2aSThomas Huth case ASI_BLK_PL: 1384fcf5ef2aSThomas Huth case ASI_FL8_P: 1385fcf5ef2aSThomas Huth case ASI_FL8_PL: 1386fcf5ef2aSThomas Huth case ASI_FL16_P: 1387fcf5ef2aSThomas Huth case ASI_FL16_PL: 1388fcf5ef2aSThomas Huth break; 1389fcf5ef2aSThomas Huth } 1390fcf5ef2aSThomas Huth switch (asi) { 1391fcf5ef2aSThomas Huth case ASI_REAL: 1392fcf5ef2aSThomas Huth case ASI_REAL_IO: 1393fcf5ef2aSThomas Huth case ASI_REAL_L: 1394fcf5ef2aSThomas Huth case ASI_REAL_IO_L: 1395fcf5ef2aSThomas Huth case ASI_N: 1396fcf5ef2aSThomas Huth case ASI_NL: 1397fcf5ef2aSThomas Huth case ASI_AIUP: 1398fcf5ef2aSThomas Huth case ASI_AIUPL: 1399fcf5ef2aSThomas Huth case ASI_AIUS: 1400fcf5ef2aSThomas Huth case ASI_AIUSL: 1401fcf5ef2aSThomas Huth case ASI_S: 1402fcf5ef2aSThomas Huth case ASI_SL: 1403fcf5ef2aSThomas Huth case ASI_P: 1404fcf5ef2aSThomas Huth case ASI_PL: 1405fcf5ef2aSThomas Huth type = GET_ASI_DIRECT; 1406fcf5ef2aSThomas Huth break; 1407fcf5ef2aSThomas Huth case ASI_TWINX_REAL: 1408fcf5ef2aSThomas Huth case ASI_TWINX_REAL_L: 1409fcf5ef2aSThomas Huth case ASI_TWINX_N: 1410fcf5ef2aSThomas Huth case ASI_TWINX_NL: 1411fcf5ef2aSThomas Huth case ASI_TWINX_AIUP: 1412fcf5ef2aSThomas Huth case ASI_TWINX_AIUP_L: 1413fcf5ef2aSThomas Huth case ASI_TWINX_AIUS: 1414fcf5ef2aSThomas Huth case ASI_TWINX_AIUS_L: 1415fcf5ef2aSThomas Huth case ASI_TWINX_P: 1416fcf5ef2aSThomas Huth case ASI_TWINX_PL: 1417fcf5ef2aSThomas Huth case ASI_TWINX_S: 1418fcf5ef2aSThomas Huth case ASI_TWINX_SL: 1419fcf5ef2aSThomas Huth case ASI_QUAD_LDD_PHYS: 1420fcf5ef2aSThomas Huth case ASI_QUAD_LDD_PHYS_L: 1421fcf5ef2aSThomas Huth case ASI_NUCLEUS_QUAD_LDD: 1422fcf5ef2aSThomas Huth case ASI_NUCLEUS_QUAD_LDD_L: 1423fcf5ef2aSThomas Huth type = GET_ASI_DTWINX; 1424fcf5ef2aSThomas Huth break; 1425fcf5ef2aSThomas Huth case ASI_BLK_COMMIT_P: 1426fcf5ef2aSThomas Huth case ASI_BLK_COMMIT_S: 1427fcf5ef2aSThomas Huth case ASI_BLK_AIUP_4V: 1428fcf5ef2aSThomas Huth case ASI_BLK_AIUP_L_4V: 1429fcf5ef2aSThomas Huth case ASI_BLK_AIUP: 1430fcf5ef2aSThomas Huth case ASI_BLK_AIUPL: 1431fcf5ef2aSThomas Huth case ASI_BLK_AIUS_4V: 1432fcf5ef2aSThomas Huth case ASI_BLK_AIUS_L_4V: 1433fcf5ef2aSThomas Huth case ASI_BLK_AIUS: 1434fcf5ef2aSThomas Huth case ASI_BLK_AIUSL: 1435fcf5ef2aSThomas Huth case ASI_BLK_S: 1436fcf5ef2aSThomas Huth case ASI_BLK_SL: 1437fcf5ef2aSThomas Huth case ASI_BLK_P: 1438fcf5ef2aSThomas Huth case ASI_BLK_PL: 1439fcf5ef2aSThomas Huth type = GET_ASI_BLOCK; 1440fcf5ef2aSThomas Huth break; 1441fcf5ef2aSThomas Huth case ASI_FL8_S: 1442fcf5ef2aSThomas Huth case ASI_FL8_SL: 1443fcf5ef2aSThomas Huth case ASI_FL8_P: 1444fcf5ef2aSThomas Huth case ASI_FL8_PL: 1445fcf5ef2aSThomas Huth memop = MO_UB; 1446fcf5ef2aSThomas Huth type = GET_ASI_SHORT; 1447fcf5ef2aSThomas Huth break; 1448fcf5ef2aSThomas Huth case ASI_FL16_S: 1449fcf5ef2aSThomas Huth case ASI_FL16_SL: 1450fcf5ef2aSThomas Huth case ASI_FL16_P: 1451fcf5ef2aSThomas Huth case ASI_FL16_PL: 1452fcf5ef2aSThomas Huth memop = MO_TEUW; 1453fcf5ef2aSThomas Huth type = GET_ASI_SHORT; 1454fcf5ef2aSThomas Huth break; 1455fcf5ef2aSThomas Huth } 1456fcf5ef2aSThomas Huth /* The little-endian asis all have bit 3 set. */ 1457fcf5ef2aSThomas Huth if (asi & 8) { 1458fcf5ef2aSThomas Huth memop ^= MO_BSWAP; 1459fcf5ef2aSThomas Huth } 1460fcf5ef2aSThomas Huth } 1461fcf5ef2aSThomas Huth #endif 1462fcf5ef2aSThomas Huth 1463811cc0b0SRichard Henderson done: 1464fcf5ef2aSThomas Huth return (DisasASI){ type, asi, mem_idx, memop }; 1465fcf5ef2aSThomas Huth } 1466fcf5ef2aSThomas Huth 1467a76779eeSRichard Henderson #if defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64) 1468a76779eeSRichard Henderson static void gen_helper_ld_asi(TCGv_i64 r, TCGv_env e, TCGv a, 1469a76779eeSRichard Henderson TCGv_i32 asi, TCGv_i32 mop) 1470a76779eeSRichard Henderson { 1471a76779eeSRichard Henderson g_assert_not_reached(); 1472a76779eeSRichard Henderson } 1473a76779eeSRichard Henderson 1474a76779eeSRichard Henderson static void gen_helper_st_asi(TCGv_env e, TCGv a, TCGv_i64 r, 1475a76779eeSRichard Henderson TCGv_i32 asi, TCGv_i32 mop) 1476a76779eeSRichard Henderson { 1477a76779eeSRichard Henderson g_assert_not_reached(); 1478a76779eeSRichard Henderson } 1479a76779eeSRichard Henderson #endif 1480a76779eeSRichard Henderson 148142071fc1SRichard Henderson static void gen_ld_asi(DisasContext *dc, DisasASI *da, TCGv dst, TCGv addr) 1482fcf5ef2aSThomas Huth { 1483c03a0fd1SRichard Henderson switch (da->type) { 1484fcf5ef2aSThomas Huth case GET_ASI_EXCP: 1485fcf5ef2aSThomas Huth break; 1486fcf5ef2aSThomas Huth case GET_ASI_DTWINX: /* Reserved for ldda. */ 1487fcf5ef2aSThomas Huth gen_exception(dc, TT_ILL_INSN); 1488fcf5ef2aSThomas Huth break; 1489fcf5ef2aSThomas Huth case GET_ASI_DIRECT: 1490c03a0fd1SRichard Henderson tcg_gen_qemu_ld_tl(dst, addr, da->mem_idx, da->memop | MO_ALIGN); 1491fcf5ef2aSThomas Huth break; 14922786a3f8SRichard Henderson 14932786a3f8SRichard Henderson case GET_ASI_CODE: 14942786a3f8SRichard Henderson #if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64) 14952786a3f8SRichard Henderson { 14962786a3f8SRichard Henderson MemOpIdx oi = make_memop_idx(da->memop, da->mem_idx); 14972786a3f8SRichard Henderson TCGv_i64 t64 = tcg_temp_new_i64(); 14982786a3f8SRichard Henderson 14992786a3f8SRichard Henderson gen_helper_ld_code(t64, tcg_env, addr, tcg_constant_i32(oi)); 15002786a3f8SRichard Henderson tcg_gen_trunc_i64_tl(dst, t64); 15012786a3f8SRichard Henderson } 15022786a3f8SRichard Henderson break; 15032786a3f8SRichard Henderson #else 15042786a3f8SRichard Henderson g_assert_not_reached(); 15052786a3f8SRichard Henderson #endif 15062786a3f8SRichard Henderson 1507fcf5ef2aSThomas Huth default: 1508fcf5ef2aSThomas Huth { 1509c03a0fd1SRichard Henderson TCGv_i32 r_asi = tcg_constant_i32(da->asi); 1510c03a0fd1SRichard Henderson TCGv_i32 r_mop = tcg_constant_i32(da->memop | MO_ALIGN); 1511fcf5ef2aSThomas Huth 1512fcf5ef2aSThomas Huth save_state(dc); 1513fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64 1514ad75a51eSRichard Henderson gen_helper_ld_asi(dst, tcg_env, addr, r_asi, r_mop); 1515fcf5ef2aSThomas Huth #else 1516fcf5ef2aSThomas Huth { 1517fcf5ef2aSThomas Huth TCGv_i64 t64 = tcg_temp_new_i64(); 1518ad75a51eSRichard Henderson gen_helper_ld_asi(t64, tcg_env, addr, r_asi, r_mop); 1519fcf5ef2aSThomas Huth tcg_gen_trunc_i64_tl(dst, t64); 1520fcf5ef2aSThomas Huth } 1521fcf5ef2aSThomas Huth #endif 1522fcf5ef2aSThomas Huth } 1523fcf5ef2aSThomas Huth break; 1524fcf5ef2aSThomas Huth } 1525fcf5ef2aSThomas Huth } 1526fcf5ef2aSThomas Huth 152742071fc1SRichard Henderson static void gen_st_asi(DisasContext *dc, DisasASI *da, TCGv src, TCGv addr) 1528c03a0fd1SRichard Henderson { 1529c03a0fd1SRichard Henderson switch (da->type) { 1530fcf5ef2aSThomas Huth case GET_ASI_EXCP: 1531fcf5ef2aSThomas Huth break; 1532c03a0fd1SRichard Henderson 1533fcf5ef2aSThomas Huth case GET_ASI_DTWINX: /* Reserved for stda. */ 1534c03a0fd1SRichard Henderson if (TARGET_LONG_BITS == 32) { 1535fcf5ef2aSThomas Huth gen_exception(dc, TT_ILL_INSN); 1536fcf5ef2aSThomas Huth break; 1537c03a0fd1SRichard Henderson } else if (!(dc->def->features & CPU_FEATURE_HYPV)) { 15383390537bSArtyom Tarasenko /* Pre OpenSPARC CPUs don't have these */ 15393390537bSArtyom Tarasenko gen_exception(dc, TT_ILL_INSN); 1540fcf5ef2aSThomas Huth break; 1541c03a0fd1SRichard Henderson } 1542c03a0fd1SRichard Henderson /* In OpenSPARC T1+ CPUs TWINX ASIs in store are ST_BLKINIT_ ASIs */ 1543c03a0fd1SRichard Henderson /* fall through */ 1544c03a0fd1SRichard Henderson 1545c03a0fd1SRichard Henderson case GET_ASI_DIRECT: 1546c03a0fd1SRichard Henderson tcg_gen_qemu_st_tl(src, addr, da->mem_idx, da->memop | MO_ALIGN); 1547c03a0fd1SRichard Henderson break; 1548c03a0fd1SRichard Henderson 1549fcf5ef2aSThomas Huth case GET_ASI_BCOPY: 1550c03a0fd1SRichard Henderson assert(TARGET_LONG_BITS == 32); 155198271007SRichard Henderson /* 155298271007SRichard Henderson * Copy 32 bytes from the address in SRC to ADDR. 155398271007SRichard Henderson * 155498271007SRichard Henderson * From Ross RT625 hyperSPARC manual, section 4.6: 155598271007SRichard Henderson * "Block Copy and Block Fill will work only on cache line boundaries." 155698271007SRichard Henderson * 155798271007SRichard Henderson * It does not specify if an unaliged address is truncated or trapped. 155898271007SRichard Henderson * Previous qemu behaviour was to truncate to 4 byte alignment, which 155998271007SRichard Henderson * is obviously wrong. The only place I can see this used is in the 156098271007SRichard Henderson * Linux kernel which begins with page alignment, advancing by 32, 156198271007SRichard Henderson * so is always aligned. Assume truncation as the simpler option. 156298271007SRichard Henderson * 156398271007SRichard Henderson * Since the loads and stores are paired, allow the copy to happen 156498271007SRichard Henderson * in the host endianness. The copy need not be atomic. 156598271007SRichard Henderson */ 1566fcf5ef2aSThomas Huth { 156798271007SRichard Henderson MemOp mop = MO_128 | MO_ATOM_IFALIGN_PAIR; 1568fcf5ef2aSThomas Huth TCGv saddr = tcg_temp_new(); 1569fcf5ef2aSThomas Huth TCGv daddr = tcg_temp_new(); 157098271007SRichard Henderson TCGv_i128 tmp = tcg_temp_new_i128(); 1571fcf5ef2aSThomas Huth 157298271007SRichard Henderson tcg_gen_andi_tl(saddr, src, -32); 157398271007SRichard Henderson tcg_gen_andi_tl(daddr, addr, -32); 157498271007SRichard Henderson tcg_gen_qemu_ld_i128(tmp, saddr, da->mem_idx, mop); 157598271007SRichard Henderson tcg_gen_qemu_st_i128(tmp, daddr, da->mem_idx, mop); 157698271007SRichard Henderson tcg_gen_addi_tl(saddr, saddr, 16); 157798271007SRichard Henderson tcg_gen_addi_tl(daddr, daddr, 16); 157898271007SRichard Henderson tcg_gen_qemu_ld_i128(tmp, saddr, da->mem_idx, mop); 157998271007SRichard Henderson tcg_gen_qemu_st_i128(tmp, daddr, da->mem_idx, mop); 1580fcf5ef2aSThomas Huth } 1581fcf5ef2aSThomas Huth break; 1582c03a0fd1SRichard Henderson 1583fcf5ef2aSThomas Huth default: 1584fcf5ef2aSThomas Huth { 1585c03a0fd1SRichard Henderson TCGv_i32 r_asi = tcg_constant_i32(da->asi); 1586c03a0fd1SRichard Henderson TCGv_i32 r_mop = tcg_constant_i32(da->memop | MO_ALIGN); 1587fcf5ef2aSThomas Huth 1588fcf5ef2aSThomas Huth save_state(dc); 1589fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64 1590ad75a51eSRichard Henderson gen_helper_st_asi(tcg_env, addr, src, r_asi, r_mop); 1591fcf5ef2aSThomas Huth #else 1592fcf5ef2aSThomas Huth { 1593fcf5ef2aSThomas Huth TCGv_i64 t64 = tcg_temp_new_i64(); 1594fcf5ef2aSThomas Huth tcg_gen_extu_tl_i64(t64, src); 1595ad75a51eSRichard Henderson gen_helper_st_asi(tcg_env, addr, t64, r_asi, r_mop); 1596fcf5ef2aSThomas Huth } 1597fcf5ef2aSThomas Huth #endif 1598fcf5ef2aSThomas Huth 1599fcf5ef2aSThomas Huth /* A write to a TLB register may alter page maps. End the TB. */ 1600fcf5ef2aSThomas Huth dc->npc = DYNAMIC_PC; 1601fcf5ef2aSThomas Huth } 1602fcf5ef2aSThomas Huth break; 1603fcf5ef2aSThomas Huth } 1604fcf5ef2aSThomas Huth } 1605fcf5ef2aSThomas Huth 1606dca544b9SRichard Henderson static void gen_swap_asi(DisasContext *dc, DisasASI *da, 1607c03a0fd1SRichard Henderson TCGv dst, TCGv src, TCGv addr) 1608c03a0fd1SRichard Henderson { 1609c03a0fd1SRichard Henderson switch (da->type) { 1610c03a0fd1SRichard Henderson case GET_ASI_EXCP: 1611c03a0fd1SRichard Henderson break; 1612c03a0fd1SRichard Henderson case GET_ASI_DIRECT: 1613dca544b9SRichard Henderson tcg_gen_atomic_xchg_tl(dst, addr, src, 1614dca544b9SRichard Henderson da->mem_idx, da->memop | MO_ALIGN); 1615c03a0fd1SRichard Henderson break; 1616c03a0fd1SRichard Henderson default: 1617c03a0fd1SRichard Henderson /* ??? Should be DAE_invalid_asi. */ 1618c03a0fd1SRichard Henderson gen_exception(dc, TT_DATA_ACCESS); 1619c03a0fd1SRichard Henderson break; 1620c03a0fd1SRichard Henderson } 1621c03a0fd1SRichard Henderson } 1622c03a0fd1SRichard Henderson 1623d0a11d25SRichard Henderson static void gen_cas_asi(DisasContext *dc, DisasASI *da, 1624c03a0fd1SRichard Henderson TCGv oldv, TCGv newv, TCGv cmpv, TCGv addr) 1625c03a0fd1SRichard Henderson { 1626c03a0fd1SRichard Henderson switch (da->type) { 1627fcf5ef2aSThomas Huth case GET_ASI_EXCP: 1628c03a0fd1SRichard Henderson return; 1629fcf5ef2aSThomas Huth case GET_ASI_DIRECT: 1630c03a0fd1SRichard Henderson tcg_gen_atomic_cmpxchg_tl(oldv, addr, cmpv, newv, 1631c03a0fd1SRichard Henderson da->mem_idx, da->memop | MO_ALIGN); 1632fcf5ef2aSThomas Huth break; 1633fcf5ef2aSThomas Huth default: 1634fcf5ef2aSThomas Huth /* ??? Should be DAE_invalid_asi. */ 1635fcf5ef2aSThomas Huth gen_exception(dc, TT_DATA_ACCESS); 1636fcf5ef2aSThomas Huth break; 1637fcf5ef2aSThomas Huth } 1638fcf5ef2aSThomas Huth } 1639fcf5ef2aSThomas Huth 1640cf07cd1eSRichard Henderson static void gen_ldstub_asi(DisasContext *dc, DisasASI *da, TCGv dst, TCGv addr) 1641c03a0fd1SRichard Henderson { 1642c03a0fd1SRichard Henderson switch (da->type) { 1643fcf5ef2aSThomas Huth case GET_ASI_EXCP: 1644fcf5ef2aSThomas Huth break; 1645fcf5ef2aSThomas Huth case GET_ASI_DIRECT: 1646cf07cd1eSRichard Henderson tcg_gen_atomic_xchg_tl(dst, addr, tcg_constant_tl(0xff), 1647cf07cd1eSRichard Henderson da->mem_idx, MO_UB); 1648fcf5ef2aSThomas Huth break; 1649fcf5ef2aSThomas Huth default: 16503db010c3SRichard Henderson /* ??? In theory, this should be raise DAE_invalid_asi. 16513db010c3SRichard Henderson But the SS-20 roms do ldstuba [%l0] #ASI_M_CTL, %o1. */ 1652af00be49SEmilio G. Cota if (tb_cflags(dc->base.tb) & CF_PARALLEL) { 1653ad75a51eSRichard Henderson gen_helper_exit_atomic(tcg_env); 16543db010c3SRichard Henderson } else { 1655c03a0fd1SRichard Henderson TCGv_i32 r_asi = tcg_constant_i32(da->asi); 165600ab7e61SRichard Henderson TCGv_i32 r_mop = tcg_constant_i32(MO_UB); 16573db010c3SRichard Henderson TCGv_i64 s64, t64; 16583db010c3SRichard Henderson 16593db010c3SRichard Henderson save_state(dc); 16603db010c3SRichard Henderson t64 = tcg_temp_new_i64(); 1661ad75a51eSRichard Henderson gen_helper_ld_asi(t64, tcg_env, addr, r_asi, r_mop); 16623db010c3SRichard Henderson 166300ab7e61SRichard Henderson s64 = tcg_constant_i64(0xff); 1664ad75a51eSRichard Henderson gen_helper_st_asi(tcg_env, addr, s64, r_asi, r_mop); 16653db010c3SRichard Henderson 16663db010c3SRichard Henderson tcg_gen_trunc_i64_tl(dst, t64); 16673db010c3SRichard Henderson 16683db010c3SRichard Henderson /* End the TB. */ 16693db010c3SRichard Henderson dc->npc = DYNAMIC_PC; 16703db010c3SRichard Henderson } 1671fcf5ef2aSThomas Huth break; 1672fcf5ef2aSThomas Huth } 1673fcf5ef2aSThomas Huth } 1674fcf5ef2aSThomas Huth 1675287b1152SRichard Henderson static void gen_ldf_asi(DisasContext *dc, DisasASI *da, MemOp orig_size, 16763259b9e2SRichard Henderson TCGv addr, int rd) 1677fcf5ef2aSThomas Huth { 16783259b9e2SRichard Henderson MemOp memop = da->memop; 16793259b9e2SRichard Henderson MemOp size = memop & MO_SIZE; 1680fcf5ef2aSThomas Huth TCGv_i32 d32; 16811210a036SRichard Henderson TCGv_i64 d64, l64; 1682287b1152SRichard Henderson TCGv addr_tmp; 1683fcf5ef2aSThomas Huth 16843259b9e2SRichard Henderson /* TODO: Use 128-bit load/store below. */ 16853259b9e2SRichard Henderson if (size == MO_128) { 16863259b9e2SRichard Henderson memop = (memop & ~MO_SIZE) | MO_64; 16873259b9e2SRichard Henderson } 16883259b9e2SRichard Henderson 16893259b9e2SRichard Henderson switch (da->type) { 1690fcf5ef2aSThomas Huth case GET_ASI_EXCP: 1691fcf5ef2aSThomas Huth break; 1692fcf5ef2aSThomas Huth 1693fcf5ef2aSThomas Huth case GET_ASI_DIRECT: 16943259b9e2SRichard Henderson memop |= MO_ALIGN_4; 1695fcf5ef2aSThomas Huth switch (size) { 16963259b9e2SRichard Henderson case MO_32: 1697388a6465SRichard Henderson d32 = tcg_temp_new_i32(); 16983259b9e2SRichard Henderson tcg_gen_qemu_ld_i32(d32, addr, da->mem_idx, memop); 1699fcf5ef2aSThomas Huth gen_store_fpr_F(dc, rd, d32); 1700fcf5ef2aSThomas Huth break; 17013259b9e2SRichard Henderson 17023259b9e2SRichard Henderson case MO_64: 17031210a036SRichard Henderson d64 = tcg_temp_new_i64(); 17041210a036SRichard Henderson tcg_gen_qemu_ld_i64(d64, addr, da->mem_idx, memop); 17051210a036SRichard Henderson gen_store_fpr_D(dc, rd, d64); 1706fcf5ef2aSThomas Huth break; 17073259b9e2SRichard Henderson 17083259b9e2SRichard Henderson case MO_128: 1709fcf5ef2aSThomas Huth d64 = tcg_temp_new_i64(); 17101210a036SRichard Henderson l64 = tcg_temp_new_i64(); 17113259b9e2SRichard Henderson tcg_gen_qemu_ld_i64(d64, addr, da->mem_idx, memop); 1712287b1152SRichard Henderson addr_tmp = tcg_temp_new(); 1713287b1152SRichard Henderson tcg_gen_addi_tl(addr_tmp, addr, 8); 17141210a036SRichard Henderson tcg_gen_qemu_ld_i64(l64, addr_tmp, da->mem_idx, memop); 17151210a036SRichard Henderson gen_store_fpr_D(dc, rd, d64); 17161210a036SRichard Henderson gen_store_fpr_D(dc, rd + 2, l64); 1717fcf5ef2aSThomas Huth break; 1718fcf5ef2aSThomas Huth default: 1719fcf5ef2aSThomas Huth g_assert_not_reached(); 1720fcf5ef2aSThomas Huth } 1721fcf5ef2aSThomas Huth break; 1722fcf5ef2aSThomas Huth 1723fcf5ef2aSThomas Huth case GET_ASI_BLOCK: 1724fcf5ef2aSThomas Huth /* Valid for lddfa on aligned registers only. */ 17253259b9e2SRichard Henderson if (orig_size == MO_64 && (rd & 7) == 0) { 1726fcf5ef2aSThomas Huth /* The first operation checks required alignment. */ 1727287b1152SRichard Henderson addr_tmp = tcg_temp_new(); 17281210a036SRichard Henderson d64 = tcg_temp_new_i64(); 1729287b1152SRichard Henderson for (int i = 0; ; ++i) { 17301210a036SRichard Henderson tcg_gen_qemu_ld_i64(d64, addr, da->mem_idx, 17313259b9e2SRichard Henderson memop | (i == 0 ? MO_ALIGN_64 : 0)); 17321210a036SRichard Henderson gen_store_fpr_D(dc, rd + 2 * i, d64); 1733fcf5ef2aSThomas Huth if (i == 7) { 1734fcf5ef2aSThomas Huth break; 1735fcf5ef2aSThomas Huth } 1736287b1152SRichard Henderson tcg_gen_addi_tl(addr_tmp, addr, 8); 1737287b1152SRichard Henderson addr = addr_tmp; 1738fcf5ef2aSThomas Huth } 1739fcf5ef2aSThomas Huth } else { 1740fcf5ef2aSThomas Huth gen_exception(dc, TT_ILL_INSN); 1741fcf5ef2aSThomas Huth } 1742fcf5ef2aSThomas Huth break; 1743fcf5ef2aSThomas Huth 1744fcf5ef2aSThomas Huth case GET_ASI_SHORT: 1745fcf5ef2aSThomas Huth /* Valid for lddfa only. */ 17463259b9e2SRichard Henderson if (orig_size == MO_64) { 17471210a036SRichard Henderson d64 = tcg_temp_new_i64(); 17481210a036SRichard Henderson tcg_gen_qemu_ld_i64(d64, addr, da->mem_idx, memop | MO_ALIGN); 17491210a036SRichard Henderson gen_store_fpr_D(dc, rd, d64); 1750fcf5ef2aSThomas Huth } else { 1751fcf5ef2aSThomas Huth gen_exception(dc, TT_ILL_INSN); 1752fcf5ef2aSThomas Huth } 1753fcf5ef2aSThomas Huth break; 1754fcf5ef2aSThomas Huth 1755fcf5ef2aSThomas Huth default: 1756fcf5ef2aSThomas Huth { 17573259b9e2SRichard Henderson TCGv_i32 r_asi = tcg_constant_i32(da->asi); 17583259b9e2SRichard Henderson TCGv_i32 r_mop = tcg_constant_i32(memop | MO_ALIGN); 1759fcf5ef2aSThomas Huth 1760fcf5ef2aSThomas Huth save_state(dc); 1761fcf5ef2aSThomas Huth /* According to the table in the UA2011 manual, the only 1762fcf5ef2aSThomas Huth other asis that are valid for ldfa/lddfa/ldqfa are 1763fcf5ef2aSThomas Huth the NO_FAULT asis. We still need a helper for these, 1764fcf5ef2aSThomas Huth but we can just use the integer asi helper for them. */ 1765fcf5ef2aSThomas Huth switch (size) { 17663259b9e2SRichard Henderson case MO_32: 1767fcf5ef2aSThomas Huth d64 = tcg_temp_new_i64(); 1768ad75a51eSRichard Henderson gen_helper_ld_asi(d64, tcg_env, addr, r_asi, r_mop); 1769388a6465SRichard Henderson d32 = tcg_temp_new_i32(); 1770fcf5ef2aSThomas Huth tcg_gen_extrl_i64_i32(d32, d64); 1771fcf5ef2aSThomas Huth gen_store_fpr_F(dc, rd, d32); 1772fcf5ef2aSThomas Huth break; 17733259b9e2SRichard Henderson case MO_64: 17741210a036SRichard Henderson d64 = tcg_temp_new_i64(); 17751210a036SRichard Henderson gen_helper_ld_asi(d64, tcg_env, addr, r_asi, r_mop); 17761210a036SRichard Henderson gen_store_fpr_D(dc, rd, d64); 1777fcf5ef2aSThomas Huth break; 17783259b9e2SRichard Henderson case MO_128: 1779fcf5ef2aSThomas Huth d64 = tcg_temp_new_i64(); 17801210a036SRichard Henderson l64 = tcg_temp_new_i64(); 1781ad75a51eSRichard Henderson gen_helper_ld_asi(d64, tcg_env, addr, r_asi, r_mop); 1782287b1152SRichard Henderson addr_tmp = tcg_temp_new(); 1783287b1152SRichard Henderson tcg_gen_addi_tl(addr_tmp, addr, 8); 17841210a036SRichard Henderson gen_helper_ld_asi(l64, tcg_env, addr_tmp, r_asi, r_mop); 17851210a036SRichard Henderson gen_store_fpr_D(dc, rd, d64); 17861210a036SRichard Henderson gen_store_fpr_D(dc, rd + 2, l64); 1787fcf5ef2aSThomas Huth break; 1788fcf5ef2aSThomas Huth default: 1789fcf5ef2aSThomas Huth g_assert_not_reached(); 1790fcf5ef2aSThomas Huth } 1791fcf5ef2aSThomas Huth } 1792fcf5ef2aSThomas Huth break; 1793fcf5ef2aSThomas Huth } 1794fcf5ef2aSThomas Huth } 1795fcf5ef2aSThomas Huth 1796287b1152SRichard Henderson static void gen_stf_asi(DisasContext *dc, DisasASI *da, MemOp orig_size, 17973259b9e2SRichard Henderson TCGv addr, int rd) 17983259b9e2SRichard Henderson { 17993259b9e2SRichard Henderson MemOp memop = da->memop; 18003259b9e2SRichard Henderson MemOp size = memop & MO_SIZE; 1801fcf5ef2aSThomas Huth TCGv_i32 d32; 18021210a036SRichard Henderson TCGv_i64 d64; 1803287b1152SRichard Henderson TCGv addr_tmp; 1804fcf5ef2aSThomas Huth 18053259b9e2SRichard Henderson /* TODO: Use 128-bit load/store below. */ 18063259b9e2SRichard Henderson if (size == MO_128) { 18073259b9e2SRichard Henderson memop = (memop & ~MO_SIZE) | MO_64; 18083259b9e2SRichard Henderson } 18093259b9e2SRichard Henderson 18103259b9e2SRichard Henderson switch (da->type) { 1811fcf5ef2aSThomas Huth case GET_ASI_EXCP: 1812fcf5ef2aSThomas Huth break; 1813fcf5ef2aSThomas Huth 1814fcf5ef2aSThomas Huth case GET_ASI_DIRECT: 18153259b9e2SRichard Henderson memop |= MO_ALIGN_4; 1816fcf5ef2aSThomas Huth switch (size) { 18173259b9e2SRichard Henderson case MO_32: 1818fcf5ef2aSThomas Huth d32 = gen_load_fpr_F(dc, rd); 18193259b9e2SRichard Henderson tcg_gen_qemu_st_i32(d32, addr, da->mem_idx, memop | MO_ALIGN); 1820fcf5ef2aSThomas Huth break; 18213259b9e2SRichard Henderson case MO_64: 18221210a036SRichard Henderson d64 = gen_load_fpr_D(dc, rd); 18231210a036SRichard Henderson tcg_gen_qemu_st_i64(d64, addr, da->mem_idx, memop | MO_ALIGN_4); 1824fcf5ef2aSThomas Huth break; 18253259b9e2SRichard Henderson case MO_128: 1826fcf5ef2aSThomas Huth /* Only 4-byte alignment required. However, it is legal for the 1827fcf5ef2aSThomas Huth cpu to signal the alignment fault, and the OS trap handler is 1828fcf5ef2aSThomas Huth required to fix it up. Requiring 16-byte alignment here avoids 1829fcf5ef2aSThomas Huth having to probe the second page before performing the first 1830fcf5ef2aSThomas Huth write. */ 18311210a036SRichard Henderson d64 = gen_load_fpr_D(dc, rd); 18321210a036SRichard Henderson tcg_gen_qemu_st_i64(d64, addr, da->mem_idx, memop | MO_ALIGN_16); 1833287b1152SRichard Henderson addr_tmp = tcg_temp_new(); 1834287b1152SRichard Henderson tcg_gen_addi_tl(addr_tmp, addr, 8); 18351210a036SRichard Henderson d64 = gen_load_fpr_D(dc, rd + 2); 18361210a036SRichard Henderson tcg_gen_qemu_st_i64(d64, addr_tmp, da->mem_idx, memop); 1837fcf5ef2aSThomas Huth break; 1838fcf5ef2aSThomas Huth default: 1839fcf5ef2aSThomas Huth g_assert_not_reached(); 1840fcf5ef2aSThomas Huth } 1841fcf5ef2aSThomas Huth break; 1842fcf5ef2aSThomas Huth 1843fcf5ef2aSThomas Huth case GET_ASI_BLOCK: 1844fcf5ef2aSThomas Huth /* Valid for stdfa on aligned registers only. */ 18453259b9e2SRichard Henderson if (orig_size == MO_64 && (rd & 7) == 0) { 1846fcf5ef2aSThomas Huth /* The first operation checks required alignment. */ 1847287b1152SRichard Henderson addr_tmp = tcg_temp_new(); 1848287b1152SRichard Henderson for (int i = 0; ; ++i) { 18491210a036SRichard Henderson d64 = gen_load_fpr_D(dc, rd + 2 * i); 18501210a036SRichard Henderson tcg_gen_qemu_st_i64(d64, addr, da->mem_idx, 18513259b9e2SRichard Henderson memop | (i == 0 ? MO_ALIGN_64 : 0)); 1852fcf5ef2aSThomas Huth if (i == 7) { 1853fcf5ef2aSThomas Huth break; 1854fcf5ef2aSThomas Huth } 1855287b1152SRichard Henderson tcg_gen_addi_tl(addr_tmp, addr, 8); 1856287b1152SRichard Henderson addr = addr_tmp; 1857fcf5ef2aSThomas Huth } 1858fcf5ef2aSThomas Huth } else { 1859fcf5ef2aSThomas Huth gen_exception(dc, TT_ILL_INSN); 1860fcf5ef2aSThomas Huth } 1861fcf5ef2aSThomas Huth break; 1862fcf5ef2aSThomas Huth 1863fcf5ef2aSThomas Huth case GET_ASI_SHORT: 1864fcf5ef2aSThomas Huth /* Valid for stdfa only. */ 18653259b9e2SRichard Henderson if (orig_size == MO_64) { 18661210a036SRichard Henderson d64 = gen_load_fpr_D(dc, rd); 18671210a036SRichard Henderson tcg_gen_qemu_st_i64(d64, addr, da->mem_idx, memop | MO_ALIGN); 1868fcf5ef2aSThomas Huth } else { 1869fcf5ef2aSThomas Huth gen_exception(dc, TT_ILL_INSN); 1870fcf5ef2aSThomas Huth } 1871fcf5ef2aSThomas Huth break; 1872fcf5ef2aSThomas Huth 1873fcf5ef2aSThomas Huth default: 1874fcf5ef2aSThomas Huth /* According to the table in the UA2011 manual, the only 1875fcf5ef2aSThomas Huth other asis that are valid for ldfa/lddfa/ldqfa are 1876fcf5ef2aSThomas Huth the PST* asis, which aren't currently handled. */ 1877fcf5ef2aSThomas Huth gen_exception(dc, TT_ILL_INSN); 1878fcf5ef2aSThomas Huth break; 1879fcf5ef2aSThomas Huth } 1880fcf5ef2aSThomas Huth } 1881fcf5ef2aSThomas Huth 188242071fc1SRichard Henderson static void gen_ldda_asi(DisasContext *dc, DisasASI *da, TCGv addr, int rd) 1883fcf5ef2aSThomas Huth { 1884a76779eeSRichard Henderson TCGv hi = gen_dest_gpr(dc, rd); 1885a76779eeSRichard Henderson TCGv lo = gen_dest_gpr(dc, rd + 1); 1886fcf5ef2aSThomas Huth 1887c03a0fd1SRichard Henderson switch (da->type) { 1888fcf5ef2aSThomas Huth case GET_ASI_EXCP: 1889fcf5ef2aSThomas Huth return; 1890fcf5ef2aSThomas Huth 1891fcf5ef2aSThomas Huth case GET_ASI_DTWINX: 1892ebbbec92SRichard Henderson #ifdef TARGET_SPARC64 1893ebbbec92SRichard Henderson { 1894ebbbec92SRichard Henderson MemOp mop = (da->memop & MO_BSWAP) | MO_128 | MO_ALIGN_16; 1895ebbbec92SRichard Henderson TCGv_i128 t = tcg_temp_new_i128(); 1896ebbbec92SRichard Henderson 1897ebbbec92SRichard Henderson tcg_gen_qemu_ld_i128(t, addr, da->mem_idx, mop); 1898ebbbec92SRichard Henderson /* 1899ebbbec92SRichard Henderson * Note that LE twinx acts as if each 64-bit register result is 1900ebbbec92SRichard Henderson * byte swapped. We perform one 128-bit LE load, so must swap 1901ebbbec92SRichard Henderson * the order of the writebacks. 1902ebbbec92SRichard Henderson */ 1903ebbbec92SRichard Henderson if ((mop & MO_BSWAP) == MO_TE) { 1904ebbbec92SRichard Henderson tcg_gen_extr_i128_i64(lo, hi, t); 1905ebbbec92SRichard Henderson } else { 1906ebbbec92SRichard Henderson tcg_gen_extr_i128_i64(hi, lo, t); 1907ebbbec92SRichard Henderson } 1908ebbbec92SRichard Henderson } 1909fcf5ef2aSThomas Huth break; 1910ebbbec92SRichard Henderson #else 1911ebbbec92SRichard Henderson g_assert_not_reached(); 1912ebbbec92SRichard Henderson #endif 1913fcf5ef2aSThomas Huth 1914fcf5ef2aSThomas Huth case GET_ASI_DIRECT: 1915fcf5ef2aSThomas Huth { 1916fcf5ef2aSThomas Huth TCGv_i64 tmp = tcg_temp_new_i64(); 1917fcf5ef2aSThomas Huth 1918c03a0fd1SRichard Henderson tcg_gen_qemu_ld_i64(tmp, addr, da->mem_idx, da->memop | MO_ALIGN); 1919fcf5ef2aSThomas Huth 1920fcf5ef2aSThomas Huth /* Note that LE ldda acts as if each 32-bit register 1921fcf5ef2aSThomas Huth result is byte swapped. Having just performed one 1922fcf5ef2aSThomas Huth 64-bit bswap, we need now to swap the writebacks. */ 1923c03a0fd1SRichard Henderson if ((da->memop & MO_BSWAP) == MO_TE) { 1924a76779eeSRichard Henderson tcg_gen_extr_i64_tl(lo, hi, tmp); 1925fcf5ef2aSThomas Huth } else { 1926a76779eeSRichard Henderson tcg_gen_extr_i64_tl(hi, lo, tmp); 1927fcf5ef2aSThomas Huth } 1928fcf5ef2aSThomas Huth } 1929fcf5ef2aSThomas Huth break; 1930fcf5ef2aSThomas Huth 19312786a3f8SRichard Henderson case GET_ASI_CODE: 19322786a3f8SRichard Henderson #if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64) 19332786a3f8SRichard Henderson { 19342786a3f8SRichard Henderson MemOpIdx oi = make_memop_idx(da->memop, da->mem_idx); 19352786a3f8SRichard Henderson TCGv_i64 tmp = tcg_temp_new_i64(); 19362786a3f8SRichard Henderson 19372786a3f8SRichard Henderson gen_helper_ld_code(tmp, tcg_env, addr, tcg_constant_i32(oi)); 19382786a3f8SRichard Henderson 19392786a3f8SRichard Henderson /* See above. */ 19402786a3f8SRichard Henderson if ((da->memop & MO_BSWAP) == MO_TE) { 19412786a3f8SRichard Henderson tcg_gen_extr_i64_tl(lo, hi, tmp); 19422786a3f8SRichard Henderson } else { 19432786a3f8SRichard Henderson tcg_gen_extr_i64_tl(hi, lo, tmp); 19442786a3f8SRichard Henderson } 19452786a3f8SRichard Henderson } 19462786a3f8SRichard Henderson break; 19472786a3f8SRichard Henderson #else 19482786a3f8SRichard Henderson g_assert_not_reached(); 19492786a3f8SRichard Henderson #endif 19502786a3f8SRichard Henderson 1951fcf5ef2aSThomas Huth default: 1952fcf5ef2aSThomas Huth /* ??? In theory we've handled all of the ASIs that are valid 1953fcf5ef2aSThomas Huth for ldda, and this should raise DAE_invalid_asi. However, 1954fcf5ef2aSThomas Huth real hardware allows others. This can be seen with e.g. 1955fcf5ef2aSThomas Huth FreeBSD 10.3 wrt ASI_IC_TAG. */ 1956fcf5ef2aSThomas Huth { 1957c03a0fd1SRichard Henderson TCGv_i32 r_asi = tcg_constant_i32(da->asi); 1958c03a0fd1SRichard Henderson TCGv_i32 r_mop = tcg_constant_i32(da->memop); 1959fcf5ef2aSThomas Huth TCGv_i64 tmp = tcg_temp_new_i64(); 1960fcf5ef2aSThomas Huth 1961fcf5ef2aSThomas Huth save_state(dc); 1962ad75a51eSRichard Henderson gen_helper_ld_asi(tmp, tcg_env, addr, r_asi, r_mop); 1963fcf5ef2aSThomas Huth 1964fcf5ef2aSThomas Huth /* See above. */ 1965c03a0fd1SRichard Henderson if ((da->memop & MO_BSWAP) == MO_TE) { 1966a76779eeSRichard Henderson tcg_gen_extr_i64_tl(lo, hi, tmp); 1967fcf5ef2aSThomas Huth } else { 1968a76779eeSRichard Henderson tcg_gen_extr_i64_tl(hi, lo, tmp); 1969fcf5ef2aSThomas Huth } 1970fcf5ef2aSThomas Huth } 1971fcf5ef2aSThomas Huth break; 1972fcf5ef2aSThomas Huth } 1973fcf5ef2aSThomas Huth 1974fcf5ef2aSThomas Huth gen_store_gpr(dc, rd, hi); 1975fcf5ef2aSThomas Huth gen_store_gpr(dc, rd + 1, lo); 1976fcf5ef2aSThomas Huth } 1977fcf5ef2aSThomas Huth 197842071fc1SRichard Henderson static void gen_stda_asi(DisasContext *dc, DisasASI *da, TCGv addr, int rd) 1979c03a0fd1SRichard Henderson { 1980c03a0fd1SRichard Henderson TCGv hi = gen_load_gpr(dc, rd); 1981fcf5ef2aSThomas Huth TCGv lo = gen_load_gpr(dc, rd + 1); 1982fcf5ef2aSThomas Huth 1983c03a0fd1SRichard Henderson switch (da->type) { 1984fcf5ef2aSThomas Huth case GET_ASI_EXCP: 1985fcf5ef2aSThomas Huth break; 1986fcf5ef2aSThomas Huth 1987fcf5ef2aSThomas Huth case GET_ASI_DTWINX: 1988ebbbec92SRichard Henderson #ifdef TARGET_SPARC64 1989ebbbec92SRichard Henderson { 1990ebbbec92SRichard Henderson MemOp mop = (da->memop & MO_BSWAP) | MO_128 | MO_ALIGN_16; 1991ebbbec92SRichard Henderson TCGv_i128 t = tcg_temp_new_i128(); 1992ebbbec92SRichard Henderson 1993ebbbec92SRichard Henderson /* 1994ebbbec92SRichard Henderson * Note that LE twinx acts as if each 64-bit register result is 1995ebbbec92SRichard Henderson * byte swapped. We perform one 128-bit LE store, so must swap 1996ebbbec92SRichard Henderson * the order of the construction. 1997ebbbec92SRichard Henderson */ 1998ebbbec92SRichard Henderson if ((mop & MO_BSWAP) == MO_TE) { 1999ebbbec92SRichard Henderson tcg_gen_concat_i64_i128(t, lo, hi); 2000ebbbec92SRichard Henderson } else { 2001ebbbec92SRichard Henderson tcg_gen_concat_i64_i128(t, hi, lo); 2002ebbbec92SRichard Henderson } 2003ebbbec92SRichard Henderson tcg_gen_qemu_st_i128(t, addr, da->mem_idx, mop); 2004ebbbec92SRichard Henderson } 2005fcf5ef2aSThomas Huth break; 2006ebbbec92SRichard Henderson #else 2007ebbbec92SRichard Henderson g_assert_not_reached(); 2008ebbbec92SRichard Henderson #endif 2009fcf5ef2aSThomas Huth 2010fcf5ef2aSThomas Huth case GET_ASI_DIRECT: 2011fcf5ef2aSThomas Huth { 2012fcf5ef2aSThomas Huth TCGv_i64 t64 = tcg_temp_new_i64(); 2013fcf5ef2aSThomas Huth 2014fcf5ef2aSThomas Huth /* Note that LE stda acts as if each 32-bit register result is 2015fcf5ef2aSThomas Huth byte swapped. We will perform one 64-bit LE store, so now 2016fcf5ef2aSThomas Huth we must swap the order of the construction. */ 2017c03a0fd1SRichard Henderson if ((da->memop & MO_BSWAP) == MO_TE) { 2018a76779eeSRichard Henderson tcg_gen_concat_tl_i64(t64, lo, hi); 2019fcf5ef2aSThomas Huth } else { 2020a76779eeSRichard Henderson tcg_gen_concat_tl_i64(t64, hi, lo); 2021fcf5ef2aSThomas Huth } 2022c03a0fd1SRichard Henderson tcg_gen_qemu_st_i64(t64, addr, da->mem_idx, da->memop | MO_ALIGN); 2023fcf5ef2aSThomas Huth } 2024fcf5ef2aSThomas Huth break; 2025fcf5ef2aSThomas Huth 2026a76779eeSRichard Henderson case GET_ASI_BFILL: 2027a76779eeSRichard Henderson assert(TARGET_LONG_BITS == 32); 202854c3e953SRichard Henderson /* 202954c3e953SRichard Henderson * Store 32 bytes of [rd:rd+1] to ADDR. 203054c3e953SRichard Henderson * See comments for GET_ASI_COPY above. 203154c3e953SRichard Henderson */ 2032a76779eeSRichard Henderson { 203354c3e953SRichard Henderson MemOp mop = MO_TE | MO_128 | MO_ATOM_IFALIGN_PAIR; 203454c3e953SRichard Henderson TCGv_i64 t8 = tcg_temp_new_i64(); 203554c3e953SRichard Henderson TCGv_i128 t16 = tcg_temp_new_i128(); 203654c3e953SRichard Henderson TCGv daddr = tcg_temp_new(); 2037a76779eeSRichard Henderson 203854c3e953SRichard Henderson tcg_gen_concat_tl_i64(t8, lo, hi); 203954c3e953SRichard Henderson tcg_gen_concat_i64_i128(t16, t8, t8); 204054c3e953SRichard Henderson tcg_gen_andi_tl(daddr, addr, -32); 204154c3e953SRichard Henderson tcg_gen_qemu_st_i128(t16, daddr, da->mem_idx, mop); 204254c3e953SRichard Henderson tcg_gen_addi_tl(daddr, daddr, 16); 204354c3e953SRichard Henderson tcg_gen_qemu_st_i128(t16, daddr, da->mem_idx, mop); 2044a76779eeSRichard Henderson } 2045a76779eeSRichard Henderson break; 2046a76779eeSRichard Henderson 2047fcf5ef2aSThomas Huth default: 2048fcf5ef2aSThomas Huth /* ??? In theory we've handled all of the ASIs that are valid 2049fcf5ef2aSThomas Huth for stda, and this should raise DAE_invalid_asi. */ 2050fcf5ef2aSThomas Huth { 2051c03a0fd1SRichard Henderson TCGv_i32 r_asi = tcg_constant_i32(da->asi); 2052c03a0fd1SRichard Henderson TCGv_i32 r_mop = tcg_constant_i32(da->memop); 2053fcf5ef2aSThomas Huth TCGv_i64 t64 = tcg_temp_new_i64(); 2054fcf5ef2aSThomas Huth 2055fcf5ef2aSThomas Huth /* See above. */ 2056c03a0fd1SRichard Henderson if ((da->memop & MO_BSWAP) == MO_TE) { 2057a76779eeSRichard Henderson tcg_gen_concat_tl_i64(t64, lo, hi); 2058fcf5ef2aSThomas Huth } else { 2059a76779eeSRichard Henderson tcg_gen_concat_tl_i64(t64, hi, lo); 2060fcf5ef2aSThomas Huth } 2061fcf5ef2aSThomas Huth 2062fcf5ef2aSThomas Huth save_state(dc); 2063ad75a51eSRichard Henderson gen_helper_st_asi(tcg_env, addr, t64, r_asi, r_mop); 2064fcf5ef2aSThomas Huth } 2065fcf5ef2aSThomas Huth break; 2066fcf5ef2aSThomas Huth } 2067fcf5ef2aSThomas Huth } 2068fcf5ef2aSThomas Huth 2069fcf5ef2aSThomas Huth static void gen_fmovs(DisasContext *dc, DisasCompare *cmp, int rd, int rs) 2070fcf5ef2aSThomas Huth { 2071f7ec8155SRichard Henderson #ifdef TARGET_SPARC64 2072fcf5ef2aSThomas Huth TCGv_i32 c32, zero, dst, s1, s2; 2073dd7dbfccSRichard Henderson TCGv_i64 c64 = tcg_temp_new_i64(); 2074fcf5ef2aSThomas Huth 2075fcf5ef2aSThomas Huth /* We have two choices here: extend the 32 bit data and use movcond_i64, 2076fcf5ef2aSThomas Huth or fold the comparison down to 32 bits and use movcond_i32. Choose 2077fcf5ef2aSThomas Huth the later. */ 2078fcf5ef2aSThomas Huth c32 = tcg_temp_new_i32(); 2079c8507ebfSRichard Henderson tcg_gen_setcondi_i64(cmp->cond, c64, cmp->c1, cmp->c2); 2080fcf5ef2aSThomas Huth tcg_gen_extrl_i64_i32(c32, c64); 2081fcf5ef2aSThomas Huth 2082fcf5ef2aSThomas Huth s1 = gen_load_fpr_F(dc, rs); 2083fcf5ef2aSThomas Huth s2 = gen_load_fpr_F(dc, rd); 2084388a6465SRichard Henderson dst = tcg_temp_new_i32(); 208500ab7e61SRichard Henderson zero = tcg_constant_i32(0); 2086fcf5ef2aSThomas Huth 2087fcf5ef2aSThomas Huth tcg_gen_movcond_i32(TCG_COND_NE, dst, c32, zero, s1, s2); 2088fcf5ef2aSThomas Huth 2089fcf5ef2aSThomas Huth gen_store_fpr_F(dc, rd, dst); 2090f7ec8155SRichard Henderson #else 2091f7ec8155SRichard Henderson qemu_build_not_reached(); 2092f7ec8155SRichard Henderson #endif 2093fcf5ef2aSThomas Huth } 2094fcf5ef2aSThomas Huth 2095fcf5ef2aSThomas Huth static void gen_fmovd(DisasContext *dc, DisasCompare *cmp, int rd, int rs) 2096fcf5ef2aSThomas Huth { 2097f7ec8155SRichard Henderson #ifdef TARGET_SPARC64 209852f46d46SRichard Henderson TCGv_i64 dst = tcg_temp_new_i64(); 2099c8507ebfSRichard Henderson tcg_gen_movcond_i64(cmp->cond, dst, cmp->c1, tcg_constant_tl(cmp->c2), 2100fcf5ef2aSThomas Huth gen_load_fpr_D(dc, rs), 2101fcf5ef2aSThomas Huth gen_load_fpr_D(dc, rd)); 2102fcf5ef2aSThomas Huth gen_store_fpr_D(dc, rd, dst); 2103f7ec8155SRichard Henderson #else 2104f7ec8155SRichard Henderson qemu_build_not_reached(); 2105f7ec8155SRichard Henderson #endif 2106fcf5ef2aSThomas Huth } 2107fcf5ef2aSThomas Huth 2108fcf5ef2aSThomas Huth static void gen_fmovq(DisasContext *dc, DisasCompare *cmp, int rd, int rs) 2109fcf5ef2aSThomas Huth { 2110f7ec8155SRichard Henderson #ifdef TARGET_SPARC64 2111c8507ebfSRichard Henderson TCGv c2 = tcg_constant_tl(cmp->c2); 21121210a036SRichard Henderson TCGv_i64 h = tcg_temp_new_i64(); 21131210a036SRichard Henderson TCGv_i64 l = tcg_temp_new_i64(); 2114fcf5ef2aSThomas Huth 21151210a036SRichard Henderson tcg_gen_movcond_i64(cmp->cond, h, cmp->c1, c2, 21161210a036SRichard Henderson gen_load_fpr_D(dc, rs), 21171210a036SRichard Henderson gen_load_fpr_D(dc, rd)); 21181210a036SRichard Henderson tcg_gen_movcond_i64(cmp->cond, l, cmp->c1, c2, 21191210a036SRichard Henderson gen_load_fpr_D(dc, rs + 2), 21201210a036SRichard Henderson gen_load_fpr_D(dc, rd + 2)); 21211210a036SRichard Henderson gen_store_fpr_D(dc, rd, h); 21221210a036SRichard Henderson gen_store_fpr_D(dc, rd + 2, l); 2123f7ec8155SRichard Henderson #else 2124f7ec8155SRichard Henderson qemu_build_not_reached(); 2125f7ec8155SRichard Henderson #endif 2126fcf5ef2aSThomas Huth } 2127fcf5ef2aSThomas Huth 2128f7ec8155SRichard Henderson #ifdef TARGET_SPARC64 21295d617bfbSRichard Henderson static void gen_load_trap_state_at_tl(TCGv_ptr r_tsptr) 2130fcf5ef2aSThomas Huth { 2131fcf5ef2aSThomas Huth TCGv_i32 r_tl = tcg_temp_new_i32(); 2132fcf5ef2aSThomas Huth 2133fcf5ef2aSThomas Huth /* load env->tl into r_tl */ 2134ad75a51eSRichard Henderson tcg_gen_ld_i32(r_tl, tcg_env, offsetof(CPUSPARCState, tl)); 2135fcf5ef2aSThomas Huth 2136fcf5ef2aSThomas Huth /* tl = [0 ... MAXTL_MASK] where MAXTL_MASK must be power of 2 */ 2137fcf5ef2aSThomas Huth tcg_gen_andi_i32(r_tl, r_tl, MAXTL_MASK); 2138fcf5ef2aSThomas Huth 2139fcf5ef2aSThomas Huth /* calculate offset to current trap state from env->ts, reuse r_tl */ 2140fcf5ef2aSThomas Huth tcg_gen_muli_i32(r_tl, r_tl, sizeof (trap_state)); 2141ad75a51eSRichard Henderson tcg_gen_addi_ptr(r_tsptr, tcg_env, offsetof(CPUSPARCState, ts)); 2142fcf5ef2aSThomas Huth 2143fcf5ef2aSThomas Huth /* tsptr = env->ts[env->tl & MAXTL_MASK] */ 2144fcf5ef2aSThomas Huth { 2145fcf5ef2aSThomas Huth TCGv_ptr r_tl_tmp = tcg_temp_new_ptr(); 2146fcf5ef2aSThomas Huth tcg_gen_ext_i32_ptr(r_tl_tmp, r_tl); 2147fcf5ef2aSThomas Huth tcg_gen_add_ptr(r_tsptr, r_tsptr, r_tl_tmp); 2148fcf5ef2aSThomas Huth } 2149fcf5ef2aSThomas Huth } 2150fcf5ef2aSThomas Huth #endif 2151fcf5ef2aSThomas Huth 215206c060d9SRichard Henderson static int extract_dfpreg(DisasContext *dc, int x) 215306c060d9SRichard Henderson { 21540bba7572SRichard Henderson int r = x & 0x1e; 21550bba7572SRichard Henderson #ifdef TARGET_SPARC64 21560bba7572SRichard Henderson r |= (x & 1) << 5; 21570bba7572SRichard Henderson #endif 21580bba7572SRichard Henderson return r; 215906c060d9SRichard Henderson } 216006c060d9SRichard Henderson 216106c060d9SRichard Henderson static int extract_qfpreg(DisasContext *dc, int x) 216206c060d9SRichard Henderson { 21630bba7572SRichard Henderson int r = x & 0x1c; 21640bba7572SRichard Henderson #ifdef TARGET_SPARC64 21650bba7572SRichard Henderson r |= (x & 1) << 5; 21660bba7572SRichard Henderson #endif 21670bba7572SRichard Henderson return r; 216806c060d9SRichard Henderson } 216906c060d9SRichard Henderson 2170878cc677SRichard Henderson /* Include the auto-generated decoder. */ 2171878cc677SRichard Henderson #include "decode-insns.c.inc" 2172878cc677SRichard Henderson 2173878cc677SRichard Henderson #define TRANS(NAME, AVAIL, FUNC, ...) \ 2174878cc677SRichard Henderson static bool trans_##NAME(DisasContext *dc, arg_##NAME *a) \ 2175878cc677SRichard Henderson { return avail_##AVAIL(dc) && FUNC(dc, __VA_ARGS__); } 2176878cc677SRichard Henderson 2177878cc677SRichard Henderson #define avail_ALL(C) true 2178878cc677SRichard Henderson #ifdef TARGET_SPARC64 2179878cc677SRichard Henderson # define avail_32(C) false 2180af25071cSRichard Henderson # define avail_ASR17(C) false 2181d0a11d25SRichard Henderson # define avail_CASA(C) true 2182c2636853SRichard Henderson # define avail_DIV(C) true 2183b5372650SRichard Henderson # define avail_MUL(C) true 21840faef01bSRichard Henderson # define avail_POWERDOWN(C) false 2185878cc677SRichard Henderson # define avail_64(C) true 2186*4fd71d19SRichard Henderson # define avail_FMAF(C) ((C)->def->features & CPU_FEATURE_FMAF) 21875d617bfbSRichard Henderson # define avail_GL(C) ((C)->def->features & CPU_FEATURE_GL) 2188af25071cSRichard Henderson # define avail_HYPV(C) ((C)->def->features & CPU_FEATURE_HYPV) 2189b88ce6f2SRichard Henderson # define avail_VIS1(C) ((C)->def->features & CPU_FEATURE_VIS1) 2190b88ce6f2SRichard Henderson # define avail_VIS2(C) ((C)->def->features & CPU_FEATURE_VIS2) 2191878cc677SRichard Henderson #else 2192878cc677SRichard Henderson # define avail_32(C) true 2193af25071cSRichard Henderson # define avail_ASR17(C) ((C)->def->features & CPU_FEATURE_ASR17) 2194d0a11d25SRichard Henderson # define avail_CASA(C) ((C)->def->features & CPU_FEATURE_CASA) 2195c2636853SRichard Henderson # define avail_DIV(C) ((C)->def->features & CPU_FEATURE_DIV) 2196b5372650SRichard Henderson # define avail_MUL(C) ((C)->def->features & CPU_FEATURE_MUL) 21970faef01bSRichard Henderson # define avail_POWERDOWN(C) ((C)->def->features & CPU_FEATURE_POWERDOWN) 2198878cc677SRichard Henderson # define avail_64(C) false 2199*4fd71d19SRichard Henderson # define avail_FMAF(C) false 22005d617bfbSRichard Henderson # define avail_GL(C) false 2201af25071cSRichard Henderson # define avail_HYPV(C) false 2202b88ce6f2SRichard Henderson # define avail_VIS1(C) false 2203b88ce6f2SRichard Henderson # define avail_VIS2(C) false 2204878cc677SRichard Henderson #endif 2205878cc677SRichard Henderson 2206878cc677SRichard Henderson /* Default case for non jump instructions. */ 2207878cc677SRichard Henderson static bool advance_pc(DisasContext *dc) 2208878cc677SRichard Henderson { 22094a8d145dSRichard Henderson TCGLabel *l1; 22104a8d145dSRichard Henderson 221189527e3aSRichard Henderson finishing_insn(dc); 221289527e3aSRichard Henderson 2213878cc677SRichard Henderson if (dc->npc & 3) { 2214878cc677SRichard Henderson switch (dc->npc) { 2215878cc677SRichard Henderson case DYNAMIC_PC: 2216878cc677SRichard Henderson case DYNAMIC_PC_LOOKUP: 2217878cc677SRichard Henderson dc->pc = dc->npc; 2218444d8b30SRichard Henderson tcg_gen_mov_tl(cpu_pc, cpu_npc); 2219444d8b30SRichard Henderson tcg_gen_addi_tl(cpu_npc, cpu_npc, 4); 2220878cc677SRichard Henderson break; 22214a8d145dSRichard Henderson 2222878cc677SRichard Henderson case JUMP_PC: 2223878cc677SRichard Henderson /* we can do a static jump */ 22244a8d145dSRichard Henderson l1 = gen_new_label(); 2225533f042fSRichard Henderson tcg_gen_brcondi_tl(dc->jump.cond, dc->jump.c1, dc->jump.c2, l1); 22264a8d145dSRichard Henderson 22274a8d145dSRichard Henderson /* jump not taken */ 22284a8d145dSRichard Henderson gen_goto_tb(dc, 1, dc->jump_pc[1], dc->jump_pc[1] + 4); 22294a8d145dSRichard Henderson 22304a8d145dSRichard Henderson /* jump taken */ 22314a8d145dSRichard Henderson gen_set_label(l1); 22324a8d145dSRichard Henderson gen_goto_tb(dc, 0, dc->jump_pc[0], dc->jump_pc[0] + 4); 22334a8d145dSRichard Henderson 2234878cc677SRichard Henderson dc->base.is_jmp = DISAS_NORETURN; 2235878cc677SRichard Henderson break; 22364a8d145dSRichard Henderson 2237878cc677SRichard Henderson default: 2238878cc677SRichard Henderson g_assert_not_reached(); 2239878cc677SRichard Henderson } 2240878cc677SRichard Henderson } else { 2241878cc677SRichard Henderson dc->pc = dc->npc; 2242878cc677SRichard Henderson dc->npc = dc->npc + 4; 2243878cc677SRichard Henderson } 2244878cc677SRichard Henderson return true; 2245878cc677SRichard Henderson } 2246878cc677SRichard Henderson 22476d2a0768SRichard Henderson /* 22486d2a0768SRichard Henderson * Major opcodes 00 and 01 -- branches, call, and sethi 22496d2a0768SRichard Henderson */ 22506d2a0768SRichard Henderson 22519d4e2bc7SRichard Henderson static bool advance_jump_cond(DisasContext *dc, DisasCompare *cmp, 22523951b7a8SRichard Henderson bool annul, int disp) 2253276567aaSRichard Henderson { 22543951b7a8SRichard Henderson target_ulong dest = address_mask_i(dc, dc->pc + disp * 4); 2255c76c8045SRichard Henderson target_ulong npc; 2256c76c8045SRichard Henderson 225789527e3aSRichard Henderson finishing_insn(dc); 225889527e3aSRichard Henderson 22592d9bb237SRichard Henderson if (cmp->cond == TCG_COND_ALWAYS) { 22602d9bb237SRichard Henderson if (annul) { 22612d9bb237SRichard Henderson dc->pc = dest; 22622d9bb237SRichard Henderson dc->npc = dest + 4; 22632d9bb237SRichard Henderson } else { 22642d9bb237SRichard Henderson gen_mov_pc_npc(dc); 22652d9bb237SRichard Henderson dc->npc = dest; 22662d9bb237SRichard Henderson } 22672d9bb237SRichard Henderson return true; 22682d9bb237SRichard Henderson } 22692d9bb237SRichard Henderson 22702d9bb237SRichard Henderson if (cmp->cond == TCG_COND_NEVER) { 22712d9bb237SRichard Henderson npc = dc->npc; 22722d9bb237SRichard Henderson if (npc & 3) { 22732d9bb237SRichard Henderson gen_mov_pc_npc(dc); 22742d9bb237SRichard Henderson if (annul) { 22752d9bb237SRichard Henderson tcg_gen_addi_tl(cpu_pc, cpu_pc, 4); 22762d9bb237SRichard Henderson } 22772d9bb237SRichard Henderson tcg_gen_addi_tl(cpu_npc, cpu_pc, 4); 22782d9bb237SRichard Henderson } else { 22792d9bb237SRichard Henderson dc->pc = npc + (annul ? 4 : 0); 22802d9bb237SRichard Henderson dc->npc = dc->pc + 4; 22812d9bb237SRichard Henderson } 22822d9bb237SRichard Henderson return true; 22832d9bb237SRichard Henderson } 22842d9bb237SRichard Henderson 2285c76c8045SRichard Henderson flush_cond(dc); 2286c76c8045SRichard Henderson npc = dc->npc; 22876b3e4cc6SRichard Henderson 2288276567aaSRichard Henderson if (annul) { 22896b3e4cc6SRichard Henderson TCGLabel *l1 = gen_new_label(); 22906b3e4cc6SRichard Henderson 2291c8507ebfSRichard Henderson tcg_gen_brcondi_tl(tcg_invert_cond(cmp->cond), cmp->c1, cmp->c2, l1); 22926b3e4cc6SRichard Henderson gen_goto_tb(dc, 0, npc, dest); 22936b3e4cc6SRichard Henderson gen_set_label(l1); 22946b3e4cc6SRichard Henderson gen_goto_tb(dc, 1, npc + 4, npc + 8); 22956b3e4cc6SRichard Henderson 22966b3e4cc6SRichard Henderson dc->base.is_jmp = DISAS_NORETURN; 2297276567aaSRichard Henderson } else { 22986b3e4cc6SRichard Henderson if (npc & 3) { 22996b3e4cc6SRichard Henderson switch (npc) { 23006b3e4cc6SRichard Henderson case DYNAMIC_PC: 23016b3e4cc6SRichard Henderson case DYNAMIC_PC_LOOKUP: 23026b3e4cc6SRichard Henderson tcg_gen_mov_tl(cpu_pc, cpu_npc); 23036b3e4cc6SRichard Henderson tcg_gen_addi_tl(cpu_npc, cpu_npc, 4); 23049d4e2bc7SRichard Henderson tcg_gen_movcond_tl(cmp->cond, cpu_npc, 2305c8507ebfSRichard Henderson cmp->c1, tcg_constant_tl(cmp->c2), 23066b3e4cc6SRichard Henderson tcg_constant_tl(dest), cpu_npc); 23076b3e4cc6SRichard Henderson dc->pc = npc; 23086b3e4cc6SRichard Henderson break; 23096b3e4cc6SRichard Henderson default: 23106b3e4cc6SRichard Henderson g_assert_not_reached(); 23116b3e4cc6SRichard Henderson } 23126b3e4cc6SRichard Henderson } else { 23136b3e4cc6SRichard Henderson dc->pc = npc; 2314533f042fSRichard Henderson dc->npc = JUMP_PC; 2315533f042fSRichard Henderson dc->jump = *cmp; 23166b3e4cc6SRichard Henderson dc->jump_pc[0] = dest; 23176b3e4cc6SRichard Henderson dc->jump_pc[1] = npc + 4; 2318dd7dbfccSRichard Henderson 2319dd7dbfccSRichard Henderson /* The condition for cpu_cond is always NE -- normalize. */ 2320dd7dbfccSRichard Henderson if (cmp->cond == TCG_COND_NE) { 2321c8507ebfSRichard Henderson tcg_gen_xori_tl(cpu_cond, cmp->c1, cmp->c2); 23229d4e2bc7SRichard Henderson } else { 2323c8507ebfSRichard Henderson tcg_gen_setcondi_tl(cmp->cond, cpu_cond, cmp->c1, cmp->c2); 23249d4e2bc7SRichard Henderson } 232589527e3aSRichard Henderson dc->cpu_cond_live = true; 23266b3e4cc6SRichard Henderson } 2327276567aaSRichard Henderson } 2328276567aaSRichard Henderson return true; 2329276567aaSRichard Henderson } 2330276567aaSRichard Henderson 2331af25071cSRichard Henderson static bool raise_priv(DisasContext *dc) 2332af25071cSRichard Henderson { 2333af25071cSRichard Henderson gen_exception(dc, TT_PRIV_INSN); 2334af25071cSRichard Henderson return true; 2335af25071cSRichard Henderson } 2336af25071cSRichard Henderson 233706c060d9SRichard Henderson static bool raise_unimpfpop(DisasContext *dc) 233806c060d9SRichard Henderson { 233906c060d9SRichard Henderson gen_op_fpexception_im(dc, FSR_FTT_UNIMPFPOP); 234006c060d9SRichard Henderson return true; 234106c060d9SRichard Henderson } 234206c060d9SRichard Henderson 234306c060d9SRichard Henderson static bool gen_trap_float128(DisasContext *dc) 234406c060d9SRichard Henderson { 234506c060d9SRichard Henderson if (dc->def->features & CPU_FEATURE_FLOAT128) { 234606c060d9SRichard Henderson return false; 234706c060d9SRichard Henderson } 234806c060d9SRichard Henderson return raise_unimpfpop(dc); 234906c060d9SRichard Henderson } 235006c060d9SRichard Henderson 2351276567aaSRichard Henderson static bool do_bpcc(DisasContext *dc, arg_bcc *a) 2352276567aaSRichard Henderson { 23531ea9c62aSRichard Henderson DisasCompare cmp; 2354276567aaSRichard Henderson 23551ea9c62aSRichard Henderson gen_compare(&cmp, a->cc, a->cond, dc); 23563951b7a8SRichard Henderson return advance_jump_cond(dc, &cmp, a->a, a->i); 2357276567aaSRichard Henderson } 2358276567aaSRichard Henderson 2359276567aaSRichard Henderson TRANS(Bicc, ALL, do_bpcc, a) 2360276567aaSRichard Henderson TRANS(BPcc, 64, do_bpcc, a) 2361276567aaSRichard Henderson 236245196ea4SRichard Henderson static bool do_fbpfcc(DisasContext *dc, arg_bcc *a) 236345196ea4SRichard Henderson { 2364d5471936SRichard Henderson DisasCompare cmp; 236545196ea4SRichard Henderson 236645196ea4SRichard Henderson if (gen_trap_ifnofpu(dc)) { 236745196ea4SRichard Henderson return true; 236845196ea4SRichard Henderson } 2369d5471936SRichard Henderson gen_fcompare(&cmp, a->cc, a->cond); 23703951b7a8SRichard Henderson return advance_jump_cond(dc, &cmp, a->a, a->i); 237145196ea4SRichard Henderson } 237245196ea4SRichard Henderson 237345196ea4SRichard Henderson TRANS(FBPfcc, 64, do_fbpfcc, a) 237445196ea4SRichard Henderson TRANS(FBfcc, ALL, do_fbpfcc, a) 237545196ea4SRichard Henderson 2376ab9ffe98SRichard Henderson static bool trans_BPr(DisasContext *dc, arg_BPr *a) 2377ab9ffe98SRichard Henderson { 2378ab9ffe98SRichard Henderson DisasCompare cmp; 2379ab9ffe98SRichard Henderson 2380ab9ffe98SRichard Henderson if (!avail_64(dc)) { 2381ab9ffe98SRichard Henderson return false; 2382ab9ffe98SRichard Henderson } 23832c4f56c9SRichard Henderson if (!gen_compare_reg(&cmp, a->cond, gen_load_gpr(dc, a->rs1))) { 2384ab9ffe98SRichard Henderson return false; 2385ab9ffe98SRichard Henderson } 23863951b7a8SRichard Henderson return advance_jump_cond(dc, &cmp, a->a, a->i); 2387ab9ffe98SRichard Henderson } 2388ab9ffe98SRichard Henderson 238923ada1b1SRichard Henderson static bool trans_CALL(DisasContext *dc, arg_CALL *a) 239023ada1b1SRichard Henderson { 239123ada1b1SRichard Henderson target_long target = address_mask_i(dc, dc->pc + a->i * 4); 239223ada1b1SRichard Henderson 239323ada1b1SRichard Henderson gen_store_gpr(dc, 15, tcg_constant_tl(dc->pc)); 239423ada1b1SRichard Henderson gen_mov_pc_npc(dc); 239523ada1b1SRichard Henderson dc->npc = target; 239623ada1b1SRichard Henderson return true; 239723ada1b1SRichard Henderson } 239823ada1b1SRichard Henderson 239945196ea4SRichard Henderson static bool trans_NCP(DisasContext *dc, arg_NCP *a) 240045196ea4SRichard Henderson { 240145196ea4SRichard Henderson /* 240245196ea4SRichard Henderson * For sparc32, always generate the no-coprocessor exception. 240345196ea4SRichard Henderson * For sparc64, always generate illegal instruction. 240445196ea4SRichard Henderson */ 240545196ea4SRichard Henderson #ifdef TARGET_SPARC64 240645196ea4SRichard Henderson return false; 240745196ea4SRichard Henderson #else 240845196ea4SRichard Henderson gen_exception(dc, TT_NCP_INSN); 240945196ea4SRichard Henderson return true; 241045196ea4SRichard Henderson #endif 241145196ea4SRichard Henderson } 241245196ea4SRichard Henderson 24136d2a0768SRichard Henderson static bool trans_SETHI(DisasContext *dc, arg_SETHI *a) 24146d2a0768SRichard Henderson { 24156d2a0768SRichard Henderson /* Special-case %g0 because that's the canonical nop. */ 24166d2a0768SRichard Henderson if (a->rd) { 24176d2a0768SRichard Henderson gen_store_gpr(dc, a->rd, tcg_constant_tl((uint32_t)a->i << 10)); 24186d2a0768SRichard Henderson } 24196d2a0768SRichard Henderson return advance_pc(dc); 24206d2a0768SRichard Henderson } 24216d2a0768SRichard Henderson 24220faef01bSRichard Henderson /* 24230faef01bSRichard Henderson * Major Opcode 10 -- integer, floating-point, vis, and system insns. 24240faef01bSRichard Henderson */ 24250faef01bSRichard Henderson 242630376636SRichard Henderson static bool do_tcc(DisasContext *dc, int cond, int cc, 242730376636SRichard Henderson int rs1, bool imm, int rs2_or_imm) 242830376636SRichard Henderson { 242930376636SRichard Henderson int mask = ((dc->def->features & CPU_FEATURE_HYPV) && supervisor(dc) 243030376636SRichard Henderson ? UA2005_HTRAP_MASK : V8_TRAP_MASK); 243130376636SRichard Henderson DisasCompare cmp; 243230376636SRichard Henderson TCGLabel *lab; 243330376636SRichard Henderson TCGv_i32 trap; 243430376636SRichard Henderson 243530376636SRichard Henderson /* Trap never. */ 243630376636SRichard Henderson if (cond == 0) { 243730376636SRichard Henderson return advance_pc(dc); 243830376636SRichard Henderson } 243930376636SRichard Henderson 244030376636SRichard Henderson /* 244130376636SRichard Henderson * Immediate traps are the most common case. Since this value is 244230376636SRichard Henderson * live across the branch, it really pays to evaluate the constant. 244330376636SRichard Henderson */ 244430376636SRichard Henderson if (rs1 == 0 && (imm || rs2_or_imm == 0)) { 244530376636SRichard Henderson trap = tcg_constant_i32((rs2_or_imm & mask) + TT_TRAP); 244630376636SRichard Henderson } else { 244730376636SRichard Henderson trap = tcg_temp_new_i32(); 244830376636SRichard Henderson tcg_gen_trunc_tl_i32(trap, gen_load_gpr(dc, rs1)); 244930376636SRichard Henderson if (imm) { 245030376636SRichard Henderson tcg_gen_addi_i32(trap, trap, rs2_or_imm); 245130376636SRichard Henderson } else { 245230376636SRichard Henderson TCGv_i32 t2 = tcg_temp_new_i32(); 245330376636SRichard Henderson tcg_gen_trunc_tl_i32(t2, gen_load_gpr(dc, rs2_or_imm)); 245430376636SRichard Henderson tcg_gen_add_i32(trap, trap, t2); 245530376636SRichard Henderson } 245630376636SRichard Henderson tcg_gen_andi_i32(trap, trap, mask); 245730376636SRichard Henderson tcg_gen_addi_i32(trap, trap, TT_TRAP); 245830376636SRichard Henderson } 245930376636SRichard Henderson 246089527e3aSRichard Henderson finishing_insn(dc); 246189527e3aSRichard Henderson 246230376636SRichard Henderson /* Trap always. */ 246330376636SRichard Henderson if (cond == 8) { 246430376636SRichard Henderson save_state(dc); 246530376636SRichard Henderson gen_helper_raise_exception(tcg_env, trap); 246630376636SRichard Henderson dc->base.is_jmp = DISAS_NORETURN; 246730376636SRichard Henderson return true; 246830376636SRichard Henderson } 246930376636SRichard Henderson 247030376636SRichard Henderson /* Conditional trap. */ 247130376636SRichard Henderson flush_cond(dc); 247230376636SRichard Henderson lab = delay_exceptionv(dc, trap); 247330376636SRichard Henderson gen_compare(&cmp, cc, cond, dc); 2474c8507ebfSRichard Henderson tcg_gen_brcondi_tl(cmp.cond, cmp.c1, cmp.c2, lab); 247530376636SRichard Henderson 247630376636SRichard Henderson return advance_pc(dc); 247730376636SRichard Henderson } 247830376636SRichard Henderson 247930376636SRichard Henderson static bool trans_Tcc_r(DisasContext *dc, arg_Tcc_r *a) 248030376636SRichard Henderson { 248130376636SRichard Henderson if (avail_32(dc) && a->cc) { 248230376636SRichard Henderson return false; 248330376636SRichard Henderson } 248430376636SRichard Henderson return do_tcc(dc, a->cond, a->cc, a->rs1, false, a->rs2); 248530376636SRichard Henderson } 248630376636SRichard Henderson 248730376636SRichard Henderson static bool trans_Tcc_i_v7(DisasContext *dc, arg_Tcc_i_v7 *a) 248830376636SRichard Henderson { 248930376636SRichard Henderson if (avail_64(dc)) { 249030376636SRichard Henderson return false; 249130376636SRichard Henderson } 249230376636SRichard Henderson return do_tcc(dc, a->cond, 0, a->rs1, true, a->i); 249330376636SRichard Henderson } 249430376636SRichard Henderson 249530376636SRichard Henderson static bool trans_Tcc_i_v9(DisasContext *dc, arg_Tcc_i_v9 *a) 249630376636SRichard Henderson { 249730376636SRichard Henderson if (avail_32(dc)) { 249830376636SRichard Henderson return false; 249930376636SRichard Henderson } 250030376636SRichard Henderson return do_tcc(dc, a->cond, a->cc, a->rs1, true, a->i); 250130376636SRichard Henderson } 250230376636SRichard Henderson 2503af25071cSRichard Henderson static bool trans_STBAR(DisasContext *dc, arg_STBAR *a) 2504af25071cSRichard Henderson { 2505af25071cSRichard Henderson tcg_gen_mb(TCG_MO_ST_ST | TCG_BAR_SC); 2506af25071cSRichard Henderson return advance_pc(dc); 2507af25071cSRichard Henderson } 2508af25071cSRichard Henderson 2509af25071cSRichard Henderson static bool trans_MEMBAR(DisasContext *dc, arg_MEMBAR *a) 2510af25071cSRichard Henderson { 2511af25071cSRichard Henderson if (avail_32(dc)) { 2512af25071cSRichard Henderson return false; 2513af25071cSRichard Henderson } 2514af25071cSRichard Henderson if (a->mmask) { 2515af25071cSRichard Henderson /* Note TCG_MO_* was modeled on sparc64, so mmask matches. */ 2516af25071cSRichard Henderson tcg_gen_mb(a->mmask | TCG_BAR_SC); 2517af25071cSRichard Henderson } 2518af25071cSRichard Henderson if (a->cmask) { 2519af25071cSRichard Henderson /* For #Sync, etc, end the TB to recognize interrupts. */ 2520af25071cSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 2521af25071cSRichard Henderson } 2522af25071cSRichard Henderson return advance_pc(dc); 2523af25071cSRichard Henderson } 2524af25071cSRichard Henderson 2525af25071cSRichard Henderson static bool do_rd_special(DisasContext *dc, bool priv, int rd, 2526af25071cSRichard Henderson TCGv (*func)(DisasContext *, TCGv)) 2527af25071cSRichard Henderson { 2528af25071cSRichard Henderson if (!priv) { 2529af25071cSRichard Henderson return raise_priv(dc); 2530af25071cSRichard Henderson } 2531af25071cSRichard Henderson gen_store_gpr(dc, rd, func(dc, gen_dest_gpr(dc, rd))); 2532af25071cSRichard Henderson return advance_pc(dc); 2533af25071cSRichard Henderson } 2534af25071cSRichard Henderson 2535af25071cSRichard Henderson static TCGv do_rdy(DisasContext *dc, TCGv dst) 2536af25071cSRichard Henderson { 2537af25071cSRichard Henderson return cpu_y; 2538af25071cSRichard Henderson } 2539af25071cSRichard Henderson 2540af25071cSRichard Henderson static bool trans_RDY(DisasContext *dc, arg_RDY *a) 2541af25071cSRichard Henderson { 2542af25071cSRichard Henderson /* 2543af25071cSRichard Henderson * TODO: Need a feature bit for sparcv8. In the meantime, treat all 2544af25071cSRichard Henderson * 32-bit cpus like sparcv7, which ignores the rs1 field. 2545af25071cSRichard Henderson * This matches after all other ASR, so Leon3 Asr17 is handled first. 2546af25071cSRichard Henderson */ 2547af25071cSRichard Henderson if (avail_64(dc) && a->rs1 != 0) { 2548af25071cSRichard Henderson return false; 2549af25071cSRichard Henderson } 2550af25071cSRichard Henderson return do_rd_special(dc, true, a->rd, do_rdy); 2551af25071cSRichard Henderson } 2552af25071cSRichard Henderson 2553af25071cSRichard Henderson static TCGv do_rd_leon3_config(DisasContext *dc, TCGv dst) 2554af25071cSRichard Henderson { 2555c92948f2SClément Chigot gen_helper_rdasr17(dst, tcg_env); 2556c92948f2SClément Chigot return dst; 2557af25071cSRichard Henderson } 2558af25071cSRichard Henderson 2559af25071cSRichard Henderson TRANS(RDASR17, ASR17, do_rd_special, true, a->rd, do_rd_leon3_config) 2560af25071cSRichard Henderson 2561af25071cSRichard Henderson static TCGv do_rdccr(DisasContext *dc, TCGv dst) 2562af25071cSRichard Henderson { 2563af25071cSRichard Henderson gen_helper_rdccr(dst, tcg_env); 2564af25071cSRichard Henderson return dst; 2565af25071cSRichard Henderson } 2566af25071cSRichard Henderson 2567af25071cSRichard Henderson TRANS(RDCCR, 64, do_rd_special, true, a->rd, do_rdccr) 2568af25071cSRichard Henderson 2569af25071cSRichard Henderson static TCGv do_rdasi(DisasContext *dc, TCGv dst) 2570af25071cSRichard Henderson { 2571af25071cSRichard Henderson #ifdef TARGET_SPARC64 2572af25071cSRichard Henderson return tcg_constant_tl(dc->asi); 2573af25071cSRichard Henderson #else 2574af25071cSRichard Henderson qemu_build_not_reached(); 2575af25071cSRichard Henderson #endif 2576af25071cSRichard Henderson } 2577af25071cSRichard Henderson 2578af25071cSRichard Henderson TRANS(RDASI, 64, do_rd_special, true, a->rd, do_rdasi) 2579af25071cSRichard Henderson 2580af25071cSRichard Henderson static TCGv do_rdtick(DisasContext *dc, TCGv dst) 2581af25071cSRichard Henderson { 2582af25071cSRichard Henderson TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 2583af25071cSRichard Henderson 2584af25071cSRichard Henderson tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(tick)); 2585af25071cSRichard Henderson if (translator_io_start(&dc->base)) { 2586af25071cSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 2587af25071cSRichard Henderson } 2588af25071cSRichard Henderson gen_helper_tick_get_count(dst, tcg_env, r_tickptr, 2589af25071cSRichard Henderson tcg_constant_i32(dc->mem_idx)); 2590af25071cSRichard Henderson return dst; 2591af25071cSRichard Henderson } 2592af25071cSRichard Henderson 2593af25071cSRichard Henderson /* TODO: non-priv access only allowed when enabled. */ 2594af25071cSRichard Henderson TRANS(RDTICK, 64, do_rd_special, true, a->rd, do_rdtick) 2595af25071cSRichard Henderson 2596af25071cSRichard Henderson static TCGv do_rdpc(DisasContext *dc, TCGv dst) 2597af25071cSRichard Henderson { 2598af25071cSRichard Henderson return tcg_constant_tl(address_mask_i(dc, dc->pc)); 2599af25071cSRichard Henderson } 2600af25071cSRichard Henderson 2601af25071cSRichard Henderson TRANS(RDPC, 64, do_rd_special, true, a->rd, do_rdpc) 2602af25071cSRichard Henderson 2603af25071cSRichard Henderson static TCGv do_rdfprs(DisasContext *dc, TCGv dst) 2604af25071cSRichard Henderson { 2605af25071cSRichard Henderson tcg_gen_ext_i32_tl(dst, cpu_fprs); 2606af25071cSRichard Henderson return dst; 2607af25071cSRichard Henderson } 2608af25071cSRichard Henderson 2609af25071cSRichard Henderson TRANS(RDFPRS, 64, do_rd_special, true, a->rd, do_rdfprs) 2610af25071cSRichard Henderson 2611af25071cSRichard Henderson static TCGv do_rdgsr(DisasContext *dc, TCGv dst) 2612af25071cSRichard Henderson { 2613af25071cSRichard Henderson gen_trap_ifnofpu(dc); 2614af25071cSRichard Henderson return cpu_gsr; 2615af25071cSRichard Henderson } 2616af25071cSRichard Henderson 2617af25071cSRichard Henderson TRANS(RDGSR, 64, do_rd_special, true, a->rd, do_rdgsr) 2618af25071cSRichard Henderson 2619af25071cSRichard Henderson static TCGv do_rdsoftint(DisasContext *dc, TCGv dst) 2620af25071cSRichard Henderson { 2621af25071cSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(softint)); 2622af25071cSRichard Henderson return dst; 2623af25071cSRichard Henderson } 2624af25071cSRichard Henderson 2625af25071cSRichard Henderson TRANS(RDSOFTINT, 64, do_rd_special, supervisor(dc), a->rd, do_rdsoftint) 2626af25071cSRichard Henderson 2627af25071cSRichard Henderson static TCGv do_rdtick_cmpr(DisasContext *dc, TCGv dst) 2628af25071cSRichard Henderson { 2629577efa45SRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(tick_cmpr)); 2630577efa45SRichard Henderson return dst; 2631af25071cSRichard Henderson } 2632af25071cSRichard Henderson 2633af25071cSRichard Henderson /* TODO: non-priv access only allowed when enabled. */ 2634af25071cSRichard Henderson TRANS(RDTICK_CMPR, 64, do_rd_special, true, a->rd, do_rdtick_cmpr) 2635af25071cSRichard Henderson 2636af25071cSRichard Henderson static TCGv do_rdstick(DisasContext *dc, TCGv dst) 2637af25071cSRichard Henderson { 2638af25071cSRichard Henderson TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 2639af25071cSRichard Henderson 2640af25071cSRichard Henderson tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(stick)); 2641af25071cSRichard Henderson if (translator_io_start(&dc->base)) { 2642af25071cSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 2643af25071cSRichard Henderson } 2644af25071cSRichard Henderson gen_helper_tick_get_count(dst, tcg_env, r_tickptr, 2645af25071cSRichard Henderson tcg_constant_i32(dc->mem_idx)); 2646af25071cSRichard Henderson return dst; 2647af25071cSRichard Henderson } 2648af25071cSRichard Henderson 2649af25071cSRichard Henderson /* TODO: non-priv access only allowed when enabled. */ 2650af25071cSRichard Henderson TRANS(RDSTICK, 64, do_rd_special, true, a->rd, do_rdstick) 2651af25071cSRichard Henderson 2652af25071cSRichard Henderson static TCGv do_rdstick_cmpr(DisasContext *dc, TCGv dst) 2653af25071cSRichard Henderson { 2654577efa45SRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(stick_cmpr)); 2655577efa45SRichard Henderson return dst; 2656af25071cSRichard Henderson } 2657af25071cSRichard Henderson 2658af25071cSRichard Henderson /* TODO: supervisor access only allowed when enabled by hypervisor. */ 2659af25071cSRichard Henderson TRANS(RDSTICK_CMPR, 64, do_rd_special, supervisor(dc), a->rd, do_rdstick_cmpr) 2660af25071cSRichard Henderson 2661af25071cSRichard Henderson /* 2662af25071cSRichard Henderson * UltraSPARC-T1 Strand status. 2663af25071cSRichard Henderson * HYPV check maybe not enough, UA2005 & UA2007 describe 2664af25071cSRichard Henderson * this ASR as impl. dep 2665af25071cSRichard Henderson */ 2666af25071cSRichard Henderson static TCGv do_rdstrand_status(DisasContext *dc, TCGv dst) 2667af25071cSRichard Henderson { 2668af25071cSRichard Henderson return tcg_constant_tl(1); 2669af25071cSRichard Henderson } 2670af25071cSRichard Henderson 2671af25071cSRichard Henderson TRANS(RDSTRAND_STATUS, HYPV, do_rd_special, true, a->rd, do_rdstrand_status) 2672af25071cSRichard Henderson 2673668bb9b7SRichard Henderson static TCGv do_rdpsr(DisasContext *dc, TCGv dst) 2674668bb9b7SRichard Henderson { 2675668bb9b7SRichard Henderson gen_helper_rdpsr(dst, tcg_env); 2676668bb9b7SRichard Henderson return dst; 2677668bb9b7SRichard Henderson } 2678668bb9b7SRichard Henderson 2679668bb9b7SRichard Henderson TRANS(RDPSR, 32, do_rd_special, supervisor(dc), a->rd, do_rdpsr) 2680668bb9b7SRichard Henderson 2681668bb9b7SRichard Henderson static TCGv do_rdhpstate(DisasContext *dc, TCGv dst) 2682668bb9b7SRichard Henderson { 2683668bb9b7SRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hpstate)); 2684668bb9b7SRichard Henderson return dst; 2685668bb9b7SRichard Henderson } 2686668bb9b7SRichard Henderson 2687668bb9b7SRichard Henderson TRANS(RDHPR_hpstate, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhpstate) 2688668bb9b7SRichard Henderson 2689668bb9b7SRichard Henderson static TCGv do_rdhtstate(DisasContext *dc, TCGv dst) 2690668bb9b7SRichard Henderson { 2691668bb9b7SRichard Henderson TCGv_i32 tl = tcg_temp_new_i32(); 2692668bb9b7SRichard Henderson TCGv_ptr tp = tcg_temp_new_ptr(); 2693668bb9b7SRichard Henderson 2694668bb9b7SRichard Henderson tcg_gen_ld_i32(tl, tcg_env, env64_field_offsetof(tl)); 2695668bb9b7SRichard Henderson tcg_gen_andi_i32(tl, tl, MAXTL_MASK); 2696668bb9b7SRichard Henderson tcg_gen_shli_i32(tl, tl, 3); 2697668bb9b7SRichard Henderson tcg_gen_ext_i32_ptr(tp, tl); 2698668bb9b7SRichard Henderson tcg_gen_add_ptr(tp, tp, tcg_env); 2699668bb9b7SRichard Henderson 2700668bb9b7SRichard Henderson tcg_gen_ld_tl(dst, tp, env64_field_offsetof(htstate)); 2701668bb9b7SRichard Henderson return dst; 2702668bb9b7SRichard Henderson } 2703668bb9b7SRichard Henderson 2704668bb9b7SRichard Henderson TRANS(RDHPR_htstate, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhtstate) 2705668bb9b7SRichard Henderson 2706668bb9b7SRichard Henderson static TCGv do_rdhintp(DisasContext *dc, TCGv dst) 2707668bb9b7SRichard Henderson { 27082da789deSRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hintp)); 27092da789deSRichard Henderson return dst; 2710668bb9b7SRichard Henderson } 2711668bb9b7SRichard Henderson 2712668bb9b7SRichard Henderson TRANS(RDHPR_hintp, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhintp) 2713668bb9b7SRichard Henderson 2714668bb9b7SRichard Henderson static TCGv do_rdhtba(DisasContext *dc, TCGv dst) 2715668bb9b7SRichard Henderson { 27162da789deSRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(htba)); 27172da789deSRichard Henderson return dst; 2718668bb9b7SRichard Henderson } 2719668bb9b7SRichard Henderson 2720668bb9b7SRichard Henderson TRANS(RDHPR_htba, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhtba) 2721668bb9b7SRichard Henderson 2722668bb9b7SRichard Henderson static TCGv do_rdhver(DisasContext *dc, TCGv dst) 2723668bb9b7SRichard Henderson { 27242da789deSRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hver)); 27252da789deSRichard Henderson return dst; 2726668bb9b7SRichard Henderson } 2727668bb9b7SRichard Henderson 2728668bb9b7SRichard Henderson TRANS(RDHPR_hver, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhver) 2729668bb9b7SRichard Henderson 2730668bb9b7SRichard Henderson static TCGv do_rdhstick_cmpr(DisasContext *dc, TCGv dst) 2731668bb9b7SRichard Henderson { 2732577efa45SRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hstick_cmpr)); 2733577efa45SRichard Henderson return dst; 2734668bb9b7SRichard Henderson } 2735668bb9b7SRichard Henderson 2736668bb9b7SRichard Henderson TRANS(RDHPR_hstick_cmpr, HYPV, do_rd_special, hypervisor(dc), a->rd, 2737668bb9b7SRichard Henderson do_rdhstick_cmpr) 2738668bb9b7SRichard Henderson 27395d617bfbSRichard Henderson static TCGv do_rdwim(DisasContext *dc, TCGv dst) 27405d617bfbSRichard Henderson { 2741cd6269f7SRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env32_field_offsetof(wim)); 2742cd6269f7SRichard Henderson return dst; 27435d617bfbSRichard Henderson } 27445d617bfbSRichard Henderson 27455d617bfbSRichard Henderson TRANS(RDWIM, 32, do_rd_special, supervisor(dc), a->rd, do_rdwim) 27465d617bfbSRichard Henderson 27475d617bfbSRichard Henderson static TCGv do_rdtpc(DisasContext *dc, TCGv dst) 27485d617bfbSRichard Henderson { 27495d617bfbSRichard Henderson #ifdef TARGET_SPARC64 27505d617bfbSRichard Henderson TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 27515d617bfbSRichard Henderson 27525d617bfbSRichard Henderson gen_load_trap_state_at_tl(r_tsptr); 27535d617bfbSRichard Henderson tcg_gen_ld_tl(dst, r_tsptr, offsetof(trap_state, tpc)); 27545d617bfbSRichard Henderson return dst; 27555d617bfbSRichard Henderson #else 27565d617bfbSRichard Henderson qemu_build_not_reached(); 27575d617bfbSRichard Henderson #endif 27585d617bfbSRichard Henderson } 27595d617bfbSRichard Henderson 27605d617bfbSRichard Henderson TRANS(RDPR_tpc, 64, do_rd_special, supervisor(dc), a->rd, do_rdtpc) 27615d617bfbSRichard Henderson 27625d617bfbSRichard Henderson static TCGv do_rdtnpc(DisasContext *dc, TCGv dst) 27635d617bfbSRichard Henderson { 27645d617bfbSRichard Henderson #ifdef TARGET_SPARC64 27655d617bfbSRichard Henderson TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 27665d617bfbSRichard Henderson 27675d617bfbSRichard Henderson gen_load_trap_state_at_tl(r_tsptr); 27685d617bfbSRichard Henderson tcg_gen_ld_tl(dst, r_tsptr, offsetof(trap_state, tnpc)); 27695d617bfbSRichard Henderson return dst; 27705d617bfbSRichard Henderson #else 27715d617bfbSRichard Henderson qemu_build_not_reached(); 27725d617bfbSRichard Henderson #endif 27735d617bfbSRichard Henderson } 27745d617bfbSRichard Henderson 27755d617bfbSRichard Henderson TRANS(RDPR_tnpc, 64, do_rd_special, supervisor(dc), a->rd, do_rdtnpc) 27765d617bfbSRichard Henderson 27775d617bfbSRichard Henderson static TCGv do_rdtstate(DisasContext *dc, TCGv dst) 27785d617bfbSRichard Henderson { 27795d617bfbSRichard Henderson #ifdef TARGET_SPARC64 27805d617bfbSRichard Henderson TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 27815d617bfbSRichard Henderson 27825d617bfbSRichard Henderson gen_load_trap_state_at_tl(r_tsptr); 27835d617bfbSRichard Henderson tcg_gen_ld_tl(dst, r_tsptr, offsetof(trap_state, tstate)); 27845d617bfbSRichard Henderson return dst; 27855d617bfbSRichard Henderson #else 27865d617bfbSRichard Henderson qemu_build_not_reached(); 27875d617bfbSRichard Henderson #endif 27885d617bfbSRichard Henderson } 27895d617bfbSRichard Henderson 27905d617bfbSRichard Henderson TRANS(RDPR_tstate, 64, do_rd_special, supervisor(dc), a->rd, do_rdtstate) 27915d617bfbSRichard Henderson 27925d617bfbSRichard Henderson static TCGv do_rdtt(DisasContext *dc, TCGv dst) 27935d617bfbSRichard Henderson { 27945d617bfbSRichard Henderson #ifdef TARGET_SPARC64 27955d617bfbSRichard Henderson TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 27965d617bfbSRichard Henderson 27975d617bfbSRichard Henderson gen_load_trap_state_at_tl(r_tsptr); 27985d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, r_tsptr, offsetof(trap_state, tt)); 27995d617bfbSRichard Henderson return dst; 28005d617bfbSRichard Henderson #else 28015d617bfbSRichard Henderson qemu_build_not_reached(); 28025d617bfbSRichard Henderson #endif 28035d617bfbSRichard Henderson } 28045d617bfbSRichard Henderson 28055d617bfbSRichard Henderson TRANS(RDPR_tt, 64, do_rd_special, supervisor(dc), a->rd, do_rdtt) 28065d617bfbSRichard Henderson TRANS(RDPR_tick, 64, do_rd_special, supervisor(dc), a->rd, do_rdtick) 28075d617bfbSRichard Henderson 28085d617bfbSRichard Henderson static TCGv do_rdtba(DisasContext *dc, TCGv dst) 28095d617bfbSRichard Henderson { 28105d617bfbSRichard Henderson return cpu_tbr; 28115d617bfbSRichard Henderson } 28125d617bfbSRichard Henderson 2813e8325dc0SRichard Henderson TRANS(RDTBR, 32, do_rd_special, supervisor(dc), a->rd, do_rdtba) 28145d617bfbSRichard Henderson TRANS(RDPR_tba, 64, do_rd_special, supervisor(dc), a->rd, do_rdtba) 28155d617bfbSRichard Henderson 28165d617bfbSRichard Henderson static TCGv do_rdpstate(DisasContext *dc, TCGv dst) 28175d617bfbSRichard Henderson { 28185d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(pstate)); 28195d617bfbSRichard Henderson return dst; 28205d617bfbSRichard Henderson } 28215d617bfbSRichard Henderson 28225d617bfbSRichard Henderson TRANS(RDPR_pstate, 64, do_rd_special, supervisor(dc), a->rd, do_rdpstate) 28235d617bfbSRichard Henderson 28245d617bfbSRichard Henderson static TCGv do_rdtl(DisasContext *dc, TCGv dst) 28255d617bfbSRichard Henderson { 28265d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(tl)); 28275d617bfbSRichard Henderson return dst; 28285d617bfbSRichard Henderson } 28295d617bfbSRichard Henderson 28305d617bfbSRichard Henderson TRANS(RDPR_tl, 64, do_rd_special, supervisor(dc), a->rd, do_rdtl) 28315d617bfbSRichard Henderson 28325d617bfbSRichard Henderson static TCGv do_rdpil(DisasContext *dc, TCGv dst) 28335d617bfbSRichard Henderson { 28345d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env_field_offsetof(psrpil)); 28355d617bfbSRichard Henderson return dst; 28365d617bfbSRichard Henderson } 28375d617bfbSRichard Henderson 28385d617bfbSRichard Henderson TRANS(RDPR_pil, 64, do_rd_special, supervisor(dc), a->rd, do_rdpil) 28395d617bfbSRichard Henderson 28405d617bfbSRichard Henderson static TCGv do_rdcwp(DisasContext *dc, TCGv dst) 28415d617bfbSRichard Henderson { 28425d617bfbSRichard Henderson gen_helper_rdcwp(dst, tcg_env); 28435d617bfbSRichard Henderson return dst; 28445d617bfbSRichard Henderson } 28455d617bfbSRichard Henderson 28465d617bfbSRichard Henderson TRANS(RDPR_cwp, 64, do_rd_special, supervisor(dc), a->rd, do_rdcwp) 28475d617bfbSRichard Henderson 28485d617bfbSRichard Henderson static TCGv do_rdcansave(DisasContext *dc, TCGv dst) 28495d617bfbSRichard Henderson { 28505d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(cansave)); 28515d617bfbSRichard Henderson return dst; 28525d617bfbSRichard Henderson } 28535d617bfbSRichard Henderson 28545d617bfbSRichard Henderson TRANS(RDPR_cansave, 64, do_rd_special, supervisor(dc), a->rd, do_rdcansave) 28555d617bfbSRichard Henderson 28565d617bfbSRichard Henderson static TCGv do_rdcanrestore(DisasContext *dc, TCGv dst) 28575d617bfbSRichard Henderson { 28585d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(canrestore)); 28595d617bfbSRichard Henderson return dst; 28605d617bfbSRichard Henderson } 28615d617bfbSRichard Henderson 28625d617bfbSRichard Henderson TRANS(RDPR_canrestore, 64, do_rd_special, supervisor(dc), a->rd, 28635d617bfbSRichard Henderson do_rdcanrestore) 28645d617bfbSRichard Henderson 28655d617bfbSRichard Henderson static TCGv do_rdcleanwin(DisasContext *dc, TCGv dst) 28665d617bfbSRichard Henderson { 28675d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(cleanwin)); 28685d617bfbSRichard Henderson return dst; 28695d617bfbSRichard Henderson } 28705d617bfbSRichard Henderson 28715d617bfbSRichard Henderson TRANS(RDPR_cleanwin, 64, do_rd_special, supervisor(dc), a->rd, do_rdcleanwin) 28725d617bfbSRichard Henderson 28735d617bfbSRichard Henderson static TCGv do_rdotherwin(DisasContext *dc, TCGv dst) 28745d617bfbSRichard Henderson { 28755d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(otherwin)); 28765d617bfbSRichard Henderson return dst; 28775d617bfbSRichard Henderson } 28785d617bfbSRichard Henderson 28795d617bfbSRichard Henderson TRANS(RDPR_otherwin, 64, do_rd_special, supervisor(dc), a->rd, do_rdotherwin) 28805d617bfbSRichard Henderson 28815d617bfbSRichard Henderson static TCGv do_rdwstate(DisasContext *dc, TCGv dst) 28825d617bfbSRichard Henderson { 28835d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(wstate)); 28845d617bfbSRichard Henderson return dst; 28855d617bfbSRichard Henderson } 28865d617bfbSRichard Henderson 28875d617bfbSRichard Henderson TRANS(RDPR_wstate, 64, do_rd_special, supervisor(dc), a->rd, do_rdwstate) 28885d617bfbSRichard Henderson 28895d617bfbSRichard Henderson static TCGv do_rdgl(DisasContext *dc, TCGv dst) 28905d617bfbSRichard Henderson { 28915d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(gl)); 28925d617bfbSRichard Henderson return dst; 28935d617bfbSRichard Henderson } 28945d617bfbSRichard Henderson 28955d617bfbSRichard Henderson TRANS(RDPR_gl, GL, do_rd_special, supervisor(dc), a->rd, do_rdgl) 28965d617bfbSRichard Henderson 28975d617bfbSRichard Henderson /* UA2005 strand status */ 28985d617bfbSRichard Henderson static TCGv do_rdssr(DisasContext *dc, TCGv dst) 28995d617bfbSRichard Henderson { 29002da789deSRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(ssr)); 29012da789deSRichard Henderson return dst; 29025d617bfbSRichard Henderson } 29035d617bfbSRichard Henderson 29045d617bfbSRichard Henderson TRANS(RDPR_strand_status, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdssr) 29055d617bfbSRichard Henderson 29065d617bfbSRichard Henderson static TCGv do_rdver(DisasContext *dc, TCGv dst) 29075d617bfbSRichard Henderson { 29082da789deSRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(version)); 29092da789deSRichard Henderson return dst; 29105d617bfbSRichard Henderson } 29115d617bfbSRichard Henderson 29125d617bfbSRichard Henderson TRANS(RDPR_ver, 64, do_rd_special, supervisor(dc), a->rd, do_rdver) 29135d617bfbSRichard Henderson 2914e8325dc0SRichard Henderson static bool trans_FLUSHW(DisasContext *dc, arg_FLUSHW *a) 2915e8325dc0SRichard Henderson { 2916e8325dc0SRichard Henderson if (avail_64(dc)) { 2917e8325dc0SRichard Henderson gen_helper_flushw(tcg_env); 2918e8325dc0SRichard Henderson return advance_pc(dc); 2919e8325dc0SRichard Henderson } 2920e8325dc0SRichard Henderson return false; 2921e8325dc0SRichard Henderson } 2922e8325dc0SRichard Henderson 29230faef01bSRichard Henderson static bool do_wr_special(DisasContext *dc, arg_r_r_ri *a, bool priv, 29240faef01bSRichard Henderson void (*func)(DisasContext *, TCGv)) 29250faef01bSRichard Henderson { 29260faef01bSRichard Henderson TCGv src; 29270faef01bSRichard Henderson 29280faef01bSRichard Henderson /* For simplicity, we under-decoded the rs2 form. */ 29290faef01bSRichard Henderson if (!a->imm && (a->rs2_or_imm & ~0x1f)) { 29300faef01bSRichard Henderson return false; 29310faef01bSRichard Henderson } 29320faef01bSRichard Henderson if (!priv) { 29330faef01bSRichard Henderson return raise_priv(dc); 29340faef01bSRichard Henderson } 29350faef01bSRichard Henderson 29360faef01bSRichard Henderson if (a->rs1 == 0 && (a->imm || a->rs2_or_imm == 0)) { 29370faef01bSRichard Henderson src = tcg_constant_tl(a->rs2_or_imm); 29380faef01bSRichard Henderson } else { 29390faef01bSRichard Henderson TCGv src1 = gen_load_gpr(dc, a->rs1); 29400faef01bSRichard Henderson if (a->rs2_or_imm == 0) { 29410faef01bSRichard Henderson src = src1; 29420faef01bSRichard Henderson } else { 29430faef01bSRichard Henderson src = tcg_temp_new(); 29440faef01bSRichard Henderson if (a->imm) { 29450faef01bSRichard Henderson tcg_gen_xori_tl(src, src1, a->rs2_or_imm); 29460faef01bSRichard Henderson } else { 29470faef01bSRichard Henderson tcg_gen_xor_tl(src, src1, gen_load_gpr(dc, a->rs2_or_imm)); 29480faef01bSRichard Henderson } 29490faef01bSRichard Henderson } 29500faef01bSRichard Henderson } 29510faef01bSRichard Henderson func(dc, src); 29520faef01bSRichard Henderson return advance_pc(dc); 29530faef01bSRichard Henderson } 29540faef01bSRichard Henderson 29550faef01bSRichard Henderson static void do_wry(DisasContext *dc, TCGv src) 29560faef01bSRichard Henderson { 29570faef01bSRichard Henderson tcg_gen_ext32u_tl(cpu_y, src); 29580faef01bSRichard Henderson } 29590faef01bSRichard Henderson 29600faef01bSRichard Henderson TRANS(WRY, ALL, do_wr_special, a, true, do_wry) 29610faef01bSRichard Henderson 29620faef01bSRichard Henderson static void do_wrccr(DisasContext *dc, TCGv src) 29630faef01bSRichard Henderson { 29640faef01bSRichard Henderson gen_helper_wrccr(tcg_env, src); 29650faef01bSRichard Henderson } 29660faef01bSRichard Henderson 29670faef01bSRichard Henderson TRANS(WRCCR, 64, do_wr_special, a, true, do_wrccr) 29680faef01bSRichard Henderson 29690faef01bSRichard Henderson static void do_wrasi(DisasContext *dc, TCGv src) 29700faef01bSRichard Henderson { 29710faef01bSRichard Henderson TCGv tmp = tcg_temp_new(); 29720faef01bSRichard Henderson 29730faef01bSRichard Henderson tcg_gen_ext8u_tl(tmp, src); 29740faef01bSRichard Henderson tcg_gen_st32_tl(tmp, tcg_env, env64_field_offsetof(asi)); 29750faef01bSRichard Henderson /* End TB to notice changed ASI. */ 29760faef01bSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 29770faef01bSRichard Henderson } 29780faef01bSRichard Henderson 29790faef01bSRichard Henderson TRANS(WRASI, 64, do_wr_special, a, true, do_wrasi) 29800faef01bSRichard Henderson 29810faef01bSRichard Henderson static void do_wrfprs(DisasContext *dc, TCGv src) 29820faef01bSRichard Henderson { 29830faef01bSRichard Henderson #ifdef TARGET_SPARC64 29840faef01bSRichard Henderson tcg_gen_trunc_tl_i32(cpu_fprs, src); 29850faef01bSRichard Henderson dc->fprs_dirty = 0; 29860faef01bSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 29870faef01bSRichard Henderson #else 29880faef01bSRichard Henderson qemu_build_not_reached(); 29890faef01bSRichard Henderson #endif 29900faef01bSRichard Henderson } 29910faef01bSRichard Henderson 29920faef01bSRichard Henderson TRANS(WRFPRS, 64, do_wr_special, a, true, do_wrfprs) 29930faef01bSRichard Henderson 29940faef01bSRichard Henderson static void do_wrgsr(DisasContext *dc, TCGv src) 29950faef01bSRichard Henderson { 29960faef01bSRichard Henderson gen_trap_ifnofpu(dc); 29970faef01bSRichard Henderson tcg_gen_mov_tl(cpu_gsr, src); 29980faef01bSRichard Henderson } 29990faef01bSRichard Henderson 30000faef01bSRichard Henderson TRANS(WRGSR, 64, do_wr_special, a, true, do_wrgsr) 30010faef01bSRichard Henderson 30020faef01bSRichard Henderson static void do_wrsoftint_set(DisasContext *dc, TCGv src) 30030faef01bSRichard Henderson { 30040faef01bSRichard Henderson gen_helper_set_softint(tcg_env, src); 30050faef01bSRichard Henderson } 30060faef01bSRichard Henderson 30070faef01bSRichard Henderson TRANS(WRSOFTINT_SET, 64, do_wr_special, a, supervisor(dc), do_wrsoftint_set) 30080faef01bSRichard Henderson 30090faef01bSRichard Henderson static void do_wrsoftint_clr(DisasContext *dc, TCGv src) 30100faef01bSRichard Henderson { 30110faef01bSRichard Henderson gen_helper_clear_softint(tcg_env, src); 30120faef01bSRichard Henderson } 30130faef01bSRichard Henderson 30140faef01bSRichard Henderson TRANS(WRSOFTINT_CLR, 64, do_wr_special, a, supervisor(dc), do_wrsoftint_clr) 30150faef01bSRichard Henderson 30160faef01bSRichard Henderson static void do_wrsoftint(DisasContext *dc, TCGv src) 30170faef01bSRichard Henderson { 30180faef01bSRichard Henderson gen_helper_write_softint(tcg_env, src); 30190faef01bSRichard Henderson } 30200faef01bSRichard Henderson 30210faef01bSRichard Henderson TRANS(WRSOFTINT, 64, do_wr_special, a, supervisor(dc), do_wrsoftint) 30220faef01bSRichard Henderson 30230faef01bSRichard Henderson static void do_wrtick_cmpr(DisasContext *dc, TCGv src) 30240faef01bSRichard Henderson { 30250faef01bSRichard Henderson TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 30260faef01bSRichard Henderson 3027577efa45SRichard Henderson tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(tick_cmpr)); 3028577efa45SRichard Henderson tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(tick)); 30290faef01bSRichard Henderson translator_io_start(&dc->base); 3030577efa45SRichard Henderson gen_helper_tick_set_limit(r_tickptr, src); 30310faef01bSRichard Henderson /* End TB to handle timer interrupt */ 30320faef01bSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 30330faef01bSRichard Henderson } 30340faef01bSRichard Henderson 30350faef01bSRichard Henderson TRANS(WRTICK_CMPR, 64, do_wr_special, a, supervisor(dc), do_wrtick_cmpr) 30360faef01bSRichard Henderson 30370faef01bSRichard Henderson static void do_wrstick(DisasContext *dc, TCGv src) 30380faef01bSRichard Henderson { 30390faef01bSRichard Henderson #ifdef TARGET_SPARC64 30400faef01bSRichard Henderson TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 30410faef01bSRichard Henderson 30420faef01bSRichard Henderson tcg_gen_ld_ptr(r_tickptr, tcg_env, offsetof(CPUSPARCState, stick)); 30430faef01bSRichard Henderson translator_io_start(&dc->base); 30440faef01bSRichard Henderson gen_helper_tick_set_count(r_tickptr, src); 30450faef01bSRichard Henderson /* End TB to handle timer interrupt */ 30460faef01bSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 30470faef01bSRichard Henderson #else 30480faef01bSRichard Henderson qemu_build_not_reached(); 30490faef01bSRichard Henderson #endif 30500faef01bSRichard Henderson } 30510faef01bSRichard Henderson 30520faef01bSRichard Henderson TRANS(WRSTICK, 64, do_wr_special, a, supervisor(dc), do_wrstick) 30530faef01bSRichard Henderson 30540faef01bSRichard Henderson static void do_wrstick_cmpr(DisasContext *dc, TCGv src) 30550faef01bSRichard Henderson { 30560faef01bSRichard Henderson TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 30570faef01bSRichard Henderson 3058577efa45SRichard Henderson tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(stick_cmpr)); 3059577efa45SRichard Henderson tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(stick)); 30600faef01bSRichard Henderson translator_io_start(&dc->base); 3061577efa45SRichard Henderson gen_helper_tick_set_limit(r_tickptr, src); 30620faef01bSRichard Henderson /* End TB to handle timer interrupt */ 30630faef01bSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 30640faef01bSRichard Henderson } 30650faef01bSRichard Henderson 30660faef01bSRichard Henderson TRANS(WRSTICK_CMPR, 64, do_wr_special, a, supervisor(dc), do_wrstick_cmpr) 30670faef01bSRichard Henderson 30680faef01bSRichard Henderson static void do_wrpowerdown(DisasContext *dc, TCGv src) 30690faef01bSRichard Henderson { 307089527e3aSRichard Henderson finishing_insn(dc); 30710faef01bSRichard Henderson save_state(dc); 30720faef01bSRichard Henderson gen_helper_power_down(tcg_env); 30730faef01bSRichard Henderson } 30740faef01bSRichard Henderson 30750faef01bSRichard Henderson TRANS(WRPOWERDOWN, POWERDOWN, do_wr_special, a, supervisor(dc), do_wrpowerdown) 30760faef01bSRichard Henderson 307725524734SRichard Henderson static void do_wrpsr(DisasContext *dc, TCGv src) 307825524734SRichard Henderson { 307925524734SRichard Henderson gen_helper_wrpsr(tcg_env, src); 308025524734SRichard Henderson dc->base.is_jmp = DISAS_EXIT; 308125524734SRichard Henderson } 308225524734SRichard Henderson 308325524734SRichard Henderson TRANS(WRPSR, 32, do_wr_special, a, supervisor(dc), do_wrpsr) 308425524734SRichard Henderson 30859422278eSRichard Henderson static void do_wrwim(DisasContext *dc, TCGv src) 30869422278eSRichard Henderson { 30879422278eSRichard Henderson target_ulong mask = MAKE_64BIT_MASK(0, dc->def->nwindows); 3088cd6269f7SRichard Henderson TCGv tmp = tcg_temp_new(); 3089cd6269f7SRichard Henderson 3090cd6269f7SRichard Henderson tcg_gen_andi_tl(tmp, src, mask); 3091cd6269f7SRichard Henderson tcg_gen_st_tl(tmp, tcg_env, env32_field_offsetof(wim)); 30929422278eSRichard Henderson } 30939422278eSRichard Henderson 30949422278eSRichard Henderson TRANS(WRWIM, 32, do_wr_special, a, supervisor(dc), do_wrwim) 30959422278eSRichard Henderson 30969422278eSRichard Henderson static void do_wrtpc(DisasContext *dc, TCGv src) 30979422278eSRichard Henderson { 30989422278eSRichard Henderson #ifdef TARGET_SPARC64 30999422278eSRichard Henderson TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 31009422278eSRichard Henderson 31019422278eSRichard Henderson gen_load_trap_state_at_tl(r_tsptr); 31029422278eSRichard Henderson tcg_gen_st_tl(src, r_tsptr, offsetof(trap_state, tpc)); 31039422278eSRichard Henderson #else 31049422278eSRichard Henderson qemu_build_not_reached(); 31059422278eSRichard Henderson #endif 31069422278eSRichard Henderson } 31079422278eSRichard Henderson 31089422278eSRichard Henderson TRANS(WRPR_tpc, 64, do_wr_special, a, supervisor(dc), do_wrtpc) 31099422278eSRichard Henderson 31109422278eSRichard Henderson static void do_wrtnpc(DisasContext *dc, TCGv src) 31119422278eSRichard Henderson { 31129422278eSRichard Henderson #ifdef TARGET_SPARC64 31139422278eSRichard Henderson TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 31149422278eSRichard Henderson 31159422278eSRichard Henderson gen_load_trap_state_at_tl(r_tsptr); 31169422278eSRichard Henderson tcg_gen_st_tl(src, r_tsptr, offsetof(trap_state, tnpc)); 31179422278eSRichard Henderson #else 31189422278eSRichard Henderson qemu_build_not_reached(); 31199422278eSRichard Henderson #endif 31209422278eSRichard Henderson } 31219422278eSRichard Henderson 31229422278eSRichard Henderson TRANS(WRPR_tnpc, 64, do_wr_special, a, supervisor(dc), do_wrtnpc) 31239422278eSRichard Henderson 31249422278eSRichard Henderson static void do_wrtstate(DisasContext *dc, TCGv src) 31259422278eSRichard Henderson { 31269422278eSRichard Henderson #ifdef TARGET_SPARC64 31279422278eSRichard Henderson TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 31289422278eSRichard Henderson 31299422278eSRichard Henderson gen_load_trap_state_at_tl(r_tsptr); 31309422278eSRichard Henderson tcg_gen_st_tl(src, r_tsptr, offsetof(trap_state, tstate)); 31319422278eSRichard Henderson #else 31329422278eSRichard Henderson qemu_build_not_reached(); 31339422278eSRichard Henderson #endif 31349422278eSRichard Henderson } 31359422278eSRichard Henderson 31369422278eSRichard Henderson TRANS(WRPR_tstate, 64, do_wr_special, a, supervisor(dc), do_wrtstate) 31379422278eSRichard Henderson 31389422278eSRichard Henderson static void do_wrtt(DisasContext *dc, TCGv src) 31399422278eSRichard Henderson { 31409422278eSRichard Henderson #ifdef TARGET_SPARC64 31419422278eSRichard Henderson TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 31429422278eSRichard Henderson 31439422278eSRichard Henderson gen_load_trap_state_at_tl(r_tsptr); 31449422278eSRichard Henderson tcg_gen_st32_tl(src, r_tsptr, offsetof(trap_state, tt)); 31459422278eSRichard Henderson #else 31469422278eSRichard Henderson qemu_build_not_reached(); 31479422278eSRichard Henderson #endif 31489422278eSRichard Henderson } 31499422278eSRichard Henderson 31509422278eSRichard Henderson TRANS(WRPR_tt, 64, do_wr_special, a, supervisor(dc), do_wrtt) 31519422278eSRichard Henderson 31529422278eSRichard Henderson static void do_wrtick(DisasContext *dc, TCGv src) 31539422278eSRichard Henderson { 31549422278eSRichard Henderson TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 31559422278eSRichard Henderson 31569422278eSRichard Henderson tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(tick)); 31579422278eSRichard Henderson translator_io_start(&dc->base); 31589422278eSRichard Henderson gen_helper_tick_set_count(r_tickptr, src); 31599422278eSRichard Henderson /* End TB to handle timer interrupt */ 31609422278eSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 31619422278eSRichard Henderson } 31629422278eSRichard Henderson 31639422278eSRichard Henderson TRANS(WRPR_tick, 64, do_wr_special, a, supervisor(dc), do_wrtick) 31649422278eSRichard Henderson 31659422278eSRichard Henderson static void do_wrtba(DisasContext *dc, TCGv src) 31669422278eSRichard Henderson { 31679422278eSRichard Henderson tcg_gen_mov_tl(cpu_tbr, src); 31689422278eSRichard Henderson } 31699422278eSRichard Henderson 31709422278eSRichard Henderson TRANS(WRPR_tba, 64, do_wr_special, a, supervisor(dc), do_wrtba) 31719422278eSRichard Henderson 31729422278eSRichard Henderson static void do_wrpstate(DisasContext *dc, TCGv src) 31739422278eSRichard Henderson { 31749422278eSRichard Henderson save_state(dc); 31759422278eSRichard Henderson if (translator_io_start(&dc->base)) { 31769422278eSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 31779422278eSRichard Henderson } 31789422278eSRichard Henderson gen_helper_wrpstate(tcg_env, src); 31799422278eSRichard Henderson dc->npc = DYNAMIC_PC; 31809422278eSRichard Henderson } 31819422278eSRichard Henderson 31829422278eSRichard Henderson TRANS(WRPR_pstate, 64, do_wr_special, a, supervisor(dc), do_wrpstate) 31839422278eSRichard Henderson 31849422278eSRichard Henderson static void do_wrtl(DisasContext *dc, TCGv src) 31859422278eSRichard Henderson { 31869422278eSRichard Henderson save_state(dc); 31879422278eSRichard Henderson tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(tl)); 31889422278eSRichard Henderson dc->npc = DYNAMIC_PC; 31899422278eSRichard Henderson } 31909422278eSRichard Henderson 31919422278eSRichard Henderson TRANS(WRPR_tl, 64, do_wr_special, a, supervisor(dc), do_wrtl) 31929422278eSRichard Henderson 31939422278eSRichard Henderson static void do_wrpil(DisasContext *dc, TCGv src) 31949422278eSRichard Henderson { 31959422278eSRichard Henderson if (translator_io_start(&dc->base)) { 31969422278eSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 31979422278eSRichard Henderson } 31989422278eSRichard Henderson gen_helper_wrpil(tcg_env, src); 31999422278eSRichard Henderson } 32009422278eSRichard Henderson 32019422278eSRichard Henderson TRANS(WRPR_pil, 64, do_wr_special, a, supervisor(dc), do_wrpil) 32029422278eSRichard Henderson 32039422278eSRichard Henderson static void do_wrcwp(DisasContext *dc, TCGv src) 32049422278eSRichard Henderson { 32059422278eSRichard Henderson gen_helper_wrcwp(tcg_env, src); 32069422278eSRichard Henderson } 32079422278eSRichard Henderson 32089422278eSRichard Henderson TRANS(WRPR_cwp, 64, do_wr_special, a, supervisor(dc), do_wrcwp) 32099422278eSRichard Henderson 32109422278eSRichard Henderson static void do_wrcansave(DisasContext *dc, TCGv src) 32119422278eSRichard Henderson { 32129422278eSRichard Henderson tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(cansave)); 32139422278eSRichard Henderson } 32149422278eSRichard Henderson 32159422278eSRichard Henderson TRANS(WRPR_cansave, 64, do_wr_special, a, supervisor(dc), do_wrcansave) 32169422278eSRichard Henderson 32179422278eSRichard Henderson static void do_wrcanrestore(DisasContext *dc, TCGv src) 32189422278eSRichard Henderson { 32199422278eSRichard Henderson tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(canrestore)); 32209422278eSRichard Henderson } 32219422278eSRichard Henderson 32229422278eSRichard Henderson TRANS(WRPR_canrestore, 64, do_wr_special, a, supervisor(dc), do_wrcanrestore) 32239422278eSRichard Henderson 32249422278eSRichard Henderson static void do_wrcleanwin(DisasContext *dc, TCGv src) 32259422278eSRichard Henderson { 32269422278eSRichard Henderson tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(cleanwin)); 32279422278eSRichard Henderson } 32289422278eSRichard Henderson 32299422278eSRichard Henderson TRANS(WRPR_cleanwin, 64, do_wr_special, a, supervisor(dc), do_wrcleanwin) 32309422278eSRichard Henderson 32319422278eSRichard Henderson static void do_wrotherwin(DisasContext *dc, TCGv src) 32329422278eSRichard Henderson { 32339422278eSRichard Henderson tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(otherwin)); 32349422278eSRichard Henderson } 32359422278eSRichard Henderson 32369422278eSRichard Henderson TRANS(WRPR_otherwin, 64, do_wr_special, a, supervisor(dc), do_wrotherwin) 32379422278eSRichard Henderson 32389422278eSRichard Henderson static void do_wrwstate(DisasContext *dc, TCGv src) 32399422278eSRichard Henderson { 32409422278eSRichard Henderson tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(wstate)); 32419422278eSRichard Henderson } 32429422278eSRichard Henderson 32439422278eSRichard Henderson TRANS(WRPR_wstate, 64, do_wr_special, a, supervisor(dc), do_wrwstate) 32449422278eSRichard Henderson 32459422278eSRichard Henderson static void do_wrgl(DisasContext *dc, TCGv src) 32469422278eSRichard Henderson { 32479422278eSRichard Henderson gen_helper_wrgl(tcg_env, src); 32489422278eSRichard Henderson } 32499422278eSRichard Henderson 32509422278eSRichard Henderson TRANS(WRPR_gl, GL, do_wr_special, a, supervisor(dc), do_wrgl) 32519422278eSRichard Henderson 32529422278eSRichard Henderson /* UA2005 strand status */ 32539422278eSRichard Henderson static void do_wrssr(DisasContext *dc, TCGv src) 32549422278eSRichard Henderson { 32552da789deSRichard Henderson tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(ssr)); 32569422278eSRichard Henderson } 32579422278eSRichard Henderson 32589422278eSRichard Henderson TRANS(WRPR_strand_status, HYPV, do_wr_special, a, hypervisor(dc), do_wrssr) 32599422278eSRichard Henderson 3260bb97f2f5SRichard Henderson TRANS(WRTBR, 32, do_wr_special, a, supervisor(dc), do_wrtba) 3261bb97f2f5SRichard Henderson 3262bb97f2f5SRichard Henderson static void do_wrhpstate(DisasContext *dc, TCGv src) 3263bb97f2f5SRichard Henderson { 3264bb97f2f5SRichard Henderson tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(hpstate)); 3265bb97f2f5SRichard Henderson dc->base.is_jmp = DISAS_EXIT; 3266bb97f2f5SRichard Henderson } 3267bb97f2f5SRichard Henderson 3268bb97f2f5SRichard Henderson TRANS(WRHPR_hpstate, HYPV, do_wr_special, a, hypervisor(dc), do_wrhpstate) 3269bb97f2f5SRichard Henderson 3270bb97f2f5SRichard Henderson static void do_wrhtstate(DisasContext *dc, TCGv src) 3271bb97f2f5SRichard Henderson { 3272bb97f2f5SRichard Henderson TCGv_i32 tl = tcg_temp_new_i32(); 3273bb97f2f5SRichard Henderson TCGv_ptr tp = tcg_temp_new_ptr(); 3274bb97f2f5SRichard Henderson 3275bb97f2f5SRichard Henderson tcg_gen_ld_i32(tl, tcg_env, env64_field_offsetof(tl)); 3276bb97f2f5SRichard Henderson tcg_gen_andi_i32(tl, tl, MAXTL_MASK); 3277bb97f2f5SRichard Henderson tcg_gen_shli_i32(tl, tl, 3); 3278bb97f2f5SRichard Henderson tcg_gen_ext_i32_ptr(tp, tl); 3279bb97f2f5SRichard Henderson tcg_gen_add_ptr(tp, tp, tcg_env); 3280bb97f2f5SRichard Henderson 3281bb97f2f5SRichard Henderson tcg_gen_st_tl(src, tp, env64_field_offsetof(htstate)); 3282bb97f2f5SRichard Henderson } 3283bb97f2f5SRichard Henderson 3284bb97f2f5SRichard Henderson TRANS(WRHPR_htstate, HYPV, do_wr_special, a, hypervisor(dc), do_wrhtstate) 3285bb97f2f5SRichard Henderson 3286bb97f2f5SRichard Henderson static void do_wrhintp(DisasContext *dc, TCGv src) 3287bb97f2f5SRichard Henderson { 32882da789deSRichard Henderson tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(hintp)); 3289bb97f2f5SRichard Henderson } 3290bb97f2f5SRichard Henderson 3291bb97f2f5SRichard Henderson TRANS(WRHPR_hintp, HYPV, do_wr_special, a, hypervisor(dc), do_wrhintp) 3292bb97f2f5SRichard Henderson 3293bb97f2f5SRichard Henderson static void do_wrhtba(DisasContext *dc, TCGv src) 3294bb97f2f5SRichard Henderson { 32952da789deSRichard Henderson tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(htba)); 3296bb97f2f5SRichard Henderson } 3297bb97f2f5SRichard Henderson 3298bb97f2f5SRichard Henderson TRANS(WRHPR_htba, HYPV, do_wr_special, a, hypervisor(dc), do_wrhtba) 3299bb97f2f5SRichard Henderson 3300bb97f2f5SRichard Henderson static void do_wrhstick_cmpr(DisasContext *dc, TCGv src) 3301bb97f2f5SRichard Henderson { 3302bb97f2f5SRichard Henderson TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 3303bb97f2f5SRichard Henderson 3304577efa45SRichard Henderson tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(hstick_cmpr)); 3305bb97f2f5SRichard Henderson tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(hstick)); 3306bb97f2f5SRichard Henderson translator_io_start(&dc->base); 3307577efa45SRichard Henderson gen_helper_tick_set_limit(r_tickptr, src); 3308bb97f2f5SRichard Henderson /* End TB to handle timer interrupt */ 3309bb97f2f5SRichard Henderson dc->base.is_jmp = DISAS_EXIT; 3310bb97f2f5SRichard Henderson } 3311bb97f2f5SRichard Henderson 3312bb97f2f5SRichard Henderson TRANS(WRHPR_hstick_cmpr, HYPV, do_wr_special, a, hypervisor(dc), 3313bb97f2f5SRichard Henderson do_wrhstick_cmpr) 3314bb97f2f5SRichard Henderson 331525524734SRichard Henderson static bool do_saved_restored(DisasContext *dc, bool saved) 331625524734SRichard Henderson { 331725524734SRichard Henderson if (!supervisor(dc)) { 331825524734SRichard Henderson return raise_priv(dc); 331925524734SRichard Henderson } 332025524734SRichard Henderson if (saved) { 332125524734SRichard Henderson gen_helper_saved(tcg_env); 332225524734SRichard Henderson } else { 332325524734SRichard Henderson gen_helper_restored(tcg_env); 332425524734SRichard Henderson } 332525524734SRichard Henderson return advance_pc(dc); 332625524734SRichard Henderson } 332725524734SRichard Henderson 332825524734SRichard Henderson TRANS(SAVED, 64, do_saved_restored, true) 332925524734SRichard Henderson TRANS(RESTORED, 64, do_saved_restored, false) 333025524734SRichard Henderson 3331d3825800SRichard Henderson static bool trans_NOP(DisasContext *dc, arg_NOP *a) 3332d3825800SRichard Henderson { 3333d3825800SRichard Henderson return advance_pc(dc); 3334d3825800SRichard Henderson } 3335d3825800SRichard Henderson 33360faef01bSRichard Henderson /* 33370faef01bSRichard Henderson * TODO: Need a feature bit for sparcv8. 33380faef01bSRichard Henderson * In the meantime, treat all 32-bit cpus like sparcv7. 33390faef01bSRichard Henderson */ 33405458fd31SRichard Henderson TRANS(NOP_v7, 32, trans_NOP, a) 33415458fd31SRichard Henderson TRANS(NOP_v9, 64, trans_NOP, a) 33420faef01bSRichard Henderson 3343b597eedcSRichard Henderson static bool do_arith_int(DisasContext *dc, arg_r_r_ri_cc *a, 3344428881deSRichard Henderson void (*func)(TCGv, TCGv, TCGv), 33452a45b736SRichard Henderson void (*funci)(TCGv, TCGv, target_long), 33462a45b736SRichard Henderson bool logic_cc) 3347428881deSRichard Henderson { 3348428881deSRichard Henderson TCGv dst, src1; 3349428881deSRichard Henderson 3350428881deSRichard Henderson /* For simplicity, we under-decoded the rs2 form. */ 3351428881deSRichard Henderson if (!a->imm && a->rs2_or_imm & ~0x1f) { 3352428881deSRichard Henderson return false; 3353428881deSRichard Henderson } 3354428881deSRichard Henderson 33552a45b736SRichard Henderson if (logic_cc) { 33562a45b736SRichard Henderson dst = cpu_cc_N; 3357428881deSRichard Henderson } else { 3358428881deSRichard Henderson dst = gen_dest_gpr(dc, a->rd); 3359428881deSRichard Henderson } 3360428881deSRichard Henderson src1 = gen_load_gpr(dc, a->rs1); 3361428881deSRichard Henderson 3362428881deSRichard Henderson if (a->imm || a->rs2_or_imm == 0) { 3363428881deSRichard Henderson if (funci) { 3364428881deSRichard Henderson funci(dst, src1, a->rs2_or_imm); 3365428881deSRichard Henderson } else { 3366428881deSRichard Henderson func(dst, src1, tcg_constant_tl(a->rs2_or_imm)); 3367428881deSRichard Henderson } 3368428881deSRichard Henderson } else { 3369428881deSRichard Henderson func(dst, src1, cpu_regs[a->rs2_or_imm]); 3370428881deSRichard Henderson } 33712a45b736SRichard Henderson 33722a45b736SRichard Henderson if (logic_cc) { 33732a45b736SRichard Henderson if (TARGET_LONG_BITS == 64) { 33742a45b736SRichard Henderson tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N); 33752a45b736SRichard Henderson tcg_gen_movi_tl(cpu_icc_C, 0); 33762a45b736SRichard Henderson } 33772a45b736SRichard Henderson tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N); 33782a45b736SRichard Henderson tcg_gen_movi_tl(cpu_cc_C, 0); 33792a45b736SRichard Henderson tcg_gen_movi_tl(cpu_cc_V, 0); 33802a45b736SRichard Henderson } 33812a45b736SRichard Henderson 3382428881deSRichard Henderson gen_store_gpr(dc, a->rd, dst); 3383428881deSRichard Henderson return advance_pc(dc); 3384428881deSRichard Henderson } 3385428881deSRichard Henderson 3386b597eedcSRichard Henderson static bool do_arith(DisasContext *dc, arg_r_r_ri_cc *a, 3387428881deSRichard Henderson void (*func)(TCGv, TCGv, TCGv), 3388428881deSRichard Henderson void (*funci)(TCGv, TCGv, target_long), 3389428881deSRichard Henderson void (*func_cc)(TCGv, TCGv, TCGv)) 3390428881deSRichard Henderson { 3391428881deSRichard Henderson if (a->cc) { 3392b597eedcSRichard Henderson return do_arith_int(dc, a, func_cc, NULL, false); 3393428881deSRichard Henderson } 3394b597eedcSRichard Henderson return do_arith_int(dc, a, func, funci, false); 3395428881deSRichard Henderson } 3396428881deSRichard Henderson 3397428881deSRichard Henderson static bool do_logic(DisasContext *dc, arg_r_r_ri_cc *a, 3398428881deSRichard Henderson void (*func)(TCGv, TCGv, TCGv), 3399428881deSRichard Henderson void (*funci)(TCGv, TCGv, target_long)) 3400428881deSRichard Henderson { 3401b597eedcSRichard Henderson return do_arith_int(dc, a, func, funci, a->cc); 3402428881deSRichard Henderson } 3403428881deSRichard Henderson 3404b597eedcSRichard Henderson TRANS(ADD, ALL, do_arith, a, tcg_gen_add_tl, tcg_gen_addi_tl, gen_op_addcc) 3405b597eedcSRichard Henderson TRANS(SUB, ALL, do_arith, a, tcg_gen_sub_tl, tcg_gen_subi_tl, gen_op_subcc) 3406b597eedcSRichard Henderson TRANS(ADDC, ALL, do_arith, a, gen_op_addc, NULL, gen_op_addccc) 3407b597eedcSRichard Henderson TRANS(SUBC, ALL, do_arith, a, gen_op_subc, NULL, gen_op_subccc) 3408428881deSRichard Henderson 3409b597eedcSRichard Henderson TRANS(TADDcc, ALL, do_arith, a, NULL, NULL, gen_op_taddcc) 3410b597eedcSRichard Henderson TRANS(TSUBcc, ALL, do_arith, a, NULL, NULL, gen_op_tsubcc) 3411b597eedcSRichard Henderson TRANS(TADDccTV, ALL, do_arith, a, NULL, NULL, gen_op_taddcctv) 3412b597eedcSRichard Henderson TRANS(TSUBccTV, ALL, do_arith, a, NULL, NULL, gen_op_tsubcctv) 3413a9aba13dSRichard Henderson 3414428881deSRichard Henderson TRANS(AND, ALL, do_logic, a, tcg_gen_and_tl, tcg_gen_andi_tl) 3415428881deSRichard Henderson TRANS(XOR, ALL, do_logic, a, tcg_gen_xor_tl, tcg_gen_xori_tl) 3416428881deSRichard Henderson TRANS(ANDN, ALL, do_logic, a, tcg_gen_andc_tl, NULL) 3417428881deSRichard Henderson TRANS(ORN, ALL, do_logic, a, tcg_gen_orc_tl, NULL) 3418428881deSRichard Henderson TRANS(XORN, ALL, do_logic, a, tcg_gen_eqv_tl, NULL) 3419428881deSRichard Henderson 3420b597eedcSRichard Henderson TRANS(MULX, 64, do_arith, a, tcg_gen_mul_tl, tcg_gen_muli_tl, NULL) 3421b5372650SRichard Henderson TRANS(UMUL, MUL, do_logic, a, gen_op_umul, NULL) 3422b5372650SRichard Henderson TRANS(SMUL, MUL, do_logic, a, gen_op_smul, NULL) 3423b597eedcSRichard Henderson TRANS(MULScc, ALL, do_arith, a, NULL, NULL, gen_op_mulscc) 342422188d7dSRichard Henderson 34253a6b8de3SRichard Henderson TRANS(UDIVcc, DIV, do_arith, a, NULL, NULL, gen_op_udivcc) 3426b597eedcSRichard Henderson TRANS(SDIV, DIV, do_arith, a, gen_op_sdiv, NULL, gen_op_sdivcc) 34274ee85ea9SRichard Henderson 34289c6ec5bcSRichard Henderson /* TODO: Should have feature bit -- comes in with UltraSparc T2. */ 3429b597eedcSRichard Henderson TRANS(POPC, 64, do_arith, a, gen_op_popc, NULL, NULL) 34309c6ec5bcSRichard Henderson 3431428881deSRichard Henderson static bool trans_OR(DisasContext *dc, arg_r_r_ri_cc *a) 3432428881deSRichard Henderson { 3433428881deSRichard Henderson /* OR with %g0 is the canonical alias for MOV. */ 3434428881deSRichard Henderson if (!a->cc && a->rs1 == 0) { 3435428881deSRichard Henderson if (a->imm || a->rs2_or_imm == 0) { 3436428881deSRichard Henderson gen_store_gpr(dc, a->rd, tcg_constant_tl(a->rs2_or_imm)); 3437428881deSRichard Henderson } else if (a->rs2_or_imm & ~0x1f) { 3438428881deSRichard Henderson /* For simplicity, we under-decoded the rs2 form. */ 3439428881deSRichard Henderson return false; 3440428881deSRichard Henderson } else { 3441428881deSRichard Henderson gen_store_gpr(dc, a->rd, cpu_regs[a->rs2_or_imm]); 3442428881deSRichard Henderson } 3443428881deSRichard Henderson return advance_pc(dc); 3444428881deSRichard Henderson } 3445428881deSRichard Henderson return do_logic(dc, a, tcg_gen_or_tl, tcg_gen_ori_tl); 3446428881deSRichard Henderson } 3447428881deSRichard Henderson 34483a6b8de3SRichard Henderson static bool trans_UDIV(DisasContext *dc, arg_r_r_ri *a) 34493a6b8de3SRichard Henderson { 34503a6b8de3SRichard Henderson TCGv_i64 t1, t2; 34513a6b8de3SRichard Henderson TCGv dst; 34523a6b8de3SRichard Henderson 34533a6b8de3SRichard Henderson if (!avail_DIV(dc)) { 34543a6b8de3SRichard Henderson return false; 34553a6b8de3SRichard Henderson } 34563a6b8de3SRichard Henderson /* For simplicity, we under-decoded the rs2 form. */ 34573a6b8de3SRichard Henderson if (!a->imm && a->rs2_or_imm & ~0x1f) { 34583a6b8de3SRichard Henderson return false; 34593a6b8de3SRichard Henderson } 34603a6b8de3SRichard Henderson 34613a6b8de3SRichard Henderson if (unlikely(a->rs2_or_imm == 0)) { 34623a6b8de3SRichard Henderson gen_exception(dc, TT_DIV_ZERO); 34633a6b8de3SRichard Henderson return true; 34643a6b8de3SRichard Henderson } 34653a6b8de3SRichard Henderson 34663a6b8de3SRichard Henderson if (a->imm) { 34673a6b8de3SRichard Henderson t2 = tcg_constant_i64((uint32_t)a->rs2_or_imm); 34683a6b8de3SRichard Henderson } else { 34693a6b8de3SRichard Henderson TCGLabel *lab; 34703a6b8de3SRichard Henderson TCGv_i32 n2; 34713a6b8de3SRichard Henderson 34723a6b8de3SRichard Henderson finishing_insn(dc); 34733a6b8de3SRichard Henderson flush_cond(dc); 34743a6b8de3SRichard Henderson 34753a6b8de3SRichard Henderson n2 = tcg_temp_new_i32(); 34763a6b8de3SRichard Henderson tcg_gen_trunc_tl_i32(n2, cpu_regs[a->rs2_or_imm]); 34773a6b8de3SRichard Henderson 34783a6b8de3SRichard Henderson lab = delay_exception(dc, TT_DIV_ZERO); 34793a6b8de3SRichard Henderson tcg_gen_brcondi_i32(TCG_COND_EQ, n2, 0, lab); 34803a6b8de3SRichard Henderson 34813a6b8de3SRichard Henderson t2 = tcg_temp_new_i64(); 34823a6b8de3SRichard Henderson #ifdef TARGET_SPARC64 34833a6b8de3SRichard Henderson tcg_gen_ext32u_i64(t2, cpu_regs[a->rs2_or_imm]); 34843a6b8de3SRichard Henderson #else 34853a6b8de3SRichard Henderson tcg_gen_extu_i32_i64(t2, cpu_regs[a->rs2_or_imm]); 34863a6b8de3SRichard Henderson #endif 34873a6b8de3SRichard Henderson } 34883a6b8de3SRichard Henderson 34893a6b8de3SRichard Henderson t1 = tcg_temp_new_i64(); 34903a6b8de3SRichard Henderson tcg_gen_concat_tl_i64(t1, gen_load_gpr(dc, a->rs1), cpu_y); 34913a6b8de3SRichard Henderson 34923a6b8de3SRichard Henderson tcg_gen_divu_i64(t1, t1, t2); 34933a6b8de3SRichard Henderson tcg_gen_umin_i64(t1, t1, tcg_constant_i64(UINT32_MAX)); 34943a6b8de3SRichard Henderson 34953a6b8de3SRichard Henderson dst = gen_dest_gpr(dc, a->rd); 34963a6b8de3SRichard Henderson tcg_gen_trunc_i64_tl(dst, t1); 34973a6b8de3SRichard Henderson gen_store_gpr(dc, a->rd, dst); 34983a6b8de3SRichard Henderson return advance_pc(dc); 34993a6b8de3SRichard Henderson } 35003a6b8de3SRichard Henderson 3501f3141174SRichard Henderson static bool trans_UDIVX(DisasContext *dc, arg_r_r_ri *a) 3502f3141174SRichard Henderson { 3503f3141174SRichard Henderson TCGv dst, src1, src2; 3504f3141174SRichard Henderson 3505f3141174SRichard Henderson if (!avail_64(dc)) { 3506f3141174SRichard Henderson return false; 3507f3141174SRichard Henderson } 3508f3141174SRichard Henderson /* For simplicity, we under-decoded the rs2 form. */ 3509f3141174SRichard Henderson if (!a->imm && a->rs2_or_imm & ~0x1f) { 3510f3141174SRichard Henderson return false; 3511f3141174SRichard Henderson } 3512f3141174SRichard Henderson 3513f3141174SRichard Henderson if (unlikely(a->rs2_or_imm == 0)) { 3514f3141174SRichard Henderson gen_exception(dc, TT_DIV_ZERO); 3515f3141174SRichard Henderson return true; 3516f3141174SRichard Henderson } 3517f3141174SRichard Henderson 3518f3141174SRichard Henderson if (a->imm) { 3519f3141174SRichard Henderson src2 = tcg_constant_tl(a->rs2_or_imm); 3520f3141174SRichard Henderson } else { 3521f3141174SRichard Henderson TCGLabel *lab; 3522f3141174SRichard Henderson 3523f3141174SRichard Henderson finishing_insn(dc); 3524f3141174SRichard Henderson flush_cond(dc); 3525f3141174SRichard Henderson 3526f3141174SRichard Henderson lab = delay_exception(dc, TT_DIV_ZERO); 3527f3141174SRichard Henderson src2 = cpu_regs[a->rs2_or_imm]; 3528f3141174SRichard Henderson tcg_gen_brcondi_tl(TCG_COND_EQ, src2, 0, lab); 3529f3141174SRichard Henderson } 3530f3141174SRichard Henderson 3531f3141174SRichard Henderson dst = gen_dest_gpr(dc, a->rd); 3532f3141174SRichard Henderson src1 = gen_load_gpr(dc, a->rs1); 3533f3141174SRichard Henderson 3534f3141174SRichard Henderson tcg_gen_divu_tl(dst, src1, src2); 3535f3141174SRichard Henderson gen_store_gpr(dc, a->rd, dst); 3536f3141174SRichard Henderson return advance_pc(dc); 3537f3141174SRichard Henderson } 3538f3141174SRichard Henderson 3539f3141174SRichard Henderson static bool trans_SDIVX(DisasContext *dc, arg_r_r_ri *a) 3540f3141174SRichard Henderson { 3541f3141174SRichard Henderson TCGv dst, src1, src2; 3542f3141174SRichard Henderson 3543f3141174SRichard Henderson if (!avail_64(dc)) { 3544f3141174SRichard Henderson return false; 3545f3141174SRichard Henderson } 3546f3141174SRichard Henderson /* For simplicity, we under-decoded the rs2 form. */ 3547f3141174SRichard Henderson if (!a->imm && a->rs2_or_imm & ~0x1f) { 3548f3141174SRichard Henderson return false; 3549f3141174SRichard Henderson } 3550f3141174SRichard Henderson 3551f3141174SRichard Henderson if (unlikely(a->rs2_or_imm == 0)) { 3552f3141174SRichard Henderson gen_exception(dc, TT_DIV_ZERO); 3553f3141174SRichard Henderson return true; 3554f3141174SRichard Henderson } 3555f3141174SRichard Henderson 3556f3141174SRichard Henderson dst = gen_dest_gpr(dc, a->rd); 3557f3141174SRichard Henderson src1 = gen_load_gpr(dc, a->rs1); 3558f3141174SRichard Henderson 3559f3141174SRichard Henderson if (a->imm) { 3560f3141174SRichard Henderson if (unlikely(a->rs2_or_imm == -1)) { 3561f3141174SRichard Henderson tcg_gen_neg_tl(dst, src1); 3562f3141174SRichard Henderson gen_store_gpr(dc, a->rd, dst); 3563f3141174SRichard Henderson return advance_pc(dc); 3564f3141174SRichard Henderson } 3565f3141174SRichard Henderson src2 = tcg_constant_tl(a->rs2_or_imm); 3566f3141174SRichard Henderson } else { 3567f3141174SRichard Henderson TCGLabel *lab; 3568f3141174SRichard Henderson TCGv t1, t2; 3569f3141174SRichard Henderson 3570f3141174SRichard Henderson finishing_insn(dc); 3571f3141174SRichard Henderson flush_cond(dc); 3572f3141174SRichard Henderson 3573f3141174SRichard Henderson lab = delay_exception(dc, TT_DIV_ZERO); 3574f3141174SRichard Henderson src2 = cpu_regs[a->rs2_or_imm]; 3575f3141174SRichard Henderson tcg_gen_brcondi_tl(TCG_COND_EQ, src2, 0, lab); 3576f3141174SRichard Henderson 3577f3141174SRichard Henderson /* 3578f3141174SRichard Henderson * Need to avoid INT64_MIN / -1, which will trap on x86 host. 3579f3141174SRichard Henderson * Set SRC2 to 1 as a new divisor, to produce the correct result. 3580f3141174SRichard Henderson */ 3581f3141174SRichard Henderson t1 = tcg_temp_new(); 3582f3141174SRichard Henderson t2 = tcg_temp_new(); 3583f3141174SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_EQ, t1, src1, (target_long)INT64_MIN); 3584f3141174SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_EQ, t2, src2, -1); 3585f3141174SRichard Henderson tcg_gen_and_tl(t1, t1, t2); 3586f3141174SRichard Henderson tcg_gen_movcond_tl(TCG_COND_NE, t1, t1, tcg_constant_tl(0), 3587f3141174SRichard Henderson tcg_constant_tl(1), src2); 3588f3141174SRichard Henderson src2 = t1; 3589f3141174SRichard Henderson } 3590f3141174SRichard Henderson 3591f3141174SRichard Henderson tcg_gen_div_tl(dst, src1, src2); 3592f3141174SRichard Henderson gen_store_gpr(dc, a->rd, dst); 3593f3141174SRichard Henderson return advance_pc(dc); 3594f3141174SRichard Henderson } 3595f3141174SRichard Henderson 3596b88ce6f2SRichard Henderson static bool gen_edge(DisasContext *dc, arg_r_r_r *a, 359743db5838SRichard Henderson int width, bool cc, bool little_endian) 3598b88ce6f2SRichard Henderson { 359943db5838SRichard Henderson TCGv dst, s1, s2, l, r, t, m; 360043db5838SRichard Henderson uint64_t amask = address_mask_i(dc, -8); 3601b88ce6f2SRichard Henderson 3602b88ce6f2SRichard Henderson dst = gen_dest_gpr(dc, a->rd); 3603b88ce6f2SRichard Henderson s1 = gen_load_gpr(dc, a->rs1); 3604b88ce6f2SRichard Henderson s2 = gen_load_gpr(dc, a->rs2); 3605b88ce6f2SRichard Henderson 3606b88ce6f2SRichard Henderson if (cc) { 3607f828df74SRichard Henderson gen_op_subcc(cpu_cc_N, s1, s2); 3608b88ce6f2SRichard Henderson } 3609b88ce6f2SRichard Henderson 361043db5838SRichard Henderson l = tcg_temp_new(); 361143db5838SRichard Henderson r = tcg_temp_new(); 361243db5838SRichard Henderson t = tcg_temp_new(); 361343db5838SRichard Henderson 3614b88ce6f2SRichard Henderson switch (width) { 3615b88ce6f2SRichard Henderson case 8: 361643db5838SRichard Henderson tcg_gen_andi_tl(l, s1, 7); 361743db5838SRichard Henderson tcg_gen_andi_tl(r, s2, 7); 361843db5838SRichard Henderson tcg_gen_xori_tl(r, r, 7); 361943db5838SRichard Henderson m = tcg_constant_tl(0xff); 3620b88ce6f2SRichard Henderson break; 3621b88ce6f2SRichard Henderson case 16: 362243db5838SRichard Henderson tcg_gen_extract_tl(l, s1, 1, 2); 362343db5838SRichard Henderson tcg_gen_extract_tl(r, s2, 1, 2); 362443db5838SRichard Henderson tcg_gen_xori_tl(r, r, 3); 362543db5838SRichard Henderson m = tcg_constant_tl(0xf); 3626b88ce6f2SRichard Henderson break; 3627b88ce6f2SRichard Henderson case 32: 362843db5838SRichard Henderson tcg_gen_extract_tl(l, s1, 2, 1); 362943db5838SRichard Henderson tcg_gen_extract_tl(r, s2, 2, 1); 363043db5838SRichard Henderson tcg_gen_xori_tl(r, r, 1); 363143db5838SRichard Henderson m = tcg_constant_tl(0x3); 3632b88ce6f2SRichard Henderson break; 3633b88ce6f2SRichard Henderson default: 3634b88ce6f2SRichard Henderson abort(); 3635b88ce6f2SRichard Henderson } 3636b88ce6f2SRichard Henderson 363743db5838SRichard Henderson /* Compute Left Edge */ 363843db5838SRichard Henderson if (little_endian) { 363943db5838SRichard Henderson tcg_gen_shl_tl(l, m, l); 364043db5838SRichard Henderson tcg_gen_and_tl(l, l, m); 364143db5838SRichard Henderson } else { 364243db5838SRichard Henderson tcg_gen_shr_tl(l, m, l); 364343db5838SRichard Henderson } 364443db5838SRichard Henderson /* Compute Right Edge */ 364543db5838SRichard Henderson if (little_endian) { 364643db5838SRichard Henderson tcg_gen_shr_tl(r, m, r); 364743db5838SRichard Henderson } else { 364843db5838SRichard Henderson tcg_gen_shl_tl(r, m, r); 364943db5838SRichard Henderson tcg_gen_and_tl(r, r, m); 365043db5838SRichard Henderson } 3651b88ce6f2SRichard Henderson 365243db5838SRichard Henderson /* Compute dst = (s1 == s2 under amask ? l : l & r) */ 365343db5838SRichard Henderson tcg_gen_xor_tl(t, s1, s2); 365443db5838SRichard Henderson tcg_gen_and_tl(r, r, l); 365543db5838SRichard Henderson tcg_gen_movcond_tl(TCG_COND_TSTEQ, dst, t, tcg_constant_tl(amask), r, l); 3656b88ce6f2SRichard Henderson 3657b88ce6f2SRichard Henderson gen_store_gpr(dc, a->rd, dst); 3658b88ce6f2SRichard Henderson return advance_pc(dc); 3659b88ce6f2SRichard Henderson } 3660b88ce6f2SRichard Henderson 3661b88ce6f2SRichard Henderson TRANS(EDGE8cc, VIS1, gen_edge, a, 8, 1, 0) 3662b88ce6f2SRichard Henderson TRANS(EDGE8Lcc, VIS1, gen_edge, a, 8, 1, 1) 3663b88ce6f2SRichard Henderson TRANS(EDGE16cc, VIS1, gen_edge, a, 16, 1, 0) 3664b88ce6f2SRichard Henderson TRANS(EDGE16Lcc, VIS1, gen_edge, a, 16, 1, 1) 3665b88ce6f2SRichard Henderson TRANS(EDGE32cc, VIS1, gen_edge, a, 32, 1, 0) 3666b88ce6f2SRichard Henderson TRANS(EDGE32Lcc, VIS1, gen_edge, a, 32, 1, 1) 3667b88ce6f2SRichard Henderson 3668b88ce6f2SRichard Henderson TRANS(EDGE8N, VIS2, gen_edge, a, 8, 0, 0) 3669b88ce6f2SRichard Henderson TRANS(EDGE8LN, VIS2, gen_edge, a, 8, 0, 1) 3670b88ce6f2SRichard Henderson TRANS(EDGE16N, VIS2, gen_edge, a, 16, 0, 0) 3671b88ce6f2SRichard Henderson TRANS(EDGE16LN, VIS2, gen_edge, a, 16, 0, 1) 3672b88ce6f2SRichard Henderson TRANS(EDGE32N, VIS2, gen_edge, a, 32, 0, 0) 3673b88ce6f2SRichard Henderson TRANS(EDGE32LN, VIS2, gen_edge, a, 32, 0, 1) 3674b88ce6f2SRichard Henderson 367545bfed3bSRichard Henderson static bool do_rrr(DisasContext *dc, arg_r_r_r *a, 367645bfed3bSRichard Henderson void (*func)(TCGv, TCGv, TCGv)) 367745bfed3bSRichard Henderson { 367845bfed3bSRichard Henderson TCGv dst = gen_dest_gpr(dc, a->rd); 367945bfed3bSRichard Henderson TCGv src1 = gen_load_gpr(dc, a->rs1); 368045bfed3bSRichard Henderson TCGv src2 = gen_load_gpr(dc, a->rs2); 368145bfed3bSRichard Henderson 368245bfed3bSRichard Henderson func(dst, src1, src2); 368345bfed3bSRichard Henderson gen_store_gpr(dc, a->rd, dst); 368445bfed3bSRichard Henderson return advance_pc(dc); 368545bfed3bSRichard Henderson } 368645bfed3bSRichard Henderson 368745bfed3bSRichard Henderson TRANS(ARRAY8, VIS1, do_rrr, a, gen_helper_array8) 368845bfed3bSRichard Henderson TRANS(ARRAY16, VIS1, do_rrr, a, gen_op_array16) 368945bfed3bSRichard Henderson TRANS(ARRAY32, VIS1, do_rrr, a, gen_op_array32) 369045bfed3bSRichard Henderson 36919e20ca94SRichard Henderson static void gen_op_alignaddr(TCGv dst, TCGv s1, TCGv s2) 36929e20ca94SRichard Henderson { 36939e20ca94SRichard Henderson #ifdef TARGET_SPARC64 36949e20ca94SRichard Henderson TCGv tmp = tcg_temp_new(); 36959e20ca94SRichard Henderson 36969e20ca94SRichard Henderson tcg_gen_add_tl(tmp, s1, s2); 36979e20ca94SRichard Henderson tcg_gen_andi_tl(dst, tmp, -8); 36989e20ca94SRichard Henderson tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, tmp, 0, 3); 36999e20ca94SRichard Henderson #else 37009e20ca94SRichard Henderson g_assert_not_reached(); 37019e20ca94SRichard Henderson #endif 37029e20ca94SRichard Henderson } 37039e20ca94SRichard Henderson 37049e20ca94SRichard Henderson static void gen_op_alignaddrl(TCGv dst, TCGv s1, TCGv s2) 37059e20ca94SRichard Henderson { 37069e20ca94SRichard Henderson #ifdef TARGET_SPARC64 37079e20ca94SRichard Henderson TCGv tmp = tcg_temp_new(); 37089e20ca94SRichard Henderson 37099e20ca94SRichard Henderson tcg_gen_add_tl(tmp, s1, s2); 37109e20ca94SRichard Henderson tcg_gen_andi_tl(dst, tmp, -8); 37119e20ca94SRichard Henderson tcg_gen_neg_tl(tmp, tmp); 37129e20ca94SRichard Henderson tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, tmp, 0, 3); 37139e20ca94SRichard Henderson #else 37149e20ca94SRichard Henderson g_assert_not_reached(); 37159e20ca94SRichard Henderson #endif 37169e20ca94SRichard Henderson } 37179e20ca94SRichard Henderson 37189e20ca94SRichard Henderson TRANS(ALIGNADDR, VIS1, do_rrr, a, gen_op_alignaddr) 37199e20ca94SRichard Henderson TRANS(ALIGNADDRL, VIS1, do_rrr, a, gen_op_alignaddrl) 37209e20ca94SRichard Henderson 372139ca3490SRichard Henderson static void gen_op_bmask(TCGv dst, TCGv s1, TCGv s2) 372239ca3490SRichard Henderson { 372339ca3490SRichard Henderson #ifdef TARGET_SPARC64 372439ca3490SRichard Henderson tcg_gen_add_tl(dst, s1, s2); 372539ca3490SRichard Henderson tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, dst, 32, 32); 372639ca3490SRichard Henderson #else 372739ca3490SRichard Henderson g_assert_not_reached(); 372839ca3490SRichard Henderson #endif 372939ca3490SRichard Henderson } 373039ca3490SRichard Henderson 373139ca3490SRichard Henderson TRANS(BMASK, VIS2, do_rrr, a, gen_op_bmask) 373239ca3490SRichard Henderson 37335fc546eeSRichard Henderson static bool do_shift_r(DisasContext *dc, arg_shiftr *a, bool l, bool u) 37345fc546eeSRichard Henderson { 37355fc546eeSRichard Henderson TCGv dst, src1, src2; 37365fc546eeSRichard Henderson 37375fc546eeSRichard Henderson /* Reject 64-bit shifts for sparc32. */ 37385fc546eeSRichard Henderson if (avail_32(dc) && a->x) { 37395fc546eeSRichard Henderson return false; 37405fc546eeSRichard Henderson } 37415fc546eeSRichard Henderson 37425fc546eeSRichard Henderson src2 = tcg_temp_new(); 37435fc546eeSRichard Henderson tcg_gen_andi_tl(src2, gen_load_gpr(dc, a->rs2), a->x ? 63 : 31); 37445fc546eeSRichard Henderson src1 = gen_load_gpr(dc, a->rs1); 37455fc546eeSRichard Henderson dst = gen_dest_gpr(dc, a->rd); 37465fc546eeSRichard Henderson 37475fc546eeSRichard Henderson if (l) { 37485fc546eeSRichard Henderson tcg_gen_shl_tl(dst, src1, src2); 37495fc546eeSRichard Henderson if (!a->x) { 37505fc546eeSRichard Henderson tcg_gen_ext32u_tl(dst, dst); 37515fc546eeSRichard Henderson } 37525fc546eeSRichard Henderson } else if (u) { 37535fc546eeSRichard Henderson if (!a->x) { 37545fc546eeSRichard Henderson tcg_gen_ext32u_tl(dst, src1); 37555fc546eeSRichard Henderson src1 = dst; 37565fc546eeSRichard Henderson } 37575fc546eeSRichard Henderson tcg_gen_shr_tl(dst, src1, src2); 37585fc546eeSRichard Henderson } else { 37595fc546eeSRichard Henderson if (!a->x) { 37605fc546eeSRichard Henderson tcg_gen_ext32s_tl(dst, src1); 37615fc546eeSRichard Henderson src1 = dst; 37625fc546eeSRichard Henderson } 37635fc546eeSRichard Henderson tcg_gen_sar_tl(dst, src1, src2); 37645fc546eeSRichard Henderson } 37655fc546eeSRichard Henderson gen_store_gpr(dc, a->rd, dst); 37665fc546eeSRichard Henderson return advance_pc(dc); 37675fc546eeSRichard Henderson } 37685fc546eeSRichard Henderson 37695fc546eeSRichard Henderson TRANS(SLL_r, ALL, do_shift_r, a, true, true) 37705fc546eeSRichard Henderson TRANS(SRL_r, ALL, do_shift_r, a, false, true) 37715fc546eeSRichard Henderson TRANS(SRA_r, ALL, do_shift_r, a, false, false) 37725fc546eeSRichard Henderson 37735fc546eeSRichard Henderson static bool do_shift_i(DisasContext *dc, arg_shifti *a, bool l, bool u) 37745fc546eeSRichard Henderson { 37755fc546eeSRichard Henderson TCGv dst, src1; 37765fc546eeSRichard Henderson 37775fc546eeSRichard Henderson /* Reject 64-bit shifts for sparc32. */ 37785fc546eeSRichard Henderson if (avail_32(dc) && (a->x || a->i >= 32)) { 37795fc546eeSRichard Henderson return false; 37805fc546eeSRichard Henderson } 37815fc546eeSRichard Henderson 37825fc546eeSRichard Henderson src1 = gen_load_gpr(dc, a->rs1); 37835fc546eeSRichard Henderson dst = gen_dest_gpr(dc, a->rd); 37845fc546eeSRichard Henderson 37855fc546eeSRichard Henderson if (avail_32(dc) || a->x) { 37865fc546eeSRichard Henderson if (l) { 37875fc546eeSRichard Henderson tcg_gen_shli_tl(dst, src1, a->i); 37885fc546eeSRichard Henderson } else if (u) { 37895fc546eeSRichard Henderson tcg_gen_shri_tl(dst, src1, a->i); 37905fc546eeSRichard Henderson } else { 37915fc546eeSRichard Henderson tcg_gen_sari_tl(dst, src1, a->i); 37925fc546eeSRichard Henderson } 37935fc546eeSRichard Henderson } else { 37945fc546eeSRichard Henderson if (l) { 37955fc546eeSRichard Henderson tcg_gen_deposit_z_tl(dst, src1, a->i, 32 - a->i); 37965fc546eeSRichard Henderson } else if (u) { 37975fc546eeSRichard Henderson tcg_gen_extract_tl(dst, src1, a->i, 32 - a->i); 37985fc546eeSRichard Henderson } else { 37995fc546eeSRichard Henderson tcg_gen_sextract_tl(dst, src1, a->i, 32 - a->i); 38005fc546eeSRichard Henderson } 38015fc546eeSRichard Henderson } 38025fc546eeSRichard Henderson gen_store_gpr(dc, a->rd, dst); 38035fc546eeSRichard Henderson return advance_pc(dc); 38045fc546eeSRichard Henderson } 38055fc546eeSRichard Henderson 38065fc546eeSRichard Henderson TRANS(SLL_i, ALL, do_shift_i, a, true, true) 38075fc546eeSRichard Henderson TRANS(SRL_i, ALL, do_shift_i, a, false, true) 38085fc546eeSRichard Henderson TRANS(SRA_i, ALL, do_shift_i, a, false, false) 38095fc546eeSRichard Henderson 3810fb4ed7aaSRichard Henderson static TCGv gen_rs2_or_imm(DisasContext *dc, bool imm, int rs2_or_imm) 3811fb4ed7aaSRichard Henderson { 3812fb4ed7aaSRichard Henderson /* For simplicity, we under-decoded the rs2 form. */ 3813fb4ed7aaSRichard Henderson if (!imm && rs2_or_imm & ~0x1f) { 3814fb4ed7aaSRichard Henderson return NULL; 3815fb4ed7aaSRichard Henderson } 3816fb4ed7aaSRichard Henderson if (imm || rs2_or_imm == 0) { 3817fb4ed7aaSRichard Henderson return tcg_constant_tl(rs2_or_imm); 3818fb4ed7aaSRichard Henderson } else { 3819fb4ed7aaSRichard Henderson return cpu_regs[rs2_or_imm]; 3820fb4ed7aaSRichard Henderson } 3821fb4ed7aaSRichard Henderson } 3822fb4ed7aaSRichard Henderson 3823fb4ed7aaSRichard Henderson static bool do_mov_cond(DisasContext *dc, DisasCompare *cmp, int rd, TCGv src2) 3824fb4ed7aaSRichard Henderson { 3825fb4ed7aaSRichard Henderson TCGv dst = gen_load_gpr(dc, rd); 3826c8507ebfSRichard Henderson TCGv c2 = tcg_constant_tl(cmp->c2); 3827fb4ed7aaSRichard Henderson 3828c8507ebfSRichard Henderson tcg_gen_movcond_tl(cmp->cond, dst, cmp->c1, c2, src2, dst); 3829fb4ed7aaSRichard Henderson gen_store_gpr(dc, rd, dst); 3830fb4ed7aaSRichard Henderson return advance_pc(dc); 3831fb4ed7aaSRichard Henderson } 3832fb4ed7aaSRichard Henderson 3833fb4ed7aaSRichard Henderson static bool trans_MOVcc(DisasContext *dc, arg_MOVcc *a) 3834fb4ed7aaSRichard Henderson { 3835fb4ed7aaSRichard Henderson TCGv src2 = gen_rs2_or_imm(dc, a->imm, a->rs2_or_imm); 3836fb4ed7aaSRichard Henderson DisasCompare cmp; 3837fb4ed7aaSRichard Henderson 3838fb4ed7aaSRichard Henderson if (src2 == NULL) { 3839fb4ed7aaSRichard Henderson return false; 3840fb4ed7aaSRichard Henderson } 3841fb4ed7aaSRichard Henderson gen_compare(&cmp, a->cc, a->cond, dc); 3842fb4ed7aaSRichard Henderson return do_mov_cond(dc, &cmp, a->rd, src2); 3843fb4ed7aaSRichard Henderson } 3844fb4ed7aaSRichard Henderson 3845fb4ed7aaSRichard Henderson static bool trans_MOVfcc(DisasContext *dc, arg_MOVfcc *a) 3846fb4ed7aaSRichard Henderson { 3847fb4ed7aaSRichard Henderson TCGv src2 = gen_rs2_or_imm(dc, a->imm, a->rs2_or_imm); 3848fb4ed7aaSRichard Henderson DisasCompare cmp; 3849fb4ed7aaSRichard Henderson 3850fb4ed7aaSRichard Henderson if (src2 == NULL) { 3851fb4ed7aaSRichard Henderson return false; 3852fb4ed7aaSRichard Henderson } 3853fb4ed7aaSRichard Henderson gen_fcompare(&cmp, a->cc, a->cond); 3854fb4ed7aaSRichard Henderson return do_mov_cond(dc, &cmp, a->rd, src2); 3855fb4ed7aaSRichard Henderson } 3856fb4ed7aaSRichard Henderson 3857fb4ed7aaSRichard Henderson static bool trans_MOVR(DisasContext *dc, arg_MOVR *a) 3858fb4ed7aaSRichard Henderson { 3859fb4ed7aaSRichard Henderson TCGv src2 = gen_rs2_or_imm(dc, a->imm, a->rs2_or_imm); 3860fb4ed7aaSRichard Henderson DisasCompare cmp; 3861fb4ed7aaSRichard Henderson 3862fb4ed7aaSRichard Henderson if (src2 == NULL) { 3863fb4ed7aaSRichard Henderson return false; 3864fb4ed7aaSRichard Henderson } 38652c4f56c9SRichard Henderson if (!gen_compare_reg(&cmp, a->cond, gen_load_gpr(dc, a->rs1))) { 38662c4f56c9SRichard Henderson return false; 38672c4f56c9SRichard Henderson } 3868fb4ed7aaSRichard Henderson return do_mov_cond(dc, &cmp, a->rd, src2); 3869fb4ed7aaSRichard Henderson } 3870fb4ed7aaSRichard Henderson 387186b82fe0SRichard Henderson static bool do_add_special(DisasContext *dc, arg_r_r_ri *a, 387286b82fe0SRichard Henderson bool (*func)(DisasContext *dc, int rd, TCGv src)) 387386b82fe0SRichard Henderson { 387486b82fe0SRichard Henderson TCGv src1, sum; 387586b82fe0SRichard Henderson 387686b82fe0SRichard Henderson /* For simplicity, we under-decoded the rs2 form. */ 387786b82fe0SRichard Henderson if (!a->imm && a->rs2_or_imm & ~0x1f) { 387886b82fe0SRichard Henderson return false; 387986b82fe0SRichard Henderson } 388086b82fe0SRichard Henderson 388186b82fe0SRichard Henderson /* 388286b82fe0SRichard Henderson * Always load the sum into a new temporary. 388386b82fe0SRichard Henderson * This is required to capture the value across a window change, 388486b82fe0SRichard Henderson * e.g. SAVE and RESTORE, and may be optimized away otherwise. 388586b82fe0SRichard Henderson */ 388686b82fe0SRichard Henderson sum = tcg_temp_new(); 388786b82fe0SRichard Henderson src1 = gen_load_gpr(dc, a->rs1); 388886b82fe0SRichard Henderson if (a->imm || a->rs2_or_imm == 0) { 388986b82fe0SRichard Henderson tcg_gen_addi_tl(sum, src1, a->rs2_or_imm); 389086b82fe0SRichard Henderson } else { 389186b82fe0SRichard Henderson tcg_gen_add_tl(sum, src1, cpu_regs[a->rs2_or_imm]); 389286b82fe0SRichard Henderson } 389386b82fe0SRichard Henderson return func(dc, a->rd, sum); 389486b82fe0SRichard Henderson } 389586b82fe0SRichard Henderson 389686b82fe0SRichard Henderson static bool do_jmpl(DisasContext *dc, int rd, TCGv src) 389786b82fe0SRichard Henderson { 389886b82fe0SRichard Henderson /* 389986b82fe0SRichard Henderson * Preserve pc across advance, so that we can delay 390086b82fe0SRichard Henderson * the writeback to rd until after src is consumed. 390186b82fe0SRichard Henderson */ 390286b82fe0SRichard Henderson target_ulong cur_pc = dc->pc; 390386b82fe0SRichard Henderson 390486b82fe0SRichard Henderson gen_check_align(dc, src, 3); 390586b82fe0SRichard Henderson 390686b82fe0SRichard Henderson gen_mov_pc_npc(dc); 390786b82fe0SRichard Henderson tcg_gen_mov_tl(cpu_npc, src); 390886b82fe0SRichard Henderson gen_address_mask(dc, cpu_npc); 390986b82fe0SRichard Henderson gen_store_gpr(dc, rd, tcg_constant_tl(cur_pc)); 391086b82fe0SRichard Henderson 391186b82fe0SRichard Henderson dc->npc = DYNAMIC_PC_LOOKUP; 391286b82fe0SRichard Henderson return true; 391386b82fe0SRichard Henderson } 391486b82fe0SRichard Henderson 391586b82fe0SRichard Henderson TRANS(JMPL, ALL, do_add_special, a, do_jmpl) 391686b82fe0SRichard Henderson 391786b82fe0SRichard Henderson static bool do_rett(DisasContext *dc, int rd, TCGv src) 391886b82fe0SRichard Henderson { 391986b82fe0SRichard Henderson if (!supervisor(dc)) { 392086b82fe0SRichard Henderson return raise_priv(dc); 392186b82fe0SRichard Henderson } 392286b82fe0SRichard Henderson 392386b82fe0SRichard Henderson gen_check_align(dc, src, 3); 392486b82fe0SRichard Henderson 392586b82fe0SRichard Henderson gen_mov_pc_npc(dc); 392686b82fe0SRichard Henderson tcg_gen_mov_tl(cpu_npc, src); 392786b82fe0SRichard Henderson gen_helper_rett(tcg_env); 392886b82fe0SRichard Henderson 392986b82fe0SRichard Henderson dc->npc = DYNAMIC_PC; 393086b82fe0SRichard Henderson return true; 393186b82fe0SRichard Henderson } 393286b82fe0SRichard Henderson 393386b82fe0SRichard Henderson TRANS(RETT, 32, do_add_special, a, do_rett) 393486b82fe0SRichard Henderson 393586b82fe0SRichard Henderson static bool do_return(DisasContext *dc, int rd, TCGv src) 393686b82fe0SRichard Henderson { 393786b82fe0SRichard Henderson gen_check_align(dc, src, 3); 39380dfae4f9SRichard Henderson gen_helper_restore(tcg_env); 393986b82fe0SRichard Henderson 394086b82fe0SRichard Henderson gen_mov_pc_npc(dc); 394186b82fe0SRichard Henderson tcg_gen_mov_tl(cpu_npc, src); 394286b82fe0SRichard Henderson gen_address_mask(dc, cpu_npc); 394386b82fe0SRichard Henderson 394486b82fe0SRichard Henderson dc->npc = DYNAMIC_PC_LOOKUP; 394586b82fe0SRichard Henderson return true; 394686b82fe0SRichard Henderson } 394786b82fe0SRichard Henderson 394886b82fe0SRichard Henderson TRANS(RETURN, 64, do_add_special, a, do_return) 394986b82fe0SRichard Henderson 3950d3825800SRichard Henderson static bool do_save(DisasContext *dc, int rd, TCGv src) 3951d3825800SRichard Henderson { 3952d3825800SRichard Henderson gen_helper_save(tcg_env); 3953d3825800SRichard Henderson gen_store_gpr(dc, rd, src); 3954d3825800SRichard Henderson return advance_pc(dc); 3955d3825800SRichard Henderson } 3956d3825800SRichard Henderson 3957d3825800SRichard Henderson TRANS(SAVE, ALL, do_add_special, a, do_save) 3958d3825800SRichard Henderson 3959d3825800SRichard Henderson static bool do_restore(DisasContext *dc, int rd, TCGv src) 3960d3825800SRichard Henderson { 3961d3825800SRichard Henderson gen_helper_restore(tcg_env); 3962d3825800SRichard Henderson gen_store_gpr(dc, rd, src); 3963d3825800SRichard Henderson return advance_pc(dc); 3964d3825800SRichard Henderson } 3965d3825800SRichard Henderson 3966d3825800SRichard Henderson TRANS(RESTORE, ALL, do_add_special, a, do_restore) 3967d3825800SRichard Henderson 39688f75b8a4SRichard Henderson static bool do_done_retry(DisasContext *dc, bool done) 39698f75b8a4SRichard Henderson { 39708f75b8a4SRichard Henderson if (!supervisor(dc)) { 39718f75b8a4SRichard Henderson return raise_priv(dc); 39728f75b8a4SRichard Henderson } 39738f75b8a4SRichard Henderson dc->npc = DYNAMIC_PC; 39748f75b8a4SRichard Henderson dc->pc = DYNAMIC_PC; 39758f75b8a4SRichard Henderson translator_io_start(&dc->base); 39768f75b8a4SRichard Henderson if (done) { 39778f75b8a4SRichard Henderson gen_helper_done(tcg_env); 39788f75b8a4SRichard Henderson } else { 39798f75b8a4SRichard Henderson gen_helper_retry(tcg_env); 39808f75b8a4SRichard Henderson } 39818f75b8a4SRichard Henderson return true; 39828f75b8a4SRichard Henderson } 39838f75b8a4SRichard Henderson 39848f75b8a4SRichard Henderson TRANS(DONE, 64, do_done_retry, true) 39858f75b8a4SRichard Henderson TRANS(RETRY, 64, do_done_retry, false) 39868f75b8a4SRichard Henderson 39870880d20bSRichard Henderson /* 39880880d20bSRichard Henderson * Major opcode 11 -- load and store instructions 39890880d20bSRichard Henderson */ 39900880d20bSRichard Henderson 39910880d20bSRichard Henderson static TCGv gen_ldst_addr(DisasContext *dc, int rs1, bool imm, int rs2_or_imm) 39920880d20bSRichard Henderson { 39930880d20bSRichard Henderson TCGv addr, tmp = NULL; 39940880d20bSRichard Henderson 39950880d20bSRichard Henderson /* For simplicity, we under-decoded the rs2 form. */ 39960880d20bSRichard Henderson if (!imm && rs2_or_imm & ~0x1f) { 39970880d20bSRichard Henderson return NULL; 39980880d20bSRichard Henderson } 39990880d20bSRichard Henderson 40000880d20bSRichard Henderson addr = gen_load_gpr(dc, rs1); 40010880d20bSRichard Henderson if (rs2_or_imm) { 40020880d20bSRichard Henderson tmp = tcg_temp_new(); 40030880d20bSRichard Henderson if (imm) { 40040880d20bSRichard Henderson tcg_gen_addi_tl(tmp, addr, rs2_or_imm); 40050880d20bSRichard Henderson } else { 40060880d20bSRichard Henderson tcg_gen_add_tl(tmp, addr, cpu_regs[rs2_or_imm]); 40070880d20bSRichard Henderson } 40080880d20bSRichard Henderson addr = tmp; 40090880d20bSRichard Henderson } 40100880d20bSRichard Henderson if (AM_CHECK(dc)) { 40110880d20bSRichard Henderson if (!tmp) { 40120880d20bSRichard Henderson tmp = tcg_temp_new(); 40130880d20bSRichard Henderson } 40140880d20bSRichard Henderson tcg_gen_ext32u_tl(tmp, addr); 40150880d20bSRichard Henderson addr = tmp; 40160880d20bSRichard Henderson } 40170880d20bSRichard Henderson return addr; 40180880d20bSRichard Henderson } 40190880d20bSRichard Henderson 40200880d20bSRichard Henderson static bool do_ld_gpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp mop) 40210880d20bSRichard Henderson { 40220880d20bSRichard Henderson TCGv reg, addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 40230880d20bSRichard Henderson DisasASI da; 40240880d20bSRichard Henderson 40250880d20bSRichard Henderson if (addr == NULL) { 40260880d20bSRichard Henderson return false; 40270880d20bSRichard Henderson } 40280880d20bSRichard Henderson da = resolve_asi(dc, a->asi, mop); 40290880d20bSRichard Henderson 40300880d20bSRichard Henderson reg = gen_dest_gpr(dc, a->rd); 403142071fc1SRichard Henderson gen_ld_asi(dc, &da, reg, addr); 40320880d20bSRichard Henderson gen_store_gpr(dc, a->rd, reg); 40330880d20bSRichard Henderson return advance_pc(dc); 40340880d20bSRichard Henderson } 40350880d20bSRichard Henderson 40360880d20bSRichard Henderson TRANS(LDUW, ALL, do_ld_gpr, a, MO_TEUL) 40370880d20bSRichard Henderson TRANS(LDUB, ALL, do_ld_gpr, a, MO_UB) 40380880d20bSRichard Henderson TRANS(LDUH, ALL, do_ld_gpr, a, MO_TEUW) 40390880d20bSRichard Henderson TRANS(LDSB, ALL, do_ld_gpr, a, MO_SB) 40400880d20bSRichard Henderson TRANS(LDSH, ALL, do_ld_gpr, a, MO_TESW) 40410880d20bSRichard Henderson TRANS(LDSW, 64, do_ld_gpr, a, MO_TESL) 40420880d20bSRichard Henderson TRANS(LDX, 64, do_ld_gpr, a, MO_TEUQ) 40430880d20bSRichard Henderson 40440880d20bSRichard Henderson static bool do_st_gpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp mop) 40450880d20bSRichard Henderson { 40460880d20bSRichard Henderson TCGv reg, addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 40470880d20bSRichard Henderson DisasASI da; 40480880d20bSRichard Henderson 40490880d20bSRichard Henderson if (addr == NULL) { 40500880d20bSRichard Henderson return false; 40510880d20bSRichard Henderson } 40520880d20bSRichard Henderson da = resolve_asi(dc, a->asi, mop); 40530880d20bSRichard Henderson 40540880d20bSRichard Henderson reg = gen_load_gpr(dc, a->rd); 405542071fc1SRichard Henderson gen_st_asi(dc, &da, reg, addr); 40560880d20bSRichard Henderson return advance_pc(dc); 40570880d20bSRichard Henderson } 40580880d20bSRichard Henderson 40590880d20bSRichard Henderson TRANS(STW, ALL, do_st_gpr, a, MO_TEUL) 40600880d20bSRichard Henderson TRANS(STB, ALL, do_st_gpr, a, MO_UB) 40610880d20bSRichard Henderson TRANS(STH, ALL, do_st_gpr, a, MO_TEUW) 40620880d20bSRichard Henderson TRANS(STX, 64, do_st_gpr, a, MO_TEUQ) 40630880d20bSRichard Henderson 40640880d20bSRichard Henderson static bool trans_LDD(DisasContext *dc, arg_r_r_ri_asi *a) 40650880d20bSRichard Henderson { 40660880d20bSRichard Henderson TCGv addr; 40670880d20bSRichard Henderson DisasASI da; 40680880d20bSRichard Henderson 40690880d20bSRichard Henderson if (a->rd & 1) { 40700880d20bSRichard Henderson return false; 40710880d20bSRichard Henderson } 40720880d20bSRichard Henderson addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 40730880d20bSRichard Henderson if (addr == NULL) { 40740880d20bSRichard Henderson return false; 40750880d20bSRichard Henderson } 40760880d20bSRichard Henderson da = resolve_asi(dc, a->asi, MO_TEUQ); 407742071fc1SRichard Henderson gen_ldda_asi(dc, &da, addr, a->rd); 40780880d20bSRichard Henderson return advance_pc(dc); 40790880d20bSRichard Henderson } 40800880d20bSRichard Henderson 40810880d20bSRichard Henderson static bool trans_STD(DisasContext *dc, arg_r_r_ri_asi *a) 40820880d20bSRichard Henderson { 40830880d20bSRichard Henderson TCGv addr; 40840880d20bSRichard Henderson DisasASI da; 40850880d20bSRichard Henderson 40860880d20bSRichard Henderson if (a->rd & 1) { 40870880d20bSRichard Henderson return false; 40880880d20bSRichard Henderson } 40890880d20bSRichard Henderson addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 40900880d20bSRichard Henderson if (addr == NULL) { 40910880d20bSRichard Henderson return false; 40920880d20bSRichard Henderson } 40930880d20bSRichard Henderson da = resolve_asi(dc, a->asi, MO_TEUQ); 409442071fc1SRichard Henderson gen_stda_asi(dc, &da, addr, a->rd); 40950880d20bSRichard Henderson return advance_pc(dc); 40960880d20bSRichard Henderson } 40970880d20bSRichard Henderson 4098cf07cd1eSRichard Henderson static bool trans_LDSTUB(DisasContext *dc, arg_r_r_ri_asi *a) 4099cf07cd1eSRichard Henderson { 4100cf07cd1eSRichard Henderson TCGv addr, reg; 4101cf07cd1eSRichard Henderson DisasASI da; 4102cf07cd1eSRichard Henderson 4103cf07cd1eSRichard Henderson addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 4104cf07cd1eSRichard Henderson if (addr == NULL) { 4105cf07cd1eSRichard Henderson return false; 4106cf07cd1eSRichard Henderson } 4107cf07cd1eSRichard Henderson da = resolve_asi(dc, a->asi, MO_UB); 4108cf07cd1eSRichard Henderson 4109cf07cd1eSRichard Henderson reg = gen_dest_gpr(dc, a->rd); 4110cf07cd1eSRichard Henderson gen_ldstub_asi(dc, &da, reg, addr); 4111cf07cd1eSRichard Henderson gen_store_gpr(dc, a->rd, reg); 4112cf07cd1eSRichard Henderson return advance_pc(dc); 4113cf07cd1eSRichard Henderson } 4114cf07cd1eSRichard Henderson 4115dca544b9SRichard Henderson static bool trans_SWAP(DisasContext *dc, arg_r_r_ri_asi *a) 4116dca544b9SRichard Henderson { 4117dca544b9SRichard Henderson TCGv addr, dst, src; 4118dca544b9SRichard Henderson DisasASI da; 4119dca544b9SRichard Henderson 4120dca544b9SRichard Henderson addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 4121dca544b9SRichard Henderson if (addr == NULL) { 4122dca544b9SRichard Henderson return false; 4123dca544b9SRichard Henderson } 4124dca544b9SRichard Henderson da = resolve_asi(dc, a->asi, MO_TEUL); 4125dca544b9SRichard Henderson 4126dca544b9SRichard Henderson dst = gen_dest_gpr(dc, a->rd); 4127dca544b9SRichard Henderson src = gen_load_gpr(dc, a->rd); 4128dca544b9SRichard Henderson gen_swap_asi(dc, &da, dst, src, addr); 4129dca544b9SRichard Henderson gen_store_gpr(dc, a->rd, dst); 4130dca544b9SRichard Henderson return advance_pc(dc); 4131dca544b9SRichard Henderson } 4132dca544b9SRichard Henderson 4133d0a11d25SRichard Henderson static bool do_casa(DisasContext *dc, arg_r_r_ri_asi *a, MemOp mop) 4134d0a11d25SRichard Henderson { 4135d0a11d25SRichard Henderson TCGv addr, o, n, c; 4136d0a11d25SRichard Henderson DisasASI da; 4137d0a11d25SRichard Henderson 4138d0a11d25SRichard Henderson addr = gen_ldst_addr(dc, a->rs1, true, 0); 4139d0a11d25SRichard Henderson if (addr == NULL) { 4140d0a11d25SRichard Henderson return false; 4141d0a11d25SRichard Henderson } 4142d0a11d25SRichard Henderson da = resolve_asi(dc, a->asi, mop); 4143d0a11d25SRichard Henderson 4144d0a11d25SRichard Henderson o = gen_dest_gpr(dc, a->rd); 4145d0a11d25SRichard Henderson n = gen_load_gpr(dc, a->rd); 4146d0a11d25SRichard Henderson c = gen_load_gpr(dc, a->rs2_or_imm); 4147d0a11d25SRichard Henderson gen_cas_asi(dc, &da, o, n, c, addr); 4148d0a11d25SRichard Henderson gen_store_gpr(dc, a->rd, o); 4149d0a11d25SRichard Henderson return advance_pc(dc); 4150d0a11d25SRichard Henderson } 4151d0a11d25SRichard Henderson 4152d0a11d25SRichard Henderson TRANS(CASA, CASA, do_casa, a, MO_TEUL) 4153d0a11d25SRichard Henderson TRANS(CASXA, 64, do_casa, a, MO_TEUQ) 4154d0a11d25SRichard Henderson 415506c060d9SRichard Henderson static bool do_ld_fpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp sz) 415606c060d9SRichard Henderson { 415706c060d9SRichard Henderson TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 415806c060d9SRichard Henderson DisasASI da; 415906c060d9SRichard Henderson 416006c060d9SRichard Henderson if (addr == NULL) { 416106c060d9SRichard Henderson return false; 416206c060d9SRichard Henderson } 416306c060d9SRichard Henderson if (gen_trap_ifnofpu(dc)) { 416406c060d9SRichard Henderson return true; 416506c060d9SRichard Henderson } 416606c060d9SRichard Henderson if (sz == MO_128 && gen_trap_float128(dc)) { 416706c060d9SRichard Henderson return true; 416806c060d9SRichard Henderson } 416906c060d9SRichard Henderson da = resolve_asi(dc, a->asi, MO_TE | sz); 4170287b1152SRichard Henderson gen_ldf_asi(dc, &da, sz, addr, a->rd); 417106c060d9SRichard Henderson gen_update_fprs_dirty(dc, a->rd); 417206c060d9SRichard Henderson return advance_pc(dc); 417306c060d9SRichard Henderson } 417406c060d9SRichard Henderson 417506c060d9SRichard Henderson TRANS(LDF, ALL, do_ld_fpr, a, MO_32) 417606c060d9SRichard Henderson TRANS(LDDF, ALL, do_ld_fpr, a, MO_64) 417706c060d9SRichard Henderson TRANS(LDQF, ALL, do_ld_fpr, a, MO_128) 417806c060d9SRichard Henderson 4179287b1152SRichard Henderson TRANS(LDFA, 64, do_ld_fpr, a, MO_32) 4180287b1152SRichard Henderson TRANS(LDDFA, 64, do_ld_fpr, a, MO_64) 4181287b1152SRichard Henderson TRANS(LDQFA, 64, do_ld_fpr, a, MO_128) 4182287b1152SRichard Henderson 418306c060d9SRichard Henderson static bool do_st_fpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp sz) 418406c060d9SRichard Henderson { 418506c060d9SRichard Henderson TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 418606c060d9SRichard Henderson DisasASI da; 418706c060d9SRichard Henderson 418806c060d9SRichard Henderson if (addr == NULL) { 418906c060d9SRichard Henderson return false; 419006c060d9SRichard Henderson } 419106c060d9SRichard Henderson if (gen_trap_ifnofpu(dc)) { 419206c060d9SRichard Henderson return true; 419306c060d9SRichard Henderson } 419406c060d9SRichard Henderson if (sz == MO_128 && gen_trap_float128(dc)) { 419506c060d9SRichard Henderson return true; 419606c060d9SRichard Henderson } 419706c060d9SRichard Henderson da = resolve_asi(dc, a->asi, MO_TE | sz); 4198287b1152SRichard Henderson gen_stf_asi(dc, &da, sz, addr, a->rd); 419906c060d9SRichard Henderson return advance_pc(dc); 420006c060d9SRichard Henderson } 420106c060d9SRichard Henderson 420206c060d9SRichard Henderson TRANS(STF, ALL, do_st_fpr, a, MO_32) 420306c060d9SRichard Henderson TRANS(STDF, ALL, do_st_fpr, a, MO_64) 420406c060d9SRichard Henderson TRANS(STQF, ALL, do_st_fpr, a, MO_128) 420506c060d9SRichard Henderson 4206287b1152SRichard Henderson TRANS(STFA, 64, do_st_fpr, a, MO_32) 4207287b1152SRichard Henderson TRANS(STDFA, 64, do_st_fpr, a, MO_64) 4208287b1152SRichard Henderson TRANS(STQFA, 64, do_st_fpr, a, MO_128) 4209287b1152SRichard Henderson 421006c060d9SRichard Henderson static bool trans_STDFQ(DisasContext *dc, arg_STDFQ *a) 421106c060d9SRichard Henderson { 421206c060d9SRichard Henderson if (!avail_32(dc)) { 421306c060d9SRichard Henderson return false; 421406c060d9SRichard Henderson } 421506c060d9SRichard Henderson if (!supervisor(dc)) { 421606c060d9SRichard Henderson return raise_priv(dc); 421706c060d9SRichard Henderson } 421806c060d9SRichard Henderson if (gen_trap_ifnofpu(dc)) { 421906c060d9SRichard Henderson return true; 422006c060d9SRichard Henderson } 422106c060d9SRichard Henderson gen_op_fpexception_im(dc, FSR_FTT_SEQ_ERROR); 422206c060d9SRichard Henderson return true; 422306c060d9SRichard Henderson } 422406c060d9SRichard Henderson 4225d8c5b92fSRichard Henderson static bool trans_LDFSR(DisasContext *dc, arg_r_r_ri *a) 42263d3c0673SRichard Henderson { 42273590f01eSRichard Henderson TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 4228d8c5b92fSRichard Henderson TCGv_i32 tmp; 42293590f01eSRichard Henderson 42303d3c0673SRichard Henderson if (addr == NULL) { 42313d3c0673SRichard Henderson return false; 42323d3c0673SRichard Henderson } 42333d3c0673SRichard Henderson if (gen_trap_ifnofpu(dc)) { 42343d3c0673SRichard Henderson return true; 42353d3c0673SRichard Henderson } 4236d8c5b92fSRichard Henderson 4237d8c5b92fSRichard Henderson tmp = tcg_temp_new_i32(); 4238d8c5b92fSRichard Henderson tcg_gen_qemu_ld_i32(tmp, addr, dc->mem_idx, MO_TEUL | MO_ALIGN); 4239d8c5b92fSRichard Henderson 4240d8c5b92fSRichard Henderson tcg_gen_extract_i32(cpu_fcc[0], tmp, FSR_FCC0_SHIFT, 2); 4241d8c5b92fSRichard Henderson /* LDFSR does not change FCC[1-3]. */ 4242d8c5b92fSRichard Henderson 4243d8c5b92fSRichard Henderson gen_helper_set_fsr_nofcc_noftt(tcg_env, tmp); 42443d3c0673SRichard Henderson return advance_pc(dc); 42453d3c0673SRichard Henderson } 42463d3c0673SRichard Henderson 4247d8c5b92fSRichard Henderson static bool trans_LDXFSR(DisasContext *dc, arg_r_r_ri *a) 4248d8c5b92fSRichard Henderson { 4249d8c5b92fSRichard Henderson #ifdef TARGET_SPARC64 4250d8c5b92fSRichard Henderson TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 4251d8c5b92fSRichard Henderson TCGv_i64 t64; 4252d8c5b92fSRichard Henderson TCGv_i32 lo, hi; 4253d8c5b92fSRichard Henderson 4254d8c5b92fSRichard Henderson if (addr == NULL) { 4255d8c5b92fSRichard Henderson return false; 4256d8c5b92fSRichard Henderson } 4257d8c5b92fSRichard Henderson if (gen_trap_ifnofpu(dc)) { 4258d8c5b92fSRichard Henderson return true; 4259d8c5b92fSRichard Henderson } 4260d8c5b92fSRichard Henderson 4261d8c5b92fSRichard Henderson t64 = tcg_temp_new_i64(); 4262d8c5b92fSRichard Henderson tcg_gen_qemu_ld_i64(t64, addr, dc->mem_idx, MO_TEUQ | MO_ALIGN); 4263d8c5b92fSRichard Henderson 4264d8c5b92fSRichard Henderson lo = tcg_temp_new_i32(); 4265d8c5b92fSRichard Henderson hi = cpu_fcc[3]; 4266d8c5b92fSRichard Henderson tcg_gen_extr_i64_i32(lo, hi, t64); 4267d8c5b92fSRichard Henderson tcg_gen_extract_i32(cpu_fcc[0], lo, FSR_FCC0_SHIFT, 2); 4268d8c5b92fSRichard Henderson tcg_gen_extract_i32(cpu_fcc[1], hi, FSR_FCC1_SHIFT - 32, 2); 4269d8c5b92fSRichard Henderson tcg_gen_extract_i32(cpu_fcc[2], hi, FSR_FCC2_SHIFT - 32, 2); 4270d8c5b92fSRichard Henderson tcg_gen_extract_i32(cpu_fcc[3], hi, FSR_FCC3_SHIFT - 32, 2); 4271d8c5b92fSRichard Henderson 4272d8c5b92fSRichard Henderson gen_helper_set_fsr_nofcc_noftt(tcg_env, lo); 4273d8c5b92fSRichard Henderson return advance_pc(dc); 4274d8c5b92fSRichard Henderson #else 4275d8c5b92fSRichard Henderson return false; 4276d8c5b92fSRichard Henderson #endif 4277d8c5b92fSRichard Henderson } 42783d3c0673SRichard Henderson 42793d3c0673SRichard Henderson static bool do_stfsr(DisasContext *dc, arg_r_r_ri *a, MemOp mop) 42803d3c0673SRichard Henderson { 42813d3c0673SRichard Henderson TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 42821ccd6e13SRichard Henderson TCGv fsr; 42831ccd6e13SRichard Henderson 42843d3c0673SRichard Henderson if (addr == NULL) { 42853d3c0673SRichard Henderson return false; 42863d3c0673SRichard Henderson } 42873d3c0673SRichard Henderson if (gen_trap_ifnofpu(dc)) { 42883d3c0673SRichard Henderson return true; 42893d3c0673SRichard Henderson } 42901ccd6e13SRichard Henderson 42911ccd6e13SRichard Henderson fsr = tcg_temp_new(); 42921ccd6e13SRichard Henderson gen_helper_get_fsr(fsr, tcg_env); 42931ccd6e13SRichard Henderson tcg_gen_qemu_st_tl(fsr, addr, dc->mem_idx, mop | MO_ALIGN); 42943d3c0673SRichard Henderson return advance_pc(dc); 42953d3c0673SRichard Henderson } 42963d3c0673SRichard Henderson 42973d3c0673SRichard Henderson TRANS(STFSR, ALL, do_stfsr, a, MO_TEUL) 42983d3c0673SRichard Henderson TRANS(STXFSR, 64, do_stfsr, a, MO_TEUQ) 42993d3c0673SRichard Henderson 43001210a036SRichard Henderson static bool do_fc(DisasContext *dc, int rd, int32_t c) 43013a38260eSRichard Henderson { 43023a38260eSRichard Henderson if (gen_trap_ifnofpu(dc)) { 43033a38260eSRichard Henderson return true; 43043a38260eSRichard Henderson } 43051210a036SRichard Henderson gen_store_fpr_F(dc, rd, tcg_constant_i32(c)); 43063a38260eSRichard Henderson return advance_pc(dc); 43073a38260eSRichard Henderson } 43083a38260eSRichard Henderson 43093a38260eSRichard Henderson TRANS(FZEROs, VIS1, do_fc, a->rd, 0) 43101210a036SRichard Henderson TRANS(FONEs, VIS1, do_fc, a->rd, -1) 43113a38260eSRichard Henderson 43123a38260eSRichard Henderson static bool do_dc(DisasContext *dc, int rd, int64_t c) 43133a38260eSRichard Henderson { 43143a38260eSRichard Henderson if (gen_trap_ifnofpu(dc)) { 43153a38260eSRichard Henderson return true; 43163a38260eSRichard Henderson } 43171210a036SRichard Henderson gen_store_fpr_D(dc, rd, tcg_constant_i64(c)); 43183a38260eSRichard Henderson return advance_pc(dc); 43193a38260eSRichard Henderson } 43203a38260eSRichard Henderson 43213a38260eSRichard Henderson TRANS(FZEROd, VIS1, do_dc, a->rd, 0) 43223a38260eSRichard Henderson TRANS(FONEd, VIS1, do_dc, a->rd, -1) 43233a38260eSRichard Henderson 4324baf3dbf2SRichard Henderson static bool do_ff(DisasContext *dc, arg_r_r *a, 4325baf3dbf2SRichard Henderson void (*func)(TCGv_i32, TCGv_i32)) 4326baf3dbf2SRichard Henderson { 4327baf3dbf2SRichard Henderson TCGv_i32 tmp; 4328baf3dbf2SRichard Henderson 4329baf3dbf2SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4330baf3dbf2SRichard Henderson return true; 4331baf3dbf2SRichard Henderson } 4332baf3dbf2SRichard Henderson 4333baf3dbf2SRichard Henderson tmp = gen_load_fpr_F(dc, a->rs); 4334baf3dbf2SRichard Henderson func(tmp, tmp); 4335baf3dbf2SRichard Henderson gen_store_fpr_F(dc, a->rd, tmp); 4336baf3dbf2SRichard Henderson return advance_pc(dc); 4337baf3dbf2SRichard Henderson } 4338baf3dbf2SRichard Henderson 4339baf3dbf2SRichard Henderson TRANS(FMOVs, ALL, do_ff, a, gen_op_fmovs) 4340baf3dbf2SRichard Henderson TRANS(FNEGs, ALL, do_ff, a, gen_op_fnegs) 4341baf3dbf2SRichard Henderson TRANS(FABSs, ALL, do_ff, a, gen_op_fabss) 4342baf3dbf2SRichard Henderson TRANS(FSRCs, VIS1, do_ff, a, tcg_gen_mov_i32) 4343baf3dbf2SRichard Henderson TRANS(FNOTs, VIS1, do_ff, a, tcg_gen_not_i32) 4344baf3dbf2SRichard Henderson 43452f722641SRichard Henderson static bool do_fd(DisasContext *dc, arg_r_r *a, 43462f722641SRichard Henderson void (*func)(TCGv_i32, TCGv_i64)) 43472f722641SRichard Henderson { 43482f722641SRichard Henderson TCGv_i32 dst; 43492f722641SRichard Henderson TCGv_i64 src; 43502f722641SRichard Henderson 43512f722641SRichard Henderson if (gen_trap_ifnofpu(dc)) { 43522f722641SRichard Henderson return true; 43532f722641SRichard Henderson } 43542f722641SRichard Henderson 4355388a6465SRichard Henderson dst = tcg_temp_new_i32(); 43562f722641SRichard Henderson src = gen_load_fpr_D(dc, a->rs); 43572f722641SRichard Henderson func(dst, src); 43582f722641SRichard Henderson gen_store_fpr_F(dc, a->rd, dst); 43592f722641SRichard Henderson return advance_pc(dc); 43602f722641SRichard Henderson } 43612f722641SRichard Henderson 43622f722641SRichard Henderson TRANS(FPACK16, VIS1, do_fd, a, gen_op_fpack16) 43632f722641SRichard Henderson TRANS(FPACKFIX, VIS1, do_fd, a, gen_op_fpackfix) 43642f722641SRichard Henderson 4365119cb94fSRichard Henderson static bool do_env_ff(DisasContext *dc, arg_r_r *a, 4366119cb94fSRichard Henderson void (*func)(TCGv_i32, TCGv_env, TCGv_i32)) 4367119cb94fSRichard Henderson { 4368119cb94fSRichard Henderson TCGv_i32 tmp; 4369119cb94fSRichard Henderson 4370119cb94fSRichard Henderson if (gen_trap_ifnofpu(dc)) { 4371119cb94fSRichard Henderson return true; 4372119cb94fSRichard Henderson } 4373119cb94fSRichard Henderson 4374119cb94fSRichard Henderson tmp = gen_load_fpr_F(dc, a->rs); 4375119cb94fSRichard Henderson func(tmp, tcg_env, tmp); 4376119cb94fSRichard Henderson gen_store_fpr_F(dc, a->rd, tmp); 4377119cb94fSRichard Henderson return advance_pc(dc); 4378119cb94fSRichard Henderson } 4379119cb94fSRichard Henderson 4380119cb94fSRichard Henderson TRANS(FSQRTs, ALL, do_env_ff, a, gen_helper_fsqrts) 4381119cb94fSRichard Henderson TRANS(FiTOs, ALL, do_env_ff, a, gen_helper_fitos) 4382119cb94fSRichard Henderson TRANS(FsTOi, ALL, do_env_ff, a, gen_helper_fstoi) 4383119cb94fSRichard Henderson 43848c94bcd8SRichard Henderson static bool do_env_fd(DisasContext *dc, arg_r_r *a, 43858c94bcd8SRichard Henderson void (*func)(TCGv_i32, TCGv_env, TCGv_i64)) 43868c94bcd8SRichard Henderson { 43878c94bcd8SRichard Henderson TCGv_i32 dst; 43888c94bcd8SRichard Henderson TCGv_i64 src; 43898c94bcd8SRichard Henderson 43908c94bcd8SRichard Henderson if (gen_trap_ifnofpu(dc)) { 43918c94bcd8SRichard Henderson return true; 43928c94bcd8SRichard Henderson } 43938c94bcd8SRichard Henderson 4394388a6465SRichard Henderson dst = tcg_temp_new_i32(); 43958c94bcd8SRichard Henderson src = gen_load_fpr_D(dc, a->rs); 43968c94bcd8SRichard Henderson func(dst, tcg_env, src); 43978c94bcd8SRichard Henderson gen_store_fpr_F(dc, a->rd, dst); 43988c94bcd8SRichard Henderson return advance_pc(dc); 43998c94bcd8SRichard Henderson } 44008c94bcd8SRichard Henderson 44018c94bcd8SRichard Henderson TRANS(FdTOs, ALL, do_env_fd, a, gen_helper_fdtos) 44028c94bcd8SRichard Henderson TRANS(FdTOi, ALL, do_env_fd, a, gen_helper_fdtoi) 44038c94bcd8SRichard Henderson TRANS(FxTOs, 64, do_env_fd, a, gen_helper_fxtos) 44048c94bcd8SRichard Henderson 4405c6d83e4fSRichard Henderson static bool do_dd(DisasContext *dc, arg_r_r *a, 4406c6d83e4fSRichard Henderson void (*func)(TCGv_i64, TCGv_i64)) 4407c6d83e4fSRichard Henderson { 4408c6d83e4fSRichard Henderson TCGv_i64 dst, src; 4409c6d83e4fSRichard Henderson 4410c6d83e4fSRichard Henderson if (gen_trap_ifnofpu(dc)) { 4411c6d83e4fSRichard Henderson return true; 4412c6d83e4fSRichard Henderson } 4413c6d83e4fSRichard Henderson 441452f46d46SRichard Henderson dst = tcg_temp_new_i64(); 4415c6d83e4fSRichard Henderson src = gen_load_fpr_D(dc, a->rs); 4416c6d83e4fSRichard Henderson func(dst, src); 4417c6d83e4fSRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 4418c6d83e4fSRichard Henderson return advance_pc(dc); 4419c6d83e4fSRichard Henderson } 4420c6d83e4fSRichard Henderson 4421c6d83e4fSRichard Henderson TRANS(FMOVd, 64, do_dd, a, gen_op_fmovd) 4422c6d83e4fSRichard Henderson TRANS(FNEGd, 64, do_dd, a, gen_op_fnegd) 4423c6d83e4fSRichard Henderson TRANS(FABSd, 64, do_dd, a, gen_op_fabsd) 4424c6d83e4fSRichard Henderson TRANS(FSRCd, VIS1, do_dd, a, tcg_gen_mov_i64) 4425c6d83e4fSRichard Henderson TRANS(FNOTd, VIS1, do_dd, a, tcg_gen_not_i64) 4426c6d83e4fSRichard Henderson 44278aa418b3SRichard Henderson static bool do_env_dd(DisasContext *dc, arg_r_r *a, 44288aa418b3SRichard Henderson void (*func)(TCGv_i64, TCGv_env, TCGv_i64)) 44298aa418b3SRichard Henderson { 44308aa418b3SRichard Henderson TCGv_i64 dst, src; 44318aa418b3SRichard Henderson 44328aa418b3SRichard Henderson if (gen_trap_ifnofpu(dc)) { 44338aa418b3SRichard Henderson return true; 44348aa418b3SRichard Henderson } 44358aa418b3SRichard Henderson 443652f46d46SRichard Henderson dst = tcg_temp_new_i64(); 44378aa418b3SRichard Henderson src = gen_load_fpr_D(dc, a->rs); 44388aa418b3SRichard Henderson func(dst, tcg_env, src); 44398aa418b3SRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 44408aa418b3SRichard Henderson return advance_pc(dc); 44418aa418b3SRichard Henderson } 44428aa418b3SRichard Henderson 44438aa418b3SRichard Henderson TRANS(FSQRTd, ALL, do_env_dd, a, gen_helper_fsqrtd) 44448aa418b3SRichard Henderson TRANS(FxTOd, 64, do_env_dd, a, gen_helper_fxtod) 44458aa418b3SRichard Henderson TRANS(FdTOx, 64, do_env_dd, a, gen_helper_fdtox) 44468aa418b3SRichard Henderson 44477b616f36SRichard Henderson static bool do_df(DisasContext *dc, arg_r_r *a, 44487b616f36SRichard Henderson void (*func)(TCGv_i64, TCGv_i32)) 44497b616f36SRichard Henderson { 44507b616f36SRichard Henderson TCGv_i64 dst; 44517b616f36SRichard Henderson TCGv_i32 src; 44527b616f36SRichard Henderson 44537b616f36SRichard Henderson if (gen_trap_ifnofpu(dc)) { 44547b616f36SRichard Henderson return true; 44557b616f36SRichard Henderson } 44567b616f36SRichard Henderson 44577b616f36SRichard Henderson dst = tcg_temp_new_i64(); 44587b616f36SRichard Henderson src = gen_load_fpr_F(dc, a->rs); 44597b616f36SRichard Henderson func(dst, src); 44607b616f36SRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 44617b616f36SRichard Henderson return advance_pc(dc); 44627b616f36SRichard Henderson } 44637b616f36SRichard Henderson 44647b616f36SRichard Henderson TRANS(FEXPAND, VIS1, do_df, a, gen_helper_fexpand) 44657b616f36SRichard Henderson 4466199d43efSRichard Henderson static bool do_env_df(DisasContext *dc, arg_r_r *a, 4467199d43efSRichard Henderson void (*func)(TCGv_i64, TCGv_env, TCGv_i32)) 4468199d43efSRichard Henderson { 4469199d43efSRichard Henderson TCGv_i64 dst; 4470199d43efSRichard Henderson TCGv_i32 src; 4471199d43efSRichard Henderson 4472199d43efSRichard Henderson if (gen_trap_ifnofpu(dc)) { 4473199d43efSRichard Henderson return true; 4474199d43efSRichard Henderson } 4475199d43efSRichard Henderson 447652f46d46SRichard Henderson dst = tcg_temp_new_i64(); 4477199d43efSRichard Henderson src = gen_load_fpr_F(dc, a->rs); 4478199d43efSRichard Henderson func(dst, tcg_env, src); 4479199d43efSRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 4480199d43efSRichard Henderson return advance_pc(dc); 4481199d43efSRichard Henderson } 4482199d43efSRichard Henderson 4483199d43efSRichard Henderson TRANS(FiTOd, ALL, do_env_df, a, gen_helper_fitod) 4484199d43efSRichard Henderson TRANS(FsTOd, ALL, do_env_df, a, gen_helper_fstod) 4485199d43efSRichard Henderson TRANS(FsTOx, 64, do_env_df, a, gen_helper_fstox) 4486199d43efSRichard Henderson 4487daf457d4SRichard Henderson static bool do_qq(DisasContext *dc, arg_r_r *a, 4488daf457d4SRichard Henderson void (*func)(TCGv_i128, TCGv_i128)) 4489f4e18df5SRichard Henderson { 449033ec4245SRichard Henderson TCGv_i128 t; 4491f4e18df5SRichard Henderson 4492f4e18df5SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4493f4e18df5SRichard Henderson return true; 4494f4e18df5SRichard Henderson } 4495f4e18df5SRichard Henderson if (gen_trap_float128(dc)) { 4496f4e18df5SRichard Henderson return true; 4497f4e18df5SRichard Henderson } 4498f4e18df5SRichard Henderson 4499f4e18df5SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 450033ec4245SRichard Henderson t = gen_load_fpr_Q(dc, a->rs); 4501daf457d4SRichard Henderson func(t, t); 450233ec4245SRichard Henderson gen_store_fpr_Q(dc, a->rd, t); 4503f4e18df5SRichard Henderson return advance_pc(dc); 4504f4e18df5SRichard Henderson } 4505f4e18df5SRichard Henderson 4506daf457d4SRichard Henderson TRANS(FMOVq, 64, do_qq, a, tcg_gen_mov_i128) 4507daf457d4SRichard Henderson TRANS(FNEGq, 64, do_qq, a, gen_op_fnegq) 4508daf457d4SRichard Henderson TRANS(FABSq, 64, do_qq, a, gen_op_fabsq) 4509f4e18df5SRichard Henderson 4510c995216bSRichard Henderson static bool do_env_qq(DisasContext *dc, arg_r_r *a, 4511e41716beSRichard Henderson void (*func)(TCGv_i128, TCGv_env, TCGv_i128)) 4512c995216bSRichard Henderson { 4513e41716beSRichard Henderson TCGv_i128 t; 4514e41716beSRichard Henderson 4515c995216bSRichard Henderson if (gen_trap_ifnofpu(dc)) { 4516c995216bSRichard Henderson return true; 4517c995216bSRichard Henderson } 4518c995216bSRichard Henderson if (gen_trap_float128(dc)) { 4519c995216bSRichard Henderson return true; 4520c995216bSRichard Henderson } 4521c995216bSRichard Henderson 4522e41716beSRichard Henderson t = gen_load_fpr_Q(dc, a->rs); 4523e41716beSRichard Henderson func(t, tcg_env, t); 4524e41716beSRichard Henderson gen_store_fpr_Q(dc, a->rd, t); 4525c995216bSRichard Henderson return advance_pc(dc); 4526c995216bSRichard Henderson } 4527c995216bSRichard Henderson 4528c995216bSRichard Henderson TRANS(FSQRTq, ALL, do_env_qq, a, gen_helper_fsqrtq) 4529c995216bSRichard Henderson 4530bd9c5c42SRichard Henderson static bool do_env_fq(DisasContext *dc, arg_r_r *a, 4531d81e3efeSRichard Henderson void (*func)(TCGv_i32, TCGv_env, TCGv_i128)) 4532bd9c5c42SRichard Henderson { 4533d81e3efeSRichard Henderson TCGv_i128 src; 4534bd9c5c42SRichard Henderson TCGv_i32 dst; 4535bd9c5c42SRichard Henderson 4536bd9c5c42SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4537bd9c5c42SRichard Henderson return true; 4538bd9c5c42SRichard Henderson } 4539bd9c5c42SRichard Henderson if (gen_trap_float128(dc)) { 4540bd9c5c42SRichard Henderson return true; 4541bd9c5c42SRichard Henderson } 4542bd9c5c42SRichard Henderson 4543d81e3efeSRichard Henderson src = gen_load_fpr_Q(dc, a->rs); 4544388a6465SRichard Henderson dst = tcg_temp_new_i32(); 4545d81e3efeSRichard Henderson func(dst, tcg_env, src); 4546bd9c5c42SRichard Henderson gen_store_fpr_F(dc, a->rd, dst); 4547bd9c5c42SRichard Henderson return advance_pc(dc); 4548bd9c5c42SRichard Henderson } 4549bd9c5c42SRichard Henderson 4550bd9c5c42SRichard Henderson TRANS(FqTOs, ALL, do_env_fq, a, gen_helper_fqtos) 4551bd9c5c42SRichard Henderson TRANS(FqTOi, ALL, do_env_fq, a, gen_helper_fqtoi) 4552bd9c5c42SRichard Henderson 45531617586fSRichard Henderson static bool do_env_dq(DisasContext *dc, arg_r_r *a, 455425a5769eSRichard Henderson void (*func)(TCGv_i64, TCGv_env, TCGv_i128)) 45551617586fSRichard Henderson { 455625a5769eSRichard Henderson TCGv_i128 src; 45571617586fSRichard Henderson TCGv_i64 dst; 45581617586fSRichard Henderson 45591617586fSRichard Henderson if (gen_trap_ifnofpu(dc)) { 45601617586fSRichard Henderson return true; 45611617586fSRichard Henderson } 45621617586fSRichard Henderson if (gen_trap_float128(dc)) { 45631617586fSRichard Henderson return true; 45641617586fSRichard Henderson } 45651617586fSRichard Henderson 456625a5769eSRichard Henderson src = gen_load_fpr_Q(dc, a->rs); 456752f46d46SRichard Henderson dst = tcg_temp_new_i64(); 456825a5769eSRichard Henderson func(dst, tcg_env, src); 45691617586fSRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 45701617586fSRichard Henderson return advance_pc(dc); 45711617586fSRichard Henderson } 45721617586fSRichard Henderson 45731617586fSRichard Henderson TRANS(FqTOd, ALL, do_env_dq, a, gen_helper_fqtod) 45741617586fSRichard Henderson TRANS(FqTOx, 64, do_env_dq, a, gen_helper_fqtox) 45751617586fSRichard Henderson 457613ebcc77SRichard Henderson static bool do_env_qf(DisasContext *dc, arg_r_r *a, 45770b2a61ccSRichard Henderson void (*func)(TCGv_i128, TCGv_env, TCGv_i32)) 457813ebcc77SRichard Henderson { 457913ebcc77SRichard Henderson TCGv_i32 src; 45800b2a61ccSRichard Henderson TCGv_i128 dst; 458113ebcc77SRichard Henderson 458213ebcc77SRichard Henderson if (gen_trap_ifnofpu(dc)) { 458313ebcc77SRichard Henderson return true; 458413ebcc77SRichard Henderson } 458513ebcc77SRichard Henderson if (gen_trap_float128(dc)) { 458613ebcc77SRichard Henderson return true; 458713ebcc77SRichard Henderson } 458813ebcc77SRichard Henderson 458913ebcc77SRichard Henderson src = gen_load_fpr_F(dc, a->rs); 45900b2a61ccSRichard Henderson dst = tcg_temp_new_i128(); 45910b2a61ccSRichard Henderson func(dst, tcg_env, src); 45920b2a61ccSRichard Henderson gen_store_fpr_Q(dc, a->rd, dst); 459313ebcc77SRichard Henderson return advance_pc(dc); 459413ebcc77SRichard Henderson } 459513ebcc77SRichard Henderson 459613ebcc77SRichard Henderson TRANS(FiTOq, ALL, do_env_qf, a, gen_helper_fitoq) 459713ebcc77SRichard Henderson TRANS(FsTOq, ALL, do_env_qf, a, gen_helper_fstoq) 459813ebcc77SRichard Henderson 45997b8e3e1aSRichard Henderson static bool do_env_qd(DisasContext *dc, arg_r_r *a, 4600fdc50716SRichard Henderson void (*func)(TCGv_i128, TCGv_env, TCGv_i64)) 46017b8e3e1aSRichard Henderson { 46027b8e3e1aSRichard Henderson TCGv_i64 src; 4603fdc50716SRichard Henderson TCGv_i128 dst; 46047b8e3e1aSRichard Henderson 46057b8e3e1aSRichard Henderson if (gen_trap_ifnofpu(dc)) { 46067b8e3e1aSRichard Henderson return true; 46077b8e3e1aSRichard Henderson } 46087b8e3e1aSRichard Henderson if (gen_trap_float128(dc)) { 46097b8e3e1aSRichard Henderson return true; 46107b8e3e1aSRichard Henderson } 46117b8e3e1aSRichard Henderson 46127b8e3e1aSRichard Henderson src = gen_load_fpr_D(dc, a->rs); 4613fdc50716SRichard Henderson dst = tcg_temp_new_i128(); 4614fdc50716SRichard Henderson func(dst, tcg_env, src); 4615fdc50716SRichard Henderson gen_store_fpr_Q(dc, a->rd, dst); 46167b8e3e1aSRichard Henderson return advance_pc(dc); 46177b8e3e1aSRichard Henderson } 46187b8e3e1aSRichard Henderson 46197b8e3e1aSRichard Henderson TRANS(FdTOq, ALL, do_env_qd, a, gen_helper_fdtoq) 46207b8e3e1aSRichard Henderson TRANS(FxTOq, 64, do_env_qd, a, gen_helper_fxtoq) 46217b8e3e1aSRichard Henderson 46227f10b52fSRichard Henderson static bool do_fff(DisasContext *dc, arg_r_r_r *a, 46237f10b52fSRichard Henderson void (*func)(TCGv_i32, TCGv_i32, TCGv_i32)) 46247f10b52fSRichard Henderson { 46257f10b52fSRichard Henderson TCGv_i32 src1, src2; 46267f10b52fSRichard Henderson 46277f10b52fSRichard Henderson if (gen_trap_ifnofpu(dc)) { 46287f10b52fSRichard Henderson return true; 46297f10b52fSRichard Henderson } 46307f10b52fSRichard Henderson 46317f10b52fSRichard Henderson src1 = gen_load_fpr_F(dc, a->rs1); 46327f10b52fSRichard Henderson src2 = gen_load_fpr_F(dc, a->rs2); 46337f10b52fSRichard Henderson func(src1, src1, src2); 46347f10b52fSRichard Henderson gen_store_fpr_F(dc, a->rd, src1); 46357f10b52fSRichard Henderson return advance_pc(dc); 46367f10b52fSRichard Henderson } 46377f10b52fSRichard Henderson 46387f10b52fSRichard Henderson TRANS(FPADD16s, VIS1, do_fff, a, tcg_gen_vec_add16_i32) 46397f10b52fSRichard Henderson TRANS(FPADD32s, VIS1, do_fff, a, tcg_gen_add_i32) 46407f10b52fSRichard Henderson TRANS(FPSUB16s, VIS1, do_fff, a, tcg_gen_vec_sub16_i32) 46417f10b52fSRichard Henderson TRANS(FPSUB32s, VIS1, do_fff, a, tcg_gen_sub_i32) 46427f10b52fSRichard Henderson TRANS(FNORs, VIS1, do_fff, a, tcg_gen_nor_i32) 46437f10b52fSRichard Henderson TRANS(FANDNOTs, VIS1, do_fff, a, tcg_gen_andc_i32) 46447f10b52fSRichard Henderson TRANS(FXORs, VIS1, do_fff, a, tcg_gen_xor_i32) 46457f10b52fSRichard Henderson TRANS(FNANDs, VIS1, do_fff, a, tcg_gen_nand_i32) 46467f10b52fSRichard Henderson TRANS(FANDs, VIS1, do_fff, a, tcg_gen_and_i32) 46477f10b52fSRichard Henderson TRANS(FXNORs, VIS1, do_fff, a, tcg_gen_eqv_i32) 46487f10b52fSRichard Henderson TRANS(FORNOTs, VIS1, do_fff, a, tcg_gen_orc_i32) 46497f10b52fSRichard Henderson TRANS(FORs, VIS1, do_fff, a, tcg_gen_or_i32) 46507f10b52fSRichard Henderson 4651c1514961SRichard Henderson static bool do_env_fff(DisasContext *dc, arg_r_r_r *a, 4652c1514961SRichard Henderson void (*func)(TCGv_i32, TCGv_env, TCGv_i32, TCGv_i32)) 4653c1514961SRichard Henderson { 4654c1514961SRichard Henderson TCGv_i32 src1, src2; 4655c1514961SRichard Henderson 4656c1514961SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4657c1514961SRichard Henderson return true; 4658c1514961SRichard Henderson } 4659c1514961SRichard Henderson 4660c1514961SRichard Henderson src1 = gen_load_fpr_F(dc, a->rs1); 4661c1514961SRichard Henderson src2 = gen_load_fpr_F(dc, a->rs2); 4662c1514961SRichard Henderson func(src1, tcg_env, src1, src2); 4663c1514961SRichard Henderson gen_store_fpr_F(dc, a->rd, src1); 4664c1514961SRichard Henderson return advance_pc(dc); 4665c1514961SRichard Henderson } 4666c1514961SRichard Henderson 4667c1514961SRichard Henderson TRANS(FADDs, ALL, do_env_fff, a, gen_helper_fadds) 4668c1514961SRichard Henderson TRANS(FSUBs, ALL, do_env_fff, a, gen_helper_fsubs) 4669c1514961SRichard Henderson TRANS(FMULs, ALL, do_env_fff, a, gen_helper_fmuls) 4670c1514961SRichard Henderson TRANS(FDIVs, ALL, do_env_fff, a, gen_helper_fdivs) 4671c1514961SRichard Henderson 4672a859602cSRichard Henderson static bool do_dff(DisasContext *dc, arg_r_r_r *a, 4673a859602cSRichard Henderson void (*func)(TCGv_i64, TCGv_i32, TCGv_i32)) 4674a859602cSRichard Henderson { 4675a859602cSRichard Henderson TCGv_i64 dst; 4676a859602cSRichard Henderson TCGv_i32 src1, src2; 4677a859602cSRichard Henderson 4678a859602cSRichard Henderson if (gen_trap_ifnofpu(dc)) { 4679a859602cSRichard Henderson return true; 4680a859602cSRichard Henderson } 4681a859602cSRichard Henderson 468252f46d46SRichard Henderson dst = tcg_temp_new_i64(); 4683a859602cSRichard Henderson src1 = gen_load_fpr_F(dc, a->rs1); 4684a859602cSRichard Henderson src2 = gen_load_fpr_F(dc, a->rs2); 4685a859602cSRichard Henderson func(dst, src1, src2); 4686a859602cSRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 4687a859602cSRichard Henderson return advance_pc(dc); 4688a859602cSRichard Henderson } 4689a859602cSRichard Henderson 4690a859602cSRichard Henderson TRANS(FMUL8x16AU, VIS1, do_dff, a, gen_op_fmul8x16au) 4691a859602cSRichard Henderson TRANS(FMUL8x16AL, VIS1, do_dff, a, gen_op_fmul8x16al) 4692be8998e0SRichard Henderson TRANS(FMULD8SUx16, VIS1, do_dff, a, gen_op_fmuld8sux16) 4693be8998e0SRichard Henderson TRANS(FMULD8ULx16, VIS1, do_dff, a, gen_op_fmuld8ulx16) 4694d3ef26afSRichard Henderson TRANS(FPMERGE, VIS1, do_dff, a, gen_helper_fpmerge) 4695a859602cSRichard Henderson 46969157dcccSRichard Henderson static bool do_dfd(DisasContext *dc, arg_r_r_r *a, 46979157dcccSRichard Henderson void (*func)(TCGv_i64, TCGv_i32, TCGv_i64)) 46989157dcccSRichard Henderson { 46999157dcccSRichard Henderson TCGv_i64 dst, src2; 47009157dcccSRichard Henderson TCGv_i32 src1; 47019157dcccSRichard Henderson 47029157dcccSRichard Henderson if (gen_trap_ifnofpu(dc)) { 47039157dcccSRichard Henderson return true; 47049157dcccSRichard Henderson } 47059157dcccSRichard Henderson 470652f46d46SRichard Henderson dst = tcg_temp_new_i64(); 47079157dcccSRichard Henderson src1 = gen_load_fpr_F(dc, a->rs1); 47089157dcccSRichard Henderson src2 = gen_load_fpr_D(dc, a->rs2); 47099157dcccSRichard Henderson func(dst, src1, src2); 47109157dcccSRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 47119157dcccSRichard Henderson return advance_pc(dc); 47129157dcccSRichard Henderson } 47139157dcccSRichard Henderson 47149157dcccSRichard Henderson TRANS(FMUL8x16, VIS1, do_dfd, a, gen_helper_fmul8x16) 47159157dcccSRichard Henderson 471628c131a3SRichard Henderson static bool do_gvec_ddd(DisasContext *dc, arg_r_r_r *a, MemOp vece, 471728c131a3SRichard Henderson void (*func)(unsigned, uint32_t, uint32_t, 471828c131a3SRichard Henderson uint32_t, uint32_t, uint32_t)) 471928c131a3SRichard Henderson { 472028c131a3SRichard Henderson if (gen_trap_ifnofpu(dc)) { 472128c131a3SRichard Henderson return true; 472228c131a3SRichard Henderson } 472328c131a3SRichard Henderson 472428c131a3SRichard Henderson func(vece, gen_offset_fpr_D(a->rd), gen_offset_fpr_D(a->rs1), 472528c131a3SRichard Henderson gen_offset_fpr_D(a->rs2), 8, 8); 472628c131a3SRichard Henderson return advance_pc(dc); 472728c131a3SRichard Henderson } 472828c131a3SRichard Henderson 472928c131a3SRichard Henderson TRANS(FPADD16, VIS1, do_gvec_ddd, a, MO_16, tcg_gen_gvec_add) 473028c131a3SRichard Henderson TRANS(FPADD32, VIS1, do_gvec_ddd, a, MO_32, tcg_gen_gvec_add) 473128c131a3SRichard Henderson TRANS(FPSUB16, VIS1, do_gvec_ddd, a, MO_16, tcg_gen_gvec_sub) 473228c131a3SRichard Henderson TRANS(FPSUB32, VIS1, do_gvec_ddd, a, MO_32, tcg_gen_gvec_sub) 473328c131a3SRichard Henderson 4734e06c9f83SRichard Henderson static bool do_ddd(DisasContext *dc, arg_r_r_r *a, 4735e06c9f83SRichard Henderson void (*func)(TCGv_i64, TCGv_i64, TCGv_i64)) 4736e06c9f83SRichard Henderson { 4737e06c9f83SRichard Henderson TCGv_i64 dst, src1, src2; 4738e06c9f83SRichard Henderson 4739e06c9f83SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4740e06c9f83SRichard Henderson return true; 4741e06c9f83SRichard Henderson } 4742e06c9f83SRichard Henderson 474352f46d46SRichard Henderson dst = tcg_temp_new_i64(); 4744e06c9f83SRichard Henderson src1 = gen_load_fpr_D(dc, a->rs1); 4745e06c9f83SRichard Henderson src2 = gen_load_fpr_D(dc, a->rs2); 4746e06c9f83SRichard Henderson func(dst, src1, src2); 4747e06c9f83SRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 4748e06c9f83SRichard Henderson return advance_pc(dc); 4749e06c9f83SRichard Henderson } 4750e06c9f83SRichard Henderson 4751e06c9f83SRichard Henderson TRANS(FMUL8SUx16, VIS1, do_ddd, a, gen_helper_fmul8sux16) 4752e06c9f83SRichard Henderson TRANS(FMUL8ULx16, VIS1, do_ddd, a, gen_helper_fmul8ulx16) 4753e06c9f83SRichard Henderson 4754e06c9f83SRichard Henderson TRANS(FNORd, VIS1, do_ddd, a, tcg_gen_nor_i64) 4755e06c9f83SRichard Henderson TRANS(FANDNOTd, VIS1, do_ddd, a, tcg_gen_andc_i64) 4756e06c9f83SRichard Henderson TRANS(FXORd, VIS1, do_ddd, a, tcg_gen_xor_i64) 4757e06c9f83SRichard Henderson TRANS(FNANDd, VIS1, do_ddd, a, tcg_gen_nand_i64) 4758e06c9f83SRichard Henderson TRANS(FANDd, VIS1, do_ddd, a, tcg_gen_and_i64) 4759e06c9f83SRichard Henderson TRANS(FXNORd, VIS1, do_ddd, a, tcg_gen_eqv_i64) 4760e06c9f83SRichard Henderson TRANS(FORNOTd, VIS1, do_ddd, a, tcg_gen_orc_i64) 4761e06c9f83SRichard Henderson TRANS(FORd, VIS1, do_ddd, a, tcg_gen_or_i64) 4762e06c9f83SRichard Henderson 47634b6edc0aSRichard Henderson TRANS(FPACK32, VIS1, do_ddd, a, gen_op_fpack32) 47644b6edc0aSRichard Henderson TRANS(FALIGNDATAg, VIS1, do_ddd, a, gen_op_faligndata) 47654b6edc0aSRichard Henderson TRANS(BSHUFFLE, VIS2, do_ddd, a, gen_op_bshuffle) 47664b6edc0aSRichard Henderson 4767e2fa6bd1SRichard Henderson static bool do_rdd(DisasContext *dc, arg_r_r_r *a, 4768e2fa6bd1SRichard Henderson void (*func)(TCGv, TCGv_i64, TCGv_i64)) 4769e2fa6bd1SRichard Henderson { 4770e2fa6bd1SRichard Henderson TCGv_i64 src1, src2; 4771e2fa6bd1SRichard Henderson TCGv dst; 4772e2fa6bd1SRichard Henderson 4773e2fa6bd1SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4774e2fa6bd1SRichard Henderson return true; 4775e2fa6bd1SRichard Henderson } 4776e2fa6bd1SRichard Henderson 4777e2fa6bd1SRichard Henderson dst = gen_dest_gpr(dc, a->rd); 4778e2fa6bd1SRichard Henderson src1 = gen_load_fpr_D(dc, a->rs1); 4779e2fa6bd1SRichard Henderson src2 = gen_load_fpr_D(dc, a->rs2); 4780e2fa6bd1SRichard Henderson func(dst, src1, src2); 4781e2fa6bd1SRichard Henderson gen_store_gpr(dc, a->rd, dst); 4782e2fa6bd1SRichard Henderson return advance_pc(dc); 4783e2fa6bd1SRichard Henderson } 4784e2fa6bd1SRichard Henderson 4785e2fa6bd1SRichard Henderson TRANS(FPCMPLE16, VIS1, do_rdd, a, gen_helper_fcmple16) 4786e2fa6bd1SRichard Henderson TRANS(FPCMPNE16, VIS1, do_rdd, a, gen_helper_fcmpne16) 4787e2fa6bd1SRichard Henderson TRANS(FPCMPGT16, VIS1, do_rdd, a, gen_helper_fcmpgt16) 4788e2fa6bd1SRichard Henderson TRANS(FPCMPEQ16, VIS1, do_rdd, a, gen_helper_fcmpeq16) 4789e2fa6bd1SRichard Henderson 4790e2fa6bd1SRichard Henderson TRANS(FPCMPLE32, VIS1, do_rdd, a, gen_helper_fcmple32) 4791e2fa6bd1SRichard Henderson TRANS(FPCMPNE32, VIS1, do_rdd, a, gen_helper_fcmpne32) 4792e2fa6bd1SRichard Henderson TRANS(FPCMPGT32, VIS1, do_rdd, a, gen_helper_fcmpgt32) 4793e2fa6bd1SRichard Henderson TRANS(FPCMPEQ32, VIS1, do_rdd, a, gen_helper_fcmpeq32) 4794e2fa6bd1SRichard Henderson 4795f2a59b0aSRichard Henderson static bool do_env_ddd(DisasContext *dc, arg_r_r_r *a, 4796f2a59b0aSRichard Henderson void (*func)(TCGv_i64, TCGv_env, TCGv_i64, TCGv_i64)) 4797f2a59b0aSRichard Henderson { 4798f2a59b0aSRichard Henderson TCGv_i64 dst, src1, src2; 4799f2a59b0aSRichard Henderson 4800f2a59b0aSRichard Henderson if (gen_trap_ifnofpu(dc)) { 4801f2a59b0aSRichard Henderson return true; 4802f2a59b0aSRichard Henderson } 4803f2a59b0aSRichard Henderson 480452f46d46SRichard Henderson dst = tcg_temp_new_i64(); 4805f2a59b0aSRichard Henderson src1 = gen_load_fpr_D(dc, a->rs1); 4806f2a59b0aSRichard Henderson src2 = gen_load_fpr_D(dc, a->rs2); 4807f2a59b0aSRichard Henderson func(dst, tcg_env, src1, src2); 4808f2a59b0aSRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 4809f2a59b0aSRichard Henderson return advance_pc(dc); 4810f2a59b0aSRichard Henderson } 4811f2a59b0aSRichard Henderson 4812f2a59b0aSRichard Henderson TRANS(FADDd, ALL, do_env_ddd, a, gen_helper_faddd) 4813f2a59b0aSRichard Henderson TRANS(FSUBd, ALL, do_env_ddd, a, gen_helper_fsubd) 4814f2a59b0aSRichard Henderson TRANS(FMULd, ALL, do_env_ddd, a, gen_helper_fmuld) 4815f2a59b0aSRichard Henderson TRANS(FDIVd, ALL, do_env_ddd, a, gen_helper_fdivd) 4816f2a59b0aSRichard Henderson 4817ff4c711bSRichard Henderson static bool trans_FsMULd(DisasContext *dc, arg_r_r_r *a) 4818ff4c711bSRichard Henderson { 4819ff4c711bSRichard Henderson TCGv_i64 dst; 4820ff4c711bSRichard Henderson TCGv_i32 src1, src2; 4821ff4c711bSRichard Henderson 4822ff4c711bSRichard Henderson if (gen_trap_ifnofpu(dc)) { 4823ff4c711bSRichard Henderson return true; 4824ff4c711bSRichard Henderson } 4825ff4c711bSRichard Henderson if (!(dc->def->features & CPU_FEATURE_FSMULD)) { 4826ff4c711bSRichard Henderson return raise_unimpfpop(dc); 4827ff4c711bSRichard Henderson } 4828ff4c711bSRichard Henderson 482952f46d46SRichard Henderson dst = tcg_temp_new_i64(); 4830ff4c711bSRichard Henderson src1 = gen_load_fpr_F(dc, a->rs1); 4831ff4c711bSRichard Henderson src2 = gen_load_fpr_F(dc, a->rs2); 4832ff4c711bSRichard Henderson gen_helper_fsmuld(dst, tcg_env, src1, src2); 4833ff4c711bSRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 4834ff4c711bSRichard Henderson return advance_pc(dc); 4835ff4c711bSRichard Henderson } 4836ff4c711bSRichard Henderson 4837*4fd71d19SRichard Henderson static bool do_ffff(DisasContext *dc, arg_r_r_r_r *a, 4838*4fd71d19SRichard Henderson void (*func)(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_i32)) 4839*4fd71d19SRichard Henderson { 4840*4fd71d19SRichard Henderson TCGv_i32 dst, src1, src2, src3; 4841*4fd71d19SRichard Henderson 4842*4fd71d19SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4843*4fd71d19SRichard Henderson return true; 4844*4fd71d19SRichard Henderson } 4845*4fd71d19SRichard Henderson 4846*4fd71d19SRichard Henderson src1 = gen_load_fpr_F(dc, a->rs1); 4847*4fd71d19SRichard Henderson src2 = gen_load_fpr_F(dc, a->rs2); 4848*4fd71d19SRichard Henderson src3 = gen_load_fpr_F(dc, a->rs3); 4849*4fd71d19SRichard Henderson dst = tcg_temp_new_i32(); 4850*4fd71d19SRichard Henderson func(dst, src1, src2, src3); 4851*4fd71d19SRichard Henderson gen_store_fpr_F(dc, a->rd, dst); 4852*4fd71d19SRichard Henderson return advance_pc(dc); 4853*4fd71d19SRichard Henderson } 4854*4fd71d19SRichard Henderson 4855*4fd71d19SRichard Henderson TRANS(FMADDs, FMAF, do_ffff, a, gen_op_fmadds) 4856*4fd71d19SRichard Henderson TRANS(FMSUBs, FMAF, do_ffff, a, gen_op_fmsubs) 4857*4fd71d19SRichard Henderson TRANS(FNMSUBs, FMAF, do_ffff, a, gen_op_fnmsubs) 4858*4fd71d19SRichard Henderson TRANS(FNMADDs, FMAF, do_ffff, a, gen_op_fnmadds) 4859*4fd71d19SRichard Henderson 4860*4fd71d19SRichard Henderson static bool do_dddd(DisasContext *dc, arg_r_r_r_r *a, 4861afb04344SRichard Henderson void (*func)(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_i64)) 4862afb04344SRichard Henderson { 4863*4fd71d19SRichard Henderson TCGv_i64 dst, src1, src2, src3; 4864afb04344SRichard Henderson 4865afb04344SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4866afb04344SRichard Henderson return true; 4867afb04344SRichard Henderson } 4868afb04344SRichard Henderson 486952f46d46SRichard Henderson dst = tcg_temp_new_i64(); 4870afb04344SRichard Henderson src1 = gen_load_fpr_D(dc, a->rs1); 4871afb04344SRichard Henderson src2 = gen_load_fpr_D(dc, a->rs2); 4872*4fd71d19SRichard Henderson src3 = gen_load_fpr_D(dc, a->rs3); 4873*4fd71d19SRichard Henderson func(dst, src1, src2, src3); 4874afb04344SRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 4875afb04344SRichard Henderson return advance_pc(dc); 4876afb04344SRichard Henderson } 4877afb04344SRichard Henderson 4878afb04344SRichard Henderson TRANS(PDIST, VIS1, do_dddd, a, gen_helper_pdist) 4879*4fd71d19SRichard Henderson TRANS(FMADDd, FMAF, do_dddd, a, gen_op_fmaddd) 4880*4fd71d19SRichard Henderson TRANS(FMSUBd, FMAF, do_dddd, a, gen_op_fmsubd) 4881*4fd71d19SRichard Henderson TRANS(FNMSUBd, FMAF, do_dddd, a, gen_op_fnmsubd) 4882*4fd71d19SRichard Henderson TRANS(FNMADDd, FMAF, do_dddd, a, gen_op_fnmaddd) 4883afb04344SRichard Henderson 4884a4056239SRichard Henderson static bool do_env_qqq(DisasContext *dc, arg_r_r_r *a, 488516bedf89SRichard Henderson void (*func)(TCGv_i128, TCGv_env, TCGv_i128, TCGv_i128)) 4886a4056239SRichard Henderson { 488716bedf89SRichard Henderson TCGv_i128 src1, src2; 488816bedf89SRichard Henderson 4889a4056239SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4890a4056239SRichard Henderson return true; 4891a4056239SRichard Henderson } 4892a4056239SRichard Henderson if (gen_trap_float128(dc)) { 4893a4056239SRichard Henderson return true; 4894a4056239SRichard Henderson } 4895a4056239SRichard Henderson 489616bedf89SRichard Henderson src1 = gen_load_fpr_Q(dc, a->rs1); 489716bedf89SRichard Henderson src2 = gen_load_fpr_Q(dc, a->rs2); 489816bedf89SRichard Henderson func(src1, tcg_env, src1, src2); 489916bedf89SRichard Henderson gen_store_fpr_Q(dc, a->rd, src1); 4900a4056239SRichard Henderson return advance_pc(dc); 4901a4056239SRichard Henderson } 4902a4056239SRichard Henderson 4903a4056239SRichard Henderson TRANS(FADDq, ALL, do_env_qqq, a, gen_helper_faddq) 4904a4056239SRichard Henderson TRANS(FSUBq, ALL, do_env_qqq, a, gen_helper_fsubq) 4905a4056239SRichard Henderson TRANS(FMULq, ALL, do_env_qqq, a, gen_helper_fmulq) 4906a4056239SRichard Henderson TRANS(FDIVq, ALL, do_env_qqq, a, gen_helper_fdivq) 4907a4056239SRichard Henderson 49085e3b17bbSRichard Henderson static bool trans_FdMULq(DisasContext *dc, arg_r_r_r *a) 49095e3b17bbSRichard Henderson { 49105e3b17bbSRichard Henderson TCGv_i64 src1, src2; 4911ba21dc99SRichard Henderson TCGv_i128 dst; 49125e3b17bbSRichard Henderson 49135e3b17bbSRichard Henderson if (gen_trap_ifnofpu(dc)) { 49145e3b17bbSRichard Henderson return true; 49155e3b17bbSRichard Henderson } 49165e3b17bbSRichard Henderson if (gen_trap_float128(dc)) { 49175e3b17bbSRichard Henderson return true; 49185e3b17bbSRichard Henderson } 49195e3b17bbSRichard Henderson 49205e3b17bbSRichard Henderson src1 = gen_load_fpr_D(dc, a->rs1); 49215e3b17bbSRichard Henderson src2 = gen_load_fpr_D(dc, a->rs2); 4922ba21dc99SRichard Henderson dst = tcg_temp_new_i128(); 4923ba21dc99SRichard Henderson gen_helper_fdmulq(dst, tcg_env, src1, src2); 4924ba21dc99SRichard Henderson gen_store_fpr_Q(dc, a->rd, dst); 49255e3b17bbSRichard Henderson return advance_pc(dc); 49265e3b17bbSRichard Henderson } 49275e3b17bbSRichard Henderson 4928f7ec8155SRichard Henderson static bool do_fmovr(DisasContext *dc, arg_FMOVRs *a, bool is_128, 4929f7ec8155SRichard Henderson void (*func)(DisasContext *, DisasCompare *, int, int)) 4930f7ec8155SRichard Henderson { 4931f7ec8155SRichard Henderson DisasCompare cmp; 4932f7ec8155SRichard Henderson 49332c4f56c9SRichard Henderson if (!gen_compare_reg(&cmp, a->cond, gen_load_gpr(dc, a->rs1))) { 49342c4f56c9SRichard Henderson return false; 49352c4f56c9SRichard Henderson } 4936f7ec8155SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4937f7ec8155SRichard Henderson return true; 4938f7ec8155SRichard Henderson } 4939f7ec8155SRichard Henderson if (is_128 && gen_trap_float128(dc)) { 4940f7ec8155SRichard Henderson return true; 4941f7ec8155SRichard Henderson } 4942f7ec8155SRichard Henderson 4943f7ec8155SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 4944f7ec8155SRichard Henderson func(dc, &cmp, a->rd, a->rs2); 4945f7ec8155SRichard Henderson return advance_pc(dc); 4946f7ec8155SRichard Henderson } 4947f7ec8155SRichard Henderson 4948f7ec8155SRichard Henderson TRANS(FMOVRs, 64, do_fmovr, a, false, gen_fmovs) 4949f7ec8155SRichard Henderson TRANS(FMOVRd, 64, do_fmovr, a, false, gen_fmovd) 4950f7ec8155SRichard Henderson TRANS(FMOVRq, 64, do_fmovr, a, true, gen_fmovq) 4951f7ec8155SRichard Henderson 4952f7ec8155SRichard Henderson static bool do_fmovcc(DisasContext *dc, arg_FMOVscc *a, bool is_128, 4953f7ec8155SRichard Henderson void (*func)(DisasContext *, DisasCompare *, int, int)) 4954f7ec8155SRichard Henderson { 4955f7ec8155SRichard Henderson DisasCompare cmp; 4956f7ec8155SRichard Henderson 4957f7ec8155SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4958f7ec8155SRichard Henderson return true; 4959f7ec8155SRichard Henderson } 4960f7ec8155SRichard Henderson if (is_128 && gen_trap_float128(dc)) { 4961f7ec8155SRichard Henderson return true; 4962f7ec8155SRichard Henderson } 4963f7ec8155SRichard Henderson 4964f7ec8155SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 4965f7ec8155SRichard Henderson gen_compare(&cmp, a->cc, a->cond, dc); 4966f7ec8155SRichard Henderson func(dc, &cmp, a->rd, a->rs2); 4967f7ec8155SRichard Henderson return advance_pc(dc); 4968f7ec8155SRichard Henderson } 4969f7ec8155SRichard Henderson 4970f7ec8155SRichard Henderson TRANS(FMOVscc, 64, do_fmovcc, a, false, gen_fmovs) 4971f7ec8155SRichard Henderson TRANS(FMOVdcc, 64, do_fmovcc, a, false, gen_fmovd) 4972f7ec8155SRichard Henderson TRANS(FMOVqcc, 64, do_fmovcc, a, true, gen_fmovq) 4973f7ec8155SRichard Henderson 4974f7ec8155SRichard Henderson static bool do_fmovfcc(DisasContext *dc, arg_FMOVsfcc *a, bool is_128, 4975f7ec8155SRichard Henderson void (*func)(DisasContext *, DisasCompare *, int, int)) 4976f7ec8155SRichard Henderson { 4977f7ec8155SRichard Henderson DisasCompare cmp; 4978f7ec8155SRichard Henderson 4979f7ec8155SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4980f7ec8155SRichard Henderson return true; 4981f7ec8155SRichard Henderson } 4982f7ec8155SRichard Henderson if (is_128 && gen_trap_float128(dc)) { 4983f7ec8155SRichard Henderson return true; 4984f7ec8155SRichard Henderson } 4985f7ec8155SRichard Henderson 4986f7ec8155SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 4987f7ec8155SRichard Henderson gen_fcompare(&cmp, a->cc, a->cond); 4988f7ec8155SRichard Henderson func(dc, &cmp, a->rd, a->rs2); 4989f7ec8155SRichard Henderson return advance_pc(dc); 4990f7ec8155SRichard Henderson } 4991f7ec8155SRichard Henderson 4992f7ec8155SRichard Henderson TRANS(FMOVsfcc, 64, do_fmovfcc, a, false, gen_fmovs) 4993f7ec8155SRichard Henderson TRANS(FMOVdfcc, 64, do_fmovfcc, a, false, gen_fmovd) 4994f7ec8155SRichard Henderson TRANS(FMOVqfcc, 64, do_fmovfcc, a, true, gen_fmovq) 4995f7ec8155SRichard Henderson 499640f9ad21SRichard Henderson static bool do_fcmps(DisasContext *dc, arg_FCMPs *a, bool e) 499740f9ad21SRichard Henderson { 499840f9ad21SRichard Henderson TCGv_i32 src1, src2; 499940f9ad21SRichard Henderson 500040f9ad21SRichard Henderson if (avail_32(dc) && a->cc != 0) { 500140f9ad21SRichard Henderson return false; 500240f9ad21SRichard Henderson } 500340f9ad21SRichard Henderson if (gen_trap_ifnofpu(dc)) { 500440f9ad21SRichard Henderson return true; 500540f9ad21SRichard Henderson } 500640f9ad21SRichard Henderson 500740f9ad21SRichard Henderson src1 = gen_load_fpr_F(dc, a->rs1); 500840f9ad21SRichard Henderson src2 = gen_load_fpr_F(dc, a->rs2); 500940f9ad21SRichard Henderson if (e) { 5010d8c5b92fSRichard Henderson gen_helper_fcmpes(cpu_fcc[a->cc], tcg_env, src1, src2); 501140f9ad21SRichard Henderson } else { 5012d8c5b92fSRichard Henderson gen_helper_fcmps(cpu_fcc[a->cc], tcg_env, src1, src2); 501340f9ad21SRichard Henderson } 501440f9ad21SRichard Henderson return advance_pc(dc); 501540f9ad21SRichard Henderson } 501640f9ad21SRichard Henderson 501740f9ad21SRichard Henderson TRANS(FCMPs, ALL, do_fcmps, a, false) 501840f9ad21SRichard Henderson TRANS(FCMPEs, ALL, do_fcmps, a, true) 501940f9ad21SRichard Henderson 502040f9ad21SRichard Henderson static bool do_fcmpd(DisasContext *dc, arg_FCMPd *a, bool e) 502140f9ad21SRichard Henderson { 502240f9ad21SRichard Henderson TCGv_i64 src1, src2; 502340f9ad21SRichard Henderson 502440f9ad21SRichard Henderson if (avail_32(dc) && a->cc != 0) { 502540f9ad21SRichard Henderson return false; 502640f9ad21SRichard Henderson } 502740f9ad21SRichard Henderson if (gen_trap_ifnofpu(dc)) { 502840f9ad21SRichard Henderson return true; 502940f9ad21SRichard Henderson } 503040f9ad21SRichard Henderson 503140f9ad21SRichard Henderson src1 = gen_load_fpr_D(dc, a->rs1); 503240f9ad21SRichard Henderson src2 = gen_load_fpr_D(dc, a->rs2); 503340f9ad21SRichard Henderson if (e) { 5034d8c5b92fSRichard Henderson gen_helper_fcmped(cpu_fcc[a->cc], tcg_env, src1, src2); 503540f9ad21SRichard Henderson } else { 5036d8c5b92fSRichard Henderson gen_helper_fcmpd(cpu_fcc[a->cc], tcg_env, src1, src2); 503740f9ad21SRichard Henderson } 503840f9ad21SRichard Henderson return advance_pc(dc); 503940f9ad21SRichard Henderson } 504040f9ad21SRichard Henderson 504140f9ad21SRichard Henderson TRANS(FCMPd, ALL, do_fcmpd, a, false) 504240f9ad21SRichard Henderson TRANS(FCMPEd, ALL, do_fcmpd, a, true) 504340f9ad21SRichard Henderson 504440f9ad21SRichard Henderson static bool do_fcmpq(DisasContext *dc, arg_FCMPq *a, bool e) 504540f9ad21SRichard Henderson { 5046f3ceafadSRichard Henderson TCGv_i128 src1, src2; 5047f3ceafadSRichard Henderson 504840f9ad21SRichard Henderson if (avail_32(dc) && a->cc != 0) { 504940f9ad21SRichard Henderson return false; 505040f9ad21SRichard Henderson } 505140f9ad21SRichard Henderson if (gen_trap_ifnofpu(dc)) { 505240f9ad21SRichard Henderson return true; 505340f9ad21SRichard Henderson } 505440f9ad21SRichard Henderson if (gen_trap_float128(dc)) { 505540f9ad21SRichard Henderson return true; 505640f9ad21SRichard Henderson } 505740f9ad21SRichard Henderson 5058f3ceafadSRichard Henderson src1 = gen_load_fpr_Q(dc, a->rs1); 5059f3ceafadSRichard Henderson src2 = gen_load_fpr_Q(dc, a->rs2); 506040f9ad21SRichard Henderson if (e) { 5061d8c5b92fSRichard Henderson gen_helper_fcmpeq(cpu_fcc[a->cc], tcg_env, src1, src2); 506240f9ad21SRichard Henderson } else { 5063d8c5b92fSRichard Henderson gen_helper_fcmpq(cpu_fcc[a->cc], tcg_env, src1, src2); 506440f9ad21SRichard Henderson } 506540f9ad21SRichard Henderson return advance_pc(dc); 506640f9ad21SRichard Henderson } 506740f9ad21SRichard Henderson 506840f9ad21SRichard Henderson TRANS(FCMPq, ALL, do_fcmpq, a, false) 506940f9ad21SRichard Henderson TRANS(FCMPEq, ALL, do_fcmpq, a, true) 507040f9ad21SRichard Henderson 50716e61bc94SEmilio G. Cota static void sparc_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) 5072fcf5ef2aSThomas Huth { 50736e61bc94SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 50746e61bc94SEmilio G. Cota int bound; 5075af00be49SEmilio G. Cota 5076af00be49SEmilio G. Cota dc->pc = dc->base.pc_first; 50776e61bc94SEmilio G. Cota dc->npc = (target_ulong)dc->base.tb->cs_base; 50786e61bc94SEmilio G. Cota dc->mem_idx = dc->base.tb->flags & TB_FLAG_MMU_MASK; 507977976769SPhilippe Mathieu-Daudé dc->def = &cpu_env(cs)->def; 50806e61bc94SEmilio G. Cota dc->fpu_enabled = tb_fpu_enabled(dc->base.tb->flags); 50816e61bc94SEmilio G. Cota dc->address_mask_32bit = tb_am_enabled(dc->base.tb->flags); 5082c9b459aaSArtyom Tarasenko #ifndef CONFIG_USER_ONLY 50836e61bc94SEmilio G. Cota dc->supervisor = (dc->base.tb->flags & TB_FLAG_SUPER) != 0; 5084c9b459aaSArtyom Tarasenko #endif 5085fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64 5086fcf5ef2aSThomas Huth dc->fprs_dirty = 0; 50876e61bc94SEmilio G. Cota dc->asi = (dc->base.tb->flags >> TB_FLAG_ASI_SHIFT) & 0xff; 5088c9b459aaSArtyom Tarasenko #ifndef CONFIG_USER_ONLY 50896e61bc94SEmilio G. Cota dc->hypervisor = (dc->base.tb->flags & TB_FLAG_HYPER) != 0; 5090c9b459aaSArtyom Tarasenko #endif 5091fcf5ef2aSThomas Huth #endif 50926e61bc94SEmilio G. Cota /* 50936e61bc94SEmilio G. Cota * if we reach a page boundary, we stop generation so that the 50946e61bc94SEmilio G. Cota * PC of a TT_TFAULT exception is always in the right page 50956e61bc94SEmilio G. Cota */ 50966e61bc94SEmilio G. Cota bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4; 50976e61bc94SEmilio G. Cota dc->base.max_insns = MIN(dc->base.max_insns, bound); 5098af00be49SEmilio G. Cota } 5099fcf5ef2aSThomas Huth 51006e61bc94SEmilio G. Cota static void sparc_tr_tb_start(DisasContextBase *db, CPUState *cs) 51016e61bc94SEmilio G. Cota { 51026e61bc94SEmilio G. Cota } 51036e61bc94SEmilio G. Cota 51046e61bc94SEmilio G. Cota static void sparc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) 51056e61bc94SEmilio G. Cota { 51066e61bc94SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 5107633c4283SRichard Henderson target_ulong npc = dc->npc; 51086e61bc94SEmilio G. Cota 5109633c4283SRichard Henderson if (npc & 3) { 5110633c4283SRichard Henderson switch (npc) { 5111633c4283SRichard Henderson case JUMP_PC: 5112fcf5ef2aSThomas Huth assert(dc->jump_pc[1] == dc->pc + 4); 5113633c4283SRichard Henderson npc = dc->jump_pc[0] | JUMP_PC; 5114633c4283SRichard Henderson break; 5115633c4283SRichard Henderson case DYNAMIC_PC: 5116633c4283SRichard Henderson case DYNAMIC_PC_LOOKUP: 5117633c4283SRichard Henderson npc = DYNAMIC_PC; 5118633c4283SRichard Henderson break; 5119633c4283SRichard Henderson default: 5120633c4283SRichard Henderson g_assert_not_reached(); 5121fcf5ef2aSThomas Huth } 51226e61bc94SEmilio G. Cota } 5123633c4283SRichard Henderson tcg_gen_insn_start(dc->pc, npc); 5124633c4283SRichard Henderson } 5125fcf5ef2aSThomas Huth 51266e61bc94SEmilio G. Cota static void sparc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) 51276e61bc94SEmilio G. Cota { 51286e61bc94SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 51296e61bc94SEmilio G. Cota unsigned int insn; 5130fcf5ef2aSThomas Huth 513177976769SPhilippe Mathieu-Daudé insn = translator_ldl(cpu_env(cs), &dc->base, dc->pc); 5132af00be49SEmilio G. Cota dc->base.pc_next += 4; 5133878cc677SRichard Henderson 5134878cc677SRichard Henderson if (!decode(dc, insn)) { 5135ba9c09b4SRichard Henderson gen_exception(dc, TT_ILL_INSN); 5136878cc677SRichard Henderson } 5137fcf5ef2aSThomas Huth 5138af00be49SEmilio G. Cota if (dc->base.is_jmp == DISAS_NORETURN) { 51396e61bc94SEmilio G. Cota return; 5140c5e6ccdfSEmilio G. Cota } 5141af00be49SEmilio G. Cota if (dc->pc != dc->base.pc_next) { 51426e61bc94SEmilio G. Cota dc->base.is_jmp = DISAS_TOO_MANY; 5143af00be49SEmilio G. Cota } 51446e61bc94SEmilio G. Cota } 5145fcf5ef2aSThomas Huth 51466e61bc94SEmilio G. Cota static void sparc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) 51476e61bc94SEmilio G. Cota { 51486e61bc94SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 5149186e7890SRichard Henderson DisasDelayException *e, *e_next; 5150633c4283SRichard Henderson bool may_lookup; 51516e61bc94SEmilio G. Cota 515289527e3aSRichard Henderson finishing_insn(dc); 515389527e3aSRichard Henderson 515446bb0137SMark Cave-Ayland switch (dc->base.is_jmp) { 515546bb0137SMark Cave-Ayland case DISAS_NEXT: 515646bb0137SMark Cave-Ayland case DISAS_TOO_MANY: 5157633c4283SRichard Henderson if (((dc->pc | dc->npc) & 3) == 0) { 5158fcf5ef2aSThomas Huth /* static PC and NPC: we can use direct chaining */ 5159fcf5ef2aSThomas Huth gen_goto_tb(dc, 0, dc->pc, dc->npc); 5160633c4283SRichard Henderson break; 5161fcf5ef2aSThomas Huth } 5162633c4283SRichard Henderson 5163930f1865SRichard Henderson may_lookup = true; 5164633c4283SRichard Henderson if (dc->pc & 3) { 5165633c4283SRichard Henderson switch (dc->pc) { 5166633c4283SRichard Henderson case DYNAMIC_PC_LOOKUP: 5167633c4283SRichard Henderson break; 5168633c4283SRichard Henderson case DYNAMIC_PC: 5169633c4283SRichard Henderson may_lookup = false; 5170633c4283SRichard Henderson break; 5171633c4283SRichard Henderson default: 5172633c4283SRichard Henderson g_assert_not_reached(); 5173633c4283SRichard Henderson } 5174633c4283SRichard Henderson } else { 5175633c4283SRichard Henderson tcg_gen_movi_tl(cpu_pc, dc->pc); 5176633c4283SRichard Henderson } 5177633c4283SRichard Henderson 5178930f1865SRichard Henderson if (dc->npc & 3) { 5179930f1865SRichard Henderson switch (dc->npc) { 5180930f1865SRichard Henderson case JUMP_PC: 5181930f1865SRichard Henderson gen_generic_branch(dc); 5182930f1865SRichard Henderson break; 5183930f1865SRichard Henderson case DYNAMIC_PC: 5184930f1865SRichard Henderson may_lookup = false; 5185930f1865SRichard Henderson break; 5186930f1865SRichard Henderson case DYNAMIC_PC_LOOKUP: 5187930f1865SRichard Henderson break; 5188930f1865SRichard Henderson default: 5189930f1865SRichard Henderson g_assert_not_reached(); 5190930f1865SRichard Henderson } 5191930f1865SRichard Henderson } else { 5192930f1865SRichard Henderson tcg_gen_movi_tl(cpu_npc, dc->npc); 5193930f1865SRichard Henderson } 5194633c4283SRichard Henderson if (may_lookup) { 5195633c4283SRichard Henderson tcg_gen_lookup_and_goto_ptr(); 5196633c4283SRichard Henderson } else { 519707ea28b4SRichard Henderson tcg_gen_exit_tb(NULL, 0); 5198fcf5ef2aSThomas Huth } 519946bb0137SMark Cave-Ayland break; 520046bb0137SMark Cave-Ayland 520146bb0137SMark Cave-Ayland case DISAS_NORETURN: 520246bb0137SMark Cave-Ayland break; 520346bb0137SMark Cave-Ayland 520446bb0137SMark Cave-Ayland case DISAS_EXIT: 520546bb0137SMark Cave-Ayland /* Exit TB */ 520646bb0137SMark Cave-Ayland save_state(dc); 520746bb0137SMark Cave-Ayland tcg_gen_exit_tb(NULL, 0); 520846bb0137SMark Cave-Ayland break; 520946bb0137SMark Cave-Ayland 521046bb0137SMark Cave-Ayland default: 521146bb0137SMark Cave-Ayland g_assert_not_reached(); 5212fcf5ef2aSThomas Huth } 5213186e7890SRichard Henderson 5214186e7890SRichard Henderson for (e = dc->delay_excp_list; e ; e = e_next) { 5215186e7890SRichard Henderson gen_set_label(e->lab); 5216186e7890SRichard Henderson 5217186e7890SRichard Henderson tcg_gen_movi_tl(cpu_pc, e->pc); 5218186e7890SRichard Henderson if (e->npc % 4 == 0) { 5219186e7890SRichard Henderson tcg_gen_movi_tl(cpu_npc, e->npc); 5220186e7890SRichard Henderson } 5221186e7890SRichard Henderson gen_helper_raise_exception(tcg_env, e->excp); 5222186e7890SRichard Henderson 5223186e7890SRichard Henderson e_next = e->next; 5224186e7890SRichard Henderson g_free(e); 5225186e7890SRichard Henderson } 5226fcf5ef2aSThomas Huth } 52276e61bc94SEmilio G. Cota 52286e61bc94SEmilio G. Cota static const TranslatorOps sparc_tr_ops = { 52296e61bc94SEmilio G. Cota .init_disas_context = sparc_tr_init_disas_context, 52306e61bc94SEmilio G. Cota .tb_start = sparc_tr_tb_start, 52316e61bc94SEmilio G. Cota .insn_start = sparc_tr_insn_start, 52326e61bc94SEmilio G. Cota .translate_insn = sparc_tr_translate_insn, 52336e61bc94SEmilio G. Cota .tb_stop = sparc_tr_tb_stop, 52346e61bc94SEmilio G. Cota }; 52356e61bc94SEmilio G. Cota 5236597f9b2dSRichard Henderson void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int *max_insns, 523732f0c394SAnton Johansson vaddr pc, void *host_pc) 52386e61bc94SEmilio G. Cota { 52396e61bc94SEmilio G. Cota DisasContext dc = {}; 52406e61bc94SEmilio G. Cota 5241306c8721SRichard Henderson translator_loop(cs, tb, max_insns, pc, host_pc, &sparc_tr_ops, &dc.base); 5242fcf5ef2aSThomas Huth } 5243fcf5ef2aSThomas Huth 524455c3ceefSRichard Henderson void sparc_tcg_init(void) 5245fcf5ef2aSThomas Huth { 5246fcf5ef2aSThomas Huth static const char gregnames[32][4] = { 5247fcf5ef2aSThomas Huth "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7", 5248fcf5ef2aSThomas Huth "o0", "o1", "o2", "o3", "o4", "o5", "o6", "o7", 5249fcf5ef2aSThomas Huth "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7", 5250fcf5ef2aSThomas Huth "i0", "i1", "i2", "i3", "i4", "i5", "i6", "i7", 5251fcf5ef2aSThomas Huth }; 5252fcf5ef2aSThomas Huth 5253d8c5b92fSRichard Henderson static const struct { TCGv_i32 *ptr; int off; const char *name; } r32[] = { 5254d8c5b92fSRichard Henderson #ifdef TARGET_SPARC64 5255d8c5b92fSRichard Henderson { &cpu_fprs, offsetof(CPUSPARCState, fprs), "fprs" }, 5256d8c5b92fSRichard Henderson { &cpu_fcc[0], offsetof(CPUSPARCState, fcc[0]), "fcc0" }, 5257d8c5b92fSRichard Henderson { &cpu_fcc[1], offsetof(CPUSPARCState, fcc[1]), "fcc1" }, 5258d8c5b92fSRichard Henderson { &cpu_fcc[2], offsetof(CPUSPARCState, fcc[2]), "fcc2" }, 5259d8c5b92fSRichard Henderson { &cpu_fcc[3], offsetof(CPUSPARCState, fcc[3]), "fcc3" }, 5260d8c5b92fSRichard Henderson #else 5261d8c5b92fSRichard Henderson { &cpu_fcc[0], offsetof(CPUSPARCState, fcc[0]), "fcc" }, 5262d8c5b92fSRichard Henderson #endif 5263d8c5b92fSRichard Henderson }; 5264d8c5b92fSRichard Henderson 5265fcf5ef2aSThomas Huth static const struct { TCGv *ptr; int off; const char *name; } rtl[] = { 5266fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64 5267fcf5ef2aSThomas Huth { &cpu_gsr, offsetof(CPUSPARCState, gsr), "gsr" }, 52682a1905c7SRichard Henderson { &cpu_xcc_Z, offsetof(CPUSPARCState, xcc_Z), "xcc_Z" }, 52692a1905c7SRichard Henderson { &cpu_xcc_C, offsetof(CPUSPARCState, xcc_C), "xcc_C" }, 5270fcf5ef2aSThomas Huth #endif 52712a1905c7SRichard Henderson { &cpu_cc_N, offsetof(CPUSPARCState, cc_N), "cc_N" }, 52722a1905c7SRichard Henderson { &cpu_cc_V, offsetof(CPUSPARCState, cc_V), "cc_V" }, 52732a1905c7SRichard Henderson { &cpu_icc_Z, offsetof(CPUSPARCState, icc_Z), "icc_Z" }, 52742a1905c7SRichard Henderson { &cpu_icc_C, offsetof(CPUSPARCState, icc_C), "icc_C" }, 5275fcf5ef2aSThomas Huth { &cpu_cond, offsetof(CPUSPARCState, cond), "cond" }, 5276fcf5ef2aSThomas Huth { &cpu_pc, offsetof(CPUSPARCState, pc), "pc" }, 5277fcf5ef2aSThomas Huth { &cpu_npc, offsetof(CPUSPARCState, npc), "npc" }, 5278fcf5ef2aSThomas Huth { &cpu_y, offsetof(CPUSPARCState, y), "y" }, 5279fcf5ef2aSThomas Huth { &cpu_tbr, offsetof(CPUSPARCState, tbr), "tbr" }, 5280fcf5ef2aSThomas Huth }; 5281fcf5ef2aSThomas Huth 5282fcf5ef2aSThomas Huth unsigned int i; 5283fcf5ef2aSThomas Huth 5284ad75a51eSRichard Henderson cpu_regwptr = tcg_global_mem_new_ptr(tcg_env, 5285fcf5ef2aSThomas Huth offsetof(CPUSPARCState, regwptr), 5286fcf5ef2aSThomas Huth "regwptr"); 5287fcf5ef2aSThomas Huth 5288d8c5b92fSRichard Henderson for (i = 0; i < ARRAY_SIZE(r32); ++i) { 5289d8c5b92fSRichard Henderson *r32[i].ptr = tcg_global_mem_new_i32(tcg_env, r32[i].off, r32[i].name); 5290d8c5b92fSRichard Henderson } 5291d8c5b92fSRichard Henderson 5292fcf5ef2aSThomas Huth for (i = 0; i < ARRAY_SIZE(rtl); ++i) { 5293ad75a51eSRichard Henderson *rtl[i].ptr = tcg_global_mem_new(tcg_env, rtl[i].off, rtl[i].name); 5294fcf5ef2aSThomas Huth } 5295fcf5ef2aSThomas Huth 5296f764718dSRichard Henderson cpu_regs[0] = NULL; 5297fcf5ef2aSThomas Huth for (i = 1; i < 8; ++i) { 5298ad75a51eSRichard Henderson cpu_regs[i] = tcg_global_mem_new(tcg_env, 5299fcf5ef2aSThomas Huth offsetof(CPUSPARCState, gregs[i]), 5300fcf5ef2aSThomas Huth gregnames[i]); 5301fcf5ef2aSThomas Huth } 5302fcf5ef2aSThomas Huth 5303fcf5ef2aSThomas Huth for (i = 8; i < 32; ++i) { 5304fcf5ef2aSThomas Huth cpu_regs[i] = tcg_global_mem_new(cpu_regwptr, 5305fcf5ef2aSThomas Huth (i - 8) * sizeof(target_ulong), 5306fcf5ef2aSThomas Huth gregnames[i]); 5307fcf5ef2aSThomas Huth } 5308fcf5ef2aSThomas Huth } 5309fcf5ef2aSThomas Huth 5310f36aaa53SRichard Henderson void sparc_restore_state_to_opc(CPUState *cs, 5311f36aaa53SRichard Henderson const TranslationBlock *tb, 5312f36aaa53SRichard Henderson const uint64_t *data) 5313fcf5ef2aSThomas Huth { 531477976769SPhilippe Mathieu-Daudé CPUSPARCState *env = cpu_env(cs); 5315fcf5ef2aSThomas Huth target_ulong pc = data[0]; 5316fcf5ef2aSThomas Huth target_ulong npc = data[1]; 5317fcf5ef2aSThomas Huth 5318fcf5ef2aSThomas Huth env->pc = pc; 5319fcf5ef2aSThomas Huth if (npc == DYNAMIC_PC) { 5320fcf5ef2aSThomas Huth /* dynamic NPC: already stored */ 5321fcf5ef2aSThomas Huth } else if (npc & JUMP_PC) { 5322fcf5ef2aSThomas Huth /* jump PC: use 'cond' and the jump targets of the translation */ 5323fcf5ef2aSThomas Huth if (env->cond) { 5324fcf5ef2aSThomas Huth env->npc = npc & ~3; 5325fcf5ef2aSThomas Huth } else { 5326fcf5ef2aSThomas Huth env->npc = pc + 4; 5327fcf5ef2aSThomas Huth } 5328fcf5ef2aSThomas Huth } else { 5329fcf5ef2aSThomas Huth env->npc = npc; 5330fcf5ef2aSThomas Huth } 5331fcf5ef2aSThomas Huth } 5332