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 "disas/disas.h" 25fcf5ef2aSThomas Huth #include "exec/helper-proto.h" 26fcf5ef2aSThomas Huth #include "exec/exec-all.h" 27dcb32f1dSPhilippe Mathieu-Daudé #include "tcg/tcg-op.h" 28fafba1bbSRichard Henderson #include "tcg/tcg-op-gvec.h" 29fcf5ef2aSThomas Huth #include "exec/helper-gen.h" 30c5e6ccdfSEmilio G. Cota #include "exec/translator.h" 31fcf5ef2aSThomas Huth #include "exec/log.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() 4086b82fe0SRichard Henderson # define gen_helper_rett(E) qemu_build_not_reached() 410faef01bSRichard Henderson # define gen_helper_power_down(E) qemu_build_not_reached() 4225524734SRichard Henderson # define gen_helper_wrpsr(E, S) qemu_build_not_reached() 43668bb9b7SRichard Henderson #else 440faef01bSRichard Henderson # define gen_helper_clear_softint(E, S) qemu_build_not_reached() 458f75b8a4SRichard Henderson # define gen_helper_done(E) qemu_build_not_reached() 46c6d83e4fSRichard Henderson # define gen_helper_fabsd(D, S) qemu_build_not_reached() 47e8325dc0SRichard Henderson # define gen_helper_flushw(E) qemu_build_not_reached() 48c6d83e4fSRichard Henderson # define gen_helper_fnegd(D, S) 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() 544ee85ea9SRichard Henderson # define gen_helper_sdivx(D, E, A, B) qemu_build_not_reached() 550faef01bSRichard Henderson # define gen_helper_set_softint(E, S) qemu_build_not_reached() 56af25071cSRichard Henderson # define gen_helper_tick_get_count(D, E, T, C) qemu_build_not_reached() 579422278eSRichard Henderson # define gen_helper_tick_set_count(P, S) qemu_build_not_reached() 58bb97f2f5SRichard Henderson # define gen_helper_tick_set_limit(P, S) qemu_build_not_reached() 594ee85ea9SRichard Henderson # define gen_helper_udivx(D, E, A, B) qemu_build_not_reached() 600faef01bSRichard Henderson # define gen_helper_wrccr(E, S) qemu_build_not_reached() 619422278eSRichard Henderson # define gen_helper_wrcwp(E, S) qemu_build_not_reached() 629422278eSRichard Henderson # define gen_helper_wrgl(E, S) qemu_build_not_reached() 630faef01bSRichard Henderson # define gen_helper_write_softint(E, S) qemu_build_not_reached() 649422278eSRichard Henderson # define gen_helper_wrpil(E, S) qemu_build_not_reached() 659422278eSRichard Henderson # define gen_helper_wrpstate(E, S) qemu_build_not_reached() 66f4e18df5SRichard Henderson # define gen_helper_fabsq ({ qemu_build_not_reached(); NULL; }) 67e2fa6bd1SRichard Henderson # define gen_helper_fcmpeq16 ({ qemu_build_not_reached(); NULL; }) 68e2fa6bd1SRichard Henderson # define gen_helper_fcmpeq32 ({ qemu_build_not_reached(); NULL; }) 69e2fa6bd1SRichard Henderson # define gen_helper_fcmpgt16 ({ qemu_build_not_reached(); NULL; }) 70e2fa6bd1SRichard Henderson # define gen_helper_fcmpgt32 ({ qemu_build_not_reached(); NULL; }) 71e2fa6bd1SRichard Henderson # define gen_helper_fcmple16 ({ qemu_build_not_reached(); NULL; }) 72e2fa6bd1SRichard Henderson # define gen_helper_fcmple32 ({ qemu_build_not_reached(); NULL; }) 73e2fa6bd1SRichard Henderson # define gen_helper_fcmpne16 ({ qemu_build_not_reached(); NULL; }) 74e2fa6bd1SRichard Henderson # define gen_helper_fcmpne32 ({ qemu_build_not_reached(); NULL; }) 758aa418b3SRichard Henderson # define gen_helper_fdtox ({ qemu_build_not_reached(); NULL; }) 76e06c9f83SRichard Henderson # define gen_helper_fexpand ({ qemu_build_not_reached(); NULL; }) 77e06c9f83SRichard Henderson # define gen_helper_fmul8sux16 ({ qemu_build_not_reached(); NULL; }) 78e06c9f83SRichard Henderson # define gen_helper_fmul8ulx16 ({ qemu_build_not_reached(); NULL; }) 79e06c9f83SRichard Henderson # define gen_helper_fmul8x16al ({ qemu_build_not_reached(); NULL; }) 80e06c9f83SRichard Henderson # define gen_helper_fmul8x16au ({ qemu_build_not_reached(); NULL; }) 81e06c9f83SRichard Henderson # define gen_helper_fmul8x16 ({ qemu_build_not_reached(); NULL; }) 82e06c9f83SRichard Henderson # define gen_helper_fmuld8sux16 ({ qemu_build_not_reached(); NULL; }) 83e06c9f83SRichard Henderson # define gen_helper_fmuld8ulx16 ({ qemu_build_not_reached(); NULL; }) 84f4e18df5SRichard Henderson # define gen_helper_fnegq ({ qemu_build_not_reached(); NULL; }) 85e06c9f83SRichard Henderson # define gen_helper_fpmerge ({ qemu_build_not_reached(); NULL; }) 861617586fSRichard Henderson # define gen_helper_fqtox ({ qemu_build_not_reached(); NULL; }) 87199d43efSRichard Henderson # define gen_helper_fstox ({ qemu_build_not_reached(); NULL; }) 888aa418b3SRichard Henderson # define gen_helper_fxtod ({ qemu_build_not_reached(); NULL; }) 897b8e3e1aSRichard Henderson # define gen_helper_fxtoq ({ qemu_build_not_reached(); NULL; }) 90f4e18df5SRichard Henderson # define gen_helper_fxtos ({ qemu_build_not_reached(); NULL; }) 91afb04344SRichard Henderson # define gen_helper_pdist ({ qemu_build_not_reached(); NULL; }) 92da681406SRichard Henderson # define FSR_LDXFSR_MASK 0 93da681406SRichard Henderson # define FSR_LDXFSR_OLDMASK 0 94668bb9b7SRichard Henderson # define MAXTL_MASK 0 95af25071cSRichard Henderson #endif 96af25071cSRichard Henderson 97633c4283SRichard Henderson /* Dynamic PC, must exit to main loop. */ 98633c4283SRichard Henderson #define DYNAMIC_PC 1 99633c4283SRichard Henderson /* Dynamic PC, one of two values according to jump_pc[T2]. */ 100633c4283SRichard Henderson #define JUMP_PC 2 101633c4283SRichard Henderson /* Dynamic PC, may lookup next TB. */ 102633c4283SRichard Henderson #define DYNAMIC_PC_LOOKUP 3 103fcf5ef2aSThomas Huth 10446bb0137SMark Cave-Ayland #define DISAS_EXIT DISAS_TARGET_0 10546bb0137SMark Cave-Ayland 106fcf5ef2aSThomas Huth /* global register indexes */ 107fcf5ef2aSThomas Huth static TCGv_ptr cpu_regwptr; 108fcf5ef2aSThomas Huth static TCGv cpu_cc_src, cpu_cc_src2, cpu_cc_dst; 109fcf5ef2aSThomas Huth static TCGv_i32 cpu_cc_op; 110fcf5ef2aSThomas Huth static TCGv cpu_fsr, cpu_pc, cpu_npc; 111fcf5ef2aSThomas Huth static TCGv cpu_regs[32]; 112fcf5ef2aSThomas Huth static TCGv cpu_y; 113fcf5ef2aSThomas Huth static TCGv cpu_tbr; 114fcf5ef2aSThomas Huth static TCGv cpu_cond; 1152a1905c7SRichard Henderson static TCGv cpu_cc_N; 1162a1905c7SRichard Henderson static TCGv cpu_cc_V; 1172a1905c7SRichard Henderson static TCGv cpu_icc_Z; 1182a1905c7SRichard Henderson static TCGv cpu_icc_C; 119fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64 1202a1905c7SRichard Henderson static TCGv cpu_xcc_Z; 1212a1905c7SRichard Henderson static TCGv cpu_xcc_C; 1222a1905c7SRichard Henderson static TCGv_i32 cpu_fprs; 123fcf5ef2aSThomas Huth static TCGv cpu_gsr; 124fcf5ef2aSThomas Huth #else 125af25071cSRichard Henderson # define cpu_fprs ({ qemu_build_not_reached(); (TCGv)NULL; }) 126af25071cSRichard Henderson # define cpu_gsr ({ qemu_build_not_reached(); (TCGv)NULL; }) 127fcf5ef2aSThomas Huth #endif 1282a1905c7SRichard Henderson 1292a1905c7SRichard Henderson #ifdef TARGET_SPARC64 1302a1905c7SRichard Henderson #define cpu_cc_Z cpu_xcc_Z 1312a1905c7SRichard Henderson #define cpu_cc_C cpu_xcc_C 1322a1905c7SRichard Henderson #else 1332a1905c7SRichard Henderson #define cpu_cc_Z cpu_icc_Z 1342a1905c7SRichard Henderson #define cpu_cc_C cpu_icc_C 1352a1905c7SRichard Henderson #define cpu_xcc_Z ({ qemu_build_not_reached(); NULL; }) 1362a1905c7SRichard Henderson #define cpu_xcc_C ({ qemu_build_not_reached(); NULL; }) 1372a1905c7SRichard Henderson #endif 1382a1905c7SRichard Henderson 139fcf5ef2aSThomas Huth /* Floating point registers */ 140fcf5ef2aSThomas Huth static TCGv_i64 cpu_fpr[TARGET_DPREGS]; 141fcf5ef2aSThomas Huth 142af25071cSRichard Henderson #define env_field_offsetof(X) offsetof(CPUSPARCState, X) 143af25071cSRichard Henderson #ifdef TARGET_SPARC64 144cd6269f7SRichard Henderson # define env32_field_offsetof(X) ({ qemu_build_not_reached(); 0; }) 145af25071cSRichard Henderson # define env64_field_offsetof(X) env_field_offsetof(X) 146af25071cSRichard Henderson #else 147cd6269f7SRichard Henderson # define env32_field_offsetof(X) env_field_offsetof(X) 148af25071cSRichard Henderson # define env64_field_offsetof(X) ({ qemu_build_not_reached(); 0; }) 149af25071cSRichard Henderson #endif 150af25071cSRichard Henderson 151186e7890SRichard Henderson typedef struct DisasDelayException { 152186e7890SRichard Henderson struct DisasDelayException *next; 153186e7890SRichard Henderson TCGLabel *lab; 154186e7890SRichard Henderson TCGv_i32 excp; 155186e7890SRichard Henderson /* Saved state at parent insn. */ 156186e7890SRichard Henderson target_ulong pc; 157186e7890SRichard Henderson target_ulong npc; 158186e7890SRichard Henderson } DisasDelayException; 159186e7890SRichard Henderson 160fcf5ef2aSThomas Huth typedef struct DisasContext { 161af00be49SEmilio G. Cota DisasContextBase base; 162fcf5ef2aSThomas Huth target_ulong pc; /* current Program Counter: integer or DYNAMIC_PC */ 163fcf5ef2aSThomas Huth target_ulong npc; /* next PC: integer or DYNAMIC_PC or JUMP_PC */ 164fcf5ef2aSThomas Huth target_ulong jump_pc[2]; /* used when JUMP_PC pc value is used */ 165fcf5ef2aSThomas Huth int mem_idx; 166c9b459aaSArtyom Tarasenko bool fpu_enabled; 167c9b459aaSArtyom Tarasenko bool address_mask_32bit; 168c9b459aaSArtyom Tarasenko #ifndef CONFIG_USER_ONLY 169c9b459aaSArtyom Tarasenko bool supervisor; 170c9b459aaSArtyom Tarasenko #ifdef TARGET_SPARC64 171c9b459aaSArtyom Tarasenko bool hypervisor; 172c9b459aaSArtyom Tarasenko #endif 173c9b459aaSArtyom Tarasenko #endif 174c9b459aaSArtyom Tarasenko 175fcf5ef2aSThomas Huth uint32_t cc_op; /* current CC operation */ 176fcf5ef2aSThomas Huth sparc_def_t *def; 177fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64 178fcf5ef2aSThomas Huth int fprs_dirty; 179fcf5ef2aSThomas Huth int asi; 180fcf5ef2aSThomas Huth #endif 181186e7890SRichard Henderson DisasDelayException *delay_excp_list; 182fcf5ef2aSThomas Huth } DisasContext; 183fcf5ef2aSThomas Huth 184fcf5ef2aSThomas Huth typedef struct { 185fcf5ef2aSThomas Huth TCGCond cond; 186fcf5ef2aSThomas Huth bool is_bool; 187fcf5ef2aSThomas Huth TCGv c1, c2; 188fcf5ef2aSThomas Huth } DisasCompare; 189fcf5ef2aSThomas Huth 190fcf5ef2aSThomas Huth // This function uses non-native bit order 191fcf5ef2aSThomas Huth #define GET_FIELD(X, FROM, TO) \ 192fcf5ef2aSThomas Huth ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1)) 193fcf5ef2aSThomas Huth 194fcf5ef2aSThomas Huth // This function uses the order in the manuals, i.e. bit 0 is 2^0 195fcf5ef2aSThomas Huth #define GET_FIELD_SP(X, FROM, TO) \ 196fcf5ef2aSThomas Huth GET_FIELD(X, 31 - (TO), 31 - (FROM)) 197fcf5ef2aSThomas Huth 198fcf5ef2aSThomas Huth #define GET_FIELDs(x,a,b) sign_extend (GET_FIELD(x,a,b), (b) - (a) + 1) 199fcf5ef2aSThomas Huth #define GET_FIELD_SPs(x,a,b) sign_extend (GET_FIELD_SP(x,a,b), ((b) - (a) + 1)) 200fcf5ef2aSThomas Huth 201fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64 202fcf5ef2aSThomas Huth #define DFPREG(r) (((r & 1) << 5) | (r & 0x1e)) 203fcf5ef2aSThomas Huth #define QFPREG(r) (((r & 1) << 5) | (r & 0x1c)) 204fcf5ef2aSThomas Huth #else 205fcf5ef2aSThomas Huth #define DFPREG(r) (r & 0x1e) 206fcf5ef2aSThomas Huth #define QFPREG(r) (r & 0x1c) 207fcf5ef2aSThomas Huth #endif 208fcf5ef2aSThomas Huth 209fcf5ef2aSThomas Huth #define UA2005_HTRAP_MASK 0xff 210fcf5ef2aSThomas Huth #define V8_TRAP_MASK 0x7f 211fcf5ef2aSThomas Huth 212fcf5ef2aSThomas Huth #define IS_IMM (insn & (1<<13)) 213fcf5ef2aSThomas Huth 2140c2e96c1SRichard Henderson static void gen_update_fprs_dirty(DisasContext *dc, int rd) 215fcf5ef2aSThomas Huth { 216fcf5ef2aSThomas Huth #if defined(TARGET_SPARC64) 217fcf5ef2aSThomas Huth int bit = (rd < 32) ? 1 : 2; 218fcf5ef2aSThomas Huth /* If we know we've already set this bit within the TB, 219fcf5ef2aSThomas Huth we can avoid setting it again. */ 220fcf5ef2aSThomas Huth if (!(dc->fprs_dirty & bit)) { 221fcf5ef2aSThomas Huth dc->fprs_dirty |= bit; 222fcf5ef2aSThomas Huth tcg_gen_ori_i32(cpu_fprs, cpu_fprs, bit); 223fcf5ef2aSThomas Huth } 224fcf5ef2aSThomas Huth #endif 225fcf5ef2aSThomas Huth } 226fcf5ef2aSThomas Huth 227fcf5ef2aSThomas Huth /* floating point registers moves */ 228fcf5ef2aSThomas Huth static TCGv_i32 gen_load_fpr_F(DisasContext *dc, unsigned int src) 229fcf5ef2aSThomas Huth { 23036ab4623SRichard Henderson TCGv_i32 ret = tcg_temp_new_i32(); 231dc41aa7dSRichard Henderson if (src & 1) { 232dc41aa7dSRichard Henderson tcg_gen_extrl_i64_i32(ret, cpu_fpr[src / 2]); 233dc41aa7dSRichard Henderson } else { 234dc41aa7dSRichard Henderson tcg_gen_extrh_i64_i32(ret, cpu_fpr[src / 2]); 235fcf5ef2aSThomas Huth } 236dc41aa7dSRichard Henderson return ret; 237fcf5ef2aSThomas Huth } 238fcf5ef2aSThomas Huth 239fcf5ef2aSThomas Huth static void gen_store_fpr_F(DisasContext *dc, unsigned int dst, TCGv_i32 v) 240fcf5ef2aSThomas Huth { 2418e7bbc75SRichard Henderson TCGv_i64 t = tcg_temp_new_i64(); 2428e7bbc75SRichard Henderson 2438e7bbc75SRichard Henderson tcg_gen_extu_i32_i64(t, v); 244fcf5ef2aSThomas Huth tcg_gen_deposit_i64(cpu_fpr[dst / 2], cpu_fpr[dst / 2], t, 245fcf5ef2aSThomas Huth (dst & 1 ? 0 : 32), 32); 246fcf5ef2aSThomas Huth gen_update_fprs_dirty(dc, dst); 247fcf5ef2aSThomas Huth } 248fcf5ef2aSThomas Huth 249fcf5ef2aSThomas Huth static TCGv_i32 gen_dest_fpr_F(DisasContext *dc) 250fcf5ef2aSThomas Huth { 25136ab4623SRichard Henderson return tcg_temp_new_i32(); 252fcf5ef2aSThomas Huth } 253fcf5ef2aSThomas Huth 254fcf5ef2aSThomas Huth static TCGv_i64 gen_load_fpr_D(DisasContext *dc, unsigned int src) 255fcf5ef2aSThomas Huth { 256fcf5ef2aSThomas Huth src = DFPREG(src); 257fcf5ef2aSThomas Huth return cpu_fpr[src / 2]; 258fcf5ef2aSThomas Huth } 259fcf5ef2aSThomas Huth 260fcf5ef2aSThomas Huth static void gen_store_fpr_D(DisasContext *dc, unsigned int dst, TCGv_i64 v) 261fcf5ef2aSThomas Huth { 262fcf5ef2aSThomas Huth dst = DFPREG(dst); 263fcf5ef2aSThomas Huth tcg_gen_mov_i64(cpu_fpr[dst / 2], v); 264fcf5ef2aSThomas Huth gen_update_fprs_dirty(dc, dst); 265fcf5ef2aSThomas Huth } 266fcf5ef2aSThomas Huth 267fcf5ef2aSThomas Huth static TCGv_i64 gen_dest_fpr_D(DisasContext *dc, unsigned int dst) 268fcf5ef2aSThomas Huth { 269fcf5ef2aSThomas Huth return cpu_fpr[DFPREG(dst) / 2]; 270fcf5ef2aSThomas Huth } 271fcf5ef2aSThomas Huth 272fcf5ef2aSThomas Huth static void gen_op_load_fpr_QT0(unsigned int src) 273fcf5ef2aSThomas Huth { 274ad75a51eSRichard Henderson tcg_gen_st_i64(cpu_fpr[src / 2], tcg_env, offsetof(CPUSPARCState, qt0) + 275fcf5ef2aSThomas Huth offsetof(CPU_QuadU, ll.upper)); 276ad75a51eSRichard Henderson tcg_gen_st_i64(cpu_fpr[src/2 + 1], tcg_env, offsetof(CPUSPARCState, qt0) + 277fcf5ef2aSThomas Huth offsetof(CPU_QuadU, ll.lower)); 278fcf5ef2aSThomas Huth } 279fcf5ef2aSThomas Huth 280fcf5ef2aSThomas Huth static void gen_op_load_fpr_QT1(unsigned int src) 281fcf5ef2aSThomas Huth { 282ad75a51eSRichard Henderson tcg_gen_st_i64(cpu_fpr[src / 2], tcg_env, offsetof(CPUSPARCState, qt1) + 283fcf5ef2aSThomas Huth offsetof(CPU_QuadU, ll.upper)); 284ad75a51eSRichard Henderson tcg_gen_st_i64(cpu_fpr[src/2 + 1], tcg_env, offsetof(CPUSPARCState, qt1) + 285fcf5ef2aSThomas Huth offsetof(CPU_QuadU, ll.lower)); 286fcf5ef2aSThomas Huth } 287fcf5ef2aSThomas Huth 288fcf5ef2aSThomas Huth static void gen_op_store_QT0_fpr(unsigned int dst) 289fcf5ef2aSThomas Huth { 290ad75a51eSRichard Henderson tcg_gen_ld_i64(cpu_fpr[dst / 2], tcg_env, offsetof(CPUSPARCState, qt0) + 291fcf5ef2aSThomas Huth offsetof(CPU_QuadU, ll.upper)); 292ad75a51eSRichard Henderson tcg_gen_ld_i64(cpu_fpr[dst/2 + 1], tcg_env, offsetof(CPUSPARCState, qt0) + 293fcf5ef2aSThomas Huth offsetof(CPU_QuadU, ll.lower)); 294fcf5ef2aSThomas Huth } 295fcf5ef2aSThomas Huth 296fcf5ef2aSThomas Huth /* moves */ 297fcf5ef2aSThomas Huth #ifdef CONFIG_USER_ONLY 298fcf5ef2aSThomas Huth #define supervisor(dc) 0 299fcf5ef2aSThomas Huth #define hypervisor(dc) 0 300fcf5ef2aSThomas Huth #else 301fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64 302c9b459aaSArtyom Tarasenko #define hypervisor(dc) (dc->hypervisor) 303c9b459aaSArtyom Tarasenko #define supervisor(dc) (dc->supervisor | dc->hypervisor) 304fcf5ef2aSThomas Huth #else 305c9b459aaSArtyom Tarasenko #define supervisor(dc) (dc->supervisor) 306668bb9b7SRichard Henderson #define hypervisor(dc) 0 307fcf5ef2aSThomas Huth #endif 308fcf5ef2aSThomas Huth #endif 309fcf5ef2aSThomas Huth 310b1bc09eaSRichard Henderson #if !defined(TARGET_SPARC64) 311b1bc09eaSRichard Henderson # define AM_CHECK(dc) false 312b1bc09eaSRichard Henderson #elif defined(TARGET_ABI32) 313b1bc09eaSRichard Henderson # define AM_CHECK(dc) true 314b1bc09eaSRichard Henderson #elif defined(CONFIG_USER_ONLY) 315b1bc09eaSRichard Henderson # define AM_CHECK(dc) false 316fcf5ef2aSThomas Huth #else 317b1bc09eaSRichard Henderson # define AM_CHECK(dc) ((dc)->address_mask_32bit) 318fcf5ef2aSThomas Huth #endif 319fcf5ef2aSThomas Huth 3200c2e96c1SRichard Henderson static void gen_address_mask(DisasContext *dc, TCGv addr) 321fcf5ef2aSThomas Huth { 322b1bc09eaSRichard Henderson if (AM_CHECK(dc)) { 323fcf5ef2aSThomas Huth tcg_gen_andi_tl(addr, addr, 0xffffffffULL); 324b1bc09eaSRichard Henderson } 325fcf5ef2aSThomas Huth } 326fcf5ef2aSThomas Huth 32723ada1b1SRichard Henderson static target_ulong address_mask_i(DisasContext *dc, target_ulong addr) 32823ada1b1SRichard Henderson { 32923ada1b1SRichard Henderson return AM_CHECK(dc) ? (uint32_t)addr : addr; 33023ada1b1SRichard Henderson } 33123ada1b1SRichard Henderson 3320c2e96c1SRichard Henderson static TCGv gen_load_gpr(DisasContext *dc, int reg) 333fcf5ef2aSThomas Huth { 334fcf5ef2aSThomas Huth if (reg > 0) { 335fcf5ef2aSThomas Huth assert(reg < 32); 336fcf5ef2aSThomas Huth return cpu_regs[reg]; 337fcf5ef2aSThomas Huth } else { 33852123f14SRichard Henderson TCGv t = tcg_temp_new(); 339fcf5ef2aSThomas Huth tcg_gen_movi_tl(t, 0); 340fcf5ef2aSThomas Huth return t; 341fcf5ef2aSThomas Huth } 342fcf5ef2aSThomas Huth } 343fcf5ef2aSThomas Huth 3440c2e96c1SRichard Henderson static void gen_store_gpr(DisasContext *dc, int reg, TCGv v) 345fcf5ef2aSThomas Huth { 346fcf5ef2aSThomas Huth if (reg > 0) { 347fcf5ef2aSThomas Huth assert(reg < 32); 348fcf5ef2aSThomas Huth tcg_gen_mov_tl(cpu_regs[reg], v); 349fcf5ef2aSThomas Huth } 350fcf5ef2aSThomas Huth } 351fcf5ef2aSThomas Huth 3520c2e96c1SRichard Henderson static TCGv gen_dest_gpr(DisasContext *dc, int reg) 353fcf5ef2aSThomas Huth { 354fcf5ef2aSThomas Huth if (reg > 0) { 355fcf5ef2aSThomas Huth assert(reg < 32); 356fcf5ef2aSThomas Huth return cpu_regs[reg]; 357fcf5ef2aSThomas Huth } else { 35852123f14SRichard Henderson return tcg_temp_new(); 359fcf5ef2aSThomas Huth } 360fcf5ef2aSThomas Huth } 361fcf5ef2aSThomas Huth 3625645aa2eSRichard Henderson static bool use_goto_tb(DisasContext *s, target_ulong pc, target_ulong npc) 363fcf5ef2aSThomas Huth { 3645645aa2eSRichard Henderson return translator_use_goto_tb(&s->base, pc) && 3655645aa2eSRichard Henderson translator_use_goto_tb(&s->base, npc); 366fcf5ef2aSThomas Huth } 367fcf5ef2aSThomas Huth 3685645aa2eSRichard Henderson static void gen_goto_tb(DisasContext *s, int tb_num, 369fcf5ef2aSThomas Huth target_ulong pc, target_ulong npc) 370fcf5ef2aSThomas Huth { 371fcf5ef2aSThomas Huth if (use_goto_tb(s, pc, npc)) { 372fcf5ef2aSThomas Huth /* jump to same page: we can use a direct jump */ 373fcf5ef2aSThomas Huth tcg_gen_goto_tb(tb_num); 374fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_pc, pc); 375fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_npc, npc); 37607ea28b4SRichard Henderson tcg_gen_exit_tb(s->base.tb, tb_num); 377fcf5ef2aSThomas Huth } else { 378f67ccb2fSRichard Henderson /* jump to another page: we can use an indirect jump */ 379fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_pc, pc); 380fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_npc, npc); 381f67ccb2fSRichard Henderson tcg_gen_lookup_and_goto_ptr(); 382fcf5ef2aSThomas Huth } 383fcf5ef2aSThomas Huth } 384fcf5ef2aSThomas Huth 3850c2e96c1SRichard Henderson static void gen_op_add_cc(TCGv dst, TCGv src1, TCGv src2) 386fcf5ef2aSThomas Huth { 387fcf5ef2aSThomas Huth tcg_gen_mov_tl(cpu_cc_src, src1); 388fcf5ef2aSThomas Huth tcg_gen_mov_tl(cpu_cc_src2, src2); 389fcf5ef2aSThomas Huth tcg_gen_add_tl(cpu_cc_dst, cpu_cc_src, cpu_cc_src2); 390fcf5ef2aSThomas Huth tcg_gen_mov_tl(dst, cpu_cc_dst); 391fcf5ef2aSThomas Huth } 392fcf5ef2aSThomas Huth 393fcf5ef2aSThomas Huth static TCGv_i32 gen_add32_carry32(void) 394fcf5ef2aSThomas Huth { 395fcf5ef2aSThomas Huth TCGv_i32 carry_32, cc_src1_32, cc_src2_32; 396fcf5ef2aSThomas Huth 397fcf5ef2aSThomas Huth /* Carry is computed from a previous add: (dst < src) */ 398fcf5ef2aSThomas Huth #if TARGET_LONG_BITS == 64 399fcf5ef2aSThomas Huth cc_src1_32 = tcg_temp_new_i32(); 400fcf5ef2aSThomas Huth cc_src2_32 = tcg_temp_new_i32(); 401fcf5ef2aSThomas Huth tcg_gen_extrl_i64_i32(cc_src1_32, cpu_cc_dst); 402fcf5ef2aSThomas Huth tcg_gen_extrl_i64_i32(cc_src2_32, cpu_cc_src); 403fcf5ef2aSThomas Huth #else 404fcf5ef2aSThomas Huth cc_src1_32 = cpu_cc_dst; 405fcf5ef2aSThomas Huth cc_src2_32 = cpu_cc_src; 406fcf5ef2aSThomas Huth #endif 407fcf5ef2aSThomas Huth 408fcf5ef2aSThomas Huth carry_32 = tcg_temp_new_i32(); 409fcf5ef2aSThomas Huth tcg_gen_setcond_i32(TCG_COND_LTU, carry_32, cc_src1_32, cc_src2_32); 410fcf5ef2aSThomas Huth 411fcf5ef2aSThomas Huth return carry_32; 412fcf5ef2aSThomas Huth } 413fcf5ef2aSThomas Huth 414fcf5ef2aSThomas Huth static TCGv_i32 gen_sub32_carry32(void) 415fcf5ef2aSThomas Huth { 416fcf5ef2aSThomas Huth TCGv_i32 carry_32, cc_src1_32, cc_src2_32; 417fcf5ef2aSThomas Huth 418fcf5ef2aSThomas Huth /* Carry is computed from a previous borrow: (src1 < src2) */ 419fcf5ef2aSThomas Huth #if TARGET_LONG_BITS == 64 420fcf5ef2aSThomas Huth cc_src1_32 = tcg_temp_new_i32(); 421fcf5ef2aSThomas Huth cc_src2_32 = tcg_temp_new_i32(); 422fcf5ef2aSThomas Huth tcg_gen_extrl_i64_i32(cc_src1_32, cpu_cc_src); 423fcf5ef2aSThomas Huth tcg_gen_extrl_i64_i32(cc_src2_32, cpu_cc_src2); 424fcf5ef2aSThomas Huth #else 425fcf5ef2aSThomas Huth cc_src1_32 = cpu_cc_src; 426fcf5ef2aSThomas Huth cc_src2_32 = cpu_cc_src2; 427fcf5ef2aSThomas Huth #endif 428fcf5ef2aSThomas Huth 429fcf5ef2aSThomas Huth carry_32 = tcg_temp_new_i32(); 430fcf5ef2aSThomas Huth tcg_gen_setcond_i32(TCG_COND_LTU, carry_32, cc_src1_32, cc_src2_32); 431fcf5ef2aSThomas Huth 432fcf5ef2aSThomas Huth return carry_32; 433fcf5ef2aSThomas Huth } 434fcf5ef2aSThomas Huth 435420a187dSRichard Henderson static void gen_op_addc_int(TCGv dst, TCGv src1, TCGv src2, 436420a187dSRichard Henderson TCGv_i32 carry_32, bool update_cc) 437fcf5ef2aSThomas Huth { 438fcf5ef2aSThomas Huth tcg_gen_add_tl(dst, src1, src2); 439fcf5ef2aSThomas Huth 440420a187dSRichard Henderson #ifdef TARGET_SPARC64 441420a187dSRichard Henderson TCGv carry = tcg_temp_new(); 442420a187dSRichard Henderson tcg_gen_extu_i32_tl(carry, carry_32); 443420a187dSRichard Henderson tcg_gen_add_tl(dst, dst, carry); 444fcf5ef2aSThomas Huth #else 445420a187dSRichard Henderson tcg_gen_add_i32(dst, dst, carry_32); 446fcf5ef2aSThomas Huth #endif 447fcf5ef2aSThomas Huth 448fcf5ef2aSThomas Huth if (update_cc) { 449420a187dSRichard Henderson tcg_debug_assert(dst == cpu_cc_dst); 450fcf5ef2aSThomas Huth tcg_gen_mov_tl(cpu_cc_src, src1); 451fcf5ef2aSThomas Huth tcg_gen_mov_tl(cpu_cc_src2, src2); 452fcf5ef2aSThomas Huth } 453fcf5ef2aSThomas Huth } 454fcf5ef2aSThomas Huth 455420a187dSRichard Henderson static void gen_op_addc_int_add(TCGv dst, TCGv src1, TCGv src2, bool update_cc) 456420a187dSRichard Henderson { 457420a187dSRichard Henderson TCGv discard; 458420a187dSRichard Henderson 459420a187dSRichard Henderson if (TARGET_LONG_BITS == 64) { 460420a187dSRichard Henderson gen_op_addc_int(dst, src1, src2, gen_add32_carry32(), update_cc); 461420a187dSRichard Henderson return; 462420a187dSRichard Henderson } 463420a187dSRichard Henderson 464420a187dSRichard Henderson /* 465420a187dSRichard Henderson * We can re-use the host's hardware carry generation by using 466420a187dSRichard Henderson * an ADD2 opcode. We discard the low part of the output. 467420a187dSRichard Henderson * Ideally we'd combine this operation with the add that 468420a187dSRichard Henderson * generated the carry in the first place. 469420a187dSRichard Henderson */ 470420a187dSRichard Henderson discard = tcg_temp_new(); 471420a187dSRichard Henderson tcg_gen_add2_tl(discard, dst, cpu_cc_src, src1, cpu_cc_src2, src2); 472420a187dSRichard Henderson 473420a187dSRichard Henderson if (update_cc) { 474420a187dSRichard Henderson tcg_debug_assert(dst == cpu_cc_dst); 475420a187dSRichard Henderson tcg_gen_mov_tl(cpu_cc_src, src1); 476420a187dSRichard Henderson tcg_gen_mov_tl(cpu_cc_src2, src2); 477420a187dSRichard Henderson } 478420a187dSRichard Henderson } 479420a187dSRichard Henderson 480420a187dSRichard Henderson static void gen_op_addc_add(TCGv dst, TCGv src1, TCGv src2) 481420a187dSRichard Henderson { 482420a187dSRichard Henderson gen_op_addc_int_add(dst, src1, src2, false); 483420a187dSRichard Henderson } 484420a187dSRichard Henderson 485420a187dSRichard Henderson static void gen_op_addccc_add(TCGv dst, TCGv src1, TCGv src2) 486420a187dSRichard Henderson { 487420a187dSRichard Henderson gen_op_addc_int_add(dst, src1, src2, true); 488420a187dSRichard Henderson } 489420a187dSRichard Henderson 490420a187dSRichard Henderson static void gen_op_addc_sub(TCGv dst, TCGv src1, TCGv src2) 491420a187dSRichard Henderson { 492420a187dSRichard Henderson gen_op_addc_int(dst, src1, src2, gen_sub32_carry32(), false); 493420a187dSRichard Henderson } 494420a187dSRichard Henderson 495420a187dSRichard Henderson static void gen_op_addccc_sub(TCGv dst, TCGv src1, TCGv src2) 496420a187dSRichard Henderson { 497420a187dSRichard Henderson gen_op_addc_int(dst, src1, src2, gen_sub32_carry32(), true); 498420a187dSRichard Henderson } 499420a187dSRichard Henderson 500420a187dSRichard Henderson static void gen_op_addc_int_generic(TCGv dst, TCGv src1, TCGv src2, 501420a187dSRichard Henderson bool update_cc) 502420a187dSRichard Henderson { 503420a187dSRichard Henderson TCGv_i32 carry_32 = tcg_temp_new_i32(); 504420a187dSRichard Henderson gen_helper_compute_C_icc(carry_32, tcg_env); 505420a187dSRichard Henderson gen_op_addc_int(dst, src1, src2, carry_32, update_cc); 506420a187dSRichard Henderson } 507420a187dSRichard Henderson 508420a187dSRichard Henderson static void gen_op_addc_generic(TCGv dst, TCGv src1, TCGv src2) 509420a187dSRichard Henderson { 510420a187dSRichard Henderson gen_op_addc_int_generic(dst, src1, src2, false); 511420a187dSRichard Henderson } 512420a187dSRichard Henderson 513420a187dSRichard Henderson static void gen_op_addccc_generic(TCGv dst, TCGv src1, TCGv src2) 514420a187dSRichard Henderson { 515420a187dSRichard Henderson gen_op_addc_int_generic(dst, src1, src2, true); 516420a187dSRichard Henderson } 517420a187dSRichard Henderson 5180c2e96c1SRichard Henderson static void gen_op_sub_cc(TCGv dst, TCGv src1, TCGv src2) 519fcf5ef2aSThomas Huth { 520fcf5ef2aSThomas Huth tcg_gen_mov_tl(cpu_cc_src, src1); 521fcf5ef2aSThomas Huth tcg_gen_mov_tl(cpu_cc_src2, src2); 522fcf5ef2aSThomas Huth tcg_gen_sub_tl(cpu_cc_dst, cpu_cc_src, cpu_cc_src2); 523fcf5ef2aSThomas Huth tcg_gen_mov_tl(dst, cpu_cc_dst); 524fcf5ef2aSThomas Huth } 525fcf5ef2aSThomas Huth 526dfebb950SRichard Henderson static void gen_op_subc_int(TCGv dst, TCGv src1, TCGv src2, 527dfebb950SRichard Henderson TCGv_i32 carry_32, bool update_cc) 528fcf5ef2aSThomas Huth { 529fcf5ef2aSThomas Huth TCGv carry; 530fcf5ef2aSThomas Huth 531fcf5ef2aSThomas Huth #if TARGET_LONG_BITS == 64 532fcf5ef2aSThomas Huth carry = tcg_temp_new(); 533fcf5ef2aSThomas Huth tcg_gen_extu_i32_i64(carry, carry_32); 534fcf5ef2aSThomas Huth #else 535fcf5ef2aSThomas Huth carry = carry_32; 536fcf5ef2aSThomas Huth #endif 537fcf5ef2aSThomas Huth 538fcf5ef2aSThomas Huth tcg_gen_sub_tl(dst, src1, src2); 539fcf5ef2aSThomas Huth tcg_gen_sub_tl(dst, dst, carry); 540fcf5ef2aSThomas Huth 541fcf5ef2aSThomas Huth if (update_cc) { 542dfebb950SRichard Henderson tcg_debug_assert(dst == cpu_cc_dst); 543fcf5ef2aSThomas Huth tcg_gen_mov_tl(cpu_cc_src, src1); 544fcf5ef2aSThomas Huth tcg_gen_mov_tl(cpu_cc_src2, src2); 545fcf5ef2aSThomas Huth } 546fcf5ef2aSThomas Huth } 547fcf5ef2aSThomas Huth 548dfebb950SRichard Henderson static void gen_op_subc_add(TCGv dst, TCGv src1, TCGv src2) 549dfebb950SRichard Henderson { 550dfebb950SRichard Henderson gen_op_subc_int(dst, src1, src2, gen_add32_carry32(), false); 551dfebb950SRichard Henderson } 552dfebb950SRichard Henderson 553dfebb950SRichard Henderson static void gen_op_subccc_add(TCGv dst, TCGv src1, TCGv src2) 554dfebb950SRichard Henderson { 555dfebb950SRichard Henderson gen_op_subc_int(dst, src1, src2, gen_add32_carry32(), true); 556dfebb950SRichard Henderson } 557dfebb950SRichard Henderson 558dfebb950SRichard Henderson static void gen_op_subc_int_sub(TCGv dst, TCGv src1, TCGv src2, bool update_cc) 559dfebb950SRichard Henderson { 560dfebb950SRichard Henderson TCGv discard; 561dfebb950SRichard Henderson 562dfebb950SRichard Henderson if (TARGET_LONG_BITS == 64) { 563dfebb950SRichard Henderson gen_op_subc_int(dst, src1, src2, gen_sub32_carry32(), update_cc); 564dfebb950SRichard Henderson return; 565dfebb950SRichard Henderson } 566dfebb950SRichard Henderson 567dfebb950SRichard Henderson /* 568dfebb950SRichard Henderson * We can re-use the host's hardware carry generation by using 569dfebb950SRichard Henderson * a SUB2 opcode. We discard the low part of the output. 570dfebb950SRichard Henderson */ 571dfebb950SRichard Henderson discard = tcg_temp_new(); 572dfebb950SRichard Henderson tcg_gen_sub2_tl(discard, dst, cpu_cc_src, src1, cpu_cc_src2, src2); 573dfebb950SRichard Henderson 574dfebb950SRichard Henderson if (update_cc) { 575dfebb950SRichard Henderson tcg_debug_assert(dst == cpu_cc_dst); 576dfebb950SRichard Henderson tcg_gen_mov_tl(cpu_cc_src, src1); 577dfebb950SRichard Henderson tcg_gen_mov_tl(cpu_cc_src2, src2); 578dfebb950SRichard Henderson } 579dfebb950SRichard Henderson } 580dfebb950SRichard Henderson 581dfebb950SRichard Henderson static void gen_op_subc_sub(TCGv dst, TCGv src1, TCGv src2) 582dfebb950SRichard Henderson { 583dfebb950SRichard Henderson gen_op_subc_int_sub(dst, src1, src2, false); 584dfebb950SRichard Henderson } 585dfebb950SRichard Henderson 586dfebb950SRichard Henderson static void gen_op_subccc_sub(TCGv dst, TCGv src1, TCGv src2) 587dfebb950SRichard Henderson { 588dfebb950SRichard Henderson gen_op_subc_int_sub(dst, src1, src2, true); 589dfebb950SRichard Henderson } 590dfebb950SRichard Henderson 591dfebb950SRichard Henderson static void gen_op_subc_int_generic(TCGv dst, TCGv src1, TCGv src2, 592dfebb950SRichard Henderson bool update_cc) 593dfebb950SRichard Henderson { 594dfebb950SRichard Henderson TCGv_i32 carry_32 = tcg_temp_new_i32(); 595dfebb950SRichard Henderson 596dfebb950SRichard Henderson gen_helper_compute_C_icc(carry_32, tcg_env); 597dfebb950SRichard Henderson gen_op_subc_int(dst, src1, src2, carry_32, update_cc); 598dfebb950SRichard Henderson } 599dfebb950SRichard Henderson 600dfebb950SRichard Henderson static void gen_op_subc_generic(TCGv dst, TCGv src1, TCGv src2) 601dfebb950SRichard Henderson { 602dfebb950SRichard Henderson gen_op_subc_int_generic(dst, src1, src2, false); 603dfebb950SRichard Henderson } 604dfebb950SRichard Henderson 605dfebb950SRichard Henderson static void gen_op_subccc_generic(TCGv dst, TCGv src1, TCGv src2) 606dfebb950SRichard Henderson { 607dfebb950SRichard Henderson gen_op_subc_int_generic(dst, src1, src2, true); 608dfebb950SRichard Henderson } 609dfebb950SRichard Henderson 6100c2e96c1SRichard Henderson static void gen_op_mulscc(TCGv dst, TCGv src1, TCGv src2) 611fcf5ef2aSThomas Huth { 612fcf5ef2aSThomas Huth TCGv r_temp, zero, t0; 613fcf5ef2aSThomas Huth 614fcf5ef2aSThomas Huth r_temp = tcg_temp_new(); 615fcf5ef2aSThomas Huth t0 = tcg_temp_new(); 616fcf5ef2aSThomas Huth 617fcf5ef2aSThomas Huth /* old op: 618fcf5ef2aSThomas Huth if (!(env->y & 1)) 619fcf5ef2aSThomas Huth T1 = 0; 620fcf5ef2aSThomas Huth */ 62100ab7e61SRichard Henderson zero = tcg_constant_tl(0); 622fcf5ef2aSThomas Huth tcg_gen_andi_tl(cpu_cc_src, src1, 0xffffffff); 623fcf5ef2aSThomas Huth tcg_gen_andi_tl(r_temp, cpu_y, 0x1); 624fcf5ef2aSThomas Huth tcg_gen_andi_tl(cpu_cc_src2, src2, 0xffffffff); 625fcf5ef2aSThomas Huth tcg_gen_movcond_tl(TCG_COND_EQ, cpu_cc_src2, r_temp, zero, 626fcf5ef2aSThomas Huth zero, cpu_cc_src2); 627fcf5ef2aSThomas Huth 628fcf5ef2aSThomas Huth // b2 = T0 & 1; 629fcf5ef2aSThomas Huth // env->y = (b2 << 31) | (env->y >> 1); 6300b1183e3SPhilippe Mathieu-Daudé tcg_gen_extract_tl(t0, cpu_y, 1, 31); 63108d64e0dSPhilippe Mathieu-Daudé tcg_gen_deposit_tl(cpu_y, t0, cpu_cc_src, 31, 1); 632fcf5ef2aSThomas Huth 633fcf5ef2aSThomas Huth // b1 = N ^ V; 6342a1905c7SRichard Henderson tcg_gen_xor_tl(t0, cpu_cc_N, cpu_cc_V); 635fcf5ef2aSThomas Huth 636fcf5ef2aSThomas Huth // T0 = (b1 << 31) | (T0 >> 1); 637fcf5ef2aSThomas Huth // src1 = T0; 6382a1905c7SRichard Henderson tcg_gen_andi_tl(t0, t0, 1u << 31); 639fcf5ef2aSThomas Huth tcg_gen_shri_tl(cpu_cc_src, cpu_cc_src, 1); 640fcf5ef2aSThomas Huth tcg_gen_or_tl(cpu_cc_src, cpu_cc_src, t0); 641fcf5ef2aSThomas Huth 642fcf5ef2aSThomas Huth tcg_gen_add_tl(cpu_cc_dst, cpu_cc_src, cpu_cc_src2); 643fcf5ef2aSThomas Huth 644fcf5ef2aSThomas Huth tcg_gen_mov_tl(dst, cpu_cc_dst); 645fcf5ef2aSThomas Huth } 646fcf5ef2aSThomas Huth 6470c2e96c1SRichard Henderson static void gen_op_multiply(TCGv dst, TCGv src1, TCGv src2, int sign_ext) 648fcf5ef2aSThomas Huth { 649fcf5ef2aSThomas Huth #if TARGET_LONG_BITS == 32 650fcf5ef2aSThomas Huth if (sign_ext) { 651fcf5ef2aSThomas Huth tcg_gen_muls2_tl(dst, cpu_y, src1, src2); 652fcf5ef2aSThomas Huth } else { 653fcf5ef2aSThomas Huth tcg_gen_mulu2_tl(dst, cpu_y, src1, src2); 654fcf5ef2aSThomas Huth } 655fcf5ef2aSThomas Huth #else 656fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new_i64(); 657fcf5ef2aSThomas Huth TCGv t1 = tcg_temp_new_i64(); 658fcf5ef2aSThomas Huth 659fcf5ef2aSThomas Huth if (sign_ext) { 660fcf5ef2aSThomas Huth tcg_gen_ext32s_i64(t0, src1); 661fcf5ef2aSThomas Huth tcg_gen_ext32s_i64(t1, src2); 662fcf5ef2aSThomas Huth } else { 663fcf5ef2aSThomas Huth tcg_gen_ext32u_i64(t0, src1); 664fcf5ef2aSThomas Huth tcg_gen_ext32u_i64(t1, src2); 665fcf5ef2aSThomas Huth } 666fcf5ef2aSThomas Huth 667fcf5ef2aSThomas Huth tcg_gen_mul_i64(dst, t0, t1); 668fcf5ef2aSThomas Huth tcg_gen_shri_i64(cpu_y, dst, 32); 669fcf5ef2aSThomas Huth #endif 670fcf5ef2aSThomas Huth } 671fcf5ef2aSThomas Huth 6720c2e96c1SRichard Henderson static void gen_op_umul(TCGv dst, TCGv src1, TCGv src2) 673fcf5ef2aSThomas Huth { 674fcf5ef2aSThomas Huth /* zero-extend truncated operands before multiplication */ 675fcf5ef2aSThomas Huth gen_op_multiply(dst, src1, src2, 0); 676fcf5ef2aSThomas Huth } 677fcf5ef2aSThomas Huth 6780c2e96c1SRichard Henderson static void gen_op_smul(TCGv dst, TCGv src1, TCGv src2) 679fcf5ef2aSThomas Huth { 680fcf5ef2aSThomas Huth /* sign-extend truncated operands before multiplication */ 681fcf5ef2aSThomas Huth gen_op_multiply(dst, src1, src2, 1); 682fcf5ef2aSThomas Huth } 683fcf5ef2aSThomas Huth 6844ee85ea9SRichard Henderson static void gen_op_udivx(TCGv dst, TCGv src1, TCGv src2) 6854ee85ea9SRichard Henderson { 6864ee85ea9SRichard Henderson gen_helper_udivx(dst, tcg_env, src1, src2); 6874ee85ea9SRichard Henderson } 6884ee85ea9SRichard Henderson 6894ee85ea9SRichard Henderson static void gen_op_sdivx(TCGv dst, TCGv src1, TCGv src2) 6904ee85ea9SRichard Henderson { 6914ee85ea9SRichard Henderson gen_helper_sdivx(dst, tcg_env, src1, src2); 6924ee85ea9SRichard Henderson } 6934ee85ea9SRichard Henderson 694c2636853SRichard Henderson static void gen_op_udiv(TCGv dst, TCGv src1, TCGv src2) 695c2636853SRichard Henderson { 696c2636853SRichard Henderson gen_helper_udiv(dst, tcg_env, src1, src2); 697c2636853SRichard Henderson } 698c2636853SRichard Henderson 699c2636853SRichard Henderson static void gen_op_sdiv(TCGv dst, TCGv src1, TCGv src2) 700c2636853SRichard Henderson { 701c2636853SRichard Henderson gen_helper_sdiv(dst, tcg_env, src1, src2); 702c2636853SRichard Henderson } 703c2636853SRichard Henderson 704c2636853SRichard Henderson static void gen_op_udivcc(TCGv dst, TCGv src1, TCGv src2) 705c2636853SRichard Henderson { 706c2636853SRichard Henderson gen_helper_udiv_cc(dst, tcg_env, src1, src2); 707c2636853SRichard Henderson } 708c2636853SRichard Henderson 709c2636853SRichard Henderson static void gen_op_sdivcc(TCGv dst, TCGv src1, TCGv src2) 710c2636853SRichard Henderson { 711c2636853SRichard Henderson gen_helper_sdiv_cc(dst, tcg_env, src1, src2); 712c2636853SRichard Henderson } 713c2636853SRichard Henderson 714a9aba13dSRichard Henderson static void gen_op_taddcctv(TCGv dst, TCGv src1, TCGv src2) 715a9aba13dSRichard Henderson { 716a9aba13dSRichard Henderson gen_helper_taddcctv(dst, tcg_env, src1, src2); 717a9aba13dSRichard Henderson } 718a9aba13dSRichard Henderson 719a9aba13dSRichard Henderson static void gen_op_tsubcctv(TCGv dst, TCGv src1, TCGv src2) 720a9aba13dSRichard Henderson { 721a9aba13dSRichard Henderson gen_helper_tsubcctv(dst, tcg_env, src1, src2); 722a9aba13dSRichard Henderson } 723a9aba13dSRichard Henderson 7249c6ec5bcSRichard Henderson static void gen_op_popc(TCGv dst, TCGv src1, TCGv src2) 7259c6ec5bcSRichard Henderson { 7269c6ec5bcSRichard Henderson tcg_gen_ctpop_tl(dst, src2); 7279c6ec5bcSRichard Henderson } 7289c6ec5bcSRichard Henderson 72945bfed3bSRichard Henderson #ifndef TARGET_SPARC64 73045bfed3bSRichard Henderson static void gen_helper_array8(TCGv dst, TCGv src1, TCGv src2) 73145bfed3bSRichard Henderson { 73245bfed3bSRichard Henderson g_assert_not_reached(); 73345bfed3bSRichard Henderson } 73445bfed3bSRichard Henderson #endif 73545bfed3bSRichard Henderson 73645bfed3bSRichard Henderson static void gen_op_array16(TCGv dst, TCGv src1, TCGv src2) 73745bfed3bSRichard Henderson { 73845bfed3bSRichard Henderson gen_helper_array8(dst, src1, src2); 73945bfed3bSRichard Henderson tcg_gen_shli_tl(dst, dst, 1); 74045bfed3bSRichard Henderson } 74145bfed3bSRichard Henderson 74245bfed3bSRichard Henderson static void gen_op_array32(TCGv dst, TCGv src1, TCGv src2) 74345bfed3bSRichard Henderson { 74445bfed3bSRichard Henderson gen_helper_array8(dst, src1, src2); 74545bfed3bSRichard Henderson tcg_gen_shli_tl(dst, dst, 2); 74645bfed3bSRichard Henderson } 74745bfed3bSRichard Henderson 7482f722641SRichard Henderson static void gen_op_fpack16(TCGv_i32 dst, TCGv_i64 src) 7492f722641SRichard Henderson { 7502f722641SRichard Henderson #ifdef TARGET_SPARC64 7512f722641SRichard Henderson gen_helper_fpack16(dst, cpu_gsr, src); 7522f722641SRichard Henderson #else 7532f722641SRichard Henderson g_assert_not_reached(); 7542f722641SRichard Henderson #endif 7552f722641SRichard Henderson } 7562f722641SRichard Henderson 7572f722641SRichard Henderson static void gen_op_fpackfix(TCGv_i32 dst, TCGv_i64 src) 7582f722641SRichard Henderson { 7592f722641SRichard Henderson #ifdef TARGET_SPARC64 7602f722641SRichard Henderson gen_helper_fpackfix(dst, cpu_gsr, src); 7612f722641SRichard Henderson #else 7622f722641SRichard Henderson g_assert_not_reached(); 7632f722641SRichard Henderson #endif 7642f722641SRichard Henderson } 7652f722641SRichard Henderson 7664b6edc0aSRichard Henderson static void gen_op_fpack32(TCGv_i64 dst, TCGv_i64 src1, TCGv_i64 src2) 7674b6edc0aSRichard Henderson { 7684b6edc0aSRichard Henderson #ifdef TARGET_SPARC64 7694b6edc0aSRichard Henderson gen_helper_fpack32(dst, cpu_gsr, src1, src2); 7704b6edc0aSRichard Henderson #else 7714b6edc0aSRichard Henderson g_assert_not_reached(); 7724b6edc0aSRichard Henderson #endif 7734b6edc0aSRichard Henderson } 7744b6edc0aSRichard Henderson 7754b6edc0aSRichard Henderson static void gen_op_faligndata(TCGv_i64 dst, TCGv_i64 s1, TCGv_i64 s2) 7764b6edc0aSRichard Henderson { 7774b6edc0aSRichard Henderson #ifdef TARGET_SPARC64 7784b6edc0aSRichard Henderson TCGv t1, t2, shift; 7794b6edc0aSRichard Henderson 7804b6edc0aSRichard Henderson t1 = tcg_temp_new(); 7814b6edc0aSRichard Henderson t2 = tcg_temp_new(); 7824b6edc0aSRichard Henderson shift = tcg_temp_new(); 7834b6edc0aSRichard Henderson 7844b6edc0aSRichard Henderson tcg_gen_andi_tl(shift, cpu_gsr, 7); 7854b6edc0aSRichard Henderson tcg_gen_shli_tl(shift, shift, 3); 7864b6edc0aSRichard Henderson tcg_gen_shl_tl(t1, s1, shift); 7874b6edc0aSRichard Henderson 7884b6edc0aSRichard Henderson /* 7894b6edc0aSRichard Henderson * A shift of 64 does not produce 0 in TCG. Divide this into a 7904b6edc0aSRichard Henderson * shift of (up to 63) followed by a constant shift of 1. 7914b6edc0aSRichard Henderson */ 7924b6edc0aSRichard Henderson tcg_gen_xori_tl(shift, shift, 63); 7934b6edc0aSRichard Henderson tcg_gen_shr_tl(t2, s2, shift); 7944b6edc0aSRichard Henderson tcg_gen_shri_tl(t2, t2, 1); 7954b6edc0aSRichard Henderson 7964b6edc0aSRichard Henderson tcg_gen_or_tl(dst, t1, t2); 7974b6edc0aSRichard Henderson #else 7984b6edc0aSRichard Henderson g_assert_not_reached(); 7994b6edc0aSRichard Henderson #endif 8004b6edc0aSRichard Henderson } 8014b6edc0aSRichard Henderson 8024b6edc0aSRichard Henderson static void gen_op_bshuffle(TCGv_i64 dst, TCGv_i64 src1, TCGv_i64 src2) 8034b6edc0aSRichard Henderson { 8044b6edc0aSRichard Henderson #ifdef TARGET_SPARC64 8054b6edc0aSRichard Henderson gen_helper_bshuffle(dst, cpu_gsr, src1, src2); 8064b6edc0aSRichard Henderson #else 8074b6edc0aSRichard Henderson g_assert_not_reached(); 8084b6edc0aSRichard Henderson #endif 8094b6edc0aSRichard Henderson } 8104b6edc0aSRichard Henderson 811fcf5ef2aSThomas Huth // 1 8120c2e96c1SRichard Henderson static void gen_op_eval_ba(TCGv dst) 813fcf5ef2aSThomas Huth { 814fcf5ef2aSThomas Huth tcg_gen_movi_tl(dst, 1); 815fcf5ef2aSThomas Huth } 816fcf5ef2aSThomas Huth 817fcf5ef2aSThomas Huth // 0 8180c2e96c1SRichard Henderson static void gen_op_eval_bn(TCGv dst) 819fcf5ef2aSThomas Huth { 820fcf5ef2aSThomas Huth tcg_gen_movi_tl(dst, 0); 821fcf5ef2aSThomas Huth } 822fcf5ef2aSThomas Huth 823fcf5ef2aSThomas Huth /* 824fcf5ef2aSThomas Huth FPSR bit field FCC1 | FCC0: 825fcf5ef2aSThomas Huth 0 = 826fcf5ef2aSThomas Huth 1 < 827fcf5ef2aSThomas Huth 2 > 828fcf5ef2aSThomas Huth 3 unordered 829fcf5ef2aSThomas Huth */ 8300c2e96c1SRichard Henderson static void gen_mov_reg_FCC0(TCGv reg, TCGv src, 831fcf5ef2aSThomas Huth unsigned int fcc_offset) 832fcf5ef2aSThomas Huth { 833fcf5ef2aSThomas Huth tcg_gen_shri_tl(reg, src, FSR_FCC0_SHIFT + fcc_offset); 834fcf5ef2aSThomas Huth tcg_gen_andi_tl(reg, reg, 0x1); 835fcf5ef2aSThomas Huth } 836fcf5ef2aSThomas Huth 8370c2e96c1SRichard Henderson static void gen_mov_reg_FCC1(TCGv reg, TCGv src, unsigned int fcc_offset) 838fcf5ef2aSThomas Huth { 839fcf5ef2aSThomas Huth tcg_gen_shri_tl(reg, src, FSR_FCC1_SHIFT + fcc_offset); 840fcf5ef2aSThomas Huth tcg_gen_andi_tl(reg, reg, 0x1); 841fcf5ef2aSThomas Huth } 842fcf5ef2aSThomas Huth 843fcf5ef2aSThomas Huth // !0: FCC0 | FCC1 8440c2e96c1SRichard Henderson static void gen_op_eval_fbne(TCGv dst, TCGv src, unsigned int fcc_offset) 845fcf5ef2aSThomas Huth { 846fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new(); 847fcf5ef2aSThomas Huth gen_mov_reg_FCC0(dst, src, fcc_offset); 848fcf5ef2aSThomas Huth gen_mov_reg_FCC1(t0, src, fcc_offset); 849fcf5ef2aSThomas Huth tcg_gen_or_tl(dst, dst, t0); 850fcf5ef2aSThomas Huth } 851fcf5ef2aSThomas Huth 852fcf5ef2aSThomas Huth // 1 or 2: FCC0 ^ FCC1 8530c2e96c1SRichard Henderson static void gen_op_eval_fblg(TCGv dst, TCGv src, unsigned int fcc_offset) 854fcf5ef2aSThomas Huth { 855fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new(); 856fcf5ef2aSThomas Huth gen_mov_reg_FCC0(dst, src, fcc_offset); 857fcf5ef2aSThomas Huth gen_mov_reg_FCC1(t0, src, fcc_offset); 858fcf5ef2aSThomas Huth tcg_gen_xor_tl(dst, dst, t0); 859fcf5ef2aSThomas Huth } 860fcf5ef2aSThomas Huth 861fcf5ef2aSThomas Huth // 1 or 3: FCC0 8620c2e96c1SRichard Henderson static void gen_op_eval_fbul(TCGv dst, TCGv src, unsigned int fcc_offset) 863fcf5ef2aSThomas Huth { 864fcf5ef2aSThomas Huth gen_mov_reg_FCC0(dst, src, fcc_offset); 865fcf5ef2aSThomas Huth } 866fcf5ef2aSThomas Huth 867fcf5ef2aSThomas Huth // 1: FCC0 & !FCC1 8680c2e96c1SRichard Henderson static void gen_op_eval_fbl(TCGv dst, TCGv src, unsigned int fcc_offset) 869fcf5ef2aSThomas Huth { 870fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new(); 871fcf5ef2aSThomas Huth gen_mov_reg_FCC0(dst, src, fcc_offset); 872fcf5ef2aSThomas Huth gen_mov_reg_FCC1(t0, src, fcc_offset); 873fcf5ef2aSThomas Huth tcg_gen_andc_tl(dst, dst, t0); 874fcf5ef2aSThomas Huth } 875fcf5ef2aSThomas Huth 876fcf5ef2aSThomas Huth // 2 or 3: FCC1 8770c2e96c1SRichard Henderson static void gen_op_eval_fbug(TCGv dst, TCGv src, unsigned int fcc_offset) 878fcf5ef2aSThomas Huth { 879fcf5ef2aSThomas Huth gen_mov_reg_FCC1(dst, src, fcc_offset); 880fcf5ef2aSThomas Huth } 881fcf5ef2aSThomas Huth 882fcf5ef2aSThomas Huth // 2: !FCC0 & FCC1 8830c2e96c1SRichard Henderson static void gen_op_eval_fbg(TCGv dst, TCGv src, unsigned int fcc_offset) 884fcf5ef2aSThomas Huth { 885fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new(); 886fcf5ef2aSThomas Huth gen_mov_reg_FCC0(dst, src, fcc_offset); 887fcf5ef2aSThomas Huth gen_mov_reg_FCC1(t0, src, fcc_offset); 888fcf5ef2aSThomas Huth tcg_gen_andc_tl(dst, t0, dst); 889fcf5ef2aSThomas Huth } 890fcf5ef2aSThomas Huth 891fcf5ef2aSThomas Huth // 3: FCC0 & FCC1 8920c2e96c1SRichard Henderson static void gen_op_eval_fbu(TCGv dst, TCGv src, unsigned int fcc_offset) 893fcf5ef2aSThomas Huth { 894fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new(); 895fcf5ef2aSThomas Huth gen_mov_reg_FCC0(dst, src, fcc_offset); 896fcf5ef2aSThomas Huth gen_mov_reg_FCC1(t0, src, fcc_offset); 897fcf5ef2aSThomas Huth tcg_gen_and_tl(dst, dst, t0); 898fcf5ef2aSThomas Huth } 899fcf5ef2aSThomas Huth 900fcf5ef2aSThomas Huth // 0: !(FCC0 | FCC1) 9010c2e96c1SRichard Henderson static void gen_op_eval_fbe(TCGv dst, TCGv src, unsigned int fcc_offset) 902fcf5ef2aSThomas Huth { 903fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new(); 904fcf5ef2aSThomas Huth gen_mov_reg_FCC0(dst, src, fcc_offset); 905fcf5ef2aSThomas Huth gen_mov_reg_FCC1(t0, src, fcc_offset); 906fcf5ef2aSThomas Huth tcg_gen_or_tl(dst, dst, t0); 907fcf5ef2aSThomas Huth tcg_gen_xori_tl(dst, dst, 0x1); 908fcf5ef2aSThomas Huth } 909fcf5ef2aSThomas Huth 910fcf5ef2aSThomas Huth // 0 or 3: !(FCC0 ^ FCC1) 9110c2e96c1SRichard Henderson static void gen_op_eval_fbue(TCGv dst, TCGv src, unsigned int fcc_offset) 912fcf5ef2aSThomas Huth { 913fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new(); 914fcf5ef2aSThomas Huth gen_mov_reg_FCC0(dst, src, fcc_offset); 915fcf5ef2aSThomas Huth gen_mov_reg_FCC1(t0, src, fcc_offset); 916fcf5ef2aSThomas Huth tcg_gen_xor_tl(dst, dst, t0); 917fcf5ef2aSThomas Huth tcg_gen_xori_tl(dst, dst, 0x1); 918fcf5ef2aSThomas Huth } 919fcf5ef2aSThomas Huth 920fcf5ef2aSThomas Huth // 0 or 2: !FCC0 9210c2e96c1SRichard Henderson static void gen_op_eval_fbge(TCGv dst, TCGv src, unsigned int fcc_offset) 922fcf5ef2aSThomas Huth { 923fcf5ef2aSThomas Huth gen_mov_reg_FCC0(dst, src, fcc_offset); 924fcf5ef2aSThomas Huth tcg_gen_xori_tl(dst, dst, 0x1); 925fcf5ef2aSThomas Huth } 926fcf5ef2aSThomas Huth 927fcf5ef2aSThomas Huth // !1: !(FCC0 & !FCC1) 9280c2e96c1SRichard Henderson static void gen_op_eval_fbuge(TCGv dst, TCGv src, unsigned int fcc_offset) 929fcf5ef2aSThomas Huth { 930fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new(); 931fcf5ef2aSThomas Huth gen_mov_reg_FCC0(dst, src, fcc_offset); 932fcf5ef2aSThomas Huth gen_mov_reg_FCC1(t0, src, fcc_offset); 933fcf5ef2aSThomas Huth tcg_gen_andc_tl(dst, dst, t0); 934fcf5ef2aSThomas Huth tcg_gen_xori_tl(dst, dst, 0x1); 935fcf5ef2aSThomas Huth } 936fcf5ef2aSThomas Huth 937fcf5ef2aSThomas Huth // 0 or 1: !FCC1 9380c2e96c1SRichard Henderson static void gen_op_eval_fble(TCGv dst, TCGv src, unsigned int fcc_offset) 939fcf5ef2aSThomas Huth { 940fcf5ef2aSThomas Huth gen_mov_reg_FCC1(dst, src, fcc_offset); 941fcf5ef2aSThomas Huth tcg_gen_xori_tl(dst, dst, 0x1); 942fcf5ef2aSThomas Huth } 943fcf5ef2aSThomas Huth 944fcf5ef2aSThomas Huth // !2: !(!FCC0 & FCC1) 9450c2e96c1SRichard Henderson static void gen_op_eval_fbule(TCGv dst, TCGv src, unsigned int fcc_offset) 946fcf5ef2aSThomas Huth { 947fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new(); 948fcf5ef2aSThomas Huth gen_mov_reg_FCC0(dst, src, fcc_offset); 949fcf5ef2aSThomas Huth gen_mov_reg_FCC1(t0, src, fcc_offset); 950fcf5ef2aSThomas Huth tcg_gen_andc_tl(dst, t0, dst); 951fcf5ef2aSThomas Huth tcg_gen_xori_tl(dst, dst, 0x1); 952fcf5ef2aSThomas Huth } 953fcf5ef2aSThomas Huth 954fcf5ef2aSThomas Huth // !3: !(FCC0 & FCC1) 9550c2e96c1SRichard Henderson static void gen_op_eval_fbo(TCGv dst, TCGv src, unsigned int fcc_offset) 956fcf5ef2aSThomas Huth { 957fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new(); 958fcf5ef2aSThomas Huth gen_mov_reg_FCC0(dst, src, fcc_offset); 959fcf5ef2aSThomas Huth gen_mov_reg_FCC1(t0, src, fcc_offset); 960fcf5ef2aSThomas Huth tcg_gen_and_tl(dst, dst, t0); 961fcf5ef2aSThomas Huth tcg_gen_xori_tl(dst, dst, 0x1); 962fcf5ef2aSThomas Huth } 963fcf5ef2aSThomas Huth 9640c2e96c1SRichard Henderson static void gen_branch2(DisasContext *dc, target_ulong pc1, 965fcf5ef2aSThomas Huth target_ulong pc2, TCGv r_cond) 966fcf5ef2aSThomas Huth { 967fcf5ef2aSThomas Huth TCGLabel *l1 = gen_new_label(); 968fcf5ef2aSThomas Huth 969fcf5ef2aSThomas Huth tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, 0, l1); 970fcf5ef2aSThomas Huth 971fcf5ef2aSThomas Huth gen_goto_tb(dc, 0, pc1, pc1 + 4); 972fcf5ef2aSThomas Huth 973fcf5ef2aSThomas Huth gen_set_label(l1); 974fcf5ef2aSThomas Huth gen_goto_tb(dc, 1, pc2, pc2 + 4); 975fcf5ef2aSThomas Huth } 976fcf5ef2aSThomas Huth 9770c2e96c1SRichard Henderson static void gen_generic_branch(DisasContext *dc) 978fcf5ef2aSThomas Huth { 97900ab7e61SRichard Henderson TCGv npc0 = tcg_constant_tl(dc->jump_pc[0]); 98000ab7e61SRichard Henderson TCGv npc1 = tcg_constant_tl(dc->jump_pc[1]); 98100ab7e61SRichard Henderson TCGv zero = tcg_constant_tl(0); 982fcf5ef2aSThomas Huth 983fcf5ef2aSThomas Huth tcg_gen_movcond_tl(TCG_COND_NE, cpu_npc, cpu_cond, zero, npc0, npc1); 984fcf5ef2aSThomas Huth } 985fcf5ef2aSThomas Huth 986fcf5ef2aSThomas Huth /* call this function before using the condition register as it may 987fcf5ef2aSThomas Huth have been set for a jump */ 9880c2e96c1SRichard Henderson static void flush_cond(DisasContext *dc) 989fcf5ef2aSThomas Huth { 990fcf5ef2aSThomas Huth if (dc->npc == JUMP_PC) { 991fcf5ef2aSThomas Huth gen_generic_branch(dc); 99299c82c47SRichard Henderson dc->npc = DYNAMIC_PC_LOOKUP; 993fcf5ef2aSThomas Huth } 994fcf5ef2aSThomas Huth } 995fcf5ef2aSThomas Huth 9960c2e96c1SRichard Henderson static void save_npc(DisasContext *dc) 997fcf5ef2aSThomas Huth { 998633c4283SRichard Henderson if (dc->npc & 3) { 999633c4283SRichard Henderson switch (dc->npc) { 1000633c4283SRichard Henderson case JUMP_PC: 1001fcf5ef2aSThomas Huth gen_generic_branch(dc); 100299c82c47SRichard Henderson dc->npc = DYNAMIC_PC_LOOKUP; 1003633c4283SRichard Henderson break; 1004633c4283SRichard Henderson case DYNAMIC_PC: 1005633c4283SRichard Henderson case DYNAMIC_PC_LOOKUP: 1006633c4283SRichard Henderson break; 1007633c4283SRichard Henderson default: 1008633c4283SRichard Henderson g_assert_not_reached(); 1009633c4283SRichard Henderson } 1010633c4283SRichard Henderson } else { 1011fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_npc, dc->npc); 1012fcf5ef2aSThomas Huth } 1013fcf5ef2aSThomas Huth } 1014fcf5ef2aSThomas Huth 10150c2e96c1SRichard Henderson static void update_psr(DisasContext *dc) 1016fcf5ef2aSThomas Huth { 1017fcf5ef2aSThomas Huth if (dc->cc_op != CC_OP_FLAGS) { 1018fcf5ef2aSThomas Huth dc->cc_op = CC_OP_FLAGS; 1019ad75a51eSRichard Henderson gen_helper_compute_psr(tcg_env); 1020fcf5ef2aSThomas Huth } 1021fcf5ef2aSThomas Huth } 1022fcf5ef2aSThomas Huth 10230c2e96c1SRichard Henderson static void save_state(DisasContext *dc) 1024fcf5ef2aSThomas Huth { 1025fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_pc, dc->pc); 1026fcf5ef2aSThomas Huth save_npc(dc); 1027fcf5ef2aSThomas Huth } 1028fcf5ef2aSThomas Huth 1029fcf5ef2aSThomas Huth static void gen_exception(DisasContext *dc, int which) 1030fcf5ef2aSThomas Huth { 1031fcf5ef2aSThomas Huth save_state(dc); 1032ad75a51eSRichard Henderson gen_helper_raise_exception(tcg_env, tcg_constant_i32(which)); 1033af00be49SEmilio G. Cota dc->base.is_jmp = DISAS_NORETURN; 1034fcf5ef2aSThomas Huth } 1035fcf5ef2aSThomas Huth 1036186e7890SRichard Henderson static TCGLabel *delay_exceptionv(DisasContext *dc, TCGv_i32 excp) 1037fcf5ef2aSThomas Huth { 1038186e7890SRichard Henderson DisasDelayException *e = g_new0(DisasDelayException, 1); 1039186e7890SRichard Henderson 1040186e7890SRichard Henderson e->next = dc->delay_excp_list; 1041186e7890SRichard Henderson dc->delay_excp_list = e; 1042186e7890SRichard Henderson 1043186e7890SRichard Henderson e->lab = gen_new_label(); 1044186e7890SRichard Henderson e->excp = excp; 1045186e7890SRichard Henderson e->pc = dc->pc; 1046186e7890SRichard Henderson /* Caller must have used flush_cond before branch. */ 1047186e7890SRichard Henderson assert(e->npc != JUMP_PC); 1048186e7890SRichard Henderson e->npc = dc->npc; 1049186e7890SRichard Henderson 1050186e7890SRichard Henderson return e->lab; 1051186e7890SRichard Henderson } 1052186e7890SRichard Henderson 1053186e7890SRichard Henderson static TCGLabel *delay_exception(DisasContext *dc, int excp) 1054186e7890SRichard Henderson { 1055186e7890SRichard Henderson return delay_exceptionv(dc, tcg_constant_i32(excp)); 1056186e7890SRichard Henderson } 1057186e7890SRichard Henderson 1058186e7890SRichard Henderson static void gen_check_align(DisasContext *dc, TCGv addr, int mask) 1059186e7890SRichard Henderson { 1060186e7890SRichard Henderson TCGv t = tcg_temp_new(); 1061186e7890SRichard Henderson TCGLabel *lab; 1062186e7890SRichard Henderson 1063186e7890SRichard Henderson tcg_gen_andi_tl(t, addr, mask); 1064186e7890SRichard Henderson 1065186e7890SRichard Henderson flush_cond(dc); 1066186e7890SRichard Henderson lab = delay_exception(dc, TT_UNALIGNED); 1067186e7890SRichard Henderson tcg_gen_brcondi_tl(TCG_COND_NE, t, 0, lab); 1068fcf5ef2aSThomas Huth } 1069fcf5ef2aSThomas Huth 10700c2e96c1SRichard Henderson static void gen_mov_pc_npc(DisasContext *dc) 1071fcf5ef2aSThomas Huth { 1072633c4283SRichard Henderson if (dc->npc & 3) { 1073633c4283SRichard Henderson switch (dc->npc) { 1074633c4283SRichard Henderson case JUMP_PC: 1075fcf5ef2aSThomas Huth gen_generic_branch(dc); 1076fcf5ef2aSThomas Huth tcg_gen_mov_tl(cpu_pc, cpu_npc); 107799c82c47SRichard Henderson dc->pc = DYNAMIC_PC_LOOKUP; 1078633c4283SRichard Henderson break; 1079633c4283SRichard Henderson case DYNAMIC_PC: 1080633c4283SRichard Henderson case DYNAMIC_PC_LOOKUP: 1081fcf5ef2aSThomas Huth tcg_gen_mov_tl(cpu_pc, cpu_npc); 1082633c4283SRichard Henderson dc->pc = dc->npc; 1083633c4283SRichard Henderson break; 1084633c4283SRichard Henderson default: 1085633c4283SRichard Henderson g_assert_not_reached(); 1086633c4283SRichard Henderson } 1087fcf5ef2aSThomas Huth } else { 1088fcf5ef2aSThomas Huth dc->pc = dc->npc; 1089fcf5ef2aSThomas Huth } 1090fcf5ef2aSThomas Huth } 1091fcf5ef2aSThomas Huth 10920c2e96c1SRichard Henderson static void gen_op_next_insn(void) 1093fcf5ef2aSThomas Huth { 1094fcf5ef2aSThomas Huth tcg_gen_mov_tl(cpu_pc, cpu_npc); 1095fcf5ef2aSThomas Huth tcg_gen_addi_tl(cpu_npc, cpu_npc, 4); 1096fcf5ef2aSThomas Huth } 1097fcf5ef2aSThomas Huth 1098fcf5ef2aSThomas Huth static void gen_compare(DisasCompare *cmp, bool xcc, unsigned int cond, 1099fcf5ef2aSThomas Huth DisasContext *dc) 1100fcf5ef2aSThomas Huth { 1101fcf5ef2aSThomas Huth static int subcc_cond[16] = { 1102fcf5ef2aSThomas Huth TCG_COND_NEVER, 1103fcf5ef2aSThomas Huth TCG_COND_EQ, 1104fcf5ef2aSThomas Huth TCG_COND_LE, 1105fcf5ef2aSThomas Huth TCG_COND_LT, 1106fcf5ef2aSThomas Huth TCG_COND_LEU, 1107fcf5ef2aSThomas Huth TCG_COND_LTU, 1108fcf5ef2aSThomas Huth -1, /* neg */ 1109fcf5ef2aSThomas Huth -1, /* overflow */ 1110fcf5ef2aSThomas Huth TCG_COND_ALWAYS, 1111fcf5ef2aSThomas Huth TCG_COND_NE, 1112fcf5ef2aSThomas Huth TCG_COND_GT, 1113fcf5ef2aSThomas Huth TCG_COND_GE, 1114fcf5ef2aSThomas Huth TCG_COND_GTU, 1115fcf5ef2aSThomas Huth TCG_COND_GEU, 1116fcf5ef2aSThomas Huth -1, /* pos */ 1117fcf5ef2aSThomas Huth -1, /* no overflow */ 1118fcf5ef2aSThomas Huth }; 1119fcf5ef2aSThomas Huth 11202a1905c7SRichard Henderson TCGv t1, t2; 1121fcf5ef2aSThomas Huth 11222a1905c7SRichard Henderson cmp->is_bool = false; 1123fcf5ef2aSThomas Huth 1124fcf5ef2aSThomas Huth switch (dc->cc_op) { 1125*2a45b736SRichard Henderson case CC_OP_SUB: 1126*2a45b736SRichard Henderson switch (cond) { 1127*2a45b736SRichard Henderson case 6: /* neg */ 1128*2a45b736SRichard Henderson case 14: /* pos */ 1129*2a45b736SRichard Henderson cmp->cond = (cond == 6 ? TCG_COND_LT : TCG_COND_GE); 113000ab7e61SRichard Henderson cmp->c2 = tcg_constant_tl(0); 11312a1905c7SRichard Henderson if (TARGET_LONG_BITS == 32 || xcc) { 1132fcf5ef2aSThomas Huth cmp->c1 = cpu_cc_dst; 11332a1905c7SRichard Henderson } else { 11342a1905c7SRichard Henderson cmp->c1 = t1 = tcg_temp_new(); 11352a1905c7SRichard Henderson tcg_gen_ext32s_tl(t1, cpu_cc_dst); 11362a1905c7SRichard Henderson } 11372a1905c7SRichard Henderson return; 1138fcf5ef2aSThomas Huth 1139fcf5ef2aSThomas Huth case 7: /* overflow */ 1140fcf5ef2aSThomas Huth case 15: /* !overflow */ 11412a1905c7SRichard Henderson break; 1142fcf5ef2aSThomas Huth 1143fcf5ef2aSThomas Huth default: 1144fcf5ef2aSThomas Huth cmp->cond = subcc_cond[cond]; 11452a1905c7SRichard Henderson if (TARGET_LONG_BITS == 32 || xcc) { 1146fcf5ef2aSThomas Huth cmp->c1 = cpu_cc_src; 1147fcf5ef2aSThomas Huth cmp->c2 = cpu_cc_src2; 11482a1905c7SRichard Henderson } else { 11492a1905c7SRichard Henderson /* Note that sign-extension works for unsigned compares as 11502a1905c7SRichard Henderson long as both operands are sign-extended. */ 11512a1905c7SRichard Henderson cmp->c1 = t1 = tcg_temp_new(); 11522a1905c7SRichard Henderson tcg_gen_ext32s_tl(t1, cpu_cc_src); 11532a1905c7SRichard Henderson cmp->c2 = t2 = tcg_temp_new(); 11542a1905c7SRichard Henderson tcg_gen_ext32s_tl(t2, cpu_cc_src2); 11552a1905c7SRichard Henderson } 11562a1905c7SRichard Henderson return; 1157fcf5ef2aSThomas Huth } 1158fcf5ef2aSThomas Huth break; 1159fcf5ef2aSThomas Huth 1160fcf5ef2aSThomas Huth default: 1161ad75a51eSRichard Henderson gen_helper_compute_psr(tcg_env); 1162fcf5ef2aSThomas Huth dc->cc_op = CC_OP_FLAGS; 11632a1905c7SRichard Henderson break; 1164fcf5ef2aSThomas Huth 1165fcf5ef2aSThomas Huth case CC_OP_FLAGS: 1166fcf5ef2aSThomas Huth break; 1167fcf5ef2aSThomas Huth } 11682a1905c7SRichard Henderson 11692a1905c7SRichard Henderson cmp->c1 = t1 = tcg_temp_new(); 11702a1905c7SRichard Henderson cmp->c2 = tcg_constant_tl(0); 11712a1905c7SRichard Henderson 11722a1905c7SRichard Henderson switch (cond & 7) { 11732a1905c7SRichard Henderson case 0x0: /* never */ 11742a1905c7SRichard Henderson cmp->cond = TCG_COND_NEVER; 11752a1905c7SRichard Henderson cmp->c1 = cmp->c2; 1176fcf5ef2aSThomas Huth break; 11772a1905c7SRichard Henderson 11782a1905c7SRichard Henderson case 0x1: /* eq: Z */ 11792a1905c7SRichard Henderson cmp->cond = TCG_COND_EQ; 11802a1905c7SRichard Henderson if (TARGET_LONG_BITS == 32 || xcc) { 11812a1905c7SRichard Henderson tcg_gen_mov_tl(t1, cpu_cc_Z); 11822a1905c7SRichard Henderson } else { 11832a1905c7SRichard Henderson tcg_gen_ext32u_tl(t1, cpu_icc_Z); 11842a1905c7SRichard Henderson } 11852a1905c7SRichard Henderson break; 11862a1905c7SRichard Henderson 11872a1905c7SRichard Henderson case 0x2: /* le: Z | (N ^ V) */ 11882a1905c7SRichard Henderson /* 11892a1905c7SRichard Henderson * Simplify: 11902a1905c7SRichard Henderson * cc_Z || (N ^ V) < 0 NE 11912a1905c7SRichard Henderson * cc_Z && !((N ^ V) < 0) EQ 11922a1905c7SRichard Henderson * cc_Z & ~((N ^ V) >> TLB) EQ 11932a1905c7SRichard Henderson */ 11942a1905c7SRichard Henderson cmp->cond = TCG_COND_EQ; 11952a1905c7SRichard Henderson tcg_gen_xor_tl(t1, cpu_cc_N, cpu_cc_V); 11962a1905c7SRichard Henderson tcg_gen_sextract_tl(t1, t1, xcc ? 63 : 31, 1); 11972a1905c7SRichard Henderson tcg_gen_andc_tl(t1, xcc ? cpu_cc_Z : cpu_icc_Z, t1); 11982a1905c7SRichard Henderson if (TARGET_LONG_BITS == 64 && !xcc) { 11992a1905c7SRichard Henderson tcg_gen_ext32u_tl(t1, t1); 12002a1905c7SRichard Henderson } 12012a1905c7SRichard Henderson break; 12022a1905c7SRichard Henderson 12032a1905c7SRichard Henderson case 0x3: /* lt: N ^ V */ 12042a1905c7SRichard Henderson cmp->cond = TCG_COND_LT; 12052a1905c7SRichard Henderson tcg_gen_xor_tl(t1, cpu_cc_N, cpu_cc_V); 12062a1905c7SRichard Henderson if (TARGET_LONG_BITS == 64 && !xcc) { 12072a1905c7SRichard Henderson tcg_gen_ext32s_tl(t1, t1); 12082a1905c7SRichard Henderson } 12092a1905c7SRichard Henderson break; 12102a1905c7SRichard Henderson 12112a1905c7SRichard Henderson case 0x4: /* leu: Z | C */ 12122a1905c7SRichard Henderson /* 12132a1905c7SRichard Henderson * Simplify: 12142a1905c7SRichard Henderson * cc_Z == 0 || cc_C != 0 NE 12152a1905c7SRichard Henderson * cc_Z != 0 && cc_C == 0 EQ 12162a1905c7SRichard Henderson * cc_Z & (cc_C ? 0 : -1) EQ 12172a1905c7SRichard Henderson * cc_Z & (cc_C - 1) EQ 12182a1905c7SRichard Henderson */ 12192a1905c7SRichard Henderson cmp->cond = TCG_COND_EQ; 12202a1905c7SRichard Henderson if (TARGET_LONG_BITS == 32 || xcc) { 12212a1905c7SRichard Henderson tcg_gen_subi_tl(t1, cpu_cc_C, 1); 12222a1905c7SRichard Henderson tcg_gen_and_tl(t1, t1, cpu_cc_Z); 12232a1905c7SRichard Henderson } else { 12242a1905c7SRichard Henderson tcg_gen_extract_tl(t1, cpu_icc_C, 32, 1); 12252a1905c7SRichard Henderson tcg_gen_subi_tl(t1, t1, 1); 12262a1905c7SRichard Henderson tcg_gen_and_tl(t1, t1, cpu_icc_Z); 12272a1905c7SRichard Henderson tcg_gen_ext32u_tl(t1, t1); 12282a1905c7SRichard Henderson } 12292a1905c7SRichard Henderson break; 12302a1905c7SRichard Henderson 12312a1905c7SRichard Henderson case 0x5: /* ltu: C */ 12322a1905c7SRichard Henderson cmp->cond = TCG_COND_NE; 12332a1905c7SRichard Henderson cmp->is_bool = true; 12342a1905c7SRichard Henderson if (TARGET_LONG_BITS == 32 || xcc) { 12352a1905c7SRichard Henderson tcg_gen_mov_tl(t1, cpu_cc_C); 12362a1905c7SRichard Henderson } else { 12372a1905c7SRichard Henderson tcg_gen_extract_tl(t1, cpu_icc_C, 32, 1); 12382a1905c7SRichard Henderson } 12392a1905c7SRichard Henderson break; 12402a1905c7SRichard Henderson 12412a1905c7SRichard Henderson case 0x6: /* neg: N */ 12422a1905c7SRichard Henderson cmp->cond = TCG_COND_LT; 12432a1905c7SRichard Henderson if (TARGET_LONG_BITS == 32 || xcc) { 12442a1905c7SRichard Henderson tcg_gen_mov_tl(t1, cpu_cc_N); 12452a1905c7SRichard Henderson } else { 12462a1905c7SRichard Henderson tcg_gen_ext32s_tl(t1, cpu_cc_N); 12472a1905c7SRichard Henderson } 12482a1905c7SRichard Henderson break; 12492a1905c7SRichard Henderson 12502a1905c7SRichard Henderson case 0x7: /* vs: V */ 12512a1905c7SRichard Henderson cmp->cond = TCG_COND_LT; 12522a1905c7SRichard Henderson if (TARGET_LONG_BITS == 32 || xcc) { 12532a1905c7SRichard Henderson tcg_gen_mov_tl(t1, cpu_cc_V); 12542a1905c7SRichard Henderson } else { 12552a1905c7SRichard Henderson tcg_gen_ext32s_tl(t1, cpu_cc_V); 12562a1905c7SRichard Henderson } 12572a1905c7SRichard Henderson break; 12582a1905c7SRichard Henderson } 12592a1905c7SRichard Henderson if (cond & 8) { 12602a1905c7SRichard Henderson cmp->cond = tcg_invert_cond(cmp->cond); 12612a1905c7SRichard Henderson cmp->is_bool = false; 1262fcf5ef2aSThomas Huth } 1263fcf5ef2aSThomas Huth } 1264fcf5ef2aSThomas Huth 1265fcf5ef2aSThomas Huth static void gen_fcompare(DisasCompare *cmp, unsigned int cc, unsigned int cond) 1266fcf5ef2aSThomas Huth { 1267fcf5ef2aSThomas Huth unsigned int offset; 1268fcf5ef2aSThomas Huth TCGv r_dst; 1269fcf5ef2aSThomas Huth 1270fcf5ef2aSThomas Huth /* For now we still generate a straight boolean result. */ 1271fcf5ef2aSThomas Huth cmp->cond = TCG_COND_NE; 1272fcf5ef2aSThomas Huth cmp->is_bool = true; 1273fcf5ef2aSThomas Huth cmp->c1 = r_dst = tcg_temp_new(); 127400ab7e61SRichard Henderson cmp->c2 = tcg_constant_tl(0); 1275fcf5ef2aSThomas Huth 1276fcf5ef2aSThomas Huth switch (cc) { 1277fcf5ef2aSThomas Huth default: 1278fcf5ef2aSThomas Huth case 0x0: 1279fcf5ef2aSThomas Huth offset = 0; 1280fcf5ef2aSThomas Huth break; 1281fcf5ef2aSThomas Huth case 0x1: 1282fcf5ef2aSThomas Huth offset = 32 - 10; 1283fcf5ef2aSThomas Huth break; 1284fcf5ef2aSThomas Huth case 0x2: 1285fcf5ef2aSThomas Huth offset = 34 - 10; 1286fcf5ef2aSThomas Huth break; 1287fcf5ef2aSThomas Huth case 0x3: 1288fcf5ef2aSThomas Huth offset = 36 - 10; 1289fcf5ef2aSThomas Huth break; 1290fcf5ef2aSThomas Huth } 1291fcf5ef2aSThomas Huth 1292fcf5ef2aSThomas Huth switch (cond) { 1293fcf5ef2aSThomas Huth case 0x0: 1294fcf5ef2aSThomas Huth gen_op_eval_bn(r_dst); 1295fcf5ef2aSThomas Huth break; 1296fcf5ef2aSThomas Huth case 0x1: 1297fcf5ef2aSThomas Huth gen_op_eval_fbne(r_dst, cpu_fsr, offset); 1298fcf5ef2aSThomas Huth break; 1299fcf5ef2aSThomas Huth case 0x2: 1300fcf5ef2aSThomas Huth gen_op_eval_fblg(r_dst, cpu_fsr, offset); 1301fcf5ef2aSThomas Huth break; 1302fcf5ef2aSThomas Huth case 0x3: 1303fcf5ef2aSThomas Huth gen_op_eval_fbul(r_dst, cpu_fsr, offset); 1304fcf5ef2aSThomas Huth break; 1305fcf5ef2aSThomas Huth case 0x4: 1306fcf5ef2aSThomas Huth gen_op_eval_fbl(r_dst, cpu_fsr, offset); 1307fcf5ef2aSThomas Huth break; 1308fcf5ef2aSThomas Huth case 0x5: 1309fcf5ef2aSThomas Huth gen_op_eval_fbug(r_dst, cpu_fsr, offset); 1310fcf5ef2aSThomas Huth break; 1311fcf5ef2aSThomas Huth case 0x6: 1312fcf5ef2aSThomas Huth gen_op_eval_fbg(r_dst, cpu_fsr, offset); 1313fcf5ef2aSThomas Huth break; 1314fcf5ef2aSThomas Huth case 0x7: 1315fcf5ef2aSThomas Huth gen_op_eval_fbu(r_dst, cpu_fsr, offset); 1316fcf5ef2aSThomas Huth break; 1317fcf5ef2aSThomas Huth case 0x8: 1318fcf5ef2aSThomas Huth gen_op_eval_ba(r_dst); 1319fcf5ef2aSThomas Huth break; 1320fcf5ef2aSThomas Huth case 0x9: 1321fcf5ef2aSThomas Huth gen_op_eval_fbe(r_dst, cpu_fsr, offset); 1322fcf5ef2aSThomas Huth break; 1323fcf5ef2aSThomas Huth case 0xa: 1324fcf5ef2aSThomas Huth gen_op_eval_fbue(r_dst, cpu_fsr, offset); 1325fcf5ef2aSThomas Huth break; 1326fcf5ef2aSThomas Huth case 0xb: 1327fcf5ef2aSThomas Huth gen_op_eval_fbge(r_dst, cpu_fsr, offset); 1328fcf5ef2aSThomas Huth break; 1329fcf5ef2aSThomas Huth case 0xc: 1330fcf5ef2aSThomas Huth gen_op_eval_fbuge(r_dst, cpu_fsr, offset); 1331fcf5ef2aSThomas Huth break; 1332fcf5ef2aSThomas Huth case 0xd: 1333fcf5ef2aSThomas Huth gen_op_eval_fble(r_dst, cpu_fsr, offset); 1334fcf5ef2aSThomas Huth break; 1335fcf5ef2aSThomas Huth case 0xe: 1336fcf5ef2aSThomas Huth gen_op_eval_fbule(r_dst, cpu_fsr, offset); 1337fcf5ef2aSThomas Huth break; 1338fcf5ef2aSThomas Huth case 0xf: 1339fcf5ef2aSThomas Huth gen_op_eval_fbo(r_dst, cpu_fsr, offset); 1340fcf5ef2aSThomas Huth break; 1341fcf5ef2aSThomas Huth } 1342fcf5ef2aSThomas Huth } 1343fcf5ef2aSThomas Huth 1344fcf5ef2aSThomas Huth // Inverted logic 1345ab9ffe98SRichard Henderson static const TCGCond gen_tcg_cond_reg[8] = { 1346ab9ffe98SRichard Henderson TCG_COND_NEVER, /* reserved */ 1347fcf5ef2aSThomas Huth TCG_COND_NE, 1348fcf5ef2aSThomas Huth TCG_COND_GT, 1349fcf5ef2aSThomas Huth TCG_COND_GE, 1350ab9ffe98SRichard Henderson TCG_COND_NEVER, /* reserved */ 1351fcf5ef2aSThomas Huth TCG_COND_EQ, 1352fcf5ef2aSThomas Huth TCG_COND_LE, 1353fcf5ef2aSThomas Huth TCG_COND_LT, 1354fcf5ef2aSThomas Huth }; 1355fcf5ef2aSThomas Huth 1356fcf5ef2aSThomas Huth static void gen_compare_reg(DisasCompare *cmp, int cond, TCGv r_src) 1357fcf5ef2aSThomas Huth { 1358fcf5ef2aSThomas Huth cmp->cond = tcg_invert_cond(gen_tcg_cond_reg[cond]); 1359fcf5ef2aSThomas Huth cmp->is_bool = false; 1360fcf5ef2aSThomas Huth cmp->c1 = r_src; 136100ab7e61SRichard Henderson cmp->c2 = tcg_constant_tl(0); 1362fcf5ef2aSThomas Huth } 1363fcf5ef2aSThomas Huth 1364baf3dbf2SRichard Henderson static void gen_op_clear_ieee_excp_and_FTT(void) 1365baf3dbf2SRichard Henderson { 1366baf3dbf2SRichard Henderson tcg_gen_andi_tl(cpu_fsr, cpu_fsr, FSR_FTT_CEXC_NMASK); 1367baf3dbf2SRichard Henderson } 1368baf3dbf2SRichard Henderson 1369baf3dbf2SRichard Henderson static void gen_op_fmovs(TCGv_i32 dst, TCGv_i32 src) 1370baf3dbf2SRichard Henderson { 1371baf3dbf2SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 1372baf3dbf2SRichard Henderson tcg_gen_mov_i32(dst, src); 1373baf3dbf2SRichard Henderson } 1374baf3dbf2SRichard Henderson 1375baf3dbf2SRichard Henderson static void gen_op_fnegs(TCGv_i32 dst, TCGv_i32 src) 1376baf3dbf2SRichard Henderson { 1377baf3dbf2SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 1378baf3dbf2SRichard Henderson gen_helper_fnegs(dst, src); 1379baf3dbf2SRichard Henderson } 1380baf3dbf2SRichard Henderson 1381baf3dbf2SRichard Henderson static void gen_op_fabss(TCGv_i32 dst, TCGv_i32 src) 1382baf3dbf2SRichard Henderson { 1383baf3dbf2SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 1384baf3dbf2SRichard Henderson gen_helper_fabss(dst, src); 1385baf3dbf2SRichard Henderson } 1386baf3dbf2SRichard Henderson 1387c6d83e4fSRichard Henderson static void gen_op_fmovd(TCGv_i64 dst, TCGv_i64 src) 1388c6d83e4fSRichard Henderson { 1389c6d83e4fSRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 1390c6d83e4fSRichard Henderson tcg_gen_mov_i64(dst, src); 1391c6d83e4fSRichard Henderson } 1392c6d83e4fSRichard Henderson 1393c6d83e4fSRichard Henderson static void gen_op_fnegd(TCGv_i64 dst, TCGv_i64 src) 1394c6d83e4fSRichard Henderson { 1395c6d83e4fSRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 1396c6d83e4fSRichard Henderson gen_helper_fnegd(dst, src); 1397c6d83e4fSRichard Henderson } 1398c6d83e4fSRichard Henderson 1399c6d83e4fSRichard Henderson static void gen_op_fabsd(TCGv_i64 dst, TCGv_i64 src) 1400c6d83e4fSRichard Henderson { 1401c6d83e4fSRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 1402c6d83e4fSRichard Henderson gen_helper_fabsd(dst, src); 1403c6d83e4fSRichard Henderson } 1404c6d83e4fSRichard Henderson 1405fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64 14060c2e96c1SRichard Henderson static void gen_op_fcmps(int fccno, TCGv_i32 r_rs1, TCGv_i32 r_rs2) 1407fcf5ef2aSThomas Huth { 1408fcf5ef2aSThomas Huth switch (fccno) { 1409fcf5ef2aSThomas Huth case 0: 1410ad75a51eSRichard Henderson gen_helper_fcmps(cpu_fsr, tcg_env, r_rs1, r_rs2); 1411fcf5ef2aSThomas Huth break; 1412fcf5ef2aSThomas Huth case 1: 1413ad75a51eSRichard Henderson gen_helper_fcmps_fcc1(cpu_fsr, tcg_env, r_rs1, r_rs2); 1414fcf5ef2aSThomas Huth break; 1415fcf5ef2aSThomas Huth case 2: 1416ad75a51eSRichard Henderson gen_helper_fcmps_fcc2(cpu_fsr, tcg_env, r_rs1, r_rs2); 1417fcf5ef2aSThomas Huth break; 1418fcf5ef2aSThomas Huth case 3: 1419ad75a51eSRichard Henderson gen_helper_fcmps_fcc3(cpu_fsr, tcg_env, r_rs1, r_rs2); 1420fcf5ef2aSThomas Huth break; 1421fcf5ef2aSThomas Huth } 1422fcf5ef2aSThomas Huth } 1423fcf5ef2aSThomas Huth 14240c2e96c1SRichard Henderson static void gen_op_fcmpd(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2) 1425fcf5ef2aSThomas Huth { 1426fcf5ef2aSThomas Huth switch (fccno) { 1427fcf5ef2aSThomas Huth case 0: 1428ad75a51eSRichard Henderson gen_helper_fcmpd(cpu_fsr, tcg_env, r_rs1, r_rs2); 1429fcf5ef2aSThomas Huth break; 1430fcf5ef2aSThomas Huth case 1: 1431ad75a51eSRichard Henderson gen_helper_fcmpd_fcc1(cpu_fsr, tcg_env, r_rs1, r_rs2); 1432fcf5ef2aSThomas Huth break; 1433fcf5ef2aSThomas Huth case 2: 1434ad75a51eSRichard Henderson gen_helper_fcmpd_fcc2(cpu_fsr, tcg_env, r_rs1, r_rs2); 1435fcf5ef2aSThomas Huth break; 1436fcf5ef2aSThomas Huth case 3: 1437ad75a51eSRichard Henderson gen_helper_fcmpd_fcc3(cpu_fsr, tcg_env, r_rs1, r_rs2); 1438fcf5ef2aSThomas Huth break; 1439fcf5ef2aSThomas Huth } 1440fcf5ef2aSThomas Huth } 1441fcf5ef2aSThomas Huth 14420c2e96c1SRichard Henderson static void gen_op_fcmpq(int fccno) 1443fcf5ef2aSThomas Huth { 1444fcf5ef2aSThomas Huth switch (fccno) { 1445fcf5ef2aSThomas Huth case 0: 1446ad75a51eSRichard Henderson gen_helper_fcmpq(cpu_fsr, tcg_env); 1447fcf5ef2aSThomas Huth break; 1448fcf5ef2aSThomas Huth case 1: 1449ad75a51eSRichard Henderson gen_helper_fcmpq_fcc1(cpu_fsr, tcg_env); 1450fcf5ef2aSThomas Huth break; 1451fcf5ef2aSThomas Huth case 2: 1452ad75a51eSRichard Henderson gen_helper_fcmpq_fcc2(cpu_fsr, tcg_env); 1453fcf5ef2aSThomas Huth break; 1454fcf5ef2aSThomas Huth case 3: 1455ad75a51eSRichard Henderson gen_helper_fcmpq_fcc3(cpu_fsr, tcg_env); 1456fcf5ef2aSThomas Huth break; 1457fcf5ef2aSThomas Huth } 1458fcf5ef2aSThomas Huth } 1459fcf5ef2aSThomas Huth 14600c2e96c1SRichard Henderson static void gen_op_fcmpes(int fccno, TCGv_i32 r_rs1, TCGv_i32 r_rs2) 1461fcf5ef2aSThomas Huth { 1462fcf5ef2aSThomas Huth switch (fccno) { 1463fcf5ef2aSThomas Huth case 0: 1464ad75a51eSRichard Henderson gen_helper_fcmpes(cpu_fsr, tcg_env, r_rs1, r_rs2); 1465fcf5ef2aSThomas Huth break; 1466fcf5ef2aSThomas Huth case 1: 1467ad75a51eSRichard Henderson gen_helper_fcmpes_fcc1(cpu_fsr, tcg_env, r_rs1, r_rs2); 1468fcf5ef2aSThomas Huth break; 1469fcf5ef2aSThomas Huth case 2: 1470ad75a51eSRichard Henderson gen_helper_fcmpes_fcc2(cpu_fsr, tcg_env, r_rs1, r_rs2); 1471fcf5ef2aSThomas Huth break; 1472fcf5ef2aSThomas Huth case 3: 1473ad75a51eSRichard Henderson gen_helper_fcmpes_fcc3(cpu_fsr, tcg_env, r_rs1, r_rs2); 1474fcf5ef2aSThomas Huth break; 1475fcf5ef2aSThomas Huth } 1476fcf5ef2aSThomas Huth } 1477fcf5ef2aSThomas Huth 14780c2e96c1SRichard Henderson static void gen_op_fcmped(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2) 1479fcf5ef2aSThomas Huth { 1480fcf5ef2aSThomas Huth switch (fccno) { 1481fcf5ef2aSThomas Huth case 0: 1482ad75a51eSRichard Henderson gen_helper_fcmped(cpu_fsr, tcg_env, r_rs1, r_rs2); 1483fcf5ef2aSThomas Huth break; 1484fcf5ef2aSThomas Huth case 1: 1485ad75a51eSRichard Henderson gen_helper_fcmped_fcc1(cpu_fsr, tcg_env, r_rs1, r_rs2); 1486fcf5ef2aSThomas Huth break; 1487fcf5ef2aSThomas Huth case 2: 1488ad75a51eSRichard Henderson gen_helper_fcmped_fcc2(cpu_fsr, tcg_env, r_rs1, r_rs2); 1489fcf5ef2aSThomas Huth break; 1490fcf5ef2aSThomas Huth case 3: 1491ad75a51eSRichard Henderson gen_helper_fcmped_fcc3(cpu_fsr, tcg_env, r_rs1, r_rs2); 1492fcf5ef2aSThomas Huth break; 1493fcf5ef2aSThomas Huth } 1494fcf5ef2aSThomas Huth } 1495fcf5ef2aSThomas Huth 14960c2e96c1SRichard Henderson static void gen_op_fcmpeq(int fccno) 1497fcf5ef2aSThomas Huth { 1498fcf5ef2aSThomas Huth switch (fccno) { 1499fcf5ef2aSThomas Huth case 0: 1500ad75a51eSRichard Henderson gen_helper_fcmpeq(cpu_fsr, tcg_env); 1501fcf5ef2aSThomas Huth break; 1502fcf5ef2aSThomas Huth case 1: 1503ad75a51eSRichard Henderson gen_helper_fcmpeq_fcc1(cpu_fsr, tcg_env); 1504fcf5ef2aSThomas Huth break; 1505fcf5ef2aSThomas Huth case 2: 1506ad75a51eSRichard Henderson gen_helper_fcmpeq_fcc2(cpu_fsr, tcg_env); 1507fcf5ef2aSThomas Huth break; 1508fcf5ef2aSThomas Huth case 3: 1509ad75a51eSRichard Henderson gen_helper_fcmpeq_fcc3(cpu_fsr, tcg_env); 1510fcf5ef2aSThomas Huth break; 1511fcf5ef2aSThomas Huth } 1512fcf5ef2aSThomas Huth } 1513fcf5ef2aSThomas Huth 1514fcf5ef2aSThomas Huth #else 1515fcf5ef2aSThomas Huth 15160c2e96c1SRichard Henderson static void gen_op_fcmps(int fccno, TCGv r_rs1, TCGv r_rs2) 1517fcf5ef2aSThomas Huth { 1518ad75a51eSRichard Henderson gen_helper_fcmps(cpu_fsr, tcg_env, r_rs1, r_rs2); 1519fcf5ef2aSThomas Huth } 1520fcf5ef2aSThomas Huth 15210c2e96c1SRichard Henderson static void gen_op_fcmpd(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2) 1522fcf5ef2aSThomas Huth { 1523ad75a51eSRichard Henderson gen_helper_fcmpd(cpu_fsr, tcg_env, r_rs1, r_rs2); 1524fcf5ef2aSThomas Huth } 1525fcf5ef2aSThomas Huth 15260c2e96c1SRichard Henderson static void gen_op_fcmpq(int fccno) 1527fcf5ef2aSThomas Huth { 1528ad75a51eSRichard Henderson gen_helper_fcmpq(cpu_fsr, tcg_env); 1529fcf5ef2aSThomas Huth } 1530fcf5ef2aSThomas Huth 15310c2e96c1SRichard Henderson static void gen_op_fcmpes(int fccno, TCGv r_rs1, TCGv r_rs2) 1532fcf5ef2aSThomas Huth { 1533ad75a51eSRichard Henderson gen_helper_fcmpes(cpu_fsr, tcg_env, r_rs1, r_rs2); 1534fcf5ef2aSThomas Huth } 1535fcf5ef2aSThomas Huth 15360c2e96c1SRichard Henderson static void gen_op_fcmped(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2) 1537fcf5ef2aSThomas Huth { 1538ad75a51eSRichard Henderson gen_helper_fcmped(cpu_fsr, tcg_env, r_rs1, r_rs2); 1539fcf5ef2aSThomas Huth } 1540fcf5ef2aSThomas Huth 15410c2e96c1SRichard Henderson static void gen_op_fcmpeq(int fccno) 1542fcf5ef2aSThomas Huth { 1543ad75a51eSRichard Henderson gen_helper_fcmpeq(cpu_fsr, tcg_env); 1544fcf5ef2aSThomas Huth } 1545fcf5ef2aSThomas Huth #endif 1546fcf5ef2aSThomas Huth 1547fcf5ef2aSThomas Huth static void gen_op_fpexception_im(DisasContext *dc, int fsr_flags) 1548fcf5ef2aSThomas Huth { 1549fcf5ef2aSThomas Huth tcg_gen_andi_tl(cpu_fsr, cpu_fsr, FSR_FTT_NMASK); 1550fcf5ef2aSThomas Huth tcg_gen_ori_tl(cpu_fsr, cpu_fsr, fsr_flags); 1551fcf5ef2aSThomas Huth gen_exception(dc, TT_FP_EXCP); 1552fcf5ef2aSThomas Huth } 1553fcf5ef2aSThomas Huth 1554fcf5ef2aSThomas Huth static int gen_trap_ifnofpu(DisasContext *dc) 1555fcf5ef2aSThomas Huth { 1556fcf5ef2aSThomas Huth #if !defined(CONFIG_USER_ONLY) 1557fcf5ef2aSThomas Huth if (!dc->fpu_enabled) { 1558fcf5ef2aSThomas Huth gen_exception(dc, TT_NFPU_INSN); 1559fcf5ef2aSThomas Huth return 1; 1560fcf5ef2aSThomas Huth } 1561fcf5ef2aSThomas Huth #endif 1562fcf5ef2aSThomas Huth return 0; 1563fcf5ef2aSThomas Huth } 1564fcf5ef2aSThomas Huth 1565fcf5ef2aSThomas Huth /* asi moves */ 1566fcf5ef2aSThomas Huth typedef enum { 1567fcf5ef2aSThomas Huth GET_ASI_HELPER, 1568fcf5ef2aSThomas Huth GET_ASI_EXCP, 1569fcf5ef2aSThomas Huth GET_ASI_DIRECT, 1570fcf5ef2aSThomas Huth GET_ASI_DTWINX, 1571fcf5ef2aSThomas Huth GET_ASI_BLOCK, 1572fcf5ef2aSThomas Huth GET_ASI_SHORT, 1573fcf5ef2aSThomas Huth GET_ASI_BCOPY, 1574fcf5ef2aSThomas Huth GET_ASI_BFILL, 1575fcf5ef2aSThomas Huth } ASIType; 1576fcf5ef2aSThomas Huth 1577fcf5ef2aSThomas Huth typedef struct { 1578fcf5ef2aSThomas Huth ASIType type; 1579fcf5ef2aSThomas Huth int asi; 1580fcf5ef2aSThomas Huth int mem_idx; 158114776ab5STony Nguyen MemOp memop; 1582fcf5ef2aSThomas Huth } DisasASI; 1583fcf5ef2aSThomas Huth 1584811cc0b0SRichard Henderson /* 1585811cc0b0SRichard Henderson * Build DisasASI. 1586811cc0b0SRichard Henderson * For asi == -1, treat as non-asi. 1587811cc0b0SRichard Henderson * For ask == -2, treat as immediate offset (v8 error, v9 %asi). 1588811cc0b0SRichard Henderson */ 1589811cc0b0SRichard Henderson static DisasASI resolve_asi(DisasContext *dc, int asi, MemOp memop) 1590fcf5ef2aSThomas Huth { 1591fcf5ef2aSThomas Huth ASIType type = GET_ASI_HELPER; 1592fcf5ef2aSThomas Huth int mem_idx = dc->mem_idx; 1593fcf5ef2aSThomas Huth 1594811cc0b0SRichard Henderson if (asi == -1) { 1595811cc0b0SRichard Henderson /* Artificial "non-asi" case. */ 1596811cc0b0SRichard Henderson type = GET_ASI_DIRECT; 1597811cc0b0SRichard Henderson goto done; 1598811cc0b0SRichard Henderson } 1599811cc0b0SRichard Henderson 1600fcf5ef2aSThomas Huth #ifndef TARGET_SPARC64 1601fcf5ef2aSThomas Huth /* Before v9, all asis are immediate and privileged. */ 1602811cc0b0SRichard Henderson if (asi < 0) { 1603fcf5ef2aSThomas Huth gen_exception(dc, TT_ILL_INSN); 1604fcf5ef2aSThomas Huth type = GET_ASI_EXCP; 1605fcf5ef2aSThomas Huth } else if (supervisor(dc) 1606fcf5ef2aSThomas Huth /* Note that LEON accepts ASI_USERDATA in user mode, for 1607fcf5ef2aSThomas Huth use with CASA. Also note that previous versions of 1608fcf5ef2aSThomas Huth QEMU allowed (and old versions of gcc emitted) ASI_P 1609fcf5ef2aSThomas Huth for LEON, which is incorrect. */ 1610fcf5ef2aSThomas Huth || (asi == ASI_USERDATA 1611fcf5ef2aSThomas Huth && (dc->def->features & CPU_FEATURE_CASA))) { 1612fcf5ef2aSThomas Huth switch (asi) { 1613fcf5ef2aSThomas Huth case ASI_USERDATA: /* User data access */ 1614fcf5ef2aSThomas Huth mem_idx = MMU_USER_IDX; 1615fcf5ef2aSThomas Huth type = GET_ASI_DIRECT; 1616fcf5ef2aSThomas Huth break; 1617fcf5ef2aSThomas Huth case ASI_KERNELDATA: /* Supervisor data access */ 1618fcf5ef2aSThomas Huth mem_idx = MMU_KERNEL_IDX; 1619fcf5ef2aSThomas Huth type = GET_ASI_DIRECT; 1620fcf5ef2aSThomas Huth break; 1621fcf5ef2aSThomas Huth case ASI_M_BYPASS: /* MMU passthrough */ 1622fcf5ef2aSThomas Huth case ASI_LEON_BYPASS: /* LEON MMU passthrough */ 1623fcf5ef2aSThomas Huth mem_idx = MMU_PHYS_IDX; 1624fcf5ef2aSThomas Huth type = GET_ASI_DIRECT; 1625fcf5ef2aSThomas Huth break; 1626fcf5ef2aSThomas Huth case ASI_M_BCOPY: /* Block copy, sta access */ 1627fcf5ef2aSThomas Huth mem_idx = MMU_KERNEL_IDX; 1628fcf5ef2aSThomas Huth type = GET_ASI_BCOPY; 1629fcf5ef2aSThomas Huth break; 1630fcf5ef2aSThomas Huth case ASI_M_BFILL: /* Block fill, stda access */ 1631fcf5ef2aSThomas Huth mem_idx = MMU_KERNEL_IDX; 1632fcf5ef2aSThomas Huth type = GET_ASI_BFILL; 1633fcf5ef2aSThomas Huth break; 1634fcf5ef2aSThomas Huth } 16356e10f37cSKONRAD Frederic 16366e10f37cSKONRAD Frederic /* MMU_PHYS_IDX is used when the MMU is disabled to passthrough the 16376e10f37cSKONRAD Frederic * permissions check in get_physical_address(..). 16386e10f37cSKONRAD Frederic */ 16396e10f37cSKONRAD Frederic mem_idx = (dc->mem_idx == MMU_PHYS_IDX) ? MMU_PHYS_IDX : mem_idx; 1640fcf5ef2aSThomas Huth } else { 1641fcf5ef2aSThomas Huth gen_exception(dc, TT_PRIV_INSN); 1642fcf5ef2aSThomas Huth type = GET_ASI_EXCP; 1643fcf5ef2aSThomas Huth } 1644fcf5ef2aSThomas Huth #else 1645811cc0b0SRichard Henderson if (asi < 0) { 1646fcf5ef2aSThomas Huth asi = dc->asi; 1647fcf5ef2aSThomas Huth } 1648fcf5ef2aSThomas Huth /* With v9, all asis below 0x80 are privileged. */ 1649fcf5ef2aSThomas Huth /* ??? We ought to check cpu_has_hypervisor, but we didn't copy 1650fcf5ef2aSThomas Huth down that bit into DisasContext. For the moment that's ok, 1651fcf5ef2aSThomas Huth since the direct implementations below doesn't have any ASIs 1652fcf5ef2aSThomas Huth in the restricted [0x30, 0x7f] range, and the check will be 1653fcf5ef2aSThomas Huth done properly in the helper. */ 1654fcf5ef2aSThomas Huth if (!supervisor(dc) && asi < 0x80) { 1655fcf5ef2aSThomas Huth gen_exception(dc, TT_PRIV_ACT); 1656fcf5ef2aSThomas Huth type = GET_ASI_EXCP; 1657fcf5ef2aSThomas Huth } else { 1658fcf5ef2aSThomas Huth switch (asi) { 1659fcf5ef2aSThomas Huth case ASI_REAL: /* Bypass */ 1660fcf5ef2aSThomas Huth case ASI_REAL_IO: /* Bypass, non-cacheable */ 1661fcf5ef2aSThomas Huth case ASI_REAL_L: /* Bypass LE */ 1662fcf5ef2aSThomas Huth case ASI_REAL_IO_L: /* Bypass, non-cacheable LE */ 1663fcf5ef2aSThomas Huth case ASI_TWINX_REAL: /* Real address, twinx */ 1664fcf5ef2aSThomas Huth case ASI_TWINX_REAL_L: /* Real address, twinx, LE */ 1665fcf5ef2aSThomas Huth case ASI_QUAD_LDD_PHYS: 1666fcf5ef2aSThomas Huth case ASI_QUAD_LDD_PHYS_L: 1667fcf5ef2aSThomas Huth mem_idx = MMU_PHYS_IDX; 1668fcf5ef2aSThomas Huth break; 1669fcf5ef2aSThomas Huth case ASI_N: /* Nucleus */ 1670fcf5ef2aSThomas Huth case ASI_NL: /* Nucleus LE */ 1671fcf5ef2aSThomas Huth case ASI_TWINX_N: 1672fcf5ef2aSThomas Huth case ASI_TWINX_NL: 1673fcf5ef2aSThomas Huth case ASI_NUCLEUS_QUAD_LDD: 1674fcf5ef2aSThomas Huth case ASI_NUCLEUS_QUAD_LDD_L: 16759a10756dSArtyom Tarasenko if (hypervisor(dc)) { 167684f8f587SArtyom Tarasenko mem_idx = MMU_PHYS_IDX; 16779a10756dSArtyom Tarasenko } else { 1678fcf5ef2aSThomas Huth mem_idx = MMU_NUCLEUS_IDX; 16799a10756dSArtyom Tarasenko } 1680fcf5ef2aSThomas Huth break; 1681fcf5ef2aSThomas Huth case ASI_AIUP: /* As if user primary */ 1682fcf5ef2aSThomas Huth case ASI_AIUPL: /* As if user primary LE */ 1683fcf5ef2aSThomas Huth case ASI_TWINX_AIUP: 1684fcf5ef2aSThomas Huth case ASI_TWINX_AIUP_L: 1685fcf5ef2aSThomas Huth case ASI_BLK_AIUP_4V: 1686fcf5ef2aSThomas Huth case ASI_BLK_AIUP_L_4V: 1687fcf5ef2aSThomas Huth case ASI_BLK_AIUP: 1688fcf5ef2aSThomas Huth case ASI_BLK_AIUPL: 1689fcf5ef2aSThomas Huth mem_idx = MMU_USER_IDX; 1690fcf5ef2aSThomas Huth break; 1691fcf5ef2aSThomas Huth case ASI_AIUS: /* As if user secondary */ 1692fcf5ef2aSThomas Huth case ASI_AIUSL: /* As if user secondary LE */ 1693fcf5ef2aSThomas Huth case ASI_TWINX_AIUS: 1694fcf5ef2aSThomas Huth case ASI_TWINX_AIUS_L: 1695fcf5ef2aSThomas Huth case ASI_BLK_AIUS_4V: 1696fcf5ef2aSThomas Huth case ASI_BLK_AIUS_L_4V: 1697fcf5ef2aSThomas Huth case ASI_BLK_AIUS: 1698fcf5ef2aSThomas Huth case ASI_BLK_AIUSL: 1699fcf5ef2aSThomas Huth mem_idx = MMU_USER_SECONDARY_IDX; 1700fcf5ef2aSThomas Huth break; 1701fcf5ef2aSThomas Huth case ASI_S: /* Secondary */ 1702fcf5ef2aSThomas Huth case ASI_SL: /* Secondary LE */ 1703fcf5ef2aSThomas Huth case ASI_TWINX_S: 1704fcf5ef2aSThomas Huth case ASI_TWINX_SL: 1705fcf5ef2aSThomas Huth case ASI_BLK_COMMIT_S: 1706fcf5ef2aSThomas Huth case ASI_BLK_S: 1707fcf5ef2aSThomas Huth case ASI_BLK_SL: 1708fcf5ef2aSThomas Huth case ASI_FL8_S: 1709fcf5ef2aSThomas Huth case ASI_FL8_SL: 1710fcf5ef2aSThomas Huth case ASI_FL16_S: 1711fcf5ef2aSThomas Huth case ASI_FL16_SL: 1712fcf5ef2aSThomas Huth if (mem_idx == MMU_USER_IDX) { 1713fcf5ef2aSThomas Huth mem_idx = MMU_USER_SECONDARY_IDX; 1714fcf5ef2aSThomas Huth } else if (mem_idx == MMU_KERNEL_IDX) { 1715fcf5ef2aSThomas Huth mem_idx = MMU_KERNEL_SECONDARY_IDX; 1716fcf5ef2aSThomas Huth } 1717fcf5ef2aSThomas Huth break; 1718fcf5ef2aSThomas Huth case ASI_P: /* Primary */ 1719fcf5ef2aSThomas Huth case ASI_PL: /* Primary LE */ 1720fcf5ef2aSThomas Huth case ASI_TWINX_P: 1721fcf5ef2aSThomas Huth case ASI_TWINX_PL: 1722fcf5ef2aSThomas Huth case ASI_BLK_COMMIT_P: 1723fcf5ef2aSThomas Huth case ASI_BLK_P: 1724fcf5ef2aSThomas Huth case ASI_BLK_PL: 1725fcf5ef2aSThomas Huth case ASI_FL8_P: 1726fcf5ef2aSThomas Huth case ASI_FL8_PL: 1727fcf5ef2aSThomas Huth case ASI_FL16_P: 1728fcf5ef2aSThomas Huth case ASI_FL16_PL: 1729fcf5ef2aSThomas Huth break; 1730fcf5ef2aSThomas Huth } 1731fcf5ef2aSThomas Huth switch (asi) { 1732fcf5ef2aSThomas Huth case ASI_REAL: 1733fcf5ef2aSThomas Huth case ASI_REAL_IO: 1734fcf5ef2aSThomas Huth case ASI_REAL_L: 1735fcf5ef2aSThomas Huth case ASI_REAL_IO_L: 1736fcf5ef2aSThomas Huth case ASI_N: 1737fcf5ef2aSThomas Huth case ASI_NL: 1738fcf5ef2aSThomas Huth case ASI_AIUP: 1739fcf5ef2aSThomas Huth case ASI_AIUPL: 1740fcf5ef2aSThomas Huth case ASI_AIUS: 1741fcf5ef2aSThomas Huth case ASI_AIUSL: 1742fcf5ef2aSThomas Huth case ASI_S: 1743fcf5ef2aSThomas Huth case ASI_SL: 1744fcf5ef2aSThomas Huth case ASI_P: 1745fcf5ef2aSThomas Huth case ASI_PL: 1746fcf5ef2aSThomas Huth type = GET_ASI_DIRECT; 1747fcf5ef2aSThomas Huth break; 1748fcf5ef2aSThomas Huth case ASI_TWINX_REAL: 1749fcf5ef2aSThomas Huth case ASI_TWINX_REAL_L: 1750fcf5ef2aSThomas Huth case ASI_TWINX_N: 1751fcf5ef2aSThomas Huth case ASI_TWINX_NL: 1752fcf5ef2aSThomas Huth case ASI_TWINX_AIUP: 1753fcf5ef2aSThomas Huth case ASI_TWINX_AIUP_L: 1754fcf5ef2aSThomas Huth case ASI_TWINX_AIUS: 1755fcf5ef2aSThomas Huth case ASI_TWINX_AIUS_L: 1756fcf5ef2aSThomas Huth case ASI_TWINX_P: 1757fcf5ef2aSThomas Huth case ASI_TWINX_PL: 1758fcf5ef2aSThomas Huth case ASI_TWINX_S: 1759fcf5ef2aSThomas Huth case ASI_TWINX_SL: 1760fcf5ef2aSThomas Huth case ASI_QUAD_LDD_PHYS: 1761fcf5ef2aSThomas Huth case ASI_QUAD_LDD_PHYS_L: 1762fcf5ef2aSThomas Huth case ASI_NUCLEUS_QUAD_LDD: 1763fcf5ef2aSThomas Huth case ASI_NUCLEUS_QUAD_LDD_L: 1764fcf5ef2aSThomas Huth type = GET_ASI_DTWINX; 1765fcf5ef2aSThomas Huth break; 1766fcf5ef2aSThomas Huth case ASI_BLK_COMMIT_P: 1767fcf5ef2aSThomas Huth case ASI_BLK_COMMIT_S: 1768fcf5ef2aSThomas Huth case ASI_BLK_AIUP_4V: 1769fcf5ef2aSThomas Huth case ASI_BLK_AIUP_L_4V: 1770fcf5ef2aSThomas Huth case ASI_BLK_AIUP: 1771fcf5ef2aSThomas Huth case ASI_BLK_AIUPL: 1772fcf5ef2aSThomas Huth case ASI_BLK_AIUS_4V: 1773fcf5ef2aSThomas Huth case ASI_BLK_AIUS_L_4V: 1774fcf5ef2aSThomas Huth case ASI_BLK_AIUS: 1775fcf5ef2aSThomas Huth case ASI_BLK_AIUSL: 1776fcf5ef2aSThomas Huth case ASI_BLK_S: 1777fcf5ef2aSThomas Huth case ASI_BLK_SL: 1778fcf5ef2aSThomas Huth case ASI_BLK_P: 1779fcf5ef2aSThomas Huth case ASI_BLK_PL: 1780fcf5ef2aSThomas Huth type = GET_ASI_BLOCK; 1781fcf5ef2aSThomas Huth break; 1782fcf5ef2aSThomas Huth case ASI_FL8_S: 1783fcf5ef2aSThomas Huth case ASI_FL8_SL: 1784fcf5ef2aSThomas Huth case ASI_FL8_P: 1785fcf5ef2aSThomas Huth case ASI_FL8_PL: 1786fcf5ef2aSThomas Huth memop = MO_UB; 1787fcf5ef2aSThomas Huth type = GET_ASI_SHORT; 1788fcf5ef2aSThomas Huth break; 1789fcf5ef2aSThomas Huth case ASI_FL16_S: 1790fcf5ef2aSThomas Huth case ASI_FL16_SL: 1791fcf5ef2aSThomas Huth case ASI_FL16_P: 1792fcf5ef2aSThomas Huth case ASI_FL16_PL: 1793fcf5ef2aSThomas Huth memop = MO_TEUW; 1794fcf5ef2aSThomas Huth type = GET_ASI_SHORT; 1795fcf5ef2aSThomas Huth break; 1796fcf5ef2aSThomas Huth } 1797fcf5ef2aSThomas Huth /* The little-endian asis all have bit 3 set. */ 1798fcf5ef2aSThomas Huth if (asi & 8) { 1799fcf5ef2aSThomas Huth memop ^= MO_BSWAP; 1800fcf5ef2aSThomas Huth } 1801fcf5ef2aSThomas Huth } 1802fcf5ef2aSThomas Huth #endif 1803fcf5ef2aSThomas Huth 1804811cc0b0SRichard Henderson done: 1805fcf5ef2aSThomas Huth return (DisasASI){ type, asi, mem_idx, memop }; 1806fcf5ef2aSThomas Huth } 1807fcf5ef2aSThomas Huth 1808a76779eeSRichard Henderson #if defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64) 1809a76779eeSRichard Henderson static void gen_helper_ld_asi(TCGv_i64 r, TCGv_env e, TCGv a, 1810a76779eeSRichard Henderson TCGv_i32 asi, TCGv_i32 mop) 1811a76779eeSRichard Henderson { 1812a76779eeSRichard Henderson g_assert_not_reached(); 1813a76779eeSRichard Henderson } 1814a76779eeSRichard Henderson 1815a76779eeSRichard Henderson static void gen_helper_st_asi(TCGv_env e, TCGv a, TCGv_i64 r, 1816a76779eeSRichard Henderson TCGv_i32 asi, TCGv_i32 mop) 1817a76779eeSRichard Henderson { 1818a76779eeSRichard Henderson g_assert_not_reached(); 1819a76779eeSRichard Henderson } 1820a76779eeSRichard Henderson #endif 1821a76779eeSRichard Henderson 182242071fc1SRichard Henderson static void gen_ld_asi(DisasContext *dc, DisasASI *da, TCGv dst, TCGv addr) 1823fcf5ef2aSThomas Huth { 1824c03a0fd1SRichard Henderson switch (da->type) { 1825fcf5ef2aSThomas Huth case GET_ASI_EXCP: 1826fcf5ef2aSThomas Huth break; 1827fcf5ef2aSThomas Huth case GET_ASI_DTWINX: /* Reserved for ldda. */ 1828fcf5ef2aSThomas Huth gen_exception(dc, TT_ILL_INSN); 1829fcf5ef2aSThomas Huth break; 1830fcf5ef2aSThomas Huth case GET_ASI_DIRECT: 1831c03a0fd1SRichard Henderson tcg_gen_qemu_ld_tl(dst, addr, da->mem_idx, da->memop | MO_ALIGN); 1832fcf5ef2aSThomas Huth break; 1833fcf5ef2aSThomas Huth default: 1834fcf5ef2aSThomas Huth { 1835c03a0fd1SRichard Henderson TCGv_i32 r_asi = tcg_constant_i32(da->asi); 1836c03a0fd1SRichard Henderson TCGv_i32 r_mop = tcg_constant_i32(da->memop | MO_ALIGN); 1837fcf5ef2aSThomas Huth 1838fcf5ef2aSThomas Huth save_state(dc); 1839fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64 1840ad75a51eSRichard Henderson gen_helper_ld_asi(dst, tcg_env, addr, r_asi, r_mop); 1841fcf5ef2aSThomas Huth #else 1842fcf5ef2aSThomas Huth { 1843fcf5ef2aSThomas Huth TCGv_i64 t64 = tcg_temp_new_i64(); 1844ad75a51eSRichard Henderson gen_helper_ld_asi(t64, tcg_env, addr, r_asi, r_mop); 1845fcf5ef2aSThomas Huth tcg_gen_trunc_i64_tl(dst, t64); 1846fcf5ef2aSThomas Huth } 1847fcf5ef2aSThomas Huth #endif 1848fcf5ef2aSThomas Huth } 1849fcf5ef2aSThomas Huth break; 1850fcf5ef2aSThomas Huth } 1851fcf5ef2aSThomas Huth } 1852fcf5ef2aSThomas Huth 185342071fc1SRichard Henderson static void gen_st_asi(DisasContext *dc, DisasASI *da, TCGv src, TCGv addr) 1854c03a0fd1SRichard Henderson { 1855c03a0fd1SRichard Henderson switch (da->type) { 1856fcf5ef2aSThomas Huth case GET_ASI_EXCP: 1857fcf5ef2aSThomas Huth break; 1858c03a0fd1SRichard Henderson 1859fcf5ef2aSThomas Huth case GET_ASI_DTWINX: /* Reserved for stda. */ 1860c03a0fd1SRichard Henderson if (TARGET_LONG_BITS == 32) { 1861fcf5ef2aSThomas Huth gen_exception(dc, TT_ILL_INSN); 1862fcf5ef2aSThomas Huth break; 1863c03a0fd1SRichard Henderson } else if (!(dc->def->features & CPU_FEATURE_HYPV)) { 18643390537bSArtyom Tarasenko /* Pre OpenSPARC CPUs don't have these */ 18653390537bSArtyom Tarasenko gen_exception(dc, TT_ILL_INSN); 1866fcf5ef2aSThomas Huth break; 1867c03a0fd1SRichard Henderson } 1868c03a0fd1SRichard Henderson /* In OpenSPARC T1+ CPUs TWINX ASIs in store are ST_BLKINIT_ ASIs */ 1869c03a0fd1SRichard Henderson /* fall through */ 1870c03a0fd1SRichard Henderson 1871c03a0fd1SRichard Henderson case GET_ASI_DIRECT: 1872c03a0fd1SRichard Henderson tcg_gen_qemu_st_tl(src, addr, da->mem_idx, da->memop | MO_ALIGN); 1873c03a0fd1SRichard Henderson break; 1874c03a0fd1SRichard Henderson 1875fcf5ef2aSThomas Huth case GET_ASI_BCOPY: 1876c03a0fd1SRichard Henderson assert(TARGET_LONG_BITS == 32); 1877fcf5ef2aSThomas Huth /* Copy 32 bytes from the address in SRC to ADDR. */ 1878fcf5ef2aSThomas Huth /* ??? The original qemu code suggests 4-byte alignment, dropping 1879fcf5ef2aSThomas Huth the low bits, but the only place I can see this used is in the 1880fcf5ef2aSThomas Huth Linux kernel with 32 byte alignment, which would make more sense 1881fcf5ef2aSThomas Huth as a cacheline-style operation. */ 1882fcf5ef2aSThomas Huth { 1883fcf5ef2aSThomas Huth TCGv saddr = tcg_temp_new(); 1884fcf5ef2aSThomas Huth TCGv daddr = tcg_temp_new(); 188500ab7e61SRichard Henderson TCGv four = tcg_constant_tl(4); 1886fcf5ef2aSThomas Huth TCGv_i32 tmp = tcg_temp_new_i32(); 1887fcf5ef2aSThomas Huth int i; 1888fcf5ef2aSThomas Huth 1889fcf5ef2aSThomas Huth tcg_gen_andi_tl(saddr, src, -4); 1890fcf5ef2aSThomas Huth tcg_gen_andi_tl(daddr, addr, -4); 1891fcf5ef2aSThomas Huth for (i = 0; i < 32; i += 4) { 1892fcf5ef2aSThomas Huth /* Since the loads and stores are paired, allow the 1893fcf5ef2aSThomas Huth copy to happen in the host endianness. */ 1894c03a0fd1SRichard Henderson tcg_gen_qemu_ld_i32(tmp, saddr, da->mem_idx, MO_UL); 1895c03a0fd1SRichard Henderson tcg_gen_qemu_st_i32(tmp, daddr, da->mem_idx, MO_UL); 1896fcf5ef2aSThomas Huth tcg_gen_add_tl(saddr, saddr, four); 1897fcf5ef2aSThomas Huth tcg_gen_add_tl(daddr, daddr, four); 1898fcf5ef2aSThomas Huth } 1899fcf5ef2aSThomas Huth } 1900fcf5ef2aSThomas Huth break; 1901c03a0fd1SRichard Henderson 1902fcf5ef2aSThomas Huth default: 1903fcf5ef2aSThomas Huth { 1904c03a0fd1SRichard Henderson TCGv_i32 r_asi = tcg_constant_i32(da->asi); 1905c03a0fd1SRichard Henderson TCGv_i32 r_mop = tcg_constant_i32(da->memop | MO_ALIGN); 1906fcf5ef2aSThomas Huth 1907fcf5ef2aSThomas Huth save_state(dc); 1908fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64 1909ad75a51eSRichard Henderson gen_helper_st_asi(tcg_env, addr, src, r_asi, r_mop); 1910fcf5ef2aSThomas Huth #else 1911fcf5ef2aSThomas Huth { 1912fcf5ef2aSThomas Huth TCGv_i64 t64 = tcg_temp_new_i64(); 1913fcf5ef2aSThomas Huth tcg_gen_extu_tl_i64(t64, src); 1914ad75a51eSRichard Henderson gen_helper_st_asi(tcg_env, addr, t64, r_asi, r_mop); 1915fcf5ef2aSThomas Huth } 1916fcf5ef2aSThomas Huth #endif 1917fcf5ef2aSThomas Huth 1918fcf5ef2aSThomas Huth /* A write to a TLB register may alter page maps. End the TB. */ 1919fcf5ef2aSThomas Huth dc->npc = DYNAMIC_PC; 1920fcf5ef2aSThomas Huth } 1921fcf5ef2aSThomas Huth break; 1922fcf5ef2aSThomas Huth } 1923fcf5ef2aSThomas Huth } 1924fcf5ef2aSThomas Huth 1925dca544b9SRichard Henderson static void gen_swap_asi(DisasContext *dc, DisasASI *da, 1926c03a0fd1SRichard Henderson TCGv dst, TCGv src, TCGv addr) 1927c03a0fd1SRichard Henderson { 1928c03a0fd1SRichard Henderson switch (da->type) { 1929c03a0fd1SRichard Henderson case GET_ASI_EXCP: 1930c03a0fd1SRichard Henderson break; 1931c03a0fd1SRichard Henderson case GET_ASI_DIRECT: 1932dca544b9SRichard Henderson tcg_gen_atomic_xchg_tl(dst, addr, src, 1933dca544b9SRichard Henderson da->mem_idx, da->memop | MO_ALIGN); 1934c03a0fd1SRichard Henderson break; 1935c03a0fd1SRichard Henderson default: 1936c03a0fd1SRichard Henderson /* ??? Should be DAE_invalid_asi. */ 1937c03a0fd1SRichard Henderson gen_exception(dc, TT_DATA_ACCESS); 1938c03a0fd1SRichard Henderson break; 1939c03a0fd1SRichard Henderson } 1940c03a0fd1SRichard Henderson } 1941c03a0fd1SRichard Henderson 1942d0a11d25SRichard Henderson static void gen_cas_asi(DisasContext *dc, DisasASI *da, 1943c03a0fd1SRichard Henderson TCGv oldv, TCGv newv, TCGv cmpv, TCGv addr) 1944c03a0fd1SRichard Henderson { 1945c03a0fd1SRichard Henderson switch (da->type) { 1946fcf5ef2aSThomas Huth case GET_ASI_EXCP: 1947c03a0fd1SRichard Henderson return; 1948fcf5ef2aSThomas Huth case GET_ASI_DIRECT: 1949c03a0fd1SRichard Henderson tcg_gen_atomic_cmpxchg_tl(oldv, addr, cmpv, newv, 1950c03a0fd1SRichard Henderson da->mem_idx, da->memop | MO_ALIGN); 1951fcf5ef2aSThomas Huth break; 1952fcf5ef2aSThomas Huth default: 1953fcf5ef2aSThomas Huth /* ??? Should be DAE_invalid_asi. */ 1954fcf5ef2aSThomas Huth gen_exception(dc, TT_DATA_ACCESS); 1955fcf5ef2aSThomas Huth break; 1956fcf5ef2aSThomas Huth } 1957fcf5ef2aSThomas Huth } 1958fcf5ef2aSThomas Huth 1959cf07cd1eSRichard Henderson static void gen_ldstub_asi(DisasContext *dc, DisasASI *da, TCGv dst, TCGv addr) 1960c03a0fd1SRichard Henderson { 1961c03a0fd1SRichard Henderson switch (da->type) { 1962fcf5ef2aSThomas Huth case GET_ASI_EXCP: 1963fcf5ef2aSThomas Huth break; 1964fcf5ef2aSThomas Huth case GET_ASI_DIRECT: 1965cf07cd1eSRichard Henderson tcg_gen_atomic_xchg_tl(dst, addr, tcg_constant_tl(0xff), 1966cf07cd1eSRichard Henderson da->mem_idx, MO_UB); 1967fcf5ef2aSThomas Huth break; 1968fcf5ef2aSThomas Huth default: 19693db010c3SRichard Henderson /* ??? In theory, this should be raise DAE_invalid_asi. 19703db010c3SRichard Henderson But the SS-20 roms do ldstuba [%l0] #ASI_M_CTL, %o1. */ 1971af00be49SEmilio G. Cota if (tb_cflags(dc->base.tb) & CF_PARALLEL) { 1972ad75a51eSRichard Henderson gen_helper_exit_atomic(tcg_env); 19733db010c3SRichard Henderson } else { 1974c03a0fd1SRichard Henderson TCGv_i32 r_asi = tcg_constant_i32(da->asi); 197500ab7e61SRichard Henderson TCGv_i32 r_mop = tcg_constant_i32(MO_UB); 19763db010c3SRichard Henderson TCGv_i64 s64, t64; 19773db010c3SRichard Henderson 19783db010c3SRichard Henderson save_state(dc); 19793db010c3SRichard Henderson t64 = tcg_temp_new_i64(); 1980ad75a51eSRichard Henderson gen_helper_ld_asi(t64, tcg_env, addr, r_asi, r_mop); 19813db010c3SRichard Henderson 198200ab7e61SRichard Henderson s64 = tcg_constant_i64(0xff); 1983ad75a51eSRichard Henderson gen_helper_st_asi(tcg_env, addr, s64, r_asi, r_mop); 19843db010c3SRichard Henderson 19853db010c3SRichard Henderson tcg_gen_trunc_i64_tl(dst, t64); 19863db010c3SRichard Henderson 19873db010c3SRichard Henderson /* End the TB. */ 19883db010c3SRichard Henderson dc->npc = DYNAMIC_PC; 19893db010c3SRichard Henderson } 1990fcf5ef2aSThomas Huth break; 1991fcf5ef2aSThomas Huth } 1992fcf5ef2aSThomas Huth } 1993fcf5ef2aSThomas Huth 1994287b1152SRichard Henderson static void gen_ldf_asi(DisasContext *dc, DisasASI *da, MemOp orig_size, 19953259b9e2SRichard Henderson TCGv addr, int rd) 1996fcf5ef2aSThomas Huth { 19973259b9e2SRichard Henderson MemOp memop = da->memop; 19983259b9e2SRichard Henderson MemOp size = memop & MO_SIZE; 1999fcf5ef2aSThomas Huth TCGv_i32 d32; 2000fcf5ef2aSThomas Huth TCGv_i64 d64; 2001287b1152SRichard Henderson TCGv addr_tmp; 2002fcf5ef2aSThomas Huth 20033259b9e2SRichard Henderson /* TODO: Use 128-bit load/store below. */ 20043259b9e2SRichard Henderson if (size == MO_128) { 20053259b9e2SRichard Henderson memop = (memop & ~MO_SIZE) | MO_64; 20063259b9e2SRichard Henderson } 20073259b9e2SRichard Henderson 20083259b9e2SRichard Henderson switch (da->type) { 2009fcf5ef2aSThomas Huth case GET_ASI_EXCP: 2010fcf5ef2aSThomas Huth break; 2011fcf5ef2aSThomas Huth 2012fcf5ef2aSThomas Huth case GET_ASI_DIRECT: 20133259b9e2SRichard Henderson memop |= MO_ALIGN_4; 2014fcf5ef2aSThomas Huth switch (size) { 20153259b9e2SRichard Henderson case MO_32: 2016fcf5ef2aSThomas Huth d32 = gen_dest_fpr_F(dc); 20173259b9e2SRichard Henderson tcg_gen_qemu_ld_i32(d32, addr, da->mem_idx, memop); 2018fcf5ef2aSThomas Huth gen_store_fpr_F(dc, rd, d32); 2019fcf5ef2aSThomas Huth break; 20203259b9e2SRichard Henderson 20213259b9e2SRichard Henderson case MO_64: 20223259b9e2SRichard Henderson tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2], addr, da->mem_idx, memop); 2023fcf5ef2aSThomas Huth break; 20243259b9e2SRichard Henderson 20253259b9e2SRichard Henderson case MO_128: 2026fcf5ef2aSThomas Huth d64 = tcg_temp_new_i64(); 20273259b9e2SRichard Henderson tcg_gen_qemu_ld_i64(d64, addr, da->mem_idx, memop); 2028287b1152SRichard Henderson addr_tmp = tcg_temp_new(); 2029287b1152SRichard Henderson tcg_gen_addi_tl(addr_tmp, addr, 8); 2030287b1152SRichard Henderson tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2 + 1], addr_tmp, da->mem_idx, memop); 2031fcf5ef2aSThomas Huth tcg_gen_mov_i64(cpu_fpr[rd / 2], d64); 2032fcf5ef2aSThomas Huth break; 2033fcf5ef2aSThomas Huth default: 2034fcf5ef2aSThomas Huth g_assert_not_reached(); 2035fcf5ef2aSThomas Huth } 2036fcf5ef2aSThomas Huth break; 2037fcf5ef2aSThomas Huth 2038fcf5ef2aSThomas Huth case GET_ASI_BLOCK: 2039fcf5ef2aSThomas Huth /* Valid for lddfa on aligned registers only. */ 20403259b9e2SRichard Henderson if (orig_size == MO_64 && (rd & 7) == 0) { 2041fcf5ef2aSThomas Huth /* The first operation checks required alignment. */ 2042287b1152SRichard Henderson addr_tmp = tcg_temp_new(); 2043287b1152SRichard Henderson for (int i = 0; ; ++i) { 20443259b9e2SRichard Henderson tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2 + i], addr, da->mem_idx, 20453259b9e2SRichard Henderson memop | (i == 0 ? MO_ALIGN_64 : 0)); 2046fcf5ef2aSThomas Huth if (i == 7) { 2047fcf5ef2aSThomas Huth break; 2048fcf5ef2aSThomas Huth } 2049287b1152SRichard Henderson tcg_gen_addi_tl(addr_tmp, addr, 8); 2050287b1152SRichard Henderson addr = addr_tmp; 2051fcf5ef2aSThomas Huth } 2052fcf5ef2aSThomas Huth } else { 2053fcf5ef2aSThomas Huth gen_exception(dc, TT_ILL_INSN); 2054fcf5ef2aSThomas Huth } 2055fcf5ef2aSThomas Huth break; 2056fcf5ef2aSThomas Huth 2057fcf5ef2aSThomas Huth case GET_ASI_SHORT: 2058fcf5ef2aSThomas Huth /* Valid for lddfa only. */ 20593259b9e2SRichard Henderson if (orig_size == MO_64) { 20603259b9e2SRichard Henderson tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2], addr, da->mem_idx, 20613259b9e2SRichard Henderson memop | MO_ALIGN); 2062fcf5ef2aSThomas Huth } else { 2063fcf5ef2aSThomas Huth gen_exception(dc, TT_ILL_INSN); 2064fcf5ef2aSThomas Huth } 2065fcf5ef2aSThomas Huth break; 2066fcf5ef2aSThomas Huth 2067fcf5ef2aSThomas Huth default: 2068fcf5ef2aSThomas Huth { 20693259b9e2SRichard Henderson TCGv_i32 r_asi = tcg_constant_i32(da->asi); 20703259b9e2SRichard Henderson TCGv_i32 r_mop = tcg_constant_i32(memop | MO_ALIGN); 2071fcf5ef2aSThomas Huth 2072fcf5ef2aSThomas Huth save_state(dc); 2073fcf5ef2aSThomas Huth /* According to the table in the UA2011 manual, the only 2074fcf5ef2aSThomas Huth other asis that are valid for ldfa/lddfa/ldqfa are 2075fcf5ef2aSThomas Huth the NO_FAULT asis. We still need a helper for these, 2076fcf5ef2aSThomas Huth but we can just use the integer asi helper for them. */ 2077fcf5ef2aSThomas Huth switch (size) { 20783259b9e2SRichard Henderson case MO_32: 2079fcf5ef2aSThomas Huth d64 = tcg_temp_new_i64(); 2080ad75a51eSRichard Henderson gen_helper_ld_asi(d64, tcg_env, addr, r_asi, r_mop); 2081fcf5ef2aSThomas Huth d32 = gen_dest_fpr_F(dc); 2082fcf5ef2aSThomas Huth tcg_gen_extrl_i64_i32(d32, d64); 2083fcf5ef2aSThomas Huth gen_store_fpr_F(dc, rd, d32); 2084fcf5ef2aSThomas Huth break; 20853259b9e2SRichard Henderson case MO_64: 20863259b9e2SRichard Henderson gen_helper_ld_asi(cpu_fpr[rd / 2], tcg_env, addr, 20873259b9e2SRichard Henderson r_asi, r_mop); 2088fcf5ef2aSThomas Huth break; 20893259b9e2SRichard Henderson case MO_128: 2090fcf5ef2aSThomas Huth d64 = tcg_temp_new_i64(); 2091ad75a51eSRichard Henderson gen_helper_ld_asi(d64, tcg_env, addr, r_asi, r_mop); 2092287b1152SRichard Henderson addr_tmp = tcg_temp_new(); 2093287b1152SRichard Henderson tcg_gen_addi_tl(addr_tmp, addr, 8); 2094287b1152SRichard Henderson gen_helper_ld_asi(cpu_fpr[rd / 2 + 1], tcg_env, addr_tmp, 20953259b9e2SRichard Henderson r_asi, r_mop); 2096fcf5ef2aSThomas Huth tcg_gen_mov_i64(cpu_fpr[rd / 2], d64); 2097fcf5ef2aSThomas Huth break; 2098fcf5ef2aSThomas Huth default: 2099fcf5ef2aSThomas Huth g_assert_not_reached(); 2100fcf5ef2aSThomas Huth } 2101fcf5ef2aSThomas Huth } 2102fcf5ef2aSThomas Huth break; 2103fcf5ef2aSThomas Huth } 2104fcf5ef2aSThomas Huth } 2105fcf5ef2aSThomas Huth 2106287b1152SRichard Henderson static void gen_stf_asi(DisasContext *dc, DisasASI *da, MemOp orig_size, 21073259b9e2SRichard Henderson TCGv addr, int rd) 21083259b9e2SRichard Henderson { 21093259b9e2SRichard Henderson MemOp memop = da->memop; 21103259b9e2SRichard Henderson MemOp size = memop & MO_SIZE; 2111fcf5ef2aSThomas Huth TCGv_i32 d32; 2112287b1152SRichard Henderson TCGv addr_tmp; 2113fcf5ef2aSThomas Huth 21143259b9e2SRichard Henderson /* TODO: Use 128-bit load/store below. */ 21153259b9e2SRichard Henderson if (size == MO_128) { 21163259b9e2SRichard Henderson memop = (memop & ~MO_SIZE) | MO_64; 21173259b9e2SRichard Henderson } 21183259b9e2SRichard Henderson 21193259b9e2SRichard Henderson switch (da->type) { 2120fcf5ef2aSThomas Huth case GET_ASI_EXCP: 2121fcf5ef2aSThomas Huth break; 2122fcf5ef2aSThomas Huth 2123fcf5ef2aSThomas Huth case GET_ASI_DIRECT: 21243259b9e2SRichard Henderson memop |= MO_ALIGN_4; 2125fcf5ef2aSThomas Huth switch (size) { 21263259b9e2SRichard Henderson case MO_32: 2127fcf5ef2aSThomas Huth d32 = gen_load_fpr_F(dc, rd); 21283259b9e2SRichard Henderson tcg_gen_qemu_st_i32(d32, addr, da->mem_idx, memop | MO_ALIGN); 2129fcf5ef2aSThomas Huth break; 21303259b9e2SRichard Henderson case MO_64: 21313259b9e2SRichard Henderson tcg_gen_qemu_st_i64(cpu_fpr[rd / 2], addr, da->mem_idx, 21323259b9e2SRichard Henderson memop | MO_ALIGN_4); 2133fcf5ef2aSThomas Huth break; 21343259b9e2SRichard Henderson case MO_128: 2135fcf5ef2aSThomas Huth /* Only 4-byte alignment required. However, it is legal for the 2136fcf5ef2aSThomas Huth cpu to signal the alignment fault, and the OS trap handler is 2137fcf5ef2aSThomas Huth required to fix it up. Requiring 16-byte alignment here avoids 2138fcf5ef2aSThomas Huth having to probe the second page before performing the first 2139fcf5ef2aSThomas Huth write. */ 21403259b9e2SRichard Henderson tcg_gen_qemu_st_i64(cpu_fpr[rd / 2], addr, da->mem_idx, 21413259b9e2SRichard Henderson memop | MO_ALIGN_16); 2142287b1152SRichard Henderson addr_tmp = tcg_temp_new(); 2143287b1152SRichard Henderson tcg_gen_addi_tl(addr_tmp, addr, 8); 2144287b1152SRichard Henderson tcg_gen_qemu_st_i64(cpu_fpr[rd / 2 + 1], addr_tmp, da->mem_idx, memop); 2145fcf5ef2aSThomas Huth break; 2146fcf5ef2aSThomas Huth default: 2147fcf5ef2aSThomas Huth g_assert_not_reached(); 2148fcf5ef2aSThomas Huth } 2149fcf5ef2aSThomas Huth break; 2150fcf5ef2aSThomas Huth 2151fcf5ef2aSThomas Huth case GET_ASI_BLOCK: 2152fcf5ef2aSThomas Huth /* Valid for stdfa on aligned registers only. */ 21533259b9e2SRichard Henderson if (orig_size == MO_64 && (rd & 7) == 0) { 2154fcf5ef2aSThomas Huth /* The first operation checks required alignment. */ 2155287b1152SRichard Henderson addr_tmp = tcg_temp_new(); 2156287b1152SRichard Henderson for (int i = 0; ; ++i) { 21573259b9e2SRichard Henderson tcg_gen_qemu_st_i64(cpu_fpr[rd / 2 + i], addr, da->mem_idx, 21583259b9e2SRichard Henderson memop | (i == 0 ? MO_ALIGN_64 : 0)); 2159fcf5ef2aSThomas Huth if (i == 7) { 2160fcf5ef2aSThomas Huth break; 2161fcf5ef2aSThomas Huth } 2162287b1152SRichard Henderson tcg_gen_addi_tl(addr_tmp, addr, 8); 2163287b1152SRichard Henderson addr = addr_tmp; 2164fcf5ef2aSThomas Huth } 2165fcf5ef2aSThomas Huth } else { 2166fcf5ef2aSThomas Huth gen_exception(dc, TT_ILL_INSN); 2167fcf5ef2aSThomas Huth } 2168fcf5ef2aSThomas Huth break; 2169fcf5ef2aSThomas Huth 2170fcf5ef2aSThomas Huth case GET_ASI_SHORT: 2171fcf5ef2aSThomas Huth /* Valid for stdfa only. */ 21723259b9e2SRichard Henderson if (orig_size == MO_64) { 21733259b9e2SRichard Henderson tcg_gen_qemu_st_i64(cpu_fpr[rd / 2], addr, da->mem_idx, 21743259b9e2SRichard Henderson memop | MO_ALIGN); 2175fcf5ef2aSThomas Huth } else { 2176fcf5ef2aSThomas Huth gen_exception(dc, TT_ILL_INSN); 2177fcf5ef2aSThomas Huth } 2178fcf5ef2aSThomas Huth break; 2179fcf5ef2aSThomas Huth 2180fcf5ef2aSThomas Huth default: 2181fcf5ef2aSThomas Huth /* According to the table in the UA2011 manual, the only 2182fcf5ef2aSThomas Huth other asis that are valid for ldfa/lddfa/ldqfa are 2183fcf5ef2aSThomas Huth the PST* asis, which aren't currently handled. */ 2184fcf5ef2aSThomas Huth gen_exception(dc, TT_ILL_INSN); 2185fcf5ef2aSThomas Huth break; 2186fcf5ef2aSThomas Huth } 2187fcf5ef2aSThomas Huth } 2188fcf5ef2aSThomas Huth 218942071fc1SRichard Henderson static void gen_ldda_asi(DisasContext *dc, DisasASI *da, TCGv addr, int rd) 2190fcf5ef2aSThomas Huth { 2191a76779eeSRichard Henderson TCGv hi = gen_dest_gpr(dc, rd); 2192a76779eeSRichard Henderson TCGv lo = gen_dest_gpr(dc, rd + 1); 2193fcf5ef2aSThomas Huth 2194c03a0fd1SRichard Henderson switch (da->type) { 2195fcf5ef2aSThomas Huth case GET_ASI_EXCP: 2196fcf5ef2aSThomas Huth return; 2197fcf5ef2aSThomas Huth 2198fcf5ef2aSThomas Huth case GET_ASI_DTWINX: 2199ebbbec92SRichard Henderson #ifdef TARGET_SPARC64 2200ebbbec92SRichard Henderson { 2201ebbbec92SRichard Henderson MemOp mop = (da->memop & MO_BSWAP) | MO_128 | MO_ALIGN_16; 2202ebbbec92SRichard Henderson TCGv_i128 t = tcg_temp_new_i128(); 2203ebbbec92SRichard Henderson 2204ebbbec92SRichard Henderson tcg_gen_qemu_ld_i128(t, addr, da->mem_idx, mop); 2205ebbbec92SRichard Henderson /* 2206ebbbec92SRichard Henderson * Note that LE twinx acts as if each 64-bit register result is 2207ebbbec92SRichard Henderson * byte swapped. We perform one 128-bit LE load, so must swap 2208ebbbec92SRichard Henderson * the order of the writebacks. 2209ebbbec92SRichard Henderson */ 2210ebbbec92SRichard Henderson if ((mop & MO_BSWAP) == MO_TE) { 2211ebbbec92SRichard Henderson tcg_gen_extr_i128_i64(lo, hi, t); 2212ebbbec92SRichard Henderson } else { 2213ebbbec92SRichard Henderson tcg_gen_extr_i128_i64(hi, lo, t); 2214ebbbec92SRichard Henderson } 2215ebbbec92SRichard Henderson } 2216fcf5ef2aSThomas Huth break; 2217ebbbec92SRichard Henderson #else 2218ebbbec92SRichard Henderson g_assert_not_reached(); 2219ebbbec92SRichard Henderson #endif 2220fcf5ef2aSThomas Huth 2221fcf5ef2aSThomas Huth case GET_ASI_DIRECT: 2222fcf5ef2aSThomas Huth { 2223fcf5ef2aSThomas Huth TCGv_i64 tmp = tcg_temp_new_i64(); 2224fcf5ef2aSThomas Huth 2225c03a0fd1SRichard Henderson tcg_gen_qemu_ld_i64(tmp, addr, da->mem_idx, da->memop | MO_ALIGN); 2226fcf5ef2aSThomas Huth 2227fcf5ef2aSThomas Huth /* Note that LE ldda acts as if each 32-bit register 2228fcf5ef2aSThomas Huth result is byte swapped. Having just performed one 2229fcf5ef2aSThomas Huth 64-bit bswap, we need now to swap the writebacks. */ 2230c03a0fd1SRichard Henderson if ((da->memop & MO_BSWAP) == MO_TE) { 2231a76779eeSRichard Henderson tcg_gen_extr_i64_tl(lo, hi, tmp); 2232fcf5ef2aSThomas Huth } else { 2233a76779eeSRichard Henderson tcg_gen_extr_i64_tl(hi, lo, tmp); 2234fcf5ef2aSThomas Huth } 2235fcf5ef2aSThomas Huth } 2236fcf5ef2aSThomas Huth break; 2237fcf5ef2aSThomas Huth 2238fcf5ef2aSThomas Huth default: 2239fcf5ef2aSThomas Huth /* ??? In theory we've handled all of the ASIs that are valid 2240fcf5ef2aSThomas Huth for ldda, and this should raise DAE_invalid_asi. However, 2241fcf5ef2aSThomas Huth real hardware allows others. This can be seen with e.g. 2242fcf5ef2aSThomas Huth FreeBSD 10.3 wrt ASI_IC_TAG. */ 2243fcf5ef2aSThomas Huth { 2244c03a0fd1SRichard Henderson TCGv_i32 r_asi = tcg_constant_i32(da->asi); 2245c03a0fd1SRichard Henderson TCGv_i32 r_mop = tcg_constant_i32(da->memop); 2246fcf5ef2aSThomas Huth TCGv_i64 tmp = tcg_temp_new_i64(); 2247fcf5ef2aSThomas Huth 2248fcf5ef2aSThomas Huth save_state(dc); 2249ad75a51eSRichard Henderson gen_helper_ld_asi(tmp, tcg_env, addr, r_asi, r_mop); 2250fcf5ef2aSThomas Huth 2251fcf5ef2aSThomas Huth /* See above. */ 2252c03a0fd1SRichard Henderson if ((da->memop & MO_BSWAP) == MO_TE) { 2253a76779eeSRichard Henderson tcg_gen_extr_i64_tl(lo, hi, tmp); 2254fcf5ef2aSThomas Huth } else { 2255a76779eeSRichard Henderson tcg_gen_extr_i64_tl(hi, lo, tmp); 2256fcf5ef2aSThomas Huth } 2257fcf5ef2aSThomas Huth } 2258fcf5ef2aSThomas Huth break; 2259fcf5ef2aSThomas Huth } 2260fcf5ef2aSThomas Huth 2261fcf5ef2aSThomas Huth gen_store_gpr(dc, rd, hi); 2262fcf5ef2aSThomas Huth gen_store_gpr(dc, rd + 1, lo); 2263fcf5ef2aSThomas Huth } 2264fcf5ef2aSThomas Huth 226542071fc1SRichard Henderson static void gen_stda_asi(DisasContext *dc, DisasASI *da, TCGv addr, int rd) 2266c03a0fd1SRichard Henderson { 2267c03a0fd1SRichard Henderson TCGv hi = gen_load_gpr(dc, rd); 2268fcf5ef2aSThomas Huth TCGv lo = gen_load_gpr(dc, rd + 1); 2269fcf5ef2aSThomas Huth 2270c03a0fd1SRichard Henderson switch (da->type) { 2271fcf5ef2aSThomas Huth case GET_ASI_EXCP: 2272fcf5ef2aSThomas Huth break; 2273fcf5ef2aSThomas Huth 2274fcf5ef2aSThomas Huth case GET_ASI_DTWINX: 2275ebbbec92SRichard Henderson #ifdef TARGET_SPARC64 2276ebbbec92SRichard Henderson { 2277ebbbec92SRichard Henderson MemOp mop = (da->memop & MO_BSWAP) | MO_128 | MO_ALIGN_16; 2278ebbbec92SRichard Henderson TCGv_i128 t = tcg_temp_new_i128(); 2279ebbbec92SRichard Henderson 2280ebbbec92SRichard Henderson /* 2281ebbbec92SRichard Henderson * Note that LE twinx acts as if each 64-bit register result is 2282ebbbec92SRichard Henderson * byte swapped. We perform one 128-bit LE store, so must swap 2283ebbbec92SRichard Henderson * the order of the construction. 2284ebbbec92SRichard Henderson */ 2285ebbbec92SRichard Henderson if ((mop & MO_BSWAP) == MO_TE) { 2286ebbbec92SRichard Henderson tcg_gen_concat_i64_i128(t, lo, hi); 2287ebbbec92SRichard Henderson } else { 2288ebbbec92SRichard Henderson tcg_gen_concat_i64_i128(t, hi, lo); 2289ebbbec92SRichard Henderson } 2290ebbbec92SRichard Henderson tcg_gen_qemu_st_i128(t, addr, da->mem_idx, mop); 2291ebbbec92SRichard Henderson } 2292fcf5ef2aSThomas Huth break; 2293ebbbec92SRichard Henderson #else 2294ebbbec92SRichard Henderson g_assert_not_reached(); 2295ebbbec92SRichard Henderson #endif 2296fcf5ef2aSThomas Huth 2297fcf5ef2aSThomas Huth case GET_ASI_DIRECT: 2298fcf5ef2aSThomas Huth { 2299fcf5ef2aSThomas Huth TCGv_i64 t64 = tcg_temp_new_i64(); 2300fcf5ef2aSThomas Huth 2301fcf5ef2aSThomas Huth /* Note that LE stda acts as if each 32-bit register result is 2302fcf5ef2aSThomas Huth byte swapped. We will perform one 64-bit LE store, so now 2303fcf5ef2aSThomas Huth we must swap the order of the construction. */ 2304c03a0fd1SRichard Henderson if ((da->memop & MO_BSWAP) == MO_TE) { 2305a76779eeSRichard Henderson tcg_gen_concat_tl_i64(t64, lo, hi); 2306fcf5ef2aSThomas Huth } else { 2307a76779eeSRichard Henderson tcg_gen_concat_tl_i64(t64, hi, lo); 2308fcf5ef2aSThomas Huth } 2309c03a0fd1SRichard Henderson tcg_gen_qemu_st_i64(t64, addr, da->mem_idx, da->memop | MO_ALIGN); 2310fcf5ef2aSThomas Huth } 2311fcf5ef2aSThomas Huth break; 2312fcf5ef2aSThomas Huth 2313a76779eeSRichard Henderson case GET_ASI_BFILL: 2314a76779eeSRichard Henderson assert(TARGET_LONG_BITS == 32); 2315a76779eeSRichard Henderson /* Store 32 bytes of T64 to ADDR. */ 2316a76779eeSRichard Henderson /* ??? The original qemu code suggests 8-byte alignment, dropping 2317a76779eeSRichard Henderson the low bits, but the only place I can see this used is in the 2318a76779eeSRichard Henderson Linux kernel with 32 byte alignment, which would make more sense 2319a76779eeSRichard Henderson as a cacheline-style operation. */ 2320a76779eeSRichard Henderson { 2321a76779eeSRichard Henderson TCGv_i64 t64 = tcg_temp_new_i64(); 2322a76779eeSRichard Henderson TCGv d_addr = tcg_temp_new(); 2323a76779eeSRichard Henderson TCGv eight = tcg_constant_tl(8); 2324a76779eeSRichard Henderson int i; 2325a76779eeSRichard Henderson 2326a76779eeSRichard Henderson tcg_gen_concat_tl_i64(t64, lo, hi); 2327a76779eeSRichard Henderson tcg_gen_andi_tl(d_addr, addr, -8); 2328a76779eeSRichard Henderson for (i = 0; i < 32; i += 8) { 2329c03a0fd1SRichard Henderson tcg_gen_qemu_st_i64(t64, d_addr, da->mem_idx, da->memop); 2330a76779eeSRichard Henderson tcg_gen_add_tl(d_addr, d_addr, eight); 2331a76779eeSRichard Henderson } 2332a76779eeSRichard Henderson } 2333a76779eeSRichard Henderson break; 2334a76779eeSRichard Henderson 2335fcf5ef2aSThomas Huth default: 2336fcf5ef2aSThomas Huth /* ??? In theory we've handled all of the ASIs that are valid 2337fcf5ef2aSThomas Huth for stda, and this should raise DAE_invalid_asi. */ 2338fcf5ef2aSThomas Huth { 2339c03a0fd1SRichard Henderson TCGv_i32 r_asi = tcg_constant_i32(da->asi); 2340c03a0fd1SRichard Henderson TCGv_i32 r_mop = tcg_constant_i32(da->memop); 2341fcf5ef2aSThomas Huth TCGv_i64 t64 = tcg_temp_new_i64(); 2342fcf5ef2aSThomas Huth 2343fcf5ef2aSThomas Huth /* See above. */ 2344c03a0fd1SRichard Henderson if ((da->memop & MO_BSWAP) == MO_TE) { 2345a76779eeSRichard Henderson tcg_gen_concat_tl_i64(t64, lo, hi); 2346fcf5ef2aSThomas Huth } else { 2347a76779eeSRichard Henderson tcg_gen_concat_tl_i64(t64, hi, lo); 2348fcf5ef2aSThomas Huth } 2349fcf5ef2aSThomas Huth 2350fcf5ef2aSThomas Huth save_state(dc); 2351ad75a51eSRichard Henderson gen_helper_st_asi(tcg_env, addr, t64, r_asi, r_mop); 2352fcf5ef2aSThomas Huth } 2353fcf5ef2aSThomas Huth break; 2354fcf5ef2aSThomas Huth } 2355fcf5ef2aSThomas Huth } 2356fcf5ef2aSThomas Huth 2357fcf5ef2aSThomas Huth static void gen_fmovs(DisasContext *dc, DisasCompare *cmp, int rd, int rs) 2358fcf5ef2aSThomas Huth { 2359f7ec8155SRichard Henderson #ifdef TARGET_SPARC64 2360fcf5ef2aSThomas Huth TCGv_i32 c32, zero, dst, s1, s2; 2361fcf5ef2aSThomas Huth 2362fcf5ef2aSThomas Huth /* We have two choices here: extend the 32 bit data and use movcond_i64, 2363fcf5ef2aSThomas Huth or fold the comparison down to 32 bits and use movcond_i32. Choose 2364fcf5ef2aSThomas Huth the later. */ 2365fcf5ef2aSThomas Huth c32 = tcg_temp_new_i32(); 2366fcf5ef2aSThomas Huth if (cmp->is_bool) { 2367fcf5ef2aSThomas Huth tcg_gen_extrl_i64_i32(c32, cmp->c1); 2368fcf5ef2aSThomas Huth } else { 2369fcf5ef2aSThomas Huth TCGv_i64 c64 = tcg_temp_new_i64(); 2370fcf5ef2aSThomas Huth tcg_gen_setcond_i64(cmp->cond, c64, cmp->c1, cmp->c2); 2371fcf5ef2aSThomas Huth tcg_gen_extrl_i64_i32(c32, c64); 2372fcf5ef2aSThomas Huth } 2373fcf5ef2aSThomas Huth 2374fcf5ef2aSThomas Huth s1 = gen_load_fpr_F(dc, rs); 2375fcf5ef2aSThomas Huth s2 = gen_load_fpr_F(dc, rd); 2376fcf5ef2aSThomas Huth dst = gen_dest_fpr_F(dc); 237700ab7e61SRichard Henderson zero = tcg_constant_i32(0); 2378fcf5ef2aSThomas Huth 2379fcf5ef2aSThomas Huth tcg_gen_movcond_i32(TCG_COND_NE, dst, c32, zero, s1, s2); 2380fcf5ef2aSThomas Huth 2381fcf5ef2aSThomas Huth gen_store_fpr_F(dc, rd, dst); 2382f7ec8155SRichard Henderson #else 2383f7ec8155SRichard Henderson qemu_build_not_reached(); 2384f7ec8155SRichard Henderson #endif 2385fcf5ef2aSThomas Huth } 2386fcf5ef2aSThomas Huth 2387fcf5ef2aSThomas Huth static void gen_fmovd(DisasContext *dc, DisasCompare *cmp, int rd, int rs) 2388fcf5ef2aSThomas Huth { 2389f7ec8155SRichard Henderson #ifdef TARGET_SPARC64 2390fcf5ef2aSThomas Huth TCGv_i64 dst = gen_dest_fpr_D(dc, rd); 2391fcf5ef2aSThomas Huth tcg_gen_movcond_i64(cmp->cond, dst, cmp->c1, cmp->c2, 2392fcf5ef2aSThomas Huth gen_load_fpr_D(dc, rs), 2393fcf5ef2aSThomas Huth gen_load_fpr_D(dc, rd)); 2394fcf5ef2aSThomas Huth gen_store_fpr_D(dc, rd, dst); 2395f7ec8155SRichard Henderson #else 2396f7ec8155SRichard Henderson qemu_build_not_reached(); 2397f7ec8155SRichard Henderson #endif 2398fcf5ef2aSThomas Huth } 2399fcf5ef2aSThomas Huth 2400fcf5ef2aSThomas Huth static void gen_fmovq(DisasContext *dc, DisasCompare *cmp, int rd, int rs) 2401fcf5ef2aSThomas Huth { 2402f7ec8155SRichard Henderson #ifdef TARGET_SPARC64 2403fcf5ef2aSThomas Huth int qd = QFPREG(rd); 2404fcf5ef2aSThomas Huth int qs = QFPREG(rs); 2405fcf5ef2aSThomas Huth 2406fcf5ef2aSThomas Huth tcg_gen_movcond_i64(cmp->cond, cpu_fpr[qd / 2], cmp->c1, cmp->c2, 2407fcf5ef2aSThomas Huth cpu_fpr[qs / 2], cpu_fpr[qd / 2]); 2408fcf5ef2aSThomas Huth tcg_gen_movcond_i64(cmp->cond, cpu_fpr[qd / 2 + 1], cmp->c1, cmp->c2, 2409fcf5ef2aSThomas Huth cpu_fpr[qs / 2 + 1], cpu_fpr[qd / 2 + 1]); 2410fcf5ef2aSThomas Huth 2411fcf5ef2aSThomas Huth gen_update_fprs_dirty(dc, qd); 2412f7ec8155SRichard Henderson #else 2413f7ec8155SRichard Henderson qemu_build_not_reached(); 2414f7ec8155SRichard Henderson #endif 2415fcf5ef2aSThomas Huth } 2416fcf5ef2aSThomas Huth 2417f7ec8155SRichard Henderson #ifdef TARGET_SPARC64 24185d617bfbSRichard Henderson static void gen_load_trap_state_at_tl(TCGv_ptr r_tsptr) 2419fcf5ef2aSThomas Huth { 2420fcf5ef2aSThomas Huth TCGv_i32 r_tl = tcg_temp_new_i32(); 2421fcf5ef2aSThomas Huth 2422fcf5ef2aSThomas Huth /* load env->tl into r_tl */ 2423ad75a51eSRichard Henderson tcg_gen_ld_i32(r_tl, tcg_env, offsetof(CPUSPARCState, tl)); 2424fcf5ef2aSThomas Huth 2425fcf5ef2aSThomas Huth /* tl = [0 ... MAXTL_MASK] where MAXTL_MASK must be power of 2 */ 2426fcf5ef2aSThomas Huth tcg_gen_andi_i32(r_tl, r_tl, MAXTL_MASK); 2427fcf5ef2aSThomas Huth 2428fcf5ef2aSThomas Huth /* calculate offset to current trap state from env->ts, reuse r_tl */ 2429fcf5ef2aSThomas Huth tcg_gen_muli_i32(r_tl, r_tl, sizeof (trap_state)); 2430ad75a51eSRichard Henderson tcg_gen_addi_ptr(r_tsptr, tcg_env, offsetof(CPUSPARCState, ts)); 2431fcf5ef2aSThomas Huth 2432fcf5ef2aSThomas Huth /* tsptr = env->ts[env->tl & MAXTL_MASK] */ 2433fcf5ef2aSThomas Huth { 2434fcf5ef2aSThomas Huth TCGv_ptr r_tl_tmp = tcg_temp_new_ptr(); 2435fcf5ef2aSThomas Huth tcg_gen_ext_i32_ptr(r_tl_tmp, r_tl); 2436fcf5ef2aSThomas Huth tcg_gen_add_ptr(r_tsptr, r_tsptr, r_tl_tmp); 2437fcf5ef2aSThomas Huth } 2438fcf5ef2aSThomas Huth } 2439fcf5ef2aSThomas Huth #endif 2440fcf5ef2aSThomas Huth 244106c060d9SRichard Henderson static int extract_dfpreg(DisasContext *dc, int x) 244206c060d9SRichard Henderson { 244306c060d9SRichard Henderson return DFPREG(x); 244406c060d9SRichard Henderson } 244506c060d9SRichard Henderson 244606c060d9SRichard Henderson static int extract_qfpreg(DisasContext *dc, int x) 244706c060d9SRichard Henderson { 244806c060d9SRichard Henderson return QFPREG(x); 244906c060d9SRichard Henderson } 245006c060d9SRichard Henderson 2451878cc677SRichard Henderson /* Include the auto-generated decoder. */ 2452878cc677SRichard Henderson #include "decode-insns.c.inc" 2453878cc677SRichard Henderson 2454878cc677SRichard Henderson #define TRANS(NAME, AVAIL, FUNC, ...) \ 2455878cc677SRichard Henderson static bool trans_##NAME(DisasContext *dc, arg_##NAME *a) \ 2456878cc677SRichard Henderson { return avail_##AVAIL(dc) && FUNC(dc, __VA_ARGS__); } 2457878cc677SRichard Henderson 2458878cc677SRichard Henderson #define avail_ALL(C) true 2459878cc677SRichard Henderson #ifdef TARGET_SPARC64 2460878cc677SRichard Henderson # define avail_32(C) false 2461af25071cSRichard Henderson # define avail_ASR17(C) false 2462d0a11d25SRichard Henderson # define avail_CASA(C) true 2463c2636853SRichard Henderson # define avail_DIV(C) true 2464b5372650SRichard Henderson # define avail_MUL(C) true 24650faef01bSRichard Henderson # define avail_POWERDOWN(C) false 2466878cc677SRichard Henderson # define avail_64(C) true 24675d617bfbSRichard Henderson # define avail_GL(C) ((C)->def->features & CPU_FEATURE_GL) 2468af25071cSRichard Henderson # define avail_HYPV(C) ((C)->def->features & CPU_FEATURE_HYPV) 2469b88ce6f2SRichard Henderson # define avail_VIS1(C) ((C)->def->features & CPU_FEATURE_VIS1) 2470b88ce6f2SRichard Henderson # define avail_VIS2(C) ((C)->def->features & CPU_FEATURE_VIS2) 2471878cc677SRichard Henderson #else 2472878cc677SRichard Henderson # define avail_32(C) true 2473af25071cSRichard Henderson # define avail_ASR17(C) ((C)->def->features & CPU_FEATURE_ASR17) 2474d0a11d25SRichard Henderson # define avail_CASA(C) ((C)->def->features & CPU_FEATURE_CASA) 2475c2636853SRichard Henderson # define avail_DIV(C) ((C)->def->features & CPU_FEATURE_DIV) 2476b5372650SRichard Henderson # define avail_MUL(C) ((C)->def->features & CPU_FEATURE_MUL) 24770faef01bSRichard Henderson # define avail_POWERDOWN(C) ((C)->def->features & CPU_FEATURE_POWERDOWN) 2478878cc677SRichard Henderson # define avail_64(C) false 24795d617bfbSRichard Henderson # define avail_GL(C) false 2480af25071cSRichard Henderson # define avail_HYPV(C) false 2481b88ce6f2SRichard Henderson # define avail_VIS1(C) false 2482b88ce6f2SRichard Henderson # define avail_VIS2(C) false 2483878cc677SRichard Henderson #endif 2484878cc677SRichard Henderson 2485878cc677SRichard Henderson /* Default case for non jump instructions. */ 2486878cc677SRichard Henderson static bool advance_pc(DisasContext *dc) 2487878cc677SRichard Henderson { 2488878cc677SRichard Henderson if (dc->npc & 3) { 2489878cc677SRichard Henderson switch (dc->npc) { 2490878cc677SRichard Henderson case DYNAMIC_PC: 2491878cc677SRichard Henderson case DYNAMIC_PC_LOOKUP: 2492878cc677SRichard Henderson dc->pc = dc->npc; 2493878cc677SRichard Henderson gen_op_next_insn(); 2494878cc677SRichard Henderson break; 2495878cc677SRichard Henderson case JUMP_PC: 2496878cc677SRichard Henderson /* we can do a static jump */ 2497878cc677SRichard Henderson gen_branch2(dc, dc->jump_pc[0], dc->jump_pc[1], cpu_cond); 2498878cc677SRichard Henderson dc->base.is_jmp = DISAS_NORETURN; 2499878cc677SRichard Henderson break; 2500878cc677SRichard Henderson default: 2501878cc677SRichard Henderson g_assert_not_reached(); 2502878cc677SRichard Henderson } 2503878cc677SRichard Henderson } else { 2504878cc677SRichard Henderson dc->pc = dc->npc; 2505878cc677SRichard Henderson dc->npc = dc->npc + 4; 2506878cc677SRichard Henderson } 2507878cc677SRichard Henderson return true; 2508878cc677SRichard Henderson } 2509878cc677SRichard Henderson 25106d2a0768SRichard Henderson /* 25116d2a0768SRichard Henderson * Major opcodes 00 and 01 -- branches, call, and sethi 25126d2a0768SRichard Henderson */ 25136d2a0768SRichard Henderson 2514276567aaSRichard Henderson static bool advance_jump_uncond_never(DisasContext *dc, bool annul) 2515276567aaSRichard Henderson { 2516276567aaSRichard Henderson if (annul) { 2517276567aaSRichard Henderson dc->pc = dc->npc + 4; 2518276567aaSRichard Henderson dc->npc = dc->pc + 4; 2519276567aaSRichard Henderson } else { 2520276567aaSRichard Henderson dc->pc = dc->npc; 2521276567aaSRichard Henderson dc->npc = dc->pc + 4; 2522276567aaSRichard Henderson } 2523276567aaSRichard Henderson return true; 2524276567aaSRichard Henderson } 2525276567aaSRichard Henderson 2526276567aaSRichard Henderson static bool advance_jump_uncond_always(DisasContext *dc, bool annul, 2527276567aaSRichard Henderson target_ulong dest) 2528276567aaSRichard Henderson { 2529276567aaSRichard Henderson if (annul) { 2530276567aaSRichard Henderson dc->pc = dest; 2531276567aaSRichard Henderson dc->npc = dest + 4; 2532276567aaSRichard Henderson } else { 2533276567aaSRichard Henderson dc->pc = dc->npc; 2534276567aaSRichard Henderson dc->npc = dest; 2535276567aaSRichard Henderson tcg_gen_mov_tl(cpu_pc, cpu_npc); 2536276567aaSRichard Henderson } 2537276567aaSRichard Henderson return true; 2538276567aaSRichard Henderson } 2539276567aaSRichard Henderson 25409d4e2bc7SRichard Henderson static bool advance_jump_cond(DisasContext *dc, DisasCompare *cmp, 25419d4e2bc7SRichard Henderson bool annul, target_ulong dest) 2542276567aaSRichard Henderson { 25436b3e4cc6SRichard Henderson target_ulong npc = dc->npc; 25446b3e4cc6SRichard Henderson 2545276567aaSRichard Henderson if (annul) { 25466b3e4cc6SRichard Henderson TCGLabel *l1 = gen_new_label(); 25476b3e4cc6SRichard Henderson 25489d4e2bc7SRichard Henderson tcg_gen_brcond_tl(tcg_invert_cond(cmp->cond), cmp->c1, cmp->c2, l1); 25496b3e4cc6SRichard Henderson gen_goto_tb(dc, 0, npc, dest); 25506b3e4cc6SRichard Henderson gen_set_label(l1); 25516b3e4cc6SRichard Henderson gen_goto_tb(dc, 1, npc + 4, npc + 8); 25526b3e4cc6SRichard Henderson 25536b3e4cc6SRichard Henderson dc->base.is_jmp = DISAS_NORETURN; 2554276567aaSRichard Henderson } else { 25556b3e4cc6SRichard Henderson if (npc & 3) { 25566b3e4cc6SRichard Henderson switch (npc) { 25576b3e4cc6SRichard Henderson case DYNAMIC_PC: 25586b3e4cc6SRichard Henderson case DYNAMIC_PC_LOOKUP: 25596b3e4cc6SRichard Henderson tcg_gen_mov_tl(cpu_pc, cpu_npc); 25606b3e4cc6SRichard Henderson tcg_gen_addi_tl(cpu_npc, cpu_npc, 4); 25619d4e2bc7SRichard Henderson tcg_gen_movcond_tl(cmp->cond, cpu_npc, 25629d4e2bc7SRichard Henderson cmp->c1, cmp->c2, 25636b3e4cc6SRichard Henderson tcg_constant_tl(dest), cpu_npc); 25646b3e4cc6SRichard Henderson dc->pc = npc; 25656b3e4cc6SRichard Henderson break; 25666b3e4cc6SRichard Henderson default: 25676b3e4cc6SRichard Henderson g_assert_not_reached(); 25686b3e4cc6SRichard Henderson } 25696b3e4cc6SRichard Henderson } else { 25706b3e4cc6SRichard Henderson dc->pc = npc; 25716b3e4cc6SRichard Henderson dc->jump_pc[0] = dest; 25726b3e4cc6SRichard Henderson dc->jump_pc[1] = npc + 4; 25736b3e4cc6SRichard Henderson dc->npc = JUMP_PC; 25749d4e2bc7SRichard Henderson if (cmp->is_bool) { 25759d4e2bc7SRichard Henderson tcg_gen_mov_tl(cpu_cond, cmp->c1); 25769d4e2bc7SRichard Henderson } else { 25779d4e2bc7SRichard Henderson tcg_gen_setcond_tl(cmp->cond, cpu_cond, cmp->c1, cmp->c2); 25789d4e2bc7SRichard Henderson } 25796b3e4cc6SRichard Henderson } 2580276567aaSRichard Henderson } 2581276567aaSRichard Henderson return true; 2582276567aaSRichard Henderson } 2583276567aaSRichard Henderson 2584af25071cSRichard Henderson static bool raise_priv(DisasContext *dc) 2585af25071cSRichard Henderson { 2586af25071cSRichard Henderson gen_exception(dc, TT_PRIV_INSN); 2587af25071cSRichard Henderson return true; 2588af25071cSRichard Henderson } 2589af25071cSRichard Henderson 259006c060d9SRichard Henderson static bool raise_unimpfpop(DisasContext *dc) 259106c060d9SRichard Henderson { 259206c060d9SRichard Henderson gen_op_fpexception_im(dc, FSR_FTT_UNIMPFPOP); 259306c060d9SRichard Henderson return true; 259406c060d9SRichard Henderson } 259506c060d9SRichard Henderson 259606c060d9SRichard Henderson static bool gen_trap_float128(DisasContext *dc) 259706c060d9SRichard Henderson { 259806c060d9SRichard Henderson if (dc->def->features & CPU_FEATURE_FLOAT128) { 259906c060d9SRichard Henderson return false; 260006c060d9SRichard Henderson } 260106c060d9SRichard Henderson return raise_unimpfpop(dc); 260206c060d9SRichard Henderson } 260306c060d9SRichard Henderson 2604276567aaSRichard Henderson static bool do_bpcc(DisasContext *dc, arg_bcc *a) 2605276567aaSRichard Henderson { 2606276567aaSRichard Henderson target_long target = address_mask_i(dc, dc->pc + a->i * 4); 26071ea9c62aSRichard Henderson DisasCompare cmp; 2608276567aaSRichard Henderson 2609276567aaSRichard Henderson switch (a->cond) { 2610276567aaSRichard Henderson case 0x0: 2611276567aaSRichard Henderson return advance_jump_uncond_never(dc, a->a); 2612276567aaSRichard Henderson case 0x8: 2613276567aaSRichard Henderson return advance_jump_uncond_always(dc, a->a, target); 2614276567aaSRichard Henderson default: 2615276567aaSRichard Henderson flush_cond(dc); 26161ea9c62aSRichard Henderson 26171ea9c62aSRichard Henderson gen_compare(&cmp, a->cc, a->cond, dc); 26189d4e2bc7SRichard Henderson return advance_jump_cond(dc, &cmp, a->a, target); 2619276567aaSRichard Henderson } 2620276567aaSRichard Henderson } 2621276567aaSRichard Henderson 2622276567aaSRichard Henderson TRANS(Bicc, ALL, do_bpcc, a) 2623276567aaSRichard Henderson TRANS(BPcc, 64, do_bpcc, a) 2624276567aaSRichard Henderson 262545196ea4SRichard Henderson static bool do_fbpfcc(DisasContext *dc, arg_bcc *a) 262645196ea4SRichard Henderson { 262745196ea4SRichard Henderson target_long target = address_mask_i(dc, dc->pc + a->i * 4); 2628d5471936SRichard Henderson DisasCompare cmp; 262945196ea4SRichard Henderson 263045196ea4SRichard Henderson if (gen_trap_ifnofpu(dc)) { 263145196ea4SRichard Henderson return true; 263245196ea4SRichard Henderson } 263345196ea4SRichard Henderson switch (a->cond) { 263445196ea4SRichard Henderson case 0x0: 263545196ea4SRichard Henderson return advance_jump_uncond_never(dc, a->a); 263645196ea4SRichard Henderson case 0x8: 263745196ea4SRichard Henderson return advance_jump_uncond_always(dc, a->a, target); 263845196ea4SRichard Henderson default: 263945196ea4SRichard Henderson flush_cond(dc); 2640d5471936SRichard Henderson 2641d5471936SRichard Henderson gen_fcompare(&cmp, a->cc, a->cond); 26429d4e2bc7SRichard Henderson return advance_jump_cond(dc, &cmp, a->a, target); 264345196ea4SRichard Henderson } 264445196ea4SRichard Henderson } 264545196ea4SRichard Henderson 264645196ea4SRichard Henderson TRANS(FBPfcc, 64, do_fbpfcc, a) 264745196ea4SRichard Henderson TRANS(FBfcc, ALL, do_fbpfcc, a) 264845196ea4SRichard Henderson 2649ab9ffe98SRichard Henderson static bool trans_BPr(DisasContext *dc, arg_BPr *a) 2650ab9ffe98SRichard Henderson { 2651ab9ffe98SRichard Henderson target_long target = address_mask_i(dc, dc->pc + a->i * 4); 2652ab9ffe98SRichard Henderson DisasCompare cmp; 2653ab9ffe98SRichard Henderson 2654ab9ffe98SRichard Henderson if (!avail_64(dc)) { 2655ab9ffe98SRichard Henderson return false; 2656ab9ffe98SRichard Henderson } 2657ab9ffe98SRichard Henderson if (gen_tcg_cond_reg[a->cond] == TCG_COND_NEVER) { 2658ab9ffe98SRichard Henderson return false; 2659ab9ffe98SRichard Henderson } 2660ab9ffe98SRichard Henderson 2661ab9ffe98SRichard Henderson flush_cond(dc); 2662ab9ffe98SRichard Henderson gen_compare_reg(&cmp, a->cond, gen_load_gpr(dc, a->rs1)); 26639d4e2bc7SRichard Henderson return advance_jump_cond(dc, &cmp, a->a, target); 2664ab9ffe98SRichard Henderson } 2665ab9ffe98SRichard Henderson 266623ada1b1SRichard Henderson static bool trans_CALL(DisasContext *dc, arg_CALL *a) 266723ada1b1SRichard Henderson { 266823ada1b1SRichard Henderson target_long target = address_mask_i(dc, dc->pc + a->i * 4); 266923ada1b1SRichard Henderson 267023ada1b1SRichard Henderson gen_store_gpr(dc, 15, tcg_constant_tl(dc->pc)); 267123ada1b1SRichard Henderson gen_mov_pc_npc(dc); 267223ada1b1SRichard Henderson dc->npc = target; 267323ada1b1SRichard Henderson return true; 267423ada1b1SRichard Henderson } 267523ada1b1SRichard Henderson 267645196ea4SRichard Henderson static bool trans_NCP(DisasContext *dc, arg_NCP *a) 267745196ea4SRichard Henderson { 267845196ea4SRichard Henderson /* 267945196ea4SRichard Henderson * For sparc32, always generate the no-coprocessor exception. 268045196ea4SRichard Henderson * For sparc64, always generate illegal instruction. 268145196ea4SRichard Henderson */ 268245196ea4SRichard Henderson #ifdef TARGET_SPARC64 268345196ea4SRichard Henderson return false; 268445196ea4SRichard Henderson #else 268545196ea4SRichard Henderson gen_exception(dc, TT_NCP_INSN); 268645196ea4SRichard Henderson return true; 268745196ea4SRichard Henderson #endif 268845196ea4SRichard Henderson } 268945196ea4SRichard Henderson 26906d2a0768SRichard Henderson static bool trans_SETHI(DisasContext *dc, arg_SETHI *a) 26916d2a0768SRichard Henderson { 26926d2a0768SRichard Henderson /* Special-case %g0 because that's the canonical nop. */ 26936d2a0768SRichard Henderson if (a->rd) { 26946d2a0768SRichard Henderson gen_store_gpr(dc, a->rd, tcg_constant_tl((uint32_t)a->i << 10)); 26956d2a0768SRichard Henderson } 26966d2a0768SRichard Henderson return advance_pc(dc); 26976d2a0768SRichard Henderson } 26986d2a0768SRichard Henderson 26990faef01bSRichard Henderson /* 27000faef01bSRichard Henderson * Major Opcode 10 -- integer, floating-point, vis, and system insns. 27010faef01bSRichard Henderson */ 27020faef01bSRichard Henderson 270330376636SRichard Henderson static bool do_tcc(DisasContext *dc, int cond, int cc, 270430376636SRichard Henderson int rs1, bool imm, int rs2_or_imm) 270530376636SRichard Henderson { 270630376636SRichard Henderson int mask = ((dc->def->features & CPU_FEATURE_HYPV) && supervisor(dc) 270730376636SRichard Henderson ? UA2005_HTRAP_MASK : V8_TRAP_MASK); 270830376636SRichard Henderson DisasCompare cmp; 270930376636SRichard Henderson TCGLabel *lab; 271030376636SRichard Henderson TCGv_i32 trap; 271130376636SRichard Henderson 271230376636SRichard Henderson /* Trap never. */ 271330376636SRichard Henderson if (cond == 0) { 271430376636SRichard Henderson return advance_pc(dc); 271530376636SRichard Henderson } 271630376636SRichard Henderson 271730376636SRichard Henderson /* 271830376636SRichard Henderson * Immediate traps are the most common case. Since this value is 271930376636SRichard Henderson * live across the branch, it really pays to evaluate the constant. 272030376636SRichard Henderson */ 272130376636SRichard Henderson if (rs1 == 0 && (imm || rs2_or_imm == 0)) { 272230376636SRichard Henderson trap = tcg_constant_i32((rs2_or_imm & mask) + TT_TRAP); 272330376636SRichard Henderson } else { 272430376636SRichard Henderson trap = tcg_temp_new_i32(); 272530376636SRichard Henderson tcg_gen_trunc_tl_i32(trap, gen_load_gpr(dc, rs1)); 272630376636SRichard Henderson if (imm) { 272730376636SRichard Henderson tcg_gen_addi_i32(trap, trap, rs2_or_imm); 272830376636SRichard Henderson } else { 272930376636SRichard Henderson TCGv_i32 t2 = tcg_temp_new_i32(); 273030376636SRichard Henderson tcg_gen_trunc_tl_i32(t2, gen_load_gpr(dc, rs2_or_imm)); 273130376636SRichard Henderson tcg_gen_add_i32(trap, trap, t2); 273230376636SRichard Henderson } 273330376636SRichard Henderson tcg_gen_andi_i32(trap, trap, mask); 273430376636SRichard Henderson tcg_gen_addi_i32(trap, trap, TT_TRAP); 273530376636SRichard Henderson } 273630376636SRichard Henderson 273730376636SRichard Henderson /* Trap always. */ 273830376636SRichard Henderson if (cond == 8) { 273930376636SRichard Henderson save_state(dc); 274030376636SRichard Henderson gen_helper_raise_exception(tcg_env, trap); 274130376636SRichard Henderson dc->base.is_jmp = DISAS_NORETURN; 274230376636SRichard Henderson return true; 274330376636SRichard Henderson } 274430376636SRichard Henderson 274530376636SRichard Henderson /* Conditional trap. */ 274630376636SRichard Henderson flush_cond(dc); 274730376636SRichard Henderson lab = delay_exceptionv(dc, trap); 274830376636SRichard Henderson gen_compare(&cmp, cc, cond, dc); 274930376636SRichard Henderson tcg_gen_brcond_tl(cmp.cond, cmp.c1, cmp.c2, lab); 275030376636SRichard Henderson 275130376636SRichard Henderson return advance_pc(dc); 275230376636SRichard Henderson } 275330376636SRichard Henderson 275430376636SRichard Henderson static bool trans_Tcc_r(DisasContext *dc, arg_Tcc_r *a) 275530376636SRichard Henderson { 275630376636SRichard Henderson if (avail_32(dc) && a->cc) { 275730376636SRichard Henderson return false; 275830376636SRichard Henderson } 275930376636SRichard Henderson return do_tcc(dc, a->cond, a->cc, a->rs1, false, a->rs2); 276030376636SRichard Henderson } 276130376636SRichard Henderson 276230376636SRichard Henderson static bool trans_Tcc_i_v7(DisasContext *dc, arg_Tcc_i_v7 *a) 276330376636SRichard Henderson { 276430376636SRichard Henderson if (avail_64(dc)) { 276530376636SRichard Henderson return false; 276630376636SRichard Henderson } 276730376636SRichard Henderson return do_tcc(dc, a->cond, 0, a->rs1, true, a->i); 276830376636SRichard Henderson } 276930376636SRichard Henderson 277030376636SRichard Henderson static bool trans_Tcc_i_v9(DisasContext *dc, arg_Tcc_i_v9 *a) 277130376636SRichard Henderson { 277230376636SRichard Henderson if (avail_32(dc)) { 277330376636SRichard Henderson return false; 277430376636SRichard Henderson } 277530376636SRichard Henderson return do_tcc(dc, a->cond, a->cc, a->rs1, true, a->i); 277630376636SRichard Henderson } 277730376636SRichard Henderson 2778af25071cSRichard Henderson static bool trans_STBAR(DisasContext *dc, arg_STBAR *a) 2779af25071cSRichard Henderson { 2780af25071cSRichard Henderson tcg_gen_mb(TCG_MO_ST_ST | TCG_BAR_SC); 2781af25071cSRichard Henderson return advance_pc(dc); 2782af25071cSRichard Henderson } 2783af25071cSRichard Henderson 2784af25071cSRichard Henderson static bool trans_MEMBAR(DisasContext *dc, arg_MEMBAR *a) 2785af25071cSRichard Henderson { 2786af25071cSRichard Henderson if (avail_32(dc)) { 2787af25071cSRichard Henderson return false; 2788af25071cSRichard Henderson } 2789af25071cSRichard Henderson if (a->mmask) { 2790af25071cSRichard Henderson /* Note TCG_MO_* was modeled on sparc64, so mmask matches. */ 2791af25071cSRichard Henderson tcg_gen_mb(a->mmask | TCG_BAR_SC); 2792af25071cSRichard Henderson } 2793af25071cSRichard Henderson if (a->cmask) { 2794af25071cSRichard Henderson /* For #Sync, etc, end the TB to recognize interrupts. */ 2795af25071cSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 2796af25071cSRichard Henderson } 2797af25071cSRichard Henderson return advance_pc(dc); 2798af25071cSRichard Henderson } 2799af25071cSRichard Henderson 2800af25071cSRichard Henderson static bool do_rd_special(DisasContext *dc, bool priv, int rd, 2801af25071cSRichard Henderson TCGv (*func)(DisasContext *, TCGv)) 2802af25071cSRichard Henderson { 2803af25071cSRichard Henderson if (!priv) { 2804af25071cSRichard Henderson return raise_priv(dc); 2805af25071cSRichard Henderson } 2806af25071cSRichard Henderson gen_store_gpr(dc, rd, func(dc, gen_dest_gpr(dc, rd))); 2807af25071cSRichard Henderson return advance_pc(dc); 2808af25071cSRichard Henderson } 2809af25071cSRichard Henderson 2810af25071cSRichard Henderson static TCGv do_rdy(DisasContext *dc, TCGv dst) 2811af25071cSRichard Henderson { 2812af25071cSRichard Henderson return cpu_y; 2813af25071cSRichard Henderson } 2814af25071cSRichard Henderson 2815af25071cSRichard Henderson static bool trans_RDY(DisasContext *dc, arg_RDY *a) 2816af25071cSRichard Henderson { 2817af25071cSRichard Henderson /* 2818af25071cSRichard Henderson * TODO: Need a feature bit for sparcv8. In the meantime, treat all 2819af25071cSRichard Henderson * 32-bit cpus like sparcv7, which ignores the rs1 field. 2820af25071cSRichard Henderson * This matches after all other ASR, so Leon3 Asr17 is handled first. 2821af25071cSRichard Henderson */ 2822af25071cSRichard Henderson if (avail_64(dc) && a->rs1 != 0) { 2823af25071cSRichard Henderson return false; 2824af25071cSRichard Henderson } 2825af25071cSRichard Henderson return do_rd_special(dc, true, a->rd, do_rdy); 2826af25071cSRichard Henderson } 2827af25071cSRichard Henderson 2828af25071cSRichard Henderson static TCGv do_rd_leon3_config(DisasContext *dc, TCGv dst) 2829af25071cSRichard Henderson { 2830af25071cSRichard Henderson uint32_t val; 2831af25071cSRichard Henderson 2832af25071cSRichard Henderson /* 2833af25071cSRichard Henderson * TODO: There are many more fields to be filled, 2834af25071cSRichard Henderson * some of which are writable. 2835af25071cSRichard Henderson */ 2836af25071cSRichard Henderson val = dc->def->nwindows - 1; /* [4:0] NWIN */ 2837af25071cSRichard Henderson val |= 1 << 8; /* [8] V8 */ 2838af25071cSRichard Henderson 2839af25071cSRichard Henderson return tcg_constant_tl(val); 2840af25071cSRichard Henderson } 2841af25071cSRichard Henderson 2842af25071cSRichard Henderson TRANS(RDASR17, ASR17, do_rd_special, true, a->rd, do_rd_leon3_config) 2843af25071cSRichard Henderson 2844af25071cSRichard Henderson static TCGv do_rdccr(DisasContext *dc, TCGv dst) 2845af25071cSRichard Henderson { 2846af25071cSRichard Henderson update_psr(dc); 2847af25071cSRichard Henderson gen_helper_rdccr(dst, tcg_env); 2848af25071cSRichard Henderson return dst; 2849af25071cSRichard Henderson } 2850af25071cSRichard Henderson 2851af25071cSRichard Henderson TRANS(RDCCR, 64, do_rd_special, true, a->rd, do_rdccr) 2852af25071cSRichard Henderson 2853af25071cSRichard Henderson static TCGv do_rdasi(DisasContext *dc, TCGv dst) 2854af25071cSRichard Henderson { 2855af25071cSRichard Henderson #ifdef TARGET_SPARC64 2856af25071cSRichard Henderson return tcg_constant_tl(dc->asi); 2857af25071cSRichard Henderson #else 2858af25071cSRichard Henderson qemu_build_not_reached(); 2859af25071cSRichard Henderson #endif 2860af25071cSRichard Henderson } 2861af25071cSRichard Henderson 2862af25071cSRichard Henderson TRANS(RDASI, 64, do_rd_special, true, a->rd, do_rdasi) 2863af25071cSRichard Henderson 2864af25071cSRichard Henderson static TCGv do_rdtick(DisasContext *dc, TCGv dst) 2865af25071cSRichard Henderson { 2866af25071cSRichard Henderson TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 2867af25071cSRichard Henderson 2868af25071cSRichard Henderson tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(tick)); 2869af25071cSRichard Henderson if (translator_io_start(&dc->base)) { 2870af25071cSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 2871af25071cSRichard Henderson } 2872af25071cSRichard Henderson gen_helper_tick_get_count(dst, tcg_env, r_tickptr, 2873af25071cSRichard Henderson tcg_constant_i32(dc->mem_idx)); 2874af25071cSRichard Henderson return dst; 2875af25071cSRichard Henderson } 2876af25071cSRichard Henderson 2877af25071cSRichard Henderson /* TODO: non-priv access only allowed when enabled. */ 2878af25071cSRichard Henderson TRANS(RDTICK, 64, do_rd_special, true, a->rd, do_rdtick) 2879af25071cSRichard Henderson 2880af25071cSRichard Henderson static TCGv do_rdpc(DisasContext *dc, TCGv dst) 2881af25071cSRichard Henderson { 2882af25071cSRichard Henderson return tcg_constant_tl(address_mask_i(dc, dc->pc)); 2883af25071cSRichard Henderson } 2884af25071cSRichard Henderson 2885af25071cSRichard Henderson TRANS(RDPC, 64, do_rd_special, true, a->rd, do_rdpc) 2886af25071cSRichard Henderson 2887af25071cSRichard Henderson static TCGv do_rdfprs(DisasContext *dc, TCGv dst) 2888af25071cSRichard Henderson { 2889af25071cSRichard Henderson tcg_gen_ext_i32_tl(dst, cpu_fprs); 2890af25071cSRichard Henderson return dst; 2891af25071cSRichard Henderson } 2892af25071cSRichard Henderson 2893af25071cSRichard Henderson TRANS(RDFPRS, 64, do_rd_special, true, a->rd, do_rdfprs) 2894af25071cSRichard Henderson 2895af25071cSRichard Henderson static TCGv do_rdgsr(DisasContext *dc, TCGv dst) 2896af25071cSRichard Henderson { 2897af25071cSRichard Henderson gen_trap_ifnofpu(dc); 2898af25071cSRichard Henderson return cpu_gsr; 2899af25071cSRichard Henderson } 2900af25071cSRichard Henderson 2901af25071cSRichard Henderson TRANS(RDGSR, 64, do_rd_special, true, a->rd, do_rdgsr) 2902af25071cSRichard Henderson 2903af25071cSRichard Henderson static TCGv do_rdsoftint(DisasContext *dc, TCGv dst) 2904af25071cSRichard Henderson { 2905af25071cSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(softint)); 2906af25071cSRichard Henderson return dst; 2907af25071cSRichard Henderson } 2908af25071cSRichard Henderson 2909af25071cSRichard Henderson TRANS(RDSOFTINT, 64, do_rd_special, supervisor(dc), a->rd, do_rdsoftint) 2910af25071cSRichard Henderson 2911af25071cSRichard Henderson static TCGv do_rdtick_cmpr(DisasContext *dc, TCGv dst) 2912af25071cSRichard Henderson { 2913577efa45SRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(tick_cmpr)); 2914577efa45SRichard Henderson return dst; 2915af25071cSRichard Henderson } 2916af25071cSRichard Henderson 2917af25071cSRichard Henderson /* TODO: non-priv access only allowed when enabled. */ 2918af25071cSRichard Henderson TRANS(RDTICK_CMPR, 64, do_rd_special, true, a->rd, do_rdtick_cmpr) 2919af25071cSRichard Henderson 2920af25071cSRichard Henderson static TCGv do_rdstick(DisasContext *dc, TCGv dst) 2921af25071cSRichard Henderson { 2922af25071cSRichard Henderson TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 2923af25071cSRichard Henderson 2924af25071cSRichard Henderson tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(stick)); 2925af25071cSRichard Henderson if (translator_io_start(&dc->base)) { 2926af25071cSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 2927af25071cSRichard Henderson } 2928af25071cSRichard Henderson gen_helper_tick_get_count(dst, tcg_env, r_tickptr, 2929af25071cSRichard Henderson tcg_constant_i32(dc->mem_idx)); 2930af25071cSRichard Henderson return dst; 2931af25071cSRichard Henderson } 2932af25071cSRichard Henderson 2933af25071cSRichard Henderson /* TODO: non-priv access only allowed when enabled. */ 2934af25071cSRichard Henderson TRANS(RDSTICK, 64, do_rd_special, true, a->rd, do_rdstick) 2935af25071cSRichard Henderson 2936af25071cSRichard Henderson static TCGv do_rdstick_cmpr(DisasContext *dc, TCGv dst) 2937af25071cSRichard Henderson { 2938577efa45SRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(stick_cmpr)); 2939577efa45SRichard Henderson return dst; 2940af25071cSRichard Henderson } 2941af25071cSRichard Henderson 2942af25071cSRichard Henderson /* TODO: supervisor access only allowed when enabled by hypervisor. */ 2943af25071cSRichard Henderson TRANS(RDSTICK_CMPR, 64, do_rd_special, supervisor(dc), a->rd, do_rdstick_cmpr) 2944af25071cSRichard Henderson 2945af25071cSRichard Henderson /* 2946af25071cSRichard Henderson * UltraSPARC-T1 Strand status. 2947af25071cSRichard Henderson * HYPV check maybe not enough, UA2005 & UA2007 describe 2948af25071cSRichard Henderson * this ASR as impl. dep 2949af25071cSRichard Henderson */ 2950af25071cSRichard Henderson static TCGv do_rdstrand_status(DisasContext *dc, TCGv dst) 2951af25071cSRichard Henderson { 2952af25071cSRichard Henderson return tcg_constant_tl(1); 2953af25071cSRichard Henderson } 2954af25071cSRichard Henderson 2955af25071cSRichard Henderson TRANS(RDSTRAND_STATUS, HYPV, do_rd_special, true, a->rd, do_rdstrand_status) 2956af25071cSRichard Henderson 2957668bb9b7SRichard Henderson static TCGv do_rdpsr(DisasContext *dc, TCGv dst) 2958668bb9b7SRichard Henderson { 2959668bb9b7SRichard Henderson update_psr(dc); 2960668bb9b7SRichard Henderson gen_helper_rdpsr(dst, tcg_env); 2961668bb9b7SRichard Henderson return dst; 2962668bb9b7SRichard Henderson } 2963668bb9b7SRichard Henderson 2964668bb9b7SRichard Henderson TRANS(RDPSR, 32, do_rd_special, supervisor(dc), a->rd, do_rdpsr) 2965668bb9b7SRichard Henderson 2966668bb9b7SRichard Henderson static TCGv do_rdhpstate(DisasContext *dc, TCGv dst) 2967668bb9b7SRichard Henderson { 2968668bb9b7SRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hpstate)); 2969668bb9b7SRichard Henderson return dst; 2970668bb9b7SRichard Henderson } 2971668bb9b7SRichard Henderson 2972668bb9b7SRichard Henderson TRANS(RDHPR_hpstate, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhpstate) 2973668bb9b7SRichard Henderson 2974668bb9b7SRichard Henderson static TCGv do_rdhtstate(DisasContext *dc, TCGv dst) 2975668bb9b7SRichard Henderson { 2976668bb9b7SRichard Henderson TCGv_i32 tl = tcg_temp_new_i32(); 2977668bb9b7SRichard Henderson TCGv_ptr tp = tcg_temp_new_ptr(); 2978668bb9b7SRichard Henderson 2979668bb9b7SRichard Henderson tcg_gen_ld_i32(tl, tcg_env, env64_field_offsetof(tl)); 2980668bb9b7SRichard Henderson tcg_gen_andi_i32(tl, tl, MAXTL_MASK); 2981668bb9b7SRichard Henderson tcg_gen_shli_i32(tl, tl, 3); 2982668bb9b7SRichard Henderson tcg_gen_ext_i32_ptr(tp, tl); 2983668bb9b7SRichard Henderson tcg_gen_add_ptr(tp, tp, tcg_env); 2984668bb9b7SRichard Henderson 2985668bb9b7SRichard Henderson tcg_gen_ld_tl(dst, tp, env64_field_offsetof(htstate)); 2986668bb9b7SRichard Henderson return dst; 2987668bb9b7SRichard Henderson } 2988668bb9b7SRichard Henderson 2989668bb9b7SRichard Henderson TRANS(RDHPR_htstate, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhtstate) 2990668bb9b7SRichard Henderson 2991668bb9b7SRichard Henderson static TCGv do_rdhintp(DisasContext *dc, TCGv dst) 2992668bb9b7SRichard Henderson { 29932da789deSRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hintp)); 29942da789deSRichard Henderson return dst; 2995668bb9b7SRichard Henderson } 2996668bb9b7SRichard Henderson 2997668bb9b7SRichard Henderson TRANS(RDHPR_hintp, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhintp) 2998668bb9b7SRichard Henderson 2999668bb9b7SRichard Henderson static TCGv do_rdhtba(DisasContext *dc, TCGv dst) 3000668bb9b7SRichard Henderson { 30012da789deSRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(htba)); 30022da789deSRichard Henderson return dst; 3003668bb9b7SRichard Henderson } 3004668bb9b7SRichard Henderson 3005668bb9b7SRichard Henderson TRANS(RDHPR_htba, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhtba) 3006668bb9b7SRichard Henderson 3007668bb9b7SRichard Henderson static TCGv do_rdhver(DisasContext *dc, TCGv dst) 3008668bb9b7SRichard Henderson { 30092da789deSRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hver)); 30102da789deSRichard Henderson return dst; 3011668bb9b7SRichard Henderson } 3012668bb9b7SRichard Henderson 3013668bb9b7SRichard Henderson TRANS(RDHPR_hver, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhver) 3014668bb9b7SRichard Henderson 3015668bb9b7SRichard Henderson static TCGv do_rdhstick_cmpr(DisasContext *dc, TCGv dst) 3016668bb9b7SRichard Henderson { 3017577efa45SRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hstick_cmpr)); 3018577efa45SRichard Henderson return dst; 3019668bb9b7SRichard Henderson } 3020668bb9b7SRichard Henderson 3021668bb9b7SRichard Henderson TRANS(RDHPR_hstick_cmpr, HYPV, do_rd_special, hypervisor(dc), a->rd, 3022668bb9b7SRichard Henderson do_rdhstick_cmpr) 3023668bb9b7SRichard Henderson 30245d617bfbSRichard Henderson static TCGv do_rdwim(DisasContext *dc, TCGv dst) 30255d617bfbSRichard Henderson { 3026cd6269f7SRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env32_field_offsetof(wim)); 3027cd6269f7SRichard Henderson return dst; 30285d617bfbSRichard Henderson } 30295d617bfbSRichard Henderson 30305d617bfbSRichard Henderson TRANS(RDWIM, 32, do_rd_special, supervisor(dc), a->rd, do_rdwim) 30315d617bfbSRichard Henderson 30325d617bfbSRichard Henderson static TCGv do_rdtpc(DisasContext *dc, TCGv dst) 30335d617bfbSRichard Henderson { 30345d617bfbSRichard Henderson #ifdef TARGET_SPARC64 30355d617bfbSRichard Henderson TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 30365d617bfbSRichard Henderson 30375d617bfbSRichard Henderson gen_load_trap_state_at_tl(r_tsptr); 30385d617bfbSRichard Henderson tcg_gen_ld_tl(dst, r_tsptr, offsetof(trap_state, tpc)); 30395d617bfbSRichard Henderson return dst; 30405d617bfbSRichard Henderson #else 30415d617bfbSRichard Henderson qemu_build_not_reached(); 30425d617bfbSRichard Henderson #endif 30435d617bfbSRichard Henderson } 30445d617bfbSRichard Henderson 30455d617bfbSRichard Henderson TRANS(RDPR_tpc, 64, do_rd_special, supervisor(dc), a->rd, do_rdtpc) 30465d617bfbSRichard Henderson 30475d617bfbSRichard Henderson static TCGv do_rdtnpc(DisasContext *dc, TCGv dst) 30485d617bfbSRichard Henderson { 30495d617bfbSRichard Henderson #ifdef TARGET_SPARC64 30505d617bfbSRichard Henderson TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 30515d617bfbSRichard Henderson 30525d617bfbSRichard Henderson gen_load_trap_state_at_tl(r_tsptr); 30535d617bfbSRichard Henderson tcg_gen_ld_tl(dst, r_tsptr, offsetof(trap_state, tnpc)); 30545d617bfbSRichard Henderson return dst; 30555d617bfbSRichard Henderson #else 30565d617bfbSRichard Henderson qemu_build_not_reached(); 30575d617bfbSRichard Henderson #endif 30585d617bfbSRichard Henderson } 30595d617bfbSRichard Henderson 30605d617bfbSRichard Henderson TRANS(RDPR_tnpc, 64, do_rd_special, supervisor(dc), a->rd, do_rdtnpc) 30615d617bfbSRichard Henderson 30625d617bfbSRichard Henderson static TCGv do_rdtstate(DisasContext *dc, TCGv dst) 30635d617bfbSRichard Henderson { 30645d617bfbSRichard Henderson #ifdef TARGET_SPARC64 30655d617bfbSRichard Henderson TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 30665d617bfbSRichard Henderson 30675d617bfbSRichard Henderson gen_load_trap_state_at_tl(r_tsptr); 30685d617bfbSRichard Henderson tcg_gen_ld_tl(dst, r_tsptr, offsetof(trap_state, tstate)); 30695d617bfbSRichard Henderson return dst; 30705d617bfbSRichard Henderson #else 30715d617bfbSRichard Henderson qemu_build_not_reached(); 30725d617bfbSRichard Henderson #endif 30735d617bfbSRichard Henderson } 30745d617bfbSRichard Henderson 30755d617bfbSRichard Henderson TRANS(RDPR_tstate, 64, do_rd_special, supervisor(dc), a->rd, do_rdtstate) 30765d617bfbSRichard Henderson 30775d617bfbSRichard Henderson static TCGv do_rdtt(DisasContext *dc, TCGv dst) 30785d617bfbSRichard Henderson { 30795d617bfbSRichard Henderson #ifdef TARGET_SPARC64 30805d617bfbSRichard Henderson TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 30815d617bfbSRichard Henderson 30825d617bfbSRichard Henderson gen_load_trap_state_at_tl(r_tsptr); 30835d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, r_tsptr, offsetof(trap_state, tt)); 30845d617bfbSRichard Henderson return dst; 30855d617bfbSRichard Henderson #else 30865d617bfbSRichard Henderson qemu_build_not_reached(); 30875d617bfbSRichard Henderson #endif 30885d617bfbSRichard Henderson } 30895d617bfbSRichard Henderson 30905d617bfbSRichard Henderson TRANS(RDPR_tt, 64, do_rd_special, supervisor(dc), a->rd, do_rdtt) 30915d617bfbSRichard Henderson TRANS(RDPR_tick, 64, do_rd_special, supervisor(dc), a->rd, do_rdtick) 30925d617bfbSRichard Henderson 30935d617bfbSRichard Henderson static TCGv do_rdtba(DisasContext *dc, TCGv dst) 30945d617bfbSRichard Henderson { 30955d617bfbSRichard Henderson return cpu_tbr; 30965d617bfbSRichard Henderson } 30975d617bfbSRichard Henderson 3098e8325dc0SRichard Henderson TRANS(RDTBR, 32, do_rd_special, supervisor(dc), a->rd, do_rdtba) 30995d617bfbSRichard Henderson TRANS(RDPR_tba, 64, do_rd_special, supervisor(dc), a->rd, do_rdtba) 31005d617bfbSRichard Henderson 31015d617bfbSRichard Henderson static TCGv do_rdpstate(DisasContext *dc, TCGv dst) 31025d617bfbSRichard Henderson { 31035d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(pstate)); 31045d617bfbSRichard Henderson return dst; 31055d617bfbSRichard Henderson } 31065d617bfbSRichard Henderson 31075d617bfbSRichard Henderson TRANS(RDPR_pstate, 64, do_rd_special, supervisor(dc), a->rd, do_rdpstate) 31085d617bfbSRichard Henderson 31095d617bfbSRichard Henderson static TCGv do_rdtl(DisasContext *dc, TCGv dst) 31105d617bfbSRichard Henderson { 31115d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(tl)); 31125d617bfbSRichard Henderson return dst; 31135d617bfbSRichard Henderson } 31145d617bfbSRichard Henderson 31155d617bfbSRichard Henderson TRANS(RDPR_tl, 64, do_rd_special, supervisor(dc), a->rd, do_rdtl) 31165d617bfbSRichard Henderson 31175d617bfbSRichard Henderson static TCGv do_rdpil(DisasContext *dc, TCGv dst) 31185d617bfbSRichard Henderson { 31195d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env_field_offsetof(psrpil)); 31205d617bfbSRichard Henderson return dst; 31215d617bfbSRichard Henderson } 31225d617bfbSRichard Henderson 31235d617bfbSRichard Henderson TRANS(RDPR_pil, 64, do_rd_special, supervisor(dc), a->rd, do_rdpil) 31245d617bfbSRichard Henderson 31255d617bfbSRichard Henderson static TCGv do_rdcwp(DisasContext *dc, TCGv dst) 31265d617bfbSRichard Henderson { 31275d617bfbSRichard Henderson gen_helper_rdcwp(dst, tcg_env); 31285d617bfbSRichard Henderson return dst; 31295d617bfbSRichard Henderson } 31305d617bfbSRichard Henderson 31315d617bfbSRichard Henderson TRANS(RDPR_cwp, 64, do_rd_special, supervisor(dc), a->rd, do_rdcwp) 31325d617bfbSRichard Henderson 31335d617bfbSRichard Henderson static TCGv do_rdcansave(DisasContext *dc, TCGv dst) 31345d617bfbSRichard Henderson { 31355d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(cansave)); 31365d617bfbSRichard Henderson return dst; 31375d617bfbSRichard Henderson } 31385d617bfbSRichard Henderson 31395d617bfbSRichard Henderson TRANS(RDPR_cansave, 64, do_rd_special, supervisor(dc), a->rd, do_rdcansave) 31405d617bfbSRichard Henderson 31415d617bfbSRichard Henderson static TCGv do_rdcanrestore(DisasContext *dc, TCGv dst) 31425d617bfbSRichard Henderson { 31435d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(canrestore)); 31445d617bfbSRichard Henderson return dst; 31455d617bfbSRichard Henderson } 31465d617bfbSRichard Henderson 31475d617bfbSRichard Henderson TRANS(RDPR_canrestore, 64, do_rd_special, supervisor(dc), a->rd, 31485d617bfbSRichard Henderson do_rdcanrestore) 31495d617bfbSRichard Henderson 31505d617bfbSRichard Henderson static TCGv do_rdcleanwin(DisasContext *dc, TCGv dst) 31515d617bfbSRichard Henderson { 31525d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(cleanwin)); 31535d617bfbSRichard Henderson return dst; 31545d617bfbSRichard Henderson } 31555d617bfbSRichard Henderson 31565d617bfbSRichard Henderson TRANS(RDPR_cleanwin, 64, do_rd_special, supervisor(dc), a->rd, do_rdcleanwin) 31575d617bfbSRichard Henderson 31585d617bfbSRichard Henderson static TCGv do_rdotherwin(DisasContext *dc, TCGv dst) 31595d617bfbSRichard Henderson { 31605d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(otherwin)); 31615d617bfbSRichard Henderson return dst; 31625d617bfbSRichard Henderson } 31635d617bfbSRichard Henderson 31645d617bfbSRichard Henderson TRANS(RDPR_otherwin, 64, do_rd_special, supervisor(dc), a->rd, do_rdotherwin) 31655d617bfbSRichard Henderson 31665d617bfbSRichard Henderson static TCGv do_rdwstate(DisasContext *dc, TCGv dst) 31675d617bfbSRichard Henderson { 31685d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(wstate)); 31695d617bfbSRichard Henderson return dst; 31705d617bfbSRichard Henderson } 31715d617bfbSRichard Henderson 31725d617bfbSRichard Henderson TRANS(RDPR_wstate, 64, do_rd_special, supervisor(dc), a->rd, do_rdwstate) 31735d617bfbSRichard Henderson 31745d617bfbSRichard Henderson static TCGv do_rdgl(DisasContext *dc, TCGv dst) 31755d617bfbSRichard Henderson { 31765d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(gl)); 31775d617bfbSRichard Henderson return dst; 31785d617bfbSRichard Henderson } 31795d617bfbSRichard Henderson 31805d617bfbSRichard Henderson TRANS(RDPR_gl, GL, do_rd_special, supervisor(dc), a->rd, do_rdgl) 31815d617bfbSRichard Henderson 31825d617bfbSRichard Henderson /* UA2005 strand status */ 31835d617bfbSRichard Henderson static TCGv do_rdssr(DisasContext *dc, TCGv dst) 31845d617bfbSRichard Henderson { 31852da789deSRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(ssr)); 31862da789deSRichard Henderson return dst; 31875d617bfbSRichard Henderson } 31885d617bfbSRichard Henderson 31895d617bfbSRichard Henderson TRANS(RDPR_strand_status, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdssr) 31905d617bfbSRichard Henderson 31915d617bfbSRichard Henderson static TCGv do_rdver(DisasContext *dc, TCGv dst) 31925d617bfbSRichard Henderson { 31932da789deSRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(version)); 31942da789deSRichard Henderson return dst; 31955d617bfbSRichard Henderson } 31965d617bfbSRichard Henderson 31975d617bfbSRichard Henderson TRANS(RDPR_ver, 64, do_rd_special, supervisor(dc), a->rd, do_rdver) 31985d617bfbSRichard Henderson 3199e8325dc0SRichard Henderson static bool trans_FLUSHW(DisasContext *dc, arg_FLUSHW *a) 3200e8325dc0SRichard Henderson { 3201e8325dc0SRichard Henderson if (avail_64(dc)) { 3202e8325dc0SRichard Henderson gen_helper_flushw(tcg_env); 3203e8325dc0SRichard Henderson return advance_pc(dc); 3204e8325dc0SRichard Henderson } 3205e8325dc0SRichard Henderson return false; 3206e8325dc0SRichard Henderson } 3207e8325dc0SRichard Henderson 32080faef01bSRichard Henderson static bool do_wr_special(DisasContext *dc, arg_r_r_ri *a, bool priv, 32090faef01bSRichard Henderson void (*func)(DisasContext *, TCGv)) 32100faef01bSRichard Henderson { 32110faef01bSRichard Henderson TCGv src; 32120faef01bSRichard Henderson 32130faef01bSRichard Henderson /* For simplicity, we under-decoded the rs2 form. */ 32140faef01bSRichard Henderson if (!a->imm && (a->rs2_or_imm & ~0x1f)) { 32150faef01bSRichard Henderson return false; 32160faef01bSRichard Henderson } 32170faef01bSRichard Henderson if (!priv) { 32180faef01bSRichard Henderson return raise_priv(dc); 32190faef01bSRichard Henderson } 32200faef01bSRichard Henderson 32210faef01bSRichard Henderson if (a->rs1 == 0 && (a->imm || a->rs2_or_imm == 0)) { 32220faef01bSRichard Henderson src = tcg_constant_tl(a->rs2_or_imm); 32230faef01bSRichard Henderson } else { 32240faef01bSRichard Henderson TCGv src1 = gen_load_gpr(dc, a->rs1); 32250faef01bSRichard Henderson if (a->rs2_or_imm == 0) { 32260faef01bSRichard Henderson src = src1; 32270faef01bSRichard Henderson } else { 32280faef01bSRichard Henderson src = tcg_temp_new(); 32290faef01bSRichard Henderson if (a->imm) { 32300faef01bSRichard Henderson tcg_gen_xori_tl(src, src1, a->rs2_or_imm); 32310faef01bSRichard Henderson } else { 32320faef01bSRichard Henderson tcg_gen_xor_tl(src, src1, gen_load_gpr(dc, a->rs2_or_imm)); 32330faef01bSRichard Henderson } 32340faef01bSRichard Henderson } 32350faef01bSRichard Henderson } 32360faef01bSRichard Henderson func(dc, src); 32370faef01bSRichard Henderson return advance_pc(dc); 32380faef01bSRichard Henderson } 32390faef01bSRichard Henderson 32400faef01bSRichard Henderson static void do_wry(DisasContext *dc, TCGv src) 32410faef01bSRichard Henderson { 32420faef01bSRichard Henderson tcg_gen_ext32u_tl(cpu_y, src); 32430faef01bSRichard Henderson } 32440faef01bSRichard Henderson 32450faef01bSRichard Henderson TRANS(WRY, ALL, do_wr_special, a, true, do_wry) 32460faef01bSRichard Henderson 32470faef01bSRichard Henderson static void do_wrccr(DisasContext *dc, TCGv src) 32480faef01bSRichard Henderson { 32490faef01bSRichard Henderson gen_helper_wrccr(tcg_env, src); 32500faef01bSRichard Henderson } 32510faef01bSRichard Henderson 32520faef01bSRichard Henderson TRANS(WRCCR, 64, do_wr_special, a, true, do_wrccr) 32530faef01bSRichard Henderson 32540faef01bSRichard Henderson static void do_wrasi(DisasContext *dc, TCGv src) 32550faef01bSRichard Henderson { 32560faef01bSRichard Henderson TCGv tmp = tcg_temp_new(); 32570faef01bSRichard Henderson 32580faef01bSRichard Henderson tcg_gen_ext8u_tl(tmp, src); 32590faef01bSRichard Henderson tcg_gen_st32_tl(tmp, tcg_env, env64_field_offsetof(asi)); 32600faef01bSRichard Henderson /* End TB to notice changed ASI. */ 32610faef01bSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 32620faef01bSRichard Henderson } 32630faef01bSRichard Henderson 32640faef01bSRichard Henderson TRANS(WRASI, 64, do_wr_special, a, true, do_wrasi) 32650faef01bSRichard Henderson 32660faef01bSRichard Henderson static void do_wrfprs(DisasContext *dc, TCGv src) 32670faef01bSRichard Henderson { 32680faef01bSRichard Henderson #ifdef TARGET_SPARC64 32690faef01bSRichard Henderson tcg_gen_trunc_tl_i32(cpu_fprs, src); 32700faef01bSRichard Henderson dc->fprs_dirty = 0; 32710faef01bSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 32720faef01bSRichard Henderson #else 32730faef01bSRichard Henderson qemu_build_not_reached(); 32740faef01bSRichard Henderson #endif 32750faef01bSRichard Henderson } 32760faef01bSRichard Henderson 32770faef01bSRichard Henderson TRANS(WRFPRS, 64, do_wr_special, a, true, do_wrfprs) 32780faef01bSRichard Henderson 32790faef01bSRichard Henderson static void do_wrgsr(DisasContext *dc, TCGv src) 32800faef01bSRichard Henderson { 32810faef01bSRichard Henderson gen_trap_ifnofpu(dc); 32820faef01bSRichard Henderson tcg_gen_mov_tl(cpu_gsr, src); 32830faef01bSRichard Henderson } 32840faef01bSRichard Henderson 32850faef01bSRichard Henderson TRANS(WRGSR, 64, do_wr_special, a, true, do_wrgsr) 32860faef01bSRichard Henderson 32870faef01bSRichard Henderson static void do_wrsoftint_set(DisasContext *dc, TCGv src) 32880faef01bSRichard Henderson { 32890faef01bSRichard Henderson gen_helper_set_softint(tcg_env, src); 32900faef01bSRichard Henderson } 32910faef01bSRichard Henderson 32920faef01bSRichard Henderson TRANS(WRSOFTINT_SET, 64, do_wr_special, a, supervisor(dc), do_wrsoftint_set) 32930faef01bSRichard Henderson 32940faef01bSRichard Henderson static void do_wrsoftint_clr(DisasContext *dc, TCGv src) 32950faef01bSRichard Henderson { 32960faef01bSRichard Henderson gen_helper_clear_softint(tcg_env, src); 32970faef01bSRichard Henderson } 32980faef01bSRichard Henderson 32990faef01bSRichard Henderson TRANS(WRSOFTINT_CLR, 64, do_wr_special, a, supervisor(dc), do_wrsoftint_clr) 33000faef01bSRichard Henderson 33010faef01bSRichard Henderson static void do_wrsoftint(DisasContext *dc, TCGv src) 33020faef01bSRichard Henderson { 33030faef01bSRichard Henderson gen_helper_write_softint(tcg_env, src); 33040faef01bSRichard Henderson } 33050faef01bSRichard Henderson 33060faef01bSRichard Henderson TRANS(WRSOFTINT, 64, do_wr_special, a, supervisor(dc), do_wrsoftint) 33070faef01bSRichard Henderson 33080faef01bSRichard Henderson static void do_wrtick_cmpr(DisasContext *dc, TCGv src) 33090faef01bSRichard Henderson { 33100faef01bSRichard Henderson TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 33110faef01bSRichard Henderson 3312577efa45SRichard Henderson tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(tick_cmpr)); 3313577efa45SRichard Henderson tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(tick)); 33140faef01bSRichard Henderson translator_io_start(&dc->base); 3315577efa45SRichard Henderson gen_helper_tick_set_limit(r_tickptr, src); 33160faef01bSRichard Henderson /* End TB to handle timer interrupt */ 33170faef01bSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 33180faef01bSRichard Henderson } 33190faef01bSRichard Henderson 33200faef01bSRichard Henderson TRANS(WRTICK_CMPR, 64, do_wr_special, a, supervisor(dc), do_wrtick_cmpr) 33210faef01bSRichard Henderson 33220faef01bSRichard Henderson static void do_wrstick(DisasContext *dc, TCGv src) 33230faef01bSRichard Henderson { 33240faef01bSRichard Henderson #ifdef TARGET_SPARC64 33250faef01bSRichard Henderson TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 33260faef01bSRichard Henderson 33270faef01bSRichard Henderson tcg_gen_ld_ptr(r_tickptr, tcg_env, offsetof(CPUSPARCState, stick)); 33280faef01bSRichard Henderson translator_io_start(&dc->base); 33290faef01bSRichard Henderson gen_helper_tick_set_count(r_tickptr, src); 33300faef01bSRichard Henderson /* End TB to handle timer interrupt */ 33310faef01bSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 33320faef01bSRichard Henderson #else 33330faef01bSRichard Henderson qemu_build_not_reached(); 33340faef01bSRichard Henderson #endif 33350faef01bSRichard Henderson } 33360faef01bSRichard Henderson 33370faef01bSRichard Henderson TRANS(WRSTICK, 64, do_wr_special, a, supervisor(dc), do_wrstick) 33380faef01bSRichard Henderson 33390faef01bSRichard Henderson static void do_wrstick_cmpr(DisasContext *dc, TCGv src) 33400faef01bSRichard Henderson { 33410faef01bSRichard Henderson TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 33420faef01bSRichard Henderson 3343577efa45SRichard Henderson tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(stick_cmpr)); 3344577efa45SRichard Henderson tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(stick)); 33450faef01bSRichard Henderson translator_io_start(&dc->base); 3346577efa45SRichard Henderson gen_helper_tick_set_limit(r_tickptr, src); 33470faef01bSRichard Henderson /* End TB to handle timer interrupt */ 33480faef01bSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 33490faef01bSRichard Henderson } 33500faef01bSRichard Henderson 33510faef01bSRichard Henderson TRANS(WRSTICK_CMPR, 64, do_wr_special, a, supervisor(dc), do_wrstick_cmpr) 33520faef01bSRichard Henderson 33530faef01bSRichard Henderson static void do_wrpowerdown(DisasContext *dc, TCGv src) 33540faef01bSRichard Henderson { 33550faef01bSRichard Henderson save_state(dc); 33560faef01bSRichard Henderson gen_helper_power_down(tcg_env); 33570faef01bSRichard Henderson } 33580faef01bSRichard Henderson 33590faef01bSRichard Henderson TRANS(WRPOWERDOWN, POWERDOWN, do_wr_special, a, supervisor(dc), do_wrpowerdown) 33600faef01bSRichard Henderson 336125524734SRichard Henderson static void do_wrpsr(DisasContext *dc, TCGv src) 336225524734SRichard Henderson { 336325524734SRichard Henderson gen_helper_wrpsr(tcg_env, src); 336425524734SRichard Henderson tcg_gen_movi_i32(cpu_cc_op, CC_OP_FLAGS); 336525524734SRichard Henderson dc->cc_op = CC_OP_FLAGS; 336625524734SRichard Henderson dc->base.is_jmp = DISAS_EXIT; 336725524734SRichard Henderson } 336825524734SRichard Henderson 336925524734SRichard Henderson TRANS(WRPSR, 32, do_wr_special, a, supervisor(dc), do_wrpsr) 337025524734SRichard Henderson 33719422278eSRichard Henderson static void do_wrwim(DisasContext *dc, TCGv src) 33729422278eSRichard Henderson { 33739422278eSRichard Henderson target_ulong mask = MAKE_64BIT_MASK(0, dc->def->nwindows); 3374cd6269f7SRichard Henderson TCGv tmp = tcg_temp_new(); 3375cd6269f7SRichard Henderson 3376cd6269f7SRichard Henderson tcg_gen_andi_tl(tmp, src, mask); 3377cd6269f7SRichard Henderson tcg_gen_st_tl(tmp, tcg_env, env32_field_offsetof(wim)); 33789422278eSRichard Henderson } 33799422278eSRichard Henderson 33809422278eSRichard Henderson TRANS(WRWIM, 32, do_wr_special, a, supervisor(dc), do_wrwim) 33819422278eSRichard Henderson 33829422278eSRichard Henderson static void do_wrtpc(DisasContext *dc, TCGv src) 33839422278eSRichard Henderson { 33849422278eSRichard Henderson #ifdef TARGET_SPARC64 33859422278eSRichard Henderson TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 33869422278eSRichard Henderson 33879422278eSRichard Henderson gen_load_trap_state_at_tl(r_tsptr); 33889422278eSRichard Henderson tcg_gen_st_tl(src, r_tsptr, offsetof(trap_state, tpc)); 33899422278eSRichard Henderson #else 33909422278eSRichard Henderson qemu_build_not_reached(); 33919422278eSRichard Henderson #endif 33929422278eSRichard Henderson } 33939422278eSRichard Henderson 33949422278eSRichard Henderson TRANS(WRPR_tpc, 64, do_wr_special, a, supervisor(dc), do_wrtpc) 33959422278eSRichard Henderson 33969422278eSRichard Henderson static void do_wrtnpc(DisasContext *dc, TCGv src) 33979422278eSRichard Henderson { 33989422278eSRichard Henderson #ifdef TARGET_SPARC64 33999422278eSRichard Henderson TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 34009422278eSRichard Henderson 34019422278eSRichard Henderson gen_load_trap_state_at_tl(r_tsptr); 34029422278eSRichard Henderson tcg_gen_st_tl(src, r_tsptr, offsetof(trap_state, tnpc)); 34039422278eSRichard Henderson #else 34049422278eSRichard Henderson qemu_build_not_reached(); 34059422278eSRichard Henderson #endif 34069422278eSRichard Henderson } 34079422278eSRichard Henderson 34089422278eSRichard Henderson TRANS(WRPR_tnpc, 64, do_wr_special, a, supervisor(dc), do_wrtnpc) 34099422278eSRichard Henderson 34109422278eSRichard Henderson static void do_wrtstate(DisasContext *dc, TCGv src) 34119422278eSRichard Henderson { 34129422278eSRichard Henderson #ifdef TARGET_SPARC64 34139422278eSRichard Henderson TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 34149422278eSRichard Henderson 34159422278eSRichard Henderson gen_load_trap_state_at_tl(r_tsptr); 34169422278eSRichard Henderson tcg_gen_st_tl(src, r_tsptr, offsetof(trap_state, tstate)); 34179422278eSRichard Henderson #else 34189422278eSRichard Henderson qemu_build_not_reached(); 34199422278eSRichard Henderson #endif 34209422278eSRichard Henderson } 34219422278eSRichard Henderson 34229422278eSRichard Henderson TRANS(WRPR_tstate, 64, do_wr_special, a, supervisor(dc), do_wrtstate) 34239422278eSRichard Henderson 34249422278eSRichard Henderson static void do_wrtt(DisasContext *dc, TCGv src) 34259422278eSRichard Henderson { 34269422278eSRichard Henderson #ifdef TARGET_SPARC64 34279422278eSRichard Henderson TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 34289422278eSRichard Henderson 34299422278eSRichard Henderson gen_load_trap_state_at_tl(r_tsptr); 34309422278eSRichard Henderson tcg_gen_st32_tl(src, r_tsptr, offsetof(trap_state, tt)); 34319422278eSRichard Henderson #else 34329422278eSRichard Henderson qemu_build_not_reached(); 34339422278eSRichard Henderson #endif 34349422278eSRichard Henderson } 34359422278eSRichard Henderson 34369422278eSRichard Henderson TRANS(WRPR_tt, 64, do_wr_special, a, supervisor(dc), do_wrtt) 34379422278eSRichard Henderson 34389422278eSRichard Henderson static void do_wrtick(DisasContext *dc, TCGv src) 34399422278eSRichard Henderson { 34409422278eSRichard Henderson TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 34419422278eSRichard Henderson 34429422278eSRichard Henderson tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(tick)); 34439422278eSRichard Henderson translator_io_start(&dc->base); 34449422278eSRichard Henderson gen_helper_tick_set_count(r_tickptr, src); 34459422278eSRichard Henderson /* End TB to handle timer interrupt */ 34469422278eSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 34479422278eSRichard Henderson } 34489422278eSRichard Henderson 34499422278eSRichard Henderson TRANS(WRPR_tick, 64, do_wr_special, a, supervisor(dc), do_wrtick) 34509422278eSRichard Henderson 34519422278eSRichard Henderson static void do_wrtba(DisasContext *dc, TCGv src) 34529422278eSRichard Henderson { 34539422278eSRichard Henderson tcg_gen_mov_tl(cpu_tbr, src); 34549422278eSRichard Henderson } 34559422278eSRichard Henderson 34569422278eSRichard Henderson TRANS(WRPR_tba, 64, do_wr_special, a, supervisor(dc), do_wrtba) 34579422278eSRichard Henderson 34589422278eSRichard Henderson static void do_wrpstate(DisasContext *dc, TCGv src) 34599422278eSRichard Henderson { 34609422278eSRichard Henderson save_state(dc); 34619422278eSRichard Henderson if (translator_io_start(&dc->base)) { 34629422278eSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 34639422278eSRichard Henderson } 34649422278eSRichard Henderson gen_helper_wrpstate(tcg_env, src); 34659422278eSRichard Henderson dc->npc = DYNAMIC_PC; 34669422278eSRichard Henderson } 34679422278eSRichard Henderson 34689422278eSRichard Henderson TRANS(WRPR_pstate, 64, do_wr_special, a, supervisor(dc), do_wrpstate) 34699422278eSRichard Henderson 34709422278eSRichard Henderson static void do_wrtl(DisasContext *dc, TCGv src) 34719422278eSRichard Henderson { 34729422278eSRichard Henderson save_state(dc); 34739422278eSRichard Henderson tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(tl)); 34749422278eSRichard Henderson dc->npc = DYNAMIC_PC; 34759422278eSRichard Henderson } 34769422278eSRichard Henderson 34779422278eSRichard Henderson TRANS(WRPR_tl, 64, do_wr_special, a, supervisor(dc), do_wrtl) 34789422278eSRichard Henderson 34799422278eSRichard Henderson static void do_wrpil(DisasContext *dc, TCGv src) 34809422278eSRichard Henderson { 34819422278eSRichard Henderson if (translator_io_start(&dc->base)) { 34829422278eSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 34839422278eSRichard Henderson } 34849422278eSRichard Henderson gen_helper_wrpil(tcg_env, src); 34859422278eSRichard Henderson } 34869422278eSRichard Henderson 34879422278eSRichard Henderson TRANS(WRPR_pil, 64, do_wr_special, a, supervisor(dc), do_wrpil) 34889422278eSRichard Henderson 34899422278eSRichard Henderson static void do_wrcwp(DisasContext *dc, TCGv src) 34909422278eSRichard Henderson { 34919422278eSRichard Henderson gen_helper_wrcwp(tcg_env, src); 34929422278eSRichard Henderson } 34939422278eSRichard Henderson 34949422278eSRichard Henderson TRANS(WRPR_cwp, 64, do_wr_special, a, supervisor(dc), do_wrcwp) 34959422278eSRichard Henderson 34969422278eSRichard Henderson static void do_wrcansave(DisasContext *dc, TCGv src) 34979422278eSRichard Henderson { 34989422278eSRichard Henderson tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(cansave)); 34999422278eSRichard Henderson } 35009422278eSRichard Henderson 35019422278eSRichard Henderson TRANS(WRPR_cansave, 64, do_wr_special, a, supervisor(dc), do_wrcansave) 35029422278eSRichard Henderson 35039422278eSRichard Henderson static void do_wrcanrestore(DisasContext *dc, TCGv src) 35049422278eSRichard Henderson { 35059422278eSRichard Henderson tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(canrestore)); 35069422278eSRichard Henderson } 35079422278eSRichard Henderson 35089422278eSRichard Henderson TRANS(WRPR_canrestore, 64, do_wr_special, a, supervisor(dc), do_wrcanrestore) 35099422278eSRichard Henderson 35109422278eSRichard Henderson static void do_wrcleanwin(DisasContext *dc, TCGv src) 35119422278eSRichard Henderson { 35129422278eSRichard Henderson tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(cleanwin)); 35139422278eSRichard Henderson } 35149422278eSRichard Henderson 35159422278eSRichard Henderson TRANS(WRPR_cleanwin, 64, do_wr_special, a, supervisor(dc), do_wrcleanwin) 35169422278eSRichard Henderson 35179422278eSRichard Henderson static void do_wrotherwin(DisasContext *dc, TCGv src) 35189422278eSRichard Henderson { 35199422278eSRichard Henderson tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(otherwin)); 35209422278eSRichard Henderson } 35219422278eSRichard Henderson 35229422278eSRichard Henderson TRANS(WRPR_otherwin, 64, do_wr_special, a, supervisor(dc), do_wrotherwin) 35239422278eSRichard Henderson 35249422278eSRichard Henderson static void do_wrwstate(DisasContext *dc, TCGv src) 35259422278eSRichard Henderson { 35269422278eSRichard Henderson tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(wstate)); 35279422278eSRichard Henderson } 35289422278eSRichard Henderson 35299422278eSRichard Henderson TRANS(WRPR_wstate, 64, do_wr_special, a, supervisor(dc), do_wrwstate) 35309422278eSRichard Henderson 35319422278eSRichard Henderson static void do_wrgl(DisasContext *dc, TCGv src) 35329422278eSRichard Henderson { 35339422278eSRichard Henderson gen_helper_wrgl(tcg_env, src); 35349422278eSRichard Henderson } 35359422278eSRichard Henderson 35369422278eSRichard Henderson TRANS(WRPR_gl, GL, do_wr_special, a, supervisor(dc), do_wrgl) 35379422278eSRichard Henderson 35389422278eSRichard Henderson /* UA2005 strand status */ 35399422278eSRichard Henderson static void do_wrssr(DisasContext *dc, TCGv src) 35409422278eSRichard Henderson { 35412da789deSRichard Henderson tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(ssr)); 35429422278eSRichard Henderson } 35439422278eSRichard Henderson 35449422278eSRichard Henderson TRANS(WRPR_strand_status, HYPV, do_wr_special, a, hypervisor(dc), do_wrssr) 35459422278eSRichard Henderson 3546bb97f2f5SRichard Henderson TRANS(WRTBR, 32, do_wr_special, a, supervisor(dc), do_wrtba) 3547bb97f2f5SRichard Henderson 3548bb97f2f5SRichard Henderson static void do_wrhpstate(DisasContext *dc, TCGv src) 3549bb97f2f5SRichard Henderson { 3550bb97f2f5SRichard Henderson tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(hpstate)); 3551bb97f2f5SRichard Henderson dc->base.is_jmp = DISAS_EXIT; 3552bb97f2f5SRichard Henderson } 3553bb97f2f5SRichard Henderson 3554bb97f2f5SRichard Henderson TRANS(WRHPR_hpstate, HYPV, do_wr_special, a, hypervisor(dc), do_wrhpstate) 3555bb97f2f5SRichard Henderson 3556bb97f2f5SRichard Henderson static void do_wrhtstate(DisasContext *dc, TCGv src) 3557bb97f2f5SRichard Henderson { 3558bb97f2f5SRichard Henderson TCGv_i32 tl = tcg_temp_new_i32(); 3559bb97f2f5SRichard Henderson TCGv_ptr tp = tcg_temp_new_ptr(); 3560bb97f2f5SRichard Henderson 3561bb97f2f5SRichard Henderson tcg_gen_ld_i32(tl, tcg_env, env64_field_offsetof(tl)); 3562bb97f2f5SRichard Henderson tcg_gen_andi_i32(tl, tl, MAXTL_MASK); 3563bb97f2f5SRichard Henderson tcg_gen_shli_i32(tl, tl, 3); 3564bb97f2f5SRichard Henderson tcg_gen_ext_i32_ptr(tp, tl); 3565bb97f2f5SRichard Henderson tcg_gen_add_ptr(tp, tp, tcg_env); 3566bb97f2f5SRichard Henderson 3567bb97f2f5SRichard Henderson tcg_gen_st_tl(src, tp, env64_field_offsetof(htstate)); 3568bb97f2f5SRichard Henderson } 3569bb97f2f5SRichard Henderson 3570bb97f2f5SRichard Henderson TRANS(WRHPR_htstate, HYPV, do_wr_special, a, hypervisor(dc), do_wrhtstate) 3571bb97f2f5SRichard Henderson 3572bb97f2f5SRichard Henderson static void do_wrhintp(DisasContext *dc, TCGv src) 3573bb97f2f5SRichard Henderson { 35742da789deSRichard Henderson tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(hintp)); 3575bb97f2f5SRichard Henderson } 3576bb97f2f5SRichard Henderson 3577bb97f2f5SRichard Henderson TRANS(WRHPR_hintp, HYPV, do_wr_special, a, hypervisor(dc), do_wrhintp) 3578bb97f2f5SRichard Henderson 3579bb97f2f5SRichard Henderson static void do_wrhtba(DisasContext *dc, TCGv src) 3580bb97f2f5SRichard Henderson { 35812da789deSRichard Henderson tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(htba)); 3582bb97f2f5SRichard Henderson } 3583bb97f2f5SRichard Henderson 3584bb97f2f5SRichard Henderson TRANS(WRHPR_htba, HYPV, do_wr_special, a, hypervisor(dc), do_wrhtba) 3585bb97f2f5SRichard Henderson 3586bb97f2f5SRichard Henderson static void do_wrhstick_cmpr(DisasContext *dc, TCGv src) 3587bb97f2f5SRichard Henderson { 3588bb97f2f5SRichard Henderson TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 3589bb97f2f5SRichard Henderson 3590577efa45SRichard Henderson tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(hstick_cmpr)); 3591bb97f2f5SRichard Henderson tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(hstick)); 3592bb97f2f5SRichard Henderson translator_io_start(&dc->base); 3593577efa45SRichard Henderson gen_helper_tick_set_limit(r_tickptr, src); 3594bb97f2f5SRichard Henderson /* End TB to handle timer interrupt */ 3595bb97f2f5SRichard Henderson dc->base.is_jmp = DISAS_EXIT; 3596bb97f2f5SRichard Henderson } 3597bb97f2f5SRichard Henderson 3598bb97f2f5SRichard Henderson TRANS(WRHPR_hstick_cmpr, HYPV, do_wr_special, a, hypervisor(dc), 3599bb97f2f5SRichard Henderson do_wrhstick_cmpr) 3600bb97f2f5SRichard Henderson 360125524734SRichard Henderson static bool do_saved_restored(DisasContext *dc, bool saved) 360225524734SRichard Henderson { 360325524734SRichard Henderson if (!supervisor(dc)) { 360425524734SRichard Henderson return raise_priv(dc); 360525524734SRichard Henderson } 360625524734SRichard Henderson if (saved) { 360725524734SRichard Henderson gen_helper_saved(tcg_env); 360825524734SRichard Henderson } else { 360925524734SRichard Henderson gen_helper_restored(tcg_env); 361025524734SRichard Henderson } 361125524734SRichard Henderson return advance_pc(dc); 361225524734SRichard Henderson } 361325524734SRichard Henderson 361425524734SRichard Henderson TRANS(SAVED, 64, do_saved_restored, true) 361525524734SRichard Henderson TRANS(RESTORED, 64, do_saved_restored, false) 361625524734SRichard Henderson 3617d3825800SRichard Henderson static bool trans_NOP(DisasContext *dc, arg_NOP *a) 3618d3825800SRichard Henderson { 3619d3825800SRichard Henderson return advance_pc(dc); 3620d3825800SRichard Henderson } 3621d3825800SRichard Henderson 36220faef01bSRichard Henderson /* 36230faef01bSRichard Henderson * TODO: Need a feature bit for sparcv8. 36240faef01bSRichard Henderson * In the meantime, treat all 32-bit cpus like sparcv7. 36250faef01bSRichard Henderson */ 36265458fd31SRichard Henderson TRANS(NOP_v7, 32, trans_NOP, a) 36275458fd31SRichard Henderson TRANS(NOP_v9, 64, trans_NOP, a) 36280faef01bSRichard Henderson 3629428881deSRichard Henderson static bool do_arith_int(DisasContext *dc, arg_r_r_ri_cc *a, int cc_op, 3630428881deSRichard Henderson void (*func)(TCGv, TCGv, TCGv), 3631*2a45b736SRichard Henderson void (*funci)(TCGv, TCGv, target_long), 3632*2a45b736SRichard Henderson bool logic_cc) 3633428881deSRichard Henderson { 3634428881deSRichard Henderson TCGv dst, src1; 3635428881deSRichard Henderson 3636428881deSRichard Henderson /* For simplicity, we under-decoded the rs2 form. */ 3637428881deSRichard Henderson if (!a->imm && a->rs2_or_imm & ~0x1f) { 3638428881deSRichard Henderson return false; 3639428881deSRichard Henderson } 3640428881deSRichard Henderson 3641*2a45b736SRichard Henderson if (logic_cc) { 3642*2a45b736SRichard Henderson dst = cpu_cc_N; 3643*2a45b736SRichard Henderson } else if (a->cc && cc_op > CC_OP_FLAGS) { 3644428881deSRichard Henderson dst = cpu_cc_dst; 3645428881deSRichard Henderson } else { 3646428881deSRichard Henderson dst = gen_dest_gpr(dc, a->rd); 3647428881deSRichard Henderson } 3648428881deSRichard Henderson src1 = gen_load_gpr(dc, a->rs1); 3649428881deSRichard Henderson 3650428881deSRichard Henderson if (a->imm || a->rs2_or_imm == 0) { 3651428881deSRichard Henderson if (funci) { 3652428881deSRichard Henderson funci(dst, src1, a->rs2_or_imm); 3653428881deSRichard Henderson } else { 3654428881deSRichard Henderson func(dst, src1, tcg_constant_tl(a->rs2_or_imm)); 3655428881deSRichard Henderson } 3656428881deSRichard Henderson } else { 3657428881deSRichard Henderson func(dst, src1, cpu_regs[a->rs2_or_imm]); 3658428881deSRichard Henderson } 3659*2a45b736SRichard Henderson 3660*2a45b736SRichard Henderson if (logic_cc) { 3661*2a45b736SRichard Henderson if (TARGET_LONG_BITS == 64) { 3662*2a45b736SRichard Henderson tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N); 3663*2a45b736SRichard Henderson tcg_gen_movi_tl(cpu_icc_C, 0); 3664*2a45b736SRichard Henderson } 3665*2a45b736SRichard Henderson tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N); 3666*2a45b736SRichard Henderson tcg_gen_movi_tl(cpu_cc_C, 0); 3667*2a45b736SRichard Henderson tcg_gen_movi_tl(cpu_cc_V, 0); 3668*2a45b736SRichard Henderson } 3669*2a45b736SRichard Henderson 3670428881deSRichard Henderson gen_store_gpr(dc, a->rd, dst); 3671428881deSRichard Henderson 3672428881deSRichard Henderson if (a->cc) { 3673428881deSRichard Henderson tcg_gen_movi_i32(cpu_cc_op, cc_op); 3674428881deSRichard Henderson dc->cc_op = cc_op; 3675428881deSRichard Henderson } 3676428881deSRichard Henderson return advance_pc(dc); 3677428881deSRichard Henderson } 3678428881deSRichard Henderson 3679428881deSRichard Henderson static bool do_arith(DisasContext *dc, arg_r_r_ri_cc *a, int cc_op, 3680428881deSRichard Henderson void (*func)(TCGv, TCGv, TCGv), 3681428881deSRichard Henderson void (*funci)(TCGv, TCGv, target_long), 3682428881deSRichard Henderson void (*func_cc)(TCGv, TCGv, TCGv)) 3683428881deSRichard Henderson { 3684428881deSRichard Henderson if (a->cc) { 368522188d7dSRichard Henderson assert(cc_op >= 0); 3686*2a45b736SRichard Henderson return do_arith_int(dc, a, cc_op, func_cc, NULL, false); 3687428881deSRichard Henderson } 3688*2a45b736SRichard Henderson return do_arith_int(dc, a, cc_op, func, funci, false); 3689428881deSRichard Henderson } 3690428881deSRichard Henderson 3691428881deSRichard Henderson static bool do_logic(DisasContext *dc, arg_r_r_ri_cc *a, 3692428881deSRichard Henderson void (*func)(TCGv, TCGv, TCGv), 3693428881deSRichard Henderson void (*funci)(TCGv, TCGv, target_long)) 3694428881deSRichard Henderson { 3695*2a45b736SRichard Henderson return do_arith_int(dc, a, CC_OP_FLAGS, func, funci, a->cc); 3696428881deSRichard Henderson } 3697428881deSRichard Henderson 3698428881deSRichard Henderson TRANS(ADD, ALL, do_arith, a, CC_OP_ADD, 3699428881deSRichard Henderson tcg_gen_add_tl, tcg_gen_addi_tl, gen_op_add_cc) 3700428881deSRichard Henderson TRANS(SUB, ALL, do_arith, a, CC_OP_SUB, 3701428881deSRichard Henderson tcg_gen_sub_tl, tcg_gen_subi_tl, gen_op_sub_cc) 3702428881deSRichard Henderson 3703a9aba13dSRichard Henderson TRANS(TADDcc, ALL, do_arith, a, CC_OP_TADD, NULL, NULL, gen_op_add_cc) 3704a9aba13dSRichard Henderson TRANS(TSUBcc, ALL, do_arith, a, CC_OP_TSUB, NULL, NULL, gen_op_sub_cc) 3705a9aba13dSRichard Henderson TRANS(TADDccTV, ALL, do_arith, a, CC_OP_TADDTV, NULL, NULL, gen_op_taddcctv) 3706a9aba13dSRichard Henderson TRANS(TSUBccTV, ALL, do_arith, a, CC_OP_TSUBTV, NULL, NULL, gen_op_tsubcctv) 3707a9aba13dSRichard Henderson 3708428881deSRichard Henderson TRANS(AND, ALL, do_logic, a, tcg_gen_and_tl, tcg_gen_andi_tl) 3709428881deSRichard Henderson TRANS(XOR, ALL, do_logic, a, tcg_gen_xor_tl, tcg_gen_xori_tl) 3710428881deSRichard Henderson TRANS(ANDN, ALL, do_logic, a, tcg_gen_andc_tl, NULL) 3711428881deSRichard Henderson TRANS(ORN, ALL, do_logic, a, tcg_gen_orc_tl, NULL) 3712428881deSRichard Henderson TRANS(XORN, ALL, do_logic, a, tcg_gen_eqv_tl, NULL) 3713428881deSRichard Henderson 371422188d7dSRichard Henderson TRANS(MULX, 64, do_arith, a, -1, tcg_gen_mul_tl, tcg_gen_muli_tl, NULL) 3715b5372650SRichard Henderson TRANS(UMUL, MUL, do_logic, a, gen_op_umul, NULL) 3716b5372650SRichard Henderson TRANS(SMUL, MUL, do_logic, a, gen_op_smul, NULL) 371722188d7dSRichard Henderson 37184ee85ea9SRichard Henderson TRANS(UDIVX, 64, do_arith, a, -1, gen_op_udivx, NULL, NULL) 37194ee85ea9SRichard Henderson TRANS(SDIVX, 64, do_arith, a, -1, gen_op_sdivx, NULL, NULL) 3720c2636853SRichard Henderson TRANS(UDIV, DIV, do_arith, a, CC_OP_DIV, gen_op_udiv, NULL, gen_op_udivcc) 3721c2636853SRichard Henderson TRANS(SDIV, DIV, do_arith, a, CC_OP_DIV, gen_op_sdiv, NULL, gen_op_sdivcc) 37224ee85ea9SRichard Henderson 37239c6ec5bcSRichard Henderson /* TODO: Should have feature bit -- comes in with UltraSparc T2. */ 37249c6ec5bcSRichard Henderson TRANS(POPC, 64, do_arith, a, -1, gen_op_popc, NULL, NULL) 37259c6ec5bcSRichard Henderson 3726428881deSRichard Henderson static bool trans_OR(DisasContext *dc, arg_r_r_ri_cc *a) 3727428881deSRichard Henderson { 3728428881deSRichard Henderson /* OR with %g0 is the canonical alias for MOV. */ 3729428881deSRichard Henderson if (!a->cc && a->rs1 == 0) { 3730428881deSRichard Henderson if (a->imm || a->rs2_or_imm == 0) { 3731428881deSRichard Henderson gen_store_gpr(dc, a->rd, tcg_constant_tl(a->rs2_or_imm)); 3732428881deSRichard Henderson } else if (a->rs2_or_imm & ~0x1f) { 3733428881deSRichard Henderson /* For simplicity, we under-decoded the rs2 form. */ 3734428881deSRichard Henderson return false; 3735428881deSRichard Henderson } else { 3736428881deSRichard Henderson gen_store_gpr(dc, a->rd, cpu_regs[a->rs2_or_imm]); 3737428881deSRichard Henderson } 3738428881deSRichard Henderson return advance_pc(dc); 3739428881deSRichard Henderson } 3740428881deSRichard Henderson return do_logic(dc, a, tcg_gen_or_tl, tcg_gen_ori_tl); 3741428881deSRichard Henderson } 3742428881deSRichard Henderson 3743420a187dSRichard Henderson static bool trans_ADDC(DisasContext *dc, arg_r_r_ri_cc *a) 3744420a187dSRichard Henderson { 3745420a187dSRichard Henderson switch (dc->cc_op) { 3746420a187dSRichard Henderson case CC_OP_DIV: 3747420a187dSRichard Henderson /* Carry is known to be zero. Fall back to plain ADD. */ 3748420a187dSRichard Henderson return do_arith(dc, a, CC_OP_ADD, 3749420a187dSRichard Henderson tcg_gen_add_tl, tcg_gen_addi_tl, gen_op_add_cc); 3750420a187dSRichard Henderson case CC_OP_ADD: 3751420a187dSRichard Henderson case CC_OP_TADD: 3752420a187dSRichard Henderson case CC_OP_TADDTV: 3753420a187dSRichard Henderson return do_arith(dc, a, CC_OP_ADDX, 3754420a187dSRichard Henderson gen_op_addc_add, NULL, gen_op_addccc_add); 3755420a187dSRichard Henderson case CC_OP_SUB: 3756420a187dSRichard Henderson case CC_OP_TSUB: 3757420a187dSRichard Henderson case CC_OP_TSUBTV: 3758420a187dSRichard Henderson return do_arith(dc, a, CC_OP_ADDX, 3759420a187dSRichard Henderson gen_op_addc_sub, NULL, gen_op_addccc_sub); 3760420a187dSRichard Henderson default: 3761420a187dSRichard Henderson return do_arith(dc, a, CC_OP_ADDX, 3762420a187dSRichard Henderson gen_op_addc_generic, NULL, gen_op_addccc_generic); 3763420a187dSRichard Henderson } 3764420a187dSRichard Henderson } 3765420a187dSRichard Henderson 3766dfebb950SRichard Henderson static bool trans_SUBC(DisasContext *dc, arg_r_r_ri_cc *a) 3767dfebb950SRichard Henderson { 3768dfebb950SRichard Henderson switch (dc->cc_op) { 3769dfebb950SRichard Henderson case CC_OP_DIV: 3770dfebb950SRichard Henderson /* Carry is known to be zero. Fall back to plain SUB. */ 3771dfebb950SRichard Henderson return do_arith(dc, a, CC_OP_SUB, 3772dfebb950SRichard Henderson tcg_gen_sub_tl, tcg_gen_subi_tl, gen_op_sub_cc); 3773dfebb950SRichard Henderson case CC_OP_ADD: 3774dfebb950SRichard Henderson case CC_OP_TADD: 3775dfebb950SRichard Henderson case CC_OP_TADDTV: 3776dfebb950SRichard Henderson return do_arith(dc, a, CC_OP_SUBX, 3777dfebb950SRichard Henderson gen_op_subc_add, NULL, gen_op_subccc_add); 3778dfebb950SRichard Henderson case CC_OP_SUB: 3779dfebb950SRichard Henderson case CC_OP_TSUB: 3780dfebb950SRichard Henderson case CC_OP_TSUBTV: 3781dfebb950SRichard Henderson return do_arith(dc, a, CC_OP_SUBX, 3782dfebb950SRichard Henderson gen_op_subc_sub, NULL, gen_op_subccc_sub); 3783dfebb950SRichard Henderson default: 3784dfebb950SRichard Henderson return do_arith(dc, a, CC_OP_SUBX, 3785dfebb950SRichard Henderson gen_op_subc_generic, NULL, gen_op_subccc_generic); 3786dfebb950SRichard Henderson } 3787dfebb950SRichard Henderson } 3788dfebb950SRichard Henderson 3789a9aba13dSRichard Henderson static bool trans_MULScc(DisasContext *dc, arg_r_r_ri_cc *a) 3790a9aba13dSRichard Henderson { 3791a9aba13dSRichard Henderson update_psr(dc); 3792a9aba13dSRichard Henderson return do_arith(dc, a, CC_OP_ADD, NULL, NULL, gen_op_mulscc); 3793a9aba13dSRichard Henderson } 3794a9aba13dSRichard Henderson 3795b88ce6f2SRichard Henderson static bool gen_edge(DisasContext *dc, arg_r_r_r *a, 3796b88ce6f2SRichard Henderson int width, bool cc, bool left) 3797b88ce6f2SRichard Henderson { 3798b88ce6f2SRichard Henderson TCGv dst, s1, s2, lo1, lo2; 3799b88ce6f2SRichard Henderson uint64_t amask, tabl, tabr; 3800b88ce6f2SRichard Henderson int shift, imask, omask; 3801b88ce6f2SRichard Henderson 3802b88ce6f2SRichard Henderson dst = gen_dest_gpr(dc, a->rd); 3803b88ce6f2SRichard Henderson s1 = gen_load_gpr(dc, a->rs1); 3804b88ce6f2SRichard Henderson s2 = gen_load_gpr(dc, a->rs2); 3805b88ce6f2SRichard Henderson 3806b88ce6f2SRichard Henderson if (cc) { 3807b88ce6f2SRichard Henderson tcg_gen_mov_tl(cpu_cc_src, s1); 3808b88ce6f2SRichard Henderson tcg_gen_mov_tl(cpu_cc_src2, s2); 3809b88ce6f2SRichard Henderson tcg_gen_sub_tl(cpu_cc_dst, s1, s2); 3810b88ce6f2SRichard Henderson tcg_gen_movi_i32(cpu_cc_op, CC_OP_SUB); 3811b88ce6f2SRichard Henderson dc->cc_op = CC_OP_SUB; 3812b88ce6f2SRichard Henderson } 3813b88ce6f2SRichard Henderson 3814b88ce6f2SRichard Henderson /* 3815b88ce6f2SRichard Henderson * Theory of operation: there are two tables, left and right (not to 3816b88ce6f2SRichard Henderson * be confused with the left and right versions of the opcode). These 3817b88ce6f2SRichard Henderson * are indexed by the low 3 bits of the inputs. To make things "easy", 3818b88ce6f2SRichard Henderson * these tables are loaded into two constants, TABL and TABR below. 3819b88ce6f2SRichard Henderson * The operation index = (input & imask) << shift calculates the index 3820b88ce6f2SRichard Henderson * into the constant, while val = (table >> index) & omask calculates 3821b88ce6f2SRichard Henderson * the value we're looking for. 3822b88ce6f2SRichard Henderson */ 3823b88ce6f2SRichard Henderson switch (width) { 3824b88ce6f2SRichard Henderson case 8: 3825b88ce6f2SRichard Henderson imask = 0x7; 3826b88ce6f2SRichard Henderson shift = 3; 3827b88ce6f2SRichard Henderson omask = 0xff; 3828b88ce6f2SRichard Henderson if (left) { 3829b88ce6f2SRichard Henderson tabl = 0x80c0e0f0f8fcfeffULL; 3830b88ce6f2SRichard Henderson tabr = 0xff7f3f1f0f070301ULL; 3831b88ce6f2SRichard Henderson } else { 3832b88ce6f2SRichard Henderson tabl = 0x0103070f1f3f7fffULL; 3833b88ce6f2SRichard Henderson tabr = 0xfffefcf8f0e0c080ULL; 3834b88ce6f2SRichard Henderson } 3835b88ce6f2SRichard Henderson break; 3836b88ce6f2SRichard Henderson case 16: 3837b88ce6f2SRichard Henderson imask = 0x6; 3838b88ce6f2SRichard Henderson shift = 1; 3839b88ce6f2SRichard Henderson omask = 0xf; 3840b88ce6f2SRichard Henderson if (left) { 3841b88ce6f2SRichard Henderson tabl = 0x8cef; 3842b88ce6f2SRichard Henderson tabr = 0xf731; 3843b88ce6f2SRichard Henderson } else { 3844b88ce6f2SRichard Henderson tabl = 0x137f; 3845b88ce6f2SRichard Henderson tabr = 0xfec8; 3846b88ce6f2SRichard Henderson } 3847b88ce6f2SRichard Henderson break; 3848b88ce6f2SRichard Henderson case 32: 3849b88ce6f2SRichard Henderson imask = 0x4; 3850b88ce6f2SRichard Henderson shift = 0; 3851b88ce6f2SRichard Henderson omask = 0x3; 3852b88ce6f2SRichard Henderson if (left) { 3853b88ce6f2SRichard Henderson tabl = (2 << 2) | 3; 3854b88ce6f2SRichard Henderson tabr = (3 << 2) | 1; 3855b88ce6f2SRichard Henderson } else { 3856b88ce6f2SRichard Henderson tabl = (1 << 2) | 3; 3857b88ce6f2SRichard Henderson tabr = (3 << 2) | 2; 3858b88ce6f2SRichard Henderson } 3859b88ce6f2SRichard Henderson break; 3860b88ce6f2SRichard Henderson default: 3861b88ce6f2SRichard Henderson abort(); 3862b88ce6f2SRichard Henderson } 3863b88ce6f2SRichard Henderson 3864b88ce6f2SRichard Henderson lo1 = tcg_temp_new(); 3865b88ce6f2SRichard Henderson lo2 = tcg_temp_new(); 3866b88ce6f2SRichard Henderson tcg_gen_andi_tl(lo1, s1, imask); 3867b88ce6f2SRichard Henderson tcg_gen_andi_tl(lo2, s2, imask); 3868b88ce6f2SRichard Henderson tcg_gen_shli_tl(lo1, lo1, shift); 3869b88ce6f2SRichard Henderson tcg_gen_shli_tl(lo2, lo2, shift); 3870b88ce6f2SRichard Henderson 3871b88ce6f2SRichard Henderson tcg_gen_shr_tl(lo1, tcg_constant_tl(tabl), lo1); 3872b88ce6f2SRichard Henderson tcg_gen_shr_tl(lo2, tcg_constant_tl(tabr), lo2); 3873b88ce6f2SRichard Henderson tcg_gen_andi_tl(lo1, lo1, omask); 3874b88ce6f2SRichard Henderson tcg_gen_andi_tl(lo2, lo2, omask); 3875b88ce6f2SRichard Henderson 3876b88ce6f2SRichard Henderson amask = address_mask_i(dc, -8); 3877b88ce6f2SRichard Henderson tcg_gen_andi_tl(s1, s1, amask); 3878b88ce6f2SRichard Henderson tcg_gen_andi_tl(s2, s2, amask); 3879b88ce6f2SRichard Henderson 3880b88ce6f2SRichard Henderson /* Compute dst = (s1 == s2 ? lo1 : lo1 & lo2). */ 3881b88ce6f2SRichard Henderson tcg_gen_and_tl(lo2, lo2, lo1); 3882b88ce6f2SRichard Henderson tcg_gen_movcond_tl(TCG_COND_EQ, dst, s1, s2, lo1, lo2); 3883b88ce6f2SRichard Henderson 3884b88ce6f2SRichard Henderson gen_store_gpr(dc, a->rd, dst); 3885b88ce6f2SRichard Henderson return advance_pc(dc); 3886b88ce6f2SRichard Henderson } 3887b88ce6f2SRichard Henderson 3888b88ce6f2SRichard Henderson TRANS(EDGE8cc, VIS1, gen_edge, a, 8, 1, 0) 3889b88ce6f2SRichard Henderson TRANS(EDGE8Lcc, VIS1, gen_edge, a, 8, 1, 1) 3890b88ce6f2SRichard Henderson TRANS(EDGE16cc, VIS1, gen_edge, a, 16, 1, 0) 3891b88ce6f2SRichard Henderson TRANS(EDGE16Lcc, VIS1, gen_edge, a, 16, 1, 1) 3892b88ce6f2SRichard Henderson TRANS(EDGE32cc, VIS1, gen_edge, a, 32, 1, 0) 3893b88ce6f2SRichard Henderson TRANS(EDGE32Lcc, VIS1, gen_edge, a, 32, 1, 1) 3894b88ce6f2SRichard Henderson 3895b88ce6f2SRichard Henderson TRANS(EDGE8N, VIS2, gen_edge, a, 8, 0, 0) 3896b88ce6f2SRichard Henderson TRANS(EDGE8LN, VIS2, gen_edge, a, 8, 0, 1) 3897b88ce6f2SRichard Henderson TRANS(EDGE16N, VIS2, gen_edge, a, 16, 0, 0) 3898b88ce6f2SRichard Henderson TRANS(EDGE16LN, VIS2, gen_edge, a, 16, 0, 1) 3899b88ce6f2SRichard Henderson TRANS(EDGE32N, VIS2, gen_edge, a, 32, 0, 0) 3900b88ce6f2SRichard Henderson TRANS(EDGE32LN, VIS2, gen_edge, a, 32, 0, 1) 3901b88ce6f2SRichard Henderson 390245bfed3bSRichard Henderson static bool do_rrr(DisasContext *dc, arg_r_r_r *a, 390345bfed3bSRichard Henderson void (*func)(TCGv, TCGv, TCGv)) 390445bfed3bSRichard Henderson { 390545bfed3bSRichard Henderson TCGv dst = gen_dest_gpr(dc, a->rd); 390645bfed3bSRichard Henderson TCGv src1 = gen_load_gpr(dc, a->rs1); 390745bfed3bSRichard Henderson TCGv src2 = gen_load_gpr(dc, a->rs2); 390845bfed3bSRichard Henderson 390945bfed3bSRichard Henderson func(dst, src1, src2); 391045bfed3bSRichard Henderson gen_store_gpr(dc, a->rd, dst); 391145bfed3bSRichard Henderson return advance_pc(dc); 391245bfed3bSRichard Henderson } 391345bfed3bSRichard Henderson 391445bfed3bSRichard Henderson TRANS(ARRAY8, VIS1, do_rrr, a, gen_helper_array8) 391545bfed3bSRichard Henderson TRANS(ARRAY16, VIS1, do_rrr, a, gen_op_array16) 391645bfed3bSRichard Henderson TRANS(ARRAY32, VIS1, do_rrr, a, gen_op_array32) 391745bfed3bSRichard Henderson 39189e20ca94SRichard Henderson static void gen_op_alignaddr(TCGv dst, TCGv s1, TCGv s2) 39199e20ca94SRichard Henderson { 39209e20ca94SRichard Henderson #ifdef TARGET_SPARC64 39219e20ca94SRichard Henderson TCGv tmp = tcg_temp_new(); 39229e20ca94SRichard Henderson 39239e20ca94SRichard Henderson tcg_gen_add_tl(tmp, s1, s2); 39249e20ca94SRichard Henderson tcg_gen_andi_tl(dst, tmp, -8); 39259e20ca94SRichard Henderson tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, tmp, 0, 3); 39269e20ca94SRichard Henderson #else 39279e20ca94SRichard Henderson g_assert_not_reached(); 39289e20ca94SRichard Henderson #endif 39299e20ca94SRichard Henderson } 39309e20ca94SRichard Henderson 39319e20ca94SRichard Henderson static void gen_op_alignaddrl(TCGv dst, TCGv s1, TCGv s2) 39329e20ca94SRichard Henderson { 39339e20ca94SRichard Henderson #ifdef TARGET_SPARC64 39349e20ca94SRichard Henderson TCGv tmp = tcg_temp_new(); 39359e20ca94SRichard Henderson 39369e20ca94SRichard Henderson tcg_gen_add_tl(tmp, s1, s2); 39379e20ca94SRichard Henderson tcg_gen_andi_tl(dst, tmp, -8); 39389e20ca94SRichard Henderson tcg_gen_neg_tl(tmp, tmp); 39399e20ca94SRichard Henderson tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, tmp, 0, 3); 39409e20ca94SRichard Henderson #else 39419e20ca94SRichard Henderson g_assert_not_reached(); 39429e20ca94SRichard Henderson #endif 39439e20ca94SRichard Henderson } 39449e20ca94SRichard Henderson 39459e20ca94SRichard Henderson TRANS(ALIGNADDR, VIS1, do_rrr, a, gen_op_alignaddr) 39469e20ca94SRichard Henderson TRANS(ALIGNADDRL, VIS1, do_rrr, a, gen_op_alignaddrl) 39479e20ca94SRichard Henderson 394839ca3490SRichard Henderson static void gen_op_bmask(TCGv dst, TCGv s1, TCGv s2) 394939ca3490SRichard Henderson { 395039ca3490SRichard Henderson #ifdef TARGET_SPARC64 395139ca3490SRichard Henderson tcg_gen_add_tl(dst, s1, s2); 395239ca3490SRichard Henderson tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, dst, 32, 32); 395339ca3490SRichard Henderson #else 395439ca3490SRichard Henderson g_assert_not_reached(); 395539ca3490SRichard Henderson #endif 395639ca3490SRichard Henderson } 395739ca3490SRichard Henderson 395839ca3490SRichard Henderson TRANS(BMASK, VIS2, do_rrr, a, gen_op_bmask) 395939ca3490SRichard Henderson 39605fc546eeSRichard Henderson static bool do_shift_r(DisasContext *dc, arg_shiftr *a, bool l, bool u) 39615fc546eeSRichard Henderson { 39625fc546eeSRichard Henderson TCGv dst, src1, src2; 39635fc546eeSRichard Henderson 39645fc546eeSRichard Henderson /* Reject 64-bit shifts for sparc32. */ 39655fc546eeSRichard Henderson if (avail_32(dc) && a->x) { 39665fc546eeSRichard Henderson return false; 39675fc546eeSRichard Henderson } 39685fc546eeSRichard Henderson 39695fc546eeSRichard Henderson src2 = tcg_temp_new(); 39705fc546eeSRichard Henderson tcg_gen_andi_tl(src2, gen_load_gpr(dc, a->rs2), a->x ? 63 : 31); 39715fc546eeSRichard Henderson src1 = gen_load_gpr(dc, a->rs1); 39725fc546eeSRichard Henderson dst = gen_dest_gpr(dc, a->rd); 39735fc546eeSRichard Henderson 39745fc546eeSRichard Henderson if (l) { 39755fc546eeSRichard Henderson tcg_gen_shl_tl(dst, src1, src2); 39765fc546eeSRichard Henderson if (!a->x) { 39775fc546eeSRichard Henderson tcg_gen_ext32u_tl(dst, dst); 39785fc546eeSRichard Henderson } 39795fc546eeSRichard Henderson } else if (u) { 39805fc546eeSRichard Henderson if (!a->x) { 39815fc546eeSRichard Henderson tcg_gen_ext32u_tl(dst, src1); 39825fc546eeSRichard Henderson src1 = dst; 39835fc546eeSRichard Henderson } 39845fc546eeSRichard Henderson tcg_gen_shr_tl(dst, src1, src2); 39855fc546eeSRichard Henderson } else { 39865fc546eeSRichard Henderson if (!a->x) { 39875fc546eeSRichard Henderson tcg_gen_ext32s_tl(dst, src1); 39885fc546eeSRichard Henderson src1 = dst; 39895fc546eeSRichard Henderson } 39905fc546eeSRichard Henderson tcg_gen_sar_tl(dst, src1, src2); 39915fc546eeSRichard Henderson } 39925fc546eeSRichard Henderson gen_store_gpr(dc, a->rd, dst); 39935fc546eeSRichard Henderson return advance_pc(dc); 39945fc546eeSRichard Henderson } 39955fc546eeSRichard Henderson 39965fc546eeSRichard Henderson TRANS(SLL_r, ALL, do_shift_r, a, true, true) 39975fc546eeSRichard Henderson TRANS(SRL_r, ALL, do_shift_r, a, false, true) 39985fc546eeSRichard Henderson TRANS(SRA_r, ALL, do_shift_r, a, false, false) 39995fc546eeSRichard Henderson 40005fc546eeSRichard Henderson static bool do_shift_i(DisasContext *dc, arg_shifti *a, bool l, bool u) 40015fc546eeSRichard Henderson { 40025fc546eeSRichard Henderson TCGv dst, src1; 40035fc546eeSRichard Henderson 40045fc546eeSRichard Henderson /* Reject 64-bit shifts for sparc32. */ 40055fc546eeSRichard Henderson if (avail_32(dc) && (a->x || a->i >= 32)) { 40065fc546eeSRichard Henderson return false; 40075fc546eeSRichard Henderson } 40085fc546eeSRichard Henderson 40095fc546eeSRichard Henderson src1 = gen_load_gpr(dc, a->rs1); 40105fc546eeSRichard Henderson dst = gen_dest_gpr(dc, a->rd); 40115fc546eeSRichard Henderson 40125fc546eeSRichard Henderson if (avail_32(dc) || a->x) { 40135fc546eeSRichard Henderson if (l) { 40145fc546eeSRichard Henderson tcg_gen_shli_tl(dst, src1, a->i); 40155fc546eeSRichard Henderson } else if (u) { 40165fc546eeSRichard Henderson tcg_gen_shri_tl(dst, src1, a->i); 40175fc546eeSRichard Henderson } else { 40185fc546eeSRichard Henderson tcg_gen_sari_tl(dst, src1, a->i); 40195fc546eeSRichard Henderson } 40205fc546eeSRichard Henderson } else { 40215fc546eeSRichard Henderson if (l) { 40225fc546eeSRichard Henderson tcg_gen_deposit_z_tl(dst, src1, a->i, 32 - a->i); 40235fc546eeSRichard Henderson } else if (u) { 40245fc546eeSRichard Henderson tcg_gen_extract_tl(dst, src1, a->i, 32 - a->i); 40255fc546eeSRichard Henderson } else { 40265fc546eeSRichard Henderson tcg_gen_sextract_tl(dst, src1, a->i, 32 - a->i); 40275fc546eeSRichard Henderson } 40285fc546eeSRichard Henderson } 40295fc546eeSRichard Henderson gen_store_gpr(dc, a->rd, dst); 40305fc546eeSRichard Henderson return advance_pc(dc); 40315fc546eeSRichard Henderson } 40325fc546eeSRichard Henderson 40335fc546eeSRichard Henderson TRANS(SLL_i, ALL, do_shift_i, a, true, true) 40345fc546eeSRichard Henderson TRANS(SRL_i, ALL, do_shift_i, a, false, true) 40355fc546eeSRichard Henderson TRANS(SRA_i, ALL, do_shift_i, a, false, false) 40365fc546eeSRichard Henderson 4037fb4ed7aaSRichard Henderson static TCGv gen_rs2_or_imm(DisasContext *dc, bool imm, int rs2_or_imm) 4038fb4ed7aaSRichard Henderson { 4039fb4ed7aaSRichard Henderson /* For simplicity, we under-decoded the rs2 form. */ 4040fb4ed7aaSRichard Henderson if (!imm && rs2_or_imm & ~0x1f) { 4041fb4ed7aaSRichard Henderson return NULL; 4042fb4ed7aaSRichard Henderson } 4043fb4ed7aaSRichard Henderson if (imm || rs2_or_imm == 0) { 4044fb4ed7aaSRichard Henderson return tcg_constant_tl(rs2_or_imm); 4045fb4ed7aaSRichard Henderson } else { 4046fb4ed7aaSRichard Henderson return cpu_regs[rs2_or_imm]; 4047fb4ed7aaSRichard Henderson } 4048fb4ed7aaSRichard Henderson } 4049fb4ed7aaSRichard Henderson 4050fb4ed7aaSRichard Henderson static bool do_mov_cond(DisasContext *dc, DisasCompare *cmp, int rd, TCGv src2) 4051fb4ed7aaSRichard Henderson { 4052fb4ed7aaSRichard Henderson TCGv dst = gen_load_gpr(dc, rd); 4053fb4ed7aaSRichard Henderson 4054fb4ed7aaSRichard Henderson tcg_gen_movcond_tl(cmp->cond, dst, cmp->c1, cmp->c2, src2, dst); 4055fb4ed7aaSRichard Henderson gen_store_gpr(dc, rd, dst); 4056fb4ed7aaSRichard Henderson return advance_pc(dc); 4057fb4ed7aaSRichard Henderson } 4058fb4ed7aaSRichard Henderson 4059fb4ed7aaSRichard Henderson static bool trans_MOVcc(DisasContext *dc, arg_MOVcc *a) 4060fb4ed7aaSRichard Henderson { 4061fb4ed7aaSRichard Henderson TCGv src2 = gen_rs2_or_imm(dc, a->imm, a->rs2_or_imm); 4062fb4ed7aaSRichard Henderson DisasCompare cmp; 4063fb4ed7aaSRichard Henderson 4064fb4ed7aaSRichard Henderson if (src2 == NULL) { 4065fb4ed7aaSRichard Henderson return false; 4066fb4ed7aaSRichard Henderson } 4067fb4ed7aaSRichard Henderson gen_compare(&cmp, a->cc, a->cond, dc); 4068fb4ed7aaSRichard Henderson return do_mov_cond(dc, &cmp, a->rd, src2); 4069fb4ed7aaSRichard Henderson } 4070fb4ed7aaSRichard Henderson 4071fb4ed7aaSRichard Henderson static bool trans_MOVfcc(DisasContext *dc, arg_MOVfcc *a) 4072fb4ed7aaSRichard Henderson { 4073fb4ed7aaSRichard Henderson TCGv src2 = gen_rs2_or_imm(dc, a->imm, a->rs2_or_imm); 4074fb4ed7aaSRichard Henderson DisasCompare cmp; 4075fb4ed7aaSRichard Henderson 4076fb4ed7aaSRichard Henderson if (src2 == NULL) { 4077fb4ed7aaSRichard Henderson return false; 4078fb4ed7aaSRichard Henderson } 4079fb4ed7aaSRichard Henderson gen_fcompare(&cmp, a->cc, a->cond); 4080fb4ed7aaSRichard Henderson return do_mov_cond(dc, &cmp, a->rd, src2); 4081fb4ed7aaSRichard Henderson } 4082fb4ed7aaSRichard Henderson 4083fb4ed7aaSRichard Henderson static bool trans_MOVR(DisasContext *dc, arg_MOVR *a) 4084fb4ed7aaSRichard Henderson { 4085fb4ed7aaSRichard Henderson TCGv src2 = gen_rs2_or_imm(dc, a->imm, a->rs2_or_imm); 4086fb4ed7aaSRichard Henderson DisasCompare cmp; 4087fb4ed7aaSRichard Henderson 4088fb4ed7aaSRichard Henderson if (src2 == NULL) { 4089fb4ed7aaSRichard Henderson return false; 4090fb4ed7aaSRichard Henderson } 4091fb4ed7aaSRichard Henderson gen_compare_reg(&cmp, a->cond, gen_load_gpr(dc, a->rs1)); 4092fb4ed7aaSRichard Henderson return do_mov_cond(dc, &cmp, a->rd, src2); 4093fb4ed7aaSRichard Henderson } 4094fb4ed7aaSRichard Henderson 409586b82fe0SRichard Henderson static bool do_add_special(DisasContext *dc, arg_r_r_ri *a, 409686b82fe0SRichard Henderson bool (*func)(DisasContext *dc, int rd, TCGv src)) 409786b82fe0SRichard Henderson { 409886b82fe0SRichard Henderson TCGv src1, sum; 409986b82fe0SRichard Henderson 410086b82fe0SRichard Henderson /* For simplicity, we under-decoded the rs2 form. */ 410186b82fe0SRichard Henderson if (!a->imm && a->rs2_or_imm & ~0x1f) { 410286b82fe0SRichard Henderson return false; 410386b82fe0SRichard Henderson } 410486b82fe0SRichard Henderson 410586b82fe0SRichard Henderson /* 410686b82fe0SRichard Henderson * Always load the sum into a new temporary. 410786b82fe0SRichard Henderson * This is required to capture the value across a window change, 410886b82fe0SRichard Henderson * e.g. SAVE and RESTORE, and may be optimized away otherwise. 410986b82fe0SRichard Henderson */ 411086b82fe0SRichard Henderson sum = tcg_temp_new(); 411186b82fe0SRichard Henderson src1 = gen_load_gpr(dc, a->rs1); 411286b82fe0SRichard Henderson if (a->imm || a->rs2_or_imm == 0) { 411386b82fe0SRichard Henderson tcg_gen_addi_tl(sum, src1, a->rs2_or_imm); 411486b82fe0SRichard Henderson } else { 411586b82fe0SRichard Henderson tcg_gen_add_tl(sum, src1, cpu_regs[a->rs2_or_imm]); 411686b82fe0SRichard Henderson } 411786b82fe0SRichard Henderson return func(dc, a->rd, sum); 411886b82fe0SRichard Henderson } 411986b82fe0SRichard Henderson 412086b82fe0SRichard Henderson static bool do_jmpl(DisasContext *dc, int rd, TCGv src) 412186b82fe0SRichard Henderson { 412286b82fe0SRichard Henderson /* 412386b82fe0SRichard Henderson * Preserve pc across advance, so that we can delay 412486b82fe0SRichard Henderson * the writeback to rd until after src is consumed. 412586b82fe0SRichard Henderson */ 412686b82fe0SRichard Henderson target_ulong cur_pc = dc->pc; 412786b82fe0SRichard Henderson 412886b82fe0SRichard Henderson gen_check_align(dc, src, 3); 412986b82fe0SRichard Henderson 413086b82fe0SRichard Henderson gen_mov_pc_npc(dc); 413186b82fe0SRichard Henderson tcg_gen_mov_tl(cpu_npc, src); 413286b82fe0SRichard Henderson gen_address_mask(dc, cpu_npc); 413386b82fe0SRichard Henderson gen_store_gpr(dc, rd, tcg_constant_tl(cur_pc)); 413486b82fe0SRichard Henderson 413586b82fe0SRichard Henderson dc->npc = DYNAMIC_PC_LOOKUP; 413686b82fe0SRichard Henderson return true; 413786b82fe0SRichard Henderson } 413886b82fe0SRichard Henderson 413986b82fe0SRichard Henderson TRANS(JMPL, ALL, do_add_special, a, do_jmpl) 414086b82fe0SRichard Henderson 414186b82fe0SRichard Henderson static bool do_rett(DisasContext *dc, int rd, TCGv src) 414286b82fe0SRichard Henderson { 414386b82fe0SRichard Henderson if (!supervisor(dc)) { 414486b82fe0SRichard Henderson return raise_priv(dc); 414586b82fe0SRichard Henderson } 414686b82fe0SRichard Henderson 414786b82fe0SRichard Henderson gen_check_align(dc, src, 3); 414886b82fe0SRichard Henderson 414986b82fe0SRichard Henderson gen_mov_pc_npc(dc); 415086b82fe0SRichard Henderson tcg_gen_mov_tl(cpu_npc, src); 415186b82fe0SRichard Henderson gen_helper_rett(tcg_env); 415286b82fe0SRichard Henderson 415386b82fe0SRichard Henderson dc->npc = DYNAMIC_PC; 415486b82fe0SRichard Henderson return true; 415586b82fe0SRichard Henderson } 415686b82fe0SRichard Henderson 415786b82fe0SRichard Henderson TRANS(RETT, 32, do_add_special, a, do_rett) 415886b82fe0SRichard Henderson 415986b82fe0SRichard Henderson static bool do_return(DisasContext *dc, int rd, TCGv src) 416086b82fe0SRichard Henderson { 416186b82fe0SRichard Henderson gen_check_align(dc, src, 3); 416286b82fe0SRichard Henderson 416386b82fe0SRichard Henderson gen_mov_pc_npc(dc); 416486b82fe0SRichard Henderson tcg_gen_mov_tl(cpu_npc, src); 416586b82fe0SRichard Henderson gen_address_mask(dc, cpu_npc); 416686b82fe0SRichard Henderson 416786b82fe0SRichard Henderson gen_helper_restore(tcg_env); 416886b82fe0SRichard Henderson dc->npc = DYNAMIC_PC_LOOKUP; 416986b82fe0SRichard Henderson return true; 417086b82fe0SRichard Henderson } 417186b82fe0SRichard Henderson 417286b82fe0SRichard Henderson TRANS(RETURN, 64, do_add_special, a, do_return) 417386b82fe0SRichard Henderson 4174d3825800SRichard Henderson static bool do_save(DisasContext *dc, int rd, TCGv src) 4175d3825800SRichard Henderson { 4176d3825800SRichard Henderson gen_helper_save(tcg_env); 4177d3825800SRichard Henderson gen_store_gpr(dc, rd, src); 4178d3825800SRichard Henderson return advance_pc(dc); 4179d3825800SRichard Henderson } 4180d3825800SRichard Henderson 4181d3825800SRichard Henderson TRANS(SAVE, ALL, do_add_special, a, do_save) 4182d3825800SRichard Henderson 4183d3825800SRichard Henderson static bool do_restore(DisasContext *dc, int rd, TCGv src) 4184d3825800SRichard Henderson { 4185d3825800SRichard Henderson gen_helper_restore(tcg_env); 4186d3825800SRichard Henderson gen_store_gpr(dc, rd, src); 4187d3825800SRichard Henderson return advance_pc(dc); 4188d3825800SRichard Henderson } 4189d3825800SRichard Henderson 4190d3825800SRichard Henderson TRANS(RESTORE, ALL, do_add_special, a, do_restore) 4191d3825800SRichard Henderson 41928f75b8a4SRichard Henderson static bool do_done_retry(DisasContext *dc, bool done) 41938f75b8a4SRichard Henderson { 41948f75b8a4SRichard Henderson if (!supervisor(dc)) { 41958f75b8a4SRichard Henderson return raise_priv(dc); 41968f75b8a4SRichard Henderson } 41978f75b8a4SRichard Henderson dc->npc = DYNAMIC_PC; 41988f75b8a4SRichard Henderson dc->pc = DYNAMIC_PC; 41998f75b8a4SRichard Henderson translator_io_start(&dc->base); 42008f75b8a4SRichard Henderson if (done) { 42018f75b8a4SRichard Henderson gen_helper_done(tcg_env); 42028f75b8a4SRichard Henderson } else { 42038f75b8a4SRichard Henderson gen_helper_retry(tcg_env); 42048f75b8a4SRichard Henderson } 42058f75b8a4SRichard Henderson return true; 42068f75b8a4SRichard Henderson } 42078f75b8a4SRichard Henderson 42088f75b8a4SRichard Henderson TRANS(DONE, 64, do_done_retry, true) 42098f75b8a4SRichard Henderson TRANS(RETRY, 64, do_done_retry, false) 42108f75b8a4SRichard Henderson 42110880d20bSRichard Henderson /* 42120880d20bSRichard Henderson * Major opcode 11 -- load and store instructions 42130880d20bSRichard Henderson */ 42140880d20bSRichard Henderson 42150880d20bSRichard Henderson static TCGv gen_ldst_addr(DisasContext *dc, int rs1, bool imm, int rs2_or_imm) 42160880d20bSRichard Henderson { 42170880d20bSRichard Henderson TCGv addr, tmp = NULL; 42180880d20bSRichard Henderson 42190880d20bSRichard Henderson /* For simplicity, we under-decoded the rs2 form. */ 42200880d20bSRichard Henderson if (!imm && rs2_or_imm & ~0x1f) { 42210880d20bSRichard Henderson return NULL; 42220880d20bSRichard Henderson } 42230880d20bSRichard Henderson 42240880d20bSRichard Henderson addr = gen_load_gpr(dc, rs1); 42250880d20bSRichard Henderson if (rs2_or_imm) { 42260880d20bSRichard Henderson tmp = tcg_temp_new(); 42270880d20bSRichard Henderson if (imm) { 42280880d20bSRichard Henderson tcg_gen_addi_tl(tmp, addr, rs2_or_imm); 42290880d20bSRichard Henderson } else { 42300880d20bSRichard Henderson tcg_gen_add_tl(tmp, addr, cpu_regs[rs2_or_imm]); 42310880d20bSRichard Henderson } 42320880d20bSRichard Henderson addr = tmp; 42330880d20bSRichard Henderson } 42340880d20bSRichard Henderson if (AM_CHECK(dc)) { 42350880d20bSRichard Henderson if (!tmp) { 42360880d20bSRichard Henderson tmp = tcg_temp_new(); 42370880d20bSRichard Henderson } 42380880d20bSRichard Henderson tcg_gen_ext32u_tl(tmp, addr); 42390880d20bSRichard Henderson addr = tmp; 42400880d20bSRichard Henderson } 42410880d20bSRichard Henderson return addr; 42420880d20bSRichard Henderson } 42430880d20bSRichard Henderson 42440880d20bSRichard Henderson static bool do_ld_gpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp mop) 42450880d20bSRichard Henderson { 42460880d20bSRichard Henderson TCGv reg, addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 42470880d20bSRichard Henderson DisasASI da; 42480880d20bSRichard Henderson 42490880d20bSRichard Henderson if (addr == NULL) { 42500880d20bSRichard Henderson return false; 42510880d20bSRichard Henderson } 42520880d20bSRichard Henderson da = resolve_asi(dc, a->asi, mop); 42530880d20bSRichard Henderson 42540880d20bSRichard Henderson reg = gen_dest_gpr(dc, a->rd); 425542071fc1SRichard Henderson gen_ld_asi(dc, &da, reg, addr); 42560880d20bSRichard Henderson gen_store_gpr(dc, a->rd, reg); 42570880d20bSRichard Henderson return advance_pc(dc); 42580880d20bSRichard Henderson } 42590880d20bSRichard Henderson 42600880d20bSRichard Henderson TRANS(LDUW, ALL, do_ld_gpr, a, MO_TEUL) 42610880d20bSRichard Henderson TRANS(LDUB, ALL, do_ld_gpr, a, MO_UB) 42620880d20bSRichard Henderson TRANS(LDUH, ALL, do_ld_gpr, a, MO_TEUW) 42630880d20bSRichard Henderson TRANS(LDSB, ALL, do_ld_gpr, a, MO_SB) 42640880d20bSRichard Henderson TRANS(LDSH, ALL, do_ld_gpr, a, MO_TESW) 42650880d20bSRichard Henderson TRANS(LDSW, 64, do_ld_gpr, a, MO_TESL) 42660880d20bSRichard Henderson TRANS(LDX, 64, do_ld_gpr, a, MO_TEUQ) 42670880d20bSRichard Henderson 42680880d20bSRichard Henderson static bool do_st_gpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp mop) 42690880d20bSRichard Henderson { 42700880d20bSRichard Henderson TCGv reg, addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 42710880d20bSRichard Henderson DisasASI da; 42720880d20bSRichard Henderson 42730880d20bSRichard Henderson if (addr == NULL) { 42740880d20bSRichard Henderson return false; 42750880d20bSRichard Henderson } 42760880d20bSRichard Henderson da = resolve_asi(dc, a->asi, mop); 42770880d20bSRichard Henderson 42780880d20bSRichard Henderson reg = gen_load_gpr(dc, a->rd); 427942071fc1SRichard Henderson gen_st_asi(dc, &da, reg, addr); 42800880d20bSRichard Henderson return advance_pc(dc); 42810880d20bSRichard Henderson } 42820880d20bSRichard Henderson 42830880d20bSRichard Henderson TRANS(STW, ALL, do_st_gpr, a, MO_TEUL) 42840880d20bSRichard Henderson TRANS(STB, ALL, do_st_gpr, a, MO_UB) 42850880d20bSRichard Henderson TRANS(STH, ALL, do_st_gpr, a, MO_TEUW) 42860880d20bSRichard Henderson TRANS(STX, 64, do_st_gpr, a, MO_TEUQ) 42870880d20bSRichard Henderson 42880880d20bSRichard Henderson static bool trans_LDD(DisasContext *dc, arg_r_r_ri_asi *a) 42890880d20bSRichard Henderson { 42900880d20bSRichard Henderson TCGv addr; 42910880d20bSRichard Henderson DisasASI da; 42920880d20bSRichard Henderson 42930880d20bSRichard Henderson if (a->rd & 1) { 42940880d20bSRichard Henderson return false; 42950880d20bSRichard Henderson } 42960880d20bSRichard Henderson addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 42970880d20bSRichard Henderson if (addr == NULL) { 42980880d20bSRichard Henderson return false; 42990880d20bSRichard Henderson } 43000880d20bSRichard Henderson da = resolve_asi(dc, a->asi, MO_TEUQ); 430142071fc1SRichard Henderson gen_ldda_asi(dc, &da, addr, a->rd); 43020880d20bSRichard Henderson return advance_pc(dc); 43030880d20bSRichard Henderson } 43040880d20bSRichard Henderson 43050880d20bSRichard Henderson static bool trans_STD(DisasContext *dc, arg_r_r_ri_asi *a) 43060880d20bSRichard Henderson { 43070880d20bSRichard Henderson TCGv addr; 43080880d20bSRichard Henderson DisasASI da; 43090880d20bSRichard Henderson 43100880d20bSRichard Henderson if (a->rd & 1) { 43110880d20bSRichard Henderson return false; 43120880d20bSRichard Henderson } 43130880d20bSRichard Henderson addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 43140880d20bSRichard Henderson if (addr == NULL) { 43150880d20bSRichard Henderson return false; 43160880d20bSRichard Henderson } 43170880d20bSRichard Henderson da = resolve_asi(dc, a->asi, MO_TEUQ); 431842071fc1SRichard Henderson gen_stda_asi(dc, &da, addr, a->rd); 43190880d20bSRichard Henderson return advance_pc(dc); 43200880d20bSRichard Henderson } 43210880d20bSRichard Henderson 4322cf07cd1eSRichard Henderson static bool trans_LDSTUB(DisasContext *dc, arg_r_r_ri_asi *a) 4323cf07cd1eSRichard Henderson { 4324cf07cd1eSRichard Henderson TCGv addr, reg; 4325cf07cd1eSRichard Henderson DisasASI da; 4326cf07cd1eSRichard Henderson 4327cf07cd1eSRichard Henderson addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 4328cf07cd1eSRichard Henderson if (addr == NULL) { 4329cf07cd1eSRichard Henderson return false; 4330cf07cd1eSRichard Henderson } 4331cf07cd1eSRichard Henderson da = resolve_asi(dc, a->asi, MO_UB); 4332cf07cd1eSRichard Henderson 4333cf07cd1eSRichard Henderson reg = gen_dest_gpr(dc, a->rd); 4334cf07cd1eSRichard Henderson gen_ldstub_asi(dc, &da, reg, addr); 4335cf07cd1eSRichard Henderson gen_store_gpr(dc, a->rd, reg); 4336cf07cd1eSRichard Henderson return advance_pc(dc); 4337cf07cd1eSRichard Henderson } 4338cf07cd1eSRichard Henderson 4339dca544b9SRichard Henderson static bool trans_SWAP(DisasContext *dc, arg_r_r_ri_asi *a) 4340dca544b9SRichard Henderson { 4341dca544b9SRichard Henderson TCGv addr, dst, src; 4342dca544b9SRichard Henderson DisasASI da; 4343dca544b9SRichard Henderson 4344dca544b9SRichard Henderson addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 4345dca544b9SRichard Henderson if (addr == NULL) { 4346dca544b9SRichard Henderson return false; 4347dca544b9SRichard Henderson } 4348dca544b9SRichard Henderson da = resolve_asi(dc, a->asi, MO_TEUL); 4349dca544b9SRichard Henderson 4350dca544b9SRichard Henderson dst = gen_dest_gpr(dc, a->rd); 4351dca544b9SRichard Henderson src = gen_load_gpr(dc, a->rd); 4352dca544b9SRichard Henderson gen_swap_asi(dc, &da, dst, src, addr); 4353dca544b9SRichard Henderson gen_store_gpr(dc, a->rd, dst); 4354dca544b9SRichard Henderson return advance_pc(dc); 4355dca544b9SRichard Henderson } 4356dca544b9SRichard Henderson 4357d0a11d25SRichard Henderson static bool do_casa(DisasContext *dc, arg_r_r_ri_asi *a, MemOp mop) 4358d0a11d25SRichard Henderson { 4359d0a11d25SRichard Henderson TCGv addr, o, n, c; 4360d0a11d25SRichard Henderson DisasASI da; 4361d0a11d25SRichard Henderson 4362d0a11d25SRichard Henderson addr = gen_ldst_addr(dc, a->rs1, true, 0); 4363d0a11d25SRichard Henderson if (addr == NULL) { 4364d0a11d25SRichard Henderson return false; 4365d0a11d25SRichard Henderson } 4366d0a11d25SRichard Henderson da = resolve_asi(dc, a->asi, mop); 4367d0a11d25SRichard Henderson 4368d0a11d25SRichard Henderson o = gen_dest_gpr(dc, a->rd); 4369d0a11d25SRichard Henderson n = gen_load_gpr(dc, a->rd); 4370d0a11d25SRichard Henderson c = gen_load_gpr(dc, a->rs2_or_imm); 4371d0a11d25SRichard Henderson gen_cas_asi(dc, &da, o, n, c, addr); 4372d0a11d25SRichard Henderson gen_store_gpr(dc, a->rd, o); 4373d0a11d25SRichard Henderson return advance_pc(dc); 4374d0a11d25SRichard Henderson } 4375d0a11d25SRichard Henderson 4376d0a11d25SRichard Henderson TRANS(CASA, CASA, do_casa, a, MO_TEUL) 4377d0a11d25SRichard Henderson TRANS(CASXA, 64, do_casa, a, MO_TEUQ) 4378d0a11d25SRichard Henderson 437906c060d9SRichard Henderson static bool do_ld_fpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp sz) 438006c060d9SRichard Henderson { 438106c060d9SRichard Henderson TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 438206c060d9SRichard Henderson DisasASI da; 438306c060d9SRichard Henderson 438406c060d9SRichard Henderson if (addr == NULL) { 438506c060d9SRichard Henderson return false; 438606c060d9SRichard Henderson } 438706c060d9SRichard Henderson if (gen_trap_ifnofpu(dc)) { 438806c060d9SRichard Henderson return true; 438906c060d9SRichard Henderson } 439006c060d9SRichard Henderson if (sz == MO_128 && gen_trap_float128(dc)) { 439106c060d9SRichard Henderson return true; 439206c060d9SRichard Henderson } 439306c060d9SRichard Henderson da = resolve_asi(dc, a->asi, MO_TE | sz); 4394287b1152SRichard Henderson gen_ldf_asi(dc, &da, sz, addr, a->rd); 439506c060d9SRichard Henderson gen_update_fprs_dirty(dc, a->rd); 439606c060d9SRichard Henderson return advance_pc(dc); 439706c060d9SRichard Henderson } 439806c060d9SRichard Henderson 439906c060d9SRichard Henderson TRANS(LDF, ALL, do_ld_fpr, a, MO_32) 440006c060d9SRichard Henderson TRANS(LDDF, ALL, do_ld_fpr, a, MO_64) 440106c060d9SRichard Henderson TRANS(LDQF, ALL, do_ld_fpr, a, MO_128) 440206c060d9SRichard Henderson 4403287b1152SRichard Henderson TRANS(LDFA, 64, do_ld_fpr, a, MO_32) 4404287b1152SRichard Henderson TRANS(LDDFA, 64, do_ld_fpr, a, MO_64) 4405287b1152SRichard Henderson TRANS(LDQFA, 64, do_ld_fpr, a, MO_128) 4406287b1152SRichard Henderson 440706c060d9SRichard Henderson static bool do_st_fpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp sz) 440806c060d9SRichard Henderson { 440906c060d9SRichard Henderson TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 441006c060d9SRichard Henderson DisasASI da; 441106c060d9SRichard Henderson 441206c060d9SRichard Henderson if (addr == NULL) { 441306c060d9SRichard Henderson return false; 441406c060d9SRichard Henderson } 441506c060d9SRichard Henderson if (gen_trap_ifnofpu(dc)) { 441606c060d9SRichard Henderson return true; 441706c060d9SRichard Henderson } 441806c060d9SRichard Henderson if (sz == MO_128 && gen_trap_float128(dc)) { 441906c060d9SRichard Henderson return true; 442006c060d9SRichard Henderson } 442106c060d9SRichard Henderson da = resolve_asi(dc, a->asi, MO_TE | sz); 4422287b1152SRichard Henderson gen_stf_asi(dc, &da, sz, addr, a->rd); 442306c060d9SRichard Henderson return advance_pc(dc); 442406c060d9SRichard Henderson } 442506c060d9SRichard Henderson 442606c060d9SRichard Henderson TRANS(STF, ALL, do_st_fpr, a, MO_32) 442706c060d9SRichard Henderson TRANS(STDF, ALL, do_st_fpr, a, MO_64) 442806c060d9SRichard Henderson TRANS(STQF, ALL, do_st_fpr, a, MO_128) 442906c060d9SRichard Henderson 4430287b1152SRichard Henderson TRANS(STFA, 64, do_st_fpr, a, MO_32) 4431287b1152SRichard Henderson TRANS(STDFA, 64, do_st_fpr, a, MO_64) 4432287b1152SRichard Henderson TRANS(STQFA, 64, do_st_fpr, a, MO_128) 4433287b1152SRichard Henderson 443406c060d9SRichard Henderson static bool trans_STDFQ(DisasContext *dc, arg_STDFQ *a) 443506c060d9SRichard Henderson { 443606c060d9SRichard Henderson if (!avail_32(dc)) { 443706c060d9SRichard Henderson return false; 443806c060d9SRichard Henderson } 443906c060d9SRichard Henderson if (!supervisor(dc)) { 444006c060d9SRichard Henderson return raise_priv(dc); 444106c060d9SRichard Henderson } 444206c060d9SRichard Henderson if (gen_trap_ifnofpu(dc)) { 444306c060d9SRichard Henderson return true; 444406c060d9SRichard Henderson } 444506c060d9SRichard Henderson gen_op_fpexception_im(dc, FSR_FTT_SEQ_ERROR); 444606c060d9SRichard Henderson return true; 444706c060d9SRichard Henderson } 444806c060d9SRichard Henderson 4449da681406SRichard Henderson static bool do_ldfsr(DisasContext *dc, arg_r_r_ri *a, MemOp mop, 4450da681406SRichard Henderson target_ulong new_mask, target_ulong old_mask) 44513d3c0673SRichard Henderson { 4452da681406SRichard Henderson TCGv tmp, addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 44533d3c0673SRichard Henderson if (addr == NULL) { 44543d3c0673SRichard Henderson return false; 44553d3c0673SRichard Henderson } 44563d3c0673SRichard Henderson if (gen_trap_ifnofpu(dc)) { 44573d3c0673SRichard Henderson return true; 44583d3c0673SRichard Henderson } 4459da681406SRichard Henderson tmp = tcg_temp_new(); 4460da681406SRichard Henderson tcg_gen_qemu_ld_tl(tmp, addr, dc->mem_idx, mop | MO_ALIGN); 4461da681406SRichard Henderson tcg_gen_andi_tl(tmp, tmp, new_mask); 4462da681406SRichard Henderson tcg_gen_andi_tl(cpu_fsr, cpu_fsr, old_mask); 4463da681406SRichard Henderson tcg_gen_or_tl(cpu_fsr, cpu_fsr, tmp); 4464da681406SRichard Henderson gen_helper_set_fsr(tcg_env, cpu_fsr); 44653d3c0673SRichard Henderson return advance_pc(dc); 44663d3c0673SRichard Henderson } 44673d3c0673SRichard Henderson 4468da681406SRichard Henderson TRANS(LDFSR, ALL, do_ldfsr, a, MO_TEUL, FSR_LDFSR_MASK, FSR_LDFSR_OLDMASK) 4469da681406SRichard Henderson TRANS(LDXFSR, 64, do_ldfsr, a, MO_TEUQ, FSR_LDXFSR_MASK, FSR_LDXFSR_OLDMASK) 44703d3c0673SRichard Henderson 44713d3c0673SRichard Henderson static bool do_stfsr(DisasContext *dc, arg_r_r_ri *a, MemOp mop) 44723d3c0673SRichard Henderson { 44733d3c0673SRichard Henderson TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 44743d3c0673SRichard Henderson if (addr == NULL) { 44753d3c0673SRichard Henderson return false; 44763d3c0673SRichard Henderson } 44773d3c0673SRichard Henderson if (gen_trap_ifnofpu(dc)) { 44783d3c0673SRichard Henderson return true; 44793d3c0673SRichard Henderson } 44803d3c0673SRichard Henderson tcg_gen_qemu_st_tl(cpu_fsr, addr, dc->mem_idx, mop | MO_ALIGN); 44813d3c0673SRichard Henderson return advance_pc(dc); 44823d3c0673SRichard Henderson } 44833d3c0673SRichard Henderson 44843d3c0673SRichard Henderson TRANS(STFSR, ALL, do_stfsr, a, MO_TEUL) 44853d3c0673SRichard Henderson TRANS(STXFSR, 64, do_stfsr, a, MO_TEUQ) 44863d3c0673SRichard Henderson 44873a38260eSRichard Henderson static bool do_fc(DisasContext *dc, int rd, bool c) 44883a38260eSRichard Henderson { 44893a38260eSRichard Henderson uint64_t mask; 44903a38260eSRichard Henderson 44913a38260eSRichard Henderson if (gen_trap_ifnofpu(dc)) { 44923a38260eSRichard Henderson return true; 44933a38260eSRichard Henderson } 44943a38260eSRichard Henderson 44953a38260eSRichard Henderson if (rd & 1) { 44963a38260eSRichard Henderson mask = MAKE_64BIT_MASK(0, 32); 44973a38260eSRichard Henderson } else { 44983a38260eSRichard Henderson mask = MAKE_64BIT_MASK(32, 32); 44993a38260eSRichard Henderson } 45003a38260eSRichard Henderson if (c) { 45013a38260eSRichard Henderson tcg_gen_ori_i64(cpu_fpr[rd / 2], cpu_fpr[rd / 2], mask); 45023a38260eSRichard Henderson } else { 45033a38260eSRichard Henderson tcg_gen_andi_i64(cpu_fpr[rd / 2], cpu_fpr[rd / 2], ~mask); 45043a38260eSRichard Henderson } 45053a38260eSRichard Henderson gen_update_fprs_dirty(dc, rd); 45063a38260eSRichard Henderson return advance_pc(dc); 45073a38260eSRichard Henderson } 45083a38260eSRichard Henderson 45093a38260eSRichard Henderson TRANS(FZEROs, VIS1, do_fc, a->rd, 0) 45103a38260eSRichard Henderson TRANS(FONEs, VIS1, do_fc, a->rd, 1) 45113a38260eSRichard Henderson 45123a38260eSRichard Henderson static bool do_dc(DisasContext *dc, int rd, int64_t c) 45133a38260eSRichard Henderson { 45143a38260eSRichard Henderson if (gen_trap_ifnofpu(dc)) { 45153a38260eSRichard Henderson return true; 45163a38260eSRichard Henderson } 45173a38260eSRichard Henderson 45183a38260eSRichard Henderson tcg_gen_movi_i64(cpu_fpr[rd / 2], c); 45193a38260eSRichard Henderson gen_update_fprs_dirty(dc, rd); 45203a38260eSRichard Henderson return advance_pc(dc); 45213a38260eSRichard Henderson } 45223a38260eSRichard Henderson 45233a38260eSRichard Henderson TRANS(FZEROd, VIS1, do_dc, a->rd, 0) 45243a38260eSRichard Henderson TRANS(FONEd, VIS1, do_dc, a->rd, -1) 45253a38260eSRichard Henderson 4526baf3dbf2SRichard Henderson static bool do_ff(DisasContext *dc, arg_r_r *a, 4527baf3dbf2SRichard Henderson void (*func)(TCGv_i32, TCGv_i32)) 4528baf3dbf2SRichard Henderson { 4529baf3dbf2SRichard Henderson TCGv_i32 tmp; 4530baf3dbf2SRichard Henderson 4531baf3dbf2SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4532baf3dbf2SRichard Henderson return true; 4533baf3dbf2SRichard Henderson } 4534baf3dbf2SRichard Henderson 4535baf3dbf2SRichard Henderson tmp = gen_load_fpr_F(dc, a->rs); 4536baf3dbf2SRichard Henderson func(tmp, tmp); 4537baf3dbf2SRichard Henderson gen_store_fpr_F(dc, a->rd, tmp); 4538baf3dbf2SRichard Henderson return advance_pc(dc); 4539baf3dbf2SRichard Henderson } 4540baf3dbf2SRichard Henderson 4541baf3dbf2SRichard Henderson TRANS(FMOVs, ALL, do_ff, a, gen_op_fmovs) 4542baf3dbf2SRichard Henderson TRANS(FNEGs, ALL, do_ff, a, gen_op_fnegs) 4543baf3dbf2SRichard Henderson TRANS(FABSs, ALL, do_ff, a, gen_op_fabss) 4544baf3dbf2SRichard Henderson TRANS(FSRCs, VIS1, do_ff, a, tcg_gen_mov_i32) 4545baf3dbf2SRichard Henderson TRANS(FNOTs, VIS1, do_ff, a, tcg_gen_not_i32) 4546baf3dbf2SRichard Henderson 45472f722641SRichard Henderson static bool do_fd(DisasContext *dc, arg_r_r *a, 45482f722641SRichard Henderson void (*func)(TCGv_i32, TCGv_i64)) 45492f722641SRichard Henderson { 45502f722641SRichard Henderson TCGv_i32 dst; 45512f722641SRichard Henderson TCGv_i64 src; 45522f722641SRichard Henderson 45532f722641SRichard Henderson if (gen_trap_ifnofpu(dc)) { 45542f722641SRichard Henderson return true; 45552f722641SRichard Henderson } 45562f722641SRichard Henderson 45572f722641SRichard Henderson dst = gen_dest_fpr_F(dc); 45582f722641SRichard Henderson src = gen_load_fpr_D(dc, a->rs); 45592f722641SRichard Henderson func(dst, src); 45602f722641SRichard Henderson gen_store_fpr_F(dc, a->rd, dst); 45612f722641SRichard Henderson return advance_pc(dc); 45622f722641SRichard Henderson } 45632f722641SRichard Henderson 45642f722641SRichard Henderson TRANS(FPACK16, VIS1, do_fd, a, gen_op_fpack16) 45652f722641SRichard Henderson TRANS(FPACKFIX, VIS1, do_fd, a, gen_op_fpackfix) 45662f722641SRichard Henderson 4567119cb94fSRichard Henderson static bool do_env_ff(DisasContext *dc, arg_r_r *a, 4568119cb94fSRichard Henderson void (*func)(TCGv_i32, TCGv_env, TCGv_i32)) 4569119cb94fSRichard Henderson { 4570119cb94fSRichard Henderson TCGv_i32 tmp; 4571119cb94fSRichard Henderson 4572119cb94fSRichard Henderson if (gen_trap_ifnofpu(dc)) { 4573119cb94fSRichard Henderson return true; 4574119cb94fSRichard Henderson } 4575119cb94fSRichard Henderson 4576119cb94fSRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 4577119cb94fSRichard Henderson tmp = gen_load_fpr_F(dc, a->rs); 4578119cb94fSRichard Henderson func(tmp, tcg_env, tmp); 4579119cb94fSRichard Henderson gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env); 4580119cb94fSRichard Henderson gen_store_fpr_F(dc, a->rd, tmp); 4581119cb94fSRichard Henderson return advance_pc(dc); 4582119cb94fSRichard Henderson } 4583119cb94fSRichard Henderson 4584119cb94fSRichard Henderson TRANS(FSQRTs, ALL, do_env_ff, a, gen_helper_fsqrts) 4585119cb94fSRichard Henderson TRANS(FiTOs, ALL, do_env_ff, a, gen_helper_fitos) 4586119cb94fSRichard Henderson TRANS(FsTOi, ALL, do_env_ff, a, gen_helper_fstoi) 4587119cb94fSRichard Henderson 45888c94bcd8SRichard Henderson static bool do_env_fd(DisasContext *dc, arg_r_r *a, 45898c94bcd8SRichard Henderson void (*func)(TCGv_i32, TCGv_env, TCGv_i64)) 45908c94bcd8SRichard Henderson { 45918c94bcd8SRichard Henderson TCGv_i32 dst; 45928c94bcd8SRichard Henderson TCGv_i64 src; 45938c94bcd8SRichard Henderson 45948c94bcd8SRichard Henderson if (gen_trap_ifnofpu(dc)) { 45958c94bcd8SRichard Henderson return true; 45968c94bcd8SRichard Henderson } 45978c94bcd8SRichard Henderson 45988c94bcd8SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 45998c94bcd8SRichard Henderson dst = gen_dest_fpr_F(dc); 46008c94bcd8SRichard Henderson src = gen_load_fpr_D(dc, a->rs); 46018c94bcd8SRichard Henderson func(dst, tcg_env, src); 46028c94bcd8SRichard Henderson gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env); 46038c94bcd8SRichard Henderson gen_store_fpr_F(dc, a->rd, dst); 46048c94bcd8SRichard Henderson return advance_pc(dc); 46058c94bcd8SRichard Henderson } 46068c94bcd8SRichard Henderson 46078c94bcd8SRichard Henderson TRANS(FdTOs, ALL, do_env_fd, a, gen_helper_fdtos) 46088c94bcd8SRichard Henderson TRANS(FdTOi, ALL, do_env_fd, a, gen_helper_fdtoi) 46098c94bcd8SRichard Henderson TRANS(FxTOs, 64, do_env_fd, a, gen_helper_fxtos) 46108c94bcd8SRichard Henderson 4611c6d83e4fSRichard Henderson static bool do_dd(DisasContext *dc, arg_r_r *a, 4612c6d83e4fSRichard Henderson void (*func)(TCGv_i64, TCGv_i64)) 4613c6d83e4fSRichard Henderson { 4614c6d83e4fSRichard Henderson TCGv_i64 dst, src; 4615c6d83e4fSRichard Henderson 4616c6d83e4fSRichard Henderson if (gen_trap_ifnofpu(dc)) { 4617c6d83e4fSRichard Henderson return true; 4618c6d83e4fSRichard Henderson } 4619c6d83e4fSRichard Henderson 4620c6d83e4fSRichard Henderson dst = gen_dest_fpr_D(dc, a->rd); 4621c6d83e4fSRichard Henderson src = gen_load_fpr_D(dc, a->rs); 4622c6d83e4fSRichard Henderson func(dst, src); 4623c6d83e4fSRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 4624c6d83e4fSRichard Henderson return advance_pc(dc); 4625c6d83e4fSRichard Henderson } 4626c6d83e4fSRichard Henderson 4627c6d83e4fSRichard Henderson TRANS(FMOVd, 64, do_dd, a, gen_op_fmovd) 4628c6d83e4fSRichard Henderson TRANS(FNEGd, 64, do_dd, a, gen_op_fnegd) 4629c6d83e4fSRichard Henderson TRANS(FABSd, 64, do_dd, a, gen_op_fabsd) 4630c6d83e4fSRichard Henderson TRANS(FSRCd, VIS1, do_dd, a, tcg_gen_mov_i64) 4631c6d83e4fSRichard Henderson TRANS(FNOTd, VIS1, do_dd, a, tcg_gen_not_i64) 4632c6d83e4fSRichard Henderson 46338aa418b3SRichard Henderson static bool do_env_dd(DisasContext *dc, arg_r_r *a, 46348aa418b3SRichard Henderson void (*func)(TCGv_i64, TCGv_env, TCGv_i64)) 46358aa418b3SRichard Henderson { 46368aa418b3SRichard Henderson TCGv_i64 dst, src; 46378aa418b3SRichard Henderson 46388aa418b3SRichard Henderson if (gen_trap_ifnofpu(dc)) { 46398aa418b3SRichard Henderson return true; 46408aa418b3SRichard Henderson } 46418aa418b3SRichard Henderson 46428aa418b3SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 46438aa418b3SRichard Henderson dst = gen_dest_fpr_D(dc, a->rd); 46448aa418b3SRichard Henderson src = gen_load_fpr_D(dc, a->rs); 46458aa418b3SRichard Henderson func(dst, tcg_env, src); 46468aa418b3SRichard Henderson gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env); 46478aa418b3SRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 46488aa418b3SRichard Henderson return advance_pc(dc); 46498aa418b3SRichard Henderson } 46508aa418b3SRichard Henderson 46518aa418b3SRichard Henderson TRANS(FSQRTd, ALL, do_env_dd, a, gen_helper_fsqrtd) 46528aa418b3SRichard Henderson TRANS(FxTOd, 64, do_env_dd, a, gen_helper_fxtod) 46538aa418b3SRichard Henderson TRANS(FdTOx, 64, do_env_dd, a, gen_helper_fdtox) 46548aa418b3SRichard Henderson 4655199d43efSRichard Henderson static bool do_env_df(DisasContext *dc, arg_r_r *a, 4656199d43efSRichard Henderson void (*func)(TCGv_i64, TCGv_env, TCGv_i32)) 4657199d43efSRichard Henderson { 4658199d43efSRichard Henderson TCGv_i64 dst; 4659199d43efSRichard Henderson TCGv_i32 src; 4660199d43efSRichard Henderson 4661199d43efSRichard Henderson if (gen_trap_ifnofpu(dc)) { 4662199d43efSRichard Henderson return true; 4663199d43efSRichard Henderson } 4664199d43efSRichard Henderson 4665199d43efSRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 4666199d43efSRichard Henderson dst = gen_dest_fpr_D(dc, a->rd); 4667199d43efSRichard Henderson src = gen_load_fpr_F(dc, a->rs); 4668199d43efSRichard Henderson func(dst, tcg_env, src); 4669199d43efSRichard Henderson gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env); 4670199d43efSRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 4671199d43efSRichard Henderson return advance_pc(dc); 4672199d43efSRichard Henderson } 4673199d43efSRichard Henderson 4674199d43efSRichard Henderson TRANS(FiTOd, ALL, do_env_df, a, gen_helper_fitod) 4675199d43efSRichard Henderson TRANS(FsTOd, ALL, do_env_df, a, gen_helper_fstod) 4676199d43efSRichard Henderson TRANS(FsTOx, 64, do_env_df, a, gen_helper_fstox) 4677199d43efSRichard Henderson 4678f4e18df5SRichard Henderson static bool trans_FMOVq(DisasContext *dc, arg_FMOVq *a) 4679f4e18df5SRichard Henderson { 4680f4e18df5SRichard Henderson int rd, rs; 4681f4e18df5SRichard Henderson 4682f4e18df5SRichard Henderson if (!avail_64(dc)) { 4683f4e18df5SRichard Henderson return false; 4684f4e18df5SRichard Henderson } 4685f4e18df5SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4686f4e18df5SRichard Henderson return true; 4687f4e18df5SRichard Henderson } 4688f4e18df5SRichard Henderson if (gen_trap_float128(dc)) { 4689f4e18df5SRichard Henderson return true; 4690f4e18df5SRichard Henderson } 4691f4e18df5SRichard Henderson 4692f4e18df5SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 4693f4e18df5SRichard Henderson rd = QFPREG(a->rd); 4694f4e18df5SRichard Henderson rs = QFPREG(a->rs); 4695f4e18df5SRichard Henderson tcg_gen_mov_i64(cpu_fpr[rd / 2], cpu_fpr[rs / 2]); 4696f4e18df5SRichard Henderson tcg_gen_mov_i64(cpu_fpr[rd / 2 + 1], cpu_fpr[rs / 2 + 1]); 4697f4e18df5SRichard Henderson gen_update_fprs_dirty(dc, rd); 4698f4e18df5SRichard Henderson return advance_pc(dc); 4699f4e18df5SRichard Henderson } 4700f4e18df5SRichard Henderson 4701f4e18df5SRichard Henderson static bool do_qq(DisasContext *dc, arg_r_r *a, 4702f4e18df5SRichard Henderson void (*func)(TCGv_env)) 4703f4e18df5SRichard Henderson { 4704f4e18df5SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4705f4e18df5SRichard Henderson return true; 4706f4e18df5SRichard Henderson } 4707f4e18df5SRichard Henderson if (gen_trap_float128(dc)) { 4708f4e18df5SRichard Henderson return true; 4709f4e18df5SRichard Henderson } 4710f4e18df5SRichard Henderson 4711f4e18df5SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 4712f4e18df5SRichard Henderson gen_op_load_fpr_QT1(QFPREG(a->rs)); 4713f4e18df5SRichard Henderson func(tcg_env); 4714f4e18df5SRichard Henderson gen_op_store_QT0_fpr(QFPREG(a->rd)); 4715f4e18df5SRichard Henderson gen_update_fprs_dirty(dc, QFPREG(a->rd)); 4716f4e18df5SRichard Henderson return advance_pc(dc); 4717f4e18df5SRichard Henderson } 4718f4e18df5SRichard Henderson 4719f4e18df5SRichard Henderson TRANS(FNEGq, 64, do_qq, a, gen_helper_fnegq) 4720f4e18df5SRichard Henderson TRANS(FABSq, 64, do_qq, a, gen_helper_fabsq) 4721f4e18df5SRichard Henderson 4722c995216bSRichard Henderson static bool do_env_qq(DisasContext *dc, arg_r_r *a, 4723c995216bSRichard Henderson void (*func)(TCGv_env)) 4724c995216bSRichard Henderson { 4725c995216bSRichard Henderson if (gen_trap_ifnofpu(dc)) { 4726c995216bSRichard Henderson return true; 4727c995216bSRichard Henderson } 4728c995216bSRichard Henderson if (gen_trap_float128(dc)) { 4729c995216bSRichard Henderson return true; 4730c995216bSRichard Henderson } 4731c995216bSRichard Henderson 4732c995216bSRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 4733c995216bSRichard Henderson gen_op_load_fpr_QT1(QFPREG(a->rs)); 4734c995216bSRichard Henderson func(tcg_env); 4735c995216bSRichard Henderson gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env); 4736c995216bSRichard Henderson gen_op_store_QT0_fpr(QFPREG(a->rd)); 4737c995216bSRichard Henderson gen_update_fprs_dirty(dc, QFPREG(a->rd)); 4738c995216bSRichard Henderson return advance_pc(dc); 4739c995216bSRichard Henderson } 4740c995216bSRichard Henderson 4741c995216bSRichard Henderson TRANS(FSQRTq, ALL, do_env_qq, a, gen_helper_fsqrtq) 4742c995216bSRichard Henderson 4743bd9c5c42SRichard Henderson static bool do_env_fq(DisasContext *dc, arg_r_r *a, 4744bd9c5c42SRichard Henderson void (*func)(TCGv_i32, TCGv_env)) 4745bd9c5c42SRichard Henderson { 4746bd9c5c42SRichard Henderson TCGv_i32 dst; 4747bd9c5c42SRichard Henderson 4748bd9c5c42SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4749bd9c5c42SRichard Henderson return true; 4750bd9c5c42SRichard Henderson } 4751bd9c5c42SRichard Henderson if (gen_trap_float128(dc)) { 4752bd9c5c42SRichard Henderson return true; 4753bd9c5c42SRichard Henderson } 4754bd9c5c42SRichard Henderson 4755bd9c5c42SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 4756bd9c5c42SRichard Henderson gen_op_load_fpr_QT1(QFPREG(a->rs)); 4757bd9c5c42SRichard Henderson dst = gen_dest_fpr_F(dc); 4758bd9c5c42SRichard Henderson func(dst, tcg_env); 4759bd9c5c42SRichard Henderson gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env); 4760bd9c5c42SRichard Henderson gen_store_fpr_F(dc, a->rd, dst); 4761bd9c5c42SRichard Henderson return advance_pc(dc); 4762bd9c5c42SRichard Henderson } 4763bd9c5c42SRichard Henderson 4764bd9c5c42SRichard Henderson TRANS(FqTOs, ALL, do_env_fq, a, gen_helper_fqtos) 4765bd9c5c42SRichard Henderson TRANS(FqTOi, ALL, do_env_fq, a, gen_helper_fqtoi) 4766bd9c5c42SRichard Henderson 47671617586fSRichard Henderson static bool do_env_dq(DisasContext *dc, arg_r_r *a, 47681617586fSRichard Henderson void (*func)(TCGv_i64, TCGv_env)) 47691617586fSRichard Henderson { 47701617586fSRichard Henderson TCGv_i64 dst; 47711617586fSRichard Henderson 47721617586fSRichard Henderson if (gen_trap_ifnofpu(dc)) { 47731617586fSRichard Henderson return true; 47741617586fSRichard Henderson } 47751617586fSRichard Henderson if (gen_trap_float128(dc)) { 47761617586fSRichard Henderson return true; 47771617586fSRichard Henderson } 47781617586fSRichard Henderson 47791617586fSRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 47801617586fSRichard Henderson gen_op_load_fpr_QT1(QFPREG(a->rs)); 47811617586fSRichard Henderson dst = gen_dest_fpr_D(dc, a->rd); 47821617586fSRichard Henderson func(dst, tcg_env); 47831617586fSRichard Henderson gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env); 47841617586fSRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 47851617586fSRichard Henderson return advance_pc(dc); 47861617586fSRichard Henderson } 47871617586fSRichard Henderson 47881617586fSRichard Henderson TRANS(FqTOd, ALL, do_env_dq, a, gen_helper_fqtod) 47891617586fSRichard Henderson TRANS(FqTOx, 64, do_env_dq, a, gen_helper_fqtox) 47901617586fSRichard Henderson 479113ebcc77SRichard Henderson static bool do_env_qf(DisasContext *dc, arg_r_r *a, 479213ebcc77SRichard Henderson void (*func)(TCGv_env, TCGv_i32)) 479313ebcc77SRichard Henderson { 479413ebcc77SRichard Henderson TCGv_i32 src; 479513ebcc77SRichard Henderson 479613ebcc77SRichard Henderson if (gen_trap_ifnofpu(dc)) { 479713ebcc77SRichard Henderson return true; 479813ebcc77SRichard Henderson } 479913ebcc77SRichard Henderson if (gen_trap_float128(dc)) { 480013ebcc77SRichard Henderson return true; 480113ebcc77SRichard Henderson } 480213ebcc77SRichard Henderson 480313ebcc77SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 480413ebcc77SRichard Henderson src = gen_load_fpr_F(dc, a->rs); 480513ebcc77SRichard Henderson func(tcg_env, src); 480613ebcc77SRichard Henderson gen_op_store_QT0_fpr(QFPREG(a->rd)); 480713ebcc77SRichard Henderson gen_update_fprs_dirty(dc, QFPREG(a->rd)); 480813ebcc77SRichard Henderson return advance_pc(dc); 480913ebcc77SRichard Henderson } 481013ebcc77SRichard Henderson 481113ebcc77SRichard Henderson TRANS(FiTOq, ALL, do_env_qf, a, gen_helper_fitoq) 481213ebcc77SRichard Henderson TRANS(FsTOq, ALL, do_env_qf, a, gen_helper_fstoq) 481313ebcc77SRichard Henderson 48147b8e3e1aSRichard Henderson static bool do_env_qd(DisasContext *dc, arg_r_r *a, 48157b8e3e1aSRichard Henderson void (*func)(TCGv_env, TCGv_i64)) 48167b8e3e1aSRichard Henderson { 48177b8e3e1aSRichard Henderson TCGv_i64 src; 48187b8e3e1aSRichard Henderson 48197b8e3e1aSRichard Henderson if (gen_trap_ifnofpu(dc)) { 48207b8e3e1aSRichard Henderson return true; 48217b8e3e1aSRichard Henderson } 48227b8e3e1aSRichard Henderson if (gen_trap_float128(dc)) { 48237b8e3e1aSRichard Henderson return true; 48247b8e3e1aSRichard Henderson } 48257b8e3e1aSRichard Henderson 48267b8e3e1aSRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 48277b8e3e1aSRichard Henderson src = gen_load_fpr_D(dc, a->rs); 48287b8e3e1aSRichard Henderson func(tcg_env, src); 48297b8e3e1aSRichard Henderson gen_op_store_QT0_fpr(QFPREG(a->rd)); 48307b8e3e1aSRichard Henderson gen_update_fprs_dirty(dc, QFPREG(a->rd)); 48317b8e3e1aSRichard Henderson return advance_pc(dc); 48327b8e3e1aSRichard Henderson } 48337b8e3e1aSRichard Henderson 48347b8e3e1aSRichard Henderson TRANS(FdTOq, ALL, do_env_qd, a, gen_helper_fdtoq) 48357b8e3e1aSRichard Henderson TRANS(FxTOq, 64, do_env_qd, a, gen_helper_fxtoq) 48367b8e3e1aSRichard Henderson 48377f10b52fSRichard Henderson static bool do_fff(DisasContext *dc, arg_r_r_r *a, 48387f10b52fSRichard Henderson void (*func)(TCGv_i32, TCGv_i32, TCGv_i32)) 48397f10b52fSRichard Henderson { 48407f10b52fSRichard Henderson TCGv_i32 src1, src2; 48417f10b52fSRichard Henderson 48427f10b52fSRichard Henderson if (gen_trap_ifnofpu(dc)) { 48437f10b52fSRichard Henderson return true; 48447f10b52fSRichard Henderson } 48457f10b52fSRichard Henderson 48467f10b52fSRichard Henderson src1 = gen_load_fpr_F(dc, a->rs1); 48477f10b52fSRichard Henderson src2 = gen_load_fpr_F(dc, a->rs2); 48487f10b52fSRichard Henderson func(src1, src1, src2); 48497f10b52fSRichard Henderson gen_store_fpr_F(dc, a->rd, src1); 48507f10b52fSRichard Henderson return advance_pc(dc); 48517f10b52fSRichard Henderson } 48527f10b52fSRichard Henderson 48537f10b52fSRichard Henderson TRANS(FPADD16s, VIS1, do_fff, a, tcg_gen_vec_add16_i32) 48547f10b52fSRichard Henderson TRANS(FPADD32s, VIS1, do_fff, a, tcg_gen_add_i32) 48557f10b52fSRichard Henderson TRANS(FPSUB16s, VIS1, do_fff, a, tcg_gen_vec_sub16_i32) 48567f10b52fSRichard Henderson TRANS(FPSUB32s, VIS1, do_fff, a, tcg_gen_sub_i32) 48577f10b52fSRichard Henderson TRANS(FNORs, VIS1, do_fff, a, tcg_gen_nor_i32) 48587f10b52fSRichard Henderson TRANS(FANDNOTs, VIS1, do_fff, a, tcg_gen_andc_i32) 48597f10b52fSRichard Henderson TRANS(FXORs, VIS1, do_fff, a, tcg_gen_xor_i32) 48607f10b52fSRichard Henderson TRANS(FNANDs, VIS1, do_fff, a, tcg_gen_nand_i32) 48617f10b52fSRichard Henderson TRANS(FANDs, VIS1, do_fff, a, tcg_gen_and_i32) 48627f10b52fSRichard Henderson TRANS(FXNORs, VIS1, do_fff, a, tcg_gen_eqv_i32) 48637f10b52fSRichard Henderson TRANS(FORNOTs, VIS1, do_fff, a, tcg_gen_orc_i32) 48647f10b52fSRichard Henderson TRANS(FORs, VIS1, do_fff, a, tcg_gen_or_i32) 48657f10b52fSRichard Henderson 4866c1514961SRichard Henderson static bool do_env_fff(DisasContext *dc, arg_r_r_r *a, 4867c1514961SRichard Henderson void (*func)(TCGv_i32, TCGv_env, TCGv_i32, TCGv_i32)) 4868c1514961SRichard Henderson { 4869c1514961SRichard Henderson TCGv_i32 src1, src2; 4870c1514961SRichard Henderson 4871c1514961SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4872c1514961SRichard Henderson return true; 4873c1514961SRichard Henderson } 4874c1514961SRichard Henderson 4875c1514961SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 4876c1514961SRichard Henderson src1 = gen_load_fpr_F(dc, a->rs1); 4877c1514961SRichard Henderson src2 = gen_load_fpr_F(dc, a->rs2); 4878c1514961SRichard Henderson func(src1, tcg_env, src1, src2); 4879c1514961SRichard Henderson gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env); 4880c1514961SRichard Henderson gen_store_fpr_F(dc, a->rd, src1); 4881c1514961SRichard Henderson return advance_pc(dc); 4882c1514961SRichard Henderson } 4883c1514961SRichard Henderson 4884c1514961SRichard Henderson TRANS(FADDs, ALL, do_env_fff, a, gen_helper_fadds) 4885c1514961SRichard Henderson TRANS(FSUBs, ALL, do_env_fff, a, gen_helper_fsubs) 4886c1514961SRichard Henderson TRANS(FMULs, ALL, do_env_fff, a, gen_helper_fmuls) 4887c1514961SRichard Henderson TRANS(FDIVs, ALL, do_env_fff, a, gen_helper_fdivs) 4888c1514961SRichard Henderson 4889e06c9f83SRichard Henderson static bool do_ddd(DisasContext *dc, arg_r_r_r *a, 4890e06c9f83SRichard Henderson void (*func)(TCGv_i64, TCGv_i64, TCGv_i64)) 4891e06c9f83SRichard Henderson { 4892e06c9f83SRichard Henderson TCGv_i64 dst, src1, src2; 4893e06c9f83SRichard Henderson 4894e06c9f83SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4895e06c9f83SRichard Henderson return true; 4896e06c9f83SRichard Henderson } 4897e06c9f83SRichard Henderson 4898e06c9f83SRichard Henderson dst = gen_dest_fpr_D(dc, a->rd); 4899e06c9f83SRichard Henderson src1 = gen_load_fpr_D(dc, a->rs1); 4900e06c9f83SRichard Henderson src2 = gen_load_fpr_D(dc, a->rs2); 4901e06c9f83SRichard Henderson func(dst, src1, src2); 4902e06c9f83SRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 4903e06c9f83SRichard Henderson return advance_pc(dc); 4904e06c9f83SRichard Henderson } 4905e06c9f83SRichard Henderson 4906e06c9f83SRichard Henderson TRANS(FMUL8x16, VIS1, do_ddd, a, gen_helper_fmul8x16) 4907e06c9f83SRichard Henderson TRANS(FMUL8x16AU, VIS1, do_ddd, a, gen_helper_fmul8x16au) 4908e06c9f83SRichard Henderson TRANS(FMUL8x16AL, VIS1, do_ddd, a, gen_helper_fmul8x16al) 4909e06c9f83SRichard Henderson TRANS(FMUL8SUx16, VIS1, do_ddd, a, gen_helper_fmul8sux16) 4910e06c9f83SRichard Henderson TRANS(FMUL8ULx16, VIS1, do_ddd, a, gen_helper_fmul8ulx16) 4911e06c9f83SRichard Henderson TRANS(FMULD8SUx16, VIS1, do_ddd, a, gen_helper_fmuld8sux16) 4912e06c9f83SRichard Henderson TRANS(FMULD8ULx16, VIS1, do_ddd, a, gen_helper_fmuld8ulx16) 4913e06c9f83SRichard Henderson TRANS(FPMERGE, VIS1, do_ddd, a, gen_helper_fpmerge) 4914e06c9f83SRichard Henderson TRANS(FEXPAND, VIS1, do_ddd, a, gen_helper_fexpand) 4915e06c9f83SRichard Henderson 4916e06c9f83SRichard Henderson TRANS(FPADD16, VIS1, do_ddd, a, tcg_gen_vec_add16_i64) 4917e06c9f83SRichard Henderson TRANS(FPADD32, VIS1, do_ddd, a, tcg_gen_vec_add32_i64) 4918e06c9f83SRichard Henderson TRANS(FPSUB16, VIS1, do_ddd, a, tcg_gen_vec_sub16_i64) 4919e06c9f83SRichard Henderson TRANS(FPSUB32, VIS1, do_ddd, a, tcg_gen_vec_sub32_i64) 4920e06c9f83SRichard Henderson TRANS(FNORd, VIS1, do_ddd, a, tcg_gen_nor_i64) 4921e06c9f83SRichard Henderson TRANS(FANDNOTd, VIS1, do_ddd, a, tcg_gen_andc_i64) 4922e06c9f83SRichard Henderson TRANS(FXORd, VIS1, do_ddd, a, tcg_gen_xor_i64) 4923e06c9f83SRichard Henderson TRANS(FNANDd, VIS1, do_ddd, a, tcg_gen_nand_i64) 4924e06c9f83SRichard Henderson TRANS(FANDd, VIS1, do_ddd, a, tcg_gen_and_i64) 4925e06c9f83SRichard Henderson TRANS(FXNORd, VIS1, do_ddd, a, tcg_gen_eqv_i64) 4926e06c9f83SRichard Henderson TRANS(FORNOTd, VIS1, do_ddd, a, tcg_gen_orc_i64) 4927e06c9f83SRichard Henderson TRANS(FORd, VIS1, do_ddd, a, tcg_gen_or_i64) 4928e06c9f83SRichard Henderson 49294b6edc0aSRichard Henderson TRANS(FPACK32, VIS1, do_ddd, a, gen_op_fpack32) 49304b6edc0aSRichard Henderson TRANS(FALIGNDATAg, VIS1, do_ddd, a, gen_op_faligndata) 49314b6edc0aSRichard Henderson TRANS(BSHUFFLE, VIS2, do_ddd, a, gen_op_bshuffle) 49324b6edc0aSRichard Henderson 4933e2fa6bd1SRichard Henderson static bool do_rdd(DisasContext *dc, arg_r_r_r *a, 4934e2fa6bd1SRichard Henderson void (*func)(TCGv, TCGv_i64, TCGv_i64)) 4935e2fa6bd1SRichard Henderson { 4936e2fa6bd1SRichard Henderson TCGv_i64 src1, src2; 4937e2fa6bd1SRichard Henderson TCGv dst; 4938e2fa6bd1SRichard Henderson 4939e2fa6bd1SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4940e2fa6bd1SRichard Henderson return true; 4941e2fa6bd1SRichard Henderson } 4942e2fa6bd1SRichard Henderson 4943e2fa6bd1SRichard Henderson dst = gen_dest_gpr(dc, a->rd); 4944e2fa6bd1SRichard Henderson src1 = gen_load_fpr_D(dc, a->rs1); 4945e2fa6bd1SRichard Henderson src2 = gen_load_fpr_D(dc, a->rs2); 4946e2fa6bd1SRichard Henderson func(dst, src1, src2); 4947e2fa6bd1SRichard Henderson gen_store_gpr(dc, a->rd, dst); 4948e2fa6bd1SRichard Henderson return advance_pc(dc); 4949e2fa6bd1SRichard Henderson } 4950e2fa6bd1SRichard Henderson 4951e2fa6bd1SRichard Henderson TRANS(FPCMPLE16, VIS1, do_rdd, a, gen_helper_fcmple16) 4952e2fa6bd1SRichard Henderson TRANS(FPCMPNE16, VIS1, do_rdd, a, gen_helper_fcmpne16) 4953e2fa6bd1SRichard Henderson TRANS(FPCMPGT16, VIS1, do_rdd, a, gen_helper_fcmpgt16) 4954e2fa6bd1SRichard Henderson TRANS(FPCMPEQ16, VIS1, do_rdd, a, gen_helper_fcmpeq16) 4955e2fa6bd1SRichard Henderson 4956e2fa6bd1SRichard Henderson TRANS(FPCMPLE32, VIS1, do_rdd, a, gen_helper_fcmple32) 4957e2fa6bd1SRichard Henderson TRANS(FPCMPNE32, VIS1, do_rdd, a, gen_helper_fcmpne32) 4958e2fa6bd1SRichard Henderson TRANS(FPCMPGT32, VIS1, do_rdd, a, gen_helper_fcmpgt32) 4959e2fa6bd1SRichard Henderson TRANS(FPCMPEQ32, VIS1, do_rdd, a, gen_helper_fcmpeq32) 4960e2fa6bd1SRichard Henderson 4961f2a59b0aSRichard Henderson static bool do_env_ddd(DisasContext *dc, arg_r_r_r *a, 4962f2a59b0aSRichard Henderson void (*func)(TCGv_i64, TCGv_env, TCGv_i64, TCGv_i64)) 4963f2a59b0aSRichard Henderson { 4964f2a59b0aSRichard Henderson TCGv_i64 dst, src1, src2; 4965f2a59b0aSRichard Henderson 4966f2a59b0aSRichard Henderson if (gen_trap_ifnofpu(dc)) { 4967f2a59b0aSRichard Henderson return true; 4968f2a59b0aSRichard Henderson } 4969f2a59b0aSRichard Henderson 4970f2a59b0aSRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 4971f2a59b0aSRichard Henderson dst = gen_dest_fpr_D(dc, a->rd); 4972f2a59b0aSRichard Henderson src1 = gen_load_fpr_D(dc, a->rs1); 4973f2a59b0aSRichard Henderson src2 = gen_load_fpr_D(dc, a->rs2); 4974f2a59b0aSRichard Henderson func(dst, tcg_env, src1, src2); 4975f2a59b0aSRichard Henderson gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env); 4976f2a59b0aSRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 4977f2a59b0aSRichard Henderson return advance_pc(dc); 4978f2a59b0aSRichard Henderson } 4979f2a59b0aSRichard Henderson 4980f2a59b0aSRichard Henderson TRANS(FADDd, ALL, do_env_ddd, a, gen_helper_faddd) 4981f2a59b0aSRichard Henderson TRANS(FSUBd, ALL, do_env_ddd, a, gen_helper_fsubd) 4982f2a59b0aSRichard Henderson TRANS(FMULd, ALL, do_env_ddd, a, gen_helper_fmuld) 4983f2a59b0aSRichard Henderson TRANS(FDIVd, ALL, do_env_ddd, a, gen_helper_fdivd) 4984f2a59b0aSRichard Henderson 4985ff4c711bSRichard Henderson static bool trans_FsMULd(DisasContext *dc, arg_r_r_r *a) 4986ff4c711bSRichard Henderson { 4987ff4c711bSRichard Henderson TCGv_i64 dst; 4988ff4c711bSRichard Henderson TCGv_i32 src1, src2; 4989ff4c711bSRichard Henderson 4990ff4c711bSRichard Henderson if (gen_trap_ifnofpu(dc)) { 4991ff4c711bSRichard Henderson return true; 4992ff4c711bSRichard Henderson } 4993ff4c711bSRichard Henderson if (!(dc->def->features & CPU_FEATURE_FSMULD)) { 4994ff4c711bSRichard Henderson return raise_unimpfpop(dc); 4995ff4c711bSRichard Henderson } 4996ff4c711bSRichard Henderson 4997ff4c711bSRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 4998ff4c711bSRichard Henderson dst = gen_dest_fpr_D(dc, a->rd); 4999ff4c711bSRichard Henderson src1 = gen_load_fpr_F(dc, a->rs1); 5000ff4c711bSRichard Henderson src2 = gen_load_fpr_F(dc, a->rs2); 5001ff4c711bSRichard Henderson gen_helper_fsmuld(dst, tcg_env, src1, src2); 5002ff4c711bSRichard Henderson gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env); 5003ff4c711bSRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 5004ff4c711bSRichard Henderson return advance_pc(dc); 5005ff4c711bSRichard Henderson } 5006ff4c711bSRichard Henderson 5007afb04344SRichard Henderson static bool do_dddd(DisasContext *dc, arg_r_r_r *a, 5008afb04344SRichard Henderson void (*func)(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_i64)) 5009afb04344SRichard Henderson { 5010afb04344SRichard Henderson TCGv_i64 dst, src0, src1, src2; 5011afb04344SRichard Henderson 5012afb04344SRichard Henderson if (gen_trap_ifnofpu(dc)) { 5013afb04344SRichard Henderson return true; 5014afb04344SRichard Henderson } 5015afb04344SRichard Henderson 5016afb04344SRichard Henderson dst = gen_dest_fpr_D(dc, a->rd); 5017afb04344SRichard Henderson src0 = gen_load_fpr_D(dc, a->rd); 5018afb04344SRichard Henderson src1 = gen_load_fpr_D(dc, a->rs1); 5019afb04344SRichard Henderson src2 = gen_load_fpr_D(dc, a->rs2); 5020afb04344SRichard Henderson func(dst, src0, src1, src2); 5021afb04344SRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 5022afb04344SRichard Henderson return advance_pc(dc); 5023afb04344SRichard Henderson } 5024afb04344SRichard Henderson 5025afb04344SRichard Henderson TRANS(PDIST, VIS1, do_dddd, a, gen_helper_pdist) 5026afb04344SRichard Henderson 5027a4056239SRichard Henderson static bool do_env_qqq(DisasContext *dc, arg_r_r_r *a, 5028a4056239SRichard Henderson void (*func)(TCGv_env)) 5029a4056239SRichard Henderson { 5030a4056239SRichard Henderson if (gen_trap_ifnofpu(dc)) { 5031a4056239SRichard Henderson return true; 5032a4056239SRichard Henderson } 5033a4056239SRichard Henderson if (gen_trap_float128(dc)) { 5034a4056239SRichard Henderson return true; 5035a4056239SRichard Henderson } 5036a4056239SRichard Henderson 5037a4056239SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 5038a4056239SRichard Henderson gen_op_load_fpr_QT0(QFPREG(a->rs1)); 5039a4056239SRichard Henderson gen_op_load_fpr_QT1(QFPREG(a->rs2)); 5040a4056239SRichard Henderson func(tcg_env); 5041a4056239SRichard Henderson gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env); 5042a4056239SRichard Henderson gen_op_store_QT0_fpr(QFPREG(a->rd)); 5043a4056239SRichard Henderson gen_update_fprs_dirty(dc, QFPREG(a->rd)); 5044a4056239SRichard Henderson return advance_pc(dc); 5045a4056239SRichard Henderson } 5046a4056239SRichard Henderson 5047a4056239SRichard Henderson TRANS(FADDq, ALL, do_env_qqq, a, gen_helper_faddq) 5048a4056239SRichard Henderson TRANS(FSUBq, ALL, do_env_qqq, a, gen_helper_fsubq) 5049a4056239SRichard Henderson TRANS(FMULq, ALL, do_env_qqq, a, gen_helper_fmulq) 5050a4056239SRichard Henderson TRANS(FDIVq, ALL, do_env_qqq, a, gen_helper_fdivq) 5051a4056239SRichard Henderson 50525e3b17bbSRichard Henderson static bool trans_FdMULq(DisasContext *dc, arg_r_r_r *a) 50535e3b17bbSRichard Henderson { 50545e3b17bbSRichard Henderson TCGv_i64 src1, src2; 50555e3b17bbSRichard Henderson 50565e3b17bbSRichard Henderson if (gen_trap_ifnofpu(dc)) { 50575e3b17bbSRichard Henderson return true; 50585e3b17bbSRichard Henderson } 50595e3b17bbSRichard Henderson if (gen_trap_float128(dc)) { 50605e3b17bbSRichard Henderson return true; 50615e3b17bbSRichard Henderson } 50625e3b17bbSRichard Henderson 50635e3b17bbSRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 50645e3b17bbSRichard Henderson src1 = gen_load_fpr_D(dc, a->rs1); 50655e3b17bbSRichard Henderson src2 = gen_load_fpr_D(dc, a->rs2); 50665e3b17bbSRichard Henderson gen_helper_fdmulq(tcg_env, src1, src2); 50675e3b17bbSRichard Henderson gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env); 50685e3b17bbSRichard Henderson gen_op_store_QT0_fpr(QFPREG(a->rd)); 50695e3b17bbSRichard Henderson gen_update_fprs_dirty(dc, QFPREG(a->rd)); 50705e3b17bbSRichard Henderson return advance_pc(dc); 50715e3b17bbSRichard Henderson } 50725e3b17bbSRichard Henderson 5073f7ec8155SRichard Henderson static bool do_fmovr(DisasContext *dc, arg_FMOVRs *a, bool is_128, 5074f7ec8155SRichard Henderson void (*func)(DisasContext *, DisasCompare *, int, int)) 5075f7ec8155SRichard Henderson { 5076f7ec8155SRichard Henderson DisasCompare cmp; 5077f7ec8155SRichard Henderson 5078f7ec8155SRichard Henderson if (gen_trap_ifnofpu(dc)) { 5079f7ec8155SRichard Henderson return true; 5080f7ec8155SRichard Henderson } 5081f7ec8155SRichard Henderson if (is_128 && gen_trap_float128(dc)) { 5082f7ec8155SRichard Henderson return true; 5083f7ec8155SRichard Henderson } 5084f7ec8155SRichard Henderson 5085f7ec8155SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 5086f7ec8155SRichard Henderson gen_compare_reg(&cmp, a->cond, gen_load_gpr(dc, a->rs1)); 5087f7ec8155SRichard Henderson func(dc, &cmp, a->rd, a->rs2); 5088f7ec8155SRichard Henderson return advance_pc(dc); 5089f7ec8155SRichard Henderson } 5090f7ec8155SRichard Henderson 5091f7ec8155SRichard Henderson TRANS(FMOVRs, 64, do_fmovr, a, false, gen_fmovs) 5092f7ec8155SRichard Henderson TRANS(FMOVRd, 64, do_fmovr, a, false, gen_fmovd) 5093f7ec8155SRichard Henderson TRANS(FMOVRq, 64, do_fmovr, a, true, gen_fmovq) 5094f7ec8155SRichard Henderson 5095f7ec8155SRichard Henderson static bool do_fmovcc(DisasContext *dc, arg_FMOVscc *a, bool is_128, 5096f7ec8155SRichard Henderson void (*func)(DisasContext *, DisasCompare *, int, int)) 5097f7ec8155SRichard Henderson { 5098f7ec8155SRichard Henderson DisasCompare cmp; 5099f7ec8155SRichard Henderson 5100f7ec8155SRichard Henderson if (gen_trap_ifnofpu(dc)) { 5101f7ec8155SRichard Henderson return true; 5102f7ec8155SRichard Henderson } 5103f7ec8155SRichard Henderson if (is_128 && gen_trap_float128(dc)) { 5104f7ec8155SRichard Henderson return true; 5105f7ec8155SRichard Henderson } 5106f7ec8155SRichard Henderson 5107f7ec8155SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 5108f7ec8155SRichard Henderson gen_compare(&cmp, a->cc, a->cond, dc); 5109f7ec8155SRichard Henderson func(dc, &cmp, a->rd, a->rs2); 5110f7ec8155SRichard Henderson return advance_pc(dc); 5111f7ec8155SRichard Henderson } 5112f7ec8155SRichard Henderson 5113f7ec8155SRichard Henderson TRANS(FMOVscc, 64, do_fmovcc, a, false, gen_fmovs) 5114f7ec8155SRichard Henderson TRANS(FMOVdcc, 64, do_fmovcc, a, false, gen_fmovd) 5115f7ec8155SRichard Henderson TRANS(FMOVqcc, 64, do_fmovcc, a, true, gen_fmovq) 5116f7ec8155SRichard Henderson 5117f7ec8155SRichard Henderson static bool do_fmovfcc(DisasContext *dc, arg_FMOVsfcc *a, bool is_128, 5118f7ec8155SRichard Henderson void (*func)(DisasContext *, DisasCompare *, int, int)) 5119f7ec8155SRichard Henderson { 5120f7ec8155SRichard Henderson DisasCompare cmp; 5121f7ec8155SRichard Henderson 5122f7ec8155SRichard Henderson if (gen_trap_ifnofpu(dc)) { 5123f7ec8155SRichard Henderson return true; 5124f7ec8155SRichard Henderson } 5125f7ec8155SRichard Henderson if (is_128 && gen_trap_float128(dc)) { 5126f7ec8155SRichard Henderson return true; 5127f7ec8155SRichard Henderson } 5128f7ec8155SRichard Henderson 5129f7ec8155SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 5130f7ec8155SRichard Henderson gen_fcompare(&cmp, a->cc, a->cond); 5131f7ec8155SRichard Henderson func(dc, &cmp, a->rd, a->rs2); 5132f7ec8155SRichard Henderson return advance_pc(dc); 5133f7ec8155SRichard Henderson } 5134f7ec8155SRichard Henderson 5135f7ec8155SRichard Henderson TRANS(FMOVsfcc, 64, do_fmovfcc, a, false, gen_fmovs) 5136f7ec8155SRichard Henderson TRANS(FMOVdfcc, 64, do_fmovfcc, a, false, gen_fmovd) 5137f7ec8155SRichard Henderson TRANS(FMOVqfcc, 64, do_fmovfcc, a, true, gen_fmovq) 5138f7ec8155SRichard Henderson 513940f9ad21SRichard Henderson static bool do_fcmps(DisasContext *dc, arg_FCMPs *a, bool e) 514040f9ad21SRichard Henderson { 514140f9ad21SRichard Henderson TCGv_i32 src1, src2; 514240f9ad21SRichard Henderson 514340f9ad21SRichard Henderson if (avail_32(dc) && a->cc != 0) { 514440f9ad21SRichard Henderson return false; 514540f9ad21SRichard Henderson } 514640f9ad21SRichard Henderson if (gen_trap_ifnofpu(dc)) { 514740f9ad21SRichard Henderson return true; 514840f9ad21SRichard Henderson } 514940f9ad21SRichard Henderson 515040f9ad21SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 515140f9ad21SRichard Henderson src1 = gen_load_fpr_F(dc, a->rs1); 515240f9ad21SRichard Henderson src2 = gen_load_fpr_F(dc, a->rs2); 515340f9ad21SRichard Henderson if (e) { 515440f9ad21SRichard Henderson gen_op_fcmpes(a->cc, src1, src2); 515540f9ad21SRichard Henderson } else { 515640f9ad21SRichard Henderson gen_op_fcmps(a->cc, src1, src2); 515740f9ad21SRichard Henderson } 515840f9ad21SRichard Henderson return advance_pc(dc); 515940f9ad21SRichard Henderson } 516040f9ad21SRichard Henderson 516140f9ad21SRichard Henderson TRANS(FCMPs, ALL, do_fcmps, a, false) 516240f9ad21SRichard Henderson TRANS(FCMPEs, ALL, do_fcmps, a, true) 516340f9ad21SRichard Henderson 516440f9ad21SRichard Henderson static bool do_fcmpd(DisasContext *dc, arg_FCMPd *a, bool e) 516540f9ad21SRichard Henderson { 516640f9ad21SRichard Henderson TCGv_i64 src1, src2; 516740f9ad21SRichard Henderson 516840f9ad21SRichard Henderson if (avail_32(dc) && a->cc != 0) { 516940f9ad21SRichard Henderson return false; 517040f9ad21SRichard Henderson } 517140f9ad21SRichard Henderson if (gen_trap_ifnofpu(dc)) { 517240f9ad21SRichard Henderson return true; 517340f9ad21SRichard Henderson } 517440f9ad21SRichard Henderson 517540f9ad21SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 517640f9ad21SRichard Henderson src1 = gen_load_fpr_D(dc, a->rs1); 517740f9ad21SRichard Henderson src2 = gen_load_fpr_D(dc, a->rs2); 517840f9ad21SRichard Henderson if (e) { 517940f9ad21SRichard Henderson gen_op_fcmped(a->cc, src1, src2); 518040f9ad21SRichard Henderson } else { 518140f9ad21SRichard Henderson gen_op_fcmpd(a->cc, src1, src2); 518240f9ad21SRichard Henderson } 518340f9ad21SRichard Henderson return advance_pc(dc); 518440f9ad21SRichard Henderson } 518540f9ad21SRichard Henderson 518640f9ad21SRichard Henderson TRANS(FCMPd, ALL, do_fcmpd, a, false) 518740f9ad21SRichard Henderson TRANS(FCMPEd, ALL, do_fcmpd, a, true) 518840f9ad21SRichard Henderson 518940f9ad21SRichard Henderson static bool do_fcmpq(DisasContext *dc, arg_FCMPq *a, bool e) 519040f9ad21SRichard Henderson { 519140f9ad21SRichard Henderson if (avail_32(dc) && a->cc != 0) { 519240f9ad21SRichard Henderson return false; 519340f9ad21SRichard Henderson } 519440f9ad21SRichard Henderson if (gen_trap_ifnofpu(dc)) { 519540f9ad21SRichard Henderson return true; 519640f9ad21SRichard Henderson } 519740f9ad21SRichard Henderson if (gen_trap_float128(dc)) { 519840f9ad21SRichard Henderson return true; 519940f9ad21SRichard Henderson } 520040f9ad21SRichard Henderson 520140f9ad21SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 520240f9ad21SRichard Henderson gen_op_load_fpr_QT0(QFPREG(a->rs1)); 520340f9ad21SRichard Henderson gen_op_load_fpr_QT1(QFPREG(a->rs2)); 520440f9ad21SRichard Henderson if (e) { 520540f9ad21SRichard Henderson gen_op_fcmpeq(a->cc); 520640f9ad21SRichard Henderson } else { 520740f9ad21SRichard Henderson gen_op_fcmpq(a->cc); 520840f9ad21SRichard Henderson } 520940f9ad21SRichard Henderson return advance_pc(dc); 521040f9ad21SRichard Henderson } 521140f9ad21SRichard Henderson 521240f9ad21SRichard Henderson TRANS(FCMPq, ALL, do_fcmpq, a, false) 521340f9ad21SRichard Henderson TRANS(FCMPEq, ALL, do_fcmpq, a, true) 521440f9ad21SRichard Henderson 52156e61bc94SEmilio G. Cota static void sparc_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) 5216fcf5ef2aSThomas Huth { 52176e61bc94SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 5218b77af26eSRichard Henderson CPUSPARCState *env = cpu_env(cs); 52196e61bc94SEmilio G. Cota int bound; 5220af00be49SEmilio G. Cota 5221af00be49SEmilio G. Cota dc->pc = dc->base.pc_first; 52226e61bc94SEmilio G. Cota dc->npc = (target_ulong)dc->base.tb->cs_base; 5223fcf5ef2aSThomas Huth dc->cc_op = CC_OP_DYNAMIC; 52246e61bc94SEmilio G. Cota dc->mem_idx = dc->base.tb->flags & TB_FLAG_MMU_MASK; 5225576e1c4cSIgor Mammedov dc->def = &env->def; 52266e61bc94SEmilio G. Cota dc->fpu_enabled = tb_fpu_enabled(dc->base.tb->flags); 52276e61bc94SEmilio G. Cota dc->address_mask_32bit = tb_am_enabled(dc->base.tb->flags); 5228c9b459aaSArtyom Tarasenko #ifndef CONFIG_USER_ONLY 52296e61bc94SEmilio G. Cota dc->supervisor = (dc->base.tb->flags & TB_FLAG_SUPER) != 0; 5230c9b459aaSArtyom Tarasenko #endif 5231fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64 5232fcf5ef2aSThomas Huth dc->fprs_dirty = 0; 52336e61bc94SEmilio G. Cota dc->asi = (dc->base.tb->flags >> TB_FLAG_ASI_SHIFT) & 0xff; 5234c9b459aaSArtyom Tarasenko #ifndef CONFIG_USER_ONLY 52356e61bc94SEmilio G. Cota dc->hypervisor = (dc->base.tb->flags & TB_FLAG_HYPER) != 0; 5236c9b459aaSArtyom Tarasenko #endif 5237fcf5ef2aSThomas Huth #endif 52386e61bc94SEmilio G. Cota /* 52396e61bc94SEmilio G. Cota * if we reach a page boundary, we stop generation so that the 52406e61bc94SEmilio G. Cota * PC of a TT_TFAULT exception is always in the right page 52416e61bc94SEmilio G. Cota */ 52426e61bc94SEmilio G. Cota bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4; 52436e61bc94SEmilio G. Cota dc->base.max_insns = MIN(dc->base.max_insns, bound); 5244af00be49SEmilio G. Cota } 5245fcf5ef2aSThomas Huth 52466e61bc94SEmilio G. Cota static void sparc_tr_tb_start(DisasContextBase *db, CPUState *cs) 52476e61bc94SEmilio G. Cota { 52486e61bc94SEmilio G. Cota } 52496e61bc94SEmilio G. Cota 52506e61bc94SEmilio G. Cota static void sparc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) 52516e61bc94SEmilio G. Cota { 52526e61bc94SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 5253633c4283SRichard Henderson target_ulong npc = dc->npc; 52546e61bc94SEmilio G. Cota 5255633c4283SRichard Henderson if (npc & 3) { 5256633c4283SRichard Henderson switch (npc) { 5257633c4283SRichard Henderson case JUMP_PC: 5258fcf5ef2aSThomas Huth assert(dc->jump_pc[1] == dc->pc + 4); 5259633c4283SRichard Henderson npc = dc->jump_pc[0] | JUMP_PC; 5260633c4283SRichard Henderson break; 5261633c4283SRichard Henderson case DYNAMIC_PC: 5262633c4283SRichard Henderson case DYNAMIC_PC_LOOKUP: 5263633c4283SRichard Henderson npc = DYNAMIC_PC; 5264633c4283SRichard Henderson break; 5265633c4283SRichard Henderson default: 5266633c4283SRichard Henderson g_assert_not_reached(); 5267fcf5ef2aSThomas Huth } 52686e61bc94SEmilio G. Cota } 5269633c4283SRichard Henderson tcg_gen_insn_start(dc->pc, npc); 5270633c4283SRichard Henderson } 5271fcf5ef2aSThomas Huth 52726e61bc94SEmilio G. Cota static void sparc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) 52736e61bc94SEmilio G. Cota { 52746e61bc94SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 5275b77af26eSRichard Henderson CPUSPARCState *env = cpu_env(cs); 52766e61bc94SEmilio G. Cota unsigned int insn; 5277fcf5ef2aSThomas Huth 52784e116893SIlya Leoshkevich insn = translator_ldl(env, &dc->base, dc->pc); 5279af00be49SEmilio G. Cota dc->base.pc_next += 4; 5280878cc677SRichard Henderson 5281878cc677SRichard Henderson if (!decode(dc, insn)) { 5282ba9c09b4SRichard Henderson gen_exception(dc, TT_ILL_INSN); 5283878cc677SRichard Henderson } 5284fcf5ef2aSThomas Huth 5285af00be49SEmilio G. Cota if (dc->base.is_jmp == DISAS_NORETURN) { 52866e61bc94SEmilio G. Cota return; 5287c5e6ccdfSEmilio G. Cota } 5288af00be49SEmilio G. Cota if (dc->pc != dc->base.pc_next) { 52896e61bc94SEmilio G. Cota dc->base.is_jmp = DISAS_TOO_MANY; 5290af00be49SEmilio G. Cota } 52916e61bc94SEmilio G. Cota } 5292fcf5ef2aSThomas Huth 52936e61bc94SEmilio G. Cota static void sparc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) 52946e61bc94SEmilio G. Cota { 52956e61bc94SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 5296186e7890SRichard Henderson DisasDelayException *e, *e_next; 5297633c4283SRichard Henderson bool may_lookup; 52986e61bc94SEmilio G. Cota 529946bb0137SMark Cave-Ayland switch (dc->base.is_jmp) { 530046bb0137SMark Cave-Ayland case DISAS_NEXT: 530146bb0137SMark Cave-Ayland case DISAS_TOO_MANY: 5302633c4283SRichard Henderson if (((dc->pc | dc->npc) & 3) == 0) { 5303fcf5ef2aSThomas Huth /* static PC and NPC: we can use direct chaining */ 5304fcf5ef2aSThomas Huth gen_goto_tb(dc, 0, dc->pc, dc->npc); 5305633c4283SRichard Henderson break; 5306fcf5ef2aSThomas Huth } 5307633c4283SRichard Henderson 5308930f1865SRichard Henderson may_lookup = true; 5309633c4283SRichard Henderson if (dc->pc & 3) { 5310633c4283SRichard Henderson switch (dc->pc) { 5311633c4283SRichard Henderson case DYNAMIC_PC_LOOKUP: 5312633c4283SRichard Henderson break; 5313633c4283SRichard Henderson case DYNAMIC_PC: 5314633c4283SRichard Henderson may_lookup = false; 5315633c4283SRichard Henderson break; 5316633c4283SRichard Henderson default: 5317633c4283SRichard Henderson g_assert_not_reached(); 5318633c4283SRichard Henderson } 5319633c4283SRichard Henderson } else { 5320633c4283SRichard Henderson tcg_gen_movi_tl(cpu_pc, dc->pc); 5321633c4283SRichard Henderson } 5322633c4283SRichard Henderson 5323930f1865SRichard Henderson if (dc->npc & 3) { 5324930f1865SRichard Henderson switch (dc->npc) { 5325930f1865SRichard Henderson case JUMP_PC: 5326930f1865SRichard Henderson gen_generic_branch(dc); 5327930f1865SRichard Henderson break; 5328930f1865SRichard Henderson case DYNAMIC_PC: 5329930f1865SRichard Henderson may_lookup = false; 5330930f1865SRichard Henderson break; 5331930f1865SRichard Henderson case DYNAMIC_PC_LOOKUP: 5332930f1865SRichard Henderson break; 5333930f1865SRichard Henderson default: 5334930f1865SRichard Henderson g_assert_not_reached(); 5335930f1865SRichard Henderson } 5336930f1865SRichard Henderson } else { 5337930f1865SRichard Henderson tcg_gen_movi_tl(cpu_npc, dc->npc); 5338930f1865SRichard Henderson } 5339633c4283SRichard Henderson if (may_lookup) { 5340633c4283SRichard Henderson tcg_gen_lookup_and_goto_ptr(); 5341633c4283SRichard Henderson } else { 534207ea28b4SRichard Henderson tcg_gen_exit_tb(NULL, 0); 5343fcf5ef2aSThomas Huth } 534446bb0137SMark Cave-Ayland break; 534546bb0137SMark Cave-Ayland 534646bb0137SMark Cave-Ayland case DISAS_NORETURN: 534746bb0137SMark Cave-Ayland break; 534846bb0137SMark Cave-Ayland 534946bb0137SMark Cave-Ayland case DISAS_EXIT: 535046bb0137SMark Cave-Ayland /* Exit TB */ 535146bb0137SMark Cave-Ayland save_state(dc); 535246bb0137SMark Cave-Ayland tcg_gen_exit_tb(NULL, 0); 535346bb0137SMark Cave-Ayland break; 535446bb0137SMark Cave-Ayland 535546bb0137SMark Cave-Ayland default: 535646bb0137SMark Cave-Ayland g_assert_not_reached(); 5357fcf5ef2aSThomas Huth } 5358186e7890SRichard Henderson 5359186e7890SRichard Henderson for (e = dc->delay_excp_list; e ; e = e_next) { 5360186e7890SRichard Henderson gen_set_label(e->lab); 5361186e7890SRichard Henderson 5362186e7890SRichard Henderson tcg_gen_movi_tl(cpu_pc, e->pc); 5363186e7890SRichard Henderson if (e->npc % 4 == 0) { 5364186e7890SRichard Henderson tcg_gen_movi_tl(cpu_npc, e->npc); 5365186e7890SRichard Henderson } 5366186e7890SRichard Henderson gen_helper_raise_exception(tcg_env, e->excp); 5367186e7890SRichard Henderson 5368186e7890SRichard Henderson e_next = e->next; 5369186e7890SRichard Henderson g_free(e); 5370186e7890SRichard Henderson } 5371fcf5ef2aSThomas Huth } 53726e61bc94SEmilio G. Cota 53738eb806a7SRichard Henderson static void sparc_tr_disas_log(const DisasContextBase *dcbase, 53748eb806a7SRichard Henderson CPUState *cpu, FILE *logfile) 53756e61bc94SEmilio G. Cota { 53768eb806a7SRichard Henderson fprintf(logfile, "IN: %s\n", lookup_symbol(dcbase->pc_first)); 53778eb806a7SRichard Henderson target_disas(logfile, cpu, dcbase->pc_first, dcbase->tb->size); 53786e61bc94SEmilio G. Cota } 53796e61bc94SEmilio G. Cota 53806e61bc94SEmilio G. Cota static const TranslatorOps sparc_tr_ops = { 53816e61bc94SEmilio G. Cota .init_disas_context = sparc_tr_init_disas_context, 53826e61bc94SEmilio G. Cota .tb_start = sparc_tr_tb_start, 53836e61bc94SEmilio G. Cota .insn_start = sparc_tr_insn_start, 53846e61bc94SEmilio G. Cota .translate_insn = sparc_tr_translate_insn, 53856e61bc94SEmilio G. Cota .tb_stop = sparc_tr_tb_stop, 53866e61bc94SEmilio G. Cota .disas_log = sparc_tr_disas_log, 53876e61bc94SEmilio G. Cota }; 53886e61bc94SEmilio G. Cota 5389597f9b2dSRichard Henderson void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int *max_insns, 5390306c8721SRichard Henderson target_ulong pc, void *host_pc) 53916e61bc94SEmilio G. Cota { 53926e61bc94SEmilio G. Cota DisasContext dc = {}; 53936e61bc94SEmilio G. Cota 5394306c8721SRichard Henderson translator_loop(cs, tb, max_insns, pc, host_pc, &sparc_tr_ops, &dc.base); 5395fcf5ef2aSThomas Huth } 5396fcf5ef2aSThomas Huth 539755c3ceefSRichard Henderson void sparc_tcg_init(void) 5398fcf5ef2aSThomas Huth { 5399fcf5ef2aSThomas Huth static const char gregnames[32][4] = { 5400fcf5ef2aSThomas Huth "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7", 5401fcf5ef2aSThomas Huth "o0", "o1", "o2", "o3", "o4", "o5", "o6", "o7", 5402fcf5ef2aSThomas Huth "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7", 5403fcf5ef2aSThomas Huth "i0", "i1", "i2", "i3", "i4", "i5", "i6", "i7", 5404fcf5ef2aSThomas Huth }; 5405fcf5ef2aSThomas Huth static const char fregnames[32][4] = { 5406fcf5ef2aSThomas Huth "f0", "f2", "f4", "f6", "f8", "f10", "f12", "f14", 5407fcf5ef2aSThomas Huth "f16", "f18", "f20", "f22", "f24", "f26", "f28", "f30", 5408fcf5ef2aSThomas Huth "f32", "f34", "f36", "f38", "f40", "f42", "f44", "f46", 5409fcf5ef2aSThomas Huth "f48", "f50", "f52", "f54", "f56", "f58", "f60", "f62", 5410fcf5ef2aSThomas Huth }; 5411fcf5ef2aSThomas Huth 5412fcf5ef2aSThomas Huth static const struct { TCGv_i32 *ptr; int off; const char *name; } r32[] = { 5413fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64 5414fcf5ef2aSThomas Huth { &cpu_fprs, offsetof(CPUSPARCState, fprs), "fprs" }, 5415fcf5ef2aSThomas Huth #endif 5416fcf5ef2aSThomas Huth { &cpu_cc_op, offsetof(CPUSPARCState, cc_op), "cc_op" }, 5417fcf5ef2aSThomas Huth }; 5418fcf5ef2aSThomas Huth 5419fcf5ef2aSThomas Huth static const struct { TCGv *ptr; int off; const char *name; } rtl[] = { 5420fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64 5421fcf5ef2aSThomas Huth { &cpu_gsr, offsetof(CPUSPARCState, gsr), "gsr" }, 54222a1905c7SRichard Henderson { &cpu_xcc_Z, offsetof(CPUSPARCState, xcc_Z), "xcc_Z" }, 54232a1905c7SRichard Henderson { &cpu_xcc_C, offsetof(CPUSPARCState, xcc_C), "xcc_C" }, 5424fcf5ef2aSThomas Huth #endif 54252a1905c7SRichard Henderson { &cpu_cc_N, offsetof(CPUSPARCState, cc_N), "cc_N" }, 54262a1905c7SRichard Henderson { &cpu_cc_V, offsetof(CPUSPARCState, cc_V), "cc_V" }, 54272a1905c7SRichard Henderson { &cpu_icc_Z, offsetof(CPUSPARCState, icc_Z), "icc_Z" }, 54282a1905c7SRichard Henderson { &cpu_icc_C, offsetof(CPUSPARCState, icc_C), "icc_C" }, 5429fcf5ef2aSThomas Huth { &cpu_cond, offsetof(CPUSPARCState, cond), "cond" }, 5430fcf5ef2aSThomas Huth { &cpu_cc_src, offsetof(CPUSPARCState, cc_src), "cc_src" }, 5431fcf5ef2aSThomas Huth { &cpu_cc_src2, offsetof(CPUSPARCState, cc_src2), "cc_src2" }, 5432fcf5ef2aSThomas Huth { &cpu_cc_dst, offsetof(CPUSPARCState, cc_dst), "cc_dst" }, 5433fcf5ef2aSThomas Huth { &cpu_fsr, offsetof(CPUSPARCState, fsr), "fsr" }, 5434fcf5ef2aSThomas Huth { &cpu_pc, offsetof(CPUSPARCState, pc), "pc" }, 5435fcf5ef2aSThomas Huth { &cpu_npc, offsetof(CPUSPARCState, npc), "npc" }, 5436fcf5ef2aSThomas Huth { &cpu_y, offsetof(CPUSPARCState, y), "y" }, 5437fcf5ef2aSThomas Huth { &cpu_tbr, offsetof(CPUSPARCState, tbr), "tbr" }, 5438fcf5ef2aSThomas Huth }; 5439fcf5ef2aSThomas Huth 5440fcf5ef2aSThomas Huth unsigned int i; 5441fcf5ef2aSThomas Huth 5442ad75a51eSRichard Henderson cpu_regwptr = tcg_global_mem_new_ptr(tcg_env, 5443fcf5ef2aSThomas Huth offsetof(CPUSPARCState, regwptr), 5444fcf5ef2aSThomas Huth "regwptr"); 5445fcf5ef2aSThomas Huth 5446fcf5ef2aSThomas Huth for (i = 0; i < ARRAY_SIZE(r32); ++i) { 5447ad75a51eSRichard Henderson *r32[i].ptr = tcg_global_mem_new_i32(tcg_env, r32[i].off, r32[i].name); 5448fcf5ef2aSThomas Huth } 5449fcf5ef2aSThomas Huth 5450fcf5ef2aSThomas Huth for (i = 0; i < ARRAY_SIZE(rtl); ++i) { 5451ad75a51eSRichard Henderson *rtl[i].ptr = tcg_global_mem_new(tcg_env, rtl[i].off, rtl[i].name); 5452fcf5ef2aSThomas Huth } 5453fcf5ef2aSThomas Huth 5454f764718dSRichard Henderson cpu_regs[0] = NULL; 5455fcf5ef2aSThomas Huth for (i = 1; i < 8; ++i) { 5456ad75a51eSRichard Henderson cpu_regs[i] = tcg_global_mem_new(tcg_env, 5457fcf5ef2aSThomas Huth offsetof(CPUSPARCState, gregs[i]), 5458fcf5ef2aSThomas Huth gregnames[i]); 5459fcf5ef2aSThomas Huth } 5460fcf5ef2aSThomas Huth 5461fcf5ef2aSThomas Huth for (i = 8; i < 32; ++i) { 5462fcf5ef2aSThomas Huth cpu_regs[i] = tcg_global_mem_new(cpu_regwptr, 5463fcf5ef2aSThomas Huth (i - 8) * sizeof(target_ulong), 5464fcf5ef2aSThomas Huth gregnames[i]); 5465fcf5ef2aSThomas Huth } 5466fcf5ef2aSThomas Huth 5467fcf5ef2aSThomas Huth for (i = 0; i < TARGET_DPREGS; i++) { 5468ad75a51eSRichard Henderson cpu_fpr[i] = tcg_global_mem_new_i64(tcg_env, 5469fcf5ef2aSThomas Huth offsetof(CPUSPARCState, fpr[i]), 5470fcf5ef2aSThomas Huth fregnames[i]); 5471fcf5ef2aSThomas Huth } 5472fcf5ef2aSThomas Huth } 5473fcf5ef2aSThomas Huth 5474f36aaa53SRichard Henderson void sparc_restore_state_to_opc(CPUState *cs, 5475f36aaa53SRichard Henderson const TranslationBlock *tb, 5476f36aaa53SRichard Henderson const uint64_t *data) 5477fcf5ef2aSThomas Huth { 5478f36aaa53SRichard Henderson SPARCCPU *cpu = SPARC_CPU(cs); 5479f36aaa53SRichard Henderson CPUSPARCState *env = &cpu->env; 5480fcf5ef2aSThomas Huth target_ulong pc = data[0]; 5481fcf5ef2aSThomas Huth target_ulong npc = data[1]; 5482fcf5ef2aSThomas Huth 5483fcf5ef2aSThomas Huth env->pc = pc; 5484fcf5ef2aSThomas Huth if (npc == DYNAMIC_PC) { 5485fcf5ef2aSThomas Huth /* dynamic NPC: already stored */ 5486fcf5ef2aSThomas Huth } else if (npc & JUMP_PC) { 5487fcf5ef2aSThomas Huth /* jump PC: use 'cond' and the jump targets of the translation */ 5488fcf5ef2aSThomas Huth if (env->cond) { 5489fcf5ef2aSThomas Huth env->npc = npc & ~3; 5490fcf5ef2aSThomas Huth } else { 5491fcf5ef2aSThomas Huth env->npc = pc + 4; 5492fcf5ef2aSThomas Huth } 5493fcf5ef2aSThomas Huth } else { 5494fcf5ef2aSThomas Huth env->npc = npc; 5495fcf5ef2aSThomas Huth } 5496fcf5ef2aSThomas Huth } 5497