xref: /openbmc/qemu/target/sparc/translate.c (revision 29b99802aaf519c3c5b9ac8f713458908cf70799)
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"
314fd71d19SRichard 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()
64c973b4e8SRichard Henderson # define gen_helper_cmask8               ({ qemu_build_not_reached(); NULL; })
65c973b4e8SRichard Henderson # define gen_helper_cmask16              ({ qemu_build_not_reached(); NULL; })
66c973b4e8SRichard Henderson # define gen_helper_cmask32              ({ qemu_build_not_reached(); NULL; })
67669e0774SRichard Henderson # define gen_helper_fcmpeq8              ({ qemu_build_not_reached(); NULL; })
68e2fa6bd1SRichard Henderson # define gen_helper_fcmpeq16             ({ qemu_build_not_reached(); NULL; })
69e2fa6bd1SRichard Henderson # define gen_helper_fcmpeq32             ({ qemu_build_not_reached(); NULL; })
70b3c934ddSRichard Henderson # define gen_helper_fcmpgt8              ({ qemu_build_not_reached(); NULL; })
71e2fa6bd1SRichard Henderson # define gen_helper_fcmpgt16             ({ qemu_build_not_reached(); NULL; })
72e2fa6bd1SRichard Henderson # define gen_helper_fcmpgt32             ({ qemu_build_not_reached(); NULL; })
73b3c934ddSRichard Henderson # define gen_helper_fcmple8              ({ qemu_build_not_reached(); NULL; })
74e2fa6bd1SRichard Henderson # define gen_helper_fcmple16             ({ qemu_build_not_reached(); NULL; })
75e2fa6bd1SRichard Henderson # define gen_helper_fcmple32             ({ qemu_build_not_reached(); NULL; })
76669e0774SRichard Henderson # define gen_helper_fcmpne8              ({ qemu_build_not_reached(); NULL; })
77e2fa6bd1SRichard Henderson # define gen_helper_fcmpne16             ({ qemu_build_not_reached(); NULL; })
78e2fa6bd1SRichard Henderson # define gen_helper_fcmpne32             ({ qemu_build_not_reached(); NULL; })
79669e0774SRichard Henderson # define gen_helper_fcmpule8             ({ qemu_build_not_reached(); NULL; })
80b3c934ddSRichard Henderson # define gen_helper_fcmpule16            ({ qemu_build_not_reached(); NULL; })
81b3c934ddSRichard Henderson # define gen_helper_fcmpule32            ({ qemu_build_not_reached(); NULL; })
82669e0774SRichard Henderson # define gen_helper_fcmpugt8             ({ qemu_build_not_reached(); NULL; })
83b3c934ddSRichard Henderson # define gen_helper_fcmpugt16            ({ qemu_build_not_reached(); NULL; })
84b3c934ddSRichard Henderson # define gen_helper_fcmpugt32            ({ qemu_build_not_reached(); NULL; })
858aa418b3SRichard Henderson # define gen_helper_fdtox                ({ qemu_build_not_reached(); NULL; })
86e06c9f83SRichard Henderson # define gen_helper_fexpand              ({ qemu_build_not_reached(); NULL; })
87e06c9f83SRichard Henderson # define gen_helper_fmul8sux16           ({ qemu_build_not_reached(); NULL; })
88e06c9f83SRichard Henderson # define gen_helper_fmul8ulx16           ({ qemu_build_not_reached(); NULL; })
89e06c9f83SRichard Henderson # define gen_helper_fmul8x16             ({ qemu_build_not_reached(); NULL; })
90e06c9f83SRichard Henderson # define gen_helper_fpmerge              ({ qemu_build_not_reached(); NULL; })
911617586fSRichard Henderson # define gen_helper_fqtox                ({ qemu_build_not_reached(); NULL; })
92fbc5c8d4SRichard Henderson # define gen_helper_fslas16              ({ qemu_build_not_reached(); NULL; })
93fbc5c8d4SRichard Henderson # define gen_helper_fslas32              ({ qemu_build_not_reached(); NULL; })
94199d43efSRichard Henderson # define gen_helper_fstox                ({ qemu_build_not_reached(); NULL; })
958aa418b3SRichard Henderson # define gen_helper_fxtod                ({ qemu_build_not_reached(); NULL; })
967b8e3e1aSRichard Henderson # define gen_helper_fxtoq                ({ qemu_build_not_reached(); NULL; })
97f4e18df5SRichard Henderson # define gen_helper_fxtos                ({ qemu_build_not_reached(); NULL; })
98afb04344SRichard Henderson # define gen_helper_pdist                ({ qemu_build_not_reached(); NULL; })
99029b0283SRichard Henderson # define gen_helper_xmulx                ({ qemu_build_not_reached(); NULL; })
100029b0283SRichard Henderson # define gen_helper_xmulxhi              ({ qemu_build_not_reached(); NULL; })
101668bb9b7SRichard Henderson # define MAXTL_MASK                             0
102af25071cSRichard Henderson #endif
103af25071cSRichard Henderson 
104633c4283SRichard Henderson /* Dynamic PC, must exit to main loop. */
105633c4283SRichard Henderson #define DYNAMIC_PC         1
106633c4283SRichard Henderson /* Dynamic PC, one of two values according to jump_pc[T2]. */
107633c4283SRichard Henderson #define JUMP_PC            2
108633c4283SRichard Henderson /* Dynamic PC, may lookup next TB. */
109633c4283SRichard Henderson #define DYNAMIC_PC_LOOKUP  3
110fcf5ef2aSThomas Huth 
11146bb0137SMark Cave-Ayland #define DISAS_EXIT  DISAS_TARGET_0
11246bb0137SMark Cave-Ayland 
113fcf5ef2aSThomas Huth /* global register indexes */
114fcf5ef2aSThomas Huth static TCGv_ptr cpu_regwptr;
115c9fa8e58SRichard Henderson static TCGv cpu_pc, cpu_npc;
116fcf5ef2aSThomas Huth static TCGv cpu_regs[32];
117fcf5ef2aSThomas Huth static TCGv cpu_y;
118fcf5ef2aSThomas Huth static TCGv cpu_tbr;
119fcf5ef2aSThomas Huth static TCGv cpu_cond;
1202a1905c7SRichard Henderson static TCGv cpu_cc_N;
1212a1905c7SRichard Henderson static TCGv cpu_cc_V;
1222a1905c7SRichard Henderson static TCGv cpu_icc_Z;
1232a1905c7SRichard Henderson static TCGv cpu_icc_C;
124fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
1252a1905c7SRichard Henderson static TCGv cpu_xcc_Z;
1262a1905c7SRichard Henderson static TCGv cpu_xcc_C;
1272a1905c7SRichard Henderson static TCGv_i32 cpu_fprs;
128fcf5ef2aSThomas Huth static TCGv cpu_gsr;
129fcf5ef2aSThomas Huth #else
130af25071cSRichard Henderson # define cpu_fprs               ({ qemu_build_not_reached(); (TCGv)NULL; })
131af25071cSRichard Henderson # define cpu_gsr                ({ qemu_build_not_reached(); (TCGv)NULL; })
132fcf5ef2aSThomas Huth #endif
1332a1905c7SRichard Henderson 
1342a1905c7SRichard Henderson #ifdef TARGET_SPARC64
1352a1905c7SRichard Henderson #define cpu_cc_Z  cpu_xcc_Z
1362a1905c7SRichard Henderson #define cpu_cc_C  cpu_xcc_C
1372a1905c7SRichard Henderson #else
1382a1905c7SRichard Henderson #define cpu_cc_Z  cpu_icc_Z
1392a1905c7SRichard Henderson #define cpu_cc_C  cpu_icc_C
1402a1905c7SRichard Henderson #define cpu_xcc_Z ({ qemu_build_not_reached(); NULL; })
1412a1905c7SRichard Henderson #define cpu_xcc_C ({ qemu_build_not_reached(); NULL; })
1422a1905c7SRichard Henderson #endif
1432a1905c7SRichard Henderson 
1441210a036SRichard Henderson /* Floating point comparison registers */
145d8c5b92fSRichard Henderson static TCGv_i32 cpu_fcc[TARGET_FCCREGS];
146fcf5ef2aSThomas Huth 
147af25071cSRichard Henderson #define env_field_offsetof(X)     offsetof(CPUSPARCState, X)
148af25071cSRichard Henderson #ifdef TARGET_SPARC64
149cd6269f7SRichard Henderson # define env32_field_offsetof(X)  ({ qemu_build_not_reached(); 0; })
150af25071cSRichard Henderson # define env64_field_offsetof(X)  env_field_offsetof(X)
151af25071cSRichard Henderson #else
152cd6269f7SRichard Henderson # define env32_field_offsetof(X)  env_field_offsetof(X)
153af25071cSRichard Henderson # define env64_field_offsetof(X)  ({ qemu_build_not_reached(); 0; })
154af25071cSRichard Henderson #endif
155af25071cSRichard Henderson 
156533f042fSRichard Henderson typedef struct DisasCompare {
157533f042fSRichard Henderson     TCGCond cond;
158533f042fSRichard Henderson     TCGv c1;
159533f042fSRichard Henderson     int c2;
160533f042fSRichard Henderson } DisasCompare;
161533f042fSRichard Henderson 
162186e7890SRichard Henderson typedef struct DisasDelayException {
163186e7890SRichard Henderson     struct DisasDelayException *next;
164186e7890SRichard Henderson     TCGLabel *lab;
165186e7890SRichard Henderson     TCGv_i32 excp;
166186e7890SRichard Henderson     /* Saved state at parent insn. */
167186e7890SRichard Henderson     target_ulong pc;
168186e7890SRichard Henderson     target_ulong npc;
169186e7890SRichard Henderson } DisasDelayException;
170186e7890SRichard Henderson 
171fcf5ef2aSThomas Huth typedef struct DisasContext {
172af00be49SEmilio G. Cota     DisasContextBase base;
173fcf5ef2aSThomas Huth     target_ulong pc;    /* current Program Counter: integer or DYNAMIC_PC */
174fcf5ef2aSThomas Huth     target_ulong npc;   /* next PC: integer or DYNAMIC_PC or JUMP_PC */
175533f042fSRichard Henderson 
176533f042fSRichard Henderson     /* Used when JUMP_PC value is used. */
177533f042fSRichard Henderson     DisasCompare jump;
178533f042fSRichard Henderson     target_ulong jump_pc[2];
179533f042fSRichard Henderson 
180fcf5ef2aSThomas Huth     int mem_idx;
18189527e3aSRichard Henderson     bool cpu_cond_live;
182c9b459aaSArtyom Tarasenko     bool fpu_enabled;
183c9b459aaSArtyom Tarasenko     bool address_mask_32bit;
184c9b459aaSArtyom Tarasenko #ifndef CONFIG_USER_ONLY
185c9b459aaSArtyom Tarasenko     bool supervisor;
186c9b459aaSArtyom Tarasenko #ifdef TARGET_SPARC64
187c9b459aaSArtyom Tarasenko     bool hypervisor;
1885a165e26SRichard Henderson #else
1895a165e26SRichard Henderson     bool fsr_qne;
190c9b459aaSArtyom Tarasenko #endif
191c9b459aaSArtyom Tarasenko #endif
192c9b459aaSArtyom Tarasenko 
193fcf5ef2aSThomas Huth     sparc_def_t *def;
194fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
195fcf5ef2aSThomas Huth     int fprs_dirty;
196fcf5ef2aSThomas Huth     int asi;
197fcf5ef2aSThomas Huth #endif
198186e7890SRichard Henderson     DisasDelayException *delay_excp_list;
199fcf5ef2aSThomas Huth } DisasContext;
200fcf5ef2aSThomas Huth 
201fcf5ef2aSThomas Huth // This function uses non-native bit order
202fcf5ef2aSThomas Huth #define GET_FIELD(X, FROM, TO)                                  \
203fcf5ef2aSThomas Huth     ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))
204fcf5ef2aSThomas Huth 
205fcf5ef2aSThomas Huth // This function uses the order in the manuals, i.e. bit 0 is 2^0
206fcf5ef2aSThomas Huth #define GET_FIELD_SP(X, FROM, TO)               \
207fcf5ef2aSThomas Huth     GET_FIELD(X, 31 - (TO), 31 - (FROM))
208fcf5ef2aSThomas Huth 
209fcf5ef2aSThomas Huth #define GET_FIELDs(x,a,b) sign_extend (GET_FIELD(x,a,b), (b) - (a) + 1)
210fcf5ef2aSThomas Huth #define GET_FIELD_SPs(x,a,b) sign_extend (GET_FIELD_SP(x,a,b), ((b) - (a) + 1))
211fcf5ef2aSThomas Huth 
212fcf5ef2aSThomas Huth #define UA2005_HTRAP_MASK 0xff
213fcf5ef2aSThomas Huth #define V8_TRAP_MASK 0x7f
214fcf5ef2aSThomas Huth 
215fcf5ef2aSThomas Huth #define IS_IMM (insn & (1<<13))
216fcf5ef2aSThomas Huth 
2170c2e96c1SRichard Henderson static void gen_update_fprs_dirty(DisasContext *dc, int rd)
218fcf5ef2aSThomas Huth {
219fcf5ef2aSThomas Huth #if defined(TARGET_SPARC64)
220fcf5ef2aSThomas Huth     int bit = (rd < 32) ? 1 : 2;
221fcf5ef2aSThomas Huth     /* If we know we've already set this bit within the TB,
222fcf5ef2aSThomas Huth        we can avoid setting it again.  */
223fcf5ef2aSThomas Huth     if (!(dc->fprs_dirty & bit)) {
224fcf5ef2aSThomas Huth         dc->fprs_dirty |= bit;
225fcf5ef2aSThomas Huth         tcg_gen_ori_i32(cpu_fprs, cpu_fprs, bit);
226fcf5ef2aSThomas Huth     }
227fcf5ef2aSThomas Huth #endif
228fcf5ef2aSThomas Huth }
229fcf5ef2aSThomas Huth 
230fcf5ef2aSThomas Huth /* floating point registers moves */
2311210a036SRichard Henderson 
2321210a036SRichard Henderson static int gen_offset_fpr_F(unsigned int reg)
2331210a036SRichard Henderson {
2341210a036SRichard Henderson     int ret;
2351210a036SRichard Henderson 
2361210a036SRichard Henderson     tcg_debug_assert(reg < 32);
2371210a036SRichard Henderson     ret= offsetof(CPUSPARCState, fpr[reg / 2]);
2381210a036SRichard Henderson     if (reg & 1) {
2391210a036SRichard Henderson         ret += offsetof(CPU_DoubleU, l.lower);
2401210a036SRichard Henderson     } else {
2411210a036SRichard Henderson         ret += offsetof(CPU_DoubleU, l.upper);
2421210a036SRichard Henderson     }
2431210a036SRichard Henderson     return ret;
2441210a036SRichard Henderson }
2451210a036SRichard Henderson 
246fcf5ef2aSThomas Huth static TCGv_i32 gen_load_fpr_F(DisasContext *dc, unsigned int src)
247fcf5ef2aSThomas Huth {
24836ab4623SRichard Henderson     TCGv_i32 ret = tcg_temp_new_i32();
2491210a036SRichard Henderson     tcg_gen_ld_i32(ret, tcg_env, gen_offset_fpr_F(src));
250dc41aa7dSRichard Henderson     return ret;
251fcf5ef2aSThomas Huth }
252fcf5ef2aSThomas Huth 
253fcf5ef2aSThomas Huth static void gen_store_fpr_F(DisasContext *dc, unsigned int dst, TCGv_i32 v)
254fcf5ef2aSThomas Huth {
2551210a036SRichard Henderson     tcg_gen_st_i32(v, tcg_env, gen_offset_fpr_F(dst));
256fcf5ef2aSThomas Huth     gen_update_fprs_dirty(dc, dst);
257fcf5ef2aSThomas Huth }
258fcf5ef2aSThomas Huth 
2591210a036SRichard Henderson static int gen_offset_fpr_D(unsigned int reg)
2601210a036SRichard Henderson {
2611210a036SRichard Henderson     tcg_debug_assert(reg < 64);
2621210a036SRichard Henderson     tcg_debug_assert(reg % 2 == 0);
2631210a036SRichard Henderson     return offsetof(CPUSPARCState, fpr[reg / 2]);
2641210a036SRichard Henderson }
2651210a036SRichard Henderson 
266fcf5ef2aSThomas Huth static TCGv_i64 gen_load_fpr_D(DisasContext *dc, unsigned int src)
267fcf5ef2aSThomas Huth {
2681210a036SRichard Henderson     TCGv_i64 ret = tcg_temp_new_i64();
2691210a036SRichard Henderson     tcg_gen_ld_i64(ret, tcg_env, gen_offset_fpr_D(src));
2701210a036SRichard Henderson     return ret;
271fcf5ef2aSThomas Huth }
272fcf5ef2aSThomas Huth 
273fcf5ef2aSThomas Huth static void gen_store_fpr_D(DisasContext *dc, unsigned int dst, TCGv_i64 v)
274fcf5ef2aSThomas Huth {
2751210a036SRichard Henderson     tcg_gen_st_i64(v, tcg_env, gen_offset_fpr_D(dst));
276fcf5ef2aSThomas Huth     gen_update_fprs_dirty(dc, dst);
277fcf5ef2aSThomas Huth }
278fcf5ef2aSThomas Huth 
27933ec4245SRichard Henderson static TCGv_i128 gen_load_fpr_Q(DisasContext *dc, unsigned int src)
28033ec4245SRichard Henderson {
28133ec4245SRichard Henderson     TCGv_i128 ret = tcg_temp_new_i128();
2821210a036SRichard Henderson     TCGv_i64 h = gen_load_fpr_D(dc, src);
2831210a036SRichard Henderson     TCGv_i64 l = gen_load_fpr_D(dc, src + 2);
28433ec4245SRichard Henderson 
2851210a036SRichard Henderson     tcg_gen_concat_i64_i128(ret, l, h);
28633ec4245SRichard Henderson     return ret;
28733ec4245SRichard Henderson }
28833ec4245SRichard Henderson 
28933ec4245SRichard Henderson static void gen_store_fpr_Q(DisasContext *dc, unsigned int dst, TCGv_i128 v)
29033ec4245SRichard Henderson {
2911210a036SRichard Henderson     TCGv_i64 h = tcg_temp_new_i64();
2921210a036SRichard Henderson     TCGv_i64 l = tcg_temp_new_i64();
2931210a036SRichard Henderson 
2941210a036SRichard Henderson     tcg_gen_extr_i128_i64(l, h, v);
2951210a036SRichard Henderson     gen_store_fpr_D(dc, dst, h);
2961210a036SRichard Henderson     gen_store_fpr_D(dc, dst + 2, l);
29733ec4245SRichard Henderson }
29833ec4245SRichard Henderson 
299fcf5ef2aSThomas Huth /* moves */
300fcf5ef2aSThomas Huth #ifdef CONFIG_USER_ONLY
301fcf5ef2aSThomas Huth #define supervisor(dc) 0
302fcf5ef2aSThomas Huth #define hypervisor(dc) 0
303fcf5ef2aSThomas Huth #else
304fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
305c9b459aaSArtyom Tarasenko #define hypervisor(dc) (dc->hypervisor)
306c9b459aaSArtyom Tarasenko #define supervisor(dc) (dc->supervisor | dc->hypervisor)
307fcf5ef2aSThomas Huth #else
308c9b459aaSArtyom Tarasenko #define supervisor(dc) (dc->supervisor)
309668bb9b7SRichard Henderson #define hypervisor(dc) 0
310fcf5ef2aSThomas Huth #endif
311fcf5ef2aSThomas Huth #endif
312fcf5ef2aSThomas Huth 
313b1bc09eaSRichard Henderson #if !defined(TARGET_SPARC64)
314b1bc09eaSRichard Henderson # define AM_CHECK(dc)  false
315b1bc09eaSRichard Henderson #elif defined(TARGET_ABI32)
316b1bc09eaSRichard Henderson # define AM_CHECK(dc)  true
317b1bc09eaSRichard Henderson #elif defined(CONFIG_USER_ONLY)
318b1bc09eaSRichard Henderson # define AM_CHECK(dc)  false
319fcf5ef2aSThomas Huth #else
320b1bc09eaSRichard Henderson # define AM_CHECK(dc)  ((dc)->address_mask_32bit)
321fcf5ef2aSThomas Huth #endif
322fcf5ef2aSThomas Huth 
3230c2e96c1SRichard Henderson static void gen_address_mask(DisasContext *dc, TCGv addr)
324fcf5ef2aSThomas Huth {
325b1bc09eaSRichard Henderson     if (AM_CHECK(dc)) {
326fcf5ef2aSThomas Huth         tcg_gen_andi_tl(addr, addr, 0xffffffffULL);
327b1bc09eaSRichard Henderson     }
328fcf5ef2aSThomas Huth }
329fcf5ef2aSThomas Huth 
33023ada1b1SRichard Henderson static target_ulong address_mask_i(DisasContext *dc, target_ulong addr)
33123ada1b1SRichard Henderson {
33223ada1b1SRichard Henderson     return AM_CHECK(dc) ? (uint32_t)addr : addr;
33323ada1b1SRichard Henderson }
33423ada1b1SRichard Henderson 
3350c2e96c1SRichard Henderson static TCGv gen_load_gpr(DisasContext *dc, int reg)
336fcf5ef2aSThomas Huth {
337fcf5ef2aSThomas Huth     if (reg > 0) {
338fcf5ef2aSThomas Huth         assert(reg < 32);
339fcf5ef2aSThomas Huth         return cpu_regs[reg];
340fcf5ef2aSThomas Huth     } else {
34152123f14SRichard Henderson         TCGv t = tcg_temp_new();
342fcf5ef2aSThomas Huth         tcg_gen_movi_tl(t, 0);
343fcf5ef2aSThomas Huth         return t;
344fcf5ef2aSThomas Huth     }
345fcf5ef2aSThomas Huth }
346fcf5ef2aSThomas Huth 
3470c2e96c1SRichard Henderson static void gen_store_gpr(DisasContext *dc, int reg, TCGv v)
348fcf5ef2aSThomas Huth {
349fcf5ef2aSThomas Huth     if (reg > 0) {
350fcf5ef2aSThomas Huth         assert(reg < 32);
351fcf5ef2aSThomas Huth         tcg_gen_mov_tl(cpu_regs[reg], v);
352fcf5ef2aSThomas Huth     }
353fcf5ef2aSThomas Huth }
354fcf5ef2aSThomas Huth 
3550c2e96c1SRichard Henderson static TCGv gen_dest_gpr(DisasContext *dc, int reg)
356fcf5ef2aSThomas Huth {
357fcf5ef2aSThomas Huth     if (reg > 0) {
358fcf5ef2aSThomas Huth         assert(reg < 32);
359fcf5ef2aSThomas Huth         return cpu_regs[reg];
360fcf5ef2aSThomas Huth     } else {
36152123f14SRichard Henderson         return tcg_temp_new();
362fcf5ef2aSThomas Huth     }
363fcf5ef2aSThomas Huth }
364fcf5ef2aSThomas Huth 
3655645aa2eSRichard Henderson static bool use_goto_tb(DisasContext *s, target_ulong pc, target_ulong npc)
366fcf5ef2aSThomas Huth {
3675645aa2eSRichard Henderson     return translator_use_goto_tb(&s->base, pc) &&
3685645aa2eSRichard Henderson            translator_use_goto_tb(&s->base, npc);
369fcf5ef2aSThomas Huth }
370fcf5ef2aSThomas Huth 
3715645aa2eSRichard Henderson static void gen_goto_tb(DisasContext *s, int tb_num,
372fcf5ef2aSThomas Huth                         target_ulong pc, target_ulong npc)
373fcf5ef2aSThomas Huth {
374fcf5ef2aSThomas Huth     if (use_goto_tb(s, pc, npc))  {
375fcf5ef2aSThomas Huth         /* jump to same page: we can use a direct jump */
376fcf5ef2aSThomas Huth         tcg_gen_goto_tb(tb_num);
377fcf5ef2aSThomas Huth         tcg_gen_movi_tl(cpu_pc, pc);
378fcf5ef2aSThomas Huth         tcg_gen_movi_tl(cpu_npc, npc);
37907ea28b4SRichard Henderson         tcg_gen_exit_tb(s->base.tb, tb_num);
380fcf5ef2aSThomas Huth     } else {
381f67ccb2fSRichard Henderson         /* jump to another page: we can use an indirect jump */
382fcf5ef2aSThomas Huth         tcg_gen_movi_tl(cpu_pc, pc);
383fcf5ef2aSThomas Huth         tcg_gen_movi_tl(cpu_npc, npc);
384f67ccb2fSRichard Henderson         tcg_gen_lookup_and_goto_ptr();
385fcf5ef2aSThomas Huth     }
386fcf5ef2aSThomas Huth }
387fcf5ef2aSThomas Huth 
388b989ce73SRichard Henderson static TCGv gen_carry32(void)
389fcf5ef2aSThomas Huth {
390b989ce73SRichard Henderson     if (TARGET_LONG_BITS == 64) {
391b989ce73SRichard Henderson         TCGv t = tcg_temp_new();
392b989ce73SRichard Henderson         tcg_gen_extract_tl(t, cpu_icc_C, 32, 1);
393b989ce73SRichard Henderson         return t;
394b989ce73SRichard Henderson     }
395b989ce73SRichard Henderson     return cpu_icc_C;
396fcf5ef2aSThomas Huth }
397fcf5ef2aSThomas Huth 
398b989ce73SRichard Henderson static void gen_op_addcc_int(TCGv dst, TCGv src1, TCGv src2, TCGv cin)
399fcf5ef2aSThomas Huth {
400b989ce73SRichard Henderson     TCGv z = tcg_constant_tl(0);
401fcf5ef2aSThomas Huth 
402b989ce73SRichard Henderson     if (cin) {
403b989ce73SRichard Henderson         tcg_gen_add2_tl(cpu_cc_N, cpu_cc_C, src1, z, cin, z);
404b989ce73SRichard Henderson         tcg_gen_add2_tl(cpu_cc_N, cpu_cc_C, cpu_cc_N, cpu_cc_C, src2, z);
405b989ce73SRichard Henderson     } else {
406b989ce73SRichard Henderson         tcg_gen_add2_tl(cpu_cc_N, cpu_cc_C, src1, z, src2, z);
407b989ce73SRichard Henderson     }
408b989ce73SRichard Henderson     tcg_gen_xor_tl(cpu_cc_Z, src1, src2);
409b989ce73SRichard Henderson     tcg_gen_xor_tl(cpu_cc_V, cpu_cc_N, src2);
410b989ce73SRichard Henderson     tcg_gen_andc_tl(cpu_cc_V, cpu_cc_V, cpu_cc_Z);
411b989ce73SRichard Henderson     if (TARGET_LONG_BITS == 64) {
412b989ce73SRichard Henderson         /*
413b989ce73SRichard Henderson          * Carry-in to bit 32 is result ^ src1 ^ src2.
414b989ce73SRichard Henderson          * We already have the src xor term in Z, from computation of V.
415b989ce73SRichard Henderson          */
416b989ce73SRichard Henderson         tcg_gen_xor_tl(cpu_icc_C, cpu_cc_Z, cpu_cc_N);
417b989ce73SRichard Henderson         tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N);
418b989ce73SRichard Henderson     }
419b989ce73SRichard Henderson     tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N);
420b989ce73SRichard Henderson     tcg_gen_mov_tl(dst, cpu_cc_N);
421b989ce73SRichard Henderson }
422fcf5ef2aSThomas Huth 
423b989ce73SRichard Henderson static void gen_op_addcc(TCGv dst, TCGv src1, TCGv src2)
424b989ce73SRichard Henderson {
425b989ce73SRichard Henderson     gen_op_addcc_int(dst, src1, src2, NULL);
426b989ce73SRichard Henderson }
427fcf5ef2aSThomas Huth 
428b989ce73SRichard Henderson static void gen_op_taddcc(TCGv dst, TCGv src1, TCGv src2)
429b989ce73SRichard Henderson {
430b989ce73SRichard Henderson     TCGv t = tcg_temp_new();
431b989ce73SRichard Henderson 
432b989ce73SRichard Henderson     /* Save the tag bits around modification of dst. */
433b989ce73SRichard Henderson     tcg_gen_or_tl(t, src1, src2);
434b989ce73SRichard Henderson 
435b989ce73SRichard Henderson     gen_op_addcc(dst, src1, src2);
436b989ce73SRichard Henderson 
437b989ce73SRichard Henderson     /* Incorprate tag bits into icc.V */
438b989ce73SRichard Henderson     tcg_gen_andi_tl(t, t, 3);
439b989ce73SRichard Henderson     tcg_gen_neg_tl(t, t);
440b989ce73SRichard Henderson     tcg_gen_ext32u_tl(t, t);
441b989ce73SRichard Henderson     tcg_gen_or_tl(cpu_cc_V, cpu_cc_V, t);
442b989ce73SRichard Henderson }
443b989ce73SRichard Henderson 
444b989ce73SRichard Henderson static void gen_op_addc(TCGv dst, TCGv src1, TCGv src2)
445b989ce73SRichard Henderson {
446b989ce73SRichard Henderson     tcg_gen_add_tl(dst, src1, src2);
447b989ce73SRichard Henderson     tcg_gen_add_tl(dst, dst, gen_carry32());
448b989ce73SRichard Henderson }
449b989ce73SRichard Henderson 
450b989ce73SRichard Henderson static void gen_op_addccc(TCGv dst, TCGv src1, TCGv src2)
451b989ce73SRichard Henderson {
452b989ce73SRichard Henderson     gen_op_addcc_int(dst, src1, src2, gen_carry32());
453fcf5ef2aSThomas Huth }
454fcf5ef2aSThomas Huth 
455015fc6fcSRichard Henderson static void gen_op_addxc(TCGv dst, TCGv src1, TCGv src2)
456015fc6fcSRichard Henderson {
457015fc6fcSRichard Henderson     tcg_gen_add_tl(dst, src1, src2);
458015fc6fcSRichard Henderson     tcg_gen_add_tl(dst, dst, cpu_cc_C);
459015fc6fcSRichard Henderson }
460015fc6fcSRichard Henderson 
461015fc6fcSRichard Henderson static void gen_op_addxccc(TCGv dst, TCGv src1, TCGv src2)
462015fc6fcSRichard Henderson {
463015fc6fcSRichard Henderson     gen_op_addcc_int(dst, src1, src2, cpu_cc_C);
464015fc6fcSRichard Henderson }
465015fc6fcSRichard Henderson 
466f828df74SRichard Henderson static void gen_op_subcc_int(TCGv dst, TCGv src1, TCGv src2, TCGv cin)
467fcf5ef2aSThomas Huth {
468f828df74SRichard Henderson     TCGv z = tcg_constant_tl(0);
469fcf5ef2aSThomas Huth 
470f828df74SRichard Henderson     if (cin) {
471f828df74SRichard Henderson         tcg_gen_sub2_tl(cpu_cc_N, cpu_cc_C, src1, z, cin, z);
472f828df74SRichard Henderson         tcg_gen_sub2_tl(cpu_cc_N, cpu_cc_C, cpu_cc_N, cpu_cc_C, src2, z);
473f828df74SRichard Henderson     } else {
474f828df74SRichard Henderson         tcg_gen_sub2_tl(cpu_cc_N, cpu_cc_C, src1, z, src2, z);
475f828df74SRichard Henderson     }
476f828df74SRichard Henderson     tcg_gen_neg_tl(cpu_cc_C, cpu_cc_C);
477f828df74SRichard Henderson     tcg_gen_xor_tl(cpu_cc_Z, src1, src2);
478f828df74SRichard Henderson     tcg_gen_xor_tl(cpu_cc_V, cpu_cc_N, src1);
479f828df74SRichard Henderson     tcg_gen_and_tl(cpu_cc_V, cpu_cc_V, cpu_cc_Z);
480f828df74SRichard Henderson #ifdef TARGET_SPARC64
481f828df74SRichard Henderson     tcg_gen_xor_tl(cpu_icc_C, cpu_cc_Z, cpu_cc_N);
482f828df74SRichard Henderson     tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N);
483fcf5ef2aSThomas Huth #endif
484f828df74SRichard Henderson     tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N);
485f828df74SRichard Henderson     tcg_gen_mov_tl(dst, cpu_cc_N);
486fcf5ef2aSThomas Huth }
487fcf5ef2aSThomas Huth 
488f828df74SRichard Henderson static void gen_op_subcc(TCGv dst, TCGv src1, TCGv src2)
489fcf5ef2aSThomas Huth {
490f828df74SRichard Henderson     gen_op_subcc_int(dst, src1, src2, NULL);
491fcf5ef2aSThomas Huth }
492fcf5ef2aSThomas Huth 
493f828df74SRichard Henderson static void gen_op_tsubcc(TCGv dst, TCGv src1, TCGv src2)
494fcf5ef2aSThomas Huth {
495f828df74SRichard Henderson     TCGv t = tcg_temp_new();
496fcf5ef2aSThomas Huth 
497f828df74SRichard Henderson     /* Save the tag bits around modification of dst. */
498f828df74SRichard Henderson     tcg_gen_or_tl(t, src1, src2);
499fcf5ef2aSThomas Huth 
500f828df74SRichard Henderson     gen_op_subcc(dst, src1, src2);
501f828df74SRichard Henderson 
502f828df74SRichard Henderson     /* Incorprate tag bits into icc.V */
503f828df74SRichard Henderson     tcg_gen_andi_tl(t, t, 3);
504f828df74SRichard Henderson     tcg_gen_neg_tl(t, t);
505f828df74SRichard Henderson     tcg_gen_ext32u_tl(t, t);
506f828df74SRichard Henderson     tcg_gen_or_tl(cpu_cc_V, cpu_cc_V, t);
507f828df74SRichard Henderson }
508f828df74SRichard Henderson 
509f828df74SRichard Henderson static void gen_op_subc(TCGv dst, TCGv src1, TCGv src2)
510f828df74SRichard Henderson {
511fcf5ef2aSThomas Huth     tcg_gen_sub_tl(dst, src1, src2);
512f828df74SRichard Henderson     tcg_gen_sub_tl(dst, dst, gen_carry32());
513fcf5ef2aSThomas Huth }
514fcf5ef2aSThomas Huth 
515f828df74SRichard Henderson static void gen_op_subccc(TCGv dst, TCGv src1, TCGv src2)
516dfebb950SRichard Henderson {
517f828df74SRichard Henderson     gen_op_subcc_int(dst, src1, src2, gen_carry32());
518dfebb950SRichard Henderson }
519dfebb950SRichard Henderson 
52056f2ef9cSRichard Henderson static void gen_op_subxc(TCGv dst, TCGv src1, TCGv src2)
52156f2ef9cSRichard Henderson {
52256f2ef9cSRichard Henderson     tcg_gen_sub_tl(dst, src1, src2);
52356f2ef9cSRichard Henderson     tcg_gen_sub_tl(dst, dst, cpu_cc_C);
52456f2ef9cSRichard Henderson }
52556f2ef9cSRichard Henderson 
52656f2ef9cSRichard Henderson static void gen_op_subxccc(TCGv dst, TCGv src1, TCGv src2)
52756f2ef9cSRichard Henderson {
52856f2ef9cSRichard Henderson     gen_op_subcc_int(dst, src1, src2, cpu_cc_C);
52956f2ef9cSRichard Henderson }
53056f2ef9cSRichard Henderson 
5310c2e96c1SRichard Henderson static void gen_op_mulscc(TCGv dst, TCGv src1, TCGv src2)
532fcf5ef2aSThomas Huth {
533b989ce73SRichard Henderson     TCGv zero = tcg_constant_tl(0);
53450280618SRichard Henderson     TCGv one = tcg_constant_tl(1);
535b989ce73SRichard Henderson     TCGv t_src1 = tcg_temp_new();
536b989ce73SRichard Henderson     TCGv t_src2 = tcg_temp_new();
537b989ce73SRichard Henderson     TCGv t0 = tcg_temp_new();
538fcf5ef2aSThomas Huth 
539b989ce73SRichard Henderson     tcg_gen_ext32u_tl(t_src1, src1);
540b989ce73SRichard Henderson     tcg_gen_ext32u_tl(t_src2, src2);
541fcf5ef2aSThomas Huth 
542b989ce73SRichard Henderson     /*
543b989ce73SRichard Henderson      * if (!(env->y & 1))
544b989ce73SRichard Henderson      *   src2 = 0;
545fcf5ef2aSThomas Huth      */
54650280618SRichard Henderson     tcg_gen_movcond_tl(TCG_COND_TSTEQ, t_src2, cpu_y, one, zero, t_src2);
547fcf5ef2aSThomas Huth 
548b989ce73SRichard Henderson     /*
549b989ce73SRichard Henderson      * b2 = src1 & 1;
550b989ce73SRichard Henderson      * y = (b2 << 31) | (y >> 1);
551b989ce73SRichard Henderson      */
5520b1183e3SPhilippe Mathieu-Daudé     tcg_gen_extract_tl(t0, cpu_y, 1, 31);
553b989ce73SRichard Henderson     tcg_gen_deposit_tl(cpu_y, t0, src1, 31, 1);
554fcf5ef2aSThomas Huth 
555fcf5ef2aSThomas Huth     // b1 = N ^ V;
5562a1905c7SRichard Henderson     tcg_gen_xor_tl(t0, cpu_cc_N, cpu_cc_V);
557fcf5ef2aSThomas Huth 
558b989ce73SRichard Henderson     /*
559b989ce73SRichard Henderson      * src1 = (b1 << 31) | (src1 >> 1)
560b989ce73SRichard Henderson      */
5612a1905c7SRichard Henderson     tcg_gen_andi_tl(t0, t0, 1u << 31);
562b989ce73SRichard Henderson     tcg_gen_shri_tl(t_src1, t_src1, 1);
563b989ce73SRichard Henderson     tcg_gen_or_tl(t_src1, t_src1, t0);
564fcf5ef2aSThomas Huth 
565b989ce73SRichard Henderson     gen_op_addcc(dst, t_src1, t_src2);
566fcf5ef2aSThomas Huth }
567fcf5ef2aSThomas Huth 
5680c2e96c1SRichard Henderson static void gen_op_multiply(TCGv dst, TCGv src1, TCGv src2, int sign_ext)
569fcf5ef2aSThomas Huth {
570fcf5ef2aSThomas Huth #if TARGET_LONG_BITS == 32
571fcf5ef2aSThomas Huth     if (sign_ext) {
572fcf5ef2aSThomas Huth         tcg_gen_muls2_tl(dst, cpu_y, src1, src2);
573fcf5ef2aSThomas Huth     } else {
574fcf5ef2aSThomas Huth         tcg_gen_mulu2_tl(dst, cpu_y, src1, src2);
575fcf5ef2aSThomas Huth     }
576fcf5ef2aSThomas Huth #else
577fcf5ef2aSThomas Huth     TCGv t0 = tcg_temp_new_i64();
578fcf5ef2aSThomas Huth     TCGv t1 = tcg_temp_new_i64();
579fcf5ef2aSThomas Huth 
580fcf5ef2aSThomas Huth     if (sign_ext) {
581fcf5ef2aSThomas Huth         tcg_gen_ext32s_i64(t0, src1);
582fcf5ef2aSThomas Huth         tcg_gen_ext32s_i64(t1, src2);
583fcf5ef2aSThomas Huth     } else {
584fcf5ef2aSThomas Huth         tcg_gen_ext32u_i64(t0, src1);
585fcf5ef2aSThomas Huth         tcg_gen_ext32u_i64(t1, src2);
586fcf5ef2aSThomas Huth     }
587fcf5ef2aSThomas Huth 
588fcf5ef2aSThomas Huth     tcg_gen_mul_i64(dst, t0, t1);
589fcf5ef2aSThomas Huth     tcg_gen_shri_i64(cpu_y, dst, 32);
590fcf5ef2aSThomas Huth #endif
591fcf5ef2aSThomas Huth }
592fcf5ef2aSThomas Huth 
5930c2e96c1SRichard Henderson static void gen_op_umul(TCGv dst, TCGv src1, TCGv src2)
594fcf5ef2aSThomas Huth {
595fcf5ef2aSThomas Huth     /* zero-extend truncated operands before multiplication */
596fcf5ef2aSThomas Huth     gen_op_multiply(dst, src1, src2, 0);
597fcf5ef2aSThomas Huth }
598fcf5ef2aSThomas Huth 
5990c2e96c1SRichard Henderson static void gen_op_smul(TCGv dst, TCGv src1, TCGv src2)
600fcf5ef2aSThomas Huth {
601fcf5ef2aSThomas Huth     /* sign-extend truncated operands before multiplication */
602fcf5ef2aSThomas Huth     gen_op_multiply(dst, src1, src2, 1);
603fcf5ef2aSThomas Huth }
604fcf5ef2aSThomas Huth 
605680af1b4SRichard Henderson static void gen_op_umulxhi(TCGv dst, TCGv src1, TCGv src2)
606680af1b4SRichard Henderson {
607680af1b4SRichard Henderson     TCGv discard = tcg_temp_new();
608680af1b4SRichard Henderson     tcg_gen_mulu2_tl(discard, dst, src1, src2);
609680af1b4SRichard Henderson }
610680af1b4SRichard Henderson 
61168a414e9SRichard Henderson static void gen_op_fpmaddx(TCGv_i64 dst, TCGv_i64 src1,
61268a414e9SRichard Henderson                            TCGv_i64 src2, TCGv_i64 src3)
61368a414e9SRichard Henderson {
61468a414e9SRichard Henderson     TCGv_i64 t = tcg_temp_new_i64();
61568a414e9SRichard Henderson 
61668a414e9SRichard Henderson     tcg_gen_mul_i64(t, src1, src2);
61768a414e9SRichard Henderson     tcg_gen_add_i64(dst, src3, t);
61868a414e9SRichard Henderson }
61968a414e9SRichard Henderson 
62068a414e9SRichard Henderson static void gen_op_fpmaddxhi(TCGv_i64 dst, TCGv_i64 src1,
62168a414e9SRichard Henderson                              TCGv_i64 src2, TCGv_i64 src3)
62268a414e9SRichard Henderson {
62368a414e9SRichard Henderson     TCGv_i64 l = tcg_temp_new_i64();
62468a414e9SRichard Henderson     TCGv_i64 h = tcg_temp_new_i64();
62568a414e9SRichard Henderson     TCGv_i64 z = tcg_constant_i64(0);
62668a414e9SRichard Henderson 
62768a414e9SRichard Henderson     tcg_gen_mulu2_i64(l, h, src1, src2);
62868a414e9SRichard Henderson     tcg_gen_add2_i64(l, dst, l, h, src3, z);
62968a414e9SRichard Henderson }
63068a414e9SRichard Henderson 
631c2636853SRichard Henderson static void gen_op_sdiv(TCGv dst, TCGv src1, TCGv src2)
632c2636853SRichard Henderson {
63313260103SRichard Henderson #ifdef TARGET_SPARC64
634c2636853SRichard Henderson     gen_helper_sdiv(dst, tcg_env, src1, src2);
63513260103SRichard Henderson     tcg_gen_ext32s_tl(dst, dst);
63613260103SRichard Henderson #else
63713260103SRichard Henderson     TCGv_i64 t64 = tcg_temp_new_i64();
63813260103SRichard Henderson     gen_helper_sdiv(t64, tcg_env, src1, src2);
63913260103SRichard Henderson     tcg_gen_trunc_i64_tl(dst, t64);
64013260103SRichard Henderson #endif
641c2636853SRichard Henderson }
642c2636853SRichard Henderson 
643c2636853SRichard Henderson static void gen_op_udivcc(TCGv dst, TCGv src1, TCGv src2)
644c2636853SRichard Henderson {
64513260103SRichard Henderson     TCGv_i64 t64;
64613260103SRichard Henderson 
64713260103SRichard Henderson #ifdef TARGET_SPARC64
64813260103SRichard Henderson     t64 = cpu_cc_V;
64913260103SRichard Henderson #else
65013260103SRichard Henderson     t64 = tcg_temp_new_i64();
65113260103SRichard Henderson #endif
65213260103SRichard Henderson 
65313260103SRichard Henderson     gen_helper_udiv(t64, tcg_env, src1, src2);
65413260103SRichard Henderson 
65513260103SRichard Henderson #ifdef TARGET_SPARC64
65613260103SRichard Henderson     tcg_gen_ext32u_tl(cpu_cc_N, t64);
65713260103SRichard Henderson     tcg_gen_shri_tl(cpu_cc_V, t64, 32);
65813260103SRichard Henderson     tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N);
65913260103SRichard Henderson     tcg_gen_movi_tl(cpu_icc_C, 0);
66013260103SRichard Henderson #else
66113260103SRichard Henderson     tcg_gen_extr_i64_tl(cpu_cc_N, cpu_cc_V, t64);
66213260103SRichard Henderson #endif
66313260103SRichard Henderson     tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N);
66413260103SRichard Henderson     tcg_gen_movi_tl(cpu_cc_C, 0);
66513260103SRichard Henderson     tcg_gen_mov_tl(dst, cpu_cc_N);
666c2636853SRichard Henderson }
667c2636853SRichard Henderson 
668c2636853SRichard Henderson static void gen_op_sdivcc(TCGv dst, TCGv src1, TCGv src2)
669c2636853SRichard Henderson {
67013260103SRichard Henderson     TCGv_i64 t64;
67113260103SRichard Henderson 
67213260103SRichard Henderson #ifdef TARGET_SPARC64
67313260103SRichard Henderson     t64 = cpu_cc_V;
67413260103SRichard Henderson #else
67513260103SRichard Henderson     t64 = tcg_temp_new_i64();
67613260103SRichard Henderson #endif
67713260103SRichard Henderson 
67813260103SRichard Henderson     gen_helper_sdiv(t64, tcg_env, src1, src2);
67913260103SRichard Henderson 
68013260103SRichard Henderson #ifdef TARGET_SPARC64
68113260103SRichard Henderson     tcg_gen_ext32s_tl(cpu_cc_N, t64);
68213260103SRichard Henderson     tcg_gen_shri_tl(cpu_cc_V, t64, 32);
68313260103SRichard Henderson     tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N);
68413260103SRichard Henderson     tcg_gen_movi_tl(cpu_icc_C, 0);
68513260103SRichard Henderson #else
68613260103SRichard Henderson     tcg_gen_extr_i64_tl(cpu_cc_N, cpu_cc_V, t64);
68713260103SRichard Henderson #endif
68813260103SRichard Henderson     tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N);
68913260103SRichard Henderson     tcg_gen_movi_tl(cpu_cc_C, 0);
69013260103SRichard Henderson     tcg_gen_mov_tl(dst, cpu_cc_N);
691c2636853SRichard Henderson }
692c2636853SRichard Henderson 
693a9aba13dSRichard Henderson static void gen_op_taddcctv(TCGv dst, TCGv src1, TCGv src2)
694a9aba13dSRichard Henderson {
695a9aba13dSRichard Henderson     gen_helper_taddcctv(dst, tcg_env, src1, src2);
696a9aba13dSRichard Henderson }
697a9aba13dSRichard Henderson 
698a9aba13dSRichard Henderson static void gen_op_tsubcctv(TCGv dst, TCGv src1, TCGv src2)
699a9aba13dSRichard Henderson {
700a9aba13dSRichard Henderson     gen_helper_tsubcctv(dst, tcg_env, src1, src2);
701a9aba13dSRichard Henderson }
702a9aba13dSRichard Henderson 
7039c6ec5bcSRichard Henderson static void gen_op_popc(TCGv dst, TCGv src1, TCGv src2)
7049c6ec5bcSRichard Henderson {
7059c6ec5bcSRichard Henderson     tcg_gen_ctpop_tl(dst, src2);
7069c6ec5bcSRichard Henderson }
7079c6ec5bcSRichard Henderson 
708875ce392SRichard Henderson static void gen_op_lzcnt(TCGv dst, TCGv src)
709875ce392SRichard Henderson {
710875ce392SRichard Henderson     tcg_gen_clzi_tl(dst, src, TARGET_LONG_BITS);
711875ce392SRichard Henderson }
712875ce392SRichard Henderson 
71345bfed3bSRichard Henderson #ifndef TARGET_SPARC64
71445bfed3bSRichard Henderson static void gen_helper_array8(TCGv dst, TCGv src1, TCGv src2)
71545bfed3bSRichard Henderson {
71645bfed3bSRichard Henderson     g_assert_not_reached();
71745bfed3bSRichard Henderson }
71845bfed3bSRichard Henderson #endif
71945bfed3bSRichard Henderson 
72045bfed3bSRichard Henderson static void gen_op_array16(TCGv dst, TCGv src1, TCGv src2)
72145bfed3bSRichard Henderson {
72245bfed3bSRichard Henderson     gen_helper_array8(dst, src1, src2);
72345bfed3bSRichard Henderson     tcg_gen_shli_tl(dst, dst, 1);
72445bfed3bSRichard Henderson }
72545bfed3bSRichard Henderson 
72645bfed3bSRichard Henderson static void gen_op_array32(TCGv dst, TCGv src1, TCGv src2)
72745bfed3bSRichard Henderson {
72845bfed3bSRichard Henderson     gen_helper_array8(dst, src1, src2);
72945bfed3bSRichard Henderson     tcg_gen_shli_tl(dst, dst, 2);
73045bfed3bSRichard Henderson }
73145bfed3bSRichard Henderson 
7322f722641SRichard Henderson static void gen_op_fpack16(TCGv_i32 dst, TCGv_i64 src)
7332f722641SRichard Henderson {
7342f722641SRichard Henderson #ifdef TARGET_SPARC64
7352f722641SRichard Henderson     gen_helper_fpack16(dst, cpu_gsr, src);
7362f722641SRichard Henderson #else
7372f722641SRichard Henderson     g_assert_not_reached();
7382f722641SRichard Henderson #endif
7392f722641SRichard Henderson }
7402f722641SRichard Henderson 
7412f722641SRichard Henderson static void gen_op_fpackfix(TCGv_i32 dst, TCGv_i64 src)
7422f722641SRichard Henderson {
7432f722641SRichard Henderson #ifdef TARGET_SPARC64
7442f722641SRichard Henderson     gen_helper_fpackfix(dst, cpu_gsr, src);
7452f722641SRichard Henderson #else
7462f722641SRichard Henderson     g_assert_not_reached();
7472f722641SRichard Henderson #endif
7482f722641SRichard Henderson }
7492f722641SRichard Henderson 
7504b6edc0aSRichard Henderson static void gen_op_fpack32(TCGv_i64 dst, TCGv_i64 src1, TCGv_i64 src2)
7514b6edc0aSRichard Henderson {
7524b6edc0aSRichard Henderson #ifdef TARGET_SPARC64
7534b6edc0aSRichard Henderson     gen_helper_fpack32(dst, cpu_gsr, src1, src2);
7544b6edc0aSRichard Henderson #else
7554b6edc0aSRichard Henderson     g_assert_not_reached();
7564b6edc0aSRichard Henderson #endif
7574b6edc0aSRichard Henderson }
7584b6edc0aSRichard Henderson 
7590d1d3aafSRichard Henderson static void gen_op_fpadds16s(TCGv_i32 d, TCGv_i32 src1, TCGv_i32 src2)
7600d1d3aafSRichard Henderson {
7610d1d3aafSRichard Henderson     TCGv_i32 t[2];
7620d1d3aafSRichard Henderson 
7630d1d3aafSRichard Henderson     for (int i = 0; i < 2; i++) {
7640d1d3aafSRichard Henderson         TCGv_i32 u = tcg_temp_new_i32();
7650d1d3aafSRichard Henderson         TCGv_i32 v = tcg_temp_new_i32();
7660d1d3aafSRichard Henderson 
7670d1d3aafSRichard Henderson         tcg_gen_sextract_i32(u, src1, i * 16, 16);
7680d1d3aafSRichard Henderson         tcg_gen_sextract_i32(v, src2, i * 16, 16);
7690d1d3aafSRichard Henderson         tcg_gen_add_i32(u, u, v);
7700d1d3aafSRichard Henderson         tcg_gen_smax_i32(u, u, tcg_constant_i32(INT16_MIN));
7710d1d3aafSRichard Henderson         tcg_gen_smin_i32(u, u, tcg_constant_i32(INT16_MAX));
7720d1d3aafSRichard Henderson         t[i] = u;
7730d1d3aafSRichard Henderson     }
7740d1d3aafSRichard Henderson     tcg_gen_deposit_i32(d, t[0], t[1], 16, 16);
7750d1d3aafSRichard Henderson }
7760d1d3aafSRichard Henderson 
7770d1d3aafSRichard Henderson static void gen_op_fpsubs16s(TCGv_i32 d, TCGv_i32 src1, TCGv_i32 src2)
7780d1d3aafSRichard Henderson {
7790d1d3aafSRichard Henderson     TCGv_i32 t[2];
7800d1d3aafSRichard Henderson 
7810d1d3aafSRichard Henderson     for (int i = 0; i < 2; i++) {
7820d1d3aafSRichard Henderson         TCGv_i32 u = tcg_temp_new_i32();
7830d1d3aafSRichard Henderson         TCGv_i32 v = tcg_temp_new_i32();
7840d1d3aafSRichard Henderson 
7850d1d3aafSRichard Henderson         tcg_gen_sextract_i32(u, src1, i * 16, 16);
7860d1d3aafSRichard Henderson         tcg_gen_sextract_i32(v, src2, i * 16, 16);
7870d1d3aafSRichard Henderson         tcg_gen_sub_i32(u, u, v);
7880d1d3aafSRichard Henderson         tcg_gen_smax_i32(u, u, tcg_constant_i32(INT16_MIN));
7890d1d3aafSRichard Henderson         tcg_gen_smin_i32(u, u, tcg_constant_i32(INT16_MAX));
7900d1d3aafSRichard Henderson         t[i] = u;
7910d1d3aafSRichard Henderson     }
7920d1d3aafSRichard Henderson     tcg_gen_deposit_i32(d, t[0], t[1], 16, 16);
7930d1d3aafSRichard Henderson }
7940d1d3aafSRichard Henderson 
7950d1d3aafSRichard Henderson static void gen_op_fpadds32s(TCGv_i32 d, TCGv_i32 src1, TCGv_i32 src2)
7960d1d3aafSRichard Henderson {
7970d1d3aafSRichard Henderson     TCGv_i32 r = tcg_temp_new_i32();
7980d1d3aafSRichard Henderson     TCGv_i32 t = tcg_temp_new_i32();
7990d1d3aafSRichard Henderson     TCGv_i32 v = tcg_temp_new_i32();
8000d1d3aafSRichard Henderson     TCGv_i32 z = tcg_constant_i32(0);
8010d1d3aafSRichard Henderson 
8020d1d3aafSRichard Henderson     tcg_gen_add_i32(r, src1, src2);
8030d1d3aafSRichard Henderson     tcg_gen_xor_i32(t, src1, src2);
8040d1d3aafSRichard Henderson     tcg_gen_xor_i32(v, r, src2);
8050d1d3aafSRichard Henderson     tcg_gen_andc_i32(v, v, t);
8060d1d3aafSRichard Henderson 
8070d1d3aafSRichard Henderson     tcg_gen_setcond_i32(TCG_COND_GE, t, r, z);
8080d1d3aafSRichard Henderson     tcg_gen_addi_i32(t, t, INT32_MAX);
8090d1d3aafSRichard Henderson 
8100d1d3aafSRichard Henderson     tcg_gen_movcond_i32(TCG_COND_LT, d, v, z, t, r);
8110d1d3aafSRichard Henderson }
8120d1d3aafSRichard Henderson 
8130d1d3aafSRichard Henderson static void gen_op_fpsubs32s(TCGv_i32 d, TCGv_i32 src1, TCGv_i32 src2)
8140d1d3aafSRichard Henderson {
8150d1d3aafSRichard Henderson     TCGv_i32 r = tcg_temp_new_i32();
8160d1d3aafSRichard Henderson     TCGv_i32 t = tcg_temp_new_i32();
8170d1d3aafSRichard Henderson     TCGv_i32 v = tcg_temp_new_i32();
8180d1d3aafSRichard Henderson     TCGv_i32 z = tcg_constant_i32(0);
8190d1d3aafSRichard Henderson 
8200d1d3aafSRichard Henderson     tcg_gen_sub_i32(r, src1, src2);
8210d1d3aafSRichard Henderson     tcg_gen_xor_i32(t, src1, src2);
8220d1d3aafSRichard Henderson     tcg_gen_xor_i32(v, r, src1);
8230d1d3aafSRichard Henderson     tcg_gen_and_i32(v, v, t);
8240d1d3aafSRichard Henderson 
8250d1d3aafSRichard Henderson     tcg_gen_setcond_i32(TCG_COND_GE, t, r, z);
8260d1d3aafSRichard Henderson     tcg_gen_addi_i32(t, t, INT32_MAX);
8270d1d3aafSRichard Henderson 
8280d1d3aafSRichard Henderson     tcg_gen_movcond_i32(TCG_COND_LT, d, v, z, t, r);
8290d1d3aafSRichard Henderson }
8300d1d3aafSRichard Henderson 
831b2b48493SRichard Henderson static void gen_op_faligndata_i(TCGv_i64 dst, TCGv_i64 s1,
832b2b48493SRichard Henderson                                 TCGv_i64 s2, TCGv gsr)
8334b6edc0aSRichard Henderson {
8344b6edc0aSRichard Henderson #ifdef TARGET_SPARC64
8354b6edc0aSRichard Henderson     TCGv t1, t2, shift;
8364b6edc0aSRichard Henderson 
8374b6edc0aSRichard Henderson     t1 = tcg_temp_new();
8384b6edc0aSRichard Henderson     t2 = tcg_temp_new();
8394b6edc0aSRichard Henderson     shift = tcg_temp_new();
8404b6edc0aSRichard Henderson 
841b2b48493SRichard Henderson     tcg_gen_andi_tl(shift, gsr, 7);
8424b6edc0aSRichard Henderson     tcg_gen_shli_tl(shift, shift, 3);
8434b6edc0aSRichard Henderson     tcg_gen_shl_tl(t1, s1, shift);
8444b6edc0aSRichard Henderson 
8454b6edc0aSRichard Henderson     /*
8464b6edc0aSRichard Henderson      * A shift of 64 does not produce 0 in TCG.  Divide this into a
8474b6edc0aSRichard Henderson      * shift of (up to 63) followed by a constant shift of 1.
8484b6edc0aSRichard Henderson      */
8494b6edc0aSRichard Henderson     tcg_gen_xori_tl(shift, shift, 63);
8504b6edc0aSRichard Henderson     tcg_gen_shr_tl(t2, s2, shift);
8514b6edc0aSRichard Henderson     tcg_gen_shri_tl(t2, t2, 1);
8524b6edc0aSRichard Henderson 
8534b6edc0aSRichard Henderson     tcg_gen_or_tl(dst, t1, t2);
8544b6edc0aSRichard Henderson #else
8554b6edc0aSRichard Henderson     g_assert_not_reached();
8564b6edc0aSRichard Henderson #endif
8574b6edc0aSRichard Henderson }
8584b6edc0aSRichard Henderson 
859b2b48493SRichard Henderson static void gen_op_faligndata_g(TCGv_i64 dst, TCGv_i64 s1, TCGv_i64 s2)
860b2b48493SRichard Henderson {
861b2b48493SRichard Henderson     gen_op_faligndata_i(dst, s1, s2, cpu_gsr);
862b2b48493SRichard Henderson }
863b2b48493SRichard Henderson 
8644b6edc0aSRichard Henderson static void gen_op_bshuffle(TCGv_i64 dst, TCGv_i64 src1, TCGv_i64 src2)
8654b6edc0aSRichard Henderson {
8664b6edc0aSRichard Henderson #ifdef TARGET_SPARC64
8674b6edc0aSRichard Henderson     gen_helper_bshuffle(dst, cpu_gsr, src1, src2);
8684b6edc0aSRichard Henderson #else
8694b6edc0aSRichard Henderson     g_assert_not_reached();
8704b6edc0aSRichard Henderson #endif
8714b6edc0aSRichard Henderson }
8724b6edc0aSRichard Henderson 
8737d5ebd8fSRichard Henderson static void gen_op_pdistn(TCGv dst, TCGv_i64 src1, TCGv_i64 src2)
8747d5ebd8fSRichard Henderson {
8757d5ebd8fSRichard Henderson #ifdef TARGET_SPARC64
8767d5ebd8fSRichard Henderson     gen_helper_pdist(dst, tcg_constant_i64(0), src1, src2);
8777d5ebd8fSRichard Henderson #else
8787d5ebd8fSRichard Henderson     g_assert_not_reached();
8797d5ebd8fSRichard Henderson #endif
8807d5ebd8fSRichard Henderson }
8817d5ebd8fSRichard Henderson 
882a859602cSRichard Henderson static void gen_op_fmul8x16al(TCGv_i64 dst, TCGv_i32 src1, TCGv_i32 src2)
883a859602cSRichard Henderson {
884a859602cSRichard Henderson     tcg_gen_ext16s_i32(src2, src2);
885a859602cSRichard Henderson     gen_helper_fmul8x16a(dst, src1, src2);
886a859602cSRichard Henderson }
887a859602cSRichard Henderson 
888a859602cSRichard Henderson static void gen_op_fmul8x16au(TCGv_i64 dst, TCGv_i32 src1, TCGv_i32 src2)
889a859602cSRichard Henderson {
890a859602cSRichard Henderson     tcg_gen_sari_i32(src2, src2, 16);
891a859602cSRichard Henderson     gen_helper_fmul8x16a(dst, src1, src2);
892a859602cSRichard Henderson }
893a859602cSRichard Henderson 
894be8998e0SRichard Henderson static void gen_op_fmuld8ulx16(TCGv_i64 dst, TCGv_i32 src1, TCGv_i32 src2)
895be8998e0SRichard Henderson {
896be8998e0SRichard Henderson     TCGv_i32 t0 = tcg_temp_new_i32();
897be8998e0SRichard Henderson     TCGv_i32 t1 = tcg_temp_new_i32();
898be8998e0SRichard Henderson     TCGv_i32 t2 = tcg_temp_new_i32();
899be8998e0SRichard Henderson 
900be8998e0SRichard Henderson     tcg_gen_ext8u_i32(t0, src1);
901be8998e0SRichard Henderson     tcg_gen_ext16s_i32(t1, src2);
902be8998e0SRichard Henderson     tcg_gen_mul_i32(t0, t0, t1);
903be8998e0SRichard Henderson 
904be8998e0SRichard Henderson     tcg_gen_extract_i32(t1, src1, 16, 8);
905be8998e0SRichard Henderson     tcg_gen_sextract_i32(t2, src2, 16, 16);
906be8998e0SRichard Henderson     tcg_gen_mul_i32(t1, t1, t2);
907be8998e0SRichard Henderson 
908be8998e0SRichard Henderson     tcg_gen_concat_i32_i64(dst, t0, t1);
909be8998e0SRichard Henderson }
910be8998e0SRichard Henderson 
911be8998e0SRichard Henderson static void gen_op_fmuld8sux16(TCGv_i64 dst, TCGv_i32 src1, TCGv_i32 src2)
912be8998e0SRichard Henderson {
913be8998e0SRichard Henderson     TCGv_i32 t0 = tcg_temp_new_i32();
914be8998e0SRichard Henderson     TCGv_i32 t1 = tcg_temp_new_i32();
915be8998e0SRichard Henderson     TCGv_i32 t2 = tcg_temp_new_i32();
916be8998e0SRichard Henderson 
917be8998e0SRichard Henderson     /*
918be8998e0SRichard Henderson      * The insn description talks about extracting the upper 8 bits
919be8998e0SRichard Henderson      * of the signed 16-bit input rs1, performing the multiply, then
920be8998e0SRichard Henderson      * shifting left by 8 bits.  Instead, zap the lower 8 bits of
921be8998e0SRichard Henderson      * the rs1 input, which avoids the need for two shifts.
922be8998e0SRichard Henderson      */
923be8998e0SRichard Henderson     tcg_gen_ext16s_i32(t0, src1);
924be8998e0SRichard Henderson     tcg_gen_andi_i32(t0, t0, ~0xff);
925be8998e0SRichard Henderson     tcg_gen_ext16s_i32(t1, src2);
926be8998e0SRichard Henderson     tcg_gen_mul_i32(t0, t0, t1);
927be8998e0SRichard Henderson 
928be8998e0SRichard Henderson     tcg_gen_sextract_i32(t1, src1, 16, 16);
929be8998e0SRichard Henderson     tcg_gen_andi_i32(t1, t1, ~0xff);
930be8998e0SRichard Henderson     tcg_gen_sextract_i32(t2, src2, 16, 16);
931be8998e0SRichard Henderson     tcg_gen_mul_i32(t1, t1, t2);
932be8998e0SRichard Henderson 
933be8998e0SRichard Henderson     tcg_gen_concat_i32_i64(dst, t0, t1);
934be8998e0SRichard Henderson }
935be8998e0SRichard Henderson 
9367837185eSRichard Henderson #ifdef TARGET_SPARC64
9377837185eSRichard Henderson static void gen_vec_fchksm16(unsigned vece, TCGv_vec dst,
9387837185eSRichard Henderson                              TCGv_vec src1, TCGv_vec src2)
9397837185eSRichard Henderson {
9407837185eSRichard Henderson     TCGv_vec a = tcg_temp_new_vec_matching(dst);
9417837185eSRichard Henderson     TCGv_vec c = tcg_temp_new_vec_matching(dst);
9427837185eSRichard Henderson 
9437837185eSRichard Henderson     tcg_gen_add_vec(vece, a, src1, src2);
9447837185eSRichard Henderson     tcg_gen_cmp_vec(TCG_COND_LTU, vece, c, a, src1);
9457837185eSRichard Henderson     /* Vector cmp produces -1 for true, so subtract to add carry. */
9467837185eSRichard Henderson     tcg_gen_sub_vec(vece, dst, a, c);
9477837185eSRichard Henderson }
9487837185eSRichard Henderson 
9497837185eSRichard Henderson static void gen_op_fchksm16(unsigned vece, uint32_t dofs, uint32_t aofs,
9507837185eSRichard Henderson                             uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
9517837185eSRichard Henderson {
9527837185eSRichard Henderson     static const TCGOpcode vecop_list[] = {
9537837185eSRichard Henderson         INDEX_op_cmp_vec, INDEX_op_add_vec, INDEX_op_sub_vec,
9547837185eSRichard Henderson     };
9557837185eSRichard Henderson     static const GVecGen3 op = {
9567837185eSRichard Henderson         .fni8 = gen_helper_fchksm16,
9577837185eSRichard Henderson         .fniv = gen_vec_fchksm16,
9587837185eSRichard Henderson         .opt_opc = vecop_list,
9597837185eSRichard Henderson         .vece = MO_16,
9607837185eSRichard Henderson     };
9617837185eSRichard Henderson     tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &op);
9627837185eSRichard Henderson }
963d6ff1ccbSRichard Henderson 
964d6ff1ccbSRichard Henderson static void gen_vec_fmean16(unsigned vece, TCGv_vec dst,
965d6ff1ccbSRichard Henderson                             TCGv_vec src1, TCGv_vec src2)
966d6ff1ccbSRichard Henderson {
967d6ff1ccbSRichard Henderson     TCGv_vec t = tcg_temp_new_vec_matching(dst);
968d6ff1ccbSRichard Henderson 
969d6ff1ccbSRichard Henderson     tcg_gen_or_vec(vece, t, src1, src2);
970d6ff1ccbSRichard Henderson     tcg_gen_and_vec(vece, t, t, tcg_constant_vec_matching(dst, vece, 1));
971d6ff1ccbSRichard Henderson     tcg_gen_sari_vec(vece, src1, src1, 1);
972d6ff1ccbSRichard Henderson     tcg_gen_sari_vec(vece, src2, src2, 1);
973d6ff1ccbSRichard Henderson     tcg_gen_add_vec(vece, dst, src1, src2);
974d6ff1ccbSRichard Henderson     tcg_gen_add_vec(vece, dst, dst, t);
975d6ff1ccbSRichard Henderson }
976d6ff1ccbSRichard Henderson 
977d6ff1ccbSRichard Henderson static void gen_op_fmean16(unsigned vece, uint32_t dofs, uint32_t aofs,
978d6ff1ccbSRichard Henderson                            uint32_t bofs, uint32_t oprsz, uint32_t maxsz)
979d6ff1ccbSRichard Henderson {
980d6ff1ccbSRichard Henderson     static const TCGOpcode vecop_list[] = {
981d6ff1ccbSRichard Henderson         INDEX_op_add_vec, INDEX_op_sari_vec,
982d6ff1ccbSRichard Henderson     };
983d6ff1ccbSRichard Henderson     static const GVecGen3 op = {
984d6ff1ccbSRichard Henderson         .fni8 = gen_helper_fmean16,
985d6ff1ccbSRichard Henderson         .fniv = gen_vec_fmean16,
986d6ff1ccbSRichard Henderson         .opt_opc = vecop_list,
987d6ff1ccbSRichard Henderson         .vece = MO_16,
988d6ff1ccbSRichard Henderson     };
989d6ff1ccbSRichard Henderson     tcg_gen_gvec_3(dofs, aofs, bofs, oprsz, maxsz, &op);
990d6ff1ccbSRichard Henderson }
9917837185eSRichard Henderson #else
9927837185eSRichard Henderson #define gen_op_fchksm16   ({ qemu_build_not_reached(); NULL; })
993d6ff1ccbSRichard Henderson #define gen_op_fmean16    ({ qemu_build_not_reached(); NULL; })
9947837185eSRichard Henderson #endif
9957837185eSRichard Henderson 
99689527e3aSRichard Henderson static void finishing_insn(DisasContext *dc)
99789527e3aSRichard Henderson {
99889527e3aSRichard Henderson     /*
99989527e3aSRichard Henderson      * From here, there is no future path through an unwinding exception.
100089527e3aSRichard Henderson      * If the current insn cannot raise an exception, the computation of
100189527e3aSRichard Henderson      * cpu_cond may be able to be elided.
100289527e3aSRichard Henderson      */
100389527e3aSRichard Henderson     if (dc->cpu_cond_live) {
100489527e3aSRichard Henderson         tcg_gen_discard_tl(cpu_cond);
100589527e3aSRichard Henderson         dc->cpu_cond_live = false;
100689527e3aSRichard Henderson     }
100789527e3aSRichard Henderson }
100889527e3aSRichard Henderson 
10090c2e96c1SRichard Henderson static void gen_generic_branch(DisasContext *dc)
1010fcf5ef2aSThomas Huth {
101100ab7e61SRichard Henderson     TCGv npc0 = tcg_constant_tl(dc->jump_pc[0]);
101200ab7e61SRichard Henderson     TCGv npc1 = tcg_constant_tl(dc->jump_pc[1]);
1013533f042fSRichard Henderson     TCGv c2 = tcg_constant_tl(dc->jump.c2);
1014fcf5ef2aSThomas Huth 
1015533f042fSRichard Henderson     tcg_gen_movcond_tl(dc->jump.cond, cpu_npc, dc->jump.c1, c2, npc0, npc1);
1016fcf5ef2aSThomas Huth }
1017fcf5ef2aSThomas Huth 
1018fcf5ef2aSThomas Huth /* call this function before using the condition register as it may
1019fcf5ef2aSThomas Huth    have been set for a jump */
10200c2e96c1SRichard Henderson static void flush_cond(DisasContext *dc)
1021fcf5ef2aSThomas Huth {
1022fcf5ef2aSThomas Huth     if (dc->npc == JUMP_PC) {
1023fcf5ef2aSThomas Huth         gen_generic_branch(dc);
102499c82c47SRichard Henderson         dc->npc = DYNAMIC_PC_LOOKUP;
1025fcf5ef2aSThomas Huth     }
1026fcf5ef2aSThomas Huth }
1027fcf5ef2aSThomas Huth 
10280c2e96c1SRichard Henderson static void save_npc(DisasContext *dc)
1029fcf5ef2aSThomas Huth {
1030633c4283SRichard Henderson     if (dc->npc & 3) {
1031633c4283SRichard Henderson         switch (dc->npc) {
1032633c4283SRichard Henderson         case JUMP_PC:
1033fcf5ef2aSThomas Huth             gen_generic_branch(dc);
103499c82c47SRichard Henderson             dc->npc = DYNAMIC_PC_LOOKUP;
1035633c4283SRichard Henderson             break;
1036633c4283SRichard Henderson         case DYNAMIC_PC:
1037633c4283SRichard Henderson         case DYNAMIC_PC_LOOKUP:
1038633c4283SRichard Henderson             break;
1039633c4283SRichard Henderson         default:
1040633c4283SRichard Henderson             g_assert_not_reached();
1041633c4283SRichard Henderson         }
1042633c4283SRichard Henderson     } else {
1043fcf5ef2aSThomas Huth         tcg_gen_movi_tl(cpu_npc, dc->npc);
1044fcf5ef2aSThomas Huth     }
1045fcf5ef2aSThomas Huth }
1046fcf5ef2aSThomas Huth 
10470c2e96c1SRichard Henderson static void save_state(DisasContext *dc)
1048fcf5ef2aSThomas Huth {
1049fcf5ef2aSThomas Huth     tcg_gen_movi_tl(cpu_pc, dc->pc);
1050fcf5ef2aSThomas Huth     save_npc(dc);
1051fcf5ef2aSThomas Huth }
1052fcf5ef2aSThomas Huth 
1053fcf5ef2aSThomas Huth static void gen_exception(DisasContext *dc, int which)
1054fcf5ef2aSThomas Huth {
105589527e3aSRichard Henderson     finishing_insn(dc);
1056fcf5ef2aSThomas Huth     save_state(dc);
1057ad75a51eSRichard Henderson     gen_helper_raise_exception(tcg_env, tcg_constant_i32(which));
1058af00be49SEmilio G. Cota     dc->base.is_jmp = DISAS_NORETURN;
1059fcf5ef2aSThomas Huth }
1060fcf5ef2aSThomas Huth 
1061186e7890SRichard Henderson static TCGLabel *delay_exceptionv(DisasContext *dc, TCGv_i32 excp)
1062fcf5ef2aSThomas Huth {
1063186e7890SRichard Henderson     DisasDelayException *e = g_new0(DisasDelayException, 1);
1064186e7890SRichard Henderson 
1065186e7890SRichard Henderson     e->next = dc->delay_excp_list;
1066186e7890SRichard Henderson     dc->delay_excp_list = e;
1067186e7890SRichard Henderson 
1068186e7890SRichard Henderson     e->lab = gen_new_label();
1069186e7890SRichard Henderson     e->excp = excp;
1070186e7890SRichard Henderson     e->pc = dc->pc;
1071186e7890SRichard Henderson     /* Caller must have used flush_cond before branch. */
1072186e7890SRichard Henderson     assert(e->npc != JUMP_PC);
1073186e7890SRichard Henderson     e->npc = dc->npc;
1074186e7890SRichard Henderson 
1075186e7890SRichard Henderson     return e->lab;
1076186e7890SRichard Henderson }
1077186e7890SRichard Henderson 
1078186e7890SRichard Henderson static TCGLabel *delay_exception(DisasContext *dc, int excp)
1079186e7890SRichard Henderson {
1080186e7890SRichard Henderson     return delay_exceptionv(dc, tcg_constant_i32(excp));
1081186e7890SRichard Henderson }
1082186e7890SRichard Henderson 
1083186e7890SRichard Henderson static void gen_check_align(DisasContext *dc, TCGv addr, int mask)
1084186e7890SRichard Henderson {
1085186e7890SRichard Henderson     TCGv t = tcg_temp_new();
1086186e7890SRichard Henderson     TCGLabel *lab;
1087186e7890SRichard Henderson 
1088186e7890SRichard Henderson     tcg_gen_andi_tl(t, addr, mask);
1089186e7890SRichard Henderson 
1090186e7890SRichard Henderson     flush_cond(dc);
1091186e7890SRichard Henderson     lab = delay_exception(dc, TT_UNALIGNED);
1092186e7890SRichard Henderson     tcg_gen_brcondi_tl(TCG_COND_NE, t, 0, lab);
1093fcf5ef2aSThomas Huth }
1094fcf5ef2aSThomas Huth 
10950c2e96c1SRichard Henderson static void gen_mov_pc_npc(DisasContext *dc)
1096fcf5ef2aSThomas Huth {
109789527e3aSRichard Henderson     finishing_insn(dc);
109889527e3aSRichard Henderson 
1099633c4283SRichard Henderson     if (dc->npc & 3) {
1100633c4283SRichard Henderson         switch (dc->npc) {
1101633c4283SRichard Henderson         case JUMP_PC:
1102fcf5ef2aSThomas Huth             gen_generic_branch(dc);
1103fcf5ef2aSThomas Huth             tcg_gen_mov_tl(cpu_pc, cpu_npc);
110499c82c47SRichard Henderson             dc->pc = DYNAMIC_PC_LOOKUP;
1105633c4283SRichard Henderson             break;
1106633c4283SRichard Henderson         case DYNAMIC_PC:
1107633c4283SRichard Henderson         case DYNAMIC_PC_LOOKUP:
1108fcf5ef2aSThomas Huth             tcg_gen_mov_tl(cpu_pc, cpu_npc);
1109633c4283SRichard Henderson             dc->pc = dc->npc;
1110633c4283SRichard Henderson             break;
1111633c4283SRichard Henderson         default:
1112633c4283SRichard Henderson             g_assert_not_reached();
1113633c4283SRichard Henderson         }
1114fcf5ef2aSThomas Huth     } else {
1115fcf5ef2aSThomas Huth         dc->pc = dc->npc;
1116fcf5ef2aSThomas Huth     }
1117fcf5ef2aSThomas Huth }
1118fcf5ef2aSThomas Huth 
1119fcf5ef2aSThomas Huth static void gen_compare(DisasCompare *cmp, bool xcc, unsigned int cond,
1120fcf5ef2aSThomas Huth                         DisasContext *dc)
1121fcf5ef2aSThomas Huth {
1122b597eedcSRichard Henderson     TCGv t1;
1123fcf5ef2aSThomas Huth 
11242a1905c7SRichard Henderson     cmp->c1 = t1 = tcg_temp_new();
1125c8507ebfSRichard Henderson     cmp->c2 = 0;
11262a1905c7SRichard Henderson 
11272a1905c7SRichard Henderson     switch (cond & 7) {
11282a1905c7SRichard Henderson     case 0x0: /* never */
11292a1905c7SRichard Henderson         cmp->cond = TCG_COND_NEVER;
1130c8507ebfSRichard Henderson         cmp->c1 = tcg_constant_tl(0);
1131fcf5ef2aSThomas Huth         break;
11322a1905c7SRichard Henderson 
11332a1905c7SRichard Henderson     case 0x1: /* eq: Z */
11342a1905c7SRichard Henderson         cmp->cond = TCG_COND_EQ;
11352a1905c7SRichard Henderson         if (TARGET_LONG_BITS == 32 || xcc) {
11362a1905c7SRichard Henderson             tcg_gen_mov_tl(t1, cpu_cc_Z);
11372a1905c7SRichard Henderson         } else {
11382a1905c7SRichard Henderson             tcg_gen_ext32u_tl(t1, cpu_icc_Z);
11392a1905c7SRichard Henderson         }
11402a1905c7SRichard Henderson         break;
11412a1905c7SRichard Henderson 
11422a1905c7SRichard Henderson     case 0x2: /* le: Z | (N ^ V) */
11432a1905c7SRichard Henderson         /*
11442a1905c7SRichard Henderson          * Simplify:
11452a1905c7SRichard Henderson          *   cc_Z || (N ^ V) < 0        NE
11462a1905c7SRichard Henderson          *   cc_Z && !((N ^ V) < 0)     EQ
11472a1905c7SRichard Henderson          *   cc_Z & ~((N ^ V) >> TLB)   EQ
11482a1905c7SRichard Henderson          */
11492a1905c7SRichard Henderson         cmp->cond = TCG_COND_EQ;
11502a1905c7SRichard Henderson         tcg_gen_xor_tl(t1, cpu_cc_N, cpu_cc_V);
11512a1905c7SRichard Henderson         tcg_gen_sextract_tl(t1, t1, xcc ? 63 : 31, 1);
11522a1905c7SRichard Henderson         tcg_gen_andc_tl(t1, xcc ? cpu_cc_Z : cpu_icc_Z, t1);
11532a1905c7SRichard Henderson         if (TARGET_LONG_BITS == 64 && !xcc) {
11542a1905c7SRichard Henderson             tcg_gen_ext32u_tl(t1, t1);
11552a1905c7SRichard Henderson         }
11562a1905c7SRichard Henderson         break;
11572a1905c7SRichard Henderson 
11582a1905c7SRichard Henderson     case 0x3: /* lt: N ^ V */
11592a1905c7SRichard Henderson         cmp->cond = TCG_COND_LT;
11602a1905c7SRichard Henderson         tcg_gen_xor_tl(t1, cpu_cc_N, cpu_cc_V);
11612a1905c7SRichard Henderson         if (TARGET_LONG_BITS == 64 && !xcc) {
11622a1905c7SRichard Henderson             tcg_gen_ext32s_tl(t1, t1);
11632a1905c7SRichard Henderson         }
11642a1905c7SRichard Henderson         break;
11652a1905c7SRichard Henderson 
11662a1905c7SRichard Henderson     case 0x4: /* leu: Z | C */
11672a1905c7SRichard Henderson         /*
11682a1905c7SRichard Henderson          * Simplify:
11692a1905c7SRichard Henderson          *   cc_Z == 0 || cc_C != 0     NE
11702a1905c7SRichard Henderson          *   cc_Z != 0 && cc_C == 0     EQ
11712a1905c7SRichard Henderson          *   cc_Z & (cc_C ? 0 : -1)     EQ
11722a1905c7SRichard Henderson          *   cc_Z & (cc_C - 1)          EQ
11732a1905c7SRichard Henderson          */
11742a1905c7SRichard Henderson         cmp->cond = TCG_COND_EQ;
11752a1905c7SRichard Henderson         if (TARGET_LONG_BITS == 32 || xcc) {
11762a1905c7SRichard Henderson             tcg_gen_subi_tl(t1, cpu_cc_C, 1);
11772a1905c7SRichard Henderson             tcg_gen_and_tl(t1, t1, cpu_cc_Z);
11782a1905c7SRichard Henderson         } else {
11792a1905c7SRichard Henderson             tcg_gen_extract_tl(t1, cpu_icc_C, 32, 1);
11802a1905c7SRichard Henderson             tcg_gen_subi_tl(t1, t1, 1);
11812a1905c7SRichard Henderson             tcg_gen_and_tl(t1, t1, cpu_icc_Z);
11822a1905c7SRichard Henderson             tcg_gen_ext32u_tl(t1, t1);
11832a1905c7SRichard Henderson         }
11842a1905c7SRichard Henderson         break;
11852a1905c7SRichard Henderson 
11862a1905c7SRichard Henderson     case 0x5: /* ltu: C */
11872a1905c7SRichard Henderson         cmp->cond = TCG_COND_NE;
11882a1905c7SRichard Henderson         if (TARGET_LONG_BITS == 32 || xcc) {
11892a1905c7SRichard Henderson             tcg_gen_mov_tl(t1, cpu_cc_C);
11902a1905c7SRichard Henderson         } else {
11912a1905c7SRichard Henderson             tcg_gen_extract_tl(t1, cpu_icc_C, 32, 1);
11922a1905c7SRichard Henderson         }
11932a1905c7SRichard Henderson         break;
11942a1905c7SRichard Henderson 
11952a1905c7SRichard Henderson     case 0x6: /* neg: N */
11962a1905c7SRichard Henderson         cmp->cond = TCG_COND_LT;
11972a1905c7SRichard Henderson         if (TARGET_LONG_BITS == 32 || xcc) {
11982a1905c7SRichard Henderson             tcg_gen_mov_tl(t1, cpu_cc_N);
11992a1905c7SRichard Henderson         } else {
12002a1905c7SRichard Henderson             tcg_gen_ext32s_tl(t1, cpu_cc_N);
12012a1905c7SRichard Henderson         }
12022a1905c7SRichard Henderson         break;
12032a1905c7SRichard Henderson 
12042a1905c7SRichard Henderson     case 0x7: /* vs: V */
12052a1905c7SRichard Henderson         cmp->cond = TCG_COND_LT;
12062a1905c7SRichard Henderson         if (TARGET_LONG_BITS == 32 || xcc) {
12072a1905c7SRichard Henderson             tcg_gen_mov_tl(t1, cpu_cc_V);
12082a1905c7SRichard Henderson         } else {
12092a1905c7SRichard Henderson             tcg_gen_ext32s_tl(t1, cpu_cc_V);
12102a1905c7SRichard Henderson         }
12112a1905c7SRichard Henderson         break;
12122a1905c7SRichard Henderson     }
12132a1905c7SRichard Henderson     if (cond & 8) {
12142a1905c7SRichard Henderson         cmp->cond = tcg_invert_cond(cmp->cond);
1215fcf5ef2aSThomas Huth     }
1216fcf5ef2aSThomas Huth }
1217fcf5ef2aSThomas Huth 
1218fcf5ef2aSThomas Huth static void gen_fcompare(DisasCompare *cmp, unsigned int cc, unsigned int cond)
1219fcf5ef2aSThomas Huth {
1220d8c5b92fSRichard Henderson     TCGv_i32 fcc = cpu_fcc[cc];
1221d8c5b92fSRichard Henderson     TCGv_i32 c1 = fcc;
1222d8c5b92fSRichard Henderson     int c2 = 0;
1223d8c5b92fSRichard Henderson     TCGCond tcond;
1224fcf5ef2aSThomas Huth 
1225d8c5b92fSRichard Henderson     /*
1226d8c5b92fSRichard Henderson      * FCC values:
1227d8c5b92fSRichard Henderson      * 0 =
1228d8c5b92fSRichard Henderson      * 1 <
1229d8c5b92fSRichard Henderson      * 2 >
1230d8c5b92fSRichard Henderson      * 3 unordered
1231d8c5b92fSRichard Henderson      */
1232d8c5b92fSRichard Henderson     switch (cond & 7) {
1233d8c5b92fSRichard Henderson     case 0x0: /* fbn */
1234d8c5b92fSRichard Henderson         tcond = TCG_COND_NEVER;
1235fcf5ef2aSThomas Huth         break;
1236d8c5b92fSRichard Henderson     case 0x1: /* fbne : !0 */
1237d8c5b92fSRichard Henderson         tcond = TCG_COND_NE;
1238fcf5ef2aSThomas Huth         break;
1239d8c5b92fSRichard Henderson     case 0x2: /* fblg : 1 or 2 */
1240d8c5b92fSRichard Henderson         /* fcc in {1,2} - 1 -> fcc in {0,1} */
1241d8c5b92fSRichard Henderson         c1 = tcg_temp_new_i32();
1242d8c5b92fSRichard Henderson         tcg_gen_addi_i32(c1, fcc, -1);
1243d8c5b92fSRichard Henderson         c2 = 1;
1244d8c5b92fSRichard Henderson         tcond = TCG_COND_LEU;
1245fcf5ef2aSThomas Huth         break;
1246d8c5b92fSRichard Henderson     case 0x3: /* fbul : 1 or 3 */
1247d8c5b92fSRichard Henderson         c1 = tcg_temp_new_i32();
1248d8c5b92fSRichard Henderson         tcg_gen_andi_i32(c1, fcc, 1);
1249d8c5b92fSRichard Henderson         tcond = TCG_COND_NE;
1250d8c5b92fSRichard Henderson         break;
1251d8c5b92fSRichard Henderson     case 0x4: /* fbl  : 1 */
1252d8c5b92fSRichard Henderson         c2 = 1;
1253d8c5b92fSRichard Henderson         tcond = TCG_COND_EQ;
1254d8c5b92fSRichard Henderson         break;
1255d8c5b92fSRichard Henderson     case 0x5: /* fbug : 2 or 3 */
1256d8c5b92fSRichard Henderson         c2 = 2;
1257d8c5b92fSRichard Henderson         tcond = TCG_COND_GEU;
1258d8c5b92fSRichard Henderson         break;
1259d8c5b92fSRichard Henderson     case 0x6: /* fbg  : 2 */
1260d8c5b92fSRichard Henderson         c2 = 2;
1261d8c5b92fSRichard Henderson         tcond = TCG_COND_EQ;
1262d8c5b92fSRichard Henderson         break;
1263d8c5b92fSRichard Henderson     case 0x7: /* fbu  : 3 */
1264d8c5b92fSRichard Henderson         c2 = 3;
1265d8c5b92fSRichard Henderson         tcond = TCG_COND_EQ;
1266fcf5ef2aSThomas Huth         break;
1267fcf5ef2aSThomas Huth     }
1268d8c5b92fSRichard Henderson     if (cond & 8) {
1269d8c5b92fSRichard Henderson         tcond = tcg_invert_cond(tcond);
1270fcf5ef2aSThomas Huth     }
1271d8c5b92fSRichard Henderson 
1272d8c5b92fSRichard Henderson     cmp->cond = tcond;
1273d8c5b92fSRichard Henderson     cmp->c2 = c2;
1274d8c5b92fSRichard Henderson     cmp->c1 = tcg_temp_new();
1275d8c5b92fSRichard Henderson     tcg_gen_extu_i32_tl(cmp->c1, c1);
1276fcf5ef2aSThomas Huth }
1277fcf5ef2aSThomas Huth 
12782c4f56c9SRichard Henderson static bool gen_compare_reg(DisasCompare *cmp, int cond, TCGv r_src)
12792c4f56c9SRichard Henderson {
12802c4f56c9SRichard Henderson     static const TCGCond cond_reg[4] = {
1281ab9ffe98SRichard Henderson         TCG_COND_NEVER,  /* reserved */
1282fcf5ef2aSThomas Huth         TCG_COND_EQ,
1283fcf5ef2aSThomas Huth         TCG_COND_LE,
1284fcf5ef2aSThomas Huth         TCG_COND_LT,
1285fcf5ef2aSThomas Huth     };
12862c4f56c9SRichard Henderson     TCGCond tcond;
1287fcf5ef2aSThomas Huth 
12882c4f56c9SRichard Henderson     if ((cond & 3) == 0) {
12892c4f56c9SRichard Henderson         return false;
12902c4f56c9SRichard Henderson     }
12912c4f56c9SRichard Henderson     tcond = cond_reg[cond & 3];
12922c4f56c9SRichard Henderson     if (cond & 4) {
12932c4f56c9SRichard Henderson         tcond = tcg_invert_cond(tcond);
12942c4f56c9SRichard Henderson     }
12952c4f56c9SRichard Henderson 
12962c4f56c9SRichard Henderson     cmp->cond = tcond;
1297816f89b7SRichard Henderson     cmp->c1 = tcg_temp_new();
1298c8507ebfSRichard Henderson     cmp->c2 = 0;
1299816f89b7SRichard Henderson     tcg_gen_mov_tl(cmp->c1, r_src);
13002c4f56c9SRichard Henderson     return true;
1301fcf5ef2aSThomas Huth }
1302fcf5ef2aSThomas Huth 
1303baf3dbf2SRichard Henderson static void gen_op_clear_ieee_excp_and_FTT(void)
1304baf3dbf2SRichard Henderson {
13053590f01eSRichard Henderson     tcg_gen_st_i32(tcg_constant_i32(0), tcg_env,
13063590f01eSRichard Henderson                    offsetof(CPUSPARCState, fsr_cexc_ftt));
1307baf3dbf2SRichard Henderson }
1308baf3dbf2SRichard Henderson 
1309baf3dbf2SRichard Henderson static void gen_op_fmovs(TCGv_i32 dst, TCGv_i32 src)
1310baf3dbf2SRichard Henderson {
1311baf3dbf2SRichard Henderson     gen_op_clear_ieee_excp_and_FTT();
1312baf3dbf2SRichard Henderson     tcg_gen_mov_i32(dst, src);
1313baf3dbf2SRichard Henderson }
1314baf3dbf2SRichard Henderson 
1315baf3dbf2SRichard Henderson static void gen_op_fnegs(TCGv_i32 dst, TCGv_i32 src)
1316baf3dbf2SRichard Henderson {
1317baf3dbf2SRichard Henderson     gen_op_clear_ieee_excp_and_FTT();
1318daf457d4SRichard Henderson     tcg_gen_xori_i32(dst, src, 1u << 31);
1319baf3dbf2SRichard Henderson }
1320baf3dbf2SRichard Henderson 
1321baf3dbf2SRichard Henderson static void gen_op_fabss(TCGv_i32 dst, TCGv_i32 src)
1322baf3dbf2SRichard Henderson {
1323baf3dbf2SRichard Henderson     gen_op_clear_ieee_excp_and_FTT();
1324daf457d4SRichard Henderson     tcg_gen_andi_i32(dst, src, ~(1u << 31));
1325baf3dbf2SRichard Henderson }
1326baf3dbf2SRichard Henderson 
1327c6d83e4fSRichard Henderson static void gen_op_fmovd(TCGv_i64 dst, TCGv_i64 src)
1328c6d83e4fSRichard Henderson {
1329c6d83e4fSRichard Henderson     gen_op_clear_ieee_excp_and_FTT();
1330c6d83e4fSRichard Henderson     tcg_gen_mov_i64(dst, src);
1331c6d83e4fSRichard Henderson }
1332c6d83e4fSRichard Henderson 
1333c6d83e4fSRichard Henderson static void gen_op_fnegd(TCGv_i64 dst, TCGv_i64 src)
1334c6d83e4fSRichard Henderson {
1335c6d83e4fSRichard Henderson     gen_op_clear_ieee_excp_and_FTT();
1336daf457d4SRichard Henderson     tcg_gen_xori_i64(dst, src, 1ull << 63);
1337c6d83e4fSRichard Henderson }
1338c6d83e4fSRichard Henderson 
1339c6d83e4fSRichard Henderson static void gen_op_fabsd(TCGv_i64 dst, TCGv_i64 src)
1340c6d83e4fSRichard Henderson {
1341c6d83e4fSRichard Henderson     gen_op_clear_ieee_excp_and_FTT();
1342daf457d4SRichard Henderson     tcg_gen_andi_i64(dst, src, ~(1ull << 63));
1343daf457d4SRichard Henderson }
1344daf457d4SRichard Henderson 
1345daf457d4SRichard Henderson static void gen_op_fnegq(TCGv_i128 dst, TCGv_i128 src)
1346daf457d4SRichard Henderson {
1347daf457d4SRichard Henderson     TCGv_i64 l = tcg_temp_new_i64();
1348daf457d4SRichard Henderson     TCGv_i64 h = tcg_temp_new_i64();
1349daf457d4SRichard Henderson 
1350daf457d4SRichard Henderson     tcg_gen_extr_i128_i64(l, h, src);
1351daf457d4SRichard Henderson     tcg_gen_xori_i64(h, h, 1ull << 63);
1352daf457d4SRichard Henderson     tcg_gen_concat_i64_i128(dst, l, h);
1353daf457d4SRichard Henderson }
1354daf457d4SRichard Henderson 
1355daf457d4SRichard Henderson static void gen_op_fabsq(TCGv_i128 dst, TCGv_i128 src)
1356daf457d4SRichard Henderson {
1357daf457d4SRichard Henderson     TCGv_i64 l = tcg_temp_new_i64();
1358daf457d4SRichard Henderson     TCGv_i64 h = tcg_temp_new_i64();
1359daf457d4SRichard Henderson 
1360daf457d4SRichard Henderson     tcg_gen_extr_i128_i64(l, h, src);
1361daf457d4SRichard Henderson     tcg_gen_andi_i64(h, h, ~(1ull << 63));
1362daf457d4SRichard Henderson     tcg_gen_concat_i64_i128(dst, l, h);
1363c6d83e4fSRichard Henderson }
1364c6d83e4fSRichard Henderson 
13654fd71d19SRichard Henderson static void gen_op_fmadds(TCGv_i32 d, TCGv_i32 s1, TCGv_i32 s2, TCGv_i32 s3)
13664fd71d19SRichard Henderson {
13674fd71d19SRichard Henderson     gen_helper_fmadds(d, tcg_env, s1, s2, s3, tcg_constant_i32(0));
13684fd71d19SRichard Henderson }
13694fd71d19SRichard Henderson 
13704fd71d19SRichard Henderson static void gen_op_fmaddd(TCGv_i64 d, TCGv_i64 s1, TCGv_i64 s2, TCGv_i64 s3)
13714fd71d19SRichard Henderson {
13724fd71d19SRichard Henderson     gen_helper_fmaddd(d, tcg_env, s1, s2, s3, tcg_constant_i32(0));
13734fd71d19SRichard Henderson }
13744fd71d19SRichard Henderson 
13754fd71d19SRichard Henderson static void gen_op_fmsubs(TCGv_i32 d, TCGv_i32 s1, TCGv_i32 s2, TCGv_i32 s3)
13764fd71d19SRichard Henderson {
13774fd71d19SRichard Henderson     int op = float_muladd_negate_c;
13784fd71d19SRichard Henderson     gen_helper_fmadds(d, tcg_env, s1, s2, s3, tcg_constant_i32(op));
13794fd71d19SRichard Henderson }
13804fd71d19SRichard Henderson 
13814fd71d19SRichard Henderson static void gen_op_fmsubd(TCGv_i64 d, TCGv_i64 s1, TCGv_i64 s2, TCGv_i64 s3)
13824fd71d19SRichard Henderson {
13834fd71d19SRichard Henderson     int op = float_muladd_negate_c;
13844fd71d19SRichard Henderson     gen_helper_fmaddd(d, tcg_env, s1, s2, s3, tcg_constant_i32(op));
13854fd71d19SRichard Henderson }
13864fd71d19SRichard Henderson 
13874fd71d19SRichard Henderson static void gen_op_fnmsubs(TCGv_i32 d, TCGv_i32 s1, TCGv_i32 s2, TCGv_i32 s3)
13884fd71d19SRichard Henderson {
13894fd71d19SRichard Henderson     int op = float_muladd_negate_c | float_muladd_negate_result;
13904fd71d19SRichard Henderson     gen_helper_fmadds(d, tcg_env, s1, s2, s3, tcg_constant_i32(op));
13914fd71d19SRichard Henderson }
13924fd71d19SRichard Henderson 
13934fd71d19SRichard Henderson static void gen_op_fnmsubd(TCGv_i64 d, TCGv_i64 s1, TCGv_i64 s2, TCGv_i64 s3)
13944fd71d19SRichard Henderson {
13954fd71d19SRichard Henderson     int op = float_muladd_negate_c | float_muladd_negate_result;
13964fd71d19SRichard Henderson     gen_helper_fmaddd(d, tcg_env, s1, s2, s3, tcg_constant_i32(op));
13974fd71d19SRichard Henderson }
13984fd71d19SRichard Henderson 
13994fd71d19SRichard Henderson static void gen_op_fnmadds(TCGv_i32 d, TCGv_i32 s1, TCGv_i32 s2, TCGv_i32 s3)
14004fd71d19SRichard Henderson {
14014fd71d19SRichard Henderson     int op = float_muladd_negate_result;
14024fd71d19SRichard Henderson     gen_helper_fmadds(d, tcg_env, s1, s2, s3, tcg_constant_i32(op));
14034fd71d19SRichard Henderson }
14044fd71d19SRichard Henderson 
14054fd71d19SRichard Henderson static void gen_op_fnmaddd(TCGv_i64 d, TCGv_i64 s1, TCGv_i64 s2, TCGv_i64 s3)
14064fd71d19SRichard Henderson {
14074fd71d19SRichard Henderson     int op = float_muladd_negate_result;
14084fd71d19SRichard Henderson     gen_helper_fmaddd(d, tcg_env, s1, s2, s3, tcg_constant_i32(op));
14094fd71d19SRichard Henderson }
14104fd71d19SRichard Henderson 
14113d50b728SRichard Henderson /* Use muladd to compute (1 * src1) + src2 / 2 with one rounding. */
14123d50b728SRichard Henderson static void gen_op_fhadds(TCGv_i32 d, TCGv_i32 s1, TCGv_i32 s2)
14133d50b728SRichard Henderson {
14143d50b728SRichard Henderson     TCGv_i32 one = tcg_constant_i32(float32_one);
14153d50b728SRichard Henderson     int op = float_muladd_halve_result;
14163d50b728SRichard Henderson     gen_helper_fmadds(d, tcg_env, one, s1, s2, tcg_constant_i32(op));
14173d50b728SRichard Henderson }
14183d50b728SRichard Henderson 
14193d50b728SRichard Henderson static void gen_op_fhaddd(TCGv_i64 d, TCGv_i64 s1, TCGv_i64 s2)
14203d50b728SRichard Henderson {
14213d50b728SRichard Henderson     TCGv_i64 one = tcg_constant_i64(float64_one);
14223d50b728SRichard Henderson     int op = float_muladd_halve_result;
14233d50b728SRichard Henderson     gen_helper_fmaddd(d, tcg_env, one, s1, s2, tcg_constant_i32(op));
14243d50b728SRichard Henderson }
14253d50b728SRichard Henderson 
14263d50b728SRichard Henderson /* Use muladd to compute (1 * src1) - src2 / 2 with one rounding. */
14273d50b728SRichard Henderson static void gen_op_fhsubs(TCGv_i32 d, TCGv_i32 s1, TCGv_i32 s2)
14283d50b728SRichard Henderson {
14293d50b728SRichard Henderson     TCGv_i32 one = tcg_constant_i32(float32_one);
14303d50b728SRichard Henderson     int op = float_muladd_negate_c | float_muladd_halve_result;
14313d50b728SRichard Henderson     gen_helper_fmadds(d, tcg_env, one, s1, s2, tcg_constant_i32(op));
14323d50b728SRichard Henderson }
14333d50b728SRichard Henderson 
14343d50b728SRichard Henderson static void gen_op_fhsubd(TCGv_i64 d, TCGv_i64 s1, TCGv_i64 s2)
14353d50b728SRichard Henderson {
14363d50b728SRichard Henderson     TCGv_i64 one = tcg_constant_i64(float64_one);
14373d50b728SRichard Henderson     int op = float_muladd_negate_c | float_muladd_halve_result;
14383d50b728SRichard Henderson     gen_helper_fmaddd(d, tcg_env, one, s1, s2, tcg_constant_i32(op));
14393d50b728SRichard Henderson }
14403d50b728SRichard Henderson 
14413d50b728SRichard Henderson /* Use muladd to compute -((1 * src1) + src2 / 2) with one rounding. */
14423d50b728SRichard Henderson static void gen_op_fnhadds(TCGv_i32 d, TCGv_i32 s1, TCGv_i32 s2)
14433d50b728SRichard Henderson {
14443d50b728SRichard Henderson     TCGv_i32 one = tcg_constant_i32(float32_one);
14453d50b728SRichard Henderson     int op = float_muladd_negate_result | float_muladd_halve_result;
14463d50b728SRichard Henderson     gen_helper_fmadds(d, tcg_env, one, s1, s2, tcg_constant_i32(op));
14473d50b728SRichard Henderson }
14483d50b728SRichard Henderson 
14493d50b728SRichard Henderson static void gen_op_fnhaddd(TCGv_i64 d, TCGv_i64 s1, TCGv_i64 s2)
14503d50b728SRichard Henderson {
14513d50b728SRichard Henderson     TCGv_i64 one = tcg_constant_i64(float64_one);
14523d50b728SRichard Henderson     int op = float_muladd_negate_result | float_muladd_halve_result;
14533d50b728SRichard Henderson     gen_helper_fmaddd(d, tcg_env, one, s1, s2, tcg_constant_i32(op));
14543d50b728SRichard Henderson }
14553d50b728SRichard Henderson 
14563590f01eSRichard Henderson static void gen_op_fpexception_im(DisasContext *dc, int ftt)
1457fcf5ef2aSThomas Huth {
14583590f01eSRichard Henderson     /*
14593590f01eSRichard Henderson      * CEXC is only set when succesfully completing an FPop,
14603590f01eSRichard Henderson      * or when raising FSR_FTT_IEEE_EXCP, i.e. check_ieee_exception.
14613590f01eSRichard Henderson      * Thus we can simply store FTT into this field.
14623590f01eSRichard Henderson      */
14633590f01eSRichard Henderson     tcg_gen_st_i32(tcg_constant_i32(ftt), tcg_env,
14643590f01eSRichard Henderson                    offsetof(CPUSPARCState, fsr_cexc_ftt));
1465fcf5ef2aSThomas Huth     gen_exception(dc, TT_FP_EXCP);
1466fcf5ef2aSThomas Huth }
1467fcf5ef2aSThomas Huth 
1468fcf5ef2aSThomas Huth static int gen_trap_ifnofpu(DisasContext *dc)
1469fcf5ef2aSThomas Huth {
1470fcf5ef2aSThomas Huth #if !defined(CONFIG_USER_ONLY)
1471fcf5ef2aSThomas Huth     if (!dc->fpu_enabled) {
1472fcf5ef2aSThomas Huth         gen_exception(dc, TT_NFPU_INSN);
1473fcf5ef2aSThomas Huth         return 1;
1474fcf5ef2aSThomas Huth     }
1475fcf5ef2aSThomas Huth #endif
1476fcf5ef2aSThomas Huth     return 0;
1477fcf5ef2aSThomas Huth }
1478fcf5ef2aSThomas Huth 
1479fcf5ef2aSThomas Huth /* asi moves */
1480fcf5ef2aSThomas Huth typedef enum {
1481fcf5ef2aSThomas Huth     GET_ASI_HELPER,
1482fcf5ef2aSThomas Huth     GET_ASI_EXCP,
1483fcf5ef2aSThomas Huth     GET_ASI_DIRECT,
1484fcf5ef2aSThomas Huth     GET_ASI_DTWINX,
14852786a3f8SRichard Henderson     GET_ASI_CODE,
1486fcf5ef2aSThomas Huth     GET_ASI_BLOCK,
1487fcf5ef2aSThomas Huth     GET_ASI_SHORT,
1488fcf5ef2aSThomas Huth     GET_ASI_BCOPY,
1489fcf5ef2aSThomas Huth     GET_ASI_BFILL,
1490fcf5ef2aSThomas Huth } ASIType;
1491fcf5ef2aSThomas Huth 
1492fcf5ef2aSThomas Huth typedef struct {
1493fcf5ef2aSThomas Huth     ASIType type;
1494fcf5ef2aSThomas Huth     int asi;
1495fcf5ef2aSThomas Huth     int mem_idx;
149614776ab5STony Nguyen     MemOp memop;
1497fcf5ef2aSThomas Huth } DisasASI;
1498fcf5ef2aSThomas Huth 
1499811cc0b0SRichard Henderson /*
1500811cc0b0SRichard Henderson  * Build DisasASI.
1501811cc0b0SRichard Henderson  * For asi == -1, treat as non-asi.
1502811cc0b0SRichard Henderson  * For ask == -2, treat as immediate offset (v8 error, v9 %asi).
1503811cc0b0SRichard Henderson  */
1504811cc0b0SRichard Henderson static DisasASI resolve_asi(DisasContext *dc, int asi, MemOp memop)
1505fcf5ef2aSThomas Huth {
1506fcf5ef2aSThomas Huth     ASIType type = GET_ASI_HELPER;
1507fcf5ef2aSThomas Huth     int mem_idx = dc->mem_idx;
1508fcf5ef2aSThomas Huth 
1509811cc0b0SRichard Henderson     if (asi == -1) {
1510811cc0b0SRichard Henderson         /* Artificial "non-asi" case. */
1511811cc0b0SRichard Henderson         type = GET_ASI_DIRECT;
1512811cc0b0SRichard Henderson         goto done;
1513811cc0b0SRichard Henderson     }
1514811cc0b0SRichard Henderson 
1515fcf5ef2aSThomas Huth #ifndef TARGET_SPARC64
1516fcf5ef2aSThomas Huth     /* Before v9, all asis are immediate and privileged.  */
1517811cc0b0SRichard Henderson     if (asi < 0) {
1518fcf5ef2aSThomas Huth         gen_exception(dc, TT_ILL_INSN);
1519fcf5ef2aSThomas Huth         type = GET_ASI_EXCP;
1520fcf5ef2aSThomas Huth     } else if (supervisor(dc)
1521fcf5ef2aSThomas Huth                /* Note that LEON accepts ASI_USERDATA in user mode, for
1522fcf5ef2aSThomas Huth                   use with CASA.  Also note that previous versions of
1523fcf5ef2aSThomas Huth                   QEMU allowed (and old versions of gcc emitted) ASI_P
1524fcf5ef2aSThomas Huth                   for LEON, which is incorrect.  */
1525fcf5ef2aSThomas Huth                || (asi == ASI_USERDATA
1526fcf5ef2aSThomas Huth                    && (dc->def->features & CPU_FEATURE_CASA))) {
1527fcf5ef2aSThomas Huth         switch (asi) {
1528fcf5ef2aSThomas Huth         case ASI_USERDATA:    /* User data access */
1529fcf5ef2aSThomas Huth             mem_idx = MMU_USER_IDX;
1530fcf5ef2aSThomas Huth             type = GET_ASI_DIRECT;
1531fcf5ef2aSThomas Huth             break;
1532fcf5ef2aSThomas Huth         case ASI_KERNELDATA:  /* Supervisor data access */
1533fcf5ef2aSThomas Huth             mem_idx = MMU_KERNEL_IDX;
1534fcf5ef2aSThomas Huth             type = GET_ASI_DIRECT;
1535fcf5ef2aSThomas Huth             break;
15362786a3f8SRichard Henderson         case ASI_USERTXT:     /* User text access */
15372786a3f8SRichard Henderson             mem_idx = MMU_USER_IDX;
15382786a3f8SRichard Henderson             type = GET_ASI_CODE;
15392786a3f8SRichard Henderson             break;
15402786a3f8SRichard Henderson         case ASI_KERNELTXT:   /* Supervisor text access */
15412786a3f8SRichard Henderson             mem_idx = MMU_KERNEL_IDX;
15422786a3f8SRichard Henderson             type = GET_ASI_CODE;
15432786a3f8SRichard Henderson             break;
1544fcf5ef2aSThomas Huth         case ASI_M_BYPASS:    /* MMU passthrough */
1545fcf5ef2aSThomas Huth         case ASI_LEON_BYPASS: /* LEON MMU passthrough */
1546fcf5ef2aSThomas Huth             mem_idx = MMU_PHYS_IDX;
1547fcf5ef2aSThomas Huth             type = GET_ASI_DIRECT;
1548fcf5ef2aSThomas Huth             break;
1549fcf5ef2aSThomas Huth         case ASI_M_BCOPY: /* Block copy, sta access */
1550fcf5ef2aSThomas Huth             mem_idx = MMU_KERNEL_IDX;
1551fcf5ef2aSThomas Huth             type = GET_ASI_BCOPY;
1552fcf5ef2aSThomas Huth             break;
1553fcf5ef2aSThomas Huth         case ASI_M_BFILL: /* Block fill, stda access */
1554fcf5ef2aSThomas Huth             mem_idx = MMU_KERNEL_IDX;
1555fcf5ef2aSThomas Huth             type = GET_ASI_BFILL;
1556fcf5ef2aSThomas Huth             break;
1557fcf5ef2aSThomas Huth         }
15586e10f37cSKONRAD Frederic 
15596e10f37cSKONRAD Frederic         /* MMU_PHYS_IDX is used when the MMU is disabled to passthrough the
15606e10f37cSKONRAD Frederic          * permissions check in get_physical_address(..).
15616e10f37cSKONRAD Frederic          */
15626e10f37cSKONRAD Frederic         mem_idx = (dc->mem_idx == MMU_PHYS_IDX) ? MMU_PHYS_IDX : mem_idx;
1563fcf5ef2aSThomas Huth     } else {
1564fcf5ef2aSThomas Huth         gen_exception(dc, TT_PRIV_INSN);
1565fcf5ef2aSThomas Huth         type = GET_ASI_EXCP;
1566fcf5ef2aSThomas Huth     }
1567fcf5ef2aSThomas Huth #else
1568811cc0b0SRichard Henderson     if (asi < 0) {
1569fcf5ef2aSThomas Huth         asi = dc->asi;
1570fcf5ef2aSThomas Huth     }
1571fcf5ef2aSThomas Huth     /* With v9, all asis below 0x80 are privileged.  */
1572fcf5ef2aSThomas Huth     /* ??? We ought to check cpu_has_hypervisor, but we didn't copy
1573fcf5ef2aSThomas Huth        down that bit into DisasContext.  For the moment that's ok,
1574fcf5ef2aSThomas Huth        since the direct implementations below doesn't have any ASIs
1575fcf5ef2aSThomas Huth        in the restricted [0x30, 0x7f] range, and the check will be
1576fcf5ef2aSThomas Huth        done properly in the helper.  */
1577fcf5ef2aSThomas Huth     if (!supervisor(dc) && asi < 0x80) {
1578fcf5ef2aSThomas Huth         gen_exception(dc, TT_PRIV_ACT);
1579fcf5ef2aSThomas Huth         type = GET_ASI_EXCP;
1580fcf5ef2aSThomas Huth     } else {
1581fcf5ef2aSThomas Huth         switch (asi) {
1582fcf5ef2aSThomas Huth         case ASI_REAL:      /* Bypass */
1583fcf5ef2aSThomas Huth         case ASI_REAL_IO:   /* Bypass, non-cacheable */
1584fcf5ef2aSThomas Huth         case ASI_REAL_L:    /* Bypass LE */
1585fcf5ef2aSThomas Huth         case ASI_REAL_IO_L: /* Bypass, non-cacheable LE */
1586fcf5ef2aSThomas Huth         case ASI_TWINX_REAL:   /* Real address, twinx */
1587fcf5ef2aSThomas Huth         case ASI_TWINX_REAL_L: /* Real address, twinx, LE */
1588fcf5ef2aSThomas Huth         case ASI_QUAD_LDD_PHYS:
1589fcf5ef2aSThomas Huth         case ASI_QUAD_LDD_PHYS_L:
1590fcf5ef2aSThomas Huth             mem_idx = MMU_PHYS_IDX;
1591fcf5ef2aSThomas Huth             break;
1592fcf5ef2aSThomas Huth         case ASI_N:  /* Nucleus */
1593fcf5ef2aSThomas Huth         case ASI_NL: /* Nucleus LE */
1594fcf5ef2aSThomas Huth         case ASI_TWINX_N:
1595fcf5ef2aSThomas Huth         case ASI_TWINX_NL:
1596fcf5ef2aSThomas Huth         case ASI_NUCLEUS_QUAD_LDD:
1597fcf5ef2aSThomas Huth         case ASI_NUCLEUS_QUAD_LDD_L:
15989a10756dSArtyom Tarasenko             if (hypervisor(dc)) {
159984f8f587SArtyom Tarasenko                 mem_idx = MMU_PHYS_IDX;
16009a10756dSArtyom Tarasenko             } else {
1601fcf5ef2aSThomas Huth                 mem_idx = MMU_NUCLEUS_IDX;
16029a10756dSArtyom Tarasenko             }
1603fcf5ef2aSThomas Huth             break;
1604fcf5ef2aSThomas Huth         case ASI_AIUP:  /* As if user primary */
1605fcf5ef2aSThomas Huth         case ASI_AIUPL: /* As if user primary LE */
1606fcf5ef2aSThomas Huth         case ASI_TWINX_AIUP:
1607fcf5ef2aSThomas Huth         case ASI_TWINX_AIUP_L:
1608fcf5ef2aSThomas Huth         case ASI_BLK_AIUP_4V:
1609fcf5ef2aSThomas Huth         case ASI_BLK_AIUP_L_4V:
1610fcf5ef2aSThomas Huth         case ASI_BLK_AIUP:
1611fcf5ef2aSThomas Huth         case ASI_BLK_AIUPL:
1612eeb3f592SRichard Henderson         case ASI_MON_AIUP:
1613fcf5ef2aSThomas Huth             mem_idx = MMU_USER_IDX;
1614fcf5ef2aSThomas Huth             break;
1615fcf5ef2aSThomas Huth         case ASI_AIUS:  /* As if user secondary */
1616fcf5ef2aSThomas Huth         case ASI_AIUSL: /* As if user secondary LE */
1617fcf5ef2aSThomas Huth         case ASI_TWINX_AIUS:
1618fcf5ef2aSThomas Huth         case ASI_TWINX_AIUS_L:
1619fcf5ef2aSThomas Huth         case ASI_BLK_AIUS_4V:
1620fcf5ef2aSThomas Huth         case ASI_BLK_AIUS_L_4V:
1621fcf5ef2aSThomas Huth         case ASI_BLK_AIUS:
1622fcf5ef2aSThomas Huth         case ASI_BLK_AIUSL:
1623eeb3f592SRichard Henderson         case ASI_MON_AIUS:
1624fcf5ef2aSThomas Huth             mem_idx = MMU_USER_SECONDARY_IDX;
1625fcf5ef2aSThomas Huth             break;
1626fcf5ef2aSThomas Huth         case ASI_S:  /* Secondary */
1627fcf5ef2aSThomas Huth         case ASI_SL: /* Secondary LE */
1628fcf5ef2aSThomas Huth         case ASI_TWINX_S:
1629fcf5ef2aSThomas Huth         case ASI_TWINX_SL:
1630fcf5ef2aSThomas Huth         case ASI_BLK_COMMIT_S:
1631fcf5ef2aSThomas Huth         case ASI_BLK_S:
1632fcf5ef2aSThomas Huth         case ASI_BLK_SL:
1633fcf5ef2aSThomas Huth         case ASI_FL8_S:
1634fcf5ef2aSThomas Huth         case ASI_FL8_SL:
1635fcf5ef2aSThomas Huth         case ASI_FL16_S:
1636fcf5ef2aSThomas Huth         case ASI_FL16_SL:
1637eeb3f592SRichard Henderson         case ASI_MON_S:
1638fcf5ef2aSThomas Huth             if (mem_idx == MMU_USER_IDX) {
1639fcf5ef2aSThomas Huth                 mem_idx = MMU_USER_SECONDARY_IDX;
1640fcf5ef2aSThomas Huth             } else if (mem_idx == MMU_KERNEL_IDX) {
1641fcf5ef2aSThomas Huth                 mem_idx = MMU_KERNEL_SECONDARY_IDX;
1642fcf5ef2aSThomas Huth             }
1643fcf5ef2aSThomas Huth             break;
1644fcf5ef2aSThomas Huth         case ASI_P:  /* Primary */
1645fcf5ef2aSThomas Huth         case ASI_PL: /* Primary LE */
1646fcf5ef2aSThomas Huth         case ASI_TWINX_P:
1647fcf5ef2aSThomas Huth         case ASI_TWINX_PL:
1648fcf5ef2aSThomas Huth         case ASI_BLK_COMMIT_P:
1649fcf5ef2aSThomas Huth         case ASI_BLK_P:
1650fcf5ef2aSThomas Huth         case ASI_BLK_PL:
1651fcf5ef2aSThomas Huth         case ASI_FL8_P:
1652fcf5ef2aSThomas Huth         case ASI_FL8_PL:
1653fcf5ef2aSThomas Huth         case ASI_FL16_P:
1654fcf5ef2aSThomas Huth         case ASI_FL16_PL:
1655eeb3f592SRichard Henderson         case ASI_MON_P:
1656fcf5ef2aSThomas Huth             break;
1657fcf5ef2aSThomas Huth         }
1658fcf5ef2aSThomas Huth         switch (asi) {
1659fcf5ef2aSThomas Huth         case ASI_REAL:
1660fcf5ef2aSThomas Huth         case ASI_REAL_IO:
1661fcf5ef2aSThomas Huth         case ASI_REAL_L:
1662fcf5ef2aSThomas Huth         case ASI_REAL_IO_L:
1663fcf5ef2aSThomas Huth         case ASI_N:
1664fcf5ef2aSThomas Huth         case ASI_NL:
1665fcf5ef2aSThomas Huth         case ASI_AIUP:
1666fcf5ef2aSThomas Huth         case ASI_AIUPL:
1667fcf5ef2aSThomas Huth         case ASI_AIUS:
1668fcf5ef2aSThomas Huth         case ASI_AIUSL:
1669fcf5ef2aSThomas Huth         case ASI_S:
1670fcf5ef2aSThomas Huth         case ASI_SL:
1671fcf5ef2aSThomas Huth         case ASI_P:
1672fcf5ef2aSThomas Huth         case ASI_PL:
1673eeb3f592SRichard Henderson         case ASI_MON_P:
1674eeb3f592SRichard Henderson         case ASI_MON_S:
1675eeb3f592SRichard Henderson         case ASI_MON_AIUP:
1676eeb3f592SRichard Henderson         case ASI_MON_AIUS:
1677fcf5ef2aSThomas Huth             type = GET_ASI_DIRECT;
1678fcf5ef2aSThomas Huth             break;
1679fcf5ef2aSThomas Huth         case ASI_TWINX_REAL:
1680fcf5ef2aSThomas Huth         case ASI_TWINX_REAL_L:
1681fcf5ef2aSThomas Huth         case ASI_TWINX_N:
1682fcf5ef2aSThomas Huth         case ASI_TWINX_NL:
1683fcf5ef2aSThomas Huth         case ASI_TWINX_AIUP:
1684fcf5ef2aSThomas Huth         case ASI_TWINX_AIUP_L:
1685fcf5ef2aSThomas Huth         case ASI_TWINX_AIUS:
1686fcf5ef2aSThomas Huth         case ASI_TWINX_AIUS_L:
1687fcf5ef2aSThomas Huth         case ASI_TWINX_P:
1688fcf5ef2aSThomas Huth         case ASI_TWINX_PL:
1689fcf5ef2aSThomas Huth         case ASI_TWINX_S:
1690fcf5ef2aSThomas Huth         case ASI_TWINX_SL:
1691fcf5ef2aSThomas Huth         case ASI_QUAD_LDD_PHYS:
1692fcf5ef2aSThomas Huth         case ASI_QUAD_LDD_PHYS_L:
1693fcf5ef2aSThomas Huth         case ASI_NUCLEUS_QUAD_LDD:
1694fcf5ef2aSThomas Huth         case ASI_NUCLEUS_QUAD_LDD_L:
1695fcf5ef2aSThomas Huth             type = GET_ASI_DTWINX;
1696fcf5ef2aSThomas Huth             break;
1697fcf5ef2aSThomas Huth         case ASI_BLK_COMMIT_P:
1698fcf5ef2aSThomas Huth         case ASI_BLK_COMMIT_S:
1699fcf5ef2aSThomas Huth         case ASI_BLK_AIUP_4V:
1700fcf5ef2aSThomas Huth         case ASI_BLK_AIUP_L_4V:
1701fcf5ef2aSThomas Huth         case ASI_BLK_AIUP:
1702fcf5ef2aSThomas Huth         case ASI_BLK_AIUPL:
1703fcf5ef2aSThomas Huth         case ASI_BLK_AIUS_4V:
1704fcf5ef2aSThomas Huth         case ASI_BLK_AIUS_L_4V:
1705fcf5ef2aSThomas Huth         case ASI_BLK_AIUS:
1706fcf5ef2aSThomas Huth         case ASI_BLK_AIUSL:
1707fcf5ef2aSThomas Huth         case ASI_BLK_S:
1708fcf5ef2aSThomas Huth         case ASI_BLK_SL:
1709fcf5ef2aSThomas Huth         case ASI_BLK_P:
1710fcf5ef2aSThomas Huth         case ASI_BLK_PL:
1711fcf5ef2aSThomas Huth             type = GET_ASI_BLOCK;
1712fcf5ef2aSThomas Huth             break;
1713fcf5ef2aSThomas Huth         case ASI_FL8_S:
1714fcf5ef2aSThomas Huth         case ASI_FL8_SL:
1715fcf5ef2aSThomas Huth         case ASI_FL8_P:
1716fcf5ef2aSThomas Huth         case ASI_FL8_PL:
1717fcf5ef2aSThomas Huth             memop = MO_UB;
1718fcf5ef2aSThomas Huth             type = GET_ASI_SHORT;
1719fcf5ef2aSThomas Huth             break;
1720fcf5ef2aSThomas Huth         case ASI_FL16_S:
1721fcf5ef2aSThomas Huth         case ASI_FL16_SL:
1722fcf5ef2aSThomas Huth         case ASI_FL16_P:
1723fcf5ef2aSThomas Huth         case ASI_FL16_PL:
1724fcf5ef2aSThomas Huth             memop = MO_TEUW;
1725fcf5ef2aSThomas Huth             type = GET_ASI_SHORT;
1726fcf5ef2aSThomas Huth             break;
1727fcf5ef2aSThomas Huth         }
1728fcf5ef2aSThomas Huth         /* The little-endian asis all have bit 3 set.  */
1729fcf5ef2aSThomas Huth         if (asi & 8) {
1730fcf5ef2aSThomas Huth             memop ^= MO_BSWAP;
1731fcf5ef2aSThomas Huth         }
1732fcf5ef2aSThomas Huth     }
1733fcf5ef2aSThomas Huth #endif
1734fcf5ef2aSThomas Huth 
1735811cc0b0SRichard Henderson  done:
1736fcf5ef2aSThomas Huth     return (DisasASI){ type, asi, mem_idx, memop };
1737fcf5ef2aSThomas Huth }
1738fcf5ef2aSThomas Huth 
1739a76779eeSRichard Henderson #if defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
1740a76779eeSRichard Henderson static void gen_helper_ld_asi(TCGv_i64 r, TCGv_env e, TCGv a,
1741a76779eeSRichard Henderson                               TCGv_i32 asi, TCGv_i32 mop)
1742a76779eeSRichard Henderson {
1743a76779eeSRichard Henderson     g_assert_not_reached();
1744a76779eeSRichard Henderson }
1745a76779eeSRichard Henderson 
1746a76779eeSRichard Henderson static void gen_helper_st_asi(TCGv_env e, TCGv a, TCGv_i64 r,
1747a76779eeSRichard Henderson                               TCGv_i32 asi, TCGv_i32 mop)
1748a76779eeSRichard Henderson {
1749a76779eeSRichard Henderson     g_assert_not_reached();
1750a76779eeSRichard Henderson }
1751a76779eeSRichard Henderson #endif
1752a76779eeSRichard Henderson 
175342071fc1SRichard Henderson static void gen_ld_asi(DisasContext *dc, DisasASI *da, TCGv dst, TCGv addr)
1754fcf5ef2aSThomas Huth {
1755c03a0fd1SRichard Henderson     switch (da->type) {
1756fcf5ef2aSThomas Huth     case GET_ASI_EXCP:
1757fcf5ef2aSThomas Huth         break;
1758fcf5ef2aSThomas Huth     case GET_ASI_DTWINX: /* Reserved for ldda.  */
1759fcf5ef2aSThomas Huth         gen_exception(dc, TT_ILL_INSN);
1760fcf5ef2aSThomas Huth         break;
1761fcf5ef2aSThomas Huth     case GET_ASI_DIRECT:
1762c03a0fd1SRichard Henderson         tcg_gen_qemu_ld_tl(dst, addr, da->mem_idx, da->memop | MO_ALIGN);
1763fcf5ef2aSThomas Huth         break;
17642786a3f8SRichard Henderson 
17652786a3f8SRichard Henderson     case GET_ASI_CODE:
17662786a3f8SRichard Henderson #if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
17672786a3f8SRichard Henderson         {
17682786a3f8SRichard Henderson             MemOpIdx oi = make_memop_idx(da->memop, da->mem_idx);
17692786a3f8SRichard Henderson             TCGv_i64 t64 = tcg_temp_new_i64();
17702786a3f8SRichard Henderson 
17712786a3f8SRichard Henderson             gen_helper_ld_code(t64, tcg_env, addr, tcg_constant_i32(oi));
17722786a3f8SRichard Henderson             tcg_gen_trunc_i64_tl(dst, t64);
17732786a3f8SRichard Henderson         }
17742786a3f8SRichard Henderson         break;
17752786a3f8SRichard Henderson #else
17762786a3f8SRichard Henderson         g_assert_not_reached();
17772786a3f8SRichard Henderson #endif
17782786a3f8SRichard Henderson 
1779fcf5ef2aSThomas Huth     default:
1780fcf5ef2aSThomas Huth         {
1781c03a0fd1SRichard Henderson             TCGv_i32 r_asi = tcg_constant_i32(da->asi);
1782c03a0fd1SRichard Henderson             TCGv_i32 r_mop = tcg_constant_i32(da->memop | MO_ALIGN);
1783fcf5ef2aSThomas Huth 
1784fcf5ef2aSThomas Huth             save_state(dc);
1785fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
1786ad75a51eSRichard Henderson             gen_helper_ld_asi(dst, tcg_env, addr, r_asi, r_mop);
1787fcf5ef2aSThomas Huth #else
1788fcf5ef2aSThomas Huth             {
1789fcf5ef2aSThomas Huth                 TCGv_i64 t64 = tcg_temp_new_i64();
1790ad75a51eSRichard Henderson                 gen_helper_ld_asi(t64, tcg_env, addr, r_asi, r_mop);
1791fcf5ef2aSThomas Huth                 tcg_gen_trunc_i64_tl(dst, t64);
1792fcf5ef2aSThomas Huth             }
1793fcf5ef2aSThomas Huth #endif
1794fcf5ef2aSThomas Huth         }
1795fcf5ef2aSThomas Huth         break;
1796fcf5ef2aSThomas Huth     }
1797fcf5ef2aSThomas Huth }
1798fcf5ef2aSThomas Huth 
179942071fc1SRichard Henderson static void gen_st_asi(DisasContext *dc, DisasASI *da, TCGv src, TCGv addr)
1800c03a0fd1SRichard Henderson {
1801c03a0fd1SRichard Henderson     switch (da->type) {
1802fcf5ef2aSThomas Huth     case GET_ASI_EXCP:
1803fcf5ef2aSThomas Huth         break;
1804c03a0fd1SRichard Henderson 
1805fcf5ef2aSThomas Huth     case GET_ASI_DTWINX: /* Reserved for stda.  */
1806c03a0fd1SRichard Henderson         if (TARGET_LONG_BITS == 32) {
1807fcf5ef2aSThomas Huth             gen_exception(dc, TT_ILL_INSN);
1808fcf5ef2aSThomas Huth             break;
1809c03a0fd1SRichard Henderson         } else if (!(dc->def->features & CPU_FEATURE_HYPV)) {
18103390537bSArtyom Tarasenko             /* Pre OpenSPARC CPUs don't have these */
18113390537bSArtyom Tarasenko             gen_exception(dc, TT_ILL_INSN);
1812fcf5ef2aSThomas Huth             break;
1813c03a0fd1SRichard Henderson         }
1814c03a0fd1SRichard Henderson         /* In OpenSPARC T1+ CPUs TWINX ASIs in store are ST_BLKINIT_ ASIs */
1815c03a0fd1SRichard Henderson         /* fall through */
1816c03a0fd1SRichard Henderson 
1817c03a0fd1SRichard Henderson     case GET_ASI_DIRECT:
1818c03a0fd1SRichard Henderson         tcg_gen_qemu_st_tl(src, addr, da->mem_idx, da->memop | MO_ALIGN);
1819c03a0fd1SRichard Henderson         break;
1820c03a0fd1SRichard Henderson 
1821fcf5ef2aSThomas Huth     case GET_ASI_BCOPY:
1822c03a0fd1SRichard Henderson         assert(TARGET_LONG_BITS == 32);
182398271007SRichard Henderson         /*
182498271007SRichard Henderson          * Copy 32 bytes from the address in SRC to ADDR.
182598271007SRichard Henderson          *
182698271007SRichard Henderson          * From Ross RT625 hyperSPARC manual, section 4.6:
182798271007SRichard Henderson          * "Block Copy and Block Fill will work only on cache line boundaries."
182898271007SRichard Henderson          *
182998271007SRichard Henderson          * It does not specify if an unaliged address is truncated or trapped.
183098271007SRichard Henderson          * Previous qemu behaviour was to truncate to 4 byte alignment, which
183198271007SRichard Henderson          * is obviously wrong.  The only place I can see this used is in the
183298271007SRichard Henderson          * Linux kernel which begins with page alignment, advancing by 32,
183398271007SRichard Henderson          * so is always aligned.  Assume truncation as the simpler option.
183498271007SRichard Henderson          *
183598271007SRichard Henderson          * Since the loads and stores are paired, allow the copy to happen
183698271007SRichard Henderson          * in the host endianness.  The copy need not be atomic.
183798271007SRichard Henderson          */
1838fcf5ef2aSThomas Huth         {
183998271007SRichard Henderson             MemOp mop = MO_128 | MO_ATOM_IFALIGN_PAIR;
1840fcf5ef2aSThomas Huth             TCGv saddr = tcg_temp_new();
1841fcf5ef2aSThomas Huth             TCGv daddr = tcg_temp_new();
184298271007SRichard Henderson             TCGv_i128 tmp = tcg_temp_new_i128();
1843fcf5ef2aSThomas Huth 
184498271007SRichard Henderson             tcg_gen_andi_tl(saddr, src, -32);
184598271007SRichard Henderson             tcg_gen_andi_tl(daddr, addr, -32);
184698271007SRichard Henderson             tcg_gen_qemu_ld_i128(tmp, saddr, da->mem_idx, mop);
184798271007SRichard Henderson             tcg_gen_qemu_st_i128(tmp, daddr, da->mem_idx, mop);
184898271007SRichard Henderson             tcg_gen_addi_tl(saddr, saddr, 16);
184998271007SRichard Henderson             tcg_gen_addi_tl(daddr, daddr, 16);
185098271007SRichard Henderson             tcg_gen_qemu_ld_i128(tmp, saddr, da->mem_idx, mop);
185198271007SRichard Henderson             tcg_gen_qemu_st_i128(tmp, daddr, da->mem_idx, mop);
1852fcf5ef2aSThomas Huth         }
1853fcf5ef2aSThomas Huth         break;
1854c03a0fd1SRichard Henderson 
1855fcf5ef2aSThomas Huth     default:
1856fcf5ef2aSThomas Huth         {
1857c03a0fd1SRichard Henderson             TCGv_i32 r_asi = tcg_constant_i32(da->asi);
1858c03a0fd1SRichard Henderson             TCGv_i32 r_mop = tcg_constant_i32(da->memop | MO_ALIGN);
1859fcf5ef2aSThomas Huth 
1860fcf5ef2aSThomas Huth             save_state(dc);
1861fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
1862ad75a51eSRichard Henderson             gen_helper_st_asi(tcg_env, addr, src, r_asi, r_mop);
1863fcf5ef2aSThomas Huth #else
1864fcf5ef2aSThomas Huth             {
1865fcf5ef2aSThomas Huth                 TCGv_i64 t64 = tcg_temp_new_i64();
1866fcf5ef2aSThomas Huth                 tcg_gen_extu_tl_i64(t64, src);
1867ad75a51eSRichard Henderson                 gen_helper_st_asi(tcg_env, addr, t64, r_asi, r_mop);
1868fcf5ef2aSThomas Huth             }
1869fcf5ef2aSThomas Huth #endif
1870fcf5ef2aSThomas Huth 
1871fcf5ef2aSThomas Huth             /* A write to a TLB register may alter page maps.  End the TB. */
1872fcf5ef2aSThomas Huth             dc->npc = DYNAMIC_PC;
1873fcf5ef2aSThomas Huth         }
1874fcf5ef2aSThomas Huth         break;
1875fcf5ef2aSThomas Huth     }
1876fcf5ef2aSThomas Huth }
1877fcf5ef2aSThomas Huth 
1878dca544b9SRichard Henderson static void gen_swap_asi(DisasContext *dc, DisasASI *da,
1879c03a0fd1SRichard Henderson                          TCGv dst, TCGv src, TCGv addr)
1880c03a0fd1SRichard Henderson {
1881c03a0fd1SRichard Henderson     switch (da->type) {
1882c03a0fd1SRichard Henderson     case GET_ASI_EXCP:
1883c03a0fd1SRichard Henderson         break;
1884c03a0fd1SRichard Henderson     case GET_ASI_DIRECT:
1885dca544b9SRichard Henderson         tcg_gen_atomic_xchg_tl(dst, addr, src,
1886dca544b9SRichard Henderson                                da->mem_idx, da->memop | MO_ALIGN);
1887c03a0fd1SRichard Henderson         break;
1888c03a0fd1SRichard Henderson     default:
1889c03a0fd1SRichard Henderson         /* ??? Should be DAE_invalid_asi.  */
1890c03a0fd1SRichard Henderson         gen_exception(dc, TT_DATA_ACCESS);
1891c03a0fd1SRichard Henderson         break;
1892c03a0fd1SRichard Henderson     }
1893c03a0fd1SRichard Henderson }
1894c03a0fd1SRichard Henderson 
1895d0a11d25SRichard Henderson static void gen_cas_asi(DisasContext *dc, DisasASI *da,
1896c03a0fd1SRichard Henderson                         TCGv oldv, TCGv newv, TCGv cmpv, TCGv addr)
1897c03a0fd1SRichard Henderson {
1898c03a0fd1SRichard Henderson     switch (da->type) {
1899fcf5ef2aSThomas Huth     case GET_ASI_EXCP:
1900c03a0fd1SRichard Henderson         return;
1901fcf5ef2aSThomas Huth     case GET_ASI_DIRECT:
1902c03a0fd1SRichard Henderson         tcg_gen_atomic_cmpxchg_tl(oldv, addr, cmpv, newv,
1903c03a0fd1SRichard Henderson                                   da->mem_idx, da->memop | MO_ALIGN);
1904fcf5ef2aSThomas Huth         break;
1905fcf5ef2aSThomas Huth     default:
1906fcf5ef2aSThomas Huth         /* ??? Should be DAE_invalid_asi.  */
1907fcf5ef2aSThomas Huth         gen_exception(dc, TT_DATA_ACCESS);
1908fcf5ef2aSThomas Huth         break;
1909fcf5ef2aSThomas Huth     }
1910fcf5ef2aSThomas Huth }
1911fcf5ef2aSThomas Huth 
1912cf07cd1eSRichard Henderson static void gen_ldstub_asi(DisasContext *dc, DisasASI *da, TCGv dst, TCGv addr)
1913c03a0fd1SRichard Henderson {
1914c03a0fd1SRichard Henderson     switch (da->type) {
1915fcf5ef2aSThomas Huth     case GET_ASI_EXCP:
1916fcf5ef2aSThomas Huth         break;
1917fcf5ef2aSThomas Huth     case GET_ASI_DIRECT:
1918cf07cd1eSRichard Henderson         tcg_gen_atomic_xchg_tl(dst, addr, tcg_constant_tl(0xff),
1919cf07cd1eSRichard Henderson                                da->mem_idx, MO_UB);
1920fcf5ef2aSThomas Huth         break;
1921fcf5ef2aSThomas Huth     default:
19223db010c3SRichard Henderson         /* ??? In theory, this should be raise DAE_invalid_asi.
19233db010c3SRichard Henderson            But the SS-20 roms do ldstuba [%l0] #ASI_M_CTL, %o1.  */
1924af00be49SEmilio G. Cota         if (tb_cflags(dc->base.tb) & CF_PARALLEL) {
1925ad75a51eSRichard Henderson             gen_helper_exit_atomic(tcg_env);
19263db010c3SRichard Henderson         } else {
1927c03a0fd1SRichard Henderson             TCGv_i32 r_asi = tcg_constant_i32(da->asi);
192800ab7e61SRichard Henderson             TCGv_i32 r_mop = tcg_constant_i32(MO_UB);
19293db010c3SRichard Henderson             TCGv_i64 s64, t64;
19303db010c3SRichard Henderson 
19313db010c3SRichard Henderson             save_state(dc);
19323db010c3SRichard Henderson             t64 = tcg_temp_new_i64();
1933ad75a51eSRichard Henderson             gen_helper_ld_asi(t64, tcg_env, addr, r_asi, r_mop);
19343db010c3SRichard Henderson 
193500ab7e61SRichard Henderson             s64 = tcg_constant_i64(0xff);
1936ad75a51eSRichard Henderson             gen_helper_st_asi(tcg_env, addr, s64, r_asi, r_mop);
19373db010c3SRichard Henderson 
19383db010c3SRichard Henderson             tcg_gen_trunc_i64_tl(dst, t64);
19393db010c3SRichard Henderson 
19403db010c3SRichard Henderson             /* End the TB.  */
19413db010c3SRichard Henderson             dc->npc = DYNAMIC_PC;
19423db010c3SRichard Henderson         }
1943fcf5ef2aSThomas Huth         break;
1944fcf5ef2aSThomas Huth     }
1945fcf5ef2aSThomas Huth }
1946fcf5ef2aSThomas Huth 
1947287b1152SRichard Henderson static void gen_ldf_asi(DisasContext *dc, DisasASI *da, MemOp orig_size,
19483259b9e2SRichard Henderson                         TCGv addr, int rd)
1949fcf5ef2aSThomas Huth {
19503259b9e2SRichard Henderson     MemOp memop = da->memop;
19513259b9e2SRichard Henderson     MemOp size = memop & MO_SIZE;
1952fcf5ef2aSThomas Huth     TCGv_i32 d32;
19531210a036SRichard Henderson     TCGv_i64 d64, l64;
1954287b1152SRichard Henderson     TCGv addr_tmp;
1955fcf5ef2aSThomas Huth 
19563259b9e2SRichard Henderson     /* TODO: Use 128-bit load/store below. */
19573259b9e2SRichard Henderson     if (size == MO_128) {
19583259b9e2SRichard Henderson         memop = (memop & ~MO_SIZE) | MO_64;
19593259b9e2SRichard Henderson     }
19603259b9e2SRichard Henderson 
19613259b9e2SRichard Henderson     switch (da->type) {
1962fcf5ef2aSThomas Huth     case GET_ASI_EXCP:
1963fcf5ef2aSThomas Huth         break;
1964fcf5ef2aSThomas Huth 
1965fcf5ef2aSThomas Huth     case GET_ASI_DIRECT:
19663259b9e2SRichard Henderson         memop |= MO_ALIGN_4;
1967fcf5ef2aSThomas Huth         switch (size) {
19683259b9e2SRichard Henderson         case MO_32:
1969388a6465SRichard Henderson             d32 = tcg_temp_new_i32();
19703259b9e2SRichard Henderson             tcg_gen_qemu_ld_i32(d32, addr, da->mem_idx, memop);
1971fcf5ef2aSThomas Huth             gen_store_fpr_F(dc, rd, d32);
1972fcf5ef2aSThomas Huth             break;
19733259b9e2SRichard Henderson 
19743259b9e2SRichard Henderson         case MO_64:
19751210a036SRichard Henderson             d64 = tcg_temp_new_i64();
19761210a036SRichard Henderson             tcg_gen_qemu_ld_i64(d64, addr, da->mem_idx, memop);
19771210a036SRichard Henderson             gen_store_fpr_D(dc, rd, d64);
1978fcf5ef2aSThomas Huth             break;
19793259b9e2SRichard Henderson 
19803259b9e2SRichard Henderson         case MO_128:
1981fcf5ef2aSThomas Huth             d64 = tcg_temp_new_i64();
19821210a036SRichard Henderson             l64 = tcg_temp_new_i64();
19833259b9e2SRichard Henderson             tcg_gen_qemu_ld_i64(d64, addr, da->mem_idx, memop);
1984287b1152SRichard Henderson             addr_tmp = tcg_temp_new();
1985287b1152SRichard Henderson             tcg_gen_addi_tl(addr_tmp, addr, 8);
19861210a036SRichard Henderson             tcg_gen_qemu_ld_i64(l64, addr_tmp, da->mem_idx, memop);
19871210a036SRichard Henderson             gen_store_fpr_D(dc, rd, d64);
19881210a036SRichard Henderson             gen_store_fpr_D(dc, rd + 2, l64);
1989fcf5ef2aSThomas Huth             break;
1990fcf5ef2aSThomas Huth         default:
1991fcf5ef2aSThomas Huth             g_assert_not_reached();
1992fcf5ef2aSThomas Huth         }
1993fcf5ef2aSThomas Huth         break;
1994fcf5ef2aSThomas Huth 
1995fcf5ef2aSThomas Huth     case GET_ASI_BLOCK:
1996fcf5ef2aSThomas Huth         /* Valid for lddfa on aligned registers only.  */
19973259b9e2SRichard Henderson         if (orig_size == MO_64 && (rd & 7) == 0) {
1998fcf5ef2aSThomas Huth             /* The first operation checks required alignment.  */
1999287b1152SRichard Henderson             addr_tmp = tcg_temp_new();
20001210a036SRichard Henderson             d64 = tcg_temp_new_i64();
2001287b1152SRichard Henderson             for (int i = 0; ; ++i) {
20021210a036SRichard Henderson                 tcg_gen_qemu_ld_i64(d64, addr, da->mem_idx,
20033259b9e2SRichard Henderson                                     memop | (i == 0 ? MO_ALIGN_64 : 0));
20041210a036SRichard Henderson                 gen_store_fpr_D(dc, rd + 2 * i, d64);
2005fcf5ef2aSThomas Huth                 if (i == 7) {
2006fcf5ef2aSThomas Huth                     break;
2007fcf5ef2aSThomas Huth                 }
2008287b1152SRichard Henderson                 tcg_gen_addi_tl(addr_tmp, addr, 8);
2009287b1152SRichard Henderson                 addr = addr_tmp;
2010fcf5ef2aSThomas Huth             }
2011fcf5ef2aSThomas Huth         } else {
2012fcf5ef2aSThomas Huth             gen_exception(dc, TT_ILL_INSN);
2013fcf5ef2aSThomas Huth         }
2014fcf5ef2aSThomas Huth         break;
2015fcf5ef2aSThomas Huth 
2016fcf5ef2aSThomas Huth     case GET_ASI_SHORT:
2017fcf5ef2aSThomas Huth         /* Valid for lddfa only.  */
20183259b9e2SRichard Henderson         if (orig_size == MO_64) {
20191210a036SRichard Henderson             d64 = tcg_temp_new_i64();
20201210a036SRichard Henderson             tcg_gen_qemu_ld_i64(d64, addr, da->mem_idx, memop | MO_ALIGN);
20211210a036SRichard Henderson             gen_store_fpr_D(dc, rd, d64);
2022fcf5ef2aSThomas Huth         } else {
2023fcf5ef2aSThomas Huth             gen_exception(dc, TT_ILL_INSN);
2024fcf5ef2aSThomas Huth         }
2025fcf5ef2aSThomas Huth         break;
2026fcf5ef2aSThomas Huth 
2027fcf5ef2aSThomas Huth     default:
2028fcf5ef2aSThomas Huth         {
20293259b9e2SRichard Henderson             TCGv_i32 r_asi = tcg_constant_i32(da->asi);
20303259b9e2SRichard Henderson             TCGv_i32 r_mop = tcg_constant_i32(memop | MO_ALIGN);
2031fcf5ef2aSThomas Huth 
2032fcf5ef2aSThomas Huth             save_state(dc);
2033fcf5ef2aSThomas Huth             /* According to the table in the UA2011 manual, the only
2034fcf5ef2aSThomas Huth                other asis that are valid for ldfa/lddfa/ldqfa are
2035fcf5ef2aSThomas Huth                the NO_FAULT asis.  We still need a helper for these,
2036fcf5ef2aSThomas Huth                but we can just use the integer asi helper for them.  */
2037fcf5ef2aSThomas Huth             switch (size) {
20383259b9e2SRichard Henderson             case MO_32:
2039fcf5ef2aSThomas Huth                 d64 = tcg_temp_new_i64();
2040ad75a51eSRichard Henderson                 gen_helper_ld_asi(d64, tcg_env, addr, r_asi, r_mop);
2041388a6465SRichard Henderson                 d32 = tcg_temp_new_i32();
2042fcf5ef2aSThomas Huth                 tcg_gen_extrl_i64_i32(d32, d64);
2043fcf5ef2aSThomas Huth                 gen_store_fpr_F(dc, rd, d32);
2044fcf5ef2aSThomas Huth                 break;
20453259b9e2SRichard Henderson             case MO_64:
20461210a036SRichard Henderson                 d64 = tcg_temp_new_i64();
20471210a036SRichard Henderson                 gen_helper_ld_asi(d64, tcg_env, addr, r_asi, r_mop);
20481210a036SRichard Henderson                 gen_store_fpr_D(dc, rd, d64);
2049fcf5ef2aSThomas Huth                 break;
20503259b9e2SRichard Henderson             case MO_128:
2051fcf5ef2aSThomas Huth                 d64 = tcg_temp_new_i64();
20521210a036SRichard Henderson                 l64 = tcg_temp_new_i64();
2053ad75a51eSRichard Henderson                 gen_helper_ld_asi(d64, tcg_env, addr, r_asi, r_mop);
2054287b1152SRichard Henderson                 addr_tmp = tcg_temp_new();
2055287b1152SRichard Henderson                 tcg_gen_addi_tl(addr_tmp, addr, 8);
20561210a036SRichard Henderson                 gen_helper_ld_asi(l64, tcg_env, addr_tmp, r_asi, r_mop);
20571210a036SRichard Henderson                 gen_store_fpr_D(dc, rd, d64);
20581210a036SRichard Henderson                 gen_store_fpr_D(dc, rd + 2, l64);
2059fcf5ef2aSThomas Huth                 break;
2060fcf5ef2aSThomas Huth             default:
2061fcf5ef2aSThomas Huth                 g_assert_not_reached();
2062fcf5ef2aSThomas Huth             }
2063fcf5ef2aSThomas Huth         }
2064fcf5ef2aSThomas Huth         break;
2065fcf5ef2aSThomas Huth     }
2066fcf5ef2aSThomas Huth }
2067fcf5ef2aSThomas Huth 
2068287b1152SRichard Henderson static void gen_stf_asi(DisasContext *dc, DisasASI *da, MemOp orig_size,
20693259b9e2SRichard Henderson                         TCGv addr, int rd)
20703259b9e2SRichard Henderson {
20713259b9e2SRichard Henderson     MemOp memop = da->memop;
20723259b9e2SRichard Henderson     MemOp size = memop & MO_SIZE;
2073fcf5ef2aSThomas Huth     TCGv_i32 d32;
20741210a036SRichard Henderson     TCGv_i64 d64;
2075287b1152SRichard Henderson     TCGv addr_tmp;
2076fcf5ef2aSThomas Huth 
20773259b9e2SRichard Henderson     /* TODO: Use 128-bit load/store below. */
20783259b9e2SRichard Henderson     if (size == MO_128) {
20793259b9e2SRichard Henderson         memop = (memop & ~MO_SIZE) | MO_64;
20803259b9e2SRichard Henderson     }
20813259b9e2SRichard Henderson 
20823259b9e2SRichard Henderson     switch (da->type) {
2083fcf5ef2aSThomas Huth     case GET_ASI_EXCP:
2084fcf5ef2aSThomas Huth         break;
2085fcf5ef2aSThomas Huth 
2086fcf5ef2aSThomas Huth     case GET_ASI_DIRECT:
20873259b9e2SRichard Henderson         memop |= MO_ALIGN_4;
2088fcf5ef2aSThomas Huth         switch (size) {
20893259b9e2SRichard Henderson         case MO_32:
2090fcf5ef2aSThomas Huth             d32 = gen_load_fpr_F(dc, rd);
20913259b9e2SRichard Henderson             tcg_gen_qemu_st_i32(d32, addr, da->mem_idx, memop | MO_ALIGN);
2092fcf5ef2aSThomas Huth             break;
20933259b9e2SRichard Henderson         case MO_64:
20941210a036SRichard Henderson             d64 = gen_load_fpr_D(dc, rd);
20951210a036SRichard Henderson             tcg_gen_qemu_st_i64(d64, addr, da->mem_idx, memop | MO_ALIGN_4);
2096fcf5ef2aSThomas Huth             break;
20973259b9e2SRichard Henderson         case MO_128:
2098fcf5ef2aSThomas Huth             /* Only 4-byte alignment required.  However, it is legal for the
2099fcf5ef2aSThomas Huth                cpu to signal the alignment fault, and the OS trap handler is
2100fcf5ef2aSThomas Huth                required to fix it up.  Requiring 16-byte alignment here avoids
2101fcf5ef2aSThomas Huth                having to probe the second page before performing the first
2102fcf5ef2aSThomas Huth                write.  */
21031210a036SRichard Henderson             d64 = gen_load_fpr_D(dc, rd);
21041210a036SRichard Henderson             tcg_gen_qemu_st_i64(d64, addr, da->mem_idx, memop | MO_ALIGN_16);
2105287b1152SRichard Henderson             addr_tmp = tcg_temp_new();
2106287b1152SRichard Henderson             tcg_gen_addi_tl(addr_tmp, addr, 8);
21071210a036SRichard Henderson             d64 = gen_load_fpr_D(dc, rd + 2);
21081210a036SRichard Henderson             tcg_gen_qemu_st_i64(d64, addr_tmp, da->mem_idx, memop);
2109fcf5ef2aSThomas Huth             break;
2110fcf5ef2aSThomas Huth         default:
2111fcf5ef2aSThomas Huth             g_assert_not_reached();
2112fcf5ef2aSThomas Huth         }
2113fcf5ef2aSThomas Huth         break;
2114fcf5ef2aSThomas Huth 
2115fcf5ef2aSThomas Huth     case GET_ASI_BLOCK:
2116fcf5ef2aSThomas Huth         /* Valid for stdfa on aligned registers only.  */
21173259b9e2SRichard Henderson         if (orig_size == MO_64 && (rd & 7) == 0) {
2118fcf5ef2aSThomas Huth             /* The first operation checks required alignment.  */
2119287b1152SRichard Henderson             addr_tmp = tcg_temp_new();
2120287b1152SRichard Henderson             for (int i = 0; ; ++i) {
21211210a036SRichard Henderson                 d64 = gen_load_fpr_D(dc, rd + 2 * i);
21221210a036SRichard Henderson                 tcg_gen_qemu_st_i64(d64, addr, da->mem_idx,
21233259b9e2SRichard Henderson                                     memop | (i == 0 ? MO_ALIGN_64 : 0));
2124fcf5ef2aSThomas Huth                 if (i == 7) {
2125fcf5ef2aSThomas Huth                     break;
2126fcf5ef2aSThomas Huth                 }
2127287b1152SRichard Henderson                 tcg_gen_addi_tl(addr_tmp, addr, 8);
2128287b1152SRichard Henderson                 addr = addr_tmp;
2129fcf5ef2aSThomas Huth             }
2130fcf5ef2aSThomas Huth         } else {
2131fcf5ef2aSThomas Huth             gen_exception(dc, TT_ILL_INSN);
2132fcf5ef2aSThomas Huth         }
2133fcf5ef2aSThomas Huth         break;
2134fcf5ef2aSThomas Huth 
2135fcf5ef2aSThomas Huth     case GET_ASI_SHORT:
2136fcf5ef2aSThomas Huth         /* Valid for stdfa only.  */
21373259b9e2SRichard Henderson         if (orig_size == MO_64) {
21381210a036SRichard Henderson             d64 = gen_load_fpr_D(dc, rd);
21391210a036SRichard Henderson             tcg_gen_qemu_st_i64(d64, addr, da->mem_idx, memop | MO_ALIGN);
2140fcf5ef2aSThomas Huth         } else {
2141fcf5ef2aSThomas Huth             gen_exception(dc, TT_ILL_INSN);
2142fcf5ef2aSThomas Huth         }
2143fcf5ef2aSThomas Huth         break;
2144fcf5ef2aSThomas Huth 
2145fcf5ef2aSThomas Huth     default:
2146fcf5ef2aSThomas Huth         /* According to the table in the UA2011 manual, the only
2147fcf5ef2aSThomas Huth            other asis that are valid for ldfa/lddfa/ldqfa are
2148fcf5ef2aSThomas Huth            the PST* asis, which aren't currently handled.  */
2149fcf5ef2aSThomas Huth         gen_exception(dc, TT_ILL_INSN);
2150fcf5ef2aSThomas Huth         break;
2151fcf5ef2aSThomas Huth     }
2152fcf5ef2aSThomas Huth }
2153fcf5ef2aSThomas Huth 
215442071fc1SRichard Henderson static void gen_ldda_asi(DisasContext *dc, DisasASI *da, TCGv addr, int rd)
2155fcf5ef2aSThomas Huth {
2156a76779eeSRichard Henderson     TCGv hi = gen_dest_gpr(dc, rd);
2157a76779eeSRichard Henderson     TCGv lo = gen_dest_gpr(dc, rd + 1);
2158fcf5ef2aSThomas Huth 
2159c03a0fd1SRichard Henderson     switch (da->type) {
2160fcf5ef2aSThomas Huth     case GET_ASI_EXCP:
2161fcf5ef2aSThomas Huth         return;
2162fcf5ef2aSThomas Huth 
2163fcf5ef2aSThomas Huth     case GET_ASI_DTWINX:
2164ebbbec92SRichard Henderson #ifdef TARGET_SPARC64
2165ebbbec92SRichard Henderson         {
2166ebbbec92SRichard Henderson             MemOp mop = (da->memop & MO_BSWAP) | MO_128 | MO_ALIGN_16;
2167ebbbec92SRichard Henderson             TCGv_i128 t = tcg_temp_new_i128();
2168ebbbec92SRichard Henderson 
2169ebbbec92SRichard Henderson             tcg_gen_qemu_ld_i128(t, addr, da->mem_idx, mop);
2170ebbbec92SRichard Henderson             /*
2171ebbbec92SRichard Henderson              * Note that LE twinx acts as if each 64-bit register result is
2172ebbbec92SRichard Henderson              * byte swapped.  We perform one 128-bit LE load, so must swap
2173ebbbec92SRichard Henderson              * the order of the writebacks.
2174ebbbec92SRichard Henderson              */
2175ebbbec92SRichard Henderson             if ((mop & MO_BSWAP) == MO_TE) {
2176ebbbec92SRichard Henderson                 tcg_gen_extr_i128_i64(lo, hi, t);
2177ebbbec92SRichard Henderson             } else {
2178ebbbec92SRichard Henderson                 tcg_gen_extr_i128_i64(hi, lo, t);
2179ebbbec92SRichard Henderson             }
2180ebbbec92SRichard Henderson         }
2181fcf5ef2aSThomas Huth         break;
2182ebbbec92SRichard Henderson #else
2183ebbbec92SRichard Henderson         g_assert_not_reached();
2184ebbbec92SRichard Henderson #endif
2185fcf5ef2aSThomas Huth 
2186fcf5ef2aSThomas Huth     case GET_ASI_DIRECT:
2187fcf5ef2aSThomas Huth         {
2188fcf5ef2aSThomas Huth             TCGv_i64 tmp = tcg_temp_new_i64();
2189fcf5ef2aSThomas Huth 
2190c03a0fd1SRichard Henderson             tcg_gen_qemu_ld_i64(tmp, addr, da->mem_idx, da->memop | MO_ALIGN);
2191fcf5ef2aSThomas Huth 
2192fcf5ef2aSThomas Huth             /* Note that LE ldda acts as if each 32-bit register
2193fcf5ef2aSThomas Huth                result is byte swapped.  Having just performed one
2194fcf5ef2aSThomas Huth                64-bit bswap, we need now to swap the writebacks.  */
2195c03a0fd1SRichard Henderson             if ((da->memop & MO_BSWAP) == MO_TE) {
2196a76779eeSRichard Henderson                 tcg_gen_extr_i64_tl(lo, hi, tmp);
2197fcf5ef2aSThomas Huth             } else {
2198a76779eeSRichard Henderson                 tcg_gen_extr_i64_tl(hi, lo, tmp);
2199fcf5ef2aSThomas Huth             }
2200fcf5ef2aSThomas Huth         }
2201fcf5ef2aSThomas Huth         break;
2202fcf5ef2aSThomas Huth 
22032786a3f8SRichard Henderson     case GET_ASI_CODE:
22042786a3f8SRichard Henderson #if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
22052786a3f8SRichard Henderson         {
22062786a3f8SRichard Henderson             MemOpIdx oi = make_memop_idx(da->memop, da->mem_idx);
22072786a3f8SRichard Henderson             TCGv_i64 tmp = tcg_temp_new_i64();
22082786a3f8SRichard Henderson 
22092786a3f8SRichard Henderson             gen_helper_ld_code(tmp, tcg_env, addr, tcg_constant_i32(oi));
22102786a3f8SRichard Henderson 
22112786a3f8SRichard Henderson             /* See above.  */
22122786a3f8SRichard Henderson             if ((da->memop & MO_BSWAP) == MO_TE) {
22132786a3f8SRichard Henderson                 tcg_gen_extr_i64_tl(lo, hi, tmp);
22142786a3f8SRichard Henderson             } else {
22152786a3f8SRichard Henderson                 tcg_gen_extr_i64_tl(hi, lo, tmp);
22162786a3f8SRichard Henderson             }
22172786a3f8SRichard Henderson         }
22182786a3f8SRichard Henderson         break;
22192786a3f8SRichard Henderson #else
22202786a3f8SRichard Henderson         g_assert_not_reached();
22212786a3f8SRichard Henderson #endif
22222786a3f8SRichard Henderson 
2223fcf5ef2aSThomas Huth     default:
2224fcf5ef2aSThomas Huth         /* ??? In theory we've handled all of the ASIs that are valid
2225fcf5ef2aSThomas Huth            for ldda, and this should raise DAE_invalid_asi.  However,
2226fcf5ef2aSThomas Huth            real hardware allows others.  This can be seen with e.g.
2227fcf5ef2aSThomas Huth            FreeBSD 10.3 wrt ASI_IC_TAG.  */
2228fcf5ef2aSThomas Huth         {
2229c03a0fd1SRichard Henderson             TCGv_i32 r_asi = tcg_constant_i32(da->asi);
2230c03a0fd1SRichard Henderson             TCGv_i32 r_mop = tcg_constant_i32(da->memop);
2231fcf5ef2aSThomas Huth             TCGv_i64 tmp = tcg_temp_new_i64();
2232fcf5ef2aSThomas Huth 
2233fcf5ef2aSThomas Huth             save_state(dc);
2234ad75a51eSRichard Henderson             gen_helper_ld_asi(tmp, tcg_env, addr, r_asi, r_mop);
2235fcf5ef2aSThomas Huth 
2236fcf5ef2aSThomas Huth             /* See above.  */
2237c03a0fd1SRichard Henderson             if ((da->memop & MO_BSWAP) == MO_TE) {
2238a76779eeSRichard Henderson                 tcg_gen_extr_i64_tl(lo, hi, tmp);
2239fcf5ef2aSThomas Huth             } else {
2240a76779eeSRichard Henderson                 tcg_gen_extr_i64_tl(hi, lo, tmp);
2241fcf5ef2aSThomas Huth             }
2242fcf5ef2aSThomas Huth         }
2243fcf5ef2aSThomas Huth         break;
2244fcf5ef2aSThomas Huth     }
2245fcf5ef2aSThomas Huth 
2246fcf5ef2aSThomas Huth     gen_store_gpr(dc, rd, hi);
2247fcf5ef2aSThomas Huth     gen_store_gpr(dc, rd + 1, lo);
2248fcf5ef2aSThomas Huth }
2249fcf5ef2aSThomas Huth 
225042071fc1SRichard Henderson static void gen_stda_asi(DisasContext *dc, DisasASI *da, TCGv addr, int rd)
2251c03a0fd1SRichard Henderson {
2252c03a0fd1SRichard Henderson     TCGv hi = gen_load_gpr(dc, rd);
2253fcf5ef2aSThomas Huth     TCGv lo = gen_load_gpr(dc, rd + 1);
2254fcf5ef2aSThomas Huth 
2255c03a0fd1SRichard Henderson     switch (da->type) {
2256fcf5ef2aSThomas Huth     case GET_ASI_EXCP:
2257fcf5ef2aSThomas Huth         break;
2258fcf5ef2aSThomas Huth 
2259fcf5ef2aSThomas Huth     case GET_ASI_DTWINX:
2260ebbbec92SRichard Henderson #ifdef TARGET_SPARC64
2261ebbbec92SRichard Henderson         {
2262ebbbec92SRichard Henderson             MemOp mop = (da->memop & MO_BSWAP) | MO_128 | MO_ALIGN_16;
2263ebbbec92SRichard Henderson             TCGv_i128 t = tcg_temp_new_i128();
2264ebbbec92SRichard Henderson 
2265ebbbec92SRichard Henderson             /*
2266ebbbec92SRichard Henderson              * Note that LE twinx acts as if each 64-bit register result is
2267ebbbec92SRichard Henderson              * byte swapped.  We perform one 128-bit LE store, so must swap
2268ebbbec92SRichard Henderson              * the order of the construction.
2269ebbbec92SRichard Henderson              */
2270ebbbec92SRichard Henderson             if ((mop & MO_BSWAP) == MO_TE) {
2271ebbbec92SRichard Henderson                 tcg_gen_concat_i64_i128(t, lo, hi);
2272ebbbec92SRichard Henderson             } else {
2273ebbbec92SRichard Henderson                 tcg_gen_concat_i64_i128(t, hi, lo);
2274ebbbec92SRichard Henderson             }
2275ebbbec92SRichard Henderson             tcg_gen_qemu_st_i128(t, addr, da->mem_idx, mop);
2276ebbbec92SRichard Henderson         }
2277fcf5ef2aSThomas Huth         break;
2278ebbbec92SRichard Henderson #else
2279ebbbec92SRichard Henderson         g_assert_not_reached();
2280ebbbec92SRichard Henderson #endif
2281fcf5ef2aSThomas Huth 
2282fcf5ef2aSThomas Huth     case GET_ASI_DIRECT:
2283fcf5ef2aSThomas Huth         {
2284fcf5ef2aSThomas Huth             TCGv_i64 t64 = tcg_temp_new_i64();
2285fcf5ef2aSThomas Huth 
2286fcf5ef2aSThomas Huth             /* Note that LE stda acts as if each 32-bit register result is
2287fcf5ef2aSThomas Huth                byte swapped.  We will perform one 64-bit LE store, so now
2288fcf5ef2aSThomas Huth                we must swap the order of the construction.  */
2289c03a0fd1SRichard Henderson             if ((da->memop & MO_BSWAP) == MO_TE) {
2290a76779eeSRichard Henderson                 tcg_gen_concat_tl_i64(t64, lo, hi);
2291fcf5ef2aSThomas Huth             } else {
2292a76779eeSRichard Henderson                 tcg_gen_concat_tl_i64(t64, hi, lo);
2293fcf5ef2aSThomas Huth             }
2294c03a0fd1SRichard Henderson             tcg_gen_qemu_st_i64(t64, addr, da->mem_idx, da->memop | MO_ALIGN);
2295fcf5ef2aSThomas Huth         }
2296fcf5ef2aSThomas Huth         break;
2297fcf5ef2aSThomas Huth 
2298a76779eeSRichard Henderson     case GET_ASI_BFILL:
2299a76779eeSRichard Henderson         assert(TARGET_LONG_BITS == 32);
230054c3e953SRichard Henderson         /*
230154c3e953SRichard Henderson          * Store 32 bytes of [rd:rd+1] to ADDR.
230254c3e953SRichard Henderson          * See comments for GET_ASI_COPY above.
230354c3e953SRichard Henderson          */
2304a76779eeSRichard Henderson         {
230554c3e953SRichard Henderson             MemOp mop = MO_TE | MO_128 | MO_ATOM_IFALIGN_PAIR;
230654c3e953SRichard Henderson             TCGv_i64 t8 = tcg_temp_new_i64();
230754c3e953SRichard Henderson             TCGv_i128 t16 = tcg_temp_new_i128();
230854c3e953SRichard Henderson             TCGv daddr = tcg_temp_new();
2309a76779eeSRichard Henderson 
231054c3e953SRichard Henderson             tcg_gen_concat_tl_i64(t8, lo, hi);
231154c3e953SRichard Henderson             tcg_gen_concat_i64_i128(t16, t8, t8);
231254c3e953SRichard Henderson             tcg_gen_andi_tl(daddr, addr, -32);
231354c3e953SRichard Henderson             tcg_gen_qemu_st_i128(t16, daddr, da->mem_idx, mop);
231454c3e953SRichard Henderson             tcg_gen_addi_tl(daddr, daddr, 16);
231554c3e953SRichard Henderson             tcg_gen_qemu_st_i128(t16, daddr, da->mem_idx, mop);
2316a76779eeSRichard Henderson         }
2317a76779eeSRichard Henderson         break;
2318a76779eeSRichard Henderson 
2319fcf5ef2aSThomas Huth     default:
2320fcf5ef2aSThomas Huth         /* ??? In theory we've handled all of the ASIs that are valid
2321fcf5ef2aSThomas Huth            for stda, and this should raise DAE_invalid_asi.  */
2322fcf5ef2aSThomas Huth         {
2323c03a0fd1SRichard Henderson             TCGv_i32 r_asi = tcg_constant_i32(da->asi);
2324c03a0fd1SRichard Henderson             TCGv_i32 r_mop = tcg_constant_i32(da->memop);
2325fcf5ef2aSThomas Huth             TCGv_i64 t64 = tcg_temp_new_i64();
2326fcf5ef2aSThomas Huth 
2327fcf5ef2aSThomas Huth             /* See above.  */
2328c03a0fd1SRichard Henderson             if ((da->memop & MO_BSWAP) == MO_TE) {
2329a76779eeSRichard Henderson                 tcg_gen_concat_tl_i64(t64, lo, hi);
2330fcf5ef2aSThomas Huth             } else {
2331a76779eeSRichard Henderson                 tcg_gen_concat_tl_i64(t64, hi, lo);
2332fcf5ef2aSThomas Huth             }
2333fcf5ef2aSThomas Huth 
2334fcf5ef2aSThomas Huth             save_state(dc);
2335ad75a51eSRichard Henderson             gen_helper_st_asi(tcg_env, addr, t64, r_asi, r_mop);
2336fcf5ef2aSThomas Huth         }
2337fcf5ef2aSThomas Huth         break;
2338fcf5ef2aSThomas Huth     }
2339fcf5ef2aSThomas Huth }
2340fcf5ef2aSThomas Huth 
2341fcf5ef2aSThomas Huth static void gen_fmovs(DisasContext *dc, DisasCompare *cmp, int rd, int rs)
2342fcf5ef2aSThomas Huth {
2343f7ec8155SRichard Henderson #ifdef TARGET_SPARC64
2344fcf5ef2aSThomas Huth     TCGv_i32 c32, zero, dst, s1, s2;
2345dd7dbfccSRichard Henderson     TCGv_i64 c64 = tcg_temp_new_i64();
2346fcf5ef2aSThomas Huth 
2347fcf5ef2aSThomas Huth     /* We have two choices here: extend the 32 bit data and use movcond_i64,
2348fcf5ef2aSThomas Huth        or fold the comparison down to 32 bits and use movcond_i32.  Choose
2349fcf5ef2aSThomas Huth        the later.  */
2350fcf5ef2aSThomas Huth     c32 = tcg_temp_new_i32();
2351c8507ebfSRichard Henderson     tcg_gen_setcondi_i64(cmp->cond, c64, cmp->c1, cmp->c2);
2352fcf5ef2aSThomas Huth     tcg_gen_extrl_i64_i32(c32, c64);
2353fcf5ef2aSThomas Huth 
2354fcf5ef2aSThomas Huth     s1 = gen_load_fpr_F(dc, rs);
2355fcf5ef2aSThomas Huth     s2 = gen_load_fpr_F(dc, rd);
2356388a6465SRichard Henderson     dst = tcg_temp_new_i32();
235700ab7e61SRichard Henderson     zero = tcg_constant_i32(0);
2358fcf5ef2aSThomas Huth 
2359fcf5ef2aSThomas Huth     tcg_gen_movcond_i32(TCG_COND_NE, dst, c32, zero, s1, s2);
2360fcf5ef2aSThomas Huth 
2361fcf5ef2aSThomas Huth     gen_store_fpr_F(dc, rd, dst);
2362f7ec8155SRichard Henderson #else
2363f7ec8155SRichard Henderson     qemu_build_not_reached();
2364f7ec8155SRichard Henderson #endif
2365fcf5ef2aSThomas Huth }
2366fcf5ef2aSThomas Huth 
2367fcf5ef2aSThomas Huth static void gen_fmovd(DisasContext *dc, DisasCompare *cmp, int rd, int rs)
2368fcf5ef2aSThomas Huth {
2369f7ec8155SRichard Henderson #ifdef TARGET_SPARC64
237052f46d46SRichard Henderson     TCGv_i64 dst = tcg_temp_new_i64();
2371c8507ebfSRichard Henderson     tcg_gen_movcond_i64(cmp->cond, dst, cmp->c1, tcg_constant_tl(cmp->c2),
2372fcf5ef2aSThomas Huth                         gen_load_fpr_D(dc, rs),
2373fcf5ef2aSThomas Huth                         gen_load_fpr_D(dc, rd));
2374fcf5ef2aSThomas Huth     gen_store_fpr_D(dc, rd, dst);
2375f7ec8155SRichard Henderson #else
2376f7ec8155SRichard Henderson     qemu_build_not_reached();
2377f7ec8155SRichard Henderson #endif
2378fcf5ef2aSThomas Huth }
2379fcf5ef2aSThomas Huth 
2380fcf5ef2aSThomas Huth static void gen_fmovq(DisasContext *dc, DisasCompare *cmp, int rd, int rs)
2381fcf5ef2aSThomas Huth {
2382f7ec8155SRichard Henderson #ifdef TARGET_SPARC64
2383c8507ebfSRichard Henderson     TCGv c2 = tcg_constant_tl(cmp->c2);
23841210a036SRichard Henderson     TCGv_i64 h = tcg_temp_new_i64();
23851210a036SRichard Henderson     TCGv_i64 l = tcg_temp_new_i64();
2386fcf5ef2aSThomas Huth 
23871210a036SRichard Henderson     tcg_gen_movcond_i64(cmp->cond, h, cmp->c1, c2,
23881210a036SRichard Henderson                         gen_load_fpr_D(dc, rs),
23891210a036SRichard Henderson                         gen_load_fpr_D(dc, rd));
23901210a036SRichard Henderson     tcg_gen_movcond_i64(cmp->cond, l, cmp->c1, c2,
23911210a036SRichard Henderson                         gen_load_fpr_D(dc, rs + 2),
23921210a036SRichard Henderson                         gen_load_fpr_D(dc, rd + 2));
23931210a036SRichard Henderson     gen_store_fpr_D(dc, rd, h);
23941210a036SRichard Henderson     gen_store_fpr_D(dc, rd + 2, l);
2395f7ec8155SRichard Henderson #else
2396f7ec8155SRichard Henderson     qemu_build_not_reached();
2397f7ec8155SRichard Henderson #endif
2398fcf5ef2aSThomas Huth }
2399fcf5ef2aSThomas Huth 
2400f7ec8155SRichard Henderson #ifdef TARGET_SPARC64
24015d617bfbSRichard Henderson static void gen_load_trap_state_at_tl(TCGv_ptr r_tsptr)
2402fcf5ef2aSThomas Huth {
2403fcf5ef2aSThomas Huth     TCGv_i32 r_tl = tcg_temp_new_i32();
2404fcf5ef2aSThomas Huth 
2405fcf5ef2aSThomas Huth     /* load env->tl into r_tl */
2406ad75a51eSRichard Henderson     tcg_gen_ld_i32(r_tl, tcg_env, offsetof(CPUSPARCState, tl));
2407fcf5ef2aSThomas Huth 
2408fcf5ef2aSThomas Huth     /* tl = [0 ... MAXTL_MASK] where MAXTL_MASK must be power of 2 */
2409fcf5ef2aSThomas Huth     tcg_gen_andi_i32(r_tl, r_tl, MAXTL_MASK);
2410fcf5ef2aSThomas Huth 
2411fcf5ef2aSThomas Huth     /* calculate offset to current trap state from env->ts, reuse r_tl */
2412fcf5ef2aSThomas Huth     tcg_gen_muli_i32(r_tl, r_tl, sizeof (trap_state));
2413ad75a51eSRichard Henderson     tcg_gen_addi_ptr(r_tsptr, tcg_env, offsetof(CPUSPARCState, ts));
2414fcf5ef2aSThomas Huth 
2415fcf5ef2aSThomas Huth     /* tsptr = env->ts[env->tl & MAXTL_MASK] */
2416fcf5ef2aSThomas Huth     {
2417fcf5ef2aSThomas Huth         TCGv_ptr r_tl_tmp = tcg_temp_new_ptr();
2418fcf5ef2aSThomas Huth         tcg_gen_ext_i32_ptr(r_tl_tmp, r_tl);
2419fcf5ef2aSThomas Huth         tcg_gen_add_ptr(r_tsptr, r_tsptr, r_tl_tmp);
2420fcf5ef2aSThomas Huth     }
2421fcf5ef2aSThomas Huth }
2422fcf5ef2aSThomas Huth #endif
2423fcf5ef2aSThomas Huth 
242406c060d9SRichard Henderson static int extract_dfpreg(DisasContext *dc, int x)
242506c060d9SRichard Henderson {
24260bba7572SRichard Henderson     int r = x & 0x1e;
24270bba7572SRichard Henderson #ifdef TARGET_SPARC64
24280bba7572SRichard Henderson     r |= (x & 1) << 5;
24290bba7572SRichard Henderson #endif
24300bba7572SRichard Henderson     return r;
243106c060d9SRichard Henderson }
243206c060d9SRichard Henderson 
243306c060d9SRichard Henderson static int extract_qfpreg(DisasContext *dc, int x)
243406c060d9SRichard Henderson {
24350bba7572SRichard Henderson     int r = x & 0x1c;
24360bba7572SRichard Henderson #ifdef TARGET_SPARC64
24370bba7572SRichard Henderson     r |= (x & 1) << 5;
24380bba7572SRichard Henderson #endif
24390bba7572SRichard Henderson     return r;
244006c060d9SRichard Henderson }
244106c060d9SRichard Henderson 
2442878cc677SRichard Henderson /* Include the auto-generated decoder.  */
2443878cc677SRichard Henderson #include "decode-insns.c.inc"
2444878cc677SRichard Henderson 
2445878cc677SRichard Henderson #define TRANS(NAME, AVAIL, FUNC, ...) \
2446878cc677SRichard Henderson     static bool trans_##NAME(DisasContext *dc, arg_##NAME *a) \
2447878cc677SRichard Henderson     { return avail_##AVAIL(dc) && FUNC(dc, __VA_ARGS__); }
2448878cc677SRichard Henderson 
2449878cc677SRichard Henderson #define avail_ALL(C)      true
2450878cc677SRichard Henderson #ifdef TARGET_SPARC64
2451878cc677SRichard Henderson # define avail_32(C)      false
2452af25071cSRichard Henderson # define avail_ASR17(C)   false
2453d0a11d25SRichard Henderson # define avail_CASA(C)    true
2454c2636853SRichard Henderson # define avail_DIV(C)     true
2455b5372650SRichard Henderson # define avail_MUL(C)     true
24560faef01bSRichard Henderson # define avail_POWERDOWN(C) false
2457878cc677SRichard Henderson # define avail_64(C)      true
24584fd71d19SRichard Henderson # define avail_FMAF(C)    ((C)->def->features & CPU_FEATURE_FMAF)
24595d617bfbSRichard Henderson # define avail_GL(C)      ((C)->def->features & CPU_FEATURE_GL)
2460af25071cSRichard Henderson # define avail_HYPV(C)    ((C)->def->features & CPU_FEATURE_HYPV)
246168a414e9SRichard Henderson # define avail_IMA(C)     ((C)->def->features & CPU_FEATURE_IMA)
2462b88ce6f2SRichard Henderson # define avail_VIS1(C)    ((C)->def->features & CPU_FEATURE_VIS1)
2463b88ce6f2SRichard Henderson # define avail_VIS2(C)    ((C)->def->features & CPU_FEATURE_VIS2)
24643335a048SRichard Henderson # define avail_VIS3(C)    ((C)->def->features & CPU_FEATURE_VIS3)
24653335a048SRichard Henderson # define avail_VIS3B(C)   avail_VIS3(C)
246690b1433dSRichard Henderson # define avail_VIS4(C)    ((C)->def->features & CPU_FEATURE_VIS4)
2467878cc677SRichard Henderson #else
2468878cc677SRichard Henderson # define avail_32(C)      true
2469af25071cSRichard Henderson # define avail_ASR17(C)   ((C)->def->features & CPU_FEATURE_ASR17)
2470d0a11d25SRichard Henderson # define avail_CASA(C)    ((C)->def->features & CPU_FEATURE_CASA)
2471c2636853SRichard Henderson # define avail_DIV(C)     ((C)->def->features & CPU_FEATURE_DIV)
2472b5372650SRichard Henderson # define avail_MUL(C)     ((C)->def->features & CPU_FEATURE_MUL)
24730faef01bSRichard Henderson # define avail_POWERDOWN(C) ((C)->def->features & CPU_FEATURE_POWERDOWN)
2474878cc677SRichard Henderson # define avail_64(C)      false
24754fd71d19SRichard Henderson # define avail_FMAF(C)    false
24765d617bfbSRichard Henderson # define avail_GL(C)      false
2477af25071cSRichard Henderson # define avail_HYPV(C)    false
247868a414e9SRichard Henderson # define avail_IMA(C)     false
2479b88ce6f2SRichard Henderson # define avail_VIS1(C)    false
2480b88ce6f2SRichard Henderson # define avail_VIS2(C)    false
24813335a048SRichard Henderson # define avail_VIS3(C)    false
24823335a048SRichard Henderson # define avail_VIS3B(C)   false
248390b1433dSRichard Henderson # define avail_VIS4(C)    false
2484878cc677SRichard Henderson #endif
2485878cc677SRichard Henderson 
2486878cc677SRichard Henderson /* Default case for non jump instructions. */
2487878cc677SRichard Henderson static bool advance_pc(DisasContext *dc)
2488878cc677SRichard Henderson {
24894a8d145dSRichard Henderson     TCGLabel *l1;
24904a8d145dSRichard Henderson 
249189527e3aSRichard Henderson     finishing_insn(dc);
249289527e3aSRichard Henderson 
2493878cc677SRichard Henderson     if (dc->npc & 3) {
2494878cc677SRichard Henderson         switch (dc->npc) {
2495878cc677SRichard Henderson         case DYNAMIC_PC:
2496878cc677SRichard Henderson         case DYNAMIC_PC_LOOKUP:
2497878cc677SRichard Henderson             dc->pc = dc->npc;
2498444d8b30SRichard Henderson             tcg_gen_mov_tl(cpu_pc, cpu_npc);
2499444d8b30SRichard Henderson             tcg_gen_addi_tl(cpu_npc, cpu_npc, 4);
2500878cc677SRichard Henderson             break;
25014a8d145dSRichard Henderson 
2502878cc677SRichard Henderson         case JUMP_PC:
2503878cc677SRichard Henderson             /* we can do a static jump */
25044a8d145dSRichard Henderson             l1 = gen_new_label();
2505533f042fSRichard Henderson             tcg_gen_brcondi_tl(dc->jump.cond, dc->jump.c1, dc->jump.c2, l1);
25064a8d145dSRichard Henderson 
25074a8d145dSRichard Henderson             /* jump not taken */
25084a8d145dSRichard Henderson             gen_goto_tb(dc, 1, dc->jump_pc[1], dc->jump_pc[1] + 4);
25094a8d145dSRichard Henderson 
25104a8d145dSRichard Henderson             /* jump taken */
25114a8d145dSRichard Henderson             gen_set_label(l1);
25124a8d145dSRichard Henderson             gen_goto_tb(dc, 0, dc->jump_pc[0], dc->jump_pc[0] + 4);
25134a8d145dSRichard Henderson 
2514878cc677SRichard Henderson             dc->base.is_jmp = DISAS_NORETURN;
2515878cc677SRichard Henderson             break;
25164a8d145dSRichard Henderson 
2517878cc677SRichard Henderson         default:
2518878cc677SRichard Henderson             g_assert_not_reached();
2519878cc677SRichard Henderson         }
2520878cc677SRichard Henderson     } else {
2521878cc677SRichard Henderson         dc->pc = dc->npc;
2522878cc677SRichard Henderson         dc->npc = dc->npc + 4;
2523878cc677SRichard Henderson     }
2524878cc677SRichard Henderson     return true;
2525878cc677SRichard Henderson }
2526878cc677SRichard Henderson 
25276d2a0768SRichard Henderson /*
25286d2a0768SRichard Henderson  * Major opcodes 00 and 01 -- branches, call, and sethi
25296d2a0768SRichard Henderson  */
25306d2a0768SRichard Henderson 
25319d4e2bc7SRichard Henderson static bool advance_jump_cond(DisasContext *dc, DisasCompare *cmp,
25323951b7a8SRichard Henderson                               bool annul, int disp)
2533276567aaSRichard Henderson {
25343951b7a8SRichard Henderson     target_ulong dest = address_mask_i(dc, dc->pc + disp * 4);
2535c76c8045SRichard Henderson     target_ulong npc;
2536c76c8045SRichard Henderson 
253789527e3aSRichard Henderson     finishing_insn(dc);
253889527e3aSRichard Henderson 
25392d9bb237SRichard Henderson     if (cmp->cond == TCG_COND_ALWAYS) {
25402d9bb237SRichard Henderson         if (annul) {
25412d9bb237SRichard Henderson             dc->pc = dest;
25422d9bb237SRichard Henderson             dc->npc = dest + 4;
25432d9bb237SRichard Henderson         } else {
25442d9bb237SRichard Henderson             gen_mov_pc_npc(dc);
25452d9bb237SRichard Henderson             dc->npc = dest;
25462d9bb237SRichard Henderson         }
25472d9bb237SRichard Henderson         return true;
25482d9bb237SRichard Henderson     }
25492d9bb237SRichard Henderson 
25502d9bb237SRichard Henderson     if (cmp->cond == TCG_COND_NEVER) {
25512d9bb237SRichard Henderson         npc = dc->npc;
25522d9bb237SRichard Henderson         if (npc & 3) {
25532d9bb237SRichard Henderson             gen_mov_pc_npc(dc);
25542d9bb237SRichard Henderson             if (annul) {
25552d9bb237SRichard Henderson                 tcg_gen_addi_tl(cpu_pc, cpu_pc, 4);
25562d9bb237SRichard Henderson             }
25572d9bb237SRichard Henderson             tcg_gen_addi_tl(cpu_npc, cpu_pc, 4);
25582d9bb237SRichard Henderson         } else {
25592d9bb237SRichard Henderson             dc->pc = npc + (annul ? 4 : 0);
25602d9bb237SRichard Henderson             dc->npc = dc->pc + 4;
25612d9bb237SRichard Henderson         }
25622d9bb237SRichard Henderson         return true;
25632d9bb237SRichard Henderson     }
25642d9bb237SRichard Henderson 
2565c76c8045SRichard Henderson     flush_cond(dc);
2566c76c8045SRichard Henderson     npc = dc->npc;
25676b3e4cc6SRichard Henderson 
2568276567aaSRichard Henderson     if (annul) {
25696b3e4cc6SRichard Henderson         TCGLabel *l1 = gen_new_label();
25706b3e4cc6SRichard Henderson 
2571c8507ebfSRichard Henderson         tcg_gen_brcondi_tl(tcg_invert_cond(cmp->cond), cmp->c1, cmp->c2, l1);
25726b3e4cc6SRichard Henderson         gen_goto_tb(dc, 0, npc, dest);
25736b3e4cc6SRichard Henderson         gen_set_label(l1);
25746b3e4cc6SRichard Henderson         gen_goto_tb(dc, 1, npc + 4, npc + 8);
25756b3e4cc6SRichard Henderson 
25766b3e4cc6SRichard Henderson         dc->base.is_jmp = DISAS_NORETURN;
2577276567aaSRichard Henderson     } else {
25786b3e4cc6SRichard Henderson         if (npc & 3) {
25796b3e4cc6SRichard Henderson             switch (npc) {
25806b3e4cc6SRichard Henderson             case DYNAMIC_PC:
25816b3e4cc6SRichard Henderson             case DYNAMIC_PC_LOOKUP:
25826b3e4cc6SRichard Henderson                 tcg_gen_mov_tl(cpu_pc, cpu_npc);
25836b3e4cc6SRichard Henderson                 tcg_gen_addi_tl(cpu_npc, cpu_npc, 4);
25849d4e2bc7SRichard Henderson                 tcg_gen_movcond_tl(cmp->cond, cpu_npc,
2585c8507ebfSRichard Henderson                                    cmp->c1, tcg_constant_tl(cmp->c2),
25866b3e4cc6SRichard Henderson                                    tcg_constant_tl(dest), cpu_npc);
25876b3e4cc6SRichard Henderson                 dc->pc = npc;
25886b3e4cc6SRichard Henderson                 break;
25896b3e4cc6SRichard Henderson             default:
25906b3e4cc6SRichard Henderson                 g_assert_not_reached();
25916b3e4cc6SRichard Henderson             }
25926b3e4cc6SRichard Henderson         } else {
25936b3e4cc6SRichard Henderson             dc->pc = npc;
2594533f042fSRichard Henderson             dc->npc = JUMP_PC;
2595533f042fSRichard Henderson             dc->jump = *cmp;
25966b3e4cc6SRichard Henderson             dc->jump_pc[0] = dest;
25976b3e4cc6SRichard Henderson             dc->jump_pc[1] = npc + 4;
2598dd7dbfccSRichard Henderson 
2599dd7dbfccSRichard Henderson             /* The condition for cpu_cond is always NE -- normalize. */
2600dd7dbfccSRichard Henderson             if (cmp->cond == TCG_COND_NE) {
2601c8507ebfSRichard Henderson                 tcg_gen_xori_tl(cpu_cond, cmp->c1, cmp->c2);
26029d4e2bc7SRichard Henderson             } else {
2603c8507ebfSRichard Henderson                 tcg_gen_setcondi_tl(cmp->cond, cpu_cond, cmp->c1, cmp->c2);
26049d4e2bc7SRichard Henderson             }
260589527e3aSRichard Henderson             dc->cpu_cond_live = true;
26066b3e4cc6SRichard Henderson         }
2607276567aaSRichard Henderson     }
2608276567aaSRichard Henderson     return true;
2609276567aaSRichard Henderson }
2610276567aaSRichard Henderson 
2611af25071cSRichard Henderson static bool raise_priv(DisasContext *dc)
2612af25071cSRichard Henderson {
2613af25071cSRichard Henderson     gen_exception(dc, TT_PRIV_INSN);
2614af25071cSRichard Henderson     return true;
2615af25071cSRichard Henderson }
2616af25071cSRichard Henderson 
261706c060d9SRichard Henderson static bool raise_unimpfpop(DisasContext *dc)
261806c060d9SRichard Henderson {
261906c060d9SRichard Henderson     gen_op_fpexception_im(dc, FSR_FTT_UNIMPFPOP);
262006c060d9SRichard Henderson     return true;
262106c060d9SRichard Henderson }
262206c060d9SRichard Henderson 
262306c060d9SRichard Henderson static bool gen_trap_float128(DisasContext *dc)
262406c060d9SRichard Henderson {
262506c060d9SRichard Henderson     if (dc->def->features & CPU_FEATURE_FLOAT128) {
262606c060d9SRichard Henderson         return false;
262706c060d9SRichard Henderson     }
262806c060d9SRichard Henderson     return raise_unimpfpop(dc);
262906c060d9SRichard Henderson }
263006c060d9SRichard Henderson 
2631276567aaSRichard Henderson static bool do_bpcc(DisasContext *dc, arg_bcc *a)
2632276567aaSRichard Henderson {
26331ea9c62aSRichard Henderson     DisasCompare cmp;
2634276567aaSRichard Henderson 
26351ea9c62aSRichard Henderson     gen_compare(&cmp, a->cc, a->cond, dc);
26363951b7a8SRichard Henderson     return advance_jump_cond(dc, &cmp, a->a, a->i);
2637276567aaSRichard Henderson }
2638276567aaSRichard Henderson 
2639276567aaSRichard Henderson TRANS(Bicc, ALL, do_bpcc, a)
2640276567aaSRichard Henderson TRANS(BPcc,  64, do_bpcc, a)
2641276567aaSRichard Henderson 
264245196ea4SRichard Henderson static bool do_fbpfcc(DisasContext *dc, arg_bcc *a)
264345196ea4SRichard Henderson {
2644d5471936SRichard Henderson     DisasCompare cmp;
264545196ea4SRichard Henderson 
264645196ea4SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
264745196ea4SRichard Henderson         return true;
264845196ea4SRichard Henderson     }
2649d5471936SRichard Henderson     gen_fcompare(&cmp, a->cc, a->cond);
26503951b7a8SRichard Henderson     return advance_jump_cond(dc, &cmp, a->a, a->i);
265145196ea4SRichard Henderson }
265245196ea4SRichard Henderson 
265345196ea4SRichard Henderson TRANS(FBPfcc,  64, do_fbpfcc, a)
265445196ea4SRichard Henderson TRANS(FBfcc,  ALL, do_fbpfcc, a)
265545196ea4SRichard Henderson 
2656ab9ffe98SRichard Henderson static bool trans_BPr(DisasContext *dc, arg_BPr *a)
2657ab9ffe98SRichard Henderson {
2658ab9ffe98SRichard Henderson     DisasCompare cmp;
2659ab9ffe98SRichard Henderson 
2660ab9ffe98SRichard Henderson     if (!avail_64(dc)) {
2661ab9ffe98SRichard Henderson         return false;
2662ab9ffe98SRichard Henderson     }
26632c4f56c9SRichard Henderson     if (!gen_compare_reg(&cmp, a->cond, gen_load_gpr(dc, a->rs1))) {
2664ab9ffe98SRichard Henderson         return false;
2665ab9ffe98SRichard Henderson     }
26663951b7a8SRichard Henderson     return advance_jump_cond(dc, &cmp, a->a, a->i);
2667ab9ffe98SRichard Henderson }
2668ab9ffe98SRichard Henderson 
266923ada1b1SRichard Henderson static bool trans_CALL(DisasContext *dc, arg_CALL *a)
267023ada1b1SRichard Henderson {
267123ada1b1SRichard Henderson     target_long target = address_mask_i(dc, dc->pc + a->i * 4);
267223ada1b1SRichard Henderson 
267323ada1b1SRichard Henderson     gen_store_gpr(dc, 15, tcg_constant_tl(dc->pc));
267423ada1b1SRichard Henderson     gen_mov_pc_npc(dc);
267523ada1b1SRichard Henderson     dc->npc = target;
267623ada1b1SRichard Henderson     return true;
267723ada1b1SRichard Henderson }
267823ada1b1SRichard Henderson 
267945196ea4SRichard Henderson static bool trans_NCP(DisasContext *dc, arg_NCP *a)
268045196ea4SRichard Henderson {
268145196ea4SRichard Henderson     /*
268245196ea4SRichard Henderson      * For sparc32, always generate the no-coprocessor exception.
268345196ea4SRichard Henderson      * For sparc64, always generate illegal instruction.
268445196ea4SRichard Henderson      */
268545196ea4SRichard Henderson #ifdef TARGET_SPARC64
268645196ea4SRichard Henderson     return false;
268745196ea4SRichard Henderson #else
268845196ea4SRichard Henderson     gen_exception(dc, TT_NCP_INSN);
268945196ea4SRichard Henderson     return true;
269045196ea4SRichard Henderson #endif
269145196ea4SRichard Henderson }
269245196ea4SRichard Henderson 
26936d2a0768SRichard Henderson static bool trans_SETHI(DisasContext *dc, arg_SETHI *a)
26946d2a0768SRichard Henderson {
26956d2a0768SRichard Henderson     /* Special-case %g0 because that's the canonical nop.  */
26966d2a0768SRichard Henderson     if (a->rd) {
26976d2a0768SRichard Henderson         gen_store_gpr(dc, a->rd, tcg_constant_tl((uint32_t)a->i << 10));
26986d2a0768SRichard Henderson     }
26996d2a0768SRichard Henderson     return advance_pc(dc);
27006d2a0768SRichard Henderson }
27016d2a0768SRichard Henderson 
27020faef01bSRichard Henderson /*
27030faef01bSRichard Henderson  * Major Opcode 10 -- integer, floating-point, vis, and system insns.
27040faef01bSRichard Henderson  */
27050faef01bSRichard Henderson 
270630376636SRichard Henderson static bool do_tcc(DisasContext *dc, int cond, int cc,
270730376636SRichard Henderson                    int rs1, bool imm, int rs2_or_imm)
270830376636SRichard Henderson {
270930376636SRichard Henderson     int mask = ((dc->def->features & CPU_FEATURE_HYPV) && supervisor(dc)
271030376636SRichard Henderson                 ? UA2005_HTRAP_MASK : V8_TRAP_MASK);
271130376636SRichard Henderson     DisasCompare cmp;
271230376636SRichard Henderson     TCGLabel *lab;
271330376636SRichard Henderson     TCGv_i32 trap;
271430376636SRichard Henderson 
271530376636SRichard Henderson     /* Trap never.  */
271630376636SRichard Henderson     if (cond == 0) {
271730376636SRichard Henderson         return advance_pc(dc);
271830376636SRichard Henderson     }
271930376636SRichard Henderson 
272030376636SRichard Henderson     /*
272130376636SRichard Henderson      * Immediate traps are the most common case.  Since this value is
272230376636SRichard Henderson      * live across the branch, it really pays to evaluate the constant.
272330376636SRichard Henderson      */
272430376636SRichard Henderson     if (rs1 == 0 && (imm || rs2_or_imm == 0)) {
272530376636SRichard Henderson         trap = tcg_constant_i32((rs2_or_imm & mask) + TT_TRAP);
272630376636SRichard Henderson     } else {
272730376636SRichard Henderson         trap = tcg_temp_new_i32();
272830376636SRichard Henderson         tcg_gen_trunc_tl_i32(trap, gen_load_gpr(dc, rs1));
272930376636SRichard Henderson         if (imm) {
273030376636SRichard Henderson             tcg_gen_addi_i32(trap, trap, rs2_or_imm);
273130376636SRichard Henderson         } else {
273230376636SRichard Henderson             TCGv_i32 t2 = tcg_temp_new_i32();
273330376636SRichard Henderson             tcg_gen_trunc_tl_i32(t2, gen_load_gpr(dc, rs2_or_imm));
273430376636SRichard Henderson             tcg_gen_add_i32(trap, trap, t2);
273530376636SRichard Henderson         }
273630376636SRichard Henderson         tcg_gen_andi_i32(trap, trap, mask);
273730376636SRichard Henderson         tcg_gen_addi_i32(trap, trap, TT_TRAP);
273830376636SRichard Henderson     }
273930376636SRichard Henderson 
274089527e3aSRichard Henderson     finishing_insn(dc);
274189527e3aSRichard Henderson 
274230376636SRichard Henderson     /* Trap always.  */
274330376636SRichard Henderson     if (cond == 8) {
274430376636SRichard Henderson         save_state(dc);
274530376636SRichard Henderson         gen_helper_raise_exception(tcg_env, trap);
274630376636SRichard Henderson         dc->base.is_jmp = DISAS_NORETURN;
274730376636SRichard Henderson         return true;
274830376636SRichard Henderson     }
274930376636SRichard Henderson 
275030376636SRichard Henderson     /* Conditional trap.  */
275130376636SRichard Henderson     flush_cond(dc);
275230376636SRichard Henderson     lab = delay_exceptionv(dc, trap);
275330376636SRichard Henderson     gen_compare(&cmp, cc, cond, dc);
2754c8507ebfSRichard Henderson     tcg_gen_brcondi_tl(cmp.cond, cmp.c1, cmp.c2, lab);
275530376636SRichard Henderson 
275630376636SRichard Henderson     return advance_pc(dc);
275730376636SRichard Henderson }
275830376636SRichard Henderson 
275930376636SRichard Henderson static bool trans_Tcc_r(DisasContext *dc, arg_Tcc_r *a)
276030376636SRichard Henderson {
276130376636SRichard Henderson     if (avail_32(dc) && a->cc) {
276230376636SRichard Henderson         return false;
276330376636SRichard Henderson     }
276430376636SRichard Henderson     return do_tcc(dc, a->cond, a->cc, a->rs1, false, a->rs2);
276530376636SRichard Henderson }
276630376636SRichard Henderson 
276730376636SRichard Henderson static bool trans_Tcc_i_v7(DisasContext *dc, arg_Tcc_i_v7 *a)
276830376636SRichard Henderson {
276930376636SRichard Henderson     if (avail_64(dc)) {
277030376636SRichard Henderson         return false;
277130376636SRichard Henderson     }
277230376636SRichard Henderson     return do_tcc(dc, a->cond, 0, a->rs1, true, a->i);
277330376636SRichard Henderson }
277430376636SRichard Henderson 
277530376636SRichard Henderson static bool trans_Tcc_i_v9(DisasContext *dc, arg_Tcc_i_v9 *a)
277630376636SRichard Henderson {
277730376636SRichard Henderson     if (avail_32(dc)) {
277830376636SRichard Henderson         return false;
277930376636SRichard Henderson     }
278030376636SRichard Henderson     return do_tcc(dc, a->cond, a->cc, a->rs1, true, a->i);
278130376636SRichard Henderson }
278230376636SRichard Henderson 
2783af25071cSRichard Henderson static bool trans_STBAR(DisasContext *dc, arg_STBAR *a)
2784af25071cSRichard Henderson {
2785af25071cSRichard Henderson     tcg_gen_mb(TCG_MO_ST_ST | TCG_BAR_SC);
2786af25071cSRichard Henderson     return advance_pc(dc);
2787af25071cSRichard Henderson }
2788af25071cSRichard Henderson 
2789af25071cSRichard Henderson static bool trans_MEMBAR(DisasContext *dc, arg_MEMBAR *a)
2790af25071cSRichard Henderson {
2791af25071cSRichard Henderson     if (avail_32(dc)) {
2792af25071cSRichard Henderson         return false;
2793af25071cSRichard Henderson     }
2794af25071cSRichard Henderson     if (a->mmask) {
2795af25071cSRichard Henderson         /* Note TCG_MO_* was modeled on sparc64, so mmask matches. */
2796af25071cSRichard Henderson         tcg_gen_mb(a->mmask | TCG_BAR_SC);
2797af25071cSRichard Henderson     }
2798af25071cSRichard Henderson     if (a->cmask) {
2799af25071cSRichard Henderson         /* For #Sync, etc, end the TB to recognize interrupts. */
2800af25071cSRichard Henderson         dc->base.is_jmp = DISAS_EXIT;
2801af25071cSRichard Henderson     }
2802af25071cSRichard Henderson     return advance_pc(dc);
2803af25071cSRichard Henderson }
2804af25071cSRichard Henderson 
2805af25071cSRichard Henderson static bool do_rd_special(DisasContext *dc, bool priv, int rd,
2806af25071cSRichard Henderson                           TCGv (*func)(DisasContext *, TCGv))
2807af25071cSRichard Henderson {
2808af25071cSRichard Henderson     if (!priv) {
2809af25071cSRichard Henderson         return raise_priv(dc);
2810af25071cSRichard Henderson     }
2811af25071cSRichard Henderson     gen_store_gpr(dc, rd, func(dc, gen_dest_gpr(dc, rd)));
2812af25071cSRichard Henderson     return advance_pc(dc);
2813af25071cSRichard Henderson }
2814af25071cSRichard Henderson 
2815af25071cSRichard Henderson static TCGv do_rdy(DisasContext *dc, TCGv dst)
2816af25071cSRichard Henderson {
2817af25071cSRichard Henderson     return cpu_y;
2818af25071cSRichard Henderson }
2819af25071cSRichard Henderson 
2820af25071cSRichard Henderson static bool trans_RDY(DisasContext *dc, arg_RDY *a)
2821af25071cSRichard Henderson {
2822af25071cSRichard Henderson     /*
2823af25071cSRichard Henderson      * TODO: Need a feature bit for sparcv8.  In the meantime, treat all
2824af25071cSRichard Henderson      * 32-bit cpus like sparcv7, which ignores the rs1 field.
2825af25071cSRichard Henderson      * This matches after all other ASR, so Leon3 Asr17 is handled first.
2826af25071cSRichard Henderson      */
2827af25071cSRichard Henderson     if (avail_64(dc) && a->rs1 != 0) {
2828af25071cSRichard Henderson         return false;
2829af25071cSRichard Henderson     }
2830af25071cSRichard Henderson     return do_rd_special(dc, true, a->rd, do_rdy);
2831af25071cSRichard Henderson }
2832af25071cSRichard Henderson 
2833af25071cSRichard Henderson static TCGv do_rd_leon3_config(DisasContext *dc, TCGv dst)
2834af25071cSRichard Henderson {
2835c92948f2SClément Chigot     gen_helper_rdasr17(dst, tcg_env);
2836c92948f2SClément Chigot     return dst;
2837af25071cSRichard Henderson }
2838af25071cSRichard Henderson 
2839af25071cSRichard Henderson TRANS(RDASR17, ASR17, do_rd_special, true, a->rd, do_rd_leon3_config)
2840af25071cSRichard Henderson 
2841af25071cSRichard Henderson static TCGv do_rdccr(DisasContext *dc, TCGv dst)
2842af25071cSRichard Henderson {
2843af25071cSRichard Henderson     gen_helper_rdccr(dst, tcg_env);
2844af25071cSRichard Henderson     return dst;
2845af25071cSRichard Henderson }
2846af25071cSRichard Henderson 
2847af25071cSRichard Henderson TRANS(RDCCR, 64, do_rd_special, true, a->rd, do_rdccr)
2848af25071cSRichard Henderson 
2849af25071cSRichard Henderson static TCGv do_rdasi(DisasContext *dc, TCGv dst)
2850af25071cSRichard Henderson {
2851af25071cSRichard Henderson #ifdef TARGET_SPARC64
2852af25071cSRichard Henderson     return tcg_constant_tl(dc->asi);
2853af25071cSRichard Henderson #else
2854af25071cSRichard Henderson     qemu_build_not_reached();
2855af25071cSRichard Henderson #endif
2856af25071cSRichard Henderson }
2857af25071cSRichard Henderson 
2858af25071cSRichard Henderson TRANS(RDASI, 64, do_rd_special, true, a->rd, do_rdasi)
2859af25071cSRichard Henderson 
2860af25071cSRichard Henderson static TCGv do_rdtick(DisasContext *dc, TCGv dst)
2861af25071cSRichard Henderson {
2862af25071cSRichard Henderson     TCGv_ptr r_tickptr = tcg_temp_new_ptr();
2863af25071cSRichard Henderson 
2864af25071cSRichard Henderson     tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(tick));
2865af25071cSRichard Henderson     if (translator_io_start(&dc->base)) {
2866af25071cSRichard Henderson         dc->base.is_jmp = DISAS_EXIT;
2867af25071cSRichard Henderson     }
2868af25071cSRichard Henderson     gen_helper_tick_get_count(dst, tcg_env, r_tickptr,
2869af25071cSRichard Henderson                               tcg_constant_i32(dc->mem_idx));
2870af25071cSRichard Henderson     return dst;
2871af25071cSRichard Henderson }
2872af25071cSRichard Henderson 
2873af25071cSRichard Henderson /* TODO: non-priv access only allowed when enabled. */
2874af25071cSRichard Henderson TRANS(RDTICK, 64, do_rd_special, true, a->rd, do_rdtick)
2875af25071cSRichard Henderson 
2876af25071cSRichard Henderson static TCGv do_rdpc(DisasContext *dc, TCGv dst)
2877af25071cSRichard Henderson {
2878af25071cSRichard Henderson     return tcg_constant_tl(address_mask_i(dc, dc->pc));
2879af25071cSRichard Henderson }
2880af25071cSRichard Henderson 
2881af25071cSRichard Henderson TRANS(RDPC, 64, do_rd_special, true, a->rd, do_rdpc)
2882af25071cSRichard Henderson 
2883af25071cSRichard Henderson static TCGv do_rdfprs(DisasContext *dc, TCGv dst)
2884af25071cSRichard Henderson {
2885af25071cSRichard Henderson     tcg_gen_ext_i32_tl(dst, cpu_fprs);
2886af25071cSRichard Henderson     return dst;
2887af25071cSRichard Henderson }
2888af25071cSRichard Henderson 
2889af25071cSRichard Henderson TRANS(RDFPRS, 64, do_rd_special, true, a->rd, do_rdfprs)
2890af25071cSRichard Henderson 
2891af25071cSRichard Henderson static TCGv do_rdgsr(DisasContext *dc, TCGv dst)
2892af25071cSRichard Henderson {
2893af25071cSRichard Henderson     gen_trap_ifnofpu(dc);
2894af25071cSRichard Henderson     return cpu_gsr;
2895af25071cSRichard Henderson }
2896af25071cSRichard Henderson 
2897af25071cSRichard Henderson TRANS(RDGSR, 64, do_rd_special, true, a->rd, do_rdgsr)
2898af25071cSRichard Henderson 
2899af25071cSRichard Henderson static TCGv do_rdsoftint(DisasContext *dc, TCGv dst)
2900af25071cSRichard Henderson {
2901af25071cSRichard Henderson     tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(softint));
2902af25071cSRichard Henderson     return dst;
2903af25071cSRichard Henderson }
2904af25071cSRichard Henderson 
2905af25071cSRichard Henderson TRANS(RDSOFTINT, 64, do_rd_special, supervisor(dc), a->rd, do_rdsoftint)
2906af25071cSRichard Henderson 
2907af25071cSRichard Henderson static TCGv do_rdtick_cmpr(DisasContext *dc, TCGv dst)
2908af25071cSRichard Henderson {
2909577efa45SRichard Henderson     tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(tick_cmpr));
2910577efa45SRichard Henderson     return dst;
2911af25071cSRichard Henderson }
2912af25071cSRichard Henderson 
2913af25071cSRichard Henderson /* TODO: non-priv access only allowed when enabled. */
2914af25071cSRichard Henderson TRANS(RDTICK_CMPR, 64, do_rd_special, true, a->rd, do_rdtick_cmpr)
2915af25071cSRichard Henderson 
2916af25071cSRichard Henderson static TCGv do_rdstick(DisasContext *dc, TCGv dst)
2917af25071cSRichard Henderson {
2918af25071cSRichard Henderson     TCGv_ptr r_tickptr = tcg_temp_new_ptr();
2919af25071cSRichard Henderson 
2920af25071cSRichard Henderson     tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(stick));
2921af25071cSRichard Henderson     if (translator_io_start(&dc->base)) {
2922af25071cSRichard Henderson         dc->base.is_jmp = DISAS_EXIT;
2923af25071cSRichard Henderson     }
2924af25071cSRichard Henderson     gen_helper_tick_get_count(dst, tcg_env, r_tickptr,
2925af25071cSRichard Henderson                               tcg_constant_i32(dc->mem_idx));
2926af25071cSRichard Henderson     return dst;
2927af25071cSRichard Henderson }
2928af25071cSRichard Henderson 
2929af25071cSRichard Henderson /* TODO: non-priv access only allowed when enabled. */
2930af25071cSRichard Henderson TRANS(RDSTICK, 64, do_rd_special, true, a->rd, do_rdstick)
2931af25071cSRichard Henderson 
2932af25071cSRichard Henderson static TCGv do_rdstick_cmpr(DisasContext *dc, TCGv dst)
2933af25071cSRichard Henderson {
2934577efa45SRichard Henderson     tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(stick_cmpr));
2935577efa45SRichard Henderson     return dst;
2936af25071cSRichard Henderson }
2937af25071cSRichard Henderson 
2938af25071cSRichard Henderson /* TODO: supervisor access only allowed when enabled by hypervisor. */
2939af25071cSRichard Henderson TRANS(RDSTICK_CMPR, 64, do_rd_special, supervisor(dc), a->rd, do_rdstick_cmpr)
2940af25071cSRichard Henderson 
2941af25071cSRichard Henderson /*
2942af25071cSRichard Henderson  * UltraSPARC-T1 Strand status.
2943af25071cSRichard Henderson  * HYPV check maybe not enough, UA2005 & UA2007 describe
2944af25071cSRichard Henderson  * this ASR as impl. dep
2945af25071cSRichard Henderson  */
2946af25071cSRichard Henderson static TCGv do_rdstrand_status(DisasContext *dc, TCGv dst)
2947af25071cSRichard Henderson {
2948af25071cSRichard Henderson     return tcg_constant_tl(1);
2949af25071cSRichard Henderson }
2950af25071cSRichard Henderson 
2951af25071cSRichard Henderson TRANS(RDSTRAND_STATUS, HYPV, do_rd_special, true, a->rd, do_rdstrand_status)
2952af25071cSRichard Henderson 
2953668bb9b7SRichard Henderson static TCGv do_rdpsr(DisasContext *dc, TCGv dst)
2954668bb9b7SRichard Henderson {
2955668bb9b7SRichard Henderson     gen_helper_rdpsr(dst, tcg_env);
2956668bb9b7SRichard Henderson     return dst;
2957668bb9b7SRichard Henderson }
2958668bb9b7SRichard Henderson 
2959668bb9b7SRichard Henderson TRANS(RDPSR, 32, do_rd_special, supervisor(dc), a->rd, do_rdpsr)
2960668bb9b7SRichard Henderson 
2961668bb9b7SRichard Henderson static TCGv do_rdhpstate(DisasContext *dc, TCGv dst)
2962668bb9b7SRichard Henderson {
2963668bb9b7SRichard Henderson     tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hpstate));
2964668bb9b7SRichard Henderson     return dst;
2965668bb9b7SRichard Henderson }
2966668bb9b7SRichard Henderson 
2967668bb9b7SRichard Henderson TRANS(RDHPR_hpstate, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhpstate)
2968668bb9b7SRichard Henderson 
2969668bb9b7SRichard Henderson static TCGv do_rdhtstate(DisasContext *dc, TCGv dst)
2970668bb9b7SRichard Henderson {
2971668bb9b7SRichard Henderson     TCGv_i32 tl = tcg_temp_new_i32();
2972668bb9b7SRichard Henderson     TCGv_ptr tp = tcg_temp_new_ptr();
2973668bb9b7SRichard Henderson 
2974668bb9b7SRichard Henderson     tcg_gen_ld_i32(tl, tcg_env, env64_field_offsetof(tl));
2975668bb9b7SRichard Henderson     tcg_gen_andi_i32(tl, tl, MAXTL_MASK);
2976668bb9b7SRichard Henderson     tcg_gen_shli_i32(tl, tl, 3);
2977668bb9b7SRichard Henderson     tcg_gen_ext_i32_ptr(tp, tl);
2978668bb9b7SRichard Henderson     tcg_gen_add_ptr(tp, tp, tcg_env);
2979668bb9b7SRichard Henderson 
2980668bb9b7SRichard Henderson     tcg_gen_ld_tl(dst, tp, env64_field_offsetof(htstate));
2981668bb9b7SRichard Henderson     return dst;
2982668bb9b7SRichard Henderson }
2983668bb9b7SRichard Henderson 
2984668bb9b7SRichard Henderson TRANS(RDHPR_htstate, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhtstate)
2985668bb9b7SRichard Henderson 
2986668bb9b7SRichard Henderson static TCGv do_rdhintp(DisasContext *dc, TCGv dst)
2987668bb9b7SRichard Henderson {
29882da789deSRichard Henderson     tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hintp));
29892da789deSRichard Henderson     return dst;
2990668bb9b7SRichard Henderson }
2991668bb9b7SRichard Henderson 
2992668bb9b7SRichard Henderson TRANS(RDHPR_hintp, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhintp)
2993668bb9b7SRichard Henderson 
2994668bb9b7SRichard Henderson static TCGv do_rdhtba(DisasContext *dc, TCGv dst)
2995668bb9b7SRichard Henderson {
29962da789deSRichard Henderson     tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(htba));
29972da789deSRichard Henderson     return dst;
2998668bb9b7SRichard Henderson }
2999668bb9b7SRichard Henderson 
3000668bb9b7SRichard Henderson TRANS(RDHPR_htba, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhtba)
3001668bb9b7SRichard Henderson 
3002668bb9b7SRichard Henderson static TCGv do_rdhver(DisasContext *dc, TCGv dst)
3003668bb9b7SRichard Henderson {
30042da789deSRichard Henderson     tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hver));
30052da789deSRichard Henderson     return dst;
3006668bb9b7SRichard Henderson }
3007668bb9b7SRichard Henderson 
3008668bb9b7SRichard Henderson TRANS(RDHPR_hver, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhver)
3009668bb9b7SRichard Henderson 
3010668bb9b7SRichard Henderson static TCGv do_rdhstick_cmpr(DisasContext *dc, TCGv dst)
3011668bb9b7SRichard Henderson {
3012577efa45SRichard Henderson     tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hstick_cmpr));
3013577efa45SRichard Henderson     return dst;
3014668bb9b7SRichard Henderson }
3015668bb9b7SRichard Henderson 
3016668bb9b7SRichard Henderson TRANS(RDHPR_hstick_cmpr, HYPV, do_rd_special, hypervisor(dc), a->rd,
3017668bb9b7SRichard Henderson       do_rdhstick_cmpr)
3018668bb9b7SRichard Henderson 
30195d617bfbSRichard Henderson static TCGv do_rdwim(DisasContext *dc, TCGv dst)
30205d617bfbSRichard Henderson {
3021cd6269f7SRichard Henderson     tcg_gen_ld_tl(dst, tcg_env, env32_field_offsetof(wim));
3022cd6269f7SRichard Henderson     return dst;
30235d617bfbSRichard Henderson }
30245d617bfbSRichard Henderson 
30255d617bfbSRichard Henderson TRANS(RDWIM, 32, do_rd_special, supervisor(dc), a->rd, do_rdwim)
30265d617bfbSRichard Henderson 
30275d617bfbSRichard Henderson static TCGv do_rdtpc(DisasContext *dc, TCGv dst)
30285d617bfbSRichard Henderson {
30295d617bfbSRichard Henderson #ifdef TARGET_SPARC64
30305d617bfbSRichard Henderson     TCGv_ptr r_tsptr = tcg_temp_new_ptr();
30315d617bfbSRichard Henderson 
30325d617bfbSRichard Henderson     gen_load_trap_state_at_tl(r_tsptr);
30335d617bfbSRichard Henderson     tcg_gen_ld_tl(dst, r_tsptr, offsetof(trap_state, tpc));
30345d617bfbSRichard Henderson     return dst;
30355d617bfbSRichard Henderson #else
30365d617bfbSRichard Henderson     qemu_build_not_reached();
30375d617bfbSRichard Henderson #endif
30385d617bfbSRichard Henderson }
30395d617bfbSRichard Henderson 
30405d617bfbSRichard Henderson TRANS(RDPR_tpc, 64, do_rd_special, supervisor(dc), a->rd, do_rdtpc)
30415d617bfbSRichard Henderson 
30425d617bfbSRichard Henderson static TCGv do_rdtnpc(DisasContext *dc, TCGv dst)
30435d617bfbSRichard Henderson {
30445d617bfbSRichard Henderson #ifdef TARGET_SPARC64
30455d617bfbSRichard Henderson     TCGv_ptr r_tsptr = tcg_temp_new_ptr();
30465d617bfbSRichard Henderson 
30475d617bfbSRichard Henderson     gen_load_trap_state_at_tl(r_tsptr);
30485d617bfbSRichard Henderson     tcg_gen_ld_tl(dst, r_tsptr, offsetof(trap_state, tnpc));
30495d617bfbSRichard Henderson     return dst;
30505d617bfbSRichard Henderson #else
30515d617bfbSRichard Henderson     qemu_build_not_reached();
30525d617bfbSRichard Henderson #endif
30535d617bfbSRichard Henderson }
30545d617bfbSRichard Henderson 
30555d617bfbSRichard Henderson TRANS(RDPR_tnpc, 64, do_rd_special, supervisor(dc), a->rd, do_rdtnpc)
30565d617bfbSRichard Henderson 
30575d617bfbSRichard Henderson static TCGv do_rdtstate(DisasContext *dc, TCGv dst)
30585d617bfbSRichard Henderson {
30595d617bfbSRichard Henderson #ifdef TARGET_SPARC64
30605d617bfbSRichard Henderson     TCGv_ptr r_tsptr = tcg_temp_new_ptr();
30615d617bfbSRichard Henderson 
30625d617bfbSRichard Henderson     gen_load_trap_state_at_tl(r_tsptr);
30635d617bfbSRichard Henderson     tcg_gen_ld_tl(dst, r_tsptr, offsetof(trap_state, tstate));
30645d617bfbSRichard Henderson     return dst;
30655d617bfbSRichard Henderson #else
30665d617bfbSRichard Henderson     qemu_build_not_reached();
30675d617bfbSRichard Henderson #endif
30685d617bfbSRichard Henderson }
30695d617bfbSRichard Henderson 
30705d617bfbSRichard Henderson TRANS(RDPR_tstate, 64, do_rd_special, supervisor(dc), a->rd, do_rdtstate)
30715d617bfbSRichard Henderson 
30725d617bfbSRichard Henderson static TCGv do_rdtt(DisasContext *dc, TCGv dst)
30735d617bfbSRichard Henderson {
30745d617bfbSRichard Henderson #ifdef TARGET_SPARC64
30755d617bfbSRichard Henderson     TCGv_ptr r_tsptr = tcg_temp_new_ptr();
30765d617bfbSRichard Henderson 
30775d617bfbSRichard Henderson     gen_load_trap_state_at_tl(r_tsptr);
30785d617bfbSRichard Henderson     tcg_gen_ld32s_tl(dst, r_tsptr, offsetof(trap_state, tt));
30795d617bfbSRichard Henderson     return dst;
30805d617bfbSRichard Henderson #else
30815d617bfbSRichard Henderson     qemu_build_not_reached();
30825d617bfbSRichard Henderson #endif
30835d617bfbSRichard Henderson }
30845d617bfbSRichard Henderson 
30855d617bfbSRichard Henderson TRANS(RDPR_tt, 64, do_rd_special, supervisor(dc), a->rd, do_rdtt)
30865d617bfbSRichard Henderson TRANS(RDPR_tick, 64, do_rd_special, supervisor(dc), a->rd, do_rdtick)
30875d617bfbSRichard Henderson 
30885d617bfbSRichard Henderson static TCGv do_rdtba(DisasContext *dc, TCGv dst)
30895d617bfbSRichard Henderson {
30905d617bfbSRichard Henderson     return cpu_tbr;
30915d617bfbSRichard Henderson }
30925d617bfbSRichard Henderson 
3093e8325dc0SRichard Henderson TRANS(RDTBR, 32, do_rd_special, supervisor(dc), a->rd, do_rdtba)
30945d617bfbSRichard Henderson TRANS(RDPR_tba, 64, do_rd_special, supervisor(dc), a->rd, do_rdtba)
30955d617bfbSRichard Henderson 
30965d617bfbSRichard Henderson static TCGv do_rdpstate(DisasContext *dc, TCGv dst)
30975d617bfbSRichard Henderson {
30985d617bfbSRichard Henderson     tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(pstate));
30995d617bfbSRichard Henderson     return dst;
31005d617bfbSRichard Henderson }
31015d617bfbSRichard Henderson 
31025d617bfbSRichard Henderson TRANS(RDPR_pstate, 64, do_rd_special, supervisor(dc), a->rd, do_rdpstate)
31035d617bfbSRichard Henderson 
31045d617bfbSRichard Henderson static TCGv do_rdtl(DisasContext *dc, TCGv dst)
31055d617bfbSRichard Henderson {
31065d617bfbSRichard Henderson     tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(tl));
31075d617bfbSRichard Henderson     return dst;
31085d617bfbSRichard Henderson }
31095d617bfbSRichard Henderson 
31105d617bfbSRichard Henderson TRANS(RDPR_tl, 64, do_rd_special, supervisor(dc), a->rd, do_rdtl)
31115d617bfbSRichard Henderson 
31125d617bfbSRichard Henderson static TCGv do_rdpil(DisasContext *dc, TCGv dst)
31135d617bfbSRichard Henderson {
31145d617bfbSRichard Henderson     tcg_gen_ld32s_tl(dst, tcg_env, env_field_offsetof(psrpil));
31155d617bfbSRichard Henderson     return dst;
31165d617bfbSRichard Henderson }
31175d617bfbSRichard Henderson 
31185d617bfbSRichard Henderson TRANS(RDPR_pil, 64, do_rd_special, supervisor(dc), a->rd, do_rdpil)
31195d617bfbSRichard Henderson 
31205d617bfbSRichard Henderson static TCGv do_rdcwp(DisasContext *dc, TCGv dst)
31215d617bfbSRichard Henderson {
31225d617bfbSRichard Henderson     gen_helper_rdcwp(dst, tcg_env);
31235d617bfbSRichard Henderson     return dst;
31245d617bfbSRichard Henderson }
31255d617bfbSRichard Henderson 
31265d617bfbSRichard Henderson TRANS(RDPR_cwp, 64, do_rd_special, supervisor(dc), a->rd, do_rdcwp)
31275d617bfbSRichard Henderson 
31285d617bfbSRichard Henderson static TCGv do_rdcansave(DisasContext *dc, TCGv dst)
31295d617bfbSRichard Henderson {
31305d617bfbSRichard Henderson     tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(cansave));
31315d617bfbSRichard Henderson     return dst;
31325d617bfbSRichard Henderson }
31335d617bfbSRichard Henderson 
31345d617bfbSRichard Henderson TRANS(RDPR_cansave, 64, do_rd_special, supervisor(dc), a->rd, do_rdcansave)
31355d617bfbSRichard Henderson 
31365d617bfbSRichard Henderson static TCGv do_rdcanrestore(DisasContext *dc, TCGv dst)
31375d617bfbSRichard Henderson {
31385d617bfbSRichard Henderson     tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(canrestore));
31395d617bfbSRichard Henderson     return dst;
31405d617bfbSRichard Henderson }
31415d617bfbSRichard Henderson 
31425d617bfbSRichard Henderson TRANS(RDPR_canrestore, 64, do_rd_special, supervisor(dc), a->rd,
31435d617bfbSRichard Henderson       do_rdcanrestore)
31445d617bfbSRichard Henderson 
31455d617bfbSRichard Henderson static TCGv do_rdcleanwin(DisasContext *dc, TCGv dst)
31465d617bfbSRichard Henderson {
31475d617bfbSRichard Henderson     tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(cleanwin));
31485d617bfbSRichard Henderson     return dst;
31495d617bfbSRichard Henderson }
31505d617bfbSRichard Henderson 
31515d617bfbSRichard Henderson TRANS(RDPR_cleanwin, 64, do_rd_special, supervisor(dc), a->rd, do_rdcleanwin)
31525d617bfbSRichard Henderson 
31535d617bfbSRichard Henderson static TCGv do_rdotherwin(DisasContext *dc, TCGv dst)
31545d617bfbSRichard Henderson {
31555d617bfbSRichard Henderson     tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(otherwin));
31565d617bfbSRichard Henderson     return dst;
31575d617bfbSRichard Henderson }
31585d617bfbSRichard Henderson 
31595d617bfbSRichard Henderson TRANS(RDPR_otherwin, 64, do_rd_special, supervisor(dc), a->rd, do_rdotherwin)
31605d617bfbSRichard Henderson 
31615d617bfbSRichard Henderson static TCGv do_rdwstate(DisasContext *dc, TCGv dst)
31625d617bfbSRichard Henderson {
31635d617bfbSRichard Henderson     tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(wstate));
31645d617bfbSRichard Henderson     return dst;
31655d617bfbSRichard Henderson }
31665d617bfbSRichard Henderson 
31675d617bfbSRichard Henderson TRANS(RDPR_wstate, 64, do_rd_special, supervisor(dc), a->rd, do_rdwstate)
31685d617bfbSRichard Henderson 
31695d617bfbSRichard Henderson static TCGv do_rdgl(DisasContext *dc, TCGv dst)
31705d617bfbSRichard Henderson {
31715d617bfbSRichard Henderson     tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(gl));
31725d617bfbSRichard Henderson     return dst;
31735d617bfbSRichard Henderson }
31745d617bfbSRichard Henderson 
31755d617bfbSRichard Henderson TRANS(RDPR_gl, GL, do_rd_special, supervisor(dc), a->rd, do_rdgl)
31765d617bfbSRichard Henderson 
31775d617bfbSRichard Henderson /* UA2005 strand status */
31785d617bfbSRichard Henderson static TCGv do_rdssr(DisasContext *dc, TCGv dst)
31795d617bfbSRichard Henderson {
31802da789deSRichard Henderson     tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(ssr));
31812da789deSRichard Henderson     return dst;
31825d617bfbSRichard Henderson }
31835d617bfbSRichard Henderson 
31845d617bfbSRichard Henderson TRANS(RDPR_strand_status, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdssr)
31855d617bfbSRichard Henderson 
31865d617bfbSRichard Henderson static TCGv do_rdver(DisasContext *dc, TCGv dst)
31875d617bfbSRichard Henderson {
31882da789deSRichard Henderson     tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(version));
31892da789deSRichard Henderson     return dst;
31905d617bfbSRichard Henderson }
31915d617bfbSRichard Henderson 
31925d617bfbSRichard Henderson TRANS(RDPR_ver, 64, do_rd_special, supervisor(dc), a->rd, do_rdver)
31935d617bfbSRichard Henderson 
3194e8325dc0SRichard Henderson static bool trans_FLUSHW(DisasContext *dc, arg_FLUSHW *a)
3195e8325dc0SRichard Henderson {
3196e8325dc0SRichard Henderson     if (avail_64(dc)) {
3197e8325dc0SRichard Henderson         gen_helper_flushw(tcg_env);
3198e8325dc0SRichard Henderson         return advance_pc(dc);
3199e8325dc0SRichard Henderson     }
3200e8325dc0SRichard Henderson     return false;
3201e8325dc0SRichard Henderson }
3202e8325dc0SRichard Henderson 
32030faef01bSRichard Henderson static bool do_wr_special(DisasContext *dc, arg_r_r_ri *a, bool priv,
32040faef01bSRichard Henderson                           void (*func)(DisasContext *, TCGv))
32050faef01bSRichard Henderson {
32060faef01bSRichard Henderson     TCGv src;
32070faef01bSRichard Henderson 
32080faef01bSRichard Henderson     /* For simplicity, we under-decoded the rs2 form. */
32090faef01bSRichard Henderson     if (!a->imm && (a->rs2_or_imm & ~0x1f)) {
32100faef01bSRichard Henderson         return false;
32110faef01bSRichard Henderson     }
32120faef01bSRichard Henderson     if (!priv) {
32130faef01bSRichard Henderson         return raise_priv(dc);
32140faef01bSRichard Henderson     }
32150faef01bSRichard Henderson 
32160faef01bSRichard Henderson     if (a->rs1 == 0 && (a->imm || a->rs2_or_imm == 0)) {
32170faef01bSRichard Henderson         src = tcg_constant_tl(a->rs2_or_imm);
32180faef01bSRichard Henderson     } else {
32190faef01bSRichard Henderson         TCGv src1 = gen_load_gpr(dc, a->rs1);
32200faef01bSRichard Henderson         if (a->rs2_or_imm == 0) {
32210faef01bSRichard Henderson             src = src1;
32220faef01bSRichard Henderson         } else {
32230faef01bSRichard Henderson             src = tcg_temp_new();
32240faef01bSRichard Henderson             if (a->imm) {
32250faef01bSRichard Henderson                 tcg_gen_xori_tl(src, src1, a->rs2_or_imm);
32260faef01bSRichard Henderson             } else {
32270faef01bSRichard Henderson                 tcg_gen_xor_tl(src, src1, gen_load_gpr(dc, a->rs2_or_imm));
32280faef01bSRichard Henderson             }
32290faef01bSRichard Henderson         }
32300faef01bSRichard Henderson     }
32310faef01bSRichard Henderson     func(dc, src);
32320faef01bSRichard Henderson     return advance_pc(dc);
32330faef01bSRichard Henderson }
32340faef01bSRichard Henderson 
32350faef01bSRichard Henderson static void do_wry(DisasContext *dc, TCGv src)
32360faef01bSRichard Henderson {
32370faef01bSRichard Henderson     tcg_gen_ext32u_tl(cpu_y, src);
32380faef01bSRichard Henderson }
32390faef01bSRichard Henderson 
32400faef01bSRichard Henderson TRANS(WRY, ALL, do_wr_special, a, true, do_wry)
32410faef01bSRichard Henderson 
32420faef01bSRichard Henderson static void do_wrccr(DisasContext *dc, TCGv src)
32430faef01bSRichard Henderson {
32440faef01bSRichard Henderson     gen_helper_wrccr(tcg_env, src);
32450faef01bSRichard Henderson }
32460faef01bSRichard Henderson 
32470faef01bSRichard Henderson TRANS(WRCCR, 64, do_wr_special, a, true, do_wrccr)
32480faef01bSRichard Henderson 
32490faef01bSRichard Henderson static void do_wrasi(DisasContext *dc, TCGv src)
32500faef01bSRichard Henderson {
32510faef01bSRichard Henderson     TCGv tmp = tcg_temp_new();
32520faef01bSRichard Henderson 
32530faef01bSRichard Henderson     tcg_gen_ext8u_tl(tmp, src);
32540faef01bSRichard Henderson     tcg_gen_st32_tl(tmp, tcg_env, env64_field_offsetof(asi));
32550faef01bSRichard Henderson     /* End TB to notice changed ASI. */
32560faef01bSRichard Henderson     dc->base.is_jmp = DISAS_EXIT;
32570faef01bSRichard Henderson }
32580faef01bSRichard Henderson 
32590faef01bSRichard Henderson TRANS(WRASI, 64, do_wr_special, a, true, do_wrasi)
32600faef01bSRichard Henderson 
32610faef01bSRichard Henderson static void do_wrfprs(DisasContext *dc, TCGv src)
32620faef01bSRichard Henderson {
32630faef01bSRichard Henderson #ifdef TARGET_SPARC64
32640faef01bSRichard Henderson     tcg_gen_trunc_tl_i32(cpu_fprs, src);
32650faef01bSRichard Henderson     dc->fprs_dirty = 0;
32660faef01bSRichard Henderson     dc->base.is_jmp = DISAS_EXIT;
32670faef01bSRichard Henderson #else
32680faef01bSRichard Henderson     qemu_build_not_reached();
32690faef01bSRichard Henderson #endif
32700faef01bSRichard Henderson }
32710faef01bSRichard Henderson 
32720faef01bSRichard Henderson TRANS(WRFPRS, 64, do_wr_special, a, true, do_wrfprs)
32730faef01bSRichard Henderson 
32740faef01bSRichard Henderson static void do_wrgsr(DisasContext *dc, TCGv src)
32750faef01bSRichard Henderson {
32760faef01bSRichard Henderson     gen_trap_ifnofpu(dc);
32770faef01bSRichard Henderson     tcg_gen_mov_tl(cpu_gsr, src);
32780faef01bSRichard Henderson }
32790faef01bSRichard Henderson 
32800faef01bSRichard Henderson TRANS(WRGSR, 64, do_wr_special, a, true, do_wrgsr)
32810faef01bSRichard Henderson 
32820faef01bSRichard Henderson static void do_wrsoftint_set(DisasContext *dc, TCGv src)
32830faef01bSRichard Henderson {
32840faef01bSRichard Henderson     gen_helper_set_softint(tcg_env, src);
32850faef01bSRichard Henderson }
32860faef01bSRichard Henderson 
32870faef01bSRichard Henderson TRANS(WRSOFTINT_SET, 64, do_wr_special, a, supervisor(dc), do_wrsoftint_set)
32880faef01bSRichard Henderson 
32890faef01bSRichard Henderson static void do_wrsoftint_clr(DisasContext *dc, TCGv src)
32900faef01bSRichard Henderson {
32910faef01bSRichard Henderson     gen_helper_clear_softint(tcg_env, src);
32920faef01bSRichard Henderson }
32930faef01bSRichard Henderson 
32940faef01bSRichard Henderson TRANS(WRSOFTINT_CLR, 64, do_wr_special, a, supervisor(dc), do_wrsoftint_clr)
32950faef01bSRichard Henderson 
32960faef01bSRichard Henderson static void do_wrsoftint(DisasContext *dc, TCGv src)
32970faef01bSRichard Henderson {
32980faef01bSRichard Henderson     gen_helper_write_softint(tcg_env, src);
32990faef01bSRichard Henderson }
33000faef01bSRichard Henderson 
33010faef01bSRichard Henderson TRANS(WRSOFTINT, 64, do_wr_special, a, supervisor(dc), do_wrsoftint)
33020faef01bSRichard Henderson 
33030faef01bSRichard Henderson static void do_wrtick_cmpr(DisasContext *dc, TCGv src)
33040faef01bSRichard Henderson {
33050faef01bSRichard Henderson     TCGv_ptr r_tickptr = tcg_temp_new_ptr();
33060faef01bSRichard Henderson 
3307577efa45SRichard Henderson     tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(tick_cmpr));
3308577efa45SRichard Henderson     tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(tick));
33090faef01bSRichard Henderson     translator_io_start(&dc->base);
3310577efa45SRichard Henderson     gen_helper_tick_set_limit(r_tickptr, src);
33110faef01bSRichard Henderson     /* End TB to handle timer interrupt */
33120faef01bSRichard Henderson     dc->base.is_jmp = DISAS_EXIT;
33130faef01bSRichard Henderson }
33140faef01bSRichard Henderson 
33150faef01bSRichard Henderson TRANS(WRTICK_CMPR, 64, do_wr_special, a, supervisor(dc), do_wrtick_cmpr)
33160faef01bSRichard Henderson 
33170faef01bSRichard Henderson static void do_wrstick(DisasContext *dc, TCGv src)
33180faef01bSRichard Henderson {
33190faef01bSRichard Henderson #ifdef TARGET_SPARC64
33200faef01bSRichard Henderson     TCGv_ptr r_tickptr = tcg_temp_new_ptr();
33210faef01bSRichard Henderson 
33220faef01bSRichard Henderson     tcg_gen_ld_ptr(r_tickptr, tcg_env, offsetof(CPUSPARCState, stick));
33230faef01bSRichard Henderson     translator_io_start(&dc->base);
33240faef01bSRichard Henderson     gen_helper_tick_set_count(r_tickptr, src);
33250faef01bSRichard Henderson     /* End TB to handle timer interrupt */
33260faef01bSRichard Henderson     dc->base.is_jmp = DISAS_EXIT;
33270faef01bSRichard Henderson #else
33280faef01bSRichard Henderson     qemu_build_not_reached();
33290faef01bSRichard Henderson #endif
33300faef01bSRichard Henderson }
33310faef01bSRichard Henderson 
33320faef01bSRichard Henderson TRANS(WRSTICK, 64, do_wr_special, a, supervisor(dc), do_wrstick)
33330faef01bSRichard Henderson 
33340faef01bSRichard Henderson static void do_wrstick_cmpr(DisasContext *dc, TCGv src)
33350faef01bSRichard Henderson {
33360faef01bSRichard Henderson     TCGv_ptr r_tickptr = tcg_temp_new_ptr();
33370faef01bSRichard Henderson 
3338577efa45SRichard Henderson     tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(stick_cmpr));
3339577efa45SRichard Henderson     tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(stick));
33400faef01bSRichard Henderson     translator_io_start(&dc->base);
3341577efa45SRichard Henderson     gen_helper_tick_set_limit(r_tickptr, src);
33420faef01bSRichard Henderson     /* End TB to handle timer interrupt */
33430faef01bSRichard Henderson     dc->base.is_jmp = DISAS_EXIT;
33440faef01bSRichard Henderson }
33450faef01bSRichard Henderson 
33460faef01bSRichard Henderson TRANS(WRSTICK_CMPR, 64, do_wr_special, a, supervisor(dc), do_wrstick_cmpr)
33470faef01bSRichard Henderson 
33480faef01bSRichard Henderson static void do_wrpowerdown(DisasContext *dc, TCGv src)
33490faef01bSRichard Henderson {
335089527e3aSRichard Henderson     finishing_insn(dc);
33510faef01bSRichard Henderson     save_state(dc);
33520faef01bSRichard Henderson     gen_helper_power_down(tcg_env);
33530faef01bSRichard Henderson }
33540faef01bSRichard Henderson 
33550faef01bSRichard Henderson TRANS(WRPOWERDOWN, POWERDOWN, do_wr_special, a, supervisor(dc), do_wrpowerdown)
33560faef01bSRichard Henderson 
33576fbc032cSRichard Henderson static void do_wrmwait(DisasContext *dc, TCGv src)
33586fbc032cSRichard Henderson {
33596fbc032cSRichard Henderson     /*
33606fbc032cSRichard Henderson      * TODO: This is a stub version of mwait, which merely recognizes
33616fbc032cSRichard Henderson      * interrupts immediately and does not wait.
33626fbc032cSRichard Henderson      */
33636fbc032cSRichard Henderson     dc->base.is_jmp = DISAS_EXIT;
33646fbc032cSRichard Henderson }
33656fbc032cSRichard Henderson 
33666fbc032cSRichard Henderson TRANS(WRMWAIT, VIS4, do_wr_special, a, true, do_wrmwait)
33676fbc032cSRichard Henderson 
336825524734SRichard Henderson static void do_wrpsr(DisasContext *dc, TCGv src)
336925524734SRichard Henderson {
337025524734SRichard Henderson     gen_helper_wrpsr(tcg_env, src);
337125524734SRichard Henderson     dc->base.is_jmp = DISAS_EXIT;
337225524734SRichard Henderson }
337325524734SRichard Henderson 
337425524734SRichard Henderson TRANS(WRPSR, 32, do_wr_special, a, supervisor(dc), do_wrpsr)
337525524734SRichard Henderson 
33769422278eSRichard Henderson static void do_wrwim(DisasContext *dc, TCGv src)
33779422278eSRichard Henderson {
33789422278eSRichard Henderson     target_ulong mask = MAKE_64BIT_MASK(0, dc->def->nwindows);
3379cd6269f7SRichard Henderson     TCGv tmp = tcg_temp_new();
3380cd6269f7SRichard Henderson 
3381cd6269f7SRichard Henderson     tcg_gen_andi_tl(tmp, src, mask);
3382cd6269f7SRichard Henderson     tcg_gen_st_tl(tmp, tcg_env, env32_field_offsetof(wim));
33839422278eSRichard Henderson }
33849422278eSRichard Henderson 
33859422278eSRichard Henderson TRANS(WRWIM, 32, do_wr_special, a, supervisor(dc), do_wrwim)
33869422278eSRichard Henderson 
33879422278eSRichard Henderson static void do_wrtpc(DisasContext *dc, TCGv src)
33889422278eSRichard Henderson {
33899422278eSRichard Henderson #ifdef TARGET_SPARC64
33909422278eSRichard Henderson     TCGv_ptr r_tsptr = tcg_temp_new_ptr();
33919422278eSRichard Henderson 
33929422278eSRichard Henderson     gen_load_trap_state_at_tl(r_tsptr);
33939422278eSRichard Henderson     tcg_gen_st_tl(src, r_tsptr, offsetof(trap_state, tpc));
33949422278eSRichard Henderson #else
33959422278eSRichard Henderson     qemu_build_not_reached();
33969422278eSRichard Henderson #endif
33979422278eSRichard Henderson }
33989422278eSRichard Henderson 
33999422278eSRichard Henderson TRANS(WRPR_tpc, 64, do_wr_special, a, supervisor(dc), do_wrtpc)
34009422278eSRichard Henderson 
34019422278eSRichard Henderson static void do_wrtnpc(DisasContext *dc, TCGv src)
34029422278eSRichard Henderson {
34039422278eSRichard Henderson #ifdef TARGET_SPARC64
34049422278eSRichard Henderson     TCGv_ptr r_tsptr = tcg_temp_new_ptr();
34059422278eSRichard Henderson 
34069422278eSRichard Henderson     gen_load_trap_state_at_tl(r_tsptr);
34079422278eSRichard Henderson     tcg_gen_st_tl(src, r_tsptr, offsetof(trap_state, tnpc));
34089422278eSRichard Henderson #else
34099422278eSRichard Henderson     qemu_build_not_reached();
34109422278eSRichard Henderson #endif
34119422278eSRichard Henderson }
34129422278eSRichard Henderson 
34139422278eSRichard Henderson TRANS(WRPR_tnpc, 64, do_wr_special, a, supervisor(dc), do_wrtnpc)
34149422278eSRichard Henderson 
34159422278eSRichard Henderson static void do_wrtstate(DisasContext *dc, TCGv src)
34169422278eSRichard Henderson {
34179422278eSRichard Henderson #ifdef TARGET_SPARC64
34189422278eSRichard Henderson     TCGv_ptr r_tsptr = tcg_temp_new_ptr();
34199422278eSRichard Henderson 
34209422278eSRichard Henderson     gen_load_trap_state_at_tl(r_tsptr);
34219422278eSRichard Henderson     tcg_gen_st_tl(src, r_tsptr, offsetof(trap_state, tstate));
34229422278eSRichard Henderson #else
34239422278eSRichard Henderson     qemu_build_not_reached();
34249422278eSRichard Henderson #endif
34259422278eSRichard Henderson }
34269422278eSRichard Henderson 
34279422278eSRichard Henderson TRANS(WRPR_tstate, 64, do_wr_special, a, supervisor(dc), do_wrtstate)
34289422278eSRichard Henderson 
34299422278eSRichard Henderson static void do_wrtt(DisasContext *dc, TCGv src)
34309422278eSRichard Henderson {
34319422278eSRichard Henderson #ifdef TARGET_SPARC64
34329422278eSRichard Henderson     TCGv_ptr r_tsptr = tcg_temp_new_ptr();
34339422278eSRichard Henderson 
34349422278eSRichard Henderson     gen_load_trap_state_at_tl(r_tsptr);
34359422278eSRichard Henderson     tcg_gen_st32_tl(src, r_tsptr, offsetof(trap_state, tt));
34369422278eSRichard Henderson #else
34379422278eSRichard Henderson     qemu_build_not_reached();
34389422278eSRichard Henderson #endif
34399422278eSRichard Henderson }
34409422278eSRichard Henderson 
34419422278eSRichard Henderson TRANS(WRPR_tt, 64, do_wr_special, a, supervisor(dc), do_wrtt)
34429422278eSRichard Henderson 
34439422278eSRichard Henderson static void do_wrtick(DisasContext *dc, TCGv src)
34449422278eSRichard Henderson {
34459422278eSRichard Henderson     TCGv_ptr r_tickptr = tcg_temp_new_ptr();
34469422278eSRichard Henderson 
34479422278eSRichard Henderson     tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(tick));
34489422278eSRichard Henderson     translator_io_start(&dc->base);
34499422278eSRichard Henderson     gen_helper_tick_set_count(r_tickptr, src);
34509422278eSRichard Henderson     /* End TB to handle timer interrupt */
34519422278eSRichard Henderson     dc->base.is_jmp = DISAS_EXIT;
34529422278eSRichard Henderson }
34539422278eSRichard Henderson 
34549422278eSRichard Henderson TRANS(WRPR_tick, 64, do_wr_special, a, supervisor(dc), do_wrtick)
34559422278eSRichard Henderson 
34569422278eSRichard Henderson static void do_wrtba(DisasContext *dc, TCGv src)
34579422278eSRichard Henderson {
34589422278eSRichard Henderson     tcg_gen_mov_tl(cpu_tbr, src);
34599422278eSRichard Henderson }
34609422278eSRichard Henderson 
34619422278eSRichard Henderson TRANS(WRPR_tba, 64, do_wr_special, a, supervisor(dc), do_wrtba)
34629422278eSRichard Henderson 
34639422278eSRichard Henderson static void do_wrpstate(DisasContext *dc, TCGv src)
34649422278eSRichard Henderson {
34659422278eSRichard Henderson     save_state(dc);
34669422278eSRichard Henderson     if (translator_io_start(&dc->base)) {
34679422278eSRichard Henderson         dc->base.is_jmp = DISAS_EXIT;
34689422278eSRichard Henderson     }
34699422278eSRichard Henderson     gen_helper_wrpstate(tcg_env, src);
34709422278eSRichard Henderson     dc->npc = DYNAMIC_PC;
34719422278eSRichard Henderson }
34729422278eSRichard Henderson 
34739422278eSRichard Henderson TRANS(WRPR_pstate, 64, do_wr_special, a, supervisor(dc), do_wrpstate)
34749422278eSRichard Henderson 
34759422278eSRichard Henderson static void do_wrtl(DisasContext *dc, TCGv src)
34769422278eSRichard Henderson {
34779422278eSRichard Henderson     save_state(dc);
34789422278eSRichard Henderson     tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(tl));
34799422278eSRichard Henderson     dc->npc = DYNAMIC_PC;
34809422278eSRichard Henderson }
34819422278eSRichard Henderson 
34829422278eSRichard Henderson TRANS(WRPR_tl, 64, do_wr_special, a, supervisor(dc), do_wrtl)
34839422278eSRichard Henderson 
34849422278eSRichard Henderson static void do_wrpil(DisasContext *dc, TCGv src)
34859422278eSRichard Henderson {
34869422278eSRichard Henderson     if (translator_io_start(&dc->base)) {
34879422278eSRichard Henderson         dc->base.is_jmp = DISAS_EXIT;
34889422278eSRichard Henderson     }
34899422278eSRichard Henderson     gen_helper_wrpil(tcg_env, src);
34909422278eSRichard Henderson }
34919422278eSRichard Henderson 
34929422278eSRichard Henderson TRANS(WRPR_pil, 64, do_wr_special, a, supervisor(dc), do_wrpil)
34939422278eSRichard Henderson 
34949422278eSRichard Henderson static void do_wrcwp(DisasContext *dc, TCGv src)
34959422278eSRichard Henderson {
34969422278eSRichard Henderson     gen_helper_wrcwp(tcg_env, src);
34979422278eSRichard Henderson }
34989422278eSRichard Henderson 
34999422278eSRichard Henderson TRANS(WRPR_cwp, 64, do_wr_special, a, supervisor(dc), do_wrcwp)
35009422278eSRichard Henderson 
35019422278eSRichard Henderson static void do_wrcansave(DisasContext *dc, TCGv src)
35029422278eSRichard Henderson {
35039422278eSRichard Henderson     tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(cansave));
35049422278eSRichard Henderson }
35059422278eSRichard Henderson 
35069422278eSRichard Henderson TRANS(WRPR_cansave, 64, do_wr_special, a, supervisor(dc), do_wrcansave)
35079422278eSRichard Henderson 
35089422278eSRichard Henderson static void do_wrcanrestore(DisasContext *dc, TCGv src)
35099422278eSRichard Henderson {
35109422278eSRichard Henderson     tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(canrestore));
35119422278eSRichard Henderson }
35129422278eSRichard Henderson 
35139422278eSRichard Henderson TRANS(WRPR_canrestore, 64, do_wr_special, a, supervisor(dc), do_wrcanrestore)
35149422278eSRichard Henderson 
35159422278eSRichard Henderson static void do_wrcleanwin(DisasContext *dc, TCGv src)
35169422278eSRichard Henderson {
35179422278eSRichard Henderson     tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(cleanwin));
35189422278eSRichard Henderson }
35199422278eSRichard Henderson 
35209422278eSRichard Henderson TRANS(WRPR_cleanwin, 64, do_wr_special, a, supervisor(dc), do_wrcleanwin)
35219422278eSRichard Henderson 
35229422278eSRichard Henderson static void do_wrotherwin(DisasContext *dc, TCGv src)
35239422278eSRichard Henderson {
35249422278eSRichard Henderson     tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(otherwin));
35259422278eSRichard Henderson }
35269422278eSRichard Henderson 
35279422278eSRichard Henderson TRANS(WRPR_otherwin, 64, do_wr_special, a, supervisor(dc), do_wrotherwin)
35289422278eSRichard Henderson 
35299422278eSRichard Henderson static void do_wrwstate(DisasContext *dc, TCGv src)
35309422278eSRichard Henderson {
35319422278eSRichard Henderson     tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(wstate));
35329422278eSRichard Henderson }
35339422278eSRichard Henderson 
35349422278eSRichard Henderson TRANS(WRPR_wstate, 64, do_wr_special, a, supervisor(dc), do_wrwstate)
35359422278eSRichard Henderson 
35369422278eSRichard Henderson static void do_wrgl(DisasContext *dc, TCGv src)
35379422278eSRichard Henderson {
35389422278eSRichard Henderson     gen_helper_wrgl(tcg_env, src);
35399422278eSRichard Henderson }
35409422278eSRichard Henderson 
35419422278eSRichard Henderson TRANS(WRPR_gl, GL, do_wr_special, a, supervisor(dc), do_wrgl)
35429422278eSRichard Henderson 
35439422278eSRichard Henderson /* UA2005 strand status */
35449422278eSRichard Henderson static void do_wrssr(DisasContext *dc, TCGv src)
35459422278eSRichard Henderson {
35462da789deSRichard Henderson     tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(ssr));
35479422278eSRichard Henderson }
35489422278eSRichard Henderson 
35499422278eSRichard Henderson TRANS(WRPR_strand_status, HYPV, do_wr_special, a, hypervisor(dc), do_wrssr)
35509422278eSRichard Henderson 
3551bb97f2f5SRichard Henderson TRANS(WRTBR, 32, do_wr_special, a, supervisor(dc), do_wrtba)
3552bb97f2f5SRichard Henderson 
3553bb97f2f5SRichard Henderson static void do_wrhpstate(DisasContext *dc, TCGv src)
3554bb97f2f5SRichard Henderson {
3555bb97f2f5SRichard Henderson     tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(hpstate));
3556bb97f2f5SRichard Henderson     dc->base.is_jmp = DISAS_EXIT;
3557bb97f2f5SRichard Henderson }
3558bb97f2f5SRichard Henderson 
3559bb97f2f5SRichard Henderson TRANS(WRHPR_hpstate, HYPV, do_wr_special, a, hypervisor(dc), do_wrhpstate)
3560bb97f2f5SRichard Henderson 
3561bb97f2f5SRichard Henderson static void do_wrhtstate(DisasContext *dc, TCGv src)
3562bb97f2f5SRichard Henderson {
3563bb97f2f5SRichard Henderson     TCGv_i32 tl = tcg_temp_new_i32();
3564bb97f2f5SRichard Henderson     TCGv_ptr tp = tcg_temp_new_ptr();
3565bb97f2f5SRichard Henderson 
3566bb97f2f5SRichard Henderson     tcg_gen_ld_i32(tl, tcg_env, env64_field_offsetof(tl));
3567bb97f2f5SRichard Henderson     tcg_gen_andi_i32(tl, tl, MAXTL_MASK);
3568bb97f2f5SRichard Henderson     tcg_gen_shli_i32(tl, tl, 3);
3569bb97f2f5SRichard Henderson     tcg_gen_ext_i32_ptr(tp, tl);
3570bb97f2f5SRichard Henderson     tcg_gen_add_ptr(tp, tp, tcg_env);
3571bb97f2f5SRichard Henderson 
3572bb97f2f5SRichard Henderson     tcg_gen_st_tl(src, tp, env64_field_offsetof(htstate));
3573bb97f2f5SRichard Henderson }
3574bb97f2f5SRichard Henderson 
3575bb97f2f5SRichard Henderson TRANS(WRHPR_htstate, HYPV, do_wr_special, a, hypervisor(dc), do_wrhtstate)
3576bb97f2f5SRichard Henderson 
3577bb97f2f5SRichard Henderson static void do_wrhintp(DisasContext *dc, TCGv src)
3578bb97f2f5SRichard Henderson {
35792da789deSRichard Henderson     tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(hintp));
3580bb97f2f5SRichard Henderson }
3581bb97f2f5SRichard Henderson 
3582bb97f2f5SRichard Henderson TRANS(WRHPR_hintp, HYPV, do_wr_special, a, hypervisor(dc), do_wrhintp)
3583bb97f2f5SRichard Henderson 
3584bb97f2f5SRichard Henderson static void do_wrhtba(DisasContext *dc, TCGv src)
3585bb97f2f5SRichard Henderson {
35862da789deSRichard Henderson     tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(htba));
3587bb97f2f5SRichard Henderson }
3588bb97f2f5SRichard Henderson 
3589bb97f2f5SRichard Henderson TRANS(WRHPR_htba, HYPV, do_wr_special, a, hypervisor(dc), do_wrhtba)
3590bb97f2f5SRichard Henderson 
3591bb97f2f5SRichard Henderson static void do_wrhstick_cmpr(DisasContext *dc, TCGv src)
3592bb97f2f5SRichard Henderson {
3593bb97f2f5SRichard Henderson     TCGv_ptr r_tickptr = tcg_temp_new_ptr();
3594bb97f2f5SRichard Henderson 
3595577efa45SRichard Henderson     tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(hstick_cmpr));
3596bb97f2f5SRichard Henderson     tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(hstick));
3597bb97f2f5SRichard Henderson     translator_io_start(&dc->base);
3598577efa45SRichard Henderson     gen_helper_tick_set_limit(r_tickptr, src);
3599bb97f2f5SRichard Henderson     /* End TB to handle timer interrupt */
3600bb97f2f5SRichard Henderson     dc->base.is_jmp = DISAS_EXIT;
3601bb97f2f5SRichard Henderson }
3602bb97f2f5SRichard Henderson 
3603bb97f2f5SRichard Henderson TRANS(WRHPR_hstick_cmpr, HYPV, do_wr_special, a, hypervisor(dc),
3604bb97f2f5SRichard Henderson       do_wrhstick_cmpr)
3605bb97f2f5SRichard Henderson 
360625524734SRichard Henderson static bool do_saved_restored(DisasContext *dc, bool saved)
360725524734SRichard Henderson {
360825524734SRichard Henderson     if (!supervisor(dc)) {
360925524734SRichard Henderson         return raise_priv(dc);
361025524734SRichard Henderson     }
361125524734SRichard Henderson     if (saved) {
361225524734SRichard Henderson         gen_helper_saved(tcg_env);
361325524734SRichard Henderson     } else {
361425524734SRichard Henderson         gen_helper_restored(tcg_env);
361525524734SRichard Henderson     }
361625524734SRichard Henderson     return advance_pc(dc);
361725524734SRichard Henderson }
361825524734SRichard Henderson 
361925524734SRichard Henderson TRANS(SAVED, 64, do_saved_restored, true)
362025524734SRichard Henderson TRANS(RESTORED, 64, do_saved_restored, false)
362125524734SRichard Henderson 
3622d3825800SRichard Henderson static bool trans_NOP(DisasContext *dc, arg_NOP *a)
3623d3825800SRichard Henderson {
3624d3825800SRichard Henderson     return advance_pc(dc);
3625d3825800SRichard Henderson }
3626d3825800SRichard Henderson 
36270faef01bSRichard Henderson /*
36280faef01bSRichard Henderson  * TODO: Need a feature bit for sparcv8.
36290faef01bSRichard Henderson  * In the meantime, treat all 32-bit cpus like sparcv7.
36300faef01bSRichard Henderson  */
36315458fd31SRichard Henderson TRANS(NOP_v7, 32, trans_NOP, a)
36325458fd31SRichard Henderson TRANS(NOP_v9, 64, trans_NOP, a)
36330faef01bSRichard Henderson 
3634b597eedcSRichard Henderson static bool do_arith_int(DisasContext *dc, arg_r_r_ri_cc *a,
3635428881deSRichard Henderson                          void (*func)(TCGv, TCGv, TCGv),
36362a45b736SRichard Henderson                          void (*funci)(TCGv, TCGv, target_long),
36372a45b736SRichard Henderson                          bool logic_cc)
3638428881deSRichard Henderson {
3639428881deSRichard Henderson     TCGv dst, src1;
3640428881deSRichard Henderson 
3641428881deSRichard Henderson     /* For simplicity, we under-decoded the rs2 form. */
3642428881deSRichard Henderson     if (!a->imm && a->rs2_or_imm & ~0x1f) {
3643428881deSRichard Henderson         return false;
3644428881deSRichard Henderson     }
3645428881deSRichard Henderson 
36462a45b736SRichard Henderson     if (logic_cc) {
36472a45b736SRichard Henderson         dst = cpu_cc_N;
3648428881deSRichard Henderson     } else {
3649428881deSRichard Henderson         dst = gen_dest_gpr(dc, a->rd);
3650428881deSRichard Henderson     }
3651428881deSRichard Henderson     src1 = gen_load_gpr(dc, a->rs1);
3652428881deSRichard Henderson 
3653428881deSRichard Henderson     if (a->imm || a->rs2_or_imm == 0) {
3654428881deSRichard Henderson         if (funci) {
3655428881deSRichard Henderson             funci(dst, src1, a->rs2_or_imm);
3656428881deSRichard Henderson         } else {
3657428881deSRichard Henderson             func(dst, src1, tcg_constant_tl(a->rs2_or_imm));
3658428881deSRichard Henderson         }
3659428881deSRichard Henderson     } else {
3660428881deSRichard Henderson         func(dst, src1, cpu_regs[a->rs2_or_imm]);
3661428881deSRichard Henderson     }
36622a45b736SRichard Henderson 
36632a45b736SRichard Henderson     if (logic_cc) {
36642a45b736SRichard Henderson         if (TARGET_LONG_BITS == 64) {
36652a45b736SRichard Henderson             tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N);
36662a45b736SRichard Henderson             tcg_gen_movi_tl(cpu_icc_C, 0);
36672a45b736SRichard Henderson         }
36682a45b736SRichard Henderson         tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N);
36692a45b736SRichard Henderson         tcg_gen_movi_tl(cpu_cc_C, 0);
36702a45b736SRichard Henderson         tcg_gen_movi_tl(cpu_cc_V, 0);
36712a45b736SRichard Henderson     }
36722a45b736SRichard Henderson 
3673428881deSRichard Henderson     gen_store_gpr(dc, a->rd, dst);
3674428881deSRichard Henderson     return advance_pc(dc);
3675428881deSRichard Henderson }
3676428881deSRichard Henderson 
3677b597eedcSRichard Henderson static bool do_arith(DisasContext *dc, arg_r_r_ri_cc *a,
3678428881deSRichard Henderson                      void (*func)(TCGv, TCGv, TCGv),
3679428881deSRichard Henderson                      void (*funci)(TCGv, TCGv, target_long),
3680428881deSRichard Henderson                      void (*func_cc)(TCGv, TCGv, TCGv))
3681428881deSRichard Henderson {
3682428881deSRichard Henderson     if (a->cc) {
3683b597eedcSRichard Henderson         return do_arith_int(dc, a, func_cc, NULL, false);
3684428881deSRichard Henderson     }
3685b597eedcSRichard Henderson     return do_arith_int(dc, a, func, funci, false);
3686428881deSRichard Henderson }
3687428881deSRichard Henderson 
3688428881deSRichard Henderson static bool do_logic(DisasContext *dc, arg_r_r_ri_cc *a,
3689428881deSRichard Henderson                      void (*func)(TCGv, TCGv, TCGv),
3690428881deSRichard Henderson                      void (*funci)(TCGv, TCGv, target_long))
3691428881deSRichard Henderson {
3692b597eedcSRichard Henderson     return do_arith_int(dc, a, func, funci, a->cc);
3693428881deSRichard Henderson }
3694428881deSRichard Henderson 
3695b597eedcSRichard Henderson TRANS(ADD, ALL, do_arith, a, tcg_gen_add_tl, tcg_gen_addi_tl, gen_op_addcc)
3696b597eedcSRichard Henderson TRANS(SUB, ALL, do_arith, a, tcg_gen_sub_tl, tcg_gen_subi_tl, gen_op_subcc)
3697b597eedcSRichard Henderson TRANS(ADDC, ALL, do_arith, a, gen_op_addc, NULL, gen_op_addccc)
3698b597eedcSRichard Henderson TRANS(SUBC, ALL, do_arith, a, gen_op_subc, NULL, gen_op_subccc)
3699428881deSRichard Henderson 
3700b597eedcSRichard Henderson TRANS(TADDcc, ALL, do_arith, a, NULL, NULL, gen_op_taddcc)
3701b597eedcSRichard Henderson TRANS(TSUBcc, ALL, do_arith, a, NULL, NULL, gen_op_tsubcc)
3702b597eedcSRichard Henderson TRANS(TADDccTV, ALL, do_arith, a, NULL, NULL, gen_op_taddcctv)
3703b597eedcSRichard Henderson TRANS(TSUBccTV, ALL, do_arith, a, NULL, NULL, gen_op_tsubcctv)
3704a9aba13dSRichard Henderson 
3705428881deSRichard Henderson TRANS(AND, ALL, do_logic, a, tcg_gen_and_tl, tcg_gen_andi_tl)
3706428881deSRichard Henderson TRANS(XOR, ALL, do_logic, a, tcg_gen_xor_tl, tcg_gen_xori_tl)
3707428881deSRichard Henderson TRANS(ANDN, ALL, do_logic, a, tcg_gen_andc_tl, NULL)
3708428881deSRichard Henderson TRANS(ORN, ALL, do_logic, a, tcg_gen_orc_tl, NULL)
3709428881deSRichard Henderson TRANS(XORN, ALL, do_logic, a, tcg_gen_eqv_tl, NULL)
3710428881deSRichard Henderson 
3711b597eedcSRichard Henderson TRANS(MULX, 64, do_arith, a, tcg_gen_mul_tl, tcg_gen_muli_tl, NULL)
3712b5372650SRichard Henderson TRANS(UMUL, MUL, do_logic, a, gen_op_umul, NULL)
3713b5372650SRichard Henderson TRANS(SMUL, MUL, do_logic, a, gen_op_smul, NULL)
3714b597eedcSRichard Henderson TRANS(MULScc, ALL, do_arith, a, NULL, NULL, gen_op_mulscc)
371522188d7dSRichard Henderson 
37163a6b8de3SRichard Henderson TRANS(UDIVcc, DIV, do_arith, a, NULL, NULL, gen_op_udivcc)
3717b597eedcSRichard Henderson TRANS(SDIV, DIV, do_arith, a, gen_op_sdiv, NULL, gen_op_sdivcc)
37184ee85ea9SRichard Henderson 
37199c6ec5bcSRichard Henderson /* TODO: Should have feature bit -- comes in with UltraSparc T2. */
3720b597eedcSRichard Henderson TRANS(POPC, 64, do_arith, a, gen_op_popc, NULL, NULL)
37219c6ec5bcSRichard Henderson 
3722428881deSRichard Henderson static bool trans_OR(DisasContext *dc, arg_r_r_ri_cc *a)
3723428881deSRichard Henderson {
3724428881deSRichard Henderson     /* OR with %g0 is the canonical alias for MOV. */
3725428881deSRichard Henderson     if (!a->cc && a->rs1 == 0) {
3726428881deSRichard Henderson         if (a->imm || a->rs2_or_imm == 0) {
3727428881deSRichard Henderson             gen_store_gpr(dc, a->rd, tcg_constant_tl(a->rs2_or_imm));
3728428881deSRichard Henderson         } else if (a->rs2_or_imm & ~0x1f) {
3729428881deSRichard Henderson             /* For simplicity, we under-decoded the rs2 form. */
3730428881deSRichard Henderson             return false;
3731428881deSRichard Henderson         } else {
3732428881deSRichard Henderson             gen_store_gpr(dc, a->rd, cpu_regs[a->rs2_or_imm]);
3733428881deSRichard Henderson         }
3734428881deSRichard Henderson         return advance_pc(dc);
3735428881deSRichard Henderson     }
3736428881deSRichard Henderson     return do_logic(dc, a, tcg_gen_or_tl, tcg_gen_ori_tl);
3737428881deSRichard Henderson }
3738428881deSRichard Henderson 
37393a6b8de3SRichard Henderson static bool trans_UDIV(DisasContext *dc, arg_r_r_ri *a)
37403a6b8de3SRichard Henderson {
37413a6b8de3SRichard Henderson     TCGv_i64 t1, t2;
37423a6b8de3SRichard Henderson     TCGv dst;
37433a6b8de3SRichard Henderson 
37443a6b8de3SRichard Henderson     if (!avail_DIV(dc)) {
37453a6b8de3SRichard Henderson         return false;
37463a6b8de3SRichard Henderson     }
37473a6b8de3SRichard Henderson     /* For simplicity, we under-decoded the rs2 form. */
37483a6b8de3SRichard Henderson     if (!a->imm && a->rs2_or_imm & ~0x1f) {
37493a6b8de3SRichard Henderson         return false;
37503a6b8de3SRichard Henderson     }
37513a6b8de3SRichard Henderson 
37523a6b8de3SRichard Henderson     if (unlikely(a->rs2_or_imm == 0)) {
37533a6b8de3SRichard Henderson         gen_exception(dc, TT_DIV_ZERO);
37543a6b8de3SRichard Henderson         return true;
37553a6b8de3SRichard Henderson     }
37563a6b8de3SRichard Henderson 
37573a6b8de3SRichard Henderson     if (a->imm) {
37583a6b8de3SRichard Henderson         t2 = tcg_constant_i64((uint32_t)a->rs2_or_imm);
37593a6b8de3SRichard Henderson     } else {
37603a6b8de3SRichard Henderson         TCGLabel *lab;
37613a6b8de3SRichard Henderson         TCGv_i32 n2;
37623a6b8de3SRichard Henderson 
37633a6b8de3SRichard Henderson         finishing_insn(dc);
37643a6b8de3SRichard Henderson         flush_cond(dc);
37653a6b8de3SRichard Henderson 
37663a6b8de3SRichard Henderson         n2 = tcg_temp_new_i32();
37673a6b8de3SRichard Henderson         tcg_gen_trunc_tl_i32(n2, cpu_regs[a->rs2_or_imm]);
37683a6b8de3SRichard Henderson 
37693a6b8de3SRichard Henderson         lab = delay_exception(dc, TT_DIV_ZERO);
37703a6b8de3SRichard Henderson         tcg_gen_brcondi_i32(TCG_COND_EQ, n2, 0, lab);
37713a6b8de3SRichard Henderson 
37723a6b8de3SRichard Henderson         t2 = tcg_temp_new_i64();
37733a6b8de3SRichard Henderson #ifdef TARGET_SPARC64
37743a6b8de3SRichard Henderson         tcg_gen_ext32u_i64(t2, cpu_regs[a->rs2_or_imm]);
37753a6b8de3SRichard Henderson #else
37763a6b8de3SRichard Henderson         tcg_gen_extu_i32_i64(t2, cpu_regs[a->rs2_or_imm]);
37773a6b8de3SRichard Henderson #endif
37783a6b8de3SRichard Henderson     }
37793a6b8de3SRichard Henderson 
37803a6b8de3SRichard Henderson     t1 = tcg_temp_new_i64();
37813a6b8de3SRichard Henderson     tcg_gen_concat_tl_i64(t1, gen_load_gpr(dc, a->rs1), cpu_y);
37823a6b8de3SRichard Henderson 
37833a6b8de3SRichard Henderson     tcg_gen_divu_i64(t1, t1, t2);
37843a6b8de3SRichard Henderson     tcg_gen_umin_i64(t1, t1, tcg_constant_i64(UINT32_MAX));
37853a6b8de3SRichard Henderson 
37863a6b8de3SRichard Henderson     dst = gen_dest_gpr(dc, a->rd);
37873a6b8de3SRichard Henderson     tcg_gen_trunc_i64_tl(dst, t1);
37883a6b8de3SRichard Henderson     gen_store_gpr(dc, a->rd, dst);
37893a6b8de3SRichard Henderson     return advance_pc(dc);
37903a6b8de3SRichard Henderson }
37913a6b8de3SRichard Henderson 
3792f3141174SRichard Henderson static bool trans_UDIVX(DisasContext *dc, arg_r_r_ri *a)
3793f3141174SRichard Henderson {
3794f3141174SRichard Henderson     TCGv dst, src1, src2;
3795f3141174SRichard Henderson 
3796f3141174SRichard Henderson     if (!avail_64(dc)) {
3797f3141174SRichard Henderson         return false;
3798f3141174SRichard Henderson     }
3799f3141174SRichard Henderson     /* For simplicity, we under-decoded the rs2 form. */
3800f3141174SRichard Henderson     if (!a->imm && a->rs2_or_imm & ~0x1f) {
3801f3141174SRichard Henderson         return false;
3802f3141174SRichard Henderson     }
3803f3141174SRichard Henderson 
3804f3141174SRichard Henderson     if (unlikely(a->rs2_or_imm == 0)) {
3805f3141174SRichard Henderson         gen_exception(dc, TT_DIV_ZERO);
3806f3141174SRichard Henderson         return true;
3807f3141174SRichard Henderson     }
3808f3141174SRichard Henderson 
3809f3141174SRichard Henderson     if (a->imm) {
3810f3141174SRichard Henderson         src2 = tcg_constant_tl(a->rs2_or_imm);
3811f3141174SRichard Henderson     } else {
3812f3141174SRichard Henderson         TCGLabel *lab;
3813f3141174SRichard Henderson 
3814f3141174SRichard Henderson         finishing_insn(dc);
3815f3141174SRichard Henderson         flush_cond(dc);
3816f3141174SRichard Henderson 
3817f3141174SRichard Henderson         lab = delay_exception(dc, TT_DIV_ZERO);
3818f3141174SRichard Henderson         src2 = cpu_regs[a->rs2_or_imm];
3819f3141174SRichard Henderson         tcg_gen_brcondi_tl(TCG_COND_EQ, src2, 0, lab);
3820f3141174SRichard Henderson     }
3821f3141174SRichard Henderson 
3822f3141174SRichard Henderson     dst = gen_dest_gpr(dc, a->rd);
3823f3141174SRichard Henderson     src1 = gen_load_gpr(dc, a->rs1);
3824f3141174SRichard Henderson 
3825f3141174SRichard Henderson     tcg_gen_divu_tl(dst, src1, src2);
3826f3141174SRichard Henderson     gen_store_gpr(dc, a->rd, dst);
3827f3141174SRichard Henderson     return advance_pc(dc);
3828f3141174SRichard Henderson }
3829f3141174SRichard Henderson 
3830f3141174SRichard Henderson static bool trans_SDIVX(DisasContext *dc, arg_r_r_ri *a)
3831f3141174SRichard Henderson {
3832f3141174SRichard Henderson     TCGv dst, src1, src2;
3833f3141174SRichard Henderson 
3834f3141174SRichard Henderson     if (!avail_64(dc)) {
3835f3141174SRichard Henderson         return false;
3836f3141174SRichard Henderson     }
3837f3141174SRichard Henderson     /* For simplicity, we under-decoded the rs2 form. */
3838f3141174SRichard Henderson     if (!a->imm && a->rs2_or_imm & ~0x1f) {
3839f3141174SRichard Henderson         return false;
3840f3141174SRichard Henderson     }
3841f3141174SRichard Henderson 
3842f3141174SRichard Henderson     if (unlikely(a->rs2_or_imm == 0)) {
3843f3141174SRichard Henderson         gen_exception(dc, TT_DIV_ZERO);
3844f3141174SRichard Henderson         return true;
3845f3141174SRichard Henderson     }
3846f3141174SRichard Henderson 
3847f3141174SRichard Henderson     dst = gen_dest_gpr(dc, a->rd);
3848f3141174SRichard Henderson     src1 = gen_load_gpr(dc, a->rs1);
3849f3141174SRichard Henderson 
3850f3141174SRichard Henderson     if (a->imm) {
3851f3141174SRichard Henderson         if (unlikely(a->rs2_or_imm == -1)) {
3852f3141174SRichard Henderson             tcg_gen_neg_tl(dst, src1);
3853f3141174SRichard Henderson             gen_store_gpr(dc, a->rd, dst);
3854f3141174SRichard Henderson             return advance_pc(dc);
3855f3141174SRichard Henderson         }
3856f3141174SRichard Henderson         src2 = tcg_constant_tl(a->rs2_or_imm);
3857f3141174SRichard Henderson     } else {
3858f3141174SRichard Henderson         TCGLabel *lab;
3859f3141174SRichard Henderson         TCGv t1, t2;
3860f3141174SRichard Henderson 
3861f3141174SRichard Henderson         finishing_insn(dc);
3862f3141174SRichard Henderson         flush_cond(dc);
3863f3141174SRichard Henderson 
3864f3141174SRichard Henderson         lab = delay_exception(dc, TT_DIV_ZERO);
3865f3141174SRichard Henderson         src2 = cpu_regs[a->rs2_or_imm];
3866f3141174SRichard Henderson         tcg_gen_brcondi_tl(TCG_COND_EQ, src2, 0, lab);
3867f3141174SRichard Henderson 
3868f3141174SRichard Henderson         /*
3869f3141174SRichard Henderson          * Need to avoid INT64_MIN / -1, which will trap on x86 host.
3870f3141174SRichard Henderson          * Set SRC2 to 1 as a new divisor, to produce the correct result.
3871f3141174SRichard Henderson          */
3872f3141174SRichard Henderson         t1 = tcg_temp_new();
3873f3141174SRichard Henderson         t2 = tcg_temp_new();
3874f3141174SRichard Henderson         tcg_gen_setcondi_tl(TCG_COND_EQ, t1, src1, (target_long)INT64_MIN);
3875f3141174SRichard Henderson         tcg_gen_setcondi_tl(TCG_COND_EQ, t2, src2, -1);
3876f3141174SRichard Henderson         tcg_gen_and_tl(t1, t1, t2);
3877f3141174SRichard Henderson         tcg_gen_movcond_tl(TCG_COND_NE, t1, t1, tcg_constant_tl(0),
3878f3141174SRichard Henderson                            tcg_constant_tl(1), src2);
3879f3141174SRichard Henderson         src2 = t1;
3880f3141174SRichard Henderson     }
3881f3141174SRichard Henderson 
3882f3141174SRichard Henderson     tcg_gen_div_tl(dst, src1, src2);
3883f3141174SRichard Henderson     gen_store_gpr(dc, a->rd, dst);
3884f3141174SRichard Henderson     return advance_pc(dc);
3885f3141174SRichard Henderson }
3886f3141174SRichard Henderson 
3887b88ce6f2SRichard Henderson static bool gen_edge(DisasContext *dc, arg_r_r_r *a,
388843db5838SRichard Henderson                      int width, bool cc, bool little_endian)
3889b88ce6f2SRichard Henderson {
389043db5838SRichard Henderson     TCGv dst, s1, s2, l, r, t, m;
389143db5838SRichard Henderson     uint64_t amask = address_mask_i(dc, -8);
3892b88ce6f2SRichard Henderson 
3893b88ce6f2SRichard Henderson     dst = gen_dest_gpr(dc, a->rd);
3894b88ce6f2SRichard Henderson     s1 = gen_load_gpr(dc, a->rs1);
3895b88ce6f2SRichard Henderson     s2 = gen_load_gpr(dc, a->rs2);
3896b88ce6f2SRichard Henderson 
3897b88ce6f2SRichard Henderson     if (cc) {
3898f828df74SRichard Henderson         gen_op_subcc(cpu_cc_N, s1, s2);
3899b88ce6f2SRichard Henderson     }
3900b88ce6f2SRichard Henderson 
390143db5838SRichard Henderson     l = tcg_temp_new();
390243db5838SRichard Henderson     r = tcg_temp_new();
390343db5838SRichard Henderson     t = tcg_temp_new();
390443db5838SRichard Henderson 
3905b88ce6f2SRichard Henderson     switch (width) {
3906b88ce6f2SRichard Henderson     case 8:
390743db5838SRichard Henderson         tcg_gen_andi_tl(l, s1, 7);
390843db5838SRichard Henderson         tcg_gen_andi_tl(r, s2, 7);
390943db5838SRichard Henderson         tcg_gen_xori_tl(r, r, 7);
391043db5838SRichard Henderson         m = tcg_constant_tl(0xff);
3911b88ce6f2SRichard Henderson         break;
3912b88ce6f2SRichard Henderson     case 16:
391343db5838SRichard Henderson         tcg_gen_extract_tl(l, s1, 1, 2);
391443db5838SRichard Henderson         tcg_gen_extract_tl(r, s2, 1, 2);
391543db5838SRichard Henderson         tcg_gen_xori_tl(r, r, 3);
391643db5838SRichard Henderson         m = tcg_constant_tl(0xf);
3917b88ce6f2SRichard Henderson         break;
3918b88ce6f2SRichard Henderson     case 32:
391943db5838SRichard Henderson         tcg_gen_extract_tl(l, s1, 2, 1);
392043db5838SRichard Henderson         tcg_gen_extract_tl(r, s2, 2, 1);
392143db5838SRichard Henderson         tcg_gen_xori_tl(r, r, 1);
392243db5838SRichard Henderson         m = tcg_constant_tl(0x3);
3923b88ce6f2SRichard Henderson         break;
3924b88ce6f2SRichard Henderson     default:
3925b88ce6f2SRichard Henderson         abort();
3926b88ce6f2SRichard Henderson     }
3927b88ce6f2SRichard Henderson 
392843db5838SRichard Henderson     /* Compute Left Edge */
392943db5838SRichard Henderson     if (little_endian) {
393043db5838SRichard Henderson         tcg_gen_shl_tl(l, m, l);
393143db5838SRichard Henderson         tcg_gen_and_tl(l, l, m);
393243db5838SRichard Henderson     } else {
393343db5838SRichard Henderson         tcg_gen_shr_tl(l, m, l);
393443db5838SRichard Henderson     }
393543db5838SRichard Henderson     /* Compute Right Edge */
393643db5838SRichard Henderson     if (little_endian) {
393743db5838SRichard Henderson         tcg_gen_shr_tl(r, m, r);
393843db5838SRichard Henderson     } else {
393943db5838SRichard Henderson         tcg_gen_shl_tl(r, m, r);
394043db5838SRichard Henderson         tcg_gen_and_tl(r, r, m);
394143db5838SRichard Henderson     }
3942b88ce6f2SRichard Henderson 
394343db5838SRichard Henderson     /* Compute dst = (s1 == s2 under amask ? l : l & r) */
394443db5838SRichard Henderson     tcg_gen_xor_tl(t, s1, s2);
394543db5838SRichard Henderson     tcg_gen_and_tl(r, r, l);
394643db5838SRichard Henderson     tcg_gen_movcond_tl(TCG_COND_TSTEQ, dst, t, tcg_constant_tl(amask), r, l);
3947b88ce6f2SRichard Henderson 
3948b88ce6f2SRichard Henderson     gen_store_gpr(dc, a->rd, dst);
3949b88ce6f2SRichard Henderson     return advance_pc(dc);
3950b88ce6f2SRichard Henderson }
3951b88ce6f2SRichard Henderson 
3952b88ce6f2SRichard Henderson TRANS(EDGE8cc, VIS1, gen_edge, a, 8, 1, 0)
3953b88ce6f2SRichard Henderson TRANS(EDGE8Lcc, VIS1, gen_edge, a, 8, 1, 1)
3954b88ce6f2SRichard Henderson TRANS(EDGE16cc, VIS1, gen_edge, a, 16, 1, 0)
3955b88ce6f2SRichard Henderson TRANS(EDGE16Lcc, VIS1, gen_edge, a, 16, 1, 1)
3956b88ce6f2SRichard Henderson TRANS(EDGE32cc, VIS1, gen_edge, a, 32, 1, 0)
3957b88ce6f2SRichard Henderson TRANS(EDGE32Lcc, VIS1, gen_edge, a, 32, 1, 1)
3958b88ce6f2SRichard Henderson 
3959b88ce6f2SRichard Henderson TRANS(EDGE8N, VIS2, gen_edge, a, 8, 0, 0)
3960b88ce6f2SRichard Henderson TRANS(EDGE8LN, VIS2, gen_edge, a, 8, 0, 1)
3961b88ce6f2SRichard Henderson TRANS(EDGE16N, VIS2, gen_edge, a, 16, 0, 0)
3962b88ce6f2SRichard Henderson TRANS(EDGE16LN, VIS2, gen_edge, a, 16, 0, 1)
3963b88ce6f2SRichard Henderson TRANS(EDGE32N, VIS2, gen_edge, a, 32, 0, 0)
3964b88ce6f2SRichard Henderson TRANS(EDGE32LN, VIS2, gen_edge, a, 32, 0, 1)
3965b88ce6f2SRichard Henderson 
3966875ce392SRichard Henderson static bool do_rr(DisasContext *dc, arg_r_r *a,
3967875ce392SRichard Henderson                   void (*func)(TCGv, TCGv))
3968875ce392SRichard Henderson {
3969875ce392SRichard Henderson     TCGv dst = gen_dest_gpr(dc, a->rd);
3970875ce392SRichard Henderson     TCGv src = gen_load_gpr(dc, a->rs);
3971875ce392SRichard Henderson 
3972875ce392SRichard Henderson     func(dst, src);
3973875ce392SRichard Henderson     gen_store_gpr(dc, a->rd, dst);
3974875ce392SRichard Henderson     return advance_pc(dc);
3975875ce392SRichard Henderson }
3976875ce392SRichard Henderson 
3977875ce392SRichard Henderson TRANS(LZCNT, VIS3, do_rr, a, gen_op_lzcnt)
3978875ce392SRichard Henderson 
397945bfed3bSRichard Henderson static bool do_rrr(DisasContext *dc, arg_r_r_r *a,
398045bfed3bSRichard Henderson                    void (*func)(TCGv, TCGv, TCGv))
398145bfed3bSRichard Henderson {
398245bfed3bSRichard Henderson     TCGv dst = gen_dest_gpr(dc, a->rd);
398345bfed3bSRichard Henderson     TCGv src1 = gen_load_gpr(dc, a->rs1);
398445bfed3bSRichard Henderson     TCGv src2 = gen_load_gpr(dc, a->rs2);
398545bfed3bSRichard Henderson 
398645bfed3bSRichard Henderson     func(dst, src1, src2);
398745bfed3bSRichard Henderson     gen_store_gpr(dc, a->rd, dst);
398845bfed3bSRichard Henderson     return advance_pc(dc);
398945bfed3bSRichard Henderson }
399045bfed3bSRichard Henderson 
399145bfed3bSRichard Henderson TRANS(ARRAY8, VIS1, do_rrr, a, gen_helper_array8)
399245bfed3bSRichard Henderson TRANS(ARRAY16, VIS1, do_rrr, a, gen_op_array16)
399345bfed3bSRichard Henderson TRANS(ARRAY32, VIS1, do_rrr, a, gen_op_array32)
399445bfed3bSRichard Henderson 
3995015fc6fcSRichard Henderson TRANS(ADDXC, VIS3, do_rrr, a, gen_op_addxc)
3996015fc6fcSRichard Henderson TRANS(ADDXCcc, VIS3, do_rrr, a, gen_op_addxccc)
3997015fc6fcSRichard Henderson 
399856f2ef9cSRichard Henderson TRANS(SUBXC, VIS4, do_rrr, a, gen_op_subxc)
399956f2ef9cSRichard Henderson TRANS(SUBXCcc, VIS4, do_rrr, a, gen_op_subxccc)
400056f2ef9cSRichard Henderson 
4001680af1b4SRichard Henderson TRANS(UMULXHI, VIS3, do_rrr, a, gen_op_umulxhi)
4002680af1b4SRichard Henderson 
40039e20ca94SRichard Henderson static void gen_op_alignaddr(TCGv dst, TCGv s1, TCGv s2)
40049e20ca94SRichard Henderson {
40059e20ca94SRichard Henderson #ifdef TARGET_SPARC64
40069e20ca94SRichard Henderson     TCGv tmp = tcg_temp_new();
40079e20ca94SRichard Henderson 
40089e20ca94SRichard Henderson     tcg_gen_add_tl(tmp, s1, s2);
40099e20ca94SRichard Henderson     tcg_gen_andi_tl(dst, tmp, -8);
40109e20ca94SRichard Henderson     tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, tmp, 0, 3);
40119e20ca94SRichard Henderson #else
40129e20ca94SRichard Henderson     g_assert_not_reached();
40139e20ca94SRichard Henderson #endif
40149e20ca94SRichard Henderson }
40159e20ca94SRichard Henderson 
40169e20ca94SRichard Henderson static void gen_op_alignaddrl(TCGv dst, TCGv s1, TCGv s2)
40179e20ca94SRichard Henderson {
40189e20ca94SRichard Henderson #ifdef TARGET_SPARC64
40199e20ca94SRichard Henderson     TCGv tmp = tcg_temp_new();
40209e20ca94SRichard Henderson 
40219e20ca94SRichard Henderson     tcg_gen_add_tl(tmp, s1, s2);
40229e20ca94SRichard Henderson     tcg_gen_andi_tl(dst, tmp, -8);
40239e20ca94SRichard Henderson     tcg_gen_neg_tl(tmp, tmp);
40249e20ca94SRichard Henderson     tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, tmp, 0, 3);
40259e20ca94SRichard Henderson #else
40269e20ca94SRichard Henderson     g_assert_not_reached();
40279e20ca94SRichard Henderson #endif
40289e20ca94SRichard Henderson }
40299e20ca94SRichard Henderson 
40309e20ca94SRichard Henderson TRANS(ALIGNADDR, VIS1, do_rrr, a, gen_op_alignaddr)
40319e20ca94SRichard Henderson TRANS(ALIGNADDRL, VIS1, do_rrr, a, gen_op_alignaddrl)
40329e20ca94SRichard Henderson 
403339ca3490SRichard Henderson static void gen_op_bmask(TCGv dst, TCGv s1, TCGv s2)
403439ca3490SRichard Henderson {
403539ca3490SRichard Henderson #ifdef TARGET_SPARC64
403639ca3490SRichard Henderson     tcg_gen_add_tl(dst, s1, s2);
403739ca3490SRichard Henderson     tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, dst, 32, 32);
403839ca3490SRichard Henderson #else
403939ca3490SRichard Henderson     g_assert_not_reached();
404039ca3490SRichard Henderson #endif
404139ca3490SRichard Henderson }
404239ca3490SRichard Henderson 
404339ca3490SRichard Henderson TRANS(BMASK, VIS2, do_rrr, a, gen_op_bmask)
404439ca3490SRichard Henderson 
4045c973b4e8SRichard Henderson static bool do_cmask(DisasContext *dc, int rs2, void (*func)(TCGv, TCGv, TCGv))
4046c973b4e8SRichard Henderson {
4047c973b4e8SRichard Henderson     func(cpu_gsr, cpu_gsr, gen_load_gpr(dc, rs2));
4048c973b4e8SRichard Henderson     return true;
4049c973b4e8SRichard Henderson }
4050c973b4e8SRichard Henderson 
4051c973b4e8SRichard Henderson TRANS(CMASK8, VIS3, do_cmask, a->rs2, gen_helper_cmask8)
4052c973b4e8SRichard Henderson TRANS(CMASK16, VIS3, do_cmask, a->rs2, gen_helper_cmask16)
4053c973b4e8SRichard Henderson TRANS(CMASK32, VIS3, do_cmask, a->rs2, gen_helper_cmask32)
4054c973b4e8SRichard Henderson 
40555fc546eeSRichard Henderson static bool do_shift_r(DisasContext *dc, arg_shiftr *a, bool l, bool u)
40565fc546eeSRichard Henderson {
40575fc546eeSRichard Henderson     TCGv dst, src1, src2;
40585fc546eeSRichard Henderson 
40595fc546eeSRichard Henderson     /* Reject 64-bit shifts for sparc32. */
40605fc546eeSRichard Henderson     if (avail_32(dc) && a->x) {
40615fc546eeSRichard Henderson         return false;
40625fc546eeSRichard Henderson     }
40635fc546eeSRichard Henderson 
40645fc546eeSRichard Henderson     src2 = tcg_temp_new();
40655fc546eeSRichard Henderson     tcg_gen_andi_tl(src2, gen_load_gpr(dc, a->rs2), a->x ? 63 : 31);
40665fc546eeSRichard Henderson     src1 = gen_load_gpr(dc, a->rs1);
40675fc546eeSRichard Henderson     dst = gen_dest_gpr(dc, a->rd);
40685fc546eeSRichard Henderson 
40695fc546eeSRichard Henderson     if (l) {
40705fc546eeSRichard Henderson         tcg_gen_shl_tl(dst, src1, src2);
40715fc546eeSRichard Henderson         if (!a->x) {
40725fc546eeSRichard Henderson             tcg_gen_ext32u_tl(dst, dst);
40735fc546eeSRichard Henderson         }
40745fc546eeSRichard Henderson     } else if (u) {
40755fc546eeSRichard Henderson         if (!a->x) {
40765fc546eeSRichard Henderson             tcg_gen_ext32u_tl(dst, src1);
40775fc546eeSRichard Henderson             src1 = dst;
40785fc546eeSRichard Henderson         }
40795fc546eeSRichard Henderson         tcg_gen_shr_tl(dst, src1, src2);
40805fc546eeSRichard Henderson     } else {
40815fc546eeSRichard Henderson         if (!a->x) {
40825fc546eeSRichard Henderson             tcg_gen_ext32s_tl(dst, src1);
40835fc546eeSRichard Henderson             src1 = dst;
40845fc546eeSRichard Henderson         }
40855fc546eeSRichard Henderson         tcg_gen_sar_tl(dst, src1, src2);
40865fc546eeSRichard Henderson     }
40875fc546eeSRichard Henderson     gen_store_gpr(dc, a->rd, dst);
40885fc546eeSRichard Henderson     return advance_pc(dc);
40895fc546eeSRichard Henderson }
40905fc546eeSRichard Henderson 
40915fc546eeSRichard Henderson TRANS(SLL_r, ALL, do_shift_r, a, true, true)
40925fc546eeSRichard Henderson TRANS(SRL_r, ALL, do_shift_r, a, false, true)
40935fc546eeSRichard Henderson TRANS(SRA_r, ALL, do_shift_r, a, false, false)
40945fc546eeSRichard Henderson 
40955fc546eeSRichard Henderson static bool do_shift_i(DisasContext *dc, arg_shifti *a, bool l, bool u)
40965fc546eeSRichard Henderson {
40975fc546eeSRichard Henderson     TCGv dst, src1;
40985fc546eeSRichard Henderson 
40995fc546eeSRichard Henderson     /* Reject 64-bit shifts for sparc32. */
41005fc546eeSRichard Henderson     if (avail_32(dc) && (a->x || a->i >= 32)) {
41015fc546eeSRichard Henderson         return false;
41025fc546eeSRichard Henderson     }
41035fc546eeSRichard Henderson 
41045fc546eeSRichard Henderson     src1 = gen_load_gpr(dc, a->rs1);
41055fc546eeSRichard Henderson     dst = gen_dest_gpr(dc, a->rd);
41065fc546eeSRichard Henderson 
41075fc546eeSRichard Henderson     if (avail_32(dc) || a->x) {
41085fc546eeSRichard Henderson         if (l) {
41095fc546eeSRichard Henderson             tcg_gen_shli_tl(dst, src1, a->i);
41105fc546eeSRichard Henderson         } else if (u) {
41115fc546eeSRichard Henderson             tcg_gen_shri_tl(dst, src1, a->i);
41125fc546eeSRichard Henderson         } else {
41135fc546eeSRichard Henderson             tcg_gen_sari_tl(dst, src1, a->i);
41145fc546eeSRichard Henderson         }
41155fc546eeSRichard Henderson     } else {
41165fc546eeSRichard Henderson         if (l) {
41175fc546eeSRichard Henderson             tcg_gen_deposit_z_tl(dst, src1, a->i, 32 - a->i);
41185fc546eeSRichard Henderson         } else if (u) {
41195fc546eeSRichard Henderson             tcg_gen_extract_tl(dst, src1, a->i, 32 - a->i);
41205fc546eeSRichard Henderson         } else {
41215fc546eeSRichard Henderson             tcg_gen_sextract_tl(dst, src1, a->i, 32 - a->i);
41225fc546eeSRichard Henderson         }
41235fc546eeSRichard Henderson     }
41245fc546eeSRichard Henderson     gen_store_gpr(dc, a->rd, dst);
41255fc546eeSRichard Henderson     return advance_pc(dc);
41265fc546eeSRichard Henderson }
41275fc546eeSRichard Henderson 
41285fc546eeSRichard Henderson TRANS(SLL_i, ALL, do_shift_i, a, true, true)
41295fc546eeSRichard Henderson TRANS(SRL_i, ALL, do_shift_i, a, false, true)
41305fc546eeSRichard Henderson TRANS(SRA_i, ALL, do_shift_i, a, false, false)
41315fc546eeSRichard Henderson 
4132fb4ed7aaSRichard Henderson static TCGv gen_rs2_or_imm(DisasContext *dc, bool imm, int rs2_or_imm)
4133fb4ed7aaSRichard Henderson {
4134fb4ed7aaSRichard Henderson     /* For simplicity, we under-decoded the rs2 form. */
4135fb4ed7aaSRichard Henderson     if (!imm && rs2_or_imm & ~0x1f) {
4136fb4ed7aaSRichard Henderson         return NULL;
4137fb4ed7aaSRichard Henderson     }
4138fb4ed7aaSRichard Henderson     if (imm || rs2_or_imm == 0) {
4139fb4ed7aaSRichard Henderson         return tcg_constant_tl(rs2_or_imm);
4140fb4ed7aaSRichard Henderson     } else {
4141fb4ed7aaSRichard Henderson         return cpu_regs[rs2_or_imm];
4142fb4ed7aaSRichard Henderson     }
4143fb4ed7aaSRichard Henderson }
4144fb4ed7aaSRichard Henderson 
4145fb4ed7aaSRichard Henderson static bool do_mov_cond(DisasContext *dc, DisasCompare *cmp, int rd, TCGv src2)
4146fb4ed7aaSRichard Henderson {
4147fb4ed7aaSRichard Henderson     TCGv dst = gen_load_gpr(dc, rd);
4148c8507ebfSRichard Henderson     TCGv c2 = tcg_constant_tl(cmp->c2);
4149fb4ed7aaSRichard Henderson 
4150c8507ebfSRichard Henderson     tcg_gen_movcond_tl(cmp->cond, dst, cmp->c1, c2, src2, dst);
4151fb4ed7aaSRichard Henderson     gen_store_gpr(dc, rd, dst);
4152fb4ed7aaSRichard Henderson     return advance_pc(dc);
4153fb4ed7aaSRichard Henderson }
4154fb4ed7aaSRichard Henderson 
4155fb4ed7aaSRichard Henderson static bool trans_MOVcc(DisasContext *dc, arg_MOVcc *a)
4156fb4ed7aaSRichard Henderson {
4157fb4ed7aaSRichard Henderson     TCGv src2 = gen_rs2_or_imm(dc, a->imm, a->rs2_or_imm);
4158fb4ed7aaSRichard Henderson     DisasCompare cmp;
4159fb4ed7aaSRichard Henderson 
4160fb4ed7aaSRichard Henderson     if (src2 == NULL) {
4161fb4ed7aaSRichard Henderson         return false;
4162fb4ed7aaSRichard Henderson     }
4163fb4ed7aaSRichard Henderson     gen_compare(&cmp, a->cc, a->cond, dc);
4164fb4ed7aaSRichard Henderson     return do_mov_cond(dc, &cmp, a->rd, src2);
4165fb4ed7aaSRichard Henderson }
4166fb4ed7aaSRichard Henderson 
4167fb4ed7aaSRichard Henderson static bool trans_MOVfcc(DisasContext *dc, arg_MOVfcc *a)
4168fb4ed7aaSRichard Henderson {
4169fb4ed7aaSRichard Henderson     TCGv src2 = gen_rs2_or_imm(dc, a->imm, a->rs2_or_imm);
4170fb4ed7aaSRichard Henderson     DisasCompare cmp;
4171fb4ed7aaSRichard Henderson 
4172fb4ed7aaSRichard Henderson     if (src2 == NULL) {
4173fb4ed7aaSRichard Henderson         return false;
4174fb4ed7aaSRichard Henderson     }
4175fb4ed7aaSRichard Henderson     gen_fcompare(&cmp, a->cc, a->cond);
4176fb4ed7aaSRichard Henderson     return do_mov_cond(dc, &cmp, a->rd, src2);
4177fb4ed7aaSRichard Henderson }
4178fb4ed7aaSRichard Henderson 
4179fb4ed7aaSRichard Henderson static bool trans_MOVR(DisasContext *dc, arg_MOVR *a)
4180fb4ed7aaSRichard Henderson {
4181fb4ed7aaSRichard Henderson     TCGv src2 = gen_rs2_or_imm(dc, a->imm, a->rs2_or_imm);
4182fb4ed7aaSRichard Henderson     DisasCompare cmp;
4183fb4ed7aaSRichard Henderson 
4184fb4ed7aaSRichard Henderson     if (src2 == NULL) {
4185fb4ed7aaSRichard Henderson         return false;
4186fb4ed7aaSRichard Henderson     }
41872c4f56c9SRichard Henderson     if (!gen_compare_reg(&cmp, a->cond, gen_load_gpr(dc, a->rs1))) {
41882c4f56c9SRichard Henderson         return false;
41892c4f56c9SRichard Henderson     }
4190fb4ed7aaSRichard Henderson     return do_mov_cond(dc, &cmp, a->rd, src2);
4191fb4ed7aaSRichard Henderson }
4192fb4ed7aaSRichard Henderson 
419386b82fe0SRichard Henderson static bool do_add_special(DisasContext *dc, arg_r_r_ri *a,
419486b82fe0SRichard Henderson                            bool (*func)(DisasContext *dc, int rd, TCGv src))
419586b82fe0SRichard Henderson {
419686b82fe0SRichard Henderson     TCGv src1, sum;
419786b82fe0SRichard Henderson 
419886b82fe0SRichard Henderson     /* For simplicity, we under-decoded the rs2 form. */
419986b82fe0SRichard Henderson     if (!a->imm && a->rs2_or_imm & ~0x1f) {
420086b82fe0SRichard Henderson         return false;
420186b82fe0SRichard Henderson     }
420286b82fe0SRichard Henderson 
420386b82fe0SRichard Henderson     /*
420486b82fe0SRichard Henderson      * Always load the sum into a new temporary.
420586b82fe0SRichard Henderson      * This is required to capture the value across a window change,
420686b82fe0SRichard Henderson      * e.g. SAVE and RESTORE, and may be optimized away otherwise.
420786b82fe0SRichard Henderson      */
420886b82fe0SRichard Henderson     sum = tcg_temp_new();
420986b82fe0SRichard Henderson     src1 = gen_load_gpr(dc, a->rs1);
421086b82fe0SRichard Henderson     if (a->imm || a->rs2_or_imm == 0) {
421186b82fe0SRichard Henderson         tcg_gen_addi_tl(sum, src1, a->rs2_or_imm);
421286b82fe0SRichard Henderson     } else {
421386b82fe0SRichard Henderson         tcg_gen_add_tl(sum, src1, cpu_regs[a->rs2_or_imm]);
421486b82fe0SRichard Henderson     }
421586b82fe0SRichard Henderson     return func(dc, a->rd, sum);
421686b82fe0SRichard Henderson }
421786b82fe0SRichard Henderson 
421886b82fe0SRichard Henderson static bool do_jmpl(DisasContext *dc, int rd, TCGv src)
421986b82fe0SRichard Henderson {
422086b82fe0SRichard Henderson     /*
422186b82fe0SRichard Henderson      * Preserve pc across advance, so that we can delay
422286b82fe0SRichard Henderson      * the writeback to rd until after src is consumed.
422386b82fe0SRichard Henderson      */
422486b82fe0SRichard Henderson     target_ulong cur_pc = dc->pc;
422586b82fe0SRichard Henderson 
422686b82fe0SRichard Henderson     gen_check_align(dc, src, 3);
422786b82fe0SRichard Henderson 
422886b82fe0SRichard Henderson     gen_mov_pc_npc(dc);
422986b82fe0SRichard Henderson     tcg_gen_mov_tl(cpu_npc, src);
423086b82fe0SRichard Henderson     gen_address_mask(dc, cpu_npc);
423186b82fe0SRichard Henderson     gen_store_gpr(dc, rd, tcg_constant_tl(cur_pc));
423286b82fe0SRichard Henderson 
423386b82fe0SRichard Henderson     dc->npc = DYNAMIC_PC_LOOKUP;
423486b82fe0SRichard Henderson     return true;
423586b82fe0SRichard Henderson }
423686b82fe0SRichard Henderson 
423786b82fe0SRichard Henderson TRANS(JMPL, ALL, do_add_special, a, do_jmpl)
423886b82fe0SRichard Henderson 
423986b82fe0SRichard Henderson static bool do_rett(DisasContext *dc, int rd, TCGv src)
424086b82fe0SRichard Henderson {
424186b82fe0SRichard Henderson     if (!supervisor(dc)) {
424286b82fe0SRichard Henderson         return raise_priv(dc);
424386b82fe0SRichard Henderson     }
424486b82fe0SRichard Henderson 
424586b82fe0SRichard Henderson     gen_check_align(dc, src, 3);
424686b82fe0SRichard Henderson 
424786b82fe0SRichard Henderson     gen_mov_pc_npc(dc);
424886b82fe0SRichard Henderson     tcg_gen_mov_tl(cpu_npc, src);
424986b82fe0SRichard Henderson     gen_helper_rett(tcg_env);
425086b82fe0SRichard Henderson 
425186b82fe0SRichard Henderson     dc->npc = DYNAMIC_PC;
425286b82fe0SRichard Henderson     return true;
425386b82fe0SRichard Henderson }
425486b82fe0SRichard Henderson 
425586b82fe0SRichard Henderson TRANS(RETT, 32, do_add_special, a, do_rett)
425686b82fe0SRichard Henderson 
425786b82fe0SRichard Henderson static bool do_return(DisasContext *dc, int rd, TCGv src)
425886b82fe0SRichard Henderson {
425986b82fe0SRichard Henderson     gen_check_align(dc, src, 3);
42600dfae4f9SRichard Henderson     gen_helper_restore(tcg_env);
426186b82fe0SRichard Henderson 
426286b82fe0SRichard Henderson     gen_mov_pc_npc(dc);
426386b82fe0SRichard Henderson     tcg_gen_mov_tl(cpu_npc, src);
426486b82fe0SRichard Henderson     gen_address_mask(dc, cpu_npc);
426586b82fe0SRichard Henderson 
426686b82fe0SRichard Henderson     dc->npc = DYNAMIC_PC_LOOKUP;
426786b82fe0SRichard Henderson     return true;
426886b82fe0SRichard Henderson }
426986b82fe0SRichard Henderson 
427086b82fe0SRichard Henderson TRANS(RETURN, 64, do_add_special, a, do_return)
427186b82fe0SRichard Henderson 
4272d3825800SRichard Henderson static bool do_save(DisasContext *dc, int rd, TCGv src)
4273d3825800SRichard Henderson {
4274d3825800SRichard Henderson     gen_helper_save(tcg_env);
4275d3825800SRichard Henderson     gen_store_gpr(dc, rd, src);
4276d3825800SRichard Henderson     return advance_pc(dc);
4277d3825800SRichard Henderson }
4278d3825800SRichard Henderson 
4279d3825800SRichard Henderson TRANS(SAVE, ALL, do_add_special, a, do_save)
4280d3825800SRichard Henderson 
4281d3825800SRichard Henderson static bool do_restore(DisasContext *dc, int rd, TCGv src)
4282d3825800SRichard Henderson {
4283d3825800SRichard Henderson     gen_helper_restore(tcg_env);
4284d3825800SRichard Henderson     gen_store_gpr(dc, rd, src);
4285d3825800SRichard Henderson     return advance_pc(dc);
4286d3825800SRichard Henderson }
4287d3825800SRichard Henderson 
4288d3825800SRichard Henderson TRANS(RESTORE, ALL, do_add_special, a, do_restore)
4289d3825800SRichard Henderson 
42908f75b8a4SRichard Henderson static bool do_done_retry(DisasContext *dc, bool done)
42918f75b8a4SRichard Henderson {
42928f75b8a4SRichard Henderson     if (!supervisor(dc)) {
42938f75b8a4SRichard Henderson         return raise_priv(dc);
42948f75b8a4SRichard Henderson     }
42958f75b8a4SRichard Henderson     dc->npc = DYNAMIC_PC;
42968f75b8a4SRichard Henderson     dc->pc = DYNAMIC_PC;
42978f75b8a4SRichard Henderson     translator_io_start(&dc->base);
42988f75b8a4SRichard Henderson     if (done) {
42998f75b8a4SRichard Henderson         gen_helper_done(tcg_env);
43008f75b8a4SRichard Henderson     } else {
43018f75b8a4SRichard Henderson         gen_helper_retry(tcg_env);
43028f75b8a4SRichard Henderson     }
43038f75b8a4SRichard Henderson     return true;
43048f75b8a4SRichard Henderson }
43058f75b8a4SRichard Henderson 
43068f75b8a4SRichard Henderson TRANS(DONE, 64, do_done_retry, true)
43078f75b8a4SRichard Henderson TRANS(RETRY, 64, do_done_retry, false)
43088f75b8a4SRichard Henderson 
43090880d20bSRichard Henderson /*
43100880d20bSRichard Henderson  * Major opcode 11 -- load and store instructions
43110880d20bSRichard Henderson  */
43120880d20bSRichard Henderson 
43130880d20bSRichard Henderson static TCGv gen_ldst_addr(DisasContext *dc, int rs1, bool imm, int rs2_or_imm)
43140880d20bSRichard Henderson {
43150880d20bSRichard Henderson     TCGv addr, tmp = NULL;
43160880d20bSRichard Henderson 
43170880d20bSRichard Henderson     /* For simplicity, we under-decoded the rs2 form. */
43180880d20bSRichard Henderson     if (!imm && rs2_or_imm & ~0x1f) {
43190880d20bSRichard Henderson         return NULL;
43200880d20bSRichard Henderson     }
43210880d20bSRichard Henderson 
43220880d20bSRichard Henderson     addr = gen_load_gpr(dc, rs1);
43230880d20bSRichard Henderson     if (rs2_or_imm) {
43240880d20bSRichard Henderson         tmp = tcg_temp_new();
43250880d20bSRichard Henderson         if (imm) {
43260880d20bSRichard Henderson             tcg_gen_addi_tl(tmp, addr, rs2_or_imm);
43270880d20bSRichard Henderson         } else {
43280880d20bSRichard Henderson             tcg_gen_add_tl(tmp, addr, cpu_regs[rs2_or_imm]);
43290880d20bSRichard Henderson         }
43300880d20bSRichard Henderson         addr = tmp;
43310880d20bSRichard Henderson     }
43320880d20bSRichard Henderson     if (AM_CHECK(dc)) {
43330880d20bSRichard Henderson         if (!tmp) {
43340880d20bSRichard Henderson             tmp = tcg_temp_new();
43350880d20bSRichard Henderson         }
43360880d20bSRichard Henderson         tcg_gen_ext32u_tl(tmp, addr);
43370880d20bSRichard Henderson         addr = tmp;
43380880d20bSRichard Henderson     }
43390880d20bSRichard Henderson     return addr;
43400880d20bSRichard Henderson }
43410880d20bSRichard Henderson 
43420880d20bSRichard Henderson static bool do_ld_gpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp mop)
43430880d20bSRichard Henderson {
43440880d20bSRichard Henderson     TCGv reg, addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
43450880d20bSRichard Henderson     DisasASI da;
43460880d20bSRichard Henderson 
43470880d20bSRichard Henderson     if (addr == NULL) {
43480880d20bSRichard Henderson         return false;
43490880d20bSRichard Henderson     }
43500880d20bSRichard Henderson     da = resolve_asi(dc, a->asi, mop);
43510880d20bSRichard Henderson 
43520880d20bSRichard Henderson     reg = gen_dest_gpr(dc, a->rd);
435342071fc1SRichard Henderson     gen_ld_asi(dc, &da, reg, addr);
43540880d20bSRichard Henderson     gen_store_gpr(dc, a->rd, reg);
43550880d20bSRichard Henderson     return advance_pc(dc);
43560880d20bSRichard Henderson }
43570880d20bSRichard Henderson 
43580880d20bSRichard Henderson TRANS(LDUW, ALL, do_ld_gpr, a, MO_TEUL)
43590880d20bSRichard Henderson TRANS(LDUB, ALL, do_ld_gpr, a, MO_UB)
43600880d20bSRichard Henderson TRANS(LDUH, ALL, do_ld_gpr, a, MO_TEUW)
43610880d20bSRichard Henderson TRANS(LDSB, ALL, do_ld_gpr, a, MO_SB)
43620880d20bSRichard Henderson TRANS(LDSH, ALL, do_ld_gpr, a, MO_TESW)
43630880d20bSRichard Henderson TRANS(LDSW, 64, do_ld_gpr, a, MO_TESL)
43640880d20bSRichard Henderson TRANS(LDX, 64, do_ld_gpr, a, MO_TEUQ)
43650880d20bSRichard Henderson 
43660880d20bSRichard Henderson static bool do_st_gpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp mop)
43670880d20bSRichard Henderson {
43680880d20bSRichard Henderson     TCGv reg, addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
43690880d20bSRichard Henderson     DisasASI da;
43700880d20bSRichard Henderson 
43710880d20bSRichard Henderson     if (addr == NULL) {
43720880d20bSRichard Henderson         return false;
43730880d20bSRichard Henderson     }
43740880d20bSRichard Henderson     da = resolve_asi(dc, a->asi, mop);
43750880d20bSRichard Henderson 
43760880d20bSRichard Henderson     reg = gen_load_gpr(dc, a->rd);
437742071fc1SRichard Henderson     gen_st_asi(dc, &da, reg, addr);
43780880d20bSRichard Henderson     return advance_pc(dc);
43790880d20bSRichard Henderson }
43800880d20bSRichard Henderson 
43810880d20bSRichard Henderson TRANS(STW, ALL, do_st_gpr, a, MO_TEUL)
43820880d20bSRichard Henderson TRANS(STB, ALL, do_st_gpr, a, MO_UB)
43830880d20bSRichard Henderson TRANS(STH, ALL, do_st_gpr, a, MO_TEUW)
43840880d20bSRichard Henderson TRANS(STX, 64, do_st_gpr, a, MO_TEUQ)
43850880d20bSRichard Henderson 
43860880d20bSRichard Henderson static bool trans_LDD(DisasContext *dc, arg_r_r_ri_asi *a)
43870880d20bSRichard Henderson {
43880880d20bSRichard Henderson     TCGv addr;
43890880d20bSRichard Henderson     DisasASI da;
43900880d20bSRichard Henderson 
43910880d20bSRichard Henderson     if (a->rd & 1) {
43920880d20bSRichard Henderson         return false;
43930880d20bSRichard Henderson     }
43940880d20bSRichard Henderson     addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
43950880d20bSRichard Henderson     if (addr == NULL) {
43960880d20bSRichard Henderson         return false;
43970880d20bSRichard Henderson     }
43980880d20bSRichard Henderson     da = resolve_asi(dc, a->asi, MO_TEUQ);
439942071fc1SRichard Henderson     gen_ldda_asi(dc, &da, addr, a->rd);
44000880d20bSRichard Henderson     return advance_pc(dc);
44010880d20bSRichard Henderson }
44020880d20bSRichard Henderson 
44030880d20bSRichard Henderson static bool trans_STD(DisasContext *dc, arg_r_r_ri_asi *a)
44040880d20bSRichard Henderson {
44050880d20bSRichard Henderson     TCGv addr;
44060880d20bSRichard Henderson     DisasASI da;
44070880d20bSRichard Henderson 
44080880d20bSRichard Henderson     if (a->rd & 1) {
44090880d20bSRichard Henderson         return false;
44100880d20bSRichard Henderson     }
44110880d20bSRichard Henderson     addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
44120880d20bSRichard Henderson     if (addr == NULL) {
44130880d20bSRichard Henderson         return false;
44140880d20bSRichard Henderson     }
44150880d20bSRichard Henderson     da = resolve_asi(dc, a->asi, MO_TEUQ);
441642071fc1SRichard Henderson     gen_stda_asi(dc, &da, addr, a->rd);
44170880d20bSRichard Henderson     return advance_pc(dc);
44180880d20bSRichard Henderson }
44190880d20bSRichard Henderson 
4420cf07cd1eSRichard Henderson static bool trans_LDSTUB(DisasContext *dc, arg_r_r_ri_asi *a)
4421cf07cd1eSRichard Henderson {
4422cf07cd1eSRichard Henderson     TCGv addr, reg;
4423cf07cd1eSRichard Henderson     DisasASI da;
4424cf07cd1eSRichard Henderson 
4425cf07cd1eSRichard Henderson     addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
4426cf07cd1eSRichard Henderson     if (addr == NULL) {
4427cf07cd1eSRichard Henderson         return false;
4428cf07cd1eSRichard Henderson     }
4429cf07cd1eSRichard Henderson     da = resolve_asi(dc, a->asi, MO_UB);
4430cf07cd1eSRichard Henderson 
4431cf07cd1eSRichard Henderson     reg = gen_dest_gpr(dc, a->rd);
4432cf07cd1eSRichard Henderson     gen_ldstub_asi(dc, &da, reg, addr);
4433cf07cd1eSRichard Henderson     gen_store_gpr(dc, a->rd, reg);
4434cf07cd1eSRichard Henderson     return advance_pc(dc);
4435cf07cd1eSRichard Henderson }
4436cf07cd1eSRichard Henderson 
4437dca544b9SRichard Henderson static bool trans_SWAP(DisasContext *dc, arg_r_r_ri_asi *a)
4438dca544b9SRichard Henderson {
4439dca544b9SRichard Henderson     TCGv addr, dst, src;
4440dca544b9SRichard Henderson     DisasASI da;
4441dca544b9SRichard Henderson 
4442dca544b9SRichard Henderson     addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
4443dca544b9SRichard Henderson     if (addr == NULL) {
4444dca544b9SRichard Henderson         return false;
4445dca544b9SRichard Henderson     }
4446dca544b9SRichard Henderson     da = resolve_asi(dc, a->asi, MO_TEUL);
4447dca544b9SRichard Henderson 
4448dca544b9SRichard Henderson     dst = gen_dest_gpr(dc, a->rd);
4449dca544b9SRichard Henderson     src = gen_load_gpr(dc, a->rd);
4450dca544b9SRichard Henderson     gen_swap_asi(dc, &da, dst, src, addr);
4451dca544b9SRichard Henderson     gen_store_gpr(dc, a->rd, dst);
4452dca544b9SRichard Henderson     return advance_pc(dc);
4453dca544b9SRichard Henderson }
4454dca544b9SRichard Henderson 
4455d0a11d25SRichard Henderson static bool do_casa(DisasContext *dc, arg_r_r_ri_asi *a, MemOp mop)
4456d0a11d25SRichard Henderson {
4457d0a11d25SRichard Henderson     TCGv addr, o, n, c;
4458d0a11d25SRichard Henderson     DisasASI da;
4459d0a11d25SRichard Henderson 
4460d0a11d25SRichard Henderson     addr = gen_ldst_addr(dc, a->rs1, true, 0);
4461d0a11d25SRichard Henderson     if (addr == NULL) {
4462d0a11d25SRichard Henderson         return false;
4463d0a11d25SRichard Henderson     }
4464d0a11d25SRichard Henderson     da = resolve_asi(dc, a->asi, mop);
4465d0a11d25SRichard Henderson 
4466d0a11d25SRichard Henderson     o = gen_dest_gpr(dc, a->rd);
4467d0a11d25SRichard Henderson     n = gen_load_gpr(dc, a->rd);
4468d0a11d25SRichard Henderson     c = gen_load_gpr(dc, a->rs2_or_imm);
4469d0a11d25SRichard Henderson     gen_cas_asi(dc, &da, o, n, c, addr);
4470d0a11d25SRichard Henderson     gen_store_gpr(dc, a->rd, o);
4471d0a11d25SRichard Henderson     return advance_pc(dc);
4472d0a11d25SRichard Henderson }
4473d0a11d25SRichard Henderson 
4474d0a11d25SRichard Henderson TRANS(CASA, CASA, do_casa, a, MO_TEUL)
4475d0a11d25SRichard Henderson TRANS(CASXA, 64, do_casa, a, MO_TEUQ)
4476d0a11d25SRichard Henderson 
447706c060d9SRichard Henderson static bool do_ld_fpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp sz)
447806c060d9SRichard Henderson {
447906c060d9SRichard Henderson     TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
448006c060d9SRichard Henderson     DisasASI da;
448106c060d9SRichard Henderson 
448206c060d9SRichard Henderson     if (addr == NULL) {
448306c060d9SRichard Henderson         return false;
448406c060d9SRichard Henderson     }
448506c060d9SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
448606c060d9SRichard Henderson         return true;
448706c060d9SRichard Henderson     }
448806c060d9SRichard Henderson     if (sz == MO_128 && gen_trap_float128(dc)) {
448906c060d9SRichard Henderson         return true;
449006c060d9SRichard Henderson     }
449106c060d9SRichard Henderson     da = resolve_asi(dc, a->asi, MO_TE | sz);
4492287b1152SRichard Henderson     gen_ldf_asi(dc, &da, sz, addr, a->rd);
449306c060d9SRichard Henderson     gen_update_fprs_dirty(dc, a->rd);
449406c060d9SRichard Henderson     return advance_pc(dc);
449506c060d9SRichard Henderson }
449606c060d9SRichard Henderson 
449706c060d9SRichard Henderson TRANS(LDF, ALL, do_ld_fpr, a, MO_32)
449806c060d9SRichard Henderson TRANS(LDDF, ALL, do_ld_fpr, a, MO_64)
449906c060d9SRichard Henderson TRANS(LDQF, ALL, do_ld_fpr, a, MO_128)
450006c060d9SRichard Henderson 
4501287b1152SRichard Henderson TRANS(LDFA, 64, do_ld_fpr, a, MO_32)
4502287b1152SRichard Henderson TRANS(LDDFA, 64, do_ld_fpr, a, MO_64)
4503287b1152SRichard Henderson TRANS(LDQFA, 64, do_ld_fpr, a, MO_128)
4504287b1152SRichard Henderson 
450506c060d9SRichard Henderson static bool do_st_fpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp sz)
450606c060d9SRichard Henderson {
450706c060d9SRichard Henderson     TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
450806c060d9SRichard Henderson     DisasASI da;
450906c060d9SRichard Henderson 
451006c060d9SRichard Henderson     if (addr == NULL) {
451106c060d9SRichard Henderson         return false;
451206c060d9SRichard Henderson     }
451306c060d9SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
451406c060d9SRichard Henderson         return true;
451506c060d9SRichard Henderson     }
451606c060d9SRichard Henderson     if (sz == MO_128 && gen_trap_float128(dc)) {
451706c060d9SRichard Henderson         return true;
451806c060d9SRichard Henderson     }
451906c060d9SRichard Henderson     da = resolve_asi(dc, a->asi, MO_TE | sz);
4520287b1152SRichard Henderson     gen_stf_asi(dc, &da, sz, addr, a->rd);
452106c060d9SRichard Henderson     return advance_pc(dc);
452206c060d9SRichard Henderson }
452306c060d9SRichard Henderson 
452406c060d9SRichard Henderson TRANS(STF, ALL, do_st_fpr, a, MO_32)
452506c060d9SRichard Henderson TRANS(STDF, ALL, do_st_fpr, a, MO_64)
452612d36294SRichard Henderson TRANS(STQF, 64, do_st_fpr, a, MO_128)
452706c060d9SRichard Henderson 
4528287b1152SRichard Henderson TRANS(STFA, 64, do_st_fpr, a, MO_32)
4529287b1152SRichard Henderson TRANS(STDFA, 64, do_st_fpr, a, MO_64)
4530287b1152SRichard Henderson TRANS(STQFA, 64, do_st_fpr, a, MO_128)
4531287b1152SRichard Henderson 
453206c060d9SRichard Henderson static bool trans_STDFQ(DisasContext *dc, arg_STDFQ *a)
453306c060d9SRichard Henderson {
4534*29b99802SRichard Henderson     TCGv addr;
4535*29b99802SRichard Henderson 
453606c060d9SRichard Henderson     if (!avail_32(dc)) {
453706c060d9SRichard Henderson         return false;
453806c060d9SRichard Henderson     }
4539*29b99802SRichard Henderson     addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
4540*29b99802SRichard Henderson     if (addr == NULL) {
4541*29b99802SRichard Henderson         return false;
4542*29b99802SRichard Henderson     }
454306c060d9SRichard Henderson     if (!supervisor(dc)) {
454406c060d9SRichard Henderson         return raise_priv(dc);
454506c060d9SRichard Henderson     }
4546*29b99802SRichard Henderson #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
454706c060d9SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
454806c060d9SRichard Henderson         return true;
454906c060d9SRichard Henderson     }
4550*29b99802SRichard Henderson     if (!dc->fsr_qne) {
455106c060d9SRichard Henderson         gen_op_fpexception_im(dc, FSR_FTT_SEQ_ERROR);
455206c060d9SRichard Henderson         return true;
455306c060d9SRichard Henderson     }
455406c060d9SRichard Henderson 
4555*29b99802SRichard Henderson     /* Store the single element from the queue. */
4556*29b99802SRichard Henderson     TCGv_i64 fq = tcg_temp_new_i64();
4557*29b99802SRichard Henderson     tcg_gen_ld_i64(fq, tcg_env, offsetof(CPUSPARCState, fq.d));
4558*29b99802SRichard Henderson     tcg_gen_qemu_st_i64(fq, addr, dc->mem_idx, MO_TEUQ | MO_ALIGN_4);
4559*29b99802SRichard Henderson 
4560*29b99802SRichard Henderson     /* Mark the queue empty, transitioning to fp_execute state. */
4561*29b99802SRichard Henderson     tcg_gen_st_i32(tcg_constant_i32(0), tcg_env,
4562*29b99802SRichard Henderson                    offsetof(CPUSPARCState, fsr_qne));
4563*29b99802SRichard Henderson     dc->fsr_qne = 0;
4564*29b99802SRichard Henderson 
4565*29b99802SRichard Henderson     return advance_pc(dc);
4566*29b99802SRichard Henderson #else
4567*29b99802SRichard Henderson     qemu_build_not_reached();
4568*29b99802SRichard Henderson #endif
4569*29b99802SRichard Henderson }
4570*29b99802SRichard Henderson 
4571d8c5b92fSRichard Henderson static bool trans_LDFSR(DisasContext *dc, arg_r_r_ri *a)
45723d3c0673SRichard Henderson {
45733590f01eSRichard Henderson     TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
4574d8c5b92fSRichard Henderson     TCGv_i32 tmp;
45753590f01eSRichard Henderson 
45763d3c0673SRichard Henderson     if (addr == NULL) {
45773d3c0673SRichard Henderson         return false;
45783d3c0673SRichard Henderson     }
45793d3c0673SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
45803d3c0673SRichard Henderson         return true;
45813d3c0673SRichard Henderson     }
4582d8c5b92fSRichard Henderson 
4583d8c5b92fSRichard Henderson     tmp = tcg_temp_new_i32();
4584d8c5b92fSRichard Henderson     tcg_gen_qemu_ld_i32(tmp, addr, dc->mem_idx, MO_TEUL | MO_ALIGN);
4585d8c5b92fSRichard Henderson 
4586d8c5b92fSRichard Henderson     tcg_gen_extract_i32(cpu_fcc[0], tmp, FSR_FCC0_SHIFT, 2);
4587d8c5b92fSRichard Henderson     /* LDFSR does not change FCC[1-3]. */
4588d8c5b92fSRichard Henderson 
4589d8c5b92fSRichard Henderson     gen_helper_set_fsr_nofcc_noftt(tcg_env, tmp);
45903d3c0673SRichard Henderson     return advance_pc(dc);
45913d3c0673SRichard Henderson }
45923d3c0673SRichard Henderson 
4593298c52f7SRichard Henderson static bool do_ldxfsr(DisasContext *dc, arg_r_r_ri *a, bool entire)
4594d8c5b92fSRichard Henderson {
4595d8c5b92fSRichard Henderson #ifdef TARGET_SPARC64
4596d8c5b92fSRichard Henderson     TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
4597d8c5b92fSRichard Henderson     TCGv_i64 t64;
4598d8c5b92fSRichard Henderson     TCGv_i32 lo, hi;
4599d8c5b92fSRichard Henderson 
4600d8c5b92fSRichard Henderson     if (addr == NULL) {
4601d8c5b92fSRichard Henderson         return false;
4602d8c5b92fSRichard Henderson     }
4603d8c5b92fSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4604d8c5b92fSRichard Henderson         return true;
4605d8c5b92fSRichard Henderson     }
4606d8c5b92fSRichard Henderson 
4607d8c5b92fSRichard Henderson     t64 = tcg_temp_new_i64();
4608d8c5b92fSRichard Henderson     tcg_gen_qemu_ld_i64(t64, addr, dc->mem_idx, MO_TEUQ | MO_ALIGN);
4609d8c5b92fSRichard Henderson 
4610d8c5b92fSRichard Henderson     lo = tcg_temp_new_i32();
4611d8c5b92fSRichard Henderson     hi = cpu_fcc[3];
4612d8c5b92fSRichard Henderson     tcg_gen_extr_i64_i32(lo, hi, t64);
4613d8c5b92fSRichard Henderson     tcg_gen_extract_i32(cpu_fcc[0], lo, FSR_FCC0_SHIFT, 2);
4614d8c5b92fSRichard Henderson     tcg_gen_extract_i32(cpu_fcc[1], hi, FSR_FCC1_SHIFT - 32, 2);
4615d8c5b92fSRichard Henderson     tcg_gen_extract_i32(cpu_fcc[2], hi, FSR_FCC2_SHIFT - 32, 2);
4616d8c5b92fSRichard Henderson     tcg_gen_extract_i32(cpu_fcc[3], hi, FSR_FCC3_SHIFT - 32, 2);
4617d8c5b92fSRichard Henderson 
4618298c52f7SRichard Henderson     if (entire) {
4619298c52f7SRichard Henderson         gen_helper_set_fsr_nofcc(tcg_env, lo);
4620298c52f7SRichard Henderson     } else {
4621d8c5b92fSRichard Henderson         gen_helper_set_fsr_nofcc_noftt(tcg_env, lo);
4622298c52f7SRichard Henderson     }
4623d8c5b92fSRichard Henderson     return advance_pc(dc);
4624d8c5b92fSRichard Henderson #else
4625d8c5b92fSRichard Henderson     return false;
4626d8c5b92fSRichard Henderson #endif
4627d8c5b92fSRichard Henderson }
46283d3c0673SRichard Henderson 
4629298c52f7SRichard Henderson TRANS(LDXFSR, 64, do_ldxfsr, a, false)
4630298c52f7SRichard Henderson TRANS(LDXEFSR, VIS3B, do_ldxfsr, a, true)
4631298c52f7SRichard Henderson 
46323d3c0673SRichard Henderson static bool do_stfsr(DisasContext *dc, arg_r_r_ri *a, MemOp mop)
46333d3c0673SRichard Henderson {
46343d3c0673SRichard Henderson     TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
46351ccd6e13SRichard Henderson     TCGv fsr;
46361ccd6e13SRichard Henderson 
46373d3c0673SRichard Henderson     if (addr == NULL) {
46383d3c0673SRichard Henderson         return false;
46393d3c0673SRichard Henderson     }
46403d3c0673SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
46413d3c0673SRichard Henderson         return true;
46423d3c0673SRichard Henderson     }
46431ccd6e13SRichard Henderson 
46441ccd6e13SRichard Henderson     fsr = tcg_temp_new();
46451ccd6e13SRichard Henderson     gen_helper_get_fsr(fsr, tcg_env);
46461ccd6e13SRichard Henderson     tcg_gen_qemu_st_tl(fsr, addr, dc->mem_idx, mop | MO_ALIGN);
46473d3c0673SRichard Henderson     return advance_pc(dc);
46483d3c0673SRichard Henderson }
46493d3c0673SRichard Henderson 
46503d3c0673SRichard Henderson TRANS(STFSR, ALL, do_stfsr, a, MO_TEUL)
46513d3c0673SRichard Henderson TRANS(STXFSR, 64, do_stfsr, a, MO_TEUQ)
46523d3c0673SRichard Henderson 
46531210a036SRichard Henderson static bool do_fc(DisasContext *dc, int rd, int32_t c)
46543a38260eSRichard Henderson {
46553a38260eSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
46563a38260eSRichard Henderson         return true;
46573a38260eSRichard Henderson     }
46581210a036SRichard Henderson     gen_store_fpr_F(dc, rd, tcg_constant_i32(c));
46593a38260eSRichard Henderson     return advance_pc(dc);
46603a38260eSRichard Henderson }
46613a38260eSRichard Henderson 
46623a38260eSRichard Henderson TRANS(FZEROs, VIS1, do_fc, a->rd, 0)
46631210a036SRichard Henderson TRANS(FONEs, VIS1, do_fc, a->rd, -1)
46643a38260eSRichard Henderson 
46653a38260eSRichard Henderson static bool do_dc(DisasContext *dc, int rd, int64_t c)
46663a38260eSRichard Henderson {
46673a38260eSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
46683a38260eSRichard Henderson         return true;
46693a38260eSRichard Henderson     }
46701210a036SRichard Henderson     gen_store_fpr_D(dc, rd, tcg_constant_i64(c));
46713a38260eSRichard Henderson     return advance_pc(dc);
46723a38260eSRichard Henderson }
46733a38260eSRichard Henderson 
46743a38260eSRichard Henderson TRANS(FZEROd, VIS1, do_dc, a->rd, 0)
46753a38260eSRichard Henderson TRANS(FONEd, VIS1, do_dc, a->rd, -1)
46763a38260eSRichard Henderson 
4677baf3dbf2SRichard Henderson static bool do_ff(DisasContext *dc, arg_r_r *a,
4678baf3dbf2SRichard Henderson                   void (*func)(TCGv_i32, TCGv_i32))
4679baf3dbf2SRichard Henderson {
4680baf3dbf2SRichard Henderson     TCGv_i32 tmp;
4681baf3dbf2SRichard Henderson 
4682baf3dbf2SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4683baf3dbf2SRichard Henderson         return true;
4684baf3dbf2SRichard Henderson     }
4685baf3dbf2SRichard Henderson 
4686baf3dbf2SRichard Henderson     tmp = gen_load_fpr_F(dc, a->rs);
4687baf3dbf2SRichard Henderson     func(tmp, tmp);
4688baf3dbf2SRichard Henderson     gen_store_fpr_F(dc, a->rd, tmp);
4689baf3dbf2SRichard Henderson     return advance_pc(dc);
4690baf3dbf2SRichard Henderson }
4691baf3dbf2SRichard Henderson 
4692baf3dbf2SRichard Henderson TRANS(FMOVs, ALL, do_ff, a, gen_op_fmovs)
4693baf3dbf2SRichard Henderson TRANS(FNEGs, ALL, do_ff, a, gen_op_fnegs)
4694baf3dbf2SRichard Henderson TRANS(FABSs, ALL, do_ff, a, gen_op_fabss)
4695baf3dbf2SRichard Henderson TRANS(FSRCs, VIS1, do_ff, a, tcg_gen_mov_i32)
4696baf3dbf2SRichard Henderson TRANS(FNOTs, VIS1, do_ff, a, tcg_gen_not_i32)
4697baf3dbf2SRichard Henderson 
46982f722641SRichard Henderson static bool do_fd(DisasContext *dc, arg_r_r *a,
46992f722641SRichard Henderson                   void (*func)(TCGv_i32, TCGv_i64))
47002f722641SRichard Henderson {
47012f722641SRichard Henderson     TCGv_i32 dst;
47022f722641SRichard Henderson     TCGv_i64 src;
47032f722641SRichard Henderson 
47042f722641SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
47052f722641SRichard Henderson         return true;
47062f722641SRichard Henderson     }
47072f722641SRichard Henderson 
4708388a6465SRichard Henderson     dst = tcg_temp_new_i32();
47092f722641SRichard Henderson     src = gen_load_fpr_D(dc, a->rs);
47102f722641SRichard Henderson     func(dst, src);
47112f722641SRichard Henderson     gen_store_fpr_F(dc, a->rd, dst);
47122f722641SRichard Henderson     return advance_pc(dc);
47132f722641SRichard Henderson }
47142f722641SRichard Henderson 
47152f722641SRichard Henderson TRANS(FPACK16, VIS1, do_fd, a, gen_op_fpack16)
47162f722641SRichard Henderson TRANS(FPACKFIX, VIS1, do_fd, a, gen_op_fpackfix)
47172f722641SRichard Henderson 
4718119cb94fSRichard Henderson static bool do_env_ff(DisasContext *dc, arg_r_r *a,
4719119cb94fSRichard Henderson                       void (*func)(TCGv_i32, TCGv_env, TCGv_i32))
4720119cb94fSRichard Henderson {
4721119cb94fSRichard Henderson     TCGv_i32 tmp;
4722119cb94fSRichard Henderson 
4723119cb94fSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4724119cb94fSRichard Henderson         return true;
4725119cb94fSRichard Henderson     }
4726119cb94fSRichard Henderson 
4727119cb94fSRichard Henderson     tmp = gen_load_fpr_F(dc, a->rs);
4728119cb94fSRichard Henderson     func(tmp, tcg_env, tmp);
4729119cb94fSRichard Henderson     gen_store_fpr_F(dc, a->rd, tmp);
4730119cb94fSRichard Henderson     return advance_pc(dc);
4731119cb94fSRichard Henderson }
4732119cb94fSRichard Henderson 
4733119cb94fSRichard Henderson TRANS(FSQRTs, ALL, do_env_ff, a, gen_helper_fsqrts)
4734119cb94fSRichard Henderson TRANS(FiTOs, ALL, do_env_ff, a, gen_helper_fitos)
4735119cb94fSRichard Henderson TRANS(FsTOi, ALL, do_env_ff, a, gen_helper_fstoi)
4736119cb94fSRichard Henderson 
47378c94bcd8SRichard Henderson static bool do_env_fd(DisasContext *dc, arg_r_r *a,
47388c94bcd8SRichard Henderson                       void (*func)(TCGv_i32, TCGv_env, TCGv_i64))
47398c94bcd8SRichard Henderson {
47408c94bcd8SRichard Henderson     TCGv_i32 dst;
47418c94bcd8SRichard Henderson     TCGv_i64 src;
47428c94bcd8SRichard Henderson 
47438c94bcd8SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
47448c94bcd8SRichard Henderson         return true;
47458c94bcd8SRichard Henderson     }
47468c94bcd8SRichard Henderson 
4747388a6465SRichard Henderson     dst = tcg_temp_new_i32();
47488c94bcd8SRichard Henderson     src = gen_load_fpr_D(dc, a->rs);
47498c94bcd8SRichard Henderson     func(dst, tcg_env, src);
47508c94bcd8SRichard Henderson     gen_store_fpr_F(dc, a->rd, dst);
47518c94bcd8SRichard Henderson     return advance_pc(dc);
47528c94bcd8SRichard Henderson }
47538c94bcd8SRichard Henderson 
47548c94bcd8SRichard Henderson TRANS(FdTOs, ALL, do_env_fd, a, gen_helper_fdtos)
47558c94bcd8SRichard Henderson TRANS(FdTOi, ALL, do_env_fd, a, gen_helper_fdtoi)
47568c94bcd8SRichard Henderson TRANS(FxTOs, 64, do_env_fd, a, gen_helper_fxtos)
47578c94bcd8SRichard Henderson 
4758c6d83e4fSRichard Henderson static bool do_dd(DisasContext *dc, arg_r_r *a,
4759c6d83e4fSRichard Henderson                   void (*func)(TCGv_i64, TCGv_i64))
4760c6d83e4fSRichard Henderson {
4761c6d83e4fSRichard Henderson     TCGv_i64 dst, src;
4762c6d83e4fSRichard Henderson 
4763c6d83e4fSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4764c6d83e4fSRichard Henderson         return true;
4765c6d83e4fSRichard Henderson     }
4766c6d83e4fSRichard Henderson 
476752f46d46SRichard Henderson     dst = tcg_temp_new_i64();
4768c6d83e4fSRichard Henderson     src = gen_load_fpr_D(dc, a->rs);
4769c6d83e4fSRichard Henderson     func(dst, src);
4770c6d83e4fSRichard Henderson     gen_store_fpr_D(dc, a->rd, dst);
4771c6d83e4fSRichard Henderson     return advance_pc(dc);
4772c6d83e4fSRichard Henderson }
4773c6d83e4fSRichard Henderson 
4774c6d83e4fSRichard Henderson TRANS(FMOVd, 64, do_dd, a, gen_op_fmovd)
4775c6d83e4fSRichard Henderson TRANS(FNEGd, 64, do_dd, a, gen_op_fnegd)
4776c6d83e4fSRichard Henderson TRANS(FABSd, 64, do_dd, a, gen_op_fabsd)
4777c6d83e4fSRichard Henderson TRANS(FSRCd, VIS1, do_dd, a, tcg_gen_mov_i64)
4778c6d83e4fSRichard Henderson TRANS(FNOTd, VIS1, do_dd, a, tcg_gen_not_i64)
4779c6d83e4fSRichard Henderson 
47808aa418b3SRichard Henderson static bool do_env_dd(DisasContext *dc, arg_r_r *a,
47818aa418b3SRichard Henderson                       void (*func)(TCGv_i64, TCGv_env, TCGv_i64))
47828aa418b3SRichard Henderson {
47838aa418b3SRichard Henderson     TCGv_i64 dst, src;
47848aa418b3SRichard Henderson 
47858aa418b3SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
47868aa418b3SRichard Henderson         return true;
47878aa418b3SRichard Henderson     }
47888aa418b3SRichard Henderson 
478952f46d46SRichard Henderson     dst = tcg_temp_new_i64();
47908aa418b3SRichard Henderson     src = gen_load_fpr_D(dc, a->rs);
47918aa418b3SRichard Henderson     func(dst, tcg_env, src);
47928aa418b3SRichard Henderson     gen_store_fpr_D(dc, a->rd, dst);
47938aa418b3SRichard Henderson     return advance_pc(dc);
47948aa418b3SRichard Henderson }
47958aa418b3SRichard Henderson 
47968aa418b3SRichard Henderson TRANS(FSQRTd, ALL, do_env_dd, a, gen_helper_fsqrtd)
47978aa418b3SRichard Henderson TRANS(FxTOd, 64, do_env_dd, a, gen_helper_fxtod)
47988aa418b3SRichard Henderson TRANS(FdTOx, 64, do_env_dd, a, gen_helper_fdtox)
47998aa418b3SRichard Henderson 
48007b616f36SRichard Henderson static bool do_df(DisasContext *dc, arg_r_r *a,
48017b616f36SRichard Henderson                   void (*func)(TCGv_i64, TCGv_i32))
48027b616f36SRichard Henderson {
48037b616f36SRichard Henderson     TCGv_i64 dst;
48047b616f36SRichard Henderson     TCGv_i32 src;
48057b616f36SRichard Henderson 
48067b616f36SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
48077b616f36SRichard Henderson         return true;
48087b616f36SRichard Henderson     }
48097b616f36SRichard Henderson 
48107b616f36SRichard Henderson     dst = tcg_temp_new_i64();
48117b616f36SRichard Henderson     src = gen_load_fpr_F(dc, a->rs);
48127b616f36SRichard Henderson     func(dst, src);
48137b616f36SRichard Henderson     gen_store_fpr_D(dc, a->rd, dst);
48147b616f36SRichard Henderson     return advance_pc(dc);
48157b616f36SRichard Henderson }
48167b616f36SRichard Henderson 
48177b616f36SRichard Henderson TRANS(FEXPAND, VIS1, do_df, a, gen_helper_fexpand)
48187b616f36SRichard Henderson 
4819199d43efSRichard Henderson static bool do_env_df(DisasContext *dc, arg_r_r *a,
4820199d43efSRichard Henderson                       void (*func)(TCGv_i64, TCGv_env, TCGv_i32))
4821199d43efSRichard Henderson {
4822199d43efSRichard Henderson     TCGv_i64 dst;
4823199d43efSRichard Henderson     TCGv_i32 src;
4824199d43efSRichard Henderson 
4825199d43efSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4826199d43efSRichard Henderson         return true;
4827199d43efSRichard Henderson     }
4828199d43efSRichard Henderson 
482952f46d46SRichard Henderson     dst = tcg_temp_new_i64();
4830199d43efSRichard Henderson     src = gen_load_fpr_F(dc, a->rs);
4831199d43efSRichard Henderson     func(dst, tcg_env, src);
4832199d43efSRichard Henderson     gen_store_fpr_D(dc, a->rd, dst);
4833199d43efSRichard Henderson     return advance_pc(dc);
4834199d43efSRichard Henderson }
4835199d43efSRichard Henderson 
4836199d43efSRichard Henderson TRANS(FiTOd, ALL, do_env_df, a, gen_helper_fitod)
4837199d43efSRichard Henderson TRANS(FsTOd, ALL, do_env_df, a, gen_helper_fstod)
4838199d43efSRichard Henderson TRANS(FsTOx, 64, do_env_df, a, gen_helper_fstox)
4839199d43efSRichard Henderson 
4840daf457d4SRichard Henderson static bool do_qq(DisasContext *dc, arg_r_r *a,
4841daf457d4SRichard Henderson                   void (*func)(TCGv_i128, TCGv_i128))
4842f4e18df5SRichard Henderson {
484333ec4245SRichard Henderson     TCGv_i128 t;
4844f4e18df5SRichard Henderson 
4845f4e18df5SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4846f4e18df5SRichard Henderson         return true;
4847f4e18df5SRichard Henderson     }
4848f4e18df5SRichard Henderson     if (gen_trap_float128(dc)) {
4849f4e18df5SRichard Henderson         return true;
4850f4e18df5SRichard Henderson     }
4851f4e18df5SRichard Henderson 
4852f4e18df5SRichard Henderson     gen_op_clear_ieee_excp_and_FTT();
485333ec4245SRichard Henderson     t = gen_load_fpr_Q(dc, a->rs);
4854daf457d4SRichard Henderson     func(t, t);
485533ec4245SRichard Henderson     gen_store_fpr_Q(dc, a->rd, t);
4856f4e18df5SRichard Henderson     return advance_pc(dc);
4857f4e18df5SRichard Henderson }
4858f4e18df5SRichard Henderson 
4859daf457d4SRichard Henderson TRANS(FMOVq, 64, do_qq, a, tcg_gen_mov_i128)
4860daf457d4SRichard Henderson TRANS(FNEGq, 64, do_qq, a, gen_op_fnegq)
4861daf457d4SRichard Henderson TRANS(FABSq, 64, do_qq, a, gen_op_fabsq)
4862f4e18df5SRichard Henderson 
4863c995216bSRichard Henderson static bool do_env_qq(DisasContext *dc, arg_r_r *a,
4864e41716beSRichard Henderson                       void (*func)(TCGv_i128, TCGv_env, TCGv_i128))
4865c995216bSRichard Henderson {
4866e41716beSRichard Henderson     TCGv_i128 t;
4867e41716beSRichard Henderson 
4868c995216bSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4869c995216bSRichard Henderson         return true;
4870c995216bSRichard Henderson     }
4871c995216bSRichard Henderson     if (gen_trap_float128(dc)) {
4872c995216bSRichard Henderson         return true;
4873c995216bSRichard Henderson     }
4874c995216bSRichard Henderson 
4875e41716beSRichard Henderson     t = gen_load_fpr_Q(dc, a->rs);
4876e41716beSRichard Henderson     func(t, tcg_env, t);
4877e41716beSRichard Henderson     gen_store_fpr_Q(dc, a->rd, t);
4878c995216bSRichard Henderson     return advance_pc(dc);
4879c995216bSRichard Henderson }
4880c995216bSRichard Henderson 
4881c995216bSRichard Henderson TRANS(FSQRTq, ALL, do_env_qq, a, gen_helper_fsqrtq)
4882c995216bSRichard Henderson 
4883bd9c5c42SRichard Henderson static bool do_env_fq(DisasContext *dc, arg_r_r *a,
4884d81e3efeSRichard Henderson                       void (*func)(TCGv_i32, TCGv_env, TCGv_i128))
4885bd9c5c42SRichard Henderson {
4886d81e3efeSRichard Henderson     TCGv_i128 src;
4887bd9c5c42SRichard Henderson     TCGv_i32 dst;
4888bd9c5c42SRichard Henderson 
4889bd9c5c42SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4890bd9c5c42SRichard Henderson         return true;
4891bd9c5c42SRichard Henderson     }
4892bd9c5c42SRichard Henderson     if (gen_trap_float128(dc)) {
4893bd9c5c42SRichard Henderson         return true;
4894bd9c5c42SRichard Henderson     }
4895bd9c5c42SRichard Henderson 
4896d81e3efeSRichard Henderson     src = gen_load_fpr_Q(dc, a->rs);
4897388a6465SRichard Henderson     dst = tcg_temp_new_i32();
4898d81e3efeSRichard Henderson     func(dst, tcg_env, src);
4899bd9c5c42SRichard Henderson     gen_store_fpr_F(dc, a->rd, dst);
4900bd9c5c42SRichard Henderson     return advance_pc(dc);
4901bd9c5c42SRichard Henderson }
4902bd9c5c42SRichard Henderson 
4903bd9c5c42SRichard Henderson TRANS(FqTOs, ALL, do_env_fq, a, gen_helper_fqtos)
4904bd9c5c42SRichard Henderson TRANS(FqTOi, ALL, do_env_fq, a, gen_helper_fqtoi)
4905bd9c5c42SRichard Henderson 
49061617586fSRichard Henderson static bool do_env_dq(DisasContext *dc, arg_r_r *a,
490725a5769eSRichard Henderson                       void (*func)(TCGv_i64, TCGv_env, TCGv_i128))
49081617586fSRichard Henderson {
490925a5769eSRichard Henderson     TCGv_i128 src;
49101617586fSRichard Henderson     TCGv_i64 dst;
49111617586fSRichard Henderson 
49121617586fSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
49131617586fSRichard Henderson         return true;
49141617586fSRichard Henderson     }
49151617586fSRichard Henderson     if (gen_trap_float128(dc)) {
49161617586fSRichard Henderson         return true;
49171617586fSRichard Henderson     }
49181617586fSRichard Henderson 
491925a5769eSRichard Henderson     src = gen_load_fpr_Q(dc, a->rs);
492052f46d46SRichard Henderson     dst = tcg_temp_new_i64();
492125a5769eSRichard Henderson     func(dst, tcg_env, src);
49221617586fSRichard Henderson     gen_store_fpr_D(dc, a->rd, dst);
49231617586fSRichard Henderson     return advance_pc(dc);
49241617586fSRichard Henderson }
49251617586fSRichard Henderson 
49261617586fSRichard Henderson TRANS(FqTOd, ALL, do_env_dq, a, gen_helper_fqtod)
49271617586fSRichard Henderson TRANS(FqTOx, 64, do_env_dq, a, gen_helper_fqtox)
49281617586fSRichard Henderson 
492913ebcc77SRichard Henderson static bool do_env_qf(DisasContext *dc, arg_r_r *a,
49300b2a61ccSRichard Henderson                       void (*func)(TCGv_i128, TCGv_env, TCGv_i32))
493113ebcc77SRichard Henderson {
493213ebcc77SRichard Henderson     TCGv_i32 src;
49330b2a61ccSRichard Henderson     TCGv_i128 dst;
493413ebcc77SRichard Henderson 
493513ebcc77SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
493613ebcc77SRichard Henderson         return true;
493713ebcc77SRichard Henderson     }
493813ebcc77SRichard Henderson     if (gen_trap_float128(dc)) {
493913ebcc77SRichard Henderson         return true;
494013ebcc77SRichard Henderson     }
494113ebcc77SRichard Henderson 
494213ebcc77SRichard Henderson     src = gen_load_fpr_F(dc, a->rs);
49430b2a61ccSRichard Henderson     dst = tcg_temp_new_i128();
49440b2a61ccSRichard Henderson     func(dst, tcg_env, src);
49450b2a61ccSRichard Henderson     gen_store_fpr_Q(dc, a->rd, dst);
494613ebcc77SRichard Henderson     return advance_pc(dc);
494713ebcc77SRichard Henderson }
494813ebcc77SRichard Henderson 
494913ebcc77SRichard Henderson TRANS(FiTOq, ALL, do_env_qf, a, gen_helper_fitoq)
495013ebcc77SRichard Henderson TRANS(FsTOq, ALL, do_env_qf, a, gen_helper_fstoq)
495113ebcc77SRichard Henderson 
49527b8e3e1aSRichard Henderson static bool do_env_qd(DisasContext *dc, arg_r_r *a,
4953fdc50716SRichard Henderson                       void (*func)(TCGv_i128, TCGv_env, TCGv_i64))
49547b8e3e1aSRichard Henderson {
49557b8e3e1aSRichard Henderson     TCGv_i64 src;
4956fdc50716SRichard Henderson     TCGv_i128 dst;
49577b8e3e1aSRichard Henderson 
49587b8e3e1aSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
49597b8e3e1aSRichard Henderson         return true;
49607b8e3e1aSRichard Henderson     }
49617b8e3e1aSRichard Henderson     if (gen_trap_float128(dc)) {
49627b8e3e1aSRichard Henderson         return true;
49637b8e3e1aSRichard Henderson     }
49647b8e3e1aSRichard Henderson 
49657b8e3e1aSRichard Henderson     src = gen_load_fpr_D(dc, a->rs);
4966fdc50716SRichard Henderson     dst = tcg_temp_new_i128();
4967fdc50716SRichard Henderson     func(dst, tcg_env, src);
4968fdc50716SRichard Henderson     gen_store_fpr_Q(dc, a->rd, dst);
49697b8e3e1aSRichard Henderson     return advance_pc(dc);
49707b8e3e1aSRichard Henderson }
49717b8e3e1aSRichard Henderson 
49727b8e3e1aSRichard Henderson TRANS(FdTOq, ALL, do_env_qd, a, gen_helper_fdtoq)
49737b8e3e1aSRichard Henderson TRANS(FxTOq, 64, do_env_qd, a, gen_helper_fxtoq)
49747b8e3e1aSRichard Henderson 
49757f10b52fSRichard Henderson static bool do_fff(DisasContext *dc, arg_r_r_r *a,
49767f10b52fSRichard Henderson                    void (*func)(TCGv_i32, TCGv_i32, TCGv_i32))
49777f10b52fSRichard Henderson {
49787f10b52fSRichard Henderson     TCGv_i32 src1, src2;
49797f10b52fSRichard Henderson 
49807f10b52fSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
49817f10b52fSRichard Henderson         return true;
49827f10b52fSRichard Henderson     }
49837f10b52fSRichard Henderson 
49847f10b52fSRichard Henderson     src1 = gen_load_fpr_F(dc, a->rs1);
49857f10b52fSRichard Henderson     src2 = gen_load_fpr_F(dc, a->rs2);
49867f10b52fSRichard Henderson     func(src1, src1, src2);
49877f10b52fSRichard Henderson     gen_store_fpr_F(dc, a->rd, src1);
49887f10b52fSRichard Henderson     return advance_pc(dc);
49897f10b52fSRichard Henderson }
49907f10b52fSRichard Henderson 
49917f10b52fSRichard Henderson TRANS(FPADD16s, VIS1, do_fff, a, tcg_gen_vec_add16_i32)
49927f10b52fSRichard Henderson TRANS(FPADD32s, VIS1, do_fff, a, tcg_gen_add_i32)
49937f10b52fSRichard Henderson TRANS(FPSUB16s, VIS1, do_fff, a, tcg_gen_vec_sub16_i32)
49947f10b52fSRichard Henderson TRANS(FPSUB32s, VIS1, do_fff, a, tcg_gen_sub_i32)
49957f10b52fSRichard Henderson TRANS(FNORs, VIS1, do_fff, a, tcg_gen_nor_i32)
49967f10b52fSRichard Henderson TRANS(FANDNOTs, VIS1, do_fff, a, tcg_gen_andc_i32)
49977f10b52fSRichard Henderson TRANS(FXORs, VIS1, do_fff, a, tcg_gen_xor_i32)
49987f10b52fSRichard Henderson TRANS(FNANDs, VIS1, do_fff, a, tcg_gen_nand_i32)
49997f10b52fSRichard Henderson TRANS(FANDs, VIS1, do_fff, a, tcg_gen_and_i32)
50007f10b52fSRichard Henderson TRANS(FXNORs, VIS1, do_fff, a, tcg_gen_eqv_i32)
50017f10b52fSRichard Henderson TRANS(FORNOTs, VIS1, do_fff, a, tcg_gen_orc_i32)
50027f10b52fSRichard Henderson TRANS(FORs, VIS1, do_fff, a, tcg_gen_or_i32)
50037f10b52fSRichard Henderson 
50043d50b728SRichard Henderson TRANS(FHADDs, VIS3, do_fff, a, gen_op_fhadds)
50053d50b728SRichard Henderson TRANS(FHSUBs, VIS3, do_fff, a, gen_op_fhsubs)
50063d50b728SRichard Henderson TRANS(FNHADDs, VIS3, do_fff, a, gen_op_fnhadds)
50073d50b728SRichard Henderson 
50080d1d3aafSRichard Henderson TRANS(FPADDS16s, VIS3, do_fff, a, gen_op_fpadds16s)
50090d1d3aafSRichard Henderson TRANS(FPSUBS16s, VIS3, do_fff, a, gen_op_fpsubs16s)
50100d1d3aafSRichard Henderson TRANS(FPADDS32s, VIS3, do_fff, a, gen_op_fpadds32s)
50110d1d3aafSRichard Henderson TRANS(FPSUBS32s, VIS3, do_fff, a, gen_op_fpsubs32s)
50120d1d3aafSRichard Henderson 
5013c1514961SRichard Henderson static bool do_env_fff(DisasContext *dc, arg_r_r_r *a,
5014c1514961SRichard Henderson                        void (*func)(TCGv_i32, TCGv_env, TCGv_i32, TCGv_i32))
5015c1514961SRichard Henderson {
5016c1514961SRichard Henderson     TCGv_i32 src1, src2;
5017c1514961SRichard Henderson 
5018c1514961SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
5019c1514961SRichard Henderson         return true;
5020c1514961SRichard Henderson     }
5021c1514961SRichard Henderson 
5022c1514961SRichard Henderson     src1 = gen_load_fpr_F(dc, a->rs1);
5023c1514961SRichard Henderson     src2 = gen_load_fpr_F(dc, a->rs2);
5024c1514961SRichard Henderson     func(src1, tcg_env, src1, src2);
5025c1514961SRichard Henderson     gen_store_fpr_F(dc, a->rd, src1);
5026c1514961SRichard Henderson     return advance_pc(dc);
5027c1514961SRichard Henderson }
5028c1514961SRichard Henderson 
5029c1514961SRichard Henderson TRANS(FADDs, ALL, do_env_fff, a, gen_helper_fadds)
5030c1514961SRichard Henderson TRANS(FSUBs, ALL, do_env_fff, a, gen_helper_fsubs)
5031c1514961SRichard Henderson TRANS(FMULs, ALL, do_env_fff, a, gen_helper_fmuls)
5032c1514961SRichard Henderson TRANS(FDIVs, ALL, do_env_fff, a, gen_helper_fdivs)
50333d50b728SRichard Henderson TRANS(FNADDs, VIS3, do_env_fff, a, gen_helper_fnadds)
50343d50b728SRichard Henderson TRANS(FNMULs, VIS3, do_env_fff, a, gen_helper_fnmuls)
5035c1514961SRichard Henderson 
5036a859602cSRichard Henderson static bool do_dff(DisasContext *dc, arg_r_r_r *a,
5037a859602cSRichard Henderson                    void (*func)(TCGv_i64, TCGv_i32, TCGv_i32))
5038a859602cSRichard Henderson {
5039a859602cSRichard Henderson     TCGv_i64 dst;
5040a859602cSRichard Henderson     TCGv_i32 src1, src2;
5041a859602cSRichard Henderson 
5042a859602cSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
5043a859602cSRichard Henderson         return true;
5044a859602cSRichard Henderson     }
5045a859602cSRichard Henderson 
504652f46d46SRichard Henderson     dst = tcg_temp_new_i64();
5047a859602cSRichard Henderson     src1 = gen_load_fpr_F(dc, a->rs1);
5048a859602cSRichard Henderson     src2 = gen_load_fpr_F(dc, a->rs2);
5049a859602cSRichard Henderson     func(dst, src1, src2);
5050a859602cSRichard Henderson     gen_store_fpr_D(dc, a->rd, dst);
5051a859602cSRichard Henderson     return advance_pc(dc);
5052a859602cSRichard Henderson }
5053a859602cSRichard Henderson 
5054a859602cSRichard Henderson TRANS(FMUL8x16AU, VIS1, do_dff, a, gen_op_fmul8x16au)
5055a859602cSRichard Henderson TRANS(FMUL8x16AL, VIS1, do_dff, a, gen_op_fmul8x16al)
5056be8998e0SRichard Henderson TRANS(FMULD8SUx16, VIS1, do_dff, a, gen_op_fmuld8sux16)
5057be8998e0SRichard Henderson TRANS(FMULD8ULx16, VIS1, do_dff, a, gen_op_fmuld8ulx16)
5058d3ef26afSRichard Henderson TRANS(FPMERGE, VIS1, do_dff, a, gen_helper_fpmerge)
5059a859602cSRichard Henderson 
50609157dcccSRichard Henderson static bool do_dfd(DisasContext *dc, arg_r_r_r *a,
50619157dcccSRichard Henderson                    void (*func)(TCGv_i64, TCGv_i32, TCGv_i64))
50629157dcccSRichard Henderson {
50639157dcccSRichard Henderson     TCGv_i64 dst, src2;
50649157dcccSRichard Henderson     TCGv_i32 src1;
50659157dcccSRichard Henderson 
50669157dcccSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
50679157dcccSRichard Henderson         return true;
50689157dcccSRichard Henderson     }
50699157dcccSRichard Henderson 
507052f46d46SRichard Henderson     dst = tcg_temp_new_i64();
50719157dcccSRichard Henderson     src1 = gen_load_fpr_F(dc, a->rs1);
50729157dcccSRichard Henderson     src2 = gen_load_fpr_D(dc, a->rs2);
50739157dcccSRichard Henderson     func(dst, src1, src2);
50749157dcccSRichard Henderson     gen_store_fpr_D(dc, a->rd, dst);
50759157dcccSRichard Henderson     return advance_pc(dc);
50769157dcccSRichard Henderson }
50779157dcccSRichard Henderson 
50789157dcccSRichard Henderson TRANS(FMUL8x16, VIS1, do_dfd, a, gen_helper_fmul8x16)
50799157dcccSRichard Henderson 
508028c131a3SRichard Henderson static bool do_gvec_ddd(DisasContext *dc, arg_r_r_r *a, MemOp vece,
508128c131a3SRichard Henderson                         void (*func)(unsigned, uint32_t, uint32_t,
508228c131a3SRichard Henderson                                      uint32_t, uint32_t, uint32_t))
508328c131a3SRichard Henderson {
508428c131a3SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
508528c131a3SRichard Henderson         return true;
508628c131a3SRichard Henderson     }
508728c131a3SRichard Henderson 
508828c131a3SRichard Henderson     func(vece, gen_offset_fpr_D(a->rd), gen_offset_fpr_D(a->rs1),
508928c131a3SRichard Henderson          gen_offset_fpr_D(a->rs2), 8, 8);
509028c131a3SRichard Henderson     return advance_pc(dc);
509128c131a3SRichard Henderson }
509228c131a3SRichard Henderson 
5093b99c1bbdSRichard Henderson TRANS(FPADD8, VIS4, do_gvec_ddd, a, MO_8, tcg_gen_gvec_add)
509428c131a3SRichard Henderson TRANS(FPADD16, VIS1, do_gvec_ddd, a, MO_16, tcg_gen_gvec_add)
509528c131a3SRichard Henderson TRANS(FPADD32, VIS1, do_gvec_ddd, a, MO_32, tcg_gen_gvec_add)
5096b99c1bbdSRichard Henderson 
5097b99c1bbdSRichard Henderson TRANS(FPSUB8, VIS4, do_gvec_ddd, a, MO_8, tcg_gen_gvec_sub)
509828c131a3SRichard Henderson TRANS(FPSUB16, VIS1, do_gvec_ddd, a, MO_16, tcg_gen_gvec_sub)
509928c131a3SRichard Henderson TRANS(FPSUB32, VIS1, do_gvec_ddd, a, MO_32, tcg_gen_gvec_sub)
5100b99c1bbdSRichard Henderson 
51017837185eSRichard Henderson TRANS(FCHKSM16, VIS3, do_gvec_ddd, a, MO_16, gen_op_fchksm16)
5102d6ff1ccbSRichard Henderson TRANS(FMEAN16, VIS3, do_gvec_ddd, a, MO_16, gen_op_fmean16)
510328c131a3SRichard Henderson 
5104b99c1bbdSRichard Henderson TRANS(FPADDS8, VIS4, do_gvec_ddd, a, MO_8, tcg_gen_gvec_ssadd)
51050d1d3aafSRichard Henderson TRANS(FPADDS16, VIS3, do_gvec_ddd, a, MO_16, tcg_gen_gvec_ssadd)
51060d1d3aafSRichard Henderson TRANS(FPADDS32, VIS3, do_gvec_ddd, a, MO_32, tcg_gen_gvec_ssadd)
5107b99c1bbdSRichard Henderson TRANS(FPADDUS8, VIS4, do_gvec_ddd, a, MO_8, tcg_gen_gvec_usadd)
5108b99c1bbdSRichard Henderson TRANS(FPADDUS16, VIS4, do_gvec_ddd, a, MO_16, tcg_gen_gvec_usadd)
5109b99c1bbdSRichard Henderson 
5110b99c1bbdSRichard Henderson TRANS(FPSUBS8, VIS4, do_gvec_ddd, a, MO_8, tcg_gen_gvec_sssub)
51110d1d3aafSRichard Henderson TRANS(FPSUBS16, VIS3, do_gvec_ddd, a, MO_16, tcg_gen_gvec_sssub)
51120d1d3aafSRichard Henderson TRANS(FPSUBS32, VIS3, do_gvec_ddd, a, MO_32, tcg_gen_gvec_sssub)
5113b99c1bbdSRichard Henderson TRANS(FPSUBUS8, VIS4, do_gvec_ddd, a, MO_8, tcg_gen_gvec_ussub)
5114b99c1bbdSRichard Henderson TRANS(FPSUBUS16, VIS4, do_gvec_ddd, a, MO_16, tcg_gen_gvec_ussub)
51150d1d3aafSRichard Henderson 
5116fbc5c8d4SRichard Henderson TRANS(FSLL16, VIS3, do_gvec_ddd, a, MO_16, tcg_gen_gvec_shlv)
5117fbc5c8d4SRichard Henderson TRANS(FSLL32, VIS3, do_gvec_ddd, a, MO_32, tcg_gen_gvec_shlv)
5118fbc5c8d4SRichard Henderson TRANS(FSRL16, VIS3, do_gvec_ddd, a, MO_16, tcg_gen_gvec_shrv)
5119fbc5c8d4SRichard Henderson TRANS(FSRL32, VIS3, do_gvec_ddd, a, MO_32, tcg_gen_gvec_shrv)
5120fbc5c8d4SRichard Henderson TRANS(FSRA16, VIS3, do_gvec_ddd, a, MO_16, tcg_gen_gvec_sarv)
5121fbc5c8d4SRichard Henderson TRANS(FSRA32, VIS3, do_gvec_ddd, a, MO_32, tcg_gen_gvec_sarv)
5122fbc5c8d4SRichard Henderson 
5123db11dfeaSRichard Henderson TRANS(FPMIN8, VIS4, do_gvec_ddd, a, MO_8, tcg_gen_gvec_smin)
5124db11dfeaSRichard Henderson TRANS(FPMIN16, VIS4, do_gvec_ddd, a, MO_16, tcg_gen_gvec_smin)
5125db11dfeaSRichard Henderson TRANS(FPMIN32, VIS4, do_gvec_ddd, a, MO_32, tcg_gen_gvec_smin)
5126db11dfeaSRichard Henderson TRANS(FPMINU8, VIS4, do_gvec_ddd, a, MO_8, tcg_gen_gvec_umin)
5127db11dfeaSRichard Henderson TRANS(FPMINU16, VIS4, do_gvec_ddd, a, MO_16, tcg_gen_gvec_umin)
5128db11dfeaSRichard Henderson TRANS(FPMINU32, VIS4, do_gvec_ddd, a, MO_32, tcg_gen_gvec_umin)
5129db11dfeaSRichard Henderson 
5130db11dfeaSRichard Henderson TRANS(FPMAX8, VIS4, do_gvec_ddd, a, MO_8, tcg_gen_gvec_smax)
5131db11dfeaSRichard Henderson TRANS(FPMAX16, VIS4, do_gvec_ddd, a, MO_16, tcg_gen_gvec_smax)
5132db11dfeaSRichard Henderson TRANS(FPMAX32, VIS4, do_gvec_ddd, a, MO_32, tcg_gen_gvec_smax)
5133db11dfeaSRichard Henderson TRANS(FPMAXU8, VIS4, do_gvec_ddd, a, MO_8, tcg_gen_gvec_umax)
5134db11dfeaSRichard Henderson TRANS(FPMAXU16, VIS4, do_gvec_ddd, a, MO_16, tcg_gen_gvec_umax)
5135db11dfeaSRichard Henderson TRANS(FPMAXU32, VIS4, do_gvec_ddd, a, MO_32, tcg_gen_gvec_umax)
5136db11dfeaSRichard Henderson 
5137e06c9f83SRichard Henderson static bool do_ddd(DisasContext *dc, arg_r_r_r *a,
5138e06c9f83SRichard Henderson                    void (*func)(TCGv_i64, TCGv_i64, TCGv_i64))
5139e06c9f83SRichard Henderson {
5140e06c9f83SRichard Henderson     TCGv_i64 dst, src1, src2;
5141e06c9f83SRichard Henderson 
5142e06c9f83SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
5143e06c9f83SRichard Henderson         return true;
5144e06c9f83SRichard Henderson     }
5145e06c9f83SRichard Henderson 
514652f46d46SRichard Henderson     dst = tcg_temp_new_i64();
5147e06c9f83SRichard Henderson     src1 = gen_load_fpr_D(dc, a->rs1);
5148e06c9f83SRichard Henderson     src2 = gen_load_fpr_D(dc, a->rs2);
5149e06c9f83SRichard Henderson     func(dst, src1, src2);
5150e06c9f83SRichard Henderson     gen_store_fpr_D(dc, a->rd, dst);
5151e06c9f83SRichard Henderson     return advance_pc(dc);
5152e06c9f83SRichard Henderson }
5153e06c9f83SRichard Henderson 
5154e06c9f83SRichard Henderson TRANS(FMUL8SUx16, VIS1, do_ddd, a, gen_helper_fmul8sux16)
5155e06c9f83SRichard Henderson TRANS(FMUL8ULx16, VIS1, do_ddd, a, gen_helper_fmul8ulx16)
5156e06c9f83SRichard Henderson 
5157e06c9f83SRichard Henderson TRANS(FNORd, VIS1, do_ddd, a, tcg_gen_nor_i64)
5158e06c9f83SRichard Henderson TRANS(FANDNOTd, VIS1, do_ddd, a, tcg_gen_andc_i64)
5159e06c9f83SRichard Henderson TRANS(FXORd, VIS1, do_ddd, a, tcg_gen_xor_i64)
5160e06c9f83SRichard Henderson TRANS(FNANDd, VIS1, do_ddd, a, tcg_gen_nand_i64)
5161e06c9f83SRichard Henderson TRANS(FANDd, VIS1, do_ddd, a, tcg_gen_and_i64)
5162e06c9f83SRichard Henderson TRANS(FXNORd, VIS1, do_ddd, a, tcg_gen_eqv_i64)
5163e06c9f83SRichard Henderson TRANS(FORNOTd, VIS1, do_ddd, a, tcg_gen_orc_i64)
5164e06c9f83SRichard Henderson TRANS(FORd, VIS1, do_ddd, a, tcg_gen_or_i64)
5165e06c9f83SRichard Henderson 
51664b6edc0aSRichard Henderson TRANS(FPACK32, VIS1, do_ddd, a, gen_op_fpack32)
5167b2b48493SRichard Henderson TRANS(FALIGNDATAg, VIS1, do_ddd, a, gen_op_faligndata_g)
51684b6edc0aSRichard Henderson TRANS(BSHUFFLE, VIS2, do_ddd, a, gen_op_bshuffle)
51694b6edc0aSRichard Henderson 
51703d50b728SRichard Henderson TRANS(FHADDd, VIS3, do_ddd, a, gen_op_fhaddd)
51713d50b728SRichard Henderson TRANS(FHSUBd, VIS3, do_ddd, a, gen_op_fhsubd)
51723d50b728SRichard Henderson TRANS(FNHADDd, VIS3, do_ddd, a, gen_op_fnhaddd)
51733d50b728SRichard Henderson 
5174bc3f14a9SRichard Henderson TRANS(FPADD64, VIS3B, do_ddd, a, tcg_gen_add_i64)
5175bc3f14a9SRichard Henderson TRANS(FPSUB64, VIS3B, do_ddd, a, tcg_gen_sub_i64)
5176fbc5c8d4SRichard Henderson TRANS(FSLAS16, VIS3, do_ddd, a, gen_helper_fslas16)
5177fbc5c8d4SRichard Henderson TRANS(FSLAS32, VIS3, do_ddd, a, gen_helper_fslas32)
5178bc3f14a9SRichard Henderson 
5179e2fa6bd1SRichard Henderson static bool do_rdd(DisasContext *dc, arg_r_r_r *a,
5180e2fa6bd1SRichard Henderson                    void (*func)(TCGv, TCGv_i64, TCGv_i64))
5181e2fa6bd1SRichard Henderson {
5182e2fa6bd1SRichard Henderson     TCGv_i64 src1, src2;
5183e2fa6bd1SRichard Henderson     TCGv dst;
5184e2fa6bd1SRichard Henderson 
5185e2fa6bd1SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
5186e2fa6bd1SRichard Henderson         return true;
5187e2fa6bd1SRichard Henderson     }
5188e2fa6bd1SRichard Henderson 
5189e2fa6bd1SRichard Henderson     dst = gen_dest_gpr(dc, a->rd);
5190e2fa6bd1SRichard Henderson     src1 = gen_load_fpr_D(dc, a->rs1);
5191e2fa6bd1SRichard Henderson     src2 = gen_load_fpr_D(dc, a->rs2);
5192e2fa6bd1SRichard Henderson     func(dst, src1, src2);
5193e2fa6bd1SRichard Henderson     gen_store_gpr(dc, a->rd, dst);
5194e2fa6bd1SRichard Henderson     return advance_pc(dc);
5195e2fa6bd1SRichard Henderson }
5196e2fa6bd1SRichard Henderson 
5197e2fa6bd1SRichard Henderson TRANS(FPCMPLE16, VIS1, do_rdd, a, gen_helper_fcmple16)
5198e2fa6bd1SRichard Henderson TRANS(FPCMPNE16, VIS1, do_rdd, a, gen_helper_fcmpne16)
5199e2fa6bd1SRichard Henderson TRANS(FPCMPGT16, VIS1, do_rdd, a, gen_helper_fcmpgt16)
5200e2fa6bd1SRichard Henderson TRANS(FPCMPEQ16, VIS1, do_rdd, a, gen_helper_fcmpeq16)
5201b3c934ddSRichard Henderson TRANS(FPCMPULE16, VIS4, do_rdd, a, gen_helper_fcmpule16)
5202b3c934ddSRichard Henderson TRANS(FPCMPUGT16, VIS4, do_rdd, a, gen_helper_fcmpugt16)
5203e2fa6bd1SRichard Henderson 
5204e2fa6bd1SRichard Henderson TRANS(FPCMPLE32, VIS1, do_rdd, a, gen_helper_fcmple32)
5205e2fa6bd1SRichard Henderson TRANS(FPCMPNE32, VIS1, do_rdd, a, gen_helper_fcmpne32)
5206e2fa6bd1SRichard Henderson TRANS(FPCMPGT32, VIS1, do_rdd, a, gen_helper_fcmpgt32)
5207e2fa6bd1SRichard Henderson TRANS(FPCMPEQ32, VIS1, do_rdd, a, gen_helper_fcmpeq32)
5208b3c934ddSRichard Henderson TRANS(FPCMPULE32, VIS4, do_rdd, a, gen_helper_fcmpule32)
5209b3c934ddSRichard Henderson TRANS(FPCMPUGT32, VIS4, do_rdd, a, gen_helper_fcmpugt32)
5210e2fa6bd1SRichard Henderson 
5211669e0774SRichard Henderson TRANS(FPCMPEQ8, VIS3B, do_rdd, a, gen_helper_fcmpeq8)
5212669e0774SRichard Henderson TRANS(FPCMPNE8, VIS3B, do_rdd, a, gen_helper_fcmpne8)
5213669e0774SRichard Henderson TRANS(FPCMPULE8, VIS3B, do_rdd, a, gen_helper_fcmpule8)
5214669e0774SRichard Henderson TRANS(FPCMPUGT8, VIS3B, do_rdd, a, gen_helper_fcmpugt8)
5215b3c934ddSRichard Henderson TRANS(FPCMPLE8, VIS4, do_rdd, a, gen_helper_fcmple8)
5216b3c934ddSRichard Henderson TRANS(FPCMPGT8, VIS4, do_rdd, a, gen_helper_fcmpgt8)
5217669e0774SRichard Henderson 
52187d5ebd8fSRichard Henderson TRANS(PDISTN, VIS3, do_rdd, a, gen_op_pdistn)
5219029b0283SRichard Henderson TRANS(XMULX, VIS3, do_rrr, a, gen_helper_xmulx)
5220029b0283SRichard Henderson TRANS(XMULXHI, VIS3, do_rrr, a, gen_helper_xmulxhi)
52217d5ebd8fSRichard Henderson 
5222f2a59b0aSRichard Henderson static bool do_env_ddd(DisasContext *dc, arg_r_r_r *a,
5223f2a59b0aSRichard Henderson                        void (*func)(TCGv_i64, TCGv_env, TCGv_i64, TCGv_i64))
5224f2a59b0aSRichard Henderson {
5225f2a59b0aSRichard Henderson     TCGv_i64 dst, src1, src2;
5226f2a59b0aSRichard Henderson 
5227f2a59b0aSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
5228f2a59b0aSRichard Henderson         return true;
5229f2a59b0aSRichard Henderson     }
5230f2a59b0aSRichard Henderson 
523152f46d46SRichard Henderson     dst = tcg_temp_new_i64();
5232f2a59b0aSRichard Henderson     src1 = gen_load_fpr_D(dc, a->rs1);
5233f2a59b0aSRichard Henderson     src2 = gen_load_fpr_D(dc, a->rs2);
5234f2a59b0aSRichard Henderson     func(dst, tcg_env, src1, src2);
5235f2a59b0aSRichard Henderson     gen_store_fpr_D(dc, a->rd, dst);
5236f2a59b0aSRichard Henderson     return advance_pc(dc);
5237f2a59b0aSRichard Henderson }
5238f2a59b0aSRichard Henderson 
5239f2a59b0aSRichard Henderson TRANS(FADDd, ALL, do_env_ddd, a, gen_helper_faddd)
5240f2a59b0aSRichard Henderson TRANS(FSUBd, ALL, do_env_ddd, a, gen_helper_fsubd)
5241f2a59b0aSRichard Henderson TRANS(FMULd, ALL, do_env_ddd, a, gen_helper_fmuld)
5242f2a59b0aSRichard Henderson TRANS(FDIVd, ALL, do_env_ddd, a, gen_helper_fdivd)
52433d50b728SRichard Henderson TRANS(FNADDd, VIS3, do_env_ddd, a, gen_helper_fnaddd)
52443d50b728SRichard Henderson TRANS(FNMULd, VIS3, do_env_ddd, a, gen_helper_fnmuld)
5245f2a59b0aSRichard Henderson 
5246ff4c711bSRichard Henderson static bool trans_FsMULd(DisasContext *dc, arg_r_r_r *a)
5247ff4c711bSRichard Henderson {
5248ff4c711bSRichard Henderson     TCGv_i64 dst;
5249ff4c711bSRichard Henderson     TCGv_i32 src1, src2;
5250ff4c711bSRichard Henderson 
5251ff4c711bSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
5252ff4c711bSRichard Henderson         return true;
5253ff4c711bSRichard Henderson     }
5254ff4c711bSRichard Henderson     if (!(dc->def->features & CPU_FEATURE_FSMULD)) {
5255ff4c711bSRichard Henderson         return raise_unimpfpop(dc);
5256ff4c711bSRichard Henderson     }
5257ff4c711bSRichard Henderson 
525852f46d46SRichard Henderson     dst = tcg_temp_new_i64();
5259ff4c711bSRichard Henderson     src1 = gen_load_fpr_F(dc, a->rs1);
5260ff4c711bSRichard Henderson     src2 = gen_load_fpr_F(dc, a->rs2);
5261ff4c711bSRichard Henderson     gen_helper_fsmuld(dst, tcg_env, src1, src2);
5262ff4c711bSRichard Henderson     gen_store_fpr_D(dc, a->rd, dst);
5263ff4c711bSRichard Henderson     return advance_pc(dc);
5264ff4c711bSRichard Henderson }
5265ff4c711bSRichard Henderson 
52663d50b728SRichard Henderson static bool trans_FNsMULd(DisasContext *dc, arg_r_r_r *a)
52673d50b728SRichard Henderson {
52683d50b728SRichard Henderson     TCGv_i64 dst;
52693d50b728SRichard Henderson     TCGv_i32 src1, src2;
52703d50b728SRichard Henderson 
52713d50b728SRichard Henderson     if (!avail_VIS3(dc)) {
52723d50b728SRichard Henderson         return false;
52733d50b728SRichard Henderson     }
52743d50b728SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
52753d50b728SRichard Henderson         return true;
52763d50b728SRichard Henderson     }
52773d50b728SRichard Henderson     dst = tcg_temp_new_i64();
52783d50b728SRichard Henderson     src1 = gen_load_fpr_F(dc, a->rs1);
52793d50b728SRichard Henderson     src2 = gen_load_fpr_F(dc, a->rs2);
52803d50b728SRichard Henderson     gen_helper_fnsmuld(dst, tcg_env, src1, src2);
52813d50b728SRichard Henderson     gen_store_fpr_D(dc, a->rd, dst);
52823d50b728SRichard Henderson     return advance_pc(dc);
52833d50b728SRichard Henderson }
52843d50b728SRichard Henderson 
52854fd71d19SRichard Henderson static bool do_ffff(DisasContext *dc, arg_r_r_r_r *a,
52864fd71d19SRichard Henderson                     void (*func)(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_i32))
52874fd71d19SRichard Henderson {
52884fd71d19SRichard Henderson     TCGv_i32 dst, src1, src2, src3;
52894fd71d19SRichard Henderson 
52904fd71d19SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
52914fd71d19SRichard Henderson         return true;
52924fd71d19SRichard Henderson     }
52934fd71d19SRichard Henderson 
52944fd71d19SRichard Henderson     src1 = gen_load_fpr_F(dc, a->rs1);
52954fd71d19SRichard Henderson     src2 = gen_load_fpr_F(dc, a->rs2);
52964fd71d19SRichard Henderson     src3 = gen_load_fpr_F(dc, a->rs3);
52974fd71d19SRichard Henderson     dst = tcg_temp_new_i32();
52984fd71d19SRichard Henderson     func(dst, src1, src2, src3);
52994fd71d19SRichard Henderson     gen_store_fpr_F(dc, a->rd, dst);
53004fd71d19SRichard Henderson     return advance_pc(dc);
53014fd71d19SRichard Henderson }
53024fd71d19SRichard Henderson 
53034fd71d19SRichard Henderson TRANS(FMADDs, FMAF, do_ffff, a, gen_op_fmadds)
53044fd71d19SRichard Henderson TRANS(FMSUBs, FMAF, do_ffff, a, gen_op_fmsubs)
53054fd71d19SRichard Henderson TRANS(FNMSUBs, FMAF, do_ffff, a, gen_op_fnmsubs)
53064fd71d19SRichard Henderson TRANS(FNMADDs, FMAF, do_ffff, a, gen_op_fnmadds)
53074fd71d19SRichard Henderson 
53084fd71d19SRichard Henderson static bool do_dddd(DisasContext *dc, arg_r_r_r_r *a,
5309afb04344SRichard Henderson                     void (*func)(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_i64))
5310afb04344SRichard Henderson {
53114fd71d19SRichard Henderson     TCGv_i64 dst, src1, src2, src3;
5312afb04344SRichard Henderson 
5313afb04344SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
5314afb04344SRichard Henderson         return true;
5315afb04344SRichard Henderson     }
5316afb04344SRichard Henderson 
531752f46d46SRichard Henderson     dst  = tcg_temp_new_i64();
5318afb04344SRichard Henderson     src1 = gen_load_fpr_D(dc, a->rs1);
5319afb04344SRichard Henderson     src2 = gen_load_fpr_D(dc, a->rs2);
53204fd71d19SRichard Henderson     src3 = gen_load_fpr_D(dc, a->rs3);
53214fd71d19SRichard Henderson     func(dst, src1, src2, src3);
5322afb04344SRichard Henderson     gen_store_fpr_D(dc, a->rd, dst);
5323afb04344SRichard Henderson     return advance_pc(dc);
5324afb04344SRichard Henderson }
5325afb04344SRichard Henderson 
5326afb04344SRichard Henderson TRANS(PDIST, VIS1, do_dddd, a, gen_helper_pdist)
53274fd71d19SRichard Henderson TRANS(FMADDd, FMAF, do_dddd, a, gen_op_fmaddd)
53284fd71d19SRichard Henderson TRANS(FMSUBd, FMAF, do_dddd, a, gen_op_fmsubd)
53294fd71d19SRichard Henderson TRANS(FNMSUBd, FMAF, do_dddd, a, gen_op_fnmsubd)
53304fd71d19SRichard Henderson TRANS(FNMADDd, FMAF, do_dddd, a, gen_op_fnmaddd)
533168a414e9SRichard Henderson TRANS(FPMADDX, IMA, do_dddd, a, gen_op_fpmaddx)
533268a414e9SRichard Henderson TRANS(FPMADDXHI, IMA, do_dddd, a, gen_op_fpmaddxhi)
5333afb04344SRichard Henderson 
5334b2b48493SRichard Henderson static bool trans_FALIGNDATAi(DisasContext *dc, arg_r_r_r *a)
5335b2b48493SRichard Henderson {
5336b2b48493SRichard Henderson     TCGv_i64 dst, src1, src2;
5337b2b48493SRichard Henderson     TCGv src3;
5338b2b48493SRichard Henderson 
5339b2b48493SRichard Henderson     if (!avail_VIS4(dc)) {
5340b2b48493SRichard Henderson         return false;
5341b2b48493SRichard Henderson     }
5342b2b48493SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
5343b2b48493SRichard Henderson         return true;
5344b2b48493SRichard Henderson     }
5345b2b48493SRichard Henderson 
5346b2b48493SRichard Henderson     dst  = tcg_temp_new_i64();
5347b2b48493SRichard Henderson     src1 = gen_load_fpr_D(dc, a->rd);
5348b2b48493SRichard Henderson     src2 = gen_load_fpr_D(dc, a->rs2);
5349b2b48493SRichard Henderson     src3 = gen_load_gpr(dc, a->rs1);
5350b2b48493SRichard Henderson     gen_op_faligndata_i(dst, src1, src2, src3);
5351b2b48493SRichard Henderson     gen_store_fpr_D(dc, a->rd, dst);
5352b2b48493SRichard Henderson     return advance_pc(dc);
5353b2b48493SRichard Henderson }
5354b2b48493SRichard Henderson 
5355a4056239SRichard Henderson static bool do_env_qqq(DisasContext *dc, arg_r_r_r *a,
535616bedf89SRichard Henderson                        void (*func)(TCGv_i128, TCGv_env, TCGv_i128, TCGv_i128))
5357a4056239SRichard Henderson {
535816bedf89SRichard Henderson     TCGv_i128 src1, src2;
535916bedf89SRichard Henderson 
5360a4056239SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
5361a4056239SRichard Henderson         return true;
5362a4056239SRichard Henderson     }
5363a4056239SRichard Henderson     if (gen_trap_float128(dc)) {
5364a4056239SRichard Henderson         return true;
5365a4056239SRichard Henderson     }
5366a4056239SRichard Henderson 
536716bedf89SRichard Henderson     src1 = gen_load_fpr_Q(dc, a->rs1);
536816bedf89SRichard Henderson     src2 = gen_load_fpr_Q(dc, a->rs2);
536916bedf89SRichard Henderson     func(src1, tcg_env, src1, src2);
537016bedf89SRichard Henderson     gen_store_fpr_Q(dc, a->rd, src1);
5371a4056239SRichard Henderson     return advance_pc(dc);
5372a4056239SRichard Henderson }
5373a4056239SRichard Henderson 
5374a4056239SRichard Henderson TRANS(FADDq, ALL, do_env_qqq, a, gen_helper_faddq)
5375a4056239SRichard Henderson TRANS(FSUBq, ALL, do_env_qqq, a, gen_helper_fsubq)
5376a4056239SRichard Henderson TRANS(FMULq, ALL, do_env_qqq, a, gen_helper_fmulq)
5377a4056239SRichard Henderson TRANS(FDIVq, ALL, do_env_qqq, a, gen_helper_fdivq)
5378a4056239SRichard Henderson 
53795e3b17bbSRichard Henderson static bool trans_FdMULq(DisasContext *dc, arg_r_r_r *a)
53805e3b17bbSRichard Henderson {
53815e3b17bbSRichard Henderson     TCGv_i64 src1, src2;
5382ba21dc99SRichard Henderson     TCGv_i128 dst;
53835e3b17bbSRichard Henderson 
53845e3b17bbSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
53855e3b17bbSRichard Henderson         return true;
53865e3b17bbSRichard Henderson     }
53875e3b17bbSRichard Henderson     if (gen_trap_float128(dc)) {
53885e3b17bbSRichard Henderson         return true;
53895e3b17bbSRichard Henderson     }
53905e3b17bbSRichard Henderson 
53915e3b17bbSRichard Henderson     src1 = gen_load_fpr_D(dc, a->rs1);
53925e3b17bbSRichard Henderson     src2 = gen_load_fpr_D(dc, a->rs2);
5393ba21dc99SRichard Henderson     dst = tcg_temp_new_i128();
5394ba21dc99SRichard Henderson     gen_helper_fdmulq(dst, tcg_env, src1, src2);
5395ba21dc99SRichard Henderson     gen_store_fpr_Q(dc, a->rd, dst);
53965e3b17bbSRichard Henderson     return advance_pc(dc);
53975e3b17bbSRichard Henderson }
53985e3b17bbSRichard Henderson 
5399f7ec8155SRichard Henderson static bool do_fmovr(DisasContext *dc, arg_FMOVRs *a, bool is_128,
5400f7ec8155SRichard Henderson                      void (*func)(DisasContext *, DisasCompare *, int, int))
5401f7ec8155SRichard Henderson {
5402f7ec8155SRichard Henderson     DisasCompare cmp;
5403f7ec8155SRichard Henderson 
54042c4f56c9SRichard Henderson     if (!gen_compare_reg(&cmp, a->cond, gen_load_gpr(dc, a->rs1))) {
54052c4f56c9SRichard Henderson         return false;
54062c4f56c9SRichard Henderson     }
5407f7ec8155SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
5408f7ec8155SRichard Henderson         return true;
5409f7ec8155SRichard Henderson     }
5410f7ec8155SRichard Henderson     if (is_128 && gen_trap_float128(dc)) {
5411f7ec8155SRichard Henderson         return true;
5412f7ec8155SRichard Henderson     }
5413f7ec8155SRichard Henderson 
5414f7ec8155SRichard Henderson     gen_op_clear_ieee_excp_and_FTT();
5415f7ec8155SRichard Henderson     func(dc, &cmp, a->rd, a->rs2);
5416f7ec8155SRichard Henderson     return advance_pc(dc);
5417f7ec8155SRichard Henderson }
5418f7ec8155SRichard Henderson 
5419f7ec8155SRichard Henderson TRANS(FMOVRs, 64, do_fmovr, a, false, gen_fmovs)
5420f7ec8155SRichard Henderson TRANS(FMOVRd, 64, do_fmovr, a, false, gen_fmovd)
5421f7ec8155SRichard Henderson TRANS(FMOVRq, 64, do_fmovr, a, true, gen_fmovq)
5422f7ec8155SRichard Henderson 
5423f7ec8155SRichard Henderson static bool do_fmovcc(DisasContext *dc, arg_FMOVscc *a, bool is_128,
5424f7ec8155SRichard Henderson                       void (*func)(DisasContext *, DisasCompare *, int, int))
5425f7ec8155SRichard Henderson {
5426f7ec8155SRichard Henderson     DisasCompare cmp;
5427f7ec8155SRichard Henderson 
5428f7ec8155SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
5429f7ec8155SRichard Henderson         return true;
5430f7ec8155SRichard Henderson     }
5431f7ec8155SRichard Henderson     if (is_128 && gen_trap_float128(dc)) {
5432f7ec8155SRichard Henderson         return true;
5433f7ec8155SRichard Henderson     }
5434f7ec8155SRichard Henderson 
5435f7ec8155SRichard Henderson     gen_op_clear_ieee_excp_and_FTT();
5436f7ec8155SRichard Henderson     gen_compare(&cmp, a->cc, a->cond, dc);
5437f7ec8155SRichard Henderson     func(dc, &cmp, a->rd, a->rs2);
5438f7ec8155SRichard Henderson     return advance_pc(dc);
5439f7ec8155SRichard Henderson }
5440f7ec8155SRichard Henderson 
5441f7ec8155SRichard Henderson TRANS(FMOVscc, 64, do_fmovcc, a, false, gen_fmovs)
5442f7ec8155SRichard Henderson TRANS(FMOVdcc, 64, do_fmovcc, a, false, gen_fmovd)
5443f7ec8155SRichard Henderson TRANS(FMOVqcc, 64, do_fmovcc, a, true, gen_fmovq)
5444f7ec8155SRichard Henderson 
5445f7ec8155SRichard Henderson static bool do_fmovfcc(DisasContext *dc, arg_FMOVsfcc *a, bool is_128,
5446f7ec8155SRichard Henderson                        void (*func)(DisasContext *, DisasCompare *, int, int))
5447f7ec8155SRichard Henderson {
5448f7ec8155SRichard Henderson     DisasCompare cmp;
5449f7ec8155SRichard Henderson 
5450f7ec8155SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
5451f7ec8155SRichard Henderson         return true;
5452f7ec8155SRichard Henderson     }
5453f7ec8155SRichard Henderson     if (is_128 && gen_trap_float128(dc)) {
5454f7ec8155SRichard Henderson         return true;
5455f7ec8155SRichard Henderson     }
5456f7ec8155SRichard Henderson 
5457f7ec8155SRichard Henderson     gen_op_clear_ieee_excp_and_FTT();
5458f7ec8155SRichard Henderson     gen_fcompare(&cmp, a->cc, a->cond);
5459f7ec8155SRichard Henderson     func(dc, &cmp, a->rd, a->rs2);
5460f7ec8155SRichard Henderson     return advance_pc(dc);
5461f7ec8155SRichard Henderson }
5462f7ec8155SRichard Henderson 
5463f7ec8155SRichard Henderson TRANS(FMOVsfcc, 64, do_fmovfcc, a, false, gen_fmovs)
5464f7ec8155SRichard Henderson TRANS(FMOVdfcc, 64, do_fmovfcc, a, false, gen_fmovd)
5465f7ec8155SRichard Henderson TRANS(FMOVqfcc, 64, do_fmovfcc, a, true, gen_fmovq)
5466f7ec8155SRichard Henderson 
546740f9ad21SRichard Henderson static bool do_fcmps(DisasContext *dc, arg_FCMPs *a, bool e)
546840f9ad21SRichard Henderson {
546940f9ad21SRichard Henderson     TCGv_i32 src1, src2;
547040f9ad21SRichard Henderson 
547140f9ad21SRichard Henderson     if (avail_32(dc) && a->cc != 0) {
547240f9ad21SRichard Henderson         return false;
547340f9ad21SRichard Henderson     }
547440f9ad21SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
547540f9ad21SRichard Henderson         return true;
547640f9ad21SRichard Henderson     }
547740f9ad21SRichard Henderson 
547840f9ad21SRichard Henderson     src1 = gen_load_fpr_F(dc, a->rs1);
547940f9ad21SRichard Henderson     src2 = gen_load_fpr_F(dc, a->rs2);
548040f9ad21SRichard Henderson     if (e) {
5481d8c5b92fSRichard Henderson         gen_helper_fcmpes(cpu_fcc[a->cc], tcg_env, src1, src2);
548240f9ad21SRichard Henderson     } else {
5483d8c5b92fSRichard Henderson         gen_helper_fcmps(cpu_fcc[a->cc], tcg_env, src1, src2);
548440f9ad21SRichard Henderson     }
548540f9ad21SRichard Henderson     return advance_pc(dc);
548640f9ad21SRichard Henderson }
548740f9ad21SRichard Henderson 
548840f9ad21SRichard Henderson TRANS(FCMPs, ALL, do_fcmps, a, false)
548940f9ad21SRichard Henderson TRANS(FCMPEs, ALL, do_fcmps, a, true)
549040f9ad21SRichard Henderson 
549140f9ad21SRichard Henderson static bool do_fcmpd(DisasContext *dc, arg_FCMPd *a, bool e)
549240f9ad21SRichard Henderson {
549340f9ad21SRichard Henderson     TCGv_i64 src1, src2;
549440f9ad21SRichard Henderson 
549540f9ad21SRichard Henderson     if (avail_32(dc) && a->cc != 0) {
549640f9ad21SRichard Henderson         return false;
549740f9ad21SRichard Henderson     }
549840f9ad21SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
549940f9ad21SRichard Henderson         return true;
550040f9ad21SRichard Henderson     }
550140f9ad21SRichard Henderson 
550240f9ad21SRichard Henderson     src1 = gen_load_fpr_D(dc, a->rs1);
550340f9ad21SRichard Henderson     src2 = gen_load_fpr_D(dc, a->rs2);
550440f9ad21SRichard Henderson     if (e) {
5505d8c5b92fSRichard Henderson         gen_helper_fcmped(cpu_fcc[a->cc], tcg_env, src1, src2);
550640f9ad21SRichard Henderson     } else {
5507d8c5b92fSRichard Henderson         gen_helper_fcmpd(cpu_fcc[a->cc], tcg_env, src1, src2);
550840f9ad21SRichard Henderson     }
550940f9ad21SRichard Henderson     return advance_pc(dc);
551040f9ad21SRichard Henderson }
551140f9ad21SRichard Henderson 
551240f9ad21SRichard Henderson TRANS(FCMPd, ALL, do_fcmpd, a, false)
551340f9ad21SRichard Henderson TRANS(FCMPEd, ALL, do_fcmpd, a, true)
551440f9ad21SRichard Henderson 
551540f9ad21SRichard Henderson static bool do_fcmpq(DisasContext *dc, arg_FCMPq *a, bool e)
551640f9ad21SRichard Henderson {
5517f3ceafadSRichard Henderson     TCGv_i128 src1, src2;
5518f3ceafadSRichard Henderson 
551940f9ad21SRichard Henderson     if (avail_32(dc) && a->cc != 0) {
552040f9ad21SRichard Henderson         return false;
552140f9ad21SRichard Henderson     }
552240f9ad21SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
552340f9ad21SRichard Henderson         return true;
552440f9ad21SRichard Henderson     }
552540f9ad21SRichard Henderson     if (gen_trap_float128(dc)) {
552640f9ad21SRichard Henderson         return true;
552740f9ad21SRichard Henderson     }
552840f9ad21SRichard Henderson 
5529f3ceafadSRichard Henderson     src1 = gen_load_fpr_Q(dc, a->rs1);
5530f3ceafadSRichard Henderson     src2 = gen_load_fpr_Q(dc, a->rs2);
553140f9ad21SRichard Henderson     if (e) {
5532d8c5b92fSRichard Henderson         gen_helper_fcmpeq(cpu_fcc[a->cc], tcg_env, src1, src2);
553340f9ad21SRichard Henderson     } else {
5534d8c5b92fSRichard Henderson         gen_helper_fcmpq(cpu_fcc[a->cc], tcg_env, src1, src2);
553540f9ad21SRichard Henderson     }
553640f9ad21SRichard Henderson     return advance_pc(dc);
553740f9ad21SRichard Henderson }
553840f9ad21SRichard Henderson 
553940f9ad21SRichard Henderson TRANS(FCMPq, ALL, do_fcmpq, a, false)
554040f9ad21SRichard Henderson TRANS(FCMPEq, ALL, do_fcmpq, a, true)
554140f9ad21SRichard Henderson 
55421d3ed3d7SRichard Henderson static bool trans_FLCMPs(DisasContext *dc, arg_FLCMPs *a)
55431d3ed3d7SRichard Henderson {
55441d3ed3d7SRichard Henderson     TCGv_i32 src1, src2;
55451d3ed3d7SRichard Henderson 
55461d3ed3d7SRichard Henderson     if (!avail_VIS3(dc)) {
55471d3ed3d7SRichard Henderson         return false;
55481d3ed3d7SRichard Henderson     }
55491d3ed3d7SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
55501d3ed3d7SRichard Henderson         return true;
55511d3ed3d7SRichard Henderson     }
55521d3ed3d7SRichard Henderson 
55531d3ed3d7SRichard Henderson     src1 = gen_load_fpr_F(dc, a->rs1);
55541d3ed3d7SRichard Henderson     src2 = gen_load_fpr_F(dc, a->rs2);
55551d3ed3d7SRichard Henderson     gen_helper_flcmps(cpu_fcc[a->cc], src1, src2);
55561d3ed3d7SRichard Henderson     return advance_pc(dc);
55571d3ed3d7SRichard Henderson }
55581d3ed3d7SRichard Henderson 
55591d3ed3d7SRichard Henderson static bool trans_FLCMPd(DisasContext *dc, arg_FLCMPd *a)
55601d3ed3d7SRichard Henderson {
55611d3ed3d7SRichard Henderson     TCGv_i64 src1, src2;
55621d3ed3d7SRichard Henderson 
55631d3ed3d7SRichard Henderson     if (!avail_VIS3(dc)) {
55641d3ed3d7SRichard Henderson         return false;
55651d3ed3d7SRichard Henderson     }
55661d3ed3d7SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
55671d3ed3d7SRichard Henderson         return true;
55681d3ed3d7SRichard Henderson     }
55691d3ed3d7SRichard Henderson 
55701d3ed3d7SRichard Henderson     src1 = gen_load_fpr_D(dc, a->rs1);
55711d3ed3d7SRichard Henderson     src2 = gen_load_fpr_D(dc, a->rs2);
55721d3ed3d7SRichard Henderson     gen_helper_flcmpd(cpu_fcc[a->cc], src1, src2);
55731d3ed3d7SRichard Henderson     return advance_pc(dc);
55741d3ed3d7SRichard Henderson }
55751d3ed3d7SRichard Henderson 
557609b157e6SRichard Henderson static bool do_movf2r(DisasContext *dc, arg_r_r *a,
557709b157e6SRichard Henderson                       int (*offset)(unsigned int),
557809b157e6SRichard Henderson                       void (*load)(TCGv, TCGv_ptr, tcg_target_long))
557909b157e6SRichard Henderson {
558009b157e6SRichard Henderson     TCGv dst;
558109b157e6SRichard Henderson 
558209b157e6SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
558309b157e6SRichard Henderson         return true;
558409b157e6SRichard Henderson     }
558509b157e6SRichard Henderson     dst = gen_dest_gpr(dc, a->rd);
558609b157e6SRichard Henderson     load(dst, tcg_env, offset(a->rs));
558709b157e6SRichard Henderson     gen_store_gpr(dc, a->rd, dst);
558809b157e6SRichard Henderson     return advance_pc(dc);
558909b157e6SRichard Henderson }
559009b157e6SRichard Henderson 
559109b157e6SRichard Henderson TRANS(MOVsTOsw, VIS3B, do_movf2r, a, gen_offset_fpr_F, tcg_gen_ld32s_tl)
559209b157e6SRichard Henderson TRANS(MOVsTOuw, VIS3B, do_movf2r, a, gen_offset_fpr_F, tcg_gen_ld32u_tl)
559309b157e6SRichard Henderson TRANS(MOVdTOx, VIS3B, do_movf2r, a, gen_offset_fpr_D, tcg_gen_ld_tl)
559409b157e6SRichard Henderson 
559509b157e6SRichard Henderson static bool do_movr2f(DisasContext *dc, arg_r_r *a,
559609b157e6SRichard Henderson                       int (*offset)(unsigned int),
559709b157e6SRichard Henderson                       void (*store)(TCGv, TCGv_ptr, tcg_target_long))
559809b157e6SRichard Henderson {
559909b157e6SRichard Henderson     TCGv src;
560009b157e6SRichard Henderson 
560109b157e6SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
560209b157e6SRichard Henderson         return true;
560309b157e6SRichard Henderson     }
560409b157e6SRichard Henderson     src = gen_load_gpr(dc, a->rs);
560509b157e6SRichard Henderson     store(src, tcg_env, offset(a->rd));
560609b157e6SRichard Henderson     return advance_pc(dc);
560709b157e6SRichard Henderson }
560809b157e6SRichard Henderson 
560909b157e6SRichard Henderson TRANS(MOVwTOs, VIS3B, do_movr2f, a, gen_offset_fpr_F, tcg_gen_st32_tl)
561009b157e6SRichard Henderson TRANS(MOVxTOd, VIS3B, do_movr2f, a, gen_offset_fpr_D, tcg_gen_st_tl)
561109b157e6SRichard Henderson 
56126e61bc94SEmilio G. Cota static void sparc_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
5613fcf5ef2aSThomas Huth {
56146e61bc94SEmilio G. Cota     DisasContext *dc = container_of(dcbase, DisasContext, base);
56156e61bc94SEmilio G. Cota     int bound;
5616af00be49SEmilio G. Cota 
5617af00be49SEmilio G. Cota     dc->pc = dc->base.pc_first;
56186e61bc94SEmilio G. Cota     dc->npc = (target_ulong)dc->base.tb->cs_base;
56196e61bc94SEmilio G. Cota     dc->mem_idx = dc->base.tb->flags & TB_FLAG_MMU_MASK;
562077976769SPhilippe Mathieu-Daudé     dc->def = &cpu_env(cs)->def;
56216e61bc94SEmilio G. Cota     dc->fpu_enabled = tb_fpu_enabled(dc->base.tb->flags);
56226e61bc94SEmilio G. Cota     dc->address_mask_32bit = tb_am_enabled(dc->base.tb->flags);
5623c9b459aaSArtyom Tarasenko #ifndef CONFIG_USER_ONLY
56246e61bc94SEmilio G. Cota     dc->supervisor = (dc->base.tb->flags & TB_FLAG_SUPER) != 0;
56255a165e26SRichard Henderson # ifdef TARGET_SPARC64
56265a165e26SRichard Henderson     dc->hypervisor = (dc->base.tb->flags & TB_FLAG_HYPER) != 0;
56275a165e26SRichard Henderson # else
56285a165e26SRichard Henderson     dc->fsr_qne = (dc->base.tb->flags & TB_FLAG_FSR_QNE) != 0;
56295a165e26SRichard Henderson # endif
5630c9b459aaSArtyom Tarasenko #endif
5631fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
5632fcf5ef2aSThomas Huth     dc->fprs_dirty = 0;
56336e61bc94SEmilio G. Cota     dc->asi = (dc->base.tb->flags >> TB_FLAG_ASI_SHIFT) & 0xff;
5634fcf5ef2aSThomas Huth #endif
56356e61bc94SEmilio G. Cota     /*
56366e61bc94SEmilio G. Cota      * if we reach a page boundary, we stop generation so that the
56376e61bc94SEmilio G. Cota      * PC of a TT_TFAULT exception is always in the right page
56386e61bc94SEmilio G. Cota      */
56396e61bc94SEmilio G. Cota     bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
56406e61bc94SEmilio G. Cota     dc->base.max_insns = MIN(dc->base.max_insns, bound);
5641af00be49SEmilio G. Cota }
5642fcf5ef2aSThomas Huth 
56436e61bc94SEmilio G. Cota static void sparc_tr_tb_start(DisasContextBase *db, CPUState *cs)
56446e61bc94SEmilio G. Cota {
56456e61bc94SEmilio G. Cota }
56466e61bc94SEmilio G. Cota 
56476e61bc94SEmilio G. Cota static void sparc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
56486e61bc94SEmilio G. Cota {
56496e61bc94SEmilio G. Cota     DisasContext *dc = container_of(dcbase, DisasContext, base);
5650633c4283SRichard Henderson     target_ulong npc = dc->npc;
56516e61bc94SEmilio G. Cota 
5652633c4283SRichard Henderson     if (npc & 3) {
5653633c4283SRichard Henderson         switch (npc) {
5654633c4283SRichard Henderson         case JUMP_PC:
5655fcf5ef2aSThomas Huth             assert(dc->jump_pc[1] == dc->pc + 4);
5656633c4283SRichard Henderson             npc = dc->jump_pc[0] | JUMP_PC;
5657633c4283SRichard Henderson             break;
5658633c4283SRichard Henderson         case DYNAMIC_PC:
5659633c4283SRichard Henderson         case DYNAMIC_PC_LOOKUP:
5660633c4283SRichard Henderson             npc = DYNAMIC_PC;
5661633c4283SRichard Henderson             break;
5662633c4283SRichard Henderson         default:
5663633c4283SRichard Henderson             g_assert_not_reached();
5664fcf5ef2aSThomas Huth         }
56656e61bc94SEmilio G. Cota     }
5666633c4283SRichard Henderson     tcg_gen_insn_start(dc->pc, npc);
5667633c4283SRichard Henderson }
5668fcf5ef2aSThomas Huth 
56696e61bc94SEmilio G. Cota static void sparc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
56706e61bc94SEmilio G. Cota {
56716e61bc94SEmilio G. Cota     DisasContext *dc = container_of(dcbase, DisasContext, base);
56726e61bc94SEmilio G. Cota     unsigned int insn;
5673fcf5ef2aSThomas Huth 
567477976769SPhilippe Mathieu-Daudé     insn = translator_ldl(cpu_env(cs), &dc->base, dc->pc);
5675af00be49SEmilio G. Cota     dc->base.pc_next += 4;
5676878cc677SRichard Henderson 
5677878cc677SRichard Henderson     if (!decode(dc, insn)) {
5678ba9c09b4SRichard Henderson         gen_exception(dc, TT_ILL_INSN);
5679878cc677SRichard Henderson     }
5680fcf5ef2aSThomas Huth 
5681af00be49SEmilio G. Cota     if (dc->base.is_jmp == DISAS_NORETURN) {
56826e61bc94SEmilio G. Cota         return;
5683c5e6ccdfSEmilio G. Cota     }
5684af00be49SEmilio G. Cota     if (dc->pc != dc->base.pc_next) {
56856e61bc94SEmilio G. Cota         dc->base.is_jmp = DISAS_TOO_MANY;
5686af00be49SEmilio G. Cota     }
56876e61bc94SEmilio G. Cota }
5688fcf5ef2aSThomas Huth 
56896e61bc94SEmilio G. Cota static void sparc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
56906e61bc94SEmilio G. Cota {
56916e61bc94SEmilio G. Cota     DisasContext *dc = container_of(dcbase, DisasContext, base);
5692186e7890SRichard Henderson     DisasDelayException *e, *e_next;
5693633c4283SRichard Henderson     bool may_lookup;
56946e61bc94SEmilio G. Cota 
569589527e3aSRichard Henderson     finishing_insn(dc);
569689527e3aSRichard Henderson 
569746bb0137SMark Cave-Ayland     switch (dc->base.is_jmp) {
569846bb0137SMark Cave-Ayland     case DISAS_NEXT:
569946bb0137SMark Cave-Ayland     case DISAS_TOO_MANY:
5700633c4283SRichard Henderson         if (((dc->pc | dc->npc) & 3) == 0) {
5701fcf5ef2aSThomas Huth             /* static PC and NPC: we can use direct chaining */
5702fcf5ef2aSThomas Huth             gen_goto_tb(dc, 0, dc->pc, dc->npc);
5703633c4283SRichard Henderson             break;
5704fcf5ef2aSThomas Huth         }
5705633c4283SRichard Henderson 
5706930f1865SRichard Henderson         may_lookup = true;
5707633c4283SRichard Henderson         if (dc->pc & 3) {
5708633c4283SRichard Henderson             switch (dc->pc) {
5709633c4283SRichard Henderson             case DYNAMIC_PC_LOOKUP:
5710633c4283SRichard Henderson                 break;
5711633c4283SRichard Henderson             case DYNAMIC_PC:
5712633c4283SRichard Henderson                 may_lookup = false;
5713633c4283SRichard Henderson                 break;
5714633c4283SRichard Henderson             default:
5715633c4283SRichard Henderson                 g_assert_not_reached();
5716633c4283SRichard Henderson             }
5717633c4283SRichard Henderson         } else {
5718633c4283SRichard Henderson             tcg_gen_movi_tl(cpu_pc, dc->pc);
5719633c4283SRichard Henderson         }
5720633c4283SRichard Henderson 
5721930f1865SRichard Henderson         if (dc->npc & 3) {
5722930f1865SRichard Henderson             switch (dc->npc) {
5723930f1865SRichard Henderson             case JUMP_PC:
5724930f1865SRichard Henderson                 gen_generic_branch(dc);
5725930f1865SRichard Henderson                 break;
5726930f1865SRichard Henderson             case DYNAMIC_PC:
5727930f1865SRichard Henderson                 may_lookup = false;
5728930f1865SRichard Henderson                 break;
5729930f1865SRichard Henderson             case DYNAMIC_PC_LOOKUP:
5730930f1865SRichard Henderson                 break;
5731930f1865SRichard Henderson             default:
5732930f1865SRichard Henderson                 g_assert_not_reached();
5733930f1865SRichard Henderson             }
5734930f1865SRichard Henderson         } else {
5735930f1865SRichard Henderson             tcg_gen_movi_tl(cpu_npc, dc->npc);
5736930f1865SRichard Henderson         }
5737633c4283SRichard Henderson         if (may_lookup) {
5738633c4283SRichard Henderson             tcg_gen_lookup_and_goto_ptr();
5739633c4283SRichard Henderson         } else {
574007ea28b4SRichard Henderson             tcg_gen_exit_tb(NULL, 0);
5741fcf5ef2aSThomas Huth         }
574246bb0137SMark Cave-Ayland         break;
574346bb0137SMark Cave-Ayland 
574446bb0137SMark Cave-Ayland     case DISAS_NORETURN:
574546bb0137SMark Cave-Ayland        break;
574646bb0137SMark Cave-Ayland 
574746bb0137SMark Cave-Ayland     case DISAS_EXIT:
574846bb0137SMark Cave-Ayland         /* Exit TB */
574946bb0137SMark Cave-Ayland         save_state(dc);
575046bb0137SMark Cave-Ayland         tcg_gen_exit_tb(NULL, 0);
575146bb0137SMark Cave-Ayland         break;
575246bb0137SMark Cave-Ayland 
575346bb0137SMark Cave-Ayland     default:
575446bb0137SMark Cave-Ayland         g_assert_not_reached();
5755fcf5ef2aSThomas Huth     }
5756186e7890SRichard Henderson 
5757186e7890SRichard Henderson     for (e = dc->delay_excp_list; e ; e = e_next) {
5758186e7890SRichard Henderson         gen_set_label(e->lab);
5759186e7890SRichard Henderson 
5760186e7890SRichard Henderson         tcg_gen_movi_tl(cpu_pc, e->pc);
5761186e7890SRichard Henderson         if (e->npc % 4 == 0) {
5762186e7890SRichard Henderson             tcg_gen_movi_tl(cpu_npc, e->npc);
5763186e7890SRichard Henderson         }
5764186e7890SRichard Henderson         gen_helper_raise_exception(tcg_env, e->excp);
5765186e7890SRichard Henderson 
5766186e7890SRichard Henderson         e_next = e->next;
5767186e7890SRichard Henderson         g_free(e);
5768186e7890SRichard Henderson     }
5769fcf5ef2aSThomas Huth }
57706e61bc94SEmilio G. Cota 
57716e61bc94SEmilio G. Cota static const TranslatorOps sparc_tr_ops = {
57726e61bc94SEmilio G. Cota     .init_disas_context = sparc_tr_init_disas_context,
57736e61bc94SEmilio G. Cota     .tb_start           = sparc_tr_tb_start,
57746e61bc94SEmilio G. Cota     .insn_start         = sparc_tr_insn_start,
57756e61bc94SEmilio G. Cota     .translate_insn     = sparc_tr_translate_insn,
57766e61bc94SEmilio G. Cota     .tb_stop            = sparc_tr_tb_stop,
57776e61bc94SEmilio G. Cota };
57786e61bc94SEmilio G. Cota 
5779597f9b2dSRichard Henderson void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int *max_insns,
578032f0c394SAnton Johansson                            vaddr pc, void *host_pc)
57816e61bc94SEmilio G. Cota {
57826e61bc94SEmilio G. Cota     DisasContext dc = {};
57836e61bc94SEmilio G. Cota 
5784306c8721SRichard Henderson     translator_loop(cs, tb, max_insns, pc, host_pc, &sparc_tr_ops, &dc.base);
5785fcf5ef2aSThomas Huth }
5786fcf5ef2aSThomas Huth 
578755c3ceefSRichard Henderson void sparc_tcg_init(void)
5788fcf5ef2aSThomas Huth {
5789fcf5ef2aSThomas Huth     static const char gregnames[32][4] = {
5790fcf5ef2aSThomas Huth         "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
5791fcf5ef2aSThomas Huth         "o0", "o1", "o2", "o3", "o4", "o5", "o6", "o7",
5792fcf5ef2aSThomas Huth         "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
5793fcf5ef2aSThomas Huth         "i0", "i1", "i2", "i3", "i4", "i5", "i6", "i7",
5794fcf5ef2aSThomas Huth     };
5795fcf5ef2aSThomas Huth 
5796d8c5b92fSRichard Henderson     static const struct { TCGv_i32 *ptr; int off; const char *name; } r32[] = {
5797d8c5b92fSRichard Henderson #ifdef TARGET_SPARC64
5798d8c5b92fSRichard Henderson         { &cpu_fprs, offsetof(CPUSPARCState, fprs), "fprs" },
5799d8c5b92fSRichard Henderson         { &cpu_fcc[0], offsetof(CPUSPARCState, fcc[0]), "fcc0" },
5800d8c5b92fSRichard Henderson         { &cpu_fcc[1], offsetof(CPUSPARCState, fcc[1]), "fcc1" },
5801d8c5b92fSRichard Henderson         { &cpu_fcc[2], offsetof(CPUSPARCState, fcc[2]), "fcc2" },
5802d8c5b92fSRichard Henderson         { &cpu_fcc[3], offsetof(CPUSPARCState, fcc[3]), "fcc3" },
5803d8c5b92fSRichard Henderson #else
5804d8c5b92fSRichard Henderson         { &cpu_fcc[0], offsetof(CPUSPARCState, fcc[0]), "fcc" },
5805d8c5b92fSRichard Henderson #endif
5806d8c5b92fSRichard Henderson     };
5807d8c5b92fSRichard Henderson 
5808fcf5ef2aSThomas Huth     static const struct { TCGv *ptr; int off; const char *name; } rtl[] = {
5809fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
5810fcf5ef2aSThomas Huth         { &cpu_gsr, offsetof(CPUSPARCState, gsr), "gsr" },
58112a1905c7SRichard Henderson         { &cpu_xcc_Z, offsetof(CPUSPARCState, xcc_Z), "xcc_Z" },
58122a1905c7SRichard Henderson         { &cpu_xcc_C, offsetof(CPUSPARCState, xcc_C), "xcc_C" },
5813fcf5ef2aSThomas Huth #endif
58142a1905c7SRichard Henderson         { &cpu_cc_N, offsetof(CPUSPARCState, cc_N), "cc_N" },
58152a1905c7SRichard Henderson         { &cpu_cc_V, offsetof(CPUSPARCState, cc_V), "cc_V" },
58162a1905c7SRichard Henderson         { &cpu_icc_Z, offsetof(CPUSPARCState, icc_Z), "icc_Z" },
58172a1905c7SRichard Henderson         { &cpu_icc_C, offsetof(CPUSPARCState, icc_C), "icc_C" },
5818fcf5ef2aSThomas Huth         { &cpu_cond, offsetof(CPUSPARCState, cond), "cond" },
5819fcf5ef2aSThomas Huth         { &cpu_pc, offsetof(CPUSPARCState, pc), "pc" },
5820fcf5ef2aSThomas Huth         { &cpu_npc, offsetof(CPUSPARCState, npc), "npc" },
5821fcf5ef2aSThomas Huth         { &cpu_y, offsetof(CPUSPARCState, y), "y" },
5822fcf5ef2aSThomas Huth         { &cpu_tbr, offsetof(CPUSPARCState, tbr), "tbr" },
5823fcf5ef2aSThomas Huth     };
5824fcf5ef2aSThomas Huth 
5825fcf5ef2aSThomas Huth     unsigned int i;
5826fcf5ef2aSThomas Huth 
5827ad75a51eSRichard Henderson     cpu_regwptr = tcg_global_mem_new_ptr(tcg_env,
5828fcf5ef2aSThomas Huth                                          offsetof(CPUSPARCState, regwptr),
5829fcf5ef2aSThomas Huth                                          "regwptr");
5830fcf5ef2aSThomas Huth 
5831d8c5b92fSRichard Henderson     for (i = 0; i < ARRAY_SIZE(r32); ++i) {
5832d8c5b92fSRichard Henderson         *r32[i].ptr = tcg_global_mem_new_i32(tcg_env, r32[i].off, r32[i].name);
5833d8c5b92fSRichard Henderson     }
5834d8c5b92fSRichard Henderson 
5835fcf5ef2aSThomas Huth     for (i = 0; i < ARRAY_SIZE(rtl); ++i) {
5836ad75a51eSRichard Henderson         *rtl[i].ptr = tcg_global_mem_new(tcg_env, rtl[i].off, rtl[i].name);
5837fcf5ef2aSThomas Huth     }
5838fcf5ef2aSThomas Huth 
5839f764718dSRichard Henderson     cpu_regs[0] = NULL;
5840fcf5ef2aSThomas Huth     for (i = 1; i < 8; ++i) {
5841ad75a51eSRichard Henderson         cpu_regs[i] = tcg_global_mem_new(tcg_env,
5842fcf5ef2aSThomas Huth                                          offsetof(CPUSPARCState, gregs[i]),
5843fcf5ef2aSThomas Huth                                          gregnames[i]);
5844fcf5ef2aSThomas Huth     }
5845fcf5ef2aSThomas Huth 
5846fcf5ef2aSThomas Huth     for (i = 8; i < 32; ++i) {
5847fcf5ef2aSThomas Huth         cpu_regs[i] = tcg_global_mem_new(cpu_regwptr,
5848fcf5ef2aSThomas Huth                                          (i - 8) * sizeof(target_ulong),
5849fcf5ef2aSThomas Huth                                          gregnames[i]);
5850fcf5ef2aSThomas Huth     }
5851fcf5ef2aSThomas Huth }
5852fcf5ef2aSThomas Huth 
5853f36aaa53SRichard Henderson void sparc_restore_state_to_opc(CPUState *cs,
5854f36aaa53SRichard Henderson                                 const TranslationBlock *tb,
5855f36aaa53SRichard Henderson                                 const uint64_t *data)
5856fcf5ef2aSThomas Huth {
585777976769SPhilippe Mathieu-Daudé     CPUSPARCState *env = cpu_env(cs);
5858fcf5ef2aSThomas Huth     target_ulong pc = data[0];
5859fcf5ef2aSThomas Huth     target_ulong npc = data[1];
5860fcf5ef2aSThomas Huth 
5861fcf5ef2aSThomas Huth     env->pc = pc;
5862fcf5ef2aSThomas Huth     if (npc == DYNAMIC_PC) {
5863fcf5ef2aSThomas Huth         /* dynamic NPC: already stored */
5864fcf5ef2aSThomas Huth     } else if (npc & JUMP_PC) {
5865fcf5ef2aSThomas Huth         /* jump PC: use 'cond' and the jump targets of the translation */
5866fcf5ef2aSThomas Huth         if (env->cond) {
5867fcf5ef2aSThomas Huth             env->npc = npc & ~3;
5868fcf5ef2aSThomas Huth         } else {
5869fcf5ef2aSThomas Huth             env->npc = pc + 4;
5870fcf5ef2aSThomas Huth         }
5871fcf5ef2aSThomas Huth     } else {
5872fcf5ef2aSThomas Huth         env->npc = npc;
5873fcf5ef2aSThomas Huth     }
5874fcf5ef2aSThomas Huth }
5875