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() 40*c92948f2SClément Chigot # define gen_helper_rdasr17(D, E) qemu_build_not_reached() 4186b82fe0SRichard Henderson # define gen_helper_rett(E) qemu_build_not_reached() 420faef01bSRichard Henderson # define gen_helper_power_down(E) qemu_build_not_reached() 4325524734SRichard Henderson # define gen_helper_wrpsr(E, S) qemu_build_not_reached() 44668bb9b7SRichard Henderson #else 450faef01bSRichard Henderson # define gen_helper_clear_softint(E, S) qemu_build_not_reached() 468f75b8a4SRichard Henderson # define gen_helper_done(E) qemu_build_not_reached() 47e8325dc0SRichard Henderson # define gen_helper_flushw(E) qemu_build_not_reached() 48af25071cSRichard Henderson # define gen_helper_rdccr(D, E) qemu_build_not_reached() 495d617bfbSRichard Henderson # define gen_helper_rdcwp(D, E) qemu_build_not_reached() 5025524734SRichard Henderson # define gen_helper_restored(E) qemu_build_not_reached() 518f75b8a4SRichard Henderson # define gen_helper_retry(E) qemu_build_not_reached() 5225524734SRichard Henderson # define gen_helper_saved(E) qemu_build_not_reached() 530faef01bSRichard Henderson # define gen_helper_set_softint(E, S) qemu_build_not_reached() 54af25071cSRichard Henderson # define gen_helper_tick_get_count(D, E, T, C) qemu_build_not_reached() 559422278eSRichard Henderson # define gen_helper_tick_set_count(P, S) qemu_build_not_reached() 56bb97f2f5SRichard Henderson # define gen_helper_tick_set_limit(P, S) qemu_build_not_reached() 570faef01bSRichard Henderson # define gen_helper_wrccr(E, S) qemu_build_not_reached() 589422278eSRichard Henderson # define gen_helper_wrcwp(E, S) qemu_build_not_reached() 599422278eSRichard Henderson # define gen_helper_wrgl(E, S) qemu_build_not_reached() 600faef01bSRichard Henderson # define gen_helper_write_softint(E, S) qemu_build_not_reached() 619422278eSRichard Henderson # define gen_helper_wrpil(E, S) qemu_build_not_reached() 629422278eSRichard Henderson # define gen_helper_wrpstate(E, S) qemu_build_not_reached() 63e2fa6bd1SRichard Henderson # define gen_helper_fcmpeq16 ({ qemu_build_not_reached(); NULL; }) 64e2fa6bd1SRichard Henderson # define gen_helper_fcmpeq32 ({ qemu_build_not_reached(); NULL; }) 65e2fa6bd1SRichard Henderson # define gen_helper_fcmpgt16 ({ qemu_build_not_reached(); NULL; }) 66e2fa6bd1SRichard Henderson # define gen_helper_fcmpgt32 ({ qemu_build_not_reached(); NULL; }) 67e2fa6bd1SRichard Henderson # define gen_helper_fcmple16 ({ qemu_build_not_reached(); NULL; }) 68e2fa6bd1SRichard Henderson # define gen_helper_fcmple32 ({ qemu_build_not_reached(); NULL; }) 69e2fa6bd1SRichard Henderson # define gen_helper_fcmpne16 ({ qemu_build_not_reached(); NULL; }) 70e2fa6bd1SRichard Henderson # define gen_helper_fcmpne32 ({ qemu_build_not_reached(); NULL; }) 718aa418b3SRichard Henderson # define gen_helper_fdtox ({ qemu_build_not_reached(); NULL; }) 72e06c9f83SRichard Henderson # define gen_helper_fexpand ({ qemu_build_not_reached(); NULL; }) 73e06c9f83SRichard Henderson # define gen_helper_fmul8sux16 ({ qemu_build_not_reached(); NULL; }) 74e06c9f83SRichard Henderson # define gen_helper_fmul8ulx16 ({ qemu_build_not_reached(); NULL; }) 75e06c9f83SRichard Henderson # define gen_helper_fmul8x16al ({ qemu_build_not_reached(); NULL; }) 76e06c9f83SRichard Henderson # define gen_helper_fmul8x16au ({ qemu_build_not_reached(); NULL; }) 77e06c9f83SRichard Henderson # define gen_helper_fmul8x16 ({ qemu_build_not_reached(); NULL; }) 78e06c9f83SRichard Henderson # define gen_helper_fmuld8sux16 ({ qemu_build_not_reached(); NULL; }) 79e06c9f83SRichard Henderson # define gen_helper_fmuld8ulx16 ({ qemu_build_not_reached(); NULL; }) 80e06c9f83SRichard Henderson # define gen_helper_fpmerge ({ qemu_build_not_reached(); NULL; }) 811617586fSRichard Henderson # define gen_helper_fqtox ({ qemu_build_not_reached(); NULL; }) 82199d43efSRichard Henderson # define gen_helper_fstox ({ qemu_build_not_reached(); NULL; }) 838aa418b3SRichard Henderson # define gen_helper_fxtod ({ qemu_build_not_reached(); NULL; }) 847b8e3e1aSRichard Henderson # define gen_helper_fxtoq ({ qemu_build_not_reached(); NULL; }) 85f4e18df5SRichard Henderson # define gen_helper_fxtos ({ qemu_build_not_reached(); NULL; }) 86afb04344SRichard Henderson # define gen_helper_pdist ({ qemu_build_not_reached(); NULL; }) 87668bb9b7SRichard Henderson # define MAXTL_MASK 0 88af25071cSRichard Henderson #endif 89af25071cSRichard Henderson 90633c4283SRichard Henderson /* Dynamic PC, must exit to main loop. */ 91633c4283SRichard Henderson #define DYNAMIC_PC 1 92633c4283SRichard Henderson /* Dynamic PC, one of two values according to jump_pc[T2]. */ 93633c4283SRichard Henderson #define JUMP_PC 2 94633c4283SRichard Henderson /* Dynamic PC, may lookup next TB. */ 95633c4283SRichard Henderson #define DYNAMIC_PC_LOOKUP 3 96fcf5ef2aSThomas Huth 9746bb0137SMark Cave-Ayland #define DISAS_EXIT DISAS_TARGET_0 9846bb0137SMark Cave-Ayland 99fcf5ef2aSThomas Huth /* global register indexes */ 100fcf5ef2aSThomas Huth static TCGv_ptr cpu_regwptr; 101c9fa8e58SRichard Henderson static TCGv cpu_pc, cpu_npc; 102fcf5ef2aSThomas Huth static TCGv cpu_regs[32]; 103fcf5ef2aSThomas Huth static TCGv cpu_y; 104fcf5ef2aSThomas Huth static TCGv cpu_tbr; 105fcf5ef2aSThomas Huth static TCGv cpu_cond; 1062a1905c7SRichard Henderson static TCGv cpu_cc_N; 1072a1905c7SRichard Henderson static TCGv cpu_cc_V; 1082a1905c7SRichard Henderson static TCGv cpu_icc_Z; 1092a1905c7SRichard Henderson static TCGv cpu_icc_C; 110fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64 1112a1905c7SRichard Henderson static TCGv cpu_xcc_Z; 1122a1905c7SRichard Henderson static TCGv cpu_xcc_C; 1132a1905c7SRichard Henderson static TCGv_i32 cpu_fprs; 114fcf5ef2aSThomas Huth static TCGv cpu_gsr; 115fcf5ef2aSThomas Huth #else 116af25071cSRichard Henderson # define cpu_fprs ({ qemu_build_not_reached(); (TCGv)NULL; }) 117af25071cSRichard Henderson # define cpu_gsr ({ qemu_build_not_reached(); (TCGv)NULL; }) 118fcf5ef2aSThomas Huth #endif 1192a1905c7SRichard Henderson 1202a1905c7SRichard Henderson #ifdef TARGET_SPARC64 1212a1905c7SRichard Henderson #define cpu_cc_Z cpu_xcc_Z 1222a1905c7SRichard Henderson #define cpu_cc_C cpu_xcc_C 1232a1905c7SRichard Henderson #else 1242a1905c7SRichard Henderson #define cpu_cc_Z cpu_icc_Z 1252a1905c7SRichard Henderson #define cpu_cc_C cpu_icc_C 1262a1905c7SRichard Henderson #define cpu_xcc_Z ({ qemu_build_not_reached(); NULL; }) 1272a1905c7SRichard Henderson #define cpu_xcc_C ({ qemu_build_not_reached(); NULL; }) 1282a1905c7SRichard Henderson #endif 1292a1905c7SRichard Henderson 130fcf5ef2aSThomas Huth /* Floating point registers */ 131fcf5ef2aSThomas Huth static TCGv_i64 cpu_fpr[TARGET_DPREGS]; 132d8c5b92fSRichard Henderson static TCGv_i32 cpu_fcc[TARGET_FCCREGS]; 133fcf5ef2aSThomas Huth 134af25071cSRichard Henderson #define env_field_offsetof(X) offsetof(CPUSPARCState, X) 135af25071cSRichard Henderson #ifdef TARGET_SPARC64 136cd6269f7SRichard Henderson # define env32_field_offsetof(X) ({ qemu_build_not_reached(); 0; }) 137af25071cSRichard Henderson # define env64_field_offsetof(X) env_field_offsetof(X) 138af25071cSRichard Henderson #else 139cd6269f7SRichard Henderson # define env32_field_offsetof(X) env_field_offsetof(X) 140af25071cSRichard Henderson # define env64_field_offsetof(X) ({ qemu_build_not_reached(); 0; }) 141af25071cSRichard Henderson #endif 142af25071cSRichard Henderson 143533f042fSRichard Henderson typedef struct DisasCompare { 144533f042fSRichard Henderson TCGCond cond; 145533f042fSRichard Henderson TCGv c1; 146533f042fSRichard Henderson int c2; 147533f042fSRichard Henderson } DisasCompare; 148533f042fSRichard Henderson 149186e7890SRichard Henderson typedef struct DisasDelayException { 150186e7890SRichard Henderson struct DisasDelayException *next; 151186e7890SRichard Henderson TCGLabel *lab; 152186e7890SRichard Henderson TCGv_i32 excp; 153186e7890SRichard Henderson /* Saved state at parent insn. */ 154186e7890SRichard Henderson target_ulong pc; 155186e7890SRichard Henderson target_ulong npc; 156186e7890SRichard Henderson } DisasDelayException; 157186e7890SRichard Henderson 158fcf5ef2aSThomas Huth typedef struct DisasContext { 159af00be49SEmilio G. Cota DisasContextBase base; 160fcf5ef2aSThomas Huth target_ulong pc; /* current Program Counter: integer or DYNAMIC_PC */ 161fcf5ef2aSThomas Huth target_ulong npc; /* next PC: integer or DYNAMIC_PC or JUMP_PC */ 162533f042fSRichard Henderson 163533f042fSRichard Henderson /* Used when JUMP_PC value is used. */ 164533f042fSRichard Henderson DisasCompare jump; 165533f042fSRichard Henderson target_ulong jump_pc[2]; 166533f042fSRichard Henderson 167fcf5ef2aSThomas Huth int mem_idx; 16889527e3aSRichard Henderson bool cpu_cond_live; 169c9b459aaSArtyom Tarasenko bool fpu_enabled; 170c9b459aaSArtyom Tarasenko bool address_mask_32bit; 171c9b459aaSArtyom Tarasenko #ifndef CONFIG_USER_ONLY 172c9b459aaSArtyom Tarasenko bool supervisor; 173c9b459aaSArtyom Tarasenko #ifdef TARGET_SPARC64 174c9b459aaSArtyom Tarasenko bool hypervisor; 175c9b459aaSArtyom Tarasenko #endif 176c9b459aaSArtyom Tarasenko #endif 177c9b459aaSArtyom Tarasenko 178fcf5ef2aSThomas Huth sparc_def_t *def; 179fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64 180fcf5ef2aSThomas Huth int fprs_dirty; 181fcf5ef2aSThomas Huth int asi; 182fcf5ef2aSThomas Huth #endif 183186e7890SRichard Henderson DisasDelayException *delay_excp_list; 184fcf5ef2aSThomas Huth } DisasContext; 185fcf5ef2aSThomas Huth 186fcf5ef2aSThomas Huth // This function uses non-native bit order 187fcf5ef2aSThomas Huth #define GET_FIELD(X, FROM, TO) \ 188fcf5ef2aSThomas Huth ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1)) 189fcf5ef2aSThomas Huth 190fcf5ef2aSThomas Huth // This function uses the order in the manuals, i.e. bit 0 is 2^0 191fcf5ef2aSThomas Huth #define GET_FIELD_SP(X, FROM, TO) \ 192fcf5ef2aSThomas Huth GET_FIELD(X, 31 - (TO), 31 - (FROM)) 193fcf5ef2aSThomas Huth 194fcf5ef2aSThomas Huth #define GET_FIELDs(x,a,b) sign_extend (GET_FIELD(x,a,b), (b) - (a) + 1) 195fcf5ef2aSThomas Huth #define GET_FIELD_SPs(x,a,b) sign_extend (GET_FIELD_SP(x,a,b), ((b) - (a) + 1)) 196fcf5ef2aSThomas Huth 197fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64 198fcf5ef2aSThomas Huth #define DFPREG(r) (((r & 1) << 5) | (r & 0x1e)) 199fcf5ef2aSThomas Huth #define QFPREG(r) (((r & 1) << 5) | (r & 0x1c)) 200fcf5ef2aSThomas Huth #else 201fcf5ef2aSThomas Huth #define DFPREG(r) (r & 0x1e) 202fcf5ef2aSThomas Huth #define QFPREG(r) (r & 0x1c) 203fcf5ef2aSThomas Huth #endif 204fcf5ef2aSThomas Huth 205fcf5ef2aSThomas Huth #define UA2005_HTRAP_MASK 0xff 206fcf5ef2aSThomas Huth #define V8_TRAP_MASK 0x7f 207fcf5ef2aSThomas Huth 208fcf5ef2aSThomas Huth #define IS_IMM (insn & (1<<13)) 209fcf5ef2aSThomas Huth 2100c2e96c1SRichard Henderson static void gen_update_fprs_dirty(DisasContext *dc, int rd) 211fcf5ef2aSThomas Huth { 212fcf5ef2aSThomas Huth #if defined(TARGET_SPARC64) 213fcf5ef2aSThomas Huth int bit = (rd < 32) ? 1 : 2; 214fcf5ef2aSThomas Huth /* If we know we've already set this bit within the TB, 215fcf5ef2aSThomas Huth we can avoid setting it again. */ 216fcf5ef2aSThomas Huth if (!(dc->fprs_dirty & bit)) { 217fcf5ef2aSThomas Huth dc->fprs_dirty |= bit; 218fcf5ef2aSThomas Huth tcg_gen_ori_i32(cpu_fprs, cpu_fprs, bit); 219fcf5ef2aSThomas Huth } 220fcf5ef2aSThomas Huth #endif 221fcf5ef2aSThomas Huth } 222fcf5ef2aSThomas Huth 223fcf5ef2aSThomas Huth /* floating point registers moves */ 224fcf5ef2aSThomas Huth static TCGv_i32 gen_load_fpr_F(DisasContext *dc, unsigned int src) 225fcf5ef2aSThomas Huth { 22636ab4623SRichard Henderson TCGv_i32 ret = tcg_temp_new_i32(); 227dc41aa7dSRichard Henderson if (src & 1) { 228dc41aa7dSRichard Henderson tcg_gen_extrl_i64_i32(ret, cpu_fpr[src / 2]); 229dc41aa7dSRichard Henderson } else { 230dc41aa7dSRichard Henderson tcg_gen_extrh_i64_i32(ret, cpu_fpr[src / 2]); 231fcf5ef2aSThomas Huth } 232dc41aa7dSRichard Henderson return ret; 233fcf5ef2aSThomas Huth } 234fcf5ef2aSThomas Huth 235fcf5ef2aSThomas Huth static void gen_store_fpr_F(DisasContext *dc, unsigned int dst, TCGv_i32 v) 236fcf5ef2aSThomas Huth { 2378e7bbc75SRichard Henderson TCGv_i64 t = tcg_temp_new_i64(); 2388e7bbc75SRichard Henderson 2398e7bbc75SRichard Henderson tcg_gen_extu_i32_i64(t, v); 240fcf5ef2aSThomas Huth tcg_gen_deposit_i64(cpu_fpr[dst / 2], cpu_fpr[dst / 2], t, 241fcf5ef2aSThomas Huth (dst & 1 ? 0 : 32), 32); 242fcf5ef2aSThomas Huth gen_update_fprs_dirty(dc, dst); 243fcf5ef2aSThomas Huth } 244fcf5ef2aSThomas Huth 245fcf5ef2aSThomas Huth static TCGv_i64 gen_load_fpr_D(DisasContext *dc, unsigned int src) 246fcf5ef2aSThomas Huth { 247fcf5ef2aSThomas Huth src = DFPREG(src); 248fcf5ef2aSThomas Huth return cpu_fpr[src / 2]; 249fcf5ef2aSThomas Huth } 250fcf5ef2aSThomas Huth 251fcf5ef2aSThomas Huth static void gen_store_fpr_D(DisasContext *dc, unsigned int dst, TCGv_i64 v) 252fcf5ef2aSThomas Huth { 253fcf5ef2aSThomas Huth dst = DFPREG(dst); 254fcf5ef2aSThomas Huth tcg_gen_mov_i64(cpu_fpr[dst / 2], v); 255fcf5ef2aSThomas Huth gen_update_fprs_dirty(dc, dst); 256fcf5ef2aSThomas Huth } 257fcf5ef2aSThomas Huth 258fcf5ef2aSThomas Huth static TCGv_i64 gen_dest_fpr_D(DisasContext *dc, unsigned int dst) 259fcf5ef2aSThomas Huth { 260fcf5ef2aSThomas Huth return cpu_fpr[DFPREG(dst) / 2]; 261fcf5ef2aSThomas Huth } 262fcf5ef2aSThomas Huth 26333ec4245SRichard Henderson static TCGv_i128 gen_load_fpr_Q(DisasContext *dc, unsigned int src) 26433ec4245SRichard Henderson { 26533ec4245SRichard Henderson TCGv_i128 ret = tcg_temp_new_i128(); 26633ec4245SRichard Henderson 26733ec4245SRichard Henderson src = QFPREG(src); 26833ec4245SRichard Henderson tcg_gen_concat_i64_i128(ret, cpu_fpr[src / 2 + 1], cpu_fpr[src / 2]); 26933ec4245SRichard Henderson return ret; 27033ec4245SRichard Henderson } 27133ec4245SRichard Henderson 27233ec4245SRichard Henderson static void gen_store_fpr_Q(DisasContext *dc, unsigned int dst, TCGv_i128 v) 27333ec4245SRichard Henderson { 27433ec4245SRichard Henderson dst = DFPREG(dst); 27533ec4245SRichard Henderson tcg_gen_extr_i128_i64(cpu_fpr[dst / 2 + 1], cpu_fpr[dst / 2], v); 27633ec4245SRichard Henderson gen_update_fprs_dirty(dc, dst); 27733ec4245SRichard Henderson } 27833ec4245SRichard Henderson 279fcf5ef2aSThomas Huth /* moves */ 280fcf5ef2aSThomas Huth #ifdef CONFIG_USER_ONLY 281fcf5ef2aSThomas Huth #define supervisor(dc) 0 282fcf5ef2aSThomas Huth #define hypervisor(dc) 0 283fcf5ef2aSThomas Huth #else 284fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64 285c9b459aaSArtyom Tarasenko #define hypervisor(dc) (dc->hypervisor) 286c9b459aaSArtyom Tarasenko #define supervisor(dc) (dc->supervisor | dc->hypervisor) 287fcf5ef2aSThomas Huth #else 288c9b459aaSArtyom Tarasenko #define supervisor(dc) (dc->supervisor) 289668bb9b7SRichard Henderson #define hypervisor(dc) 0 290fcf5ef2aSThomas Huth #endif 291fcf5ef2aSThomas Huth #endif 292fcf5ef2aSThomas Huth 293b1bc09eaSRichard Henderson #if !defined(TARGET_SPARC64) 294b1bc09eaSRichard Henderson # define AM_CHECK(dc) false 295b1bc09eaSRichard Henderson #elif defined(TARGET_ABI32) 296b1bc09eaSRichard Henderson # define AM_CHECK(dc) true 297b1bc09eaSRichard Henderson #elif defined(CONFIG_USER_ONLY) 298b1bc09eaSRichard Henderson # define AM_CHECK(dc) false 299fcf5ef2aSThomas Huth #else 300b1bc09eaSRichard Henderson # define AM_CHECK(dc) ((dc)->address_mask_32bit) 301fcf5ef2aSThomas Huth #endif 302fcf5ef2aSThomas Huth 3030c2e96c1SRichard Henderson static void gen_address_mask(DisasContext *dc, TCGv addr) 304fcf5ef2aSThomas Huth { 305b1bc09eaSRichard Henderson if (AM_CHECK(dc)) { 306fcf5ef2aSThomas Huth tcg_gen_andi_tl(addr, addr, 0xffffffffULL); 307b1bc09eaSRichard Henderson } 308fcf5ef2aSThomas Huth } 309fcf5ef2aSThomas Huth 31023ada1b1SRichard Henderson static target_ulong address_mask_i(DisasContext *dc, target_ulong addr) 31123ada1b1SRichard Henderson { 31223ada1b1SRichard Henderson return AM_CHECK(dc) ? (uint32_t)addr : addr; 31323ada1b1SRichard Henderson } 31423ada1b1SRichard Henderson 3150c2e96c1SRichard Henderson static TCGv gen_load_gpr(DisasContext *dc, int reg) 316fcf5ef2aSThomas Huth { 317fcf5ef2aSThomas Huth if (reg > 0) { 318fcf5ef2aSThomas Huth assert(reg < 32); 319fcf5ef2aSThomas Huth return cpu_regs[reg]; 320fcf5ef2aSThomas Huth } else { 32152123f14SRichard Henderson TCGv t = tcg_temp_new(); 322fcf5ef2aSThomas Huth tcg_gen_movi_tl(t, 0); 323fcf5ef2aSThomas Huth return t; 324fcf5ef2aSThomas Huth } 325fcf5ef2aSThomas Huth } 326fcf5ef2aSThomas Huth 3270c2e96c1SRichard Henderson static void gen_store_gpr(DisasContext *dc, int reg, TCGv v) 328fcf5ef2aSThomas Huth { 329fcf5ef2aSThomas Huth if (reg > 0) { 330fcf5ef2aSThomas Huth assert(reg < 32); 331fcf5ef2aSThomas Huth tcg_gen_mov_tl(cpu_regs[reg], v); 332fcf5ef2aSThomas Huth } 333fcf5ef2aSThomas Huth } 334fcf5ef2aSThomas Huth 3350c2e96c1SRichard Henderson static TCGv gen_dest_gpr(DisasContext *dc, int reg) 336fcf5ef2aSThomas Huth { 337fcf5ef2aSThomas Huth if (reg > 0) { 338fcf5ef2aSThomas Huth assert(reg < 32); 339fcf5ef2aSThomas Huth return cpu_regs[reg]; 340fcf5ef2aSThomas Huth } else { 34152123f14SRichard Henderson return tcg_temp_new(); 342fcf5ef2aSThomas Huth } 343fcf5ef2aSThomas Huth } 344fcf5ef2aSThomas Huth 3455645aa2eSRichard Henderson static bool use_goto_tb(DisasContext *s, target_ulong pc, target_ulong npc) 346fcf5ef2aSThomas Huth { 3475645aa2eSRichard Henderson return translator_use_goto_tb(&s->base, pc) && 3485645aa2eSRichard Henderson translator_use_goto_tb(&s->base, npc); 349fcf5ef2aSThomas Huth } 350fcf5ef2aSThomas Huth 3515645aa2eSRichard Henderson static void gen_goto_tb(DisasContext *s, int tb_num, 352fcf5ef2aSThomas Huth target_ulong pc, target_ulong npc) 353fcf5ef2aSThomas Huth { 354fcf5ef2aSThomas Huth if (use_goto_tb(s, pc, npc)) { 355fcf5ef2aSThomas Huth /* jump to same page: we can use a direct jump */ 356fcf5ef2aSThomas Huth tcg_gen_goto_tb(tb_num); 357fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_pc, pc); 358fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_npc, npc); 35907ea28b4SRichard Henderson tcg_gen_exit_tb(s->base.tb, tb_num); 360fcf5ef2aSThomas Huth } else { 361f67ccb2fSRichard Henderson /* jump to another page: we can use an indirect jump */ 362fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_pc, pc); 363fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_npc, npc); 364f67ccb2fSRichard Henderson tcg_gen_lookup_and_goto_ptr(); 365fcf5ef2aSThomas Huth } 366fcf5ef2aSThomas Huth } 367fcf5ef2aSThomas Huth 368b989ce73SRichard Henderson static TCGv gen_carry32(void) 369fcf5ef2aSThomas Huth { 370b989ce73SRichard Henderson if (TARGET_LONG_BITS == 64) { 371b989ce73SRichard Henderson TCGv t = tcg_temp_new(); 372b989ce73SRichard Henderson tcg_gen_extract_tl(t, cpu_icc_C, 32, 1); 373b989ce73SRichard Henderson return t; 374b989ce73SRichard Henderson } 375b989ce73SRichard Henderson return cpu_icc_C; 376fcf5ef2aSThomas Huth } 377fcf5ef2aSThomas Huth 378b989ce73SRichard Henderson static void gen_op_addcc_int(TCGv dst, TCGv src1, TCGv src2, TCGv cin) 379fcf5ef2aSThomas Huth { 380b989ce73SRichard Henderson TCGv z = tcg_constant_tl(0); 381fcf5ef2aSThomas Huth 382b989ce73SRichard Henderson if (cin) { 383b989ce73SRichard Henderson tcg_gen_add2_tl(cpu_cc_N, cpu_cc_C, src1, z, cin, z); 384b989ce73SRichard Henderson tcg_gen_add2_tl(cpu_cc_N, cpu_cc_C, cpu_cc_N, cpu_cc_C, src2, z); 385b989ce73SRichard Henderson } else { 386b989ce73SRichard Henderson tcg_gen_add2_tl(cpu_cc_N, cpu_cc_C, src1, z, src2, z); 387b989ce73SRichard Henderson } 388b989ce73SRichard Henderson tcg_gen_xor_tl(cpu_cc_Z, src1, src2); 389b989ce73SRichard Henderson tcg_gen_xor_tl(cpu_cc_V, cpu_cc_N, src2); 390b989ce73SRichard Henderson tcg_gen_andc_tl(cpu_cc_V, cpu_cc_V, cpu_cc_Z); 391b989ce73SRichard Henderson if (TARGET_LONG_BITS == 64) { 392b989ce73SRichard Henderson /* 393b989ce73SRichard Henderson * Carry-in to bit 32 is result ^ src1 ^ src2. 394b989ce73SRichard Henderson * We already have the src xor term in Z, from computation of V. 395b989ce73SRichard Henderson */ 396b989ce73SRichard Henderson tcg_gen_xor_tl(cpu_icc_C, cpu_cc_Z, cpu_cc_N); 397b989ce73SRichard Henderson tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N); 398b989ce73SRichard Henderson } 399b989ce73SRichard Henderson tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N); 400b989ce73SRichard Henderson tcg_gen_mov_tl(dst, cpu_cc_N); 401b989ce73SRichard Henderson } 402fcf5ef2aSThomas Huth 403b989ce73SRichard Henderson static void gen_op_addcc(TCGv dst, TCGv src1, TCGv src2) 404b989ce73SRichard Henderson { 405b989ce73SRichard Henderson gen_op_addcc_int(dst, src1, src2, NULL); 406b989ce73SRichard Henderson } 407fcf5ef2aSThomas Huth 408b989ce73SRichard Henderson static void gen_op_taddcc(TCGv dst, TCGv src1, TCGv src2) 409b989ce73SRichard Henderson { 410b989ce73SRichard Henderson TCGv t = tcg_temp_new(); 411b989ce73SRichard Henderson 412b989ce73SRichard Henderson /* Save the tag bits around modification of dst. */ 413b989ce73SRichard Henderson tcg_gen_or_tl(t, src1, src2); 414b989ce73SRichard Henderson 415b989ce73SRichard Henderson gen_op_addcc(dst, src1, src2); 416b989ce73SRichard Henderson 417b989ce73SRichard Henderson /* Incorprate tag bits into icc.V */ 418b989ce73SRichard Henderson tcg_gen_andi_tl(t, t, 3); 419b989ce73SRichard Henderson tcg_gen_neg_tl(t, t); 420b989ce73SRichard Henderson tcg_gen_ext32u_tl(t, t); 421b989ce73SRichard Henderson tcg_gen_or_tl(cpu_cc_V, cpu_cc_V, t); 422b989ce73SRichard Henderson } 423b989ce73SRichard Henderson 424b989ce73SRichard Henderson static void gen_op_addc(TCGv dst, TCGv src1, TCGv src2) 425b989ce73SRichard Henderson { 426b989ce73SRichard Henderson tcg_gen_add_tl(dst, src1, src2); 427b989ce73SRichard Henderson tcg_gen_add_tl(dst, dst, gen_carry32()); 428b989ce73SRichard Henderson } 429b989ce73SRichard Henderson 430b989ce73SRichard Henderson static void gen_op_addccc(TCGv dst, TCGv src1, TCGv src2) 431b989ce73SRichard Henderson { 432b989ce73SRichard Henderson gen_op_addcc_int(dst, src1, src2, gen_carry32()); 433fcf5ef2aSThomas Huth } 434fcf5ef2aSThomas Huth 435f828df74SRichard Henderson static void gen_op_subcc_int(TCGv dst, TCGv src1, TCGv src2, TCGv cin) 436fcf5ef2aSThomas Huth { 437f828df74SRichard Henderson TCGv z = tcg_constant_tl(0); 438fcf5ef2aSThomas Huth 439f828df74SRichard Henderson if (cin) { 440f828df74SRichard Henderson tcg_gen_sub2_tl(cpu_cc_N, cpu_cc_C, src1, z, cin, z); 441f828df74SRichard Henderson tcg_gen_sub2_tl(cpu_cc_N, cpu_cc_C, cpu_cc_N, cpu_cc_C, src2, z); 442f828df74SRichard Henderson } else { 443f828df74SRichard Henderson tcg_gen_sub2_tl(cpu_cc_N, cpu_cc_C, src1, z, src2, z); 444f828df74SRichard Henderson } 445f828df74SRichard Henderson tcg_gen_neg_tl(cpu_cc_C, cpu_cc_C); 446f828df74SRichard Henderson tcg_gen_xor_tl(cpu_cc_Z, src1, src2); 447f828df74SRichard Henderson tcg_gen_xor_tl(cpu_cc_V, cpu_cc_N, src1); 448f828df74SRichard Henderson tcg_gen_and_tl(cpu_cc_V, cpu_cc_V, cpu_cc_Z); 449f828df74SRichard Henderson #ifdef TARGET_SPARC64 450f828df74SRichard Henderson tcg_gen_xor_tl(cpu_icc_C, cpu_cc_Z, cpu_cc_N); 451f828df74SRichard Henderson tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N); 452fcf5ef2aSThomas Huth #endif 453f828df74SRichard Henderson tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N); 454f828df74SRichard Henderson tcg_gen_mov_tl(dst, cpu_cc_N); 455fcf5ef2aSThomas Huth } 456fcf5ef2aSThomas Huth 457f828df74SRichard Henderson static void gen_op_subcc(TCGv dst, TCGv src1, TCGv src2) 458fcf5ef2aSThomas Huth { 459f828df74SRichard Henderson gen_op_subcc_int(dst, src1, src2, NULL); 460fcf5ef2aSThomas Huth } 461fcf5ef2aSThomas Huth 462f828df74SRichard Henderson static void gen_op_tsubcc(TCGv dst, TCGv src1, TCGv src2) 463fcf5ef2aSThomas Huth { 464f828df74SRichard Henderson TCGv t = tcg_temp_new(); 465fcf5ef2aSThomas Huth 466f828df74SRichard Henderson /* Save the tag bits around modification of dst. */ 467f828df74SRichard Henderson tcg_gen_or_tl(t, src1, src2); 468fcf5ef2aSThomas Huth 469f828df74SRichard Henderson gen_op_subcc(dst, src1, src2); 470f828df74SRichard Henderson 471f828df74SRichard Henderson /* Incorprate tag bits into icc.V */ 472f828df74SRichard Henderson tcg_gen_andi_tl(t, t, 3); 473f828df74SRichard Henderson tcg_gen_neg_tl(t, t); 474f828df74SRichard Henderson tcg_gen_ext32u_tl(t, t); 475f828df74SRichard Henderson tcg_gen_or_tl(cpu_cc_V, cpu_cc_V, t); 476f828df74SRichard Henderson } 477f828df74SRichard Henderson 478f828df74SRichard Henderson static void gen_op_subc(TCGv dst, TCGv src1, TCGv src2) 479f828df74SRichard Henderson { 480fcf5ef2aSThomas Huth tcg_gen_sub_tl(dst, src1, src2); 481f828df74SRichard Henderson tcg_gen_sub_tl(dst, dst, gen_carry32()); 482fcf5ef2aSThomas Huth } 483fcf5ef2aSThomas Huth 484f828df74SRichard Henderson static void gen_op_subccc(TCGv dst, TCGv src1, TCGv src2) 485dfebb950SRichard Henderson { 486f828df74SRichard Henderson gen_op_subcc_int(dst, src1, src2, gen_carry32()); 487dfebb950SRichard Henderson } 488dfebb950SRichard Henderson 4890c2e96c1SRichard Henderson static void gen_op_mulscc(TCGv dst, TCGv src1, TCGv src2) 490fcf5ef2aSThomas Huth { 491b989ce73SRichard Henderson TCGv zero = tcg_constant_tl(0); 49250280618SRichard Henderson TCGv one = tcg_constant_tl(1); 493b989ce73SRichard Henderson TCGv t_src1 = tcg_temp_new(); 494b989ce73SRichard Henderson TCGv t_src2 = tcg_temp_new(); 495b989ce73SRichard Henderson TCGv t0 = tcg_temp_new(); 496fcf5ef2aSThomas Huth 497b989ce73SRichard Henderson tcg_gen_ext32u_tl(t_src1, src1); 498b989ce73SRichard Henderson tcg_gen_ext32u_tl(t_src2, src2); 499fcf5ef2aSThomas Huth 500b989ce73SRichard Henderson /* 501b989ce73SRichard Henderson * if (!(env->y & 1)) 502b989ce73SRichard Henderson * src2 = 0; 503fcf5ef2aSThomas Huth */ 50450280618SRichard Henderson tcg_gen_movcond_tl(TCG_COND_TSTEQ, t_src2, cpu_y, one, zero, t_src2); 505fcf5ef2aSThomas Huth 506b989ce73SRichard Henderson /* 507b989ce73SRichard Henderson * b2 = src1 & 1; 508b989ce73SRichard Henderson * y = (b2 << 31) | (y >> 1); 509b989ce73SRichard Henderson */ 5100b1183e3SPhilippe Mathieu-Daudé tcg_gen_extract_tl(t0, cpu_y, 1, 31); 511b989ce73SRichard Henderson tcg_gen_deposit_tl(cpu_y, t0, src1, 31, 1); 512fcf5ef2aSThomas Huth 513fcf5ef2aSThomas Huth // b1 = N ^ V; 5142a1905c7SRichard Henderson tcg_gen_xor_tl(t0, cpu_cc_N, cpu_cc_V); 515fcf5ef2aSThomas Huth 516b989ce73SRichard Henderson /* 517b989ce73SRichard Henderson * src1 = (b1 << 31) | (src1 >> 1) 518b989ce73SRichard Henderson */ 5192a1905c7SRichard Henderson tcg_gen_andi_tl(t0, t0, 1u << 31); 520b989ce73SRichard Henderson tcg_gen_shri_tl(t_src1, t_src1, 1); 521b989ce73SRichard Henderson tcg_gen_or_tl(t_src1, t_src1, t0); 522fcf5ef2aSThomas Huth 523b989ce73SRichard Henderson gen_op_addcc(dst, t_src1, t_src2); 524fcf5ef2aSThomas Huth } 525fcf5ef2aSThomas Huth 5260c2e96c1SRichard Henderson static void gen_op_multiply(TCGv dst, TCGv src1, TCGv src2, int sign_ext) 527fcf5ef2aSThomas Huth { 528fcf5ef2aSThomas Huth #if TARGET_LONG_BITS == 32 529fcf5ef2aSThomas Huth if (sign_ext) { 530fcf5ef2aSThomas Huth tcg_gen_muls2_tl(dst, cpu_y, src1, src2); 531fcf5ef2aSThomas Huth } else { 532fcf5ef2aSThomas Huth tcg_gen_mulu2_tl(dst, cpu_y, src1, src2); 533fcf5ef2aSThomas Huth } 534fcf5ef2aSThomas Huth #else 535fcf5ef2aSThomas Huth TCGv t0 = tcg_temp_new_i64(); 536fcf5ef2aSThomas Huth TCGv t1 = tcg_temp_new_i64(); 537fcf5ef2aSThomas Huth 538fcf5ef2aSThomas Huth if (sign_ext) { 539fcf5ef2aSThomas Huth tcg_gen_ext32s_i64(t0, src1); 540fcf5ef2aSThomas Huth tcg_gen_ext32s_i64(t1, src2); 541fcf5ef2aSThomas Huth } else { 542fcf5ef2aSThomas Huth tcg_gen_ext32u_i64(t0, src1); 543fcf5ef2aSThomas Huth tcg_gen_ext32u_i64(t1, src2); 544fcf5ef2aSThomas Huth } 545fcf5ef2aSThomas Huth 546fcf5ef2aSThomas Huth tcg_gen_mul_i64(dst, t0, t1); 547fcf5ef2aSThomas Huth tcg_gen_shri_i64(cpu_y, dst, 32); 548fcf5ef2aSThomas Huth #endif 549fcf5ef2aSThomas Huth } 550fcf5ef2aSThomas Huth 5510c2e96c1SRichard Henderson static void gen_op_umul(TCGv dst, TCGv src1, TCGv src2) 552fcf5ef2aSThomas Huth { 553fcf5ef2aSThomas Huth /* zero-extend truncated operands before multiplication */ 554fcf5ef2aSThomas Huth gen_op_multiply(dst, src1, src2, 0); 555fcf5ef2aSThomas Huth } 556fcf5ef2aSThomas Huth 5570c2e96c1SRichard Henderson static void gen_op_smul(TCGv dst, TCGv src1, TCGv src2) 558fcf5ef2aSThomas Huth { 559fcf5ef2aSThomas Huth /* sign-extend truncated operands before multiplication */ 560fcf5ef2aSThomas Huth gen_op_multiply(dst, src1, src2, 1); 561fcf5ef2aSThomas Huth } 562fcf5ef2aSThomas Huth 563c2636853SRichard Henderson static void gen_op_sdiv(TCGv dst, TCGv src1, TCGv src2) 564c2636853SRichard Henderson { 56513260103SRichard Henderson #ifdef TARGET_SPARC64 566c2636853SRichard Henderson gen_helper_sdiv(dst, tcg_env, src1, src2); 56713260103SRichard Henderson tcg_gen_ext32s_tl(dst, dst); 56813260103SRichard Henderson #else 56913260103SRichard Henderson TCGv_i64 t64 = tcg_temp_new_i64(); 57013260103SRichard Henderson gen_helper_sdiv(t64, tcg_env, src1, src2); 57113260103SRichard Henderson tcg_gen_trunc_i64_tl(dst, t64); 57213260103SRichard Henderson #endif 573c2636853SRichard Henderson } 574c2636853SRichard Henderson 575c2636853SRichard Henderson static void gen_op_udivcc(TCGv dst, TCGv src1, TCGv src2) 576c2636853SRichard Henderson { 57713260103SRichard Henderson TCGv_i64 t64; 57813260103SRichard Henderson 57913260103SRichard Henderson #ifdef TARGET_SPARC64 58013260103SRichard Henderson t64 = cpu_cc_V; 58113260103SRichard Henderson #else 58213260103SRichard Henderson t64 = tcg_temp_new_i64(); 58313260103SRichard Henderson #endif 58413260103SRichard Henderson 58513260103SRichard Henderson gen_helper_udiv(t64, tcg_env, src1, src2); 58613260103SRichard Henderson 58713260103SRichard Henderson #ifdef TARGET_SPARC64 58813260103SRichard Henderson tcg_gen_ext32u_tl(cpu_cc_N, t64); 58913260103SRichard Henderson tcg_gen_shri_tl(cpu_cc_V, t64, 32); 59013260103SRichard Henderson tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N); 59113260103SRichard Henderson tcg_gen_movi_tl(cpu_icc_C, 0); 59213260103SRichard Henderson #else 59313260103SRichard Henderson tcg_gen_extr_i64_tl(cpu_cc_N, cpu_cc_V, t64); 59413260103SRichard Henderson #endif 59513260103SRichard Henderson tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N); 59613260103SRichard Henderson tcg_gen_movi_tl(cpu_cc_C, 0); 59713260103SRichard Henderson tcg_gen_mov_tl(dst, cpu_cc_N); 598c2636853SRichard Henderson } 599c2636853SRichard Henderson 600c2636853SRichard Henderson static void gen_op_sdivcc(TCGv dst, TCGv src1, TCGv src2) 601c2636853SRichard Henderson { 60213260103SRichard Henderson TCGv_i64 t64; 60313260103SRichard Henderson 60413260103SRichard Henderson #ifdef TARGET_SPARC64 60513260103SRichard Henderson t64 = cpu_cc_V; 60613260103SRichard Henderson #else 60713260103SRichard Henderson t64 = tcg_temp_new_i64(); 60813260103SRichard Henderson #endif 60913260103SRichard Henderson 61013260103SRichard Henderson gen_helper_sdiv(t64, tcg_env, src1, src2); 61113260103SRichard Henderson 61213260103SRichard Henderson #ifdef TARGET_SPARC64 61313260103SRichard Henderson tcg_gen_ext32s_tl(cpu_cc_N, t64); 61413260103SRichard Henderson tcg_gen_shri_tl(cpu_cc_V, t64, 32); 61513260103SRichard Henderson tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N); 61613260103SRichard Henderson tcg_gen_movi_tl(cpu_icc_C, 0); 61713260103SRichard Henderson #else 61813260103SRichard Henderson tcg_gen_extr_i64_tl(cpu_cc_N, cpu_cc_V, t64); 61913260103SRichard Henderson #endif 62013260103SRichard Henderson tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N); 62113260103SRichard Henderson tcg_gen_movi_tl(cpu_cc_C, 0); 62213260103SRichard Henderson tcg_gen_mov_tl(dst, cpu_cc_N); 623c2636853SRichard Henderson } 624c2636853SRichard Henderson 625a9aba13dSRichard Henderson static void gen_op_taddcctv(TCGv dst, TCGv src1, TCGv src2) 626a9aba13dSRichard Henderson { 627a9aba13dSRichard Henderson gen_helper_taddcctv(dst, tcg_env, src1, src2); 628a9aba13dSRichard Henderson } 629a9aba13dSRichard Henderson 630a9aba13dSRichard Henderson static void gen_op_tsubcctv(TCGv dst, TCGv src1, TCGv src2) 631a9aba13dSRichard Henderson { 632a9aba13dSRichard Henderson gen_helper_tsubcctv(dst, tcg_env, src1, src2); 633a9aba13dSRichard Henderson } 634a9aba13dSRichard Henderson 6359c6ec5bcSRichard Henderson static void gen_op_popc(TCGv dst, TCGv src1, TCGv src2) 6369c6ec5bcSRichard Henderson { 6379c6ec5bcSRichard Henderson tcg_gen_ctpop_tl(dst, src2); 6389c6ec5bcSRichard Henderson } 6399c6ec5bcSRichard Henderson 64045bfed3bSRichard Henderson #ifndef TARGET_SPARC64 64145bfed3bSRichard Henderson static void gen_helper_array8(TCGv dst, TCGv src1, TCGv src2) 64245bfed3bSRichard Henderson { 64345bfed3bSRichard Henderson g_assert_not_reached(); 64445bfed3bSRichard Henderson } 64545bfed3bSRichard Henderson #endif 64645bfed3bSRichard Henderson 64745bfed3bSRichard Henderson static void gen_op_array16(TCGv dst, TCGv src1, TCGv src2) 64845bfed3bSRichard Henderson { 64945bfed3bSRichard Henderson gen_helper_array8(dst, src1, src2); 65045bfed3bSRichard Henderson tcg_gen_shli_tl(dst, dst, 1); 65145bfed3bSRichard Henderson } 65245bfed3bSRichard Henderson 65345bfed3bSRichard Henderson static void gen_op_array32(TCGv dst, TCGv src1, TCGv src2) 65445bfed3bSRichard Henderson { 65545bfed3bSRichard Henderson gen_helper_array8(dst, src1, src2); 65645bfed3bSRichard Henderson tcg_gen_shli_tl(dst, dst, 2); 65745bfed3bSRichard Henderson } 65845bfed3bSRichard Henderson 6592f722641SRichard Henderson static void gen_op_fpack16(TCGv_i32 dst, TCGv_i64 src) 6602f722641SRichard Henderson { 6612f722641SRichard Henderson #ifdef TARGET_SPARC64 6622f722641SRichard Henderson gen_helper_fpack16(dst, cpu_gsr, src); 6632f722641SRichard Henderson #else 6642f722641SRichard Henderson g_assert_not_reached(); 6652f722641SRichard Henderson #endif 6662f722641SRichard Henderson } 6672f722641SRichard Henderson 6682f722641SRichard Henderson static void gen_op_fpackfix(TCGv_i32 dst, TCGv_i64 src) 6692f722641SRichard Henderson { 6702f722641SRichard Henderson #ifdef TARGET_SPARC64 6712f722641SRichard Henderson gen_helper_fpackfix(dst, cpu_gsr, src); 6722f722641SRichard Henderson #else 6732f722641SRichard Henderson g_assert_not_reached(); 6742f722641SRichard Henderson #endif 6752f722641SRichard Henderson } 6762f722641SRichard Henderson 6774b6edc0aSRichard Henderson static void gen_op_fpack32(TCGv_i64 dst, TCGv_i64 src1, TCGv_i64 src2) 6784b6edc0aSRichard Henderson { 6794b6edc0aSRichard Henderson #ifdef TARGET_SPARC64 6804b6edc0aSRichard Henderson gen_helper_fpack32(dst, cpu_gsr, src1, src2); 6814b6edc0aSRichard Henderson #else 6824b6edc0aSRichard Henderson g_assert_not_reached(); 6834b6edc0aSRichard Henderson #endif 6844b6edc0aSRichard Henderson } 6854b6edc0aSRichard Henderson 6864b6edc0aSRichard Henderson static void gen_op_faligndata(TCGv_i64 dst, TCGv_i64 s1, TCGv_i64 s2) 6874b6edc0aSRichard Henderson { 6884b6edc0aSRichard Henderson #ifdef TARGET_SPARC64 6894b6edc0aSRichard Henderson TCGv t1, t2, shift; 6904b6edc0aSRichard Henderson 6914b6edc0aSRichard Henderson t1 = tcg_temp_new(); 6924b6edc0aSRichard Henderson t2 = tcg_temp_new(); 6934b6edc0aSRichard Henderson shift = tcg_temp_new(); 6944b6edc0aSRichard Henderson 6954b6edc0aSRichard Henderson tcg_gen_andi_tl(shift, cpu_gsr, 7); 6964b6edc0aSRichard Henderson tcg_gen_shli_tl(shift, shift, 3); 6974b6edc0aSRichard Henderson tcg_gen_shl_tl(t1, s1, shift); 6984b6edc0aSRichard Henderson 6994b6edc0aSRichard Henderson /* 7004b6edc0aSRichard Henderson * A shift of 64 does not produce 0 in TCG. Divide this into a 7014b6edc0aSRichard Henderson * shift of (up to 63) followed by a constant shift of 1. 7024b6edc0aSRichard Henderson */ 7034b6edc0aSRichard Henderson tcg_gen_xori_tl(shift, shift, 63); 7044b6edc0aSRichard Henderson tcg_gen_shr_tl(t2, s2, shift); 7054b6edc0aSRichard Henderson tcg_gen_shri_tl(t2, t2, 1); 7064b6edc0aSRichard Henderson 7074b6edc0aSRichard Henderson tcg_gen_or_tl(dst, t1, t2); 7084b6edc0aSRichard Henderson #else 7094b6edc0aSRichard Henderson g_assert_not_reached(); 7104b6edc0aSRichard Henderson #endif 7114b6edc0aSRichard Henderson } 7124b6edc0aSRichard Henderson 7134b6edc0aSRichard Henderson static void gen_op_bshuffle(TCGv_i64 dst, TCGv_i64 src1, TCGv_i64 src2) 7144b6edc0aSRichard Henderson { 7154b6edc0aSRichard Henderson #ifdef TARGET_SPARC64 7164b6edc0aSRichard Henderson gen_helper_bshuffle(dst, cpu_gsr, src1, src2); 7174b6edc0aSRichard Henderson #else 7184b6edc0aSRichard Henderson g_assert_not_reached(); 7194b6edc0aSRichard Henderson #endif 7204b6edc0aSRichard Henderson } 7214b6edc0aSRichard Henderson 72289527e3aSRichard Henderson static void finishing_insn(DisasContext *dc) 72389527e3aSRichard Henderson { 72489527e3aSRichard Henderson /* 72589527e3aSRichard Henderson * From here, there is no future path through an unwinding exception. 72689527e3aSRichard Henderson * If the current insn cannot raise an exception, the computation of 72789527e3aSRichard Henderson * cpu_cond may be able to be elided. 72889527e3aSRichard Henderson */ 72989527e3aSRichard Henderson if (dc->cpu_cond_live) { 73089527e3aSRichard Henderson tcg_gen_discard_tl(cpu_cond); 73189527e3aSRichard Henderson dc->cpu_cond_live = false; 73289527e3aSRichard Henderson } 73389527e3aSRichard Henderson } 73489527e3aSRichard Henderson 7350c2e96c1SRichard Henderson static void gen_generic_branch(DisasContext *dc) 736fcf5ef2aSThomas Huth { 73700ab7e61SRichard Henderson TCGv npc0 = tcg_constant_tl(dc->jump_pc[0]); 73800ab7e61SRichard Henderson TCGv npc1 = tcg_constant_tl(dc->jump_pc[1]); 739533f042fSRichard Henderson TCGv c2 = tcg_constant_tl(dc->jump.c2); 740fcf5ef2aSThomas Huth 741533f042fSRichard Henderson tcg_gen_movcond_tl(dc->jump.cond, cpu_npc, dc->jump.c1, c2, npc0, npc1); 742fcf5ef2aSThomas Huth } 743fcf5ef2aSThomas Huth 744fcf5ef2aSThomas Huth /* call this function before using the condition register as it may 745fcf5ef2aSThomas Huth have been set for a jump */ 7460c2e96c1SRichard Henderson static void flush_cond(DisasContext *dc) 747fcf5ef2aSThomas Huth { 748fcf5ef2aSThomas Huth if (dc->npc == JUMP_PC) { 749fcf5ef2aSThomas Huth gen_generic_branch(dc); 75099c82c47SRichard Henderson dc->npc = DYNAMIC_PC_LOOKUP; 751fcf5ef2aSThomas Huth } 752fcf5ef2aSThomas Huth } 753fcf5ef2aSThomas Huth 7540c2e96c1SRichard Henderson static void save_npc(DisasContext *dc) 755fcf5ef2aSThomas Huth { 756633c4283SRichard Henderson if (dc->npc & 3) { 757633c4283SRichard Henderson switch (dc->npc) { 758633c4283SRichard Henderson case JUMP_PC: 759fcf5ef2aSThomas Huth gen_generic_branch(dc); 76099c82c47SRichard Henderson dc->npc = DYNAMIC_PC_LOOKUP; 761633c4283SRichard Henderson break; 762633c4283SRichard Henderson case DYNAMIC_PC: 763633c4283SRichard Henderson case DYNAMIC_PC_LOOKUP: 764633c4283SRichard Henderson break; 765633c4283SRichard Henderson default: 766633c4283SRichard Henderson g_assert_not_reached(); 767633c4283SRichard Henderson } 768633c4283SRichard Henderson } else { 769fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_npc, dc->npc); 770fcf5ef2aSThomas Huth } 771fcf5ef2aSThomas Huth } 772fcf5ef2aSThomas Huth 7730c2e96c1SRichard Henderson static void save_state(DisasContext *dc) 774fcf5ef2aSThomas Huth { 775fcf5ef2aSThomas Huth tcg_gen_movi_tl(cpu_pc, dc->pc); 776fcf5ef2aSThomas Huth save_npc(dc); 777fcf5ef2aSThomas Huth } 778fcf5ef2aSThomas Huth 779fcf5ef2aSThomas Huth static void gen_exception(DisasContext *dc, int which) 780fcf5ef2aSThomas Huth { 78189527e3aSRichard Henderson finishing_insn(dc); 782fcf5ef2aSThomas Huth save_state(dc); 783ad75a51eSRichard Henderson gen_helper_raise_exception(tcg_env, tcg_constant_i32(which)); 784af00be49SEmilio G. Cota dc->base.is_jmp = DISAS_NORETURN; 785fcf5ef2aSThomas Huth } 786fcf5ef2aSThomas Huth 787186e7890SRichard Henderson static TCGLabel *delay_exceptionv(DisasContext *dc, TCGv_i32 excp) 788fcf5ef2aSThomas Huth { 789186e7890SRichard Henderson DisasDelayException *e = g_new0(DisasDelayException, 1); 790186e7890SRichard Henderson 791186e7890SRichard Henderson e->next = dc->delay_excp_list; 792186e7890SRichard Henderson dc->delay_excp_list = e; 793186e7890SRichard Henderson 794186e7890SRichard Henderson e->lab = gen_new_label(); 795186e7890SRichard Henderson e->excp = excp; 796186e7890SRichard Henderson e->pc = dc->pc; 797186e7890SRichard Henderson /* Caller must have used flush_cond before branch. */ 798186e7890SRichard Henderson assert(e->npc != JUMP_PC); 799186e7890SRichard Henderson e->npc = dc->npc; 800186e7890SRichard Henderson 801186e7890SRichard Henderson return e->lab; 802186e7890SRichard Henderson } 803186e7890SRichard Henderson 804186e7890SRichard Henderson static TCGLabel *delay_exception(DisasContext *dc, int excp) 805186e7890SRichard Henderson { 806186e7890SRichard Henderson return delay_exceptionv(dc, tcg_constant_i32(excp)); 807186e7890SRichard Henderson } 808186e7890SRichard Henderson 809186e7890SRichard Henderson static void gen_check_align(DisasContext *dc, TCGv addr, int mask) 810186e7890SRichard Henderson { 811186e7890SRichard Henderson TCGv t = tcg_temp_new(); 812186e7890SRichard Henderson TCGLabel *lab; 813186e7890SRichard Henderson 814186e7890SRichard Henderson tcg_gen_andi_tl(t, addr, mask); 815186e7890SRichard Henderson 816186e7890SRichard Henderson flush_cond(dc); 817186e7890SRichard Henderson lab = delay_exception(dc, TT_UNALIGNED); 818186e7890SRichard Henderson tcg_gen_brcondi_tl(TCG_COND_NE, t, 0, lab); 819fcf5ef2aSThomas Huth } 820fcf5ef2aSThomas Huth 8210c2e96c1SRichard Henderson static void gen_mov_pc_npc(DisasContext *dc) 822fcf5ef2aSThomas Huth { 82389527e3aSRichard Henderson finishing_insn(dc); 82489527e3aSRichard Henderson 825633c4283SRichard Henderson if (dc->npc & 3) { 826633c4283SRichard Henderson switch (dc->npc) { 827633c4283SRichard Henderson case JUMP_PC: 828fcf5ef2aSThomas Huth gen_generic_branch(dc); 829fcf5ef2aSThomas Huth tcg_gen_mov_tl(cpu_pc, cpu_npc); 83099c82c47SRichard Henderson dc->pc = DYNAMIC_PC_LOOKUP; 831633c4283SRichard Henderson break; 832633c4283SRichard Henderson case DYNAMIC_PC: 833633c4283SRichard Henderson case DYNAMIC_PC_LOOKUP: 834fcf5ef2aSThomas Huth tcg_gen_mov_tl(cpu_pc, cpu_npc); 835633c4283SRichard Henderson dc->pc = dc->npc; 836633c4283SRichard Henderson break; 837633c4283SRichard Henderson default: 838633c4283SRichard Henderson g_assert_not_reached(); 839633c4283SRichard Henderson } 840fcf5ef2aSThomas Huth } else { 841fcf5ef2aSThomas Huth dc->pc = dc->npc; 842fcf5ef2aSThomas Huth } 843fcf5ef2aSThomas Huth } 844fcf5ef2aSThomas Huth 845fcf5ef2aSThomas Huth static void gen_compare(DisasCompare *cmp, bool xcc, unsigned int cond, 846fcf5ef2aSThomas Huth DisasContext *dc) 847fcf5ef2aSThomas Huth { 848b597eedcSRichard Henderson TCGv t1; 849fcf5ef2aSThomas Huth 8502a1905c7SRichard Henderson cmp->c1 = t1 = tcg_temp_new(); 851c8507ebfSRichard Henderson cmp->c2 = 0; 8522a1905c7SRichard Henderson 8532a1905c7SRichard Henderson switch (cond & 7) { 8542a1905c7SRichard Henderson case 0x0: /* never */ 8552a1905c7SRichard Henderson cmp->cond = TCG_COND_NEVER; 856c8507ebfSRichard Henderson cmp->c1 = tcg_constant_tl(0); 857fcf5ef2aSThomas Huth break; 8582a1905c7SRichard Henderson 8592a1905c7SRichard Henderson case 0x1: /* eq: Z */ 8602a1905c7SRichard Henderson cmp->cond = TCG_COND_EQ; 8612a1905c7SRichard Henderson if (TARGET_LONG_BITS == 32 || xcc) { 8622a1905c7SRichard Henderson tcg_gen_mov_tl(t1, cpu_cc_Z); 8632a1905c7SRichard Henderson } else { 8642a1905c7SRichard Henderson tcg_gen_ext32u_tl(t1, cpu_icc_Z); 8652a1905c7SRichard Henderson } 8662a1905c7SRichard Henderson break; 8672a1905c7SRichard Henderson 8682a1905c7SRichard Henderson case 0x2: /* le: Z | (N ^ V) */ 8692a1905c7SRichard Henderson /* 8702a1905c7SRichard Henderson * Simplify: 8712a1905c7SRichard Henderson * cc_Z || (N ^ V) < 0 NE 8722a1905c7SRichard Henderson * cc_Z && !((N ^ V) < 0) EQ 8732a1905c7SRichard Henderson * cc_Z & ~((N ^ V) >> TLB) EQ 8742a1905c7SRichard Henderson */ 8752a1905c7SRichard Henderson cmp->cond = TCG_COND_EQ; 8762a1905c7SRichard Henderson tcg_gen_xor_tl(t1, cpu_cc_N, cpu_cc_V); 8772a1905c7SRichard Henderson tcg_gen_sextract_tl(t1, t1, xcc ? 63 : 31, 1); 8782a1905c7SRichard Henderson tcg_gen_andc_tl(t1, xcc ? cpu_cc_Z : cpu_icc_Z, t1); 8792a1905c7SRichard Henderson if (TARGET_LONG_BITS == 64 && !xcc) { 8802a1905c7SRichard Henderson tcg_gen_ext32u_tl(t1, t1); 8812a1905c7SRichard Henderson } 8822a1905c7SRichard Henderson break; 8832a1905c7SRichard Henderson 8842a1905c7SRichard Henderson case 0x3: /* lt: N ^ V */ 8852a1905c7SRichard Henderson cmp->cond = TCG_COND_LT; 8862a1905c7SRichard Henderson tcg_gen_xor_tl(t1, cpu_cc_N, cpu_cc_V); 8872a1905c7SRichard Henderson if (TARGET_LONG_BITS == 64 && !xcc) { 8882a1905c7SRichard Henderson tcg_gen_ext32s_tl(t1, t1); 8892a1905c7SRichard Henderson } 8902a1905c7SRichard Henderson break; 8912a1905c7SRichard Henderson 8922a1905c7SRichard Henderson case 0x4: /* leu: Z | C */ 8932a1905c7SRichard Henderson /* 8942a1905c7SRichard Henderson * Simplify: 8952a1905c7SRichard Henderson * cc_Z == 0 || cc_C != 0 NE 8962a1905c7SRichard Henderson * cc_Z != 0 && cc_C == 0 EQ 8972a1905c7SRichard Henderson * cc_Z & (cc_C ? 0 : -1) EQ 8982a1905c7SRichard Henderson * cc_Z & (cc_C - 1) EQ 8992a1905c7SRichard Henderson */ 9002a1905c7SRichard Henderson cmp->cond = TCG_COND_EQ; 9012a1905c7SRichard Henderson if (TARGET_LONG_BITS == 32 || xcc) { 9022a1905c7SRichard Henderson tcg_gen_subi_tl(t1, cpu_cc_C, 1); 9032a1905c7SRichard Henderson tcg_gen_and_tl(t1, t1, cpu_cc_Z); 9042a1905c7SRichard Henderson } else { 9052a1905c7SRichard Henderson tcg_gen_extract_tl(t1, cpu_icc_C, 32, 1); 9062a1905c7SRichard Henderson tcg_gen_subi_tl(t1, t1, 1); 9072a1905c7SRichard Henderson tcg_gen_and_tl(t1, t1, cpu_icc_Z); 9082a1905c7SRichard Henderson tcg_gen_ext32u_tl(t1, t1); 9092a1905c7SRichard Henderson } 9102a1905c7SRichard Henderson break; 9112a1905c7SRichard Henderson 9122a1905c7SRichard Henderson case 0x5: /* ltu: C */ 9132a1905c7SRichard Henderson cmp->cond = TCG_COND_NE; 9142a1905c7SRichard Henderson if (TARGET_LONG_BITS == 32 || xcc) { 9152a1905c7SRichard Henderson tcg_gen_mov_tl(t1, cpu_cc_C); 9162a1905c7SRichard Henderson } else { 9172a1905c7SRichard Henderson tcg_gen_extract_tl(t1, cpu_icc_C, 32, 1); 9182a1905c7SRichard Henderson } 9192a1905c7SRichard Henderson break; 9202a1905c7SRichard Henderson 9212a1905c7SRichard Henderson case 0x6: /* neg: N */ 9222a1905c7SRichard Henderson cmp->cond = TCG_COND_LT; 9232a1905c7SRichard Henderson if (TARGET_LONG_BITS == 32 || xcc) { 9242a1905c7SRichard Henderson tcg_gen_mov_tl(t1, cpu_cc_N); 9252a1905c7SRichard Henderson } else { 9262a1905c7SRichard Henderson tcg_gen_ext32s_tl(t1, cpu_cc_N); 9272a1905c7SRichard Henderson } 9282a1905c7SRichard Henderson break; 9292a1905c7SRichard Henderson 9302a1905c7SRichard Henderson case 0x7: /* vs: V */ 9312a1905c7SRichard Henderson cmp->cond = TCG_COND_LT; 9322a1905c7SRichard Henderson if (TARGET_LONG_BITS == 32 || xcc) { 9332a1905c7SRichard Henderson tcg_gen_mov_tl(t1, cpu_cc_V); 9342a1905c7SRichard Henderson } else { 9352a1905c7SRichard Henderson tcg_gen_ext32s_tl(t1, cpu_cc_V); 9362a1905c7SRichard Henderson } 9372a1905c7SRichard Henderson break; 9382a1905c7SRichard Henderson } 9392a1905c7SRichard Henderson if (cond & 8) { 9402a1905c7SRichard Henderson cmp->cond = tcg_invert_cond(cmp->cond); 941fcf5ef2aSThomas Huth } 942fcf5ef2aSThomas Huth } 943fcf5ef2aSThomas Huth 944fcf5ef2aSThomas Huth static void gen_fcompare(DisasCompare *cmp, unsigned int cc, unsigned int cond) 945fcf5ef2aSThomas Huth { 946d8c5b92fSRichard Henderson TCGv_i32 fcc = cpu_fcc[cc]; 947d8c5b92fSRichard Henderson TCGv_i32 c1 = fcc; 948d8c5b92fSRichard Henderson int c2 = 0; 949d8c5b92fSRichard Henderson TCGCond tcond; 950fcf5ef2aSThomas Huth 951d8c5b92fSRichard Henderson /* 952d8c5b92fSRichard Henderson * FCC values: 953d8c5b92fSRichard Henderson * 0 = 954d8c5b92fSRichard Henderson * 1 < 955d8c5b92fSRichard Henderson * 2 > 956d8c5b92fSRichard Henderson * 3 unordered 957d8c5b92fSRichard Henderson */ 958d8c5b92fSRichard Henderson switch (cond & 7) { 959d8c5b92fSRichard Henderson case 0x0: /* fbn */ 960d8c5b92fSRichard Henderson tcond = TCG_COND_NEVER; 961fcf5ef2aSThomas Huth break; 962d8c5b92fSRichard Henderson case 0x1: /* fbne : !0 */ 963d8c5b92fSRichard Henderson tcond = TCG_COND_NE; 964fcf5ef2aSThomas Huth break; 965d8c5b92fSRichard Henderson case 0x2: /* fblg : 1 or 2 */ 966d8c5b92fSRichard Henderson /* fcc in {1,2} - 1 -> fcc in {0,1} */ 967d8c5b92fSRichard Henderson c1 = tcg_temp_new_i32(); 968d8c5b92fSRichard Henderson tcg_gen_addi_i32(c1, fcc, -1); 969d8c5b92fSRichard Henderson c2 = 1; 970d8c5b92fSRichard Henderson tcond = TCG_COND_LEU; 971fcf5ef2aSThomas Huth break; 972d8c5b92fSRichard Henderson case 0x3: /* fbul : 1 or 3 */ 973d8c5b92fSRichard Henderson c1 = tcg_temp_new_i32(); 974d8c5b92fSRichard Henderson tcg_gen_andi_i32(c1, fcc, 1); 975d8c5b92fSRichard Henderson tcond = TCG_COND_NE; 976d8c5b92fSRichard Henderson break; 977d8c5b92fSRichard Henderson case 0x4: /* fbl : 1 */ 978d8c5b92fSRichard Henderson c2 = 1; 979d8c5b92fSRichard Henderson tcond = TCG_COND_EQ; 980d8c5b92fSRichard Henderson break; 981d8c5b92fSRichard Henderson case 0x5: /* fbug : 2 or 3 */ 982d8c5b92fSRichard Henderson c2 = 2; 983d8c5b92fSRichard Henderson tcond = TCG_COND_GEU; 984d8c5b92fSRichard Henderson break; 985d8c5b92fSRichard Henderson case 0x6: /* fbg : 2 */ 986d8c5b92fSRichard Henderson c2 = 2; 987d8c5b92fSRichard Henderson tcond = TCG_COND_EQ; 988d8c5b92fSRichard Henderson break; 989d8c5b92fSRichard Henderson case 0x7: /* fbu : 3 */ 990d8c5b92fSRichard Henderson c2 = 3; 991d8c5b92fSRichard Henderson tcond = TCG_COND_EQ; 992fcf5ef2aSThomas Huth break; 993fcf5ef2aSThomas Huth } 994d8c5b92fSRichard Henderson if (cond & 8) { 995d8c5b92fSRichard Henderson tcond = tcg_invert_cond(tcond); 996fcf5ef2aSThomas Huth } 997d8c5b92fSRichard Henderson 998d8c5b92fSRichard Henderson cmp->cond = tcond; 999d8c5b92fSRichard Henderson cmp->c2 = c2; 1000d8c5b92fSRichard Henderson cmp->c1 = tcg_temp_new(); 1001d8c5b92fSRichard Henderson tcg_gen_extu_i32_tl(cmp->c1, c1); 1002fcf5ef2aSThomas Huth } 1003fcf5ef2aSThomas Huth 10042c4f56c9SRichard Henderson static bool gen_compare_reg(DisasCompare *cmp, int cond, TCGv r_src) 10052c4f56c9SRichard Henderson { 10062c4f56c9SRichard Henderson static const TCGCond cond_reg[4] = { 1007ab9ffe98SRichard Henderson TCG_COND_NEVER, /* reserved */ 1008fcf5ef2aSThomas Huth TCG_COND_EQ, 1009fcf5ef2aSThomas Huth TCG_COND_LE, 1010fcf5ef2aSThomas Huth TCG_COND_LT, 1011fcf5ef2aSThomas Huth }; 10122c4f56c9SRichard Henderson TCGCond tcond; 1013fcf5ef2aSThomas Huth 10142c4f56c9SRichard Henderson if ((cond & 3) == 0) { 10152c4f56c9SRichard Henderson return false; 10162c4f56c9SRichard Henderson } 10172c4f56c9SRichard Henderson tcond = cond_reg[cond & 3]; 10182c4f56c9SRichard Henderson if (cond & 4) { 10192c4f56c9SRichard Henderson tcond = tcg_invert_cond(tcond); 10202c4f56c9SRichard Henderson } 10212c4f56c9SRichard Henderson 10222c4f56c9SRichard Henderson cmp->cond = tcond; 1023816f89b7SRichard Henderson cmp->c1 = tcg_temp_new(); 1024c8507ebfSRichard Henderson cmp->c2 = 0; 1025816f89b7SRichard Henderson tcg_gen_mov_tl(cmp->c1, r_src); 10262c4f56c9SRichard Henderson return true; 1027fcf5ef2aSThomas Huth } 1028fcf5ef2aSThomas Huth 1029baf3dbf2SRichard Henderson static void gen_op_clear_ieee_excp_and_FTT(void) 1030baf3dbf2SRichard Henderson { 10313590f01eSRichard Henderson tcg_gen_st_i32(tcg_constant_i32(0), tcg_env, 10323590f01eSRichard Henderson offsetof(CPUSPARCState, fsr_cexc_ftt)); 1033baf3dbf2SRichard Henderson } 1034baf3dbf2SRichard Henderson 1035baf3dbf2SRichard Henderson static void gen_op_fmovs(TCGv_i32 dst, TCGv_i32 src) 1036baf3dbf2SRichard Henderson { 1037baf3dbf2SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 1038baf3dbf2SRichard Henderson tcg_gen_mov_i32(dst, src); 1039baf3dbf2SRichard Henderson } 1040baf3dbf2SRichard Henderson 1041baf3dbf2SRichard Henderson static void gen_op_fnegs(TCGv_i32 dst, TCGv_i32 src) 1042baf3dbf2SRichard Henderson { 1043baf3dbf2SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 1044daf457d4SRichard Henderson tcg_gen_xori_i32(dst, src, 1u << 31); 1045baf3dbf2SRichard Henderson } 1046baf3dbf2SRichard Henderson 1047baf3dbf2SRichard Henderson static void gen_op_fabss(TCGv_i32 dst, TCGv_i32 src) 1048baf3dbf2SRichard Henderson { 1049baf3dbf2SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 1050daf457d4SRichard Henderson tcg_gen_andi_i32(dst, src, ~(1u << 31)); 1051baf3dbf2SRichard Henderson } 1052baf3dbf2SRichard Henderson 1053c6d83e4fSRichard Henderson static void gen_op_fmovd(TCGv_i64 dst, TCGv_i64 src) 1054c6d83e4fSRichard Henderson { 1055c6d83e4fSRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 1056c6d83e4fSRichard Henderson tcg_gen_mov_i64(dst, src); 1057c6d83e4fSRichard Henderson } 1058c6d83e4fSRichard Henderson 1059c6d83e4fSRichard Henderson static void gen_op_fnegd(TCGv_i64 dst, TCGv_i64 src) 1060c6d83e4fSRichard Henderson { 1061c6d83e4fSRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 1062daf457d4SRichard Henderson tcg_gen_xori_i64(dst, src, 1ull << 63); 1063c6d83e4fSRichard Henderson } 1064c6d83e4fSRichard Henderson 1065c6d83e4fSRichard Henderson static void gen_op_fabsd(TCGv_i64 dst, TCGv_i64 src) 1066c6d83e4fSRichard Henderson { 1067c6d83e4fSRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 1068daf457d4SRichard Henderson tcg_gen_andi_i64(dst, src, ~(1ull << 63)); 1069daf457d4SRichard Henderson } 1070daf457d4SRichard Henderson 1071daf457d4SRichard Henderson static void gen_op_fnegq(TCGv_i128 dst, TCGv_i128 src) 1072daf457d4SRichard Henderson { 1073daf457d4SRichard Henderson TCGv_i64 l = tcg_temp_new_i64(); 1074daf457d4SRichard Henderson TCGv_i64 h = tcg_temp_new_i64(); 1075daf457d4SRichard Henderson 1076daf457d4SRichard Henderson tcg_gen_extr_i128_i64(l, h, src); 1077daf457d4SRichard Henderson tcg_gen_xori_i64(h, h, 1ull << 63); 1078daf457d4SRichard Henderson tcg_gen_concat_i64_i128(dst, l, h); 1079daf457d4SRichard Henderson } 1080daf457d4SRichard Henderson 1081daf457d4SRichard Henderson static void gen_op_fabsq(TCGv_i128 dst, TCGv_i128 src) 1082daf457d4SRichard Henderson { 1083daf457d4SRichard Henderson TCGv_i64 l = tcg_temp_new_i64(); 1084daf457d4SRichard Henderson TCGv_i64 h = tcg_temp_new_i64(); 1085daf457d4SRichard Henderson 1086daf457d4SRichard Henderson tcg_gen_extr_i128_i64(l, h, src); 1087daf457d4SRichard Henderson tcg_gen_andi_i64(h, h, ~(1ull << 63)); 1088daf457d4SRichard Henderson tcg_gen_concat_i64_i128(dst, l, h); 1089c6d83e4fSRichard Henderson } 1090c6d83e4fSRichard Henderson 10913590f01eSRichard Henderson static void gen_op_fpexception_im(DisasContext *dc, int ftt) 1092fcf5ef2aSThomas Huth { 10933590f01eSRichard Henderson /* 10943590f01eSRichard Henderson * CEXC is only set when succesfully completing an FPop, 10953590f01eSRichard Henderson * or when raising FSR_FTT_IEEE_EXCP, i.e. check_ieee_exception. 10963590f01eSRichard Henderson * Thus we can simply store FTT into this field. 10973590f01eSRichard Henderson */ 10983590f01eSRichard Henderson tcg_gen_st_i32(tcg_constant_i32(ftt), tcg_env, 10993590f01eSRichard Henderson offsetof(CPUSPARCState, fsr_cexc_ftt)); 1100fcf5ef2aSThomas Huth gen_exception(dc, TT_FP_EXCP); 1101fcf5ef2aSThomas Huth } 1102fcf5ef2aSThomas Huth 1103fcf5ef2aSThomas Huth static int gen_trap_ifnofpu(DisasContext *dc) 1104fcf5ef2aSThomas Huth { 1105fcf5ef2aSThomas Huth #if !defined(CONFIG_USER_ONLY) 1106fcf5ef2aSThomas Huth if (!dc->fpu_enabled) { 1107fcf5ef2aSThomas Huth gen_exception(dc, TT_NFPU_INSN); 1108fcf5ef2aSThomas Huth return 1; 1109fcf5ef2aSThomas Huth } 1110fcf5ef2aSThomas Huth #endif 1111fcf5ef2aSThomas Huth return 0; 1112fcf5ef2aSThomas Huth } 1113fcf5ef2aSThomas Huth 1114fcf5ef2aSThomas Huth /* asi moves */ 1115fcf5ef2aSThomas Huth typedef enum { 1116fcf5ef2aSThomas Huth GET_ASI_HELPER, 1117fcf5ef2aSThomas Huth GET_ASI_EXCP, 1118fcf5ef2aSThomas Huth GET_ASI_DIRECT, 1119fcf5ef2aSThomas Huth GET_ASI_DTWINX, 1120fcf5ef2aSThomas Huth GET_ASI_BLOCK, 1121fcf5ef2aSThomas Huth GET_ASI_SHORT, 1122fcf5ef2aSThomas Huth GET_ASI_BCOPY, 1123fcf5ef2aSThomas Huth GET_ASI_BFILL, 1124fcf5ef2aSThomas Huth } ASIType; 1125fcf5ef2aSThomas Huth 1126fcf5ef2aSThomas Huth typedef struct { 1127fcf5ef2aSThomas Huth ASIType type; 1128fcf5ef2aSThomas Huth int asi; 1129fcf5ef2aSThomas Huth int mem_idx; 113014776ab5STony Nguyen MemOp memop; 1131fcf5ef2aSThomas Huth } DisasASI; 1132fcf5ef2aSThomas Huth 1133811cc0b0SRichard Henderson /* 1134811cc0b0SRichard Henderson * Build DisasASI. 1135811cc0b0SRichard Henderson * For asi == -1, treat as non-asi. 1136811cc0b0SRichard Henderson * For ask == -2, treat as immediate offset (v8 error, v9 %asi). 1137811cc0b0SRichard Henderson */ 1138811cc0b0SRichard Henderson static DisasASI resolve_asi(DisasContext *dc, int asi, MemOp memop) 1139fcf5ef2aSThomas Huth { 1140fcf5ef2aSThomas Huth ASIType type = GET_ASI_HELPER; 1141fcf5ef2aSThomas Huth int mem_idx = dc->mem_idx; 1142fcf5ef2aSThomas Huth 1143811cc0b0SRichard Henderson if (asi == -1) { 1144811cc0b0SRichard Henderson /* Artificial "non-asi" case. */ 1145811cc0b0SRichard Henderson type = GET_ASI_DIRECT; 1146811cc0b0SRichard Henderson goto done; 1147811cc0b0SRichard Henderson } 1148811cc0b0SRichard Henderson 1149fcf5ef2aSThomas Huth #ifndef TARGET_SPARC64 1150fcf5ef2aSThomas Huth /* Before v9, all asis are immediate and privileged. */ 1151811cc0b0SRichard Henderson if (asi < 0) { 1152fcf5ef2aSThomas Huth gen_exception(dc, TT_ILL_INSN); 1153fcf5ef2aSThomas Huth type = GET_ASI_EXCP; 1154fcf5ef2aSThomas Huth } else if (supervisor(dc) 1155fcf5ef2aSThomas Huth /* Note that LEON accepts ASI_USERDATA in user mode, for 1156fcf5ef2aSThomas Huth use with CASA. Also note that previous versions of 1157fcf5ef2aSThomas Huth QEMU allowed (and old versions of gcc emitted) ASI_P 1158fcf5ef2aSThomas Huth for LEON, which is incorrect. */ 1159fcf5ef2aSThomas Huth || (asi == ASI_USERDATA 1160fcf5ef2aSThomas Huth && (dc->def->features & CPU_FEATURE_CASA))) { 1161fcf5ef2aSThomas Huth switch (asi) { 1162fcf5ef2aSThomas Huth case ASI_USERDATA: /* User data access */ 1163fcf5ef2aSThomas Huth mem_idx = MMU_USER_IDX; 1164fcf5ef2aSThomas Huth type = GET_ASI_DIRECT; 1165fcf5ef2aSThomas Huth break; 1166fcf5ef2aSThomas Huth case ASI_KERNELDATA: /* Supervisor data access */ 1167fcf5ef2aSThomas Huth mem_idx = MMU_KERNEL_IDX; 1168fcf5ef2aSThomas Huth type = GET_ASI_DIRECT; 1169fcf5ef2aSThomas Huth break; 1170fcf5ef2aSThomas Huth case ASI_M_BYPASS: /* MMU passthrough */ 1171fcf5ef2aSThomas Huth case ASI_LEON_BYPASS: /* LEON MMU passthrough */ 1172fcf5ef2aSThomas Huth mem_idx = MMU_PHYS_IDX; 1173fcf5ef2aSThomas Huth type = GET_ASI_DIRECT; 1174fcf5ef2aSThomas Huth break; 1175fcf5ef2aSThomas Huth case ASI_M_BCOPY: /* Block copy, sta access */ 1176fcf5ef2aSThomas Huth mem_idx = MMU_KERNEL_IDX; 1177fcf5ef2aSThomas Huth type = GET_ASI_BCOPY; 1178fcf5ef2aSThomas Huth break; 1179fcf5ef2aSThomas Huth case ASI_M_BFILL: /* Block fill, stda access */ 1180fcf5ef2aSThomas Huth mem_idx = MMU_KERNEL_IDX; 1181fcf5ef2aSThomas Huth type = GET_ASI_BFILL; 1182fcf5ef2aSThomas Huth break; 1183fcf5ef2aSThomas Huth } 11846e10f37cSKONRAD Frederic 11856e10f37cSKONRAD Frederic /* MMU_PHYS_IDX is used when the MMU is disabled to passthrough the 11866e10f37cSKONRAD Frederic * permissions check in get_physical_address(..). 11876e10f37cSKONRAD Frederic */ 11886e10f37cSKONRAD Frederic mem_idx = (dc->mem_idx == MMU_PHYS_IDX) ? MMU_PHYS_IDX : mem_idx; 1189fcf5ef2aSThomas Huth } else { 1190fcf5ef2aSThomas Huth gen_exception(dc, TT_PRIV_INSN); 1191fcf5ef2aSThomas Huth type = GET_ASI_EXCP; 1192fcf5ef2aSThomas Huth } 1193fcf5ef2aSThomas Huth #else 1194811cc0b0SRichard Henderson if (asi < 0) { 1195fcf5ef2aSThomas Huth asi = dc->asi; 1196fcf5ef2aSThomas Huth } 1197fcf5ef2aSThomas Huth /* With v9, all asis below 0x80 are privileged. */ 1198fcf5ef2aSThomas Huth /* ??? We ought to check cpu_has_hypervisor, but we didn't copy 1199fcf5ef2aSThomas Huth down that bit into DisasContext. For the moment that's ok, 1200fcf5ef2aSThomas Huth since the direct implementations below doesn't have any ASIs 1201fcf5ef2aSThomas Huth in the restricted [0x30, 0x7f] range, and the check will be 1202fcf5ef2aSThomas Huth done properly in the helper. */ 1203fcf5ef2aSThomas Huth if (!supervisor(dc) && asi < 0x80) { 1204fcf5ef2aSThomas Huth gen_exception(dc, TT_PRIV_ACT); 1205fcf5ef2aSThomas Huth type = GET_ASI_EXCP; 1206fcf5ef2aSThomas Huth } else { 1207fcf5ef2aSThomas Huth switch (asi) { 1208fcf5ef2aSThomas Huth case ASI_REAL: /* Bypass */ 1209fcf5ef2aSThomas Huth case ASI_REAL_IO: /* Bypass, non-cacheable */ 1210fcf5ef2aSThomas Huth case ASI_REAL_L: /* Bypass LE */ 1211fcf5ef2aSThomas Huth case ASI_REAL_IO_L: /* Bypass, non-cacheable LE */ 1212fcf5ef2aSThomas Huth case ASI_TWINX_REAL: /* Real address, twinx */ 1213fcf5ef2aSThomas Huth case ASI_TWINX_REAL_L: /* Real address, twinx, LE */ 1214fcf5ef2aSThomas Huth case ASI_QUAD_LDD_PHYS: 1215fcf5ef2aSThomas Huth case ASI_QUAD_LDD_PHYS_L: 1216fcf5ef2aSThomas Huth mem_idx = MMU_PHYS_IDX; 1217fcf5ef2aSThomas Huth break; 1218fcf5ef2aSThomas Huth case ASI_N: /* Nucleus */ 1219fcf5ef2aSThomas Huth case ASI_NL: /* Nucleus LE */ 1220fcf5ef2aSThomas Huth case ASI_TWINX_N: 1221fcf5ef2aSThomas Huth case ASI_TWINX_NL: 1222fcf5ef2aSThomas Huth case ASI_NUCLEUS_QUAD_LDD: 1223fcf5ef2aSThomas Huth case ASI_NUCLEUS_QUAD_LDD_L: 12249a10756dSArtyom Tarasenko if (hypervisor(dc)) { 122584f8f587SArtyom Tarasenko mem_idx = MMU_PHYS_IDX; 12269a10756dSArtyom Tarasenko } else { 1227fcf5ef2aSThomas Huth mem_idx = MMU_NUCLEUS_IDX; 12289a10756dSArtyom Tarasenko } 1229fcf5ef2aSThomas Huth break; 1230fcf5ef2aSThomas Huth case ASI_AIUP: /* As if user primary */ 1231fcf5ef2aSThomas Huth case ASI_AIUPL: /* As if user primary LE */ 1232fcf5ef2aSThomas Huth case ASI_TWINX_AIUP: 1233fcf5ef2aSThomas Huth case ASI_TWINX_AIUP_L: 1234fcf5ef2aSThomas Huth case ASI_BLK_AIUP_4V: 1235fcf5ef2aSThomas Huth case ASI_BLK_AIUP_L_4V: 1236fcf5ef2aSThomas Huth case ASI_BLK_AIUP: 1237fcf5ef2aSThomas Huth case ASI_BLK_AIUPL: 1238fcf5ef2aSThomas Huth mem_idx = MMU_USER_IDX; 1239fcf5ef2aSThomas Huth break; 1240fcf5ef2aSThomas Huth case ASI_AIUS: /* As if user secondary */ 1241fcf5ef2aSThomas Huth case ASI_AIUSL: /* As if user secondary LE */ 1242fcf5ef2aSThomas Huth case ASI_TWINX_AIUS: 1243fcf5ef2aSThomas Huth case ASI_TWINX_AIUS_L: 1244fcf5ef2aSThomas Huth case ASI_BLK_AIUS_4V: 1245fcf5ef2aSThomas Huth case ASI_BLK_AIUS_L_4V: 1246fcf5ef2aSThomas Huth case ASI_BLK_AIUS: 1247fcf5ef2aSThomas Huth case ASI_BLK_AIUSL: 1248fcf5ef2aSThomas Huth mem_idx = MMU_USER_SECONDARY_IDX; 1249fcf5ef2aSThomas Huth break; 1250fcf5ef2aSThomas Huth case ASI_S: /* Secondary */ 1251fcf5ef2aSThomas Huth case ASI_SL: /* Secondary LE */ 1252fcf5ef2aSThomas Huth case ASI_TWINX_S: 1253fcf5ef2aSThomas Huth case ASI_TWINX_SL: 1254fcf5ef2aSThomas Huth case ASI_BLK_COMMIT_S: 1255fcf5ef2aSThomas Huth case ASI_BLK_S: 1256fcf5ef2aSThomas Huth case ASI_BLK_SL: 1257fcf5ef2aSThomas Huth case ASI_FL8_S: 1258fcf5ef2aSThomas Huth case ASI_FL8_SL: 1259fcf5ef2aSThomas Huth case ASI_FL16_S: 1260fcf5ef2aSThomas Huth case ASI_FL16_SL: 1261fcf5ef2aSThomas Huth if (mem_idx == MMU_USER_IDX) { 1262fcf5ef2aSThomas Huth mem_idx = MMU_USER_SECONDARY_IDX; 1263fcf5ef2aSThomas Huth } else if (mem_idx == MMU_KERNEL_IDX) { 1264fcf5ef2aSThomas Huth mem_idx = MMU_KERNEL_SECONDARY_IDX; 1265fcf5ef2aSThomas Huth } 1266fcf5ef2aSThomas Huth break; 1267fcf5ef2aSThomas Huth case ASI_P: /* Primary */ 1268fcf5ef2aSThomas Huth case ASI_PL: /* Primary LE */ 1269fcf5ef2aSThomas Huth case ASI_TWINX_P: 1270fcf5ef2aSThomas Huth case ASI_TWINX_PL: 1271fcf5ef2aSThomas Huth case ASI_BLK_COMMIT_P: 1272fcf5ef2aSThomas Huth case ASI_BLK_P: 1273fcf5ef2aSThomas Huth case ASI_BLK_PL: 1274fcf5ef2aSThomas Huth case ASI_FL8_P: 1275fcf5ef2aSThomas Huth case ASI_FL8_PL: 1276fcf5ef2aSThomas Huth case ASI_FL16_P: 1277fcf5ef2aSThomas Huth case ASI_FL16_PL: 1278fcf5ef2aSThomas Huth break; 1279fcf5ef2aSThomas Huth } 1280fcf5ef2aSThomas Huth switch (asi) { 1281fcf5ef2aSThomas Huth case ASI_REAL: 1282fcf5ef2aSThomas Huth case ASI_REAL_IO: 1283fcf5ef2aSThomas Huth case ASI_REAL_L: 1284fcf5ef2aSThomas Huth case ASI_REAL_IO_L: 1285fcf5ef2aSThomas Huth case ASI_N: 1286fcf5ef2aSThomas Huth case ASI_NL: 1287fcf5ef2aSThomas Huth case ASI_AIUP: 1288fcf5ef2aSThomas Huth case ASI_AIUPL: 1289fcf5ef2aSThomas Huth case ASI_AIUS: 1290fcf5ef2aSThomas Huth case ASI_AIUSL: 1291fcf5ef2aSThomas Huth case ASI_S: 1292fcf5ef2aSThomas Huth case ASI_SL: 1293fcf5ef2aSThomas Huth case ASI_P: 1294fcf5ef2aSThomas Huth case ASI_PL: 1295fcf5ef2aSThomas Huth type = GET_ASI_DIRECT; 1296fcf5ef2aSThomas Huth break; 1297fcf5ef2aSThomas Huth case ASI_TWINX_REAL: 1298fcf5ef2aSThomas Huth case ASI_TWINX_REAL_L: 1299fcf5ef2aSThomas Huth case ASI_TWINX_N: 1300fcf5ef2aSThomas Huth case ASI_TWINX_NL: 1301fcf5ef2aSThomas Huth case ASI_TWINX_AIUP: 1302fcf5ef2aSThomas Huth case ASI_TWINX_AIUP_L: 1303fcf5ef2aSThomas Huth case ASI_TWINX_AIUS: 1304fcf5ef2aSThomas Huth case ASI_TWINX_AIUS_L: 1305fcf5ef2aSThomas Huth case ASI_TWINX_P: 1306fcf5ef2aSThomas Huth case ASI_TWINX_PL: 1307fcf5ef2aSThomas Huth case ASI_TWINX_S: 1308fcf5ef2aSThomas Huth case ASI_TWINX_SL: 1309fcf5ef2aSThomas Huth case ASI_QUAD_LDD_PHYS: 1310fcf5ef2aSThomas Huth case ASI_QUAD_LDD_PHYS_L: 1311fcf5ef2aSThomas Huth case ASI_NUCLEUS_QUAD_LDD: 1312fcf5ef2aSThomas Huth case ASI_NUCLEUS_QUAD_LDD_L: 1313fcf5ef2aSThomas Huth type = GET_ASI_DTWINX; 1314fcf5ef2aSThomas Huth break; 1315fcf5ef2aSThomas Huth case ASI_BLK_COMMIT_P: 1316fcf5ef2aSThomas Huth case ASI_BLK_COMMIT_S: 1317fcf5ef2aSThomas Huth case ASI_BLK_AIUP_4V: 1318fcf5ef2aSThomas Huth case ASI_BLK_AIUP_L_4V: 1319fcf5ef2aSThomas Huth case ASI_BLK_AIUP: 1320fcf5ef2aSThomas Huth case ASI_BLK_AIUPL: 1321fcf5ef2aSThomas Huth case ASI_BLK_AIUS_4V: 1322fcf5ef2aSThomas Huth case ASI_BLK_AIUS_L_4V: 1323fcf5ef2aSThomas Huth case ASI_BLK_AIUS: 1324fcf5ef2aSThomas Huth case ASI_BLK_AIUSL: 1325fcf5ef2aSThomas Huth case ASI_BLK_S: 1326fcf5ef2aSThomas Huth case ASI_BLK_SL: 1327fcf5ef2aSThomas Huth case ASI_BLK_P: 1328fcf5ef2aSThomas Huth case ASI_BLK_PL: 1329fcf5ef2aSThomas Huth type = GET_ASI_BLOCK; 1330fcf5ef2aSThomas Huth break; 1331fcf5ef2aSThomas Huth case ASI_FL8_S: 1332fcf5ef2aSThomas Huth case ASI_FL8_SL: 1333fcf5ef2aSThomas Huth case ASI_FL8_P: 1334fcf5ef2aSThomas Huth case ASI_FL8_PL: 1335fcf5ef2aSThomas Huth memop = MO_UB; 1336fcf5ef2aSThomas Huth type = GET_ASI_SHORT; 1337fcf5ef2aSThomas Huth break; 1338fcf5ef2aSThomas Huth case ASI_FL16_S: 1339fcf5ef2aSThomas Huth case ASI_FL16_SL: 1340fcf5ef2aSThomas Huth case ASI_FL16_P: 1341fcf5ef2aSThomas Huth case ASI_FL16_PL: 1342fcf5ef2aSThomas Huth memop = MO_TEUW; 1343fcf5ef2aSThomas Huth type = GET_ASI_SHORT; 1344fcf5ef2aSThomas Huth break; 1345fcf5ef2aSThomas Huth } 1346fcf5ef2aSThomas Huth /* The little-endian asis all have bit 3 set. */ 1347fcf5ef2aSThomas Huth if (asi & 8) { 1348fcf5ef2aSThomas Huth memop ^= MO_BSWAP; 1349fcf5ef2aSThomas Huth } 1350fcf5ef2aSThomas Huth } 1351fcf5ef2aSThomas Huth #endif 1352fcf5ef2aSThomas Huth 1353811cc0b0SRichard Henderson done: 1354fcf5ef2aSThomas Huth return (DisasASI){ type, asi, mem_idx, memop }; 1355fcf5ef2aSThomas Huth } 1356fcf5ef2aSThomas Huth 1357a76779eeSRichard Henderson #if defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64) 1358a76779eeSRichard Henderson static void gen_helper_ld_asi(TCGv_i64 r, TCGv_env e, TCGv a, 1359a76779eeSRichard Henderson TCGv_i32 asi, TCGv_i32 mop) 1360a76779eeSRichard Henderson { 1361a76779eeSRichard Henderson g_assert_not_reached(); 1362a76779eeSRichard Henderson } 1363a76779eeSRichard Henderson 1364a76779eeSRichard Henderson static void gen_helper_st_asi(TCGv_env e, TCGv a, TCGv_i64 r, 1365a76779eeSRichard Henderson TCGv_i32 asi, TCGv_i32 mop) 1366a76779eeSRichard Henderson { 1367a76779eeSRichard Henderson g_assert_not_reached(); 1368a76779eeSRichard Henderson } 1369a76779eeSRichard Henderson #endif 1370a76779eeSRichard Henderson 137142071fc1SRichard Henderson static void gen_ld_asi(DisasContext *dc, DisasASI *da, TCGv dst, TCGv addr) 1372fcf5ef2aSThomas Huth { 1373c03a0fd1SRichard Henderson switch (da->type) { 1374fcf5ef2aSThomas Huth case GET_ASI_EXCP: 1375fcf5ef2aSThomas Huth break; 1376fcf5ef2aSThomas Huth case GET_ASI_DTWINX: /* Reserved for ldda. */ 1377fcf5ef2aSThomas Huth gen_exception(dc, TT_ILL_INSN); 1378fcf5ef2aSThomas Huth break; 1379fcf5ef2aSThomas Huth case GET_ASI_DIRECT: 1380c03a0fd1SRichard Henderson tcg_gen_qemu_ld_tl(dst, addr, da->mem_idx, da->memop | MO_ALIGN); 1381fcf5ef2aSThomas Huth break; 1382fcf5ef2aSThomas Huth default: 1383fcf5ef2aSThomas Huth { 1384c03a0fd1SRichard Henderson TCGv_i32 r_asi = tcg_constant_i32(da->asi); 1385c03a0fd1SRichard Henderson TCGv_i32 r_mop = tcg_constant_i32(da->memop | MO_ALIGN); 1386fcf5ef2aSThomas Huth 1387fcf5ef2aSThomas Huth save_state(dc); 1388fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64 1389ad75a51eSRichard Henderson gen_helper_ld_asi(dst, tcg_env, addr, r_asi, r_mop); 1390fcf5ef2aSThomas Huth #else 1391fcf5ef2aSThomas Huth { 1392fcf5ef2aSThomas Huth TCGv_i64 t64 = tcg_temp_new_i64(); 1393ad75a51eSRichard Henderson gen_helper_ld_asi(t64, tcg_env, addr, r_asi, r_mop); 1394fcf5ef2aSThomas Huth tcg_gen_trunc_i64_tl(dst, t64); 1395fcf5ef2aSThomas Huth } 1396fcf5ef2aSThomas Huth #endif 1397fcf5ef2aSThomas Huth } 1398fcf5ef2aSThomas Huth break; 1399fcf5ef2aSThomas Huth } 1400fcf5ef2aSThomas Huth } 1401fcf5ef2aSThomas Huth 140242071fc1SRichard Henderson static void gen_st_asi(DisasContext *dc, DisasASI *da, TCGv src, TCGv addr) 1403c03a0fd1SRichard Henderson { 1404c03a0fd1SRichard Henderson switch (da->type) { 1405fcf5ef2aSThomas Huth case GET_ASI_EXCP: 1406fcf5ef2aSThomas Huth break; 1407c03a0fd1SRichard Henderson 1408fcf5ef2aSThomas Huth case GET_ASI_DTWINX: /* Reserved for stda. */ 1409c03a0fd1SRichard Henderson if (TARGET_LONG_BITS == 32) { 1410fcf5ef2aSThomas Huth gen_exception(dc, TT_ILL_INSN); 1411fcf5ef2aSThomas Huth break; 1412c03a0fd1SRichard Henderson } else if (!(dc->def->features & CPU_FEATURE_HYPV)) { 14133390537bSArtyom Tarasenko /* Pre OpenSPARC CPUs don't have these */ 14143390537bSArtyom Tarasenko gen_exception(dc, TT_ILL_INSN); 1415fcf5ef2aSThomas Huth break; 1416c03a0fd1SRichard Henderson } 1417c03a0fd1SRichard Henderson /* In OpenSPARC T1+ CPUs TWINX ASIs in store are ST_BLKINIT_ ASIs */ 1418c03a0fd1SRichard Henderson /* fall through */ 1419c03a0fd1SRichard Henderson 1420c03a0fd1SRichard Henderson case GET_ASI_DIRECT: 1421c03a0fd1SRichard Henderson tcg_gen_qemu_st_tl(src, addr, da->mem_idx, da->memop | MO_ALIGN); 1422c03a0fd1SRichard Henderson break; 1423c03a0fd1SRichard Henderson 1424fcf5ef2aSThomas Huth case GET_ASI_BCOPY: 1425c03a0fd1SRichard Henderson assert(TARGET_LONG_BITS == 32); 142698271007SRichard Henderson /* 142798271007SRichard Henderson * Copy 32 bytes from the address in SRC to ADDR. 142898271007SRichard Henderson * 142998271007SRichard Henderson * From Ross RT625 hyperSPARC manual, section 4.6: 143098271007SRichard Henderson * "Block Copy and Block Fill will work only on cache line boundaries." 143198271007SRichard Henderson * 143298271007SRichard Henderson * It does not specify if an unaliged address is truncated or trapped. 143398271007SRichard Henderson * Previous qemu behaviour was to truncate to 4 byte alignment, which 143498271007SRichard Henderson * is obviously wrong. The only place I can see this used is in the 143598271007SRichard Henderson * Linux kernel which begins with page alignment, advancing by 32, 143698271007SRichard Henderson * so is always aligned. Assume truncation as the simpler option. 143798271007SRichard Henderson * 143898271007SRichard Henderson * Since the loads and stores are paired, allow the copy to happen 143998271007SRichard Henderson * in the host endianness. The copy need not be atomic. 144098271007SRichard Henderson */ 1441fcf5ef2aSThomas Huth { 144298271007SRichard Henderson MemOp mop = MO_128 | MO_ATOM_IFALIGN_PAIR; 1443fcf5ef2aSThomas Huth TCGv saddr = tcg_temp_new(); 1444fcf5ef2aSThomas Huth TCGv daddr = tcg_temp_new(); 144598271007SRichard Henderson TCGv_i128 tmp = tcg_temp_new_i128(); 1446fcf5ef2aSThomas Huth 144798271007SRichard Henderson tcg_gen_andi_tl(saddr, src, -32); 144898271007SRichard Henderson tcg_gen_andi_tl(daddr, addr, -32); 144998271007SRichard Henderson tcg_gen_qemu_ld_i128(tmp, saddr, da->mem_idx, mop); 145098271007SRichard Henderson tcg_gen_qemu_st_i128(tmp, daddr, da->mem_idx, mop); 145198271007SRichard Henderson tcg_gen_addi_tl(saddr, saddr, 16); 145298271007SRichard Henderson tcg_gen_addi_tl(daddr, daddr, 16); 145398271007SRichard Henderson tcg_gen_qemu_ld_i128(tmp, saddr, da->mem_idx, mop); 145498271007SRichard Henderson tcg_gen_qemu_st_i128(tmp, daddr, da->mem_idx, mop); 1455fcf5ef2aSThomas Huth } 1456fcf5ef2aSThomas Huth break; 1457c03a0fd1SRichard Henderson 1458fcf5ef2aSThomas Huth default: 1459fcf5ef2aSThomas Huth { 1460c03a0fd1SRichard Henderson TCGv_i32 r_asi = tcg_constant_i32(da->asi); 1461c03a0fd1SRichard Henderson TCGv_i32 r_mop = tcg_constant_i32(da->memop | MO_ALIGN); 1462fcf5ef2aSThomas Huth 1463fcf5ef2aSThomas Huth save_state(dc); 1464fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64 1465ad75a51eSRichard Henderson gen_helper_st_asi(tcg_env, addr, src, r_asi, r_mop); 1466fcf5ef2aSThomas Huth #else 1467fcf5ef2aSThomas Huth { 1468fcf5ef2aSThomas Huth TCGv_i64 t64 = tcg_temp_new_i64(); 1469fcf5ef2aSThomas Huth tcg_gen_extu_tl_i64(t64, src); 1470ad75a51eSRichard Henderson gen_helper_st_asi(tcg_env, addr, t64, r_asi, r_mop); 1471fcf5ef2aSThomas Huth } 1472fcf5ef2aSThomas Huth #endif 1473fcf5ef2aSThomas Huth 1474fcf5ef2aSThomas Huth /* A write to a TLB register may alter page maps. End the TB. */ 1475fcf5ef2aSThomas Huth dc->npc = DYNAMIC_PC; 1476fcf5ef2aSThomas Huth } 1477fcf5ef2aSThomas Huth break; 1478fcf5ef2aSThomas Huth } 1479fcf5ef2aSThomas Huth } 1480fcf5ef2aSThomas Huth 1481dca544b9SRichard Henderson static void gen_swap_asi(DisasContext *dc, DisasASI *da, 1482c03a0fd1SRichard Henderson TCGv dst, TCGv src, TCGv addr) 1483c03a0fd1SRichard Henderson { 1484c03a0fd1SRichard Henderson switch (da->type) { 1485c03a0fd1SRichard Henderson case GET_ASI_EXCP: 1486c03a0fd1SRichard Henderson break; 1487c03a0fd1SRichard Henderson case GET_ASI_DIRECT: 1488dca544b9SRichard Henderson tcg_gen_atomic_xchg_tl(dst, addr, src, 1489dca544b9SRichard Henderson da->mem_idx, da->memop | MO_ALIGN); 1490c03a0fd1SRichard Henderson break; 1491c03a0fd1SRichard Henderson default: 1492c03a0fd1SRichard Henderson /* ??? Should be DAE_invalid_asi. */ 1493c03a0fd1SRichard Henderson gen_exception(dc, TT_DATA_ACCESS); 1494c03a0fd1SRichard Henderson break; 1495c03a0fd1SRichard Henderson } 1496c03a0fd1SRichard Henderson } 1497c03a0fd1SRichard Henderson 1498d0a11d25SRichard Henderson static void gen_cas_asi(DisasContext *dc, DisasASI *da, 1499c03a0fd1SRichard Henderson TCGv oldv, TCGv newv, TCGv cmpv, TCGv addr) 1500c03a0fd1SRichard Henderson { 1501c03a0fd1SRichard Henderson switch (da->type) { 1502fcf5ef2aSThomas Huth case GET_ASI_EXCP: 1503c03a0fd1SRichard Henderson return; 1504fcf5ef2aSThomas Huth case GET_ASI_DIRECT: 1505c03a0fd1SRichard Henderson tcg_gen_atomic_cmpxchg_tl(oldv, addr, cmpv, newv, 1506c03a0fd1SRichard Henderson da->mem_idx, da->memop | MO_ALIGN); 1507fcf5ef2aSThomas Huth break; 1508fcf5ef2aSThomas Huth default: 1509fcf5ef2aSThomas Huth /* ??? Should be DAE_invalid_asi. */ 1510fcf5ef2aSThomas Huth gen_exception(dc, TT_DATA_ACCESS); 1511fcf5ef2aSThomas Huth break; 1512fcf5ef2aSThomas Huth } 1513fcf5ef2aSThomas Huth } 1514fcf5ef2aSThomas Huth 1515cf07cd1eSRichard Henderson static void gen_ldstub_asi(DisasContext *dc, DisasASI *da, TCGv dst, TCGv addr) 1516c03a0fd1SRichard Henderson { 1517c03a0fd1SRichard Henderson switch (da->type) { 1518fcf5ef2aSThomas Huth case GET_ASI_EXCP: 1519fcf5ef2aSThomas Huth break; 1520fcf5ef2aSThomas Huth case GET_ASI_DIRECT: 1521cf07cd1eSRichard Henderson tcg_gen_atomic_xchg_tl(dst, addr, tcg_constant_tl(0xff), 1522cf07cd1eSRichard Henderson da->mem_idx, MO_UB); 1523fcf5ef2aSThomas Huth break; 1524fcf5ef2aSThomas Huth default: 15253db010c3SRichard Henderson /* ??? In theory, this should be raise DAE_invalid_asi. 15263db010c3SRichard Henderson But the SS-20 roms do ldstuba [%l0] #ASI_M_CTL, %o1. */ 1527af00be49SEmilio G. Cota if (tb_cflags(dc->base.tb) & CF_PARALLEL) { 1528ad75a51eSRichard Henderson gen_helper_exit_atomic(tcg_env); 15293db010c3SRichard Henderson } else { 1530c03a0fd1SRichard Henderson TCGv_i32 r_asi = tcg_constant_i32(da->asi); 153100ab7e61SRichard Henderson TCGv_i32 r_mop = tcg_constant_i32(MO_UB); 15323db010c3SRichard Henderson TCGv_i64 s64, t64; 15333db010c3SRichard Henderson 15343db010c3SRichard Henderson save_state(dc); 15353db010c3SRichard Henderson t64 = tcg_temp_new_i64(); 1536ad75a51eSRichard Henderson gen_helper_ld_asi(t64, tcg_env, addr, r_asi, r_mop); 15373db010c3SRichard Henderson 153800ab7e61SRichard Henderson s64 = tcg_constant_i64(0xff); 1539ad75a51eSRichard Henderson gen_helper_st_asi(tcg_env, addr, s64, r_asi, r_mop); 15403db010c3SRichard Henderson 15413db010c3SRichard Henderson tcg_gen_trunc_i64_tl(dst, t64); 15423db010c3SRichard Henderson 15433db010c3SRichard Henderson /* End the TB. */ 15443db010c3SRichard Henderson dc->npc = DYNAMIC_PC; 15453db010c3SRichard Henderson } 1546fcf5ef2aSThomas Huth break; 1547fcf5ef2aSThomas Huth } 1548fcf5ef2aSThomas Huth } 1549fcf5ef2aSThomas Huth 1550287b1152SRichard Henderson static void gen_ldf_asi(DisasContext *dc, DisasASI *da, MemOp orig_size, 15513259b9e2SRichard Henderson TCGv addr, int rd) 1552fcf5ef2aSThomas Huth { 15533259b9e2SRichard Henderson MemOp memop = da->memop; 15543259b9e2SRichard Henderson MemOp size = memop & MO_SIZE; 1555fcf5ef2aSThomas Huth TCGv_i32 d32; 1556fcf5ef2aSThomas Huth TCGv_i64 d64; 1557287b1152SRichard Henderson TCGv addr_tmp; 1558fcf5ef2aSThomas Huth 15593259b9e2SRichard Henderson /* TODO: Use 128-bit load/store below. */ 15603259b9e2SRichard Henderson if (size == MO_128) { 15613259b9e2SRichard Henderson memop = (memop & ~MO_SIZE) | MO_64; 15623259b9e2SRichard Henderson } 15633259b9e2SRichard Henderson 15643259b9e2SRichard Henderson switch (da->type) { 1565fcf5ef2aSThomas Huth case GET_ASI_EXCP: 1566fcf5ef2aSThomas Huth break; 1567fcf5ef2aSThomas Huth 1568fcf5ef2aSThomas Huth case GET_ASI_DIRECT: 15693259b9e2SRichard Henderson memop |= MO_ALIGN_4; 1570fcf5ef2aSThomas Huth switch (size) { 15713259b9e2SRichard Henderson case MO_32: 1572388a6465SRichard Henderson d32 = tcg_temp_new_i32(); 15733259b9e2SRichard Henderson tcg_gen_qemu_ld_i32(d32, addr, da->mem_idx, memop); 1574fcf5ef2aSThomas Huth gen_store_fpr_F(dc, rd, d32); 1575fcf5ef2aSThomas Huth break; 15763259b9e2SRichard Henderson 15773259b9e2SRichard Henderson case MO_64: 15783259b9e2SRichard Henderson tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2], addr, da->mem_idx, memop); 1579fcf5ef2aSThomas Huth break; 15803259b9e2SRichard Henderson 15813259b9e2SRichard Henderson case MO_128: 1582fcf5ef2aSThomas Huth d64 = tcg_temp_new_i64(); 15833259b9e2SRichard Henderson tcg_gen_qemu_ld_i64(d64, addr, da->mem_idx, memop); 1584287b1152SRichard Henderson addr_tmp = tcg_temp_new(); 1585287b1152SRichard Henderson tcg_gen_addi_tl(addr_tmp, addr, 8); 1586287b1152SRichard Henderson tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2 + 1], addr_tmp, da->mem_idx, memop); 1587fcf5ef2aSThomas Huth tcg_gen_mov_i64(cpu_fpr[rd / 2], d64); 1588fcf5ef2aSThomas Huth break; 1589fcf5ef2aSThomas Huth default: 1590fcf5ef2aSThomas Huth g_assert_not_reached(); 1591fcf5ef2aSThomas Huth } 1592fcf5ef2aSThomas Huth break; 1593fcf5ef2aSThomas Huth 1594fcf5ef2aSThomas Huth case GET_ASI_BLOCK: 1595fcf5ef2aSThomas Huth /* Valid for lddfa on aligned registers only. */ 15963259b9e2SRichard Henderson if (orig_size == MO_64 && (rd & 7) == 0) { 1597fcf5ef2aSThomas Huth /* The first operation checks required alignment. */ 1598287b1152SRichard Henderson addr_tmp = tcg_temp_new(); 1599287b1152SRichard Henderson for (int i = 0; ; ++i) { 16003259b9e2SRichard Henderson tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2 + i], addr, da->mem_idx, 16013259b9e2SRichard Henderson memop | (i == 0 ? MO_ALIGN_64 : 0)); 1602fcf5ef2aSThomas Huth if (i == 7) { 1603fcf5ef2aSThomas Huth break; 1604fcf5ef2aSThomas Huth } 1605287b1152SRichard Henderson tcg_gen_addi_tl(addr_tmp, addr, 8); 1606287b1152SRichard Henderson addr = addr_tmp; 1607fcf5ef2aSThomas Huth } 1608fcf5ef2aSThomas Huth } else { 1609fcf5ef2aSThomas Huth gen_exception(dc, TT_ILL_INSN); 1610fcf5ef2aSThomas Huth } 1611fcf5ef2aSThomas Huth break; 1612fcf5ef2aSThomas Huth 1613fcf5ef2aSThomas Huth case GET_ASI_SHORT: 1614fcf5ef2aSThomas Huth /* Valid for lddfa only. */ 16153259b9e2SRichard Henderson if (orig_size == MO_64) { 16163259b9e2SRichard Henderson tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2], addr, da->mem_idx, 16173259b9e2SRichard Henderson memop | MO_ALIGN); 1618fcf5ef2aSThomas Huth } else { 1619fcf5ef2aSThomas Huth gen_exception(dc, TT_ILL_INSN); 1620fcf5ef2aSThomas Huth } 1621fcf5ef2aSThomas Huth break; 1622fcf5ef2aSThomas Huth 1623fcf5ef2aSThomas Huth default: 1624fcf5ef2aSThomas Huth { 16253259b9e2SRichard Henderson TCGv_i32 r_asi = tcg_constant_i32(da->asi); 16263259b9e2SRichard Henderson TCGv_i32 r_mop = tcg_constant_i32(memop | MO_ALIGN); 1627fcf5ef2aSThomas Huth 1628fcf5ef2aSThomas Huth save_state(dc); 1629fcf5ef2aSThomas Huth /* According to the table in the UA2011 manual, the only 1630fcf5ef2aSThomas Huth other asis that are valid for ldfa/lddfa/ldqfa are 1631fcf5ef2aSThomas Huth the NO_FAULT asis. We still need a helper for these, 1632fcf5ef2aSThomas Huth but we can just use the integer asi helper for them. */ 1633fcf5ef2aSThomas Huth switch (size) { 16343259b9e2SRichard Henderson case MO_32: 1635fcf5ef2aSThomas Huth d64 = tcg_temp_new_i64(); 1636ad75a51eSRichard Henderson gen_helper_ld_asi(d64, tcg_env, addr, r_asi, r_mop); 1637388a6465SRichard Henderson d32 = tcg_temp_new_i32(); 1638fcf5ef2aSThomas Huth tcg_gen_extrl_i64_i32(d32, d64); 1639fcf5ef2aSThomas Huth gen_store_fpr_F(dc, rd, d32); 1640fcf5ef2aSThomas Huth break; 16413259b9e2SRichard Henderson case MO_64: 16423259b9e2SRichard Henderson gen_helper_ld_asi(cpu_fpr[rd / 2], tcg_env, addr, 16433259b9e2SRichard Henderson r_asi, r_mop); 1644fcf5ef2aSThomas Huth break; 16453259b9e2SRichard Henderson case MO_128: 1646fcf5ef2aSThomas Huth d64 = tcg_temp_new_i64(); 1647ad75a51eSRichard Henderson gen_helper_ld_asi(d64, tcg_env, addr, r_asi, r_mop); 1648287b1152SRichard Henderson addr_tmp = tcg_temp_new(); 1649287b1152SRichard Henderson tcg_gen_addi_tl(addr_tmp, addr, 8); 1650287b1152SRichard Henderson gen_helper_ld_asi(cpu_fpr[rd / 2 + 1], tcg_env, addr_tmp, 16513259b9e2SRichard Henderson r_asi, r_mop); 1652fcf5ef2aSThomas Huth tcg_gen_mov_i64(cpu_fpr[rd / 2], d64); 1653fcf5ef2aSThomas Huth break; 1654fcf5ef2aSThomas Huth default: 1655fcf5ef2aSThomas Huth g_assert_not_reached(); 1656fcf5ef2aSThomas Huth } 1657fcf5ef2aSThomas Huth } 1658fcf5ef2aSThomas Huth break; 1659fcf5ef2aSThomas Huth } 1660fcf5ef2aSThomas Huth } 1661fcf5ef2aSThomas Huth 1662287b1152SRichard Henderson static void gen_stf_asi(DisasContext *dc, DisasASI *da, MemOp orig_size, 16633259b9e2SRichard Henderson TCGv addr, int rd) 16643259b9e2SRichard Henderson { 16653259b9e2SRichard Henderson MemOp memop = da->memop; 16663259b9e2SRichard Henderson MemOp size = memop & MO_SIZE; 1667fcf5ef2aSThomas Huth TCGv_i32 d32; 1668287b1152SRichard Henderson TCGv addr_tmp; 1669fcf5ef2aSThomas Huth 16703259b9e2SRichard Henderson /* TODO: Use 128-bit load/store below. */ 16713259b9e2SRichard Henderson if (size == MO_128) { 16723259b9e2SRichard Henderson memop = (memop & ~MO_SIZE) | MO_64; 16733259b9e2SRichard Henderson } 16743259b9e2SRichard Henderson 16753259b9e2SRichard Henderson switch (da->type) { 1676fcf5ef2aSThomas Huth case GET_ASI_EXCP: 1677fcf5ef2aSThomas Huth break; 1678fcf5ef2aSThomas Huth 1679fcf5ef2aSThomas Huth case GET_ASI_DIRECT: 16803259b9e2SRichard Henderson memop |= MO_ALIGN_4; 1681fcf5ef2aSThomas Huth switch (size) { 16823259b9e2SRichard Henderson case MO_32: 1683fcf5ef2aSThomas Huth d32 = gen_load_fpr_F(dc, rd); 16843259b9e2SRichard Henderson tcg_gen_qemu_st_i32(d32, addr, da->mem_idx, memop | MO_ALIGN); 1685fcf5ef2aSThomas Huth break; 16863259b9e2SRichard Henderson case MO_64: 16873259b9e2SRichard Henderson tcg_gen_qemu_st_i64(cpu_fpr[rd / 2], addr, da->mem_idx, 16883259b9e2SRichard Henderson memop | MO_ALIGN_4); 1689fcf5ef2aSThomas Huth break; 16903259b9e2SRichard Henderson case MO_128: 1691fcf5ef2aSThomas Huth /* Only 4-byte alignment required. However, it is legal for the 1692fcf5ef2aSThomas Huth cpu to signal the alignment fault, and the OS trap handler is 1693fcf5ef2aSThomas Huth required to fix it up. Requiring 16-byte alignment here avoids 1694fcf5ef2aSThomas Huth having to probe the second page before performing the first 1695fcf5ef2aSThomas Huth write. */ 16963259b9e2SRichard Henderson tcg_gen_qemu_st_i64(cpu_fpr[rd / 2], addr, da->mem_idx, 16973259b9e2SRichard Henderson memop | MO_ALIGN_16); 1698287b1152SRichard Henderson addr_tmp = tcg_temp_new(); 1699287b1152SRichard Henderson tcg_gen_addi_tl(addr_tmp, addr, 8); 1700287b1152SRichard Henderson tcg_gen_qemu_st_i64(cpu_fpr[rd / 2 + 1], addr_tmp, da->mem_idx, memop); 1701fcf5ef2aSThomas Huth break; 1702fcf5ef2aSThomas Huth default: 1703fcf5ef2aSThomas Huth g_assert_not_reached(); 1704fcf5ef2aSThomas Huth } 1705fcf5ef2aSThomas Huth break; 1706fcf5ef2aSThomas Huth 1707fcf5ef2aSThomas Huth case GET_ASI_BLOCK: 1708fcf5ef2aSThomas Huth /* Valid for stdfa on aligned registers only. */ 17093259b9e2SRichard Henderson if (orig_size == MO_64 && (rd & 7) == 0) { 1710fcf5ef2aSThomas Huth /* The first operation checks required alignment. */ 1711287b1152SRichard Henderson addr_tmp = tcg_temp_new(); 1712287b1152SRichard Henderson for (int i = 0; ; ++i) { 17133259b9e2SRichard Henderson tcg_gen_qemu_st_i64(cpu_fpr[rd / 2 + i], addr, da->mem_idx, 17143259b9e2SRichard Henderson memop | (i == 0 ? MO_ALIGN_64 : 0)); 1715fcf5ef2aSThomas Huth if (i == 7) { 1716fcf5ef2aSThomas Huth break; 1717fcf5ef2aSThomas Huth } 1718287b1152SRichard Henderson tcg_gen_addi_tl(addr_tmp, addr, 8); 1719287b1152SRichard Henderson addr = addr_tmp; 1720fcf5ef2aSThomas Huth } 1721fcf5ef2aSThomas Huth } else { 1722fcf5ef2aSThomas Huth gen_exception(dc, TT_ILL_INSN); 1723fcf5ef2aSThomas Huth } 1724fcf5ef2aSThomas Huth break; 1725fcf5ef2aSThomas Huth 1726fcf5ef2aSThomas Huth case GET_ASI_SHORT: 1727fcf5ef2aSThomas Huth /* Valid for stdfa only. */ 17283259b9e2SRichard Henderson if (orig_size == MO_64) { 17293259b9e2SRichard Henderson tcg_gen_qemu_st_i64(cpu_fpr[rd / 2], addr, da->mem_idx, 17303259b9e2SRichard Henderson memop | MO_ALIGN); 1731fcf5ef2aSThomas Huth } else { 1732fcf5ef2aSThomas Huth gen_exception(dc, TT_ILL_INSN); 1733fcf5ef2aSThomas Huth } 1734fcf5ef2aSThomas Huth break; 1735fcf5ef2aSThomas Huth 1736fcf5ef2aSThomas Huth default: 1737fcf5ef2aSThomas Huth /* According to the table in the UA2011 manual, the only 1738fcf5ef2aSThomas Huth other asis that are valid for ldfa/lddfa/ldqfa are 1739fcf5ef2aSThomas Huth the PST* asis, which aren't currently handled. */ 1740fcf5ef2aSThomas Huth gen_exception(dc, TT_ILL_INSN); 1741fcf5ef2aSThomas Huth break; 1742fcf5ef2aSThomas Huth } 1743fcf5ef2aSThomas Huth } 1744fcf5ef2aSThomas Huth 174542071fc1SRichard Henderson static void gen_ldda_asi(DisasContext *dc, DisasASI *da, TCGv addr, int rd) 1746fcf5ef2aSThomas Huth { 1747a76779eeSRichard Henderson TCGv hi = gen_dest_gpr(dc, rd); 1748a76779eeSRichard Henderson TCGv lo = gen_dest_gpr(dc, rd + 1); 1749fcf5ef2aSThomas Huth 1750c03a0fd1SRichard Henderson switch (da->type) { 1751fcf5ef2aSThomas Huth case GET_ASI_EXCP: 1752fcf5ef2aSThomas Huth return; 1753fcf5ef2aSThomas Huth 1754fcf5ef2aSThomas Huth case GET_ASI_DTWINX: 1755ebbbec92SRichard Henderson #ifdef TARGET_SPARC64 1756ebbbec92SRichard Henderson { 1757ebbbec92SRichard Henderson MemOp mop = (da->memop & MO_BSWAP) | MO_128 | MO_ALIGN_16; 1758ebbbec92SRichard Henderson TCGv_i128 t = tcg_temp_new_i128(); 1759ebbbec92SRichard Henderson 1760ebbbec92SRichard Henderson tcg_gen_qemu_ld_i128(t, addr, da->mem_idx, mop); 1761ebbbec92SRichard Henderson /* 1762ebbbec92SRichard Henderson * Note that LE twinx acts as if each 64-bit register result is 1763ebbbec92SRichard Henderson * byte swapped. We perform one 128-bit LE load, so must swap 1764ebbbec92SRichard Henderson * the order of the writebacks. 1765ebbbec92SRichard Henderson */ 1766ebbbec92SRichard Henderson if ((mop & MO_BSWAP) == MO_TE) { 1767ebbbec92SRichard Henderson tcg_gen_extr_i128_i64(lo, hi, t); 1768ebbbec92SRichard Henderson } else { 1769ebbbec92SRichard Henderson tcg_gen_extr_i128_i64(hi, lo, t); 1770ebbbec92SRichard Henderson } 1771ebbbec92SRichard Henderson } 1772fcf5ef2aSThomas Huth break; 1773ebbbec92SRichard Henderson #else 1774ebbbec92SRichard Henderson g_assert_not_reached(); 1775ebbbec92SRichard Henderson #endif 1776fcf5ef2aSThomas Huth 1777fcf5ef2aSThomas Huth case GET_ASI_DIRECT: 1778fcf5ef2aSThomas Huth { 1779fcf5ef2aSThomas Huth TCGv_i64 tmp = tcg_temp_new_i64(); 1780fcf5ef2aSThomas Huth 1781c03a0fd1SRichard Henderson tcg_gen_qemu_ld_i64(tmp, addr, da->mem_idx, da->memop | MO_ALIGN); 1782fcf5ef2aSThomas Huth 1783fcf5ef2aSThomas Huth /* Note that LE ldda acts as if each 32-bit register 1784fcf5ef2aSThomas Huth result is byte swapped. Having just performed one 1785fcf5ef2aSThomas Huth 64-bit bswap, we need now to swap the writebacks. */ 1786c03a0fd1SRichard Henderson if ((da->memop & MO_BSWAP) == MO_TE) { 1787a76779eeSRichard Henderson tcg_gen_extr_i64_tl(lo, hi, tmp); 1788fcf5ef2aSThomas Huth } else { 1789a76779eeSRichard Henderson tcg_gen_extr_i64_tl(hi, lo, tmp); 1790fcf5ef2aSThomas Huth } 1791fcf5ef2aSThomas Huth } 1792fcf5ef2aSThomas Huth break; 1793fcf5ef2aSThomas Huth 1794fcf5ef2aSThomas Huth default: 1795fcf5ef2aSThomas Huth /* ??? In theory we've handled all of the ASIs that are valid 1796fcf5ef2aSThomas Huth for ldda, and this should raise DAE_invalid_asi. However, 1797fcf5ef2aSThomas Huth real hardware allows others. This can be seen with e.g. 1798fcf5ef2aSThomas Huth FreeBSD 10.3 wrt ASI_IC_TAG. */ 1799fcf5ef2aSThomas Huth { 1800c03a0fd1SRichard Henderson TCGv_i32 r_asi = tcg_constant_i32(da->asi); 1801c03a0fd1SRichard Henderson TCGv_i32 r_mop = tcg_constant_i32(da->memop); 1802fcf5ef2aSThomas Huth TCGv_i64 tmp = tcg_temp_new_i64(); 1803fcf5ef2aSThomas Huth 1804fcf5ef2aSThomas Huth save_state(dc); 1805ad75a51eSRichard Henderson gen_helper_ld_asi(tmp, tcg_env, addr, r_asi, r_mop); 1806fcf5ef2aSThomas Huth 1807fcf5ef2aSThomas Huth /* See above. */ 1808c03a0fd1SRichard Henderson if ((da->memop & MO_BSWAP) == MO_TE) { 1809a76779eeSRichard Henderson tcg_gen_extr_i64_tl(lo, hi, tmp); 1810fcf5ef2aSThomas Huth } else { 1811a76779eeSRichard Henderson tcg_gen_extr_i64_tl(hi, lo, tmp); 1812fcf5ef2aSThomas Huth } 1813fcf5ef2aSThomas Huth } 1814fcf5ef2aSThomas Huth break; 1815fcf5ef2aSThomas Huth } 1816fcf5ef2aSThomas Huth 1817fcf5ef2aSThomas Huth gen_store_gpr(dc, rd, hi); 1818fcf5ef2aSThomas Huth gen_store_gpr(dc, rd + 1, lo); 1819fcf5ef2aSThomas Huth } 1820fcf5ef2aSThomas Huth 182142071fc1SRichard Henderson static void gen_stda_asi(DisasContext *dc, DisasASI *da, TCGv addr, int rd) 1822c03a0fd1SRichard Henderson { 1823c03a0fd1SRichard Henderson TCGv hi = gen_load_gpr(dc, rd); 1824fcf5ef2aSThomas Huth TCGv lo = gen_load_gpr(dc, rd + 1); 1825fcf5ef2aSThomas Huth 1826c03a0fd1SRichard Henderson switch (da->type) { 1827fcf5ef2aSThomas Huth case GET_ASI_EXCP: 1828fcf5ef2aSThomas Huth break; 1829fcf5ef2aSThomas Huth 1830fcf5ef2aSThomas Huth case GET_ASI_DTWINX: 1831ebbbec92SRichard Henderson #ifdef TARGET_SPARC64 1832ebbbec92SRichard Henderson { 1833ebbbec92SRichard Henderson MemOp mop = (da->memop & MO_BSWAP) | MO_128 | MO_ALIGN_16; 1834ebbbec92SRichard Henderson TCGv_i128 t = tcg_temp_new_i128(); 1835ebbbec92SRichard Henderson 1836ebbbec92SRichard Henderson /* 1837ebbbec92SRichard Henderson * Note that LE twinx acts as if each 64-bit register result is 1838ebbbec92SRichard Henderson * byte swapped. We perform one 128-bit LE store, so must swap 1839ebbbec92SRichard Henderson * the order of the construction. 1840ebbbec92SRichard Henderson */ 1841ebbbec92SRichard Henderson if ((mop & MO_BSWAP) == MO_TE) { 1842ebbbec92SRichard Henderson tcg_gen_concat_i64_i128(t, lo, hi); 1843ebbbec92SRichard Henderson } else { 1844ebbbec92SRichard Henderson tcg_gen_concat_i64_i128(t, hi, lo); 1845ebbbec92SRichard Henderson } 1846ebbbec92SRichard Henderson tcg_gen_qemu_st_i128(t, addr, da->mem_idx, mop); 1847ebbbec92SRichard Henderson } 1848fcf5ef2aSThomas Huth break; 1849ebbbec92SRichard Henderson #else 1850ebbbec92SRichard Henderson g_assert_not_reached(); 1851ebbbec92SRichard Henderson #endif 1852fcf5ef2aSThomas Huth 1853fcf5ef2aSThomas Huth case GET_ASI_DIRECT: 1854fcf5ef2aSThomas Huth { 1855fcf5ef2aSThomas Huth TCGv_i64 t64 = tcg_temp_new_i64(); 1856fcf5ef2aSThomas Huth 1857fcf5ef2aSThomas Huth /* Note that LE stda acts as if each 32-bit register result is 1858fcf5ef2aSThomas Huth byte swapped. We will perform one 64-bit LE store, so now 1859fcf5ef2aSThomas Huth we must swap the order of the construction. */ 1860c03a0fd1SRichard Henderson if ((da->memop & MO_BSWAP) == MO_TE) { 1861a76779eeSRichard Henderson tcg_gen_concat_tl_i64(t64, lo, hi); 1862fcf5ef2aSThomas Huth } else { 1863a76779eeSRichard Henderson tcg_gen_concat_tl_i64(t64, hi, lo); 1864fcf5ef2aSThomas Huth } 1865c03a0fd1SRichard Henderson tcg_gen_qemu_st_i64(t64, addr, da->mem_idx, da->memop | MO_ALIGN); 1866fcf5ef2aSThomas Huth } 1867fcf5ef2aSThomas Huth break; 1868fcf5ef2aSThomas Huth 1869a76779eeSRichard Henderson case GET_ASI_BFILL: 1870a76779eeSRichard Henderson assert(TARGET_LONG_BITS == 32); 187154c3e953SRichard Henderson /* 187254c3e953SRichard Henderson * Store 32 bytes of [rd:rd+1] to ADDR. 187354c3e953SRichard Henderson * See comments for GET_ASI_COPY above. 187454c3e953SRichard Henderson */ 1875a76779eeSRichard Henderson { 187654c3e953SRichard Henderson MemOp mop = MO_TE | MO_128 | MO_ATOM_IFALIGN_PAIR; 187754c3e953SRichard Henderson TCGv_i64 t8 = tcg_temp_new_i64(); 187854c3e953SRichard Henderson TCGv_i128 t16 = tcg_temp_new_i128(); 187954c3e953SRichard Henderson TCGv daddr = tcg_temp_new(); 1880a76779eeSRichard Henderson 188154c3e953SRichard Henderson tcg_gen_concat_tl_i64(t8, lo, hi); 188254c3e953SRichard Henderson tcg_gen_concat_i64_i128(t16, t8, t8); 188354c3e953SRichard Henderson tcg_gen_andi_tl(daddr, addr, -32); 188454c3e953SRichard Henderson tcg_gen_qemu_st_i128(t16, daddr, da->mem_idx, mop); 188554c3e953SRichard Henderson tcg_gen_addi_tl(daddr, daddr, 16); 188654c3e953SRichard Henderson tcg_gen_qemu_st_i128(t16, daddr, da->mem_idx, mop); 1887a76779eeSRichard Henderson } 1888a76779eeSRichard Henderson break; 1889a76779eeSRichard Henderson 1890fcf5ef2aSThomas Huth default: 1891fcf5ef2aSThomas Huth /* ??? In theory we've handled all of the ASIs that are valid 1892fcf5ef2aSThomas Huth for stda, and this should raise DAE_invalid_asi. */ 1893fcf5ef2aSThomas Huth { 1894c03a0fd1SRichard Henderson TCGv_i32 r_asi = tcg_constant_i32(da->asi); 1895c03a0fd1SRichard Henderson TCGv_i32 r_mop = tcg_constant_i32(da->memop); 1896fcf5ef2aSThomas Huth TCGv_i64 t64 = tcg_temp_new_i64(); 1897fcf5ef2aSThomas Huth 1898fcf5ef2aSThomas Huth /* See above. */ 1899c03a0fd1SRichard Henderson if ((da->memop & MO_BSWAP) == MO_TE) { 1900a76779eeSRichard Henderson tcg_gen_concat_tl_i64(t64, lo, hi); 1901fcf5ef2aSThomas Huth } else { 1902a76779eeSRichard Henderson tcg_gen_concat_tl_i64(t64, hi, lo); 1903fcf5ef2aSThomas Huth } 1904fcf5ef2aSThomas Huth 1905fcf5ef2aSThomas Huth save_state(dc); 1906ad75a51eSRichard Henderson gen_helper_st_asi(tcg_env, addr, t64, r_asi, r_mop); 1907fcf5ef2aSThomas Huth } 1908fcf5ef2aSThomas Huth break; 1909fcf5ef2aSThomas Huth } 1910fcf5ef2aSThomas Huth } 1911fcf5ef2aSThomas Huth 1912fcf5ef2aSThomas Huth static void gen_fmovs(DisasContext *dc, DisasCompare *cmp, int rd, int rs) 1913fcf5ef2aSThomas Huth { 1914f7ec8155SRichard Henderson #ifdef TARGET_SPARC64 1915fcf5ef2aSThomas Huth TCGv_i32 c32, zero, dst, s1, s2; 1916dd7dbfccSRichard Henderson TCGv_i64 c64 = tcg_temp_new_i64(); 1917fcf5ef2aSThomas Huth 1918fcf5ef2aSThomas Huth /* We have two choices here: extend the 32 bit data and use movcond_i64, 1919fcf5ef2aSThomas Huth or fold the comparison down to 32 bits and use movcond_i32. Choose 1920fcf5ef2aSThomas Huth the later. */ 1921fcf5ef2aSThomas Huth c32 = tcg_temp_new_i32(); 1922c8507ebfSRichard Henderson tcg_gen_setcondi_i64(cmp->cond, c64, cmp->c1, cmp->c2); 1923fcf5ef2aSThomas Huth tcg_gen_extrl_i64_i32(c32, c64); 1924fcf5ef2aSThomas Huth 1925fcf5ef2aSThomas Huth s1 = gen_load_fpr_F(dc, rs); 1926fcf5ef2aSThomas Huth s2 = gen_load_fpr_F(dc, rd); 1927388a6465SRichard Henderson dst = tcg_temp_new_i32(); 192800ab7e61SRichard Henderson zero = tcg_constant_i32(0); 1929fcf5ef2aSThomas Huth 1930fcf5ef2aSThomas Huth tcg_gen_movcond_i32(TCG_COND_NE, dst, c32, zero, s1, s2); 1931fcf5ef2aSThomas Huth 1932fcf5ef2aSThomas Huth gen_store_fpr_F(dc, rd, dst); 1933f7ec8155SRichard Henderson #else 1934f7ec8155SRichard Henderson qemu_build_not_reached(); 1935f7ec8155SRichard Henderson #endif 1936fcf5ef2aSThomas Huth } 1937fcf5ef2aSThomas Huth 1938fcf5ef2aSThomas Huth static void gen_fmovd(DisasContext *dc, DisasCompare *cmp, int rd, int rs) 1939fcf5ef2aSThomas Huth { 1940f7ec8155SRichard Henderson #ifdef TARGET_SPARC64 1941fcf5ef2aSThomas Huth TCGv_i64 dst = gen_dest_fpr_D(dc, rd); 1942c8507ebfSRichard Henderson tcg_gen_movcond_i64(cmp->cond, dst, cmp->c1, tcg_constant_tl(cmp->c2), 1943fcf5ef2aSThomas Huth gen_load_fpr_D(dc, rs), 1944fcf5ef2aSThomas Huth gen_load_fpr_D(dc, rd)); 1945fcf5ef2aSThomas Huth gen_store_fpr_D(dc, rd, dst); 1946f7ec8155SRichard Henderson #else 1947f7ec8155SRichard Henderson qemu_build_not_reached(); 1948f7ec8155SRichard Henderson #endif 1949fcf5ef2aSThomas Huth } 1950fcf5ef2aSThomas Huth 1951fcf5ef2aSThomas Huth static void gen_fmovq(DisasContext *dc, DisasCompare *cmp, int rd, int rs) 1952fcf5ef2aSThomas Huth { 1953f7ec8155SRichard Henderson #ifdef TARGET_SPARC64 1954fcf5ef2aSThomas Huth int qd = QFPREG(rd); 1955fcf5ef2aSThomas Huth int qs = QFPREG(rs); 1956c8507ebfSRichard Henderson TCGv c2 = tcg_constant_tl(cmp->c2); 1957fcf5ef2aSThomas Huth 1958c8507ebfSRichard Henderson tcg_gen_movcond_i64(cmp->cond, cpu_fpr[qd / 2], cmp->c1, c2, 1959fcf5ef2aSThomas Huth cpu_fpr[qs / 2], cpu_fpr[qd / 2]); 1960c8507ebfSRichard Henderson tcg_gen_movcond_i64(cmp->cond, cpu_fpr[qd / 2 + 1], cmp->c1, c2, 1961fcf5ef2aSThomas Huth cpu_fpr[qs / 2 + 1], cpu_fpr[qd / 2 + 1]); 1962fcf5ef2aSThomas Huth 1963fcf5ef2aSThomas Huth gen_update_fprs_dirty(dc, qd); 1964f7ec8155SRichard Henderson #else 1965f7ec8155SRichard Henderson qemu_build_not_reached(); 1966f7ec8155SRichard Henderson #endif 1967fcf5ef2aSThomas Huth } 1968fcf5ef2aSThomas Huth 1969f7ec8155SRichard Henderson #ifdef TARGET_SPARC64 19705d617bfbSRichard Henderson static void gen_load_trap_state_at_tl(TCGv_ptr r_tsptr) 1971fcf5ef2aSThomas Huth { 1972fcf5ef2aSThomas Huth TCGv_i32 r_tl = tcg_temp_new_i32(); 1973fcf5ef2aSThomas Huth 1974fcf5ef2aSThomas Huth /* load env->tl into r_tl */ 1975ad75a51eSRichard Henderson tcg_gen_ld_i32(r_tl, tcg_env, offsetof(CPUSPARCState, tl)); 1976fcf5ef2aSThomas Huth 1977fcf5ef2aSThomas Huth /* tl = [0 ... MAXTL_MASK] where MAXTL_MASK must be power of 2 */ 1978fcf5ef2aSThomas Huth tcg_gen_andi_i32(r_tl, r_tl, MAXTL_MASK); 1979fcf5ef2aSThomas Huth 1980fcf5ef2aSThomas Huth /* calculate offset to current trap state from env->ts, reuse r_tl */ 1981fcf5ef2aSThomas Huth tcg_gen_muli_i32(r_tl, r_tl, sizeof (trap_state)); 1982ad75a51eSRichard Henderson tcg_gen_addi_ptr(r_tsptr, tcg_env, offsetof(CPUSPARCState, ts)); 1983fcf5ef2aSThomas Huth 1984fcf5ef2aSThomas Huth /* tsptr = env->ts[env->tl & MAXTL_MASK] */ 1985fcf5ef2aSThomas Huth { 1986fcf5ef2aSThomas Huth TCGv_ptr r_tl_tmp = tcg_temp_new_ptr(); 1987fcf5ef2aSThomas Huth tcg_gen_ext_i32_ptr(r_tl_tmp, r_tl); 1988fcf5ef2aSThomas Huth tcg_gen_add_ptr(r_tsptr, r_tsptr, r_tl_tmp); 1989fcf5ef2aSThomas Huth } 1990fcf5ef2aSThomas Huth } 1991fcf5ef2aSThomas Huth #endif 1992fcf5ef2aSThomas Huth 199306c060d9SRichard Henderson static int extract_dfpreg(DisasContext *dc, int x) 199406c060d9SRichard Henderson { 199506c060d9SRichard Henderson return DFPREG(x); 199606c060d9SRichard Henderson } 199706c060d9SRichard Henderson 199806c060d9SRichard Henderson static int extract_qfpreg(DisasContext *dc, int x) 199906c060d9SRichard Henderson { 200006c060d9SRichard Henderson return QFPREG(x); 200106c060d9SRichard Henderson } 200206c060d9SRichard Henderson 2003878cc677SRichard Henderson /* Include the auto-generated decoder. */ 2004878cc677SRichard Henderson #include "decode-insns.c.inc" 2005878cc677SRichard Henderson 2006878cc677SRichard Henderson #define TRANS(NAME, AVAIL, FUNC, ...) \ 2007878cc677SRichard Henderson static bool trans_##NAME(DisasContext *dc, arg_##NAME *a) \ 2008878cc677SRichard Henderson { return avail_##AVAIL(dc) && FUNC(dc, __VA_ARGS__); } 2009878cc677SRichard Henderson 2010878cc677SRichard Henderson #define avail_ALL(C) true 2011878cc677SRichard Henderson #ifdef TARGET_SPARC64 2012878cc677SRichard Henderson # define avail_32(C) false 2013af25071cSRichard Henderson # define avail_ASR17(C) false 2014d0a11d25SRichard Henderson # define avail_CASA(C) true 2015c2636853SRichard Henderson # define avail_DIV(C) true 2016b5372650SRichard Henderson # define avail_MUL(C) true 20170faef01bSRichard Henderson # define avail_POWERDOWN(C) false 2018878cc677SRichard Henderson # define avail_64(C) true 20195d617bfbSRichard Henderson # define avail_GL(C) ((C)->def->features & CPU_FEATURE_GL) 2020af25071cSRichard Henderson # define avail_HYPV(C) ((C)->def->features & CPU_FEATURE_HYPV) 2021b88ce6f2SRichard Henderson # define avail_VIS1(C) ((C)->def->features & CPU_FEATURE_VIS1) 2022b88ce6f2SRichard Henderson # define avail_VIS2(C) ((C)->def->features & CPU_FEATURE_VIS2) 2023878cc677SRichard Henderson #else 2024878cc677SRichard Henderson # define avail_32(C) true 2025af25071cSRichard Henderson # define avail_ASR17(C) ((C)->def->features & CPU_FEATURE_ASR17) 2026d0a11d25SRichard Henderson # define avail_CASA(C) ((C)->def->features & CPU_FEATURE_CASA) 2027c2636853SRichard Henderson # define avail_DIV(C) ((C)->def->features & CPU_FEATURE_DIV) 2028b5372650SRichard Henderson # define avail_MUL(C) ((C)->def->features & CPU_FEATURE_MUL) 20290faef01bSRichard Henderson # define avail_POWERDOWN(C) ((C)->def->features & CPU_FEATURE_POWERDOWN) 2030878cc677SRichard Henderson # define avail_64(C) false 20315d617bfbSRichard Henderson # define avail_GL(C) false 2032af25071cSRichard Henderson # define avail_HYPV(C) false 2033b88ce6f2SRichard Henderson # define avail_VIS1(C) false 2034b88ce6f2SRichard Henderson # define avail_VIS2(C) false 2035878cc677SRichard Henderson #endif 2036878cc677SRichard Henderson 2037878cc677SRichard Henderson /* Default case for non jump instructions. */ 2038878cc677SRichard Henderson static bool advance_pc(DisasContext *dc) 2039878cc677SRichard Henderson { 20404a8d145dSRichard Henderson TCGLabel *l1; 20414a8d145dSRichard Henderson 204289527e3aSRichard Henderson finishing_insn(dc); 204389527e3aSRichard Henderson 2044878cc677SRichard Henderson if (dc->npc & 3) { 2045878cc677SRichard Henderson switch (dc->npc) { 2046878cc677SRichard Henderson case DYNAMIC_PC: 2047878cc677SRichard Henderson case DYNAMIC_PC_LOOKUP: 2048878cc677SRichard Henderson dc->pc = dc->npc; 2049444d8b30SRichard Henderson tcg_gen_mov_tl(cpu_pc, cpu_npc); 2050444d8b30SRichard Henderson tcg_gen_addi_tl(cpu_npc, cpu_npc, 4); 2051878cc677SRichard Henderson break; 20524a8d145dSRichard Henderson 2053878cc677SRichard Henderson case JUMP_PC: 2054878cc677SRichard Henderson /* we can do a static jump */ 20554a8d145dSRichard Henderson l1 = gen_new_label(); 2056533f042fSRichard Henderson tcg_gen_brcondi_tl(dc->jump.cond, dc->jump.c1, dc->jump.c2, l1); 20574a8d145dSRichard Henderson 20584a8d145dSRichard Henderson /* jump not taken */ 20594a8d145dSRichard Henderson gen_goto_tb(dc, 1, dc->jump_pc[1], dc->jump_pc[1] + 4); 20604a8d145dSRichard Henderson 20614a8d145dSRichard Henderson /* jump taken */ 20624a8d145dSRichard Henderson gen_set_label(l1); 20634a8d145dSRichard Henderson gen_goto_tb(dc, 0, dc->jump_pc[0], dc->jump_pc[0] + 4); 20644a8d145dSRichard Henderson 2065878cc677SRichard Henderson dc->base.is_jmp = DISAS_NORETURN; 2066878cc677SRichard Henderson break; 20674a8d145dSRichard Henderson 2068878cc677SRichard Henderson default: 2069878cc677SRichard Henderson g_assert_not_reached(); 2070878cc677SRichard Henderson } 2071878cc677SRichard Henderson } else { 2072878cc677SRichard Henderson dc->pc = dc->npc; 2073878cc677SRichard Henderson dc->npc = dc->npc + 4; 2074878cc677SRichard Henderson } 2075878cc677SRichard Henderson return true; 2076878cc677SRichard Henderson } 2077878cc677SRichard Henderson 20786d2a0768SRichard Henderson /* 20796d2a0768SRichard Henderson * Major opcodes 00 and 01 -- branches, call, and sethi 20806d2a0768SRichard Henderson */ 20816d2a0768SRichard Henderson 20829d4e2bc7SRichard Henderson static bool advance_jump_cond(DisasContext *dc, DisasCompare *cmp, 20833951b7a8SRichard Henderson bool annul, int disp) 2084276567aaSRichard Henderson { 20853951b7a8SRichard Henderson target_ulong dest = address_mask_i(dc, dc->pc + disp * 4); 2086c76c8045SRichard Henderson target_ulong npc; 2087c76c8045SRichard Henderson 208889527e3aSRichard Henderson finishing_insn(dc); 208989527e3aSRichard Henderson 20902d9bb237SRichard Henderson if (cmp->cond == TCG_COND_ALWAYS) { 20912d9bb237SRichard Henderson if (annul) { 20922d9bb237SRichard Henderson dc->pc = dest; 20932d9bb237SRichard Henderson dc->npc = dest + 4; 20942d9bb237SRichard Henderson } else { 20952d9bb237SRichard Henderson gen_mov_pc_npc(dc); 20962d9bb237SRichard Henderson dc->npc = dest; 20972d9bb237SRichard Henderson } 20982d9bb237SRichard Henderson return true; 20992d9bb237SRichard Henderson } 21002d9bb237SRichard Henderson 21012d9bb237SRichard Henderson if (cmp->cond == TCG_COND_NEVER) { 21022d9bb237SRichard Henderson npc = dc->npc; 21032d9bb237SRichard Henderson if (npc & 3) { 21042d9bb237SRichard Henderson gen_mov_pc_npc(dc); 21052d9bb237SRichard Henderson if (annul) { 21062d9bb237SRichard Henderson tcg_gen_addi_tl(cpu_pc, cpu_pc, 4); 21072d9bb237SRichard Henderson } 21082d9bb237SRichard Henderson tcg_gen_addi_tl(cpu_npc, cpu_pc, 4); 21092d9bb237SRichard Henderson } else { 21102d9bb237SRichard Henderson dc->pc = npc + (annul ? 4 : 0); 21112d9bb237SRichard Henderson dc->npc = dc->pc + 4; 21122d9bb237SRichard Henderson } 21132d9bb237SRichard Henderson return true; 21142d9bb237SRichard Henderson } 21152d9bb237SRichard Henderson 2116c76c8045SRichard Henderson flush_cond(dc); 2117c76c8045SRichard Henderson npc = dc->npc; 21186b3e4cc6SRichard Henderson 2119276567aaSRichard Henderson if (annul) { 21206b3e4cc6SRichard Henderson TCGLabel *l1 = gen_new_label(); 21216b3e4cc6SRichard Henderson 2122c8507ebfSRichard Henderson tcg_gen_brcondi_tl(tcg_invert_cond(cmp->cond), cmp->c1, cmp->c2, l1); 21236b3e4cc6SRichard Henderson gen_goto_tb(dc, 0, npc, dest); 21246b3e4cc6SRichard Henderson gen_set_label(l1); 21256b3e4cc6SRichard Henderson gen_goto_tb(dc, 1, npc + 4, npc + 8); 21266b3e4cc6SRichard Henderson 21276b3e4cc6SRichard Henderson dc->base.is_jmp = DISAS_NORETURN; 2128276567aaSRichard Henderson } else { 21296b3e4cc6SRichard Henderson if (npc & 3) { 21306b3e4cc6SRichard Henderson switch (npc) { 21316b3e4cc6SRichard Henderson case DYNAMIC_PC: 21326b3e4cc6SRichard Henderson case DYNAMIC_PC_LOOKUP: 21336b3e4cc6SRichard Henderson tcg_gen_mov_tl(cpu_pc, cpu_npc); 21346b3e4cc6SRichard Henderson tcg_gen_addi_tl(cpu_npc, cpu_npc, 4); 21359d4e2bc7SRichard Henderson tcg_gen_movcond_tl(cmp->cond, cpu_npc, 2136c8507ebfSRichard Henderson cmp->c1, tcg_constant_tl(cmp->c2), 21376b3e4cc6SRichard Henderson tcg_constant_tl(dest), cpu_npc); 21386b3e4cc6SRichard Henderson dc->pc = npc; 21396b3e4cc6SRichard Henderson break; 21406b3e4cc6SRichard Henderson default: 21416b3e4cc6SRichard Henderson g_assert_not_reached(); 21426b3e4cc6SRichard Henderson } 21436b3e4cc6SRichard Henderson } else { 21446b3e4cc6SRichard Henderson dc->pc = npc; 2145533f042fSRichard Henderson dc->npc = JUMP_PC; 2146533f042fSRichard Henderson dc->jump = *cmp; 21476b3e4cc6SRichard Henderson dc->jump_pc[0] = dest; 21486b3e4cc6SRichard Henderson dc->jump_pc[1] = npc + 4; 2149dd7dbfccSRichard Henderson 2150dd7dbfccSRichard Henderson /* The condition for cpu_cond is always NE -- normalize. */ 2151dd7dbfccSRichard Henderson if (cmp->cond == TCG_COND_NE) { 2152c8507ebfSRichard Henderson tcg_gen_xori_tl(cpu_cond, cmp->c1, cmp->c2); 21539d4e2bc7SRichard Henderson } else { 2154c8507ebfSRichard Henderson tcg_gen_setcondi_tl(cmp->cond, cpu_cond, cmp->c1, cmp->c2); 21559d4e2bc7SRichard Henderson } 215689527e3aSRichard Henderson dc->cpu_cond_live = true; 21576b3e4cc6SRichard Henderson } 2158276567aaSRichard Henderson } 2159276567aaSRichard Henderson return true; 2160276567aaSRichard Henderson } 2161276567aaSRichard Henderson 2162af25071cSRichard Henderson static bool raise_priv(DisasContext *dc) 2163af25071cSRichard Henderson { 2164af25071cSRichard Henderson gen_exception(dc, TT_PRIV_INSN); 2165af25071cSRichard Henderson return true; 2166af25071cSRichard Henderson } 2167af25071cSRichard Henderson 216806c060d9SRichard Henderson static bool raise_unimpfpop(DisasContext *dc) 216906c060d9SRichard Henderson { 217006c060d9SRichard Henderson gen_op_fpexception_im(dc, FSR_FTT_UNIMPFPOP); 217106c060d9SRichard Henderson return true; 217206c060d9SRichard Henderson } 217306c060d9SRichard Henderson 217406c060d9SRichard Henderson static bool gen_trap_float128(DisasContext *dc) 217506c060d9SRichard Henderson { 217606c060d9SRichard Henderson if (dc->def->features & CPU_FEATURE_FLOAT128) { 217706c060d9SRichard Henderson return false; 217806c060d9SRichard Henderson } 217906c060d9SRichard Henderson return raise_unimpfpop(dc); 218006c060d9SRichard Henderson } 218106c060d9SRichard Henderson 2182276567aaSRichard Henderson static bool do_bpcc(DisasContext *dc, arg_bcc *a) 2183276567aaSRichard Henderson { 21841ea9c62aSRichard Henderson DisasCompare cmp; 2185276567aaSRichard Henderson 21861ea9c62aSRichard Henderson gen_compare(&cmp, a->cc, a->cond, dc); 21873951b7a8SRichard Henderson return advance_jump_cond(dc, &cmp, a->a, a->i); 2188276567aaSRichard Henderson } 2189276567aaSRichard Henderson 2190276567aaSRichard Henderson TRANS(Bicc, ALL, do_bpcc, a) 2191276567aaSRichard Henderson TRANS(BPcc, 64, do_bpcc, a) 2192276567aaSRichard Henderson 219345196ea4SRichard Henderson static bool do_fbpfcc(DisasContext *dc, arg_bcc *a) 219445196ea4SRichard Henderson { 2195d5471936SRichard Henderson DisasCompare cmp; 219645196ea4SRichard Henderson 219745196ea4SRichard Henderson if (gen_trap_ifnofpu(dc)) { 219845196ea4SRichard Henderson return true; 219945196ea4SRichard Henderson } 2200d5471936SRichard Henderson gen_fcompare(&cmp, a->cc, a->cond); 22013951b7a8SRichard Henderson return advance_jump_cond(dc, &cmp, a->a, a->i); 220245196ea4SRichard Henderson } 220345196ea4SRichard Henderson 220445196ea4SRichard Henderson TRANS(FBPfcc, 64, do_fbpfcc, a) 220545196ea4SRichard Henderson TRANS(FBfcc, ALL, do_fbpfcc, a) 220645196ea4SRichard Henderson 2207ab9ffe98SRichard Henderson static bool trans_BPr(DisasContext *dc, arg_BPr *a) 2208ab9ffe98SRichard Henderson { 2209ab9ffe98SRichard Henderson DisasCompare cmp; 2210ab9ffe98SRichard Henderson 2211ab9ffe98SRichard Henderson if (!avail_64(dc)) { 2212ab9ffe98SRichard Henderson return false; 2213ab9ffe98SRichard Henderson } 22142c4f56c9SRichard Henderson if (!gen_compare_reg(&cmp, a->cond, gen_load_gpr(dc, a->rs1))) { 2215ab9ffe98SRichard Henderson return false; 2216ab9ffe98SRichard Henderson } 22173951b7a8SRichard Henderson return advance_jump_cond(dc, &cmp, a->a, a->i); 2218ab9ffe98SRichard Henderson } 2219ab9ffe98SRichard Henderson 222023ada1b1SRichard Henderson static bool trans_CALL(DisasContext *dc, arg_CALL *a) 222123ada1b1SRichard Henderson { 222223ada1b1SRichard Henderson target_long target = address_mask_i(dc, dc->pc + a->i * 4); 222323ada1b1SRichard Henderson 222423ada1b1SRichard Henderson gen_store_gpr(dc, 15, tcg_constant_tl(dc->pc)); 222523ada1b1SRichard Henderson gen_mov_pc_npc(dc); 222623ada1b1SRichard Henderson dc->npc = target; 222723ada1b1SRichard Henderson return true; 222823ada1b1SRichard Henderson } 222923ada1b1SRichard Henderson 223045196ea4SRichard Henderson static bool trans_NCP(DisasContext *dc, arg_NCP *a) 223145196ea4SRichard Henderson { 223245196ea4SRichard Henderson /* 223345196ea4SRichard Henderson * For sparc32, always generate the no-coprocessor exception. 223445196ea4SRichard Henderson * For sparc64, always generate illegal instruction. 223545196ea4SRichard Henderson */ 223645196ea4SRichard Henderson #ifdef TARGET_SPARC64 223745196ea4SRichard Henderson return false; 223845196ea4SRichard Henderson #else 223945196ea4SRichard Henderson gen_exception(dc, TT_NCP_INSN); 224045196ea4SRichard Henderson return true; 224145196ea4SRichard Henderson #endif 224245196ea4SRichard Henderson } 224345196ea4SRichard Henderson 22446d2a0768SRichard Henderson static bool trans_SETHI(DisasContext *dc, arg_SETHI *a) 22456d2a0768SRichard Henderson { 22466d2a0768SRichard Henderson /* Special-case %g0 because that's the canonical nop. */ 22476d2a0768SRichard Henderson if (a->rd) { 22486d2a0768SRichard Henderson gen_store_gpr(dc, a->rd, tcg_constant_tl((uint32_t)a->i << 10)); 22496d2a0768SRichard Henderson } 22506d2a0768SRichard Henderson return advance_pc(dc); 22516d2a0768SRichard Henderson } 22526d2a0768SRichard Henderson 22530faef01bSRichard Henderson /* 22540faef01bSRichard Henderson * Major Opcode 10 -- integer, floating-point, vis, and system insns. 22550faef01bSRichard Henderson */ 22560faef01bSRichard Henderson 225730376636SRichard Henderson static bool do_tcc(DisasContext *dc, int cond, int cc, 225830376636SRichard Henderson int rs1, bool imm, int rs2_or_imm) 225930376636SRichard Henderson { 226030376636SRichard Henderson int mask = ((dc->def->features & CPU_FEATURE_HYPV) && supervisor(dc) 226130376636SRichard Henderson ? UA2005_HTRAP_MASK : V8_TRAP_MASK); 226230376636SRichard Henderson DisasCompare cmp; 226330376636SRichard Henderson TCGLabel *lab; 226430376636SRichard Henderson TCGv_i32 trap; 226530376636SRichard Henderson 226630376636SRichard Henderson /* Trap never. */ 226730376636SRichard Henderson if (cond == 0) { 226830376636SRichard Henderson return advance_pc(dc); 226930376636SRichard Henderson } 227030376636SRichard Henderson 227130376636SRichard Henderson /* 227230376636SRichard Henderson * Immediate traps are the most common case. Since this value is 227330376636SRichard Henderson * live across the branch, it really pays to evaluate the constant. 227430376636SRichard Henderson */ 227530376636SRichard Henderson if (rs1 == 0 && (imm || rs2_or_imm == 0)) { 227630376636SRichard Henderson trap = tcg_constant_i32((rs2_or_imm & mask) + TT_TRAP); 227730376636SRichard Henderson } else { 227830376636SRichard Henderson trap = tcg_temp_new_i32(); 227930376636SRichard Henderson tcg_gen_trunc_tl_i32(trap, gen_load_gpr(dc, rs1)); 228030376636SRichard Henderson if (imm) { 228130376636SRichard Henderson tcg_gen_addi_i32(trap, trap, rs2_or_imm); 228230376636SRichard Henderson } else { 228330376636SRichard Henderson TCGv_i32 t2 = tcg_temp_new_i32(); 228430376636SRichard Henderson tcg_gen_trunc_tl_i32(t2, gen_load_gpr(dc, rs2_or_imm)); 228530376636SRichard Henderson tcg_gen_add_i32(trap, trap, t2); 228630376636SRichard Henderson } 228730376636SRichard Henderson tcg_gen_andi_i32(trap, trap, mask); 228830376636SRichard Henderson tcg_gen_addi_i32(trap, trap, TT_TRAP); 228930376636SRichard Henderson } 229030376636SRichard Henderson 229189527e3aSRichard Henderson finishing_insn(dc); 229289527e3aSRichard Henderson 229330376636SRichard Henderson /* Trap always. */ 229430376636SRichard Henderson if (cond == 8) { 229530376636SRichard Henderson save_state(dc); 229630376636SRichard Henderson gen_helper_raise_exception(tcg_env, trap); 229730376636SRichard Henderson dc->base.is_jmp = DISAS_NORETURN; 229830376636SRichard Henderson return true; 229930376636SRichard Henderson } 230030376636SRichard Henderson 230130376636SRichard Henderson /* Conditional trap. */ 230230376636SRichard Henderson flush_cond(dc); 230330376636SRichard Henderson lab = delay_exceptionv(dc, trap); 230430376636SRichard Henderson gen_compare(&cmp, cc, cond, dc); 2305c8507ebfSRichard Henderson tcg_gen_brcondi_tl(cmp.cond, cmp.c1, cmp.c2, lab); 230630376636SRichard Henderson 230730376636SRichard Henderson return advance_pc(dc); 230830376636SRichard Henderson } 230930376636SRichard Henderson 231030376636SRichard Henderson static bool trans_Tcc_r(DisasContext *dc, arg_Tcc_r *a) 231130376636SRichard Henderson { 231230376636SRichard Henderson if (avail_32(dc) && a->cc) { 231330376636SRichard Henderson return false; 231430376636SRichard Henderson } 231530376636SRichard Henderson return do_tcc(dc, a->cond, a->cc, a->rs1, false, a->rs2); 231630376636SRichard Henderson } 231730376636SRichard Henderson 231830376636SRichard Henderson static bool trans_Tcc_i_v7(DisasContext *dc, arg_Tcc_i_v7 *a) 231930376636SRichard Henderson { 232030376636SRichard Henderson if (avail_64(dc)) { 232130376636SRichard Henderson return false; 232230376636SRichard Henderson } 232330376636SRichard Henderson return do_tcc(dc, a->cond, 0, a->rs1, true, a->i); 232430376636SRichard Henderson } 232530376636SRichard Henderson 232630376636SRichard Henderson static bool trans_Tcc_i_v9(DisasContext *dc, arg_Tcc_i_v9 *a) 232730376636SRichard Henderson { 232830376636SRichard Henderson if (avail_32(dc)) { 232930376636SRichard Henderson return false; 233030376636SRichard Henderson } 233130376636SRichard Henderson return do_tcc(dc, a->cond, a->cc, a->rs1, true, a->i); 233230376636SRichard Henderson } 233330376636SRichard Henderson 2334af25071cSRichard Henderson static bool trans_STBAR(DisasContext *dc, arg_STBAR *a) 2335af25071cSRichard Henderson { 2336af25071cSRichard Henderson tcg_gen_mb(TCG_MO_ST_ST | TCG_BAR_SC); 2337af25071cSRichard Henderson return advance_pc(dc); 2338af25071cSRichard Henderson } 2339af25071cSRichard Henderson 2340af25071cSRichard Henderson static bool trans_MEMBAR(DisasContext *dc, arg_MEMBAR *a) 2341af25071cSRichard Henderson { 2342af25071cSRichard Henderson if (avail_32(dc)) { 2343af25071cSRichard Henderson return false; 2344af25071cSRichard Henderson } 2345af25071cSRichard Henderson if (a->mmask) { 2346af25071cSRichard Henderson /* Note TCG_MO_* was modeled on sparc64, so mmask matches. */ 2347af25071cSRichard Henderson tcg_gen_mb(a->mmask | TCG_BAR_SC); 2348af25071cSRichard Henderson } 2349af25071cSRichard Henderson if (a->cmask) { 2350af25071cSRichard Henderson /* For #Sync, etc, end the TB to recognize interrupts. */ 2351af25071cSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 2352af25071cSRichard Henderson } 2353af25071cSRichard Henderson return advance_pc(dc); 2354af25071cSRichard Henderson } 2355af25071cSRichard Henderson 2356af25071cSRichard Henderson static bool do_rd_special(DisasContext *dc, bool priv, int rd, 2357af25071cSRichard Henderson TCGv (*func)(DisasContext *, TCGv)) 2358af25071cSRichard Henderson { 2359af25071cSRichard Henderson if (!priv) { 2360af25071cSRichard Henderson return raise_priv(dc); 2361af25071cSRichard Henderson } 2362af25071cSRichard Henderson gen_store_gpr(dc, rd, func(dc, gen_dest_gpr(dc, rd))); 2363af25071cSRichard Henderson return advance_pc(dc); 2364af25071cSRichard Henderson } 2365af25071cSRichard Henderson 2366af25071cSRichard Henderson static TCGv do_rdy(DisasContext *dc, TCGv dst) 2367af25071cSRichard Henderson { 2368af25071cSRichard Henderson return cpu_y; 2369af25071cSRichard Henderson } 2370af25071cSRichard Henderson 2371af25071cSRichard Henderson static bool trans_RDY(DisasContext *dc, arg_RDY *a) 2372af25071cSRichard Henderson { 2373af25071cSRichard Henderson /* 2374af25071cSRichard Henderson * TODO: Need a feature bit for sparcv8. In the meantime, treat all 2375af25071cSRichard Henderson * 32-bit cpus like sparcv7, which ignores the rs1 field. 2376af25071cSRichard Henderson * This matches after all other ASR, so Leon3 Asr17 is handled first. 2377af25071cSRichard Henderson */ 2378af25071cSRichard Henderson if (avail_64(dc) && a->rs1 != 0) { 2379af25071cSRichard Henderson return false; 2380af25071cSRichard Henderson } 2381af25071cSRichard Henderson return do_rd_special(dc, true, a->rd, do_rdy); 2382af25071cSRichard Henderson } 2383af25071cSRichard Henderson 2384af25071cSRichard Henderson static TCGv do_rd_leon3_config(DisasContext *dc, TCGv dst) 2385af25071cSRichard Henderson { 2386*c92948f2SClément Chigot gen_helper_rdasr17(dst, tcg_env); 2387*c92948f2SClément Chigot return dst; 2388af25071cSRichard Henderson } 2389af25071cSRichard Henderson 2390af25071cSRichard Henderson TRANS(RDASR17, ASR17, do_rd_special, true, a->rd, do_rd_leon3_config) 2391af25071cSRichard Henderson 2392af25071cSRichard Henderson static TCGv do_rdccr(DisasContext *dc, TCGv dst) 2393af25071cSRichard Henderson { 2394af25071cSRichard Henderson gen_helper_rdccr(dst, tcg_env); 2395af25071cSRichard Henderson return dst; 2396af25071cSRichard Henderson } 2397af25071cSRichard Henderson 2398af25071cSRichard Henderson TRANS(RDCCR, 64, do_rd_special, true, a->rd, do_rdccr) 2399af25071cSRichard Henderson 2400af25071cSRichard Henderson static TCGv do_rdasi(DisasContext *dc, TCGv dst) 2401af25071cSRichard Henderson { 2402af25071cSRichard Henderson #ifdef TARGET_SPARC64 2403af25071cSRichard Henderson return tcg_constant_tl(dc->asi); 2404af25071cSRichard Henderson #else 2405af25071cSRichard Henderson qemu_build_not_reached(); 2406af25071cSRichard Henderson #endif 2407af25071cSRichard Henderson } 2408af25071cSRichard Henderson 2409af25071cSRichard Henderson TRANS(RDASI, 64, do_rd_special, true, a->rd, do_rdasi) 2410af25071cSRichard Henderson 2411af25071cSRichard Henderson static TCGv do_rdtick(DisasContext *dc, TCGv dst) 2412af25071cSRichard Henderson { 2413af25071cSRichard Henderson TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 2414af25071cSRichard Henderson 2415af25071cSRichard Henderson tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(tick)); 2416af25071cSRichard Henderson if (translator_io_start(&dc->base)) { 2417af25071cSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 2418af25071cSRichard Henderson } 2419af25071cSRichard Henderson gen_helper_tick_get_count(dst, tcg_env, r_tickptr, 2420af25071cSRichard Henderson tcg_constant_i32(dc->mem_idx)); 2421af25071cSRichard Henderson return dst; 2422af25071cSRichard Henderson } 2423af25071cSRichard Henderson 2424af25071cSRichard Henderson /* TODO: non-priv access only allowed when enabled. */ 2425af25071cSRichard Henderson TRANS(RDTICK, 64, do_rd_special, true, a->rd, do_rdtick) 2426af25071cSRichard Henderson 2427af25071cSRichard Henderson static TCGv do_rdpc(DisasContext *dc, TCGv dst) 2428af25071cSRichard Henderson { 2429af25071cSRichard Henderson return tcg_constant_tl(address_mask_i(dc, dc->pc)); 2430af25071cSRichard Henderson } 2431af25071cSRichard Henderson 2432af25071cSRichard Henderson TRANS(RDPC, 64, do_rd_special, true, a->rd, do_rdpc) 2433af25071cSRichard Henderson 2434af25071cSRichard Henderson static TCGv do_rdfprs(DisasContext *dc, TCGv dst) 2435af25071cSRichard Henderson { 2436af25071cSRichard Henderson tcg_gen_ext_i32_tl(dst, cpu_fprs); 2437af25071cSRichard Henderson return dst; 2438af25071cSRichard Henderson } 2439af25071cSRichard Henderson 2440af25071cSRichard Henderson TRANS(RDFPRS, 64, do_rd_special, true, a->rd, do_rdfprs) 2441af25071cSRichard Henderson 2442af25071cSRichard Henderson static TCGv do_rdgsr(DisasContext *dc, TCGv dst) 2443af25071cSRichard Henderson { 2444af25071cSRichard Henderson gen_trap_ifnofpu(dc); 2445af25071cSRichard Henderson return cpu_gsr; 2446af25071cSRichard Henderson } 2447af25071cSRichard Henderson 2448af25071cSRichard Henderson TRANS(RDGSR, 64, do_rd_special, true, a->rd, do_rdgsr) 2449af25071cSRichard Henderson 2450af25071cSRichard Henderson static TCGv do_rdsoftint(DisasContext *dc, TCGv dst) 2451af25071cSRichard Henderson { 2452af25071cSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(softint)); 2453af25071cSRichard Henderson return dst; 2454af25071cSRichard Henderson } 2455af25071cSRichard Henderson 2456af25071cSRichard Henderson TRANS(RDSOFTINT, 64, do_rd_special, supervisor(dc), a->rd, do_rdsoftint) 2457af25071cSRichard Henderson 2458af25071cSRichard Henderson static TCGv do_rdtick_cmpr(DisasContext *dc, TCGv dst) 2459af25071cSRichard Henderson { 2460577efa45SRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(tick_cmpr)); 2461577efa45SRichard Henderson return dst; 2462af25071cSRichard Henderson } 2463af25071cSRichard Henderson 2464af25071cSRichard Henderson /* TODO: non-priv access only allowed when enabled. */ 2465af25071cSRichard Henderson TRANS(RDTICK_CMPR, 64, do_rd_special, true, a->rd, do_rdtick_cmpr) 2466af25071cSRichard Henderson 2467af25071cSRichard Henderson static TCGv do_rdstick(DisasContext *dc, TCGv dst) 2468af25071cSRichard Henderson { 2469af25071cSRichard Henderson TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 2470af25071cSRichard Henderson 2471af25071cSRichard Henderson tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(stick)); 2472af25071cSRichard Henderson if (translator_io_start(&dc->base)) { 2473af25071cSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 2474af25071cSRichard Henderson } 2475af25071cSRichard Henderson gen_helper_tick_get_count(dst, tcg_env, r_tickptr, 2476af25071cSRichard Henderson tcg_constant_i32(dc->mem_idx)); 2477af25071cSRichard Henderson return dst; 2478af25071cSRichard Henderson } 2479af25071cSRichard Henderson 2480af25071cSRichard Henderson /* TODO: non-priv access only allowed when enabled. */ 2481af25071cSRichard Henderson TRANS(RDSTICK, 64, do_rd_special, true, a->rd, do_rdstick) 2482af25071cSRichard Henderson 2483af25071cSRichard Henderson static TCGv do_rdstick_cmpr(DisasContext *dc, TCGv dst) 2484af25071cSRichard Henderson { 2485577efa45SRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(stick_cmpr)); 2486577efa45SRichard Henderson return dst; 2487af25071cSRichard Henderson } 2488af25071cSRichard Henderson 2489af25071cSRichard Henderson /* TODO: supervisor access only allowed when enabled by hypervisor. */ 2490af25071cSRichard Henderson TRANS(RDSTICK_CMPR, 64, do_rd_special, supervisor(dc), a->rd, do_rdstick_cmpr) 2491af25071cSRichard Henderson 2492af25071cSRichard Henderson /* 2493af25071cSRichard Henderson * UltraSPARC-T1 Strand status. 2494af25071cSRichard Henderson * HYPV check maybe not enough, UA2005 & UA2007 describe 2495af25071cSRichard Henderson * this ASR as impl. dep 2496af25071cSRichard Henderson */ 2497af25071cSRichard Henderson static TCGv do_rdstrand_status(DisasContext *dc, TCGv dst) 2498af25071cSRichard Henderson { 2499af25071cSRichard Henderson return tcg_constant_tl(1); 2500af25071cSRichard Henderson } 2501af25071cSRichard Henderson 2502af25071cSRichard Henderson TRANS(RDSTRAND_STATUS, HYPV, do_rd_special, true, a->rd, do_rdstrand_status) 2503af25071cSRichard Henderson 2504668bb9b7SRichard Henderson static TCGv do_rdpsr(DisasContext *dc, TCGv dst) 2505668bb9b7SRichard Henderson { 2506668bb9b7SRichard Henderson gen_helper_rdpsr(dst, tcg_env); 2507668bb9b7SRichard Henderson return dst; 2508668bb9b7SRichard Henderson } 2509668bb9b7SRichard Henderson 2510668bb9b7SRichard Henderson TRANS(RDPSR, 32, do_rd_special, supervisor(dc), a->rd, do_rdpsr) 2511668bb9b7SRichard Henderson 2512668bb9b7SRichard Henderson static TCGv do_rdhpstate(DisasContext *dc, TCGv dst) 2513668bb9b7SRichard Henderson { 2514668bb9b7SRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hpstate)); 2515668bb9b7SRichard Henderson return dst; 2516668bb9b7SRichard Henderson } 2517668bb9b7SRichard Henderson 2518668bb9b7SRichard Henderson TRANS(RDHPR_hpstate, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhpstate) 2519668bb9b7SRichard Henderson 2520668bb9b7SRichard Henderson static TCGv do_rdhtstate(DisasContext *dc, TCGv dst) 2521668bb9b7SRichard Henderson { 2522668bb9b7SRichard Henderson TCGv_i32 tl = tcg_temp_new_i32(); 2523668bb9b7SRichard Henderson TCGv_ptr tp = tcg_temp_new_ptr(); 2524668bb9b7SRichard Henderson 2525668bb9b7SRichard Henderson tcg_gen_ld_i32(tl, tcg_env, env64_field_offsetof(tl)); 2526668bb9b7SRichard Henderson tcg_gen_andi_i32(tl, tl, MAXTL_MASK); 2527668bb9b7SRichard Henderson tcg_gen_shli_i32(tl, tl, 3); 2528668bb9b7SRichard Henderson tcg_gen_ext_i32_ptr(tp, tl); 2529668bb9b7SRichard Henderson tcg_gen_add_ptr(tp, tp, tcg_env); 2530668bb9b7SRichard Henderson 2531668bb9b7SRichard Henderson tcg_gen_ld_tl(dst, tp, env64_field_offsetof(htstate)); 2532668bb9b7SRichard Henderson return dst; 2533668bb9b7SRichard Henderson } 2534668bb9b7SRichard Henderson 2535668bb9b7SRichard Henderson TRANS(RDHPR_htstate, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhtstate) 2536668bb9b7SRichard Henderson 2537668bb9b7SRichard Henderson static TCGv do_rdhintp(DisasContext *dc, TCGv dst) 2538668bb9b7SRichard Henderson { 25392da789deSRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hintp)); 25402da789deSRichard Henderson return dst; 2541668bb9b7SRichard Henderson } 2542668bb9b7SRichard Henderson 2543668bb9b7SRichard Henderson TRANS(RDHPR_hintp, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhintp) 2544668bb9b7SRichard Henderson 2545668bb9b7SRichard Henderson static TCGv do_rdhtba(DisasContext *dc, TCGv dst) 2546668bb9b7SRichard Henderson { 25472da789deSRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(htba)); 25482da789deSRichard Henderson return dst; 2549668bb9b7SRichard Henderson } 2550668bb9b7SRichard Henderson 2551668bb9b7SRichard Henderson TRANS(RDHPR_htba, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhtba) 2552668bb9b7SRichard Henderson 2553668bb9b7SRichard Henderson static TCGv do_rdhver(DisasContext *dc, TCGv dst) 2554668bb9b7SRichard Henderson { 25552da789deSRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hver)); 25562da789deSRichard Henderson return dst; 2557668bb9b7SRichard Henderson } 2558668bb9b7SRichard Henderson 2559668bb9b7SRichard Henderson TRANS(RDHPR_hver, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhver) 2560668bb9b7SRichard Henderson 2561668bb9b7SRichard Henderson static TCGv do_rdhstick_cmpr(DisasContext *dc, TCGv dst) 2562668bb9b7SRichard Henderson { 2563577efa45SRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hstick_cmpr)); 2564577efa45SRichard Henderson return dst; 2565668bb9b7SRichard Henderson } 2566668bb9b7SRichard Henderson 2567668bb9b7SRichard Henderson TRANS(RDHPR_hstick_cmpr, HYPV, do_rd_special, hypervisor(dc), a->rd, 2568668bb9b7SRichard Henderson do_rdhstick_cmpr) 2569668bb9b7SRichard Henderson 25705d617bfbSRichard Henderson static TCGv do_rdwim(DisasContext *dc, TCGv dst) 25715d617bfbSRichard Henderson { 2572cd6269f7SRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env32_field_offsetof(wim)); 2573cd6269f7SRichard Henderson return dst; 25745d617bfbSRichard Henderson } 25755d617bfbSRichard Henderson 25765d617bfbSRichard Henderson TRANS(RDWIM, 32, do_rd_special, supervisor(dc), a->rd, do_rdwim) 25775d617bfbSRichard Henderson 25785d617bfbSRichard Henderson static TCGv do_rdtpc(DisasContext *dc, TCGv dst) 25795d617bfbSRichard Henderson { 25805d617bfbSRichard Henderson #ifdef TARGET_SPARC64 25815d617bfbSRichard Henderson TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 25825d617bfbSRichard Henderson 25835d617bfbSRichard Henderson gen_load_trap_state_at_tl(r_tsptr); 25845d617bfbSRichard Henderson tcg_gen_ld_tl(dst, r_tsptr, offsetof(trap_state, tpc)); 25855d617bfbSRichard Henderson return dst; 25865d617bfbSRichard Henderson #else 25875d617bfbSRichard Henderson qemu_build_not_reached(); 25885d617bfbSRichard Henderson #endif 25895d617bfbSRichard Henderson } 25905d617bfbSRichard Henderson 25915d617bfbSRichard Henderson TRANS(RDPR_tpc, 64, do_rd_special, supervisor(dc), a->rd, do_rdtpc) 25925d617bfbSRichard Henderson 25935d617bfbSRichard Henderson static TCGv do_rdtnpc(DisasContext *dc, TCGv dst) 25945d617bfbSRichard Henderson { 25955d617bfbSRichard Henderson #ifdef TARGET_SPARC64 25965d617bfbSRichard Henderson TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 25975d617bfbSRichard Henderson 25985d617bfbSRichard Henderson gen_load_trap_state_at_tl(r_tsptr); 25995d617bfbSRichard Henderson tcg_gen_ld_tl(dst, r_tsptr, offsetof(trap_state, tnpc)); 26005d617bfbSRichard Henderson return dst; 26015d617bfbSRichard Henderson #else 26025d617bfbSRichard Henderson qemu_build_not_reached(); 26035d617bfbSRichard Henderson #endif 26045d617bfbSRichard Henderson } 26055d617bfbSRichard Henderson 26065d617bfbSRichard Henderson TRANS(RDPR_tnpc, 64, do_rd_special, supervisor(dc), a->rd, do_rdtnpc) 26075d617bfbSRichard Henderson 26085d617bfbSRichard Henderson static TCGv do_rdtstate(DisasContext *dc, TCGv dst) 26095d617bfbSRichard Henderson { 26105d617bfbSRichard Henderson #ifdef TARGET_SPARC64 26115d617bfbSRichard Henderson TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 26125d617bfbSRichard Henderson 26135d617bfbSRichard Henderson gen_load_trap_state_at_tl(r_tsptr); 26145d617bfbSRichard Henderson tcg_gen_ld_tl(dst, r_tsptr, offsetof(trap_state, tstate)); 26155d617bfbSRichard Henderson return dst; 26165d617bfbSRichard Henderson #else 26175d617bfbSRichard Henderson qemu_build_not_reached(); 26185d617bfbSRichard Henderson #endif 26195d617bfbSRichard Henderson } 26205d617bfbSRichard Henderson 26215d617bfbSRichard Henderson TRANS(RDPR_tstate, 64, do_rd_special, supervisor(dc), a->rd, do_rdtstate) 26225d617bfbSRichard Henderson 26235d617bfbSRichard Henderson static TCGv do_rdtt(DisasContext *dc, TCGv dst) 26245d617bfbSRichard Henderson { 26255d617bfbSRichard Henderson #ifdef TARGET_SPARC64 26265d617bfbSRichard Henderson TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 26275d617bfbSRichard Henderson 26285d617bfbSRichard Henderson gen_load_trap_state_at_tl(r_tsptr); 26295d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, r_tsptr, offsetof(trap_state, tt)); 26305d617bfbSRichard Henderson return dst; 26315d617bfbSRichard Henderson #else 26325d617bfbSRichard Henderson qemu_build_not_reached(); 26335d617bfbSRichard Henderson #endif 26345d617bfbSRichard Henderson } 26355d617bfbSRichard Henderson 26365d617bfbSRichard Henderson TRANS(RDPR_tt, 64, do_rd_special, supervisor(dc), a->rd, do_rdtt) 26375d617bfbSRichard Henderson TRANS(RDPR_tick, 64, do_rd_special, supervisor(dc), a->rd, do_rdtick) 26385d617bfbSRichard Henderson 26395d617bfbSRichard Henderson static TCGv do_rdtba(DisasContext *dc, TCGv dst) 26405d617bfbSRichard Henderson { 26415d617bfbSRichard Henderson return cpu_tbr; 26425d617bfbSRichard Henderson } 26435d617bfbSRichard Henderson 2644e8325dc0SRichard Henderson TRANS(RDTBR, 32, do_rd_special, supervisor(dc), a->rd, do_rdtba) 26455d617bfbSRichard Henderson TRANS(RDPR_tba, 64, do_rd_special, supervisor(dc), a->rd, do_rdtba) 26465d617bfbSRichard Henderson 26475d617bfbSRichard Henderson static TCGv do_rdpstate(DisasContext *dc, TCGv dst) 26485d617bfbSRichard Henderson { 26495d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(pstate)); 26505d617bfbSRichard Henderson return dst; 26515d617bfbSRichard Henderson } 26525d617bfbSRichard Henderson 26535d617bfbSRichard Henderson TRANS(RDPR_pstate, 64, do_rd_special, supervisor(dc), a->rd, do_rdpstate) 26545d617bfbSRichard Henderson 26555d617bfbSRichard Henderson static TCGv do_rdtl(DisasContext *dc, TCGv dst) 26565d617bfbSRichard Henderson { 26575d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(tl)); 26585d617bfbSRichard Henderson return dst; 26595d617bfbSRichard Henderson } 26605d617bfbSRichard Henderson 26615d617bfbSRichard Henderson TRANS(RDPR_tl, 64, do_rd_special, supervisor(dc), a->rd, do_rdtl) 26625d617bfbSRichard Henderson 26635d617bfbSRichard Henderson static TCGv do_rdpil(DisasContext *dc, TCGv dst) 26645d617bfbSRichard Henderson { 26655d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env_field_offsetof(psrpil)); 26665d617bfbSRichard Henderson return dst; 26675d617bfbSRichard Henderson } 26685d617bfbSRichard Henderson 26695d617bfbSRichard Henderson TRANS(RDPR_pil, 64, do_rd_special, supervisor(dc), a->rd, do_rdpil) 26705d617bfbSRichard Henderson 26715d617bfbSRichard Henderson static TCGv do_rdcwp(DisasContext *dc, TCGv dst) 26725d617bfbSRichard Henderson { 26735d617bfbSRichard Henderson gen_helper_rdcwp(dst, tcg_env); 26745d617bfbSRichard Henderson return dst; 26755d617bfbSRichard Henderson } 26765d617bfbSRichard Henderson 26775d617bfbSRichard Henderson TRANS(RDPR_cwp, 64, do_rd_special, supervisor(dc), a->rd, do_rdcwp) 26785d617bfbSRichard Henderson 26795d617bfbSRichard Henderson static TCGv do_rdcansave(DisasContext *dc, TCGv dst) 26805d617bfbSRichard Henderson { 26815d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(cansave)); 26825d617bfbSRichard Henderson return dst; 26835d617bfbSRichard Henderson } 26845d617bfbSRichard Henderson 26855d617bfbSRichard Henderson TRANS(RDPR_cansave, 64, do_rd_special, supervisor(dc), a->rd, do_rdcansave) 26865d617bfbSRichard Henderson 26875d617bfbSRichard Henderson static TCGv do_rdcanrestore(DisasContext *dc, TCGv dst) 26885d617bfbSRichard Henderson { 26895d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(canrestore)); 26905d617bfbSRichard Henderson return dst; 26915d617bfbSRichard Henderson } 26925d617bfbSRichard Henderson 26935d617bfbSRichard Henderson TRANS(RDPR_canrestore, 64, do_rd_special, supervisor(dc), a->rd, 26945d617bfbSRichard Henderson do_rdcanrestore) 26955d617bfbSRichard Henderson 26965d617bfbSRichard Henderson static TCGv do_rdcleanwin(DisasContext *dc, TCGv dst) 26975d617bfbSRichard Henderson { 26985d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(cleanwin)); 26995d617bfbSRichard Henderson return dst; 27005d617bfbSRichard Henderson } 27015d617bfbSRichard Henderson 27025d617bfbSRichard Henderson TRANS(RDPR_cleanwin, 64, do_rd_special, supervisor(dc), a->rd, do_rdcleanwin) 27035d617bfbSRichard Henderson 27045d617bfbSRichard Henderson static TCGv do_rdotherwin(DisasContext *dc, TCGv dst) 27055d617bfbSRichard Henderson { 27065d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(otherwin)); 27075d617bfbSRichard Henderson return dst; 27085d617bfbSRichard Henderson } 27095d617bfbSRichard Henderson 27105d617bfbSRichard Henderson TRANS(RDPR_otherwin, 64, do_rd_special, supervisor(dc), a->rd, do_rdotherwin) 27115d617bfbSRichard Henderson 27125d617bfbSRichard Henderson static TCGv do_rdwstate(DisasContext *dc, TCGv dst) 27135d617bfbSRichard Henderson { 27145d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(wstate)); 27155d617bfbSRichard Henderson return dst; 27165d617bfbSRichard Henderson } 27175d617bfbSRichard Henderson 27185d617bfbSRichard Henderson TRANS(RDPR_wstate, 64, do_rd_special, supervisor(dc), a->rd, do_rdwstate) 27195d617bfbSRichard Henderson 27205d617bfbSRichard Henderson static TCGv do_rdgl(DisasContext *dc, TCGv dst) 27215d617bfbSRichard Henderson { 27225d617bfbSRichard Henderson tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(gl)); 27235d617bfbSRichard Henderson return dst; 27245d617bfbSRichard Henderson } 27255d617bfbSRichard Henderson 27265d617bfbSRichard Henderson TRANS(RDPR_gl, GL, do_rd_special, supervisor(dc), a->rd, do_rdgl) 27275d617bfbSRichard Henderson 27285d617bfbSRichard Henderson /* UA2005 strand status */ 27295d617bfbSRichard Henderson static TCGv do_rdssr(DisasContext *dc, TCGv dst) 27305d617bfbSRichard Henderson { 27312da789deSRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(ssr)); 27322da789deSRichard Henderson return dst; 27335d617bfbSRichard Henderson } 27345d617bfbSRichard Henderson 27355d617bfbSRichard Henderson TRANS(RDPR_strand_status, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdssr) 27365d617bfbSRichard Henderson 27375d617bfbSRichard Henderson static TCGv do_rdver(DisasContext *dc, TCGv dst) 27385d617bfbSRichard Henderson { 27392da789deSRichard Henderson tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(version)); 27402da789deSRichard Henderson return dst; 27415d617bfbSRichard Henderson } 27425d617bfbSRichard Henderson 27435d617bfbSRichard Henderson TRANS(RDPR_ver, 64, do_rd_special, supervisor(dc), a->rd, do_rdver) 27445d617bfbSRichard Henderson 2745e8325dc0SRichard Henderson static bool trans_FLUSHW(DisasContext *dc, arg_FLUSHW *a) 2746e8325dc0SRichard Henderson { 2747e8325dc0SRichard Henderson if (avail_64(dc)) { 2748e8325dc0SRichard Henderson gen_helper_flushw(tcg_env); 2749e8325dc0SRichard Henderson return advance_pc(dc); 2750e8325dc0SRichard Henderson } 2751e8325dc0SRichard Henderson return false; 2752e8325dc0SRichard Henderson } 2753e8325dc0SRichard Henderson 27540faef01bSRichard Henderson static bool do_wr_special(DisasContext *dc, arg_r_r_ri *a, bool priv, 27550faef01bSRichard Henderson void (*func)(DisasContext *, TCGv)) 27560faef01bSRichard Henderson { 27570faef01bSRichard Henderson TCGv src; 27580faef01bSRichard Henderson 27590faef01bSRichard Henderson /* For simplicity, we under-decoded the rs2 form. */ 27600faef01bSRichard Henderson if (!a->imm && (a->rs2_or_imm & ~0x1f)) { 27610faef01bSRichard Henderson return false; 27620faef01bSRichard Henderson } 27630faef01bSRichard Henderson if (!priv) { 27640faef01bSRichard Henderson return raise_priv(dc); 27650faef01bSRichard Henderson } 27660faef01bSRichard Henderson 27670faef01bSRichard Henderson if (a->rs1 == 0 && (a->imm || a->rs2_or_imm == 0)) { 27680faef01bSRichard Henderson src = tcg_constant_tl(a->rs2_or_imm); 27690faef01bSRichard Henderson } else { 27700faef01bSRichard Henderson TCGv src1 = gen_load_gpr(dc, a->rs1); 27710faef01bSRichard Henderson if (a->rs2_or_imm == 0) { 27720faef01bSRichard Henderson src = src1; 27730faef01bSRichard Henderson } else { 27740faef01bSRichard Henderson src = tcg_temp_new(); 27750faef01bSRichard Henderson if (a->imm) { 27760faef01bSRichard Henderson tcg_gen_xori_tl(src, src1, a->rs2_or_imm); 27770faef01bSRichard Henderson } else { 27780faef01bSRichard Henderson tcg_gen_xor_tl(src, src1, gen_load_gpr(dc, a->rs2_or_imm)); 27790faef01bSRichard Henderson } 27800faef01bSRichard Henderson } 27810faef01bSRichard Henderson } 27820faef01bSRichard Henderson func(dc, src); 27830faef01bSRichard Henderson return advance_pc(dc); 27840faef01bSRichard Henderson } 27850faef01bSRichard Henderson 27860faef01bSRichard Henderson static void do_wry(DisasContext *dc, TCGv src) 27870faef01bSRichard Henderson { 27880faef01bSRichard Henderson tcg_gen_ext32u_tl(cpu_y, src); 27890faef01bSRichard Henderson } 27900faef01bSRichard Henderson 27910faef01bSRichard Henderson TRANS(WRY, ALL, do_wr_special, a, true, do_wry) 27920faef01bSRichard Henderson 27930faef01bSRichard Henderson static void do_wrccr(DisasContext *dc, TCGv src) 27940faef01bSRichard Henderson { 27950faef01bSRichard Henderson gen_helper_wrccr(tcg_env, src); 27960faef01bSRichard Henderson } 27970faef01bSRichard Henderson 27980faef01bSRichard Henderson TRANS(WRCCR, 64, do_wr_special, a, true, do_wrccr) 27990faef01bSRichard Henderson 28000faef01bSRichard Henderson static void do_wrasi(DisasContext *dc, TCGv src) 28010faef01bSRichard Henderson { 28020faef01bSRichard Henderson TCGv tmp = tcg_temp_new(); 28030faef01bSRichard Henderson 28040faef01bSRichard Henderson tcg_gen_ext8u_tl(tmp, src); 28050faef01bSRichard Henderson tcg_gen_st32_tl(tmp, tcg_env, env64_field_offsetof(asi)); 28060faef01bSRichard Henderson /* End TB to notice changed ASI. */ 28070faef01bSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 28080faef01bSRichard Henderson } 28090faef01bSRichard Henderson 28100faef01bSRichard Henderson TRANS(WRASI, 64, do_wr_special, a, true, do_wrasi) 28110faef01bSRichard Henderson 28120faef01bSRichard Henderson static void do_wrfprs(DisasContext *dc, TCGv src) 28130faef01bSRichard Henderson { 28140faef01bSRichard Henderson #ifdef TARGET_SPARC64 28150faef01bSRichard Henderson tcg_gen_trunc_tl_i32(cpu_fprs, src); 28160faef01bSRichard Henderson dc->fprs_dirty = 0; 28170faef01bSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 28180faef01bSRichard Henderson #else 28190faef01bSRichard Henderson qemu_build_not_reached(); 28200faef01bSRichard Henderson #endif 28210faef01bSRichard Henderson } 28220faef01bSRichard Henderson 28230faef01bSRichard Henderson TRANS(WRFPRS, 64, do_wr_special, a, true, do_wrfprs) 28240faef01bSRichard Henderson 28250faef01bSRichard Henderson static void do_wrgsr(DisasContext *dc, TCGv src) 28260faef01bSRichard Henderson { 28270faef01bSRichard Henderson gen_trap_ifnofpu(dc); 28280faef01bSRichard Henderson tcg_gen_mov_tl(cpu_gsr, src); 28290faef01bSRichard Henderson } 28300faef01bSRichard Henderson 28310faef01bSRichard Henderson TRANS(WRGSR, 64, do_wr_special, a, true, do_wrgsr) 28320faef01bSRichard Henderson 28330faef01bSRichard Henderson static void do_wrsoftint_set(DisasContext *dc, TCGv src) 28340faef01bSRichard Henderson { 28350faef01bSRichard Henderson gen_helper_set_softint(tcg_env, src); 28360faef01bSRichard Henderson } 28370faef01bSRichard Henderson 28380faef01bSRichard Henderson TRANS(WRSOFTINT_SET, 64, do_wr_special, a, supervisor(dc), do_wrsoftint_set) 28390faef01bSRichard Henderson 28400faef01bSRichard Henderson static void do_wrsoftint_clr(DisasContext *dc, TCGv src) 28410faef01bSRichard Henderson { 28420faef01bSRichard Henderson gen_helper_clear_softint(tcg_env, src); 28430faef01bSRichard Henderson } 28440faef01bSRichard Henderson 28450faef01bSRichard Henderson TRANS(WRSOFTINT_CLR, 64, do_wr_special, a, supervisor(dc), do_wrsoftint_clr) 28460faef01bSRichard Henderson 28470faef01bSRichard Henderson static void do_wrsoftint(DisasContext *dc, TCGv src) 28480faef01bSRichard Henderson { 28490faef01bSRichard Henderson gen_helper_write_softint(tcg_env, src); 28500faef01bSRichard Henderson } 28510faef01bSRichard Henderson 28520faef01bSRichard Henderson TRANS(WRSOFTINT, 64, do_wr_special, a, supervisor(dc), do_wrsoftint) 28530faef01bSRichard Henderson 28540faef01bSRichard Henderson static void do_wrtick_cmpr(DisasContext *dc, TCGv src) 28550faef01bSRichard Henderson { 28560faef01bSRichard Henderson TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 28570faef01bSRichard Henderson 2858577efa45SRichard Henderson tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(tick_cmpr)); 2859577efa45SRichard Henderson tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(tick)); 28600faef01bSRichard Henderson translator_io_start(&dc->base); 2861577efa45SRichard Henderson gen_helper_tick_set_limit(r_tickptr, src); 28620faef01bSRichard Henderson /* End TB to handle timer interrupt */ 28630faef01bSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 28640faef01bSRichard Henderson } 28650faef01bSRichard Henderson 28660faef01bSRichard Henderson TRANS(WRTICK_CMPR, 64, do_wr_special, a, supervisor(dc), do_wrtick_cmpr) 28670faef01bSRichard Henderson 28680faef01bSRichard Henderson static void do_wrstick(DisasContext *dc, TCGv src) 28690faef01bSRichard Henderson { 28700faef01bSRichard Henderson #ifdef TARGET_SPARC64 28710faef01bSRichard Henderson TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 28720faef01bSRichard Henderson 28730faef01bSRichard Henderson tcg_gen_ld_ptr(r_tickptr, tcg_env, offsetof(CPUSPARCState, stick)); 28740faef01bSRichard Henderson translator_io_start(&dc->base); 28750faef01bSRichard Henderson gen_helper_tick_set_count(r_tickptr, src); 28760faef01bSRichard Henderson /* End TB to handle timer interrupt */ 28770faef01bSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 28780faef01bSRichard Henderson #else 28790faef01bSRichard Henderson qemu_build_not_reached(); 28800faef01bSRichard Henderson #endif 28810faef01bSRichard Henderson } 28820faef01bSRichard Henderson 28830faef01bSRichard Henderson TRANS(WRSTICK, 64, do_wr_special, a, supervisor(dc), do_wrstick) 28840faef01bSRichard Henderson 28850faef01bSRichard Henderson static void do_wrstick_cmpr(DisasContext *dc, TCGv src) 28860faef01bSRichard Henderson { 28870faef01bSRichard Henderson TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 28880faef01bSRichard Henderson 2889577efa45SRichard Henderson tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(stick_cmpr)); 2890577efa45SRichard Henderson tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(stick)); 28910faef01bSRichard Henderson translator_io_start(&dc->base); 2892577efa45SRichard Henderson gen_helper_tick_set_limit(r_tickptr, src); 28930faef01bSRichard Henderson /* End TB to handle timer interrupt */ 28940faef01bSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 28950faef01bSRichard Henderson } 28960faef01bSRichard Henderson 28970faef01bSRichard Henderson TRANS(WRSTICK_CMPR, 64, do_wr_special, a, supervisor(dc), do_wrstick_cmpr) 28980faef01bSRichard Henderson 28990faef01bSRichard Henderson static void do_wrpowerdown(DisasContext *dc, TCGv src) 29000faef01bSRichard Henderson { 290189527e3aSRichard Henderson finishing_insn(dc); 29020faef01bSRichard Henderson save_state(dc); 29030faef01bSRichard Henderson gen_helper_power_down(tcg_env); 29040faef01bSRichard Henderson } 29050faef01bSRichard Henderson 29060faef01bSRichard Henderson TRANS(WRPOWERDOWN, POWERDOWN, do_wr_special, a, supervisor(dc), do_wrpowerdown) 29070faef01bSRichard Henderson 290825524734SRichard Henderson static void do_wrpsr(DisasContext *dc, TCGv src) 290925524734SRichard Henderson { 291025524734SRichard Henderson gen_helper_wrpsr(tcg_env, src); 291125524734SRichard Henderson dc->base.is_jmp = DISAS_EXIT; 291225524734SRichard Henderson } 291325524734SRichard Henderson 291425524734SRichard Henderson TRANS(WRPSR, 32, do_wr_special, a, supervisor(dc), do_wrpsr) 291525524734SRichard Henderson 29169422278eSRichard Henderson static void do_wrwim(DisasContext *dc, TCGv src) 29179422278eSRichard Henderson { 29189422278eSRichard Henderson target_ulong mask = MAKE_64BIT_MASK(0, dc->def->nwindows); 2919cd6269f7SRichard Henderson TCGv tmp = tcg_temp_new(); 2920cd6269f7SRichard Henderson 2921cd6269f7SRichard Henderson tcg_gen_andi_tl(tmp, src, mask); 2922cd6269f7SRichard Henderson tcg_gen_st_tl(tmp, tcg_env, env32_field_offsetof(wim)); 29239422278eSRichard Henderson } 29249422278eSRichard Henderson 29259422278eSRichard Henderson TRANS(WRWIM, 32, do_wr_special, a, supervisor(dc), do_wrwim) 29269422278eSRichard Henderson 29279422278eSRichard Henderson static void do_wrtpc(DisasContext *dc, TCGv src) 29289422278eSRichard Henderson { 29299422278eSRichard Henderson #ifdef TARGET_SPARC64 29309422278eSRichard Henderson TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 29319422278eSRichard Henderson 29329422278eSRichard Henderson gen_load_trap_state_at_tl(r_tsptr); 29339422278eSRichard Henderson tcg_gen_st_tl(src, r_tsptr, offsetof(trap_state, tpc)); 29349422278eSRichard Henderson #else 29359422278eSRichard Henderson qemu_build_not_reached(); 29369422278eSRichard Henderson #endif 29379422278eSRichard Henderson } 29389422278eSRichard Henderson 29399422278eSRichard Henderson TRANS(WRPR_tpc, 64, do_wr_special, a, supervisor(dc), do_wrtpc) 29409422278eSRichard Henderson 29419422278eSRichard Henderson static void do_wrtnpc(DisasContext *dc, TCGv src) 29429422278eSRichard Henderson { 29439422278eSRichard Henderson #ifdef TARGET_SPARC64 29449422278eSRichard Henderson TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 29459422278eSRichard Henderson 29469422278eSRichard Henderson gen_load_trap_state_at_tl(r_tsptr); 29479422278eSRichard Henderson tcg_gen_st_tl(src, r_tsptr, offsetof(trap_state, tnpc)); 29489422278eSRichard Henderson #else 29499422278eSRichard Henderson qemu_build_not_reached(); 29509422278eSRichard Henderson #endif 29519422278eSRichard Henderson } 29529422278eSRichard Henderson 29539422278eSRichard Henderson TRANS(WRPR_tnpc, 64, do_wr_special, a, supervisor(dc), do_wrtnpc) 29549422278eSRichard Henderson 29559422278eSRichard Henderson static void do_wrtstate(DisasContext *dc, TCGv src) 29569422278eSRichard Henderson { 29579422278eSRichard Henderson #ifdef TARGET_SPARC64 29589422278eSRichard Henderson TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 29599422278eSRichard Henderson 29609422278eSRichard Henderson gen_load_trap_state_at_tl(r_tsptr); 29619422278eSRichard Henderson tcg_gen_st_tl(src, r_tsptr, offsetof(trap_state, tstate)); 29629422278eSRichard Henderson #else 29639422278eSRichard Henderson qemu_build_not_reached(); 29649422278eSRichard Henderson #endif 29659422278eSRichard Henderson } 29669422278eSRichard Henderson 29679422278eSRichard Henderson TRANS(WRPR_tstate, 64, do_wr_special, a, supervisor(dc), do_wrtstate) 29689422278eSRichard Henderson 29699422278eSRichard Henderson static void do_wrtt(DisasContext *dc, TCGv src) 29709422278eSRichard Henderson { 29719422278eSRichard Henderson #ifdef TARGET_SPARC64 29729422278eSRichard Henderson TCGv_ptr r_tsptr = tcg_temp_new_ptr(); 29739422278eSRichard Henderson 29749422278eSRichard Henderson gen_load_trap_state_at_tl(r_tsptr); 29759422278eSRichard Henderson tcg_gen_st32_tl(src, r_tsptr, offsetof(trap_state, tt)); 29769422278eSRichard Henderson #else 29779422278eSRichard Henderson qemu_build_not_reached(); 29789422278eSRichard Henderson #endif 29799422278eSRichard Henderson } 29809422278eSRichard Henderson 29819422278eSRichard Henderson TRANS(WRPR_tt, 64, do_wr_special, a, supervisor(dc), do_wrtt) 29829422278eSRichard Henderson 29839422278eSRichard Henderson static void do_wrtick(DisasContext *dc, TCGv src) 29849422278eSRichard Henderson { 29859422278eSRichard Henderson TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 29869422278eSRichard Henderson 29879422278eSRichard Henderson tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(tick)); 29889422278eSRichard Henderson translator_io_start(&dc->base); 29899422278eSRichard Henderson gen_helper_tick_set_count(r_tickptr, src); 29909422278eSRichard Henderson /* End TB to handle timer interrupt */ 29919422278eSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 29929422278eSRichard Henderson } 29939422278eSRichard Henderson 29949422278eSRichard Henderson TRANS(WRPR_tick, 64, do_wr_special, a, supervisor(dc), do_wrtick) 29959422278eSRichard Henderson 29969422278eSRichard Henderson static void do_wrtba(DisasContext *dc, TCGv src) 29979422278eSRichard Henderson { 29989422278eSRichard Henderson tcg_gen_mov_tl(cpu_tbr, src); 29999422278eSRichard Henderson } 30009422278eSRichard Henderson 30019422278eSRichard Henderson TRANS(WRPR_tba, 64, do_wr_special, a, supervisor(dc), do_wrtba) 30029422278eSRichard Henderson 30039422278eSRichard Henderson static void do_wrpstate(DisasContext *dc, TCGv src) 30049422278eSRichard Henderson { 30059422278eSRichard Henderson save_state(dc); 30069422278eSRichard Henderson if (translator_io_start(&dc->base)) { 30079422278eSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 30089422278eSRichard Henderson } 30099422278eSRichard Henderson gen_helper_wrpstate(tcg_env, src); 30109422278eSRichard Henderson dc->npc = DYNAMIC_PC; 30119422278eSRichard Henderson } 30129422278eSRichard Henderson 30139422278eSRichard Henderson TRANS(WRPR_pstate, 64, do_wr_special, a, supervisor(dc), do_wrpstate) 30149422278eSRichard Henderson 30159422278eSRichard Henderson static void do_wrtl(DisasContext *dc, TCGv src) 30169422278eSRichard Henderson { 30179422278eSRichard Henderson save_state(dc); 30189422278eSRichard Henderson tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(tl)); 30199422278eSRichard Henderson dc->npc = DYNAMIC_PC; 30209422278eSRichard Henderson } 30219422278eSRichard Henderson 30229422278eSRichard Henderson TRANS(WRPR_tl, 64, do_wr_special, a, supervisor(dc), do_wrtl) 30239422278eSRichard Henderson 30249422278eSRichard Henderson static void do_wrpil(DisasContext *dc, TCGv src) 30259422278eSRichard Henderson { 30269422278eSRichard Henderson if (translator_io_start(&dc->base)) { 30279422278eSRichard Henderson dc->base.is_jmp = DISAS_EXIT; 30289422278eSRichard Henderson } 30299422278eSRichard Henderson gen_helper_wrpil(tcg_env, src); 30309422278eSRichard Henderson } 30319422278eSRichard Henderson 30329422278eSRichard Henderson TRANS(WRPR_pil, 64, do_wr_special, a, supervisor(dc), do_wrpil) 30339422278eSRichard Henderson 30349422278eSRichard Henderson static void do_wrcwp(DisasContext *dc, TCGv src) 30359422278eSRichard Henderson { 30369422278eSRichard Henderson gen_helper_wrcwp(tcg_env, src); 30379422278eSRichard Henderson } 30389422278eSRichard Henderson 30399422278eSRichard Henderson TRANS(WRPR_cwp, 64, do_wr_special, a, supervisor(dc), do_wrcwp) 30409422278eSRichard Henderson 30419422278eSRichard Henderson static void do_wrcansave(DisasContext *dc, TCGv src) 30429422278eSRichard Henderson { 30439422278eSRichard Henderson tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(cansave)); 30449422278eSRichard Henderson } 30459422278eSRichard Henderson 30469422278eSRichard Henderson TRANS(WRPR_cansave, 64, do_wr_special, a, supervisor(dc), do_wrcansave) 30479422278eSRichard Henderson 30489422278eSRichard Henderson static void do_wrcanrestore(DisasContext *dc, TCGv src) 30499422278eSRichard Henderson { 30509422278eSRichard Henderson tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(canrestore)); 30519422278eSRichard Henderson } 30529422278eSRichard Henderson 30539422278eSRichard Henderson TRANS(WRPR_canrestore, 64, do_wr_special, a, supervisor(dc), do_wrcanrestore) 30549422278eSRichard Henderson 30559422278eSRichard Henderson static void do_wrcleanwin(DisasContext *dc, TCGv src) 30569422278eSRichard Henderson { 30579422278eSRichard Henderson tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(cleanwin)); 30589422278eSRichard Henderson } 30599422278eSRichard Henderson 30609422278eSRichard Henderson TRANS(WRPR_cleanwin, 64, do_wr_special, a, supervisor(dc), do_wrcleanwin) 30619422278eSRichard Henderson 30629422278eSRichard Henderson static void do_wrotherwin(DisasContext *dc, TCGv src) 30639422278eSRichard Henderson { 30649422278eSRichard Henderson tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(otherwin)); 30659422278eSRichard Henderson } 30669422278eSRichard Henderson 30679422278eSRichard Henderson TRANS(WRPR_otherwin, 64, do_wr_special, a, supervisor(dc), do_wrotherwin) 30689422278eSRichard Henderson 30699422278eSRichard Henderson static void do_wrwstate(DisasContext *dc, TCGv src) 30709422278eSRichard Henderson { 30719422278eSRichard Henderson tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(wstate)); 30729422278eSRichard Henderson } 30739422278eSRichard Henderson 30749422278eSRichard Henderson TRANS(WRPR_wstate, 64, do_wr_special, a, supervisor(dc), do_wrwstate) 30759422278eSRichard Henderson 30769422278eSRichard Henderson static void do_wrgl(DisasContext *dc, TCGv src) 30779422278eSRichard Henderson { 30789422278eSRichard Henderson gen_helper_wrgl(tcg_env, src); 30799422278eSRichard Henderson } 30809422278eSRichard Henderson 30819422278eSRichard Henderson TRANS(WRPR_gl, GL, do_wr_special, a, supervisor(dc), do_wrgl) 30829422278eSRichard Henderson 30839422278eSRichard Henderson /* UA2005 strand status */ 30849422278eSRichard Henderson static void do_wrssr(DisasContext *dc, TCGv src) 30859422278eSRichard Henderson { 30862da789deSRichard Henderson tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(ssr)); 30879422278eSRichard Henderson } 30889422278eSRichard Henderson 30899422278eSRichard Henderson TRANS(WRPR_strand_status, HYPV, do_wr_special, a, hypervisor(dc), do_wrssr) 30909422278eSRichard Henderson 3091bb97f2f5SRichard Henderson TRANS(WRTBR, 32, do_wr_special, a, supervisor(dc), do_wrtba) 3092bb97f2f5SRichard Henderson 3093bb97f2f5SRichard Henderson static void do_wrhpstate(DisasContext *dc, TCGv src) 3094bb97f2f5SRichard Henderson { 3095bb97f2f5SRichard Henderson tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(hpstate)); 3096bb97f2f5SRichard Henderson dc->base.is_jmp = DISAS_EXIT; 3097bb97f2f5SRichard Henderson } 3098bb97f2f5SRichard Henderson 3099bb97f2f5SRichard Henderson TRANS(WRHPR_hpstate, HYPV, do_wr_special, a, hypervisor(dc), do_wrhpstate) 3100bb97f2f5SRichard Henderson 3101bb97f2f5SRichard Henderson static void do_wrhtstate(DisasContext *dc, TCGv src) 3102bb97f2f5SRichard Henderson { 3103bb97f2f5SRichard Henderson TCGv_i32 tl = tcg_temp_new_i32(); 3104bb97f2f5SRichard Henderson TCGv_ptr tp = tcg_temp_new_ptr(); 3105bb97f2f5SRichard Henderson 3106bb97f2f5SRichard Henderson tcg_gen_ld_i32(tl, tcg_env, env64_field_offsetof(tl)); 3107bb97f2f5SRichard Henderson tcg_gen_andi_i32(tl, tl, MAXTL_MASK); 3108bb97f2f5SRichard Henderson tcg_gen_shli_i32(tl, tl, 3); 3109bb97f2f5SRichard Henderson tcg_gen_ext_i32_ptr(tp, tl); 3110bb97f2f5SRichard Henderson tcg_gen_add_ptr(tp, tp, tcg_env); 3111bb97f2f5SRichard Henderson 3112bb97f2f5SRichard Henderson tcg_gen_st_tl(src, tp, env64_field_offsetof(htstate)); 3113bb97f2f5SRichard Henderson } 3114bb97f2f5SRichard Henderson 3115bb97f2f5SRichard Henderson TRANS(WRHPR_htstate, HYPV, do_wr_special, a, hypervisor(dc), do_wrhtstate) 3116bb97f2f5SRichard Henderson 3117bb97f2f5SRichard Henderson static void do_wrhintp(DisasContext *dc, TCGv src) 3118bb97f2f5SRichard Henderson { 31192da789deSRichard Henderson tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(hintp)); 3120bb97f2f5SRichard Henderson } 3121bb97f2f5SRichard Henderson 3122bb97f2f5SRichard Henderson TRANS(WRHPR_hintp, HYPV, do_wr_special, a, hypervisor(dc), do_wrhintp) 3123bb97f2f5SRichard Henderson 3124bb97f2f5SRichard Henderson static void do_wrhtba(DisasContext *dc, TCGv src) 3125bb97f2f5SRichard Henderson { 31262da789deSRichard Henderson tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(htba)); 3127bb97f2f5SRichard Henderson } 3128bb97f2f5SRichard Henderson 3129bb97f2f5SRichard Henderson TRANS(WRHPR_htba, HYPV, do_wr_special, a, hypervisor(dc), do_wrhtba) 3130bb97f2f5SRichard Henderson 3131bb97f2f5SRichard Henderson static void do_wrhstick_cmpr(DisasContext *dc, TCGv src) 3132bb97f2f5SRichard Henderson { 3133bb97f2f5SRichard Henderson TCGv_ptr r_tickptr = tcg_temp_new_ptr(); 3134bb97f2f5SRichard Henderson 3135577efa45SRichard Henderson tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(hstick_cmpr)); 3136bb97f2f5SRichard Henderson tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(hstick)); 3137bb97f2f5SRichard Henderson translator_io_start(&dc->base); 3138577efa45SRichard Henderson gen_helper_tick_set_limit(r_tickptr, src); 3139bb97f2f5SRichard Henderson /* End TB to handle timer interrupt */ 3140bb97f2f5SRichard Henderson dc->base.is_jmp = DISAS_EXIT; 3141bb97f2f5SRichard Henderson } 3142bb97f2f5SRichard Henderson 3143bb97f2f5SRichard Henderson TRANS(WRHPR_hstick_cmpr, HYPV, do_wr_special, a, hypervisor(dc), 3144bb97f2f5SRichard Henderson do_wrhstick_cmpr) 3145bb97f2f5SRichard Henderson 314625524734SRichard Henderson static bool do_saved_restored(DisasContext *dc, bool saved) 314725524734SRichard Henderson { 314825524734SRichard Henderson if (!supervisor(dc)) { 314925524734SRichard Henderson return raise_priv(dc); 315025524734SRichard Henderson } 315125524734SRichard Henderson if (saved) { 315225524734SRichard Henderson gen_helper_saved(tcg_env); 315325524734SRichard Henderson } else { 315425524734SRichard Henderson gen_helper_restored(tcg_env); 315525524734SRichard Henderson } 315625524734SRichard Henderson return advance_pc(dc); 315725524734SRichard Henderson } 315825524734SRichard Henderson 315925524734SRichard Henderson TRANS(SAVED, 64, do_saved_restored, true) 316025524734SRichard Henderson TRANS(RESTORED, 64, do_saved_restored, false) 316125524734SRichard Henderson 3162d3825800SRichard Henderson static bool trans_NOP(DisasContext *dc, arg_NOP *a) 3163d3825800SRichard Henderson { 3164d3825800SRichard Henderson return advance_pc(dc); 3165d3825800SRichard Henderson } 3166d3825800SRichard Henderson 31670faef01bSRichard Henderson /* 31680faef01bSRichard Henderson * TODO: Need a feature bit for sparcv8. 31690faef01bSRichard Henderson * In the meantime, treat all 32-bit cpus like sparcv7. 31700faef01bSRichard Henderson */ 31715458fd31SRichard Henderson TRANS(NOP_v7, 32, trans_NOP, a) 31725458fd31SRichard Henderson TRANS(NOP_v9, 64, trans_NOP, a) 31730faef01bSRichard Henderson 3174b597eedcSRichard Henderson static bool do_arith_int(DisasContext *dc, arg_r_r_ri_cc *a, 3175428881deSRichard Henderson void (*func)(TCGv, TCGv, TCGv), 31762a45b736SRichard Henderson void (*funci)(TCGv, TCGv, target_long), 31772a45b736SRichard Henderson bool logic_cc) 3178428881deSRichard Henderson { 3179428881deSRichard Henderson TCGv dst, src1; 3180428881deSRichard Henderson 3181428881deSRichard Henderson /* For simplicity, we under-decoded the rs2 form. */ 3182428881deSRichard Henderson if (!a->imm && a->rs2_or_imm & ~0x1f) { 3183428881deSRichard Henderson return false; 3184428881deSRichard Henderson } 3185428881deSRichard Henderson 31862a45b736SRichard Henderson if (logic_cc) { 31872a45b736SRichard Henderson dst = cpu_cc_N; 3188428881deSRichard Henderson } else { 3189428881deSRichard Henderson dst = gen_dest_gpr(dc, a->rd); 3190428881deSRichard Henderson } 3191428881deSRichard Henderson src1 = gen_load_gpr(dc, a->rs1); 3192428881deSRichard Henderson 3193428881deSRichard Henderson if (a->imm || a->rs2_or_imm == 0) { 3194428881deSRichard Henderson if (funci) { 3195428881deSRichard Henderson funci(dst, src1, a->rs2_or_imm); 3196428881deSRichard Henderson } else { 3197428881deSRichard Henderson func(dst, src1, tcg_constant_tl(a->rs2_or_imm)); 3198428881deSRichard Henderson } 3199428881deSRichard Henderson } else { 3200428881deSRichard Henderson func(dst, src1, cpu_regs[a->rs2_or_imm]); 3201428881deSRichard Henderson } 32022a45b736SRichard Henderson 32032a45b736SRichard Henderson if (logic_cc) { 32042a45b736SRichard Henderson if (TARGET_LONG_BITS == 64) { 32052a45b736SRichard Henderson tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N); 32062a45b736SRichard Henderson tcg_gen_movi_tl(cpu_icc_C, 0); 32072a45b736SRichard Henderson } 32082a45b736SRichard Henderson tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N); 32092a45b736SRichard Henderson tcg_gen_movi_tl(cpu_cc_C, 0); 32102a45b736SRichard Henderson tcg_gen_movi_tl(cpu_cc_V, 0); 32112a45b736SRichard Henderson } 32122a45b736SRichard Henderson 3213428881deSRichard Henderson gen_store_gpr(dc, a->rd, dst); 3214428881deSRichard Henderson return advance_pc(dc); 3215428881deSRichard Henderson } 3216428881deSRichard Henderson 3217b597eedcSRichard Henderson static bool do_arith(DisasContext *dc, arg_r_r_ri_cc *a, 3218428881deSRichard Henderson void (*func)(TCGv, TCGv, TCGv), 3219428881deSRichard Henderson void (*funci)(TCGv, TCGv, target_long), 3220428881deSRichard Henderson void (*func_cc)(TCGv, TCGv, TCGv)) 3221428881deSRichard Henderson { 3222428881deSRichard Henderson if (a->cc) { 3223b597eedcSRichard Henderson return do_arith_int(dc, a, func_cc, NULL, false); 3224428881deSRichard Henderson } 3225b597eedcSRichard Henderson return do_arith_int(dc, a, func, funci, false); 3226428881deSRichard Henderson } 3227428881deSRichard Henderson 3228428881deSRichard Henderson static bool do_logic(DisasContext *dc, arg_r_r_ri_cc *a, 3229428881deSRichard Henderson void (*func)(TCGv, TCGv, TCGv), 3230428881deSRichard Henderson void (*funci)(TCGv, TCGv, target_long)) 3231428881deSRichard Henderson { 3232b597eedcSRichard Henderson return do_arith_int(dc, a, func, funci, a->cc); 3233428881deSRichard Henderson } 3234428881deSRichard Henderson 3235b597eedcSRichard Henderson TRANS(ADD, ALL, do_arith, a, tcg_gen_add_tl, tcg_gen_addi_tl, gen_op_addcc) 3236b597eedcSRichard Henderson TRANS(SUB, ALL, do_arith, a, tcg_gen_sub_tl, tcg_gen_subi_tl, gen_op_subcc) 3237b597eedcSRichard Henderson TRANS(ADDC, ALL, do_arith, a, gen_op_addc, NULL, gen_op_addccc) 3238b597eedcSRichard Henderson TRANS(SUBC, ALL, do_arith, a, gen_op_subc, NULL, gen_op_subccc) 3239428881deSRichard Henderson 3240b597eedcSRichard Henderson TRANS(TADDcc, ALL, do_arith, a, NULL, NULL, gen_op_taddcc) 3241b597eedcSRichard Henderson TRANS(TSUBcc, ALL, do_arith, a, NULL, NULL, gen_op_tsubcc) 3242b597eedcSRichard Henderson TRANS(TADDccTV, ALL, do_arith, a, NULL, NULL, gen_op_taddcctv) 3243b597eedcSRichard Henderson TRANS(TSUBccTV, ALL, do_arith, a, NULL, NULL, gen_op_tsubcctv) 3244a9aba13dSRichard Henderson 3245428881deSRichard Henderson TRANS(AND, ALL, do_logic, a, tcg_gen_and_tl, tcg_gen_andi_tl) 3246428881deSRichard Henderson TRANS(XOR, ALL, do_logic, a, tcg_gen_xor_tl, tcg_gen_xori_tl) 3247428881deSRichard Henderson TRANS(ANDN, ALL, do_logic, a, tcg_gen_andc_tl, NULL) 3248428881deSRichard Henderson TRANS(ORN, ALL, do_logic, a, tcg_gen_orc_tl, NULL) 3249428881deSRichard Henderson TRANS(XORN, ALL, do_logic, a, tcg_gen_eqv_tl, NULL) 3250428881deSRichard Henderson 3251b597eedcSRichard Henderson TRANS(MULX, 64, do_arith, a, tcg_gen_mul_tl, tcg_gen_muli_tl, NULL) 3252b5372650SRichard Henderson TRANS(UMUL, MUL, do_logic, a, gen_op_umul, NULL) 3253b5372650SRichard Henderson TRANS(SMUL, MUL, do_logic, a, gen_op_smul, NULL) 3254b597eedcSRichard Henderson TRANS(MULScc, ALL, do_arith, a, NULL, NULL, gen_op_mulscc) 325522188d7dSRichard Henderson 32563a6b8de3SRichard Henderson TRANS(UDIVcc, DIV, do_arith, a, NULL, NULL, gen_op_udivcc) 3257b597eedcSRichard Henderson TRANS(SDIV, DIV, do_arith, a, gen_op_sdiv, NULL, gen_op_sdivcc) 32584ee85ea9SRichard Henderson 32599c6ec5bcSRichard Henderson /* TODO: Should have feature bit -- comes in with UltraSparc T2. */ 3260b597eedcSRichard Henderson TRANS(POPC, 64, do_arith, a, gen_op_popc, NULL, NULL) 32619c6ec5bcSRichard Henderson 3262428881deSRichard Henderson static bool trans_OR(DisasContext *dc, arg_r_r_ri_cc *a) 3263428881deSRichard Henderson { 3264428881deSRichard Henderson /* OR with %g0 is the canonical alias for MOV. */ 3265428881deSRichard Henderson if (!a->cc && a->rs1 == 0) { 3266428881deSRichard Henderson if (a->imm || a->rs2_or_imm == 0) { 3267428881deSRichard Henderson gen_store_gpr(dc, a->rd, tcg_constant_tl(a->rs2_or_imm)); 3268428881deSRichard Henderson } else if (a->rs2_or_imm & ~0x1f) { 3269428881deSRichard Henderson /* For simplicity, we under-decoded the rs2 form. */ 3270428881deSRichard Henderson return false; 3271428881deSRichard Henderson } else { 3272428881deSRichard Henderson gen_store_gpr(dc, a->rd, cpu_regs[a->rs2_or_imm]); 3273428881deSRichard Henderson } 3274428881deSRichard Henderson return advance_pc(dc); 3275428881deSRichard Henderson } 3276428881deSRichard Henderson return do_logic(dc, a, tcg_gen_or_tl, tcg_gen_ori_tl); 3277428881deSRichard Henderson } 3278428881deSRichard Henderson 32793a6b8de3SRichard Henderson static bool trans_UDIV(DisasContext *dc, arg_r_r_ri *a) 32803a6b8de3SRichard Henderson { 32813a6b8de3SRichard Henderson TCGv_i64 t1, t2; 32823a6b8de3SRichard Henderson TCGv dst; 32833a6b8de3SRichard Henderson 32843a6b8de3SRichard Henderson if (!avail_DIV(dc)) { 32853a6b8de3SRichard Henderson return false; 32863a6b8de3SRichard Henderson } 32873a6b8de3SRichard Henderson /* For simplicity, we under-decoded the rs2 form. */ 32883a6b8de3SRichard Henderson if (!a->imm && a->rs2_or_imm & ~0x1f) { 32893a6b8de3SRichard Henderson return false; 32903a6b8de3SRichard Henderson } 32913a6b8de3SRichard Henderson 32923a6b8de3SRichard Henderson if (unlikely(a->rs2_or_imm == 0)) { 32933a6b8de3SRichard Henderson gen_exception(dc, TT_DIV_ZERO); 32943a6b8de3SRichard Henderson return true; 32953a6b8de3SRichard Henderson } 32963a6b8de3SRichard Henderson 32973a6b8de3SRichard Henderson if (a->imm) { 32983a6b8de3SRichard Henderson t2 = tcg_constant_i64((uint32_t)a->rs2_or_imm); 32993a6b8de3SRichard Henderson } else { 33003a6b8de3SRichard Henderson TCGLabel *lab; 33013a6b8de3SRichard Henderson TCGv_i32 n2; 33023a6b8de3SRichard Henderson 33033a6b8de3SRichard Henderson finishing_insn(dc); 33043a6b8de3SRichard Henderson flush_cond(dc); 33053a6b8de3SRichard Henderson 33063a6b8de3SRichard Henderson n2 = tcg_temp_new_i32(); 33073a6b8de3SRichard Henderson tcg_gen_trunc_tl_i32(n2, cpu_regs[a->rs2_or_imm]); 33083a6b8de3SRichard Henderson 33093a6b8de3SRichard Henderson lab = delay_exception(dc, TT_DIV_ZERO); 33103a6b8de3SRichard Henderson tcg_gen_brcondi_i32(TCG_COND_EQ, n2, 0, lab); 33113a6b8de3SRichard Henderson 33123a6b8de3SRichard Henderson t2 = tcg_temp_new_i64(); 33133a6b8de3SRichard Henderson #ifdef TARGET_SPARC64 33143a6b8de3SRichard Henderson tcg_gen_ext32u_i64(t2, cpu_regs[a->rs2_or_imm]); 33153a6b8de3SRichard Henderson #else 33163a6b8de3SRichard Henderson tcg_gen_extu_i32_i64(t2, cpu_regs[a->rs2_or_imm]); 33173a6b8de3SRichard Henderson #endif 33183a6b8de3SRichard Henderson } 33193a6b8de3SRichard Henderson 33203a6b8de3SRichard Henderson t1 = tcg_temp_new_i64(); 33213a6b8de3SRichard Henderson tcg_gen_concat_tl_i64(t1, gen_load_gpr(dc, a->rs1), cpu_y); 33223a6b8de3SRichard Henderson 33233a6b8de3SRichard Henderson tcg_gen_divu_i64(t1, t1, t2); 33243a6b8de3SRichard Henderson tcg_gen_umin_i64(t1, t1, tcg_constant_i64(UINT32_MAX)); 33253a6b8de3SRichard Henderson 33263a6b8de3SRichard Henderson dst = gen_dest_gpr(dc, a->rd); 33273a6b8de3SRichard Henderson tcg_gen_trunc_i64_tl(dst, t1); 33283a6b8de3SRichard Henderson gen_store_gpr(dc, a->rd, dst); 33293a6b8de3SRichard Henderson return advance_pc(dc); 33303a6b8de3SRichard Henderson } 33313a6b8de3SRichard Henderson 3332f3141174SRichard Henderson static bool trans_UDIVX(DisasContext *dc, arg_r_r_ri *a) 3333f3141174SRichard Henderson { 3334f3141174SRichard Henderson TCGv dst, src1, src2; 3335f3141174SRichard Henderson 3336f3141174SRichard Henderson if (!avail_64(dc)) { 3337f3141174SRichard Henderson return false; 3338f3141174SRichard Henderson } 3339f3141174SRichard Henderson /* For simplicity, we under-decoded the rs2 form. */ 3340f3141174SRichard Henderson if (!a->imm && a->rs2_or_imm & ~0x1f) { 3341f3141174SRichard Henderson return false; 3342f3141174SRichard Henderson } 3343f3141174SRichard Henderson 3344f3141174SRichard Henderson if (unlikely(a->rs2_or_imm == 0)) { 3345f3141174SRichard Henderson gen_exception(dc, TT_DIV_ZERO); 3346f3141174SRichard Henderson return true; 3347f3141174SRichard Henderson } 3348f3141174SRichard Henderson 3349f3141174SRichard Henderson if (a->imm) { 3350f3141174SRichard Henderson src2 = tcg_constant_tl(a->rs2_or_imm); 3351f3141174SRichard Henderson } else { 3352f3141174SRichard Henderson TCGLabel *lab; 3353f3141174SRichard Henderson 3354f3141174SRichard Henderson finishing_insn(dc); 3355f3141174SRichard Henderson flush_cond(dc); 3356f3141174SRichard Henderson 3357f3141174SRichard Henderson lab = delay_exception(dc, TT_DIV_ZERO); 3358f3141174SRichard Henderson src2 = cpu_regs[a->rs2_or_imm]; 3359f3141174SRichard Henderson tcg_gen_brcondi_tl(TCG_COND_EQ, src2, 0, lab); 3360f3141174SRichard Henderson } 3361f3141174SRichard Henderson 3362f3141174SRichard Henderson dst = gen_dest_gpr(dc, a->rd); 3363f3141174SRichard Henderson src1 = gen_load_gpr(dc, a->rs1); 3364f3141174SRichard Henderson 3365f3141174SRichard Henderson tcg_gen_divu_tl(dst, src1, src2); 3366f3141174SRichard Henderson gen_store_gpr(dc, a->rd, dst); 3367f3141174SRichard Henderson return advance_pc(dc); 3368f3141174SRichard Henderson } 3369f3141174SRichard Henderson 3370f3141174SRichard Henderson static bool trans_SDIVX(DisasContext *dc, arg_r_r_ri *a) 3371f3141174SRichard Henderson { 3372f3141174SRichard Henderson TCGv dst, src1, src2; 3373f3141174SRichard Henderson 3374f3141174SRichard Henderson if (!avail_64(dc)) { 3375f3141174SRichard Henderson return false; 3376f3141174SRichard Henderson } 3377f3141174SRichard Henderson /* For simplicity, we under-decoded the rs2 form. */ 3378f3141174SRichard Henderson if (!a->imm && a->rs2_or_imm & ~0x1f) { 3379f3141174SRichard Henderson return false; 3380f3141174SRichard Henderson } 3381f3141174SRichard Henderson 3382f3141174SRichard Henderson if (unlikely(a->rs2_or_imm == 0)) { 3383f3141174SRichard Henderson gen_exception(dc, TT_DIV_ZERO); 3384f3141174SRichard Henderson return true; 3385f3141174SRichard Henderson } 3386f3141174SRichard Henderson 3387f3141174SRichard Henderson dst = gen_dest_gpr(dc, a->rd); 3388f3141174SRichard Henderson src1 = gen_load_gpr(dc, a->rs1); 3389f3141174SRichard Henderson 3390f3141174SRichard Henderson if (a->imm) { 3391f3141174SRichard Henderson if (unlikely(a->rs2_or_imm == -1)) { 3392f3141174SRichard Henderson tcg_gen_neg_tl(dst, src1); 3393f3141174SRichard Henderson gen_store_gpr(dc, a->rd, dst); 3394f3141174SRichard Henderson return advance_pc(dc); 3395f3141174SRichard Henderson } 3396f3141174SRichard Henderson src2 = tcg_constant_tl(a->rs2_or_imm); 3397f3141174SRichard Henderson } else { 3398f3141174SRichard Henderson TCGLabel *lab; 3399f3141174SRichard Henderson TCGv t1, t2; 3400f3141174SRichard Henderson 3401f3141174SRichard Henderson finishing_insn(dc); 3402f3141174SRichard Henderson flush_cond(dc); 3403f3141174SRichard Henderson 3404f3141174SRichard Henderson lab = delay_exception(dc, TT_DIV_ZERO); 3405f3141174SRichard Henderson src2 = cpu_regs[a->rs2_or_imm]; 3406f3141174SRichard Henderson tcg_gen_brcondi_tl(TCG_COND_EQ, src2, 0, lab); 3407f3141174SRichard Henderson 3408f3141174SRichard Henderson /* 3409f3141174SRichard Henderson * Need to avoid INT64_MIN / -1, which will trap on x86 host. 3410f3141174SRichard Henderson * Set SRC2 to 1 as a new divisor, to produce the correct result. 3411f3141174SRichard Henderson */ 3412f3141174SRichard Henderson t1 = tcg_temp_new(); 3413f3141174SRichard Henderson t2 = tcg_temp_new(); 3414f3141174SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_EQ, t1, src1, (target_long)INT64_MIN); 3415f3141174SRichard Henderson tcg_gen_setcondi_tl(TCG_COND_EQ, t2, src2, -1); 3416f3141174SRichard Henderson tcg_gen_and_tl(t1, t1, t2); 3417f3141174SRichard Henderson tcg_gen_movcond_tl(TCG_COND_NE, t1, t1, tcg_constant_tl(0), 3418f3141174SRichard Henderson tcg_constant_tl(1), src2); 3419f3141174SRichard Henderson src2 = t1; 3420f3141174SRichard Henderson } 3421f3141174SRichard Henderson 3422f3141174SRichard Henderson tcg_gen_div_tl(dst, src1, src2); 3423f3141174SRichard Henderson gen_store_gpr(dc, a->rd, dst); 3424f3141174SRichard Henderson return advance_pc(dc); 3425f3141174SRichard Henderson } 3426f3141174SRichard Henderson 3427b88ce6f2SRichard Henderson static bool gen_edge(DisasContext *dc, arg_r_r_r *a, 3428b88ce6f2SRichard Henderson int width, bool cc, bool left) 3429b88ce6f2SRichard Henderson { 3430b88ce6f2SRichard Henderson TCGv dst, s1, s2, lo1, lo2; 3431b88ce6f2SRichard Henderson uint64_t amask, tabl, tabr; 3432b88ce6f2SRichard Henderson int shift, imask, omask; 3433b88ce6f2SRichard Henderson 3434b88ce6f2SRichard Henderson dst = gen_dest_gpr(dc, a->rd); 3435b88ce6f2SRichard Henderson s1 = gen_load_gpr(dc, a->rs1); 3436b88ce6f2SRichard Henderson s2 = gen_load_gpr(dc, a->rs2); 3437b88ce6f2SRichard Henderson 3438b88ce6f2SRichard Henderson if (cc) { 3439f828df74SRichard Henderson gen_op_subcc(cpu_cc_N, s1, s2); 3440b88ce6f2SRichard Henderson } 3441b88ce6f2SRichard Henderson 3442b88ce6f2SRichard Henderson /* 3443b88ce6f2SRichard Henderson * Theory of operation: there are two tables, left and right (not to 3444b88ce6f2SRichard Henderson * be confused with the left and right versions of the opcode). These 3445b88ce6f2SRichard Henderson * are indexed by the low 3 bits of the inputs. To make things "easy", 3446b88ce6f2SRichard Henderson * these tables are loaded into two constants, TABL and TABR below. 3447b88ce6f2SRichard Henderson * The operation index = (input & imask) << shift calculates the index 3448b88ce6f2SRichard Henderson * into the constant, while val = (table >> index) & omask calculates 3449b88ce6f2SRichard Henderson * the value we're looking for. 3450b88ce6f2SRichard Henderson */ 3451b88ce6f2SRichard Henderson switch (width) { 3452b88ce6f2SRichard Henderson case 8: 3453b88ce6f2SRichard Henderson imask = 0x7; 3454b88ce6f2SRichard Henderson shift = 3; 3455b88ce6f2SRichard Henderson omask = 0xff; 3456b88ce6f2SRichard Henderson if (left) { 3457b88ce6f2SRichard Henderson tabl = 0x80c0e0f0f8fcfeffULL; 3458b88ce6f2SRichard Henderson tabr = 0xff7f3f1f0f070301ULL; 3459b88ce6f2SRichard Henderson } else { 3460b88ce6f2SRichard Henderson tabl = 0x0103070f1f3f7fffULL; 3461b88ce6f2SRichard Henderson tabr = 0xfffefcf8f0e0c080ULL; 3462b88ce6f2SRichard Henderson } 3463b88ce6f2SRichard Henderson break; 3464b88ce6f2SRichard Henderson case 16: 3465b88ce6f2SRichard Henderson imask = 0x6; 3466b88ce6f2SRichard Henderson shift = 1; 3467b88ce6f2SRichard Henderson omask = 0xf; 3468b88ce6f2SRichard Henderson if (left) { 3469b88ce6f2SRichard Henderson tabl = 0x8cef; 3470b88ce6f2SRichard Henderson tabr = 0xf731; 3471b88ce6f2SRichard Henderson } else { 3472b88ce6f2SRichard Henderson tabl = 0x137f; 3473b88ce6f2SRichard Henderson tabr = 0xfec8; 3474b88ce6f2SRichard Henderson } 3475b88ce6f2SRichard Henderson break; 3476b88ce6f2SRichard Henderson case 32: 3477b88ce6f2SRichard Henderson imask = 0x4; 3478b88ce6f2SRichard Henderson shift = 0; 3479b88ce6f2SRichard Henderson omask = 0x3; 3480b88ce6f2SRichard Henderson if (left) { 3481b88ce6f2SRichard Henderson tabl = (2 << 2) | 3; 3482b88ce6f2SRichard Henderson tabr = (3 << 2) | 1; 3483b88ce6f2SRichard Henderson } else { 3484b88ce6f2SRichard Henderson tabl = (1 << 2) | 3; 3485b88ce6f2SRichard Henderson tabr = (3 << 2) | 2; 3486b88ce6f2SRichard Henderson } 3487b88ce6f2SRichard Henderson break; 3488b88ce6f2SRichard Henderson default: 3489b88ce6f2SRichard Henderson abort(); 3490b88ce6f2SRichard Henderson } 3491b88ce6f2SRichard Henderson 3492b88ce6f2SRichard Henderson lo1 = tcg_temp_new(); 3493b88ce6f2SRichard Henderson lo2 = tcg_temp_new(); 3494b88ce6f2SRichard Henderson tcg_gen_andi_tl(lo1, s1, imask); 3495b88ce6f2SRichard Henderson tcg_gen_andi_tl(lo2, s2, imask); 3496b88ce6f2SRichard Henderson tcg_gen_shli_tl(lo1, lo1, shift); 3497b88ce6f2SRichard Henderson tcg_gen_shli_tl(lo2, lo2, shift); 3498b88ce6f2SRichard Henderson 3499b88ce6f2SRichard Henderson tcg_gen_shr_tl(lo1, tcg_constant_tl(tabl), lo1); 3500b88ce6f2SRichard Henderson tcg_gen_shr_tl(lo2, tcg_constant_tl(tabr), lo2); 3501b88ce6f2SRichard Henderson tcg_gen_andi_tl(lo1, lo1, omask); 3502b88ce6f2SRichard Henderson tcg_gen_andi_tl(lo2, lo2, omask); 3503b88ce6f2SRichard Henderson 3504b88ce6f2SRichard Henderson amask = address_mask_i(dc, -8); 3505b88ce6f2SRichard Henderson tcg_gen_andi_tl(s1, s1, amask); 3506b88ce6f2SRichard Henderson tcg_gen_andi_tl(s2, s2, amask); 3507b88ce6f2SRichard Henderson 3508b88ce6f2SRichard Henderson /* Compute dst = (s1 == s2 ? lo1 : lo1 & lo2). */ 3509b88ce6f2SRichard Henderson tcg_gen_and_tl(lo2, lo2, lo1); 3510b88ce6f2SRichard Henderson tcg_gen_movcond_tl(TCG_COND_EQ, dst, s1, s2, lo1, lo2); 3511b88ce6f2SRichard Henderson 3512b88ce6f2SRichard Henderson gen_store_gpr(dc, a->rd, dst); 3513b88ce6f2SRichard Henderson return advance_pc(dc); 3514b88ce6f2SRichard Henderson } 3515b88ce6f2SRichard Henderson 3516b88ce6f2SRichard Henderson TRANS(EDGE8cc, VIS1, gen_edge, a, 8, 1, 0) 3517b88ce6f2SRichard Henderson TRANS(EDGE8Lcc, VIS1, gen_edge, a, 8, 1, 1) 3518b88ce6f2SRichard Henderson TRANS(EDGE16cc, VIS1, gen_edge, a, 16, 1, 0) 3519b88ce6f2SRichard Henderson TRANS(EDGE16Lcc, VIS1, gen_edge, a, 16, 1, 1) 3520b88ce6f2SRichard Henderson TRANS(EDGE32cc, VIS1, gen_edge, a, 32, 1, 0) 3521b88ce6f2SRichard Henderson TRANS(EDGE32Lcc, VIS1, gen_edge, a, 32, 1, 1) 3522b88ce6f2SRichard Henderson 3523b88ce6f2SRichard Henderson TRANS(EDGE8N, VIS2, gen_edge, a, 8, 0, 0) 3524b88ce6f2SRichard Henderson TRANS(EDGE8LN, VIS2, gen_edge, a, 8, 0, 1) 3525b88ce6f2SRichard Henderson TRANS(EDGE16N, VIS2, gen_edge, a, 16, 0, 0) 3526b88ce6f2SRichard Henderson TRANS(EDGE16LN, VIS2, gen_edge, a, 16, 0, 1) 3527b88ce6f2SRichard Henderson TRANS(EDGE32N, VIS2, gen_edge, a, 32, 0, 0) 3528b88ce6f2SRichard Henderson TRANS(EDGE32LN, VIS2, gen_edge, a, 32, 0, 1) 3529b88ce6f2SRichard Henderson 353045bfed3bSRichard Henderson static bool do_rrr(DisasContext *dc, arg_r_r_r *a, 353145bfed3bSRichard Henderson void (*func)(TCGv, TCGv, TCGv)) 353245bfed3bSRichard Henderson { 353345bfed3bSRichard Henderson TCGv dst = gen_dest_gpr(dc, a->rd); 353445bfed3bSRichard Henderson TCGv src1 = gen_load_gpr(dc, a->rs1); 353545bfed3bSRichard Henderson TCGv src2 = gen_load_gpr(dc, a->rs2); 353645bfed3bSRichard Henderson 353745bfed3bSRichard Henderson func(dst, src1, src2); 353845bfed3bSRichard Henderson gen_store_gpr(dc, a->rd, dst); 353945bfed3bSRichard Henderson return advance_pc(dc); 354045bfed3bSRichard Henderson } 354145bfed3bSRichard Henderson 354245bfed3bSRichard Henderson TRANS(ARRAY8, VIS1, do_rrr, a, gen_helper_array8) 354345bfed3bSRichard Henderson TRANS(ARRAY16, VIS1, do_rrr, a, gen_op_array16) 354445bfed3bSRichard Henderson TRANS(ARRAY32, VIS1, do_rrr, a, gen_op_array32) 354545bfed3bSRichard Henderson 35469e20ca94SRichard Henderson static void gen_op_alignaddr(TCGv dst, TCGv s1, TCGv s2) 35479e20ca94SRichard Henderson { 35489e20ca94SRichard Henderson #ifdef TARGET_SPARC64 35499e20ca94SRichard Henderson TCGv tmp = tcg_temp_new(); 35509e20ca94SRichard Henderson 35519e20ca94SRichard Henderson tcg_gen_add_tl(tmp, s1, s2); 35529e20ca94SRichard Henderson tcg_gen_andi_tl(dst, tmp, -8); 35539e20ca94SRichard Henderson tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, tmp, 0, 3); 35549e20ca94SRichard Henderson #else 35559e20ca94SRichard Henderson g_assert_not_reached(); 35569e20ca94SRichard Henderson #endif 35579e20ca94SRichard Henderson } 35589e20ca94SRichard Henderson 35599e20ca94SRichard Henderson static void gen_op_alignaddrl(TCGv dst, TCGv s1, TCGv s2) 35609e20ca94SRichard Henderson { 35619e20ca94SRichard Henderson #ifdef TARGET_SPARC64 35629e20ca94SRichard Henderson TCGv tmp = tcg_temp_new(); 35639e20ca94SRichard Henderson 35649e20ca94SRichard Henderson tcg_gen_add_tl(tmp, s1, s2); 35659e20ca94SRichard Henderson tcg_gen_andi_tl(dst, tmp, -8); 35669e20ca94SRichard Henderson tcg_gen_neg_tl(tmp, tmp); 35679e20ca94SRichard Henderson tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, tmp, 0, 3); 35689e20ca94SRichard Henderson #else 35699e20ca94SRichard Henderson g_assert_not_reached(); 35709e20ca94SRichard Henderson #endif 35719e20ca94SRichard Henderson } 35729e20ca94SRichard Henderson 35739e20ca94SRichard Henderson TRANS(ALIGNADDR, VIS1, do_rrr, a, gen_op_alignaddr) 35749e20ca94SRichard Henderson TRANS(ALIGNADDRL, VIS1, do_rrr, a, gen_op_alignaddrl) 35759e20ca94SRichard Henderson 357639ca3490SRichard Henderson static void gen_op_bmask(TCGv dst, TCGv s1, TCGv s2) 357739ca3490SRichard Henderson { 357839ca3490SRichard Henderson #ifdef TARGET_SPARC64 357939ca3490SRichard Henderson tcg_gen_add_tl(dst, s1, s2); 358039ca3490SRichard Henderson tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, dst, 32, 32); 358139ca3490SRichard Henderson #else 358239ca3490SRichard Henderson g_assert_not_reached(); 358339ca3490SRichard Henderson #endif 358439ca3490SRichard Henderson } 358539ca3490SRichard Henderson 358639ca3490SRichard Henderson TRANS(BMASK, VIS2, do_rrr, a, gen_op_bmask) 358739ca3490SRichard Henderson 35885fc546eeSRichard Henderson static bool do_shift_r(DisasContext *dc, arg_shiftr *a, bool l, bool u) 35895fc546eeSRichard Henderson { 35905fc546eeSRichard Henderson TCGv dst, src1, src2; 35915fc546eeSRichard Henderson 35925fc546eeSRichard Henderson /* Reject 64-bit shifts for sparc32. */ 35935fc546eeSRichard Henderson if (avail_32(dc) && a->x) { 35945fc546eeSRichard Henderson return false; 35955fc546eeSRichard Henderson } 35965fc546eeSRichard Henderson 35975fc546eeSRichard Henderson src2 = tcg_temp_new(); 35985fc546eeSRichard Henderson tcg_gen_andi_tl(src2, gen_load_gpr(dc, a->rs2), a->x ? 63 : 31); 35995fc546eeSRichard Henderson src1 = gen_load_gpr(dc, a->rs1); 36005fc546eeSRichard Henderson dst = gen_dest_gpr(dc, a->rd); 36015fc546eeSRichard Henderson 36025fc546eeSRichard Henderson if (l) { 36035fc546eeSRichard Henderson tcg_gen_shl_tl(dst, src1, src2); 36045fc546eeSRichard Henderson if (!a->x) { 36055fc546eeSRichard Henderson tcg_gen_ext32u_tl(dst, dst); 36065fc546eeSRichard Henderson } 36075fc546eeSRichard Henderson } else if (u) { 36085fc546eeSRichard Henderson if (!a->x) { 36095fc546eeSRichard Henderson tcg_gen_ext32u_tl(dst, src1); 36105fc546eeSRichard Henderson src1 = dst; 36115fc546eeSRichard Henderson } 36125fc546eeSRichard Henderson tcg_gen_shr_tl(dst, src1, src2); 36135fc546eeSRichard Henderson } else { 36145fc546eeSRichard Henderson if (!a->x) { 36155fc546eeSRichard Henderson tcg_gen_ext32s_tl(dst, src1); 36165fc546eeSRichard Henderson src1 = dst; 36175fc546eeSRichard Henderson } 36185fc546eeSRichard Henderson tcg_gen_sar_tl(dst, src1, src2); 36195fc546eeSRichard Henderson } 36205fc546eeSRichard Henderson gen_store_gpr(dc, a->rd, dst); 36215fc546eeSRichard Henderson return advance_pc(dc); 36225fc546eeSRichard Henderson } 36235fc546eeSRichard Henderson 36245fc546eeSRichard Henderson TRANS(SLL_r, ALL, do_shift_r, a, true, true) 36255fc546eeSRichard Henderson TRANS(SRL_r, ALL, do_shift_r, a, false, true) 36265fc546eeSRichard Henderson TRANS(SRA_r, ALL, do_shift_r, a, false, false) 36275fc546eeSRichard Henderson 36285fc546eeSRichard Henderson static bool do_shift_i(DisasContext *dc, arg_shifti *a, bool l, bool u) 36295fc546eeSRichard Henderson { 36305fc546eeSRichard Henderson TCGv dst, src1; 36315fc546eeSRichard Henderson 36325fc546eeSRichard Henderson /* Reject 64-bit shifts for sparc32. */ 36335fc546eeSRichard Henderson if (avail_32(dc) && (a->x || a->i >= 32)) { 36345fc546eeSRichard Henderson return false; 36355fc546eeSRichard Henderson } 36365fc546eeSRichard Henderson 36375fc546eeSRichard Henderson src1 = gen_load_gpr(dc, a->rs1); 36385fc546eeSRichard Henderson dst = gen_dest_gpr(dc, a->rd); 36395fc546eeSRichard Henderson 36405fc546eeSRichard Henderson if (avail_32(dc) || a->x) { 36415fc546eeSRichard Henderson if (l) { 36425fc546eeSRichard Henderson tcg_gen_shli_tl(dst, src1, a->i); 36435fc546eeSRichard Henderson } else if (u) { 36445fc546eeSRichard Henderson tcg_gen_shri_tl(dst, src1, a->i); 36455fc546eeSRichard Henderson } else { 36465fc546eeSRichard Henderson tcg_gen_sari_tl(dst, src1, a->i); 36475fc546eeSRichard Henderson } 36485fc546eeSRichard Henderson } else { 36495fc546eeSRichard Henderson if (l) { 36505fc546eeSRichard Henderson tcg_gen_deposit_z_tl(dst, src1, a->i, 32 - a->i); 36515fc546eeSRichard Henderson } else if (u) { 36525fc546eeSRichard Henderson tcg_gen_extract_tl(dst, src1, a->i, 32 - a->i); 36535fc546eeSRichard Henderson } else { 36545fc546eeSRichard Henderson tcg_gen_sextract_tl(dst, src1, a->i, 32 - a->i); 36555fc546eeSRichard Henderson } 36565fc546eeSRichard Henderson } 36575fc546eeSRichard Henderson gen_store_gpr(dc, a->rd, dst); 36585fc546eeSRichard Henderson return advance_pc(dc); 36595fc546eeSRichard Henderson } 36605fc546eeSRichard Henderson 36615fc546eeSRichard Henderson TRANS(SLL_i, ALL, do_shift_i, a, true, true) 36625fc546eeSRichard Henderson TRANS(SRL_i, ALL, do_shift_i, a, false, true) 36635fc546eeSRichard Henderson TRANS(SRA_i, ALL, do_shift_i, a, false, false) 36645fc546eeSRichard Henderson 3665fb4ed7aaSRichard Henderson static TCGv gen_rs2_or_imm(DisasContext *dc, bool imm, int rs2_or_imm) 3666fb4ed7aaSRichard Henderson { 3667fb4ed7aaSRichard Henderson /* For simplicity, we under-decoded the rs2 form. */ 3668fb4ed7aaSRichard Henderson if (!imm && rs2_or_imm & ~0x1f) { 3669fb4ed7aaSRichard Henderson return NULL; 3670fb4ed7aaSRichard Henderson } 3671fb4ed7aaSRichard Henderson if (imm || rs2_or_imm == 0) { 3672fb4ed7aaSRichard Henderson return tcg_constant_tl(rs2_or_imm); 3673fb4ed7aaSRichard Henderson } else { 3674fb4ed7aaSRichard Henderson return cpu_regs[rs2_or_imm]; 3675fb4ed7aaSRichard Henderson } 3676fb4ed7aaSRichard Henderson } 3677fb4ed7aaSRichard Henderson 3678fb4ed7aaSRichard Henderson static bool do_mov_cond(DisasContext *dc, DisasCompare *cmp, int rd, TCGv src2) 3679fb4ed7aaSRichard Henderson { 3680fb4ed7aaSRichard Henderson TCGv dst = gen_load_gpr(dc, rd); 3681c8507ebfSRichard Henderson TCGv c2 = tcg_constant_tl(cmp->c2); 3682fb4ed7aaSRichard Henderson 3683c8507ebfSRichard Henderson tcg_gen_movcond_tl(cmp->cond, dst, cmp->c1, c2, src2, dst); 3684fb4ed7aaSRichard Henderson gen_store_gpr(dc, rd, dst); 3685fb4ed7aaSRichard Henderson return advance_pc(dc); 3686fb4ed7aaSRichard Henderson } 3687fb4ed7aaSRichard Henderson 3688fb4ed7aaSRichard Henderson static bool trans_MOVcc(DisasContext *dc, arg_MOVcc *a) 3689fb4ed7aaSRichard Henderson { 3690fb4ed7aaSRichard Henderson TCGv src2 = gen_rs2_or_imm(dc, a->imm, a->rs2_or_imm); 3691fb4ed7aaSRichard Henderson DisasCompare cmp; 3692fb4ed7aaSRichard Henderson 3693fb4ed7aaSRichard Henderson if (src2 == NULL) { 3694fb4ed7aaSRichard Henderson return false; 3695fb4ed7aaSRichard Henderson } 3696fb4ed7aaSRichard Henderson gen_compare(&cmp, a->cc, a->cond, dc); 3697fb4ed7aaSRichard Henderson return do_mov_cond(dc, &cmp, a->rd, src2); 3698fb4ed7aaSRichard Henderson } 3699fb4ed7aaSRichard Henderson 3700fb4ed7aaSRichard Henderson static bool trans_MOVfcc(DisasContext *dc, arg_MOVfcc *a) 3701fb4ed7aaSRichard Henderson { 3702fb4ed7aaSRichard Henderson TCGv src2 = gen_rs2_or_imm(dc, a->imm, a->rs2_or_imm); 3703fb4ed7aaSRichard Henderson DisasCompare cmp; 3704fb4ed7aaSRichard Henderson 3705fb4ed7aaSRichard Henderson if (src2 == NULL) { 3706fb4ed7aaSRichard Henderson return false; 3707fb4ed7aaSRichard Henderson } 3708fb4ed7aaSRichard Henderson gen_fcompare(&cmp, a->cc, a->cond); 3709fb4ed7aaSRichard Henderson return do_mov_cond(dc, &cmp, a->rd, src2); 3710fb4ed7aaSRichard Henderson } 3711fb4ed7aaSRichard Henderson 3712fb4ed7aaSRichard Henderson static bool trans_MOVR(DisasContext *dc, arg_MOVR *a) 3713fb4ed7aaSRichard Henderson { 3714fb4ed7aaSRichard Henderson TCGv src2 = gen_rs2_or_imm(dc, a->imm, a->rs2_or_imm); 3715fb4ed7aaSRichard Henderson DisasCompare cmp; 3716fb4ed7aaSRichard Henderson 3717fb4ed7aaSRichard Henderson if (src2 == NULL) { 3718fb4ed7aaSRichard Henderson return false; 3719fb4ed7aaSRichard Henderson } 37202c4f56c9SRichard Henderson if (!gen_compare_reg(&cmp, a->cond, gen_load_gpr(dc, a->rs1))) { 37212c4f56c9SRichard Henderson return false; 37222c4f56c9SRichard Henderson } 3723fb4ed7aaSRichard Henderson return do_mov_cond(dc, &cmp, a->rd, src2); 3724fb4ed7aaSRichard Henderson } 3725fb4ed7aaSRichard Henderson 372686b82fe0SRichard Henderson static bool do_add_special(DisasContext *dc, arg_r_r_ri *a, 372786b82fe0SRichard Henderson bool (*func)(DisasContext *dc, int rd, TCGv src)) 372886b82fe0SRichard Henderson { 372986b82fe0SRichard Henderson TCGv src1, sum; 373086b82fe0SRichard Henderson 373186b82fe0SRichard Henderson /* For simplicity, we under-decoded the rs2 form. */ 373286b82fe0SRichard Henderson if (!a->imm && a->rs2_or_imm & ~0x1f) { 373386b82fe0SRichard Henderson return false; 373486b82fe0SRichard Henderson } 373586b82fe0SRichard Henderson 373686b82fe0SRichard Henderson /* 373786b82fe0SRichard Henderson * Always load the sum into a new temporary. 373886b82fe0SRichard Henderson * This is required to capture the value across a window change, 373986b82fe0SRichard Henderson * e.g. SAVE and RESTORE, and may be optimized away otherwise. 374086b82fe0SRichard Henderson */ 374186b82fe0SRichard Henderson sum = tcg_temp_new(); 374286b82fe0SRichard Henderson src1 = gen_load_gpr(dc, a->rs1); 374386b82fe0SRichard Henderson if (a->imm || a->rs2_or_imm == 0) { 374486b82fe0SRichard Henderson tcg_gen_addi_tl(sum, src1, a->rs2_or_imm); 374586b82fe0SRichard Henderson } else { 374686b82fe0SRichard Henderson tcg_gen_add_tl(sum, src1, cpu_regs[a->rs2_or_imm]); 374786b82fe0SRichard Henderson } 374886b82fe0SRichard Henderson return func(dc, a->rd, sum); 374986b82fe0SRichard Henderson } 375086b82fe0SRichard Henderson 375186b82fe0SRichard Henderson static bool do_jmpl(DisasContext *dc, int rd, TCGv src) 375286b82fe0SRichard Henderson { 375386b82fe0SRichard Henderson /* 375486b82fe0SRichard Henderson * Preserve pc across advance, so that we can delay 375586b82fe0SRichard Henderson * the writeback to rd until after src is consumed. 375686b82fe0SRichard Henderson */ 375786b82fe0SRichard Henderson target_ulong cur_pc = dc->pc; 375886b82fe0SRichard Henderson 375986b82fe0SRichard Henderson gen_check_align(dc, src, 3); 376086b82fe0SRichard Henderson 376186b82fe0SRichard Henderson gen_mov_pc_npc(dc); 376286b82fe0SRichard Henderson tcg_gen_mov_tl(cpu_npc, src); 376386b82fe0SRichard Henderson gen_address_mask(dc, cpu_npc); 376486b82fe0SRichard Henderson gen_store_gpr(dc, rd, tcg_constant_tl(cur_pc)); 376586b82fe0SRichard Henderson 376686b82fe0SRichard Henderson dc->npc = DYNAMIC_PC_LOOKUP; 376786b82fe0SRichard Henderson return true; 376886b82fe0SRichard Henderson } 376986b82fe0SRichard Henderson 377086b82fe0SRichard Henderson TRANS(JMPL, ALL, do_add_special, a, do_jmpl) 377186b82fe0SRichard Henderson 377286b82fe0SRichard Henderson static bool do_rett(DisasContext *dc, int rd, TCGv src) 377386b82fe0SRichard Henderson { 377486b82fe0SRichard Henderson if (!supervisor(dc)) { 377586b82fe0SRichard Henderson return raise_priv(dc); 377686b82fe0SRichard Henderson } 377786b82fe0SRichard Henderson 377886b82fe0SRichard Henderson gen_check_align(dc, src, 3); 377986b82fe0SRichard Henderson 378086b82fe0SRichard Henderson gen_mov_pc_npc(dc); 378186b82fe0SRichard Henderson tcg_gen_mov_tl(cpu_npc, src); 378286b82fe0SRichard Henderson gen_helper_rett(tcg_env); 378386b82fe0SRichard Henderson 378486b82fe0SRichard Henderson dc->npc = DYNAMIC_PC; 378586b82fe0SRichard Henderson return true; 378686b82fe0SRichard Henderson } 378786b82fe0SRichard Henderson 378886b82fe0SRichard Henderson TRANS(RETT, 32, do_add_special, a, do_rett) 378986b82fe0SRichard Henderson 379086b82fe0SRichard Henderson static bool do_return(DisasContext *dc, int rd, TCGv src) 379186b82fe0SRichard Henderson { 379286b82fe0SRichard Henderson gen_check_align(dc, src, 3); 37930dfae4f9SRichard Henderson gen_helper_restore(tcg_env); 379486b82fe0SRichard Henderson 379586b82fe0SRichard Henderson gen_mov_pc_npc(dc); 379686b82fe0SRichard Henderson tcg_gen_mov_tl(cpu_npc, src); 379786b82fe0SRichard Henderson gen_address_mask(dc, cpu_npc); 379886b82fe0SRichard Henderson 379986b82fe0SRichard Henderson dc->npc = DYNAMIC_PC_LOOKUP; 380086b82fe0SRichard Henderson return true; 380186b82fe0SRichard Henderson } 380286b82fe0SRichard Henderson 380386b82fe0SRichard Henderson TRANS(RETURN, 64, do_add_special, a, do_return) 380486b82fe0SRichard Henderson 3805d3825800SRichard Henderson static bool do_save(DisasContext *dc, int rd, TCGv src) 3806d3825800SRichard Henderson { 3807d3825800SRichard Henderson gen_helper_save(tcg_env); 3808d3825800SRichard Henderson gen_store_gpr(dc, rd, src); 3809d3825800SRichard Henderson return advance_pc(dc); 3810d3825800SRichard Henderson } 3811d3825800SRichard Henderson 3812d3825800SRichard Henderson TRANS(SAVE, ALL, do_add_special, a, do_save) 3813d3825800SRichard Henderson 3814d3825800SRichard Henderson static bool do_restore(DisasContext *dc, int rd, TCGv src) 3815d3825800SRichard Henderson { 3816d3825800SRichard Henderson gen_helper_restore(tcg_env); 3817d3825800SRichard Henderson gen_store_gpr(dc, rd, src); 3818d3825800SRichard Henderson return advance_pc(dc); 3819d3825800SRichard Henderson } 3820d3825800SRichard Henderson 3821d3825800SRichard Henderson TRANS(RESTORE, ALL, do_add_special, a, do_restore) 3822d3825800SRichard Henderson 38238f75b8a4SRichard Henderson static bool do_done_retry(DisasContext *dc, bool done) 38248f75b8a4SRichard Henderson { 38258f75b8a4SRichard Henderson if (!supervisor(dc)) { 38268f75b8a4SRichard Henderson return raise_priv(dc); 38278f75b8a4SRichard Henderson } 38288f75b8a4SRichard Henderson dc->npc = DYNAMIC_PC; 38298f75b8a4SRichard Henderson dc->pc = DYNAMIC_PC; 38308f75b8a4SRichard Henderson translator_io_start(&dc->base); 38318f75b8a4SRichard Henderson if (done) { 38328f75b8a4SRichard Henderson gen_helper_done(tcg_env); 38338f75b8a4SRichard Henderson } else { 38348f75b8a4SRichard Henderson gen_helper_retry(tcg_env); 38358f75b8a4SRichard Henderson } 38368f75b8a4SRichard Henderson return true; 38378f75b8a4SRichard Henderson } 38388f75b8a4SRichard Henderson 38398f75b8a4SRichard Henderson TRANS(DONE, 64, do_done_retry, true) 38408f75b8a4SRichard Henderson TRANS(RETRY, 64, do_done_retry, false) 38418f75b8a4SRichard Henderson 38420880d20bSRichard Henderson /* 38430880d20bSRichard Henderson * Major opcode 11 -- load and store instructions 38440880d20bSRichard Henderson */ 38450880d20bSRichard Henderson 38460880d20bSRichard Henderson static TCGv gen_ldst_addr(DisasContext *dc, int rs1, bool imm, int rs2_or_imm) 38470880d20bSRichard Henderson { 38480880d20bSRichard Henderson TCGv addr, tmp = NULL; 38490880d20bSRichard Henderson 38500880d20bSRichard Henderson /* For simplicity, we under-decoded the rs2 form. */ 38510880d20bSRichard Henderson if (!imm && rs2_or_imm & ~0x1f) { 38520880d20bSRichard Henderson return NULL; 38530880d20bSRichard Henderson } 38540880d20bSRichard Henderson 38550880d20bSRichard Henderson addr = gen_load_gpr(dc, rs1); 38560880d20bSRichard Henderson if (rs2_or_imm) { 38570880d20bSRichard Henderson tmp = tcg_temp_new(); 38580880d20bSRichard Henderson if (imm) { 38590880d20bSRichard Henderson tcg_gen_addi_tl(tmp, addr, rs2_or_imm); 38600880d20bSRichard Henderson } else { 38610880d20bSRichard Henderson tcg_gen_add_tl(tmp, addr, cpu_regs[rs2_or_imm]); 38620880d20bSRichard Henderson } 38630880d20bSRichard Henderson addr = tmp; 38640880d20bSRichard Henderson } 38650880d20bSRichard Henderson if (AM_CHECK(dc)) { 38660880d20bSRichard Henderson if (!tmp) { 38670880d20bSRichard Henderson tmp = tcg_temp_new(); 38680880d20bSRichard Henderson } 38690880d20bSRichard Henderson tcg_gen_ext32u_tl(tmp, addr); 38700880d20bSRichard Henderson addr = tmp; 38710880d20bSRichard Henderson } 38720880d20bSRichard Henderson return addr; 38730880d20bSRichard Henderson } 38740880d20bSRichard Henderson 38750880d20bSRichard Henderson static bool do_ld_gpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp mop) 38760880d20bSRichard Henderson { 38770880d20bSRichard Henderson TCGv reg, addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 38780880d20bSRichard Henderson DisasASI da; 38790880d20bSRichard Henderson 38800880d20bSRichard Henderson if (addr == NULL) { 38810880d20bSRichard Henderson return false; 38820880d20bSRichard Henderson } 38830880d20bSRichard Henderson da = resolve_asi(dc, a->asi, mop); 38840880d20bSRichard Henderson 38850880d20bSRichard Henderson reg = gen_dest_gpr(dc, a->rd); 388642071fc1SRichard Henderson gen_ld_asi(dc, &da, reg, addr); 38870880d20bSRichard Henderson gen_store_gpr(dc, a->rd, reg); 38880880d20bSRichard Henderson return advance_pc(dc); 38890880d20bSRichard Henderson } 38900880d20bSRichard Henderson 38910880d20bSRichard Henderson TRANS(LDUW, ALL, do_ld_gpr, a, MO_TEUL) 38920880d20bSRichard Henderson TRANS(LDUB, ALL, do_ld_gpr, a, MO_UB) 38930880d20bSRichard Henderson TRANS(LDUH, ALL, do_ld_gpr, a, MO_TEUW) 38940880d20bSRichard Henderson TRANS(LDSB, ALL, do_ld_gpr, a, MO_SB) 38950880d20bSRichard Henderson TRANS(LDSH, ALL, do_ld_gpr, a, MO_TESW) 38960880d20bSRichard Henderson TRANS(LDSW, 64, do_ld_gpr, a, MO_TESL) 38970880d20bSRichard Henderson TRANS(LDX, 64, do_ld_gpr, a, MO_TEUQ) 38980880d20bSRichard Henderson 38990880d20bSRichard Henderson static bool do_st_gpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp mop) 39000880d20bSRichard Henderson { 39010880d20bSRichard Henderson TCGv reg, addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 39020880d20bSRichard Henderson DisasASI da; 39030880d20bSRichard Henderson 39040880d20bSRichard Henderson if (addr == NULL) { 39050880d20bSRichard Henderson return false; 39060880d20bSRichard Henderson } 39070880d20bSRichard Henderson da = resolve_asi(dc, a->asi, mop); 39080880d20bSRichard Henderson 39090880d20bSRichard Henderson reg = gen_load_gpr(dc, a->rd); 391042071fc1SRichard Henderson gen_st_asi(dc, &da, reg, addr); 39110880d20bSRichard Henderson return advance_pc(dc); 39120880d20bSRichard Henderson } 39130880d20bSRichard Henderson 39140880d20bSRichard Henderson TRANS(STW, ALL, do_st_gpr, a, MO_TEUL) 39150880d20bSRichard Henderson TRANS(STB, ALL, do_st_gpr, a, MO_UB) 39160880d20bSRichard Henderson TRANS(STH, ALL, do_st_gpr, a, MO_TEUW) 39170880d20bSRichard Henderson TRANS(STX, 64, do_st_gpr, a, MO_TEUQ) 39180880d20bSRichard Henderson 39190880d20bSRichard Henderson static bool trans_LDD(DisasContext *dc, arg_r_r_ri_asi *a) 39200880d20bSRichard Henderson { 39210880d20bSRichard Henderson TCGv addr; 39220880d20bSRichard Henderson DisasASI da; 39230880d20bSRichard Henderson 39240880d20bSRichard Henderson if (a->rd & 1) { 39250880d20bSRichard Henderson return false; 39260880d20bSRichard Henderson } 39270880d20bSRichard Henderson addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 39280880d20bSRichard Henderson if (addr == NULL) { 39290880d20bSRichard Henderson return false; 39300880d20bSRichard Henderson } 39310880d20bSRichard Henderson da = resolve_asi(dc, a->asi, MO_TEUQ); 393242071fc1SRichard Henderson gen_ldda_asi(dc, &da, addr, a->rd); 39330880d20bSRichard Henderson return advance_pc(dc); 39340880d20bSRichard Henderson } 39350880d20bSRichard Henderson 39360880d20bSRichard Henderson static bool trans_STD(DisasContext *dc, arg_r_r_ri_asi *a) 39370880d20bSRichard Henderson { 39380880d20bSRichard Henderson TCGv addr; 39390880d20bSRichard Henderson DisasASI da; 39400880d20bSRichard Henderson 39410880d20bSRichard Henderson if (a->rd & 1) { 39420880d20bSRichard Henderson return false; 39430880d20bSRichard Henderson } 39440880d20bSRichard Henderson addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 39450880d20bSRichard Henderson if (addr == NULL) { 39460880d20bSRichard Henderson return false; 39470880d20bSRichard Henderson } 39480880d20bSRichard Henderson da = resolve_asi(dc, a->asi, MO_TEUQ); 394942071fc1SRichard Henderson gen_stda_asi(dc, &da, addr, a->rd); 39500880d20bSRichard Henderson return advance_pc(dc); 39510880d20bSRichard Henderson } 39520880d20bSRichard Henderson 3953cf07cd1eSRichard Henderson static bool trans_LDSTUB(DisasContext *dc, arg_r_r_ri_asi *a) 3954cf07cd1eSRichard Henderson { 3955cf07cd1eSRichard Henderson TCGv addr, reg; 3956cf07cd1eSRichard Henderson DisasASI da; 3957cf07cd1eSRichard Henderson 3958cf07cd1eSRichard Henderson addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 3959cf07cd1eSRichard Henderson if (addr == NULL) { 3960cf07cd1eSRichard Henderson return false; 3961cf07cd1eSRichard Henderson } 3962cf07cd1eSRichard Henderson da = resolve_asi(dc, a->asi, MO_UB); 3963cf07cd1eSRichard Henderson 3964cf07cd1eSRichard Henderson reg = gen_dest_gpr(dc, a->rd); 3965cf07cd1eSRichard Henderson gen_ldstub_asi(dc, &da, reg, addr); 3966cf07cd1eSRichard Henderson gen_store_gpr(dc, a->rd, reg); 3967cf07cd1eSRichard Henderson return advance_pc(dc); 3968cf07cd1eSRichard Henderson } 3969cf07cd1eSRichard Henderson 3970dca544b9SRichard Henderson static bool trans_SWAP(DisasContext *dc, arg_r_r_ri_asi *a) 3971dca544b9SRichard Henderson { 3972dca544b9SRichard Henderson TCGv addr, dst, src; 3973dca544b9SRichard Henderson DisasASI da; 3974dca544b9SRichard Henderson 3975dca544b9SRichard Henderson addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 3976dca544b9SRichard Henderson if (addr == NULL) { 3977dca544b9SRichard Henderson return false; 3978dca544b9SRichard Henderson } 3979dca544b9SRichard Henderson da = resolve_asi(dc, a->asi, MO_TEUL); 3980dca544b9SRichard Henderson 3981dca544b9SRichard Henderson dst = gen_dest_gpr(dc, a->rd); 3982dca544b9SRichard Henderson src = gen_load_gpr(dc, a->rd); 3983dca544b9SRichard Henderson gen_swap_asi(dc, &da, dst, src, addr); 3984dca544b9SRichard Henderson gen_store_gpr(dc, a->rd, dst); 3985dca544b9SRichard Henderson return advance_pc(dc); 3986dca544b9SRichard Henderson } 3987dca544b9SRichard Henderson 3988d0a11d25SRichard Henderson static bool do_casa(DisasContext *dc, arg_r_r_ri_asi *a, MemOp mop) 3989d0a11d25SRichard Henderson { 3990d0a11d25SRichard Henderson TCGv addr, o, n, c; 3991d0a11d25SRichard Henderson DisasASI da; 3992d0a11d25SRichard Henderson 3993d0a11d25SRichard Henderson addr = gen_ldst_addr(dc, a->rs1, true, 0); 3994d0a11d25SRichard Henderson if (addr == NULL) { 3995d0a11d25SRichard Henderson return false; 3996d0a11d25SRichard Henderson } 3997d0a11d25SRichard Henderson da = resolve_asi(dc, a->asi, mop); 3998d0a11d25SRichard Henderson 3999d0a11d25SRichard Henderson o = gen_dest_gpr(dc, a->rd); 4000d0a11d25SRichard Henderson n = gen_load_gpr(dc, a->rd); 4001d0a11d25SRichard Henderson c = gen_load_gpr(dc, a->rs2_or_imm); 4002d0a11d25SRichard Henderson gen_cas_asi(dc, &da, o, n, c, addr); 4003d0a11d25SRichard Henderson gen_store_gpr(dc, a->rd, o); 4004d0a11d25SRichard Henderson return advance_pc(dc); 4005d0a11d25SRichard Henderson } 4006d0a11d25SRichard Henderson 4007d0a11d25SRichard Henderson TRANS(CASA, CASA, do_casa, a, MO_TEUL) 4008d0a11d25SRichard Henderson TRANS(CASXA, 64, do_casa, a, MO_TEUQ) 4009d0a11d25SRichard Henderson 401006c060d9SRichard Henderson static bool do_ld_fpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp sz) 401106c060d9SRichard Henderson { 401206c060d9SRichard Henderson TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 401306c060d9SRichard Henderson DisasASI da; 401406c060d9SRichard Henderson 401506c060d9SRichard Henderson if (addr == NULL) { 401606c060d9SRichard Henderson return false; 401706c060d9SRichard Henderson } 401806c060d9SRichard Henderson if (gen_trap_ifnofpu(dc)) { 401906c060d9SRichard Henderson return true; 402006c060d9SRichard Henderson } 402106c060d9SRichard Henderson if (sz == MO_128 && gen_trap_float128(dc)) { 402206c060d9SRichard Henderson return true; 402306c060d9SRichard Henderson } 402406c060d9SRichard Henderson da = resolve_asi(dc, a->asi, MO_TE | sz); 4025287b1152SRichard Henderson gen_ldf_asi(dc, &da, sz, addr, a->rd); 402606c060d9SRichard Henderson gen_update_fprs_dirty(dc, a->rd); 402706c060d9SRichard Henderson return advance_pc(dc); 402806c060d9SRichard Henderson } 402906c060d9SRichard Henderson 403006c060d9SRichard Henderson TRANS(LDF, ALL, do_ld_fpr, a, MO_32) 403106c060d9SRichard Henderson TRANS(LDDF, ALL, do_ld_fpr, a, MO_64) 403206c060d9SRichard Henderson TRANS(LDQF, ALL, do_ld_fpr, a, MO_128) 403306c060d9SRichard Henderson 4034287b1152SRichard Henderson TRANS(LDFA, 64, do_ld_fpr, a, MO_32) 4035287b1152SRichard Henderson TRANS(LDDFA, 64, do_ld_fpr, a, MO_64) 4036287b1152SRichard Henderson TRANS(LDQFA, 64, do_ld_fpr, a, MO_128) 4037287b1152SRichard Henderson 403806c060d9SRichard Henderson static bool do_st_fpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp sz) 403906c060d9SRichard Henderson { 404006c060d9SRichard Henderson TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 404106c060d9SRichard Henderson DisasASI da; 404206c060d9SRichard Henderson 404306c060d9SRichard Henderson if (addr == NULL) { 404406c060d9SRichard Henderson return false; 404506c060d9SRichard Henderson } 404606c060d9SRichard Henderson if (gen_trap_ifnofpu(dc)) { 404706c060d9SRichard Henderson return true; 404806c060d9SRichard Henderson } 404906c060d9SRichard Henderson if (sz == MO_128 && gen_trap_float128(dc)) { 405006c060d9SRichard Henderson return true; 405106c060d9SRichard Henderson } 405206c060d9SRichard Henderson da = resolve_asi(dc, a->asi, MO_TE | sz); 4053287b1152SRichard Henderson gen_stf_asi(dc, &da, sz, addr, a->rd); 405406c060d9SRichard Henderson return advance_pc(dc); 405506c060d9SRichard Henderson } 405606c060d9SRichard Henderson 405706c060d9SRichard Henderson TRANS(STF, ALL, do_st_fpr, a, MO_32) 405806c060d9SRichard Henderson TRANS(STDF, ALL, do_st_fpr, a, MO_64) 405906c060d9SRichard Henderson TRANS(STQF, ALL, do_st_fpr, a, MO_128) 406006c060d9SRichard Henderson 4061287b1152SRichard Henderson TRANS(STFA, 64, do_st_fpr, a, MO_32) 4062287b1152SRichard Henderson TRANS(STDFA, 64, do_st_fpr, a, MO_64) 4063287b1152SRichard Henderson TRANS(STQFA, 64, do_st_fpr, a, MO_128) 4064287b1152SRichard Henderson 406506c060d9SRichard Henderson static bool trans_STDFQ(DisasContext *dc, arg_STDFQ *a) 406606c060d9SRichard Henderson { 406706c060d9SRichard Henderson if (!avail_32(dc)) { 406806c060d9SRichard Henderson return false; 406906c060d9SRichard Henderson } 407006c060d9SRichard Henderson if (!supervisor(dc)) { 407106c060d9SRichard Henderson return raise_priv(dc); 407206c060d9SRichard Henderson } 407306c060d9SRichard Henderson if (gen_trap_ifnofpu(dc)) { 407406c060d9SRichard Henderson return true; 407506c060d9SRichard Henderson } 407606c060d9SRichard Henderson gen_op_fpexception_im(dc, FSR_FTT_SEQ_ERROR); 407706c060d9SRichard Henderson return true; 407806c060d9SRichard Henderson } 407906c060d9SRichard Henderson 4080d8c5b92fSRichard Henderson static bool trans_LDFSR(DisasContext *dc, arg_r_r_ri *a) 40813d3c0673SRichard Henderson { 40823590f01eSRichard Henderson TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 4083d8c5b92fSRichard Henderson TCGv_i32 tmp; 40843590f01eSRichard Henderson 40853d3c0673SRichard Henderson if (addr == NULL) { 40863d3c0673SRichard Henderson return false; 40873d3c0673SRichard Henderson } 40883d3c0673SRichard Henderson if (gen_trap_ifnofpu(dc)) { 40893d3c0673SRichard Henderson return true; 40903d3c0673SRichard Henderson } 4091d8c5b92fSRichard Henderson 4092d8c5b92fSRichard Henderson tmp = tcg_temp_new_i32(); 4093d8c5b92fSRichard Henderson tcg_gen_qemu_ld_i32(tmp, addr, dc->mem_idx, MO_TEUL | MO_ALIGN); 4094d8c5b92fSRichard Henderson 4095d8c5b92fSRichard Henderson tcg_gen_extract_i32(cpu_fcc[0], tmp, FSR_FCC0_SHIFT, 2); 4096d8c5b92fSRichard Henderson /* LDFSR does not change FCC[1-3]. */ 4097d8c5b92fSRichard Henderson 4098d8c5b92fSRichard Henderson gen_helper_set_fsr_nofcc_noftt(tcg_env, tmp); 40993d3c0673SRichard Henderson return advance_pc(dc); 41003d3c0673SRichard Henderson } 41013d3c0673SRichard Henderson 4102d8c5b92fSRichard Henderson static bool trans_LDXFSR(DisasContext *dc, arg_r_r_ri *a) 4103d8c5b92fSRichard Henderson { 4104d8c5b92fSRichard Henderson #ifdef TARGET_SPARC64 4105d8c5b92fSRichard Henderson TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 4106d8c5b92fSRichard Henderson TCGv_i64 t64; 4107d8c5b92fSRichard Henderson TCGv_i32 lo, hi; 4108d8c5b92fSRichard Henderson 4109d8c5b92fSRichard Henderson if (addr == NULL) { 4110d8c5b92fSRichard Henderson return false; 4111d8c5b92fSRichard Henderson } 4112d8c5b92fSRichard Henderson if (gen_trap_ifnofpu(dc)) { 4113d8c5b92fSRichard Henderson return true; 4114d8c5b92fSRichard Henderson } 4115d8c5b92fSRichard Henderson 4116d8c5b92fSRichard Henderson t64 = tcg_temp_new_i64(); 4117d8c5b92fSRichard Henderson tcg_gen_qemu_ld_i64(t64, addr, dc->mem_idx, MO_TEUQ | MO_ALIGN); 4118d8c5b92fSRichard Henderson 4119d8c5b92fSRichard Henderson lo = tcg_temp_new_i32(); 4120d8c5b92fSRichard Henderson hi = cpu_fcc[3]; 4121d8c5b92fSRichard Henderson tcg_gen_extr_i64_i32(lo, hi, t64); 4122d8c5b92fSRichard Henderson tcg_gen_extract_i32(cpu_fcc[0], lo, FSR_FCC0_SHIFT, 2); 4123d8c5b92fSRichard Henderson tcg_gen_extract_i32(cpu_fcc[1], hi, FSR_FCC1_SHIFT - 32, 2); 4124d8c5b92fSRichard Henderson tcg_gen_extract_i32(cpu_fcc[2], hi, FSR_FCC2_SHIFT - 32, 2); 4125d8c5b92fSRichard Henderson tcg_gen_extract_i32(cpu_fcc[3], hi, FSR_FCC3_SHIFT - 32, 2); 4126d8c5b92fSRichard Henderson 4127d8c5b92fSRichard Henderson gen_helper_set_fsr_nofcc_noftt(tcg_env, lo); 4128d8c5b92fSRichard Henderson return advance_pc(dc); 4129d8c5b92fSRichard Henderson #else 4130d8c5b92fSRichard Henderson return false; 4131d8c5b92fSRichard Henderson #endif 4132d8c5b92fSRichard Henderson } 41333d3c0673SRichard Henderson 41343d3c0673SRichard Henderson static bool do_stfsr(DisasContext *dc, arg_r_r_ri *a, MemOp mop) 41353d3c0673SRichard Henderson { 41363d3c0673SRichard Henderson TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm); 41371ccd6e13SRichard Henderson TCGv fsr; 41381ccd6e13SRichard Henderson 41393d3c0673SRichard Henderson if (addr == NULL) { 41403d3c0673SRichard Henderson return false; 41413d3c0673SRichard Henderson } 41423d3c0673SRichard Henderson if (gen_trap_ifnofpu(dc)) { 41433d3c0673SRichard Henderson return true; 41443d3c0673SRichard Henderson } 41451ccd6e13SRichard Henderson 41461ccd6e13SRichard Henderson fsr = tcg_temp_new(); 41471ccd6e13SRichard Henderson gen_helper_get_fsr(fsr, tcg_env); 41481ccd6e13SRichard Henderson tcg_gen_qemu_st_tl(fsr, addr, dc->mem_idx, mop | MO_ALIGN); 41493d3c0673SRichard Henderson return advance_pc(dc); 41503d3c0673SRichard Henderson } 41513d3c0673SRichard Henderson 41523d3c0673SRichard Henderson TRANS(STFSR, ALL, do_stfsr, a, MO_TEUL) 41533d3c0673SRichard Henderson TRANS(STXFSR, 64, do_stfsr, a, MO_TEUQ) 41543d3c0673SRichard Henderson 41553a38260eSRichard Henderson static bool do_fc(DisasContext *dc, int rd, bool c) 41563a38260eSRichard Henderson { 41573a38260eSRichard Henderson uint64_t mask; 41583a38260eSRichard Henderson 41593a38260eSRichard Henderson if (gen_trap_ifnofpu(dc)) { 41603a38260eSRichard Henderson return true; 41613a38260eSRichard Henderson } 41623a38260eSRichard Henderson 41633a38260eSRichard Henderson if (rd & 1) { 41643a38260eSRichard Henderson mask = MAKE_64BIT_MASK(0, 32); 41653a38260eSRichard Henderson } else { 41663a38260eSRichard Henderson mask = MAKE_64BIT_MASK(32, 32); 41673a38260eSRichard Henderson } 41683a38260eSRichard Henderson if (c) { 41693a38260eSRichard Henderson tcg_gen_ori_i64(cpu_fpr[rd / 2], cpu_fpr[rd / 2], mask); 41703a38260eSRichard Henderson } else { 41713a38260eSRichard Henderson tcg_gen_andi_i64(cpu_fpr[rd / 2], cpu_fpr[rd / 2], ~mask); 41723a38260eSRichard Henderson } 41733a38260eSRichard Henderson gen_update_fprs_dirty(dc, rd); 41743a38260eSRichard Henderson return advance_pc(dc); 41753a38260eSRichard Henderson } 41763a38260eSRichard Henderson 41773a38260eSRichard Henderson TRANS(FZEROs, VIS1, do_fc, a->rd, 0) 41783a38260eSRichard Henderson TRANS(FONEs, VIS1, do_fc, a->rd, 1) 41793a38260eSRichard Henderson 41803a38260eSRichard Henderson static bool do_dc(DisasContext *dc, int rd, int64_t c) 41813a38260eSRichard Henderson { 41823a38260eSRichard Henderson if (gen_trap_ifnofpu(dc)) { 41833a38260eSRichard Henderson return true; 41843a38260eSRichard Henderson } 41853a38260eSRichard Henderson 41863a38260eSRichard Henderson tcg_gen_movi_i64(cpu_fpr[rd / 2], c); 41873a38260eSRichard Henderson gen_update_fprs_dirty(dc, rd); 41883a38260eSRichard Henderson return advance_pc(dc); 41893a38260eSRichard Henderson } 41903a38260eSRichard Henderson 41913a38260eSRichard Henderson TRANS(FZEROd, VIS1, do_dc, a->rd, 0) 41923a38260eSRichard Henderson TRANS(FONEd, VIS1, do_dc, a->rd, -1) 41933a38260eSRichard Henderson 4194baf3dbf2SRichard Henderson static bool do_ff(DisasContext *dc, arg_r_r *a, 4195baf3dbf2SRichard Henderson void (*func)(TCGv_i32, TCGv_i32)) 4196baf3dbf2SRichard Henderson { 4197baf3dbf2SRichard Henderson TCGv_i32 tmp; 4198baf3dbf2SRichard Henderson 4199baf3dbf2SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4200baf3dbf2SRichard Henderson return true; 4201baf3dbf2SRichard Henderson } 4202baf3dbf2SRichard Henderson 4203baf3dbf2SRichard Henderson tmp = gen_load_fpr_F(dc, a->rs); 4204baf3dbf2SRichard Henderson func(tmp, tmp); 4205baf3dbf2SRichard Henderson gen_store_fpr_F(dc, a->rd, tmp); 4206baf3dbf2SRichard Henderson return advance_pc(dc); 4207baf3dbf2SRichard Henderson } 4208baf3dbf2SRichard Henderson 4209baf3dbf2SRichard Henderson TRANS(FMOVs, ALL, do_ff, a, gen_op_fmovs) 4210baf3dbf2SRichard Henderson TRANS(FNEGs, ALL, do_ff, a, gen_op_fnegs) 4211baf3dbf2SRichard Henderson TRANS(FABSs, ALL, do_ff, a, gen_op_fabss) 4212baf3dbf2SRichard Henderson TRANS(FSRCs, VIS1, do_ff, a, tcg_gen_mov_i32) 4213baf3dbf2SRichard Henderson TRANS(FNOTs, VIS1, do_ff, a, tcg_gen_not_i32) 4214baf3dbf2SRichard Henderson 42152f722641SRichard Henderson static bool do_fd(DisasContext *dc, arg_r_r *a, 42162f722641SRichard Henderson void (*func)(TCGv_i32, TCGv_i64)) 42172f722641SRichard Henderson { 42182f722641SRichard Henderson TCGv_i32 dst; 42192f722641SRichard Henderson TCGv_i64 src; 42202f722641SRichard Henderson 42212f722641SRichard Henderson if (gen_trap_ifnofpu(dc)) { 42222f722641SRichard Henderson return true; 42232f722641SRichard Henderson } 42242f722641SRichard Henderson 4225388a6465SRichard Henderson dst = tcg_temp_new_i32(); 42262f722641SRichard Henderson src = gen_load_fpr_D(dc, a->rs); 42272f722641SRichard Henderson func(dst, src); 42282f722641SRichard Henderson gen_store_fpr_F(dc, a->rd, dst); 42292f722641SRichard Henderson return advance_pc(dc); 42302f722641SRichard Henderson } 42312f722641SRichard Henderson 42322f722641SRichard Henderson TRANS(FPACK16, VIS1, do_fd, a, gen_op_fpack16) 42332f722641SRichard Henderson TRANS(FPACKFIX, VIS1, do_fd, a, gen_op_fpackfix) 42342f722641SRichard Henderson 4235119cb94fSRichard Henderson static bool do_env_ff(DisasContext *dc, arg_r_r *a, 4236119cb94fSRichard Henderson void (*func)(TCGv_i32, TCGv_env, TCGv_i32)) 4237119cb94fSRichard Henderson { 4238119cb94fSRichard Henderson TCGv_i32 tmp; 4239119cb94fSRichard Henderson 4240119cb94fSRichard Henderson if (gen_trap_ifnofpu(dc)) { 4241119cb94fSRichard Henderson return true; 4242119cb94fSRichard Henderson } 4243119cb94fSRichard Henderson 4244119cb94fSRichard Henderson tmp = gen_load_fpr_F(dc, a->rs); 4245119cb94fSRichard Henderson func(tmp, tcg_env, tmp); 4246119cb94fSRichard Henderson gen_store_fpr_F(dc, a->rd, tmp); 4247119cb94fSRichard Henderson return advance_pc(dc); 4248119cb94fSRichard Henderson } 4249119cb94fSRichard Henderson 4250119cb94fSRichard Henderson TRANS(FSQRTs, ALL, do_env_ff, a, gen_helper_fsqrts) 4251119cb94fSRichard Henderson TRANS(FiTOs, ALL, do_env_ff, a, gen_helper_fitos) 4252119cb94fSRichard Henderson TRANS(FsTOi, ALL, do_env_ff, a, gen_helper_fstoi) 4253119cb94fSRichard Henderson 42548c94bcd8SRichard Henderson static bool do_env_fd(DisasContext *dc, arg_r_r *a, 42558c94bcd8SRichard Henderson void (*func)(TCGv_i32, TCGv_env, TCGv_i64)) 42568c94bcd8SRichard Henderson { 42578c94bcd8SRichard Henderson TCGv_i32 dst; 42588c94bcd8SRichard Henderson TCGv_i64 src; 42598c94bcd8SRichard Henderson 42608c94bcd8SRichard Henderson if (gen_trap_ifnofpu(dc)) { 42618c94bcd8SRichard Henderson return true; 42628c94bcd8SRichard Henderson } 42638c94bcd8SRichard Henderson 4264388a6465SRichard Henderson dst = tcg_temp_new_i32(); 42658c94bcd8SRichard Henderson src = gen_load_fpr_D(dc, a->rs); 42668c94bcd8SRichard Henderson func(dst, tcg_env, src); 42678c94bcd8SRichard Henderson gen_store_fpr_F(dc, a->rd, dst); 42688c94bcd8SRichard Henderson return advance_pc(dc); 42698c94bcd8SRichard Henderson } 42708c94bcd8SRichard Henderson 42718c94bcd8SRichard Henderson TRANS(FdTOs, ALL, do_env_fd, a, gen_helper_fdtos) 42728c94bcd8SRichard Henderson TRANS(FdTOi, ALL, do_env_fd, a, gen_helper_fdtoi) 42738c94bcd8SRichard Henderson TRANS(FxTOs, 64, do_env_fd, a, gen_helper_fxtos) 42748c94bcd8SRichard Henderson 4275c6d83e4fSRichard Henderson static bool do_dd(DisasContext *dc, arg_r_r *a, 4276c6d83e4fSRichard Henderson void (*func)(TCGv_i64, TCGv_i64)) 4277c6d83e4fSRichard Henderson { 4278c6d83e4fSRichard Henderson TCGv_i64 dst, src; 4279c6d83e4fSRichard Henderson 4280c6d83e4fSRichard Henderson if (gen_trap_ifnofpu(dc)) { 4281c6d83e4fSRichard Henderson return true; 4282c6d83e4fSRichard Henderson } 4283c6d83e4fSRichard Henderson 4284c6d83e4fSRichard Henderson dst = gen_dest_fpr_D(dc, a->rd); 4285c6d83e4fSRichard Henderson src = gen_load_fpr_D(dc, a->rs); 4286c6d83e4fSRichard Henderson func(dst, src); 4287c6d83e4fSRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 4288c6d83e4fSRichard Henderson return advance_pc(dc); 4289c6d83e4fSRichard Henderson } 4290c6d83e4fSRichard Henderson 4291c6d83e4fSRichard Henderson TRANS(FMOVd, 64, do_dd, a, gen_op_fmovd) 4292c6d83e4fSRichard Henderson TRANS(FNEGd, 64, do_dd, a, gen_op_fnegd) 4293c6d83e4fSRichard Henderson TRANS(FABSd, 64, do_dd, a, gen_op_fabsd) 4294c6d83e4fSRichard Henderson TRANS(FSRCd, VIS1, do_dd, a, tcg_gen_mov_i64) 4295c6d83e4fSRichard Henderson TRANS(FNOTd, VIS1, do_dd, a, tcg_gen_not_i64) 4296c6d83e4fSRichard Henderson 42978aa418b3SRichard Henderson static bool do_env_dd(DisasContext *dc, arg_r_r *a, 42988aa418b3SRichard Henderson void (*func)(TCGv_i64, TCGv_env, TCGv_i64)) 42998aa418b3SRichard Henderson { 43008aa418b3SRichard Henderson TCGv_i64 dst, src; 43018aa418b3SRichard Henderson 43028aa418b3SRichard Henderson if (gen_trap_ifnofpu(dc)) { 43038aa418b3SRichard Henderson return true; 43048aa418b3SRichard Henderson } 43058aa418b3SRichard Henderson 43068aa418b3SRichard Henderson dst = gen_dest_fpr_D(dc, a->rd); 43078aa418b3SRichard Henderson src = gen_load_fpr_D(dc, a->rs); 43088aa418b3SRichard Henderson func(dst, tcg_env, src); 43098aa418b3SRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 43108aa418b3SRichard Henderson return advance_pc(dc); 43118aa418b3SRichard Henderson } 43128aa418b3SRichard Henderson 43138aa418b3SRichard Henderson TRANS(FSQRTd, ALL, do_env_dd, a, gen_helper_fsqrtd) 43148aa418b3SRichard Henderson TRANS(FxTOd, 64, do_env_dd, a, gen_helper_fxtod) 43158aa418b3SRichard Henderson TRANS(FdTOx, 64, do_env_dd, a, gen_helper_fdtox) 43168aa418b3SRichard Henderson 4317199d43efSRichard Henderson static bool do_env_df(DisasContext *dc, arg_r_r *a, 4318199d43efSRichard Henderson void (*func)(TCGv_i64, TCGv_env, TCGv_i32)) 4319199d43efSRichard Henderson { 4320199d43efSRichard Henderson TCGv_i64 dst; 4321199d43efSRichard Henderson TCGv_i32 src; 4322199d43efSRichard Henderson 4323199d43efSRichard Henderson if (gen_trap_ifnofpu(dc)) { 4324199d43efSRichard Henderson return true; 4325199d43efSRichard Henderson } 4326199d43efSRichard Henderson 4327199d43efSRichard Henderson dst = gen_dest_fpr_D(dc, a->rd); 4328199d43efSRichard Henderson src = gen_load_fpr_F(dc, a->rs); 4329199d43efSRichard Henderson func(dst, tcg_env, src); 4330199d43efSRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 4331199d43efSRichard Henderson return advance_pc(dc); 4332199d43efSRichard Henderson } 4333199d43efSRichard Henderson 4334199d43efSRichard Henderson TRANS(FiTOd, ALL, do_env_df, a, gen_helper_fitod) 4335199d43efSRichard Henderson TRANS(FsTOd, ALL, do_env_df, a, gen_helper_fstod) 4336199d43efSRichard Henderson TRANS(FsTOx, 64, do_env_df, a, gen_helper_fstox) 4337199d43efSRichard Henderson 4338daf457d4SRichard Henderson static bool do_qq(DisasContext *dc, arg_r_r *a, 4339daf457d4SRichard Henderson void (*func)(TCGv_i128, TCGv_i128)) 4340f4e18df5SRichard Henderson { 434133ec4245SRichard Henderson TCGv_i128 t; 4342f4e18df5SRichard Henderson 4343f4e18df5SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4344f4e18df5SRichard Henderson return true; 4345f4e18df5SRichard Henderson } 4346f4e18df5SRichard Henderson if (gen_trap_float128(dc)) { 4347f4e18df5SRichard Henderson return true; 4348f4e18df5SRichard Henderson } 4349f4e18df5SRichard Henderson 4350f4e18df5SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 435133ec4245SRichard Henderson t = gen_load_fpr_Q(dc, a->rs); 4352daf457d4SRichard Henderson func(t, t); 435333ec4245SRichard Henderson gen_store_fpr_Q(dc, a->rd, t); 4354f4e18df5SRichard Henderson return advance_pc(dc); 4355f4e18df5SRichard Henderson } 4356f4e18df5SRichard Henderson 4357daf457d4SRichard Henderson TRANS(FMOVq, 64, do_qq, a, tcg_gen_mov_i128) 4358daf457d4SRichard Henderson TRANS(FNEGq, 64, do_qq, a, gen_op_fnegq) 4359daf457d4SRichard Henderson TRANS(FABSq, 64, do_qq, a, gen_op_fabsq) 4360f4e18df5SRichard Henderson 4361c995216bSRichard Henderson static bool do_env_qq(DisasContext *dc, arg_r_r *a, 4362e41716beSRichard Henderson void (*func)(TCGv_i128, TCGv_env, TCGv_i128)) 4363c995216bSRichard Henderson { 4364e41716beSRichard Henderson TCGv_i128 t; 4365e41716beSRichard Henderson 4366c995216bSRichard Henderson if (gen_trap_ifnofpu(dc)) { 4367c995216bSRichard Henderson return true; 4368c995216bSRichard Henderson } 4369c995216bSRichard Henderson if (gen_trap_float128(dc)) { 4370c995216bSRichard Henderson return true; 4371c995216bSRichard Henderson } 4372c995216bSRichard Henderson 4373e41716beSRichard Henderson t = gen_load_fpr_Q(dc, a->rs); 4374e41716beSRichard Henderson func(t, tcg_env, t); 4375e41716beSRichard Henderson gen_store_fpr_Q(dc, a->rd, t); 4376c995216bSRichard Henderson return advance_pc(dc); 4377c995216bSRichard Henderson } 4378c995216bSRichard Henderson 4379c995216bSRichard Henderson TRANS(FSQRTq, ALL, do_env_qq, a, gen_helper_fsqrtq) 4380c995216bSRichard Henderson 4381bd9c5c42SRichard Henderson static bool do_env_fq(DisasContext *dc, arg_r_r *a, 4382d81e3efeSRichard Henderson void (*func)(TCGv_i32, TCGv_env, TCGv_i128)) 4383bd9c5c42SRichard Henderson { 4384d81e3efeSRichard Henderson TCGv_i128 src; 4385bd9c5c42SRichard Henderson TCGv_i32 dst; 4386bd9c5c42SRichard Henderson 4387bd9c5c42SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4388bd9c5c42SRichard Henderson return true; 4389bd9c5c42SRichard Henderson } 4390bd9c5c42SRichard Henderson if (gen_trap_float128(dc)) { 4391bd9c5c42SRichard Henderson return true; 4392bd9c5c42SRichard Henderson } 4393bd9c5c42SRichard Henderson 4394d81e3efeSRichard Henderson src = gen_load_fpr_Q(dc, a->rs); 4395388a6465SRichard Henderson dst = tcg_temp_new_i32(); 4396d81e3efeSRichard Henderson func(dst, tcg_env, src); 4397bd9c5c42SRichard Henderson gen_store_fpr_F(dc, a->rd, dst); 4398bd9c5c42SRichard Henderson return advance_pc(dc); 4399bd9c5c42SRichard Henderson } 4400bd9c5c42SRichard Henderson 4401bd9c5c42SRichard Henderson TRANS(FqTOs, ALL, do_env_fq, a, gen_helper_fqtos) 4402bd9c5c42SRichard Henderson TRANS(FqTOi, ALL, do_env_fq, a, gen_helper_fqtoi) 4403bd9c5c42SRichard Henderson 44041617586fSRichard Henderson static bool do_env_dq(DisasContext *dc, arg_r_r *a, 440525a5769eSRichard Henderson void (*func)(TCGv_i64, TCGv_env, TCGv_i128)) 44061617586fSRichard Henderson { 440725a5769eSRichard Henderson TCGv_i128 src; 44081617586fSRichard Henderson TCGv_i64 dst; 44091617586fSRichard Henderson 44101617586fSRichard Henderson if (gen_trap_ifnofpu(dc)) { 44111617586fSRichard Henderson return true; 44121617586fSRichard Henderson } 44131617586fSRichard Henderson if (gen_trap_float128(dc)) { 44141617586fSRichard Henderson return true; 44151617586fSRichard Henderson } 44161617586fSRichard Henderson 441725a5769eSRichard Henderson src = gen_load_fpr_Q(dc, a->rs); 44181617586fSRichard Henderson dst = gen_dest_fpr_D(dc, a->rd); 441925a5769eSRichard Henderson func(dst, tcg_env, src); 44201617586fSRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 44211617586fSRichard Henderson return advance_pc(dc); 44221617586fSRichard Henderson } 44231617586fSRichard Henderson 44241617586fSRichard Henderson TRANS(FqTOd, ALL, do_env_dq, a, gen_helper_fqtod) 44251617586fSRichard Henderson TRANS(FqTOx, 64, do_env_dq, a, gen_helper_fqtox) 44261617586fSRichard Henderson 442713ebcc77SRichard Henderson static bool do_env_qf(DisasContext *dc, arg_r_r *a, 44280b2a61ccSRichard Henderson void (*func)(TCGv_i128, TCGv_env, TCGv_i32)) 442913ebcc77SRichard Henderson { 443013ebcc77SRichard Henderson TCGv_i32 src; 44310b2a61ccSRichard Henderson TCGv_i128 dst; 443213ebcc77SRichard Henderson 443313ebcc77SRichard Henderson if (gen_trap_ifnofpu(dc)) { 443413ebcc77SRichard Henderson return true; 443513ebcc77SRichard Henderson } 443613ebcc77SRichard Henderson if (gen_trap_float128(dc)) { 443713ebcc77SRichard Henderson return true; 443813ebcc77SRichard Henderson } 443913ebcc77SRichard Henderson 444013ebcc77SRichard Henderson src = gen_load_fpr_F(dc, a->rs); 44410b2a61ccSRichard Henderson dst = tcg_temp_new_i128(); 44420b2a61ccSRichard Henderson func(dst, tcg_env, src); 44430b2a61ccSRichard Henderson gen_store_fpr_Q(dc, a->rd, dst); 444413ebcc77SRichard Henderson return advance_pc(dc); 444513ebcc77SRichard Henderson } 444613ebcc77SRichard Henderson 444713ebcc77SRichard Henderson TRANS(FiTOq, ALL, do_env_qf, a, gen_helper_fitoq) 444813ebcc77SRichard Henderson TRANS(FsTOq, ALL, do_env_qf, a, gen_helper_fstoq) 444913ebcc77SRichard Henderson 44507b8e3e1aSRichard Henderson static bool do_env_qd(DisasContext *dc, arg_r_r *a, 4451fdc50716SRichard Henderson void (*func)(TCGv_i128, TCGv_env, TCGv_i64)) 44527b8e3e1aSRichard Henderson { 44537b8e3e1aSRichard Henderson TCGv_i64 src; 4454fdc50716SRichard Henderson TCGv_i128 dst; 44557b8e3e1aSRichard Henderson 44567b8e3e1aSRichard Henderson if (gen_trap_ifnofpu(dc)) { 44577b8e3e1aSRichard Henderson return true; 44587b8e3e1aSRichard Henderson } 44597b8e3e1aSRichard Henderson if (gen_trap_float128(dc)) { 44607b8e3e1aSRichard Henderson return true; 44617b8e3e1aSRichard Henderson } 44627b8e3e1aSRichard Henderson 44637b8e3e1aSRichard Henderson src = gen_load_fpr_D(dc, a->rs); 4464fdc50716SRichard Henderson dst = tcg_temp_new_i128(); 4465fdc50716SRichard Henderson func(dst, tcg_env, src); 4466fdc50716SRichard Henderson gen_store_fpr_Q(dc, a->rd, dst); 44677b8e3e1aSRichard Henderson return advance_pc(dc); 44687b8e3e1aSRichard Henderson } 44697b8e3e1aSRichard Henderson 44707b8e3e1aSRichard Henderson TRANS(FdTOq, ALL, do_env_qd, a, gen_helper_fdtoq) 44717b8e3e1aSRichard Henderson TRANS(FxTOq, 64, do_env_qd, a, gen_helper_fxtoq) 44727b8e3e1aSRichard Henderson 44737f10b52fSRichard Henderson static bool do_fff(DisasContext *dc, arg_r_r_r *a, 44747f10b52fSRichard Henderson void (*func)(TCGv_i32, TCGv_i32, TCGv_i32)) 44757f10b52fSRichard Henderson { 44767f10b52fSRichard Henderson TCGv_i32 src1, src2; 44777f10b52fSRichard Henderson 44787f10b52fSRichard Henderson if (gen_trap_ifnofpu(dc)) { 44797f10b52fSRichard Henderson return true; 44807f10b52fSRichard Henderson } 44817f10b52fSRichard Henderson 44827f10b52fSRichard Henderson src1 = gen_load_fpr_F(dc, a->rs1); 44837f10b52fSRichard Henderson src2 = gen_load_fpr_F(dc, a->rs2); 44847f10b52fSRichard Henderson func(src1, src1, src2); 44857f10b52fSRichard Henderson gen_store_fpr_F(dc, a->rd, src1); 44867f10b52fSRichard Henderson return advance_pc(dc); 44877f10b52fSRichard Henderson } 44887f10b52fSRichard Henderson 44897f10b52fSRichard Henderson TRANS(FPADD16s, VIS1, do_fff, a, tcg_gen_vec_add16_i32) 44907f10b52fSRichard Henderson TRANS(FPADD32s, VIS1, do_fff, a, tcg_gen_add_i32) 44917f10b52fSRichard Henderson TRANS(FPSUB16s, VIS1, do_fff, a, tcg_gen_vec_sub16_i32) 44927f10b52fSRichard Henderson TRANS(FPSUB32s, VIS1, do_fff, a, tcg_gen_sub_i32) 44937f10b52fSRichard Henderson TRANS(FNORs, VIS1, do_fff, a, tcg_gen_nor_i32) 44947f10b52fSRichard Henderson TRANS(FANDNOTs, VIS1, do_fff, a, tcg_gen_andc_i32) 44957f10b52fSRichard Henderson TRANS(FXORs, VIS1, do_fff, a, tcg_gen_xor_i32) 44967f10b52fSRichard Henderson TRANS(FNANDs, VIS1, do_fff, a, tcg_gen_nand_i32) 44977f10b52fSRichard Henderson TRANS(FANDs, VIS1, do_fff, a, tcg_gen_and_i32) 44987f10b52fSRichard Henderson TRANS(FXNORs, VIS1, do_fff, a, tcg_gen_eqv_i32) 44997f10b52fSRichard Henderson TRANS(FORNOTs, VIS1, do_fff, a, tcg_gen_orc_i32) 45007f10b52fSRichard Henderson TRANS(FORs, VIS1, do_fff, a, tcg_gen_or_i32) 45017f10b52fSRichard Henderson 4502c1514961SRichard Henderson static bool do_env_fff(DisasContext *dc, arg_r_r_r *a, 4503c1514961SRichard Henderson void (*func)(TCGv_i32, TCGv_env, TCGv_i32, TCGv_i32)) 4504c1514961SRichard Henderson { 4505c1514961SRichard Henderson TCGv_i32 src1, src2; 4506c1514961SRichard Henderson 4507c1514961SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4508c1514961SRichard Henderson return true; 4509c1514961SRichard Henderson } 4510c1514961SRichard Henderson 4511c1514961SRichard Henderson src1 = gen_load_fpr_F(dc, a->rs1); 4512c1514961SRichard Henderson src2 = gen_load_fpr_F(dc, a->rs2); 4513c1514961SRichard Henderson func(src1, tcg_env, src1, src2); 4514c1514961SRichard Henderson gen_store_fpr_F(dc, a->rd, src1); 4515c1514961SRichard Henderson return advance_pc(dc); 4516c1514961SRichard Henderson } 4517c1514961SRichard Henderson 4518c1514961SRichard Henderson TRANS(FADDs, ALL, do_env_fff, a, gen_helper_fadds) 4519c1514961SRichard Henderson TRANS(FSUBs, ALL, do_env_fff, a, gen_helper_fsubs) 4520c1514961SRichard Henderson TRANS(FMULs, ALL, do_env_fff, a, gen_helper_fmuls) 4521c1514961SRichard Henderson TRANS(FDIVs, ALL, do_env_fff, a, gen_helper_fdivs) 4522c1514961SRichard Henderson 4523e06c9f83SRichard Henderson static bool do_ddd(DisasContext *dc, arg_r_r_r *a, 4524e06c9f83SRichard Henderson void (*func)(TCGv_i64, TCGv_i64, TCGv_i64)) 4525e06c9f83SRichard Henderson { 4526e06c9f83SRichard Henderson TCGv_i64 dst, src1, src2; 4527e06c9f83SRichard Henderson 4528e06c9f83SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4529e06c9f83SRichard Henderson return true; 4530e06c9f83SRichard Henderson } 4531e06c9f83SRichard Henderson 4532e06c9f83SRichard Henderson dst = gen_dest_fpr_D(dc, a->rd); 4533e06c9f83SRichard Henderson src1 = gen_load_fpr_D(dc, a->rs1); 4534e06c9f83SRichard Henderson src2 = gen_load_fpr_D(dc, a->rs2); 4535e06c9f83SRichard Henderson func(dst, src1, src2); 4536e06c9f83SRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 4537e06c9f83SRichard Henderson return advance_pc(dc); 4538e06c9f83SRichard Henderson } 4539e06c9f83SRichard Henderson 4540e06c9f83SRichard Henderson TRANS(FMUL8x16, VIS1, do_ddd, a, gen_helper_fmul8x16) 4541e06c9f83SRichard Henderson TRANS(FMUL8x16AU, VIS1, do_ddd, a, gen_helper_fmul8x16au) 4542e06c9f83SRichard Henderson TRANS(FMUL8x16AL, VIS1, do_ddd, a, gen_helper_fmul8x16al) 4543e06c9f83SRichard Henderson TRANS(FMUL8SUx16, VIS1, do_ddd, a, gen_helper_fmul8sux16) 4544e06c9f83SRichard Henderson TRANS(FMUL8ULx16, VIS1, do_ddd, a, gen_helper_fmul8ulx16) 4545e06c9f83SRichard Henderson TRANS(FMULD8SUx16, VIS1, do_ddd, a, gen_helper_fmuld8sux16) 4546e06c9f83SRichard Henderson TRANS(FMULD8ULx16, VIS1, do_ddd, a, gen_helper_fmuld8ulx16) 4547e06c9f83SRichard Henderson TRANS(FPMERGE, VIS1, do_ddd, a, gen_helper_fpmerge) 4548e06c9f83SRichard Henderson TRANS(FEXPAND, VIS1, do_ddd, a, gen_helper_fexpand) 4549e06c9f83SRichard Henderson 4550e06c9f83SRichard Henderson TRANS(FPADD16, VIS1, do_ddd, a, tcg_gen_vec_add16_i64) 4551e06c9f83SRichard Henderson TRANS(FPADD32, VIS1, do_ddd, a, tcg_gen_vec_add32_i64) 4552e06c9f83SRichard Henderson TRANS(FPSUB16, VIS1, do_ddd, a, tcg_gen_vec_sub16_i64) 4553e06c9f83SRichard Henderson TRANS(FPSUB32, VIS1, do_ddd, a, tcg_gen_vec_sub32_i64) 4554e06c9f83SRichard Henderson TRANS(FNORd, VIS1, do_ddd, a, tcg_gen_nor_i64) 4555e06c9f83SRichard Henderson TRANS(FANDNOTd, VIS1, do_ddd, a, tcg_gen_andc_i64) 4556e06c9f83SRichard Henderson TRANS(FXORd, VIS1, do_ddd, a, tcg_gen_xor_i64) 4557e06c9f83SRichard Henderson TRANS(FNANDd, VIS1, do_ddd, a, tcg_gen_nand_i64) 4558e06c9f83SRichard Henderson TRANS(FANDd, VIS1, do_ddd, a, tcg_gen_and_i64) 4559e06c9f83SRichard Henderson TRANS(FXNORd, VIS1, do_ddd, a, tcg_gen_eqv_i64) 4560e06c9f83SRichard Henderson TRANS(FORNOTd, VIS1, do_ddd, a, tcg_gen_orc_i64) 4561e06c9f83SRichard Henderson TRANS(FORd, VIS1, do_ddd, a, tcg_gen_or_i64) 4562e06c9f83SRichard Henderson 45634b6edc0aSRichard Henderson TRANS(FPACK32, VIS1, do_ddd, a, gen_op_fpack32) 45644b6edc0aSRichard Henderson TRANS(FALIGNDATAg, VIS1, do_ddd, a, gen_op_faligndata) 45654b6edc0aSRichard Henderson TRANS(BSHUFFLE, VIS2, do_ddd, a, gen_op_bshuffle) 45664b6edc0aSRichard Henderson 4567e2fa6bd1SRichard Henderson static bool do_rdd(DisasContext *dc, arg_r_r_r *a, 4568e2fa6bd1SRichard Henderson void (*func)(TCGv, TCGv_i64, TCGv_i64)) 4569e2fa6bd1SRichard Henderson { 4570e2fa6bd1SRichard Henderson TCGv_i64 src1, src2; 4571e2fa6bd1SRichard Henderson TCGv dst; 4572e2fa6bd1SRichard Henderson 4573e2fa6bd1SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4574e2fa6bd1SRichard Henderson return true; 4575e2fa6bd1SRichard Henderson } 4576e2fa6bd1SRichard Henderson 4577e2fa6bd1SRichard Henderson dst = gen_dest_gpr(dc, a->rd); 4578e2fa6bd1SRichard Henderson src1 = gen_load_fpr_D(dc, a->rs1); 4579e2fa6bd1SRichard Henderson src2 = gen_load_fpr_D(dc, a->rs2); 4580e2fa6bd1SRichard Henderson func(dst, src1, src2); 4581e2fa6bd1SRichard Henderson gen_store_gpr(dc, a->rd, dst); 4582e2fa6bd1SRichard Henderson return advance_pc(dc); 4583e2fa6bd1SRichard Henderson } 4584e2fa6bd1SRichard Henderson 4585e2fa6bd1SRichard Henderson TRANS(FPCMPLE16, VIS1, do_rdd, a, gen_helper_fcmple16) 4586e2fa6bd1SRichard Henderson TRANS(FPCMPNE16, VIS1, do_rdd, a, gen_helper_fcmpne16) 4587e2fa6bd1SRichard Henderson TRANS(FPCMPGT16, VIS1, do_rdd, a, gen_helper_fcmpgt16) 4588e2fa6bd1SRichard Henderson TRANS(FPCMPEQ16, VIS1, do_rdd, a, gen_helper_fcmpeq16) 4589e2fa6bd1SRichard Henderson 4590e2fa6bd1SRichard Henderson TRANS(FPCMPLE32, VIS1, do_rdd, a, gen_helper_fcmple32) 4591e2fa6bd1SRichard Henderson TRANS(FPCMPNE32, VIS1, do_rdd, a, gen_helper_fcmpne32) 4592e2fa6bd1SRichard Henderson TRANS(FPCMPGT32, VIS1, do_rdd, a, gen_helper_fcmpgt32) 4593e2fa6bd1SRichard Henderson TRANS(FPCMPEQ32, VIS1, do_rdd, a, gen_helper_fcmpeq32) 4594e2fa6bd1SRichard Henderson 4595f2a59b0aSRichard Henderson static bool do_env_ddd(DisasContext *dc, arg_r_r_r *a, 4596f2a59b0aSRichard Henderson void (*func)(TCGv_i64, TCGv_env, TCGv_i64, TCGv_i64)) 4597f2a59b0aSRichard Henderson { 4598f2a59b0aSRichard Henderson TCGv_i64 dst, src1, src2; 4599f2a59b0aSRichard Henderson 4600f2a59b0aSRichard Henderson if (gen_trap_ifnofpu(dc)) { 4601f2a59b0aSRichard Henderson return true; 4602f2a59b0aSRichard Henderson } 4603f2a59b0aSRichard Henderson 4604f2a59b0aSRichard Henderson dst = gen_dest_fpr_D(dc, a->rd); 4605f2a59b0aSRichard Henderson src1 = gen_load_fpr_D(dc, a->rs1); 4606f2a59b0aSRichard Henderson src2 = gen_load_fpr_D(dc, a->rs2); 4607f2a59b0aSRichard Henderson func(dst, tcg_env, src1, src2); 4608f2a59b0aSRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 4609f2a59b0aSRichard Henderson return advance_pc(dc); 4610f2a59b0aSRichard Henderson } 4611f2a59b0aSRichard Henderson 4612f2a59b0aSRichard Henderson TRANS(FADDd, ALL, do_env_ddd, a, gen_helper_faddd) 4613f2a59b0aSRichard Henderson TRANS(FSUBd, ALL, do_env_ddd, a, gen_helper_fsubd) 4614f2a59b0aSRichard Henderson TRANS(FMULd, ALL, do_env_ddd, a, gen_helper_fmuld) 4615f2a59b0aSRichard Henderson TRANS(FDIVd, ALL, do_env_ddd, a, gen_helper_fdivd) 4616f2a59b0aSRichard Henderson 4617ff4c711bSRichard Henderson static bool trans_FsMULd(DisasContext *dc, arg_r_r_r *a) 4618ff4c711bSRichard Henderson { 4619ff4c711bSRichard Henderson TCGv_i64 dst; 4620ff4c711bSRichard Henderson TCGv_i32 src1, src2; 4621ff4c711bSRichard Henderson 4622ff4c711bSRichard Henderson if (gen_trap_ifnofpu(dc)) { 4623ff4c711bSRichard Henderson return true; 4624ff4c711bSRichard Henderson } 4625ff4c711bSRichard Henderson if (!(dc->def->features & CPU_FEATURE_FSMULD)) { 4626ff4c711bSRichard Henderson return raise_unimpfpop(dc); 4627ff4c711bSRichard Henderson } 4628ff4c711bSRichard Henderson 4629ff4c711bSRichard Henderson dst = gen_dest_fpr_D(dc, a->rd); 4630ff4c711bSRichard Henderson src1 = gen_load_fpr_F(dc, a->rs1); 4631ff4c711bSRichard Henderson src2 = gen_load_fpr_F(dc, a->rs2); 4632ff4c711bSRichard Henderson gen_helper_fsmuld(dst, tcg_env, src1, src2); 4633ff4c711bSRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 4634ff4c711bSRichard Henderson return advance_pc(dc); 4635ff4c711bSRichard Henderson } 4636ff4c711bSRichard Henderson 4637afb04344SRichard Henderson static bool do_dddd(DisasContext *dc, arg_r_r_r *a, 4638afb04344SRichard Henderson void (*func)(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_i64)) 4639afb04344SRichard Henderson { 4640afb04344SRichard Henderson TCGv_i64 dst, src0, src1, src2; 4641afb04344SRichard Henderson 4642afb04344SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4643afb04344SRichard Henderson return true; 4644afb04344SRichard Henderson } 4645afb04344SRichard Henderson 4646afb04344SRichard Henderson dst = gen_dest_fpr_D(dc, a->rd); 4647afb04344SRichard Henderson src0 = gen_load_fpr_D(dc, a->rd); 4648afb04344SRichard Henderson src1 = gen_load_fpr_D(dc, a->rs1); 4649afb04344SRichard Henderson src2 = gen_load_fpr_D(dc, a->rs2); 4650afb04344SRichard Henderson func(dst, src0, src1, src2); 4651afb04344SRichard Henderson gen_store_fpr_D(dc, a->rd, dst); 4652afb04344SRichard Henderson return advance_pc(dc); 4653afb04344SRichard Henderson } 4654afb04344SRichard Henderson 4655afb04344SRichard Henderson TRANS(PDIST, VIS1, do_dddd, a, gen_helper_pdist) 4656afb04344SRichard Henderson 4657a4056239SRichard Henderson static bool do_env_qqq(DisasContext *dc, arg_r_r_r *a, 465816bedf89SRichard Henderson void (*func)(TCGv_i128, TCGv_env, TCGv_i128, TCGv_i128)) 4659a4056239SRichard Henderson { 466016bedf89SRichard Henderson TCGv_i128 src1, src2; 466116bedf89SRichard Henderson 4662a4056239SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4663a4056239SRichard Henderson return true; 4664a4056239SRichard Henderson } 4665a4056239SRichard Henderson if (gen_trap_float128(dc)) { 4666a4056239SRichard Henderson return true; 4667a4056239SRichard Henderson } 4668a4056239SRichard Henderson 466916bedf89SRichard Henderson src1 = gen_load_fpr_Q(dc, a->rs1); 467016bedf89SRichard Henderson src2 = gen_load_fpr_Q(dc, a->rs2); 467116bedf89SRichard Henderson func(src1, tcg_env, src1, src2); 467216bedf89SRichard Henderson gen_store_fpr_Q(dc, a->rd, src1); 4673a4056239SRichard Henderson return advance_pc(dc); 4674a4056239SRichard Henderson } 4675a4056239SRichard Henderson 4676a4056239SRichard Henderson TRANS(FADDq, ALL, do_env_qqq, a, gen_helper_faddq) 4677a4056239SRichard Henderson TRANS(FSUBq, ALL, do_env_qqq, a, gen_helper_fsubq) 4678a4056239SRichard Henderson TRANS(FMULq, ALL, do_env_qqq, a, gen_helper_fmulq) 4679a4056239SRichard Henderson TRANS(FDIVq, ALL, do_env_qqq, a, gen_helper_fdivq) 4680a4056239SRichard Henderson 46815e3b17bbSRichard Henderson static bool trans_FdMULq(DisasContext *dc, arg_r_r_r *a) 46825e3b17bbSRichard Henderson { 46835e3b17bbSRichard Henderson TCGv_i64 src1, src2; 4684ba21dc99SRichard Henderson TCGv_i128 dst; 46855e3b17bbSRichard Henderson 46865e3b17bbSRichard Henderson if (gen_trap_ifnofpu(dc)) { 46875e3b17bbSRichard Henderson return true; 46885e3b17bbSRichard Henderson } 46895e3b17bbSRichard Henderson if (gen_trap_float128(dc)) { 46905e3b17bbSRichard Henderson return true; 46915e3b17bbSRichard Henderson } 46925e3b17bbSRichard Henderson 46935e3b17bbSRichard Henderson src1 = gen_load_fpr_D(dc, a->rs1); 46945e3b17bbSRichard Henderson src2 = gen_load_fpr_D(dc, a->rs2); 4695ba21dc99SRichard Henderson dst = tcg_temp_new_i128(); 4696ba21dc99SRichard Henderson gen_helper_fdmulq(dst, tcg_env, src1, src2); 4697ba21dc99SRichard Henderson gen_store_fpr_Q(dc, a->rd, dst); 46985e3b17bbSRichard Henderson return advance_pc(dc); 46995e3b17bbSRichard Henderson } 47005e3b17bbSRichard Henderson 4701f7ec8155SRichard Henderson static bool do_fmovr(DisasContext *dc, arg_FMOVRs *a, bool is_128, 4702f7ec8155SRichard Henderson void (*func)(DisasContext *, DisasCompare *, int, int)) 4703f7ec8155SRichard Henderson { 4704f7ec8155SRichard Henderson DisasCompare cmp; 4705f7ec8155SRichard Henderson 47062c4f56c9SRichard Henderson if (!gen_compare_reg(&cmp, a->cond, gen_load_gpr(dc, a->rs1))) { 47072c4f56c9SRichard Henderson return false; 47082c4f56c9SRichard Henderson } 4709f7ec8155SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4710f7ec8155SRichard Henderson return true; 4711f7ec8155SRichard Henderson } 4712f7ec8155SRichard Henderson if (is_128 && gen_trap_float128(dc)) { 4713f7ec8155SRichard Henderson return true; 4714f7ec8155SRichard Henderson } 4715f7ec8155SRichard Henderson 4716f7ec8155SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 4717f7ec8155SRichard Henderson func(dc, &cmp, a->rd, a->rs2); 4718f7ec8155SRichard Henderson return advance_pc(dc); 4719f7ec8155SRichard Henderson } 4720f7ec8155SRichard Henderson 4721f7ec8155SRichard Henderson TRANS(FMOVRs, 64, do_fmovr, a, false, gen_fmovs) 4722f7ec8155SRichard Henderson TRANS(FMOVRd, 64, do_fmovr, a, false, gen_fmovd) 4723f7ec8155SRichard Henderson TRANS(FMOVRq, 64, do_fmovr, a, true, gen_fmovq) 4724f7ec8155SRichard Henderson 4725f7ec8155SRichard Henderson static bool do_fmovcc(DisasContext *dc, arg_FMOVscc *a, bool is_128, 4726f7ec8155SRichard Henderson void (*func)(DisasContext *, DisasCompare *, int, int)) 4727f7ec8155SRichard Henderson { 4728f7ec8155SRichard Henderson DisasCompare cmp; 4729f7ec8155SRichard Henderson 4730f7ec8155SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4731f7ec8155SRichard Henderson return true; 4732f7ec8155SRichard Henderson } 4733f7ec8155SRichard Henderson if (is_128 && gen_trap_float128(dc)) { 4734f7ec8155SRichard Henderson return true; 4735f7ec8155SRichard Henderson } 4736f7ec8155SRichard Henderson 4737f7ec8155SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 4738f7ec8155SRichard Henderson gen_compare(&cmp, a->cc, a->cond, dc); 4739f7ec8155SRichard Henderson func(dc, &cmp, a->rd, a->rs2); 4740f7ec8155SRichard Henderson return advance_pc(dc); 4741f7ec8155SRichard Henderson } 4742f7ec8155SRichard Henderson 4743f7ec8155SRichard Henderson TRANS(FMOVscc, 64, do_fmovcc, a, false, gen_fmovs) 4744f7ec8155SRichard Henderson TRANS(FMOVdcc, 64, do_fmovcc, a, false, gen_fmovd) 4745f7ec8155SRichard Henderson TRANS(FMOVqcc, 64, do_fmovcc, a, true, gen_fmovq) 4746f7ec8155SRichard Henderson 4747f7ec8155SRichard Henderson static bool do_fmovfcc(DisasContext *dc, arg_FMOVsfcc *a, bool is_128, 4748f7ec8155SRichard Henderson void (*func)(DisasContext *, DisasCompare *, int, int)) 4749f7ec8155SRichard Henderson { 4750f7ec8155SRichard Henderson DisasCompare cmp; 4751f7ec8155SRichard Henderson 4752f7ec8155SRichard Henderson if (gen_trap_ifnofpu(dc)) { 4753f7ec8155SRichard Henderson return true; 4754f7ec8155SRichard Henderson } 4755f7ec8155SRichard Henderson if (is_128 && gen_trap_float128(dc)) { 4756f7ec8155SRichard Henderson return true; 4757f7ec8155SRichard Henderson } 4758f7ec8155SRichard Henderson 4759f7ec8155SRichard Henderson gen_op_clear_ieee_excp_and_FTT(); 4760f7ec8155SRichard Henderson gen_fcompare(&cmp, a->cc, a->cond); 4761f7ec8155SRichard Henderson func(dc, &cmp, a->rd, a->rs2); 4762f7ec8155SRichard Henderson return advance_pc(dc); 4763f7ec8155SRichard Henderson } 4764f7ec8155SRichard Henderson 4765f7ec8155SRichard Henderson TRANS(FMOVsfcc, 64, do_fmovfcc, a, false, gen_fmovs) 4766f7ec8155SRichard Henderson TRANS(FMOVdfcc, 64, do_fmovfcc, a, false, gen_fmovd) 4767f7ec8155SRichard Henderson TRANS(FMOVqfcc, 64, do_fmovfcc, a, true, gen_fmovq) 4768f7ec8155SRichard Henderson 476940f9ad21SRichard Henderson static bool do_fcmps(DisasContext *dc, arg_FCMPs *a, bool e) 477040f9ad21SRichard Henderson { 477140f9ad21SRichard Henderson TCGv_i32 src1, src2; 477240f9ad21SRichard Henderson 477340f9ad21SRichard Henderson if (avail_32(dc) && a->cc != 0) { 477440f9ad21SRichard Henderson return false; 477540f9ad21SRichard Henderson } 477640f9ad21SRichard Henderson if (gen_trap_ifnofpu(dc)) { 477740f9ad21SRichard Henderson return true; 477840f9ad21SRichard Henderson } 477940f9ad21SRichard Henderson 478040f9ad21SRichard Henderson src1 = gen_load_fpr_F(dc, a->rs1); 478140f9ad21SRichard Henderson src2 = gen_load_fpr_F(dc, a->rs2); 478240f9ad21SRichard Henderson if (e) { 4783d8c5b92fSRichard Henderson gen_helper_fcmpes(cpu_fcc[a->cc], tcg_env, src1, src2); 478440f9ad21SRichard Henderson } else { 4785d8c5b92fSRichard Henderson gen_helper_fcmps(cpu_fcc[a->cc], tcg_env, src1, src2); 478640f9ad21SRichard Henderson } 478740f9ad21SRichard Henderson return advance_pc(dc); 478840f9ad21SRichard Henderson } 478940f9ad21SRichard Henderson 479040f9ad21SRichard Henderson TRANS(FCMPs, ALL, do_fcmps, a, false) 479140f9ad21SRichard Henderson TRANS(FCMPEs, ALL, do_fcmps, a, true) 479240f9ad21SRichard Henderson 479340f9ad21SRichard Henderson static bool do_fcmpd(DisasContext *dc, arg_FCMPd *a, bool e) 479440f9ad21SRichard Henderson { 479540f9ad21SRichard Henderson TCGv_i64 src1, src2; 479640f9ad21SRichard Henderson 479740f9ad21SRichard Henderson if (avail_32(dc) && a->cc != 0) { 479840f9ad21SRichard Henderson return false; 479940f9ad21SRichard Henderson } 480040f9ad21SRichard Henderson if (gen_trap_ifnofpu(dc)) { 480140f9ad21SRichard Henderson return true; 480240f9ad21SRichard Henderson } 480340f9ad21SRichard Henderson 480440f9ad21SRichard Henderson src1 = gen_load_fpr_D(dc, a->rs1); 480540f9ad21SRichard Henderson src2 = gen_load_fpr_D(dc, a->rs2); 480640f9ad21SRichard Henderson if (e) { 4807d8c5b92fSRichard Henderson gen_helper_fcmped(cpu_fcc[a->cc], tcg_env, src1, src2); 480840f9ad21SRichard Henderson } else { 4809d8c5b92fSRichard Henderson gen_helper_fcmpd(cpu_fcc[a->cc], tcg_env, src1, src2); 481040f9ad21SRichard Henderson } 481140f9ad21SRichard Henderson return advance_pc(dc); 481240f9ad21SRichard Henderson } 481340f9ad21SRichard Henderson 481440f9ad21SRichard Henderson TRANS(FCMPd, ALL, do_fcmpd, a, false) 481540f9ad21SRichard Henderson TRANS(FCMPEd, ALL, do_fcmpd, a, true) 481640f9ad21SRichard Henderson 481740f9ad21SRichard Henderson static bool do_fcmpq(DisasContext *dc, arg_FCMPq *a, bool e) 481840f9ad21SRichard Henderson { 4819f3ceafadSRichard Henderson TCGv_i128 src1, src2; 4820f3ceafadSRichard Henderson 482140f9ad21SRichard Henderson if (avail_32(dc) && a->cc != 0) { 482240f9ad21SRichard Henderson return false; 482340f9ad21SRichard Henderson } 482440f9ad21SRichard Henderson if (gen_trap_ifnofpu(dc)) { 482540f9ad21SRichard Henderson return true; 482640f9ad21SRichard Henderson } 482740f9ad21SRichard Henderson if (gen_trap_float128(dc)) { 482840f9ad21SRichard Henderson return true; 482940f9ad21SRichard Henderson } 483040f9ad21SRichard Henderson 4831f3ceafadSRichard Henderson src1 = gen_load_fpr_Q(dc, a->rs1); 4832f3ceafadSRichard Henderson src2 = gen_load_fpr_Q(dc, a->rs2); 483340f9ad21SRichard Henderson if (e) { 4834d8c5b92fSRichard Henderson gen_helper_fcmpeq(cpu_fcc[a->cc], tcg_env, src1, src2); 483540f9ad21SRichard Henderson } else { 4836d8c5b92fSRichard Henderson gen_helper_fcmpq(cpu_fcc[a->cc], tcg_env, src1, src2); 483740f9ad21SRichard Henderson } 483840f9ad21SRichard Henderson return advance_pc(dc); 483940f9ad21SRichard Henderson } 484040f9ad21SRichard Henderson 484140f9ad21SRichard Henderson TRANS(FCMPq, ALL, do_fcmpq, a, false) 484240f9ad21SRichard Henderson TRANS(FCMPEq, ALL, do_fcmpq, a, true) 484340f9ad21SRichard Henderson 48446e61bc94SEmilio G. Cota static void sparc_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) 4845fcf5ef2aSThomas Huth { 48466e61bc94SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 4847b77af26eSRichard Henderson CPUSPARCState *env = cpu_env(cs); 48486e61bc94SEmilio G. Cota int bound; 4849af00be49SEmilio G. Cota 4850af00be49SEmilio G. Cota dc->pc = dc->base.pc_first; 48516e61bc94SEmilio G. Cota dc->npc = (target_ulong)dc->base.tb->cs_base; 48526e61bc94SEmilio G. Cota dc->mem_idx = dc->base.tb->flags & TB_FLAG_MMU_MASK; 4853576e1c4cSIgor Mammedov dc->def = &env->def; 48546e61bc94SEmilio G. Cota dc->fpu_enabled = tb_fpu_enabled(dc->base.tb->flags); 48556e61bc94SEmilio G. Cota dc->address_mask_32bit = tb_am_enabled(dc->base.tb->flags); 4856c9b459aaSArtyom Tarasenko #ifndef CONFIG_USER_ONLY 48576e61bc94SEmilio G. Cota dc->supervisor = (dc->base.tb->flags & TB_FLAG_SUPER) != 0; 4858c9b459aaSArtyom Tarasenko #endif 4859fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64 4860fcf5ef2aSThomas Huth dc->fprs_dirty = 0; 48616e61bc94SEmilio G. Cota dc->asi = (dc->base.tb->flags >> TB_FLAG_ASI_SHIFT) & 0xff; 4862c9b459aaSArtyom Tarasenko #ifndef CONFIG_USER_ONLY 48636e61bc94SEmilio G. Cota dc->hypervisor = (dc->base.tb->flags & TB_FLAG_HYPER) != 0; 4864c9b459aaSArtyom Tarasenko #endif 4865fcf5ef2aSThomas Huth #endif 48666e61bc94SEmilio G. Cota /* 48676e61bc94SEmilio G. Cota * if we reach a page boundary, we stop generation so that the 48686e61bc94SEmilio G. Cota * PC of a TT_TFAULT exception is always in the right page 48696e61bc94SEmilio G. Cota */ 48706e61bc94SEmilio G. Cota bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4; 48716e61bc94SEmilio G. Cota dc->base.max_insns = MIN(dc->base.max_insns, bound); 4872af00be49SEmilio G. Cota } 4873fcf5ef2aSThomas Huth 48746e61bc94SEmilio G. Cota static void sparc_tr_tb_start(DisasContextBase *db, CPUState *cs) 48756e61bc94SEmilio G. Cota { 48766e61bc94SEmilio G. Cota } 48776e61bc94SEmilio G. Cota 48786e61bc94SEmilio G. Cota static void sparc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) 48796e61bc94SEmilio G. Cota { 48806e61bc94SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 4881633c4283SRichard Henderson target_ulong npc = dc->npc; 48826e61bc94SEmilio G. Cota 4883633c4283SRichard Henderson if (npc & 3) { 4884633c4283SRichard Henderson switch (npc) { 4885633c4283SRichard Henderson case JUMP_PC: 4886fcf5ef2aSThomas Huth assert(dc->jump_pc[1] == dc->pc + 4); 4887633c4283SRichard Henderson npc = dc->jump_pc[0] | JUMP_PC; 4888633c4283SRichard Henderson break; 4889633c4283SRichard Henderson case DYNAMIC_PC: 4890633c4283SRichard Henderson case DYNAMIC_PC_LOOKUP: 4891633c4283SRichard Henderson npc = DYNAMIC_PC; 4892633c4283SRichard Henderson break; 4893633c4283SRichard Henderson default: 4894633c4283SRichard Henderson g_assert_not_reached(); 4895fcf5ef2aSThomas Huth } 48966e61bc94SEmilio G. Cota } 4897633c4283SRichard Henderson tcg_gen_insn_start(dc->pc, npc); 4898633c4283SRichard Henderson } 4899fcf5ef2aSThomas Huth 49006e61bc94SEmilio G. Cota static void sparc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) 49016e61bc94SEmilio G. Cota { 49026e61bc94SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 4903b77af26eSRichard Henderson CPUSPARCState *env = cpu_env(cs); 49046e61bc94SEmilio G. Cota unsigned int insn; 4905fcf5ef2aSThomas Huth 49064e116893SIlya Leoshkevich insn = translator_ldl(env, &dc->base, dc->pc); 4907af00be49SEmilio G. Cota dc->base.pc_next += 4; 4908878cc677SRichard Henderson 4909878cc677SRichard Henderson if (!decode(dc, insn)) { 4910ba9c09b4SRichard Henderson gen_exception(dc, TT_ILL_INSN); 4911878cc677SRichard Henderson } 4912fcf5ef2aSThomas Huth 4913af00be49SEmilio G. Cota if (dc->base.is_jmp == DISAS_NORETURN) { 49146e61bc94SEmilio G. Cota return; 4915c5e6ccdfSEmilio G. Cota } 4916af00be49SEmilio G. Cota if (dc->pc != dc->base.pc_next) { 49176e61bc94SEmilio G. Cota dc->base.is_jmp = DISAS_TOO_MANY; 4918af00be49SEmilio G. Cota } 49196e61bc94SEmilio G. Cota } 4920fcf5ef2aSThomas Huth 49216e61bc94SEmilio G. Cota static void sparc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) 49226e61bc94SEmilio G. Cota { 49236e61bc94SEmilio G. Cota DisasContext *dc = container_of(dcbase, DisasContext, base); 4924186e7890SRichard Henderson DisasDelayException *e, *e_next; 4925633c4283SRichard Henderson bool may_lookup; 49266e61bc94SEmilio G. Cota 492789527e3aSRichard Henderson finishing_insn(dc); 492889527e3aSRichard Henderson 492946bb0137SMark Cave-Ayland switch (dc->base.is_jmp) { 493046bb0137SMark Cave-Ayland case DISAS_NEXT: 493146bb0137SMark Cave-Ayland case DISAS_TOO_MANY: 4932633c4283SRichard Henderson if (((dc->pc | dc->npc) & 3) == 0) { 4933fcf5ef2aSThomas Huth /* static PC and NPC: we can use direct chaining */ 4934fcf5ef2aSThomas Huth gen_goto_tb(dc, 0, dc->pc, dc->npc); 4935633c4283SRichard Henderson break; 4936fcf5ef2aSThomas Huth } 4937633c4283SRichard Henderson 4938930f1865SRichard Henderson may_lookup = true; 4939633c4283SRichard Henderson if (dc->pc & 3) { 4940633c4283SRichard Henderson switch (dc->pc) { 4941633c4283SRichard Henderson case DYNAMIC_PC_LOOKUP: 4942633c4283SRichard Henderson break; 4943633c4283SRichard Henderson case DYNAMIC_PC: 4944633c4283SRichard Henderson may_lookup = false; 4945633c4283SRichard Henderson break; 4946633c4283SRichard Henderson default: 4947633c4283SRichard Henderson g_assert_not_reached(); 4948633c4283SRichard Henderson } 4949633c4283SRichard Henderson } else { 4950633c4283SRichard Henderson tcg_gen_movi_tl(cpu_pc, dc->pc); 4951633c4283SRichard Henderson } 4952633c4283SRichard Henderson 4953930f1865SRichard Henderson if (dc->npc & 3) { 4954930f1865SRichard Henderson switch (dc->npc) { 4955930f1865SRichard Henderson case JUMP_PC: 4956930f1865SRichard Henderson gen_generic_branch(dc); 4957930f1865SRichard Henderson break; 4958930f1865SRichard Henderson case DYNAMIC_PC: 4959930f1865SRichard Henderson may_lookup = false; 4960930f1865SRichard Henderson break; 4961930f1865SRichard Henderson case DYNAMIC_PC_LOOKUP: 4962930f1865SRichard Henderson break; 4963930f1865SRichard Henderson default: 4964930f1865SRichard Henderson g_assert_not_reached(); 4965930f1865SRichard Henderson } 4966930f1865SRichard Henderson } else { 4967930f1865SRichard Henderson tcg_gen_movi_tl(cpu_npc, dc->npc); 4968930f1865SRichard Henderson } 4969633c4283SRichard Henderson if (may_lookup) { 4970633c4283SRichard Henderson tcg_gen_lookup_and_goto_ptr(); 4971633c4283SRichard Henderson } else { 497207ea28b4SRichard Henderson tcg_gen_exit_tb(NULL, 0); 4973fcf5ef2aSThomas Huth } 497446bb0137SMark Cave-Ayland break; 497546bb0137SMark Cave-Ayland 497646bb0137SMark Cave-Ayland case DISAS_NORETURN: 497746bb0137SMark Cave-Ayland break; 497846bb0137SMark Cave-Ayland 497946bb0137SMark Cave-Ayland case DISAS_EXIT: 498046bb0137SMark Cave-Ayland /* Exit TB */ 498146bb0137SMark Cave-Ayland save_state(dc); 498246bb0137SMark Cave-Ayland tcg_gen_exit_tb(NULL, 0); 498346bb0137SMark Cave-Ayland break; 498446bb0137SMark Cave-Ayland 498546bb0137SMark Cave-Ayland default: 498646bb0137SMark Cave-Ayland g_assert_not_reached(); 4987fcf5ef2aSThomas Huth } 4988186e7890SRichard Henderson 4989186e7890SRichard Henderson for (e = dc->delay_excp_list; e ; e = e_next) { 4990186e7890SRichard Henderson gen_set_label(e->lab); 4991186e7890SRichard Henderson 4992186e7890SRichard Henderson tcg_gen_movi_tl(cpu_pc, e->pc); 4993186e7890SRichard Henderson if (e->npc % 4 == 0) { 4994186e7890SRichard Henderson tcg_gen_movi_tl(cpu_npc, e->npc); 4995186e7890SRichard Henderson } 4996186e7890SRichard Henderson gen_helper_raise_exception(tcg_env, e->excp); 4997186e7890SRichard Henderson 4998186e7890SRichard Henderson e_next = e->next; 4999186e7890SRichard Henderson g_free(e); 5000186e7890SRichard Henderson } 5001fcf5ef2aSThomas Huth } 50026e61bc94SEmilio G. Cota 50038eb806a7SRichard Henderson static void sparc_tr_disas_log(const DisasContextBase *dcbase, 50048eb806a7SRichard Henderson CPUState *cpu, FILE *logfile) 50056e61bc94SEmilio G. Cota { 50068eb806a7SRichard Henderson fprintf(logfile, "IN: %s\n", lookup_symbol(dcbase->pc_first)); 50078eb806a7SRichard Henderson target_disas(logfile, cpu, dcbase->pc_first, dcbase->tb->size); 50086e61bc94SEmilio G. Cota } 50096e61bc94SEmilio G. Cota 50106e61bc94SEmilio G. Cota static const TranslatorOps sparc_tr_ops = { 50116e61bc94SEmilio G. Cota .init_disas_context = sparc_tr_init_disas_context, 50126e61bc94SEmilio G. Cota .tb_start = sparc_tr_tb_start, 50136e61bc94SEmilio G. Cota .insn_start = sparc_tr_insn_start, 50146e61bc94SEmilio G. Cota .translate_insn = sparc_tr_translate_insn, 50156e61bc94SEmilio G. Cota .tb_stop = sparc_tr_tb_stop, 50166e61bc94SEmilio G. Cota .disas_log = sparc_tr_disas_log, 50176e61bc94SEmilio G. Cota }; 50186e61bc94SEmilio G. Cota 5019597f9b2dSRichard Henderson void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int *max_insns, 502032f0c394SAnton Johansson vaddr pc, void *host_pc) 50216e61bc94SEmilio G. Cota { 50226e61bc94SEmilio G. Cota DisasContext dc = {}; 50236e61bc94SEmilio G. Cota 5024306c8721SRichard Henderson translator_loop(cs, tb, max_insns, pc, host_pc, &sparc_tr_ops, &dc.base); 5025fcf5ef2aSThomas Huth } 5026fcf5ef2aSThomas Huth 502755c3ceefSRichard Henderson void sparc_tcg_init(void) 5028fcf5ef2aSThomas Huth { 5029fcf5ef2aSThomas Huth static const char gregnames[32][4] = { 5030fcf5ef2aSThomas Huth "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7", 5031fcf5ef2aSThomas Huth "o0", "o1", "o2", "o3", "o4", "o5", "o6", "o7", 5032fcf5ef2aSThomas Huth "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7", 5033fcf5ef2aSThomas Huth "i0", "i1", "i2", "i3", "i4", "i5", "i6", "i7", 5034fcf5ef2aSThomas Huth }; 5035fcf5ef2aSThomas Huth static const char fregnames[32][4] = { 5036fcf5ef2aSThomas Huth "f0", "f2", "f4", "f6", "f8", "f10", "f12", "f14", 5037fcf5ef2aSThomas Huth "f16", "f18", "f20", "f22", "f24", "f26", "f28", "f30", 5038fcf5ef2aSThomas Huth "f32", "f34", "f36", "f38", "f40", "f42", "f44", "f46", 5039fcf5ef2aSThomas Huth "f48", "f50", "f52", "f54", "f56", "f58", "f60", "f62", 5040fcf5ef2aSThomas Huth }; 5041fcf5ef2aSThomas Huth 5042d8c5b92fSRichard Henderson static const struct { TCGv_i32 *ptr; int off; const char *name; } r32[] = { 5043d8c5b92fSRichard Henderson #ifdef TARGET_SPARC64 5044d8c5b92fSRichard Henderson { &cpu_fprs, offsetof(CPUSPARCState, fprs), "fprs" }, 5045d8c5b92fSRichard Henderson { &cpu_fcc[0], offsetof(CPUSPARCState, fcc[0]), "fcc0" }, 5046d8c5b92fSRichard Henderson { &cpu_fcc[1], offsetof(CPUSPARCState, fcc[1]), "fcc1" }, 5047d8c5b92fSRichard Henderson { &cpu_fcc[2], offsetof(CPUSPARCState, fcc[2]), "fcc2" }, 5048d8c5b92fSRichard Henderson { &cpu_fcc[3], offsetof(CPUSPARCState, fcc[3]), "fcc3" }, 5049d8c5b92fSRichard Henderson #else 5050d8c5b92fSRichard Henderson { &cpu_fcc[0], offsetof(CPUSPARCState, fcc[0]), "fcc" }, 5051d8c5b92fSRichard Henderson #endif 5052d8c5b92fSRichard Henderson }; 5053d8c5b92fSRichard Henderson 5054fcf5ef2aSThomas Huth static const struct { TCGv *ptr; int off; const char *name; } rtl[] = { 5055fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64 5056fcf5ef2aSThomas Huth { &cpu_gsr, offsetof(CPUSPARCState, gsr), "gsr" }, 50572a1905c7SRichard Henderson { &cpu_xcc_Z, offsetof(CPUSPARCState, xcc_Z), "xcc_Z" }, 50582a1905c7SRichard Henderson { &cpu_xcc_C, offsetof(CPUSPARCState, xcc_C), "xcc_C" }, 5059fcf5ef2aSThomas Huth #endif 50602a1905c7SRichard Henderson { &cpu_cc_N, offsetof(CPUSPARCState, cc_N), "cc_N" }, 50612a1905c7SRichard Henderson { &cpu_cc_V, offsetof(CPUSPARCState, cc_V), "cc_V" }, 50622a1905c7SRichard Henderson { &cpu_icc_Z, offsetof(CPUSPARCState, icc_Z), "icc_Z" }, 50632a1905c7SRichard Henderson { &cpu_icc_C, offsetof(CPUSPARCState, icc_C), "icc_C" }, 5064fcf5ef2aSThomas Huth { &cpu_cond, offsetof(CPUSPARCState, cond), "cond" }, 5065fcf5ef2aSThomas Huth { &cpu_pc, offsetof(CPUSPARCState, pc), "pc" }, 5066fcf5ef2aSThomas Huth { &cpu_npc, offsetof(CPUSPARCState, npc), "npc" }, 5067fcf5ef2aSThomas Huth { &cpu_y, offsetof(CPUSPARCState, y), "y" }, 5068fcf5ef2aSThomas Huth { &cpu_tbr, offsetof(CPUSPARCState, tbr), "tbr" }, 5069fcf5ef2aSThomas Huth }; 5070fcf5ef2aSThomas Huth 5071fcf5ef2aSThomas Huth unsigned int i; 5072fcf5ef2aSThomas Huth 5073ad75a51eSRichard Henderson cpu_regwptr = tcg_global_mem_new_ptr(tcg_env, 5074fcf5ef2aSThomas Huth offsetof(CPUSPARCState, regwptr), 5075fcf5ef2aSThomas Huth "regwptr"); 5076fcf5ef2aSThomas Huth 5077d8c5b92fSRichard Henderson for (i = 0; i < ARRAY_SIZE(r32); ++i) { 5078d8c5b92fSRichard Henderson *r32[i].ptr = tcg_global_mem_new_i32(tcg_env, r32[i].off, r32[i].name); 5079d8c5b92fSRichard Henderson } 5080d8c5b92fSRichard Henderson 5081fcf5ef2aSThomas Huth for (i = 0; i < ARRAY_SIZE(rtl); ++i) { 5082ad75a51eSRichard Henderson *rtl[i].ptr = tcg_global_mem_new(tcg_env, rtl[i].off, rtl[i].name); 5083fcf5ef2aSThomas Huth } 5084fcf5ef2aSThomas Huth 5085f764718dSRichard Henderson cpu_regs[0] = NULL; 5086fcf5ef2aSThomas Huth for (i = 1; i < 8; ++i) { 5087ad75a51eSRichard Henderson cpu_regs[i] = tcg_global_mem_new(tcg_env, 5088fcf5ef2aSThomas Huth offsetof(CPUSPARCState, gregs[i]), 5089fcf5ef2aSThomas Huth gregnames[i]); 5090fcf5ef2aSThomas Huth } 5091fcf5ef2aSThomas Huth 5092fcf5ef2aSThomas Huth for (i = 8; i < 32; ++i) { 5093fcf5ef2aSThomas Huth cpu_regs[i] = tcg_global_mem_new(cpu_regwptr, 5094fcf5ef2aSThomas Huth (i - 8) * sizeof(target_ulong), 5095fcf5ef2aSThomas Huth gregnames[i]); 5096fcf5ef2aSThomas Huth } 5097fcf5ef2aSThomas Huth 5098fcf5ef2aSThomas Huth for (i = 0; i < TARGET_DPREGS; i++) { 5099ad75a51eSRichard Henderson cpu_fpr[i] = tcg_global_mem_new_i64(tcg_env, 5100fcf5ef2aSThomas Huth offsetof(CPUSPARCState, fpr[i]), 5101fcf5ef2aSThomas Huth fregnames[i]); 5102fcf5ef2aSThomas Huth } 5103fcf5ef2aSThomas Huth } 5104fcf5ef2aSThomas Huth 5105f36aaa53SRichard Henderson void sparc_restore_state_to_opc(CPUState *cs, 5106f36aaa53SRichard Henderson const TranslationBlock *tb, 5107f36aaa53SRichard Henderson const uint64_t *data) 5108fcf5ef2aSThomas Huth { 5109f36aaa53SRichard Henderson SPARCCPU *cpu = SPARC_CPU(cs); 5110f36aaa53SRichard Henderson CPUSPARCState *env = &cpu->env; 5111fcf5ef2aSThomas Huth target_ulong pc = data[0]; 5112fcf5ef2aSThomas Huth target_ulong npc = data[1]; 5113fcf5ef2aSThomas Huth 5114fcf5ef2aSThomas Huth env->pc = pc; 5115fcf5ef2aSThomas Huth if (npc == DYNAMIC_PC) { 5116fcf5ef2aSThomas Huth /* dynamic NPC: already stored */ 5117fcf5ef2aSThomas Huth } else if (npc & JUMP_PC) { 5118fcf5ef2aSThomas Huth /* jump PC: use 'cond' and the jump targets of the translation */ 5119fcf5ef2aSThomas Huth if (env->cond) { 5120fcf5ef2aSThomas Huth env->npc = npc & ~3; 5121fcf5ef2aSThomas Huth } else { 5122fcf5ef2aSThomas Huth env->npc = pc + 4; 5123fcf5ef2aSThomas Huth } 5124fcf5ef2aSThomas Huth } else { 5125fcf5ef2aSThomas Huth env->npc = npc; 5126fcf5ef2aSThomas Huth } 5127fcf5ef2aSThomas Huth } 5128