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