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; 115*2a1905c7SRichard Henderson static TCGv cpu_cc_N; 116*2a1905c7SRichard Henderson static TCGv cpu_cc_V; 117*2a1905c7SRichard Henderson static TCGv cpu_icc_Z; 118*2a1905c7SRichard Henderson static TCGv cpu_icc_C; 119fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64 120*2a1905c7SRichard Henderson static TCGv cpu_xcc_Z; 121*2a1905c7SRichard Henderson static TCGv cpu_xcc_C; 122*2a1905c7SRichard 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 128*2a1905c7SRichard Henderson 129*2a1905c7SRichard Henderson #ifdef TARGET_SPARC64 130*2a1905c7SRichard Henderson #define cpu_cc_Z cpu_xcc_Z 131*2a1905c7SRichard Henderson #define cpu_cc_C cpu_xcc_C 132*2a1905c7SRichard Henderson #else 133*2a1905c7SRichard Henderson #define cpu_cc_Z cpu_icc_Z 134*2a1905c7SRichard Henderson #define cpu_cc_C cpu_icc_C 135*2a1905c7SRichard Henderson #define cpu_xcc_Z ({ qemu_build_not_reached(); NULL; }) 136*2a1905c7SRichard Henderson #define cpu_xcc_C ({ qemu_build_not_reached(); NULL; }) 137*2a1905c7SRichard Henderson #endif 138*2a1905c7SRichard 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; 634*2a1905c7SRichard 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; 638*2a1905c7SRichard 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 1120fcf5ef2aSThomas Huth static int logic_cond[16] = { 1121fcf5ef2aSThomas Huth TCG_COND_NEVER, 1122fcf5ef2aSThomas Huth TCG_COND_EQ, /* eq: Z */ 1123fcf5ef2aSThomas Huth TCG_COND_LE, /* le: Z | (N ^ V) -> Z | N */ 1124fcf5ef2aSThomas Huth TCG_COND_LT, /* lt: N ^ V -> N */ 1125fcf5ef2aSThomas Huth TCG_COND_EQ, /* leu: C | Z -> Z */ 1126fcf5ef2aSThomas Huth TCG_COND_NEVER, /* ltu: C -> 0 */ 1127fcf5ef2aSThomas Huth TCG_COND_LT, /* neg: N */ 1128fcf5ef2aSThomas Huth TCG_COND_NEVER, /* vs: V -> 0 */ 1129fcf5ef2aSThomas Huth TCG_COND_ALWAYS, 1130fcf5ef2aSThomas Huth TCG_COND_NE, /* ne: !Z */ 1131fcf5ef2aSThomas Huth TCG_COND_GT, /* gt: !(Z | (N ^ V)) -> !(Z | N) */ 1132fcf5ef2aSThomas Huth TCG_COND_GE, /* ge: !(N ^ V) -> !N */ 1133fcf5ef2aSThomas Huth TCG_COND_NE, /* gtu: !(C | Z) -> !Z */ 1134fcf5ef2aSThomas Huth TCG_COND_ALWAYS, /* geu: !C -> 1 */ 1135fcf5ef2aSThomas Huth TCG_COND_GE, /* pos: !N */ 1136fcf5ef2aSThomas Huth TCG_COND_ALWAYS, /* vc: !V -> 1 */ 1137fcf5ef2aSThomas Huth }; 1138fcf5ef2aSThomas Huth 1139*2a1905c7SRichard Henderson TCGv t1, t2; 1140fcf5ef2aSThomas Huth 1141*2a1905c7SRichard Henderson cmp->is_bool = false; 1142fcf5ef2aSThomas Huth 1143fcf5ef2aSThomas Huth switch (dc->cc_op) { 1144fcf5ef2aSThomas Huth case CC_OP_LOGIC: 1145fcf5ef2aSThomas Huth cmp->cond = logic_cond[cond]; 1146fcf5ef2aSThomas Huth do_compare_dst_0: 114700ab7e61SRichard Henderson cmp->c2 = tcg_constant_tl(0); 1148*2a1905c7SRichard Henderson if (TARGET_LONG_BITS == 32 || xcc) { 1149fcf5ef2aSThomas Huth cmp->c1 = cpu_cc_dst; 1150*2a1905c7SRichard Henderson } else { 1151*2a1905c7SRichard Henderson cmp->c1 = t1 = tcg_temp_new(); 1152*2a1905c7SRichard Henderson tcg_gen_ext32s_tl(t1, cpu_cc_dst); 1153*2a1905c7SRichard Henderson } 1154*2a1905c7SRichard Henderson return; 1155fcf5ef2aSThomas Huth 1156fcf5ef2aSThomas Huth case CC_OP_SUB: 1157fcf5ef2aSThomas Huth switch (cond) { 1158fcf5ef2aSThomas Huth case 6: /* neg */ 1159fcf5ef2aSThomas Huth case 14: /* pos */ 1160fcf5ef2aSThomas Huth cmp->cond = (cond == 6 ? TCG_COND_LT : TCG_COND_GE); 1161fcf5ef2aSThomas Huth goto do_compare_dst_0; 1162fcf5ef2aSThomas Huth 1163fcf5ef2aSThomas Huth case 7: /* overflow */ 1164fcf5ef2aSThomas Huth case 15: /* !overflow */ 1165*2a1905c7SRichard Henderson break; 1166fcf5ef2aSThomas Huth 1167fcf5ef2aSThomas Huth default: 1168fcf5ef2aSThomas Huth cmp->cond = subcc_cond[cond]; 1169*2a1905c7SRichard Henderson if (TARGET_LONG_BITS == 32 || xcc) { 1170fcf5ef2aSThomas Huth cmp->c1 = cpu_cc_src; 1171fcf5ef2aSThomas Huth cmp->c2 = cpu_cc_src2; 1172*2a1905c7SRichard Henderson } else { 1173*2a1905c7SRichard Henderson /* Note that sign-extension works for unsigned compares as 1174*2a1905c7SRichard Henderson long as both operands are sign-extended. */ 1175*2a1905c7SRichard Henderson cmp->c1 = t1 = tcg_temp_new(); 1176*2a1905c7SRichard Henderson tcg_gen_ext32s_tl(t1, cpu_cc_src); 1177*2a1905c7SRichard Henderson cmp->c2 = t2 = tcg_temp_new(); 1178*2a1905c7SRichard Henderson tcg_gen_ext32s_tl(t2, cpu_cc_src2); 1179*2a1905c7SRichard Henderson } 1180*2a1905c7SRichard Henderson return; 1181fcf5ef2aSThomas Huth } 1182fcf5ef2aSThomas Huth break; 1183fcf5ef2aSThomas Huth 1184fcf5ef2aSThomas Huth default: 1185ad75a51eSRichard Henderson gen_helper_compute_psr(tcg_env); 1186fcf5ef2aSThomas Huth dc->cc_op = CC_OP_FLAGS; 1187*2a1905c7SRichard Henderson break; 1188fcf5ef2aSThomas Huth 1189fcf5ef2aSThomas Huth case CC_OP_FLAGS: 1190fcf5ef2aSThomas Huth break; 1191fcf5ef2aSThomas Huth } 1192*2a1905c7SRichard Henderson 1193*2a1905c7SRichard Henderson cmp->c1 = t1 = tcg_temp_new(); 1194*2a1905c7SRichard Henderson cmp->c2 = tcg_constant_tl(0); 1195*2a1905c7SRichard Henderson 1196*2a1905c7SRichard Henderson switch (cond & 7) { 1197*2a1905c7SRichard Henderson case 0x0: /* never */ 1198*2a1905c7SRichard Henderson cmp->cond = TCG_COND_NEVER; 1199*2a1905c7SRichard Henderson cmp->c1 = cmp->c2; 1200fcf5ef2aSThomas Huth break; 1201*2a1905c7SRichard Henderson 1202*2a1905c7SRichard Henderson case 0x1: /* eq: Z */ 1203*2a1905c7SRichard Henderson cmp->cond = TCG_COND_EQ; 1204*2a1905c7SRichard Henderson if (TARGET_LONG_BITS == 32 || xcc) { 1205*2a1905c7SRichard Henderson tcg_gen_mov_tl(t1, cpu_cc_Z); 1206*2a1905c7SRichard Henderson } else { 1207*2a1905c7SRichard Henderson tcg_gen_ext32u_tl(t1, cpu_icc_Z); 1208*2a1905c7SRichard Henderson } 1209*2a1905c7SRichard Henderson break; 1210*2a1905c7SRichard Henderson 1211*2a1905c7SRichard Henderson case 0x2: /* le: Z | (N ^ V) */ 1212*2a1905c7SRichard Henderson /* 1213*2a1905c7SRichard Henderson * Simplify: 1214*2a1905c7SRichard Henderson * cc_Z || (N ^ V) < 0 NE 1215*2a1905c7SRichard Henderson * cc_Z && !((N ^ V) < 0) EQ 1216*2a1905c7SRichard Henderson * cc_Z & ~((N ^ V) >> TLB) EQ 1217*2a1905c7SRichard Henderson */ 1218*2a1905c7SRichard Henderson cmp->cond = TCG_COND_EQ; 1219*2a1905c7SRichard Henderson tcg_gen_xor_tl(t1, cpu_cc_N, cpu_cc_V); 1220*2a1905c7SRichard Henderson tcg_gen_sextract_tl(t1, t1, xcc ? 63 : 31, 1); 1221*2a1905c7SRichard Henderson tcg_gen_andc_tl(t1, xcc ? cpu_cc_Z : cpu_icc_Z, t1); 1222*2a1905c7SRichard Henderson if (TARGET_LONG_BITS == 64 && !xcc) { 1223*2a1905c7SRichard Henderson tcg_gen_ext32u_tl(t1, t1); 1224*2a1905c7SRichard Henderson } 1225*2a1905c7SRichard Henderson break; 1226*2a1905c7SRichard Henderson 1227*2a1905c7SRichard Henderson case 0x3: /* lt: N ^ V */ 1228*2a1905c7SRichard Henderson cmp->cond = TCG_COND_LT; 1229*2a1905c7SRichard Henderson tcg_gen_xor_tl(t1, cpu_cc_N, cpu_cc_V); 1230*2a1905c7SRichard Henderson if (TARGET_LONG_BITS == 64 && !xcc) { 1231*2a1905c7SRichard Henderson tcg_gen_ext32s_tl(t1, t1); 1232*2a1905c7SRichard Henderson } 1233*2a1905c7SRichard Henderson break; 1234*2a1905c7SRichard Henderson 1235*2a1905c7SRichard Henderson case 0x4: /* leu: Z | C */ 1236*2a1905c7SRichard Henderson /* 1237*2a1905c7SRichard Henderson * Simplify: 1238*2a1905c7SRichard Henderson * cc_Z == 0 || cc_C != 0 NE 1239*2a1905c7SRichard Henderson * cc_Z != 0 && cc_C == 0 EQ 1240*2a1905c7SRichard Henderson * cc_Z & (cc_C ? 0 : -1) EQ 1241*2a1905c7SRichard Henderson * cc_Z & (cc_C - 1) EQ 1242*2a1905c7SRichard Henderson */ 1243*2a1905c7SRichard Henderson cmp->cond = TCG_COND_EQ; 1244*2a1905c7SRichard Henderson if (TARGET_LONG_BITS == 32 || xcc) { 1245*2a1905c7SRichard Henderson tcg_gen_subi_tl(t1, cpu_cc_C, 1); 1246*2a1905c7SRichard Henderson tcg_gen_and_tl(t1, t1, cpu_cc_Z); 1247*2a1905c7SRichard Henderson } else { 1248*2a1905c7SRichard Henderson tcg_gen_extract_tl(t1, cpu_icc_C, 32, 1); 1249*2a1905c7SRichard Henderson tcg_gen_subi_tl(t1, t1, 1); 1250*2a1905c7SRichard Henderson tcg_gen_and_tl(t1, t1, cpu_icc_Z); 1251*2a1905c7SRichard Henderson tcg_gen_ext32u_tl(t1, t1); 1252*2a1905c7SRichard Henderson } 1253*2a1905c7SRichard Henderson break; 1254*2a1905c7SRichard Henderson 1255*2a1905c7SRichard Henderson case 0x5: /* ltu: C */ 1256*2a1905c7SRichard Henderson cmp->cond = TCG_COND_NE; 1257*2a1905c7SRichard Henderson cmp->is_bool = true; 1258*2a1905c7SRichard Henderson if (TARGET_LONG_BITS == 32 || xcc) { 1259*2a1905c7SRichard Henderson tcg_gen_mov_tl(t1, cpu_cc_C); 1260*2a1905c7SRichard Henderson } else { 1261*2a1905c7SRichard Henderson tcg_gen_extract_tl(t1, cpu_icc_C, 32, 1); 1262*2a1905c7SRichard Henderson } 1263*2a1905c7SRichard Henderson break; 1264*2a1905c7SRichard Henderson 1265*2a1905c7SRichard Henderson case 0x6: /* neg: N */ 1266*2a1905c7SRichard Henderson cmp->cond = TCG_COND_LT; 1267*2a1905c7SRichard Henderson if (TARGET_LONG_BITS == 32 || xcc) { 1268*2a1905c7SRichard Henderson tcg_gen_mov_tl(t1, cpu_cc_N); 1269*2a1905c7SRichard Henderson } else { 1270*2a1905c7SRichard Henderson tcg_gen_ext32s_tl(t1, cpu_cc_N); 1271*2a1905c7SRichard Henderson } 1272*2a1905c7SRichard Henderson break; 1273*2a1905c7SRichard Henderson 1274*2a1905c7SRichard Henderson case 0x7: /* vs: V */ 1275*2a1905c7SRichard Henderson cmp->cond = TCG_COND_LT; 1276*2a1905c7SRichard Henderson if (TARGET_LONG_BITS == 32 || xcc) { 1277*2a1905c7SRichard Henderson tcg_gen_mov_tl(t1, cpu_cc_V); 1278*2a1905c7SRichard Henderson } else { 1279*2a1905c7SRichard Henderson tcg_gen_ext32s_tl(t1, cpu_cc_V); 1280*2a1905c7SRichard Henderson } 1281*2a1905c7SRichard Henderson break; 1282*2a1905c7SRichard Henderson } 1283*2a1905c7SRichard Henderson if (cond & 8) { 1284*2a1905c7SRichard Henderson cmp->cond = tcg_invert_cond(cmp->cond); 1285*2a1905c7SRichard Henderson cmp->is_bool = false; 1286fcf5ef2aSThomas Huth } 1287fcf5ef2aSThomas Huth } 1288fcf5ef2aSThomas Huth 1289fcf5ef2aSThomas Huth static void gen_fcompare(DisasCompare *cmp, unsigned int cc, unsigned int cond) 1290fcf5ef2aSThomas Huth { 1291fcf5ef2aSThomas Huth unsigned int offset; 1292fcf5ef2aSThomas Huth TCGv r_dst; 1293fcf5ef2aSThomas Huth 1294fcf5ef2aSThomas Huth /* For now we still generate a straight boolean result. */ 1295fcf5ef2aSThomas Huth cmp->cond = TCG_COND_NE; 1296fcf5ef2aSThomas Huth cmp->is_bool = true; 1297fcf5ef2aSThomas Huth cmp->c1 = r_dst = tcg_temp_new(); 129800ab7e61SRichard Henderson cmp->c2 = tcg_constant_tl(0); 1299fcf5ef2aSThomas Huth 1300fcf5ef2aSThomas Huth switch (cc) { 1301fcf5ef2aSThomas Huth default: 1302fcf5ef2aSThomas Huth case 0x0: 1303fcf5ef2aSThomas Huth offset = 0; 1304fcf5ef2aSThomas Huth break; 1305fcf5ef2aSThomas Huth case 0x1: 1306fcf5ef2aSThomas Huth offset = 32 - 10; 1307fcf5ef2aSThomas Huth break; 1308fcf5ef2aSThomas Huth case 0x2: 1309fcf5ef2aSThomas Huth offset = 34 - 10; 1310fcf5ef2aSThomas Huth break; 1311fcf5ef2aSThomas Huth case 0x3: 1312fcf5ef2aSThomas Huth offset = 36 - 10; 1313fcf5ef2aSThomas Huth break; 1314fcf5ef2aSThomas Huth } 1315fcf5ef2aSThomas Huth 1316fcf5ef2aSThomas Huth switch (cond) { 1317fcf5ef2aSThomas Huth case 0x0: 1318fcf5ef2aSThomas Huth gen_op_eval_bn(r_dst); 1319fcf5ef2aSThomas Huth break; 1320fcf5ef2aSThomas Huth case 0x1: 1321fcf5ef2aSThomas Huth gen_op_eval_fbne(r_dst, cpu_fsr, offset); 1322fcf5ef2aSThomas Huth break; 1323fcf5ef2aSThomas Huth case 0x2: 1324fcf5ef2aSThomas Huth gen_op_eval_fblg(r_dst, cpu_fsr, offset); 1325fcf5ef2aSThomas Huth break; 1326fcf5ef2aSThomas Huth case 0x3: 1327fcf5ef2aSThomas Huth gen_op_eval_fbul(r_dst, cpu_fsr, offset); 1328fcf5ef2aSThomas Huth break; 1329fcf5ef2aSThomas Huth case 0x4: 1330fcf5ef2aSThomas Huth gen_op_eval_fbl(r_dst, cpu_fsr, offset); 1331fcf5ef2aSThomas Huth break; 1332fcf5ef2aSThomas Huth case 0x5: 1333fcf5ef2aSThomas Huth gen_op_eval_fbug(r_dst, cpu_fsr, offset); 1334fcf5ef2aSThomas Huth break; 1335fcf5ef2aSThomas Huth case 0x6: 1336fcf5ef2aSThomas Huth gen_op_eval_fbg(r_dst, cpu_fsr, offset); 1337fcf5ef2aSThomas Huth break; 1338fcf5ef2aSThomas Huth case 0x7: 1339fcf5ef2aSThomas Huth gen_op_eval_fbu(r_dst, cpu_fsr, offset); 1340fcf5ef2aSThomas Huth break; 1341fcf5ef2aSThomas Huth case 0x8: 1342fcf5ef2aSThomas Huth gen_op_eval_ba(r_dst); 1343fcf5ef2aSThomas Huth break; 1344fcf5ef2aSThomas Huth case 0x9: 1345fcf5ef2aSThomas Huth gen_op_eval_fbe(r_dst, cpu_fsr, offset); 1346fcf5ef2aSThomas Huth break; 1347fcf5ef2aSThomas Huth case 0xa: 1348fcf5ef2aSThomas Huth gen_op_eval_fbue(r_dst, cpu_fsr, offset); 1349fcf5ef2aSThomas Huth break; 1350fcf5ef2aSThomas Huth case 0xb: 1351fcf5ef2aSThomas Huth gen_op_eval_fbge(r_dst, cpu_fsr, offset); 1352fcf5ef2aSThomas Huth break; 1353fcf5ef2aSThomas Huth case 0xc: 1354fcf5ef2aSThomas Huth gen_op_eval_fbuge(r_dst, cpu_fsr, offset); 1355fcf5ef2aSThomas Huth break; 1356fcf5ef2aSThomas Huth case 0xd: 1357fcf5ef2aSThomas Huth gen_op_eval_fble(r_dst, cpu_fsr, offset); 1358fcf5ef2aSThomas Huth break; 1359fcf5ef2aSThomas Huth case 0xe: 1360fcf5ef2aSThomas Huth gen_op_eval_fbule(r_dst, cpu_fsr, offset); 1361fcf5ef2aSThomas Huth break; 1362fcf5ef2aSThomas Huth case 0xf: 1363fcf5ef2aSThomas Huth gen_op_eval_fbo(r_dst, cpu_fsr, offset); 1364fcf5ef2aSThomas Huth break; 1365fcf5ef2aSThomas Huth } 1366fcf5ef2aSThomas Huth } 1367fcf5ef2aSThomas Huth 1368fcf5ef2aSThomas Huth // Inverted logic 1369ab9ffe98SRichard Henderson static const TCGCond gen_tcg_cond_reg[8] = { 1370ab9ffe98SRichard Henderson TCG_COND_NEVER, /* reserved */ 1371fcf5ef2aSThomas Huth TCG_COND_NE, 1372fcf5ef2aSThomas Huth TCG_COND_GT, 1373fcf5ef2aSThomas Huth TCG_COND_GE, 1374ab9ffe98SRichard Henderson TCG_COND_NEVER, /* reserved */ 1375fcf5ef2aSThomas Huth TCG_COND_EQ, 1376fcf5ef2aSThomas Huth TCG_COND_LE, 1377fcf5ef2aSThomas Huth TCG_COND_LT, 1378fcf5ef2aSThomas Huth }; 1379fcf5ef2aSThomas Huth 1380fcf5ef2aSThomas Huth static void gen_compare_reg(DisasCompare *cmp, int cond, TCGv r_src) 1381fcf5ef2aSThomas Huth { 1382fcf5ef2aSThomas Huth cmp->cond = tcg_invert_cond(gen_tcg_cond_reg[cond]); 1383fcf5ef2aSThomas Huth cmp->is_bool = false; 1384fcf5ef2aSThomas Huth cmp->c1 = r_src; 138500ab7e61SRichard Henderson cmp->c2 = tcg_constant_tl(0); 1386fcf5ef2aSThomas Huth } 1387fcf5ef2aSThomas Huth 1388baf3dbf2SRichard Henderson static void gen_op_clear_ieee_excp_and_FTT(void) 1389baf3dbf2SRichard Henderson { 1390baf3dbf2SRichard Henderson tcg_gen_andi_tl(cpu_fsr, cpu_fsr, FSR_FTT_CEXC_NMASK); 1391baf3dbf2SRichard Henderson } 1392baf3dbf2SRichard Henderson 1393baf3dbf2SRichard Henderson static void gen_op_fmovs(TCGv_i32 dst, TCGv_i32 src) 1394baf3dbf2SRichard Henderson { 1395baf3dbf2SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 1396baf3dbf2SRichard Henderson tcg_gen_mov_i32(dst, src); 1397baf3dbf2SRichard Henderson } 1398baf3dbf2SRichard Henderson 1399baf3dbf2SRichard Henderson static void gen_op_fnegs(TCGv_i32 dst, TCGv_i32 src) 1400baf3dbf2SRichard Henderson { 1401baf3dbf2SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 1402baf3dbf2SRichard Henderson gen_helper_fnegs(dst, src); 1403baf3dbf2SRichard Henderson } 1404baf3dbf2SRichard Henderson 1405baf3dbf2SRichard Henderson static void gen_op_fabss(TCGv_i32 dst, TCGv_i32 src) 1406baf3dbf2SRichard Henderson { 1407baf3dbf2SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 1408baf3dbf2SRichard Henderson gen_helper_fabss(dst, src); 1409baf3dbf2SRichard Henderson } 1410baf3dbf2SRichard Henderson 1411c6d83e4fSRichard Henderson static void gen_op_fmovd(TCGv_i64 dst, TCGv_i64 src) 1412c6d83e4fSRichard Henderson { 1413c6d83e4fSRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 1414c6d83e4fSRichard Henderson tcg_gen_mov_i64(dst, src); 1415c6d83e4fSRichard Henderson } 1416c6d83e4fSRichard Henderson 1417c6d83e4fSRichard Henderson static void gen_op_fnegd(TCGv_i64 dst, TCGv_i64 src) 1418c6d83e4fSRichard Henderson { 1419c6d83e4fSRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 1420c6d83e4fSRichard Henderson gen_helper_fnegd(dst, src); 1421c6d83e4fSRichard Henderson } 1422c6d83e4fSRichard Henderson 1423c6d83e4fSRichard Henderson static void gen_op_fabsd(TCGv_i64 dst, TCGv_i64 src) 1424c6d83e4fSRichard Henderson { 1425c6d83e4fSRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 1426c6d83e4fSRichard Henderson gen_helper_fabsd(dst, src); 1427c6d83e4fSRichard Henderson } 1428c6d83e4fSRichard Henderson 1429fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64 14300c2e96c1SRichard Henderson static void gen_op_fcmps(int fccno, TCGv_i32 r_rs1, TCGv_i32 r_rs2) 1431fcf5ef2aSThomas Huth { 1432fcf5ef2aSThomas Huth switch (fccno) { 1433fcf5ef2aSThomas Huth case 0: 1434ad75a51eSRichard Henderson gen_helper_fcmps(cpu_fsr, tcg_env, r_rs1, r_rs2); 1435fcf5ef2aSThomas Huth break; 1436fcf5ef2aSThomas Huth case 1: 1437ad75a51eSRichard Henderson gen_helper_fcmps_fcc1(cpu_fsr, tcg_env, r_rs1, r_rs2); 1438fcf5ef2aSThomas Huth break; 1439fcf5ef2aSThomas Huth case 2: 1440ad75a51eSRichard Henderson gen_helper_fcmps_fcc2(cpu_fsr, tcg_env, r_rs1, r_rs2); 1441fcf5ef2aSThomas Huth break; 1442fcf5ef2aSThomas Huth case 3: 1443ad75a51eSRichard Henderson gen_helper_fcmps_fcc3(cpu_fsr, tcg_env, r_rs1, r_rs2); 1444fcf5ef2aSThomas Huth break; 1445fcf5ef2aSThomas Huth } 1446fcf5ef2aSThomas Huth } 1447fcf5ef2aSThomas Huth 14480c2e96c1SRichard Henderson static void gen_op_fcmpd(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2) 1449fcf5ef2aSThomas Huth { 1450fcf5ef2aSThomas Huth switch (fccno) { 1451fcf5ef2aSThomas Huth case 0: 1452ad75a51eSRichard Henderson gen_helper_fcmpd(cpu_fsr, tcg_env, r_rs1, r_rs2); 1453fcf5ef2aSThomas Huth break; 1454fcf5ef2aSThomas Huth case 1: 1455ad75a51eSRichard Henderson gen_helper_fcmpd_fcc1(cpu_fsr, tcg_env, r_rs1, r_rs2); 1456fcf5ef2aSThomas Huth break; 1457fcf5ef2aSThomas Huth case 2: 1458ad75a51eSRichard Henderson gen_helper_fcmpd_fcc2(cpu_fsr, tcg_env, r_rs1, r_rs2); 1459fcf5ef2aSThomas Huth break; 1460fcf5ef2aSThomas Huth case 3: 1461ad75a51eSRichard Henderson gen_helper_fcmpd_fcc3(cpu_fsr, tcg_env, r_rs1, r_rs2); 1462fcf5ef2aSThomas Huth break; 1463fcf5ef2aSThomas Huth } 1464fcf5ef2aSThomas Huth } 1465fcf5ef2aSThomas Huth 14660c2e96c1SRichard Henderson static void gen_op_fcmpq(int fccno) 1467fcf5ef2aSThomas Huth { 1468fcf5ef2aSThomas Huth switch (fccno) { 1469fcf5ef2aSThomas Huth case 0: 1470ad75a51eSRichard Henderson gen_helper_fcmpq(cpu_fsr, tcg_env); 1471fcf5ef2aSThomas Huth break; 1472fcf5ef2aSThomas Huth case 1: 1473ad75a51eSRichard Henderson gen_helper_fcmpq_fcc1(cpu_fsr, tcg_env); 1474fcf5ef2aSThomas Huth break; 1475fcf5ef2aSThomas Huth case 2: 1476ad75a51eSRichard Henderson gen_helper_fcmpq_fcc2(cpu_fsr, tcg_env); 1477fcf5ef2aSThomas Huth break; 1478fcf5ef2aSThomas Huth case 3: 1479ad75a51eSRichard Henderson gen_helper_fcmpq_fcc3(cpu_fsr, tcg_env); 1480fcf5ef2aSThomas Huth break; 1481fcf5ef2aSThomas Huth } 1482fcf5ef2aSThomas Huth } 1483fcf5ef2aSThomas Huth 14840c2e96c1SRichard Henderson static void gen_op_fcmpes(int fccno, TCGv_i32 r_rs1, TCGv_i32 r_rs2) 1485fcf5ef2aSThomas Huth { 1486fcf5ef2aSThomas Huth switch (fccno) { 1487fcf5ef2aSThomas Huth case 0: 1488ad75a51eSRichard Henderson gen_helper_fcmpes(cpu_fsr, tcg_env, r_rs1, r_rs2); 1489fcf5ef2aSThomas Huth break; 1490fcf5ef2aSThomas Huth case 1: 1491ad75a51eSRichard Henderson gen_helper_fcmpes_fcc1(cpu_fsr, tcg_env, r_rs1, r_rs2); 1492fcf5ef2aSThomas Huth break; 1493fcf5ef2aSThomas Huth case 2: 1494ad75a51eSRichard Henderson gen_helper_fcmpes_fcc2(cpu_fsr, tcg_env, r_rs1, r_rs2); 1495fcf5ef2aSThomas Huth break; 1496fcf5ef2aSThomas Huth case 3: 1497ad75a51eSRichard Henderson gen_helper_fcmpes_fcc3(cpu_fsr, tcg_env, r_rs1, r_rs2); 1498fcf5ef2aSThomas Huth break; 1499fcf5ef2aSThomas Huth } 1500fcf5ef2aSThomas Huth } 1501fcf5ef2aSThomas Huth 15020c2e96c1SRichard Henderson static void gen_op_fcmped(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2) 1503fcf5ef2aSThomas Huth { 1504fcf5ef2aSThomas Huth switch (fccno) { 1505fcf5ef2aSThomas Huth case 0: 1506ad75a51eSRichard Henderson gen_helper_fcmped(cpu_fsr, tcg_env, r_rs1, r_rs2); 1507fcf5ef2aSThomas Huth break; 1508fcf5ef2aSThomas Huth case 1: 1509ad75a51eSRichard Henderson gen_helper_fcmped_fcc1(cpu_fsr, tcg_env, r_rs1, r_rs2); 1510fcf5ef2aSThomas Huth break; 1511fcf5ef2aSThomas Huth case 2: 1512ad75a51eSRichard Henderson gen_helper_fcmped_fcc2(cpu_fsr, tcg_env, r_rs1, r_rs2); 1513fcf5ef2aSThomas Huth break; 1514fcf5ef2aSThomas Huth case 3: 1515ad75a51eSRichard Henderson gen_helper_fcmped_fcc3(cpu_fsr, tcg_env, r_rs1, r_rs2); 1516fcf5ef2aSThomas Huth break; 1517fcf5ef2aSThomas Huth } 1518fcf5ef2aSThomas Huth } 1519fcf5ef2aSThomas Huth 15200c2e96c1SRichard Henderson static void gen_op_fcmpeq(int fccno) 1521fcf5ef2aSThomas Huth { 1522fcf5ef2aSThomas Huth switch (fccno) { 1523fcf5ef2aSThomas Huth case 0: 1524ad75a51eSRichard Henderson gen_helper_fcmpeq(cpu_fsr, tcg_env); 1525fcf5ef2aSThomas Huth break; 1526fcf5ef2aSThomas Huth case 1: 1527ad75a51eSRichard Henderson gen_helper_fcmpeq_fcc1(cpu_fsr, tcg_env); 1528fcf5ef2aSThomas Huth break; 1529fcf5ef2aSThomas Huth case 2: 1530ad75a51eSRichard Henderson gen_helper_fcmpeq_fcc2(cpu_fsr, tcg_env); 1531fcf5ef2aSThomas Huth break; 1532fcf5ef2aSThomas Huth case 3: 1533ad75a51eSRichard Henderson gen_helper_fcmpeq_fcc3(cpu_fsr, tcg_env); 1534fcf5ef2aSThomas Huth break; 1535fcf5ef2aSThomas Huth } 1536fcf5ef2aSThomas Huth } 1537fcf5ef2aSThomas Huth 1538fcf5ef2aSThomas Huth #else 1539fcf5ef2aSThomas Huth 15400c2e96c1SRichard Henderson static void gen_op_fcmps(int fccno, TCGv r_rs1, TCGv r_rs2) 1541fcf5ef2aSThomas Huth { 1542ad75a51eSRichard Henderson gen_helper_fcmps(cpu_fsr, tcg_env, r_rs1, r_rs2); 1543fcf5ef2aSThomas Huth } 1544fcf5ef2aSThomas Huth 15450c2e96c1SRichard Henderson static void gen_op_fcmpd(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2) 1546fcf5ef2aSThomas Huth { 1547ad75a51eSRichard Henderson gen_helper_fcmpd(cpu_fsr, tcg_env, r_rs1, r_rs2); 1548fcf5ef2aSThomas Huth } 1549fcf5ef2aSThomas Huth 15500c2e96c1SRichard Henderson static void gen_op_fcmpq(int fccno) 1551fcf5ef2aSThomas Huth { 1552ad75a51eSRichard Henderson gen_helper_fcmpq(cpu_fsr, tcg_env); 1553fcf5ef2aSThomas Huth } 1554fcf5ef2aSThomas Huth 15550c2e96c1SRichard Henderson static void gen_op_fcmpes(int fccno, TCGv r_rs1, TCGv r_rs2) 1556fcf5ef2aSThomas Huth { 1557ad75a51eSRichard Henderson gen_helper_fcmpes(cpu_fsr, tcg_env, r_rs1, r_rs2); 1558fcf5ef2aSThomas Huth } 1559fcf5ef2aSThomas Huth 15600c2e96c1SRichard Henderson static void gen_op_fcmped(int fccno, TCGv_i64 r_rs1, TCGv_i64 r_rs2) 1561fcf5ef2aSThomas Huth { 1562ad75a51eSRichard Henderson gen_helper_fcmped(cpu_fsr, tcg_env, r_rs1, r_rs2); 1563fcf5ef2aSThomas Huth } 1564fcf5ef2aSThomas Huth 15650c2e96c1SRichard Henderson static void gen_op_fcmpeq(int fccno) 1566fcf5ef2aSThomas Huth { 1567ad75a51eSRichard Henderson gen_helper_fcmpeq(cpu_fsr, tcg_env); 1568fcf5ef2aSThomas Huth } 1569fcf5ef2aSThomas Huth #endif 1570fcf5ef2aSThomas Huth 1571fcf5ef2aSThomas Huth static void gen_op_fpexception_im(DisasContext *dc, int fsr_flags) 1572fcf5ef2aSThomas Huth { 1573fcf5ef2aSThomas Huth tcg_gen_andi_tl(cpu_fsr, cpu_fsr, FSR_FTT_NMASK); 1574fcf5ef2aSThomas Huth tcg_gen_ori_tl(cpu_fsr, cpu_fsr, fsr_flags); 1575fcf5ef2aSThomas Huth gen_exception(dc, TT_FP_EXCP); 1576fcf5ef2aSThomas Huth } 1577fcf5ef2aSThomas Huth 1578fcf5ef2aSThomas Huth static int gen_trap_ifnofpu(DisasContext *dc) 1579fcf5ef2aSThomas Huth { 1580fcf5ef2aSThomas Huth #if !defined(CONFIG_USER_ONLY) 1581fcf5ef2aSThomas Huth if (!dc->fpu_enabled) { 1582fcf5ef2aSThomas Huth gen_exception(dc, TT_NFPU_INSN); 1583fcf5ef2aSThomas Huth return 1; 1584fcf5ef2aSThomas Huth } 1585fcf5ef2aSThomas Huth #endif 1586fcf5ef2aSThomas Huth return 0; 1587fcf5ef2aSThomas Huth } 1588fcf5ef2aSThomas Huth 1589fcf5ef2aSThomas Huth /* asi moves */ 1590fcf5ef2aSThomas Huth typedef enum { 1591fcf5ef2aSThomas Huth GET_ASI_HELPER, 1592fcf5ef2aSThomas Huth GET_ASI_EXCP, 1593fcf5ef2aSThomas Huth GET_ASI_DIRECT, 1594fcf5ef2aSThomas Huth GET_ASI_DTWINX, 1595fcf5ef2aSThomas Huth GET_ASI_BLOCK, 1596fcf5ef2aSThomas Huth GET_ASI_SHORT, 1597fcf5ef2aSThomas Huth GET_ASI_BCOPY, 1598fcf5ef2aSThomas Huth GET_ASI_BFILL, 1599fcf5ef2aSThomas Huth } ASIType; 1600fcf5ef2aSThomas Huth 1601fcf5ef2aSThomas Huth typedef struct { 1602fcf5ef2aSThomas Huth ASIType type; 1603fcf5ef2aSThomas Huth int asi; 1604fcf5ef2aSThomas Huth int mem_idx; 160514776ab5STony Nguyen MemOp memop; 1606fcf5ef2aSThomas Huth } DisasASI; 1607fcf5ef2aSThomas Huth 1608811cc0b0SRichard Henderson /* 1609811cc0b0SRichard Henderson * Build DisasASI. 1610811cc0b0SRichard Henderson * For asi == -1, treat as non-asi. 1611811cc0b0SRichard Henderson * For ask == -2, treat as immediate offset (v8 error, v9 %asi). 1612811cc0b0SRichard Henderson */ 1613811cc0b0SRichard Henderson static DisasASI resolve_asi(DisasContext *dc, int asi, MemOp memop) 1614fcf5ef2aSThomas Huth { 1615fcf5ef2aSThomas Huth ASIType type = GET_ASI_HELPER; 1616fcf5ef2aSThomas Huth int mem_idx = dc->mem_idx; 1617fcf5ef2aSThomas Huth 1618811cc0b0SRichard Henderson if (asi == -1) { 1619811cc0b0SRichard Henderson /* Artificial "non-asi" case. */ 1620811cc0b0SRichard Henderson type = GET_ASI_DIRECT; 1621811cc0b0SRichard Henderson goto done; 1622811cc0b0SRichard Henderson } 1623811cc0b0SRichard Henderson 1624fcf5ef2aSThomas Huth #ifndef TARGET_SPARC64 1625fcf5ef2aSThomas Huth /* Before v9, all asis are immediate and privileged. */ 1626811cc0b0SRichard Henderson if (asi < 0) { 1627fcf5ef2aSThomas Huth gen_exception(dc, TT_ILL_INSN); 1628fcf5ef2aSThomas Huth type = GET_ASI_EXCP; 1629fcf5ef2aSThomas Huth } else if (supervisor(dc) 1630fcf5ef2aSThomas Huth /* Note that LEON accepts ASI_USERDATA in user mode, for 1631fcf5ef2aSThomas Huth use with CASA. Also note that previous versions of 1632fcf5ef2aSThomas Huth QEMU allowed (and old versions of gcc emitted) ASI_P 1633fcf5ef2aSThomas Huth for LEON, which is incorrect. */ 1634fcf5ef2aSThomas Huth || (asi == ASI_USERDATA 1635fcf5ef2aSThomas Huth && (dc->def->features & CPU_FEATURE_CASA))) { 1636fcf5ef2aSThomas Huth switch (asi) { 1637fcf5ef2aSThomas Huth case ASI_USERDATA: /* User data access */ 1638fcf5ef2aSThomas Huth mem_idx = MMU_USER_IDX; 1639fcf5ef2aSThomas Huth type = GET_ASI_DIRECT; 1640fcf5ef2aSThomas Huth break; 1641fcf5ef2aSThomas Huth case ASI_KERNELDATA: /* Supervisor data access */ 1642fcf5ef2aSThomas Huth mem_idx = MMU_KERNEL_IDX; 1643fcf5ef2aSThomas Huth type = GET_ASI_DIRECT; 1644fcf5ef2aSThomas Huth break; 1645fcf5ef2aSThomas Huth case ASI_M_BYPASS: /* MMU passthrough */ 1646fcf5ef2aSThomas Huth case ASI_LEON_BYPASS: /* LEON MMU passthrough */ 1647fcf5ef2aSThomas Huth mem_idx = MMU_PHYS_IDX; 1648fcf5ef2aSThomas Huth type = GET_ASI_DIRECT; 1649fcf5ef2aSThomas Huth break; 1650fcf5ef2aSThomas Huth case ASI_M_BCOPY: /* Block copy, sta access */ 1651fcf5ef2aSThomas Huth mem_idx = MMU_KERNEL_IDX; 1652fcf5ef2aSThomas Huth type = GET_ASI_BCOPY; 1653fcf5ef2aSThomas Huth break; 1654fcf5ef2aSThomas Huth case ASI_M_BFILL: /* Block fill, stda access */ 1655fcf5ef2aSThomas Huth mem_idx = MMU_KERNEL_IDX; 1656fcf5ef2aSThomas Huth type = GET_ASI_BFILL; 1657fcf5ef2aSThomas Huth break; 1658fcf5ef2aSThomas Huth } 16596e10f37cSKONRAD Frederic 16606e10f37cSKONRAD Frederic /* MMU_PHYS_IDX is used when the MMU is disabled to passthrough the 16616e10f37cSKONRAD Frederic * permissions check in get_physical_address(..). 16626e10f37cSKONRAD Frederic */ 16636e10f37cSKONRAD Frederic mem_idx = (dc->mem_idx == MMU_PHYS_IDX) ? MMU_PHYS_IDX : mem_idx; 1664fcf5ef2aSThomas Huth } else { 1665fcf5ef2aSThomas Huth gen_exception(dc, TT_PRIV_INSN); 1666fcf5ef2aSThomas Huth type = GET_ASI_EXCP; 1667fcf5ef2aSThomas Huth } 1668fcf5ef2aSThomas Huth #else 1669811cc0b0SRichard Henderson if (asi < 0) { 1670fcf5ef2aSThomas Huth asi = dc->asi; 1671fcf5ef2aSThomas Huth } 1672fcf5ef2aSThomas Huth /* With v9, all asis below 0x80 are privileged. */ 1673fcf5ef2aSThomas Huth /* ??? We ought to check cpu_has_hypervisor, but we didn't copy 1674fcf5ef2aSThomas Huth down that bit into DisasContext. For the moment that's ok, 1675fcf5ef2aSThomas Huth since the direct implementations below doesn't have any ASIs 1676fcf5ef2aSThomas Huth in the restricted [0x30, 0x7f] range, and the check will be 1677fcf5ef2aSThomas Huth done properly in the helper. */ 1678fcf5ef2aSThomas Huth if (!supervisor(dc) && asi < 0x80) { 1679fcf5ef2aSThomas Huth gen_exception(dc, TT_PRIV_ACT); 1680fcf5ef2aSThomas Huth type = GET_ASI_EXCP; 1681fcf5ef2aSThomas Huth } else { 1682fcf5ef2aSThomas Huth switch (asi) { 1683fcf5ef2aSThomas Huth case ASI_REAL: /* Bypass */ 1684fcf5ef2aSThomas Huth case ASI_REAL_IO: /* Bypass, non-cacheable */ 1685fcf5ef2aSThomas Huth case ASI_REAL_L: /* Bypass LE */ 1686fcf5ef2aSThomas Huth case ASI_REAL_IO_L: /* Bypass, non-cacheable LE */ 1687fcf5ef2aSThomas Huth case ASI_TWINX_REAL: /* Real address, twinx */ 1688fcf5ef2aSThomas Huth case ASI_TWINX_REAL_L: /* Real address, twinx, LE */ 1689fcf5ef2aSThomas Huth case ASI_QUAD_LDD_PHYS: 1690fcf5ef2aSThomas Huth case ASI_QUAD_LDD_PHYS_L: 1691fcf5ef2aSThomas Huth mem_idx = MMU_PHYS_IDX; 1692fcf5ef2aSThomas Huth break; 1693fcf5ef2aSThomas Huth case ASI_N: /* Nucleus */ 1694fcf5ef2aSThomas Huth case ASI_NL: /* Nucleus LE */ 1695fcf5ef2aSThomas Huth case ASI_TWINX_N: 1696fcf5ef2aSThomas Huth case ASI_TWINX_NL: 1697fcf5ef2aSThomas Huth case ASI_NUCLEUS_QUAD_LDD: 1698fcf5ef2aSThomas Huth case ASI_NUCLEUS_QUAD_LDD_L: 16999a10756dSArtyom Tarasenko if (hypervisor(dc)) { 170084f8f587SArtyom Tarasenko mem_idx = MMU_PHYS_IDX; 17019a10756dSArtyom Tarasenko } else { 1702fcf5ef2aSThomas Huth mem_idx = MMU_NUCLEUS_IDX; 17039a10756dSArtyom Tarasenko } 1704fcf5ef2aSThomas Huth break; 1705fcf5ef2aSThomas Huth case ASI_AIUP: /* As if user primary */ 1706fcf5ef2aSThomas Huth case ASI_AIUPL: /* As if user primary LE */ 1707fcf5ef2aSThomas Huth case ASI_TWINX_AIUP: 1708fcf5ef2aSThomas Huth case ASI_TWINX_AIUP_L: 1709fcf5ef2aSThomas Huth case ASI_BLK_AIUP_4V: 1710fcf5ef2aSThomas Huth case ASI_BLK_AIUP_L_4V: 1711fcf5ef2aSThomas Huth case ASI_BLK_AIUP: 1712fcf5ef2aSThomas Huth case ASI_BLK_AIUPL: 1713fcf5ef2aSThomas Huth mem_idx = MMU_USER_IDX; 1714fcf5ef2aSThomas Huth break; 1715fcf5ef2aSThomas Huth case ASI_AIUS: /* As if user secondary */ 1716fcf5ef2aSThomas Huth case ASI_AIUSL: /* As if user secondary LE */ 1717fcf5ef2aSThomas Huth case ASI_TWINX_AIUS: 1718fcf5ef2aSThomas Huth case ASI_TWINX_AIUS_L: 1719fcf5ef2aSThomas Huth case ASI_BLK_AIUS_4V: 1720fcf5ef2aSThomas Huth case ASI_BLK_AIUS_L_4V: 1721fcf5ef2aSThomas Huth case ASI_BLK_AIUS: 1722fcf5ef2aSThomas Huth case ASI_BLK_AIUSL: 1723fcf5ef2aSThomas Huth mem_idx = MMU_USER_SECONDARY_IDX; 1724fcf5ef2aSThomas Huth break; 1725fcf5ef2aSThomas Huth case ASI_S: /* Secondary */ 1726fcf5ef2aSThomas Huth case ASI_SL: /* Secondary LE */ 1727fcf5ef2aSThomas Huth case ASI_TWINX_S: 1728fcf5ef2aSThomas Huth case ASI_TWINX_SL: 1729fcf5ef2aSThomas Huth case ASI_BLK_COMMIT_S: 1730fcf5ef2aSThomas Huth case ASI_BLK_S: 1731fcf5ef2aSThomas Huth case ASI_BLK_SL: 1732fcf5ef2aSThomas Huth case ASI_FL8_S: 1733fcf5ef2aSThomas Huth case ASI_FL8_SL: 1734fcf5ef2aSThomas Huth case ASI_FL16_S: 1735fcf5ef2aSThomas Huth case ASI_FL16_SL: 1736fcf5ef2aSThomas Huth if (mem_idx == MMU_USER_IDX) { 1737fcf5ef2aSThomas Huth mem_idx = MMU_USER_SECONDARY_IDX; 1738fcf5ef2aSThomas Huth } else if (mem_idx == MMU_KERNEL_IDX) { 1739fcf5ef2aSThomas Huth mem_idx = MMU_KERNEL_SECONDARY_IDX; 1740fcf5ef2aSThomas Huth } 1741fcf5ef2aSThomas Huth break; 1742fcf5ef2aSThomas Huth case ASI_P: /* Primary */ 1743fcf5ef2aSThomas Huth case ASI_PL: /* Primary LE */ 1744fcf5ef2aSThomas Huth case ASI_TWINX_P: 1745fcf5ef2aSThomas Huth case ASI_TWINX_PL: 1746fcf5ef2aSThomas Huth case ASI_BLK_COMMIT_P: 1747fcf5ef2aSThomas Huth case ASI_BLK_P: 1748fcf5ef2aSThomas Huth case ASI_BLK_PL: 1749fcf5ef2aSThomas Huth case ASI_FL8_P: 1750fcf5ef2aSThomas Huth case ASI_FL8_PL: 1751fcf5ef2aSThomas Huth case ASI_FL16_P: 1752fcf5ef2aSThomas Huth case ASI_FL16_PL: 1753fcf5ef2aSThomas Huth break; 1754fcf5ef2aSThomas Huth } 1755fcf5ef2aSThomas Huth switch (asi) { 1756fcf5ef2aSThomas Huth case ASI_REAL: 1757fcf5ef2aSThomas Huth case ASI_REAL_IO: 1758fcf5ef2aSThomas Huth case ASI_REAL_L: 1759fcf5ef2aSThomas Huth case ASI_REAL_IO_L: 1760fcf5ef2aSThomas Huth case ASI_N: 1761fcf5ef2aSThomas Huth case ASI_NL: 1762fcf5ef2aSThomas Huth case ASI_AIUP: 1763fcf5ef2aSThomas Huth case ASI_AIUPL: 1764fcf5ef2aSThomas Huth case ASI_AIUS: 1765fcf5ef2aSThomas Huth case ASI_AIUSL: 1766fcf5ef2aSThomas Huth case ASI_S: 1767fcf5ef2aSThomas Huth case ASI_SL: 1768fcf5ef2aSThomas Huth case ASI_P: 1769fcf5ef2aSThomas Huth case ASI_PL: 1770fcf5ef2aSThomas Huth type = GET_ASI_DIRECT; 1771fcf5ef2aSThomas Huth break; 1772fcf5ef2aSThomas Huth case ASI_TWINX_REAL: 1773fcf5ef2aSThomas Huth case ASI_TWINX_REAL_L: 1774fcf5ef2aSThomas Huth case ASI_TWINX_N: 1775fcf5ef2aSThomas Huth case ASI_TWINX_NL: 1776fcf5ef2aSThomas Huth case ASI_TWINX_AIUP: 1777fcf5ef2aSThomas Huth case ASI_TWINX_AIUP_L: 1778fcf5ef2aSThomas Huth case ASI_TWINX_AIUS: 1779fcf5ef2aSThomas Huth case ASI_TWINX_AIUS_L: 1780fcf5ef2aSThomas Huth case ASI_TWINX_P: 1781fcf5ef2aSThomas Huth case ASI_TWINX_PL: 1782fcf5ef2aSThomas Huth case ASI_TWINX_S: 1783fcf5ef2aSThomas Huth case ASI_TWINX_SL: 1784fcf5ef2aSThomas Huth case ASI_QUAD_LDD_PHYS: 1785fcf5ef2aSThomas Huth case ASI_QUAD_LDD_PHYS_L: 1786fcf5ef2aSThomas Huth case ASI_NUCLEUS_QUAD_LDD: 1787fcf5ef2aSThomas Huth case ASI_NUCLEUS_QUAD_LDD_L: 1788fcf5ef2aSThomas Huth type = GET_ASI_DTWINX; 1789fcf5ef2aSThomas Huth break; 1790fcf5ef2aSThomas Huth case ASI_BLK_COMMIT_P: 1791fcf5ef2aSThomas Huth case ASI_BLK_COMMIT_S: 1792fcf5ef2aSThomas Huth case ASI_BLK_AIUP_4V: 1793fcf5ef2aSThomas Huth case ASI_BLK_AIUP_L_4V: 1794fcf5ef2aSThomas Huth case ASI_BLK_AIUP: 1795fcf5ef2aSThomas Huth case ASI_BLK_AIUPL: 1796fcf5ef2aSThomas Huth case ASI_BLK_AIUS_4V: 1797fcf5ef2aSThomas Huth case ASI_BLK_AIUS_L_4V: 1798fcf5ef2aSThomas Huth case ASI_BLK_AIUS: 1799fcf5ef2aSThomas Huth case ASI_BLK_AIUSL: 1800fcf5ef2aSThomas Huth case ASI_BLK_S: 1801fcf5ef2aSThomas Huth case ASI_BLK_SL: 1802fcf5ef2aSThomas Huth case ASI_BLK_P: 1803fcf5ef2aSThomas Huth case ASI_BLK_PL: 1804fcf5ef2aSThomas Huth type = GET_ASI_BLOCK; 1805fcf5ef2aSThomas Huth break; 1806fcf5ef2aSThomas Huth case ASI_FL8_S: 1807fcf5ef2aSThomas Huth case ASI_FL8_SL: 1808fcf5ef2aSThomas Huth case ASI_FL8_P: 1809fcf5ef2aSThomas Huth case ASI_FL8_PL: 1810fcf5ef2aSThomas Huth memop = MO_UB; 1811fcf5ef2aSThomas Huth type = GET_ASI_SHORT; 1812fcf5ef2aSThomas Huth break; 1813fcf5ef2aSThomas Huth case ASI_FL16_S: 1814fcf5ef2aSThomas Huth case ASI_FL16_SL: 1815fcf5ef2aSThomas Huth case ASI_FL16_P: 1816fcf5ef2aSThomas Huth case ASI_FL16_PL: 1817fcf5ef2aSThomas Huth memop = MO_TEUW; 1818fcf5ef2aSThomas Huth type = GET_ASI_SHORT; 1819fcf5ef2aSThomas Huth break; 1820fcf5ef2aSThomas Huth } 1821fcf5ef2aSThomas Huth /* The little-endian asis all have bit 3 set. */ 1822fcf5ef2aSThomas Huth if (asi & 8) { 1823fcf5ef2aSThomas Huth memop ^= MO_BSWAP; 1824fcf5ef2aSThomas Huth } 1825fcf5ef2aSThomas Huth } 1826fcf5ef2aSThomas Huth #endif 1827fcf5ef2aSThomas Huth 1828811cc0b0SRichard Henderson done: 1829fcf5ef2aSThomas Huth return (DisasASI){ type, asi, mem_idx, memop }; 1830fcf5ef2aSThomas Huth } 1831fcf5ef2aSThomas Huth 1832a76779eeSRichard Henderson #if defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64) 1833a76779eeSRichard Henderson static void gen_helper_ld_asi(TCGv_i64 r, TCGv_env e, TCGv a, 1834a76779eeSRichard Henderson TCGv_i32 asi, TCGv_i32 mop) 1835a76779eeSRichard Henderson { 1836a76779eeSRichard Henderson g_assert_not_reached(); 1837a76779eeSRichard Henderson } 1838a76779eeSRichard Henderson 1839a76779eeSRichard Henderson static void gen_helper_st_asi(TCGv_env e, TCGv a, TCGv_i64 r, 1840a76779eeSRichard Henderson TCGv_i32 asi, TCGv_i32 mop) 1841a76779eeSRichard Henderson { 1842a76779eeSRichard Henderson g_assert_not_reached(); 1843a76779eeSRichard Henderson } 1844a76779eeSRichard Henderson #endif 1845a76779eeSRichard Henderson 184642071fc1SRichard Henderson static void gen_ld_asi(DisasContext *dc, DisasASI *da, TCGv dst, TCGv addr) 1847fcf5ef2aSThomas Huth { 1848c03a0fd1SRichard Henderson switch (da->type) { 1849fcf5ef2aSThomas Huth case GET_ASI_EXCP: 1850fcf5ef2aSThomas Huth break; 1851fcf5ef2aSThomas Huth case GET_ASI_DTWINX: /* Reserved for ldda. */ 1852fcf5ef2aSThomas Huth gen_exception(dc, TT_ILL_INSN); 1853fcf5ef2aSThomas Huth break; 1854fcf5ef2aSThomas Huth case GET_ASI_DIRECT: 1855c03a0fd1SRichard Henderson tcg_gen_qemu_ld_tl(dst, addr, da->mem_idx, da->memop | MO_ALIGN); 1856fcf5ef2aSThomas Huth break; 1857fcf5ef2aSThomas Huth default: 1858fcf5ef2aSThomas Huth { 1859c03a0fd1SRichard Henderson TCGv_i32 r_asi = tcg_constant_i32(da->asi); 1860c03a0fd1SRichard Henderson TCGv_i32 r_mop = tcg_constant_i32(da->memop | MO_ALIGN); 1861fcf5ef2aSThomas Huth 1862fcf5ef2aSThomas Huth save_state(dc); 1863fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64 1864ad75a51eSRichard Henderson gen_helper_ld_asi(dst, tcg_env, addr, r_asi, r_mop); 1865fcf5ef2aSThomas Huth #else 1866fcf5ef2aSThomas Huth { 1867fcf5ef2aSThomas Huth TCGv_i64 t64 = tcg_temp_new_i64(); 1868ad75a51eSRichard Henderson gen_helper_ld_asi(t64, tcg_env, addr, r_asi, r_mop); 1869fcf5ef2aSThomas Huth tcg_gen_trunc_i64_tl(dst, t64); 1870fcf5ef2aSThomas Huth } 1871fcf5ef2aSThomas Huth #endif 1872fcf5ef2aSThomas Huth } 1873fcf5ef2aSThomas Huth break; 1874fcf5ef2aSThomas Huth } 1875fcf5ef2aSThomas Huth } 1876fcf5ef2aSThomas Huth 187742071fc1SRichard Henderson static void gen_st_asi(DisasContext *dc, DisasASI *da, TCGv src, TCGv addr) 1878c03a0fd1SRichard Henderson { 1879c03a0fd1SRichard Henderson switch (da->type) { 1880fcf5ef2aSThomas Huth case GET_ASI_EXCP: 1881fcf5ef2aSThomas Huth break; 1882c03a0fd1SRichard Henderson 1883fcf5ef2aSThomas Huth case GET_ASI_DTWINX: /* Reserved for stda. */ 1884c03a0fd1SRichard Henderson if (TARGET_LONG_BITS == 32) { 1885fcf5ef2aSThomas Huth gen_exception(dc, TT_ILL_INSN); 1886fcf5ef2aSThomas Huth break; 1887c03a0fd1SRichard Henderson } else if (!(dc->def->features & CPU_FEATURE_HYPV)) { 18883390537bSArtyom Tarasenko /* Pre OpenSPARC CPUs don't have these */ 18893390537bSArtyom Tarasenko gen_exception(dc, TT_ILL_INSN); 1890fcf5ef2aSThomas Huth break; 1891c03a0fd1SRichard Henderson } 1892c03a0fd1SRichard Henderson /* In OpenSPARC T1+ CPUs TWINX ASIs in store are ST_BLKINIT_ ASIs */ 1893c03a0fd1SRichard Henderson /* fall through */ 1894c03a0fd1SRichard Henderson 1895c03a0fd1SRichard Henderson case GET_ASI_DIRECT: 1896c03a0fd1SRichard Henderson tcg_gen_qemu_st_tl(src, addr, da->mem_idx, da->memop | MO_ALIGN); 1897c03a0fd1SRichard Henderson break; 1898c03a0fd1SRichard Henderson 1899fcf5ef2aSThomas Huth case GET_ASI_BCOPY: 1900c03a0fd1SRichard Henderson assert(TARGET_LONG_BITS == 32); 1901fcf5ef2aSThomas Huth /* Copy 32 bytes from the address in SRC to ADDR. */ 1902fcf5ef2aSThomas Huth /* ??? The original qemu code suggests 4-byte alignment, dropping 1903fcf5ef2aSThomas Huth the low bits, but the only place I can see this used is in the 1904fcf5ef2aSThomas Huth Linux kernel with 32 byte alignment, which would make more sense 1905fcf5ef2aSThomas Huth as a cacheline-style operation. */ 1906fcf5ef2aSThomas Huth { 1907fcf5ef2aSThomas Huth TCGv saddr = tcg_temp_new(); 1908fcf5ef2aSThomas Huth TCGv daddr = tcg_temp_new(); 190900ab7e61SRichard Henderson TCGv four = tcg_constant_tl(4); 1910fcf5ef2aSThomas Huth TCGv_i32 tmp = tcg_temp_new_i32(); 1911fcf5ef2aSThomas Huth int i; 1912fcf5ef2aSThomas Huth 1913fcf5ef2aSThomas Huth tcg_gen_andi_tl(saddr, src, -4); 1914fcf5ef2aSThomas Huth tcg_gen_andi_tl(daddr, addr, -4); 1915fcf5ef2aSThomas Huth for (i = 0; i < 32; i += 4) { 1916fcf5ef2aSThomas Huth /* Since the loads and stores are paired, allow the 1917fcf5ef2aSThomas Huth copy to happen in the host endianness. */ 1918c03a0fd1SRichard Henderson tcg_gen_qemu_ld_i32(tmp, saddr, da->mem_idx, MO_UL); 1919c03a0fd1SRichard Henderson tcg_gen_qemu_st_i32(tmp, daddr, da->mem_idx, MO_UL); 1920fcf5ef2aSThomas Huth tcg_gen_add_tl(saddr, saddr, four); 1921fcf5ef2aSThomas Huth tcg_gen_add_tl(daddr, daddr, four); 1922fcf5ef2aSThomas Huth } 1923fcf5ef2aSThomas Huth } 1924fcf5ef2aSThomas Huth break; 1925c03a0fd1SRichard Henderson 1926fcf5ef2aSThomas Huth default: 1927fcf5ef2aSThomas Huth { 1928c03a0fd1SRichard Henderson TCGv_i32 r_asi = tcg_constant_i32(da->asi); 1929c03a0fd1SRichard Henderson TCGv_i32 r_mop = tcg_constant_i32(da->memop | MO_ALIGN); 1930fcf5ef2aSThomas Huth 1931fcf5ef2aSThomas Huth save_state(dc); 1932fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64 1933ad75a51eSRichard Henderson gen_helper_st_asi(tcg_env, addr, src, r_asi, r_mop); 1934fcf5ef2aSThomas Huth #else 1935fcf5ef2aSThomas Huth { 1936fcf5ef2aSThomas Huth TCGv_i64 t64 = tcg_temp_new_i64(); 1937fcf5ef2aSThomas Huth tcg_gen_extu_tl_i64(t64, src); 1938ad75a51eSRichard Henderson gen_helper_st_asi(tcg_env, addr, t64, r_asi, r_mop); 1939fcf5ef2aSThomas Huth } 1940fcf5ef2aSThomas Huth #endif 1941fcf5ef2aSThomas Huth 1942fcf5ef2aSThomas Huth /* A write to a TLB register may alter page maps. End the TB. */ 1943fcf5ef2aSThomas Huth dc->npc = DYNAMIC_PC; 1944fcf5ef2aSThomas Huth } 1945fcf5ef2aSThomas Huth break; 1946fcf5ef2aSThomas Huth } 1947fcf5ef2aSThomas Huth } 1948fcf5ef2aSThomas Huth 1949dca544b9SRichard Henderson static void gen_swap_asi(DisasContext *dc, DisasASI *da, 1950c03a0fd1SRichard Henderson TCGv dst, TCGv src, TCGv addr) 1951c03a0fd1SRichard Henderson { 1952c03a0fd1SRichard Henderson switch (da->type) { 1953c03a0fd1SRichard Henderson case GET_ASI_EXCP: 1954c03a0fd1SRichard Henderson break; 1955c03a0fd1SRichard Henderson case GET_ASI_DIRECT: 1956dca544b9SRichard Henderson tcg_gen_atomic_xchg_tl(dst, addr, src, 1957dca544b9SRichard Henderson da->mem_idx, da->memop | MO_ALIGN); 1958c03a0fd1SRichard Henderson break; 1959c03a0fd1SRichard Henderson default: 1960c03a0fd1SRichard Henderson /* ??? Should be DAE_invalid_asi. */ 1961c03a0fd1SRichard Henderson gen_exception(dc, TT_DATA_ACCESS); 1962c03a0fd1SRichard Henderson break; 1963c03a0fd1SRichard Henderson } 1964c03a0fd1SRichard Henderson } 1965c03a0fd1SRichard Henderson 1966d0a11d25SRichard Henderson static void gen_cas_asi(DisasContext *dc, DisasASI *da, 1967c03a0fd1SRichard Henderson TCGv oldv, TCGv newv, TCGv cmpv, TCGv addr) 1968c03a0fd1SRichard Henderson { 1969c03a0fd1SRichard Henderson switch (da->type) { 1970fcf5ef2aSThomas Huth case GET_ASI_EXCP: 1971c03a0fd1SRichard Henderson return; 1972fcf5ef2aSThomas Huth case GET_ASI_DIRECT: 1973c03a0fd1SRichard Henderson tcg_gen_atomic_cmpxchg_tl(oldv, addr, cmpv, newv, 1974c03a0fd1SRichard Henderson da->mem_idx, da->memop | MO_ALIGN); 1975fcf5ef2aSThomas Huth break; 1976fcf5ef2aSThomas Huth default: 1977fcf5ef2aSThomas Huth /* ??? Should be DAE_invalid_asi. */ 1978fcf5ef2aSThomas Huth gen_exception(dc, TT_DATA_ACCESS); 1979fcf5ef2aSThomas Huth break; 1980fcf5ef2aSThomas Huth } 1981fcf5ef2aSThomas Huth } 1982fcf5ef2aSThomas Huth 1983cf07cd1eSRichard Henderson static void gen_ldstub_asi(DisasContext *dc, DisasASI *da, TCGv dst, TCGv addr) 1984c03a0fd1SRichard Henderson { 1985c03a0fd1SRichard Henderson switch (da->type) { 1986fcf5ef2aSThomas Huth case GET_ASI_EXCP: 1987fcf5ef2aSThomas Huth break; 1988fcf5ef2aSThomas Huth case GET_ASI_DIRECT: 1989cf07cd1eSRichard Henderson tcg_gen_atomic_xchg_tl(dst, addr, tcg_constant_tl(0xff), 1990cf07cd1eSRichard Henderson da->mem_idx, MO_UB); 1991fcf5ef2aSThomas Huth break; 1992fcf5ef2aSThomas Huth default: 19933db010c3SRichard Henderson /* ??? In theory, this should be raise DAE_invalid_asi. 19943db010c3SRichard Henderson But the SS-20 roms do ldstuba [%l0] #ASI_M_CTL, %o1. */ 1995af00be49SEmilio G. Cota if (tb_cflags(dc->base.tb) & CF_PARALLEL) { 1996ad75a51eSRichard Henderson gen_helper_exit_atomic(tcg_env); 19973db010c3SRichard Henderson } else { 1998c03a0fd1SRichard Henderson TCGv_i32 r_asi = tcg_constant_i32(da->asi); 199900ab7e61SRichard Henderson TCGv_i32 r_mop = tcg_constant_i32(MO_UB); 20003db010c3SRichard Henderson TCGv_i64 s64, t64; 20013db010c3SRichard Henderson 20023db010c3SRichard Henderson save_state(dc); 20033db010c3SRichard Henderson t64 = tcg_temp_new_i64(); 2004ad75a51eSRichard Henderson gen_helper_ld_asi(t64, tcg_env, addr, r_asi, r_mop); 20053db010c3SRichard Henderson 200600ab7e61SRichard Henderson s64 = tcg_constant_i64(0xff); 2007ad75a51eSRichard Henderson gen_helper_st_asi(tcg_env, addr, s64, r_asi, r_mop); 20083db010c3SRichard Henderson 20093db010c3SRichard Henderson tcg_gen_trunc_i64_tl(dst, t64); 20103db010c3SRichard Henderson 20113db010c3SRichard Henderson /* End the TB. */ 20123db010c3SRichard Henderson dc->npc = DYNAMIC_PC; 20133db010c3SRichard Henderson } 2014fcf5ef2aSThomas Huth break; 2015fcf5ef2aSThomas Huth } 2016fcf5ef2aSThomas Huth } 2017fcf5ef2aSThomas Huth 2018287b1152SRichard Henderson static void gen_ldf_asi(DisasContext *dc, DisasASI *da, MemOp orig_size, 20193259b9e2SRichard Henderson TCGv addr, int rd) 2020fcf5ef2aSThomas Huth { 20213259b9e2SRichard Henderson MemOp memop = da->memop; 20223259b9e2SRichard Henderson MemOp size = memop & MO_SIZE; 2023fcf5ef2aSThomas Huth TCGv_i32 d32; 2024fcf5ef2aSThomas Huth TCGv_i64 d64; 2025287b1152SRichard Henderson TCGv addr_tmp; 2026fcf5ef2aSThomas Huth 20273259b9e2SRichard Henderson /* TODO: Use 128-bit load/store below. */ 20283259b9e2SRichard Henderson if (size == MO_128) { 20293259b9e2SRichard Henderson memop = (memop & ~MO_SIZE) | MO_64; 20303259b9e2SRichard Henderson } 20313259b9e2SRichard Henderson 20323259b9e2SRichard Henderson switch (da->type) { 2033fcf5ef2aSThomas Huth case GET_ASI_EXCP: 2034fcf5ef2aSThomas Huth break; 2035fcf5ef2aSThomas Huth 2036fcf5ef2aSThomas Huth case GET_ASI_DIRECT: 20373259b9e2SRichard Henderson memop |= MO_ALIGN_4; 2038fcf5ef2aSThomas Huth switch (size) { 20393259b9e2SRichard Henderson case MO_32: 2040fcf5ef2aSThomas Huth d32 = gen_dest_fpr_F(dc); 20413259b9e2SRichard Henderson tcg_gen_qemu_ld_i32(d32, addr, da->mem_idx, memop); 2042fcf5ef2aSThomas Huth gen_store_fpr_F(dc, rd, d32); 2043fcf5ef2aSThomas Huth break; 20443259b9e2SRichard Henderson 20453259b9e2SRichard Henderson case MO_64: 20463259b9e2SRichard Henderson tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2], addr, da->mem_idx, memop); 2047fcf5ef2aSThomas Huth break; 20483259b9e2SRichard Henderson 20493259b9e2SRichard Henderson case MO_128: 2050fcf5ef2aSThomas Huth d64 = tcg_temp_new_i64(); 20513259b9e2SRichard Henderson tcg_gen_qemu_ld_i64(d64, addr, da->mem_idx, memop); 2052287b1152SRichard Henderson addr_tmp = tcg_temp_new(); 2053287b1152SRichard Henderson tcg_gen_addi_tl(addr_tmp, addr, 8); 2054287b1152SRichard Henderson tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2 + 1], addr_tmp, da->mem_idx, memop); 2055fcf5ef2aSThomas Huth tcg_gen_mov_i64(cpu_fpr[rd / 2], d64); 2056fcf5ef2aSThomas Huth break; 2057fcf5ef2aSThomas Huth default: 2058fcf5ef2aSThomas Huth g_assert_not_reached(); 2059fcf5ef2aSThomas Huth } 2060fcf5ef2aSThomas Huth break; 2061fcf5ef2aSThomas Huth 2062fcf5ef2aSThomas Huth case GET_ASI_BLOCK: 2063fcf5ef2aSThomas Huth /* Valid for lddfa on aligned registers only. */ 20643259b9e2SRichard Henderson if (orig_size == MO_64 && (rd & 7) == 0) { 2065fcf5ef2aSThomas Huth /* The first operation checks required alignment. */ 2066287b1152SRichard Henderson addr_tmp = tcg_temp_new(); 2067287b1152SRichard Henderson for (int i = 0; ; ++i) { 20683259b9e2SRichard Henderson tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2 + i], addr, da->mem_idx, 20693259b9e2SRichard Henderson memop | (i == 0 ? MO_ALIGN_64 : 0)); 2070fcf5ef2aSThomas Huth if (i == 7) { 2071fcf5ef2aSThomas Huth break; 2072fcf5ef2aSThomas Huth } 2073287b1152SRichard Henderson tcg_gen_addi_tl(addr_tmp, addr, 8); 2074287b1152SRichard Henderson addr = addr_tmp; 2075fcf5ef2aSThomas Huth } 2076fcf5ef2aSThomas Huth } else { 2077fcf5ef2aSThomas Huth gen_exception(dc, TT_ILL_INSN); 2078fcf5ef2aSThomas Huth } 2079fcf5ef2aSThomas Huth break; 2080fcf5ef2aSThomas Huth 2081fcf5ef2aSThomas Huth case GET_ASI_SHORT: 2082fcf5ef2aSThomas Huth /* Valid for lddfa only. */ 20833259b9e2SRichard Henderson if (orig_size == MO_64) { 20843259b9e2SRichard Henderson tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2], addr, da->mem_idx, 20853259b9e2SRichard Henderson memop | MO_ALIGN); 2086fcf5ef2aSThomas Huth } else { 2087fcf5ef2aSThomas Huth gen_exception(dc, TT_ILL_INSN); 2088fcf5ef2aSThomas Huth } 2089fcf5ef2aSThomas Huth break; 2090fcf5ef2aSThomas Huth 2091fcf5ef2aSThomas Huth default: 2092fcf5ef2aSThomas Huth { 20933259b9e2SRichard Henderson TCGv_i32 r_asi = tcg_constant_i32(da->asi); 20943259b9e2SRichard Henderson TCGv_i32 r_mop = tcg_constant_i32(memop | MO_ALIGN); 2095fcf5ef2aSThomas Huth 2096fcf5ef2aSThomas Huth save_state(dc); 2097fcf5ef2aSThomas Huth /* According to the table in the UA2011 manual, the only 2098fcf5ef2aSThomas Huth other asis that are valid for ldfa/lddfa/ldqfa are 2099fcf5ef2aSThomas Huth the NO_FAULT asis. We still need a helper for these, 2100fcf5ef2aSThomas Huth but we can just use the integer asi helper for them. */ 2101fcf5ef2aSThomas Huth switch (size) { 21023259b9e2SRichard Henderson case MO_32: 2103fcf5ef2aSThomas Huth d64 = tcg_temp_new_i64(); 2104ad75a51eSRichard Henderson gen_helper_ld_asi(d64, tcg_env, addr, r_asi, r_mop); 2105fcf5ef2aSThomas Huth d32 = gen_dest_fpr_F(dc); 2106fcf5ef2aSThomas Huth tcg_gen_extrl_i64_i32(d32, d64); 2107fcf5ef2aSThomas Huth gen_store_fpr_F(dc, rd, d32); 2108fcf5ef2aSThomas Huth break; 21093259b9e2SRichard Henderson case MO_64: 21103259b9e2SRichard Henderson gen_helper_ld_asi(cpu_fpr[rd / 2], tcg_env, addr, 21113259b9e2SRichard Henderson r_asi, r_mop); 2112fcf5ef2aSThomas Huth break; 21133259b9e2SRichard Henderson case MO_128: 2114fcf5ef2aSThomas Huth d64 = tcg_temp_new_i64(); 2115ad75a51eSRichard Henderson gen_helper_ld_asi(d64, tcg_env, addr, r_asi, r_mop); 2116287b1152SRichard Henderson addr_tmp = tcg_temp_new(); 2117287b1152SRichard Henderson tcg_gen_addi_tl(addr_tmp, addr, 8); 2118287b1152SRichard Henderson gen_helper_ld_asi(cpu_fpr[rd / 2 + 1], tcg_env, addr_tmp, 21193259b9e2SRichard Henderson r_asi, r_mop); 2120fcf5ef2aSThomas Huth tcg_gen_mov_i64(cpu_fpr[rd / 2], d64); 2121fcf5ef2aSThomas Huth break; 2122fcf5ef2aSThomas Huth default: 2123fcf5ef2aSThomas Huth g_assert_not_reached(); 2124fcf5ef2aSThomas Huth } 2125fcf5ef2aSThomas Huth } 2126fcf5ef2aSThomas Huth break; 2127fcf5ef2aSThomas Huth } 2128fcf5ef2aSThomas Huth } 2129fcf5ef2aSThomas Huth 2130287b1152SRichard Henderson static void gen_stf_asi(DisasContext *dc, DisasASI *da, MemOp orig_size, 21313259b9e2SRichard Henderson TCGv addr, int rd) 21323259b9e2SRichard Henderson { 21333259b9e2SRichard Henderson MemOp memop = da->memop; 21343259b9e2SRichard Henderson MemOp size = memop & MO_SIZE; 2135fcf5ef2aSThomas Huth TCGv_i32 d32; 2136287b1152SRichard Henderson TCGv addr_tmp; 2137fcf5ef2aSThomas Huth 21383259b9e2SRichard Henderson /* TODO: Use 128-bit load/store below. */ 21393259b9e2SRichard Henderson if (size == MO_128) { 21403259b9e2SRichard Henderson memop = (memop & ~MO_SIZE) | MO_64; 21413259b9e2SRichard Henderson } 21423259b9e2SRichard Henderson 21433259b9e2SRichard Henderson switch (da->type) { 2144fcf5ef2aSThomas Huth case GET_ASI_EXCP: 2145fcf5ef2aSThomas Huth break; 2146fcf5ef2aSThomas Huth 2147fcf5ef2aSThomas Huth case GET_ASI_DIRECT: 21483259b9e2SRichard Henderson memop |= MO_ALIGN_4; 2149fcf5ef2aSThomas Huth switch (size) { 21503259b9e2SRichard Henderson case MO_32: 2151fcf5ef2aSThomas Huth d32 = gen_load_fpr_F(dc, rd); 21523259b9e2SRichard Henderson tcg_gen_qemu_st_i32(d32, addr, da->mem_idx, memop | MO_ALIGN); 2153fcf5ef2aSThomas Huth break; 21543259b9e2SRichard Henderson case MO_64: 21553259b9e2SRichard Henderson tcg_gen_qemu_st_i64(cpu_fpr[rd / 2], addr, da->mem_idx, 21563259b9e2SRichard Henderson memop | MO_ALIGN_4); 2157fcf5ef2aSThomas Huth break; 21583259b9e2SRichard Henderson case MO_128: 2159fcf5ef2aSThomas Huth /* Only 4-byte alignment required. However, it is legal for the 2160fcf5ef2aSThomas Huth cpu to signal the alignment fault, and the OS trap handler is 2161fcf5ef2aSThomas Huth required to fix it up. Requiring 16-byte alignment here avoids 2162fcf5ef2aSThomas Huth having to probe the second page before performing the first 2163fcf5ef2aSThomas Huth write. */ 21643259b9e2SRichard Henderson tcg_gen_qemu_st_i64(cpu_fpr[rd / 2], addr, da->mem_idx, 21653259b9e2SRichard Henderson memop | MO_ALIGN_16); 2166287b1152SRichard Henderson addr_tmp = tcg_temp_new(); 2167287b1152SRichard Henderson tcg_gen_addi_tl(addr_tmp, addr, 8); 2168287b1152SRichard Henderson tcg_gen_qemu_st_i64(cpu_fpr[rd / 2 + 1], addr_tmp, da->mem_idx, memop); 2169fcf5ef2aSThomas Huth break; 2170fcf5ef2aSThomas Huth default: 2171fcf5ef2aSThomas Huth g_assert_not_reached(); 2172fcf5ef2aSThomas Huth } 2173fcf5ef2aSThomas Huth break; 2174fcf5ef2aSThomas Huth 2175fcf5ef2aSThomas Huth case GET_ASI_BLOCK: 2176fcf5ef2aSThomas Huth /* Valid for stdfa on aligned registers only. */ 21773259b9e2SRichard Henderson if (orig_size == MO_64 && (rd & 7) == 0) { 2178fcf5ef2aSThomas Huth /* The first operation checks required alignment. */ 2179287b1152SRichard Henderson addr_tmp = tcg_temp_new(); 2180287b1152SRichard Henderson for (int i = 0; ; ++i) { 21813259b9e2SRichard Henderson tcg_gen_qemu_st_i64(cpu_fpr[rd / 2 + i], addr, da->mem_idx, 21823259b9e2SRichard Henderson memop | (i == 0 ? MO_ALIGN_64 : 0)); 2183fcf5ef2aSThomas Huth if (i == 7) { 2184fcf5ef2aSThomas Huth break; 2185fcf5ef2aSThomas Huth } 2186287b1152SRichard Henderson tcg_gen_addi_tl(addr_tmp, addr, 8); 2187287b1152SRichard Henderson addr = addr_tmp; 2188fcf5ef2aSThomas Huth } 2189fcf5ef2aSThomas Huth } else { 2190fcf5ef2aSThomas Huth gen_exception(dc, TT_ILL_INSN); 2191fcf5ef2aSThomas Huth } 2192fcf5ef2aSThomas Huth break; 2193fcf5ef2aSThomas Huth 2194fcf5ef2aSThomas Huth case GET_ASI_SHORT: 2195fcf5ef2aSThomas Huth /* Valid for stdfa only. */ 21963259b9e2SRichard Henderson if (orig_size == MO_64) { 21973259b9e2SRichard Henderson tcg_gen_qemu_st_i64(cpu_fpr[rd / 2], addr, da->mem_idx, 21983259b9e2SRichard Henderson memop | MO_ALIGN); 2199fcf5ef2aSThomas Huth } else { 2200fcf5ef2aSThomas Huth gen_exception(dc, TT_ILL_INSN); 2201fcf5ef2aSThomas Huth } 2202fcf5ef2aSThomas Huth break; 2203fcf5ef2aSThomas Huth 2204fcf5ef2aSThomas Huth default: 2205fcf5ef2aSThomas Huth /* According to the table in the UA2011 manual, the only 2206fcf5ef2aSThomas Huth other asis that are valid for ldfa/lddfa/ldqfa are 2207fcf5ef2aSThomas Huth the PST* asis, which aren't currently handled. */ 2208fcf5ef2aSThomas Huth gen_exception(dc, TT_ILL_INSN); 2209fcf5ef2aSThomas Huth break; 2210fcf5ef2aSThomas Huth } 2211fcf5ef2aSThomas Huth } 2212fcf5ef2aSThomas Huth 221342071fc1SRichard Henderson static void gen_ldda_asi(DisasContext *dc, DisasASI *da, TCGv addr, int rd) 2214fcf5ef2aSThomas Huth { 2215a76779eeSRichard Henderson TCGv hi = gen_dest_gpr(dc, rd); 2216a76779eeSRichard Henderson TCGv lo = gen_dest_gpr(dc, rd + 1); 2217fcf5ef2aSThomas Huth 2218c03a0fd1SRichard Henderson switch (da->type) { 2219fcf5ef2aSThomas Huth case GET_ASI_EXCP: 2220fcf5ef2aSThomas Huth return; 2221fcf5ef2aSThomas Huth 2222fcf5ef2aSThomas Huth case GET_ASI_DTWINX: 2223ebbbec92SRichard Henderson #ifdef TARGET_SPARC64 2224ebbbec92SRichard Henderson { 2225ebbbec92SRichard Henderson MemOp mop = (da->memop & MO_BSWAP) | MO_128 | MO_ALIGN_16; 2226ebbbec92SRichard Henderson TCGv_i128 t = tcg_temp_new_i128(); 2227ebbbec92SRichard Henderson 2228ebbbec92SRichard Henderson tcg_gen_qemu_ld_i128(t, addr, da->mem_idx, mop); 2229ebbbec92SRichard Henderson /* 2230ebbbec92SRichard Henderson * Note that LE twinx acts as if each 64-bit register result is 2231ebbbec92SRichard Henderson * byte swapped. We perform one 128-bit LE load, so must swap 2232ebbbec92SRichard Henderson * the order of the writebacks. 2233ebbbec92SRichard Henderson */ 2234ebbbec92SRichard Henderson if ((mop & MO_BSWAP) == MO_TE) { 2235ebbbec92SRichard Henderson tcg_gen_extr_i128_i64(lo, hi, t); 2236ebbbec92SRichard Henderson } else { 2237ebbbec92SRichard Henderson tcg_gen_extr_i128_i64(hi, lo, t); 2238ebbbec92SRichard Henderson } 2239ebbbec92SRichard Henderson } 2240fcf5ef2aSThomas Huth break; 2241ebbbec92SRichard Henderson #else 2242ebbbec92SRichard Henderson g_assert_not_reached(); 2243ebbbec92SRichard Henderson #endif 2244fcf5ef2aSThomas Huth 2245fcf5ef2aSThomas Huth case GET_ASI_DIRECT: 2246fcf5ef2aSThomas Huth { 2247fcf5ef2aSThomas Huth TCGv_i64 tmp = tcg_temp_new_i64(); 2248fcf5ef2aSThomas Huth 2249c03a0fd1SRichard Henderson tcg_gen_qemu_ld_i64(tmp, addr, da->mem_idx, da->memop | MO_ALIGN); 2250fcf5ef2aSThomas Huth 2251fcf5ef2aSThomas Huth /* Note that LE ldda acts as if each 32-bit register 2252fcf5ef2aSThomas Huth result is byte swapped. Having just performed one 2253fcf5ef2aSThomas Huth 64-bit bswap, we need now to swap the writebacks. */ 2254c03a0fd1SRichard Henderson if ((da->memop & MO_BSWAP) == MO_TE) { 2255a76779eeSRichard Henderson tcg_gen_extr_i64_tl(lo, hi, tmp); 2256fcf5ef2aSThomas Huth } else { 2257a76779eeSRichard Henderson tcg_gen_extr_i64_tl(hi, lo, tmp); 2258fcf5ef2aSThomas Huth } 2259fcf5ef2aSThomas Huth } 2260fcf5ef2aSThomas Huth break; 2261fcf5ef2aSThomas Huth 2262fcf5ef2aSThomas Huth default: 2263fcf5ef2aSThomas Huth /* ??? In theory we've handled all of the ASIs that are valid 2264fcf5ef2aSThomas Huth for ldda, and this should raise DAE_invalid_asi. However, 2265fcf5ef2aSThomas Huth real hardware allows others. This can be seen with e.g. 2266fcf5ef2aSThomas Huth FreeBSD 10.3 wrt ASI_IC_TAG. */ 2267fcf5ef2aSThomas Huth { 2268c03a0fd1SRichard Henderson TCGv_i32 r_asi = tcg_constant_i32(da->asi); 2269c03a0fd1SRichard Henderson TCGv_i32 r_mop = tcg_constant_i32(da->memop); 2270fcf5ef2aSThomas Huth TCGv_i64 tmp = tcg_temp_new_i64(); 2271fcf5ef2aSThomas Huth 2272fcf5ef2aSThomas Huth save_state(dc); 2273ad75a51eSRichard Henderson gen_helper_ld_asi(tmp, tcg_env, addr, r_asi, r_mop); 2274fcf5ef2aSThomas Huth 2275fcf5ef2aSThomas Huth /* See above. */ 2276c03a0fd1SRichard Henderson if ((da->memop & MO_BSWAP) == MO_TE) { 2277a76779eeSRichard Henderson tcg_gen_extr_i64_tl(lo, hi, tmp); 2278fcf5ef2aSThomas Huth } else { 2279a76779eeSRichard Henderson tcg_gen_extr_i64_tl(hi, lo, tmp); 2280fcf5ef2aSThomas Huth } 2281fcf5ef2aSThomas Huth } 2282fcf5ef2aSThomas Huth break; 2283fcf5ef2aSThomas Huth } 2284fcf5ef2aSThomas Huth 2285fcf5ef2aSThomas Huth gen_store_gpr(dc, rd, hi); 2286fcf5ef2aSThomas Huth gen_store_gpr(dc, rd + 1, lo); 2287fcf5ef2aSThomas Huth } 2288fcf5ef2aSThomas Huth 228942071fc1SRichard Henderson static void gen_stda_asi(DisasContext *dc, DisasASI *da, TCGv addr, int rd) 2290c03a0fd1SRichard Henderson { 2291c03a0fd1SRichard Henderson TCGv hi = gen_load_gpr(dc, rd); 2292fcf5ef2aSThomas Huth TCGv lo = gen_load_gpr(dc, rd + 1); 2293fcf5ef2aSThomas Huth 2294c03a0fd1SRichard Henderson switch (da->type) { 2295fcf5ef2aSThomas Huth case GET_ASI_EXCP: 2296fcf5ef2aSThomas Huth break; 2297fcf5ef2aSThomas Huth 2298fcf5ef2aSThomas Huth case GET_ASI_DTWINX: 2299ebbbec92SRichard Henderson #ifdef TARGET_SPARC64 2300ebbbec92SRichard Henderson { 2301ebbbec92SRichard Henderson MemOp mop = (da->memop & MO_BSWAP) | MO_128 | MO_ALIGN_16; 2302ebbbec92SRichard Henderson TCGv_i128 t = tcg_temp_new_i128(); 2303ebbbec92SRichard Henderson 2304ebbbec92SRichard Henderson /* 2305ebbbec92SRichard Henderson * Note that LE twinx acts as if each 64-bit register result is 2306ebbbec92SRichard Henderson * byte swapped. We perform one 128-bit LE store, so must swap 2307ebbbec92SRichard Henderson * the order of the construction. 2308ebbbec92SRichard Henderson */ 2309ebbbec92SRichard Henderson if ((mop & MO_BSWAP) == MO_TE) { 2310ebbbec92SRichard Henderson tcg_gen_concat_i64_i128(t, lo, hi); 2311ebbbec92SRichard Henderson } else { 2312ebbbec92SRichard Henderson tcg_gen_concat_i64_i128(t, hi, lo); 2313ebbbec92SRichard Henderson } 2314ebbbec92SRichard Henderson tcg_gen_qemu_st_i128(t, addr, da->mem_idx, mop); 2315ebbbec92SRichard Henderson } 2316fcf5ef2aSThomas Huth break; 2317ebbbec92SRichard Henderson #else 2318ebbbec92SRichard Henderson g_assert_not_reached(); 2319ebbbec92SRichard Henderson #endif 2320fcf5ef2aSThomas Huth 2321fcf5ef2aSThomas Huth case GET_ASI_DIRECT: 2322fcf5ef2aSThomas Huth { 2323fcf5ef2aSThomas Huth TCGv_i64 t64 = tcg_temp_new_i64(); 2324fcf5ef2aSThomas Huth 2325fcf5ef2aSThomas Huth /* Note that LE stda acts as if each 32-bit register result is 2326fcf5ef2aSThomas Huth byte swapped. We will perform one 64-bit LE store, so now 2327fcf5ef2aSThomas Huth we must swap the order of the construction. */ 2328c03a0fd1SRichard Henderson if ((da->memop & MO_BSWAP) == MO_TE) { 2329a76779eeSRichard Henderson tcg_gen_concat_tl_i64(t64, lo, hi); 2330fcf5ef2aSThomas Huth } else { 2331a76779eeSRichard Henderson tcg_gen_concat_tl_i64(t64, hi, lo); 2332fcf5ef2aSThomas Huth } 2333c03a0fd1SRichard Henderson tcg_gen_qemu_st_i64(t64, addr, da->mem_idx, da->memop | MO_ALIGN); 2334fcf5ef2aSThomas Huth } 2335fcf5ef2aSThomas Huth break; 2336fcf5ef2aSThomas Huth 2337a76779eeSRichard Henderson case GET_ASI_BFILL: 2338a76779eeSRichard Henderson assert(TARGET_LONG_BITS == 32); 2339a76779eeSRichard Henderson /* Store 32 bytes of T64 to ADDR. */ 2340a76779eeSRichard Henderson /* ??? The original qemu code suggests 8-byte alignment, dropping 2341a76779eeSRichard Henderson the low bits, but the only place I can see this used is in the 2342a76779eeSRichard Henderson Linux kernel with 32 byte alignment, which would make more sense 2343a76779eeSRichard Henderson as a cacheline-style operation. */ 2344a76779eeSRichard Henderson { 2345a76779eeSRichard Henderson TCGv_i64 t64 = tcg_temp_new_i64(); 2346a76779eeSRichard Henderson TCGv d_addr = tcg_temp_new(); 2347a76779eeSRichard Henderson TCGv eight = tcg_constant_tl(8); 2348a76779eeSRichard Henderson int i; 2349a76779eeSRichard Henderson 2350a76779eeSRichard Henderson tcg_gen_concat_tl_i64(t64, lo, hi); 2351a76779eeSRichard Henderson tcg_gen_andi_tl(d_addr, addr, -8); 2352a76779eeSRichard Henderson for (i = 0; i < 32; i += 8) { 2353c03a0fd1SRichard Henderson tcg_gen_qemu_st_i64(t64, d_addr, da->mem_idx, da->memop); 2354a76779eeSRichard Henderson tcg_gen_add_tl(d_addr, d_addr, eight); 2355a76779eeSRichard Henderson } 2356a76779eeSRichard Henderson } 2357a76779eeSRichard Henderson break; 2358a76779eeSRichard Henderson 2359fcf5ef2aSThomas Huth default: 2360fcf5ef2aSThomas Huth /* ??? In theory we've handled all of the ASIs that are valid 2361fcf5ef2aSThomas Huth for stda, and this should raise DAE_invalid_asi. */ 2362fcf5ef2aSThomas Huth { 2363c03a0fd1SRichard Henderson TCGv_i32 r_asi = tcg_constant_i32(da->asi); 2364c03a0fd1SRichard Henderson TCGv_i32 r_mop = tcg_constant_i32(da->memop); 2365fcf5ef2aSThomas Huth TCGv_i64 t64 = tcg_temp_new_i64(); 2366fcf5ef2aSThomas Huth 2367fcf5ef2aSThomas Huth /* See above. */ 2368c03a0fd1SRichard Henderson if ((da->memop & MO_BSWAP) == MO_TE) { 2369a76779eeSRichard Henderson tcg_gen_concat_tl_i64(t64, lo, hi); 2370fcf5ef2aSThomas Huth } else { 2371a76779eeSRichard Henderson tcg_gen_concat_tl_i64(t64, hi, lo); 2372fcf5ef2aSThomas Huth } 2373fcf5ef2aSThomas Huth 2374fcf5ef2aSThomas Huth save_state(dc); 2375ad75a51eSRichard Henderson gen_helper_st_asi(tcg_env, addr, t64, r_asi, r_mop); 2376fcf5ef2aSThomas Huth } 2377fcf5ef2aSThomas Huth break; 2378fcf5ef2aSThomas Huth } 2379fcf5ef2aSThomas Huth } 2380fcf5ef2aSThomas Huth 2381fcf5ef2aSThomas Huth static void gen_fmovs(DisasContext *dc, DisasCompare *cmp, int rd, int rs) 2382fcf5ef2aSThomas Huth { 2383f7ec8155SRichard Henderson #ifdef TARGET_SPARC64 2384fcf5ef2aSThomas Huth TCGv_i32 c32, zero, dst, s1, s2; 2385fcf5ef2aSThomas Huth 2386fcf5ef2aSThomas Huth /* We have two choices here: extend the 32 bit data and use movcond_i64, 2387fcf5ef2aSThomas Huth or fold the comparison down to 32 bits and use movcond_i32. Choose 2388fcf5ef2aSThomas Huth the later. */ 2389fcf5ef2aSThomas Huth c32 = tcg_temp_new_i32(); 2390fcf5ef2aSThomas Huth if (cmp->is_bool) { 2391fcf5ef2aSThomas Huth tcg_gen_extrl_i64_i32(c32, cmp->c1); 2392fcf5ef2aSThomas Huth } else { 2393fcf5ef2aSThomas Huth TCGv_i64 c64 = tcg_temp_new_i64(); 2394fcf5ef2aSThomas Huth tcg_gen_setcond_i64(cmp->cond, c64, cmp->c1, cmp->c2); 2395fcf5ef2aSThomas Huth tcg_gen_extrl_i64_i32(c32, c64); 2396fcf5ef2aSThomas Huth } 2397fcf5ef2aSThomas Huth 2398fcf5ef2aSThomas Huth s1 = gen_load_fpr_F(dc, rs); 2399fcf5ef2aSThomas Huth s2 = gen_load_fpr_F(dc, rd); 2400fcf5ef2aSThomas Huth dst = gen_dest_fpr_F(dc); 240100ab7e61SRichard Henderson zero = tcg_constant_i32(0); 2402fcf5ef2aSThomas Huth 2403fcf5ef2aSThomas Huth tcg_gen_movcond_i32(TCG_COND_NE, dst, c32, zero, s1, s2); 2404fcf5ef2aSThomas Huth 2405fcf5ef2aSThomas Huth gen_store_fpr_F(dc, rd, dst); 2406f7ec8155SRichard Henderson #else 2407f7ec8155SRichard Henderson qemu_build_not_reached(); 2408f7ec8155SRichard Henderson #endif 2409fcf5ef2aSThomas Huth } 2410fcf5ef2aSThomas Huth 2411fcf5ef2aSThomas Huth static void gen_fmovd(DisasContext *dc, DisasCompare *cmp, int rd, int rs) 2412fcf5ef2aSThomas Huth { 2413f7ec8155SRichard Henderson #ifdef TARGET_SPARC64 2414fcf5ef2aSThomas Huth TCGv_i64 dst = gen_dest_fpr_D(dc, rd); 2415fcf5ef2aSThomas Huth tcg_gen_movcond_i64(cmp->cond, dst, cmp->c1, cmp->c2, 2416fcf5ef2aSThomas Huth gen_load_fpr_D(dc, rs), 2417fcf5ef2aSThomas Huth gen_load_fpr_D(dc, rd)); 2418fcf5ef2aSThomas Huth gen_store_fpr_D(dc, rd, dst); 2419f7ec8155SRichard Henderson #else 2420f7ec8155SRichard Henderson qemu_build_not_reached(); 2421f7ec8155SRichard Henderson #endif 2422fcf5ef2aSThomas Huth } 2423fcf5ef2aSThomas Huth 2424fcf5ef2aSThomas Huth static void gen_fmovq(DisasContext *dc, DisasCompare *cmp, int rd, int rs) 2425fcf5ef2aSThomas Huth { 2426f7ec8155SRichard Henderson #ifdef TARGET_SPARC64 2427fcf5ef2aSThomas Huth int qd = QFPREG(rd); 2428fcf5ef2aSThomas Huth int qs = QFPREG(rs); 2429fcf5ef2aSThomas Huth 2430fcf5ef2aSThomas Huth tcg_gen_movcond_i64(cmp->cond, cpu_fpr[qd / 2], cmp->c1, cmp->c2, 2431fcf5ef2aSThomas Huth cpu_fpr[qs / 2], cpu_fpr[qd / 2]); 2432fcf5ef2aSThomas Huth tcg_gen_movcond_i64(cmp->cond, cpu_fpr[qd / 2 + 1], cmp->c1, cmp->c2, 2433fcf5ef2aSThomas Huth cpu_fpr[qs / 2 + 1], cpu_fpr[qd / 2 + 1]); 2434fcf5ef2aSThomas Huth 2435fcf5ef2aSThomas Huth gen_update_fprs_dirty(dc, qd); 2436f7ec8155SRichard Henderson #else 2437f7ec8155SRichard Henderson qemu_build_not_reached(); 2438f7ec8155SRichard Henderson #endif 2439fcf5ef2aSThomas Huth } 2440fcf5ef2aSThomas Huth 2441f7ec8155SRichard Henderson #ifdef TARGET_SPARC64 24425d617bfbSRichard Henderson static void gen_load_trap_state_at_tl(TCGv_ptr r_tsptr) 2443fcf5ef2aSThomas Huth { 2444fcf5ef2aSThomas Huth TCGv_i32 r_tl = tcg_temp_new_i32(); 2445fcf5ef2aSThomas Huth 2446fcf5ef2aSThomas Huth /* load env->tl into r_tl */ 2447ad75a51eSRichard Henderson tcg_gen_ld_i32(r_tl, tcg_env, offsetof(CPUSPARCState, tl)); 2448fcf5ef2aSThomas Huth 2449fcf5ef2aSThomas Huth /* tl = [0 ... MAXTL_MASK] where MAXTL_MASK must be power of 2 */ 2450fcf5ef2aSThomas Huth tcg_gen_andi_i32(r_tl, r_tl, MAXTL_MASK); 2451fcf5ef2aSThomas Huth 2452fcf5ef2aSThomas Huth /* calculate offset to current trap state from env->ts, reuse r_tl */ 2453fcf5ef2aSThomas Huth tcg_gen_muli_i32(r_tl, r_tl, sizeof (trap_state)); 2454ad75a51eSRichard Henderson tcg_gen_addi_ptr(r_tsptr, tcg_env, offsetof(CPUSPARCState, ts)); 2455fcf5ef2aSThomas Huth 2456fcf5ef2aSThomas Huth /* tsptr = env->ts[env->tl & MAXTL_MASK] */ 2457fcf5ef2aSThomas Huth { 2458fcf5ef2aSThomas Huth TCGv_ptr r_tl_tmp = tcg_temp_new_ptr(); 2459fcf5ef2aSThomas Huth tcg_gen_ext_i32_ptr(r_tl_tmp, r_tl); 2460fcf5ef2aSThomas Huth tcg_gen_add_ptr(r_tsptr, r_tsptr, r_tl_tmp); 2461fcf5ef2aSThomas Huth } 2462fcf5ef2aSThomas Huth } 2463fcf5ef2aSThomas Huth #endif 2464fcf5ef2aSThomas Huth 246506c060d9SRichard Henderson static int extract_dfpreg(DisasContext *dc, int x) 246606c060d9SRichard Henderson { 246706c060d9SRichard Henderson return DFPREG(x); 246806c060d9SRichard Henderson } 246906c060d9SRichard Henderson 247006c060d9SRichard Henderson static int extract_qfpreg(DisasContext *dc, int x) 247106c060d9SRichard Henderson { 247206c060d9SRichard Henderson return QFPREG(x); 247306c060d9SRichard Henderson } 247406c060d9SRichard Henderson 2475878cc677SRichard Henderson /* Include the auto-generated decoder. */ 2476878cc677SRichard Henderson #include "decode-insns.c.inc" 2477878cc677SRichard Henderson 2478878cc677SRichard Henderson #define TRANS(NAME, AVAIL, FUNC, ...) \ 2479878cc677SRichard Henderson static bool trans_##NAME(DisasContext *dc, arg_##NAME *a) \ 2480878cc677SRichard Henderson { return avail_##AVAIL(dc) && FUNC(dc, __VA_ARGS__); } 2481878cc677SRichard Henderson 2482878cc677SRichard Henderson #define avail_ALL(C) true 2483878cc677SRichard Henderson #ifdef TARGET_SPARC64 2484878cc677SRichard Henderson # define avail_32(C) false 2485af25071cSRichard Henderson # define avail_ASR17(C) false 2486d0a11d25SRichard Henderson # define avail_CASA(C) true 2487c2636853SRichard Henderson # define avail_DIV(C) true 2488b5372650SRichard Henderson # define avail_MUL(C) true 24890faef01bSRichard Henderson # define avail_POWERDOWN(C) false 2490878cc677SRichard Henderson # define avail_64(C) true 24915d617bfbSRichard Henderson # define avail_GL(C) ((C)->def->features & CPU_FEATURE_GL) 2492af25071cSRichard Henderson # define avail_HYPV(C) ((C)->def->features & CPU_FEATURE_HYPV) 2493b88ce6f2SRichard Henderson # define avail_VIS1(C) ((C)->def->features & CPU_FEATURE_VIS1) 2494b88ce6f2SRichard Henderson # define avail_VIS2(C) ((C)->def->features & CPU_FEATURE_VIS2) 2495878cc677SRichard Henderson #else 2496878cc677SRichard Henderson # define avail_32(C) true 2497af25071cSRichard Henderson # define avail_ASR17(C) ((C)->def->features & CPU_FEATURE_ASR17) 2498d0a11d25SRichard Henderson # define avail_CASA(C) ((C)->def->features & CPU_FEATURE_CASA) 2499c2636853SRichard Henderson # define avail_DIV(C) ((C)->def->features & CPU_FEATURE_DIV) 2500b5372650SRichard Henderson # define avail_MUL(C) ((C)->def->features & CPU_FEATURE_MUL) 25010faef01bSRichard Henderson # define avail_POWERDOWN(C) ((C)->def->features & CPU_FEATURE_POWERDOWN) 2502878cc677SRichard Henderson # define avail_64(C) false 25035d617bfbSRichard Henderson # define avail_GL(C) false 2504af25071cSRichard Henderson # define avail_HYPV(C) false 2505b88ce6f2SRichard Henderson # define avail_VIS1(C) false 2506b88ce6f2SRichard Henderson # define avail_VIS2(C) false 2507878cc677SRichard Henderson #endif 2508878cc677SRichard Henderson 2509878cc677SRichard Henderson /* Default case for non jump instructions. */ 2510878cc677SRichard Henderson static bool advance_pc(DisasContext *dc) 2511878cc677SRichard Henderson { 2512878cc677SRichard Henderson if (dc->npc & 3) { 2513878cc677SRichard Henderson switch (dc->npc) { 2514878cc677SRichard Henderson case DYNAMIC_PC: 2515878cc677SRichard Henderson case DYNAMIC_PC_LOOKUP: 2516878cc677SRichard Henderson dc->pc = dc->npc; 2517878cc677SRichard Henderson gen_op_next_insn(); 2518878cc677SRichard Henderson break; 2519878cc677SRichard Henderson case JUMP_PC: 2520878cc677SRichard Henderson /* we can do a static jump */ 2521878cc677SRichard Henderson gen_branch2(dc, dc->jump_pc[0], dc->jump_pc[1], cpu_cond); 2522878cc677SRichard Henderson dc->base.is_jmp = DISAS_NORETURN; 2523878cc677SRichard Henderson break; 2524878cc677SRichard Henderson default: 2525878cc677SRichard Henderson g_assert_not_reached(); 2526878cc677SRichard Henderson } 2527878cc677SRichard Henderson } else { 2528878cc677SRichard Henderson dc->pc = dc->npc; 2529878cc677SRichard Henderson dc->npc = dc->npc + 4; 2530878cc677SRichard Henderson } 2531878cc677SRichard Henderson return true; 2532878cc677SRichard Henderson } 2533878cc677SRichard Henderson 25346d2a0768SRichard Henderson /* 25356d2a0768SRichard Henderson * Major opcodes 00 and 01 -- branches, call, and sethi 25366d2a0768SRichard Henderson */ 25376d2a0768SRichard Henderson 2538276567aaSRichard Henderson static bool advance_jump_uncond_never(DisasContext *dc, bool annul) 2539276567aaSRichard Henderson { 2540276567aaSRichard Henderson if (annul) { 2541276567aaSRichard Henderson dc->pc = dc->npc + 4; 2542276567aaSRichard Henderson dc->npc = dc->pc + 4; 2543276567aaSRichard Henderson } else { 2544276567aaSRichard Henderson dc->pc = dc->npc; 2545276567aaSRichard Henderson dc->npc = dc->pc + 4; 2546276567aaSRichard Henderson } 2547276567aaSRichard Henderson return true; 2548276567aaSRichard Henderson } 2549276567aaSRichard Henderson 2550276567aaSRichard Henderson static bool advance_jump_uncond_always(DisasContext *dc, bool annul, 2551276567aaSRichard Henderson target_ulong dest) 2552276567aaSRichard Henderson { 2553276567aaSRichard Henderson if (annul) { 2554276567aaSRichard Henderson dc->pc = dest; 2555276567aaSRichard Henderson dc->npc = dest + 4; 2556276567aaSRichard Henderson } else { 2557276567aaSRichard Henderson dc->pc = dc->npc; 2558276567aaSRichard Henderson dc->npc = dest; 2559276567aaSRichard Henderson tcg_gen_mov_tl(cpu_pc, cpu_npc); 2560276567aaSRichard Henderson } 2561276567aaSRichard Henderson return true; 2562276567aaSRichard Henderson } 2563276567aaSRichard Henderson 25649d4e2bc7SRichard Henderson static bool advance_jump_cond(DisasContext *dc, DisasCompare *cmp, 25659d4e2bc7SRichard Henderson bool annul, target_ulong dest) 2566276567aaSRichard Henderson { 25676b3e4cc6SRichard Henderson target_ulong npc = dc->npc; 25686b3e4cc6SRichard Henderson 2569276567aaSRichard Henderson if (annul) { 25706b3e4cc6SRichard Henderson TCGLabel *l1 = gen_new_label(); 25716b3e4cc6SRichard Henderson 25729d4e2bc7SRichard Henderson tcg_gen_brcond_tl(tcg_invert_cond(cmp->cond), cmp->c1, cmp->c2, l1); 25736b3e4cc6SRichard Henderson gen_goto_tb(dc, 0, npc, dest); 25746b3e4cc6SRichard Henderson gen_set_label(l1); 25756b3e4cc6SRichard Henderson gen_goto_tb(dc, 1, npc + 4, npc + 8); 25766b3e4cc6SRichard Henderson 25776b3e4cc6SRichard Henderson dc->base.is_jmp = DISAS_NORETURN; 2578276567aaSRichard Henderson } else { 25796b3e4cc6SRichard Henderson if (npc & 3) { 25806b3e4cc6SRichard Henderson switch (npc) { 25816b3e4cc6SRichard Henderson case DYNAMIC_PC: 25826b3e4cc6SRichard Henderson case DYNAMIC_PC_LOOKUP: 25836b3e4cc6SRichard Henderson tcg_gen_mov_tl(cpu_pc, cpu_npc); 25846b3e4cc6SRichard Henderson tcg_gen_addi_tl(cpu_npc, cpu_npc, 4); 25859d4e2bc7SRichard Henderson tcg_gen_movcond_tl(cmp->cond, cpu_npc, 25869d4e2bc7SRichard Henderson cmp->c1, cmp->c2, 25876b3e4cc6SRichard Henderson tcg_constant_tl(dest), cpu_npc); 25886b3e4cc6SRichard Henderson dc->pc = npc; 25896b3e4cc6SRichard Henderson break; 25906b3e4cc6SRichard Henderson default: 25916b3e4cc6SRichard Henderson g_assert_not_reached(); 25926b3e4cc6SRichard Henderson } 25936b3e4cc6SRichard Henderson } else { 25946b3e4cc6SRichard Henderson dc->pc = npc; 25956b3e4cc6SRichard Henderson dc->jump_pc[0] = dest; 25966b3e4cc6SRichard Henderson dc->jump_pc[1] = npc + 4; 25976b3e4cc6SRichard Henderson dc->npc = JUMP_PC; 25989d4e2bc7SRichard Henderson if (cmp->is_bool) { 25999d4e2bc7SRichard Henderson tcg_gen_mov_tl(cpu_cond, cmp->c1); 26009d4e2bc7SRichard Henderson } else { 26019d4e2bc7SRichard Henderson tcg_gen_setcond_tl(cmp->cond, cpu_cond, cmp->c1, cmp->c2); 26029d4e2bc7SRichard Henderson } 26036b3e4cc6SRichard Henderson } 2604276567aaSRichard Henderson } 2605276567aaSRichard Henderson return true; 2606276567aaSRichard Henderson } 2607276567aaSRichard Henderson 2608af25071cSRichard Henderson static bool raise_priv(DisasContext *dc) 2609af25071cSRichard Henderson { 2610af25071cSRichard Henderson gen_exception(dc, TT_PRIV_INSN); 2611af25071cSRichard Henderson return true; 2612af25071cSRichard Henderson } 2613af25071cSRichard Henderson 261406c060d9SRichard Henderson static bool raise_unimpfpop(DisasContext *dc) 261506c060d9SRichard Henderson { 261606c060d9SRichard Henderson gen_op_fpexception_im(dc, FSR_FTT_UNIMPFPOP); 261706c060d9SRichard Henderson return true; 261806c060d9SRichard Henderson } 261906c060d9SRichard Henderson 262006c060d9SRichard Henderson static bool gen_trap_float128(DisasContext *dc) 262106c060d9SRichard Henderson { 262206c060d9SRichard Henderson if (dc->def->features & CPU_FEATURE_FLOAT128) { 262306c060d9SRichard Henderson return false; 262406c060d9SRichard Henderson } 262506c060d9SRichard Henderson return raise_unimpfpop(dc); 262606c060d9SRichard Henderson } 262706c060d9SRichard Henderson 2628276567aaSRichard Henderson static bool do_bpcc(DisasContext *dc, arg_bcc *a) 2629276567aaSRichard Henderson { 2630276567aaSRichard Henderson target_long target = address_mask_i(dc, dc->pc + a->i * 4); 26311ea9c62aSRichard Henderson DisasCompare cmp; 2632276567aaSRichard Henderson 2633276567aaSRichard Henderson switch (a->cond) { 2634276567aaSRichard Henderson case 0x0: 2635276567aaSRichard Henderson return advance_jump_uncond_never(dc, a->a); 2636276567aaSRichard Henderson case 0x8: 2637276567aaSRichard Henderson return advance_jump_uncond_always(dc, a->a, target); 2638276567aaSRichard Henderson default: 2639276567aaSRichard Henderson flush_cond(dc); 26401ea9c62aSRichard Henderson 26411ea9c62aSRichard Henderson gen_compare(&cmp, a->cc, a->cond, dc); 26429d4e2bc7SRichard Henderson return advance_jump_cond(dc, &cmp, a->a, target); 2643276567aaSRichard Henderson } 2644276567aaSRichard Henderson } 2645276567aaSRichard Henderson 2646276567aaSRichard Henderson TRANS(Bicc, ALL, do_bpcc, a) 2647276567aaSRichard Henderson TRANS(BPcc, 64, do_bpcc, a) 2648276567aaSRichard Henderson 264945196ea4SRichard Henderson static bool do_fbpfcc(DisasContext *dc, arg_bcc *a) 265045196ea4SRichard Henderson { 265145196ea4SRichard Henderson target_long target = address_mask_i(dc, dc->pc + a->i * 4); 2652d5471936SRichard Henderson DisasCompare cmp; 265345196ea4SRichard Henderson 265445196ea4SRichard Henderson if (gen_trap_ifnofpu(dc)) { 265545196ea4SRichard Henderson return true; 265645196ea4SRichard Henderson } 265745196ea4SRichard Henderson switch (a->cond) { 265845196ea4SRichard Henderson case 0x0: 265945196ea4SRichard Henderson return advance_jump_uncond_never(dc, a->a); 266045196ea4SRichard Henderson case 0x8: 266145196ea4SRichard Henderson return advance_jump_uncond_always(dc, a->a, target); 266245196ea4SRichard Henderson default: 266345196ea4SRichard Henderson flush_cond(dc); 2664d5471936SRichard Henderson 2665d5471936SRichard Henderson gen_fcompare(&cmp, a->cc, a->cond); 26669d4e2bc7SRichard Henderson return advance_jump_cond(dc, &cmp, a->a, target); 266745196ea4SRichard Henderson } 266845196ea4SRichard Henderson } 266945196ea4SRichard Henderson 267045196ea4SRichard Henderson TRANS(FBPfcc, 64, do_fbpfcc, a) 267145196ea4SRichard Henderson TRANS(FBfcc, ALL, do_fbpfcc, a) 267245196ea4SRichard Henderson 2673ab9ffe98SRichard Henderson static bool trans_BPr(DisasContext *dc, arg_BPr *a) 2674ab9ffe98SRichard Henderson { 2675ab9ffe98SRichard Henderson target_long target = address_mask_i(dc, dc->pc + a->i * 4); 2676ab9ffe98SRichard Henderson DisasCompare cmp; 2677ab9ffe98SRichard Henderson 2678ab9ffe98SRichard Henderson if (!avail_64(dc)) { 2679ab9ffe98SRichard Henderson return false; 2680ab9ffe98SRichard Henderson } 2681ab9ffe98SRichard Henderson if (gen_tcg_cond_reg[a->cond] == TCG_COND_NEVER) { 2682ab9ffe98SRichard Henderson return false; 2683ab9ffe98SRichard Henderson } 2684ab9ffe98SRichard Henderson 2685ab9ffe98SRichard Henderson flush_cond(dc); 2686ab9ffe98SRichard Henderson gen_compare_reg(&cmp, a->cond, gen_load_gpr(dc, a->rs1)); 26879d4e2bc7SRichard Henderson return advance_jump_cond(dc, &cmp, a->a, target); 2688ab9ffe98SRichard Henderson } 2689ab9ffe98SRichard Henderson 269023ada1b1SRichard Henderson static bool trans_CALL(DisasContext *dc, arg_CALL *a) 269123ada1b1SRichard Henderson { 269223ada1b1SRichard Henderson target_long target = address_mask_i(dc, dc->pc + a->i * 4); 269323ada1b1SRichard Henderson 269423ada1b1SRichard Henderson gen_store_gpr(dc, 15, tcg_constant_tl(dc->pc)); 269523ada1b1SRichard Henderson gen_mov_pc_npc(dc); 269623ada1b1SRichard Henderson dc->npc = target; 269723ada1b1SRichard Henderson return true; 269823ada1b1SRichard Henderson } 269923ada1b1SRichard Henderson 270045196ea4SRichard Henderson static bool trans_NCP(DisasContext *dc, arg_NCP *a) 270145196ea4SRichard Henderson { 270245196ea4SRichard Henderson /* 270345196ea4SRichard Henderson * For sparc32, always generate the no-coprocessor exception. 270445196ea4SRichard Henderson * For sparc64, always generate illegal instruction. 270545196ea4SRichard Henderson */ 270645196ea4SRichard Henderson #ifdef TARGET_SPARC64 270745196ea4SRichard Henderson return false; 270845196ea4SRichard Henderson #else 270945196ea4SRichard Henderson gen_exception(dc, TT_NCP_INSN); 271045196ea4SRichard Henderson return true; 271145196ea4SRichard Henderson #endif 271245196ea4SRichard Henderson } 271345196ea4SRichard Henderson 27146d2a0768SRichard Henderson static bool trans_SETHI(DisasContext *dc, arg_SETHI *a) 27156d2a0768SRichard Henderson { 27166d2a0768SRichard Henderson /* Special-case %g0 because that's the canonical nop. */ 27176d2a0768SRichard Henderson if (a->rd) { 27186d2a0768SRichard Henderson gen_store_gpr(dc, a->rd, tcg_constant_tl((uint32_t)a->i << 10)); 27196d2a0768SRichard Henderson } 27206d2a0768SRichard Henderson return advance_pc(dc); 27216d2a0768SRichard Henderson } 27226d2a0768SRichard Henderson 27230faef01bSRichard Henderson /* 27240faef01bSRichard Henderson * Major Opcode 10 -- integer, floating-point, vis, and system insns. 27250faef01bSRichard Henderson */ 27260faef01bSRichard Henderson 272730376636SRichard Henderson static bool do_tcc(DisasContext *dc, int cond, int cc, 272830376636SRichard Henderson int rs1, bool imm, int rs2_or_imm) 272930376636SRichard Henderson { 273030376636SRichard Henderson int mask = ((dc->def->features & CPU_FEATURE_HYPV) && supervisor(dc) 273130376636SRichard Henderson ? UA2005_HTRAP_MASK : V8_TRAP_MASK); 273230376636SRichard Henderson DisasCompare cmp; 273330376636SRichard Henderson TCGLabel *lab; 273430376636SRichard Henderson TCGv_i32 trap; 273530376636SRichard Henderson 273630376636SRichard Henderson /* Trap never. */ 273730376636SRichard Henderson if (cond == 0) { 273830376636SRichard Henderson return advance_pc(dc); 273930376636SRichard Henderson } 274030376636SRichard Henderson 274130376636SRichard Henderson /* 274230376636SRichard Henderson * Immediate traps are the most common case. Since this value is 274330376636SRichard Henderson * live across the branch, it really pays to evaluate the constant. 274430376636SRichard Henderson */ 274530376636SRichard Henderson if (rs1 == 0 && (imm || rs2_or_imm == 0)) { 274630376636SRichard Henderson trap = tcg_constant_i32((rs2_or_imm & mask) + TT_TRAP); 274730376636SRichard Henderson } else { 274830376636SRichard Henderson trap = tcg_temp_new_i32(); 274930376636SRichard Henderson tcg_gen_trunc_tl_i32(trap, gen_load_gpr(dc, rs1)); 275030376636SRichard Henderson if (imm) { 275130376636SRichard Henderson tcg_gen_addi_i32(trap, trap, rs2_or_imm); 275230376636SRichard Henderson } else { 275330376636SRichard Henderson TCGv_i32 t2 = tcg_temp_new_i32(); 275430376636SRichard Henderson tcg_gen_trunc_tl_i32(t2, gen_load_gpr(dc, rs2_or_imm)); 275530376636SRichard Henderson tcg_gen_add_i32(trap, trap, t2); 275630376636SRichard Henderson } 275730376636SRichard Henderson tcg_gen_andi_i32(trap, trap, mask); 275830376636SRichard Henderson tcg_gen_addi_i32(trap, trap, TT_TRAP); 275930376636SRichard Henderson } 276030376636SRichard Henderson 276130376636SRichard Henderson /* Trap always. */ 276230376636SRichard Henderson if (cond == 8) { 276330376636SRichard Henderson save_state(dc); 276430376636SRichard Henderson gen_helper_raise_exception(tcg_env, trap); 276530376636SRichard Henderson dc->base.is_jmp = DISAS_NORETURN; 276630376636SRichard Henderson return true; 276730376636SRichard Henderson } 276830376636SRichard Henderson 276930376636SRichard Henderson /* Conditional trap. */ 277030376636SRichard Henderson flush_cond(dc); 277130376636SRichard Henderson lab = delay_exceptionv(dc, trap); 277230376636SRichard Henderson gen_compare(&cmp, cc, cond, dc); 277330376636SRichard Henderson tcg_gen_brcond_tl(cmp.cond, cmp.c1, cmp.c2, lab); 277430376636SRichard Henderson 277530376636SRichard Henderson return advance_pc(dc); 277630376636SRichard Henderson } 277730376636SRichard Henderson 277830376636SRichard Henderson static bool trans_Tcc_r(DisasContext *dc, arg_Tcc_r *a) 277930376636SRichard Henderson { 278030376636SRichard Henderson if (avail_32(dc) && a->cc) { 278130376636SRichard Henderson return false; 278230376636SRichard Henderson } 278330376636SRichard Henderson return do_tcc(dc, a->cond, a->cc, a->rs1, false, a->rs2); 278430376636SRichard Henderson } 278530376636SRichard Henderson 278630376636SRichard Henderson static bool trans_Tcc_i_v7(DisasContext *dc, arg_Tcc_i_v7 *a) 278730376636SRichard Henderson { 278830376636SRichard Henderson if (avail_64(dc)) { 278930376636SRichard Henderson return false; 279030376636SRichard Henderson } 279130376636SRichard Henderson return do_tcc(dc, a->cond, 0, a->rs1, true, a->i); 279230376636SRichard Henderson } 279330376636SRichard Henderson 279430376636SRichard Henderson static bool trans_Tcc_i_v9(DisasContext *dc, arg_Tcc_i_v9 *a) 279530376636SRichard Henderson { 279630376636SRichard Henderson if (avail_32(dc)) { 279730376636SRichard Henderson return false; 279830376636SRichard Henderson } 279930376636SRichard Henderson return do_tcc(dc, a->cond, a->cc, a->rs1, true, a->i); 280030376636SRichard Henderson } 280130376636SRichard Henderson 2802af25071cSRichard Henderson static bool trans_STBAR(DisasContext *dc, arg_STBAR *a) 2803af25071cSRichard Henderson { 2804af25071cSRichard Henderson tcg_gen_mb(TCG_MO_ST_ST | TCG_BAR_SC); 2805af25071cSRichard Henderson return advance_pc(dc); 2806af25071cSRichard Henderson } 2807af25071cSRichard Henderson 2808af25071cSRichard Henderson static bool trans_MEMBAR(DisasContext *dc, arg_MEMBAR *a) 2809af25071cSRichard Henderson { 2810af25071cSRichard Henderson if (avail_32(dc)) { 2811af25071cSRichard Henderson return false; 2812af25071cSRichard Henderson } 2813af25071cSRichard Henderson if (a->mmask) { 2814af25071cSRichard Henderson /* Note TCG_MO_* was modeled on sparc64, so mmask matches. */ 2815af25071cSRichard Henderson tcg_gen_mb(a->mmask | TCG_BAR_SC); 2816af25071cSRichard Henderson } 2817af25071cSRichard Henderson if (a->cmask) { 2818af25071cSRichard Henderson /* For #Sync, etc, end the TB to recognize interrupts. */ 2819af25071cSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 2820af25071cSRichard Henderson } 2821af25071cSRichard Henderson return advance_pc(dc); 2822af25071cSRichard Henderson } 2823af25071cSRichard Henderson 2824af25071cSRichard Henderson static bool do_rd_special(DisasContext *dc, bool priv, int rd, 2825af25071cSRichard Henderson TCGv (*func)(DisasContext *, TCGv)) 2826af25071cSRichard Henderson { 2827af25071cSRichard Henderson if (!priv) { 2828af25071cSRichard Henderson return raise_priv(dc); 2829af25071cSRichard Henderson } 2830af25071cSRichard Henderson gen_store_gpr(dc, rd, func(dc, gen_dest_gpr(dc, rd))); 2831af25071cSRichard Henderson return advance_pc(dc); 2832af25071cSRichard Henderson } 2833af25071cSRichard Henderson 2834af25071cSRichard Henderson static TCGv do_rdy(DisasContext *dc, TCGv dst) 2835af25071cSRichard Henderson { 2836af25071cSRichard Henderson return cpu_y; 2837af25071cSRichard Henderson } 2838af25071cSRichard Henderson 2839af25071cSRichard Henderson static bool trans_RDY(DisasContext *dc, arg_RDY *a) 2840af25071cSRichard Henderson { 2841af25071cSRichard Henderson /* 2842af25071cSRichard Henderson * TODO: Need a feature bit for sparcv8. In the meantime, treat all 2843af25071cSRichard Henderson * 32-bit cpus like sparcv7, which ignores the rs1 field. 2844af25071cSRichard Henderson * This matches after all other ASR, so Leon3 Asr17 is handled first. 2845af25071cSRichard Henderson */ 2846af25071cSRichard Henderson if (avail_64(dc) && a->rs1 != 0) { 2847af25071cSRichard Henderson return false; 2848af25071cSRichard Henderson } 2849af25071cSRichard Henderson return do_rd_special(dc, true, a->rd, do_rdy); 2850af25071cSRichard Henderson } 2851af25071cSRichard Henderson 2852af25071cSRichard Henderson static TCGv do_rd_leon3_config(DisasContext *dc, TCGv dst) 2853af25071cSRichard Henderson { 2854af25071cSRichard Henderson uint32_t val; 2855af25071cSRichard Henderson 2856af25071cSRichard Henderson /* 2857af25071cSRichard Henderson * TODO: There are many more fields to be filled, 2858af25071cSRichard Henderson * some of which are writable. 2859af25071cSRichard Henderson */ 2860af25071cSRichard Henderson val = dc->def->nwindows - 1; /* [4:0] NWIN */ 2861af25071cSRichard Henderson val |= 1 << 8; /* [8] V8 */ 2862af25071cSRichard Henderson 2863af25071cSRichard Henderson return tcg_constant_tl(val); 2864af25071cSRichard Henderson } 2865af25071cSRichard Henderson 2866af25071cSRichard Henderson TRANS(RDASR17, ASR17, do_rd_special, true, a->rd, do_rd_leon3_config) 2867af25071cSRichard Henderson 2868af25071cSRichard Henderson static TCGv do_rdccr(DisasContext *dc, TCGv dst) 2869af25071cSRichard Henderson { 2870af25071cSRichard Henderson update_psr(dc); 2871af25071cSRichard Henderson gen_helper_rdccr(dst, tcg_env); 2872af25071cSRichard Henderson return dst; 2873af25071cSRichard Henderson } 2874af25071cSRichard Henderson 2875af25071cSRichard Henderson TRANS(RDCCR, 64, do_rd_special, true, a->rd, do_rdccr) 2876af25071cSRichard Henderson 2877af25071cSRichard Henderson static TCGv do_rdasi(DisasContext *dc, TCGv dst) 2878af25071cSRichard Henderson { 2879af25071cSRichard Henderson #ifdef TARGET_SPARC64 2880af25071cSRichard Henderson return tcg_constant_tl(dc->asi); 2881af25071cSRichard Henderson #else 2882af25071cSRichard Henderson qemu_build_not_reached(); 2883af25071cSRichard Henderson #endif 2884af25071cSRichard Henderson } 2885af25071cSRichard Henderson 2886af25071cSRichard Henderson TRANS(RDASI, 64, do_rd_special, true, a->rd, do_rdasi) 2887af25071cSRichard Henderson 2888af25071cSRichard Henderson static TCGv do_rdtick(DisasContext *dc, TCGv dst) 2889af25071cSRichard Henderson { 2890af25071cSRichard Henderson TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 2891af25071cSRichard Henderson 2892af25071cSRichard Henderson tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(tick)); 2893af25071cSRichard Henderson if (translator_io_start(&dc->base)) { 2894af25071cSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 2895af25071cSRichard Henderson } 2896af25071cSRichard Henderson gen_helper_tick_get_count(dst, tcg_env, r_tickptr, 2897af25071cSRichard Henderson tcg_constant_i32(dc->mem_idx)); 2898af25071cSRichard Henderson return dst; 2899af25071cSRichard Henderson } 2900af25071cSRichard Henderson 2901af25071cSRichard Henderson /* TODO: non-priv access only allowed when enabled. */ 2902af25071cSRichard Henderson TRANS(RDTICK, 64, do_rd_special, true, a->rd, do_rdtick) 2903af25071cSRichard Henderson 2904af25071cSRichard Henderson static TCGv do_rdpc(DisasContext *dc, TCGv dst) 2905af25071cSRichard Henderson { 2906af25071cSRichard Henderson return tcg_constant_tl(address_mask_i(dc, dc->pc)); 2907af25071cSRichard Henderson } 2908af25071cSRichard Henderson 2909af25071cSRichard Henderson TRANS(RDPC, 64, do_rd_special, true, a->rd, do_rdpc) 2910af25071cSRichard Henderson 2911af25071cSRichard Henderson static TCGv do_rdfprs(DisasContext *dc, TCGv dst) 2912af25071cSRichard Henderson { 2913af25071cSRichard Henderson tcg_gen_ext_i32_tl(dst, cpu_fprs); 2914af25071cSRichard Henderson return dst; 2915af25071cSRichard Henderson } 2916af25071cSRichard Henderson 2917af25071cSRichard Henderson TRANS(RDFPRS, 64, do_rd_special, true, a->rd, do_rdfprs) 2918af25071cSRichard Henderson 2919af25071cSRichard Henderson static TCGv do_rdgsr(DisasContext *dc, TCGv dst) 2920af25071cSRichard Henderson { 2921af25071cSRichard Henderson gen_trap_ifnofpu(dc); 2922af25071cSRichard Henderson return cpu_gsr; 2923af25071cSRichard Henderson } 2924af25071cSRichard Henderson 2925af25071cSRichard Henderson TRANS(RDGSR, 64, do_rd_special, true, a->rd, do_rdgsr) 2926af25071cSRichard Henderson 2927af25071cSRichard Henderson static TCGv do_rdsoftint(DisasContext *dc, TCGv dst) 2928af25071cSRichard Henderson { 2929af25071cSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(softint)); 2930af25071cSRichard Henderson return dst; 2931af25071cSRichard Henderson } 2932af25071cSRichard Henderson 2933af25071cSRichard Henderson TRANS(RDSOFTINT, 64, do_rd_special, supervisor(dc), a->rd, do_rdsoftint) 2934af25071cSRichard Henderson 2935af25071cSRichard Henderson static TCGv do_rdtick_cmpr(DisasContext *dc, TCGv dst) 2936af25071cSRichard Henderson { 2937577efa45SRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(tick_cmpr)); 2938577efa45SRichard Henderson return dst; 2939af25071cSRichard Henderson } 2940af25071cSRichard Henderson 2941af25071cSRichard Henderson /* TODO: non-priv access only allowed when enabled. */ 2942af25071cSRichard Henderson TRANS(RDTICK_CMPR, 64, do_rd_special, true, a->rd, do_rdtick_cmpr) 2943af25071cSRichard Henderson 2944af25071cSRichard Henderson static TCGv do_rdstick(DisasContext *dc, TCGv dst) 2945af25071cSRichard Henderson { 2946af25071cSRichard Henderson TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 2947af25071cSRichard Henderson 2948af25071cSRichard Henderson tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(stick)); 2949af25071cSRichard Henderson if (translator_io_start(&dc->base)) { 2950af25071cSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 2951af25071cSRichard Henderson } 2952af25071cSRichard Henderson gen_helper_tick_get_count(dst, tcg_env, r_tickptr, 2953af25071cSRichard Henderson tcg_constant_i32(dc->mem_idx)); 2954af25071cSRichard Henderson return dst; 2955af25071cSRichard Henderson } 2956af25071cSRichard Henderson 2957af25071cSRichard Henderson /* TODO: non-priv access only allowed when enabled. */ 2958af25071cSRichard Henderson TRANS(RDSTICK, 64, do_rd_special, true, a->rd, do_rdstick) 2959af25071cSRichard Henderson 2960af25071cSRichard Henderson static TCGv do_rdstick_cmpr(DisasContext *dc, TCGv dst) 2961af25071cSRichard Henderson { 2962577efa45SRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(stick_cmpr)); 2963577efa45SRichard Henderson return dst; 2964af25071cSRichard Henderson } 2965af25071cSRichard Henderson 2966af25071cSRichard Henderson /* TODO: supervisor access only allowed when enabled by hypervisor. */ 2967af25071cSRichard Henderson TRANS(RDSTICK_CMPR, 64, do_rd_special, supervisor(dc), a->rd, do_rdstick_cmpr) 2968af25071cSRichard Henderson 2969af25071cSRichard Henderson /* 2970af25071cSRichard Henderson * UltraSPARC-T1 Strand status. 2971af25071cSRichard Henderson * HYPV check maybe not enough, UA2005 & UA2007 describe 2972af25071cSRichard Henderson * this ASR as impl. dep 2973af25071cSRichard Henderson */ 2974af25071cSRichard Henderson static TCGv do_rdstrand_status(DisasContext *dc, TCGv dst) 2975af25071cSRichard Henderson { 2976af25071cSRichard Henderson return tcg_constant_tl(1); 2977af25071cSRichard Henderson } 2978af25071cSRichard Henderson 2979af25071cSRichard Henderson TRANS(RDSTRAND_STATUS, HYPV, do_rd_special, true, a->rd, do_rdstrand_status) 2980af25071cSRichard Henderson 2981668bb9b7SRichard Henderson static TCGv do_rdpsr(DisasContext *dc, TCGv dst) 2982668bb9b7SRichard Henderson { 2983668bb9b7SRichard Henderson update_psr(dc); 2984668bb9b7SRichard Henderson gen_helper_rdpsr(dst, tcg_env); 2985668bb9b7SRichard Henderson return dst; 2986668bb9b7SRichard Henderson } 2987668bb9b7SRichard Henderson 2988668bb9b7SRichard Henderson TRANS(RDPSR, 32, do_rd_special, supervisor(dc), a->rd, do_rdpsr) 2989668bb9b7SRichard Henderson 2990668bb9b7SRichard Henderson static TCGv do_rdhpstate(DisasContext *dc, TCGv dst) 2991668bb9b7SRichard Henderson { 2992668bb9b7SRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hpstate)); 2993668bb9b7SRichard Henderson return dst; 2994668bb9b7SRichard Henderson } 2995668bb9b7SRichard Henderson 2996668bb9b7SRichard Henderson TRANS(RDHPR_hpstate, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhpstate) 2997668bb9b7SRichard Henderson 2998668bb9b7SRichard Henderson static TCGv do_rdhtstate(DisasContext *dc, TCGv dst) 2999668bb9b7SRichard Henderson { 3000668bb9b7SRichard Henderson TCGv_i32 tl = tcg_temp_new_i32(); 3001668bb9b7SRichard Henderson TCGv_ptr tp = tcg_temp_new_ptr(); 3002668bb9b7SRichard Henderson 3003668bb9b7SRichard Henderson tcg_gen_ld_i32(tl, tcg_env, env64_field_offsetof(tl)); 3004668bb9b7SRichard Henderson tcg_gen_andi_i32(tl, tl, MAXTL_MASK); 3005668bb9b7SRichard Henderson tcg_gen_shli_i32(tl, tl, 3); 3006668bb9b7SRichard Henderson tcg_gen_ext_i32_ptr(tp, tl); 3007668bb9b7SRichard Henderson tcg_gen_add_ptr(tp, tp, tcg_env); 3008668bb9b7SRichard Henderson 3009668bb9b7SRichard Henderson tcg_gen_ld_tl(dst, tp, env64_field_offsetof(htstate)); 3010668bb9b7SRichard Henderson return dst; 3011668bb9b7SRichard Henderson } 3012668bb9b7SRichard Henderson 3013668bb9b7SRichard Henderson TRANS(RDHPR_htstate, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhtstate) 3014668bb9b7SRichard Henderson 3015668bb9b7SRichard Henderson static TCGv do_rdhintp(DisasContext *dc, TCGv dst) 3016668bb9b7SRichard Henderson { 30172da789deSRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hintp)); 30182da789deSRichard Henderson return dst; 3019668bb9b7SRichard Henderson } 3020668bb9b7SRichard Henderson 3021668bb9b7SRichard Henderson TRANS(RDHPR_hintp, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhintp) 3022668bb9b7SRichard Henderson 3023668bb9b7SRichard Henderson static TCGv do_rdhtba(DisasContext *dc, TCGv dst) 3024668bb9b7SRichard Henderson { 30252da789deSRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(htba)); 30262da789deSRichard Henderson return dst; 3027668bb9b7SRichard Henderson } 3028668bb9b7SRichard Henderson 3029668bb9b7SRichard Henderson TRANS(RDHPR_htba, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhtba) 3030668bb9b7SRichard Henderson 3031668bb9b7SRichard Henderson static TCGv do_rdhver(DisasContext *dc, TCGv dst) 3032668bb9b7SRichard Henderson { 30332da789deSRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hver)); 30342da789deSRichard Henderson return dst; 3035668bb9b7SRichard Henderson } 3036668bb9b7SRichard Henderson 3037668bb9b7SRichard Henderson TRANS(RDHPR_hver, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhver) 3038668bb9b7SRichard Henderson 3039668bb9b7SRichard Henderson static TCGv do_rdhstick_cmpr(DisasContext *dc, TCGv dst) 3040668bb9b7SRichard Henderson { 3041577efa45SRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hstick_cmpr)); 3042577efa45SRichard Henderson return dst; 3043668bb9b7SRichard Henderson } 3044668bb9b7SRichard Henderson 3045668bb9b7SRichard Henderson TRANS(RDHPR_hstick_cmpr, HYPV, do_rd_special, hypervisor(dc), a->rd, 3046668bb9b7SRichard Henderson do_rdhstick_cmpr) 3047668bb9b7SRichard Henderson 30485d617bfbSRichard Henderson static TCGv do_rdwim(DisasContext *dc, TCGv dst) 30495d617bfbSRichard Henderson { 3050cd6269f7SRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env32_field_offsetof(wim)); 3051cd6269f7SRichard Henderson return dst; 30525d617bfbSRichard Henderson } 30535d617bfbSRichard Henderson 30545d617bfbSRichard Henderson TRANS(RDWIM, 32, do_rd_special, supervisor(dc), a->rd, do_rdwim) 30555d617bfbSRichard Henderson 30565d617bfbSRichard Henderson static TCGv do_rdtpc(DisasContext *dc, TCGv dst) 30575d617bfbSRichard Henderson { 30585d617bfbSRichard Henderson #ifdef TARGET_SPARC64 30595d617bfbSRichard Henderson TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 30605d617bfbSRichard Henderson 30615d617bfbSRichard Henderson gen_load_trap_state_at_tl(r_tsptr); 30625d617bfbSRichard Henderson tcg_gen_ld_tl(dst, r_tsptr, offsetof(trap_state, tpc)); 30635d617bfbSRichard Henderson return dst; 30645d617bfbSRichard Henderson #else 30655d617bfbSRichard Henderson qemu_build_not_reached(); 30665d617bfbSRichard Henderson #endif 30675d617bfbSRichard Henderson } 30685d617bfbSRichard Henderson 30695d617bfbSRichard Henderson TRANS(RDPR_tpc, 64, do_rd_special, supervisor(dc), a->rd, do_rdtpc) 30705d617bfbSRichard Henderson 30715d617bfbSRichard Henderson static TCGv do_rdtnpc(DisasContext *dc, TCGv dst) 30725d617bfbSRichard Henderson { 30735d617bfbSRichard Henderson #ifdef TARGET_SPARC64 30745d617bfbSRichard Henderson TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 30755d617bfbSRichard Henderson 30765d617bfbSRichard Henderson gen_load_trap_state_at_tl(r_tsptr); 30775d617bfbSRichard Henderson tcg_gen_ld_tl(dst, r_tsptr, offsetof(trap_state, tnpc)); 30785d617bfbSRichard Henderson return dst; 30795d617bfbSRichard Henderson #else 30805d617bfbSRichard Henderson qemu_build_not_reached(); 30815d617bfbSRichard Henderson #endif 30825d617bfbSRichard Henderson } 30835d617bfbSRichard Henderson 30845d617bfbSRichard Henderson TRANS(RDPR_tnpc, 64, do_rd_special, supervisor(dc), a->rd, do_rdtnpc) 30855d617bfbSRichard Henderson 30865d617bfbSRichard Henderson static TCGv do_rdtstate(DisasContext *dc, TCGv dst) 30875d617bfbSRichard Henderson { 30885d617bfbSRichard Henderson #ifdef TARGET_SPARC64 30895d617bfbSRichard Henderson TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 30905d617bfbSRichard Henderson 30915d617bfbSRichard Henderson gen_load_trap_state_at_tl(r_tsptr); 30925d617bfbSRichard Henderson tcg_gen_ld_tl(dst, r_tsptr, offsetof(trap_state, tstate)); 30935d617bfbSRichard Henderson return dst; 30945d617bfbSRichard Henderson #else 30955d617bfbSRichard Henderson qemu_build_not_reached(); 30965d617bfbSRichard Henderson #endif 30975d617bfbSRichard Henderson } 30985d617bfbSRichard Henderson 30995d617bfbSRichard Henderson TRANS(RDPR_tstate, 64, do_rd_special, supervisor(dc), a->rd, do_rdtstate) 31005d617bfbSRichard Henderson 31015d617bfbSRichard Henderson static TCGv do_rdtt(DisasContext *dc, TCGv dst) 31025d617bfbSRichard Henderson { 31035d617bfbSRichard Henderson #ifdef TARGET_SPARC64 31045d617bfbSRichard Henderson TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 31055d617bfbSRichard Henderson 31065d617bfbSRichard Henderson gen_load_trap_state_at_tl(r_tsptr); 31075d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, r_tsptr, offsetof(trap_state, tt)); 31085d617bfbSRichard Henderson return dst; 31095d617bfbSRichard Henderson #else 31105d617bfbSRichard Henderson qemu_build_not_reached(); 31115d617bfbSRichard Henderson #endif 31125d617bfbSRichard Henderson } 31135d617bfbSRichard Henderson 31145d617bfbSRichard Henderson TRANS(RDPR_tt, 64, do_rd_special, supervisor(dc), a->rd, do_rdtt) 31155d617bfbSRichard Henderson TRANS(RDPR_tick, 64, do_rd_special, supervisor(dc), a->rd, do_rdtick) 31165d617bfbSRichard Henderson 31175d617bfbSRichard Henderson static TCGv do_rdtba(DisasContext *dc, TCGv dst) 31185d617bfbSRichard Henderson { 31195d617bfbSRichard Henderson return cpu_tbr; 31205d617bfbSRichard Henderson } 31215d617bfbSRichard Henderson 3122e8325dc0SRichard Henderson TRANS(RDTBR, 32, do_rd_special, supervisor(dc), a->rd, do_rdtba) 31235d617bfbSRichard Henderson TRANS(RDPR_tba, 64, do_rd_special, supervisor(dc), a->rd, do_rdtba) 31245d617bfbSRichard Henderson 31255d617bfbSRichard Henderson static TCGv do_rdpstate(DisasContext *dc, TCGv dst) 31265d617bfbSRichard Henderson { 31275d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(pstate)); 31285d617bfbSRichard Henderson return dst; 31295d617bfbSRichard Henderson } 31305d617bfbSRichard Henderson 31315d617bfbSRichard Henderson TRANS(RDPR_pstate, 64, do_rd_special, supervisor(dc), a->rd, do_rdpstate) 31325d617bfbSRichard Henderson 31335d617bfbSRichard Henderson static TCGv do_rdtl(DisasContext *dc, TCGv dst) 31345d617bfbSRichard Henderson { 31355d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(tl)); 31365d617bfbSRichard Henderson return dst; 31375d617bfbSRichard Henderson } 31385d617bfbSRichard Henderson 31395d617bfbSRichard Henderson TRANS(RDPR_tl, 64, do_rd_special, supervisor(dc), a->rd, do_rdtl) 31405d617bfbSRichard Henderson 31415d617bfbSRichard Henderson static TCGv do_rdpil(DisasContext *dc, TCGv dst) 31425d617bfbSRichard Henderson { 31435d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env_field_offsetof(psrpil)); 31445d617bfbSRichard Henderson return dst; 31455d617bfbSRichard Henderson } 31465d617bfbSRichard Henderson 31475d617bfbSRichard Henderson TRANS(RDPR_pil, 64, do_rd_special, supervisor(dc), a->rd, do_rdpil) 31485d617bfbSRichard Henderson 31495d617bfbSRichard Henderson static TCGv do_rdcwp(DisasContext *dc, TCGv dst) 31505d617bfbSRichard Henderson { 31515d617bfbSRichard Henderson gen_helper_rdcwp(dst, tcg_env); 31525d617bfbSRichard Henderson return dst; 31535d617bfbSRichard Henderson } 31545d617bfbSRichard Henderson 31555d617bfbSRichard Henderson TRANS(RDPR_cwp, 64, do_rd_special, supervisor(dc), a->rd, do_rdcwp) 31565d617bfbSRichard Henderson 31575d617bfbSRichard Henderson static TCGv do_rdcansave(DisasContext *dc, TCGv dst) 31585d617bfbSRichard Henderson { 31595d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(cansave)); 31605d617bfbSRichard Henderson return dst; 31615d617bfbSRichard Henderson } 31625d617bfbSRichard Henderson 31635d617bfbSRichard Henderson TRANS(RDPR_cansave, 64, do_rd_special, supervisor(dc), a->rd, do_rdcansave) 31645d617bfbSRichard Henderson 31655d617bfbSRichard Henderson static TCGv do_rdcanrestore(DisasContext *dc, TCGv dst) 31665d617bfbSRichard Henderson { 31675d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(canrestore)); 31685d617bfbSRichard Henderson return dst; 31695d617bfbSRichard Henderson } 31705d617bfbSRichard Henderson 31715d617bfbSRichard Henderson TRANS(RDPR_canrestore, 64, do_rd_special, supervisor(dc), a->rd, 31725d617bfbSRichard Henderson do_rdcanrestore) 31735d617bfbSRichard Henderson 31745d617bfbSRichard Henderson static TCGv do_rdcleanwin(DisasContext *dc, TCGv dst) 31755d617bfbSRichard Henderson { 31765d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(cleanwin)); 31775d617bfbSRichard Henderson return dst; 31785d617bfbSRichard Henderson } 31795d617bfbSRichard Henderson 31805d617bfbSRichard Henderson TRANS(RDPR_cleanwin, 64, do_rd_special, supervisor(dc), a->rd, do_rdcleanwin) 31815d617bfbSRichard Henderson 31825d617bfbSRichard Henderson static TCGv do_rdotherwin(DisasContext *dc, TCGv dst) 31835d617bfbSRichard Henderson { 31845d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(otherwin)); 31855d617bfbSRichard Henderson return dst; 31865d617bfbSRichard Henderson } 31875d617bfbSRichard Henderson 31885d617bfbSRichard Henderson TRANS(RDPR_otherwin, 64, do_rd_special, supervisor(dc), a->rd, do_rdotherwin) 31895d617bfbSRichard Henderson 31905d617bfbSRichard Henderson static TCGv do_rdwstate(DisasContext *dc, TCGv dst) 31915d617bfbSRichard Henderson { 31925d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(wstate)); 31935d617bfbSRichard Henderson return dst; 31945d617bfbSRichard Henderson } 31955d617bfbSRichard Henderson 31965d617bfbSRichard Henderson TRANS(RDPR_wstate, 64, do_rd_special, supervisor(dc), a->rd, do_rdwstate) 31975d617bfbSRichard Henderson 31985d617bfbSRichard Henderson static TCGv do_rdgl(DisasContext *dc, TCGv dst) 31995d617bfbSRichard Henderson { 32005d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(gl)); 32015d617bfbSRichard Henderson return dst; 32025d617bfbSRichard Henderson } 32035d617bfbSRichard Henderson 32045d617bfbSRichard Henderson TRANS(RDPR_gl, GL, do_rd_special, supervisor(dc), a->rd, do_rdgl) 32055d617bfbSRichard Henderson 32065d617bfbSRichard Henderson /* UA2005 strand status */ 32075d617bfbSRichard Henderson static TCGv do_rdssr(DisasContext *dc, TCGv dst) 32085d617bfbSRichard Henderson { 32092da789deSRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(ssr)); 32102da789deSRichard Henderson return dst; 32115d617bfbSRichard Henderson } 32125d617bfbSRichard Henderson 32135d617bfbSRichard Henderson TRANS(RDPR_strand_status, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdssr) 32145d617bfbSRichard Henderson 32155d617bfbSRichard Henderson static TCGv do_rdver(DisasContext *dc, TCGv dst) 32165d617bfbSRichard Henderson { 32172da789deSRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(version)); 32182da789deSRichard Henderson return dst; 32195d617bfbSRichard Henderson } 32205d617bfbSRichard Henderson 32215d617bfbSRichard Henderson TRANS(RDPR_ver, 64, do_rd_special, supervisor(dc), a->rd, do_rdver) 32225d617bfbSRichard Henderson 3223e8325dc0SRichard Henderson static bool trans_FLUSHW(DisasContext *dc, arg_FLUSHW *a) 3224e8325dc0SRichard Henderson { 3225e8325dc0SRichard Henderson if (avail_64(dc)) { 3226e8325dc0SRichard Henderson gen_helper_flushw(tcg_env); 3227e8325dc0SRichard Henderson return advance_pc(dc); 3228e8325dc0SRichard Henderson } 3229e8325dc0SRichard Henderson return false; 3230e8325dc0SRichard Henderson } 3231e8325dc0SRichard Henderson 32320faef01bSRichard Henderson static bool do_wr_special(DisasContext *dc, arg_r_r_ri *a, bool priv, 32330faef01bSRichard Henderson void (*func)(DisasContext *, TCGv)) 32340faef01bSRichard Henderson { 32350faef01bSRichard Henderson TCGv src; 32360faef01bSRichard Henderson 32370faef01bSRichard Henderson /* For simplicity, we under-decoded the rs2 form. */ 32380faef01bSRichard Henderson if (!a->imm && (a->rs2_or_imm & ~0x1f)) { 32390faef01bSRichard Henderson return false; 32400faef01bSRichard Henderson } 32410faef01bSRichard Henderson if (!priv) { 32420faef01bSRichard Henderson return raise_priv(dc); 32430faef01bSRichard Henderson } 32440faef01bSRichard Henderson 32450faef01bSRichard Henderson if (a->rs1 == 0 && (a->imm || a->rs2_or_imm == 0)) { 32460faef01bSRichard Henderson src = tcg_constant_tl(a->rs2_or_imm); 32470faef01bSRichard Henderson } else { 32480faef01bSRichard Henderson TCGv src1 = gen_load_gpr(dc, a->rs1); 32490faef01bSRichard Henderson if (a->rs2_or_imm == 0) { 32500faef01bSRichard Henderson src = src1; 32510faef01bSRichard Henderson } else { 32520faef01bSRichard Henderson src = tcg_temp_new(); 32530faef01bSRichard Henderson if (a->imm) { 32540faef01bSRichard Henderson tcg_gen_xori_tl(src, src1, a->rs2_or_imm); 32550faef01bSRichard Henderson } else { 32560faef01bSRichard Henderson tcg_gen_xor_tl(src, src1, gen_load_gpr(dc, a->rs2_or_imm)); 32570faef01bSRichard Henderson } 32580faef01bSRichard Henderson } 32590faef01bSRichard Henderson } 32600faef01bSRichard Henderson func(dc, src); 32610faef01bSRichard Henderson return advance_pc(dc); 32620faef01bSRichard Henderson } 32630faef01bSRichard Henderson 32640faef01bSRichard Henderson static void do_wry(DisasContext *dc, TCGv src) 32650faef01bSRichard Henderson { 32660faef01bSRichard Henderson tcg_gen_ext32u_tl(cpu_y, src); 32670faef01bSRichard Henderson } 32680faef01bSRichard Henderson 32690faef01bSRichard Henderson TRANS(WRY, ALL, do_wr_special, a, true, do_wry) 32700faef01bSRichard Henderson 32710faef01bSRichard Henderson static void do_wrccr(DisasContext *dc, TCGv src) 32720faef01bSRichard Henderson { 32730faef01bSRichard Henderson gen_helper_wrccr(tcg_env, src); 32740faef01bSRichard Henderson } 32750faef01bSRichard Henderson 32760faef01bSRichard Henderson TRANS(WRCCR, 64, do_wr_special, a, true, do_wrccr) 32770faef01bSRichard Henderson 32780faef01bSRichard Henderson static void do_wrasi(DisasContext *dc, TCGv src) 32790faef01bSRichard Henderson { 32800faef01bSRichard Henderson TCGv tmp = tcg_temp_new(); 32810faef01bSRichard Henderson 32820faef01bSRichard Henderson tcg_gen_ext8u_tl(tmp, src); 32830faef01bSRichard Henderson tcg_gen_st32_tl(tmp, tcg_env, env64_field_offsetof(asi)); 32840faef01bSRichard Henderson /* End TB to notice changed ASI. */ 32850faef01bSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 32860faef01bSRichard Henderson } 32870faef01bSRichard Henderson 32880faef01bSRichard Henderson TRANS(WRASI, 64, do_wr_special, a, true, do_wrasi) 32890faef01bSRichard Henderson 32900faef01bSRichard Henderson static void do_wrfprs(DisasContext *dc, TCGv src) 32910faef01bSRichard Henderson { 32920faef01bSRichard Henderson #ifdef TARGET_SPARC64 32930faef01bSRichard Henderson tcg_gen_trunc_tl_i32(cpu_fprs, src); 32940faef01bSRichard Henderson dc->fprs_dirty = 0; 32950faef01bSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 32960faef01bSRichard Henderson #else 32970faef01bSRichard Henderson qemu_build_not_reached(); 32980faef01bSRichard Henderson #endif 32990faef01bSRichard Henderson } 33000faef01bSRichard Henderson 33010faef01bSRichard Henderson TRANS(WRFPRS, 64, do_wr_special, a, true, do_wrfprs) 33020faef01bSRichard Henderson 33030faef01bSRichard Henderson static void do_wrgsr(DisasContext *dc, TCGv src) 33040faef01bSRichard Henderson { 33050faef01bSRichard Henderson gen_trap_ifnofpu(dc); 33060faef01bSRichard Henderson tcg_gen_mov_tl(cpu_gsr, src); 33070faef01bSRichard Henderson } 33080faef01bSRichard Henderson 33090faef01bSRichard Henderson TRANS(WRGSR, 64, do_wr_special, a, true, do_wrgsr) 33100faef01bSRichard Henderson 33110faef01bSRichard Henderson static void do_wrsoftint_set(DisasContext *dc, TCGv src) 33120faef01bSRichard Henderson { 33130faef01bSRichard Henderson gen_helper_set_softint(tcg_env, src); 33140faef01bSRichard Henderson } 33150faef01bSRichard Henderson 33160faef01bSRichard Henderson TRANS(WRSOFTINT_SET, 64, do_wr_special, a, supervisor(dc), do_wrsoftint_set) 33170faef01bSRichard Henderson 33180faef01bSRichard Henderson static void do_wrsoftint_clr(DisasContext *dc, TCGv src) 33190faef01bSRichard Henderson { 33200faef01bSRichard Henderson gen_helper_clear_softint(tcg_env, src); 33210faef01bSRichard Henderson } 33220faef01bSRichard Henderson 33230faef01bSRichard Henderson TRANS(WRSOFTINT_CLR, 64, do_wr_special, a, supervisor(dc), do_wrsoftint_clr) 33240faef01bSRichard Henderson 33250faef01bSRichard Henderson static void do_wrsoftint(DisasContext *dc, TCGv src) 33260faef01bSRichard Henderson { 33270faef01bSRichard Henderson gen_helper_write_softint(tcg_env, src); 33280faef01bSRichard Henderson } 33290faef01bSRichard Henderson 33300faef01bSRichard Henderson TRANS(WRSOFTINT, 64, do_wr_special, a, supervisor(dc), do_wrsoftint) 33310faef01bSRichard Henderson 33320faef01bSRichard Henderson static void do_wrtick_cmpr(DisasContext *dc, TCGv src) 33330faef01bSRichard Henderson { 33340faef01bSRichard Henderson TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 33350faef01bSRichard Henderson 3336577efa45SRichard Henderson tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(tick_cmpr)); 3337577efa45SRichard Henderson tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(tick)); 33380faef01bSRichard Henderson translator_io_start(&dc->base); 3339577efa45SRichard Henderson gen_helper_tick_set_limit(r_tickptr, src); 33400faef01bSRichard Henderson /* End TB to handle timer interrupt */ 33410faef01bSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 33420faef01bSRichard Henderson } 33430faef01bSRichard Henderson 33440faef01bSRichard Henderson TRANS(WRTICK_CMPR, 64, do_wr_special, a, supervisor(dc), do_wrtick_cmpr) 33450faef01bSRichard Henderson 33460faef01bSRichard Henderson static void do_wrstick(DisasContext *dc, TCGv src) 33470faef01bSRichard Henderson { 33480faef01bSRichard Henderson #ifdef TARGET_SPARC64 33490faef01bSRichard Henderson TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 33500faef01bSRichard Henderson 33510faef01bSRichard Henderson tcg_gen_ld_ptr(r_tickptr, tcg_env, offsetof(CPUSPARCState, stick)); 33520faef01bSRichard Henderson translator_io_start(&dc->base); 33530faef01bSRichard Henderson gen_helper_tick_set_count(r_tickptr, src); 33540faef01bSRichard Henderson /* End TB to handle timer interrupt */ 33550faef01bSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 33560faef01bSRichard Henderson #else 33570faef01bSRichard Henderson qemu_build_not_reached(); 33580faef01bSRichard Henderson #endif 33590faef01bSRichard Henderson } 33600faef01bSRichard Henderson 33610faef01bSRichard Henderson TRANS(WRSTICK, 64, do_wr_special, a, supervisor(dc), do_wrstick) 33620faef01bSRichard Henderson 33630faef01bSRichard Henderson static void do_wrstick_cmpr(DisasContext *dc, TCGv src) 33640faef01bSRichard Henderson { 33650faef01bSRichard Henderson TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 33660faef01bSRichard Henderson 3367577efa45SRichard Henderson tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(stick_cmpr)); 3368577efa45SRichard Henderson tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(stick)); 33690faef01bSRichard Henderson translator_io_start(&dc->base); 3370577efa45SRichard Henderson gen_helper_tick_set_limit(r_tickptr, src); 33710faef01bSRichard Henderson /* End TB to handle timer interrupt */ 33720faef01bSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 33730faef01bSRichard Henderson } 33740faef01bSRichard Henderson 33750faef01bSRichard Henderson TRANS(WRSTICK_CMPR, 64, do_wr_special, a, supervisor(dc), do_wrstick_cmpr) 33760faef01bSRichard Henderson 33770faef01bSRichard Henderson static void do_wrpowerdown(DisasContext *dc, TCGv src) 33780faef01bSRichard Henderson { 33790faef01bSRichard Henderson save_state(dc); 33800faef01bSRichard Henderson gen_helper_power_down(tcg_env); 33810faef01bSRichard Henderson } 33820faef01bSRichard Henderson 33830faef01bSRichard Henderson TRANS(WRPOWERDOWN, POWERDOWN, do_wr_special, a, supervisor(dc), do_wrpowerdown) 33840faef01bSRichard Henderson 338525524734SRichard Henderson static void do_wrpsr(DisasContext *dc, TCGv src) 338625524734SRichard Henderson { 338725524734SRichard Henderson gen_helper_wrpsr(tcg_env, src); 338825524734SRichard Henderson tcg_gen_movi_i32(cpu_cc_op, CC_OP_FLAGS); 338925524734SRichard Henderson dc->cc_op = CC_OP_FLAGS; 339025524734SRichard Henderson dc->base.is_jmp = DISAS_EXIT; 339125524734SRichard Henderson } 339225524734SRichard Henderson 339325524734SRichard Henderson TRANS(WRPSR, 32, do_wr_special, a, supervisor(dc), do_wrpsr) 339425524734SRichard Henderson 33959422278eSRichard Henderson static void do_wrwim(DisasContext *dc, TCGv src) 33969422278eSRichard Henderson { 33979422278eSRichard Henderson target_ulong mask = MAKE_64BIT_MASK(0, dc->def->nwindows); 3398cd6269f7SRichard Henderson TCGv tmp = tcg_temp_new(); 3399cd6269f7SRichard Henderson 3400cd6269f7SRichard Henderson tcg_gen_andi_tl(tmp, src, mask); 3401cd6269f7SRichard Henderson tcg_gen_st_tl(tmp, tcg_env, env32_field_offsetof(wim)); 34029422278eSRichard Henderson } 34039422278eSRichard Henderson 34049422278eSRichard Henderson TRANS(WRWIM, 32, do_wr_special, a, supervisor(dc), do_wrwim) 34059422278eSRichard Henderson 34069422278eSRichard Henderson static void do_wrtpc(DisasContext *dc, TCGv src) 34079422278eSRichard Henderson { 34089422278eSRichard Henderson #ifdef TARGET_SPARC64 34099422278eSRichard Henderson TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 34109422278eSRichard Henderson 34119422278eSRichard Henderson gen_load_trap_state_at_tl(r_tsptr); 34129422278eSRichard Henderson tcg_gen_st_tl(src, r_tsptr, offsetof(trap_state, tpc)); 34139422278eSRichard Henderson #else 34149422278eSRichard Henderson qemu_build_not_reached(); 34159422278eSRichard Henderson #endif 34169422278eSRichard Henderson } 34179422278eSRichard Henderson 34189422278eSRichard Henderson TRANS(WRPR_tpc, 64, do_wr_special, a, supervisor(dc), do_wrtpc) 34199422278eSRichard Henderson 34209422278eSRichard Henderson static void do_wrtnpc(DisasContext *dc, TCGv src) 34219422278eSRichard Henderson { 34229422278eSRichard Henderson #ifdef TARGET_SPARC64 34239422278eSRichard Henderson TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 34249422278eSRichard Henderson 34259422278eSRichard Henderson gen_load_trap_state_at_tl(r_tsptr); 34269422278eSRichard Henderson tcg_gen_st_tl(src, r_tsptr, offsetof(trap_state, tnpc)); 34279422278eSRichard Henderson #else 34289422278eSRichard Henderson qemu_build_not_reached(); 34299422278eSRichard Henderson #endif 34309422278eSRichard Henderson } 34319422278eSRichard Henderson 34329422278eSRichard Henderson TRANS(WRPR_tnpc, 64, do_wr_special, a, supervisor(dc), do_wrtnpc) 34339422278eSRichard Henderson 34349422278eSRichard Henderson static void do_wrtstate(DisasContext *dc, TCGv src) 34359422278eSRichard Henderson { 34369422278eSRichard Henderson #ifdef TARGET_SPARC64 34379422278eSRichard Henderson TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 34389422278eSRichard Henderson 34399422278eSRichard Henderson gen_load_trap_state_at_tl(r_tsptr); 34409422278eSRichard Henderson tcg_gen_st_tl(src, r_tsptr, offsetof(trap_state, tstate)); 34419422278eSRichard Henderson #else 34429422278eSRichard Henderson qemu_build_not_reached(); 34439422278eSRichard Henderson #endif 34449422278eSRichard Henderson } 34459422278eSRichard Henderson 34469422278eSRichard Henderson TRANS(WRPR_tstate, 64, do_wr_special, a, supervisor(dc), do_wrtstate) 34479422278eSRichard Henderson 34489422278eSRichard Henderson static void do_wrtt(DisasContext *dc, TCGv src) 34499422278eSRichard Henderson { 34509422278eSRichard Henderson #ifdef TARGET_SPARC64 34519422278eSRichard Henderson TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 34529422278eSRichard Henderson 34539422278eSRichard Henderson gen_load_trap_state_at_tl(r_tsptr); 34549422278eSRichard Henderson tcg_gen_st32_tl(src, r_tsptr, offsetof(trap_state, tt)); 34559422278eSRichard Henderson #else 34569422278eSRichard Henderson qemu_build_not_reached(); 34579422278eSRichard Henderson #endif 34589422278eSRichard Henderson } 34599422278eSRichard Henderson 34609422278eSRichard Henderson TRANS(WRPR_tt, 64, do_wr_special, a, supervisor(dc), do_wrtt) 34619422278eSRichard Henderson 34629422278eSRichard Henderson static void do_wrtick(DisasContext *dc, TCGv src) 34639422278eSRichard Henderson { 34649422278eSRichard Henderson TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 34659422278eSRichard Henderson 34669422278eSRichard Henderson tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(tick)); 34679422278eSRichard Henderson translator_io_start(&dc->base); 34689422278eSRichard Henderson gen_helper_tick_set_count(r_tickptr, src); 34699422278eSRichard Henderson /* End TB to handle timer interrupt */ 34709422278eSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 34719422278eSRichard Henderson } 34729422278eSRichard Henderson 34739422278eSRichard Henderson TRANS(WRPR_tick, 64, do_wr_special, a, supervisor(dc), do_wrtick) 34749422278eSRichard Henderson 34759422278eSRichard Henderson static void do_wrtba(DisasContext *dc, TCGv src) 34769422278eSRichard Henderson { 34779422278eSRichard Henderson tcg_gen_mov_tl(cpu_tbr, src); 34789422278eSRichard Henderson } 34799422278eSRichard Henderson 34809422278eSRichard Henderson TRANS(WRPR_tba, 64, do_wr_special, a, supervisor(dc), do_wrtba) 34819422278eSRichard Henderson 34829422278eSRichard Henderson static void do_wrpstate(DisasContext *dc, TCGv src) 34839422278eSRichard Henderson { 34849422278eSRichard Henderson save_state(dc); 34859422278eSRichard Henderson if (translator_io_start(&dc->base)) { 34869422278eSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 34879422278eSRichard Henderson } 34889422278eSRichard Henderson gen_helper_wrpstate(tcg_env, src); 34899422278eSRichard Henderson dc->npc = DYNAMIC_PC; 34909422278eSRichard Henderson } 34919422278eSRichard Henderson 34929422278eSRichard Henderson TRANS(WRPR_pstate, 64, do_wr_special, a, supervisor(dc), do_wrpstate) 34939422278eSRichard Henderson 34949422278eSRichard Henderson static void do_wrtl(DisasContext *dc, TCGv src) 34959422278eSRichard Henderson { 34969422278eSRichard Henderson save_state(dc); 34979422278eSRichard Henderson tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(tl)); 34989422278eSRichard Henderson dc->npc = DYNAMIC_PC; 34999422278eSRichard Henderson } 35009422278eSRichard Henderson 35019422278eSRichard Henderson TRANS(WRPR_tl, 64, do_wr_special, a, supervisor(dc), do_wrtl) 35029422278eSRichard Henderson 35039422278eSRichard Henderson static void do_wrpil(DisasContext *dc, TCGv src) 35049422278eSRichard Henderson { 35059422278eSRichard Henderson if (translator_io_start(&dc->base)) { 35069422278eSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 35079422278eSRichard Henderson } 35089422278eSRichard Henderson gen_helper_wrpil(tcg_env, src); 35099422278eSRichard Henderson } 35109422278eSRichard Henderson 35119422278eSRichard Henderson TRANS(WRPR_pil, 64, do_wr_special, a, supervisor(dc), do_wrpil) 35129422278eSRichard Henderson 35139422278eSRichard Henderson static void do_wrcwp(DisasContext *dc, TCGv src) 35149422278eSRichard Henderson { 35159422278eSRichard Henderson gen_helper_wrcwp(tcg_env, src); 35169422278eSRichard Henderson } 35179422278eSRichard Henderson 35189422278eSRichard Henderson TRANS(WRPR_cwp, 64, do_wr_special, a, supervisor(dc), do_wrcwp) 35199422278eSRichard Henderson 35209422278eSRichard Henderson static void do_wrcansave(DisasContext *dc, TCGv src) 35219422278eSRichard Henderson { 35229422278eSRichard Henderson tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(cansave)); 35239422278eSRichard Henderson } 35249422278eSRichard Henderson 35259422278eSRichard Henderson TRANS(WRPR_cansave, 64, do_wr_special, a, supervisor(dc), do_wrcansave) 35269422278eSRichard Henderson 35279422278eSRichard Henderson static void do_wrcanrestore(DisasContext *dc, TCGv src) 35289422278eSRichard Henderson { 35299422278eSRichard Henderson tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(canrestore)); 35309422278eSRichard Henderson } 35319422278eSRichard Henderson 35329422278eSRichard Henderson TRANS(WRPR_canrestore, 64, do_wr_special, a, supervisor(dc), do_wrcanrestore) 35339422278eSRichard Henderson 35349422278eSRichard Henderson static void do_wrcleanwin(DisasContext *dc, TCGv src) 35359422278eSRichard Henderson { 35369422278eSRichard Henderson tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(cleanwin)); 35379422278eSRichard Henderson } 35389422278eSRichard Henderson 35399422278eSRichard Henderson TRANS(WRPR_cleanwin, 64, do_wr_special, a, supervisor(dc), do_wrcleanwin) 35409422278eSRichard Henderson 35419422278eSRichard Henderson static void do_wrotherwin(DisasContext *dc, TCGv src) 35429422278eSRichard Henderson { 35439422278eSRichard Henderson tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(otherwin)); 35449422278eSRichard Henderson } 35459422278eSRichard Henderson 35469422278eSRichard Henderson TRANS(WRPR_otherwin, 64, do_wr_special, a, supervisor(dc), do_wrotherwin) 35479422278eSRichard Henderson 35489422278eSRichard Henderson static void do_wrwstate(DisasContext *dc, TCGv src) 35499422278eSRichard Henderson { 35509422278eSRichard Henderson tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(wstate)); 35519422278eSRichard Henderson } 35529422278eSRichard Henderson 35539422278eSRichard Henderson TRANS(WRPR_wstate, 64, do_wr_special, a, supervisor(dc), do_wrwstate) 35549422278eSRichard Henderson 35559422278eSRichard Henderson static void do_wrgl(DisasContext *dc, TCGv src) 35569422278eSRichard Henderson { 35579422278eSRichard Henderson gen_helper_wrgl(tcg_env, src); 35589422278eSRichard Henderson } 35599422278eSRichard Henderson 35609422278eSRichard Henderson TRANS(WRPR_gl, GL, do_wr_special, a, supervisor(dc), do_wrgl) 35619422278eSRichard Henderson 35629422278eSRichard Henderson /* UA2005 strand status */ 35639422278eSRichard Henderson static void do_wrssr(DisasContext *dc, TCGv src) 35649422278eSRichard Henderson { 35652da789deSRichard Henderson tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(ssr)); 35669422278eSRichard Henderson } 35679422278eSRichard Henderson 35689422278eSRichard Henderson TRANS(WRPR_strand_status, HYPV, do_wr_special, a, hypervisor(dc), do_wrssr) 35699422278eSRichard Henderson 3570bb97f2f5SRichard Henderson TRANS(WRTBR, 32, do_wr_special, a, supervisor(dc), do_wrtba) 3571bb97f2f5SRichard Henderson 3572bb97f2f5SRichard Henderson static void do_wrhpstate(DisasContext *dc, TCGv src) 3573bb97f2f5SRichard Henderson { 3574bb97f2f5SRichard Henderson tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(hpstate)); 3575bb97f2f5SRichard Henderson dc->base.is_jmp = DISAS_EXIT; 3576bb97f2f5SRichard Henderson } 3577bb97f2f5SRichard Henderson 3578bb97f2f5SRichard Henderson TRANS(WRHPR_hpstate, HYPV, do_wr_special, a, hypervisor(dc), do_wrhpstate) 3579bb97f2f5SRichard Henderson 3580bb97f2f5SRichard Henderson static void do_wrhtstate(DisasContext *dc, TCGv src) 3581bb97f2f5SRichard Henderson { 3582bb97f2f5SRichard Henderson TCGv_i32 tl = tcg_temp_new_i32(); 3583bb97f2f5SRichard Henderson TCGv_ptr tp = tcg_temp_new_ptr(); 3584bb97f2f5SRichard Henderson 3585bb97f2f5SRichard Henderson tcg_gen_ld_i32(tl, tcg_env, env64_field_offsetof(tl)); 3586bb97f2f5SRichard Henderson tcg_gen_andi_i32(tl, tl, MAXTL_MASK); 3587bb97f2f5SRichard Henderson tcg_gen_shli_i32(tl, tl, 3); 3588bb97f2f5SRichard Henderson tcg_gen_ext_i32_ptr(tp, tl); 3589bb97f2f5SRichard Henderson tcg_gen_add_ptr(tp, tp, tcg_env); 3590bb97f2f5SRichard Henderson 3591bb97f2f5SRichard Henderson tcg_gen_st_tl(src, tp, env64_field_offsetof(htstate)); 3592bb97f2f5SRichard Henderson } 3593bb97f2f5SRichard Henderson 3594bb97f2f5SRichard Henderson TRANS(WRHPR_htstate, HYPV, do_wr_special, a, hypervisor(dc), do_wrhtstate) 3595bb97f2f5SRichard Henderson 3596bb97f2f5SRichard Henderson static void do_wrhintp(DisasContext *dc, TCGv src) 3597bb97f2f5SRichard Henderson { 35982da789deSRichard Henderson tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(hintp)); 3599bb97f2f5SRichard Henderson } 3600bb97f2f5SRichard Henderson 3601bb97f2f5SRichard Henderson TRANS(WRHPR_hintp, HYPV, do_wr_special, a, hypervisor(dc), do_wrhintp) 3602bb97f2f5SRichard Henderson 3603bb97f2f5SRichard Henderson static void do_wrhtba(DisasContext *dc, TCGv src) 3604bb97f2f5SRichard Henderson { 36052da789deSRichard Henderson tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(htba)); 3606bb97f2f5SRichard Henderson } 3607bb97f2f5SRichard Henderson 3608bb97f2f5SRichard Henderson TRANS(WRHPR_htba, HYPV, do_wr_special, a, hypervisor(dc), do_wrhtba) 3609bb97f2f5SRichard Henderson 3610bb97f2f5SRichard Henderson static void do_wrhstick_cmpr(DisasContext *dc, TCGv src) 3611bb97f2f5SRichard Henderson { 3612bb97f2f5SRichard Henderson TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 3613bb97f2f5SRichard Henderson 3614577efa45SRichard Henderson tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(hstick_cmpr)); 3615bb97f2f5SRichard Henderson tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(hstick)); 3616bb97f2f5SRichard Henderson translator_io_start(&dc->base); 3617577efa45SRichard Henderson gen_helper_tick_set_limit(r_tickptr, src); 3618bb97f2f5SRichard Henderson /* End TB to handle timer interrupt */ 3619bb97f2f5SRichard Henderson dc->base.is_jmp = DISAS_EXIT; 3620bb97f2f5SRichard Henderson } 3621bb97f2f5SRichard Henderson 3622bb97f2f5SRichard Henderson TRANS(WRHPR_hstick_cmpr, HYPV, do_wr_special, a, hypervisor(dc), 3623bb97f2f5SRichard Henderson do_wrhstick_cmpr) 3624bb97f2f5SRichard Henderson 362525524734SRichard Henderson static bool do_saved_restored(DisasContext *dc, bool saved) 362625524734SRichard Henderson { 362725524734SRichard Henderson if (!supervisor(dc)) { 362825524734SRichard Henderson return raise_priv(dc); 362925524734SRichard Henderson } 363025524734SRichard Henderson if (saved) { 363125524734SRichard Henderson gen_helper_saved(tcg_env); 363225524734SRichard Henderson } else { 363325524734SRichard Henderson gen_helper_restored(tcg_env); 363425524734SRichard Henderson } 363525524734SRichard Henderson return advance_pc(dc); 363625524734SRichard Henderson } 363725524734SRichard Henderson 363825524734SRichard Henderson TRANS(SAVED, 64, do_saved_restored, true) 363925524734SRichard Henderson TRANS(RESTORED, 64, do_saved_restored, false) 364025524734SRichard Henderson 3641d3825800SRichard Henderson static bool trans_NOP(DisasContext *dc, arg_NOP *a) 3642d3825800SRichard Henderson { 3643d3825800SRichard Henderson return advance_pc(dc); 3644d3825800SRichard Henderson } 3645d3825800SRichard Henderson 36460faef01bSRichard Henderson /* 36470faef01bSRichard Henderson * TODO: Need a feature bit for sparcv8. 36480faef01bSRichard Henderson * In the meantime, treat all 32-bit cpus like sparcv7. 36490faef01bSRichard Henderson */ 36505458fd31SRichard Henderson TRANS(NOP_v7, 32, trans_NOP, a) 36515458fd31SRichard Henderson TRANS(NOP_v9, 64, trans_NOP, a) 36520faef01bSRichard Henderson 3653428881deSRichard Henderson static bool do_arith_int(DisasContext *dc, arg_r_r_ri_cc *a, int cc_op, 3654428881deSRichard Henderson void (*func)(TCGv, TCGv, TCGv), 3655428881deSRichard Henderson void (*funci)(TCGv, TCGv, target_long)) 3656428881deSRichard Henderson { 3657428881deSRichard Henderson TCGv dst, src1; 3658428881deSRichard Henderson 3659428881deSRichard Henderson /* For simplicity, we under-decoded the rs2 form. */ 3660428881deSRichard Henderson if (!a->imm && a->rs2_or_imm & ~0x1f) { 3661428881deSRichard Henderson return false; 3662428881deSRichard Henderson } 3663428881deSRichard Henderson 3664428881deSRichard Henderson if (a->cc) { 3665428881deSRichard Henderson dst = cpu_cc_dst; 3666428881deSRichard Henderson } else { 3667428881deSRichard Henderson dst = gen_dest_gpr(dc, a->rd); 3668428881deSRichard Henderson } 3669428881deSRichard Henderson src1 = gen_load_gpr(dc, a->rs1); 3670428881deSRichard Henderson 3671428881deSRichard Henderson if (a->imm || a->rs2_or_imm == 0) { 3672428881deSRichard Henderson if (funci) { 3673428881deSRichard Henderson funci(dst, src1, a->rs2_or_imm); 3674428881deSRichard Henderson } else { 3675428881deSRichard Henderson func(dst, src1, tcg_constant_tl(a->rs2_or_imm)); 3676428881deSRichard Henderson } 3677428881deSRichard Henderson } else { 3678428881deSRichard Henderson func(dst, src1, cpu_regs[a->rs2_or_imm]); 3679428881deSRichard Henderson } 3680428881deSRichard Henderson gen_store_gpr(dc, a->rd, dst); 3681428881deSRichard Henderson 3682428881deSRichard Henderson if (a->cc) { 3683428881deSRichard Henderson tcg_gen_movi_i32(cpu_cc_op, cc_op); 3684428881deSRichard Henderson dc->cc_op = cc_op; 3685428881deSRichard Henderson } 3686428881deSRichard Henderson return advance_pc(dc); 3687428881deSRichard Henderson } 3688428881deSRichard Henderson 3689428881deSRichard Henderson static bool do_arith(DisasContext *dc, arg_r_r_ri_cc *a, int cc_op, 3690428881deSRichard Henderson void (*func)(TCGv, TCGv, TCGv), 3691428881deSRichard Henderson void (*funci)(TCGv, TCGv, target_long), 3692428881deSRichard Henderson void (*func_cc)(TCGv, TCGv, TCGv)) 3693428881deSRichard Henderson { 3694428881deSRichard Henderson if (a->cc) { 369522188d7dSRichard Henderson assert(cc_op >= 0); 3696428881deSRichard Henderson return do_arith_int(dc, a, cc_op, func_cc, NULL); 3697428881deSRichard Henderson } 3698428881deSRichard Henderson return do_arith_int(dc, a, cc_op, func, funci); 3699428881deSRichard Henderson } 3700428881deSRichard Henderson 3701428881deSRichard Henderson static bool do_logic(DisasContext *dc, arg_r_r_ri_cc *a, 3702428881deSRichard Henderson void (*func)(TCGv, TCGv, TCGv), 3703428881deSRichard Henderson void (*funci)(TCGv, TCGv, target_long)) 3704428881deSRichard Henderson { 3705428881deSRichard Henderson return do_arith_int(dc, a, CC_OP_LOGIC, func, funci); 3706428881deSRichard Henderson } 3707428881deSRichard Henderson 3708428881deSRichard Henderson TRANS(ADD, ALL, do_arith, a, CC_OP_ADD, 3709428881deSRichard Henderson tcg_gen_add_tl, tcg_gen_addi_tl, gen_op_add_cc) 3710428881deSRichard Henderson TRANS(SUB, ALL, do_arith, a, CC_OP_SUB, 3711428881deSRichard Henderson tcg_gen_sub_tl, tcg_gen_subi_tl, gen_op_sub_cc) 3712428881deSRichard Henderson 3713a9aba13dSRichard Henderson TRANS(TADDcc, ALL, do_arith, a, CC_OP_TADD, NULL, NULL, gen_op_add_cc) 3714a9aba13dSRichard Henderson TRANS(TSUBcc, ALL, do_arith, a, CC_OP_TSUB, NULL, NULL, gen_op_sub_cc) 3715a9aba13dSRichard Henderson TRANS(TADDccTV, ALL, do_arith, a, CC_OP_TADDTV, NULL, NULL, gen_op_taddcctv) 3716a9aba13dSRichard Henderson TRANS(TSUBccTV, ALL, do_arith, a, CC_OP_TSUBTV, NULL, NULL, gen_op_tsubcctv) 3717a9aba13dSRichard Henderson 3718428881deSRichard Henderson TRANS(AND, ALL, do_logic, a, tcg_gen_and_tl, tcg_gen_andi_tl) 3719428881deSRichard Henderson TRANS(XOR, ALL, do_logic, a, tcg_gen_xor_tl, tcg_gen_xori_tl) 3720428881deSRichard Henderson TRANS(ANDN, ALL, do_logic, a, tcg_gen_andc_tl, NULL) 3721428881deSRichard Henderson TRANS(ORN, ALL, do_logic, a, tcg_gen_orc_tl, NULL) 3722428881deSRichard Henderson TRANS(XORN, ALL, do_logic, a, tcg_gen_eqv_tl, NULL) 3723428881deSRichard Henderson 372422188d7dSRichard Henderson TRANS(MULX, 64, do_arith, a, -1, tcg_gen_mul_tl, tcg_gen_muli_tl, NULL) 3725b5372650SRichard Henderson TRANS(UMUL, MUL, do_logic, a, gen_op_umul, NULL) 3726b5372650SRichard Henderson TRANS(SMUL, MUL, do_logic, a, gen_op_smul, NULL) 372722188d7dSRichard Henderson 37284ee85ea9SRichard Henderson TRANS(UDIVX, 64, do_arith, a, -1, gen_op_udivx, NULL, NULL) 37294ee85ea9SRichard Henderson TRANS(SDIVX, 64, do_arith, a, -1, gen_op_sdivx, NULL, NULL) 3730c2636853SRichard Henderson TRANS(UDIV, DIV, do_arith, a, CC_OP_DIV, gen_op_udiv, NULL, gen_op_udivcc) 3731c2636853SRichard Henderson TRANS(SDIV, DIV, do_arith, a, CC_OP_DIV, gen_op_sdiv, NULL, gen_op_sdivcc) 37324ee85ea9SRichard Henderson 37339c6ec5bcSRichard Henderson /* TODO: Should have feature bit -- comes in with UltraSparc T2. */ 37349c6ec5bcSRichard Henderson TRANS(POPC, 64, do_arith, a, -1, gen_op_popc, NULL, NULL) 37359c6ec5bcSRichard Henderson 3736428881deSRichard Henderson static bool trans_OR(DisasContext *dc, arg_r_r_ri_cc *a) 3737428881deSRichard Henderson { 3738428881deSRichard Henderson /* OR with %g0 is the canonical alias for MOV. */ 3739428881deSRichard Henderson if (!a->cc && a->rs1 == 0) { 3740428881deSRichard Henderson if (a->imm || a->rs2_or_imm == 0) { 3741428881deSRichard Henderson gen_store_gpr(dc, a->rd, tcg_constant_tl(a->rs2_or_imm)); 3742428881deSRichard Henderson } else if (a->rs2_or_imm & ~0x1f) { 3743428881deSRichard Henderson /* For simplicity, we under-decoded the rs2 form. */ 3744428881deSRichard Henderson return false; 3745428881deSRichard Henderson } else { 3746428881deSRichard Henderson gen_store_gpr(dc, a->rd, cpu_regs[a->rs2_or_imm]); 3747428881deSRichard Henderson } 3748428881deSRichard Henderson return advance_pc(dc); 3749428881deSRichard Henderson } 3750428881deSRichard Henderson return do_logic(dc, a, tcg_gen_or_tl, tcg_gen_ori_tl); 3751428881deSRichard Henderson } 3752428881deSRichard Henderson 3753420a187dSRichard Henderson static bool trans_ADDC(DisasContext *dc, arg_r_r_ri_cc *a) 3754420a187dSRichard Henderson { 3755420a187dSRichard Henderson switch (dc->cc_op) { 3756420a187dSRichard Henderson case CC_OP_DIV: 3757420a187dSRichard Henderson case CC_OP_LOGIC: 3758420a187dSRichard Henderson /* Carry is known to be zero. Fall back to plain ADD. */ 3759420a187dSRichard Henderson return do_arith(dc, a, CC_OP_ADD, 3760420a187dSRichard Henderson tcg_gen_add_tl, tcg_gen_addi_tl, gen_op_add_cc); 3761420a187dSRichard Henderson case CC_OP_ADD: 3762420a187dSRichard Henderson case CC_OP_TADD: 3763420a187dSRichard Henderson case CC_OP_TADDTV: 3764420a187dSRichard Henderson return do_arith(dc, a, CC_OP_ADDX, 3765420a187dSRichard Henderson gen_op_addc_add, NULL, gen_op_addccc_add); 3766420a187dSRichard Henderson case CC_OP_SUB: 3767420a187dSRichard Henderson case CC_OP_TSUB: 3768420a187dSRichard Henderson case CC_OP_TSUBTV: 3769420a187dSRichard Henderson return do_arith(dc, a, CC_OP_ADDX, 3770420a187dSRichard Henderson gen_op_addc_sub, NULL, gen_op_addccc_sub); 3771420a187dSRichard Henderson default: 3772420a187dSRichard Henderson return do_arith(dc, a, CC_OP_ADDX, 3773420a187dSRichard Henderson gen_op_addc_generic, NULL, gen_op_addccc_generic); 3774420a187dSRichard Henderson } 3775420a187dSRichard Henderson } 3776420a187dSRichard Henderson 3777dfebb950SRichard Henderson static bool trans_SUBC(DisasContext *dc, arg_r_r_ri_cc *a) 3778dfebb950SRichard Henderson { 3779dfebb950SRichard Henderson switch (dc->cc_op) { 3780dfebb950SRichard Henderson case CC_OP_DIV: 3781dfebb950SRichard Henderson case CC_OP_LOGIC: 3782dfebb950SRichard Henderson /* Carry is known to be zero. Fall back to plain SUB. */ 3783dfebb950SRichard Henderson return do_arith(dc, a, CC_OP_SUB, 3784dfebb950SRichard Henderson tcg_gen_sub_tl, tcg_gen_subi_tl, gen_op_sub_cc); 3785dfebb950SRichard Henderson case CC_OP_ADD: 3786dfebb950SRichard Henderson case CC_OP_TADD: 3787dfebb950SRichard Henderson case CC_OP_TADDTV: 3788dfebb950SRichard Henderson return do_arith(dc, a, CC_OP_SUBX, 3789dfebb950SRichard Henderson gen_op_subc_add, NULL, gen_op_subccc_add); 3790dfebb950SRichard Henderson case CC_OP_SUB: 3791dfebb950SRichard Henderson case CC_OP_TSUB: 3792dfebb950SRichard Henderson case CC_OP_TSUBTV: 3793dfebb950SRichard Henderson return do_arith(dc, a, CC_OP_SUBX, 3794dfebb950SRichard Henderson gen_op_subc_sub, NULL, gen_op_subccc_sub); 3795dfebb950SRichard Henderson default: 3796dfebb950SRichard Henderson return do_arith(dc, a, CC_OP_SUBX, 3797dfebb950SRichard Henderson gen_op_subc_generic, NULL, gen_op_subccc_generic); 3798dfebb950SRichard Henderson } 3799dfebb950SRichard Henderson } 3800dfebb950SRichard Henderson 3801a9aba13dSRichard Henderson static bool trans_MULScc(DisasContext *dc, arg_r_r_ri_cc *a) 3802a9aba13dSRichard Henderson { 3803a9aba13dSRichard Henderson update_psr(dc); 3804a9aba13dSRichard Henderson return do_arith(dc, a, CC_OP_ADD, NULL, NULL, gen_op_mulscc); 3805a9aba13dSRichard Henderson } 3806a9aba13dSRichard Henderson 3807b88ce6f2SRichard Henderson static bool gen_edge(DisasContext *dc, arg_r_r_r *a, 3808b88ce6f2SRichard Henderson int width, bool cc, bool left) 3809b88ce6f2SRichard Henderson { 3810b88ce6f2SRichard Henderson TCGv dst, s1, s2, lo1, lo2; 3811b88ce6f2SRichard Henderson uint64_t amask, tabl, tabr; 3812b88ce6f2SRichard Henderson int shift, imask, omask; 3813b88ce6f2SRichard Henderson 3814b88ce6f2SRichard Henderson dst = gen_dest_gpr(dc, a->rd); 3815b88ce6f2SRichard Henderson s1 = gen_load_gpr(dc, a->rs1); 3816b88ce6f2SRichard Henderson s2 = gen_load_gpr(dc, a->rs2); 3817b88ce6f2SRichard Henderson 3818b88ce6f2SRichard Henderson if (cc) { 3819b88ce6f2SRichard Henderson tcg_gen_mov_tl(cpu_cc_src, s1); 3820b88ce6f2SRichard Henderson tcg_gen_mov_tl(cpu_cc_src2, s2); 3821b88ce6f2SRichard Henderson tcg_gen_sub_tl(cpu_cc_dst, s1, s2); 3822b88ce6f2SRichard Henderson tcg_gen_movi_i32(cpu_cc_op, CC_OP_SUB); 3823b88ce6f2SRichard Henderson dc->cc_op = CC_OP_SUB; 3824b88ce6f2SRichard Henderson } 3825b88ce6f2SRichard Henderson 3826b88ce6f2SRichard Henderson /* 3827b88ce6f2SRichard Henderson * Theory of operation: there are two tables, left and right (not to 3828b88ce6f2SRichard Henderson * be confused with the left and right versions of the opcode). These 3829b88ce6f2SRichard Henderson * are indexed by the low 3 bits of the inputs. To make things "easy", 3830b88ce6f2SRichard Henderson * these tables are loaded into two constants, TABL and TABR below. 3831b88ce6f2SRichard Henderson * The operation index = (input & imask) << shift calculates the index 3832b88ce6f2SRichard Henderson * into the constant, while val = (table >> index) & omask calculates 3833b88ce6f2SRichard Henderson * the value we're looking for. 3834b88ce6f2SRichard Henderson */ 3835b88ce6f2SRichard Henderson switch (width) { 3836b88ce6f2SRichard Henderson case 8: 3837b88ce6f2SRichard Henderson imask = 0x7; 3838b88ce6f2SRichard Henderson shift = 3; 3839b88ce6f2SRichard Henderson omask = 0xff; 3840b88ce6f2SRichard Henderson if (left) { 3841b88ce6f2SRichard Henderson tabl = 0x80c0e0f0f8fcfeffULL; 3842b88ce6f2SRichard Henderson tabr = 0xff7f3f1f0f070301ULL; 3843b88ce6f2SRichard Henderson } else { 3844b88ce6f2SRichard Henderson tabl = 0x0103070f1f3f7fffULL; 3845b88ce6f2SRichard Henderson tabr = 0xfffefcf8f0e0c080ULL; 3846b88ce6f2SRichard Henderson } 3847b88ce6f2SRichard Henderson break; 3848b88ce6f2SRichard Henderson case 16: 3849b88ce6f2SRichard Henderson imask = 0x6; 3850b88ce6f2SRichard Henderson shift = 1; 3851b88ce6f2SRichard Henderson omask = 0xf; 3852b88ce6f2SRichard Henderson if (left) { 3853b88ce6f2SRichard Henderson tabl = 0x8cef; 3854b88ce6f2SRichard Henderson tabr = 0xf731; 3855b88ce6f2SRichard Henderson } else { 3856b88ce6f2SRichard Henderson tabl = 0x137f; 3857b88ce6f2SRichard Henderson tabr = 0xfec8; 3858b88ce6f2SRichard Henderson } 3859b88ce6f2SRichard Henderson break; 3860b88ce6f2SRichard Henderson case 32: 3861b88ce6f2SRichard Henderson imask = 0x4; 3862b88ce6f2SRichard Henderson shift = 0; 3863b88ce6f2SRichard Henderson omask = 0x3; 3864b88ce6f2SRichard Henderson if (left) { 3865b88ce6f2SRichard Henderson tabl = (2 << 2) | 3; 3866b88ce6f2SRichard Henderson tabr = (3 << 2) | 1; 3867b88ce6f2SRichard Henderson } else { 3868b88ce6f2SRichard Henderson tabl = (1 << 2) | 3; 3869b88ce6f2SRichard Henderson tabr = (3 << 2) | 2; 3870b88ce6f2SRichard Henderson } 3871b88ce6f2SRichard Henderson break; 3872b88ce6f2SRichard Henderson default: 3873b88ce6f2SRichard Henderson abort(); 3874b88ce6f2SRichard Henderson } 3875b88ce6f2SRichard Henderson 3876b88ce6f2SRichard Henderson lo1 = tcg_temp_new(); 3877b88ce6f2SRichard Henderson lo2 = tcg_temp_new(); 3878b88ce6f2SRichard Henderson tcg_gen_andi_tl(lo1, s1, imask); 3879b88ce6f2SRichard Henderson tcg_gen_andi_tl(lo2, s2, imask); 3880b88ce6f2SRichard Henderson tcg_gen_shli_tl(lo1, lo1, shift); 3881b88ce6f2SRichard Henderson tcg_gen_shli_tl(lo2, lo2, shift); 3882b88ce6f2SRichard Henderson 3883b88ce6f2SRichard Henderson tcg_gen_shr_tl(lo1, tcg_constant_tl(tabl), lo1); 3884b88ce6f2SRichard Henderson tcg_gen_shr_tl(lo2, tcg_constant_tl(tabr), lo2); 3885b88ce6f2SRichard Henderson tcg_gen_andi_tl(lo1, lo1, omask); 3886b88ce6f2SRichard Henderson tcg_gen_andi_tl(lo2, lo2, omask); 3887b88ce6f2SRichard Henderson 3888b88ce6f2SRichard Henderson amask = address_mask_i(dc, -8); 3889b88ce6f2SRichard Henderson tcg_gen_andi_tl(s1, s1, amask); 3890b88ce6f2SRichard Henderson tcg_gen_andi_tl(s2, s2, amask); 3891b88ce6f2SRichard Henderson 3892b88ce6f2SRichard Henderson /* Compute dst = (s1 == s2 ? lo1 : lo1 & lo2). */ 3893b88ce6f2SRichard Henderson tcg_gen_and_tl(lo2, lo2, lo1); 3894b88ce6f2SRichard Henderson tcg_gen_movcond_tl(TCG_COND_EQ, dst, s1, s2, lo1, lo2); 3895b88ce6f2SRichard Henderson 3896b88ce6f2SRichard Henderson gen_store_gpr(dc, a->rd, dst); 3897b88ce6f2SRichard Henderson return advance_pc(dc); 3898b88ce6f2SRichard Henderson } 3899b88ce6f2SRichard Henderson 3900b88ce6f2SRichard Henderson TRANS(EDGE8cc, VIS1, gen_edge, a, 8, 1, 0) 3901b88ce6f2SRichard Henderson TRANS(EDGE8Lcc, VIS1, gen_edge, a, 8, 1, 1) 3902b88ce6f2SRichard Henderson TRANS(EDGE16cc, VIS1, gen_edge, a, 16, 1, 0) 3903b88ce6f2SRichard Henderson TRANS(EDGE16Lcc, VIS1, gen_edge, a, 16, 1, 1) 3904b88ce6f2SRichard Henderson TRANS(EDGE32cc, VIS1, gen_edge, a, 32, 1, 0) 3905b88ce6f2SRichard Henderson TRANS(EDGE32Lcc, VIS1, gen_edge, a, 32, 1, 1) 3906b88ce6f2SRichard Henderson 3907b88ce6f2SRichard Henderson TRANS(EDGE8N, VIS2, gen_edge, a, 8, 0, 0) 3908b88ce6f2SRichard Henderson TRANS(EDGE8LN, VIS2, gen_edge, a, 8, 0, 1) 3909b88ce6f2SRichard Henderson TRANS(EDGE16N, VIS2, gen_edge, a, 16, 0, 0) 3910b88ce6f2SRichard Henderson TRANS(EDGE16LN, VIS2, gen_edge, a, 16, 0, 1) 3911b88ce6f2SRichard Henderson TRANS(EDGE32N, VIS2, gen_edge, a, 32, 0, 0) 3912b88ce6f2SRichard Henderson TRANS(EDGE32LN, VIS2, gen_edge, a, 32, 0, 1) 3913b88ce6f2SRichard Henderson 391445bfed3bSRichard Henderson static bool do_rrr(DisasContext *dc, arg_r_r_r *a, 391545bfed3bSRichard Henderson void (*func)(TCGv, TCGv, TCGv)) 391645bfed3bSRichard Henderson { 391745bfed3bSRichard Henderson TCGv dst = gen_dest_gpr(dc, a->rd); 391845bfed3bSRichard Henderson TCGv src1 = gen_load_gpr(dc, a->rs1); 391945bfed3bSRichard Henderson TCGv src2 = gen_load_gpr(dc, a->rs2); 392045bfed3bSRichard Henderson 392145bfed3bSRichard Henderson func(dst, src1, src2); 392245bfed3bSRichard Henderson gen_store_gpr(dc, a->rd, dst); 392345bfed3bSRichard Henderson return advance_pc(dc); 392445bfed3bSRichard Henderson } 392545bfed3bSRichard Henderson 392645bfed3bSRichard Henderson TRANS(ARRAY8, VIS1, do_rrr, a, gen_helper_array8) 392745bfed3bSRichard Henderson TRANS(ARRAY16, VIS1, do_rrr, a, gen_op_array16) 392845bfed3bSRichard Henderson TRANS(ARRAY32, VIS1, do_rrr, a, gen_op_array32) 392945bfed3bSRichard Henderson 39309e20ca94SRichard Henderson static void gen_op_alignaddr(TCGv dst, TCGv s1, TCGv s2) 39319e20ca94SRichard Henderson { 39329e20ca94SRichard Henderson #ifdef TARGET_SPARC64 39339e20ca94SRichard Henderson TCGv tmp = tcg_temp_new(); 39349e20ca94SRichard Henderson 39359e20ca94SRichard Henderson tcg_gen_add_tl(tmp, s1, s2); 39369e20ca94SRichard Henderson tcg_gen_andi_tl(dst, tmp, -8); 39379e20ca94SRichard Henderson tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, tmp, 0, 3); 39389e20ca94SRichard Henderson #else 39399e20ca94SRichard Henderson g_assert_not_reached(); 39409e20ca94SRichard Henderson #endif 39419e20ca94SRichard Henderson } 39429e20ca94SRichard Henderson 39439e20ca94SRichard Henderson static void gen_op_alignaddrl(TCGv dst, TCGv s1, TCGv s2) 39449e20ca94SRichard Henderson { 39459e20ca94SRichard Henderson #ifdef TARGET_SPARC64 39469e20ca94SRichard Henderson TCGv tmp = tcg_temp_new(); 39479e20ca94SRichard Henderson 39489e20ca94SRichard Henderson tcg_gen_add_tl(tmp, s1, s2); 39499e20ca94SRichard Henderson tcg_gen_andi_tl(dst, tmp, -8); 39509e20ca94SRichard Henderson tcg_gen_neg_tl(tmp, tmp); 39519e20ca94SRichard Henderson tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, tmp, 0, 3); 39529e20ca94SRichard Henderson #else 39539e20ca94SRichard Henderson g_assert_not_reached(); 39549e20ca94SRichard Henderson #endif 39559e20ca94SRichard Henderson } 39569e20ca94SRichard Henderson 39579e20ca94SRichard Henderson TRANS(ALIGNADDR, VIS1, do_rrr, a, gen_op_alignaddr) 39589e20ca94SRichard Henderson TRANS(ALIGNADDRL, VIS1, do_rrr, a, gen_op_alignaddrl) 39599e20ca94SRichard Henderson 396039ca3490SRichard Henderson static void gen_op_bmask(TCGv dst, TCGv s1, TCGv s2) 396139ca3490SRichard Henderson { 396239ca3490SRichard Henderson #ifdef TARGET_SPARC64 396339ca3490SRichard Henderson tcg_gen_add_tl(dst, s1, s2); 396439ca3490SRichard Henderson tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, dst, 32, 32); 396539ca3490SRichard Henderson #else 396639ca3490SRichard Henderson g_assert_not_reached(); 396739ca3490SRichard Henderson #endif 396839ca3490SRichard Henderson } 396939ca3490SRichard Henderson 397039ca3490SRichard Henderson TRANS(BMASK, VIS2, do_rrr, a, gen_op_bmask) 397139ca3490SRichard Henderson 39725fc546eeSRichard Henderson static bool do_shift_r(DisasContext *dc, arg_shiftr *a, bool l, bool u) 39735fc546eeSRichard Henderson { 39745fc546eeSRichard Henderson TCGv dst, src1, src2; 39755fc546eeSRichard Henderson 39765fc546eeSRichard Henderson /* Reject 64-bit shifts for sparc32. */ 39775fc546eeSRichard Henderson if (avail_32(dc) && a->x) { 39785fc546eeSRichard Henderson return false; 39795fc546eeSRichard Henderson } 39805fc546eeSRichard Henderson 39815fc546eeSRichard Henderson src2 = tcg_temp_new(); 39825fc546eeSRichard Henderson tcg_gen_andi_tl(src2, gen_load_gpr(dc, a->rs2), a->x ? 63 : 31); 39835fc546eeSRichard Henderson src1 = gen_load_gpr(dc, a->rs1); 39845fc546eeSRichard Henderson dst = gen_dest_gpr(dc, a->rd); 39855fc546eeSRichard Henderson 39865fc546eeSRichard Henderson if (l) { 39875fc546eeSRichard Henderson tcg_gen_shl_tl(dst, src1, src2); 39885fc546eeSRichard Henderson if (!a->x) { 39895fc546eeSRichard Henderson tcg_gen_ext32u_tl(dst, dst); 39905fc546eeSRichard Henderson } 39915fc546eeSRichard Henderson } else if (u) { 39925fc546eeSRichard Henderson if (!a->x) { 39935fc546eeSRichard Henderson tcg_gen_ext32u_tl(dst, src1); 39945fc546eeSRichard Henderson src1 = dst; 39955fc546eeSRichard Henderson } 39965fc546eeSRichard Henderson tcg_gen_shr_tl(dst, src1, src2); 39975fc546eeSRichard Henderson } else { 39985fc546eeSRichard Henderson if (!a->x) { 39995fc546eeSRichard Henderson tcg_gen_ext32s_tl(dst, src1); 40005fc546eeSRichard Henderson src1 = dst; 40015fc546eeSRichard Henderson } 40025fc546eeSRichard Henderson tcg_gen_sar_tl(dst, src1, src2); 40035fc546eeSRichard Henderson } 40045fc546eeSRichard Henderson gen_store_gpr(dc, a->rd, dst); 40055fc546eeSRichard Henderson return advance_pc(dc); 40065fc546eeSRichard Henderson } 40075fc546eeSRichard Henderson 40085fc546eeSRichard Henderson TRANS(SLL_r, ALL, do_shift_r, a, true, true) 40095fc546eeSRichard Henderson TRANS(SRL_r, ALL, do_shift_r, a, false, true) 40105fc546eeSRichard Henderson TRANS(SRA_r, ALL, do_shift_r, a, false, false) 40115fc546eeSRichard Henderson 40125fc546eeSRichard Henderson static bool do_shift_i(DisasContext *dc, arg_shifti *a, bool l, bool u) 40135fc546eeSRichard Henderson { 40145fc546eeSRichard Henderson TCGv dst, src1; 40155fc546eeSRichard Henderson 40165fc546eeSRichard Henderson /* Reject 64-bit shifts for sparc32. */ 40175fc546eeSRichard Henderson if (avail_32(dc) && (a->x || a->i >= 32)) { 40185fc546eeSRichard Henderson return false; 40195fc546eeSRichard Henderson } 40205fc546eeSRichard Henderson 40215fc546eeSRichard Henderson src1 = gen_load_gpr(dc, a->rs1); 40225fc546eeSRichard Henderson dst = gen_dest_gpr(dc, a->rd); 40235fc546eeSRichard Henderson 40245fc546eeSRichard Henderson if (avail_32(dc) || a->x) { 40255fc546eeSRichard Henderson if (l) { 40265fc546eeSRichard Henderson tcg_gen_shli_tl(dst, src1, a->i); 40275fc546eeSRichard Henderson } else if (u) { 40285fc546eeSRichard Henderson tcg_gen_shri_tl(dst, src1, a->i); 40295fc546eeSRichard Henderson } else { 40305fc546eeSRichard Henderson tcg_gen_sari_tl(dst, src1, a->i); 40315fc546eeSRichard Henderson } 40325fc546eeSRichard Henderson } else { 40335fc546eeSRichard Henderson if (l) { 40345fc546eeSRichard Henderson tcg_gen_deposit_z_tl(dst, src1, a->i, 32 - a->i); 40355fc546eeSRichard Henderson } else if (u) { 40365fc546eeSRichard Henderson tcg_gen_extract_tl(dst, src1, a->i, 32 - a->i); 40375fc546eeSRichard Henderson } else { 40385fc546eeSRichard Henderson tcg_gen_sextract_tl(dst, src1, a->i, 32 - a->i); 40395fc546eeSRichard Henderson } 40405fc546eeSRichard Henderson } 40415fc546eeSRichard Henderson gen_store_gpr(dc, a->rd, dst); 40425fc546eeSRichard Henderson return advance_pc(dc); 40435fc546eeSRichard Henderson } 40445fc546eeSRichard Henderson 40455fc546eeSRichard Henderson TRANS(SLL_i, ALL, do_shift_i, a, true, true) 40465fc546eeSRichard Henderson TRANS(SRL_i, ALL, do_shift_i, a, false, true) 40475fc546eeSRichard Henderson TRANS(SRA_i, ALL, do_shift_i, a, false, false) 40485fc546eeSRichard Henderson 4049fb4ed7aaSRichard Henderson static TCGv gen_rs2_or_imm(DisasContext *dc, bool imm, int rs2_or_imm) 4050fb4ed7aaSRichard Henderson { 4051fb4ed7aaSRichard Henderson /* For simplicity, we under-decoded the rs2 form. */ 4052fb4ed7aaSRichard Henderson if (!imm && rs2_or_imm & ~0x1f) { 4053fb4ed7aaSRichard Henderson return NULL; 4054fb4ed7aaSRichard Henderson } 4055fb4ed7aaSRichard Henderson if (imm || rs2_or_imm == 0) { 4056fb4ed7aaSRichard Henderson return tcg_constant_tl(rs2_or_imm); 4057fb4ed7aaSRichard Henderson } else { 4058fb4ed7aaSRichard Henderson return cpu_regs[rs2_or_imm]; 4059fb4ed7aaSRichard Henderson } 4060fb4ed7aaSRichard Henderson } 4061fb4ed7aaSRichard Henderson 4062fb4ed7aaSRichard Henderson static bool do_mov_cond(DisasContext *dc, DisasCompare *cmp, int rd, TCGv src2) 4063fb4ed7aaSRichard Henderson { 4064fb4ed7aaSRichard Henderson TCGv dst = gen_load_gpr(dc, rd); 4065fb4ed7aaSRichard Henderson 4066fb4ed7aaSRichard Henderson tcg_gen_movcond_tl(cmp->cond, dst, cmp->c1, cmp->c2, src2, dst); 4067fb4ed7aaSRichard Henderson gen_store_gpr(dc, rd, dst); 4068fb4ed7aaSRichard Henderson return advance_pc(dc); 4069fb4ed7aaSRichard Henderson } 4070fb4ed7aaSRichard Henderson 4071fb4ed7aaSRichard Henderson static bool trans_MOVcc(DisasContext *dc, arg_MOVcc *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_compare(&cmp, a->cc, a->cond, dc); 4080fb4ed7aaSRichard Henderson return do_mov_cond(dc, &cmp, a->rd, src2); 4081fb4ed7aaSRichard Henderson } 4082fb4ed7aaSRichard Henderson 4083fb4ed7aaSRichard Henderson static bool trans_MOVfcc(DisasContext *dc, arg_MOVfcc *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_fcompare(&cmp, a->cc, a->cond); 4092fb4ed7aaSRichard Henderson return do_mov_cond(dc, &cmp, a->rd, src2); 4093fb4ed7aaSRichard Henderson } 4094fb4ed7aaSRichard Henderson 4095fb4ed7aaSRichard Henderson static bool trans_MOVR(DisasContext *dc, arg_MOVR *a) 4096fb4ed7aaSRichard Henderson { 4097fb4ed7aaSRichard Henderson TCGv src2 = gen_rs2_or_imm(dc, a->imm, a->rs2_or_imm); 4098fb4ed7aaSRichard Henderson DisasCompare cmp; 4099fb4ed7aaSRichard Henderson 4100fb4ed7aaSRichard Henderson if (src2 == NULL) { 4101fb4ed7aaSRichard Henderson return false; 4102fb4ed7aaSRichard Henderson } 4103fb4ed7aaSRichard Henderson gen_compare_reg(&cmp, a->cond, gen_load_gpr(dc, a->rs1)); 4104fb4ed7aaSRichard Henderson return do_mov_cond(dc, &cmp, a->rd, src2); 4105fb4ed7aaSRichard Henderson } 4106fb4ed7aaSRichard Henderson 410786b82fe0SRichard Henderson static bool do_add_special(DisasContext *dc, arg_r_r_ri *a, 410886b82fe0SRichard Henderson bool (*func)(DisasContext *dc, int rd, TCGv src)) 410986b82fe0SRichard Henderson { 411086b82fe0SRichard Henderson TCGv src1, sum; 411186b82fe0SRichard Henderson 411286b82fe0SRichard Henderson /* For simplicity, we under-decoded the rs2 form. */ 411386b82fe0SRichard Henderson if (!a->imm && a->rs2_or_imm & ~0x1f) { 411486b82fe0SRichard Henderson return false; 411586b82fe0SRichard Henderson } 411686b82fe0SRichard Henderson 411786b82fe0SRichard Henderson /* 411886b82fe0SRichard Henderson * Always load the sum into a new temporary. 411986b82fe0SRichard Henderson * This is required to capture the value across a window change, 412086b82fe0SRichard Henderson * e.g. SAVE and RESTORE, and may be optimized away otherwise. 412186b82fe0SRichard Henderson */ 412286b82fe0SRichard Henderson sum = tcg_temp_new(); 412386b82fe0SRichard Henderson src1 = gen_load_gpr(dc, a->rs1); 412486b82fe0SRichard Henderson if (a->imm || a->rs2_or_imm == 0) { 412586b82fe0SRichard Henderson tcg_gen_addi_tl(sum, src1, a->rs2_or_imm); 412686b82fe0SRichard Henderson } else { 412786b82fe0SRichard Henderson tcg_gen_add_tl(sum, src1, cpu_regs[a->rs2_or_imm]); 412886b82fe0SRichard Henderson } 412986b82fe0SRichard Henderson return func(dc, a->rd, sum); 413086b82fe0SRichard Henderson } 413186b82fe0SRichard Henderson 413286b82fe0SRichard Henderson static bool do_jmpl(DisasContext *dc, int rd, TCGv src) 413386b82fe0SRichard Henderson { 413486b82fe0SRichard Henderson /* 413586b82fe0SRichard Henderson * Preserve pc across advance, so that we can delay 413686b82fe0SRichard Henderson * the writeback to rd until after src is consumed. 413786b82fe0SRichard Henderson */ 413886b82fe0SRichard Henderson target_ulong cur_pc = dc->pc; 413986b82fe0SRichard Henderson 414086b82fe0SRichard Henderson gen_check_align(dc, src, 3); 414186b82fe0SRichard Henderson 414286b82fe0SRichard Henderson gen_mov_pc_npc(dc); 414386b82fe0SRichard Henderson tcg_gen_mov_tl(cpu_npc, src); 414486b82fe0SRichard Henderson gen_address_mask(dc, cpu_npc); 414586b82fe0SRichard Henderson gen_store_gpr(dc, rd, tcg_constant_tl(cur_pc)); 414686b82fe0SRichard Henderson 414786b82fe0SRichard Henderson dc->npc = DYNAMIC_PC_LOOKUP; 414886b82fe0SRichard Henderson return true; 414986b82fe0SRichard Henderson } 415086b82fe0SRichard Henderson 415186b82fe0SRichard Henderson TRANS(JMPL, ALL, do_add_special, a, do_jmpl) 415286b82fe0SRichard Henderson 415386b82fe0SRichard Henderson static bool do_rett(DisasContext *dc, int rd, TCGv src) 415486b82fe0SRichard Henderson { 415586b82fe0SRichard Henderson if (!supervisor(dc)) { 415686b82fe0SRichard Henderson return raise_priv(dc); 415786b82fe0SRichard Henderson } 415886b82fe0SRichard Henderson 415986b82fe0SRichard Henderson gen_check_align(dc, src, 3); 416086b82fe0SRichard Henderson 416186b82fe0SRichard Henderson gen_mov_pc_npc(dc); 416286b82fe0SRichard Henderson tcg_gen_mov_tl(cpu_npc, src); 416386b82fe0SRichard Henderson gen_helper_rett(tcg_env); 416486b82fe0SRichard Henderson 416586b82fe0SRichard Henderson dc->npc = DYNAMIC_PC; 416686b82fe0SRichard Henderson return true; 416786b82fe0SRichard Henderson } 416886b82fe0SRichard Henderson 416986b82fe0SRichard Henderson TRANS(RETT, 32, do_add_special, a, do_rett) 417086b82fe0SRichard Henderson 417186b82fe0SRichard Henderson static bool do_return(DisasContext *dc, int rd, TCGv src) 417286b82fe0SRichard Henderson { 417386b82fe0SRichard Henderson gen_check_align(dc, src, 3); 417486b82fe0SRichard Henderson 417586b82fe0SRichard Henderson gen_mov_pc_npc(dc); 417686b82fe0SRichard Henderson tcg_gen_mov_tl(cpu_npc, src); 417786b82fe0SRichard Henderson gen_address_mask(dc, cpu_npc); 417886b82fe0SRichard Henderson 417986b82fe0SRichard Henderson gen_helper_restore(tcg_env); 418086b82fe0SRichard Henderson dc->npc = DYNAMIC_PC_LOOKUP; 418186b82fe0SRichard Henderson return true; 418286b82fe0SRichard Henderson } 418386b82fe0SRichard Henderson 418486b82fe0SRichard Henderson TRANS(RETURN, 64, do_add_special, a, do_return) 418586b82fe0SRichard Henderson 4186d3825800SRichard Henderson static bool do_save(DisasContext *dc, int rd, TCGv src) 4187d3825800SRichard Henderson { 4188d3825800SRichard Henderson gen_helper_save(tcg_env); 4189d3825800SRichard Henderson gen_store_gpr(dc, rd, src); 4190d3825800SRichard Henderson return advance_pc(dc); 4191d3825800SRichard Henderson } 4192d3825800SRichard Henderson 4193d3825800SRichard Henderson TRANS(SAVE, ALL, do_add_special, a, do_save) 4194d3825800SRichard Henderson 4195d3825800SRichard Henderson static bool do_restore(DisasContext *dc, int rd, TCGv src) 4196d3825800SRichard Henderson { 4197d3825800SRichard Henderson gen_helper_restore(tcg_env); 4198d3825800SRichard Henderson gen_store_gpr(dc, rd, src); 4199d3825800SRichard Henderson return advance_pc(dc); 4200d3825800SRichard Henderson } 4201d3825800SRichard Henderson 4202d3825800SRichard Henderson TRANS(RESTORE, ALL, do_add_special, a, do_restore) 4203d3825800SRichard Henderson 42048f75b8a4SRichard Henderson static bool do_done_retry(DisasContext *dc, bool done) 42058f75b8a4SRichard Henderson { 42068f75b8a4SRichard Henderson if (!supervisor(dc)) { 42078f75b8a4SRichard Henderson return raise_priv(dc); 42088f75b8a4SRichard Henderson } 42098f75b8a4SRichard Henderson dc->npc = DYNAMIC_PC; 42108f75b8a4SRichard Henderson dc->pc = DYNAMIC_PC; 42118f75b8a4SRichard Henderson translator_io_start(&dc->base); 42128f75b8a4SRichard Henderson if (done) { 42138f75b8a4SRichard Henderson gen_helper_done(tcg_env); 42148f75b8a4SRichard Henderson } else { 42158f75b8a4SRichard Henderson gen_helper_retry(tcg_env); 42168f75b8a4SRichard Henderson } 42178f75b8a4SRichard Henderson return true; 42188f75b8a4SRichard Henderson } 42198f75b8a4SRichard Henderson 42208f75b8a4SRichard Henderson TRANS(DONE, 64, do_done_retry, true) 42218f75b8a4SRichard Henderson TRANS(RETRY, 64, do_done_retry, false) 42228f75b8a4SRichard Henderson 42230880d20bSRichard Henderson /* 42240880d20bSRichard Henderson * Major opcode 11 -- load and store instructions 42250880d20bSRichard Henderson */ 42260880d20bSRichard Henderson 42270880d20bSRichard Henderson static TCGv gen_ldst_addr(DisasContext *dc, int rs1, bool imm, int rs2_or_imm) 42280880d20bSRichard Henderson { 42290880d20bSRichard Henderson TCGv addr, tmp = NULL; 42300880d20bSRichard Henderson 42310880d20bSRichard Henderson /* For simplicity, we under-decoded the rs2 form. */ 42320880d20bSRichard Henderson if (!imm && rs2_or_imm & ~0x1f) { 42330880d20bSRichard Henderson return NULL; 42340880d20bSRichard Henderson } 42350880d20bSRichard Henderson 42360880d20bSRichard Henderson addr = gen_load_gpr(dc, rs1); 42370880d20bSRichard Henderson if (rs2_or_imm) { 42380880d20bSRichard Henderson tmp = tcg_temp_new(); 42390880d20bSRichard Henderson if (imm) { 42400880d20bSRichard Henderson tcg_gen_addi_tl(tmp, addr, rs2_or_imm); 42410880d20bSRichard Henderson } else { 42420880d20bSRichard Henderson tcg_gen_add_tl(tmp, addr, cpu_regs[rs2_or_imm]); 42430880d20bSRichard Henderson } 42440880d20bSRichard Henderson addr = tmp; 42450880d20bSRichard Henderson } 42460880d20bSRichard Henderson if (AM_CHECK(dc)) { 42470880d20bSRichard Henderson if (!tmp) { 42480880d20bSRichard Henderson tmp = tcg_temp_new(); 42490880d20bSRichard Henderson } 42500880d20bSRichard Henderson tcg_gen_ext32u_tl(tmp, addr); 42510880d20bSRichard Henderson addr = tmp; 42520880d20bSRichard Henderson } 42530880d20bSRichard Henderson return addr; 42540880d20bSRichard Henderson } 42550880d20bSRichard Henderson 42560880d20bSRichard Henderson static bool do_ld_gpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp mop) 42570880d20bSRichard Henderson { 42580880d20bSRichard Henderson TCGv reg, addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 42590880d20bSRichard Henderson DisasASI da; 42600880d20bSRichard Henderson 42610880d20bSRichard Henderson if (addr == NULL) { 42620880d20bSRichard Henderson return false; 42630880d20bSRichard Henderson } 42640880d20bSRichard Henderson da = resolve_asi(dc, a->asi, mop); 42650880d20bSRichard Henderson 42660880d20bSRichard Henderson reg = gen_dest_gpr(dc, a->rd); 426742071fc1SRichard Henderson gen_ld_asi(dc, &da, reg, addr); 42680880d20bSRichard Henderson gen_store_gpr(dc, a->rd, reg); 42690880d20bSRichard Henderson return advance_pc(dc); 42700880d20bSRichard Henderson } 42710880d20bSRichard Henderson 42720880d20bSRichard Henderson TRANS(LDUW, ALL, do_ld_gpr, a, MO_TEUL) 42730880d20bSRichard Henderson TRANS(LDUB, ALL, do_ld_gpr, a, MO_UB) 42740880d20bSRichard Henderson TRANS(LDUH, ALL, do_ld_gpr, a, MO_TEUW) 42750880d20bSRichard Henderson TRANS(LDSB, ALL, do_ld_gpr, a, MO_SB) 42760880d20bSRichard Henderson TRANS(LDSH, ALL, do_ld_gpr, a, MO_TESW) 42770880d20bSRichard Henderson TRANS(LDSW, 64, do_ld_gpr, a, MO_TESL) 42780880d20bSRichard Henderson TRANS(LDX, 64, do_ld_gpr, a, MO_TEUQ) 42790880d20bSRichard Henderson 42800880d20bSRichard Henderson static bool do_st_gpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp mop) 42810880d20bSRichard Henderson { 42820880d20bSRichard Henderson TCGv reg, addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 42830880d20bSRichard Henderson DisasASI da; 42840880d20bSRichard Henderson 42850880d20bSRichard Henderson if (addr == NULL) { 42860880d20bSRichard Henderson return false; 42870880d20bSRichard Henderson } 42880880d20bSRichard Henderson da = resolve_asi(dc, a->asi, mop); 42890880d20bSRichard Henderson 42900880d20bSRichard Henderson reg = gen_load_gpr(dc, a->rd); 429142071fc1SRichard Henderson gen_st_asi(dc, &da, reg, addr); 42920880d20bSRichard Henderson return advance_pc(dc); 42930880d20bSRichard Henderson } 42940880d20bSRichard Henderson 42950880d20bSRichard Henderson TRANS(STW, ALL, do_st_gpr, a, MO_TEUL) 42960880d20bSRichard Henderson TRANS(STB, ALL, do_st_gpr, a, MO_UB) 42970880d20bSRichard Henderson TRANS(STH, ALL, do_st_gpr, a, MO_TEUW) 42980880d20bSRichard Henderson TRANS(STX, 64, do_st_gpr, a, MO_TEUQ) 42990880d20bSRichard Henderson 43000880d20bSRichard Henderson static bool trans_LDD(DisasContext *dc, arg_r_r_ri_asi *a) 43010880d20bSRichard Henderson { 43020880d20bSRichard Henderson TCGv addr; 43030880d20bSRichard Henderson DisasASI da; 43040880d20bSRichard Henderson 43050880d20bSRichard Henderson if (a->rd & 1) { 43060880d20bSRichard Henderson return false; 43070880d20bSRichard Henderson } 43080880d20bSRichard Henderson addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 43090880d20bSRichard Henderson if (addr == NULL) { 43100880d20bSRichard Henderson return false; 43110880d20bSRichard Henderson } 43120880d20bSRichard Henderson da = resolve_asi(dc, a->asi, MO_TEUQ); 431342071fc1SRichard Henderson gen_ldda_asi(dc, &da, addr, a->rd); 43140880d20bSRichard Henderson return advance_pc(dc); 43150880d20bSRichard Henderson } 43160880d20bSRichard Henderson 43170880d20bSRichard Henderson static bool trans_STD(DisasContext *dc, arg_r_r_ri_asi *a) 43180880d20bSRichard Henderson { 43190880d20bSRichard Henderson TCGv addr; 43200880d20bSRichard Henderson DisasASI da; 43210880d20bSRichard Henderson 43220880d20bSRichard Henderson if (a->rd & 1) { 43230880d20bSRichard Henderson return false; 43240880d20bSRichard Henderson } 43250880d20bSRichard Henderson addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 43260880d20bSRichard Henderson if (addr == NULL) { 43270880d20bSRichard Henderson return false; 43280880d20bSRichard Henderson } 43290880d20bSRichard Henderson da = resolve_asi(dc, a->asi, MO_TEUQ); 433042071fc1SRichard Henderson gen_stda_asi(dc, &da, addr, a->rd); 43310880d20bSRichard Henderson return advance_pc(dc); 43320880d20bSRichard Henderson } 43330880d20bSRichard Henderson 4334cf07cd1eSRichard Henderson static bool trans_LDSTUB(DisasContext *dc, arg_r_r_ri_asi *a) 4335cf07cd1eSRichard Henderson { 4336cf07cd1eSRichard Henderson TCGv addr, reg; 4337cf07cd1eSRichard Henderson DisasASI da; 4338cf07cd1eSRichard Henderson 4339cf07cd1eSRichard Henderson addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 4340cf07cd1eSRichard Henderson if (addr == NULL) { 4341cf07cd1eSRichard Henderson return false; 4342cf07cd1eSRichard Henderson } 4343cf07cd1eSRichard Henderson da = resolve_asi(dc, a->asi, MO_UB); 4344cf07cd1eSRichard Henderson 4345cf07cd1eSRichard Henderson reg = gen_dest_gpr(dc, a->rd); 4346cf07cd1eSRichard Henderson gen_ldstub_asi(dc, &da, reg, addr); 4347cf07cd1eSRichard Henderson gen_store_gpr(dc, a->rd, reg); 4348cf07cd1eSRichard Henderson return advance_pc(dc); 4349cf07cd1eSRichard Henderson } 4350cf07cd1eSRichard Henderson 4351dca544b9SRichard Henderson static bool trans_SWAP(DisasContext *dc, arg_r_r_ri_asi *a) 4352dca544b9SRichard Henderson { 4353dca544b9SRichard Henderson TCGv addr, dst, src; 4354dca544b9SRichard Henderson DisasASI da; 4355dca544b9SRichard Henderson 4356dca544b9SRichard Henderson addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 4357dca544b9SRichard Henderson if (addr == NULL) { 4358dca544b9SRichard Henderson return false; 4359dca544b9SRichard Henderson } 4360dca544b9SRichard Henderson da = resolve_asi(dc, a->asi, MO_TEUL); 4361dca544b9SRichard Henderson 4362dca544b9SRichard Henderson dst = gen_dest_gpr(dc, a->rd); 4363dca544b9SRichard Henderson src = gen_load_gpr(dc, a->rd); 4364dca544b9SRichard Henderson gen_swap_asi(dc, &da, dst, src, addr); 4365dca544b9SRichard Henderson gen_store_gpr(dc, a->rd, dst); 4366dca544b9SRichard Henderson return advance_pc(dc); 4367dca544b9SRichard Henderson } 4368dca544b9SRichard Henderson 4369d0a11d25SRichard Henderson static bool do_casa(DisasContext *dc, arg_r_r_ri_asi *a, MemOp mop) 4370d0a11d25SRichard Henderson { 4371d0a11d25SRichard Henderson TCGv addr, o, n, c; 4372d0a11d25SRichard Henderson DisasASI da; 4373d0a11d25SRichard Henderson 4374d0a11d25SRichard Henderson addr = gen_ldst_addr(dc, a->rs1, true, 0); 4375d0a11d25SRichard Henderson if (addr == NULL) { 4376d0a11d25SRichard Henderson return false; 4377d0a11d25SRichard Henderson } 4378d0a11d25SRichard Henderson da = resolve_asi(dc, a->asi, mop); 4379d0a11d25SRichard Henderson 4380d0a11d25SRichard Henderson o = gen_dest_gpr(dc, a->rd); 4381d0a11d25SRichard Henderson n = gen_load_gpr(dc, a->rd); 4382d0a11d25SRichard Henderson c = gen_load_gpr(dc, a->rs2_or_imm); 4383d0a11d25SRichard Henderson gen_cas_asi(dc, &da, o, n, c, addr); 4384d0a11d25SRichard Henderson gen_store_gpr(dc, a->rd, o); 4385d0a11d25SRichard Henderson return advance_pc(dc); 4386d0a11d25SRichard Henderson } 4387d0a11d25SRichard Henderson 4388d0a11d25SRichard Henderson TRANS(CASA, CASA, do_casa, a, MO_TEUL) 4389d0a11d25SRichard Henderson TRANS(CASXA, 64, do_casa, a, MO_TEUQ) 4390d0a11d25SRichard Henderson 439106c060d9SRichard Henderson static bool do_ld_fpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp sz) 439206c060d9SRichard Henderson { 439306c060d9SRichard Henderson TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 439406c060d9SRichard Henderson DisasASI da; 439506c060d9SRichard Henderson 439606c060d9SRichard Henderson if (addr == NULL) { 439706c060d9SRichard Henderson return false; 439806c060d9SRichard Henderson } 439906c060d9SRichard Henderson if (gen_trap_ifnofpu(dc)) { 440006c060d9SRichard Henderson return true; 440106c060d9SRichard Henderson } 440206c060d9SRichard Henderson if (sz == MO_128 && gen_trap_float128(dc)) { 440306c060d9SRichard Henderson return true; 440406c060d9SRichard Henderson } 440506c060d9SRichard Henderson da = resolve_asi(dc, a->asi, MO_TE | sz); 4406287b1152SRichard Henderson gen_ldf_asi(dc, &da, sz, addr, a->rd); 440706c060d9SRichard Henderson gen_update_fprs_dirty(dc, a->rd); 440806c060d9SRichard Henderson return advance_pc(dc); 440906c060d9SRichard Henderson } 441006c060d9SRichard Henderson 441106c060d9SRichard Henderson TRANS(LDF, ALL, do_ld_fpr, a, MO_32) 441206c060d9SRichard Henderson TRANS(LDDF, ALL, do_ld_fpr, a, MO_64) 441306c060d9SRichard Henderson TRANS(LDQF, ALL, do_ld_fpr, a, MO_128) 441406c060d9SRichard Henderson 4415287b1152SRichard Henderson TRANS(LDFA, 64, do_ld_fpr, a, MO_32) 4416287b1152SRichard Henderson TRANS(LDDFA, 64, do_ld_fpr, a, MO_64) 4417287b1152SRichard Henderson TRANS(LDQFA, 64, do_ld_fpr, a, MO_128) 4418287b1152SRichard Henderson 441906c060d9SRichard Henderson static bool do_st_fpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp sz) 442006c060d9SRichard Henderson { 442106c060d9SRichard Henderson TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 442206c060d9SRichard Henderson DisasASI da; 442306c060d9SRichard Henderson 442406c060d9SRichard Henderson if (addr == NULL) { 442506c060d9SRichard Henderson return false; 442606c060d9SRichard Henderson } 442706c060d9SRichard Henderson if (gen_trap_ifnofpu(dc)) { 442806c060d9SRichard Henderson return true; 442906c060d9SRichard Henderson } 443006c060d9SRichard Henderson if (sz == MO_128 && gen_trap_float128(dc)) { 443106c060d9SRichard Henderson return true; 443206c060d9SRichard Henderson } 443306c060d9SRichard Henderson da = resolve_asi(dc, a->asi, MO_TE | sz); 4434287b1152SRichard Henderson gen_stf_asi(dc, &da, sz, addr, a->rd); 443506c060d9SRichard Henderson return advance_pc(dc); 443606c060d9SRichard Henderson } 443706c060d9SRichard Henderson 443806c060d9SRichard Henderson TRANS(STF, ALL, do_st_fpr, a, MO_32) 443906c060d9SRichard Henderson TRANS(STDF, ALL, do_st_fpr, a, MO_64) 444006c060d9SRichard Henderson TRANS(STQF, ALL, do_st_fpr, a, MO_128) 444106c060d9SRichard Henderson 4442287b1152SRichard Henderson TRANS(STFA, 64, do_st_fpr, a, MO_32) 4443287b1152SRichard Henderson TRANS(STDFA, 64, do_st_fpr, a, MO_64) 4444287b1152SRichard Henderson TRANS(STQFA, 64, do_st_fpr, a, MO_128) 4445287b1152SRichard Henderson 444606c060d9SRichard Henderson static bool trans_STDFQ(DisasContext *dc, arg_STDFQ *a) 444706c060d9SRichard Henderson { 444806c060d9SRichard Henderson if (!avail_32(dc)) { 444906c060d9SRichard Henderson return false; 445006c060d9SRichard Henderson } 445106c060d9SRichard Henderson if (!supervisor(dc)) { 445206c060d9SRichard Henderson return raise_priv(dc); 445306c060d9SRichard Henderson } 445406c060d9SRichard Henderson if (gen_trap_ifnofpu(dc)) { 445506c060d9SRichard Henderson return true; 445606c060d9SRichard Henderson } 445706c060d9SRichard Henderson gen_op_fpexception_im(dc, FSR_FTT_SEQ_ERROR); 445806c060d9SRichard Henderson return true; 445906c060d9SRichard Henderson } 446006c060d9SRichard Henderson 4461da681406SRichard Henderson static bool do_ldfsr(DisasContext *dc, arg_r_r_ri *a, MemOp mop, 4462da681406SRichard Henderson target_ulong new_mask, target_ulong old_mask) 44633d3c0673SRichard Henderson { 4464da681406SRichard Henderson TCGv tmp, addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 44653d3c0673SRichard Henderson if (addr == NULL) { 44663d3c0673SRichard Henderson return false; 44673d3c0673SRichard Henderson } 44683d3c0673SRichard Henderson if (gen_trap_ifnofpu(dc)) { 44693d3c0673SRichard Henderson return true; 44703d3c0673SRichard Henderson } 4471da681406SRichard Henderson tmp = tcg_temp_new(); 4472da681406SRichard Henderson tcg_gen_qemu_ld_tl(tmp, addr, dc->mem_idx, mop | MO_ALIGN); 4473da681406SRichard Henderson tcg_gen_andi_tl(tmp, tmp, new_mask); 4474da681406SRichard Henderson tcg_gen_andi_tl(cpu_fsr, cpu_fsr, old_mask); 4475da681406SRichard Henderson tcg_gen_or_tl(cpu_fsr, cpu_fsr, tmp); 4476da681406SRichard Henderson gen_helper_set_fsr(tcg_env, cpu_fsr); 44773d3c0673SRichard Henderson return advance_pc(dc); 44783d3c0673SRichard Henderson } 44793d3c0673SRichard Henderson 4480da681406SRichard Henderson TRANS(LDFSR, ALL, do_ldfsr, a, MO_TEUL, FSR_LDFSR_MASK, FSR_LDFSR_OLDMASK) 4481da681406SRichard Henderson TRANS(LDXFSR, 64, do_ldfsr, a, MO_TEUQ, FSR_LDXFSR_MASK, FSR_LDXFSR_OLDMASK) 44823d3c0673SRichard Henderson 44833d3c0673SRichard Henderson static bool do_stfsr(DisasContext *dc, arg_r_r_ri *a, MemOp mop) 44843d3c0673SRichard Henderson { 44853d3c0673SRichard Henderson TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 44863d3c0673SRichard Henderson if (addr == NULL) { 44873d3c0673SRichard Henderson return false; 44883d3c0673SRichard Henderson } 44893d3c0673SRichard Henderson if (gen_trap_ifnofpu(dc)) { 44903d3c0673SRichard Henderson return true; 44913d3c0673SRichard Henderson } 44923d3c0673SRichard Henderson tcg_gen_qemu_st_tl(cpu_fsr, addr, dc->mem_idx, mop | MO_ALIGN); 44933d3c0673SRichard Henderson return advance_pc(dc); 44943d3c0673SRichard Henderson } 44953d3c0673SRichard Henderson 44963d3c0673SRichard Henderson TRANS(STFSR, ALL, do_stfsr, a, MO_TEUL) 44973d3c0673SRichard Henderson TRANS(STXFSR, 64, do_stfsr, a, MO_TEUQ) 44983d3c0673SRichard Henderson 44993a38260eSRichard Henderson static bool do_fc(DisasContext *dc, int rd, bool c) 45003a38260eSRichard Henderson { 45013a38260eSRichard Henderson uint64_t mask; 45023a38260eSRichard Henderson 45033a38260eSRichard Henderson if (gen_trap_ifnofpu(dc)) { 45043a38260eSRichard Henderson return true; 45053a38260eSRichard Henderson } 45063a38260eSRichard Henderson 45073a38260eSRichard Henderson if (rd & 1) { 45083a38260eSRichard Henderson mask = MAKE_64BIT_MASK(0, 32); 45093a38260eSRichard Henderson } else { 45103a38260eSRichard Henderson mask = MAKE_64BIT_MASK(32, 32); 45113a38260eSRichard Henderson } 45123a38260eSRichard Henderson if (c) { 45133a38260eSRichard Henderson tcg_gen_ori_i64(cpu_fpr[rd / 2], cpu_fpr[rd / 2], mask); 45143a38260eSRichard Henderson } else { 45153a38260eSRichard Henderson tcg_gen_andi_i64(cpu_fpr[rd / 2], cpu_fpr[rd / 2], ~mask); 45163a38260eSRichard Henderson } 45173a38260eSRichard Henderson gen_update_fprs_dirty(dc, rd); 45183a38260eSRichard Henderson return advance_pc(dc); 45193a38260eSRichard Henderson } 45203a38260eSRichard Henderson 45213a38260eSRichard Henderson TRANS(FZEROs, VIS1, do_fc, a->rd, 0) 45223a38260eSRichard Henderson TRANS(FONEs, VIS1, do_fc, a->rd, 1) 45233a38260eSRichard Henderson 45243a38260eSRichard Henderson static bool do_dc(DisasContext *dc, int rd, int64_t c) 45253a38260eSRichard Henderson { 45263a38260eSRichard Henderson if (gen_trap_ifnofpu(dc)) { 45273a38260eSRichard Henderson return true; 45283a38260eSRichard Henderson } 45293a38260eSRichard Henderson 45303a38260eSRichard Henderson tcg_gen_movi_i64(cpu_fpr[rd / 2], c); 45313a38260eSRichard Henderson gen_update_fprs_dirty(dc, rd); 45323a38260eSRichard Henderson return advance_pc(dc); 45333a38260eSRichard Henderson } 45343a38260eSRichard Henderson 45353a38260eSRichard Henderson TRANS(FZEROd, VIS1, do_dc, a->rd, 0) 45363a38260eSRichard Henderson TRANS(FONEd, VIS1, do_dc, a->rd, -1) 45373a38260eSRichard Henderson 4538baf3dbf2SRichard Henderson static bool do_ff(DisasContext *dc, arg_r_r *a, 4539baf3dbf2SRichard Henderson void (*func)(TCGv_i32, TCGv_i32)) 4540baf3dbf2SRichard Henderson { 4541baf3dbf2SRichard Henderson TCGv_i32 tmp; 4542baf3dbf2SRichard Henderson 4543baf3dbf2SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4544baf3dbf2SRichard Henderson return true; 4545baf3dbf2SRichard Henderson } 4546baf3dbf2SRichard Henderson 4547baf3dbf2SRichard Henderson tmp = gen_load_fpr_F(dc, a->rs); 4548baf3dbf2SRichard Henderson func(tmp, tmp); 4549baf3dbf2SRichard Henderson gen_store_fpr_F(dc, a->rd, tmp); 4550baf3dbf2SRichard Henderson return advance_pc(dc); 4551baf3dbf2SRichard Henderson } 4552baf3dbf2SRichard Henderson 4553baf3dbf2SRichard Henderson TRANS(FMOVs, ALL, do_ff, a, gen_op_fmovs) 4554baf3dbf2SRichard Henderson TRANS(FNEGs, ALL, do_ff, a, gen_op_fnegs) 4555baf3dbf2SRichard Henderson TRANS(FABSs, ALL, do_ff, a, gen_op_fabss) 4556baf3dbf2SRichard Henderson TRANS(FSRCs, VIS1, do_ff, a, tcg_gen_mov_i32) 4557baf3dbf2SRichard Henderson TRANS(FNOTs, VIS1, do_ff, a, tcg_gen_not_i32) 4558baf3dbf2SRichard Henderson 45592f722641SRichard Henderson static bool do_fd(DisasContext *dc, arg_r_r *a, 45602f722641SRichard Henderson void (*func)(TCGv_i32, TCGv_i64)) 45612f722641SRichard Henderson { 45622f722641SRichard Henderson TCGv_i32 dst; 45632f722641SRichard Henderson TCGv_i64 src; 45642f722641SRichard Henderson 45652f722641SRichard Henderson if (gen_trap_ifnofpu(dc)) { 45662f722641SRichard Henderson return true; 45672f722641SRichard Henderson } 45682f722641SRichard Henderson 45692f722641SRichard Henderson dst = gen_dest_fpr_F(dc); 45702f722641SRichard Henderson src = gen_load_fpr_D(dc, a->rs); 45712f722641SRichard Henderson func(dst, src); 45722f722641SRichard Henderson gen_store_fpr_F(dc, a->rd, dst); 45732f722641SRichard Henderson return advance_pc(dc); 45742f722641SRichard Henderson } 45752f722641SRichard Henderson 45762f722641SRichard Henderson TRANS(FPACK16, VIS1, do_fd, a, gen_op_fpack16) 45772f722641SRichard Henderson TRANS(FPACKFIX, VIS1, do_fd, a, gen_op_fpackfix) 45782f722641SRichard Henderson 4579119cb94fSRichard Henderson static bool do_env_ff(DisasContext *dc, arg_r_r *a, 4580119cb94fSRichard Henderson void (*func)(TCGv_i32, TCGv_env, TCGv_i32)) 4581119cb94fSRichard Henderson { 4582119cb94fSRichard Henderson TCGv_i32 tmp; 4583119cb94fSRichard Henderson 4584119cb94fSRichard Henderson if (gen_trap_ifnofpu(dc)) { 4585119cb94fSRichard Henderson return true; 4586119cb94fSRichard Henderson } 4587119cb94fSRichard Henderson 4588119cb94fSRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 4589119cb94fSRichard Henderson tmp = gen_load_fpr_F(dc, a->rs); 4590119cb94fSRichard Henderson func(tmp, tcg_env, tmp); 4591119cb94fSRichard Henderson gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env); 4592119cb94fSRichard Henderson gen_store_fpr_F(dc, a->rd, tmp); 4593119cb94fSRichard Henderson return advance_pc(dc); 4594119cb94fSRichard Henderson } 4595119cb94fSRichard Henderson 4596119cb94fSRichard Henderson TRANS(FSQRTs, ALL, do_env_ff, a, gen_helper_fsqrts) 4597119cb94fSRichard Henderson TRANS(FiTOs, ALL, do_env_ff, a, gen_helper_fitos) 4598119cb94fSRichard Henderson TRANS(FsTOi, ALL, do_env_ff, a, gen_helper_fstoi) 4599119cb94fSRichard Henderson 46008c94bcd8SRichard Henderson static bool do_env_fd(DisasContext *dc, arg_r_r *a, 46018c94bcd8SRichard Henderson void (*func)(TCGv_i32, TCGv_env, TCGv_i64)) 46028c94bcd8SRichard Henderson { 46038c94bcd8SRichard Henderson TCGv_i32 dst; 46048c94bcd8SRichard Henderson TCGv_i64 src; 46058c94bcd8SRichard Henderson 46068c94bcd8SRichard Henderson if (gen_trap_ifnofpu(dc)) { 46078c94bcd8SRichard Henderson return true; 46088c94bcd8SRichard Henderson } 46098c94bcd8SRichard Henderson 46108c94bcd8SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 46118c94bcd8SRichard Henderson dst = gen_dest_fpr_F(dc); 46128c94bcd8SRichard Henderson src = gen_load_fpr_D(dc, a->rs); 46138c94bcd8SRichard Henderson func(dst, tcg_env, src); 46148c94bcd8SRichard Henderson gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env); 46158c94bcd8SRichard Henderson gen_store_fpr_F(dc, a->rd, dst); 46168c94bcd8SRichard Henderson return advance_pc(dc); 46178c94bcd8SRichard Henderson } 46188c94bcd8SRichard Henderson 46198c94bcd8SRichard Henderson TRANS(FdTOs, ALL, do_env_fd, a, gen_helper_fdtos) 46208c94bcd8SRichard Henderson TRANS(FdTOi, ALL, do_env_fd, a, gen_helper_fdtoi) 46218c94bcd8SRichard Henderson TRANS(FxTOs, 64, do_env_fd, a, gen_helper_fxtos) 46228c94bcd8SRichard Henderson 4623c6d83e4fSRichard Henderson static bool do_dd(DisasContext *dc, arg_r_r *a, 4624c6d83e4fSRichard Henderson void (*func)(TCGv_i64, TCGv_i64)) 4625c6d83e4fSRichard Henderson { 4626c6d83e4fSRichard Henderson TCGv_i64 dst, src; 4627c6d83e4fSRichard Henderson 4628c6d83e4fSRichard Henderson if (gen_trap_ifnofpu(dc)) { 4629c6d83e4fSRichard Henderson return true; 4630c6d83e4fSRichard Henderson } 4631c6d83e4fSRichard Henderson 4632c6d83e4fSRichard Henderson dst = gen_dest_fpr_D(dc, a->rd); 4633c6d83e4fSRichard Henderson src = gen_load_fpr_D(dc, a->rs); 4634c6d83e4fSRichard Henderson func(dst, src); 4635c6d83e4fSRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 4636c6d83e4fSRichard Henderson return advance_pc(dc); 4637c6d83e4fSRichard Henderson } 4638c6d83e4fSRichard Henderson 4639c6d83e4fSRichard Henderson TRANS(FMOVd, 64, do_dd, a, gen_op_fmovd) 4640c6d83e4fSRichard Henderson TRANS(FNEGd, 64, do_dd, a, gen_op_fnegd) 4641c6d83e4fSRichard Henderson TRANS(FABSd, 64, do_dd, a, gen_op_fabsd) 4642c6d83e4fSRichard Henderson TRANS(FSRCd, VIS1, do_dd, a, tcg_gen_mov_i64) 4643c6d83e4fSRichard Henderson TRANS(FNOTd, VIS1, do_dd, a, tcg_gen_not_i64) 4644c6d83e4fSRichard Henderson 46458aa418b3SRichard Henderson static bool do_env_dd(DisasContext *dc, arg_r_r *a, 46468aa418b3SRichard Henderson void (*func)(TCGv_i64, TCGv_env, TCGv_i64)) 46478aa418b3SRichard Henderson { 46488aa418b3SRichard Henderson TCGv_i64 dst, src; 46498aa418b3SRichard Henderson 46508aa418b3SRichard Henderson if (gen_trap_ifnofpu(dc)) { 46518aa418b3SRichard Henderson return true; 46528aa418b3SRichard Henderson } 46538aa418b3SRichard Henderson 46548aa418b3SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 46558aa418b3SRichard Henderson dst = gen_dest_fpr_D(dc, a->rd); 46568aa418b3SRichard Henderson src = gen_load_fpr_D(dc, a->rs); 46578aa418b3SRichard Henderson func(dst, tcg_env, src); 46588aa418b3SRichard Henderson gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env); 46598aa418b3SRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 46608aa418b3SRichard Henderson return advance_pc(dc); 46618aa418b3SRichard Henderson } 46628aa418b3SRichard Henderson 46638aa418b3SRichard Henderson TRANS(FSQRTd, ALL, do_env_dd, a, gen_helper_fsqrtd) 46648aa418b3SRichard Henderson TRANS(FxTOd, 64, do_env_dd, a, gen_helper_fxtod) 46658aa418b3SRichard Henderson TRANS(FdTOx, 64, do_env_dd, a, gen_helper_fdtox) 46668aa418b3SRichard Henderson 4667199d43efSRichard Henderson static bool do_env_df(DisasContext *dc, arg_r_r *a, 4668199d43efSRichard Henderson void (*func)(TCGv_i64, TCGv_env, TCGv_i32)) 4669199d43efSRichard Henderson { 4670199d43efSRichard Henderson TCGv_i64 dst; 4671199d43efSRichard Henderson TCGv_i32 src; 4672199d43efSRichard Henderson 4673199d43efSRichard Henderson if (gen_trap_ifnofpu(dc)) { 4674199d43efSRichard Henderson return true; 4675199d43efSRichard Henderson } 4676199d43efSRichard Henderson 4677199d43efSRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 4678199d43efSRichard Henderson dst = gen_dest_fpr_D(dc, a->rd); 4679199d43efSRichard Henderson src = gen_load_fpr_F(dc, a->rs); 4680199d43efSRichard Henderson func(dst, tcg_env, src); 4681199d43efSRichard Henderson gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env); 4682199d43efSRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 4683199d43efSRichard Henderson return advance_pc(dc); 4684199d43efSRichard Henderson } 4685199d43efSRichard Henderson 4686199d43efSRichard Henderson TRANS(FiTOd, ALL, do_env_df, a, gen_helper_fitod) 4687199d43efSRichard Henderson TRANS(FsTOd, ALL, do_env_df, a, gen_helper_fstod) 4688199d43efSRichard Henderson TRANS(FsTOx, 64, do_env_df, a, gen_helper_fstox) 4689199d43efSRichard Henderson 4690f4e18df5SRichard Henderson static bool trans_FMOVq(DisasContext *dc, arg_FMOVq *a) 4691f4e18df5SRichard Henderson { 4692f4e18df5SRichard Henderson int rd, rs; 4693f4e18df5SRichard Henderson 4694f4e18df5SRichard Henderson if (!avail_64(dc)) { 4695f4e18df5SRichard Henderson return false; 4696f4e18df5SRichard Henderson } 4697f4e18df5SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4698f4e18df5SRichard Henderson return true; 4699f4e18df5SRichard Henderson } 4700f4e18df5SRichard Henderson if (gen_trap_float128(dc)) { 4701f4e18df5SRichard Henderson return true; 4702f4e18df5SRichard Henderson } 4703f4e18df5SRichard Henderson 4704f4e18df5SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 4705f4e18df5SRichard Henderson rd = QFPREG(a->rd); 4706f4e18df5SRichard Henderson rs = QFPREG(a->rs); 4707f4e18df5SRichard Henderson tcg_gen_mov_i64(cpu_fpr[rd / 2], cpu_fpr[rs / 2]); 4708f4e18df5SRichard Henderson tcg_gen_mov_i64(cpu_fpr[rd / 2 + 1], cpu_fpr[rs / 2 + 1]); 4709f4e18df5SRichard Henderson gen_update_fprs_dirty(dc, rd); 4710f4e18df5SRichard Henderson return advance_pc(dc); 4711f4e18df5SRichard Henderson } 4712f4e18df5SRichard Henderson 4713f4e18df5SRichard Henderson static bool do_qq(DisasContext *dc, arg_r_r *a, 4714f4e18df5SRichard Henderson void (*func)(TCGv_env)) 4715f4e18df5SRichard Henderson { 4716f4e18df5SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4717f4e18df5SRichard Henderson return true; 4718f4e18df5SRichard Henderson } 4719f4e18df5SRichard Henderson if (gen_trap_float128(dc)) { 4720f4e18df5SRichard Henderson return true; 4721f4e18df5SRichard Henderson } 4722f4e18df5SRichard Henderson 4723f4e18df5SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 4724f4e18df5SRichard Henderson gen_op_load_fpr_QT1(QFPREG(a->rs)); 4725f4e18df5SRichard Henderson func(tcg_env); 4726f4e18df5SRichard Henderson gen_op_store_QT0_fpr(QFPREG(a->rd)); 4727f4e18df5SRichard Henderson gen_update_fprs_dirty(dc, QFPREG(a->rd)); 4728f4e18df5SRichard Henderson return advance_pc(dc); 4729f4e18df5SRichard Henderson } 4730f4e18df5SRichard Henderson 4731f4e18df5SRichard Henderson TRANS(FNEGq, 64, do_qq, a, gen_helper_fnegq) 4732f4e18df5SRichard Henderson TRANS(FABSq, 64, do_qq, a, gen_helper_fabsq) 4733f4e18df5SRichard Henderson 4734c995216bSRichard Henderson static bool do_env_qq(DisasContext *dc, arg_r_r *a, 4735c995216bSRichard Henderson void (*func)(TCGv_env)) 4736c995216bSRichard Henderson { 4737c995216bSRichard Henderson if (gen_trap_ifnofpu(dc)) { 4738c995216bSRichard Henderson return true; 4739c995216bSRichard Henderson } 4740c995216bSRichard Henderson if (gen_trap_float128(dc)) { 4741c995216bSRichard Henderson return true; 4742c995216bSRichard Henderson } 4743c995216bSRichard Henderson 4744c995216bSRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 4745c995216bSRichard Henderson gen_op_load_fpr_QT1(QFPREG(a->rs)); 4746c995216bSRichard Henderson func(tcg_env); 4747c995216bSRichard Henderson gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env); 4748c995216bSRichard Henderson gen_op_store_QT0_fpr(QFPREG(a->rd)); 4749c995216bSRichard Henderson gen_update_fprs_dirty(dc, QFPREG(a->rd)); 4750c995216bSRichard Henderson return advance_pc(dc); 4751c995216bSRichard Henderson } 4752c995216bSRichard Henderson 4753c995216bSRichard Henderson TRANS(FSQRTq, ALL, do_env_qq, a, gen_helper_fsqrtq) 4754c995216bSRichard Henderson 4755bd9c5c42SRichard Henderson static bool do_env_fq(DisasContext *dc, arg_r_r *a, 4756bd9c5c42SRichard Henderson void (*func)(TCGv_i32, TCGv_env)) 4757bd9c5c42SRichard Henderson { 4758bd9c5c42SRichard Henderson TCGv_i32 dst; 4759bd9c5c42SRichard Henderson 4760bd9c5c42SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4761bd9c5c42SRichard Henderson return true; 4762bd9c5c42SRichard Henderson } 4763bd9c5c42SRichard Henderson if (gen_trap_float128(dc)) { 4764bd9c5c42SRichard Henderson return true; 4765bd9c5c42SRichard Henderson } 4766bd9c5c42SRichard Henderson 4767bd9c5c42SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 4768bd9c5c42SRichard Henderson gen_op_load_fpr_QT1(QFPREG(a->rs)); 4769bd9c5c42SRichard Henderson dst = gen_dest_fpr_F(dc); 4770bd9c5c42SRichard Henderson func(dst, tcg_env); 4771bd9c5c42SRichard Henderson gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env); 4772bd9c5c42SRichard Henderson gen_store_fpr_F(dc, a->rd, dst); 4773bd9c5c42SRichard Henderson return advance_pc(dc); 4774bd9c5c42SRichard Henderson } 4775bd9c5c42SRichard Henderson 4776bd9c5c42SRichard Henderson TRANS(FqTOs, ALL, do_env_fq, a, gen_helper_fqtos) 4777bd9c5c42SRichard Henderson TRANS(FqTOi, ALL, do_env_fq, a, gen_helper_fqtoi) 4778bd9c5c42SRichard Henderson 47791617586fSRichard Henderson static bool do_env_dq(DisasContext *dc, arg_r_r *a, 47801617586fSRichard Henderson void (*func)(TCGv_i64, TCGv_env)) 47811617586fSRichard Henderson { 47821617586fSRichard Henderson TCGv_i64 dst; 47831617586fSRichard Henderson 47841617586fSRichard Henderson if (gen_trap_ifnofpu(dc)) { 47851617586fSRichard Henderson return true; 47861617586fSRichard Henderson } 47871617586fSRichard Henderson if (gen_trap_float128(dc)) { 47881617586fSRichard Henderson return true; 47891617586fSRichard Henderson } 47901617586fSRichard Henderson 47911617586fSRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 47921617586fSRichard Henderson gen_op_load_fpr_QT1(QFPREG(a->rs)); 47931617586fSRichard Henderson dst = gen_dest_fpr_D(dc, a->rd); 47941617586fSRichard Henderson func(dst, tcg_env); 47951617586fSRichard Henderson gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env); 47961617586fSRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 47971617586fSRichard Henderson return advance_pc(dc); 47981617586fSRichard Henderson } 47991617586fSRichard Henderson 48001617586fSRichard Henderson TRANS(FqTOd, ALL, do_env_dq, a, gen_helper_fqtod) 48011617586fSRichard Henderson TRANS(FqTOx, 64, do_env_dq, a, gen_helper_fqtox) 48021617586fSRichard Henderson 480313ebcc77SRichard Henderson static bool do_env_qf(DisasContext *dc, arg_r_r *a, 480413ebcc77SRichard Henderson void (*func)(TCGv_env, TCGv_i32)) 480513ebcc77SRichard Henderson { 480613ebcc77SRichard Henderson TCGv_i32 src; 480713ebcc77SRichard Henderson 480813ebcc77SRichard Henderson if (gen_trap_ifnofpu(dc)) { 480913ebcc77SRichard Henderson return true; 481013ebcc77SRichard Henderson } 481113ebcc77SRichard Henderson if (gen_trap_float128(dc)) { 481213ebcc77SRichard Henderson return true; 481313ebcc77SRichard Henderson } 481413ebcc77SRichard Henderson 481513ebcc77SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 481613ebcc77SRichard Henderson src = gen_load_fpr_F(dc, a->rs); 481713ebcc77SRichard Henderson func(tcg_env, src); 481813ebcc77SRichard Henderson gen_op_store_QT0_fpr(QFPREG(a->rd)); 481913ebcc77SRichard Henderson gen_update_fprs_dirty(dc, QFPREG(a->rd)); 482013ebcc77SRichard Henderson return advance_pc(dc); 482113ebcc77SRichard Henderson } 482213ebcc77SRichard Henderson 482313ebcc77SRichard Henderson TRANS(FiTOq, ALL, do_env_qf, a, gen_helper_fitoq) 482413ebcc77SRichard Henderson TRANS(FsTOq, ALL, do_env_qf, a, gen_helper_fstoq) 482513ebcc77SRichard Henderson 48267b8e3e1aSRichard Henderson static bool do_env_qd(DisasContext *dc, arg_r_r *a, 48277b8e3e1aSRichard Henderson void (*func)(TCGv_env, TCGv_i64)) 48287b8e3e1aSRichard Henderson { 48297b8e3e1aSRichard Henderson TCGv_i64 src; 48307b8e3e1aSRichard Henderson 48317b8e3e1aSRichard Henderson if (gen_trap_ifnofpu(dc)) { 48327b8e3e1aSRichard Henderson return true; 48337b8e3e1aSRichard Henderson } 48347b8e3e1aSRichard Henderson if (gen_trap_float128(dc)) { 48357b8e3e1aSRichard Henderson return true; 48367b8e3e1aSRichard Henderson } 48377b8e3e1aSRichard Henderson 48387b8e3e1aSRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 48397b8e3e1aSRichard Henderson src = gen_load_fpr_D(dc, a->rs); 48407b8e3e1aSRichard Henderson func(tcg_env, src); 48417b8e3e1aSRichard Henderson gen_op_store_QT0_fpr(QFPREG(a->rd)); 48427b8e3e1aSRichard Henderson gen_update_fprs_dirty(dc, QFPREG(a->rd)); 48437b8e3e1aSRichard Henderson return advance_pc(dc); 48447b8e3e1aSRichard Henderson } 48457b8e3e1aSRichard Henderson 48467b8e3e1aSRichard Henderson TRANS(FdTOq, ALL, do_env_qd, a, gen_helper_fdtoq) 48477b8e3e1aSRichard Henderson TRANS(FxTOq, 64, do_env_qd, a, gen_helper_fxtoq) 48487b8e3e1aSRichard Henderson 48497f10b52fSRichard Henderson static bool do_fff(DisasContext *dc, arg_r_r_r *a, 48507f10b52fSRichard Henderson void (*func)(TCGv_i32, TCGv_i32, TCGv_i32)) 48517f10b52fSRichard Henderson { 48527f10b52fSRichard Henderson TCGv_i32 src1, src2; 48537f10b52fSRichard Henderson 48547f10b52fSRichard Henderson if (gen_trap_ifnofpu(dc)) { 48557f10b52fSRichard Henderson return true; 48567f10b52fSRichard Henderson } 48577f10b52fSRichard Henderson 48587f10b52fSRichard Henderson src1 = gen_load_fpr_F(dc, a->rs1); 48597f10b52fSRichard Henderson src2 = gen_load_fpr_F(dc, a->rs2); 48607f10b52fSRichard Henderson func(src1, src1, src2); 48617f10b52fSRichard Henderson gen_store_fpr_F(dc, a->rd, src1); 48627f10b52fSRichard Henderson return advance_pc(dc); 48637f10b52fSRichard Henderson } 48647f10b52fSRichard Henderson 48657f10b52fSRichard Henderson TRANS(FPADD16s, VIS1, do_fff, a, tcg_gen_vec_add16_i32) 48667f10b52fSRichard Henderson TRANS(FPADD32s, VIS1, do_fff, a, tcg_gen_add_i32) 48677f10b52fSRichard Henderson TRANS(FPSUB16s, VIS1, do_fff, a, tcg_gen_vec_sub16_i32) 48687f10b52fSRichard Henderson TRANS(FPSUB32s, VIS1, do_fff, a, tcg_gen_sub_i32) 48697f10b52fSRichard Henderson TRANS(FNORs, VIS1, do_fff, a, tcg_gen_nor_i32) 48707f10b52fSRichard Henderson TRANS(FANDNOTs, VIS1, do_fff, a, tcg_gen_andc_i32) 48717f10b52fSRichard Henderson TRANS(FXORs, VIS1, do_fff, a, tcg_gen_xor_i32) 48727f10b52fSRichard Henderson TRANS(FNANDs, VIS1, do_fff, a, tcg_gen_nand_i32) 48737f10b52fSRichard Henderson TRANS(FANDs, VIS1, do_fff, a, tcg_gen_and_i32) 48747f10b52fSRichard Henderson TRANS(FXNORs, VIS1, do_fff, a, tcg_gen_eqv_i32) 48757f10b52fSRichard Henderson TRANS(FORNOTs, VIS1, do_fff, a, tcg_gen_orc_i32) 48767f10b52fSRichard Henderson TRANS(FORs, VIS1, do_fff, a, tcg_gen_or_i32) 48777f10b52fSRichard Henderson 4878c1514961SRichard Henderson static bool do_env_fff(DisasContext *dc, arg_r_r_r *a, 4879c1514961SRichard Henderson void (*func)(TCGv_i32, TCGv_env, TCGv_i32, TCGv_i32)) 4880c1514961SRichard Henderson { 4881c1514961SRichard Henderson TCGv_i32 src1, src2; 4882c1514961SRichard Henderson 4883c1514961SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4884c1514961SRichard Henderson return true; 4885c1514961SRichard Henderson } 4886c1514961SRichard Henderson 4887c1514961SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 4888c1514961SRichard Henderson src1 = gen_load_fpr_F(dc, a->rs1); 4889c1514961SRichard Henderson src2 = gen_load_fpr_F(dc, a->rs2); 4890c1514961SRichard Henderson func(src1, tcg_env, src1, src2); 4891c1514961SRichard Henderson gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env); 4892c1514961SRichard Henderson gen_store_fpr_F(dc, a->rd, src1); 4893c1514961SRichard Henderson return advance_pc(dc); 4894c1514961SRichard Henderson } 4895c1514961SRichard Henderson 4896c1514961SRichard Henderson TRANS(FADDs, ALL, do_env_fff, a, gen_helper_fadds) 4897c1514961SRichard Henderson TRANS(FSUBs, ALL, do_env_fff, a, gen_helper_fsubs) 4898c1514961SRichard Henderson TRANS(FMULs, ALL, do_env_fff, a, gen_helper_fmuls) 4899c1514961SRichard Henderson TRANS(FDIVs, ALL, do_env_fff, a, gen_helper_fdivs) 4900c1514961SRichard Henderson 4901e06c9f83SRichard Henderson static bool do_ddd(DisasContext *dc, arg_r_r_r *a, 4902e06c9f83SRichard Henderson void (*func)(TCGv_i64, TCGv_i64, TCGv_i64)) 4903e06c9f83SRichard Henderson { 4904e06c9f83SRichard Henderson TCGv_i64 dst, src1, src2; 4905e06c9f83SRichard Henderson 4906e06c9f83SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4907e06c9f83SRichard Henderson return true; 4908e06c9f83SRichard Henderson } 4909e06c9f83SRichard Henderson 4910e06c9f83SRichard Henderson dst = gen_dest_fpr_D(dc, a->rd); 4911e06c9f83SRichard Henderson src1 = gen_load_fpr_D(dc, a->rs1); 4912e06c9f83SRichard Henderson src2 = gen_load_fpr_D(dc, a->rs2); 4913e06c9f83SRichard Henderson func(dst, src1, src2); 4914e06c9f83SRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 4915e06c9f83SRichard Henderson return advance_pc(dc); 4916e06c9f83SRichard Henderson } 4917e06c9f83SRichard Henderson 4918e06c9f83SRichard Henderson TRANS(FMUL8x16, VIS1, do_ddd, a, gen_helper_fmul8x16) 4919e06c9f83SRichard Henderson TRANS(FMUL8x16AU, VIS1, do_ddd, a, gen_helper_fmul8x16au) 4920e06c9f83SRichard Henderson TRANS(FMUL8x16AL, VIS1, do_ddd, a, gen_helper_fmul8x16al) 4921e06c9f83SRichard Henderson TRANS(FMUL8SUx16, VIS1, do_ddd, a, gen_helper_fmul8sux16) 4922e06c9f83SRichard Henderson TRANS(FMUL8ULx16, VIS1, do_ddd, a, gen_helper_fmul8ulx16) 4923e06c9f83SRichard Henderson TRANS(FMULD8SUx16, VIS1, do_ddd, a, gen_helper_fmuld8sux16) 4924e06c9f83SRichard Henderson TRANS(FMULD8ULx16, VIS1, do_ddd, a, gen_helper_fmuld8ulx16) 4925e06c9f83SRichard Henderson TRANS(FPMERGE, VIS1, do_ddd, a, gen_helper_fpmerge) 4926e06c9f83SRichard Henderson TRANS(FEXPAND, VIS1, do_ddd, a, gen_helper_fexpand) 4927e06c9f83SRichard Henderson 4928e06c9f83SRichard Henderson TRANS(FPADD16, VIS1, do_ddd, a, tcg_gen_vec_add16_i64) 4929e06c9f83SRichard Henderson TRANS(FPADD32, VIS1, do_ddd, a, tcg_gen_vec_add32_i64) 4930e06c9f83SRichard Henderson TRANS(FPSUB16, VIS1, do_ddd, a, tcg_gen_vec_sub16_i64) 4931e06c9f83SRichard Henderson TRANS(FPSUB32, VIS1, do_ddd, a, tcg_gen_vec_sub32_i64) 4932e06c9f83SRichard Henderson TRANS(FNORd, VIS1, do_ddd, a, tcg_gen_nor_i64) 4933e06c9f83SRichard Henderson TRANS(FANDNOTd, VIS1, do_ddd, a, tcg_gen_andc_i64) 4934e06c9f83SRichard Henderson TRANS(FXORd, VIS1, do_ddd, a, tcg_gen_xor_i64) 4935e06c9f83SRichard Henderson TRANS(FNANDd, VIS1, do_ddd, a, tcg_gen_nand_i64) 4936e06c9f83SRichard Henderson TRANS(FANDd, VIS1, do_ddd, a, tcg_gen_and_i64) 4937e06c9f83SRichard Henderson TRANS(FXNORd, VIS1, do_ddd, a, tcg_gen_eqv_i64) 4938e06c9f83SRichard Henderson TRANS(FORNOTd, VIS1, do_ddd, a, tcg_gen_orc_i64) 4939e06c9f83SRichard Henderson TRANS(FORd, VIS1, do_ddd, a, tcg_gen_or_i64) 4940e06c9f83SRichard Henderson 49414b6edc0aSRichard Henderson TRANS(FPACK32, VIS1, do_ddd, a, gen_op_fpack32) 49424b6edc0aSRichard Henderson TRANS(FALIGNDATAg, VIS1, do_ddd, a, gen_op_faligndata) 49434b6edc0aSRichard Henderson TRANS(BSHUFFLE, VIS2, do_ddd, a, gen_op_bshuffle) 49444b6edc0aSRichard Henderson 4945e2fa6bd1SRichard Henderson static bool do_rdd(DisasContext *dc, arg_r_r_r *a, 4946e2fa6bd1SRichard Henderson void (*func)(TCGv, TCGv_i64, TCGv_i64)) 4947e2fa6bd1SRichard Henderson { 4948e2fa6bd1SRichard Henderson TCGv_i64 src1, src2; 4949e2fa6bd1SRichard Henderson TCGv dst; 4950e2fa6bd1SRichard Henderson 4951e2fa6bd1SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4952e2fa6bd1SRichard Henderson return true; 4953e2fa6bd1SRichard Henderson } 4954e2fa6bd1SRichard Henderson 4955e2fa6bd1SRichard Henderson dst = gen_dest_gpr(dc, a->rd); 4956e2fa6bd1SRichard Henderson src1 = gen_load_fpr_D(dc, a->rs1); 4957e2fa6bd1SRichard Henderson src2 = gen_load_fpr_D(dc, a->rs2); 4958e2fa6bd1SRichard Henderson func(dst, src1, src2); 4959e2fa6bd1SRichard Henderson gen_store_gpr(dc, a->rd, dst); 4960e2fa6bd1SRichard Henderson return advance_pc(dc); 4961e2fa6bd1SRichard Henderson } 4962e2fa6bd1SRichard Henderson 4963e2fa6bd1SRichard Henderson TRANS(FPCMPLE16, VIS1, do_rdd, a, gen_helper_fcmple16) 4964e2fa6bd1SRichard Henderson TRANS(FPCMPNE16, VIS1, do_rdd, a, gen_helper_fcmpne16) 4965e2fa6bd1SRichard Henderson TRANS(FPCMPGT16, VIS1, do_rdd, a, gen_helper_fcmpgt16) 4966e2fa6bd1SRichard Henderson TRANS(FPCMPEQ16, VIS1, do_rdd, a, gen_helper_fcmpeq16) 4967e2fa6bd1SRichard Henderson 4968e2fa6bd1SRichard Henderson TRANS(FPCMPLE32, VIS1, do_rdd, a, gen_helper_fcmple32) 4969e2fa6bd1SRichard Henderson TRANS(FPCMPNE32, VIS1, do_rdd, a, gen_helper_fcmpne32) 4970e2fa6bd1SRichard Henderson TRANS(FPCMPGT32, VIS1, do_rdd, a, gen_helper_fcmpgt32) 4971e2fa6bd1SRichard Henderson TRANS(FPCMPEQ32, VIS1, do_rdd, a, gen_helper_fcmpeq32) 4972e2fa6bd1SRichard Henderson 4973f2a59b0aSRichard Henderson static bool do_env_ddd(DisasContext *dc, arg_r_r_r *a, 4974f2a59b0aSRichard Henderson void (*func)(TCGv_i64, TCGv_env, TCGv_i64, TCGv_i64)) 4975f2a59b0aSRichard Henderson { 4976f2a59b0aSRichard Henderson TCGv_i64 dst, src1, src2; 4977f2a59b0aSRichard Henderson 4978f2a59b0aSRichard Henderson if (gen_trap_ifnofpu(dc)) { 4979f2a59b0aSRichard Henderson return true; 4980f2a59b0aSRichard Henderson } 4981f2a59b0aSRichard Henderson 4982f2a59b0aSRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 4983f2a59b0aSRichard Henderson dst = gen_dest_fpr_D(dc, a->rd); 4984f2a59b0aSRichard Henderson src1 = gen_load_fpr_D(dc, a->rs1); 4985f2a59b0aSRichard Henderson src2 = gen_load_fpr_D(dc, a->rs2); 4986f2a59b0aSRichard Henderson func(dst, tcg_env, src1, src2); 4987f2a59b0aSRichard Henderson gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env); 4988f2a59b0aSRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 4989f2a59b0aSRichard Henderson return advance_pc(dc); 4990f2a59b0aSRichard Henderson } 4991f2a59b0aSRichard Henderson 4992f2a59b0aSRichard Henderson TRANS(FADDd, ALL, do_env_ddd, a, gen_helper_faddd) 4993f2a59b0aSRichard Henderson TRANS(FSUBd, ALL, do_env_ddd, a, gen_helper_fsubd) 4994f2a59b0aSRichard Henderson TRANS(FMULd, ALL, do_env_ddd, a, gen_helper_fmuld) 4995f2a59b0aSRichard Henderson TRANS(FDIVd, ALL, do_env_ddd, a, gen_helper_fdivd) 4996f2a59b0aSRichard Henderson 4997ff4c711bSRichard Henderson static bool trans_FsMULd(DisasContext *dc, arg_r_r_r *a) 4998ff4c711bSRichard Henderson { 4999ff4c711bSRichard Henderson TCGv_i64 dst; 5000ff4c711bSRichard Henderson TCGv_i32 src1, src2; 5001ff4c711bSRichard Henderson 5002ff4c711bSRichard Henderson if (gen_trap_ifnofpu(dc)) { 5003ff4c711bSRichard Henderson return true; 5004ff4c711bSRichard Henderson } 5005ff4c711bSRichard Henderson if (!(dc->def->features & CPU_FEATURE_FSMULD)) { 5006ff4c711bSRichard Henderson return raise_unimpfpop(dc); 5007ff4c711bSRichard Henderson } 5008ff4c711bSRichard Henderson 5009ff4c711bSRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 5010ff4c711bSRichard Henderson dst = gen_dest_fpr_D(dc, a->rd); 5011ff4c711bSRichard Henderson src1 = gen_load_fpr_F(dc, a->rs1); 5012ff4c711bSRichard Henderson src2 = gen_load_fpr_F(dc, a->rs2); 5013ff4c711bSRichard Henderson gen_helper_fsmuld(dst, tcg_env, src1, src2); 5014ff4c711bSRichard Henderson gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env); 5015ff4c711bSRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 5016ff4c711bSRichard Henderson return advance_pc(dc); 5017ff4c711bSRichard Henderson } 5018ff4c711bSRichard Henderson 5019afb04344SRichard Henderson static bool do_dddd(DisasContext *dc, arg_r_r_r *a, 5020afb04344SRichard Henderson void (*func)(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_i64)) 5021afb04344SRichard Henderson { 5022afb04344SRichard Henderson TCGv_i64 dst, src0, src1, src2; 5023afb04344SRichard Henderson 5024afb04344SRichard Henderson if (gen_trap_ifnofpu(dc)) { 5025afb04344SRichard Henderson return true; 5026afb04344SRichard Henderson } 5027afb04344SRichard Henderson 5028afb04344SRichard Henderson dst = gen_dest_fpr_D(dc, a->rd); 5029afb04344SRichard Henderson src0 = gen_load_fpr_D(dc, a->rd); 5030afb04344SRichard Henderson src1 = gen_load_fpr_D(dc, a->rs1); 5031afb04344SRichard Henderson src2 = gen_load_fpr_D(dc, a->rs2); 5032afb04344SRichard Henderson func(dst, src0, src1, src2); 5033afb04344SRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 5034afb04344SRichard Henderson return advance_pc(dc); 5035afb04344SRichard Henderson } 5036afb04344SRichard Henderson 5037afb04344SRichard Henderson TRANS(PDIST, VIS1, do_dddd, a, gen_helper_pdist) 5038afb04344SRichard Henderson 5039a4056239SRichard Henderson static bool do_env_qqq(DisasContext *dc, arg_r_r_r *a, 5040a4056239SRichard Henderson void (*func)(TCGv_env)) 5041a4056239SRichard Henderson { 5042a4056239SRichard Henderson if (gen_trap_ifnofpu(dc)) { 5043a4056239SRichard Henderson return true; 5044a4056239SRichard Henderson } 5045a4056239SRichard Henderson if (gen_trap_float128(dc)) { 5046a4056239SRichard Henderson return true; 5047a4056239SRichard Henderson } 5048a4056239SRichard Henderson 5049a4056239SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 5050a4056239SRichard Henderson gen_op_load_fpr_QT0(QFPREG(a->rs1)); 5051a4056239SRichard Henderson gen_op_load_fpr_QT1(QFPREG(a->rs2)); 5052a4056239SRichard Henderson func(tcg_env); 5053a4056239SRichard Henderson gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env); 5054a4056239SRichard Henderson gen_op_store_QT0_fpr(QFPREG(a->rd)); 5055a4056239SRichard Henderson gen_update_fprs_dirty(dc, QFPREG(a->rd)); 5056a4056239SRichard Henderson return advance_pc(dc); 5057a4056239SRichard Henderson } 5058a4056239SRichard Henderson 5059a4056239SRichard Henderson TRANS(FADDq, ALL, do_env_qqq, a, gen_helper_faddq) 5060a4056239SRichard Henderson TRANS(FSUBq, ALL, do_env_qqq, a, gen_helper_fsubq) 5061a4056239SRichard Henderson TRANS(FMULq, ALL, do_env_qqq, a, gen_helper_fmulq) 5062a4056239SRichard Henderson TRANS(FDIVq, ALL, do_env_qqq, a, gen_helper_fdivq) 5063a4056239SRichard Henderson 50645e3b17bbSRichard Henderson static bool trans_FdMULq(DisasContext *dc, arg_r_r_r *a) 50655e3b17bbSRichard Henderson { 50665e3b17bbSRichard Henderson TCGv_i64 src1, src2; 50675e3b17bbSRichard Henderson 50685e3b17bbSRichard Henderson if (gen_trap_ifnofpu(dc)) { 50695e3b17bbSRichard Henderson return true; 50705e3b17bbSRichard Henderson } 50715e3b17bbSRichard Henderson if (gen_trap_float128(dc)) { 50725e3b17bbSRichard Henderson return true; 50735e3b17bbSRichard Henderson } 50745e3b17bbSRichard Henderson 50755e3b17bbSRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 50765e3b17bbSRichard Henderson src1 = gen_load_fpr_D(dc, a->rs1); 50775e3b17bbSRichard Henderson src2 = gen_load_fpr_D(dc, a->rs2); 50785e3b17bbSRichard Henderson gen_helper_fdmulq(tcg_env, src1, src2); 50795e3b17bbSRichard Henderson gen_helper_check_ieee_exceptions(cpu_fsr, tcg_env); 50805e3b17bbSRichard Henderson gen_op_store_QT0_fpr(QFPREG(a->rd)); 50815e3b17bbSRichard Henderson gen_update_fprs_dirty(dc, QFPREG(a->rd)); 50825e3b17bbSRichard Henderson return advance_pc(dc); 50835e3b17bbSRichard Henderson } 50845e3b17bbSRichard Henderson 5085f7ec8155SRichard Henderson static bool do_fmovr(DisasContext *dc, arg_FMOVRs *a, bool is_128, 5086f7ec8155SRichard Henderson void (*func)(DisasContext *, DisasCompare *, int, int)) 5087f7ec8155SRichard Henderson { 5088f7ec8155SRichard Henderson DisasCompare cmp; 5089f7ec8155SRichard Henderson 5090f7ec8155SRichard Henderson if (gen_trap_ifnofpu(dc)) { 5091f7ec8155SRichard Henderson return true; 5092f7ec8155SRichard Henderson } 5093f7ec8155SRichard Henderson if (is_128 && gen_trap_float128(dc)) { 5094f7ec8155SRichard Henderson return true; 5095f7ec8155SRichard Henderson } 5096f7ec8155SRichard Henderson 5097f7ec8155SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 5098f7ec8155SRichard Henderson gen_compare_reg(&cmp, a->cond, gen_load_gpr(dc, a->rs1)); 5099f7ec8155SRichard Henderson func(dc, &cmp, a->rd, a->rs2); 5100f7ec8155SRichard Henderson return advance_pc(dc); 5101f7ec8155SRichard Henderson } 5102f7ec8155SRichard Henderson 5103f7ec8155SRichard Henderson TRANS(FMOVRs, 64, do_fmovr, a, false, gen_fmovs) 5104f7ec8155SRichard Henderson TRANS(FMOVRd, 64, do_fmovr, a, false, gen_fmovd) 5105f7ec8155SRichard Henderson TRANS(FMOVRq, 64, do_fmovr, a, true, gen_fmovq) 5106f7ec8155SRichard Henderson 5107f7ec8155SRichard Henderson static bool do_fmovcc(DisasContext *dc, arg_FMOVscc *a, bool is_128, 5108f7ec8155SRichard Henderson void (*func)(DisasContext *, DisasCompare *, int, int)) 5109f7ec8155SRichard Henderson { 5110f7ec8155SRichard Henderson DisasCompare cmp; 5111f7ec8155SRichard Henderson 5112f7ec8155SRichard Henderson if (gen_trap_ifnofpu(dc)) { 5113f7ec8155SRichard Henderson return true; 5114f7ec8155SRichard Henderson } 5115f7ec8155SRichard Henderson if (is_128 && gen_trap_float128(dc)) { 5116f7ec8155SRichard Henderson return true; 5117f7ec8155SRichard Henderson } 5118f7ec8155SRichard Henderson 5119f7ec8155SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 5120f7ec8155SRichard Henderson gen_compare(&cmp, a->cc, a->cond, dc); 5121f7ec8155SRichard Henderson func(dc, &cmp, a->rd, a->rs2); 5122f7ec8155SRichard Henderson return advance_pc(dc); 5123f7ec8155SRichard Henderson } 5124f7ec8155SRichard Henderson 5125f7ec8155SRichard Henderson TRANS(FMOVscc, 64, do_fmovcc, a, false, gen_fmovs) 5126f7ec8155SRichard Henderson TRANS(FMOVdcc, 64, do_fmovcc, a, false, gen_fmovd) 5127f7ec8155SRichard Henderson TRANS(FMOVqcc, 64, do_fmovcc, a, true, gen_fmovq) 5128f7ec8155SRichard Henderson 5129f7ec8155SRichard Henderson static bool do_fmovfcc(DisasContext *dc, arg_FMOVsfcc *a, bool is_128, 5130f7ec8155SRichard Henderson void (*func)(DisasContext *, DisasCompare *, int, int)) 5131f7ec8155SRichard Henderson { 5132f7ec8155SRichard Henderson DisasCompare cmp; 5133f7ec8155SRichard Henderson 5134f7ec8155SRichard Henderson if (gen_trap_ifnofpu(dc)) { 5135f7ec8155SRichard Henderson return true; 5136f7ec8155SRichard Henderson } 5137f7ec8155SRichard Henderson if (is_128 && gen_trap_float128(dc)) { 5138f7ec8155SRichard Henderson return true; 5139f7ec8155SRichard Henderson } 5140f7ec8155SRichard Henderson 5141f7ec8155SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 5142f7ec8155SRichard Henderson gen_fcompare(&cmp, a->cc, a->cond); 5143f7ec8155SRichard Henderson func(dc, &cmp, a->rd, a->rs2); 5144f7ec8155SRichard Henderson return advance_pc(dc); 5145f7ec8155SRichard Henderson } 5146f7ec8155SRichard Henderson 5147f7ec8155SRichard Henderson TRANS(FMOVsfcc, 64, do_fmovfcc, a, false, gen_fmovs) 5148f7ec8155SRichard Henderson TRANS(FMOVdfcc, 64, do_fmovfcc, a, false, gen_fmovd) 5149f7ec8155SRichard Henderson TRANS(FMOVqfcc, 64, do_fmovfcc, a, true, gen_fmovq) 5150f7ec8155SRichard Henderson 515140f9ad21SRichard Henderson static bool do_fcmps(DisasContext *dc, arg_FCMPs *a, bool e) 515240f9ad21SRichard Henderson { 515340f9ad21SRichard Henderson TCGv_i32 src1, src2; 515440f9ad21SRichard Henderson 515540f9ad21SRichard Henderson if (avail_32(dc) && a->cc != 0) { 515640f9ad21SRichard Henderson return false; 515740f9ad21SRichard Henderson } 515840f9ad21SRichard Henderson if (gen_trap_ifnofpu(dc)) { 515940f9ad21SRichard Henderson return true; 516040f9ad21SRichard Henderson } 516140f9ad21SRichard Henderson 516240f9ad21SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 516340f9ad21SRichard Henderson src1 = gen_load_fpr_F(dc, a->rs1); 516440f9ad21SRichard Henderson src2 = gen_load_fpr_F(dc, a->rs2); 516540f9ad21SRichard Henderson if (e) { 516640f9ad21SRichard Henderson gen_op_fcmpes(a->cc, src1, src2); 516740f9ad21SRichard Henderson } else { 516840f9ad21SRichard Henderson gen_op_fcmps(a->cc, src1, src2); 516940f9ad21SRichard Henderson } 517040f9ad21SRichard Henderson return advance_pc(dc); 517140f9ad21SRichard Henderson } 517240f9ad21SRichard Henderson 517340f9ad21SRichard Henderson TRANS(FCMPs, ALL, do_fcmps, a, false) 517440f9ad21SRichard Henderson TRANS(FCMPEs, ALL, do_fcmps, a, true) 517540f9ad21SRichard Henderson 517640f9ad21SRichard Henderson static bool do_fcmpd(DisasContext *dc, arg_FCMPd *a, bool e) 517740f9ad21SRichard Henderson { 517840f9ad21SRichard Henderson TCGv_i64 src1, src2; 517940f9ad21SRichard Henderson 518040f9ad21SRichard Henderson if (avail_32(dc) && a->cc != 0) { 518140f9ad21SRichard Henderson return false; 518240f9ad21SRichard Henderson } 518340f9ad21SRichard Henderson if (gen_trap_ifnofpu(dc)) { 518440f9ad21SRichard Henderson return true; 518540f9ad21SRichard Henderson } 518640f9ad21SRichard Henderson 518740f9ad21SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 518840f9ad21SRichard Henderson src1 = gen_load_fpr_D(dc, a->rs1); 518940f9ad21SRichard Henderson src2 = gen_load_fpr_D(dc, a->rs2); 519040f9ad21SRichard Henderson if (e) { 519140f9ad21SRichard Henderson gen_op_fcmped(a->cc, src1, src2); 519240f9ad21SRichard Henderson } else { 519340f9ad21SRichard Henderson gen_op_fcmpd(a->cc, src1, src2); 519440f9ad21SRichard Henderson } 519540f9ad21SRichard Henderson return advance_pc(dc); 519640f9ad21SRichard Henderson } 519740f9ad21SRichard Henderson 519840f9ad21SRichard Henderson TRANS(FCMPd, ALL, do_fcmpd, a, false) 519940f9ad21SRichard Henderson TRANS(FCMPEd, ALL, do_fcmpd, a, true) 520040f9ad21SRichard Henderson 520140f9ad21SRichard Henderson static bool do_fcmpq(DisasContext *dc, arg_FCMPq *a, bool e) 520240f9ad21SRichard Henderson { 520340f9ad21SRichard Henderson if (avail_32(dc) && a->cc != 0) { 520440f9ad21SRichard Henderson return false; 520540f9ad21SRichard Henderson } 520640f9ad21SRichard Henderson if (gen_trap_ifnofpu(dc)) { 520740f9ad21SRichard Henderson return true; 520840f9ad21SRichard Henderson } 520940f9ad21SRichard Henderson if (gen_trap_float128(dc)) { 521040f9ad21SRichard Henderson return true; 521140f9ad21SRichard Henderson } 521240f9ad21SRichard Henderson 521340f9ad21SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 521440f9ad21SRichard Henderson gen_op_load_fpr_QT0(QFPREG(a->rs1)); 521540f9ad21SRichard Henderson gen_op_load_fpr_QT1(QFPREG(a->rs2)); 521640f9ad21SRichard Henderson if (e) { 521740f9ad21SRichard Henderson gen_op_fcmpeq(a->cc); 521840f9ad21SRichard Henderson } else { 521940f9ad21SRichard Henderson gen_op_fcmpq(a->cc); 522040f9ad21SRichard Henderson } 522140f9ad21SRichard Henderson return advance_pc(dc); 522240f9ad21SRichard Henderson } 522340f9ad21SRichard Henderson 522440f9ad21SRichard Henderson TRANS(FCMPq, ALL, do_fcmpq, a, false) 522540f9ad21SRichard Henderson TRANS(FCMPEq, ALL, do_fcmpq, a, true) 522640f9ad21SRichard Henderson 52276e61bc94SEmilio G. Cota static void sparc_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) 5228fcf5ef2aSThomas Huth { 52296e61bc94SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 5230b77af26eSRichard Henderson CPUSPARCState *env = cpu_env(cs); 52316e61bc94SEmilio G. Cota int bound; 5232af00be49SEmilio G. Cota 5233af00be49SEmilio G. Cota dc->pc = dc->base.pc_first; 52346e61bc94SEmilio G. Cota dc->npc = (target_ulong)dc->base.tb->cs_base; 5235fcf5ef2aSThomas Huth dc->cc_op = CC_OP_DYNAMIC; 52366e61bc94SEmilio G. Cota dc->mem_idx = dc->base.tb->flags & TB_FLAG_MMU_MASK; 5237576e1c4cSIgor Mammedov dc->def = &env->def; 52386e61bc94SEmilio G. Cota dc->fpu_enabled = tb_fpu_enabled(dc->base.tb->flags); 52396e61bc94SEmilio G. Cota dc->address_mask_32bit = tb_am_enabled(dc->base.tb->flags); 5240c9b459aaSArtyom Tarasenko #ifndef CONFIG_USER_ONLY 52416e61bc94SEmilio G. Cota dc->supervisor = (dc->base.tb->flags & TB_FLAG_SUPER) != 0; 5242c9b459aaSArtyom Tarasenko #endif 5243fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64 5244fcf5ef2aSThomas Huth dc->fprs_dirty = 0; 52456e61bc94SEmilio G. Cota dc->asi = (dc->base.tb->flags >> TB_FLAG_ASI_SHIFT) & 0xff; 5246c9b459aaSArtyom Tarasenko #ifndef CONFIG_USER_ONLY 52476e61bc94SEmilio G. Cota dc->hypervisor = (dc->base.tb->flags & TB_FLAG_HYPER) != 0; 5248c9b459aaSArtyom Tarasenko #endif 5249fcf5ef2aSThomas Huth #endif 52506e61bc94SEmilio G. Cota /* 52516e61bc94SEmilio G. Cota * if we reach a page boundary, we stop generation so that the 52526e61bc94SEmilio G. Cota * PC of a TT_TFAULT exception is always in the right page 52536e61bc94SEmilio G. Cota */ 52546e61bc94SEmilio G. Cota bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4; 52556e61bc94SEmilio G. Cota dc->base.max_insns = MIN(dc->base.max_insns, bound); 5256af00be49SEmilio G. Cota } 5257fcf5ef2aSThomas Huth 52586e61bc94SEmilio G. Cota static void sparc_tr_tb_start(DisasContextBase *db, CPUState *cs) 52596e61bc94SEmilio G. Cota { 52606e61bc94SEmilio G. Cota } 52616e61bc94SEmilio G. Cota 52626e61bc94SEmilio G. Cota static void sparc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) 52636e61bc94SEmilio G. Cota { 52646e61bc94SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 5265633c4283SRichard Henderson target_ulong npc = dc->npc; 52666e61bc94SEmilio G. Cota 5267633c4283SRichard Henderson if (npc & 3) { 5268633c4283SRichard Henderson switch (npc) { 5269633c4283SRichard Henderson case JUMP_PC: 5270fcf5ef2aSThomas Huth assert(dc->jump_pc[1] == dc->pc + 4); 5271633c4283SRichard Henderson npc = dc->jump_pc[0] | JUMP_PC; 5272633c4283SRichard Henderson break; 5273633c4283SRichard Henderson case DYNAMIC_PC: 5274633c4283SRichard Henderson case DYNAMIC_PC_LOOKUP: 5275633c4283SRichard Henderson npc = DYNAMIC_PC; 5276633c4283SRichard Henderson break; 5277633c4283SRichard Henderson default: 5278633c4283SRichard Henderson g_assert_not_reached(); 5279fcf5ef2aSThomas Huth } 52806e61bc94SEmilio G. Cota } 5281633c4283SRichard Henderson tcg_gen_insn_start(dc->pc, npc); 5282633c4283SRichard Henderson } 5283fcf5ef2aSThomas Huth 52846e61bc94SEmilio G. Cota static void sparc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) 52856e61bc94SEmilio G. Cota { 52866e61bc94SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 5287b77af26eSRichard Henderson CPUSPARCState *env = cpu_env(cs); 52886e61bc94SEmilio G. Cota unsigned int insn; 5289fcf5ef2aSThomas Huth 52904e116893SIlya Leoshkevich insn = translator_ldl(env, &dc->base, dc->pc); 5291af00be49SEmilio G. Cota dc->base.pc_next += 4; 5292878cc677SRichard Henderson 5293878cc677SRichard Henderson if (!decode(dc, insn)) { 5294ba9c09b4SRichard Henderson gen_exception(dc, TT_ILL_INSN); 5295878cc677SRichard Henderson } 5296fcf5ef2aSThomas Huth 5297af00be49SEmilio G. Cota if (dc->base.is_jmp == DISAS_NORETURN) { 52986e61bc94SEmilio G. Cota return; 5299c5e6ccdfSEmilio G. Cota } 5300af00be49SEmilio G. Cota if (dc->pc != dc->base.pc_next) { 53016e61bc94SEmilio G. Cota dc->base.is_jmp = DISAS_TOO_MANY; 5302af00be49SEmilio G. Cota } 53036e61bc94SEmilio G. Cota } 5304fcf5ef2aSThomas Huth 53056e61bc94SEmilio G. Cota static void sparc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) 53066e61bc94SEmilio G. Cota { 53076e61bc94SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 5308186e7890SRichard Henderson DisasDelayException *e, *e_next; 5309633c4283SRichard Henderson bool may_lookup; 53106e61bc94SEmilio G. Cota 531146bb0137SMark Cave-Ayland switch (dc->base.is_jmp) { 531246bb0137SMark Cave-Ayland case DISAS_NEXT: 531346bb0137SMark Cave-Ayland case DISAS_TOO_MANY: 5314633c4283SRichard Henderson if (((dc->pc | dc->npc) & 3) == 0) { 5315fcf5ef2aSThomas Huth /* static PC and NPC: we can use direct chaining */ 5316fcf5ef2aSThomas Huth gen_goto_tb(dc, 0, dc->pc, dc->npc); 5317633c4283SRichard Henderson break; 5318fcf5ef2aSThomas Huth } 5319633c4283SRichard Henderson 5320930f1865SRichard Henderson may_lookup = true; 5321633c4283SRichard Henderson if (dc->pc & 3) { 5322633c4283SRichard Henderson switch (dc->pc) { 5323633c4283SRichard Henderson case DYNAMIC_PC_LOOKUP: 5324633c4283SRichard Henderson break; 5325633c4283SRichard Henderson case DYNAMIC_PC: 5326633c4283SRichard Henderson may_lookup = false; 5327633c4283SRichard Henderson break; 5328633c4283SRichard Henderson default: 5329633c4283SRichard Henderson g_assert_not_reached(); 5330633c4283SRichard Henderson } 5331633c4283SRichard Henderson } else { 5332633c4283SRichard Henderson tcg_gen_movi_tl(cpu_pc, dc->pc); 5333633c4283SRichard Henderson } 5334633c4283SRichard Henderson 5335930f1865SRichard Henderson if (dc->npc & 3) { 5336930f1865SRichard Henderson switch (dc->npc) { 5337930f1865SRichard Henderson case JUMP_PC: 5338930f1865SRichard Henderson gen_generic_branch(dc); 5339930f1865SRichard Henderson break; 5340930f1865SRichard Henderson case DYNAMIC_PC: 5341930f1865SRichard Henderson may_lookup = false; 5342930f1865SRichard Henderson break; 5343930f1865SRichard Henderson case DYNAMIC_PC_LOOKUP: 5344930f1865SRichard Henderson break; 5345930f1865SRichard Henderson default: 5346930f1865SRichard Henderson g_assert_not_reached(); 5347930f1865SRichard Henderson } 5348930f1865SRichard Henderson } else { 5349930f1865SRichard Henderson tcg_gen_movi_tl(cpu_npc, dc->npc); 5350930f1865SRichard Henderson } 5351633c4283SRichard Henderson if (may_lookup) { 5352633c4283SRichard Henderson tcg_gen_lookup_and_goto_ptr(); 5353633c4283SRichard Henderson } else { 535407ea28b4SRichard Henderson tcg_gen_exit_tb(NULL, 0); 5355fcf5ef2aSThomas Huth } 535646bb0137SMark Cave-Ayland break; 535746bb0137SMark Cave-Ayland 535846bb0137SMark Cave-Ayland case DISAS_NORETURN: 535946bb0137SMark Cave-Ayland break; 536046bb0137SMark Cave-Ayland 536146bb0137SMark Cave-Ayland case DISAS_EXIT: 536246bb0137SMark Cave-Ayland /* Exit TB */ 536346bb0137SMark Cave-Ayland save_state(dc); 536446bb0137SMark Cave-Ayland tcg_gen_exit_tb(NULL, 0); 536546bb0137SMark Cave-Ayland break; 536646bb0137SMark Cave-Ayland 536746bb0137SMark Cave-Ayland default: 536846bb0137SMark Cave-Ayland g_assert_not_reached(); 5369fcf5ef2aSThomas Huth } 5370186e7890SRichard Henderson 5371186e7890SRichard Henderson for (e = dc->delay_excp_list; e ; e = e_next) { 5372186e7890SRichard Henderson gen_set_label(e->lab); 5373186e7890SRichard Henderson 5374186e7890SRichard Henderson tcg_gen_movi_tl(cpu_pc, e->pc); 5375186e7890SRichard Henderson if (e->npc % 4 == 0) { 5376186e7890SRichard Henderson tcg_gen_movi_tl(cpu_npc, e->npc); 5377186e7890SRichard Henderson } 5378186e7890SRichard Henderson gen_helper_raise_exception(tcg_env, e->excp); 5379186e7890SRichard Henderson 5380186e7890SRichard Henderson e_next = e->next; 5381186e7890SRichard Henderson g_free(e); 5382186e7890SRichard Henderson } 5383fcf5ef2aSThomas Huth } 53846e61bc94SEmilio G. Cota 53858eb806a7SRichard Henderson static void sparc_tr_disas_log(const DisasContextBase *dcbase, 53868eb806a7SRichard Henderson CPUState *cpu, FILE *logfile) 53876e61bc94SEmilio G. Cota { 53888eb806a7SRichard Henderson fprintf(logfile, "IN: %s\n", lookup_symbol(dcbase->pc_first)); 53898eb806a7SRichard Henderson target_disas(logfile, cpu, dcbase->pc_first, dcbase->tb->size); 53906e61bc94SEmilio G. Cota } 53916e61bc94SEmilio G. Cota 53926e61bc94SEmilio G. Cota static const TranslatorOps sparc_tr_ops = { 53936e61bc94SEmilio G. Cota .init_disas_context = sparc_tr_init_disas_context, 53946e61bc94SEmilio G. Cota .tb_start = sparc_tr_tb_start, 53956e61bc94SEmilio G. Cota .insn_start = sparc_tr_insn_start, 53966e61bc94SEmilio G. Cota .translate_insn = sparc_tr_translate_insn, 53976e61bc94SEmilio G. Cota .tb_stop = sparc_tr_tb_stop, 53986e61bc94SEmilio G. Cota .disas_log = sparc_tr_disas_log, 53996e61bc94SEmilio G. Cota }; 54006e61bc94SEmilio G. Cota 5401597f9b2dSRichard Henderson void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int *max_insns, 5402306c8721SRichard Henderson target_ulong pc, void *host_pc) 54036e61bc94SEmilio G. Cota { 54046e61bc94SEmilio G. Cota DisasContext dc = {}; 54056e61bc94SEmilio G. Cota 5406306c8721SRichard Henderson translator_loop(cs, tb, max_insns, pc, host_pc, &sparc_tr_ops, &dc.base); 5407fcf5ef2aSThomas Huth } 5408fcf5ef2aSThomas Huth 540955c3ceefSRichard Henderson void sparc_tcg_init(void) 5410fcf5ef2aSThomas Huth { 5411fcf5ef2aSThomas Huth static const char gregnames[32][4] = { 5412fcf5ef2aSThomas Huth "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7", 5413fcf5ef2aSThomas Huth "o0", "o1", "o2", "o3", "o4", "o5", "o6", "o7", 5414fcf5ef2aSThomas Huth "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7", 5415fcf5ef2aSThomas Huth "i0", "i1", "i2", "i3", "i4", "i5", "i6", "i7", 5416fcf5ef2aSThomas Huth }; 5417fcf5ef2aSThomas Huth static const char fregnames[32][4] = { 5418fcf5ef2aSThomas Huth "f0", "f2", "f4", "f6", "f8", "f10", "f12", "f14", 5419fcf5ef2aSThomas Huth "f16", "f18", "f20", "f22", "f24", "f26", "f28", "f30", 5420fcf5ef2aSThomas Huth "f32", "f34", "f36", "f38", "f40", "f42", "f44", "f46", 5421fcf5ef2aSThomas Huth "f48", "f50", "f52", "f54", "f56", "f58", "f60", "f62", 5422fcf5ef2aSThomas Huth }; 5423fcf5ef2aSThomas Huth 5424fcf5ef2aSThomas Huth static const struct { TCGv_i32 *ptr; int off; const char *name; } r32[] = { 5425fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64 5426fcf5ef2aSThomas Huth { &cpu_fprs, offsetof(CPUSPARCState, fprs), "fprs" }, 5427fcf5ef2aSThomas Huth #endif 5428fcf5ef2aSThomas Huth { &cpu_cc_op, offsetof(CPUSPARCState, cc_op), "cc_op" }, 5429fcf5ef2aSThomas Huth }; 5430fcf5ef2aSThomas Huth 5431fcf5ef2aSThomas Huth static const struct { TCGv *ptr; int off; const char *name; } rtl[] = { 5432fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64 5433fcf5ef2aSThomas Huth { &cpu_gsr, offsetof(CPUSPARCState, gsr), "gsr" }, 5434*2a1905c7SRichard Henderson { &cpu_xcc_Z, offsetof(CPUSPARCState, xcc_Z), "xcc_Z" }, 5435*2a1905c7SRichard Henderson { &cpu_xcc_C, offsetof(CPUSPARCState, xcc_C), "xcc_C" }, 5436fcf5ef2aSThomas Huth #endif 5437*2a1905c7SRichard Henderson { &cpu_cc_N, offsetof(CPUSPARCState, cc_N), "cc_N" }, 5438*2a1905c7SRichard Henderson { &cpu_cc_V, offsetof(CPUSPARCState, cc_V), "cc_V" }, 5439*2a1905c7SRichard Henderson { &cpu_icc_Z, offsetof(CPUSPARCState, icc_Z), "icc_Z" }, 5440*2a1905c7SRichard Henderson { &cpu_icc_C, offsetof(CPUSPARCState, icc_C), "icc_C" }, 5441fcf5ef2aSThomas Huth { &cpu_cond, offsetof(CPUSPARCState, cond), "cond" }, 5442fcf5ef2aSThomas Huth { &cpu_cc_src, offsetof(CPUSPARCState, cc_src), "cc_src" }, 5443fcf5ef2aSThomas Huth { &cpu_cc_src2, offsetof(CPUSPARCState, cc_src2), "cc_src2" }, 5444fcf5ef2aSThomas Huth { &cpu_cc_dst, offsetof(CPUSPARCState, cc_dst), "cc_dst" }, 5445fcf5ef2aSThomas Huth { &cpu_fsr, offsetof(CPUSPARCState, fsr), "fsr" }, 5446fcf5ef2aSThomas Huth { &cpu_pc, offsetof(CPUSPARCState, pc), "pc" }, 5447fcf5ef2aSThomas Huth { &cpu_npc, offsetof(CPUSPARCState, npc), "npc" }, 5448fcf5ef2aSThomas Huth { &cpu_y, offsetof(CPUSPARCState, y), "y" }, 5449fcf5ef2aSThomas Huth { &cpu_tbr, offsetof(CPUSPARCState, tbr), "tbr" }, 5450fcf5ef2aSThomas Huth }; 5451fcf5ef2aSThomas Huth 5452fcf5ef2aSThomas Huth unsigned int i; 5453fcf5ef2aSThomas Huth 5454ad75a51eSRichard Henderson cpu_regwptr = tcg_global_mem_new_ptr(tcg_env, 5455fcf5ef2aSThomas Huth offsetof(CPUSPARCState, regwptr), 5456fcf5ef2aSThomas Huth "regwptr"); 5457fcf5ef2aSThomas Huth 5458fcf5ef2aSThomas Huth for (i = 0; i < ARRAY_SIZE(r32); ++i) { 5459ad75a51eSRichard Henderson *r32[i].ptr = tcg_global_mem_new_i32(tcg_env, r32[i].off, r32[i].name); 5460fcf5ef2aSThomas Huth } 5461fcf5ef2aSThomas Huth 5462fcf5ef2aSThomas Huth for (i = 0; i < ARRAY_SIZE(rtl); ++i) { 5463ad75a51eSRichard Henderson *rtl[i].ptr = tcg_global_mem_new(tcg_env, rtl[i].off, rtl[i].name); 5464fcf5ef2aSThomas Huth } 5465fcf5ef2aSThomas Huth 5466f764718dSRichard Henderson cpu_regs[0] = NULL; 5467fcf5ef2aSThomas Huth for (i = 1; i < 8; ++i) { 5468ad75a51eSRichard Henderson cpu_regs[i] = tcg_global_mem_new(tcg_env, 5469fcf5ef2aSThomas Huth offsetof(CPUSPARCState, gregs[i]), 5470fcf5ef2aSThomas Huth gregnames[i]); 5471fcf5ef2aSThomas Huth } 5472fcf5ef2aSThomas Huth 5473fcf5ef2aSThomas Huth for (i = 8; i < 32; ++i) { 5474fcf5ef2aSThomas Huth cpu_regs[i] = tcg_global_mem_new(cpu_regwptr, 5475fcf5ef2aSThomas Huth (i - 8) * sizeof(target_ulong), 5476fcf5ef2aSThomas Huth gregnames[i]); 5477fcf5ef2aSThomas Huth } 5478fcf5ef2aSThomas Huth 5479fcf5ef2aSThomas Huth for (i = 0; i < TARGET_DPREGS; i++) { 5480ad75a51eSRichard Henderson cpu_fpr[i] = tcg_global_mem_new_i64(tcg_env, 5481fcf5ef2aSThomas Huth offsetof(CPUSPARCState, fpr[i]), 5482fcf5ef2aSThomas Huth fregnames[i]); 5483fcf5ef2aSThomas Huth } 5484fcf5ef2aSThomas Huth } 5485fcf5ef2aSThomas Huth 5486f36aaa53SRichard Henderson void sparc_restore_state_to_opc(CPUState *cs, 5487f36aaa53SRichard Henderson const TranslationBlock *tb, 5488f36aaa53SRichard Henderson const uint64_t *data) 5489fcf5ef2aSThomas Huth { 5490f36aaa53SRichard Henderson SPARCCPU *cpu = SPARC_CPU(cs); 5491f36aaa53SRichard Henderson CPUSPARCState *env = &cpu->env; 5492fcf5ef2aSThomas Huth target_ulong pc = data[0]; 5493fcf5ef2aSThomas Huth target_ulong npc = data[1]; 5494fcf5ef2aSThomas Huth 5495fcf5ef2aSThomas Huth env->pc = pc; 5496fcf5ef2aSThomas Huth if (npc == DYNAMIC_PC) { 5497fcf5ef2aSThomas Huth /* dynamic NPC: already stored */ 5498fcf5ef2aSThomas Huth } else if (npc & JUMP_PC) { 5499fcf5ef2aSThomas Huth /* jump PC: use 'cond' and the jump targets of the translation */ 5500fcf5ef2aSThomas Huth if (env->cond) { 5501fcf5ef2aSThomas Huth env->npc = npc & ~3; 5502fcf5ef2aSThomas Huth } else { 5503fcf5ef2aSThomas Huth env->npc = pc + 4; 5504fcf5ef2aSThomas Huth } 5505fcf5ef2aSThomas Huth } else { 5506fcf5ef2aSThomas Huth env->npc = npc; 5507fcf5ef2aSThomas Huth } 5508fcf5ef2aSThomas Huth } 5509