xref: /openbmc/qemu/target/sparc/translate.c (revision 1210a0367d5e9eca7679d401e422c48b61b421b0)
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"
31fcf5ef2aSThomas Huth #include "asi.h"
32fcf5ef2aSThomas Huth 
33d53106c9SRichard Henderson #define HELPER_H "helper.h"
34d53106c9SRichard Henderson #include "exec/helper-info.c.inc"
35d53106c9SRichard Henderson #undef  HELPER_H
36fcf5ef2aSThomas Huth 
37668bb9b7SRichard Henderson #ifdef TARGET_SPARC64
38668bb9b7SRichard Henderson # define gen_helper_rdpsr(D, E)                 qemu_build_not_reached()
39c92948f2SClément Chigot # define gen_helper_rdasr17(D, E)               qemu_build_not_reached()
4086b82fe0SRichard Henderson # define gen_helper_rett(E)                     qemu_build_not_reached()
410faef01bSRichard Henderson # define gen_helper_power_down(E)               qemu_build_not_reached()
4225524734SRichard Henderson # define gen_helper_wrpsr(E, S)                 qemu_build_not_reached()
43668bb9b7SRichard Henderson #else
440faef01bSRichard Henderson # define gen_helper_clear_softint(E, S)         qemu_build_not_reached()
458f75b8a4SRichard Henderson # define gen_helper_done(E)                     qemu_build_not_reached()
46e8325dc0SRichard Henderson # define gen_helper_flushw(E)                   qemu_build_not_reached()
47a859602cSRichard Henderson # define gen_helper_fmul8x16a(D, S1, S2)        qemu_build_not_reached()
48af25071cSRichard Henderson # define gen_helper_rdccr(D, E)                 qemu_build_not_reached()
495d617bfbSRichard Henderson # define gen_helper_rdcwp(D, E)                 qemu_build_not_reached()
5025524734SRichard Henderson # define gen_helper_restored(E)                 qemu_build_not_reached()
518f75b8a4SRichard Henderson # define gen_helper_retry(E)                    qemu_build_not_reached()
5225524734SRichard Henderson # define gen_helper_saved(E)                    qemu_build_not_reached()
530faef01bSRichard Henderson # define gen_helper_set_softint(E, S)           qemu_build_not_reached()
54af25071cSRichard Henderson # define gen_helper_tick_get_count(D, E, T, C)  qemu_build_not_reached()
559422278eSRichard Henderson # define gen_helper_tick_set_count(P, S)        qemu_build_not_reached()
56bb97f2f5SRichard Henderson # define gen_helper_tick_set_limit(P, S)        qemu_build_not_reached()
570faef01bSRichard Henderson # define gen_helper_wrccr(E, S)                 qemu_build_not_reached()
589422278eSRichard Henderson # define gen_helper_wrcwp(E, S)                 qemu_build_not_reached()
599422278eSRichard Henderson # define gen_helper_wrgl(E, S)                  qemu_build_not_reached()
600faef01bSRichard Henderson # define gen_helper_write_softint(E, S)         qemu_build_not_reached()
619422278eSRichard Henderson # define gen_helper_wrpil(E, S)                 qemu_build_not_reached()
629422278eSRichard Henderson # define gen_helper_wrpstate(E, S)              qemu_build_not_reached()
63e2fa6bd1SRichard Henderson # define gen_helper_fcmpeq16             ({ qemu_build_not_reached(); NULL; })
64e2fa6bd1SRichard Henderson # define gen_helper_fcmpeq32             ({ qemu_build_not_reached(); NULL; })
65e2fa6bd1SRichard Henderson # define gen_helper_fcmpgt16             ({ qemu_build_not_reached(); NULL; })
66e2fa6bd1SRichard Henderson # define gen_helper_fcmpgt32             ({ qemu_build_not_reached(); NULL; })
67e2fa6bd1SRichard Henderson # define gen_helper_fcmple16             ({ qemu_build_not_reached(); NULL; })
68e2fa6bd1SRichard Henderson # define gen_helper_fcmple32             ({ qemu_build_not_reached(); NULL; })
69e2fa6bd1SRichard Henderson # define gen_helper_fcmpne16             ({ qemu_build_not_reached(); NULL; })
70e2fa6bd1SRichard Henderson # define gen_helper_fcmpne32             ({ qemu_build_not_reached(); NULL; })
718aa418b3SRichard Henderson # define gen_helper_fdtox                ({ qemu_build_not_reached(); NULL; })
72e06c9f83SRichard Henderson # define gen_helper_fexpand              ({ qemu_build_not_reached(); NULL; })
73e06c9f83SRichard Henderson # define gen_helper_fmul8sux16           ({ qemu_build_not_reached(); NULL; })
74e06c9f83SRichard Henderson # define gen_helper_fmul8ulx16           ({ qemu_build_not_reached(); NULL; })
75e06c9f83SRichard Henderson # define gen_helper_fmul8x16             ({ qemu_build_not_reached(); NULL; })
76e06c9f83SRichard Henderson # define gen_helper_fpmerge              ({ qemu_build_not_reached(); NULL; })
771617586fSRichard Henderson # define gen_helper_fqtox                ({ qemu_build_not_reached(); NULL; })
78199d43efSRichard Henderson # define gen_helper_fstox                ({ qemu_build_not_reached(); NULL; })
798aa418b3SRichard Henderson # define gen_helper_fxtod                ({ qemu_build_not_reached(); NULL; })
807b8e3e1aSRichard Henderson # define gen_helper_fxtoq                ({ qemu_build_not_reached(); NULL; })
81f4e18df5SRichard Henderson # define gen_helper_fxtos                ({ qemu_build_not_reached(); NULL; })
82afb04344SRichard Henderson # define gen_helper_pdist                ({ qemu_build_not_reached(); NULL; })
83668bb9b7SRichard Henderson # define MAXTL_MASK                             0
84af25071cSRichard Henderson #endif
85af25071cSRichard Henderson 
86633c4283SRichard Henderson /* Dynamic PC, must exit to main loop. */
87633c4283SRichard Henderson #define DYNAMIC_PC         1
88633c4283SRichard Henderson /* Dynamic PC, one of two values according to jump_pc[T2]. */
89633c4283SRichard Henderson #define JUMP_PC            2
90633c4283SRichard Henderson /* Dynamic PC, may lookup next TB. */
91633c4283SRichard Henderson #define DYNAMIC_PC_LOOKUP  3
92fcf5ef2aSThomas Huth 
9346bb0137SMark Cave-Ayland #define DISAS_EXIT  DISAS_TARGET_0
9446bb0137SMark Cave-Ayland 
95fcf5ef2aSThomas Huth /* global register indexes */
96fcf5ef2aSThomas Huth static TCGv_ptr cpu_regwptr;
97c9fa8e58SRichard Henderson static TCGv cpu_pc, cpu_npc;
98fcf5ef2aSThomas Huth static TCGv cpu_regs[32];
99fcf5ef2aSThomas Huth static TCGv cpu_y;
100fcf5ef2aSThomas Huth static TCGv cpu_tbr;
101fcf5ef2aSThomas Huth static TCGv cpu_cond;
1022a1905c7SRichard Henderson static TCGv cpu_cc_N;
1032a1905c7SRichard Henderson static TCGv cpu_cc_V;
1042a1905c7SRichard Henderson static TCGv cpu_icc_Z;
1052a1905c7SRichard Henderson static TCGv cpu_icc_C;
106fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
1072a1905c7SRichard Henderson static TCGv cpu_xcc_Z;
1082a1905c7SRichard Henderson static TCGv cpu_xcc_C;
1092a1905c7SRichard Henderson static TCGv_i32 cpu_fprs;
110fcf5ef2aSThomas Huth static TCGv cpu_gsr;
111fcf5ef2aSThomas Huth #else
112af25071cSRichard Henderson # define cpu_fprs               ({ qemu_build_not_reached(); (TCGv)NULL; })
113af25071cSRichard Henderson # define cpu_gsr                ({ qemu_build_not_reached(); (TCGv)NULL; })
114fcf5ef2aSThomas Huth #endif
1152a1905c7SRichard Henderson 
1162a1905c7SRichard Henderson #ifdef TARGET_SPARC64
1172a1905c7SRichard Henderson #define cpu_cc_Z  cpu_xcc_Z
1182a1905c7SRichard Henderson #define cpu_cc_C  cpu_xcc_C
1192a1905c7SRichard Henderson #else
1202a1905c7SRichard Henderson #define cpu_cc_Z  cpu_icc_Z
1212a1905c7SRichard Henderson #define cpu_cc_C  cpu_icc_C
1222a1905c7SRichard Henderson #define cpu_xcc_Z ({ qemu_build_not_reached(); NULL; })
1232a1905c7SRichard Henderson #define cpu_xcc_C ({ qemu_build_not_reached(); NULL; })
1242a1905c7SRichard Henderson #endif
1252a1905c7SRichard Henderson 
126*1210a036SRichard Henderson /* Floating point comparison registers */
127d8c5b92fSRichard Henderson static TCGv_i32 cpu_fcc[TARGET_FCCREGS];
128fcf5ef2aSThomas Huth 
129af25071cSRichard Henderson #define env_field_offsetof(X)     offsetof(CPUSPARCState, X)
130af25071cSRichard Henderson #ifdef TARGET_SPARC64
131cd6269f7SRichard Henderson # define env32_field_offsetof(X)  ({ qemu_build_not_reached(); 0; })
132af25071cSRichard Henderson # define env64_field_offsetof(X)  env_field_offsetof(X)
133af25071cSRichard Henderson #else
134cd6269f7SRichard Henderson # define env32_field_offsetof(X)  env_field_offsetof(X)
135af25071cSRichard Henderson # define env64_field_offsetof(X)  ({ qemu_build_not_reached(); 0; })
136af25071cSRichard Henderson #endif
137af25071cSRichard Henderson 
138533f042fSRichard Henderson typedef struct DisasCompare {
139533f042fSRichard Henderson     TCGCond cond;
140533f042fSRichard Henderson     TCGv c1;
141533f042fSRichard Henderson     int c2;
142533f042fSRichard Henderson } DisasCompare;
143533f042fSRichard Henderson 
144186e7890SRichard Henderson typedef struct DisasDelayException {
145186e7890SRichard Henderson     struct DisasDelayException *next;
146186e7890SRichard Henderson     TCGLabel *lab;
147186e7890SRichard Henderson     TCGv_i32 excp;
148186e7890SRichard Henderson     /* Saved state at parent insn. */
149186e7890SRichard Henderson     target_ulong pc;
150186e7890SRichard Henderson     target_ulong npc;
151186e7890SRichard Henderson } DisasDelayException;
152186e7890SRichard Henderson 
153fcf5ef2aSThomas Huth typedef struct DisasContext {
154af00be49SEmilio G. Cota     DisasContextBase base;
155fcf5ef2aSThomas Huth     target_ulong pc;    /* current Program Counter: integer or DYNAMIC_PC */
156fcf5ef2aSThomas Huth     target_ulong npc;   /* next PC: integer or DYNAMIC_PC or JUMP_PC */
157533f042fSRichard Henderson 
158533f042fSRichard Henderson     /* Used when JUMP_PC value is used. */
159533f042fSRichard Henderson     DisasCompare jump;
160533f042fSRichard Henderson     target_ulong jump_pc[2];
161533f042fSRichard Henderson 
162fcf5ef2aSThomas Huth     int mem_idx;
16389527e3aSRichard Henderson     bool cpu_cond_live;
164c9b459aaSArtyom Tarasenko     bool fpu_enabled;
165c9b459aaSArtyom Tarasenko     bool address_mask_32bit;
166c9b459aaSArtyom Tarasenko #ifndef CONFIG_USER_ONLY
167c9b459aaSArtyom Tarasenko     bool supervisor;
168c9b459aaSArtyom Tarasenko #ifdef TARGET_SPARC64
169c9b459aaSArtyom Tarasenko     bool hypervisor;
170c9b459aaSArtyom Tarasenko #endif
171c9b459aaSArtyom Tarasenko #endif
172c9b459aaSArtyom Tarasenko 
173fcf5ef2aSThomas Huth     sparc_def_t *def;
174fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
175fcf5ef2aSThomas Huth     int fprs_dirty;
176fcf5ef2aSThomas Huth     int asi;
177fcf5ef2aSThomas Huth #endif
178186e7890SRichard Henderson     DisasDelayException *delay_excp_list;
179fcf5ef2aSThomas Huth } DisasContext;
180fcf5ef2aSThomas Huth 
181fcf5ef2aSThomas Huth // This function uses non-native bit order
182fcf5ef2aSThomas Huth #define GET_FIELD(X, FROM, TO)                                  \
183fcf5ef2aSThomas Huth     ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))
184fcf5ef2aSThomas Huth 
185fcf5ef2aSThomas Huth // This function uses the order in the manuals, i.e. bit 0 is 2^0
186fcf5ef2aSThomas Huth #define GET_FIELD_SP(X, FROM, TO)               \
187fcf5ef2aSThomas Huth     GET_FIELD(X, 31 - (TO), 31 - (FROM))
188fcf5ef2aSThomas Huth 
189fcf5ef2aSThomas Huth #define GET_FIELDs(x,a,b) sign_extend (GET_FIELD(x,a,b), (b) - (a) + 1)
190fcf5ef2aSThomas Huth #define GET_FIELD_SPs(x,a,b) sign_extend (GET_FIELD_SP(x,a,b), ((b) - (a) + 1))
191fcf5ef2aSThomas Huth 
192fcf5ef2aSThomas Huth #define UA2005_HTRAP_MASK 0xff
193fcf5ef2aSThomas Huth #define V8_TRAP_MASK 0x7f
194fcf5ef2aSThomas Huth 
195fcf5ef2aSThomas Huth #define IS_IMM (insn & (1<<13))
196fcf5ef2aSThomas Huth 
1970c2e96c1SRichard Henderson static void gen_update_fprs_dirty(DisasContext *dc, int rd)
198fcf5ef2aSThomas Huth {
199fcf5ef2aSThomas Huth #if defined(TARGET_SPARC64)
200fcf5ef2aSThomas Huth     int bit = (rd < 32) ? 1 : 2;
201fcf5ef2aSThomas Huth     /* If we know we've already set this bit within the TB,
202fcf5ef2aSThomas Huth        we can avoid setting it again.  */
203fcf5ef2aSThomas Huth     if (!(dc->fprs_dirty & bit)) {
204fcf5ef2aSThomas Huth         dc->fprs_dirty |= bit;
205fcf5ef2aSThomas Huth         tcg_gen_ori_i32(cpu_fprs, cpu_fprs, bit);
206fcf5ef2aSThomas Huth     }
207fcf5ef2aSThomas Huth #endif
208fcf5ef2aSThomas Huth }
209fcf5ef2aSThomas Huth 
210fcf5ef2aSThomas Huth /* floating point registers moves */
211*1210a036SRichard Henderson 
212*1210a036SRichard Henderson static int gen_offset_fpr_F(unsigned int reg)
213*1210a036SRichard Henderson {
214*1210a036SRichard Henderson     int ret;
215*1210a036SRichard Henderson 
216*1210a036SRichard Henderson     tcg_debug_assert(reg < 32);
217*1210a036SRichard Henderson     ret= offsetof(CPUSPARCState, fpr[reg / 2]);
218*1210a036SRichard Henderson     if (reg & 1) {
219*1210a036SRichard Henderson         ret += offsetof(CPU_DoubleU, l.lower);
220*1210a036SRichard Henderson     } else {
221*1210a036SRichard Henderson         ret += offsetof(CPU_DoubleU, l.upper);
222*1210a036SRichard Henderson     }
223*1210a036SRichard Henderson     return ret;
224*1210a036SRichard Henderson }
225*1210a036SRichard Henderson 
226fcf5ef2aSThomas Huth static TCGv_i32 gen_load_fpr_F(DisasContext *dc, unsigned int src)
227fcf5ef2aSThomas Huth {
22836ab4623SRichard Henderson     TCGv_i32 ret = tcg_temp_new_i32();
229*1210a036SRichard Henderson     tcg_gen_ld_i32(ret, tcg_env, gen_offset_fpr_F(src));
230dc41aa7dSRichard Henderson     return ret;
231fcf5ef2aSThomas Huth }
232fcf5ef2aSThomas Huth 
233fcf5ef2aSThomas Huth static void gen_store_fpr_F(DisasContext *dc, unsigned int dst, TCGv_i32 v)
234fcf5ef2aSThomas Huth {
235*1210a036SRichard Henderson     tcg_gen_st_i32(v, tcg_env, gen_offset_fpr_F(dst));
236fcf5ef2aSThomas Huth     gen_update_fprs_dirty(dc, dst);
237fcf5ef2aSThomas Huth }
238fcf5ef2aSThomas Huth 
239*1210a036SRichard Henderson static int gen_offset_fpr_D(unsigned int reg)
240*1210a036SRichard Henderson {
241*1210a036SRichard Henderson     tcg_debug_assert(reg < 64);
242*1210a036SRichard Henderson     tcg_debug_assert(reg % 2 == 0);
243*1210a036SRichard Henderson     return offsetof(CPUSPARCState, fpr[reg / 2]);
244*1210a036SRichard Henderson }
245*1210a036SRichard Henderson 
246fcf5ef2aSThomas Huth static TCGv_i64 gen_load_fpr_D(DisasContext *dc, unsigned int src)
247fcf5ef2aSThomas Huth {
248*1210a036SRichard Henderson     TCGv_i64 ret = tcg_temp_new_i64();
249*1210a036SRichard Henderson     tcg_gen_ld_i64(ret, tcg_env, gen_offset_fpr_D(src));
250*1210a036SRichard Henderson     return ret;
251fcf5ef2aSThomas Huth }
252fcf5ef2aSThomas Huth 
253fcf5ef2aSThomas Huth static void gen_store_fpr_D(DisasContext *dc, unsigned int dst, TCGv_i64 v)
254fcf5ef2aSThomas Huth {
255*1210a036SRichard Henderson     tcg_gen_st_i64(v, tcg_env, gen_offset_fpr_D(dst));
256fcf5ef2aSThomas Huth     gen_update_fprs_dirty(dc, dst);
257fcf5ef2aSThomas Huth }
258fcf5ef2aSThomas Huth 
25933ec4245SRichard Henderson static TCGv_i128 gen_load_fpr_Q(DisasContext *dc, unsigned int src)
26033ec4245SRichard Henderson {
26133ec4245SRichard Henderson     TCGv_i128 ret = tcg_temp_new_i128();
262*1210a036SRichard Henderson     TCGv_i64 h = gen_load_fpr_D(dc, src);
263*1210a036SRichard Henderson     TCGv_i64 l = gen_load_fpr_D(dc, src + 2);
26433ec4245SRichard Henderson 
265*1210a036SRichard Henderson     tcg_gen_concat_i64_i128(ret, l, h);
26633ec4245SRichard Henderson     return ret;
26733ec4245SRichard Henderson }
26833ec4245SRichard Henderson 
26933ec4245SRichard Henderson static void gen_store_fpr_Q(DisasContext *dc, unsigned int dst, TCGv_i128 v)
27033ec4245SRichard Henderson {
271*1210a036SRichard Henderson     TCGv_i64 h = tcg_temp_new_i64();
272*1210a036SRichard Henderson     TCGv_i64 l = tcg_temp_new_i64();
273*1210a036SRichard Henderson 
274*1210a036SRichard Henderson     tcg_gen_extr_i128_i64(l, h, v);
275*1210a036SRichard Henderson     gen_store_fpr_D(dc, dst, h);
276*1210a036SRichard Henderson     gen_store_fpr_D(dc, dst + 2, l);
27733ec4245SRichard Henderson }
27833ec4245SRichard Henderson 
279fcf5ef2aSThomas Huth /* moves */
280fcf5ef2aSThomas Huth #ifdef CONFIG_USER_ONLY
281fcf5ef2aSThomas Huth #define supervisor(dc) 0
282fcf5ef2aSThomas Huth #define hypervisor(dc) 0
283fcf5ef2aSThomas Huth #else
284fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
285c9b459aaSArtyom Tarasenko #define hypervisor(dc) (dc->hypervisor)
286c9b459aaSArtyom Tarasenko #define supervisor(dc) (dc->supervisor | dc->hypervisor)
287fcf5ef2aSThomas Huth #else
288c9b459aaSArtyom Tarasenko #define supervisor(dc) (dc->supervisor)
289668bb9b7SRichard Henderson #define hypervisor(dc) 0
290fcf5ef2aSThomas Huth #endif
291fcf5ef2aSThomas Huth #endif
292fcf5ef2aSThomas Huth 
293b1bc09eaSRichard Henderson #if !defined(TARGET_SPARC64)
294b1bc09eaSRichard Henderson # define AM_CHECK(dc)  false
295b1bc09eaSRichard Henderson #elif defined(TARGET_ABI32)
296b1bc09eaSRichard Henderson # define AM_CHECK(dc)  true
297b1bc09eaSRichard Henderson #elif defined(CONFIG_USER_ONLY)
298b1bc09eaSRichard Henderson # define AM_CHECK(dc)  false
299fcf5ef2aSThomas Huth #else
300b1bc09eaSRichard Henderson # define AM_CHECK(dc)  ((dc)->address_mask_32bit)
301fcf5ef2aSThomas Huth #endif
302fcf5ef2aSThomas Huth 
3030c2e96c1SRichard Henderson static void gen_address_mask(DisasContext *dc, TCGv addr)
304fcf5ef2aSThomas Huth {
305b1bc09eaSRichard Henderson     if (AM_CHECK(dc)) {
306fcf5ef2aSThomas Huth         tcg_gen_andi_tl(addr, addr, 0xffffffffULL);
307b1bc09eaSRichard Henderson     }
308fcf5ef2aSThomas Huth }
309fcf5ef2aSThomas Huth 
31023ada1b1SRichard Henderson static target_ulong address_mask_i(DisasContext *dc, target_ulong addr)
31123ada1b1SRichard Henderson {
31223ada1b1SRichard Henderson     return AM_CHECK(dc) ? (uint32_t)addr : addr;
31323ada1b1SRichard Henderson }
31423ada1b1SRichard Henderson 
3150c2e96c1SRichard Henderson static TCGv gen_load_gpr(DisasContext *dc, int reg)
316fcf5ef2aSThomas Huth {
317fcf5ef2aSThomas Huth     if (reg > 0) {
318fcf5ef2aSThomas Huth         assert(reg < 32);
319fcf5ef2aSThomas Huth         return cpu_regs[reg];
320fcf5ef2aSThomas Huth     } else {
32152123f14SRichard Henderson         TCGv t = tcg_temp_new();
322fcf5ef2aSThomas Huth         tcg_gen_movi_tl(t, 0);
323fcf5ef2aSThomas Huth         return t;
324fcf5ef2aSThomas Huth     }
325fcf5ef2aSThomas Huth }
326fcf5ef2aSThomas Huth 
3270c2e96c1SRichard Henderson static void gen_store_gpr(DisasContext *dc, int reg, TCGv v)
328fcf5ef2aSThomas Huth {
329fcf5ef2aSThomas Huth     if (reg > 0) {
330fcf5ef2aSThomas Huth         assert(reg < 32);
331fcf5ef2aSThomas Huth         tcg_gen_mov_tl(cpu_regs[reg], v);
332fcf5ef2aSThomas Huth     }
333fcf5ef2aSThomas Huth }
334fcf5ef2aSThomas Huth 
3350c2e96c1SRichard Henderson static TCGv gen_dest_gpr(DisasContext *dc, int reg)
336fcf5ef2aSThomas Huth {
337fcf5ef2aSThomas Huth     if (reg > 0) {
338fcf5ef2aSThomas Huth         assert(reg < 32);
339fcf5ef2aSThomas Huth         return cpu_regs[reg];
340fcf5ef2aSThomas Huth     } else {
34152123f14SRichard Henderson         return tcg_temp_new();
342fcf5ef2aSThomas Huth     }
343fcf5ef2aSThomas Huth }
344fcf5ef2aSThomas Huth 
3455645aa2eSRichard Henderson static bool use_goto_tb(DisasContext *s, target_ulong pc, target_ulong npc)
346fcf5ef2aSThomas Huth {
3475645aa2eSRichard Henderson     return translator_use_goto_tb(&s->base, pc) &&
3485645aa2eSRichard Henderson            translator_use_goto_tb(&s->base, npc);
349fcf5ef2aSThomas Huth }
350fcf5ef2aSThomas Huth 
3515645aa2eSRichard Henderson static void gen_goto_tb(DisasContext *s, int tb_num,
352fcf5ef2aSThomas Huth                         target_ulong pc, target_ulong npc)
353fcf5ef2aSThomas Huth {
354fcf5ef2aSThomas Huth     if (use_goto_tb(s, pc, npc))  {
355fcf5ef2aSThomas Huth         /* jump to same page: we can use a direct jump */
356fcf5ef2aSThomas Huth         tcg_gen_goto_tb(tb_num);
357fcf5ef2aSThomas Huth         tcg_gen_movi_tl(cpu_pc, pc);
358fcf5ef2aSThomas Huth         tcg_gen_movi_tl(cpu_npc, npc);
35907ea28b4SRichard Henderson         tcg_gen_exit_tb(s->base.tb, tb_num);
360fcf5ef2aSThomas Huth     } else {
361f67ccb2fSRichard Henderson         /* jump to another page: we can use an indirect jump */
362fcf5ef2aSThomas Huth         tcg_gen_movi_tl(cpu_pc, pc);
363fcf5ef2aSThomas Huth         tcg_gen_movi_tl(cpu_npc, npc);
364f67ccb2fSRichard Henderson         tcg_gen_lookup_and_goto_ptr();
365fcf5ef2aSThomas Huth     }
366fcf5ef2aSThomas Huth }
367fcf5ef2aSThomas Huth 
368b989ce73SRichard Henderson static TCGv gen_carry32(void)
369fcf5ef2aSThomas Huth {
370b989ce73SRichard Henderson     if (TARGET_LONG_BITS == 64) {
371b989ce73SRichard Henderson         TCGv t = tcg_temp_new();
372b989ce73SRichard Henderson         tcg_gen_extract_tl(t, cpu_icc_C, 32, 1);
373b989ce73SRichard Henderson         return t;
374b989ce73SRichard Henderson     }
375b989ce73SRichard Henderson     return cpu_icc_C;
376fcf5ef2aSThomas Huth }
377fcf5ef2aSThomas Huth 
378b989ce73SRichard Henderson static void gen_op_addcc_int(TCGv dst, TCGv src1, TCGv src2, TCGv cin)
379fcf5ef2aSThomas Huth {
380b989ce73SRichard Henderson     TCGv z = tcg_constant_tl(0);
381fcf5ef2aSThomas Huth 
382b989ce73SRichard Henderson     if (cin) {
383b989ce73SRichard Henderson         tcg_gen_add2_tl(cpu_cc_N, cpu_cc_C, src1, z, cin, z);
384b989ce73SRichard Henderson         tcg_gen_add2_tl(cpu_cc_N, cpu_cc_C, cpu_cc_N, cpu_cc_C, src2, z);
385b989ce73SRichard Henderson     } else {
386b989ce73SRichard Henderson         tcg_gen_add2_tl(cpu_cc_N, cpu_cc_C, src1, z, src2, z);
387b989ce73SRichard Henderson     }
388b989ce73SRichard Henderson     tcg_gen_xor_tl(cpu_cc_Z, src1, src2);
389b989ce73SRichard Henderson     tcg_gen_xor_tl(cpu_cc_V, cpu_cc_N, src2);
390b989ce73SRichard Henderson     tcg_gen_andc_tl(cpu_cc_V, cpu_cc_V, cpu_cc_Z);
391b989ce73SRichard Henderson     if (TARGET_LONG_BITS == 64) {
392b989ce73SRichard Henderson         /*
393b989ce73SRichard Henderson          * Carry-in to bit 32 is result ^ src1 ^ src2.
394b989ce73SRichard Henderson          * We already have the src xor term in Z, from computation of V.
395b989ce73SRichard Henderson          */
396b989ce73SRichard Henderson         tcg_gen_xor_tl(cpu_icc_C, cpu_cc_Z, cpu_cc_N);
397b989ce73SRichard Henderson         tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N);
398b989ce73SRichard Henderson     }
399b989ce73SRichard Henderson     tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N);
400b989ce73SRichard Henderson     tcg_gen_mov_tl(dst, cpu_cc_N);
401b989ce73SRichard Henderson }
402fcf5ef2aSThomas Huth 
403b989ce73SRichard Henderson static void gen_op_addcc(TCGv dst, TCGv src1, TCGv src2)
404b989ce73SRichard Henderson {
405b989ce73SRichard Henderson     gen_op_addcc_int(dst, src1, src2, NULL);
406b989ce73SRichard Henderson }
407fcf5ef2aSThomas Huth 
408b989ce73SRichard Henderson static void gen_op_taddcc(TCGv dst, TCGv src1, TCGv src2)
409b989ce73SRichard Henderson {
410b989ce73SRichard Henderson     TCGv t = tcg_temp_new();
411b989ce73SRichard Henderson 
412b989ce73SRichard Henderson     /* Save the tag bits around modification of dst. */
413b989ce73SRichard Henderson     tcg_gen_or_tl(t, src1, src2);
414b989ce73SRichard Henderson 
415b989ce73SRichard Henderson     gen_op_addcc(dst, src1, src2);
416b989ce73SRichard Henderson 
417b989ce73SRichard Henderson     /* Incorprate tag bits into icc.V */
418b989ce73SRichard Henderson     tcg_gen_andi_tl(t, t, 3);
419b989ce73SRichard Henderson     tcg_gen_neg_tl(t, t);
420b989ce73SRichard Henderson     tcg_gen_ext32u_tl(t, t);
421b989ce73SRichard Henderson     tcg_gen_or_tl(cpu_cc_V, cpu_cc_V, t);
422b989ce73SRichard Henderson }
423b989ce73SRichard Henderson 
424b989ce73SRichard Henderson static void gen_op_addc(TCGv dst, TCGv src1, TCGv src2)
425b989ce73SRichard Henderson {
426b989ce73SRichard Henderson     tcg_gen_add_tl(dst, src1, src2);
427b989ce73SRichard Henderson     tcg_gen_add_tl(dst, dst, gen_carry32());
428b989ce73SRichard Henderson }
429b989ce73SRichard Henderson 
430b989ce73SRichard Henderson static void gen_op_addccc(TCGv dst, TCGv src1, TCGv src2)
431b989ce73SRichard Henderson {
432b989ce73SRichard Henderson     gen_op_addcc_int(dst, src1, src2, gen_carry32());
433fcf5ef2aSThomas Huth }
434fcf5ef2aSThomas Huth 
435f828df74SRichard Henderson static void gen_op_subcc_int(TCGv dst, TCGv src1, TCGv src2, TCGv cin)
436fcf5ef2aSThomas Huth {
437f828df74SRichard Henderson     TCGv z = tcg_constant_tl(0);
438fcf5ef2aSThomas Huth 
439f828df74SRichard Henderson     if (cin) {
440f828df74SRichard Henderson         tcg_gen_sub2_tl(cpu_cc_N, cpu_cc_C, src1, z, cin, z);
441f828df74SRichard Henderson         tcg_gen_sub2_tl(cpu_cc_N, cpu_cc_C, cpu_cc_N, cpu_cc_C, src2, z);
442f828df74SRichard Henderson     } else {
443f828df74SRichard Henderson         tcg_gen_sub2_tl(cpu_cc_N, cpu_cc_C, src1, z, src2, z);
444f828df74SRichard Henderson     }
445f828df74SRichard Henderson     tcg_gen_neg_tl(cpu_cc_C, cpu_cc_C);
446f828df74SRichard Henderson     tcg_gen_xor_tl(cpu_cc_Z, src1, src2);
447f828df74SRichard Henderson     tcg_gen_xor_tl(cpu_cc_V, cpu_cc_N, src1);
448f828df74SRichard Henderson     tcg_gen_and_tl(cpu_cc_V, cpu_cc_V, cpu_cc_Z);
449f828df74SRichard Henderson #ifdef TARGET_SPARC64
450f828df74SRichard Henderson     tcg_gen_xor_tl(cpu_icc_C, cpu_cc_Z, cpu_cc_N);
451f828df74SRichard Henderson     tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N);
452fcf5ef2aSThomas Huth #endif
453f828df74SRichard Henderson     tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N);
454f828df74SRichard Henderson     tcg_gen_mov_tl(dst, cpu_cc_N);
455fcf5ef2aSThomas Huth }
456fcf5ef2aSThomas Huth 
457f828df74SRichard Henderson static void gen_op_subcc(TCGv dst, TCGv src1, TCGv src2)
458fcf5ef2aSThomas Huth {
459f828df74SRichard Henderson     gen_op_subcc_int(dst, src1, src2, NULL);
460fcf5ef2aSThomas Huth }
461fcf5ef2aSThomas Huth 
462f828df74SRichard Henderson static void gen_op_tsubcc(TCGv dst, TCGv src1, TCGv src2)
463fcf5ef2aSThomas Huth {
464f828df74SRichard Henderson     TCGv t = tcg_temp_new();
465fcf5ef2aSThomas Huth 
466f828df74SRichard Henderson     /* Save the tag bits around modification of dst. */
467f828df74SRichard Henderson     tcg_gen_or_tl(t, src1, src2);
468fcf5ef2aSThomas Huth 
469f828df74SRichard Henderson     gen_op_subcc(dst, src1, src2);
470f828df74SRichard Henderson 
471f828df74SRichard Henderson     /* Incorprate tag bits into icc.V */
472f828df74SRichard Henderson     tcg_gen_andi_tl(t, t, 3);
473f828df74SRichard Henderson     tcg_gen_neg_tl(t, t);
474f828df74SRichard Henderson     tcg_gen_ext32u_tl(t, t);
475f828df74SRichard Henderson     tcg_gen_or_tl(cpu_cc_V, cpu_cc_V, t);
476f828df74SRichard Henderson }
477f828df74SRichard Henderson 
478f828df74SRichard Henderson static void gen_op_subc(TCGv dst, TCGv src1, TCGv src2)
479f828df74SRichard Henderson {
480fcf5ef2aSThomas Huth     tcg_gen_sub_tl(dst, src1, src2);
481f828df74SRichard Henderson     tcg_gen_sub_tl(dst, dst, gen_carry32());
482fcf5ef2aSThomas Huth }
483fcf5ef2aSThomas Huth 
484f828df74SRichard Henderson static void gen_op_subccc(TCGv dst, TCGv src1, TCGv src2)
485dfebb950SRichard Henderson {
486f828df74SRichard Henderson     gen_op_subcc_int(dst, src1, src2, gen_carry32());
487dfebb950SRichard Henderson }
488dfebb950SRichard Henderson 
4890c2e96c1SRichard Henderson static void gen_op_mulscc(TCGv dst, TCGv src1, TCGv src2)
490fcf5ef2aSThomas Huth {
491b989ce73SRichard Henderson     TCGv zero = tcg_constant_tl(0);
49250280618SRichard Henderson     TCGv one = tcg_constant_tl(1);
493b989ce73SRichard Henderson     TCGv t_src1 = tcg_temp_new();
494b989ce73SRichard Henderson     TCGv t_src2 = tcg_temp_new();
495b989ce73SRichard Henderson     TCGv t0 = tcg_temp_new();
496fcf5ef2aSThomas Huth 
497b989ce73SRichard Henderson     tcg_gen_ext32u_tl(t_src1, src1);
498b989ce73SRichard Henderson     tcg_gen_ext32u_tl(t_src2, src2);
499fcf5ef2aSThomas Huth 
500b989ce73SRichard Henderson     /*
501b989ce73SRichard Henderson      * if (!(env->y & 1))
502b989ce73SRichard Henderson      *   src2 = 0;
503fcf5ef2aSThomas Huth      */
50450280618SRichard Henderson     tcg_gen_movcond_tl(TCG_COND_TSTEQ, t_src2, cpu_y, one, zero, t_src2);
505fcf5ef2aSThomas Huth 
506b989ce73SRichard Henderson     /*
507b989ce73SRichard Henderson      * b2 = src1 & 1;
508b989ce73SRichard Henderson      * y = (b2 << 31) | (y >> 1);
509b989ce73SRichard Henderson      */
5100b1183e3SPhilippe Mathieu-Daudé     tcg_gen_extract_tl(t0, cpu_y, 1, 31);
511b989ce73SRichard Henderson     tcg_gen_deposit_tl(cpu_y, t0, src1, 31, 1);
512fcf5ef2aSThomas Huth 
513fcf5ef2aSThomas Huth     // b1 = N ^ V;
5142a1905c7SRichard Henderson     tcg_gen_xor_tl(t0, cpu_cc_N, cpu_cc_V);
515fcf5ef2aSThomas Huth 
516b989ce73SRichard Henderson     /*
517b989ce73SRichard Henderson      * src1 = (b1 << 31) | (src1 >> 1)
518b989ce73SRichard Henderson      */
5192a1905c7SRichard Henderson     tcg_gen_andi_tl(t0, t0, 1u << 31);
520b989ce73SRichard Henderson     tcg_gen_shri_tl(t_src1, t_src1, 1);
521b989ce73SRichard Henderson     tcg_gen_or_tl(t_src1, t_src1, t0);
522fcf5ef2aSThomas Huth 
523b989ce73SRichard Henderson     gen_op_addcc(dst, t_src1, t_src2);
524fcf5ef2aSThomas Huth }
525fcf5ef2aSThomas Huth 
5260c2e96c1SRichard Henderson static void gen_op_multiply(TCGv dst, TCGv src1, TCGv src2, int sign_ext)
527fcf5ef2aSThomas Huth {
528fcf5ef2aSThomas Huth #if TARGET_LONG_BITS == 32
529fcf5ef2aSThomas Huth     if (sign_ext) {
530fcf5ef2aSThomas Huth         tcg_gen_muls2_tl(dst, cpu_y, src1, src2);
531fcf5ef2aSThomas Huth     } else {
532fcf5ef2aSThomas Huth         tcg_gen_mulu2_tl(dst, cpu_y, src1, src2);
533fcf5ef2aSThomas Huth     }
534fcf5ef2aSThomas Huth #else
535fcf5ef2aSThomas Huth     TCGv t0 = tcg_temp_new_i64();
536fcf5ef2aSThomas Huth     TCGv t1 = tcg_temp_new_i64();
537fcf5ef2aSThomas Huth 
538fcf5ef2aSThomas Huth     if (sign_ext) {
539fcf5ef2aSThomas Huth         tcg_gen_ext32s_i64(t0, src1);
540fcf5ef2aSThomas Huth         tcg_gen_ext32s_i64(t1, src2);
541fcf5ef2aSThomas Huth     } else {
542fcf5ef2aSThomas Huth         tcg_gen_ext32u_i64(t0, src1);
543fcf5ef2aSThomas Huth         tcg_gen_ext32u_i64(t1, src2);
544fcf5ef2aSThomas Huth     }
545fcf5ef2aSThomas Huth 
546fcf5ef2aSThomas Huth     tcg_gen_mul_i64(dst, t0, t1);
547fcf5ef2aSThomas Huth     tcg_gen_shri_i64(cpu_y, dst, 32);
548fcf5ef2aSThomas Huth #endif
549fcf5ef2aSThomas Huth }
550fcf5ef2aSThomas Huth 
5510c2e96c1SRichard Henderson static void gen_op_umul(TCGv dst, TCGv src1, TCGv src2)
552fcf5ef2aSThomas Huth {
553fcf5ef2aSThomas Huth     /* zero-extend truncated operands before multiplication */
554fcf5ef2aSThomas Huth     gen_op_multiply(dst, src1, src2, 0);
555fcf5ef2aSThomas Huth }
556fcf5ef2aSThomas Huth 
5570c2e96c1SRichard Henderson static void gen_op_smul(TCGv dst, TCGv src1, TCGv src2)
558fcf5ef2aSThomas Huth {
559fcf5ef2aSThomas Huth     /* sign-extend truncated operands before multiplication */
560fcf5ef2aSThomas Huth     gen_op_multiply(dst, src1, src2, 1);
561fcf5ef2aSThomas Huth }
562fcf5ef2aSThomas Huth 
563c2636853SRichard Henderson static void gen_op_sdiv(TCGv dst, TCGv src1, TCGv src2)
564c2636853SRichard Henderson {
56513260103SRichard Henderson #ifdef TARGET_SPARC64
566c2636853SRichard Henderson     gen_helper_sdiv(dst, tcg_env, src1, src2);
56713260103SRichard Henderson     tcg_gen_ext32s_tl(dst, dst);
56813260103SRichard Henderson #else
56913260103SRichard Henderson     TCGv_i64 t64 = tcg_temp_new_i64();
57013260103SRichard Henderson     gen_helper_sdiv(t64, tcg_env, src1, src2);
57113260103SRichard Henderson     tcg_gen_trunc_i64_tl(dst, t64);
57213260103SRichard Henderson #endif
573c2636853SRichard Henderson }
574c2636853SRichard Henderson 
575c2636853SRichard Henderson static void gen_op_udivcc(TCGv dst, TCGv src1, TCGv src2)
576c2636853SRichard Henderson {
57713260103SRichard Henderson     TCGv_i64 t64;
57813260103SRichard Henderson 
57913260103SRichard Henderson #ifdef TARGET_SPARC64
58013260103SRichard Henderson     t64 = cpu_cc_V;
58113260103SRichard Henderson #else
58213260103SRichard Henderson     t64 = tcg_temp_new_i64();
58313260103SRichard Henderson #endif
58413260103SRichard Henderson 
58513260103SRichard Henderson     gen_helper_udiv(t64, tcg_env, src1, src2);
58613260103SRichard Henderson 
58713260103SRichard Henderson #ifdef TARGET_SPARC64
58813260103SRichard Henderson     tcg_gen_ext32u_tl(cpu_cc_N, t64);
58913260103SRichard Henderson     tcg_gen_shri_tl(cpu_cc_V, t64, 32);
59013260103SRichard Henderson     tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N);
59113260103SRichard Henderson     tcg_gen_movi_tl(cpu_icc_C, 0);
59213260103SRichard Henderson #else
59313260103SRichard Henderson     tcg_gen_extr_i64_tl(cpu_cc_N, cpu_cc_V, t64);
59413260103SRichard Henderson #endif
59513260103SRichard Henderson     tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N);
59613260103SRichard Henderson     tcg_gen_movi_tl(cpu_cc_C, 0);
59713260103SRichard Henderson     tcg_gen_mov_tl(dst, cpu_cc_N);
598c2636853SRichard Henderson }
599c2636853SRichard Henderson 
600c2636853SRichard Henderson static void gen_op_sdivcc(TCGv dst, TCGv src1, TCGv src2)
601c2636853SRichard Henderson {
60213260103SRichard Henderson     TCGv_i64 t64;
60313260103SRichard Henderson 
60413260103SRichard Henderson #ifdef TARGET_SPARC64
60513260103SRichard Henderson     t64 = cpu_cc_V;
60613260103SRichard Henderson #else
60713260103SRichard Henderson     t64 = tcg_temp_new_i64();
60813260103SRichard Henderson #endif
60913260103SRichard Henderson 
61013260103SRichard Henderson     gen_helper_sdiv(t64, tcg_env, src1, src2);
61113260103SRichard Henderson 
61213260103SRichard Henderson #ifdef TARGET_SPARC64
61313260103SRichard Henderson     tcg_gen_ext32s_tl(cpu_cc_N, t64);
61413260103SRichard Henderson     tcg_gen_shri_tl(cpu_cc_V, t64, 32);
61513260103SRichard Henderson     tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N);
61613260103SRichard Henderson     tcg_gen_movi_tl(cpu_icc_C, 0);
61713260103SRichard Henderson #else
61813260103SRichard Henderson     tcg_gen_extr_i64_tl(cpu_cc_N, cpu_cc_V, t64);
61913260103SRichard Henderson #endif
62013260103SRichard Henderson     tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N);
62113260103SRichard Henderson     tcg_gen_movi_tl(cpu_cc_C, 0);
62213260103SRichard Henderson     tcg_gen_mov_tl(dst, cpu_cc_N);
623c2636853SRichard Henderson }
624c2636853SRichard Henderson 
625a9aba13dSRichard Henderson static void gen_op_taddcctv(TCGv dst, TCGv src1, TCGv src2)
626a9aba13dSRichard Henderson {
627a9aba13dSRichard Henderson     gen_helper_taddcctv(dst, tcg_env, src1, src2);
628a9aba13dSRichard Henderson }
629a9aba13dSRichard Henderson 
630a9aba13dSRichard Henderson static void gen_op_tsubcctv(TCGv dst, TCGv src1, TCGv src2)
631a9aba13dSRichard Henderson {
632a9aba13dSRichard Henderson     gen_helper_tsubcctv(dst, tcg_env, src1, src2);
633a9aba13dSRichard Henderson }
634a9aba13dSRichard Henderson 
6359c6ec5bcSRichard Henderson static void gen_op_popc(TCGv dst, TCGv src1, TCGv src2)
6369c6ec5bcSRichard Henderson {
6379c6ec5bcSRichard Henderson     tcg_gen_ctpop_tl(dst, src2);
6389c6ec5bcSRichard Henderson }
6399c6ec5bcSRichard Henderson 
64045bfed3bSRichard Henderson #ifndef TARGET_SPARC64
64145bfed3bSRichard Henderson static void gen_helper_array8(TCGv dst, TCGv src1, TCGv src2)
64245bfed3bSRichard Henderson {
64345bfed3bSRichard Henderson     g_assert_not_reached();
64445bfed3bSRichard Henderson }
64545bfed3bSRichard Henderson #endif
64645bfed3bSRichard Henderson 
64745bfed3bSRichard Henderson static void gen_op_array16(TCGv dst, TCGv src1, TCGv src2)
64845bfed3bSRichard Henderson {
64945bfed3bSRichard Henderson     gen_helper_array8(dst, src1, src2);
65045bfed3bSRichard Henderson     tcg_gen_shli_tl(dst, dst, 1);
65145bfed3bSRichard Henderson }
65245bfed3bSRichard Henderson 
65345bfed3bSRichard Henderson static void gen_op_array32(TCGv dst, TCGv src1, TCGv src2)
65445bfed3bSRichard Henderson {
65545bfed3bSRichard Henderson     gen_helper_array8(dst, src1, src2);
65645bfed3bSRichard Henderson     tcg_gen_shli_tl(dst, dst, 2);
65745bfed3bSRichard Henderson }
65845bfed3bSRichard Henderson 
6592f722641SRichard Henderson static void gen_op_fpack16(TCGv_i32 dst, TCGv_i64 src)
6602f722641SRichard Henderson {
6612f722641SRichard Henderson #ifdef TARGET_SPARC64
6622f722641SRichard Henderson     gen_helper_fpack16(dst, cpu_gsr, src);
6632f722641SRichard Henderson #else
6642f722641SRichard Henderson     g_assert_not_reached();
6652f722641SRichard Henderson #endif
6662f722641SRichard Henderson }
6672f722641SRichard Henderson 
6682f722641SRichard Henderson static void gen_op_fpackfix(TCGv_i32 dst, TCGv_i64 src)
6692f722641SRichard Henderson {
6702f722641SRichard Henderson #ifdef TARGET_SPARC64
6712f722641SRichard Henderson     gen_helper_fpackfix(dst, cpu_gsr, src);
6722f722641SRichard Henderson #else
6732f722641SRichard Henderson     g_assert_not_reached();
6742f722641SRichard Henderson #endif
6752f722641SRichard Henderson }
6762f722641SRichard Henderson 
6774b6edc0aSRichard Henderson static void gen_op_fpack32(TCGv_i64 dst, TCGv_i64 src1, TCGv_i64 src2)
6784b6edc0aSRichard Henderson {
6794b6edc0aSRichard Henderson #ifdef TARGET_SPARC64
6804b6edc0aSRichard Henderson     gen_helper_fpack32(dst, cpu_gsr, src1, src2);
6814b6edc0aSRichard Henderson #else
6824b6edc0aSRichard Henderson     g_assert_not_reached();
6834b6edc0aSRichard Henderson #endif
6844b6edc0aSRichard Henderson }
6854b6edc0aSRichard Henderson 
6864b6edc0aSRichard Henderson static void gen_op_faligndata(TCGv_i64 dst, TCGv_i64 s1, TCGv_i64 s2)
6874b6edc0aSRichard Henderson {
6884b6edc0aSRichard Henderson #ifdef TARGET_SPARC64
6894b6edc0aSRichard Henderson     TCGv t1, t2, shift;
6904b6edc0aSRichard Henderson 
6914b6edc0aSRichard Henderson     t1 = tcg_temp_new();
6924b6edc0aSRichard Henderson     t2 = tcg_temp_new();
6934b6edc0aSRichard Henderson     shift = tcg_temp_new();
6944b6edc0aSRichard Henderson 
6954b6edc0aSRichard Henderson     tcg_gen_andi_tl(shift, cpu_gsr, 7);
6964b6edc0aSRichard Henderson     tcg_gen_shli_tl(shift, shift, 3);
6974b6edc0aSRichard Henderson     tcg_gen_shl_tl(t1, s1, shift);
6984b6edc0aSRichard Henderson 
6994b6edc0aSRichard Henderson     /*
7004b6edc0aSRichard Henderson      * A shift of 64 does not produce 0 in TCG.  Divide this into a
7014b6edc0aSRichard Henderson      * shift of (up to 63) followed by a constant shift of 1.
7024b6edc0aSRichard Henderson      */
7034b6edc0aSRichard Henderson     tcg_gen_xori_tl(shift, shift, 63);
7044b6edc0aSRichard Henderson     tcg_gen_shr_tl(t2, s2, shift);
7054b6edc0aSRichard Henderson     tcg_gen_shri_tl(t2, t2, 1);
7064b6edc0aSRichard Henderson 
7074b6edc0aSRichard Henderson     tcg_gen_or_tl(dst, t1, t2);
7084b6edc0aSRichard Henderson #else
7094b6edc0aSRichard Henderson     g_assert_not_reached();
7104b6edc0aSRichard Henderson #endif
7114b6edc0aSRichard Henderson }
7124b6edc0aSRichard Henderson 
7134b6edc0aSRichard Henderson static void gen_op_bshuffle(TCGv_i64 dst, TCGv_i64 src1, TCGv_i64 src2)
7144b6edc0aSRichard Henderson {
7154b6edc0aSRichard Henderson #ifdef TARGET_SPARC64
7164b6edc0aSRichard Henderson     gen_helper_bshuffle(dst, cpu_gsr, src1, src2);
7174b6edc0aSRichard Henderson #else
7184b6edc0aSRichard Henderson     g_assert_not_reached();
7194b6edc0aSRichard Henderson #endif
7204b6edc0aSRichard Henderson }
7214b6edc0aSRichard Henderson 
722a859602cSRichard Henderson static void gen_op_fmul8x16al(TCGv_i64 dst, TCGv_i32 src1, TCGv_i32 src2)
723a859602cSRichard Henderson {
724a859602cSRichard Henderson     tcg_gen_ext16s_i32(src2, src2);
725a859602cSRichard Henderson     gen_helper_fmul8x16a(dst, src1, src2);
726a859602cSRichard Henderson }
727a859602cSRichard Henderson 
728a859602cSRichard Henderson static void gen_op_fmul8x16au(TCGv_i64 dst, TCGv_i32 src1, TCGv_i32 src2)
729a859602cSRichard Henderson {
730a859602cSRichard Henderson     tcg_gen_sari_i32(src2, src2, 16);
731a859602cSRichard Henderson     gen_helper_fmul8x16a(dst, src1, src2);
732a859602cSRichard Henderson }
733a859602cSRichard Henderson 
734be8998e0SRichard Henderson static void gen_op_fmuld8ulx16(TCGv_i64 dst, TCGv_i32 src1, TCGv_i32 src2)
735be8998e0SRichard Henderson {
736be8998e0SRichard Henderson     TCGv_i32 t0 = tcg_temp_new_i32();
737be8998e0SRichard Henderson     TCGv_i32 t1 = tcg_temp_new_i32();
738be8998e0SRichard Henderson     TCGv_i32 t2 = tcg_temp_new_i32();
739be8998e0SRichard Henderson 
740be8998e0SRichard Henderson     tcg_gen_ext8u_i32(t0, src1);
741be8998e0SRichard Henderson     tcg_gen_ext16s_i32(t1, src2);
742be8998e0SRichard Henderson     tcg_gen_mul_i32(t0, t0, t1);
743be8998e0SRichard Henderson 
744be8998e0SRichard Henderson     tcg_gen_extract_i32(t1, src1, 16, 8);
745be8998e0SRichard Henderson     tcg_gen_sextract_i32(t2, src2, 16, 16);
746be8998e0SRichard Henderson     tcg_gen_mul_i32(t1, t1, t2);
747be8998e0SRichard Henderson 
748be8998e0SRichard Henderson     tcg_gen_concat_i32_i64(dst, t0, t1);
749be8998e0SRichard Henderson }
750be8998e0SRichard Henderson 
751be8998e0SRichard Henderson static void gen_op_fmuld8sux16(TCGv_i64 dst, TCGv_i32 src1, TCGv_i32 src2)
752be8998e0SRichard Henderson {
753be8998e0SRichard Henderson     TCGv_i32 t0 = tcg_temp_new_i32();
754be8998e0SRichard Henderson     TCGv_i32 t1 = tcg_temp_new_i32();
755be8998e0SRichard Henderson     TCGv_i32 t2 = tcg_temp_new_i32();
756be8998e0SRichard Henderson 
757be8998e0SRichard Henderson     /*
758be8998e0SRichard Henderson      * The insn description talks about extracting the upper 8 bits
759be8998e0SRichard Henderson      * of the signed 16-bit input rs1, performing the multiply, then
760be8998e0SRichard Henderson      * shifting left by 8 bits.  Instead, zap the lower 8 bits of
761be8998e0SRichard Henderson      * the rs1 input, which avoids the need for two shifts.
762be8998e0SRichard Henderson      */
763be8998e0SRichard Henderson     tcg_gen_ext16s_i32(t0, src1);
764be8998e0SRichard Henderson     tcg_gen_andi_i32(t0, t0, ~0xff);
765be8998e0SRichard Henderson     tcg_gen_ext16s_i32(t1, src2);
766be8998e0SRichard Henderson     tcg_gen_mul_i32(t0, t0, t1);
767be8998e0SRichard Henderson 
768be8998e0SRichard Henderson     tcg_gen_sextract_i32(t1, src1, 16, 16);
769be8998e0SRichard Henderson     tcg_gen_andi_i32(t1, t1, ~0xff);
770be8998e0SRichard Henderson     tcg_gen_sextract_i32(t2, src2, 16, 16);
771be8998e0SRichard Henderson     tcg_gen_mul_i32(t1, t1, t2);
772be8998e0SRichard Henderson 
773be8998e0SRichard Henderson     tcg_gen_concat_i32_i64(dst, t0, t1);
774be8998e0SRichard Henderson }
775be8998e0SRichard Henderson 
77689527e3aSRichard Henderson static void finishing_insn(DisasContext *dc)
77789527e3aSRichard Henderson {
77889527e3aSRichard Henderson     /*
77989527e3aSRichard Henderson      * From here, there is no future path through an unwinding exception.
78089527e3aSRichard Henderson      * If the current insn cannot raise an exception, the computation of
78189527e3aSRichard Henderson      * cpu_cond may be able to be elided.
78289527e3aSRichard Henderson      */
78389527e3aSRichard Henderson     if (dc->cpu_cond_live) {
78489527e3aSRichard Henderson         tcg_gen_discard_tl(cpu_cond);
78589527e3aSRichard Henderson         dc->cpu_cond_live = false;
78689527e3aSRichard Henderson     }
78789527e3aSRichard Henderson }
78889527e3aSRichard Henderson 
7890c2e96c1SRichard Henderson static void gen_generic_branch(DisasContext *dc)
790fcf5ef2aSThomas Huth {
79100ab7e61SRichard Henderson     TCGv npc0 = tcg_constant_tl(dc->jump_pc[0]);
79200ab7e61SRichard Henderson     TCGv npc1 = tcg_constant_tl(dc->jump_pc[1]);
793533f042fSRichard Henderson     TCGv c2 = tcg_constant_tl(dc->jump.c2);
794fcf5ef2aSThomas Huth 
795533f042fSRichard Henderson     tcg_gen_movcond_tl(dc->jump.cond, cpu_npc, dc->jump.c1, c2, npc0, npc1);
796fcf5ef2aSThomas Huth }
797fcf5ef2aSThomas Huth 
798fcf5ef2aSThomas Huth /* call this function before using the condition register as it may
799fcf5ef2aSThomas Huth    have been set for a jump */
8000c2e96c1SRichard Henderson static void flush_cond(DisasContext *dc)
801fcf5ef2aSThomas Huth {
802fcf5ef2aSThomas Huth     if (dc->npc == JUMP_PC) {
803fcf5ef2aSThomas Huth         gen_generic_branch(dc);
80499c82c47SRichard Henderson         dc->npc = DYNAMIC_PC_LOOKUP;
805fcf5ef2aSThomas Huth     }
806fcf5ef2aSThomas Huth }
807fcf5ef2aSThomas Huth 
8080c2e96c1SRichard Henderson static void save_npc(DisasContext *dc)
809fcf5ef2aSThomas Huth {
810633c4283SRichard Henderson     if (dc->npc & 3) {
811633c4283SRichard Henderson         switch (dc->npc) {
812633c4283SRichard Henderson         case JUMP_PC:
813fcf5ef2aSThomas Huth             gen_generic_branch(dc);
81499c82c47SRichard Henderson             dc->npc = DYNAMIC_PC_LOOKUP;
815633c4283SRichard Henderson             break;
816633c4283SRichard Henderson         case DYNAMIC_PC:
817633c4283SRichard Henderson         case DYNAMIC_PC_LOOKUP:
818633c4283SRichard Henderson             break;
819633c4283SRichard Henderson         default:
820633c4283SRichard Henderson             g_assert_not_reached();
821633c4283SRichard Henderson         }
822633c4283SRichard Henderson     } else {
823fcf5ef2aSThomas Huth         tcg_gen_movi_tl(cpu_npc, dc->npc);
824fcf5ef2aSThomas Huth     }
825fcf5ef2aSThomas Huth }
826fcf5ef2aSThomas Huth 
8270c2e96c1SRichard Henderson static void save_state(DisasContext *dc)
828fcf5ef2aSThomas Huth {
829fcf5ef2aSThomas Huth     tcg_gen_movi_tl(cpu_pc, dc->pc);
830fcf5ef2aSThomas Huth     save_npc(dc);
831fcf5ef2aSThomas Huth }
832fcf5ef2aSThomas Huth 
833fcf5ef2aSThomas Huth static void gen_exception(DisasContext *dc, int which)
834fcf5ef2aSThomas Huth {
83589527e3aSRichard Henderson     finishing_insn(dc);
836fcf5ef2aSThomas Huth     save_state(dc);
837ad75a51eSRichard Henderson     gen_helper_raise_exception(tcg_env, tcg_constant_i32(which));
838af00be49SEmilio G. Cota     dc->base.is_jmp = DISAS_NORETURN;
839fcf5ef2aSThomas Huth }
840fcf5ef2aSThomas Huth 
841186e7890SRichard Henderson static TCGLabel *delay_exceptionv(DisasContext *dc, TCGv_i32 excp)
842fcf5ef2aSThomas Huth {
843186e7890SRichard Henderson     DisasDelayException *e = g_new0(DisasDelayException, 1);
844186e7890SRichard Henderson 
845186e7890SRichard Henderson     e->next = dc->delay_excp_list;
846186e7890SRichard Henderson     dc->delay_excp_list = e;
847186e7890SRichard Henderson 
848186e7890SRichard Henderson     e->lab = gen_new_label();
849186e7890SRichard Henderson     e->excp = excp;
850186e7890SRichard Henderson     e->pc = dc->pc;
851186e7890SRichard Henderson     /* Caller must have used flush_cond before branch. */
852186e7890SRichard Henderson     assert(e->npc != JUMP_PC);
853186e7890SRichard Henderson     e->npc = dc->npc;
854186e7890SRichard Henderson 
855186e7890SRichard Henderson     return e->lab;
856186e7890SRichard Henderson }
857186e7890SRichard Henderson 
858186e7890SRichard Henderson static TCGLabel *delay_exception(DisasContext *dc, int excp)
859186e7890SRichard Henderson {
860186e7890SRichard Henderson     return delay_exceptionv(dc, tcg_constant_i32(excp));
861186e7890SRichard Henderson }
862186e7890SRichard Henderson 
863186e7890SRichard Henderson static void gen_check_align(DisasContext *dc, TCGv addr, int mask)
864186e7890SRichard Henderson {
865186e7890SRichard Henderson     TCGv t = tcg_temp_new();
866186e7890SRichard Henderson     TCGLabel *lab;
867186e7890SRichard Henderson 
868186e7890SRichard Henderson     tcg_gen_andi_tl(t, addr, mask);
869186e7890SRichard Henderson 
870186e7890SRichard Henderson     flush_cond(dc);
871186e7890SRichard Henderson     lab = delay_exception(dc, TT_UNALIGNED);
872186e7890SRichard Henderson     tcg_gen_brcondi_tl(TCG_COND_NE, t, 0, lab);
873fcf5ef2aSThomas Huth }
874fcf5ef2aSThomas Huth 
8750c2e96c1SRichard Henderson static void gen_mov_pc_npc(DisasContext *dc)
876fcf5ef2aSThomas Huth {
87789527e3aSRichard Henderson     finishing_insn(dc);
87889527e3aSRichard Henderson 
879633c4283SRichard Henderson     if (dc->npc & 3) {
880633c4283SRichard Henderson         switch (dc->npc) {
881633c4283SRichard Henderson         case JUMP_PC:
882fcf5ef2aSThomas Huth             gen_generic_branch(dc);
883fcf5ef2aSThomas Huth             tcg_gen_mov_tl(cpu_pc, cpu_npc);
88499c82c47SRichard Henderson             dc->pc = DYNAMIC_PC_LOOKUP;
885633c4283SRichard Henderson             break;
886633c4283SRichard Henderson         case DYNAMIC_PC:
887633c4283SRichard Henderson         case DYNAMIC_PC_LOOKUP:
888fcf5ef2aSThomas Huth             tcg_gen_mov_tl(cpu_pc, cpu_npc);
889633c4283SRichard Henderson             dc->pc = dc->npc;
890633c4283SRichard Henderson             break;
891633c4283SRichard Henderson         default:
892633c4283SRichard Henderson             g_assert_not_reached();
893633c4283SRichard Henderson         }
894fcf5ef2aSThomas Huth     } else {
895fcf5ef2aSThomas Huth         dc->pc = dc->npc;
896fcf5ef2aSThomas Huth     }
897fcf5ef2aSThomas Huth }
898fcf5ef2aSThomas Huth 
899fcf5ef2aSThomas Huth static void gen_compare(DisasCompare *cmp, bool xcc, unsigned int cond,
900fcf5ef2aSThomas Huth                         DisasContext *dc)
901fcf5ef2aSThomas Huth {
902b597eedcSRichard Henderson     TCGv t1;
903fcf5ef2aSThomas Huth 
9042a1905c7SRichard Henderson     cmp->c1 = t1 = tcg_temp_new();
905c8507ebfSRichard Henderson     cmp->c2 = 0;
9062a1905c7SRichard Henderson 
9072a1905c7SRichard Henderson     switch (cond & 7) {
9082a1905c7SRichard Henderson     case 0x0: /* never */
9092a1905c7SRichard Henderson         cmp->cond = TCG_COND_NEVER;
910c8507ebfSRichard Henderson         cmp->c1 = tcg_constant_tl(0);
911fcf5ef2aSThomas Huth         break;
9122a1905c7SRichard Henderson 
9132a1905c7SRichard Henderson     case 0x1: /* eq: Z */
9142a1905c7SRichard Henderson         cmp->cond = TCG_COND_EQ;
9152a1905c7SRichard Henderson         if (TARGET_LONG_BITS == 32 || xcc) {
9162a1905c7SRichard Henderson             tcg_gen_mov_tl(t1, cpu_cc_Z);
9172a1905c7SRichard Henderson         } else {
9182a1905c7SRichard Henderson             tcg_gen_ext32u_tl(t1, cpu_icc_Z);
9192a1905c7SRichard Henderson         }
9202a1905c7SRichard Henderson         break;
9212a1905c7SRichard Henderson 
9222a1905c7SRichard Henderson     case 0x2: /* le: Z | (N ^ V) */
9232a1905c7SRichard Henderson         /*
9242a1905c7SRichard Henderson          * Simplify:
9252a1905c7SRichard Henderson          *   cc_Z || (N ^ V) < 0        NE
9262a1905c7SRichard Henderson          *   cc_Z && !((N ^ V) < 0)     EQ
9272a1905c7SRichard Henderson          *   cc_Z & ~((N ^ V) >> TLB)   EQ
9282a1905c7SRichard Henderson          */
9292a1905c7SRichard Henderson         cmp->cond = TCG_COND_EQ;
9302a1905c7SRichard Henderson         tcg_gen_xor_tl(t1, cpu_cc_N, cpu_cc_V);
9312a1905c7SRichard Henderson         tcg_gen_sextract_tl(t1, t1, xcc ? 63 : 31, 1);
9322a1905c7SRichard Henderson         tcg_gen_andc_tl(t1, xcc ? cpu_cc_Z : cpu_icc_Z, t1);
9332a1905c7SRichard Henderson         if (TARGET_LONG_BITS == 64 && !xcc) {
9342a1905c7SRichard Henderson             tcg_gen_ext32u_tl(t1, t1);
9352a1905c7SRichard Henderson         }
9362a1905c7SRichard Henderson         break;
9372a1905c7SRichard Henderson 
9382a1905c7SRichard Henderson     case 0x3: /* lt: N ^ V */
9392a1905c7SRichard Henderson         cmp->cond = TCG_COND_LT;
9402a1905c7SRichard Henderson         tcg_gen_xor_tl(t1, cpu_cc_N, cpu_cc_V);
9412a1905c7SRichard Henderson         if (TARGET_LONG_BITS == 64 && !xcc) {
9422a1905c7SRichard Henderson             tcg_gen_ext32s_tl(t1, t1);
9432a1905c7SRichard Henderson         }
9442a1905c7SRichard Henderson         break;
9452a1905c7SRichard Henderson 
9462a1905c7SRichard Henderson     case 0x4: /* leu: Z | C */
9472a1905c7SRichard Henderson         /*
9482a1905c7SRichard Henderson          * Simplify:
9492a1905c7SRichard Henderson          *   cc_Z == 0 || cc_C != 0     NE
9502a1905c7SRichard Henderson          *   cc_Z != 0 && cc_C == 0     EQ
9512a1905c7SRichard Henderson          *   cc_Z & (cc_C ? 0 : -1)     EQ
9522a1905c7SRichard Henderson          *   cc_Z & (cc_C - 1)          EQ
9532a1905c7SRichard Henderson          */
9542a1905c7SRichard Henderson         cmp->cond = TCG_COND_EQ;
9552a1905c7SRichard Henderson         if (TARGET_LONG_BITS == 32 || xcc) {
9562a1905c7SRichard Henderson             tcg_gen_subi_tl(t1, cpu_cc_C, 1);
9572a1905c7SRichard Henderson             tcg_gen_and_tl(t1, t1, cpu_cc_Z);
9582a1905c7SRichard Henderson         } else {
9592a1905c7SRichard Henderson             tcg_gen_extract_tl(t1, cpu_icc_C, 32, 1);
9602a1905c7SRichard Henderson             tcg_gen_subi_tl(t1, t1, 1);
9612a1905c7SRichard Henderson             tcg_gen_and_tl(t1, t1, cpu_icc_Z);
9622a1905c7SRichard Henderson             tcg_gen_ext32u_tl(t1, t1);
9632a1905c7SRichard Henderson         }
9642a1905c7SRichard Henderson         break;
9652a1905c7SRichard Henderson 
9662a1905c7SRichard Henderson     case 0x5: /* ltu: C */
9672a1905c7SRichard Henderson         cmp->cond = TCG_COND_NE;
9682a1905c7SRichard Henderson         if (TARGET_LONG_BITS == 32 || xcc) {
9692a1905c7SRichard Henderson             tcg_gen_mov_tl(t1, cpu_cc_C);
9702a1905c7SRichard Henderson         } else {
9712a1905c7SRichard Henderson             tcg_gen_extract_tl(t1, cpu_icc_C, 32, 1);
9722a1905c7SRichard Henderson         }
9732a1905c7SRichard Henderson         break;
9742a1905c7SRichard Henderson 
9752a1905c7SRichard Henderson     case 0x6: /* neg: N */
9762a1905c7SRichard Henderson         cmp->cond = TCG_COND_LT;
9772a1905c7SRichard Henderson         if (TARGET_LONG_BITS == 32 || xcc) {
9782a1905c7SRichard Henderson             tcg_gen_mov_tl(t1, cpu_cc_N);
9792a1905c7SRichard Henderson         } else {
9802a1905c7SRichard Henderson             tcg_gen_ext32s_tl(t1, cpu_cc_N);
9812a1905c7SRichard Henderson         }
9822a1905c7SRichard Henderson         break;
9832a1905c7SRichard Henderson 
9842a1905c7SRichard Henderson     case 0x7: /* vs: V */
9852a1905c7SRichard Henderson         cmp->cond = TCG_COND_LT;
9862a1905c7SRichard Henderson         if (TARGET_LONG_BITS == 32 || xcc) {
9872a1905c7SRichard Henderson             tcg_gen_mov_tl(t1, cpu_cc_V);
9882a1905c7SRichard Henderson         } else {
9892a1905c7SRichard Henderson             tcg_gen_ext32s_tl(t1, cpu_cc_V);
9902a1905c7SRichard Henderson         }
9912a1905c7SRichard Henderson         break;
9922a1905c7SRichard Henderson     }
9932a1905c7SRichard Henderson     if (cond & 8) {
9942a1905c7SRichard Henderson         cmp->cond = tcg_invert_cond(cmp->cond);
995fcf5ef2aSThomas Huth     }
996fcf5ef2aSThomas Huth }
997fcf5ef2aSThomas Huth 
998fcf5ef2aSThomas Huth static void gen_fcompare(DisasCompare *cmp, unsigned int cc, unsigned int cond)
999fcf5ef2aSThomas Huth {
1000d8c5b92fSRichard Henderson     TCGv_i32 fcc = cpu_fcc[cc];
1001d8c5b92fSRichard Henderson     TCGv_i32 c1 = fcc;
1002d8c5b92fSRichard Henderson     int c2 = 0;
1003d8c5b92fSRichard Henderson     TCGCond tcond;
1004fcf5ef2aSThomas Huth 
1005d8c5b92fSRichard Henderson     /*
1006d8c5b92fSRichard Henderson      * FCC values:
1007d8c5b92fSRichard Henderson      * 0 =
1008d8c5b92fSRichard Henderson      * 1 <
1009d8c5b92fSRichard Henderson      * 2 >
1010d8c5b92fSRichard Henderson      * 3 unordered
1011d8c5b92fSRichard Henderson      */
1012d8c5b92fSRichard Henderson     switch (cond & 7) {
1013d8c5b92fSRichard Henderson     case 0x0: /* fbn */
1014d8c5b92fSRichard Henderson         tcond = TCG_COND_NEVER;
1015fcf5ef2aSThomas Huth         break;
1016d8c5b92fSRichard Henderson     case 0x1: /* fbne : !0 */
1017d8c5b92fSRichard Henderson         tcond = TCG_COND_NE;
1018fcf5ef2aSThomas Huth         break;
1019d8c5b92fSRichard Henderson     case 0x2: /* fblg : 1 or 2 */
1020d8c5b92fSRichard Henderson         /* fcc in {1,2} - 1 -> fcc in {0,1} */
1021d8c5b92fSRichard Henderson         c1 = tcg_temp_new_i32();
1022d8c5b92fSRichard Henderson         tcg_gen_addi_i32(c1, fcc, -1);
1023d8c5b92fSRichard Henderson         c2 = 1;
1024d8c5b92fSRichard Henderson         tcond = TCG_COND_LEU;
1025fcf5ef2aSThomas Huth         break;
1026d8c5b92fSRichard Henderson     case 0x3: /* fbul : 1 or 3 */
1027d8c5b92fSRichard Henderson         c1 = tcg_temp_new_i32();
1028d8c5b92fSRichard Henderson         tcg_gen_andi_i32(c1, fcc, 1);
1029d8c5b92fSRichard Henderson         tcond = TCG_COND_NE;
1030d8c5b92fSRichard Henderson         break;
1031d8c5b92fSRichard Henderson     case 0x4: /* fbl  : 1 */
1032d8c5b92fSRichard Henderson         c2 = 1;
1033d8c5b92fSRichard Henderson         tcond = TCG_COND_EQ;
1034d8c5b92fSRichard Henderson         break;
1035d8c5b92fSRichard Henderson     case 0x5: /* fbug : 2 or 3 */
1036d8c5b92fSRichard Henderson         c2 = 2;
1037d8c5b92fSRichard Henderson         tcond = TCG_COND_GEU;
1038d8c5b92fSRichard Henderson         break;
1039d8c5b92fSRichard Henderson     case 0x6: /* fbg  : 2 */
1040d8c5b92fSRichard Henderson         c2 = 2;
1041d8c5b92fSRichard Henderson         tcond = TCG_COND_EQ;
1042d8c5b92fSRichard Henderson         break;
1043d8c5b92fSRichard Henderson     case 0x7: /* fbu  : 3 */
1044d8c5b92fSRichard Henderson         c2 = 3;
1045d8c5b92fSRichard Henderson         tcond = TCG_COND_EQ;
1046fcf5ef2aSThomas Huth         break;
1047fcf5ef2aSThomas Huth     }
1048d8c5b92fSRichard Henderson     if (cond & 8) {
1049d8c5b92fSRichard Henderson         tcond = tcg_invert_cond(tcond);
1050fcf5ef2aSThomas Huth     }
1051d8c5b92fSRichard Henderson 
1052d8c5b92fSRichard Henderson     cmp->cond = tcond;
1053d8c5b92fSRichard Henderson     cmp->c2 = c2;
1054d8c5b92fSRichard Henderson     cmp->c1 = tcg_temp_new();
1055d8c5b92fSRichard Henderson     tcg_gen_extu_i32_tl(cmp->c1, c1);
1056fcf5ef2aSThomas Huth }
1057fcf5ef2aSThomas Huth 
10582c4f56c9SRichard Henderson static bool gen_compare_reg(DisasCompare *cmp, int cond, TCGv r_src)
10592c4f56c9SRichard Henderson {
10602c4f56c9SRichard Henderson     static const TCGCond cond_reg[4] = {
1061ab9ffe98SRichard Henderson         TCG_COND_NEVER,  /* reserved */
1062fcf5ef2aSThomas Huth         TCG_COND_EQ,
1063fcf5ef2aSThomas Huth         TCG_COND_LE,
1064fcf5ef2aSThomas Huth         TCG_COND_LT,
1065fcf5ef2aSThomas Huth     };
10662c4f56c9SRichard Henderson     TCGCond tcond;
1067fcf5ef2aSThomas Huth 
10682c4f56c9SRichard Henderson     if ((cond & 3) == 0) {
10692c4f56c9SRichard Henderson         return false;
10702c4f56c9SRichard Henderson     }
10712c4f56c9SRichard Henderson     tcond = cond_reg[cond & 3];
10722c4f56c9SRichard Henderson     if (cond & 4) {
10732c4f56c9SRichard Henderson         tcond = tcg_invert_cond(tcond);
10742c4f56c9SRichard Henderson     }
10752c4f56c9SRichard Henderson 
10762c4f56c9SRichard Henderson     cmp->cond = tcond;
1077816f89b7SRichard Henderson     cmp->c1 = tcg_temp_new();
1078c8507ebfSRichard Henderson     cmp->c2 = 0;
1079816f89b7SRichard Henderson     tcg_gen_mov_tl(cmp->c1, r_src);
10802c4f56c9SRichard Henderson     return true;
1081fcf5ef2aSThomas Huth }
1082fcf5ef2aSThomas Huth 
1083baf3dbf2SRichard Henderson static void gen_op_clear_ieee_excp_and_FTT(void)
1084baf3dbf2SRichard Henderson {
10853590f01eSRichard Henderson     tcg_gen_st_i32(tcg_constant_i32(0), tcg_env,
10863590f01eSRichard Henderson                    offsetof(CPUSPARCState, fsr_cexc_ftt));
1087baf3dbf2SRichard Henderson }
1088baf3dbf2SRichard Henderson 
1089baf3dbf2SRichard Henderson static void gen_op_fmovs(TCGv_i32 dst, TCGv_i32 src)
1090baf3dbf2SRichard Henderson {
1091baf3dbf2SRichard Henderson     gen_op_clear_ieee_excp_and_FTT();
1092baf3dbf2SRichard Henderson     tcg_gen_mov_i32(dst, src);
1093baf3dbf2SRichard Henderson }
1094baf3dbf2SRichard Henderson 
1095baf3dbf2SRichard Henderson static void gen_op_fnegs(TCGv_i32 dst, TCGv_i32 src)
1096baf3dbf2SRichard Henderson {
1097baf3dbf2SRichard Henderson     gen_op_clear_ieee_excp_and_FTT();
1098daf457d4SRichard Henderson     tcg_gen_xori_i32(dst, src, 1u << 31);
1099baf3dbf2SRichard Henderson }
1100baf3dbf2SRichard Henderson 
1101baf3dbf2SRichard Henderson static void gen_op_fabss(TCGv_i32 dst, TCGv_i32 src)
1102baf3dbf2SRichard Henderson {
1103baf3dbf2SRichard Henderson     gen_op_clear_ieee_excp_and_FTT();
1104daf457d4SRichard Henderson     tcg_gen_andi_i32(dst, src, ~(1u << 31));
1105baf3dbf2SRichard Henderson }
1106baf3dbf2SRichard Henderson 
1107c6d83e4fSRichard Henderson static void gen_op_fmovd(TCGv_i64 dst, TCGv_i64 src)
1108c6d83e4fSRichard Henderson {
1109c6d83e4fSRichard Henderson     gen_op_clear_ieee_excp_and_FTT();
1110c6d83e4fSRichard Henderson     tcg_gen_mov_i64(dst, src);
1111c6d83e4fSRichard Henderson }
1112c6d83e4fSRichard Henderson 
1113c6d83e4fSRichard Henderson static void gen_op_fnegd(TCGv_i64 dst, TCGv_i64 src)
1114c6d83e4fSRichard Henderson {
1115c6d83e4fSRichard Henderson     gen_op_clear_ieee_excp_and_FTT();
1116daf457d4SRichard Henderson     tcg_gen_xori_i64(dst, src, 1ull << 63);
1117c6d83e4fSRichard Henderson }
1118c6d83e4fSRichard Henderson 
1119c6d83e4fSRichard Henderson static void gen_op_fabsd(TCGv_i64 dst, TCGv_i64 src)
1120c6d83e4fSRichard Henderson {
1121c6d83e4fSRichard Henderson     gen_op_clear_ieee_excp_and_FTT();
1122daf457d4SRichard Henderson     tcg_gen_andi_i64(dst, src, ~(1ull << 63));
1123daf457d4SRichard Henderson }
1124daf457d4SRichard Henderson 
1125daf457d4SRichard Henderson static void gen_op_fnegq(TCGv_i128 dst, TCGv_i128 src)
1126daf457d4SRichard Henderson {
1127daf457d4SRichard Henderson     TCGv_i64 l = tcg_temp_new_i64();
1128daf457d4SRichard Henderson     TCGv_i64 h = tcg_temp_new_i64();
1129daf457d4SRichard Henderson 
1130daf457d4SRichard Henderson     tcg_gen_extr_i128_i64(l, h, src);
1131daf457d4SRichard Henderson     tcg_gen_xori_i64(h, h, 1ull << 63);
1132daf457d4SRichard Henderson     tcg_gen_concat_i64_i128(dst, l, h);
1133daf457d4SRichard Henderson }
1134daf457d4SRichard Henderson 
1135daf457d4SRichard Henderson static void gen_op_fabsq(TCGv_i128 dst, TCGv_i128 src)
1136daf457d4SRichard Henderson {
1137daf457d4SRichard Henderson     TCGv_i64 l = tcg_temp_new_i64();
1138daf457d4SRichard Henderson     TCGv_i64 h = tcg_temp_new_i64();
1139daf457d4SRichard Henderson 
1140daf457d4SRichard Henderson     tcg_gen_extr_i128_i64(l, h, src);
1141daf457d4SRichard Henderson     tcg_gen_andi_i64(h, h, ~(1ull << 63));
1142daf457d4SRichard Henderson     tcg_gen_concat_i64_i128(dst, l, h);
1143c6d83e4fSRichard Henderson }
1144c6d83e4fSRichard Henderson 
11453590f01eSRichard Henderson static void gen_op_fpexception_im(DisasContext *dc, int ftt)
1146fcf5ef2aSThomas Huth {
11473590f01eSRichard Henderson     /*
11483590f01eSRichard Henderson      * CEXC is only set when succesfully completing an FPop,
11493590f01eSRichard Henderson      * or when raising FSR_FTT_IEEE_EXCP, i.e. check_ieee_exception.
11503590f01eSRichard Henderson      * Thus we can simply store FTT into this field.
11513590f01eSRichard Henderson      */
11523590f01eSRichard Henderson     tcg_gen_st_i32(tcg_constant_i32(ftt), tcg_env,
11533590f01eSRichard Henderson                    offsetof(CPUSPARCState, fsr_cexc_ftt));
1154fcf5ef2aSThomas Huth     gen_exception(dc, TT_FP_EXCP);
1155fcf5ef2aSThomas Huth }
1156fcf5ef2aSThomas Huth 
1157fcf5ef2aSThomas Huth static int gen_trap_ifnofpu(DisasContext *dc)
1158fcf5ef2aSThomas Huth {
1159fcf5ef2aSThomas Huth #if !defined(CONFIG_USER_ONLY)
1160fcf5ef2aSThomas Huth     if (!dc->fpu_enabled) {
1161fcf5ef2aSThomas Huth         gen_exception(dc, TT_NFPU_INSN);
1162fcf5ef2aSThomas Huth         return 1;
1163fcf5ef2aSThomas Huth     }
1164fcf5ef2aSThomas Huth #endif
1165fcf5ef2aSThomas Huth     return 0;
1166fcf5ef2aSThomas Huth }
1167fcf5ef2aSThomas Huth 
1168fcf5ef2aSThomas Huth /* asi moves */
1169fcf5ef2aSThomas Huth typedef enum {
1170fcf5ef2aSThomas Huth     GET_ASI_HELPER,
1171fcf5ef2aSThomas Huth     GET_ASI_EXCP,
1172fcf5ef2aSThomas Huth     GET_ASI_DIRECT,
1173fcf5ef2aSThomas Huth     GET_ASI_DTWINX,
11742786a3f8SRichard Henderson     GET_ASI_CODE,
1175fcf5ef2aSThomas Huth     GET_ASI_BLOCK,
1176fcf5ef2aSThomas Huth     GET_ASI_SHORT,
1177fcf5ef2aSThomas Huth     GET_ASI_BCOPY,
1178fcf5ef2aSThomas Huth     GET_ASI_BFILL,
1179fcf5ef2aSThomas Huth } ASIType;
1180fcf5ef2aSThomas Huth 
1181fcf5ef2aSThomas Huth typedef struct {
1182fcf5ef2aSThomas Huth     ASIType type;
1183fcf5ef2aSThomas Huth     int asi;
1184fcf5ef2aSThomas Huth     int mem_idx;
118514776ab5STony Nguyen     MemOp memop;
1186fcf5ef2aSThomas Huth } DisasASI;
1187fcf5ef2aSThomas Huth 
1188811cc0b0SRichard Henderson /*
1189811cc0b0SRichard Henderson  * Build DisasASI.
1190811cc0b0SRichard Henderson  * For asi == -1, treat as non-asi.
1191811cc0b0SRichard Henderson  * For ask == -2, treat as immediate offset (v8 error, v9 %asi).
1192811cc0b0SRichard Henderson  */
1193811cc0b0SRichard Henderson static DisasASI resolve_asi(DisasContext *dc, int asi, MemOp memop)
1194fcf5ef2aSThomas Huth {
1195fcf5ef2aSThomas Huth     ASIType type = GET_ASI_HELPER;
1196fcf5ef2aSThomas Huth     int mem_idx = dc->mem_idx;
1197fcf5ef2aSThomas Huth 
1198811cc0b0SRichard Henderson     if (asi == -1) {
1199811cc0b0SRichard Henderson         /* Artificial "non-asi" case. */
1200811cc0b0SRichard Henderson         type = GET_ASI_DIRECT;
1201811cc0b0SRichard Henderson         goto done;
1202811cc0b0SRichard Henderson     }
1203811cc0b0SRichard Henderson 
1204fcf5ef2aSThomas Huth #ifndef TARGET_SPARC64
1205fcf5ef2aSThomas Huth     /* Before v9, all asis are immediate and privileged.  */
1206811cc0b0SRichard Henderson     if (asi < 0) {
1207fcf5ef2aSThomas Huth         gen_exception(dc, TT_ILL_INSN);
1208fcf5ef2aSThomas Huth         type = GET_ASI_EXCP;
1209fcf5ef2aSThomas Huth     } else if (supervisor(dc)
1210fcf5ef2aSThomas Huth                /* Note that LEON accepts ASI_USERDATA in user mode, for
1211fcf5ef2aSThomas Huth                   use with CASA.  Also note that previous versions of
1212fcf5ef2aSThomas Huth                   QEMU allowed (and old versions of gcc emitted) ASI_P
1213fcf5ef2aSThomas Huth                   for LEON, which is incorrect.  */
1214fcf5ef2aSThomas Huth                || (asi == ASI_USERDATA
1215fcf5ef2aSThomas Huth                    && (dc->def->features & CPU_FEATURE_CASA))) {
1216fcf5ef2aSThomas Huth         switch (asi) {
1217fcf5ef2aSThomas Huth         case ASI_USERDATA:    /* User data access */
1218fcf5ef2aSThomas Huth             mem_idx = MMU_USER_IDX;
1219fcf5ef2aSThomas Huth             type = GET_ASI_DIRECT;
1220fcf5ef2aSThomas Huth             break;
1221fcf5ef2aSThomas Huth         case ASI_KERNELDATA:  /* Supervisor data access */
1222fcf5ef2aSThomas Huth             mem_idx = MMU_KERNEL_IDX;
1223fcf5ef2aSThomas Huth             type = GET_ASI_DIRECT;
1224fcf5ef2aSThomas Huth             break;
12252786a3f8SRichard Henderson         case ASI_USERTXT:     /* User text access */
12262786a3f8SRichard Henderson             mem_idx = MMU_USER_IDX;
12272786a3f8SRichard Henderson             type = GET_ASI_CODE;
12282786a3f8SRichard Henderson             break;
12292786a3f8SRichard Henderson         case ASI_KERNELTXT:   /* Supervisor text access */
12302786a3f8SRichard Henderson             mem_idx = MMU_KERNEL_IDX;
12312786a3f8SRichard Henderson             type = GET_ASI_CODE;
12322786a3f8SRichard Henderson             break;
1233fcf5ef2aSThomas Huth         case ASI_M_BYPASS:    /* MMU passthrough */
1234fcf5ef2aSThomas Huth         case ASI_LEON_BYPASS: /* LEON MMU passthrough */
1235fcf5ef2aSThomas Huth             mem_idx = MMU_PHYS_IDX;
1236fcf5ef2aSThomas Huth             type = GET_ASI_DIRECT;
1237fcf5ef2aSThomas Huth             break;
1238fcf5ef2aSThomas Huth         case ASI_M_BCOPY: /* Block copy, sta access */
1239fcf5ef2aSThomas Huth             mem_idx = MMU_KERNEL_IDX;
1240fcf5ef2aSThomas Huth             type = GET_ASI_BCOPY;
1241fcf5ef2aSThomas Huth             break;
1242fcf5ef2aSThomas Huth         case ASI_M_BFILL: /* Block fill, stda access */
1243fcf5ef2aSThomas Huth             mem_idx = MMU_KERNEL_IDX;
1244fcf5ef2aSThomas Huth             type = GET_ASI_BFILL;
1245fcf5ef2aSThomas Huth             break;
1246fcf5ef2aSThomas Huth         }
12476e10f37cSKONRAD Frederic 
12486e10f37cSKONRAD Frederic         /* MMU_PHYS_IDX is used when the MMU is disabled to passthrough the
12496e10f37cSKONRAD Frederic          * permissions check in get_physical_address(..).
12506e10f37cSKONRAD Frederic          */
12516e10f37cSKONRAD Frederic         mem_idx = (dc->mem_idx == MMU_PHYS_IDX) ? MMU_PHYS_IDX : mem_idx;
1252fcf5ef2aSThomas Huth     } else {
1253fcf5ef2aSThomas Huth         gen_exception(dc, TT_PRIV_INSN);
1254fcf5ef2aSThomas Huth         type = GET_ASI_EXCP;
1255fcf5ef2aSThomas Huth     }
1256fcf5ef2aSThomas Huth #else
1257811cc0b0SRichard Henderson     if (asi < 0) {
1258fcf5ef2aSThomas Huth         asi = dc->asi;
1259fcf5ef2aSThomas Huth     }
1260fcf5ef2aSThomas Huth     /* With v9, all asis below 0x80 are privileged.  */
1261fcf5ef2aSThomas Huth     /* ??? We ought to check cpu_has_hypervisor, but we didn't copy
1262fcf5ef2aSThomas Huth        down that bit into DisasContext.  For the moment that's ok,
1263fcf5ef2aSThomas Huth        since the direct implementations below doesn't have any ASIs
1264fcf5ef2aSThomas Huth        in the restricted [0x30, 0x7f] range, and the check will be
1265fcf5ef2aSThomas Huth        done properly in the helper.  */
1266fcf5ef2aSThomas Huth     if (!supervisor(dc) && asi < 0x80) {
1267fcf5ef2aSThomas Huth         gen_exception(dc, TT_PRIV_ACT);
1268fcf5ef2aSThomas Huth         type = GET_ASI_EXCP;
1269fcf5ef2aSThomas Huth     } else {
1270fcf5ef2aSThomas Huth         switch (asi) {
1271fcf5ef2aSThomas Huth         case ASI_REAL:      /* Bypass */
1272fcf5ef2aSThomas Huth         case ASI_REAL_IO:   /* Bypass, non-cacheable */
1273fcf5ef2aSThomas Huth         case ASI_REAL_L:    /* Bypass LE */
1274fcf5ef2aSThomas Huth         case ASI_REAL_IO_L: /* Bypass, non-cacheable LE */
1275fcf5ef2aSThomas Huth         case ASI_TWINX_REAL:   /* Real address, twinx */
1276fcf5ef2aSThomas Huth         case ASI_TWINX_REAL_L: /* Real address, twinx, LE */
1277fcf5ef2aSThomas Huth         case ASI_QUAD_LDD_PHYS:
1278fcf5ef2aSThomas Huth         case ASI_QUAD_LDD_PHYS_L:
1279fcf5ef2aSThomas Huth             mem_idx = MMU_PHYS_IDX;
1280fcf5ef2aSThomas Huth             break;
1281fcf5ef2aSThomas Huth         case ASI_N:  /* Nucleus */
1282fcf5ef2aSThomas Huth         case ASI_NL: /* Nucleus LE */
1283fcf5ef2aSThomas Huth         case ASI_TWINX_N:
1284fcf5ef2aSThomas Huth         case ASI_TWINX_NL:
1285fcf5ef2aSThomas Huth         case ASI_NUCLEUS_QUAD_LDD:
1286fcf5ef2aSThomas Huth         case ASI_NUCLEUS_QUAD_LDD_L:
12879a10756dSArtyom Tarasenko             if (hypervisor(dc)) {
128884f8f587SArtyom Tarasenko                 mem_idx = MMU_PHYS_IDX;
12899a10756dSArtyom Tarasenko             } else {
1290fcf5ef2aSThomas Huth                 mem_idx = MMU_NUCLEUS_IDX;
12919a10756dSArtyom Tarasenko             }
1292fcf5ef2aSThomas Huth             break;
1293fcf5ef2aSThomas Huth         case ASI_AIUP:  /* As if user primary */
1294fcf5ef2aSThomas Huth         case ASI_AIUPL: /* As if user primary LE */
1295fcf5ef2aSThomas Huth         case ASI_TWINX_AIUP:
1296fcf5ef2aSThomas Huth         case ASI_TWINX_AIUP_L:
1297fcf5ef2aSThomas Huth         case ASI_BLK_AIUP_4V:
1298fcf5ef2aSThomas Huth         case ASI_BLK_AIUP_L_4V:
1299fcf5ef2aSThomas Huth         case ASI_BLK_AIUP:
1300fcf5ef2aSThomas Huth         case ASI_BLK_AIUPL:
1301fcf5ef2aSThomas Huth             mem_idx = MMU_USER_IDX;
1302fcf5ef2aSThomas Huth             break;
1303fcf5ef2aSThomas Huth         case ASI_AIUS:  /* As if user secondary */
1304fcf5ef2aSThomas Huth         case ASI_AIUSL: /* As if user secondary LE */
1305fcf5ef2aSThomas Huth         case ASI_TWINX_AIUS:
1306fcf5ef2aSThomas Huth         case ASI_TWINX_AIUS_L:
1307fcf5ef2aSThomas Huth         case ASI_BLK_AIUS_4V:
1308fcf5ef2aSThomas Huth         case ASI_BLK_AIUS_L_4V:
1309fcf5ef2aSThomas Huth         case ASI_BLK_AIUS:
1310fcf5ef2aSThomas Huth         case ASI_BLK_AIUSL:
1311fcf5ef2aSThomas Huth             mem_idx = MMU_USER_SECONDARY_IDX;
1312fcf5ef2aSThomas Huth             break;
1313fcf5ef2aSThomas Huth         case ASI_S:  /* Secondary */
1314fcf5ef2aSThomas Huth         case ASI_SL: /* Secondary LE */
1315fcf5ef2aSThomas Huth         case ASI_TWINX_S:
1316fcf5ef2aSThomas Huth         case ASI_TWINX_SL:
1317fcf5ef2aSThomas Huth         case ASI_BLK_COMMIT_S:
1318fcf5ef2aSThomas Huth         case ASI_BLK_S:
1319fcf5ef2aSThomas Huth         case ASI_BLK_SL:
1320fcf5ef2aSThomas Huth         case ASI_FL8_S:
1321fcf5ef2aSThomas Huth         case ASI_FL8_SL:
1322fcf5ef2aSThomas Huth         case ASI_FL16_S:
1323fcf5ef2aSThomas Huth         case ASI_FL16_SL:
1324fcf5ef2aSThomas Huth             if (mem_idx == MMU_USER_IDX) {
1325fcf5ef2aSThomas Huth                 mem_idx = MMU_USER_SECONDARY_IDX;
1326fcf5ef2aSThomas Huth             } else if (mem_idx == MMU_KERNEL_IDX) {
1327fcf5ef2aSThomas Huth                 mem_idx = MMU_KERNEL_SECONDARY_IDX;
1328fcf5ef2aSThomas Huth             }
1329fcf5ef2aSThomas Huth             break;
1330fcf5ef2aSThomas Huth         case ASI_P:  /* Primary */
1331fcf5ef2aSThomas Huth         case ASI_PL: /* Primary LE */
1332fcf5ef2aSThomas Huth         case ASI_TWINX_P:
1333fcf5ef2aSThomas Huth         case ASI_TWINX_PL:
1334fcf5ef2aSThomas Huth         case ASI_BLK_COMMIT_P:
1335fcf5ef2aSThomas Huth         case ASI_BLK_P:
1336fcf5ef2aSThomas Huth         case ASI_BLK_PL:
1337fcf5ef2aSThomas Huth         case ASI_FL8_P:
1338fcf5ef2aSThomas Huth         case ASI_FL8_PL:
1339fcf5ef2aSThomas Huth         case ASI_FL16_P:
1340fcf5ef2aSThomas Huth         case ASI_FL16_PL:
1341fcf5ef2aSThomas Huth             break;
1342fcf5ef2aSThomas Huth         }
1343fcf5ef2aSThomas Huth         switch (asi) {
1344fcf5ef2aSThomas Huth         case ASI_REAL:
1345fcf5ef2aSThomas Huth         case ASI_REAL_IO:
1346fcf5ef2aSThomas Huth         case ASI_REAL_L:
1347fcf5ef2aSThomas Huth         case ASI_REAL_IO_L:
1348fcf5ef2aSThomas Huth         case ASI_N:
1349fcf5ef2aSThomas Huth         case ASI_NL:
1350fcf5ef2aSThomas Huth         case ASI_AIUP:
1351fcf5ef2aSThomas Huth         case ASI_AIUPL:
1352fcf5ef2aSThomas Huth         case ASI_AIUS:
1353fcf5ef2aSThomas Huth         case ASI_AIUSL:
1354fcf5ef2aSThomas Huth         case ASI_S:
1355fcf5ef2aSThomas Huth         case ASI_SL:
1356fcf5ef2aSThomas Huth         case ASI_P:
1357fcf5ef2aSThomas Huth         case ASI_PL:
1358fcf5ef2aSThomas Huth             type = GET_ASI_DIRECT;
1359fcf5ef2aSThomas Huth             break;
1360fcf5ef2aSThomas Huth         case ASI_TWINX_REAL:
1361fcf5ef2aSThomas Huth         case ASI_TWINX_REAL_L:
1362fcf5ef2aSThomas Huth         case ASI_TWINX_N:
1363fcf5ef2aSThomas Huth         case ASI_TWINX_NL:
1364fcf5ef2aSThomas Huth         case ASI_TWINX_AIUP:
1365fcf5ef2aSThomas Huth         case ASI_TWINX_AIUP_L:
1366fcf5ef2aSThomas Huth         case ASI_TWINX_AIUS:
1367fcf5ef2aSThomas Huth         case ASI_TWINX_AIUS_L:
1368fcf5ef2aSThomas Huth         case ASI_TWINX_P:
1369fcf5ef2aSThomas Huth         case ASI_TWINX_PL:
1370fcf5ef2aSThomas Huth         case ASI_TWINX_S:
1371fcf5ef2aSThomas Huth         case ASI_TWINX_SL:
1372fcf5ef2aSThomas Huth         case ASI_QUAD_LDD_PHYS:
1373fcf5ef2aSThomas Huth         case ASI_QUAD_LDD_PHYS_L:
1374fcf5ef2aSThomas Huth         case ASI_NUCLEUS_QUAD_LDD:
1375fcf5ef2aSThomas Huth         case ASI_NUCLEUS_QUAD_LDD_L:
1376fcf5ef2aSThomas Huth             type = GET_ASI_DTWINX;
1377fcf5ef2aSThomas Huth             break;
1378fcf5ef2aSThomas Huth         case ASI_BLK_COMMIT_P:
1379fcf5ef2aSThomas Huth         case ASI_BLK_COMMIT_S:
1380fcf5ef2aSThomas Huth         case ASI_BLK_AIUP_4V:
1381fcf5ef2aSThomas Huth         case ASI_BLK_AIUP_L_4V:
1382fcf5ef2aSThomas Huth         case ASI_BLK_AIUP:
1383fcf5ef2aSThomas Huth         case ASI_BLK_AIUPL:
1384fcf5ef2aSThomas Huth         case ASI_BLK_AIUS_4V:
1385fcf5ef2aSThomas Huth         case ASI_BLK_AIUS_L_4V:
1386fcf5ef2aSThomas Huth         case ASI_BLK_AIUS:
1387fcf5ef2aSThomas Huth         case ASI_BLK_AIUSL:
1388fcf5ef2aSThomas Huth         case ASI_BLK_S:
1389fcf5ef2aSThomas Huth         case ASI_BLK_SL:
1390fcf5ef2aSThomas Huth         case ASI_BLK_P:
1391fcf5ef2aSThomas Huth         case ASI_BLK_PL:
1392fcf5ef2aSThomas Huth             type = GET_ASI_BLOCK;
1393fcf5ef2aSThomas Huth             break;
1394fcf5ef2aSThomas Huth         case ASI_FL8_S:
1395fcf5ef2aSThomas Huth         case ASI_FL8_SL:
1396fcf5ef2aSThomas Huth         case ASI_FL8_P:
1397fcf5ef2aSThomas Huth         case ASI_FL8_PL:
1398fcf5ef2aSThomas Huth             memop = MO_UB;
1399fcf5ef2aSThomas Huth             type = GET_ASI_SHORT;
1400fcf5ef2aSThomas Huth             break;
1401fcf5ef2aSThomas Huth         case ASI_FL16_S:
1402fcf5ef2aSThomas Huth         case ASI_FL16_SL:
1403fcf5ef2aSThomas Huth         case ASI_FL16_P:
1404fcf5ef2aSThomas Huth         case ASI_FL16_PL:
1405fcf5ef2aSThomas Huth             memop = MO_TEUW;
1406fcf5ef2aSThomas Huth             type = GET_ASI_SHORT;
1407fcf5ef2aSThomas Huth             break;
1408fcf5ef2aSThomas Huth         }
1409fcf5ef2aSThomas Huth         /* The little-endian asis all have bit 3 set.  */
1410fcf5ef2aSThomas Huth         if (asi & 8) {
1411fcf5ef2aSThomas Huth             memop ^= MO_BSWAP;
1412fcf5ef2aSThomas Huth         }
1413fcf5ef2aSThomas Huth     }
1414fcf5ef2aSThomas Huth #endif
1415fcf5ef2aSThomas Huth 
1416811cc0b0SRichard Henderson  done:
1417fcf5ef2aSThomas Huth     return (DisasASI){ type, asi, mem_idx, memop };
1418fcf5ef2aSThomas Huth }
1419fcf5ef2aSThomas Huth 
1420a76779eeSRichard Henderson #if defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
1421a76779eeSRichard Henderson static void gen_helper_ld_asi(TCGv_i64 r, TCGv_env e, TCGv a,
1422a76779eeSRichard Henderson                               TCGv_i32 asi, TCGv_i32 mop)
1423a76779eeSRichard Henderson {
1424a76779eeSRichard Henderson     g_assert_not_reached();
1425a76779eeSRichard Henderson }
1426a76779eeSRichard Henderson 
1427a76779eeSRichard Henderson static void gen_helper_st_asi(TCGv_env e, TCGv a, TCGv_i64 r,
1428a76779eeSRichard Henderson                               TCGv_i32 asi, TCGv_i32 mop)
1429a76779eeSRichard Henderson {
1430a76779eeSRichard Henderson     g_assert_not_reached();
1431a76779eeSRichard Henderson }
1432a76779eeSRichard Henderson #endif
1433a76779eeSRichard Henderson 
143442071fc1SRichard Henderson static void gen_ld_asi(DisasContext *dc, DisasASI *da, TCGv dst, TCGv addr)
1435fcf5ef2aSThomas Huth {
1436c03a0fd1SRichard Henderson     switch (da->type) {
1437fcf5ef2aSThomas Huth     case GET_ASI_EXCP:
1438fcf5ef2aSThomas Huth         break;
1439fcf5ef2aSThomas Huth     case GET_ASI_DTWINX: /* Reserved for ldda.  */
1440fcf5ef2aSThomas Huth         gen_exception(dc, TT_ILL_INSN);
1441fcf5ef2aSThomas Huth         break;
1442fcf5ef2aSThomas Huth     case GET_ASI_DIRECT:
1443c03a0fd1SRichard Henderson         tcg_gen_qemu_ld_tl(dst, addr, da->mem_idx, da->memop | MO_ALIGN);
1444fcf5ef2aSThomas Huth         break;
14452786a3f8SRichard Henderson 
14462786a3f8SRichard Henderson     case GET_ASI_CODE:
14472786a3f8SRichard Henderson #if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
14482786a3f8SRichard Henderson         {
14492786a3f8SRichard Henderson             MemOpIdx oi = make_memop_idx(da->memop, da->mem_idx);
14502786a3f8SRichard Henderson             TCGv_i64 t64 = tcg_temp_new_i64();
14512786a3f8SRichard Henderson 
14522786a3f8SRichard Henderson             gen_helper_ld_code(t64, tcg_env, addr, tcg_constant_i32(oi));
14532786a3f8SRichard Henderson             tcg_gen_trunc_i64_tl(dst, t64);
14542786a3f8SRichard Henderson         }
14552786a3f8SRichard Henderson         break;
14562786a3f8SRichard Henderson #else
14572786a3f8SRichard Henderson         g_assert_not_reached();
14582786a3f8SRichard Henderson #endif
14592786a3f8SRichard Henderson 
1460fcf5ef2aSThomas Huth     default:
1461fcf5ef2aSThomas Huth         {
1462c03a0fd1SRichard Henderson             TCGv_i32 r_asi = tcg_constant_i32(da->asi);
1463c03a0fd1SRichard Henderson             TCGv_i32 r_mop = tcg_constant_i32(da->memop | MO_ALIGN);
1464fcf5ef2aSThomas Huth 
1465fcf5ef2aSThomas Huth             save_state(dc);
1466fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
1467ad75a51eSRichard Henderson             gen_helper_ld_asi(dst, tcg_env, addr, r_asi, r_mop);
1468fcf5ef2aSThomas Huth #else
1469fcf5ef2aSThomas Huth             {
1470fcf5ef2aSThomas Huth                 TCGv_i64 t64 = tcg_temp_new_i64();
1471ad75a51eSRichard Henderson                 gen_helper_ld_asi(t64, tcg_env, addr, r_asi, r_mop);
1472fcf5ef2aSThomas Huth                 tcg_gen_trunc_i64_tl(dst, t64);
1473fcf5ef2aSThomas Huth             }
1474fcf5ef2aSThomas Huth #endif
1475fcf5ef2aSThomas Huth         }
1476fcf5ef2aSThomas Huth         break;
1477fcf5ef2aSThomas Huth     }
1478fcf5ef2aSThomas Huth }
1479fcf5ef2aSThomas Huth 
148042071fc1SRichard Henderson static void gen_st_asi(DisasContext *dc, DisasASI *da, TCGv src, TCGv addr)
1481c03a0fd1SRichard Henderson {
1482c03a0fd1SRichard Henderson     switch (da->type) {
1483fcf5ef2aSThomas Huth     case GET_ASI_EXCP:
1484fcf5ef2aSThomas Huth         break;
1485c03a0fd1SRichard Henderson 
1486fcf5ef2aSThomas Huth     case GET_ASI_DTWINX: /* Reserved for stda.  */
1487c03a0fd1SRichard Henderson         if (TARGET_LONG_BITS == 32) {
1488fcf5ef2aSThomas Huth             gen_exception(dc, TT_ILL_INSN);
1489fcf5ef2aSThomas Huth             break;
1490c03a0fd1SRichard Henderson         } else if (!(dc->def->features & CPU_FEATURE_HYPV)) {
14913390537bSArtyom Tarasenko             /* Pre OpenSPARC CPUs don't have these */
14923390537bSArtyom Tarasenko             gen_exception(dc, TT_ILL_INSN);
1493fcf5ef2aSThomas Huth             break;
1494c03a0fd1SRichard Henderson         }
1495c03a0fd1SRichard Henderson         /* In OpenSPARC T1+ CPUs TWINX ASIs in store are ST_BLKINIT_ ASIs */
1496c03a0fd1SRichard Henderson         /* fall through */
1497c03a0fd1SRichard Henderson 
1498c03a0fd1SRichard Henderson     case GET_ASI_DIRECT:
1499c03a0fd1SRichard Henderson         tcg_gen_qemu_st_tl(src, addr, da->mem_idx, da->memop | MO_ALIGN);
1500c03a0fd1SRichard Henderson         break;
1501c03a0fd1SRichard Henderson 
1502fcf5ef2aSThomas Huth     case GET_ASI_BCOPY:
1503c03a0fd1SRichard Henderson         assert(TARGET_LONG_BITS == 32);
150498271007SRichard Henderson         /*
150598271007SRichard Henderson          * Copy 32 bytes from the address in SRC to ADDR.
150698271007SRichard Henderson          *
150798271007SRichard Henderson          * From Ross RT625 hyperSPARC manual, section 4.6:
150898271007SRichard Henderson          * "Block Copy and Block Fill will work only on cache line boundaries."
150998271007SRichard Henderson          *
151098271007SRichard Henderson          * It does not specify if an unaliged address is truncated or trapped.
151198271007SRichard Henderson          * Previous qemu behaviour was to truncate to 4 byte alignment, which
151298271007SRichard Henderson          * is obviously wrong.  The only place I can see this used is in the
151398271007SRichard Henderson          * Linux kernel which begins with page alignment, advancing by 32,
151498271007SRichard Henderson          * so is always aligned.  Assume truncation as the simpler option.
151598271007SRichard Henderson          *
151698271007SRichard Henderson          * Since the loads and stores are paired, allow the copy to happen
151798271007SRichard Henderson          * in the host endianness.  The copy need not be atomic.
151898271007SRichard Henderson          */
1519fcf5ef2aSThomas Huth         {
152098271007SRichard Henderson             MemOp mop = MO_128 | MO_ATOM_IFALIGN_PAIR;
1521fcf5ef2aSThomas Huth             TCGv saddr = tcg_temp_new();
1522fcf5ef2aSThomas Huth             TCGv daddr = tcg_temp_new();
152398271007SRichard Henderson             TCGv_i128 tmp = tcg_temp_new_i128();
1524fcf5ef2aSThomas Huth 
152598271007SRichard Henderson             tcg_gen_andi_tl(saddr, src, -32);
152698271007SRichard Henderson             tcg_gen_andi_tl(daddr, addr, -32);
152798271007SRichard Henderson             tcg_gen_qemu_ld_i128(tmp, saddr, da->mem_idx, mop);
152898271007SRichard Henderson             tcg_gen_qemu_st_i128(tmp, daddr, da->mem_idx, mop);
152998271007SRichard Henderson             tcg_gen_addi_tl(saddr, saddr, 16);
153098271007SRichard Henderson             tcg_gen_addi_tl(daddr, daddr, 16);
153198271007SRichard Henderson             tcg_gen_qemu_ld_i128(tmp, saddr, da->mem_idx, mop);
153298271007SRichard Henderson             tcg_gen_qemu_st_i128(tmp, daddr, da->mem_idx, mop);
1533fcf5ef2aSThomas Huth         }
1534fcf5ef2aSThomas Huth         break;
1535c03a0fd1SRichard Henderson 
1536fcf5ef2aSThomas Huth     default:
1537fcf5ef2aSThomas Huth         {
1538c03a0fd1SRichard Henderson             TCGv_i32 r_asi = tcg_constant_i32(da->asi);
1539c03a0fd1SRichard Henderson             TCGv_i32 r_mop = tcg_constant_i32(da->memop | MO_ALIGN);
1540fcf5ef2aSThomas Huth 
1541fcf5ef2aSThomas Huth             save_state(dc);
1542fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
1543ad75a51eSRichard Henderson             gen_helper_st_asi(tcg_env, addr, src, r_asi, r_mop);
1544fcf5ef2aSThomas Huth #else
1545fcf5ef2aSThomas Huth             {
1546fcf5ef2aSThomas Huth                 TCGv_i64 t64 = tcg_temp_new_i64();
1547fcf5ef2aSThomas Huth                 tcg_gen_extu_tl_i64(t64, src);
1548ad75a51eSRichard Henderson                 gen_helper_st_asi(tcg_env, addr, t64, r_asi, r_mop);
1549fcf5ef2aSThomas Huth             }
1550fcf5ef2aSThomas Huth #endif
1551fcf5ef2aSThomas Huth 
1552fcf5ef2aSThomas Huth             /* A write to a TLB register may alter page maps.  End the TB. */
1553fcf5ef2aSThomas Huth             dc->npc = DYNAMIC_PC;
1554fcf5ef2aSThomas Huth         }
1555fcf5ef2aSThomas Huth         break;
1556fcf5ef2aSThomas Huth     }
1557fcf5ef2aSThomas Huth }
1558fcf5ef2aSThomas Huth 
1559dca544b9SRichard Henderson static void gen_swap_asi(DisasContext *dc, DisasASI *da,
1560c03a0fd1SRichard Henderson                          TCGv dst, TCGv src, TCGv addr)
1561c03a0fd1SRichard Henderson {
1562c03a0fd1SRichard Henderson     switch (da->type) {
1563c03a0fd1SRichard Henderson     case GET_ASI_EXCP:
1564c03a0fd1SRichard Henderson         break;
1565c03a0fd1SRichard Henderson     case GET_ASI_DIRECT:
1566dca544b9SRichard Henderson         tcg_gen_atomic_xchg_tl(dst, addr, src,
1567dca544b9SRichard Henderson                                da->mem_idx, da->memop | MO_ALIGN);
1568c03a0fd1SRichard Henderson         break;
1569c03a0fd1SRichard Henderson     default:
1570c03a0fd1SRichard Henderson         /* ??? Should be DAE_invalid_asi.  */
1571c03a0fd1SRichard Henderson         gen_exception(dc, TT_DATA_ACCESS);
1572c03a0fd1SRichard Henderson         break;
1573c03a0fd1SRichard Henderson     }
1574c03a0fd1SRichard Henderson }
1575c03a0fd1SRichard Henderson 
1576d0a11d25SRichard Henderson static void gen_cas_asi(DisasContext *dc, DisasASI *da,
1577c03a0fd1SRichard Henderson                         TCGv oldv, TCGv newv, TCGv cmpv, TCGv addr)
1578c03a0fd1SRichard Henderson {
1579c03a0fd1SRichard Henderson     switch (da->type) {
1580fcf5ef2aSThomas Huth     case GET_ASI_EXCP:
1581c03a0fd1SRichard Henderson         return;
1582fcf5ef2aSThomas Huth     case GET_ASI_DIRECT:
1583c03a0fd1SRichard Henderson         tcg_gen_atomic_cmpxchg_tl(oldv, addr, cmpv, newv,
1584c03a0fd1SRichard Henderson                                   da->mem_idx, da->memop | MO_ALIGN);
1585fcf5ef2aSThomas Huth         break;
1586fcf5ef2aSThomas Huth     default:
1587fcf5ef2aSThomas Huth         /* ??? Should be DAE_invalid_asi.  */
1588fcf5ef2aSThomas Huth         gen_exception(dc, TT_DATA_ACCESS);
1589fcf5ef2aSThomas Huth         break;
1590fcf5ef2aSThomas Huth     }
1591fcf5ef2aSThomas Huth }
1592fcf5ef2aSThomas Huth 
1593cf07cd1eSRichard Henderson static void gen_ldstub_asi(DisasContext *dc, DisasASI *da, TCGv dst, TCGv addr)
1594c03a0fd1SRichard Henderson {
1595c03a0fd1SRichard Henderson     switch (da->type) {
1596fcf5ef2aSThomas Huth     case GET_ASI_EXCP:
1597fcf5ef2aSThomas Huth         break;
1598fcf5ef2aSThomas Huth     case GET_ASI_DIRECT:
1599cf07cd1eSRichard Henderson         tcg_gen_atomic_xchg_tl(dst, addr, tcg_constant_tl(0xff),
1600cf07cd1eSRichard Henderson                                da->mem_idx, MO_UB);
1601fcf5ef2aSThomas Huth         break;
1602fcf5ef2aSThomas Huth     default:
16033db010c3SRichard Henderson         /* ??? In theory, this should be raise DAE_invalid_asi.
16043db010c3SRichard Henderson            But the SS-20 roms do ldstuba [%l0] #ASI_M_CTL, %o1.  */
1605af00be49SEmilio G. Cota         if (tb_cflags(dc->base.tb) & CF_PARALLEL) {
1606ad75a51eSRichard Henderson             gen_helper_exit_atomic(tcg_env);
16073db010c3SRichard Henderson         } else {
1608c03a0fd1SRichard Henderson             TCGv_i32 r_asi = tcg_constant_i32(da->asi);
160900ab7e61SRichard Henderson             TCGv_i32 r_mop = tcg_constant_i32(MO_UB);
16103db010c3SRichard Henderson             TCGv_i64 s64, t64;
16113db010c3SRichard Henderson 
16123db010c3SRichard Henderson             save_state(dc);
16133db010c3SRichard Henderson             t64 = tcg_temp_new_i64();
1614ad75a51eSRichard Henderson             gen_helper_ld_asi(t64, tcg_env, addr, r_asi, r_mop);
16153db010c3SRichard Henderson 
161600ab7e61SRichard Henderson             s64 = tcg_constant_i64(0xff);
1617ad75a51eSRichard Henderson             gen_helper_st_asi(tcg_env, addr, s64, r_asi, r_mop);
16183db010c3SRichard Henderson 
16193db010c3SRichard Henderson             tcg_gen_trunc_i64_tl(dst, t64);
16203db010c3SRichard Henderson 
16213db010c3SRichard Henderson             /* End the TB.  */
16223db010c3SRichard Henderson             dc->npc = DYNAMIC_PC;
16233db010c3SRichard Henderson         }
1624fcf5ef2aSThomas Huth         break;
1625fcf5ef2aSThomas Huth     }
1626fcf5ef2aSThomas Huth }
1627fcf5ef2aSThomas Huth 
1628287b1152SRichard Henderson static void gen_ldf_asi(DisasContext *dc, DisasASI *da, MemOp orig_size,
16293259b9e2SRichard Henderson                         TCGv addr, int rd)
1630fcf5ef2aSThomas Huth {
16313259b9e2SRichard Henderson     MemOp memop = da->memop;
16323259b9e2SRichard Henderson     MemOp size = memop & MO_SIZE;
1633fcf5ef2aSThomas Huth     TCGv_i32 d32;
1634*1210a036SRichard Henderson     TCGv_i64 d64, l64;
1635287b1152SRichard Henderson     TCGv addr_tmp;
1636fcf5ef2aSThomas Huth 
16373259b9e2SRichard Henderson     /* TODO: Use 128-bit load/store below. */
16383259b9e2SRichard Henderson     if (size == MO_128) {
16393259b9e2SRichard Henderson         memop = (memop & ~MO_SIZE) | MO_64;
16403259b9e2SRichard Henderson     }
16413259b9e2SRichard Henderson 
16423259b9e2SRichard Henderson     switch (da->type) {
1643fcf5ef2aSThomas Huth     case GET_ASI_EXCP:
1644fcf5ef2aSThomas Huth         break;
1645fcf5ef2aSThomas Huth 
1646fcf5ef2aSThomas Huth     case GET_ASI_DIRECT:
16473259b9e2SRichard Henderson         memop |= MO_ALIGN_4;
1648fcf5ef2aSThomas Huth         switch (size) {
16493259b9e2SRichard Henderson         case MO_32:
1650388a6465SRichard Henderson             d32 = tcg_temp_new_i32();
16513259b9e2SRichard Henderson             tcg_gen_qemu_ld_i32(d32, addr, da->mem_idx, memop);
1652fcf5ef2aSThomas Huth             gen_store_fpr_F(dc, rd, d32);
1653fcf5ef2aSThomas Huth             break;
16543259b9e2SRichard Henderson 
16553259b9e2SRichard Henderson         case MO_64:
1656*1210a036SRichard Henderson             d64 = tcg_temp_new_i64();
1657*1210a036SRichard Henderson             tcg_gen_qemu_ld_i64(d64, addr, da->mem_idx, memop);
1658*1210a036SRichard Henderson             gen_store_fpr_D(dc, rd, d64);
1659fcf5ef2aSThomas Huth             break;
16603259b9e2SRichard Henderson 
16613259b9e2SRichard Henderson         case MO_128:
1662fcf5ef2aSThomas Huth             d64 = tcg_temp_new_i64();
1663*1210a036SRichard Henderson             l64 = tcg_temp_new_i64();
16643259b9e2SRichard Henderson             tcg_gen_qemu_ld_i64(d64, addr, da->mem_idx, memop);
1665287b1152SRichard Henderson             addr_tmp = tcg_temp_new();
1666287b1152SRichard Henderson             tcg_gen_addi_tl(addr_tmp, addr, 8);
1667*1210a036SRichard Henderson             tcg_gen_qemu_ld_i64(l64, addr_tmp, da->mem_idx, memop);
1668*1210a036SRichard Henderson             gen_store_fpr_D(dc, rd, d64);
1669*1210a036SRichard Henderson             gen_store_fpr_D(dc, rd + 2, l64);
1670fcf5ef2aSThomas Huth             break;
1671fcf5ef2aSThomas Huth         default:
1672fcf5ef2aSThomas Huth             g_assert_not_reached();
1673fcf5ef2aSThomas Huth         }
1674fcf5ef2aSThomas Huth         break;
1675fcf5ef2aSThomas Huth 
1676fcf5ef2aSThomas Huth     case GET_ASI_BLOCK:
1677fcf5ef2aSThomas Huth         /* Valid for lddfa on aligned registers only.  */
16783259b9e2SRichard Henderson         if (orig_size == MO_64 && (rd & 7) == 0) {
1679fcf5ef2aSThomas Huth             /* The first operation checks required alignment.  */
1680287b1152SRichard Henderson             addr_tmp = tcg_temp_new();
1681*1210a036SRichard Henderson             d64 = tcg_temp_new_i64();
1682287b1152SRichard Henderson             for (int i = 0; ; ++i) {
1683*1210a036SRichard Henderson                 tcg_gen_qemu_ld_i64(d64, addr, da->mem_idx,
16843259b9e2SRichard Henderson                                     memop | (i == 0 ? MO_ALIGN_64 : 0));
1685*1210a036SRichard Henderson                 gen_store_fpr_D(dc, rd + 2 * i, d64);
1686fcf5ef2aSThomas Huth                 if (i == 7) {
1687fcf5ef2aSThomas Huth                     break;
1688fcf5ef2aSThomas Huth                 }
1689287b1152SRichard Henderson                 tcg_gen_addi_tl(addr_tmp, addr, 8);
1690287b1152SRichard Henderson                 addr = addr_tmp;
1691fcf5ef2aSThomas Huth             }
1692fcf5ef2aSThomas Huth         } else {
1693fcf5ef2aSThomas Huth             gen_exception(dc, TT_ILL_INSN);
1694fcf5ef2aSThomas Huth         }
1695fcf5ef2aSThomas Huth         break;
1696fcf5ef2aSThomas Huth 
1697fcf5ef2aSThomas Huth     case GET_ASI_SHORT:
1698fcf5ef2aSThomas Huth         /* Valid for lddfa only.  */
16993259b9e2SRichard Henderson         if (orig_size == MO_64) {
1700*1210a036SRichard Henderson             d64 = tcg_temp_new_i64();
1701*1210a036SRichard Henderson             tcg_gen_qemu_ld_i64(d64, addr, da->mem_idx, memop | MO_ALIGN);
1702*1210a036SRichard Henderson             gen_store_fpr_D(dc, rd, d64);
1703fcf5ef2aSThomas Huth         } else {
1704fcf5ef2aSThomas Huth             gen_exception(dc, TT_ILL_INSN);
1705fcf5ef2aSThomas Huth         }
1706fcf5ef2aSThomas Huth         break;
1707fcf5ef2aSThomas Huth 
1708fcf5ef2aSThomas Huth     default:
1709fcf5ef2aSThomas Huth         {
17103259b9e2SRichard Henderson             TCGv_i32 r_asi = tcg_constant_i32(da->asi);
17113259b9e2SRichard Henderson             TCGv_i32 r_mop = tcg_constant_i32(memop | MO_ALIGN);
1712fcf5ef2aSThomas Huth 
1713fcf5ef2aSThomas Huth             save_state(dc);
1714fcf5ef2aSThomas Huth             /* According to the table in the UA2011 manual, the only
1715fcf5ef2aSThomas Huth                other asis that are valid for ldfa/lddfa/ldqfa are
1716fcf5ef2aSThomas Huth                the NO_FAULT asis.  We still need a helper for these,
1717fcf5ef2aSThomas Huth                but we can just use the integer asi helper for them.  */
1718fcf5ef2aSThomas Huth             switch (size) {
17193259b9e2SRichard Henderson             case MO_32:
1720fcf5ef2aSThomas Huth                 d64 = tcg_temp_new_i64();
1721ad75a51eSRichard Henderson                 gen_helper_ld_asi(d64, tcg_env, addr, r_asi, r_mop);
1722388a6465SRichard Henderson                 d32 = tcg_temp_new_i32();
1723fcf5ef2aSThomas Huth                 tcg_gen_extrl_i64_i32(d32, d64);
1724fcf5ef2aSThomas Huth                 gen_store_fpr_F(dc, rd, d32);
1725fcf5ef2aSThomas Huth                 break;
17263259b9e2SRichard Henderson             case MO_64:
1727*1210a036SRichard Henderson                 d64 = tcg_temp_new_i64();
1728*1210a036SRichard Henderson                 gen_helper_ld_asi(d64, tcg_env, addr, r_asi, r_mop);
1729*1210a036SRichard Henderson                 gen_store_fpr_D(dc, rd, d64);
1730fcf5ef2aSThomas Huth                 break;
17313259b9e2SRichard Henderson             case MO_128:
1732fcf5ef2aSThomas Huth                 d64 = tcg_temp_new_i64();
1733*1210a036SRichard Henderson                 l64 = tcg_temp_new_i64();
1734ad75a51eSRichard Henderson                 gen_helper_ld_asi(d64, tcg_env, addr, r_asi, r_mop);
1735287b1152SRichard Henderson                 addr_tmp = tcg_temp_new();
1736287b1152SRichard Henderson                 tcg_gen_addi_tl(addr_tmp, addr, 8);
1737*1210a036SRichard Henderson                 gen_helper_ld_asi(l64, tcg_env, addr_tmp, r_asi, r_mop);
1738*1210a036SRichard Henderson                 gen_store_fpr_D(dc, rd, d64);
1739*1210a036SRichard Henderson                 gen_store_fpr_D(dc, rd + 2, l64);
1740fcf5ef2aSThomas Huth                 break;
1741fcf5ef2aSThomas Huth             default:
1742fcf5ef2aSThomas Huth                 g_assert_not_reached();
1743fcf5ef2aSThomas Huth             }
1744fcf5ef2aSThomas Huth         }
1745fcf5ef2aSThomas Huth         break;
1746fcf5ef2aSThomas Huth     }
1747fcf5ef2aSThomas Huth }
1748fcf5ef2aSThomas Huth 
1749287b1152SRichard Henderson static void gen_stf_asi(DisasContext *dc, DisasASI *da, MemOp orig_size,
17503259b9e2SRichard Henderson                         TCGv addr, int rd)
17513259b9e2SRichard Henderson {
17523259b9e2SRichard Henderson     MemOp memop = da->memop;
17533259b9e2SRichard Henderson     MemOp size = memop & MO_SIZE;
1754fcf5ef2aSThomas Huth     TCGv_i32 d32;
1755*1210a036SRichard Henderson     TCGv_i64 d64;
1756287b1152SRichard Henderson     TCGv addr_tmp;
1757fcf5ef2aSThomas Huth 
17583259b9e2SRichard Henderson     /* TODO: Use 128-bit load/store below. */
17593259b9e2SRichard Henderson     if (size == MO_128) {
17603259b9e2SRichard Henderson         memop = (memop & ~MO_SIZE) | MO_64;
17613259b9e2SRichard Henderson     }
17623259b9e2SRichard Henderson 
17633259b9e2SRichard Henderson     switch (da->type) {
1764fcf5ef2aSThomas Huth     case GET_ASI_EXCP:
1765fcf5ef2aSThomas Huth         break;
1766fcf5ef2aSThomas Huth 
1767fcf5ef2aSThomas Huth     case GET_ASI_DIRECT:
17683259b9e2SRichard Henderson         memop |= MO_ALIGN_4;
1769fcf5ef2aSThomas Huth         switch (size) {
17703259b9e2SRichard Henderson         case MO_32:
1771fcf5ef2aSThomas Huth             d32 = gen_load_fpr_F(dc, rd);
17723259b9e2SRichard Henderson             tcg_gen_qemu_st_i32(d32, addr, da->mem_idx, memop | MO_ALIGN);
1773fcf5ef2aSThomas Huth             break;
17743259b9e2SRichard Henderson         case MO_64:
1775*1210a036SRichard Henderson             d64 = gen_load_fpr_D(dc, rd);
1776*1210a036SRichard Henderson             tcg_gen_qemu_st_i64(d64, addr, da->mem_idx, memop | MO_ALIGN_4);
1777fcf5ef2aSThomas Huth             break;
17783259b9e2SRichard Henderson         case MO_128:
1779fcf5ef2aSThomas Huth             /* Only 4-byte alignment required.  However, it is legal for the
1780fcf5ef2aSThomas Huth                cpu to signal the alignment fault, and the OS trap handler is
1781fcf5ef2aSThomas Huth                required to fix it up.  Requiring 16-byte alignment here avoids
1782fcf5ef2aSThomas Huth                having to probe the second page before performing the first
1783fcf5ef2aSThomas Huth                write.  */
1784*1210a036SRichard Henderson             d64 = gen_load_fpr_D(dc, rd);
1785*1210a036SRichard Henderson             tcg_gen_qemu_st_i64(d64, addr, da->mem_idx, memop | MO_ALIGN_16);
1786287b1152SRichard Henderson             addr_tmp = tcg_temp_new();
1787287b1152SRichard Henderson             tcg_gen_addi_tl(addr_tmp, addr, 8);
1788*1210a036SRichard Henderson             d64 = gen_load_fpr_D(dc, rd + 2);
1789*1210a036SRichard Henderson             tcg_gen_qemu_st_i64(d64, addr_tmp, da->mem_idx, memop);
1790fcf5ef2aSThomas Huth             break;
1791fcf5ef2aSThomas Huth         default:
1792fcf5ef2aSThomas Huth             g_assert_not_reached();
1793fcf5ef2aSThomas Huth         }
1794fcf5ef2aSThomas Huth         break;
1795fcf5ef2aSThomas Huth 
1796fcf5ef2aSThomas Huth     case GET_ASI_BLOCK:
1797fcf5ef2aSThomas Huth         /* Valid for stdfa on aligned registers only.  */
17983259b9e2SRichard Henderson         if (orig_size == MO_64 && (rd & 7) == 0) {
1799fcf5ef2aSThomas Huth             /* The first operation checks required alignment.  */
1800287b1152SRichard Henderson             addr_tmp = tcg_temp_new();
1801287b1152SRichard Henderson             for (int i = 0; ; ++i) {
1802*1210a036SRichard Henderson                 d64 = gen_load_fpr_D(dc, rd + 2 * i);
1803*1210a036SRichard Henderson                 tcg_gen_qemu_st_i64(d64, addr, da->mem_idx,
18043259b9e2SRichard Henderson                                     memop | (i == 0 ? MO_ALIGN_64 : 0));
1805fcf5ef2aSThomas Huth                 if (i == 7) {
1806fcf5ef2aSThomas Huth                     break;
1807fcf5ef2aSThomas Huth                 }
1808287b1152SRichard Henderson                 tcg_gen_addi_tl(addr_tmp, addr, 8);
1809287b1152SRichard Henderson                 addr = addr_tmp;
1810fcf5ef2aSThomas Huth             }
1811fcf5ef2aSThomas Huth         } else {
1812fcf5ef2aSThomas Huth             gen_exception(dc, TT_ILL_INSN);
1813fcf5ef2aSThomas Huth         }
1814fcf5ef2aSThomas Huth         break;
1815fcf5ef2aSThomas Huth 
1816fcf5ef2aSThomas Huth     case GET_ASI_SHORT:
1817fcf5ef2aSThomas Huth         /* Valid for stdfa only.  */
18183259b9e2SRichard Henderson         if (orig_size == MO_64) {
1819*1210a036SRichard Henderson             d64 = gen_load_fpr_D(dc, rd);
1820*1210a036SRichard Henderson             tcg_gen_qemu_st_i64(d64, addr, da->mem_idx, memop | MO_ALIGN);
1821fcf5ef2aSThomas Huth         } else {
1822fcf5ef2aSThomas Huth             gen_exception(dc, TT_ILL_INSN);
1823fcf5ef2aSThomas Huth         }
1824fcf5ef2aSThomas Huth         break;
1825fcf5ef2aSThomas Huth 
1826fcf5ef2aSThomas Huth     default:
1827fcf5ef2aSThomas Huth         /* According to the table in the UA2011 manual, the only
1828fcf5ef2aSThomas Huth            other asis that are valid for ldfa/lddfa/ldqfa are
1829fcf5ef2aSThomas Huth            the PST* asis, which aren't currently handled.  */
1830fcf5ef2aSThomas Huth         gen_exception(dc, TT_ILL_INSN);
1831fcf5ef2aSThomas Huth         break;
1832fcf5ef2aSThomas Huth     }
1833fcf5ef2aSThomas Huth }
1834fcf5ef2aSThomas Huth 
183542071fc1SRichard Henderson static void gen_ldda_asi(DisasContext *dc, DisasASI *da, TCGv addr, int rd)
1836fcf5ef2aSThomas Huth {
1837a76779eeSRichard Henderson     TCGv hi = gen_dest_gpr(dc, rd);
1838a76779eeSRichard Henderson     TCGv lo = gen_dest_gpr(dc, rd + 1);
1839fcf5ef2aSThomas Huth 
1840c03a0fd1SRichard Henderson     switch (da->type) {
1841fcf5ef2aSThomas Huth     case GET_ASI_EXCP:
1842fcf5ef2aSThomas Huth         return;
1843fcf5ef2aSThomas Huth 
1844fcf5ef2aSThomas Huth     case GET_ASI_DTWINX:
1845ebbbec92SRichard Henderson #ifdef TARGET_SPARC64
1846ebbbec92SRichard Henderson         {
1847ebbbec92SRichard Henderson             MemOp mop = (da->memop & MO_BSWAP) | MO_128 | MO_ALIGN_16;
1848ebbbec92SRichard Henderson             TCGv_i128 t = tcg_temp_new_i128();
1849ebbbec92SRichard Henderson 
1850ebbbec92SRichard Henderson             tcg_gen_qemu_ld_i128(t, addr, da->mem_idx, mop);
1851ebbbec92SRichard Henderson             /*
1852ebbbec92SRichard Henderson              * Note that LE twinx acts as if each 64-bit register result is
1853ebbbec92SRichard Henderson              * byte swapped.  We perform one 128-bit LE load, so must swap
1854ebbbec92SRichard Henderson              * the order of the writebacks.
1855ebbbec92SRichard Henderson              */
1856ebbbec92SRichard Henderson             if ((mop & MO_BSWAP) == MO_TE) {
1857ebbbec92SRichard Henderson                 tcg_gen_extr_i128_i64(lo, hi, t);
1858ebbbec92SRichard Henderson             } else {
1859ebbbec92SRichard Henderson                 tcg_gen_extr_i128_i64(hi, lo, t);
1860ebbbec92SRichard Henderson             }
1861ebbbec92SRichard Henderson         }
1862fcf5ef2aSThomas Huth         break;
1863ebbbec92SRichard Henderson #else
1864ebbbec92SRichard Henderson         g_assert_not_reached();
1865ebbbec92SRichard Henderson #endif
1866fcf5ef2aSThomas Huth 
1867fcf5ef2aSThomas Huth     case GET_ASI_DIRECT:
1868fcf5ef2aSThomas Huth         {
1869fcf5ef2aSThomas Huth             TCGv_i64 tmp = tcg_temp_new_i64();
1870fcf5ef2aSThomas Huth 
1871c03a0fd1SRichard Henderson             tcg_gen_qemu_ld_i64(tmp, addr, da->mem_idx, da->memop | MO_ALIGN);
1872fcf5ef2aSThomas Huth 
1873fcf5ef2aSThomas Huth             /* Note that LE ldda acts as if each 32-bit register
1874fcf5ef2aSThomas Huth                result is byte swapped.  Having just performed one
1875fcf5ef2aSThomas Huth                64-bit bswap, we need now to swap the writebacks.  */
1876c03a0fd1SRichard Henderson             if ((da->memop & MO_BSWAP) == MO_TE) {
1877a76779eeSRichard Henderson                 tcg_gen_extr_i64_tl(lo, hi, tmp);
1878fcf5ef2aSThomas Huth             } else {
1879a76779eeSRichard Henderson                 tcg_gen_extr_i64_tl(hi, lo, tmp);
1880fcf5ef2aSThomas Huth             }
1881fcf5ef2aSThomas Huth         }
1882fcf5ef2aSThomas Huth         break;
1883fcf5ef2aSThomas Huth 
18842786a3f8SRichard Henderson     case GET_ASI_CODE:
18852786a3f8SRichard Henderson #if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
18862786a3f8SRichard Henderson         {
18872786a3f8SRichard Henderson             MemOpIdx oi = make_memop_idx(da->memop, da->mem_idx);
18882786a3f8SRichard Henderson             TCGv_i64 tmp = tcg_temp_new_i64();
18892786a3f8SRichard Henderson 
18902786a3f8SRichard Henderson             gen_helper_ld_code(tmp, tcg_env, addr, tcg_constant_i32(oi));
18912786a3f8SRichard Henderson 
18922786a3f8SRichard Henderson             /* See above.  */
18932786a3f8SRichard Henderson             if ((da->memop & MO_BSWAP) == MO_TE) {
18942786a3f8SRichard Henderson                 tcg_gen_extr_i64_tl(lo, hi, tmp);
18952786a3f8SRichard Henderson             } else {
18962786a3f8SRichard Henderson                 tcg_gen_extr_i64_tl(hi, lo, tmp);
18972786a3f8SRichard Henderson             }
18982786a3f8SRichard Henderson         }
18992786a3f8SRichard Henderson         break;
19002786a3f8SRichard Henderson #else
19012786a3f8SRichard Henderson         g_assert_not_reached();
19022786a3f8SRichard Henderson #endif
19032786a3f8SRichard Henderson 
1904fcf5ef2aSThomas Huth     default:
1905fcf5ef2aSThomas Huth         /* ??? In theory we've handled all of the ASIs that are valid
1906fcf5ef2aSThomas Huth            for ldda, and this should raise DAE_invalid_asi.  However,
1907fcf5ef2aSThomas Huth            real hardware allows others.  This can be seen with e.g.
1908fcf5ef2aSThomas Huth            FreeBSD 10.3 wrt ASI_IC_TAG.  */
1909fcf5ef2aSThomas Huth         {
1910c03a0fd1SRichard Henderson             TCGv_i32 r_asi = tcg_constant_i32(da->asi);
1911c03a0fd1SRichard Henderson             TCGv_i32 r_mop = tcg_constant_i32(da->memop);
1912fcf5ef2aSThomas Huth             TCGv_i64 tmp = tcg_temp_new_i64();
1913fcf5ef2aSThomas Huth 
1914fcf5ef2aSThomas Huth             save_state(dc);
1915ad75a51eSRichard Henderson             gen_helper_ld_asi(tmp, tcg_env, addr, r_asi, r_mop);
1916fcf5ef2aSThomas Huth 
1917fcf5ef2aSThomas Huth             /* See above.  */
1918c03a0fd1SRichard Henderson             if ((da->memop & MO_BSWAP) == MO_TE) {
1919a76779eeSRichard Henderson                 tcg_gen_extr_i64_tl(lo, hi, tmp);
1920fcf5ef2aSThomas Huth             } else {
1921a76779eeSRichard Henderson                 tcg_gen_extr_i64_tl(hi, lo, tmp);
1922fcf5ef2aSThomas Huth             }
1923fcf5ef2aSThomas Huth         }
1924fcf5ef2aSThomas Huth         break;
1925fcf5ef2aSThomas Huth     }
1926fcf5ef2aSThomas Huth 
1927fcf5ef2aSThomas Huth     gen_store_gpr(dc, rd, hi);
1928fcf5ef2aSThomas Huth     gen_store_gpr(dc, rd + 1, lo);
1929fcf5ef2aSThomas Huth }
1930fcf5ef2aSThomas Huth 
193142071fc1SRichard Henderson static void gen_stda_asi(DisasContext *dc, DisasASI *da, TCGv addr, int rd)
1932c03a0fd1SRichard Henderson {
1933c03a0fd1SRichard Henderson     TCGv hi = gen_load_gpr(dc, rd);
1934fcf5ef2aSThomas Huth     TCGv lo = gen_load_gpr(dc, rd + 1);
1935fcf5ef2aSThomas Huth 
1936c03a0fd1SRichard Henderson     switch (da->type) {
1937fcf5ef2aSThomas Huth     case GET_ASI_EXCP:
1938fcf5ef2aSThomas Huth         break;
1939fcf5ef2aSThomas Huth 
1940fcf5ef2aSThomas Huth     case GET_ASI_DTWINX:
1941ebbbec92SRichard Henderson #ifdef TARGET_SPARC64
1942ebbbec92SRichard Henderson         {
1943ebbbec92SRichard Henderson             MemOp mop = (da->memop & MO_BSWAP) | MO_128 | MO_ALIGN_16;
1944ebbbec92SRichard Henderson             TCGv_i128 t = tcg_temp_new_i128();
1945ebbbec92SRichard Henderson 
1946ebbbec92SRichard Henderson             /*
1947ebbbec92SRichard Henderson              * Note that LE twinx acts as if each 64-bit register result is
1948ebbbec92SRichard Henderson              * byte swapped.  We perform one 128-bit LE store, so must swap
1949ebbbec92SRichard Henderson              * the order of the construction.
1950ebbbec92SRichard Henderson              */
1951ebbbec92SRichard Henderson             if ((mop & MO_BSWAP) == MO_TE) {
1952ebbbec92SRichard Henderson                 tcg_gen_concat_i64_i128(t, lo, hi);
1953ebbbec92SRichard Henderson             } else {
1954ebbbec92SRichard Henderson                 tcg_gen_concat_i64_i128(t, hi, lo);
1955ebbbec92SRichard Henderson             }
1956ebbbec92SRichard Henderson             tcg_gen_qemu_st_i128(t, addr, da->mem_idx, mop);
1957ebbbec92SRichard Henderson         }
1958fcf5ef2aSThomas Huth         break;
1959ebbbec92SRichard Henderson #else
1960ebbbec92SRichard Henderson         g_assert_not_reached();
1961ebbbec92SRichard Henderson #endif
1962fcf5ef2aSThomas Huth 
1963fcf5ef2aSThomas Huth     case GET_ASI_DIRECT:
1964fcf5ef2aSThomas Huth         {
1965fcf5ef2aSThomas Huth             TCGv_i64 t64 = tcg_temp_new_i64();
1966fcf5ef2aSThomas Huth 
1967fcf5ef2aSThomas Huth             /* Note that LE stda acts as if each 32-bit register result is
1968fcf5ef2aSThomas Huth                byte swapped.  We will perform one 64-bit LE store, so now
1969fcf5ef2aSThomas Huth                we must swap the order of the construction.  */
1970c03a0fd1SRichard Henderson             if ((da->memop & MO_BSWAP) == MO_TE) {
1971a76779eeSRichard Henderson                 tcg_gen_concat_tl_i64(t64, lo, hi);
1972fcf5ef2aSThomas Huth             } else {
1973a76779eeSRichard Henderson                 tcg_gen_concat_tl_i64(t64, hi, lo);
1974fcf5ef2aSThomas Huth             }
1975c03a0fd1SRichard Henderson             tcg_gen_qemu_st_i64(t64, addr, da->mem_idx, da->memop | MO_ALIGN);
1976fcf5ef2aSThomas Huth         }
1977fcf5ef2aSThomas Huth         break;
1978fcf5ef2aSThomas Huth 
1979a76779eeSRichard Henderson     case GET_ASI_BFILL:
1980a76779eeSRichard Henderson         assert(TARGET_LONG_BITS == 32);
198154c3e953SRichard Henderson         /*
198254c3e953SRichard Henderson          * Store 32 bytes of [rd:rd+1] to ADDR.
198354c3e953SRichard Henderson          * See comments for GET_ASI_COPY above.
198454c3e953SRichard Henderson          */
1985a76779eeSRichard Henderson         {
198654c3e953SRichard Henderson             MemOp mop = MO_TE | MO_128 | MO_ATOM_IFALIGN_PAIR;
198754c3e953SRichard Henderson             TCGv_i64 t8 = tcg_temp_new_i64();
198854c3e953SRichard Henderson             TCGv_i128 t16 = tcg_temp_new_i128();
198954c3e953SRichard Henderson             TCGv daddr = tcg_temp_new();
1990a76779eeSRichard Henderson 
199154c3e953SRichard Henderson             tcg_gen_concat_tl_i64(t8, lo, hi);
199254c3e953SRichard Henderson             tcg_gen_concat_i64_i128(t16, t8, t8);
199354c3e953SRichard Henderson             tcg_gen_andi_tl(daddr, addr, -32);
199454c3e953SRichard Henderson             tcg_gen_qemu_st_i128(t16, daddr, da->mem_idx, mop);
199554c3e953SRichard Henderson             tcg_gen_addi_tl(daddr, daddr, 16);
199654c3e953SRichard Henderson             tcg_gen_qemu_st_i128(t16, daddr, da->mem_idx, mop);
1997a76779eeSRichard Henderson         }
1998a76779eeSRichard Henderson         break;
1999a76779eeSRichard Henderson 
2000fcf5ef2aSThomas Huth     default:
2001fcf5ef2aSThomas Huth         /* ??? In theory we've handled all of the ASIs that are valid
2002fcf5ef2aSThomas Huth            for stda, and this should raise DAE_invalid_asi.  */
2003fcf5ef2aSThomas Huth         {
2004c03a0fd1SRichard Henderson             TCGv_i32 r_asi = tcg_constant_i32(da->asi);
2005c03a0fd1SRichard Henderson             TCGv_i32 r_mop = tcg_constant_i32(da->memop);
2006fcf5ef2aSThomas Huth             TCGv_i64 t64 = tcg_temp_new_i64();
2007fcf5ef2aSThomas Huth 
2008fcf5ef2aSThomas Huth             /* See above.  */
2009c03a0fd1SRichard Henderson             if ((da->memop & MO_BSWAP) == MO_TE) {
2010a76779eeSRichard Henderson                 tcg_gen_concat_tl_i64(t64, lo, hi);
2011fcf5ef2aSThomas Huth             } else {
2012a76779eeSRichard Henderson                 tcg_gen_concat_tl_i64(t64, hi, lo);
2013fcf5ef2aSThomas Huth             }
2014fcf5ef2aSThomas Huth 
2015fcf5ef2aSThomas Huth             save_state(dc);
2016ad75a51eSRichard Henderson             gen_helper_st_asi(tcg_env, addr, t64, r_asi, r_mop);
2017fcf5ef2aSThomas Huth         }
2018fcf5ef2aSThomas Huth         break;
2019fcf5ef2aSThomas Huth     }
2020fcf5ef2aSThomas Huth }
2021fcf5ef2aSThomas Huth 
2022fcf5ef2aSThomas Huth static void gen_fmovs(DisasContext *dc, DisasCompare *cmp, int rd, int rs)
2023fcf5ef2aSThomas Huth {
2024f7ec8155SRichard Henderson #ifdef TARGET_SPARC64
2025fcf5ef2aSThomas Huth     TCGv_i32 c32, zero, dst, s1, s2;
2026dd7dbfccSRichard Henderson     TCGv_i64 c64 = tcg_temp_new_i64();
2027fcf5ef2aSThomas Huth 
2028fcf5ef2aSThomas Huth     /* We have two choices here: extend the 32 bit data and use movcond_i64,
2029fcf5ef2aSThomas Huth        or fold the comparison down to 32 bits and use movcond_i32.  Choose
2030fcf5ef2aSThomas Huth        the later.  */
2031fcf5ef2aSThomas Huth     c32 = tcg_temp_new_i32();
2032c8507ebfSRichard Henderson     tcg_gen_setcondi_i64(cmp->cond, c64, cmp->c1, cmp->c2);
2033fcf5ef2aSThomas Huth     tcg_gen_extrl_i64_i32(c32, c64);
2034fcf5ef2aSThomas Huth 
2035fcf5ef2aSThomas Huth     s1 = gen_load_fpr_F(dc, rs);
2036fcf5ef2aSThomas Huth     s2 = gen_load_fpr_F(dc, rd);
2037388a6465SRichard Henderson     dst = tcg_temp_new_i32();
203800ab7e61SRichard Henderson     zero = tcg_constant_i32(0);
2039fcf5ef2aSThomas Huth 
2040fcf5ef2aSThomas Huth     tcg_gen_movcond_i32(TCG_COND_NE, dst, c32, zero, s1, s2);
2041fcf5ef2aSThomas Huth 
2042fcf5ef2aSThomas Huth     gen_store_fpr_F(dc, rd, dst);
2043f7ec8155SRichard Henderson #else
2044f7ec8155SRichard Henderson     qemu_build_not_reached();
2045f7ec8155SRichard Henderson #endif
2046fcf5ef2aSThomas Huth }
2047fcf5ef2aSThomas Huth 
2048fcf5ef2aSThomas Huth static void gen_fmovd(DisasContext *dc, DisasCompare *cmp, int rd, int rs)
2049fcf5ef2aSThomas Huth {
2050f7ec8155SRichard Henderson #ifdef TARGET_SPARC64
205152f46d46SRichard Henderson     TCGv_i64 dst = tcg_temp_new_i64();
2052c8507ebfSRichard Henderson     tcg_gen_movcond_i64(cmp->cond, dst, cmp->c1, tcg_constant_tl(cmp->c2),
2053fcf5ef2aSThomas Huth                         gen_load_fpr_D(dc, rs),
2054fcf5ef2aSThomas Huth                         gen_load_fpr_D(dc, rd));
2055fcf5ef2aSThomas Huth     gen_store_fpr_D(dc, rd, dst);
2056f7ec8155SRichard Henderson #else
2057f7ec8155SRichard Henderson     qemu_build_not_reached();
2058f7ec8155SRichard Henderson #endif
2059fcf5ef2aSThomas Huth }
2060fcf5ef2aSThomas Huth 
2061fcf5ef2aSThomas Huth static void gen_fmovq(DisasContext *dc, DisasCompare *cmp, int rd, int rs)
2062fcf5ef2aSThomas Huth {
2063f7ec8155SRichard Henderson #ifdef TARGET_SPARC64
2064c8507ebfSRichard Henderson     TCGv c2 = tcg_constant_tl(cmp->c2);
2065*1210a036SRichard Henderson     TCGv_i64 h = tcg_temp_new_i64();
2066*1210a036SRichard Henderson     TCGv_i64 l = tcg_temp_new_i64();
2067fcf5ef2aSThomas Huth 
2068*1210a036SRichard Henderson     tcg_gen_movcond_i64(cmp->cond, h, cmp->c1, c2,
2069*1210a036SRichard Henderson                         gen_load_fpr_D(dc, rs),
2070*1210a036SRichard Henderson                         gen_load_fpr_D(dc, rd));
2071*1210a036SRichard Henderson     tcg_gen_movcond_i64(cmp->cond, l, cmp->c1, c2,
2072*1210a036SRichard Henderson                         gen_load_fpr_D(dc, rs + 2),
2073*1210a036SRichard Henderson                         gen_load_fpr_D(dc, rd + 2));
2074*1210a036SRichard Henderson     gen_store_fpr_D(dc, rd, h);
2075*1210a036SRichard Henderson     gen_store_fpr_D(dc, rd + 2, l);
2076f7ec8155SRichard Henderson #else
2077f7ec8155SRichard Henderson     qemu_build_not_reached();
2078f7ec8155SRichard Henderson #endif
2079fcf5ef2aSThomas Huth }
2080fcf5ef2aSThomas Huth 
2081f7ec8155SRichard Henderson #ifdef TARGET_SPARC64
20825d617bfbSRichard Henderson static void gen_load_trap_state_at_tl(TCGv_ptr r_tsptr)
2083fcf5ef2aSThomas Huth {
2084fcf5ef2aSThomas Huth     TCGv_i32 r_tl = tcg_temp_new_i32();
2085fcf5ef2aSThomas Huth 
2086fcf5ef2aSThomas Huth     /* load env->tl into r_tl */
2087ad75a51eSRichard Henderson     tcg_gen_ld_i32(r_tl, tcg_env, offsetof(CPUSPARCState, tl));
2088fcf5ef2aSThomas Huth 
2089fcf5ef2aSThomas Huth     /* tl = [0 ... MAXTL_MASK] where MAXTL_MASK must be power of 2 */
2090fcf5ef2aSThomas Huth     tcg_gen_andi_i32(r_tl, r_tl, MAXTL_MASK);
2091fcf5ef2aSThomas Huth 
2092fcf5ef2aSThomas Huth     /* calculate offset to current trap state from env->ts, reuse r_tl */
2093fcf5ef2aSThomas Huth     tcg_gen_muli_i32(r_tl, r_tl, sizeof (trap_state));
2094ad75a51eSRichard Henderson     tcg_gen_addi_ptr(r_tsptr, tcg_env, offsetof(CPUSPARCState, ts));
2095fcf5ef2aSThomas Huth 
2096fcf5ef2aSThomas Huth     /* tsptr = env->ts[env->tl & MAXTL_MASK] */
2097fcf5ef2aSThomas Huth     {
2098fcf5ef2aSThomas Huth         TCGv_ptr r_tl_tmp = tcg_temp_new_ptr();
2099fcf5ef2aSThomas Huth         tcg_gen_ext_i32_ptr(r_tl_tmp, r_tl);
2100fcf5ef2aSThomas Huth         tcg_gen_add_ptr(r_tsptr, r_tsptr, r_tl_tmp);
2101fcf5ef2aSThomas Huth     }
2102fcf5ef2aSThomas Huth }
2103fcf5ef2aSThomas Huth #endif
2104fcf5ef2aSThomas Huth 
210506c060d9SRichard Henderson static int extract_dfpreg(DisasContext *dc, int x)
210606c060d9SRichard Henderson {
21070bba7572SRichard Henderson     int r = x & 0x1e;
21080bba7572SRichard Henderson #ifdef TARGET_SPARC64
21090bba7572SRichard Henderson     r |= (x & 1) << 5;
21100bba7572SRichard Henderson #endif
21110bba7572SRichard Henderson     return r;
211206c060d9SRichard Henderson }
211306c060d9SRichard Henderson 
211406c060d9SRichard Henderson static int extract_qfpreg(DisasContext *dc, int x)
211506c060d9SRichard Henderson {
21160bba7572SRichard Henderson     int r = x & 0x1c;
21170bba7572SRichard Henderson #ifdef TARGET_SPARC64
21180bba7572SRichard Henderson     r |= (x & 1) << 5;
21190bba7572SRichard Henderson #endif
21200bba7572SRichard Henderson     return r;
212106c060d9SRichard Henderson }
212206c060d9SRichard Henderson 
2123878cc677SRichard Henderson /* Include the auto-generated decoder.  */
2124878cc677SRichard Henderson #include "decode-insns.c.inc"
2125878cc677SRichard Henderson 
2126878cc677SRichard Henderson #define TRANS(NAME, AVAIL, FUNC, ...) \
2127878cc677SRichard Henderson     static bool trans_##NAME(DisasContext *dc, arg_##NAME *a) \
2128878cc677SRichard Henderson     { return avail_##AVAIL(dc) && FUNC(dc, __VA_ARGS__); }
2129878cc677SRichard Henderson 
2130878cc677SRichard Henderson #define avail_ALL(C)      true
2131878cc677SRichard Henderson #ifdef TARGET_SPARC64
2132878cc677SRichard Henderson # define avail_32(C)      false
2133af25071cSRichard Henderson # define avail_ASR17(C)   false
2134d0a11d25SRichard Henderson # define avail_CASA(C)    true
2135c2636853SRichard Henderson # define avail_DIV(C)     true
2136b5372650SRichard Henderson # define avail_MUL(C)     true
21370faef01bSRichard Henderson # define avail_POWERDOWN(C) false
2138878cc677SRichard Henderson # define avail_64(C)      true
21395d617bfbSRichard Henderson # define avail_GL(C)      ((C)->def->features & CPU_FEATURE_GL)
2140af25071cSRichard Henderson # define avail_HYPV(C)    ((C)->def->features & CPU_FEATURE_HYPV)
2141b88ce6f2SRichard Henderson # define avail_VIS1(C)    ((C)->def->features & CPU_FEATURE_VIS1)
2142b88ce6f2SRichard Henderson # define avail_VIS2(C)    ((C)->def->features & CPU_FEATURE_VIS2)
2143878cc677SRichard Henderson #else
2144878cc677SRichard Henderson # define avail_32(C)      true
2145af25071cSRichard Henderson # define avail_ASR17(C)   ((C)->def->features & CPU_FEATURE_ASR17)
2146d0a11d25SRichard Henderson # define avail_CASA(C)    ((C)->def->features & CPU_FEATURE_CASA)
2147c2636853SRichard Henderson # define avail_DIV(C)     ((C)->def->features & CPU_FEATURE_DIV)
2148b5372650SRichard Henderson # define avail_MUL(C)     ((C)->def->features & CPU_FEATURE_MUL)
21490faef01bSRichard Henderson # define avail_POWERDOWN(C) ((C)->def->features & CPU_FEATURE_POWERDOWN)
2150878cc677SRichard Henderson # define avail_64(C)      false
21515d617bfbSRichard Henderson # define avail_GL(C)      false
2152af25071cSRichard Henderson # define avail_HYPV(C)    false
2153b88ce6f2SRichard Henderson # define avail_VIS1(C)    false
2154b88ce6f2SRichard Henderson # define avail_VIS2(C)    false
2155878cc677SRichard Henderson #endif
2156878cc677SRichard Henderson 
2157878cc677SRichard Henderson /* Default case for non jump instructions. */
2158878cc677SRichard Henderson static bool advance_pc(DisasContext *dc)
2159878cc677SRichard Henderson {
21604a8d145dSRichard Henderson     TCGLabel *l1;
21614a8d145dSRichard Henderson 
216289527e3aSRichard Henderson     finishing_insn(dc);
216389527e3aSRichard Henderson 
2164878cc677SRichard Henderson     if (dc->npc & 3) {
2165878cc677SRichard Henderson         switch (dc->npc) {
2166878cc677SRichard Henderson         case DYNAMIC_PC:
2167878cc677SRichard Henderson         case DYNAMIC_PC_LOOKUP:
2168878cc677SRichard Henderson             dc->pc = dc->npc;
2169444d8b30SRichard Henderson             tcg_gen_mov_tl(cpu_pc, cpu_npc);
2170444d8b30SRichard Henderson             tcg_gen_addi_tl(cpu_npc, cpu_npc, 4);
2171878cc677SRichard Henderson             break;
21724a8d145dSRichard Henderson 
2173878cc677SRichard Henderson         case JUMP_PC:
2174878cc677SRichard Henderson             /* we can do a static jump */
21754a8d145dSRichard Henderson             l1 = gen_new_label();
2176533f042fSRichard Henderson             tcg_gen_brcondi_tl(dc->jump.cond, dc->jump.c1, dc->jump.c2, l1);
21774a8d145dSRichard Henderson 
21784a8d145dSRichard Henderson             /* jump not taken */
21794a8d145dSRichard Henderson             gen_goto_tb(dc, 1, dc->jump_pc[1], dc->jump_pc[1] + 4);
21804a8d145dSRichard Henderson 
21814a8d145dSRichard Henderson             /* jump taken */
21824a8d145dSRichard Henderson             gen_set_label(l1);
21834a8d145dSRichard Henderson             gen_goto_tb(dc, 0, dc->jump_pc[0], dc->jump_pc[0] + 4);
21844a8d145dSRichard Henderson 
2185878cc677SRichard Henderson             dc->base.is_jmp = DISAS_NORETURN;
2186878cc677SRichard Henderson             break;
21874a8d145dSRichard Henderson 
2188878cc677SRichard Henderson         default:
2189878cc677SRichard Henderson             g_assert_not_reached();
2190878cc677SRichard Henderson         }
2191878cc677SRichard Henderson     } else {
2192878cc677SRichard Henderson         dc->pc = dc->npc;
2193878cc677SRichard Henderson         dc->npc = dc->npc + 4;
2194878cc677SRichard Henderson     }
2195878cc677SRichard Henderson     return true;
2196878cc677SRichard Henderson }
2197878cc677SRichard Henderson 
21986d2a0768SRichard Henderson /*
21996d2a0768SRichard Henderson  * Major opcodes 00 and 01 -- branches, call, and sethi
22006d2a0768SRichard Henderson  */
22016d2a0768SRichard Henderson 
22029d4e2bc7SRichard Henderson static bool advance_jump_cond(DisasContext *dc, DisasCompare *cmp,
22033951b7a8SRichard Henderson                               bool annul, int disp)
2204276567aaSRichard Henderson {
22053951b7a8SRichard Henderson     target_ulong dest = address_mask_i(dc, dc->pc + disp * 4);
2206c76c8045SRichard Henderson     target_ulong npc;
2207c76c8045SRichard Henderson 
220889527e3aSRichard Henderson     finishing_insn(dc);
220989527e3aSRichard Henderson 
22102d9bb237SRichard Henderson     if (cmp->cond == TCG_COND_ALWAYS) {
22112d9bb237SRichard Henderson         if (annul) {
22122d9bb237SRichard Henderson             dc->pc = dest;
22132d9bb237SRichard Henderson             dc->npc = dest + 4;
22142d9bb237SRichard Henderson         } else {
22152d9bb237SRichard Henderson             gen_mov_pc_npc(dc);
22162d9bb237SRichard Henderson             dc->npc = dest;
22172d9bb237SRichard Henderson         }
22182d9bb237SRichard Henderson         return true;
22192d9bb237SRichard Henderson     }
22202d9bb237SRichard Henderson 
22212d9bb237SRichard Henderson     if (cmp->cond == TCG_COND_NEVER) {
22222d9bb237SRichard Henderson         npc = dc->npc;
22232d9bb237SRichard Henderson         if (npc & 3) {
22242d9bb237SRichard Henderson             gen_mov_pc_npc(dc);
22252d9bb237SRichard Henderson             if (annul) {
22262d9bb237SRichard Henderson                 tcg_gen_addi_tl(cpu_pc, cpu_pc, 4);
22272d9bb237SRichard Henderson             }
22282d9bb237SRichard Henderson             tcg_gen_addi_tl(cpu_npc, cpu_pc, 4);
22292d9bb237SRichard Henderson         } else {
22302d9bb237SRichard Henderson             dc->pc = npc + (annul ? 4 : 0);
22312d9bb237SRichard Henderson             dc->npc = dc->pc + 4;
22322d9bb237SRichard Henderson         }
22332d9bb237SRichard Henderson         return true;
22342d9bb237SRichard Henderson     }
22352d9bb237SRichard Henderson 
2236c76c8045SRichard Henderson     flush_cond(dc);
2237c76c8045SRichard Henderson     npc = dc->npc;
22386b3e4cc6SRichard Henderson 
2239276567aaSRichard Henderson     if (annul) {
22406b3e4cc6SRichard Henderson         TCGLabel *l1 = gen_new_label();
22416b3e4cc6SRichard Henderson 
2242c8507ebfSRichard Henderson         tcg_gen_brcondi_tl(tcg_invert_cond(cmp->cond), cmp->c1, cmp->c2, l1);
22436b3e4cc6SRichard Henderson         gen_goto_tb(dc, 0, npc, dest);
22446b3e4cc6SRichard Henderson         gen_set_label(l1);
22456b3e4cc6SRichard Henderson         gen_goto_tb(dc, 1, npc + 4, npc + 8);
22466b3e4cc6SRichard Henderson 
22476b3e4cc6SRichard Henderson         dc->base.is_jmp = DISAS_NORETURN;
2248276567aaSRichard Henderson     } else {
22496b3e4cc6SRichard Henderson         if (npc & 3) {
22506b3e4cc6SRichard Henderson             switch (npc) {
22516b3e4cc6SRichard Henderson             case DYNAMIC_PC:
22526b3e4cc6SRichard Henderson             case DYNAMIC_PC_LOOKUP:
22536b3e4cc6SRichard Henderson                 tcg_gen_mov_tl(cpu_pc, cpu_npc);
22546b3e4cc6SRichard Henderson                 tcg_gen_addi_tl(cpu_npc, cpu_npc, 4);
22559d4e2bc7SRichard Henderson                 tcg_gen_movcond_tl(cmp->cond, cpu_npc,
2256c8507ebfSRichard Henderson                                    cmp->c1, tcg_constant_tl(cmp->c2),
22576b3e4cc6SRichard Henderson                                    tcg_constant_tl(dest), cpu_npc);
22586b3e4cc6SRichard Henderson                 dc->pc = npc;
22596b3e4cc6SRichard Henderson                 break;
22606b3e4cc6SRichard Henderson             default:
22616b3e4cc6SRichard Henderson                 g_assert_not_reached();
22626b3e4cc6SRichard Henderson             }
22636b3e4cc6SRichard Henderson         } else {
22646b3e4cc6SRichard Henderson             dc->pc = npc;
2265533f042fSRichard Henderson             dc->npc = JUMP_PC;
2266533f042fSRichard Henderson             dc->jump = *cmp;
22676b3e4cc6SRichard Henderson             dc->jump_pc[0] = dest;
22686b3e4cc6SRichard Henderson             dc->jump_pc[1] = npc + 4;
2269dd7dbfccSRichard Henderson 
2270dd7dbfccSRichard Henderson             /* The condition for cpu_cond is always NE -- normalize. */
2271dd7dbfccSRichard Henderson             if (cmp->cond == TCG_COND_NE) {
2272c8507ebfSRichard Henderson                 tcg_gen_xori_tl(cpu_cond, cmp->c1, cmp->c2);
22739d4e2bc7SRichard Henderson             } else {
2274c8507ebfSRichard Henderson                 tcg_gen_setcondi_tl(cmp->cond, cpu_cond, cmp->c1, cmp->c2);
22759d4e2bc7SRichard Henderson             }
227689527e3aSRichard Henderson             dc->cpu_cond_live = true;
22776b3e4cc6SRichard Henderson         }
2278276567aaSRichard Henderson     }
2279276567aaSRichard Henderson     return true;
2280276567aaSRichard Henderson }
2281276567aaSRichard Henderson 
2282af25071cSRichard Henderson static bool raise_priv(DisasContext *dc)
2283af25071cSRichard Henderson {
2284af25071cSRichard Henderson     gen_exception(dc, TT_PRIV_INSN);
2285af25071cSRichard Henderson     return true;
2286af25071cSRichard Henderson }
2287af25071cSRichard Henderson 
228806c060d9SRichard Henderson static bool raise_unimpfpop(DisasContext *dc)
228906c060d9SRichard Henderson {
229006c060d9SRichard Henderson     gen_op_fpexception_im(dc, FSR_FTT_UNIMPFPOP);
229106c060d9SRichard Henderson     return true;
229206c060d9SRichard Henderson }
229306c060d9SRichard Henderson 
229406c060d9SRichard Henderson static bool gen_trap_float128(DisasContext *dc)
229506c060d9SRichard Henderson {
229606c060d9SRichard Henderson     if (dc->def->features & CPU_FEATURE_FLOAT128) {
229706c060d9SRichard Henderson         return false;
229806c060d9SRichard Henderson     }
229906c060d9SRichard Henderson     return raise_unimpfpop(dc);
230006c060d9SRichard Henderson }
230106c060d9SRichard Henderson 
2302276567aaSRichard Henderson static bool do_bpcc(DisasContext *dc, arg_bcc *a)
2303276567aaSRichard Henderson {
23041ea9c62aSRichard Henderson     DisasCompare cmp;
2305276567aaSRichard Henderson 
23061ea9c62aSRichard Henderson     gen_compare(&cmp, a->cc, a->cond, dc);
23073951b7a8SRichard Henderson     return advance_jump_cond(dc, &cmp, a->a, a->i);
2308276567aaSRichard Henderson }
2309276567aaSRichard Henderson 
2310276567aaSRichard Henderson TRANS(Bicc, ALL, do_bpcc, a)
2311276567aaSRichard Henderson TRANS(BPcc,  64, do_bpcc, a)
2312276567aaSRichard Henderson 
231345196ea4SRichard Henderson static bool do_fbpfcc(DisasContext *dc, arg_bcc *a)
231445196ea4SRichard Henderson {
2315d5471936SRichard Henderson     DisasCompare cmp;
231645196ea4SRichard Henderson 
231745196ea4SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
231845196ea4SRichard Henderson         return true;
231945196ea4SRichard Henderson     }
2320d5471936SRichard Henderson     gen_fcompare(&cmp, a->cc, a->cond);
23213951b7a8SRichard Henderson     return advance_jump_cond(dc, &cmp, a->a, a->i);
232245196ea4SRichard Henderson }
232345196ea4SRichard Henderson 
232445196ea4SRichard Henderson TRANS(FBPfcc,  64, do_fbpfcc, a)
232545196ea4SRichard Henderson TRANS(FBfcc,  ALL, do_fbpfcc, a)
232645196ea4SRichard Henderson 
2327ab9ffe98SRichard Henderson static bool trans_BPr(DisasContext *dc, arg_BPr *a)
2328ab9ffe98SRichard Henderson {
2329ab9ffe98SRichard Henderson     DisasCompare cmp;
2330ab9ffe98SRichard Henderson 
2331ab9ffe98SRichard Henderson     if (!avail_64(dc)) {
2332ab9ffe98SRichard Henderson         return false;
2333ab9ffe98SRichard Henderson     }
23342c4f56c9SRichard Henderson     if (!gen_compare_reg(&cmp, a->cond, gen_load_gpr(dc, a->rs1))) {
2335ab9ffe98SRichard Henderson         return false;
2336ab9ffe98SRichard Henderson     }
23373951b7a8SRichard Henderson     return advance_jump_cond(dc, &cmp, a->a, a->i);
2338ab9ffe98SRichard Henderson }
2339ab9ffe98SRichard Henderson 
234023ada1b1SRichard Henderson static bool trans_CALL(DisasContext *dc, arg_CALL *a)
234123ada1b1SRichard Henderson {
234223ada1b1SRichard Henderson     target_long target = address_mask_i(dc, dc->pc + a->i * 4);
234323ada1b1SRichard Henderson 
234423ada1b1SRichard Henderson     gen_store_gpr(dc, 15, tcg_constant_tl(dc->pc));
234523ada1b1SRichard Henderson     gen_mov_pc_npc(dc);
234623ada1b1SRichard Henderson     dc->npc = target;
234723ada1b1SRichard Henderson     return true;
234823ada1b1SRichard Henderson }
234923ada1b1SRichard Henderson 
235045196ea4SRichard Henderson static bool trans_NCP(DisasContext *dc, arg_NCP *a)
235145196ea4SRichard Henderson {
235245196ea4SRichard Henderson     /*
235345196ea4SRichard Henderson      * For sparc32, always generate the no-coprocessor exception.
235445196ea4SRichard Henderson      * For sparc64, always generate illegal instruction.
235545196ea4SRichard Henderson      */
235645196ea4SRichard Henderson #ifdef TARGET_SPARC64
235745196ea4SRichard Henderson     return false;
235845196ea4SRichard Henderson #else
235945196ea4SRichard Henderson     gen_exception(dc, TT_NCP_INSN);
236045196ea4SRichard Henderson     return true;
236145196ea4SRichard Henderson #endif
236245196ea4SRichard Henderson }
236345196ea4SRichard Henderson 
23646d2a0768SRichard Henderson static bool trans_SETHI(DisasContext *dc, arg_SETHI *a)
23656d2a0768SRichard Henderson {
23666d2a0768SRichard Henderson     /* Special-case %g0 because that's the canonical nop.  */
23676d2a0768SRichard Henderson     if (a->rd) {
23686d2a0768SRichard Henderson         gen_store_gpr(dc, a->rd, tcg_constant_tl((uint32_t)a->i << 10));
23696d2a0768SRichard Henderson     }
23706d2a0768SRichard Henderson     return advance_pc(dc);
23716d2a0768SRichard Henderson }
23726d2a0768SRichard Henderson 
23730faef01bSRichard Henderson /*
23740faef01bSRichard Henderson  * Major Opcode 10 -- integer, floating-point, vis, and system insns.
23750faef01bSRichard Henderson  */
23760faef01bSRichard Henderson 
237730376636SRichard Henderson static bool do_tcc(DisasContext *dc, int cond, int cc,
237830376636SRichard Henderson                    int rs1, bool imm, int rs2_or_imm)
237930376636SRichard Henderson {
238030376636SRichard Henderson     int mask = ((dc->def->features & CPU_FEATURE_HYPV) && supervisor(dc)
238130376636SRichard Henderson                 ? UA2005_HTRAP_MASK : V8_TRAP_MASK);
238230376636SRichard Henderson     DisasCompare cmp;
238330376636SRichard Henderson     TCGLabel *lab;
238430376636SRichard Henderson     TCGv_i32 trap;
238530376636SRichard Henderson 
238630376636SRichard Henderson     /* Trap never.  */
238730376636SRichard Henderson     if (cond == 0) {
238830376636SRichard Henderson         return advance_pc(dc);
238930376636SRichard Henderson     }
239030376636SRichard Henderson 
239130376636SRichard Henderson     /*
239230376636SRichard Henderson      * Immediate traps are the most common case.  Since this value is
239330376636SRichard Henderson      * live across the branch, it really pays to evaluate the constant.
239430376636SRichard Henderson      */
239530376636SRichard Henderson     if (rs1 == 0 && (imm || rs2_or_imm == 0)) {
239630376636SRichard Henderson         trap = tcg_constant_i32((rs2_or_imm & mask) + TT_TRAP);
239730376636SRichard Henderson     } else {
239830376636SRichard Henderson         trap = tcg_temp_new_i32();
239930376636SRichard Henderson         tcg_gen_trunc_tl_i32(trap, gen_load_gpr(dc, rs1));
240030376636SRichard Henderson         if (imm) {
240130376636SRichard Henderson             tcg_gen_addi_i32(trap, trap, rs2_or_imm);
240230376636SRichard Henderson         } else {
240330376636SRichard Henderson             TCGv_i32 t2 = tcg_temp_new_i32();
240430376636SRichard Henderson             tcg_gen_trunc_tl_i32(t2, gen_load_gpr(dc, rs2_or_imm));
240530376636SRichard Henderson             tcg_gen_add_i32(trap, trap, t2);
240630376636SRichard Henderson         }
240730376636SRichard Henderson         tcg_gen_andi_i32(trap, trap, mask);
240830376636SRichard Henderson         tcg_gen_addi_i32(trap, trap, TT_TRAP);
240930376636SRichard Henderson     }
241030376636SRichard Henderson 
241189527e3aSRichard Henderson     finishing_insn(dc);
241289527e3aSRichard Henderson 
241330376636SRichard Henderson     /* Trap always.  */
241430376636SRichard Henderson     if (cond == 8) {
241530376636SRichard Henderson         save_state(dc);
241630376636SRichard Henderson         gen_helper_raise_exception(tcg_env, trap);
241730376636SRichard Henderson         dc->base.is_jmp = DISAS_NORETURN;
241830376636SRichard Henderson         return true;
241930376636SRichard Henderson     }
242030376636SRichard Henderson 
242130376636SRichard Henderson     /* Conditional trap.  */
242230376636SRichard Henderson     flush_cond(dc);
242330376636SRichard Henderson     lab = delay_exceptionv(dc, trap);
242430376636SRichard Henderson     gen_compare(&cmp, cc, cond, dc);
2425c8507ebfSRichard Henderson     tcg_gen_brcondi_tl(cmp.cond, cmp.c1, cmp.c2, lab);
242630376636SRichard Henderson 
242730376636SRichard Henderson     return advance_pc(dc);
242830376636SRichard Henderson }
242930376636SRichard Henderson 
243030376636SRichard Henderson static bool trans_Tcc_r(DisasContext *dc, arg_Tcc_r *a)
243130376636SRichard Henderson {
243230376636SRichard Henderson     if (avail_32(dc) && a->cc) {
243330376636SRichard Henderson         return false;
243430376636SRichard Henderson     }
243530376636SRichard Henderson     return do_tcc(dc, a->cond, a->cc, a->rs1, false, a->rs2);
243630376636SRichard Henderson }
243730376636SRichard Henderson 
243830376636SRichard Henderson static bool trans_Tcc_i_v7(DisasContext *dc, arg_Tcc_i_v7 *a)
243930376636SRichard Henderson {
244030376636SRichard Henderson     if (avail_64(dc)) {
244130376636SRichard Henderson         return false;
244230376636SRichard Henderson     }
244330376636SRichard Henderson     return do_tcc(dc, a->cond, 0, a->rs1, true, a->i);
244430376636SRichard Henderson }
244530376636SRichard Henderson 
244630376636SRichard Henderson static bool trans_Tcc_i_v9(DisasContext *dc, arg_Tcc_i_v9 *a)
244730376636SRichard Henderson {
244830376636SRichard Henderson     if (avail_32(dc)) {
244930376636SRichard Henderson         return false;
245030376636SRichard Henderson     }
245130376636SRichard Henderson     return do_tcc(dc, a->cond, a->cc, a->rs1, true, a->i);
245230376636SRichard Henderson }
245330376636SRichard Henderson 
2454af25071cSRichard Henderson static bool trans_STBAR(DisasContext *dc, arg_STBAR *a)
2455af25071cSRichard Henderson {
2456af25071cSRichard Henderson     tcg_gen_mb(TCG_MO_ST_ST | TCG_BAR_SC);
2457af25071cSRichard Henderson     return advance_pc(dc);
2458af25071cSRichard Henderson }
2459af25071cSRichard Henderson 
2460af25071cSRichard Henderson static bool trans_MEMBAR(DisasContext *dc, arg_MEMBAR *a)
2461af25071cSRichard Henderson {
2462af25071cSRichard Henderson     if (avail_32(dc)) {
2463af25071cSRichard Henderson         return false;
2464af25071cSRichard Henderson     }
2465af25071cSRichard Henderson     if (a->mmask) {
2466af25071cSRichard Henderson         /* Note TCG_MO_* was modeled on sparc64, so mmask matches. */
2467af25071cSRichard Henderson         tcg_gen_mb(a->mmask | TCG_BAR_SC);
2468af25071cSRichard Henderson     }
2469af25071cSRichard Henderson     if (a->cmask) {
2470af25071cSRichard Henderson         /* For #Sync, etc, end the TB to recognize interrupts. */
2471af25071cSRichard Henderson         dc->base.is_jmp = DISAS_EXIT;
2472af25071cSRichard Henderson     }
2473af25071cSRichard Henderson     return advance_pc(dc);
2474af25071cSRichard Henderson }
2475af25071cSRichard Henderson 
2476af25071cSRichard Henderson static bool do_rd_special(DisasContext *dc, bool priv, int rd,
2477af25071cSRichard Henderson                           TCGv (*func)(DisasContext *, TCGv))
2478af25071cSRichard Henderson {
2479af25071cSRichard Henderson     if (!priv) {
2480af25071cSRichard Henderson         return raise_priv(dc);
2481af25071cSRichard Henderson     }
2482af25071cSRichard Henderson     gen_store_gpr(dc, rd, func(dc, gen_dest_gpr(dc, rd)));
2483af25071cSRichard Henderson     return advance_pc(dc);
2484af25071cSRichard Henderson }
2485af25071cSRichard Henderson 
2486af25071cSRichard Henderson static TCGv do_rdy(DisasContext *dc, TCGv dst)
2487af25071cSRichard Henderson {
2488af25071cSRichard Henderson     return cpu_y;
2489af25071cSRichard Henderson }
2490af25071cSRichard Henderson 
2491af25071cSRichard Henderson static bool trans_RDY(DisasContext *dc, arg_RDY *a)
2492af25071cSRichard Henderson {
2493af25071cSRichard Henderson     /*
2494af25071cSRichard Henderson      * TODO: Need a feature bit for sparcv8.  In the meantime, treat all
2495af25071cSRichard Henderson      * 32-bit cpus like sparcv7, which ignores the rs1 field.
2496af25071cSRichard Henderson      * This matches after all other ASR, so Leon3 Asr17 is handled first.
2497af25071cSRichard Henderson      */
2498af25071cSRichard Henderson     if (avail_64(dc) && a->rs1 != 0) {
2499af25071cSRichard Henderson         return false;
2500af25071cSRichard Henderson     }
2501af25071cSRichard Henderson     return do_rd_special(dc, true, a->rd, do_rdy);
2502af25071cSRichard Henderson }
2503af25071cSRichard Henderson 
2504af25071cSRichard Henderson static TCGv do_rd_leon3_config(DisasContext *dc, TCGv dst)
2505af25071cSRichard Henderson {
2506c92948f2SClément Chigot     gen_helper_rdasr17(dst, tcg_env);
2507c92948f2SClément Chigot     return dst;
2508af25071cSRichard Henderson }
2509af25071cSRichard Henderson 
2510af25071cSRichard Henderson TRANS(RDASR17, ASR17, do_rd_special, true, a->rd, do_rd_leon3_config)
2511af25071cSRichard Henderson 
2512af25071cSRichard Henderson static TCGv do_rdccr(DisasContext *dc, TCGv dst)
2513af25071cSRichard Henderson {
2514af25071cSRichard Henderson     gen_helper_rdccr(dst, tcg_env);
2515af25071cSRichard Henderson     return dst;
2516af25071cSRichard Henderson }
2517af25071cSRichard Henderson 
2518af25071cSRichard Henderson TRANS(RDCCR, 64, do_rd_special, true, a->rd, do_rdccr)
2519af25071cSRichard Henderson 
2520af25071cSRichard Henderson static TCGv do_rdasi(DisasContext *dc, TCGv dst)
2521af25071cSRichard Henderson {
2522af25071cSRichard Henderson #ifdef TARGET_SPARC64
2523af25071cSRichard Henderson     return tcg_constant_tl(dc->asi);
2524af25071cSRichard Henderson #else
2525af25071cSRichard Henderson     qemu_build_not_reached();
2526af25071cSRichard Henderson #endif
2527af25071cSRichard Henderson }
2528af25071cSRichard Henderson 
2529af25071cSRichard Henderson TRANS(RDASI, 64, do_rd_special, true, a->rd, do_rdasi)
2530af25071cSRichard Henderson 
2531af25071cSRichard Henderson static TCGv do_rdtick(DisasContext *dc, TCGv dst)
2532af25071cSRichard Henderson {
2533af25071cSRichard Henderson     TCGv_ptr r_tickptr = tcg_temp_new_ptr();
2534af25071cSRichard Henderson 
2535af25071cSRichard Henderson     tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(tick));
2536af25071cSRichard Henderson     if (translator_io_start(&dc->base)) {
2537af25071cSRichard Henderson         dc->base.is_jmp = DISAS_EXIT;
2538af25071cSRichard Henderson     }
2539af25071cSRichard Henderson     gen_helper_tick_get_count(dst, tcg_env, r_tickptr,
2540af25071cSRichard Henderson                               tcg_constant_i32(dc->mem_idx));
2541af25071cSRichard Henderson     return dst;
2542af25071cSRichard Henderson }
2543af25071cSRichard Henderson 
2544af25071cSRichard Henderson /* TODO: non-priv access only allowed when enabled. */
2545af25071cSRichard Henderson TRANS(RDTICK, 64, do_rd_special, true, a->rd, do_rdtick)
2546af25071cSRichard Henderson 
2547af25071cSRichard Henderson static TCGv do_rdpc(DisasContext *dc, TCGv dst)
2548af25071cSRichard Henderson {
2549af25071cSRichard Henderson     return tcg_constant_tl(address_mask_i(dc, dc->pc));
2550af25071cSRichard Henderson }
2551af25071cSRichard Henderson 
2552af25071cSRichard Henderson TRANS(RDPC, 64, do_rd_special, true, a->rd, do_rdpc)
2553af25071cSRichard Henderson 
2554af25071cSRichard Henderson static TCGv do_rdfprs(DisasContext *dc, TCGv dst)
2555af25071cSRichard Henderson {
2556af25071cSRichard Henderson     tcg_gen_ext_i32_tl(dst, cpu_fprs);
2557af25071cSRichard Henderson     return dst;
2558af25071cSRichard Henderson }
2559af25071cSRichard Henderson 
2560af25071cSRichard Henderson TRANS(RDFPRS, 64, do_rd_special, true, a->rd, do_rdfprs)
2561af25071cSRichard Henderson 
2562af25071cSRichard Henderson static TCGv do_rdgsr(DisasContext *dc, TCGv dst)
2563af25071cSRichard Henderson {
2564af25071cSRichard Henderson     gen_trap_ifnofpu(dc);
2565af25071cSRichard Henderson     return cpu_gsr;
2566af25071cSRichard Henderson }
2567af25071cSRichard Henderson 
2568af25071cSRichard Henderson TRANS(RDGSR, 64, do_rd_special, true, a->rd, do_rdgsr)
2569af25071cSRichard Henderson 
2570af25071cSRichard Henderson static TCGv do_rdsoftint(DisasContext *dc, TCGv dst)
2571af25071cSRichard Henderson {
2572af25071cSRichard Henderson     tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(softint));
2573af25071cSRichard Henderson     return dst;
2574af25071cSRichard Henderson }
2575af25071cSRichard Henderson 
2576af25071cSRichard Henderson TRANS(RDSOFTINT, 64, do_rd_special, supervisor(dc), a->rd, do_rdsoftint)
2577af25071cSRichard Henderson 
2578af25071cSRichard Henderson static TCGv do_rdtick_cmpr(DisasContext *dc, TCGv dst)
2579af25071cSRichard Henderson {
2580577efa45SRichard Henderson     tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(tick_cmpr));
2581577efa45SRichard Henderson     return dst;
2582af25071cSRichard Henderson }
2583af25071cSRichard Henderson 
2584af25071cSRichard Henderson /* TODO: non-priv access only allowed when enabled. */
2585af25071cSRichard Henderson TRANS(RDTICK_CMPR, 64, do_rd_special, true, a->rd, do_rdtick_cmpr)
2586af25071cSRichard Henderson 
2587af25071cSRichard Henderson static TCGv do_rdstick(DisasContext *dc, TCGv dst)
2588af25071cSRichard Henderson {
2589af25071cSRichard Henderson     TCGv_ptr r_tickptr = tcg_temp_new_ptr();
2590af25071cSRichard Henderson 
2591af25071cSRichard Henderson     tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(stick));
2592af25071cSRichard Henderson     if (translator_io_start(&dc->base)) {
2593af25071cSRichard Henderson         dc->base.is_jmp = DISAS_EXIT;
2594af25071cSRichard Henderson     }
2595af25071cSRichard Henderson     gen_helper_tick_get_count(dst, tcg_env, r_tickptr,
2596af25071cSRichard Henderson                               tcg_constant_i32(dc->mem_idx));
2597af25071cSRichard Henderson     return dst;
2598af25071cSRichard Henderson }
2599af25071cSRichard Henderson 
2600af25071cSRichard Henderson /* TODO: non-priv access only allowed when enabled. */
2601af25071cSRichard Henderson TRANS(RDSTICK, 64, do_rd_special, true, a->rd, do_rdstick)
2602af25071cSRichard Henderson 
2603af25071cSRichard Henderson static TCGv do_rdstick_cmpr(DisasContext *dc, TCGv dst)
2604af25071cSRichard Henderson {
2605577efa45SRichard Henderson     tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(stick_cmpr));
2606577efa45SRichard Henderson     return dst;
2607af25071cSRichard Henderson }
2608af25071cSRichard Henderson 
2609af25071cSRichard Henderson /* TODO: supervisor access only allowed when enabled by hypervisor. */
2610af25071cSRichard Henderson TRANS(RDSTICK_CMPR, 64, do_rd_special, supervisor(dc), a->rd, do_rdstick_cmpr)
2611af25071cSRichard Henderson 
2612af25071cSRichard Henderson /*
2613af25071cSRichard Henderson  * UltraSPARC-T1 Strand status.
2614af25071cSRichard Henderson  * HYPV check maybe not enough, UA2005 & UA2007 describe
2615af25071cSRichard Henderson  * this ASR as impl. dep
2616af25071cSRichard Henderson  */
2617af25071cSRichard Henderson static TCGv do_rdstrand_status(DisasContext *dc, TCGv dst)
2618af25071cSRichard Henderson {
2619af25071cSRichard Henderson     return tcg_constant_tl(1);
2620af25071cSRichard Henderson }
2621af25071cSRichard Henderson 
2622af25071cSRichard Henderson TRANS(RDSTRAND_STATUS, HYPV, do_rd_special, true, a->rd, do_rdstrand_status)
2623af25071cSRichard Henderson 
2624668bb9b7SRichard Henderson static TCGv do_rdpsr(DisasContext *dc, TCGv dst)
2625668bb9b7SRichard Henderson {
2626668bb9b7SRichard Henderson     gen_helper_rdpsr(dst, tcg_env);
2627668bb9b7SRichard Henderson     return dst;
2628668bb9b7SRichard Henderson }
2629668bb9b7SRichard Henderson 
2630668bb9b7SRichard Henderson TRANS(RDPSR, 32, do_rd_special, supervisor(dc), a->rd, do_rdpsr)
2631668bb9b7SRichard Henderson 
2632668bb9b7SRichard Henderson static TCGv do_rdhpstate(DisasContext *dc, TCGv dst)
2633668bb9b7SRichard Henderson {
2634668bb9b7SRichard Henderson     tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hpstate));
2635668bb9b7SRichard Henderson     return dst;
2636668bb9b7SRichard Henderson }
2637668bb9b7SRichard Henderson 
2638668bb9b7SRichard Henderson TRANS(RDHPR_hpstate, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhpstate)
2639668bb9b7SRichard Henderson 
2640668bb9b7SRichard Henderson static TCGv do_rdhtstate(DisasContext *dc, TCGv dst)
2641668bb9b7SRichard Henderson {
2642668bb9b7SRichard Henderson     TCGv_i32 tl = tcg_temp_new_i32();
2643668bb9b7SRichard Henderson     TCGv_ptr tp = tcg_temp_new_ptr();
2644668bb9b7SRichard Henderson 
2645668bb9b7SRichard Henderson     tcg_gen_ld_i32(tl, tcg_env, env64_field_offsetof(tl));
2646668bb9b7SRichard Henderson     tcg_gen_andi_i32(tl, tl, MAXTL_MASK);
2647668bb9b7SRichard Henderson     tcg_gen_shli_i32(tl, tl, 3);
2648668bb9b7SRichard Henderson     tcg_gen_ext_i32_ptr(tp, tl);
2649668bb9b7SRichard Henderson     tcg_gen_add_ptr(tp, tp, tcg_env);
2650668bb9b7SRichard Henderson 
2651668bb9b7SRichard Henderson     tcg_gen_ld_tl(dst, tp, env64_field_offsetof(htstate));
2652668bb9b7SRichard Henderson     return dst;
2653668bb9b7SRichard Henderson }
2654668bb9b7SRichard Henderson 
2655668bb9b7SRichard Henderson TRANS(RDHPR_htstate, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhtstate)
2656668bb9b7SRichard Henderson 
2657668bb9b7SRichard Henderson static TCGv do_rdhintp(DisasContext *dc, TCGv dst)
2658668bb9b7SRichard Henderson {
26592da789deSRichard Henderson     tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hintp));
26602da789deSRichard Henderson     return dst;
2661668bb9b7SRichard Henderson }
2662668bb9b7SRichard Henderson 
2663668bb9b7SRichard Henderson TRANS(RDHPR_hintp, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhintp)
2664668bb9b7SRichard Henderson 
2665668bb9b7SRichard Henderson static TCGv do_rdhtba(DisasContext *dc, TCGv dst)
2666668bb9b7SRichard Henderson {
26672da789deSRichard Henderson     tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(htba));
26682da789deSRichard Henderson     return dst;
2669668bb9b7SRichard Henderson }
2670668bb9b7SRichard Henderson 
2671668bb9b7SRichard Henderson TRANS(RDHPR_htba, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhtba)
2672668bb9b7SRichard Henderson 
2673668bb9b7SRichard Henderson static TCGv do_rdhver(DisasContext *dc, TCGv dst)
2674668bb9b7SRichard Henderson {
26752da789deSRichard Henderson     tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hver));
26762da789deSRichard Henderson     return dst;
2677668bb9b7SRichard Henderson }
2678668bb9b7SRichard Henderson 
2679668bb9b7SRichard Henderson TRANS(RDHPR_hver, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhver)
2680668bb9b7SRichard Henderson 
2681668bb9b7SRichard Henderson static TCGv do_rdhstick_cmpr(DisasContext *dc, TCGv dst)
2682668bb9b7SRichard Henderson {
2683577efa45SRichard Henderson     tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hstick_cmpr));
2684577efa45SRichard Henderson     return dst;
2685668bb9b7SRichard Henderson }
2686668bb9b7SRichard Henderson 
2687668bb9b7SRichard Henderson TRANS(RDHPR_hstick_cmpr, HYPV, do_rd_special, hypervisor(dc), a->rd,
2688668bb9b7SRichard Henderson       do_rdhstick_cmpr)
2689668bb9b7SRichard Henderson 
26905d617bfbSRichard Henderson static TCGv do_rdwim(DisasContext *dc, TCGv dst)
26915d617bfbSRichard Henderson {
2692cd6269f7SRichard Henderson     tcg_gen_ld_tl(dst, tcg_env, env32_field_offsetof(wim));
2693cd6269f7SRichard Henderson     return dst;
26945d617bfbSRichard Henderson }
26955d617bfbSRichard Henderson 
26965d617bfbSRichard Henderson TRANS(RDWIM, 32, do_rd_special, supervisor(dc), a->rd, do_rdwim)
26975d617bfbSRichard Henderson 
26985d617bfbSRichard Henderson static TCGv do_rdtpc(DisasContext *dc, TCGv dst)
26995d617bfbSRichard Henderson {
27005d617bfbSRichard Henderson #ifdef TARGET_SPARC64
27015d617bfbSRichard Henderson     TCGv_ptr r_tsptr = tcg_temp_new_ptr();
27025d617bfbSRichard Henderson 
27035d617bfbSRichard Henderson     gen_load_trap_state_at_tl(r_tsptr);
27045d617bfbSRichard Henderson     tcg_gen_ld_tl(dst, r_tsptr, offsetof(trap_state, tpc));
27055d617bfbSRichard Henderson     return dst;
27065d617bfbSRichard Henderson #else
27075d617bfbSRichard Henderson     qemu_build_not_reached();
27085d617bfbSRichard Henderson #endif
27095d617bfbSRichard Henderson }
27105d617bfbSRichard Henderson 
27115d617bfbSRichard Henderson TRANS(RDPR_tpc, 64, do_rd_special, supervisor(dc), a->rd, do_rdtpc)
27125d617bfbSRichard Henderson 
27135d617bfbSRichard Henderson static TCGv do_rdtnpc(DisasContext *dc, TCGv dst)
27145d617bfbSRichard Henderson {
27155d617bfbSRichard Henderson #ifdef TARGET_SPARC64
27165d617bfbSRichard Henderson     TCGv_ptr r_tsptr = tcg_temp_new_ptr();
27175d617bfbSRichard Henderson 
27185d617bfbSRichard Henderson     gen_load_trap_state_at_tl(r_tsptr);
27195d617bfbSRichard Henderson     tcg_gen_ld_tl(dst, r_tsptr, offsetof(trap_state, tnpc));
27205d617bfbSRichard Henderson     return dst;
27215d617bfbSRichard Henderson #else
27225d617bfbSRichard Henderson     qemu_build_not_reached();
27235d617bfbSRichard Henderson #endif
27245d617bfbSRichard Henderson }
27255d617bfbSRichard Henderson 
27265d617bfbSRichard Henderson TRANS(RDPR_tnpc, 64, do_rd_special, supervisor(dc), a->rd, do_rdtnpc)
27275d617bfbSRichard Henderson 
27285d617bfbSRichard Henderson static TCGv do_rdtstate(DisasContext *dc, TCGv dst)
27295d617bfbSRichard Henderson {
27305d617bfbSRichard Henderson #ifdef TARGET_SPARC64
27315d617bfbSRichard Henderson     TCGv_ptr r_tsptr = tcg_temp_new_ptr();
27325d617bfbSRichard Henderson 
27335d617bfbSRichard Henderson     gen_load_trap_state_at_tl(r_tsptr);
27345d617bfbSRichard Henderson     tcg_gen_ld_tl(dst, r_tsptr, offsetof(trap_state, tstate));
27355d617bfbSRichard Henderson     return dst;
27365d617bfbSRichard Henderson #else
27375d617bfbSRichard Henderson     qemu_build_not_reached();
27385d617bfbSRichard Henderson #endif
27395d617bfbSRichard Henderson }
27405d617bfbSRichard Henderson 
27415d617bfbSRichard Henderson TRANS(RDPR_tstate, 64, do_rd_special, supervisor(dc), a->rd, do_rdtstate)
27425d617bfbSRichard Henderson 
27435d617bfbSRichard Henderson static TCGv do_rdtt(DisasContext *dc, TCGv dst)
27445d617bfbSRichard Henderson {
27455d617bfbSRichard Henderson #ifdef TARGET_SPARC64
27465d617bfbSRichard Henderson     TCGv_ptr r_tsptr = tcg_temp_new_ptr();
27475d617bfbSRichard Henderson 
27485d617bfbSRichard Henderson     gen_load_trap_state_at_tl(r_tsptr);
27495d617bfbSRichard Henderson     tcg_gen_ld32s_tl(dst, r_tsptr, offsetof(trap_state, tt));
27505d617bfbSRichard Henderson     return dst;
27515d617bfbSRichard Henderson #else
27525d617bfbSRichard Henderson     qemu_build_not_reached();
27535d617bfbSRichard Henderson #endif
27545d617bfbSRichard Henderson }
27555d617bfbSRichard Henderson 
27565d617bfbSRichard Henderson TRANS(RDPR_tt, 64, do_rd_special, supervisor(dc), a->rd, do_rdtt)
27575d617bfbSRichard Henderson TRANS(RDPR_tick, 64, do_rd_special, supervisor(dc), a->rd, do_rdtick)
27585d617bfbSRichard Henderson 
27595d617bfbSRichard Henderson static TCGv do_rdtba(DisasContext *dc, TCGv dst)
27605d617bfbSRichard Henderson {
27615d617bfbSRichard Henderson     return cpu_tbr;
27625d617bfbSRichard Henderson }
27635d617bfbSRichard Henderson 
2764e8325dc0SRichard Henderson TRANS(RDTBR, 32, do_rd_special, supervisor(dc), a->rd, do_rdtba)
27655d617bfbSRichard Henderson TRANS(RDPR_tba, 64, do_rd_special, supervisor(dc), a->rd, do_rdtba)
27665d617bfbSRichard Henderson 
27675d617bfbSRichard Henderson static TCGv do_rdpstate(DisasContext *dc, TCGv dst)
27685d617bfbSRichard Henderson {
27695d617bfbSRichard Henderson     tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(pstate));
27705d617bfbSRichard Henderson     return dst;
27715d617bfbSRichard Henderson }
27725d617bfbSRichard Henderson 
27735d617bfbSRichard Henderson TRANS(RDPR_pstate, 64, do_rd_special, supervisor(dc), a->rd, do_rdpstate)
27745d617bfbSRichard Henderson 
27755d617bfbSRichard Henderson static TCGv do_rdtl(DisasContext *dc, TCGv dst)
27765d617bfbSRichard Henderson {
27775d617bfbSRichard Henderson     tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(tl));
27785d617bfbSRichard Henderson     return dst;
27795d617bfbSRichard Henderson }
27805d617bfbSRichard Henderson 
27815d617bfbSRichard Henderson TRANS(RDPR_tl, 64, do_rd_special, supervisor(dc), a->rd, do_rdtl)
27825d617bfbSRichard Henderson 
27835d617bfbSRichard Henderson static TCGv do_rdpil(DisasContext *dc, TCGv dst)
27845d617bfbSRichard Henderson {
27855d617bfbSRichard Henderson     tcg_gen_ld32s_tl(dst, tcg_env, env_field_offsetof(psrpil));
27865d617bfbSRichard Henderson     return dst;
27875d617bfbSRichard Henderson }
27885d617bfbSRichard Henderson 
27895d617bfbSRichard Henderson TRANS(RDPR_pil, 64, do_rd_special, supervisor(dc), a->rd, do_rdpil)
27905d617bfbSRichard Henderson 
27915d617bfbSRichard Henderson static TCGv do_rdcwp(DisasContext *dc, TCGv dst)
27925d617bfbSRichard Henderson {
27935d617bfbSRichard Henderson     gen_helper_rdcwp(dst, tcg_env);
27945d617bfbSRichard Henderson     return dst;
27955d617bfbSRichard Henderson }
27965d617bfbSRichard Henderson 
27975d617bfbSRichard Henderson TRANS(RDPR_cwp, 64, do_rd_special, supervisor(dc), a->rd, do_rdcwp)
27985d617bfbSRichard Henderson 
27995d617bfbSRichard Henderson static TCGv do_rdcansave(DisasContext *dc, TCGv dst)
28005d617bfbSRichard Henderson {
28015d617bfbSRichard Henderson     tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(cansave));
28025d617bfbSRichard Henderson     return dst;
28035d617bfbSRichard Henderson }
28045d617bfbSRichard Henderson 
28055d617bfbSRichard Henderson TRANS(RDPR_cansave, 64, do_rd_special, supervisor(dc), a->rd, do_rdcansave)
28065d617bfbSRichard Henderson 
28075d617bfbSRichard Henderson static TCGv do_rdcanrestore(DisasContext *dc, TCGv dst)
28085d617bfbSRichard Henderson {
28095d617bfbSRichard Henderson     tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(canrestore));
28105d617bfbSRichard Henderson     return dst;
28115d617bfbSRichard Henderson }
28125d617bfbSRichard Henderson 
28135d617bfbSRichard Henderson TRANS(RDPR_canrestore, 64, do_rd_special, supervisor(dc), a->rd,
28145d617bfbSRichard Henderson       do_rdcanrestore)
28155d617bfbSRichard Henderson 
28165d617bfbSRichard Henderson static TCGv do_rdcleanwin(DisasContext *dc, TCGv dst)
28175d617bfbSRichard Henderson {
28185d617bfbSRichard Henderson     tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(cleanwin));
28195d617bfbSRichard Henderson     return dst;
28205d617bfbSRichard Henderson }
28215d617bfbSRichard Henderson 
28225d617bfbSRichard Henderson TRANS(RDPR_cleanwin, 64, do_rd_special, supervisor(dc), a->rd, do_rdcleanwin)
28235d617bfbSRichard Henderson 
28245d617bfbSRichard Henderson static TCGv do_rdotherwin(DisasContext *dc, TCGv dst)
28255d617bfbSRichard Henderson {
28265d617bfbSRichard Henderson     tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(otherwin));
28275d617bfbSRichard Henderson     return dst;
28285d617bfbSRichard Henderson }
28295d617bfbSRichard Henderson 
28305d617bfbSRichard Henderson TRANS(RDPR_otherwin, 64, do_rd_special, supervisor(dc), a->rd, do_rdotherwin)
28315d617bfbSRichard Henderson 
28325d617bfbSRichard Henderson static TCGv do_rdwstate(DisasContext *dc, TCGv dst)
28335d617bfbSRichard Henderson {
28345d617bfbSRichard Henderson     tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(wstate));
28355d617bfbSRichard Henderson     return dst;
28365d617bfbSRichard Henderson }
28375d617bfbSRichard Henderson 
28385d617bfbSRichard Henderson TRANS(RDPR_wstate, 64, do_rd_special, supervisor(dc), a->rd, do_rdwstate)
28395d617bfbSRichard Henderson 
28405d617bfbSRichard Henderson static TCGv do_rdgl(DisasContext *dc, TCGv dst)
28415d617bfbSRichard Henderson {
28425d617bfbSRichard Henderson     tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(gl));
28435d617bfbSRichard Henderson     return dst;
28445d617bfbSRichard Henderson }
28455d617bfbSRichard Henderson 
28465d617bfbSRichard Henderson TRANS(RDPR_gl, GL, do_rd_special, supervisor(dc), a->rd, do_rdgl)
28475d617bfbSRichard Henderson 
28485d617bfbSRichard Henderson /* UA2005 strand status */
28495d617bfbSRichard Henderson static TCGv do_rdssr(DisasContext *dc, TCGv dst)
28505d617bfbSRichard Henderson {
28512da789deSRichard Henderson     tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(ssr));
28522da789deSRichard Henderson     return dst;
28535d617bfbSRichard Henderson }
28545d617bfbSRichard Henderson 
28555d617bfbSRichard Henderson TRANS(RDPR_strand_status, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdssr)
28565d617bfbSRichard Henderson 
28575d617bfbSRichard Henderson static TCGv do_rdver(DisasContext *dc, TCGv dst)
28585d617bfbSRichard Henderson {
28592da789deSRichard Henderson     tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(version));
28602da789deSRichard Henderson     return dst;
28615d617bfbSRichard Henderson }
28625d617bfbSRichard Henderson 
28635d617bfbSRichard Henderson TRANS(RDPR_ver, 64, do_rd_special, supervisor(dc), a->rd, do_rdver)
28645d617bfbSRichard Henderson 
2865e8325dc0SRichard Henderson static bool trans_FLUSHW(DisasContext *dc, arg_FLUSHW *a)
2866e8325dc0SRichard Henderson {
2867e8325dc0SRichard Henderson     if (avail_64(dc)) {
2868e8325dc0SRichard Henderson         gen_helper_flushw(tcg_env);
2869e8325dc0SRichard Henderson         return advance_pc(dc);
2870e8325dc0SRichard Henderson     }
2871e8325dc0SRichard Henderson     return false;
2872e8325dc0SRichard Henderson }
2873e8325dc0SRichard Henderson 
28740faef01bSRichard Henderson static bool do_wr_special(DisasContext *dc, arg_r_r_ri *a, bool priv,
28750faef01bSRichard Henderson                           void (*func)(DisasContext *, TCGv))
28760faef01bSRichard Henderson {
28770faef01bSRichard Henderson     TCGv src;
28780faef01bSRichard Henderson 
28790faef01bSRichard Henderson     /* For simplicity, we under-decoded the rs2 form. */
28800faef01bSRichard Henderson     if (!a->imm && (a->rs2_or_imm & ~0x1f)) {
28810faef01bSRichard Henderson         return false;
28820faef01bSRichard Henderson     }
28830faef01bSRichard Henderson     if (!priv) {
28840faef01bSRichard Henderson         return raise_priv(dc);
28850faef01bSRichard Henderson     }
28860faef01bSRichard Henderson 
28870faef01bSRichard Henderson     if (a->rs1 == 0 && (a->imm || a->rs2_or_imm == 0)) {
28880faef01bSRichard Henderson         src = tcg_constant_tl(a->rs2_or_imm);
28890faef01bSRichard Henderson     } else {
28900faef01bSRichard Henderson         TCGv src1 = gen_load_gpr(dc, a->rs1);
28910faef01bSRichard Henderson         if (a->rs2_or_imm == 0) {
28920faef01bSRichard Henderson             src = src1;
28930faef01bSRichard Henderson         } else {
28940faef01bSRichard Henderson             src = tcg_temp_new();
28950faef01bSRichard Henderson             if (a->imm) {
28960faef01bSRichard Henderson                 tcg_gen_xori_tl(src, src1, a->rs2_or_imm);
28970faef01bSRichard Henderson             } else {
28980faef01bSRichard Henderson                 tcg_gen_xor_tl(src, src1, gen_load_gpr(dc, a->rs2_or_imm));
28990faef01bSRichard Henderson             }
29000faef01bSRichard Henderson         }
29010faef01bSRichard Henderson     }
29020faef01bSRichard Henderson     func(dc, src);
29030faef01bSRichard Henderson     return advance_pc(dc);
29040faef01bSRichard Henderson }
29050faef01bSRichard Henderson 
29060faef01bSRichard Henderson static void do_wry(DisasContext *dc, TCGv src)
29070faef01bSRichard Henderson {
29080faef01bSRichard Henderson     tcg_gen_ext32u_tl(cpu_y, src);
29090faef01bSRichard Henderson }
29100faef01bSRichard Henderson 
29110faef01bSRichard Henderson TRANS(WRY, ALL, do_wr_special, a, true, do_wry)
29120faef01bSRichard Henderson 
29130faef01bSRichard Henderson static void do_wrccr(DisasContext *dc, TCGv src)
29140faef01bSRichard Henderson {
29150faef01bSRichard Henderson     gen_helper_wrccr(tcg_env, src);
29160faef01bSRichard Henderson }
29170faef01bSRichard Henderson 
29180faef01bSRichard Henderson TRANS(WRCCR, 64, do_wr_special, a, true, do_wrccr)
29190faef01bSRichard Henderson 
29200faef01bSRichard Henderson static void do_wrasi(DisasContext *dc, TCGv src)
29210faef01bSRichard Henderson {
29220faef01bSRichard Henderson     TCGv tmp = tcg_temp_new();
29230faef01bSRichard Henderson 
29240faef01bSRichard Henderson     tcg_gen_ext8u_tl(tmp, src);
29250faef01bSRichard Henderson     tcg_gen_st32_tl(tmp, tcg_env, env64_field_offsetof(asi));
29260faef01bSRichard Henderson     /* End TB to notice changed ASI. */
29270faef01bSRichard Henderson     dc->base.is_jmp = DISAS_EXIT;
29280faef01bSRichard Henderson }
29290faef01bSRichard Henderson 
29300faef01bSRichard Henderson TRANS(WRASI, 64, do_wr_special, a, true, do_wrasi)
29310faef01bSRichard Henderson 
29320faef01bSRichard Henderson static void do_wrfprs(DisasContext *dc, TCGv src)
29330faef01bSRichard Henderson {
29340faef01bSRichard Henderson #ifdef TARGET_SPARC64
29350faef01bSRichard Henderson     tcg_gen_trunc_tl_i32(cpu_fprs, src);
29360faef01bSRichard Henderson     dc->fprs_dirty = 0;
29370faef01bSRichard Henderson     dc->base.is_jmp = DISAS_EXIT;
29380faef01bSRichard Henderson #else
29390faef01bSRichard Henderson     qemu_build_not_reached();
29400faef01bSRichard Henderson #endif
29410faef01bSRichard Henderson }
29420faef01bSRichard Henderson 
29430faef01bSRichard Henderson TRANS(WRFPRS, 64, do_wr_special, a, true, do_wrfprs)
29440faef01bSRichard Henderson 
29450faef01bSRichard Henderson static void do_wrgsr(DisasContext *dc, TCGv src)
29460faef01bSRichard Henderson {
29470faef01bSRichard Henderson     gen_trap_ifnofpu(dc);
29480faef01bSRichard Henderson     tcg_gen_mov_tl(cpu_gsr, src);
29490faef01bSRichard Henderson }
29500faef01bSRichard Henderson 
29510faef01bSRichard Henderson TRANS(WRGSR, 64, do_wr_special, a, true, do_wrgsr)
29520faef01bSRichard Henderson 
29530faef01bSRichard Henderson static void do_wrsoftint_set(DisasContext *dc, TCGv src)
29540faef01bSRichard Henderson {
29550faef01bSRichard Henderson     gen_helper_set_softint(tcg_env, src);
29560faef01bSRichard Henderson }
29570faef01bSRichard Henderson 
29580faef01bSRichard Henderson TRANS(WRSOFTINT_SET, 64, do_wr_special, a, supervisor(dc), do_wrsoftint_set)
29590faef01bSRichard Henderson 
29600faef01bSRichard Henderson static void do_wrsoftint_clr(DisasContext *dc, TCGv src)
29610faef01bSRichard Henderson {
29620faef01bSRichard Henderson     gen_helper_clear_softint(tcg_env, src);
29630faef01bSRichard Henderson }
29640faef01bSRichard Henderson 
29650faef01bSRichard Henderson TRANS(WRSOFTINT_CLR, 64, do_wr_special, a, supervisor(dc), do_wrsoftint_clr)
29660faef01bSRichard Henderson 
29670faef01bSRichard Henderson static void do_wrsoftint(DisasContext *dc, TCGv src)
29680faef01bSRichard Henderson {
29690faef01bSRichard Henderson     gen_helper_write_softint(tcg_env, src);
29700faef01bSRichard Henderson }
29710faef01bSRichard Henderson 
29720faef01bSRichard Henderson TRANS(WRSOFTINT, 64, do_wr_special, a, supervisor(dc), do_wrsoftint)
29730faef01bSRichard Henderson 
29740faef01bSRichard Henderson static void do_wrtick_cmpr(DisasContext *dc, TCGv src)
29750faef01bSRichard Henderson {
29760faef01bSRichard Henderson     TCGv_ptr r_tickptr = tcg_temp_new_ptr();
29770faef01bSRichard Henderson 
2978577efa45SRichard Henderson     tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(tick_cmpr));
2979577efa45SRichard Henderson     tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(tick));
29800faef01bSRichard Henderson     translator_io_start(&dc->base);
2981577efa45SRichard Henderson     gen_helper_tick_set_limit(r_tickptr, src);
29820faef01bSRichard Henderson     /* End TB to handle timer interrupt */
29830faef01bSRichard Henderson     dc->base.is_jmp = DISAS_EXIT;
29840faef01bSRichard Henderson }
29850faef01bSRichard Henderson 
29860faef01bSRichard Henderson TRANS(WRTICK_CMPR, 64, do_wr_special, a, supervisor(dc), do_wrtick_cmpr)
29870faef01bSRichard Henderson 
29880faef01bSRichard Henderson static void do_wrstick(DisasContext *dc, TCGv src)
29890faef01bSRichard Henderson {
29900faef01bSRichard Henderson #ifdef TARGET_SPARC64
29910faef01bSRichard Henderson     TCGv_ptr r_tickptr = tcg_temp_new_ptr();
29920faef01bSRichard Henderson 
29930faef01bSRichard Henderson     tcg_gen_ld_ptr(r_tickptr, tcg_env, offsetof(CPUSPARCState, stick));
29940faef01bSRichard Henderson     translator_io_start(&dc->base);
29950faef01bSRichard Henderson     gen_helper_tick_set_count(r_tickptr, src);
29960faef01bSRichard Henderson     /* End TB to handle timer interrupt */
29970faef01bSRichard Henderson     dc->base.is_jmp = DISAS_EXIT;
29980faef01bSRichard Henderson #else
29990faef01bSRichard Henderson     qemu_build_not_reached();
30000faef01bSRichard Henderson #endif
30010faef01bSRichard Henderson }
30020faef01bSRichard Henderson 
30030faef01bSRichard Henderson TRANS(WRSTICK, 64, do_wr_special, a, supervisor(dc), do_wrstick)
30040faef01bSRichard Henderson 
30050faef01bSRichard Henderson static void do_wrstick_cmpr(DisasContext *dc, TCGv src)
30060faef01bSRichard Henderson {
30070faef01bSRichard Henderson     TCGv_ptr r_tickptr = tcg_temp_new_ptr();
30080faef01bSRichard Henderson 
3009577efa45SRichard Henderson     tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(stick_cmpr));
3010577efa45SRichard Henderson     tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(stick));
30110faef01bSRichard Henderson     translator_io_start(&dc->base);
3012577efa45SRichard Henderson     gen_helper_tick_set_limit(r_tickptr, src);
30130faef01bSRichard Henderson     /* End TB to handle timer interrupt */
30140faef01bSRichard Henderson     dc->base.is_jmp = DISAS_EXIT;
30150faef01bSRichard Henderson }
30160faef01bSRichard Henderson 
30170faef01bSRichard Henderson TRANS(WRSTICK_CMPR, 64, do_wr_special, a, supervisor(dc), do_wrstick_cmpr)
30180faef01bSRichard Henderson 
30190faef01bSRichard Henderson static void do_wrpowerdown(DisasContext *dc, TCGv src)
30200faef01bSRichard Henderson {
302189527e3aSRichard Henderson     finishing_insn(dc);
30220faef01bSRichard Henderson     save_state(dc);
30230faef01bSRichard Henderson     gen_helper_power_down(tcg_env);
30240faef01bSRichard Henderson }
30250faef01bSRichard Henderson 
30260faef01bSRichard Henderson TRANS(WRPOWERDOWN, POWERDOWN, do_wr_special, a, supervisor(dc), do_wrpowerdown)
30270faef01bSRichard Henderson 
302825524734SRichard Henderson static void do_wrpsr(DisasContext *dc, TCGv src)
302925524734SRichard Henderson {
303025524734SRichard Henderson     gen_helper_wrpsr(tcg_env, src);
303125524734SRichard Henderson     dc->base.is_jmp = DISAS_EXIT;
303225524734SRichard Henderson }
303325524734SRichard Henderson 
303425524734SRichard Henderson TRANS(WRPSR, 32, do_wr_special, a, supervisor(dc), do_wrpsr)
303525524734SRichard Henderson 
30369422278eSRichard Henderson static void do_wrwim(DisasContext *dc, TCGv src)
30379422278eSRichard Henderson {
30389422278eSRichard Henderson     target_ulong mask = MAKE_64BIT_MASK(0, dc->def->nwindows);
3039cd6269f7SRichard Henderson     TCGv tmp = tcg_temp_new();
3040cd6269f7SRichard Henderson 
3041cd6269f7SRichard Henderson     tcg_gen_andi_tl(tmp, src, mask);
3042cd6269f7SRichard Henderson     tcg_gen_st_tl(tmp, tcg_env, env32_field_offsetof(wim));
30439422278eSRichard Henderson }
30449422278eSRichard Henderson 
30459422278eSRichard Henderson TRANS(WRWIM, 32, do_wr_special, a, supervisor(dc), do_wrwim)
30469422278eSRichard Henderson 
30479422278eSRichard Henderson static void do_wrtpc(DisasContext *dc, TCGv src)
30489422278eSRichard Henderson {
30499422278eSRichard Henderson #ifdef TARGET_SPARC64
30509422278eSRichard Henderson     TCGv_ptr r_tsptr = tcg_temp_new_ptr();
30519422278eSRichard Henderson 
30529422278eSRichard Henderson     gen_load_trap_state_at_tl(r_tsptr);
30539422278eSRichard Henderson     tcg_gen_st_tl(src, r_tsptr, offsetof(trap_state, tpc));
30549422278eSRichard Henderson #else
30559422278eSRichard Henderson     qemu_build_not_reached();
30569422278eSRichard Henderson #endif
30579422278eSRichard Henderson }
30589422278eSRichard Henderson 
30599422278eSRichard Henderson TRANS(WRPR_tpc, 64, do_wr_special, a, supervisor(dc), do_wrtpc)
30609422278eSRichard Henderson 
30619422278eSRichard Henderson static void do_wrtnpc(DisasContext *dc, TCGv src)
30629422278eSRichard Henderson {
30639422278eSRichard Henderson #ifdef TARGET_SPARC64
30649422278eSRichard Henderson     TCGv_ptr r_tsptr = tcg_temp_new_ptr();
30659422278eSRichard Henderson 
30669422278eSRichard Henderson     gen_load_trap_state_at_tl(r_tsptr);
30679422278eSRichard Henderson     tcg_gen_st_tl(src, r_tsptr, offsetof(trap_state, tnpc));
30689422278eSRichard Henderson #else
30699422278eSRichard Henderson     qemu_build_not_reached();
30709422278eSRichard Henderson #endif
30719422278eSRichard Henderson }
30729422278eSRichard Henderson 
30739422278eSRichard Henderson TRANS(WRPR_tnpc, 64, do_wr_special, a, supervisor(dc), do_wrtnpc)
30749422278eSRichard Henderson 
30759422278eSRichard Henderson static void do_wrtstate(DisasContext *dc, TCGv src)
30769422278eSRichard Henderson {
30779422278eSRichard Henderson #ifdef TARGET_SPARC64
30789422278eSRichard Henderson     TCGv_ptr r_tsptr = tcg_temp_new_ptr();
30799422278eSRichard Henderson 
30809422278eSRichard Henderson     gen_load_trap_state_at_tl(r_tsptr);
30819422278eSRichard Henderson     tcg_gen_st_tl(src, r_tsptr, offsetof(trap_state, tstate));
30829422278eSRichard Henderson #else
30839422278eSRichard Henderson     qemu_build_not_reached();
30849422278eSRichard Henderson #endif
30859422278eSRichard Henderson }
30869422278eSRichard Henderson 
30879422278eSRichard Henderson TRANS(WRPR_tstate, 64, do_wr_special, a, supervisor(dc), do_wrtstate)
30889422278eSRichard Henderson 
30899422278eSRichard Henderson static void do_wrtt(DisasContext *dc, TCGv src)
30909422278eSRichard Henderson {
30919422278eSRichard Henderson #ifdef TARGET_SPARC64
30929422278eSRichard Henderson     TCGv_ptr r_tsptr = tcg_temp_new_ptr();
30939422278eSRichard Henderson 
30949422278eSRichard Henderson     gen_load_trap_state_at_tl(r_tsptr);
30959422278eSRichard Henderson     tcg_gen_st32_tl(src, r_tsptr, offsetof(trap_state, tt));
30969422278eSRichard Henderson #else
30979422278eSRichard Henderson     qemu_build_not_reached();
30989422278eSRichard Henderson #endif
30999422278eSRichard Henderson }
31009422278eSRichard Henderson 
31019422278eSRichard Henderson TRANS(WRPR_tt, 64, do_wr_special, a, supervisor(dc), do_wrtt)
31029422278eSRichard Henderson 
31039422278eSRichard Henderson static void do_wrtick(DisasContext *dc, TCGv src)
31049422278eSRichard Henderson {
31059422278eSRichard Henderson     TCGv_ptr r_tickptr = tcg_temp_new_ptr();
31069422278eSRichard Henderson 
31079422278eSRichard Henderson     tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(tick));
31089422278eSRichard Henderson     translator_io_start(&dc->base);
31099422278eSRichard Henderson     gen_helper_tick_set_count(r_tickptr, src);
31109422278eSRichard Henderson     /* End TB to handle timer interrupt */
31119422278eSRichard Henderson     dc->base.is_jmp = DISAS_EXIT;
31129422278eSRichard Henderson }
31139422278eSRichard Henderson 
31149422278eSRichard Henderson TRANS(WRPR_tick, 64, do_wr_special, a, supervisor(dc), do_wrtick)
31159422278eSRichard Henderson 
31169422278eSRichard Henderson static void do_wrtba(DisasContext *dc, TCGv src)
31179422278eSRichard Henderson {
31189422278eSRichard Henderson     tcg_gen_mov_tl(cpu_tbr, src);
31199422278eSRichard Henderson }
31209422278eSRichard Henderson 
31219422278eSRichard Henderson TRANS(WRPR_tba, 64, do_wr_special, a, supervisor(dc), do_wrtba)
31229422278eSRichard Henderson 
31239422278eSRichard Henderson static void do_wrpstate(DisasContext *dc, TCGv src)
31249422278eSRichard Henderson {
31259422278eSRichard Henderson     save_state(dc);
31269422278eSRichard Henderson     if (translator_io_start(&dc->base)) {
31279422278eSRichard Henderson         dc->base.is_jmp = DISAS_EXIT;
31289422278eSRichard Henderson     }
31299422278eSRichard Henderson     gen_helper_wrpstate(tcg_env, src);
31309422278eSRichard Henderson     dc->npc = DYNAMIC_PC;
31319422278eSRichard Henderson }
31329422278eSRichard Henderson 
31339422278eSRichard Henderson TRANS(WRPR_pstate, 64, do_wr_special, a, supervisor(dc), do_wrpstate)
31349422278eSRichard Henderson 
31359422278eSRichard Henderson static void do_wrtl(DisasContext *dc, TCGv src)
31369422278eSRichard Henderson {
31379422278eSRichard Henderson     save_state(dc);
31389422278eSRichard Henderson     tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(tl));
31399422278eSRichard Henderson     dc->npc = DYNAMIC_PC;
31409422278eSRichard Henderson }
31419422278eSRichard Henderson 
31429422278eSRichard Henderson TRANS(WRPR_tl, 64, do_wr_special, a, supervisor(dc), do_wrtl)
31439422278eSRichard Henderson 
31449422278eSRichard Henderson static void do_wrpil(DisasContext *dc, TCGv src)
31459422278eSRichard Henderson {
31469422278eSRichard Henderson     if (translator_io_start(&dc->base)) {
31479422278eSRichard Henderson         dc->base.is_jmp = DISAS_EXIT;
31489422278eSRichard Henderson     }
31499422278eSRichard Henderson     gen_helper_wrpil(tcg_env, src);
31509422278eSRichard Henderson }
31519422278eSRichard Henderson 
31529422278eSRichard Henderson TRANS(WRPR_pil, 64, do_wr_special, a, supervisor(dc), do_wrpil)
31539422278eSRichard Henderson 
31549422278eSRichard Henderson static void do_wrcwp(DisasContext *dc, TCGv src)
31559422278eSRichard Henderson {
31569422278eSRichard Henderson     gen_helper_wrcwp(tcg_env, src);
31579422278eSRichard Henderson }
31589422278eSRichard Henderson 
31599422278eSRichard Henderson TRANS(WRPR_cwp, 64, do_wr_special, a, supervisor(dc), do_wrcwp)
31609422278eSRichard Henderson 
31619422278eSRichard Henderson static void do_wrcansave(DisasContext *dc, TCGv src)
31629422278eSRichard Henderson {
31639422278eSRichard Henderson     tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(cansave));
31649422278eSRichard Henderson }
31659422278eSRichard Henderson 
31669422278eSRichard Henderson TRANS(WRPR_cansave, 64, do_wr_special, a, supervisor(dc), do_wrcansave)
31679422278eSRichard Henderson 
31689422278eSRichard Henderson static void do_wrcanrestore(DisasContext *dc, TCGv src)
31699422278eSRichard Henderson {
31709422278eSRichard Henderson     tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(canrestore));
31719422278eSRichard Henderson }
31729422278eSRichard Henderson 
31739422278eSRichard Henderson TRANS(WRPR_canrestore, 64, do_wr_special, a, supervisor(dc), do_wrcanrestore)
31749422278eSRichard Henderson 
31759422278eSRichard Henderson static void do_wrcleanwin(DisasContext *dc, TCGv src)
31769422278eSRichard Henderson {
31779422278eSRichard Henderson     tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(cleanwin));
31789422278eSRichard Henderson }
31799422278eSRichard Henderson 
31809422278eSRichard Henderson TRANS(WRPR_cleanwin, 64, do_wr_special, a, supervisor(dc), do_wrcleanwin)
31819422278eSRichard Henderson 
31829422278eSRichard Henderson static void do_wrotherwin(DisasContext *dc, TCGv src)
31839422278eSRichard Henderson {
31849422278eSRichard Henderson     tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(otherwin));
31859422278eSRichard Henderson }
31869422278eSRichard Henderson 
31879422278eSRichard Henderson TRANS(WRPR_otherwin, 64, do_wr_special, a, supervisor(dc), do_wrotherwin)
31889422278eSRichard Henderson 
31899422278eSRichard Henderson static void do_wrwstate(DisasContext *dc, TCGv src)
31909422278eSRichard Henderson {
31919422278eSRichard Henderson     tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(wstate));
31929422278eSRichard Henderson }
31939422278eSRichard Henderson 
31949422278eSRichard Henderson TRANS(WRPR_wstate, 64, do_wr_special, a, supervisor(dc), do_wrwstate)
31959422278eSRichard Henderson 
31969422278eSRichard Henderson static void do_wrgl(DisasContext *dc, TCGv src)
31979422278eSRichard Henderson {
31989422278eSRichard Henderson     gen_helper_wrgl(tcg_env, src);
31999422278eSRichard Henderson }
32009422278eSRichard Henderson 
32019422278eSRichard Henderson TRANS(WRPR_gl, GL, do_wr_special, a, supervisor(dc), do_wrgl)
32029422278eSRichard Henderson 
32039422278eSRichard Henderson /* UA2005 strand status */
32049422278eSRichard Henderson static void do_wrssr(DisasContext *dc, TCGv src)
32059422278eSRichard Henderson {
32062da789deSRichard Henderson     tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(ssr));
32079422278eSRichard Henderson }
32089422278eSRichard Henderson 
32099422278eSRichard Henderson TRANS(WRPR_strand_status, HYPV, do_wr_special, a, hypervisor(dc), do_wrssr)
32109422278eSRichard Henderson 
3211bb97f2f5SRichard Henderson TRANS(WRTBR, 32, do_wr_special, a, supervisor(dc), do_wrtba)
3212bb97f2f5SRichard Henderson 
3213bb97f2f5SRichard Henderson static void do_wrhpstate(DisasContext *dc, TCGv src)
3214bb97f2f5SRichard Henderson {
3215bb97f2f5SRichard Henderson     tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(hpstate));
3216bb97f2f5SRichard Henderson     dc->base.is_jmp = DISAS_EXIT;
3217bb97f2f5SRichard Henderson }
3218bb97f2f5SRichard Henderson 
3219bb97f2f5SRichard Henderson TRANS(WRHPR_hpstate, HYPV, do_wr_special, a, hypervisor(dc), do_wrhpstate)
3220bb97f2f5SRichard Henderson 
3221bb97f2f5SRichard Henderson static void do_wrhtstate(DisasContext *dc, TCGv src)
3222bb97f2f5SRichard Henderson {
3223bb97f2f5SRichard Henderson     TCGv_i32 tl = tcg_temp_new_i32();
3224bb97f2f5SRichard Henderson     TCGv_ptr tp = tcg_temp_new_ptr();
3225bb97f2f5SRichard Henderson 
3226bb97f2f5SRichard Henderson     tcg_gen_ld_i32(tl, tcg_env, env64_field_offsetof(tl));
3227bb97f2f5SRichard Henderson     tcg_gen_andi_i32(tl, tl, MAXTL_MASK);
3228bb97f2f5SRichard Henderson     tcg_gen_shli_i32(tl, tl, 3);
3229bb97f2f5SRichard Henderson     tcg_gen_ext_i32_ptr(tp, tl);
3230bb97f2f5SRichard Henderson     tcg_gen_add_ptr(tp, tp, tcg_env);
3231bb97f2f5SRichard Henderson 
3232bb97f2f5SRichard Henderson     tcg_gen_st_tl(src, tp, env64_field_offsetof(htstate));
3233bb97f2f5SRichard Henderson }
3234bb97f2f5SRichard Henderson 
3235bb97f2f5SRichard Henderson TRANS(WRHPR_htstate, HYPV, do_wr_special, a, hypervisor(dc), do_wrhtstate)
3236bb97f2f5SRichard Henderson 
3237bb97f2f5SRichard Henderson static void do_wrhintp(DisasContext *dc, TCGv src)
3238bb97f2f5SRichard Henderson {
32392da789deSRichard Henderson     tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(hintp));
3240bb97f2f5SRichard Henderson }
3241bb97f2f5SRichard Henderson 
3242bb97f2f5SRichard Henderson TRANS(WRHPR_hintp, HYPV, do_wr_special, a, hypervisor(dc), do_wrhintp)
3243bb97f2f5SRichard Henderson 
3244bb97f2f5SRichard Henderson static void do_wrhtba(DisasContext *dc, TCGv src)
3245bb97f2f5SRichard Henderson {
32462da789deSRichard Henderson     tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(htba));
3247bb97f2f5SRichard Henderson }
3248bb97f2f5SRichard Henderson 
3249bb97f2f5SRichard Henderson TRANS(WRHPR_htba, HYPV, do_wr_special, a, hypervisor(dc), do_wrhtba)
3250bb97f2f5SRichard Henderson 
3251bb97f2f5SRichard Henderson static void do_wrhstick_cmpr(DisasContext *dc, TCGv src)
3252bb97f2f5SRichard Henderson {
3253bb97f2f5SRichard Henderson     TCGv_ptr r_tickptr = tcg_temp_new_ptr();
3254bb97f2f5SRichard Henderson 
3255577efa45SRichard Henderson     tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(hstick_cmpr));
3256bb97f2f5SRichard Henderson     tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(hstick));
3257bb97f2f5SRichard Henderson     translator_io_start(&dc->base);
3258577efa45SRichard Henderson     gen_helper_tick_set_limit(r_tickptr, src);
3259bb97f2f5SRichard Henderson     /* End TB to handle timer interrupt */
3260bb97f2f5SRichard Henderson     dc->base.is_jmp = DISAS_EXIT;
3261bb97f2f5SRichard Henderson }
3262bb97f2f5SRichard Henderson 
3263bb97f2f5SRichard Henderson TRANS(WRHPR_hstick_cmpr, HYPV, do_wr_special, a, hypervisor(dc),
3264bb97f2f5SRichard Henderson       do_wrhstick_cmpr)
3265bb97f2f5SRichard Henderson 
326625524734SRichard Henderson static bool do_saved_restored(DisasContext *dc, bool saved)
326725524734SRichard Henderson {
326825524734SRichard Henderson     if (!supervisor(dc)) {
326925524734SRichard Henderson         return raise_priv(dc);
327025524734SRichard Henderson     }
327125524734SRichard Henderson     if (saved) {
327225524734SRichard Henderson         gen_helper_saved(tcg_env);
327325524734SRichard Henderson     } else {
327425524734SRichard Henderson         gen_helper_restored(tcg_env);
327525524734SRichard Henderson     }
327625524734SRichard Henderson     return advance_pc(dc);
327725524734SRichard Henderson }
327825524734SRichard Henderson 
327925524734SRichard Henderson TRANS(SAVED, 64, do_saved_restored, true)
328025524734SRichard Henderson TRANS(RESTORED, 64, do_saved_restored, false)
328125524734SRichard Henderson 
3282d3825800SRichard Henderson static bool trans_NOP(DisasContext *dc, arg_NOP *a)
3283d3825800SRichard Henderson {
3284d3825800SRichard Henderson     return advance_pc(dc);
3285d3825800SRichard Henderson }
3286d3825800SRichard Henderson 
32870faef01bSRichard Henderson /*
32880faef01bSRichard Henderson  * TODO: Need a feature bit for sparcv8.
32890faef01bSRichard Henderson  * In the meantime, treat all 32-bit cpus like sparcv7.
32900faef01bSRichard Henderson  */
32915458fd31SRichard Henderson TRANS(NOP_v7, 32, trans_NOP, a)
32925458fd31SRichard Henderson TRANS(NOP_v9, 64, trans_NOP, a)
32930faef01bSRichard Henderson 
3294b597eedcSRichard Henderson static bool do_arith_int(DisasContext *dc, arg_r_r_ri_cc *a,
3295428881deSRichard Henderson                          void (*func)(TCGv, TCGv, TCGv),
32962a45b736SRichard Henderson                          void (*funci)(TCGv, TCGv, target_long),
32972a45b736SRichard Henderson                          bool logic_cc)
3298428881deSRichard Henderson {
3299428881deSRichard Henderson     TCGv dst, src1;
3300428881deSRichard Henderson 
3301428881deSRichard Henderson     /* For simplicity, we under-decoded the rs2 form. */
3302428881deSRichard Henderson     if (!a->imm && a->rs2_or_imm & ~0x1f) {
3303428881deSRichard Henderson         return false;
3304428881deSRichard Henderson     }
3305428881deSRichard Henderson 
33062a45b736SRichard Henderson     if (logic_cc) {
33072a45b736SRichard Henderson         dst = cpu_cc_N;
3308428881deSRichard Henderson     } else {
3309428881deSRichard Henderson         dst = gen_dest_gpr(dc, a->rd);
3310428881deSRichard Henderson     }
3311428881deSRichard Henderson     src1 = gen_load_gpr(dc, a->rs1);
3312428881deSRichard Henderson 
3313428881deSRichard Henderson     if (a->imm || a->rs2_or_imm == 0) {
3314428881deSRichard Henderson         if (funci) {
3315428881deSRichard Henderson             funci(dst, src1, a->rs2_or_imm);
3316428881deSRichard Henderson         } else {
3317428881deSRichard Henderson             func(dst, src1, tcg_constant_tl(a->rs2_or_imm));
3318428881deSRichard Henderson         }
3319428881deSRichard Henderson     } else {
3320428881deSRichard Henderson         func(dst, src1, cpu_regs[a->rs2_or_imm]);
3321428881deSRichard Henderson     }
33222a45b736SRichard Henderson 
33232a45b736SRichard Henderson     if (logic_cc) {
33242a45b736SRichard Henderson         if (TARGET_LONG_BITS == 64) {
33252a45b736SRichard Henderson             tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N);
33262a45b736SRichard Henderson             tcg_gen_movi_tl(cpu_icc_C, 0);
33272a45b736SRichard Henderson         }
33282a45b736SRichard Henderson         tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N);
33292a45b736SRichard Henderson         tcg_gen_movi_tl(cpu_cc_C, 0);
33302a45b736SRichard Henderson         tcg_gen_movi_tl(cpu_cc_V, 0);
33312a45b736SRichard Henderson     }
33322a45b736SRichard Henderson 
3333428881deSRichard Henderson     gen_store_gpr(dc, a->rd, dst);
3334428881deSRichard Henderson     return advance_pc(dc);
3335428881deSRichard Henderson }
3336428881deSRichard Henderson 
3337b597eedcSRichard Henderson static bool do_arith(DisasContext *dc, arg_r_r_ri_cc *a,
3338428881deSRichard Henderson                      void (*func)(TCGv, TCGv, TCGv),
3339428881deSRichard Henderson                      void (*funci)(TCGv, TCGv, target_long),
3340428881deSRichard Henderson                      void (*func_cc)(TCGv, TCGv, TCGv))
3341428881deSRichard Henderson {
3342428881deSRichard Henderson     if (a->cc) {
3343b597eedcSRichard Henderson         return do_arith_int(dc, a, func_cc, NULL, false);
3344428881deSRichard Henderson     }
3345b597eedcSRichard Henderson     return do_arith_int(dc, a, func, funci, false);
3346428881deSRichard Henderson }
3347428881deSRichard Henderson 
3348428881deSRichard Henderson static bool do_logic(DisasContext *dc, arg_r_r_ri_cc *a,
3349428881deSRichard Henderson                      void (*func)(TCGv, TCGv, TCGv),
3350428881deSRichard Henderson                      void (*funci)(TCGv, TCGv, target_long))
3351428881deSRichard Henderson {
3352b597eedcSRichard Henderson     return do_arith_int(dc, a, func, funci, a->cc);
3353428881deSRichard Henderson }
3354428881deSRichard Henderson 
3355b597eedcSRichard Henderson TRANS(ADD, ALL, do_arith, a, tcg_gen_add_tl, tcg_gen_addi_tl, gen_op_addcc)
3356b597eedcSRichard Henderson TRANS(SUB, ALL, do_arith, a, tcg_gen_sub_tl, tcg_gen_subi_tl, gen_op_subcc)
3357b597eedcSRichard Henderson TRANS(ADDC, ALL, do_arith, a, gen_op_addc, NULL, gen_op_addccc)
3358b597eedcSRichard Henderson TRANS(SUBC, ALL, do_arith, a, gen_op_subc, NULL, gen_op_subccc)
3359428881deSRichard Henderson 
3360b597eedcSRichard Henderson TRANS(TADDcc, ALL, do_arith, a, NULL, NULL, gen_op_taddcc)
3361b597eedcSRichard Henderson TRANS(TSUBcc, ALL, do_arith, a, NULL, NULL, gen_op_tsubcc)
3362b597eedcSRichard Henderson TRANS(TADDccTV, ALL, do_arith, a, NULL, NULL, gen_op_taddcctv)
3363b597eedcSRichard Henderson TRANS(TSUBccTV, ALL, do_arith, a, NULL, NULL, gen_op_tsubcctv)
3364a9aba13dSRichard Henderson 
3365428881deSRichard Henderson TRANS(AND, ALL, do_logic, a, tcg_gen_and_tl, tcg_gen_andi_tl)
3366428881deSRichard Henderson TRANS(XOR, ALL, do_logic, a, tcg_gen_xor_tl, tcg_gen_xori_tl)
3367428881deSRichard Henderson TRANS(ANDN, ALL, do_logic, a, tcg_gen_andc_tl, NULL)
3368428881deSRichard Henderson TRANS(ORN, ALL, do_logic, a, tcg_gen_orc_tl, NULL)
3369428881deSRichard Henderson TRANS(XORN, ALL, do_logic, a, tcg_gen_eqv_tl, NULL)
3370428881deSRichard Henderson 
3371b597eedcSRichard Henderson TRANS(MULX, 64, do_arith, a, tcg_gen_mul_tl, tcg_gen_muli_tl, NULL)
3372b5372650SRichard Henderson TRANS(UMUL, MUL, do_logic, a, gen_op_umul, NULL)
3373b5372650SRichard Henderson TRANS(SMUL, MUL, do_logic, a, gen_op_smul, NULL)
3374b597eedcSRichard Henderson TRANS(MULScc, ALL, do_arith, a, NULL, NULL, gen_op_mulscc)
337522188d7dSRichard Henderson 
33763a6b8de3SRichard Henderson TRANS(UDIVcc, DIV, do_arith, a, NULL, NULL, gen_op_udivcc)
3377b597eedcSRichard Henderson TRANS(SDIV, DIV, do_arith, a, gen_op_sdiv, NULL, gen_op_sdivcc)
33784ee85ea9SRichard Henderson 
33799c6ec5bcSRichard Henderson /* TODO: Should have feature bit -- comes in with UltraSparc T2. */
3380b597eedcSRichard Henderson TRANS(POPC, 64, do_arith, a, gen_op_popc, NULL, NULL)
33819c6ec5bcSRichard Henderson 
3382428881deSRichard Henderson static bool trans_OR(DisasContext *dc, arg_r_r_ri_cc *a)
3383428881deSRichard Henderson {
3384428881deSRichard Henderson     /* OR with %g0 is the canonical alias for MOV. */
3385428881deSRichard Henderson     if (!a->cc && a->rs1 == 0) {
3386428881deSRichard Henderson         if (a->imm || a->rs2_or_imm == 0) {
3387428881deSRichard Henderson             gen_store_gpr(dc, a->rd, tcg_constant_tl(a->rs2_or_imm));
3388428881deSRichard Henderson         } else if (a->rs2_or_imm & ~0x1f) {
3389428881deSRichard Henderson             /* For simplicity, we under-decoded the rs2 form. */
3390428881deSRichard Henderson             return false;
3391428881deSRichard Henderson         } else {
3392428881deSRichard Henderson             gen_store_gpr(dc, a->rd, cpu_regs[a->rs2_or_imm]);
3393428881deSRichard Henderson         }
3394428881deSRichard Henderson         return advance_pc(dc);
3395428881deSRichard Henderson     }
3396428881deSRichard Henderson     return do_logic(dc, a, tcg_gen_or_tl, tcg_gen_ori_tl);
3397428881deSRichard Henderson }
3398428881deSRichard Henderson 
33993a6b8de3SRichard Henderson static bool trans_UDIV(DisasContext *dc, arg_r_r_ri *a)
34003a6b8de3SRichard Henderson {
34013a6b8de3SRichard Henderson     TCGv_i64 t1, t2;
34023a6b8de3SRichard Henderson     TCGv dst;
34033a6b8de3SRichard Henderson 
34043a6b8de3SRichard Henderson     if (!avail_DIV(dc)) {
34053a6b8de3SRichard Henderson         return false;
34063a6b8de3SRichard Henderson     }
34073a6b8de3SRichard Henderson     /* For simplicity, we under-decoded the rs2 form. */
34083a6b8de3SRichard Henderson     if (!a->imm && a->rs2_or_imm & ~0x1f) {
34093a6b8de3SRichard Henderson         return false;
34103a6b8de3SRichard Henderson     }
34113a6b8de3SRichard Henderson 
34123a6b8de3SRichard Henderson     if (unlikely(a->rs2_or_imm == 0)) {
34133a6b8de3SRichard Henderson         gen_exception(dc, TT_DIV_ZERO);
34143a6b8de3SRichard Henderson         return true;
34153a6b8de3SRichard Henderson     }
34163a6b8de3SRichard Henderson 
34173a6b8de3SRichard Henderson     if (a->imm) {
34183a6b8de3SRichard Henderson         t2 = tcg_constant_i64((uint32_t)a->rs2_or_imm);
34193a6b8de3SRichard Henderson     } else {
34203a6b8de3SRichard Henderson         TCGLabel *lab;
34213a6b8de3SRichard Henderson         TCGv_i32 n2;
34223a6b8de3SRichard Henderson 
34233a6b8de3SRichard Henderson         finishing_insn(dc);
34243a6b8de3SRichard Henderson         flush_cond(dc);
34253a6b8de3SRichard Henderson 
34263a6b8de3SRichard Henderson         n2 = tcg_temp_new_i32();
34273a6b8de3SRichard Henderson         tcg_gen_trunc_tl_i32(n2, cpu_regs[a->rs2_or_imm]);
34283a6b8de3SRichard Henderson 
34293a6b8de3SRichard Henderson         lab = delay_exception(dc, TT_DIV_ZERO);
34303a6b8de3SRichard Henderson         tcg_gen_brcondi_i32(TCG_COND_EQ, n2, 0, lab);
34313a6b8de3SRichard Henderson 
34323a6b8de3SRichard Henderson         t2 = tcg_temp_new_i64();
34333a6b8de3SRichard Henderson #ifdef TARGET_SPARC64
34343a6b8de3SRichard Henderson         tcg_gen_ext32u_i64(t2, cpu_regs[a->rs2_or_imm]);
34353a6b8de3SRichard Henderson #else
34363a6b8de3SRichard Henderson         tcg_gen_extu_i32_i64(t2, cpu_regs[a->rs2_or_imm]);
34373a6b8de3SRichard Henderson #endif
34383a6b8de3SRichard Henderson     }
34393a6b8de3SRichard Henderson 
34403a6b8de3SRichard Henderson     t1 = tcg_temp_new_i64();
34413a6b8de3SRichard Henderson     tcg_gen_concat_tl_i64(t1, gen_load_gpr(dc, a->rs1), cpu_y);
34423a6b8de3SRichard Henderson 
34433a6b8de3SRichard Henderson     tcg_gen_divu_i64(t1, t1, t2);
34443a6b8de3SRichard Henderson     tcg_gen_umin_i64(t1, t1, tcg_constant_i64(UINT32_MAX));
34453a6b8de3SRichard Henderson 
34463a6b8de3SRichard Henderson     dst = gen_dest_gpr(dc, a->rd);
34473a6b8de3SRichard Henderson     tcg_gen_trunc_i64_tl(dst, t1);
34483a6b8de3SRichard Henderson     gen_store_gpr(dc, a->rd, dst);
34493a6b8de3SRichard Henderson     return advance_pc(dc);
34503a6b8de3SRichard Henderson }
34513a6b8de3SRichard Henderson 
3452f3141174SRichard Henderson static bool trans_UDIVX(DisasContext *dc, arg_r_r_ri *a)
3453f3141174SRichard Henderson {
3454f3141174SRichard Henderson     TCGv dst, src1, src2;
3455f3141174SRichard Henderson 
3456f3141174SRichard Henderson     if (!avail_64(dc)) {
3457f3141174SRichard Henderson         return false;
3458f3141174SRichard Henderson     }
3459f3141174SRichard Henderson     /* For simplicity, we under-decoded the rs2 form. */
3460f3141174SRichard Henderson     if (!a->imm && a->rs2_or_imm & ~0x1f) {
3461f3141174SRichard Henderson         return false;
3462f3141174SRichard Henderson     }
3463f3141174SRichard Henderson 
3464f3141174SRichard Henderson     if (unlikely(a->rs2_or_imm == 0)) {
3465f3141174SRichard Henderson         gen_exception(dc, TT_DIV_ZERO);
3466f3141174SRichard Henderson         return true;
3467f3141174SRichard Henderson     }
3468f3141174SRichard Henderson 
3469f3141174SRichard Henderson     if (a->imm) {
3470f3141174SRichard Henderson         src2 = tcg_constant_tl(a->rs2_or_imm);
3471f3141174SRichard Henderson     } else {
3472f3141174SRichard Henderson         TCGLabel *lab;
3473f3141174SRichard Henderson 
3474f3141174SRichard Henderson         finishing_insn(dc);
3475f3141174SRichard Henderson         flush_cond(dc);
3476f3141174SRichard Henderson 
3477f3141174SRichard Henderson         lab = delay_exception(dc, TT_DIV_ZERO);
3478f3141174SRichard Henderson         src2 = cpu_regs[a->rs2_or_imm];
3479f3141174SRichard Henderson         tcg_gen_brcondi_tl(TCG_COND_EQ, src2, 0, lab);
3480f3141174SRichard Henderson     }
3481f3141174SRichard Henderson 
3482f3141174SRichard Henderson     dst = gen_dest_gpr(dc, a->rd);
3483f3141174SRichard Henderson     src1 = gen_load_gpr(dc, a->rs1);
3484f3141174SRichard Henderson 
3485f3141174SRichard Henderson     tcg_gen_divu_tl(dst, src1, src2);
3486f3141174SRichard Henderson     gen_store_gpr(dc, a->rd, dst);
3487f3141174SRichard Henderson     return advance_pc(dc);
3488f3141174SRichard Henderson }
3489f3141174SRichard Henderson 
3490f3141174SRichard Henderson static bool trans_SDIVX(DisasContext *dc, arg_r_r_ri *a)
3491f3141174SRichard Henderson {
3492f3141174SRichard Henderson     TCGv dst, src1, src2;
3493f3141174SRichard Henderson 
3494f3141174SRichard Henderson     if (!avail_64(dc)) {
3495f3141174SRichard Henderson         return false;
3496f3141174SRichard Henderson     }
3497f3141174SRichard Henderson     /* For simplicity, we under-decoded the rs2 form. */
3498f3141174SRichard Henderson     if (!a->imm && a->rs2_or_imm & ~0x1f) {
3499f3141174SRichard Henderson         return false;
3500f3141174SRichard Henderson     }
3501f3141174SRichard Henderson 
3502f3141174SRichard Henderson     if (unlikely(a->rs2_or_imm == 0)) {
3503f3141174SRichard Henderson         gen_exception(dc, TT_DIV_ZERO);
3504f3141174SRichard Henderson         return true;
3505f3141174SRichard Henderson     }
3506f3141174SRichard Henderson 
3507f3141174SRichard Henderson     dst = gen_dest_gpr(dc, a->rd);
3508f3141174SRichard Henderson     src1 = gen_load_gpr(dc, a->rs1);
3509f3141174SRichard Henderson 
3510f3141174SRichard Henderson     if (a->imm) {
3511f3141174SRichard Henderson         if (unlikely(a->rs2_or_imm == -1)) {
3512f3141174SRichard Henderson             tcg_gen_neg_tl(dst, src1);
3513f3141174SRichard Henderson             gen_store_gpr(dc, a->rd, dst);
3514f3141174SRichard Henderson             return advance_pc(dc);
3515f3141174SRichard Henderson         }
3516f3141174SRichard Henderson         src2 = tcg_constant_tl(a->rs2_or_imm);
3517f3141174SRichard Henderson     } else {
3518f3141174SRichard Henderson         TCGLabel *lab;
3519f3141174SRichard Henderson         TCGv t1, t2;
3520f3141174SRichard Henderson 
3521f3141174SRichard Henderson         finishing_insn(dc);
3522f3141174SRichard Henderson         flush_cond(dc);
3523f3141174SRichard Henderson 
3524f3141174SRichard Henderson         lab = delay_exception(dc, TT_DIV_ZERO);
3525f3141174SRichard Henderson         src2 = cpu_regs[a->rs2_or_imm];
3526f3141174SRichard Henderson         tcg_gen_brcondi_tl(TCG_COND_EQ, src2, 0, lab);
3527f3141174SRichard Henderson 
3528f3141174SRichard Henderson         /*
3529f3141174SRichard Henderson          * Need to avoid INT64_MIN / -1, which will trap on x86 host.
3530f3141174SRichard Henderson          * Set SRC2 to 1 as a new divisor, to produce the correct result.
3531f3141174SRichard Henderson          */
3532f3141174SRichard Henderson         t1 = tcg_temp_new();
3533f3141174SRichard Henderson         t2 = tcg_temp_new();
3534f3141174SRichard Henderson         tcg_gen_setcondi_tl(TCG_COND_EQ, t1, src1, (target_long)INT64_MIN);
3535f3141174SRichard Henderson         tcg_gen_setcondi_tl(TCG_COND_EQ, t2, src2, -1);
3536f3141174SRichard Henderson         tcg_gen_and_tl(t1, t1, t2);
3537f3141174SRichard Henderson         tcg_gen_movcond_tl(TCG_COND_NE, t1, t1, tcg_constant_tl(0),
3538f3141174SRichard Henderson                            tcg_constant_tl(1), src2);
3539f3141174SRichard Henderson         src2 = t1;
3540f3141174SRichard Henderson     }
3541f3141174SRichard Henderson 
3542f3141174SRichard Henderson     tcg_gen_div_tl(dst, src1, src2);
3543f3141174SRichard Henderson     gen_store_gpr(dc, a->rd, dst);
3544f3141174SRichard Henderson     return advance_pc(dc);
3545f3141174SRichard Henderson }
3546f3141174SRichard Henderson 
3547b88ce6f2SRichard Henderson static bool gen_edge(DisasContext *dc, arg_r_r_r *a,
354843db5838SRichard Henderson                      int width, bool cc, bool little_endian)
3549b88ce6f2SRichard Henderson {
355043db5838SRichard Henderson     TCGv dst, s1, s2, l, r, t, m;
355143db5838SRichard Henderson     uint64_t amask = address_mask_i(dc, -8);
3552b88ce6f2SRichard Henderson 
3553b88ce6f2SRichard Henderson     dst = gen_dest_gpr(dc, a->rd);
3554b88ce6f2SRichard Henderson     s1 = gen_load_gpr(dc, a->rs1);
3555b88ce6f2SRichard Henderson     s2 = gen_load_gpr(dc, a->rs2);
3556b88ce6f2SRichard Henderson 
3557b88ce6f2SRichard Henderson     if (cc) {
3558f828df74SRichard Henderson         gen_op_subcc(cpu_cc_N, s1, s2);
3559b88ce6f2SRichard Henderson     }
3560b88ce6f2SRichard Henderson 
356143db5838SRichard Henderson     l = tcg_temp_new();
356243db5838SRichard Henderson     r = tcg_temp_new();
356343db5838SRichard Henderson     t = tcg_temp_new();
356443db5838SRichard Henderson 
3565b88ce6f2SRichard Henderson     switch (width) {
3566b88ce6f2SRichard Henderson     case 8:
356743db5838SRichard Henderson         tcg_gen_andi_tl(l, s1, 7);
356843db5838SRichard Henderson         tcg_gen_andi_tl(r, s2, 7);
356943db5838SRichard Henderson         tcg_gen_xori_tl(r, r, 7);
357043db5838SRichard Henderson         m = tcg_constant_tl(0xff);
3571b88ce6f2SRichard Henderson         break;
3572b88ce6f2SRichard Henderson     case 16:
357343db5838SRichard Henderson         tcg_gen_extract_tl(l, s1, 1, 2);
357443db5838SRichard Henderson         tcg_gen_extract_tl(r, s2, 1, 2);
357543db5838SRichard Henderson         tcg_gen_xori_tl(r, r, 3);
357643db5838SRichard Henderson         m = tcg_constant_tl(0xf);
3577b88ce6f2SRichard Henderson         break;
3578b88ce6f2SRichard Henderson     case 32:
357943db5838SRichard Henderson         tcg_gen_extract_tl(l, s1, 2, 1);
358043db5838SRichard Henderson         tcg_gen_extract_tl(r, s2, 2, 1);
358143db5838SRichard Henderson         tcg_gen_xori_tl(r, r, 1);
358243db5838SRichard Henderson         m = tcg_constant_tl(0x3);
3583b88ce6f2SRichard Henderson         break;
3584b88ce6f2SRichard Henderson     default:
3585b88ce6f2SRichard Henderson         abort();
3586b88ce6f2SRichard Henderson     }
3587b88ce6f2SRichard Henderson 
358843db5838SRichard Henderson     /* Compute Left Edge */
358943db5838SRichard Henderson     if (little_endian) {
359043db5838SRichard Henderson         tcg_gen_shl_tl(l, m, l);
359143db5838SRichard Henderson         tcg_gen_and_tl(l, l, m);
359243db5838SRichard Henderson     } else {
359343db5838SRichard Henderson         tcg_gen_shr_tl(l, m, l);
359443db5838SRichard Henderson     }
359543db5838SRichard Henderson     /* Compute Right Edge */
359643db5838SRichard Henderson     if (little_endian) {
359743db5838SRichard Henderson         tcg_gen_shr_tl(r, m, r);
359843db5838SRichard Henderson     } else {
359943db5838SRichard Henderson         tcg_gen_shl_tl(r, m, r);
360043db5838SRichard Henderson         tcg_gen_and_tl(r, r, m);
360143db5838SRichard Henderson     }
3602b88ce6f2SRichard Henderson 
360343db5838SRichard Henderson     /* Compute dst = (s1 == s2 under amask ? l : l & r) */
360443db5838SRichard Henderson     tcg_gen_xor_tl(t, s1, s2);
360543db5838SRichard Henderson     tcg_gen_and_tl(r, r, l);
360643db5838SRichard Henderson     tcg_gen_movcond_tl(TCG_COND_TSTEQ, dst, t, tcg_constant_tl(amask), r, l);
3607b88ce6f2SRichard Henderson 
3608b88ce6f2SRichard Henderson     gen_store_gpr(dc, a->rd, dst);
3609b88ce6f2SRichard Henderson     return advance_pc(dc);
3610b88ce6f2SRichard Henderson }
3611b88ce6f2SRichard Henderson 
3612b88ce6f2SRichard Henderson TRANS(EDGE8cc, VIS1, gen_edge, a, 8, 1, 0)
3613b88ce6f2SRichard Henderson TRANS(EDGE8Lcc, VIS1, gen_edge, a, 8, 1, 1)
3614b88ce6f2SRichard Henderson TRANS(EDGE16cc, VIS1, gen_edge, a, 16, 1, 0)
3615b88ce6f2SRichard Henderson TRANS(EDGE16Lcc, VIS1, gen_edge, a, 16, 1, 1)
3616b88ce6f2SRichard Henderson TRANS(EDGE32cc, VIS1, gen_edge, a, 32, 1, 0)
3617b88ce6f2SRichard Henderson TRANS(EDGE32Lcc, VIS1, gen_edge, a, 32, 1, 1)
3618b88ce6f2SRichard Henderson 
3619b88ce6f2SRichard Henderson TRANS(EDGE8N, VIS2, gen_edge, a, 8, 0, 0)
3620b88ce6f2SRichard Henderson TRANS(EDGE8LN, VIS2, gen_edge, a, 8, 0, 1)
3621b88ce6f2SRichard Henderson TRANS(EDGE16N, VIS2, gen_edge, a, 16, 0, 0)
3622b88ce6f2SRichard Henderson TRANS(EDGE16LN, VIS2, gen_edge, a, 16, 0, 1)
3623b88ce6f2SRichard Henderson TRANS(EDGE32N, VIS2, gen_edge, a, 32, 0, 0)
3624b88ce6f2SRichard Henderson TRANS(EDGE32LN, VIS2, gen_edge, a, 32, 0, 1)
3625b88ce6f2SRichard Henderson 
362645bfed3bSRichard Henderson static bool do_rrr(DisasContext *dc, arg_r_r_r *a,
362745bfed3bSRichard Henderson                    void (*func)(TCGv, TCGv, TCGv))
362845bfed3bSRichard Henderson {
362945bfed3bSRichard Henderson     TCGv dst = gen_dest_gpr(dc, a->rd);
363045bfed3bSRichard Henderson     TCGv src1 = gen_load_gpr(dc, a->rs1);
363145bfed3bSRichard Henderson     TCGv src2 = gen_load_gpr(dc, a->rs2);
363245bfed3bSRichard Henderson 
363345bfed3bSRichard Henderson     func(dst, src1, src2);
363445bfed3bSRichard Henderson     gen_store_gpr(dc, a->rd, dst);
363545bfed3bSRichard Henderson     return advance_pc(dc);
363645bfed3bSRichard Henderson }
363745bfed3bSRichard Henderson 
363845bfed3bSRichard Henderson TRANS(ARRAY8, VIS1, do_rrr, a, gen_helper_array8)
363945bfed3bSRichard Henderson TRANS(ARRAY16, VIS1, do_rrr, a, gen_op_array16)
364045bfed3bSRichard Henderson TRANS(ARRAY32, VIS1, do_rrr, a, gen_op_array32)
364145bfed3bSRichard Henderson 
36429e20ca94SRichard Henderson static void gen_op_alignaddr(TCGv dst, TCGv s1, TCGv s2)
36439e20ca94SRichard Henderson {
36449e20ca94SRichard Henderson #ifdef TARGET_SPARC64
36459e20ca94SRichard Henderson     TCGv tmp = tcg_temp_new();
36469e20ca94SRichard Henderson 
36479e20ca94SRichard Henderson     tcg_gen_add_tl(tmp, s1, s2);
36489e20ca94SRichard Henderson     tcg_gen_andi_tl(dst, tmp, -8);
36499e20ca94SRichard Henderson     tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, tmp, 0, 3);
36509e20ca94SRichard Henderson #else
36519e20ca94SRichard Henderson     g_assert_not_reached();
36529e20ca94SRichard Henderson #endif
36539e20ca94SRichard Henderson }
36549e20ca94SRichard Henderson 
36559e20ca94SRichard Henderson static void gen_op_alignaddrl(TCGv dst, TCGv s1, TCGv s2)
36569e20ca94SRichard Henderson {
36579e20ca94SRichard Henderson #ifdef TARGET_SPARC64
36589e20ca94SRichard Henderson     TCGv tmp = tcg_temp_new();
36599e20ca94SRichard Henderson 
36609e20ca94SRichard Henderson     tcg_gen_add_tl(tmp, s1, s2);
36619e20ca94SRichard Henderson     tcg_gen_andi_tl(dst, tmp, -8);
36629e20ca94SRichard Henderson     tcg_gen_neg_tl(tmp, tmp);
36639e20ca94SRichard Henderson     tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, tmp, 0, 3);
36649e20ca94SRichard Henderson #else
36659e20ca94SRichard Henderson     g_assert_not_reached();
36669e20ca94SRichard Henderson #endif
36679e20ca94SRichard Henderson }
36689e20ca94SRichard Henderson 
36699e20ca94SRichard Henderson TRANS(ALIGNADDR, VIS1, do_rrr, a, gen_op_alignaddr)
36709e20ca94SRichard Henderson TRANS(ALIGNADDRL, VIS1, do_rrr, a, gen_op_alignaddrl)
36719e20ca94SRichard Henderson 
367239ca3490SRichard Henderson static void gen_op_bmask(TCGv dst, TCGv s1, TCGv s2)
367339ca3490SRichard Henderson {
367439ca3490SRichard Henderson #ifdef TARGET_SPARC64
367539ca3490SRichard Henderson     tcg_gen_add_tl(dst, s1, s2);
367639ca3490SRichard Henderson     tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, dst, 32, 32);
367739ca3490SRichard Henderson #else
367839ca3490SRichard Henderson     g_assert_not_reached();
367939ca3490SRichard Henderson #endif
368039ca3490SRichard Henderson }
368139ca3490SRichard Henderson 
368239ca3490SRichard Henderson TRANS(BMASK, VIS2, do_rrr, a, gen_op_bmask)
368339ca3490SRichard Henderson 
36845fc546eeSRichard Henderson static bool do_shift_r(DisasContext *dc, arg_shiftr *a, bool l, bool u)
36855fc546eeSRichard Henderson {
36865fc546eeSRichard Henderson     TCGv dst, src1, src2;
36875fc546eeSRichard Henderson 
36885fc546eeSRichard Henderson     /* Reject 64-bit shifts for sparc32. */
36895fc546eeSRichard Henderson     if (avail_32(dc) && a->x) {
36905fc546eeSRichard Henderson         return false;
36915fc546eeSRichard Henderson     }
36925fc546eeSRichard Henderson 
36935fc546eeSRichard Henderson     src2 = tcg_temp_new();
36945fc546eeSRichard Henderson     tcg_gen_andi_tl(src2, gen_load_gpr(dc, a->rs2), a->x ? 63 : 31);
36955fc546eeSRichard Henderson     src1 = gen_load_gpr(dc, a->rs1);
36965fc546eeSRichard Henderson     dst = gen_dest_gpr(dc, a->rd);
36975fc546eeSRichard Henderson 
36985fc546eeSRichard Henderson     if (l) {
36995fc546eeSRichard Henderson         tcg_gen_shl_tl(dst, src1, src2);
37005fc546eeSRichard Henderson         if (!a->x) {
37015fc546eeSRichard Henderson             tcg_gen_ext32u_tl(dst, dst);
37025fc546eeSRichard Henderson         }
37035fc546eeSRichard Henderson     } else if (u) {
37045fc546eeSRichard Henderson         if (!a->x) {
37055fc546eeSRichard Henderson             tcg_gen_ext32u_tl(dst, src1);
37065fc546eeSRichard Henderson             src1 = dst;
37075fc546eeSRichard Henderson         }
37085fc546eeSRichard Henderson         tcg_gen_shr_tl(dst, src1, src2);
37095fc546eeSRichard Henderson     } else {
37105fc546eeSRichard Henderson         if (!a->x) {
37115fc546eeSRichard Henderson             tcg_gen_ext32s_tl(dst, src1);
37125fc546eeSRichard Henderson             src1 = dst;
37135fc546eeSRichard Henderson         }
37145fc546eeSRichard Henderson         tcg_gen_sar_tl(dst, src1, src2);
37155fc546eeSRichard Henderson     }
37165fc546eeSRichard Henderson     gen_store_gpr(dc, a->rd, dst);
37175fc546eeSRichard Henderson     return advance_pc(dc);
37185fc546eeSRichard Henderson }
37195fc546eeSRichard Henderson 
37205fc546eeSRichard Henderson TRANS(SLL_r, ALL, do_shift_r, a, true, true)
37215fc546eeSRichard Henderson TRANS(SRL_r, ALL, do_shift_r, a, false, true)
37225fc546eeSRichard Henderson TRANS(SRA_r, ALL, do_shift_r, a, false, false)
37235fc546eeSRichard Henderson 
37245fc546eeSRichard Henderson static bool do_shift_i(DisasContext *dc, arg_shifti *a, bool l, bool u)
37255fc546eeSRichard Henderson {
37265fc546eeSRichard Henderson     TCGv dst, src1;
37275fc546eeSRichard Henderson 
37285fc546eeSRichard Henderson     /* Reject 64-bit shifts for sparc32. */
37295fc546eeSRichard Henderson     if (avail_32(dc) && (a->x || a->i >= 32)) {
37305fc546eeSRichard Henderson         return false;
37315fc546eeSRichard Henderson     }
37325fc546eeSRichard Henderson 
37335fc546eeSRichard Henderson     src1 = gen_load_gpr(dc, a->rs1);
37345fc546eeSRichard Henderson     dst = gen_dest_gpr(dc, a->rd);
37355fc546eeSRichard Henderson 
37365fc546eeSRichard Henderson     if (avail_32(dc) || a->x) {
37375fc546eeSRichard Henderson         if (l) {
37385fc546eeSRichard Henderson             tcg_gen_shli_tl(dst, src1, a->i);
37395fc546eeSRichard Henderson         } else if (u) {
37405fc546eeSRichard Henderson             tcg_gen_shri_tl(dst, src1, a->i);
37415fc546eeSRichard Henderson         } else {
37425fc546eeSRichard Henderson             tcg_gen_sari_tl(dst, src1, a->i);
37435fc546eeSRichard Henderson         }
37445fc546eeSRichard Henderson     } else {
37455fc546eeSRichard Henderson         if (l) {
37465fc546eeSRichard Henderson             tcg_gen_deposit_z_tl(dst, src1, a->i, 32 - a->i);
37475fc546eeSRichard Henderson         } else if (u) {
37485fc546eeSRichard Henderson             tcg_gen_extract_tl(dst, src1, a->i, 32 - a->i);
37495fc546eeSRichard Henderson         } else {
37505fc546eeSRichard Henderson             tcg_gen_sextract_tl(dst, src1, a->i, 32 - a->i);
37515fc546eeSRichard Henderson         }
37525fc546eeSRichard Henderson     }
37535fc546eeSRichard Henderson     gen_store_gpr(dc, a->rd, dst);
37545fc546eeSRichard Henderson     return advance_pc(dc);
37555fc546eeSRichard Henderson }
37565fc546eeSRichard Henderson 
37575fc546eeSRichard Henderson TRANS(SLL_i, ALL, do_shift_i, a, true, true)
37585fc546eeSRichard Henderson TRANS(SRL_i, ALL, do_shift_i, a, false, true)
37595fc546eeSRichard Henderson TRANS(SRA_i, ALL, do_shift_i, a, false, false)
37605fc546eeSRichard Henderson 
3761fb4ed7aaSRichard Henderson static TCGv gen_rs2_or_imm(DisasContext *dc, bool imm, int rs2_or_imm)
3762fb4ed7aaSRichard Henderson {
3763fb4ed7aaSRichard Henderson     /* For simplicity, we under-decoded the rs2 form. */
3764fb4ed7aaSRichard Henderson     if (!imm && rs2_or_imm & ~0x1f) {
3765fb4ed7aaSRichard Henderson         return NULL;
3766fb4ed7aaSRichard Henderson     }
3767fb4ed7aaSRichard Henderson     if (imm || rs2_or_imm == 0) {
3768fb4ed7aaSRichard Henderson         return tcg_constant_tl(rs2_or_imm);
3769fb4ed7aaSRichard Henderson     } else {
3770fb4ed7aaSRichard Henderson         return cpu_regs[rs2_or_imm];
3771fb4ed7aaSRichard Henderson     }
3772fb4ed7aaSRichard Henderson }
3773fb4ed7aaSRichard Henderson 
3774fb4ed7aaSRichard Henderson static bool do_mov_cond(DisasContext *dc, DisasCompare *cmp, int rd, TCGv src2)
3775fb4ed7aaSRichard Henderson {
3776fb4ed7aaSRichard Henderson     TCGv dst = gen_load_gpr(dc, rd);
3777c8507ebfSRichard Henderson     TCGv c2 = tcg_constant_tl(cmp->c2);
3778fb4ed7aaSRichard Henderson 
3779c8507ebfSRichard Henderson     tcg_gen_movcond_tl(cmp->cond, dst, cmp->c1, c2, src2, dst);
3780fb4ed7aaSRichard Henderson     gen_store_gpr(dc, rd, dst);
3781fb4ed7aaSRichard Henderson     return advance_pc(dc);
3782fb4ed7aaSRichard Henderson }
3783fb4ed7aaSRichard Henderson 
3784fb4ed7aaSRichard Henderson static bool trans_MOVcc(DisasContext *dc, arg_MOVcc *a)
3785fb4ed7aaSRichard Henderson {
3786fb4ed7aaSRichard Henderson     TCGv src2 = gen_rs2_or_imm(dc, a->imm, a->rs2_or_imm);
3787fb4ed7aaSRichard Henderson     DisasCompare cmp;
3788fb4ed7aaSRichard Henderson 
3789fb4ed7aaSRichard Henderson     if (src2 == NULL) {
3790fb4ed7aaSRichard Henderson         return false;
3791fb4ed7aaSRichard Henderson     }
3792fb4ed7aaSRichard Henderson     gen_compare(&cmp, a->cc, a->cond, dc);
3793fb4ed7aaSRichard Henderson     return do_mov_cond(dc, &cmp, a->rd, src2);
3794fb4ed7aaSRichard Henderson }
3795fb4ed7aaSRichard Henderson 
3796fb4ed7aaSRichard Henderson static bool trans_MOVfcc(DisasContext *dc, arg_MOVfcc *a)
3797fb4ed7aaSRichard Henderson {
3798fb4ed7aaSRichard Henderson     TCGv src2 = gen_rs2_or_imm(dc, a->imm, a->rs2_or_imm);
3799fb4ed7aaSRichard Henderson     DisasCompare cmp;
3800fb4ed7aaSRichard Henderson 
3801fb4ed7aaSRichard Henderson     if (src2 == NULL) {
3802fb4ed7aaSRichard Henderson         return false;
3803fb4ed7aaSRichard Henderson     }
3804fb4ed7aaSRichard Henderson     gen_fcompare(&cmp, a->cc, a->cond);
3805fb4ed7aaSRichard Henderson     return do_mov_cond(dc, &cmp, a->rd, src2);
3806fb4ed7aaSRichard Henderson }
3807fb4ed7aaSRichard Henderson 
3808fb4ed7aaSRichard Henderson static bool trans_MOVR(DisasContext *dc, arg_MOVR *a)
3809fb4ed7aaSRichard Henderson {
3810fb4ed7aaSRichard Henderson     TCGv src2 = gen_rs2_or_imm(dc, a->imm, a->rs2_or_imm);
3811fb4ed7aaSRichard Henderson     DisasCompare cmp;
3812fb4ed7aaSRichard Henderson 
3813fb4ed7aaSRichard Henderson     if (src2 == NULL) {
3814fb4ed7aaSRichard Henderson         return false;
3815fb4ed7aaSRichard Henderson     }
38162c4f56c9SRichard Henderson     if (!gen_compare_reg(&cmp, a->cond, gen_load_gpr(dc, a->rs1))) {
38172c4f56c9SRichard Henderson         return false;
38182c4f56c9SRichard Henderson     }
3819fb4ed7aaSRichard Henderson     return do_mov_cond(dc, &cmp, a->rd, src2);
3820fb4ed7aaSRichard Henderson }
3821fb4ed7aaSRichard Henderson 
382286b82fe0SRichard Henderson static bool do_add_special(DisasContext *dc, arg_r_r_ri *a,
382386b82fe0SRichard Henderson                            bool (*func)(DisasContext *dc, int rd, TCGv src))
382486b82fe0SRichard Henderson {
382586b82fe0SRichard Henderson     TCGv src1, sum;
382686b82fe0SRichard Henderson 
382786b82fe0SRichard Henderson     /* For simplicity, we under-decoded the rs2 form. */
382886b82fe0SRichard Henderson     if (!a->imm && a->rs2_or_imm & ~0x1f) {
382986b82fe0SRichard Henderson         return false;
383086b82fe0SRichard Henderson     }
383186b82fe0SRichard Henderson 
383286b82fe0SRichard Henderson     /*
383386b82fe0SRichard Henderson      * Always load the sum into a new temporary.
383486b82fe0SRichard Henderson      * This is required to capture the value across a window change,
383586b82fe0SRichard Henderson      * e.g. SAVE and RESTORE, and may be optimized away otherwise.
383686b82fe0SRichard Henderson      */
383786b82fe0SRichard Henderson     sum = tcg_temp_new();
383886b82fe0SRichard Henderson     src1 = gen_load_gpr(dc, a->rs1);
383986b82fe0SRichard Henderson     if (a->imm || a->rs2_or_imm == 0) {
384086b82fe0SRichard Henderson         tcg_gen_addi_tl(sum, src1, a->rs2_or_imm);
384186b82fe0SRichard Henderson     } else {
384286b82fe0SRichard Henderson         tcg_gen_add_tl(sum, src1, cpu_regs[a->rs2_or_imm]);
384386b82fe0SRichard Henderson     }
384486b82fe0SRichard Henderson     return func(dc, a->rd, sum);
384586b82fe0SRichard Henderson }
384686b82fe0SRichard Henderson 
384786b82fe0SRichard Henderson static bool do_jmpl(DisasContext *dc, int rd, TCGv src)
384886b82fe0SRichard Henderson {
384986b82fe0SRichard Henderson     /*
385086b82fe0SRichard Henderson      * Preserve pc across advance, so that we can delay
385186b82fe0SRichard Henderson      * the writeback to rd until after src is consumed.
385286b82fe0SRichard Henderson      */
385386b82fe0SRichard Henderson     target_ulong cur_pc = dc->pc;
385486b82fe0SRichard Henderson 
385586b82fe0SRichard Henderson     gen_check_align(dc, src, 3);
385686b82fe0SRichard Henderson 
385786b82fe0SRichard Henderson     gen_mov_pc_npc(dc);
385886b82fe0SRichard Henderson     tcg_gen_mov_tl(cpu_npc, src);
385986b82fe0SRichard Henderson     gen_address_mask(dc, cpu_npc);
386086b82fe0SRichard Henderson     gen_store_gpr(dc, rd, tcg_constant_tl(cur_pc));
386186b82fe0SRichard Henderson 
386286b82fe0SRichard Henderson     dc->npc = DYNAMIC_PC_LOOKUP;
386386b82fe0SRichard Henderson     return true;
386486b82fe0SRichard Henderson }
386586b82fe0SRichard Henderson 
386686b82fe0SRichard Henderson TRANS(JMPL, ALL, do_add_special, a, do_jmpl)
386786b82fe0SRichard Henderson 
386886b82fe0SRichard Henderson static bool do_rett(DisasContext *dc, int rd, TCGv src)
386986b82fe0SRichard Henderson {
387086b82fe0SRichard Henderson     if (!supervisor(dc)) {
387186b82fe0SRichard Henderson         return raise_priv(dc);
387286b82fe0SRichard Henderson     }
387386b82fe0SRichard Henderson 
387486b82fe0SRichard Henderson     gen_check_align(dc, src, 3);
387586b82fe0SRichard Henderson 
387686b82fe0SRichard Henderson     gen_mov_pc_npc(dc);
387786b82fe0SRichard Henderson     tcg_gen_mov_tl(cpu_npc, src);
387886b82fe0SRichard Henderson     gen_helper_rett(tcg_env);
387986b82fe0SRichard Henderson 
388086b82fe0SRichard Henderson     dc->npc = DYNAMIC_PC;
388186b82fe0SRichard Henderson     return true;
388286b82fe0SRichard Henderson }
388386b82fe0SRichard Henderson 
388486b82fe0SRichard Henderson TRANS(RETT, 32, do_add_special, a, do_rett)
388586b82fe0SRichard Henderson 
388686b82fe0SRichard Henderson static bool do_return(DisasContext *dc, int rd, TCGv src)
388786b82fe0SRichard Henderson {
388886b82fe0SRichard Henderson     gen_check_align(dc, src, 3);
38890dfae4f9SRichard Henderson     gen_helper_restore(tcg_env);
389086b82fe0SRichard Henderson 
389186b82fe0SRichard Henderson     gen_mov_pc_npc(dc);
389286b82fe0SRichard Henderson     tcg_gen_mov_tl(cpu_npc, src);
389386b82fe0SRichard Henderson     gen_address_mask(dc, cpu_npc);
389486b82fe0SRichard Henderson 
389586b82fe0SRichard Henderson     dc->npc = DYNAMIC_PC_LOOKUP;
389686b82fe0SRichard Henderson     return true;
389786b82fe0SRichard Henderson }
389886b82fe0SRichard Henderson 
389986b82fe0SRichard Henderson TRANS(RETURN, 64, do_add_special, a, do_return)
390086b82fe0SRichard Henderson 
3901d3825800SRichard Henderson static bool do_save(DisasContext *dc, int rd, TCGv src)
3902d3825800SRichard Henderson {
3903d3825800SRichard Henderson     gen_helper_save(tcg_env);
3904d3825800SRichard Henderson     gen_store_gpr(dc, rd, src);
3905d3825800SRichard Henderson     return advance_pc(dc);
3906d3825800SRichard Henderson }
3907d3825800SRichard Henderson 
3908d3825800SRichard Henderson TRANS(SAVE, ALL, do_add_special, a, do_save)
3909d3825800SRichard Henderson 
3910d3825800SRichard Henderson static bool do_restore(DisasContext *dc, int rd, TCGv src)
3911d3825800SRichard Henderson {
3912d3825800SRichard Henderson     gen_helper_restore(tcg_env);
3913d3825800SRichard Henderson     gen_store_gpr(dc, rd, src);
3914d3825800SRichard Henderson     return advance_pc(dc);
3915d3825800SRichard Henderson }
3916d3825800SRichard Henderson 
3917d3825800SRichard Henderson TRANS(RESTORE, ALL, do_add_special, a, do_restore)
3918d3825800SRichard Henderson 
39198f75b8a4SRichard Henderson static bool do_done_retry(DisasContext *dc, bool done)
39208f75b8a4SRichard Henderson {
39218f75b8a4SRichard Henderson     if (!supervisor(dc)) {
39228f75b8a4SRichard Henderson         return raise_priv(dc);
39238f75b8a4SRichard Henderson     }
39248f75b8a4SRichard Henderson     dc->npc = DYNAMIC_PC;
39258f75b8a4SRichard Henderson     dc->pc = DYNAMIC_PC;
39268f75b8a4SRichard Henderson     translator_io_start(&dc->base);
39278f75b8a4SRichard Henderson     if (done) {
39288f75b8a4SRichard Henderson         gen_helper_done(tcg_env);
39298f75b8a4SRichard Henderson     } else {
39308f75b8a4SRichard Henderson         gen_helper_retry(tcg_env);
39318f75b8a4SRichard Henderson     }
39328f75b8a4SRichard Henderson     return true;
39338f75b8a4SRichard Henderson }
39348f75b8a4SRichard Henderson 
39358f75b8a4SRichard Henderson TRANS(DONE, 64, do_done_retry, true)
39368f75b8a4SRichard Henderson TRANS(RETRY, 64, do_done_retry, false)
39378f75b8a4SRichard Henderson 
39380880d20bSRichard Henderson /*
39390880d20bSRichard Henderson  * Major opcode 11 -- load and store instructions
39400880d20bSRichard Henderson  */
39410880d20bSRichard Henderson 
39420880d20bSRichard Henderson static TCGv gen_ldst_addr(DisasContext *dc, int rs1, bool imm, int rs2_or_imm)
39430880d20bSRichard Henderson {
39440880d20bSRichard Henderson     TCGv addr, tmp = NULL;
39450880d20bSRichard Henderson 
39460880d20bSRichard Henderson     /* For simplicity, we under-decoded the rs2 form. */
39470880d20bSRichard Henderson     if (!imm && rs2_or_imm & ~0x1f) {
39480880d20bSRichard Henderson         return NULL;
39490880d20bSRichard Henderson     }
39500880d20bSRichard Henderson 
39510880d20bSRichard Henderson     addr = gen_load_gpr(dc, rs1);
39520880d20bSRichard Henderson     if (rs2_or_imm) {
39530880d20bSRichard Henderson         tmp = tcg_temp_new();
39540880d20bSRichard Henderson         if (imm) {
39550880d20bSRichard Henderson             tcg_gen_addi_tl(tmp, addr, rs2_or_imm);
39560880d20bSRichard Henderson         } else {
39570880d20bSRichard Henderson             tcg_gen_add_tl(tmp, addr, cpu_regs[rs2_or_imm]);
39580880d20bSRichard Henderson         }
39590880d20bSRichard Henderson         addr = tmp;
39600880d20bSRichard Henderson     }
39610880d20bSRichard Henderson     if (AM_CHECK(dc)) {
39620880d20bSRichard Henderson         if (!tmp) {
39630880d20bSRichard Henderson             tmp = tcg_temp_new();
39640880d20bSRichard Henderson         }
39650880d20bSRichard Henderson         tcg_gen_ext32u_tl(tmp, addr);
39660880d20bSRichard Henderson         addr = tmp;
39670880d20bSRichard Henderson     }
39680880d20bSRichard Henderson     return addr;
39690880d20bSRichard Henderson }
39700880d20bSRichard Henderson 
39710880d20bSRichard Henderson static bool do_ld_gpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp mop)
39720880d20bSRichard Henderson {
39730880d20bSRichard Henderson     TCGv reg, addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
39740880d20bSRichard Henderson     DisasASI da;
39750880d20bSRichard Henderson 
39760880d20bSRichard Henderson     if (addr == NULL) {
39770880d20bSRichard Henderson         return false;
39780880d20bSRichard Henderson     }
39790880d20bSRichard Henderson     da = resolve_asi(dc, a->asi, mop);
39800880d20bSRichard Henderson 
39810880d20bSRichard Henderson     reg = gen_dest_gpr(dc, a->rd);
398242071fc1SRichard Henderson     gen_ld_asi(dc, &da, reg, addr);
39830880d20bSRichard Henderson     gen_store_gpr(dc, a->rd, reg);
39840880d20bSRichard Henderson     return advance_pc(dc);
39850880d20bSRichard Henderson }
39860880d20bSRichard Henderson 
39870880d20bSRichard Henderson TRANS(LDUW, ALL, do_ld_gpr, a, MO_TEUL)
39880880d20bSRichard Henderson TRANS(LDUB, ALL, do_ld_gpr, a, MO_UB)
39890880d20bSRichard Henderson TRANS(LDUH, ALL, do_ld_gpr, a, MO_TEUW)
39900880d20bSRichard Henderson TRANS(LDSB, ALL, do_ld_gpr, a, MO_SB)
39910880d20bSRichard Henderson TRANS(LDSH, ALL, do_ld_gpr, a, MO_TESW)
39920880d20bSRichard Henderson TRANS(LDSW, 64, do_ld_gpr, a, MO_TESL)
39930880d20bSRichard Henderson TRANS(LDX, 64, do_ld_gpr, a, MO_TEUQ)
39940880d20bSRichard Henderson 
39950880d20bSRichard Henderson static bool do_st_gpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp mop)
39960880d20bSRichard Henderson {
39970880d20bSRichard Henderson     TCGv reg, addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
39980880d20bSRichard Henderson     DisasASI da;
39990880d20bSRichard Henderson 
40000880d20bSRichard Henderson     if (addr == NULL) {
40010880d20bSRichard Henderson         return false;
40020880d20bSRichard Henderson     }
40030880d20bSRichard Henderson     da = resolve_asi(dc, a->asi, mop);
40040880d20bSRichard Henderson 
40050880d20bSRichard Henderson     reg = gen_load_gpr(dc, a->rd);
400642071fc1SRichard Henderson     gen_st_asi(dc, &da, reg, addr);
40070880d20bSRichard Henderson     return advance_pc(dc);
40080880d20bSRichard Henderson }
40090880d20bSRichard Henderson 
40100880d20bSRichard Henderson TRANS(STW, ALL, do_st_gpr, a, MO_TEUL)
40110880d20bSRichard Henderson TRANS(STB, ALL, do_st_gpr, a, MO_UB)
40120880d20bSRichard Henderson TRANS(STH, ALL, do_st_gpr, a, MO_TEUW)
40130880d20bSRichard Henderson TRANS(STX, 64, do_st_gpr, a, MO_TEUQ)
40140880d20bSRichard Henderson 
40150880d20bSRichard Henderson static bool trans_LDD(DisasContext *dc, arg_r_r_ri_asi *a)
40160880d20bSRichard Henderson {
40170880d20bSRichard Henderson     TCGv addr;
40180880d20bSRichard Henderson     DisasASI da;
40190880d20bSRichard Henderson 
40200880d20bSRichard Henderson     if (a->rd & 1) {
40210880d20bSRichard Henderson         return false;
40220880d20bSRichard Henderson     }
40230880d20bSRichard Henderson     addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
40240880d20bSRichard Henderson     if (addr == NULL) {
40250880d20bSRichard Henderson         return false;
40260880d20bSRichard Henderson     }
40270880d20bSRichard Henderson     da = resolve_asi(dc, a->asi, MO_TEUQ);
402842071fc1SRichard Henderson     gen_ldda_asi(dc, &da, addr, a->rd);
40290880d20bSRichard Henderson     return advance_pc(dc);
40300880d20bSRichard Henderson }
40310880d20bSRichard Henderson 
40320880d20bSRichard Henderson static bool trans_STD(DisasContext *dc, arg_r_r_ri_asi *a)
40330880d20bSRichard Henderson {
40340880d20bSRichard Henderson     TCGv addr;
40350880d20bSRichard Henderson     DisasASI da;
40360880d20bSRichard Henderson 
40370880d20bSRichard Henderson     if (a->rd & 1) {
40380880d20bSRichard Henderson         return false;
40390880d20bSRichard Henderson     }
40400880d20bSRichard Henderson     addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
40410880d20bSRichard Henderson     if (addr == NULL) {
40420880d20bSRichard Henderson         return false;
40430880d20bSRichard Henderson     }
40440880d20bSRichard Henderson     da = resolve_asi(dc, a->asi, MO_TEUQ);
404542071fc1SRichard Henderson     gen_stda_asi(dc, &da, addr, a->rd);
40460880d20bSRichard Henderson     return advance_pc(dc);
40470880d20bSRichard Henderson }
40480880d20bSRichard Henderson 
4049cf07cd1eSRichard Henderson static bool trans_LDSTUB(DisasContext *dc, arg_r_r_ri_asi *a)
4050cf07cd1eSRichard Henderson {
4051cf07cd1eSRichard Henderson     TCGv addr, reg;
4052cf07cd1eSRichard Henderson     DisasASI da;
4053cf07cd1eSRichard Henderson 
4054cf07cd1eSRichard Henderson     addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
4055cf07cd1eSRichard Henderson     if (addr == NULL) {
4056cf07cd1eSRichard Henderson         return false;
4057cf07cd1eSRichard Henderson     }
4058cf07cd1eSRichard Henderson     da = resolve_asi(dc, a->asi, MO_UB);
4059cf07cd1eSRichard Henderson 
4060cf07cd1eSRichard Henderson     reg = gen_dest_gpr(dc, a->rd);
4061cf07cd1eSRichard Henderson     gen_ldstub_asi(dc, &da, reg, addr);
4062cf07cd1eSRichard Henderson     gen_store_gpr(dc, a->rd, reg);
4063cf07cd1eSRichard Henderson     return advance_pc(dc);
4064cf07cd1eSRichard Henderson }
4065cf07cd1eSRichard Henderson 
4066dca544b9SRichard Henderson static bool trans_SWAP(DisasContext *dc, arg_r_r_ri_asi *a)
4067dca544b9SRichard Henderson {
4068dca544b9SRichard Henderson     TCGv addr, dst, src;
4069dca544b9SRichard Henderson     DisasASI da;
4070dca544b9SRichard Henderson 
4071dca544b9SRichard Henderson     addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
4072dca544b9SRichard Henderson     if (addr == NULL) {
4073dca544b9SRichard Henderson         return false;
4074dca544b9SRichard Henderson     }
4075dca544b9SRichard Henderson     da = resolve_asi(dc, a->asi, MO_TEUL);
4076dca544b9SRichard Henderson 
4077dca544b9SRichard Henderson     dst = gen_dest_gpr(dc, a->rd);
4078dca544b9SRichard Henderson     src = gen_load_gpr(dc, a->rd);
4079dca544b9SRichard Henderson     gen_swap_asi(dc, &da, dst, src, addr);
4080dca544b9SRichard Henderson     gen_store_gpr(dc, a->rd, dst);
4081dca544b9SRichard Henderson     return advance_pc(dc);
4082dca544b9SRichard Henderson }
4083dca544b9SRichard Henderson 
4084d0a11d25SRichard Henderson static bool do_casa(DisasContext *dc, arg_r_r_ri_asi *a, MemOp mop)
4085d0a11d25SRichard Henderson {
4086d0a11d25SRichard Henderson     TCGv addr, o, n, c;
4087d0a11d25SRichard Henderson     DisasASI da;
4088d0a11d25SRichard Henderson 
4089d0a11d25SRichard Henderson     addr = gen_ldst_addr(dc, a->rs1, true, 0);
4090d0a11d25SRichard Henderson     if (addr == NULL) {
4091d0a11d25SRichard Henderson         return false;
4092d0a11d25SRichard Henderson     }
4093d0a11d25SRichard Henderson     da = resolve_asi(dc, a->asi, mop);
4094d0a11d25SRichard Henderson 
4095d0a11d25SRichard Henderson     o = gen_dest_gpr(dc, a->rd);
4096d0a11d25SRichard Henderson     n = gen_load_gpr(dc, a->rd);
4097d0a11d25SRichard Henderson     c = gen_load_gpr(dc, a->rs2_or_imm);
4098d0a11d25SRichard Henderson     gen_cas_asi(dc, &da, o, n, c, addr);
4099d0a11d25SRichard Henderson     gen_store_gpr(dc, a->rd, o);
4100d0a11d25SRichard Henderson     return advance_pc(dc);
4101d0a11d25SRichard Henderson }
4102d0a11d25SRichard Henderson 
4103d0a11d25SRichard Henderson TRANS(CASA, CASA, do_casa, a, MO_TEUL)
4104d0a11d25SRichard Henderson TRANS(CASXA, 64, do_casa, a, MO_TEUQ)
4105d0a11d25SRichard Henderson 
410606c060d9SRichard Henderson static bool do_ld_fpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp sz)
410706c060d9SRichard Henderson {
410806c060d9SRichard Henderson     TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
410906c060d9SRichard Henderson     DisasASI da;
411006c060d9SRichard Henderson 
411106c060d9SRichard Henderson     if (addr == NULL) {
411206c060d9SRichard Henderson         return false;
411306c060d9SRichard Henderson     }
411406c060d9SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
411506c060d9SRichard Henderson         return true;
411606c060d9SRichard Henderson     }
411706c060d9SRichard Henderson     if (sz == MO_128 && gen_trap_float128(dc)) {
411806c060d9SRichard Henderson         return true;
411906c060d9SRichard Henderson     }
412006c060d9SRichard Henderson     da = resolve_asi(dc, a->asi, MO_TE | sz);
4121287b1152SRichard Henderson     gen_ldf_asi(dc, &da, sz, addr, a->rd);
412206c060d9SRichard Henderson     gen_update_fprs_dirty(dc, a->rd);
412306c060d9SRichard Henderson     return advance_pc(dc);
412406c060d9SRichard Henderson }
412506c060d9SRichard Henderson 
412606c060d9SRichard Henderson TRANS(LDF, ALL, do_ld_fpr, a, MO_32)
412706c060d9SRichard Henderson TRANS(LDDF, ALL, do_ld_fpr, a, MO_64)
412806c060d9SRichard Henderson TRANS(LDQF, ALL, do_ld_fpr, a, MO_128)
412906c060d9SRichard Henderson 
4130287b1152SRichard Henderson TRANS(LDFA, 64, do_ld_fpr, a, MO_32)
4131287b1152SRichard Henderson TRANS(LDDFA, 64, do_ld_fpr, a, MO_64)
4132287b1152SRichard Henderson TRANS(LDQFA, 64, do_ld_fpr, a, MO_128)
4133287b1152SRichard Henderson 
413406c060d9SRichard Henderson static bool do_st_fpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp sz)
413506c060d9SRichard Henderson {
413606c060d9SRichard Henderson     TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
413706c060d9SRichard Henderson     DisasASI da;
413806c060d9SRichard Henderson 
413906c060d9SRichard Henderson     if (addr == NULL) {
414006c060d9SRichard Henderson         return false;
414106c060d9SRichard Henderson     }
414206c060d9SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
414306c060d9SRichard Henderson         return true;
414406c060d9SRichard Henderson     }
414506c060d9SRichard Henderson     if (sz == MO_128 && gen_trap_float128(dc)) {
414606c060d9SRichard Henderson         return true;
414706c060d9SRichard Henderson     }
414806c060d9SRichard Henderson     da = resolve_asi(dc, a->asi, MO_TE | sz);
4149287b1152SRichard Henderson     gen_stf_asi(dc, &da, sz, addr, a->rd);
415006c060d9SRichard Henderson     return advance_pc(dc);
415106c060d9SRichard Henderson }
415206c060d9SRichard Henderson 
415306c060d9SRichard Henderson TRANS(STF, ALL, do_st_fpr, a, MO_32)
415406c060d9SRichard Henderson TRANS(STDF, ALL, do_st_fpr, a, MO_64)
415506c060d9SRichard Henderson TRANS(STQF, ALL, do_st_fpr, a, MO_128)
415606c060d9SRichard Henderson 
4157287b1152SRichard Henderson TRANS(STFA, 64, do_st_fpr, a, MO_32)
4158287b1152SRichard Henderson TRANS(STDFA, 64, do_st_fpr, a, MO_64)
4159287b1152SRichard Henderson TRANS(STQFA, 64, do_st_fpr, a, MO_128)
4160287b1152SRichard Henderson 
416106c060d9SRichard Henderson static bool trans_STDFQ(DisasContext *dc, arg_STDFQ *a)
416206c060d9SRichard Henderson {
416306c060d9SRichard Henderson     if (!avail_32(dc)) {
416406c060d9SRichard Henderson         return false;
416506c060d9SRichard Henderson     }
416606c060d9SRichard Henderson     if (!supervisor(dc)) {
416706c060d9SRichard Henderson         return raise_priv(dc);
416806c060d9SRichard Henderson     }
416906c060d9SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
417006c060d9SRichard Henderson         return true;
417106c060d9SRichard Henderson     }
417206c060d9SRichard Henderson     gen_op_fpexception_im(dc, FSR_FTT_SEQ_ERROR);
417306c060d9SRichard Henderson     return true;
417406c060d9SRichard Henderson }
417506c060d9SRichard Henderson 
4176d8c5b92fSRichard Henderson static bool trans_LDFSR(DisasContext *dc, arg_r_r_ri *a)
41773d3c0673SRichard Henderson {
41783590f01eSRichard Henderson     TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
4179d8c5b92fSRichard Henderson     TCGv_i32 tmp;
41803590f01eSRichard Henderson 
41813d3c0673SRichard Henderson     if (addr == NULL) {
41823d3c0673SRichard Henderson         return false;
41833d3c0673SRichard Henderson     }
41843d3c0673SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
41853d3c0673SRichard Henderson         return true;
41863d3c0673SRichard Henderson     }
4187d8c5b92fSRichard Henderson 
4188d8c5b92fSRichard Henderson     tmp = tcg_temp_new_i32();
4189d8c5b92fSRichard Henderson     tcg_gen_qemu_ld_i32(tmp, addr, dc->mem_idx, MO_TEUL | MO_ALIGN);
4190d8c5b92fSRichard Henderson 
4191d8c5b92fSRichard Henderson     tcg_gen_extract_i32(cpu_fcc[0], tmp, FSR_FCC0_SHIFT, 2);
4192d8c5b92fSRichard Henderson     /* LDFSR does not change FCC[1-3]. */
4193d8c5b92fSRichard Henderson 
4194d8c5b92fSRichard Henderson     gen_helper_set_fsr_nofcc_noftt(tcg_env, tmp);
41953d3c0673SRichard Henderson     return advance_pc(dc);
41963d3c0673SRichard Henderson }
41973d3c0673SRichard Henderson 
4198d8c5b92fSRichard Henderson static bool trans_LDXFSR(DisasContext *dc, arg_r_r_ri *a)
4199d8c5b92fSRichard Henderson {
4200d8c5b92fSRichard Henderson #ifdef TARGET_SPARC64
4201d8c5b92fSRichard Henderson     TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
4202d8c5b92fSRichard Henderson     TCGv_i64 t64;
4203d8c5b92fSRichard Henderson     TCGv_i32 lo, hi;
4204d8c5b92fSRichard Henderson 
4205d8c5b92fSRichard Henderson     if (addr == NULL) {
4206d8c5b92fSRichard Henderson         return false;
4207d8c5b92fSRichard Henderson     }
4208d8c5b92fSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4209d8c5b92fSRichard Henderson         return true;
4210d8c5b92fSRichard Henderson     }
4211d8c5b92fSRichard Henderson 
4212d8c5b92fSRichard Henderson     t64 = tcg_temp_new_i64();
4213d8c5b92fSRichard Henderson     tcg_gen_qemu_ld_i64(t64, addr, dc->mem_idx, MO_TEUQ | MO_ALIGN);
4214d8c5b92fSRichard Henderson 
4215d8c5b92fSRichard Henderson     lo = tcg_temp_new_i32();
4216d8c5b92fSRichard Henderson     hi = cpu_fcc[3];
4217d8c5b92fSRichard Henderson     tcg_gen_extr_i64_i32(lo, hi, t64);
4218d8c5b92fSRichard Henderson     tcg_gen_extract_i32(cpu_fcc[0], lo, FSR_FCC0_SHIFT, 2);
4219d8c5b92fSRichard Henderson     tcg_gen_extract_i32(cpu_fcc[1], hi, FSR_FCC1_SHIFT - 32, 2);
4220d8c5b92fSRichard Henderson     tcg_gen_extract_i32(cpu_fcc[2], hi, FSR_FCC2_SHIFT - 32, 2);
4221d8c5b92fSRichard Henderson     tcg_gen_extract_i32(cpu_fcc[3], hi, FSR_FCC3_SHIFT - 32, 2);
4222d8c5b92fSRichard Henderson 
4223d8c5b92fSRichard Henderson     gen_helper_set_fsr_nofcc_noftt(tcg_env, lo);
4224d8c5b92fSRichard Henderson     return advance_pc(dc);
4225d8c5b92fSRichard Henderson #else
4226d8c5b92fSRichard Henderson     return false;
4227d8c5b92fSRichard Henderson #endif
4228d8c5b92fSRichard Henderson }
42293d3c0673SRichard Henderson 
42303d3c0673SRichard Henderson static bool do_stfsr(DisasContext *dc, arg_r_r_ri *a, MemOp mop)
42313d3c0673SRichard Henderson {
42323d3c0673SRichard Henderson     TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
42331ccd6e13SRichard Henderson     TCGv fsr;
42341ccd6e13SRichard Henderson 
42353d3c0673SRichard Henderson     if (addr == NULL) {
42363d3c0673SRichard Henderson         return false;
42373d3c0673SRichard Henderson     }
42383d3c0673SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
42393d3c0673SRichard Henderson         return true;
42403d3c0673SRichard Henderson     }
42411ccd6e13SRichard Henderson 
42421ccd6e13SRichard Henderson     fsr = tcg_temp_new();
42431ccd6e13SRichard Henderson     gen_helper_get_fsr(fsr, tcg_env);
42441ccd6e13SRichard Henderson     tcg_gen_qemu_st_tl(fsr, addr, dc->mem_idx, mop | MO_ALIGN);
42453d3c0673SRichard Henderson     return advance_pc(dc);
42463d3c0673SRichard Henderson }
42473d3c0673SRichard Henderson 
42483d3c0673SRichard Henderson TRANS(STFSR, ALL, do_stfsr, a, MO_TEUL)
42493d3c0673SRichard Henderson TRANS(STXFSR, 64, do_stfsr, a, MO_TEUQ)
42503d3c0673SRichard Henderson 
4251*1210a036SRichard Henderson static bool do_fc(DisasContext *dc, int rd, int32_t c)
42523a38260eSRichard Henderson {
42533a38260eSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
42543a38260eSRichard Henderson         return true;
42553a38260eSRichard Henderson     }
4256*1210a036SRichard Henderson     gen_store_fpr_F(dc, rd, tcg_constant_i32(c));
42573a38260eSRichard Henderson     return advance_pc(dc);
42583a38260eSRichard Henderson }
42593a38260eSRichard Henderson 
42603a38260eSRichard Henderson TRANS(FZEROs, VIS1, do_fc, a->rd, 0)
4261*1210a036SRichard Henderson TRANS(FONEs, VIS1, do_fc, a->rd, -1)
42623a38260eSRichard Henderson 
42633a38260eSRichard Henderson static bool do_dc(DisasContext *dc, int rd, int64_t c)
42643a38260eSRichard Henderson {
42653a38260eSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
42663a38260eSRichard Henderson         return true;
42673a38260eSRichard Henderson     }
4268*1210a036SRichard Henderson     gen_store_fpr_D(dc, rd, tcg_constant_i64(c));
42693a38260eSRichard Henderson     return advance_pc(dc);
42703a38260eSRichard Henderson }
42713a38260eSRichard Henderson 
42723a38260eSRichard Henderson TRANS(FZEROd, VIS1, do_dc, a->rd, 0)
42733a38260eSRichard Henderson TRANS(FONEd, VIS1, do_dc, a->rd, -1)
42743a38260eSRichard Henderson 
4275baf3dbf2SRichard Henderson static bool do_ff(DisasContext *dc, arg_r_r *a,
4276baf3dbf2SRichard Henderson                   void (*func)(TCGv_i32, TCGv_i32))
4277baf3dbf2SRichard Henderson {
4278baf3dbf2SRichard Henderson     TCGv_i32 tmp;
4279baf3dbf2SRichard Henderson 
4280baf3dbf2SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4281baf3dbf2SRichard Henderson         return true;
4282baf3dbf2SRichard Henderson     }
4283baf3dbf2SRichard Henderson 
4284baf3dbf2SRichard Henderson     tmp = gen_load_fpr_F(dc, a->rs);
4285baf3dbf2SRichard Henderson     func(tmp, tmp);
4286baf3dbf2SRichard Henderson     gen_store_fpr_F(dc, a->rd, tmp);
4287baf3dbf2SRichard Henderson     return advance_pc(dc);
4288baf3dbf2SRichard Henderson }
4289baf3dbf2SRichard Henderson 
4290baf3dbf2SRichard Henderson TRANS(FMOVs, ALL, do_ff, a, gen_op_fmovs)
4291baf3dbf2SRichard Henderson TRANS(FNEGs, ALL, do_ff, a, gen_op_fnegs)
4292baf3dbf2SRichard Henderson TRANS(FABSs, ALL, do_ff, a, gen_op_fabss)
4293baf3dbf2SRichard Henderson TRANS(FSRCs, VIS1, do_ff, a, tcg_gen_mov_i32)
4294baf3dbf2SRichard Henderson TRANS(FNOTs, VIS1, do_ff, a, tcg_gen_not_i32)
4295baf3dbf2SRichard Henderson 
42962f722641SRichard Henderson static bool do_fd(DisasContext *dc, arg_r_r *a,
42972f722641SRichard Henderson                   void (*func)(TCGv_i32, TCGv_i64))
42982f722641SRichard Henderson {
42992f722641SRichard Henderson     TCGv_i32 dst;
43002f722641SRichard Henderson     TCGv_i64 src;
43012f722641SRichard Henderson 
43022f722641SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
43032f722641SRichard Henderson         return true;
43042f722641SRichard Henderson     }
43052f722641SRichard Henderson 
4306388a6465SRichard Henderson     dst = tcg_temp_new_i32();
43072f722641SRichard Henderson     src = gen_load_fpr_D(dc, a->rs);
43082f722641SRichard Henderson     func(dst, src);
43092f722641SRichard Henderson     gen_store_fpr_F(dc, a->rd, dst);
43102f722641SRichard Henderson     return advance_pc(dc);
43112f722641SRichard Henderson }
43122f722641SRichard Henderson 
43132f722641SRichard Henderson TRANS(FPACK16, VIS1, do_fd, a, gen_op_fpack16)
43142f722641SRichard Henderson TRANS(FPACKFIX, VIS1, do_fd, a, gen_op_fpackfix)
43152f722641SRichard Henderson 
4316119cb94fSRichard Henderson static bool do_env_ff(DisasContext *dc, arg_r_r *a,
4317119cb94fSRichard Henderson                       void (*func)(TCGv_i32, TCGv_env, TCGv_i32))
4318119cb94fSRichard Henderson {
4319119cb94fSRichard Henderson     TCGv_i32 tmp;
4320119cb94fSRichard Henderson 
4321119cb94fSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4322119cb94fSRichard Henderson         return true;
4323119cb94fSRichard Henderson     }
4324119cb94fSRichard Henderson 
4325119cb94fSRichard Henderson     tmp = gen_load_fpr_F(dc, a->rs);
4326119cb94fSRichard Henderson     func(tmp, tcg_env, tmp);
4327119cb94fSRichard Henderson     gen_store_fpr_F(dc, a->rd, tmp);
4328119cb94fSRichard Henderson     return advance_pc(dc);
4329119cb94fSRichard Henderson }
4330119cb94fSRichard Henderson 
4331119cb94fSRichard Henderson TRANS(FSQRTs, ALL, do_env_ff, a, gen_helper_fsqrts)
4332119cb94fSRichard Henderson TRANS(FiTOs, ALL, do_env_ff, a, gen_helper_fitos)
4333119cb94fSRichard Henderson TRANS(FsTOi, ALL, do_env_ff, a, gen_helper_fstoi)
4334119cb94fSRichard Henderson 
43358c94bcd8SRichard Henderson static bool do_env_fd(DisasContext *dc, arg_r_r *a,
43368c94bcd8SRichard Henderson                       void (*func)(TCGv_i32, TCGv_env, TCGv_i64))
43378c94bcd8SRichard Henderson {
43388c94bcd8SRichard Henderson     TCGv_i32 dst;
43398c94bcd8SRichard Henderson     TCGv_i64 src;
43408c94bcd8SRichard Henderson 
43418c94bcd8SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
43428c94bcd8SRichard Henderson         return true;
43438c94bcd8SRichard Henderson     }
43448c94bcd8SRichard Henderson 
4345388a6465SRichard Henderson     dst = tcg_temp_new_i32();
43468c94bcd8SRichard Henderson     src = gen_load_fpr_D(dc, a->rs);
43478c94bcd8SRichard Henderson     func(dst, tcg_env, src);
43488c94bcd8SRichard Henderson     gen_store_fpr_F(dc, a->rd, dst);
43498c94bcd8SRichard Henderson     return advance_pc(dc);
43508c94bcd8SRichard Henderson }
43518c94bcd8SRichard Henderson 
43528c94bcd8SRichard Henderson TRANS(FdTOs, ALL, do_env_fd, a, gen_helper_fdtos)
43538c94bcd8SRichard Henderson TRANS(FdTOi, ALL, do_env_fd, a, gen_helper_fdtoi)
43548c94bcd8SRichard Henderson TRANS(FxTOs, 64, do_env_fd, a, gen_helper_fxtos)
43558c94bcd8SRichard Henderson 
4356c6d83e4fSRichard Henderson static bool do_dd(DisasContext *dc, arg_r_r *a,
4357c6d83e4fSRichard Henderson                   void (*func)(TCGv_i64, TCGv_i64))
4358c6d83e4fSRichard Henderson {
4359c6d83e4fSRichard Henderson     TCGv_i64 dst, src;
4360c6d83e4fSRichard Henderson 
4361c6d83e4fSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4362c6d83e4fSRichard Henderson         return true;
4363c6d83e4fSRichard Henderson     }
4364c6d83e4fSRichard Henderson 
436552f46d46SRichard Henderson     dst = tcg_temp_new_i64();
4366c6d83e4fSRichard Henderson     src = gen_load_fpr_D(dc, a->rs);
4367c6d83e4fSRichard Henderson     func(dst, src);
4368c6d83e4fSRichard Henderson     gen_store_fpr_D(dc, a->rd, dst);
4369c6d83e4fSRichard Henderson     return advance_pc(dc);
4370c6d83e4fSRichard Henderson }
4371c6d83e4fSRichard Henderson 
4372c6d83e4fSRichard Henderson TRANS(FMOVd, 64, do_dd, a, gen_op_fmovd)
4373c6d83e4fSRichard Henderson TRANS(FNEGd, 64, do_dd, a, gen_op_fnegd)
4374c6d83e4fSRichard Henderson TRANS(FABSd, 64, do_dd, a, gen_op_fabsd)
4375c6d83e4fSRichard Henderson TRANS(FSRCd, VIS1, do_dd, a, tcg_gen_mov_i64)
4376c6d83e4fSRichard Henderson TRANS(FNOTd, VIS1, do_dd, a, tcg_gen_not_i64)
4377c6d83e4fSRichard Henderson 
43788aa418b3SRichard Henderson static bool do_env_dd(DisasContext *dc, arg_r_r *a,
43798aa418b3SRichard Henderson                       void (*func)(TCGv_i64, TCGv_env, TCGv_i64))
43808aa418b3SRichard Henderson {
43818aa418b3SRichard Henderson     TCGv_i64 dst, src;
43828aa418b3SRichard Henderson 
43838aa418b3SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
43848aa418b3SRichard Henderson         return true;
43858aa418b3SRichard Henderson     }
43868aa418b3SRichard Henderson 
438752f46d46SRichard Henderson     dst = tcg_temp_new_i64();
43888aa418b3SRichard Henderson     src = gen_load_fpr_D(dc, a->rs);
43898aa418b3SRichard Henderson     func(dst, tcg_env, src);
43908aa418b3SRichard Henderson     gen_store_fpr_D(dc, a->rd, dst);
43918aa418b3SRichard Henderson     return advance_pc(dc);
43928aa418b3SRichard Henderson }
43938aa418b3SRichard Henderson 
43948aa418b3SRichard Henderson TRANS(FSQRTd, ALL, do_env_dd, a, gen_helper_fsqrtd)
43958aa418b3SRichard Henderson TRANS(FxTOd, 64, do_env_dd, a, gen_helper_fxtod)
43968aa418b3SRichard Henderson TRANS(FdTOx, 64, do_env_dd, a, gen_helper_fdtox)
43978aa418b3SRichard Henderson 
43987b616f36SRichard Henderson static bool do_df(DisasContext *dc, arg_r_r *a,
43997b616f36SRichard Henderson                   void (*func)(TCGv_i64, TCGv_i32))
44007b616f36SRichard Henderson {
44017b616f36SRichard Henderson     TCGv_i64 dst;
44027b616f36SRichard Henderson     TCGv_i32 src;
44037b616f36SRichard Henderson 
44047b616f36SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
44057b616f36SRichard Henderson         return true;
44067b616f36SRichard Henderson     }
44077b616f36SRichard Henderson 
44087b616f36SRichard Henderson     dst = tcg_temp_new_i64();
44097b616f36SRichard Henderson     src = gen_load_fpr_F(dc, a->rs);
44107b616f36SRichard Henderson     func(dst, src);
44117b616f36SRichard Henderson     gen_store_fpr_D(dc, a->rd, dst);
44127b616f36SRichard Henderson     return advance_pc(dc);
44137b616f36SRichard Henderson }
44147b616f36SRichard Henderson 
44157b616f36SRichard Henderson TRANS(FEXPAND, VIS1, do_df, a, gen_helper_fexpand)
44167b616f36SRichard Henderson 
4417199d43efSRichard Henderson static bool do_env_df(DisasContext *dc, arg_r_r *a,
4418199d43efSRichard Henderson                       void (*func)(TCGv_i64, TCGv_env, TCGv_i32))
4419199d43efSRichard Henderson {
4420199d43efSRichard Henderson     TCGv_i64 dst;
4421199d43efSRichard Henderson     TCGv_i32 src;
4422199d43efSRichard Henderson 
4423199d43efSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4424199d43efSRichard Henderson         return true;
4425199d43efSRichard Henderson     }
4426199d43efSRichard Henderson 
442752f46d46SRichard Henderson     dst = tcg_temp_new_i64();
4428199d43efSRichard Henderson     src = gen_load_fpr_F(dc, a->rs);
4429199d43efSRichard Henderson     func(dst, tcg_env, src);
4430199d43efSRichard Henderson     gen_store_fpr_D(dc, a->rd, dst);
4431199d43efSRichard Henderson     return advance_pc(dc);
4432199d43efSRichard Henderson }
4433199d43efSRichard Henderson 
4434199d43efSRichard Henderson TRANS(FiTOd, ALL, do_env_df, a, gen_helper_fitod)
4435199d43efSRichard Henderson TRANS(FsTOd, ALL, do_env_df, a, gen_helper_fstod)
4436199d43efSRichard Henderson TRANS(FsTOx, 64, do_env_df, a, gen_helper_fstox)
4437199d43efSRichard Henderson 
4438daf457d4SRichard Henderson static bool do_qq(DisasContext *dc, arg_r_r *a,
4439daf457d4SRichard Henderson                   void (*func)(TCGv_i128, TCGv_i128))
4440f4e18df5SRichard Henderson {
444133ec4245SRichard Henderson     TCGv_i128 t;
4442f4e18df5SRichard Henderson 
4443f4e18df5SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4444f4e18df5SRichard Henderson         return true;
4445f4e18df5SRichard Henderson     }
4446f4e18df5SRichard Henderson     if (gen_trap_float128(dc)) {
4447f4e18df5SRichard Henderson         return true;
4448f4e18df5SRichard Henderson     }
4449f4e18df5SRichard Henderson 
4450f4e18df5SRichard Henderson     gen_op_clear_ieee_excp_and_FTT();
445133ec4245SRichard Henderson     t = gen_load_fpr_Q(dc, a->rs);
4452daf457d4SRichard Henderson     func(t, t);
445333ec4245SRichard Henderson     gen_store_fpr_Q(dc, a->rd, t);
4454f4e18df5SRichard Henderson     return advance_pc(dc);
4455f4e18df5SRichard Henderson }
4456f4e18df5SRichard Henderson 
4457daf457d4SRichard Henderson TRANS(FMOVq, 64, do_qq, a, tcg_gen_mov_i128)
4458daf457d4SRichard Henderson TRANS(FNEGq, 64, do_qq, a, gen_op_fnegq)
4459daf457d4SRichard Henderson TRANS(FABSq, 64, do_qq, a, gen_op_fabsq)
4460f4e18df5SRichard Henderson 
4461c995216bSRichard Henderson static bool do_env_qq(DisasContext *dc, arg_r_r *a,
4462e41716beSRichard Henderson                       void (*func)(TCGv_i128, TCGv_env, TCGv_i128))
4463c995216bSRichard Henderson {
4464e41716beSRichard Henderson     TCGv_i128 t;
4465e41716beSRichard Henderson 
4466c995216bSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4467c995216bSRichard Henderson         return true;
4468c995216bSRichard Henderson     }
4469c995216bSRichard Henderson     if (gen_trap_float128(dc)) {
4470c995216bSRichard Henderson         return true;
4471c995216bSRichard Henderson     }
4472c995216bSRichard Henderson 
4473e41716beSRichard Henderson     t = gen_load_fpr_Q(dc, a->rs);
4474e41716beSRichard Henderson     func(t, tcg_env, t);
4475e41716beSRichard Henderson     gen_store_fpr_Q(dc, a->rd, t);
4476c995216bSRichard Henderson     return advance_pc(dc);
4477c995216bSRichard Henderson }
4478c995216bSRichard Henderson 
4479c995216bSRichard Henderson TRANS(FSQRTq, ALL, do_env_qq, a, gen_helper_fsqrtq)
4480c995216bSRichard Henderson 
4481bd9c5c42SRichard Henderson static bool do_env_fq(DisasContext *dc, arg_r_r *a,
4482d81e3efeSRichard Henderson                       void (*func)(TCGv_i32, TCGv_env, TCGv_i128))
4483bd9c5c42SRichard Henderson {
4484d81e3efeSRichard Henderson     TCGv_i128 src;
4485bd9c5c42SRichard Henderson     TCGv_i32 dst;
4486bd9c5c42SRichard Henderson 
4487bd9c5c42SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4488bd9c5c42SRichard Henderson         return true;
4489bd9c5c42SRichard Henderson     }
4490bd9c5c42SRichard Henderson     if (gen_trap_float128(dc)) {
4491bd9c5c42SRichard Henderson         return true;
4492bd9c5c42SRichard Henderson     }
4493bd9c5c42SRichard Henderson 
4494d81e3efeSRichard Henderson     src = gen_load_fpr_Q(dc, a->rs);
4495388a6465SRichard Henderson     dst = tcg_temp_new_i32();
4496d81e3efeSRichard Henderson     func(dst, tcg_env, src);
4497bd9c5c42SRichard Henderson     gen_store_fpr_F(dc, a->rd, dst);
4498bd9c5c42SRichard Henderson     return advance_pc(dc);
4499bd9c5c42SRichard Henderson }
4500bd9c5c42SRichard Henderson 
4501bd9c5c42SRichard Henderson TRANS(FqTOs, ALL, do_env_fq, a, gen_helper_fqtos)
4502bd9c5c42SRichard Henderson TRANS(FqTOi, ALL, do_env_fq, a, gen_helper_fqtoi)
4503bd9c5c42SRichard Henderson 
45041617586fSRichard Henderson static bool do_env_dq(DisasContext *dc, arg_r_r *a,
450525a5769eSRichard Henderson                       void (*func)(TCGv_i64, TCGv_env, TCGv_i128))
45061617586fSRichard Henderson {
450725a5769eSRichard Henderson     TCGv_i128 src;
45081617586fSRichard Henderson     TCGv_i64 dst;
45091617586fSRichard Henderson 
45101617586fSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
45111617586fSRichard Henderson         return true;
45121617586fSRichard Henderson     }
45131617586fSRichard Henderson     if (gen_trap_float128(dc)) {
45141617586fSRichard Henderson         return true;
45151617586fSRichard Henderson     }
45161617586fSRichard Henderson 
451725a5769eSRichard Henderson     src = gen_load_fpr_Q(dc, a->rs);
451852f46d46SRichard Henderson     dst = tcg_temp_new_i64();
451925a5769eSRichard Henderson     func(dst, tcg_env, src);
45201617586fSRichard Henderson     gen_store_fpr_D(dc, a->rd, dst);
45211617586fSRichard Henderson     return advance_pc(dc);
45221617586fSRichard Henderson }
45231617586fSRichard Henderson 
45241617586fSRichard Henderson TRANS(FqTOd, ALL, do_env_dq, a, gen_helper_fqtod)
45251617586fSRichard Henderson TRANS(FqTOx, 64, do_env_dq, a, gen_helper_fqtox)
45261617586fSRichard Henderson 
452713ebcc77SRichard Henderson static bool do_env_qf(DisasContext *dc, arg_r_r *a,
45280b2a61ccSRichard Henderson                       void (*func)(TCGv_i128, TCGv_env, TCGv_i32))
452913ebcc77SRichard Henderson {
453013ebcc77SRichard Henderson     TCGv_i32 src;
45310b2a61ccSRichard Henderson     TCGv_i128 dst;
453213ebcc77SRichard Henderson 
453313ebcc77SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
453413ebcc77SRichard Henderson         return true;
453513ebcc77SRichard Henderson     }
453613ebcc77SRichard Henderson     if (gen_trap_float128(dc)) {
453713ebcc77SRichard Henderson         return true;
453813ebcc77SRichard Henderson     }
453913ebcc77SRichard Henderson 
454013ebcc77SRichard Henderson     src = gen_load_fpr_F(dc, a->rs);
45410b2a61ccSRichard Henderson     dst = tcg_temp_new_i128();
45420b2a61ccSRichard Henderson     func(dst, tcg_env, src);
45430b2a61ccSRichard Henderson     gen_store_fpr_Q(dc, a->rd, dst);
454413ebcc77SRichard Henderson     return advance_pc(dc);
454513ebcc77SRichard Henderson }
454613ebcc77SRichard Henderson 
454713ebcc77SRichard Henderson TRANS(FiTOq, ALL, do_env_qf, a, gen_helper_fitoq)
454813ebcc77SRichard Henderson TRANS(FsTOq, ALL, do_env_qf, a, gen_helper_fstoq)
454913ebcc77SRichard Henderson 
45507b8e3e1aSRichard Henderson static bool do_env_qd(DisasContext *dc, arg_r_r *a,
4551fdc50716SRichard Henderson                       void (*func)(TCGv_i128, TCGv_env, TCGv_i64))
45527b8e3e1aSRichard Henderson {
45537b8e3e1aSRichard Henderson     TCGv_i64 src;
4554fdc50716SRichard Henderson     TCGv_i128 dst;
45557b8e3e1aSRichard Henderson 
45567b8e3e1aSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
45577b8e3e1aSRichard Henderson         return true;
45587b8e3e1aSRichard Henderson     }
45597b8e3e1aSRichard Henderson     if (gen_trap_float128(dc)) {
45607b8e3e1aSRichard Henderson         return true;
45617b8e3e1aSRichard Henderson     }
45627b8e3e1aSRichard Henderson 
45637b8e3e1aSRichard Henderson     src = gen_load_fpr_D(dc, a->rs);
4564fdc50716SRichard Henderson     dst = tcg_temp_new_i128();
4565fdc50716SRichard Henderson     func(dst, tcg_env, src);
4566fdc50716SRichard Henderson     gen_store_fpr_Q(dc, a->rd, dst);
45677b8e3e1aSRichard Henderson     return advance_pc(dc);
45687b8e3e1aSRichard Henderson }
45697b8e3e1aSRichard Henderson 
45707b8e3e1aSRichard Henderson TRANS(FdTOq, ALL, do_env_qd, a, gen_helper_fdtoq)
45717b8e3e1aSRichard Henderson TRANS(FxTOq, 64, do_env_qd, a, gen_helper_fxtoq)
45727b8e3e1aSRichard Henderson 
45737f10b52fSRichard Henderson static bool do_fff(DisasContext *dc, arg_r_r_r *a,
45747f10b52fSRichard Henderson                    void (*func)(TCGv_i32, TCGv_i32, TCGv_i32))
45757f10b52fSRichard Henderson {
45767f10b52fSRichard Henderson     TCGv_i32 src1, src2;
45777f10b52fSRichard Henderson 
45787f10b52fSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
45797f10b52fSRichard Henderson         return true;
45807f10b52fSRichard Henderson     }
45817f10b52fSRichard Henderson 
45827f10b52fSRichard Henderson     src1 = gen_load_fpr_F(dc, a->rs1);
45837f10b52fSRichard Henderson     src2 = gen_load_fpr_F(dc, a->rs2);
45847f10b52fSRichard Henderson     func(src1, src1, src2);
45857f10b52fSRichard Henderson     gen_store_fpr_F(dc, a->rd, src1);
45867f10b52fSRichard Henderson     return advance_pc(dc);
45877f10b52fSRichard Henderson }
45887f10b52fSRichard Henderson 
45897f10b52fSRichard Henderson TRANS(FPADD16s, VIS1, do_fff, a, tcg_gen_vec_add16_i32)
45907f10b52fSRichard Henderson TRANS(FPADD32s, VIS1, do_fff, a, tcg_gen_add_i32)
45917f10b52fSRichard Henderson TRANS(FPSUB16s, VIS1, do_fff, a, tcg_gen_vec_sub16_i32)
45927f10b52fSRichard Henderson TRANS(FPSUB32s, VIS1, do_fff, a, tcg_gen_sub_i32)
45937f10b52fSRichard Henderson TRANS(FNORs, VIS1, do_fff, a, tcg_gen_nor_i32)
45947f10b52fSRichard Henderson TRANS(FANDNOTs, VIS1, do_fff, a, tcg_gen_andc_i32)
45957f10b52fSRichard Henderson TRANS(FXORs, VIS1, do_fff, a, tcg_gen_xor_i32)
45967f10b52fSRichard Henderson TRANS(FNANDs, VIS1, do_fff, a, tcg_gen_nand_i32)
45977f10b52fSRichard Henderson TRANS(FANDs, VIS1, do_fff, a, tcg_gen_and_i32)
45987f10b52fSRichard Henderson TRANS(FXNORs, VIS1, do_fff, a, tcg_gen_eqv_i32)
45997f10b52fSRichard Henderson TRANS(FORNOTs, VIS1, do_fff, a, tcg_gen_orc_i32)
46007f10b52fSRichard Henderson TRANS(FORs, VIS1, do_fff, a, tcg_gen_or_i32)
46017f10b52fSRichard Henderson 
4602c1514961SRichard Henderson static bool do_env_fff(DisasContext *dc, arg_r_r_r *a,
4603c1514961SRichard Henderson                        void (*func)(TCGv_i32, TCGv_env, TCGv_i32, TCGv_i32))
4604c1514961SRichard Henderson {
4605c1514961SRichard Henderson     TCGv_i32 src1, src2;
4606c1514961SRichard Henderson 
4607c1514961SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4608c1514961SRichard Henderson         return true;
4609c1514961SRichard Henderson     }
4610c1514961SRichard Henderson 
4611c1514961SRichard Henderson     src1 = gen_load_fpr_F(dc, a->rs1);
4612c1514961SRichard Henderson     src2 = gen_load_fpr_F(dc, a->rs2);
4613c1514961SRichard Henderson     func(src1, tcg_env, src1, src2);
4614c1514961SRichard Henderson     gen_store_fpr_F(dc, a->rd, src1);
4615c1514961SRichard Henderson     return advance_pc(dc);
4616c1514961SRichard Henderson }
4617c1514961SRichard Henderson 
4618c1514961SRichard Henderson TRANS(FADDs, ALL, do_env_fff, a, gen_helper_fadds)
4619c1514961SRichard Henderson TRANS(FSUBs, ALL, do_env_fff, a, gen_helper_fsubs)
4620c1514961SRichard Henderson TRANS(FMULs, ALL, do_env_fff, a, gen_helper_fmuls)
4621c1514961SRichard Henderson TRANS(FDIVs, ALL, do_env_fff, a, gen_helper_fdivs)
4622c1514961SRichard Henderson 
4623a859602cSRichard Henderson static bool do_dff(DisasContext *dc, arg_r_r_r *a,
4624a859602cSRichard Henderson                    void (*func)(TCGv_i64, TCGv_i32, TCGv_i32))
4625a859602cSRichard Henderson {
4626a859602cSRichard Henderson     TCGv_i64 dst;
4627a859602cSRichard Henderson     TCGv_i32 src1, src2;
4628a859602cSRichard Henderson 
4629a859602cSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4630a859602cSRichard Henderson         return true;
4631a859602cSRichard Henderson     }
4632a859602cSRichard Henderson 
463352f46d46SRichard Henderson     dst = tcg_temp_new_i64();
4634a859602cSRichard Henderson     src1 = gen_load_fpr_F(dc, a->rs1);
4635a859602cSRichard Henderson     src2 = gen_load_fpr_F(dc, a->rs2);
4636a859602cSRichard Henderson     func(dst, src1, src2);
4637a859602cSRichard Henderson     gen_store_fpr_D(dc, a->rd, dst);
4638a859602cSRichard Henderson     return advance_pc(dc);
4639a859602cSRichard Henderson }
4640a859602cSRichard Henderson 
4641a859602cSRichard Henderson TRANS(FMUL8x16AU, VIS1, do_dff, a, gen_op_fmul8x16au)
4642a859602cSRichard Henderson TRANS(FMUL8x16AL, VIS1, do_dff, a, gen_op_fmul8x16al)
4643be8998e0SRichard Henderson TRANS(FMULD8SUx16, VIS1, do_dff, a, gen_op_fmuld8sux16)
4644be8998e0SRichard Henderson TRANS(FMULD8ULx16, VIS1, do_dff, a, gen_op_fmuld8ulx16)
4645d3ef26afSRichard Henderson TRANS(FPMERGE, VIS1, do_dff, a, gen_helper_fpmerge)
4646a859602cSRichard Henderson 
46479157dcccSRichard Henderson static bool do_dfd(DisasContext *dc, arg_r_r_r *a,
46489157dcccSRichard Henderson                    void (*func)(TCGv_i64, TCGv_i32, TCGv_i64))
46499157dcccSRichard Henderson {
46509157dcccSRichard Henderson     TCGv_i64 dst, src2;
46519157dcccSRichard Henderson     TCGv_i32 src1;
46529157dcccSRichard Henderson 
46539157dcccSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
46549157dcccSRichard Henderson         return true;
46559157dcccSRichard Henderson     }
46569157dcccSRichard Henderson 
465752f46d46SRichard Henderson     dst = tcg_temp_new_i64();
46589157dcccSRichard Henderson     src1 = gen_load_fpr_F(dc, a->rs1);
46599157dcccSRichard Henderson     src2 = gen_load_fpr_D(dc, a->rs2);
46609157dcccSRichard Henderson     func(dst, src1, src2);
46619157dcccSRichard Henderson     gen_store_fpr_D(dc, a->rd, dst);
46629157dcccSRichard Henderson     return advance_pc(dc);
46639157dcccSRichard Henderson }
46649157dcccSRichard Henderson 
46659157dcccSRichard Henderson TRANS(FMUL8x16, VIS1, do_dfd, a, gen_helper_fmul8x16)
46669157dcccSRichard Henderson 
4667e06c9f83SRichard Henderson static bool do_ddd(DisasContext *dc, arg_r_r_r *a,
4668e06c9f83SRichard Henderson                    void (*func)(TCGv_i64, TCGv_i64, TCGv_i64))
4669e06c9f83SRichard Henderson {
4670e06c9f83SRichard Henderson     TCGv_i64 dst, src1, src2;
4671e06c9f83SRichard Henderson 
4672e06c9f83SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4673e06c9f83SRichard Henderson         return true;
4674e06c9f83SRichard Henderson     }
4675e06c9f83SRichard Henderson 
467652f46d46SRichard Henderson     dst = tcg_temp_new_i64();
4677e06c9f83SRichard Henderson     src1 = gen_load_fpr_D(dc, a->rs1);
4678e06c9f83SRichard Henderson     src2 = gen_load_fpr_D(dc, a->rs2);
4679e06c9f83SRichard Henderson     func(dst, src1, src2);
4680e06c9f83SRichard Henderson     gen_store_fpr_D(dc, a->rd, dst);
4681e06c9f83SRichard Henderson     return advance_pc(dc);
4682e06c9f83SRichard Henderson }
4683e06c9f83SRichard Henderson 
4684e06c9f83SRichard Henderson TRANS(FMUL8SUx16, VIS1, do_ddd, a, gen_helper_fmul8sux16)
4685e06c9f83SRichard Henderson TRANS(FMUL8ULx16, VIS1, do_ddd, a, gen_helper_fmul8ulx16)
4686e06c9f83SRichard Henderson 
4687e06c9f83SRichard Henderson TRANS(FPADD16, VIS1, do_ddd, a, tcg_gen_vec_add16_i64)
4688e06c9f83SRichard Henderson TRANS(FPADD32, VIS1, do_ddd, a, tcg_gen_vec_add32_i64)
4689e06c9f83SRichard Henderson TRANS(FPSUB16, VIS1, do_ddd, a, tcg_gen_vec_sub16_i64)
4690e06c9f83SRichard Henderson TRANS(FPSUB32, VIS1, do_ddd, a, tcg_gen_vec_sub32_i64)
4691e06c9f83SRichard Henderson TRANS(FNORd, VIS1, do_ddd, a, tcg_gen_nor_i64)
4692e06c9f83SRichard Henderson TRANS(FANDNOTd, VIS1, do_ddd, a, tcg_gen_andc_i64)
4693e06c9f83SRichard Henderson TRANS(FXORd, VIS1, do_ddd, a, tcg_gen_xor_i64)
4694e06c9f83SRichard Henderson TRANS(FNANDd, VIS1, do_ddd, a, tcg_gen_nand_i64)
4695e06c9f83SRichard Henderson TRANS(FANDd, VIS1, do_ddd, a, tcg_gen_and_i64)
4696e06c9f83SRichard Henderson TRANS(FXNORd, VIS1, do_ddd, a, tcg_gen_eqv_i64)
4697e06c9f83SRichard Henderson TRANS(FORNOTd, VIS1, do_ddd, a, tcg_gen_orc_i64)
4698e06c9f83SRichard Henderson TRANS(FORd, VIS1, do_ddd, a, tcg_gen_or_i64)
4699e06c9f83SRichard Henderson 
47004b6edc0aSRichard Henderson TRANS(FPACK32, VIS1, do_ddd, a, gen_op_fpack32)
47014b6edc0aSRichard Henderson TRANS(FALIGNDATAg, VIS1, do_ddd, a, gen_op_faligndata)
47024b6edc0aSRichard Henderson TRANS(BSHUFFLE, VIS2, do_ddd, a, gen_op_bshuffle)
47034b6edc0aSRichard Henderson 
4704e2fa6bd1SRichard Henderson static bool do_rdd(DisasContext *dc, arg_r_r_r *a,
4705e2fa6bd1SRichard Henderson                    void (*func)(TCGv, TCGv_i64, TCGv_i64))
4706e2fa6bd1SRichard Henderson {
4707e2fa6bd1SRichard Henderson     TCGv_i64 src1, src2;
4708e2fa6bd1SRichard Henderson     TCGv dst;
4709e2fa6bd1SRichard Henderson 
4710e2fa6bd1SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4711e2fa6bd1SRichard Henderson         return true;
4712e2fa6bd1SRichard Henderson     }
4713e2fa6bd1SRichard Henderson 
4714e2fa6bd1SRichard Henderson     dst = gen_dest_gpr(dc, a->rd);
4715e2fa6bd1SRichard Henderson     src1 = gen_load_fpr_D(dc, a->rs1);
4716e2fa6bd1SRichard Henderson     src2 = gen_load_fpr_D(dc, a->rs2);
4717e2fa6bd1SRichard Henderson     func(dst, src1, src2);
4718e2fa6bd1SRichard Henderson     gen_store_gpr(dc, a->rd, dst);
4719e2fa6bd1SRichard Henderson     return advance_pc(dc);
4720e2fa6bd1SRichard Henderson }
4721e2fa6bd1SRichard Henderson 
4722e2fa6bd1SRichard Henderson TRANS(FPCMPLE16, VIS1, do_rdd, a, gen_helper_fcmple16)
4723e2fa6bd1SRichard Henderson TRANS(FPCMPNE16, VIS1, do_rdd, a, gen_helper_fcmpne16)
4724e2fa6bd1SRichard Henderson TRANS(FPCMPGT16, VIS1, do_rdd, a, gen_helper_fcmpgt16)
4725e2fa6bd1SRichard Henderson TRANS(FPCMPEQ16, VIS1, do_rdd, a, gen_helper_fcmpeq16)
4726e2fa6bd1SRichard Henderson 
4727e2fa6bd1SRichard Henderson TRANS(FPCMPLE32, VIS1, do_rdd, a, gen_helper_fcmple32)
4728e2fa6bd1SRichard Henderson TRANS(FPCMPNE32, VIS1, do_rdd, a, gen_helper_fcmpne32)
4729e2fa6bd1SRichard Henderson TRANS(FPCMPGT32, VIS1, do_rdd, a, gen_helper_fcmpgt32)
4730e2fa6bd1SRichard Henderson TRANS(FPCMPEQ32, VIS1, do_rdd, a, gen_helper_fcmpeq32)
4731e2fa6bd1SRichard Henderson 
4732f2a59b0aSRichard Henderson static bool do_env_ddd(DisasContext *dc, arg_r_r_r *a,
4733f2a59b0aSRichard Henderson                        void (*func)(TCGv_i64, TCGv_env, TCGv_i64, TCGv_i64))
4734f2a59b0aSRichard Henderson {
4735f2a59b0aSRichard Henderson     TCGv_i64 dst, src1, src2;
4736f2a59b0aSRichard Henderson 
4737f2a59b0aSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4738f2a59b0aSRichard Henderson         return true;
4739f2a59b0aSRichard Henderson     }
4740f2a59b0aSRichard Henderson 
474152f46d46SRichard Henderson     dst = tcg_temp_new_i64();
4742f2a59b0aSRichard Henderson     src1 = gen_load_fpr_D(dc, a->rs1);
4743f2a59b0aSRichard Henderson     src2 = gen_load_fpr_D(dc, a->rs2);
4744f2a59b0aSRichard Henderson     func(dst, tcg_env, src1, src2);
4745f2a59b0aSRichard Henderson     gen_store_fpr_D(dc, a->rd, dst);
4746f2a59b0aSRichard Henderson     return advance_pc(dc);
4747f2a59b0aSRichard Henderson }
4748f2a59b0aSRichard Henderson 
4749f2a59b0aSRichard Henderson TRANS(FADDd, ALL, do_env_ddd, a, gen_helper_faddd)
4750f2a59b0aSRichard Henderson TRANS(FSUBd, ALL, do_env_ddd, a, gen_helper_fsubd)
4751f2a59b0aSRichard Henderson TRANS(FMULd, ALL, do_env_ddd, a, gen_helper_fmuld)
4752f2a59b0aSRichard Henderson TRANS(FDIVd, ALL, do_env_ddd, a, gen_helper_fdivd)
4753f2a59b0aSRichard Henderson 
4754ff4c711bSRichard Henderson static bool trans_FsMULd(DisasContext *dc, arg_r_r_r *a)
4755ff4c711bSRichard Henderson {
4756ff4c711bSRichard Henderson     TCGv_i64 dst;
4757ff4c711bSRichard Henderson     TCGv_i32 src1, src2;
4758ff4c711bSRichard Henderson 
4759ff4c711bSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4760ff4c711bSRichard Henderson         return true;
4761ff4c711bSRichard Henderson     }
4762ff4c711bSRichard Henderson     if (!(dc->def->features & CPU_FEATURE_FSMULD)) {
4763ff4c711bSRichard Henderson         return raise_unimpfpop(dc);
4764ff4c711bSRichard Henderson     }
4765ff4c711bSRichard Henderson 
476652f46d46SRichard Henderson     dst = tcg_temp_new_i64();
4767ff4c711bSRichard Henderson     src1 = gen_load_fpr_F(dc, a->rs1);
4768ff4c711bSRichard Henderson     src2 = gen_load_fpr_F(dc, a->rs2);
4769ff4c711bSRichard Henderson     gen_helper_fsmuld(dst, tcg_env, src1, src2);
4770ff4c711bSRichard Henderson     gen_store_fpr_D(dc, a->rd, dst);
4771ff4c711bSRichard Henderson     return advance_pc(dc);
4772ff4c711bSRichard Henderson }
4773ff4c711bSRichard Henderson 
4774afb04344SRichard Henderson static bool do_dddd(DisasContext *dc, arg_r_r_r *a,
4775afb04344SRichard Henderson                     void (*func)(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_i64))
4776afb04344SRichard Henderson {
4777afb04344SRichard Henderson     TCGv_i64 dst, src0, src1, src2;
4778afb04344SRichard Henderson 
4779afb04344SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4780afb04344SRichard Henderson         return true;
4781afb04344SRichard Henderson     }
4782afb04344SRichard Henderson 
478352f46d46SRichard Henderson     dst  = tcg_temp_new_i64();
4784afb04344SRichard Henderson     src0 = gen_load_fpr_D(dc, a->rd);
4785afb04344SRichard Henderson     src1 = gen_load_fpr_D(dc, a->rs1);
4786afb04344SRichard Henderson     src2 = gen_load_fpr_D(dc, a->rs2);
4787afb04344SRichard Henderson     func(dst, src0, src1, src2);
4788afb04344SRichard Henderson     gen_store_fpr_D(dc, a->rd, dst);
4789afb04344SRichard Henderson     return advance_pc(dc);
4790afb04344SRichard Henderson }
4791afb04344SRichard Henderson 
4792afb04344SRichard Henderson TRANS(PDIST, VIS1, do_dddd, a, gen_helper_pdist)
4793afb04344SRichard Henderson 
4794a4056239SRichard Henderson static bool do_env_qqq(DisasContext *dc, arg_r_r_r *a,
479516bedf89SRichard Henderson                        void (*func)(TCGv_i128, TCGv_env, TCGv_i128, TCGv_i128))
4796a4056239SRichard Henderson {
479716bedf89SRichard Henderson     TCGv_i128 src1, src2;
479816bedf89SRichard Henderson 
4799a4056239SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4800a4056239SRichard Henderson         return true;
4801a4056239SRichard Henderson     }
4802a4056239SRichard Henderson     if (gen_trap_float128(dc)) {
4803a4056239SRichard Henderson         return true;
4804a4056239SRichard Henderson     }
4805a4056239SRichard Henderson 
480616bedf89SRichard Henderson     src1 = gen_load_fpr_Q(dc, a->rs1);
480716bedf89SRichard Henderson     src2 = gen_load_fpr_Q(dc, a->rs2);
480816bedf89SRichard Henderson     func(src1, tcg_env, src1, src2);
480916bedf89SRichard Henderson     gen_store_fpr_Q(dc, a->rd, src1);
4810a4056239SRichard Henderson     return advance_pc(dc);
4811a4056239SRichard Henderson }
4812a4056239SRichard Henderson 
4813a4056239SRichard Henderson TRANS(FADDq, ALL, do_env_qqq, a, gen_helper_faddq)
4814a4056239SRichard Henderson TRANS(FSUBq, ALL, do_env_qqq, a, gen_helper_fsubq)
4815a4056239SRichard Henderson TRANS(FMULq, ALL, do_env_qqq, a, gen_helper_fmulq)
4816a4056239SRichard Henderson TRANS(FDIVq, ALL, do_env_qqq, a, gen_helper_fdivq)
4817a4056239SRichard Henderson 
48185e3b17bbSRichard Henderson static bool trans_FdMULq(DisasContext *dc, arg_r_r_r *a)
48195e3b17bbSRichard Henderson {
48205e3b17bbSRichard Henderson     TCGv_i64 src1, src2;
4821ba21dc99SRichard Henderson     TCGv_i128 dst;
48225e3b17bbSRichard Henderson 
48235e3b17bbSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
48245e3b17bbSRichard Henderson         return true;
48255e3b17bbSRichard Henderson     }
48265e3b17bbSRichard Henderson     if (gen_trap_float128(dc)) {
48275e3b17bbSRichard Henderson         return true;
48285e3b17bbSRichard Henderson     }
48295e3b17bbSRichard Henderson 
48305e3b17bbSRichard Henderson     src1 = gen_load_fpr_D(dc, a->rs1);
48315e3b17bbSRichard Henderson     src2 = gen_load_fpr_D(dc, a->rs2);
4832ba21dc99SRichard Henderson     dst = tcg_temp_new_i128();
4833ba21dc99SRichard Henderson     gen_helper_fdmulq(dst, tcg_env, src1, src2);
4834ba21dc99SRichard Henderson     gen_store_fpr_Q(dc, a->rd, dst);
48355e3b17bbSRichard Henderson     return advance_pc(dc);
48365e3b17bbSRichard Henderson }
48375e3b17bbSRichard Henderson 
4838f7ec8155SRichard Henderson static bool do_fmovr(DisasContext *dc, arg_FMOVRs *a, bool is_128,
4839f7ec8155SRichard Henderson                      void (*func)(DisasContext *, DisasCompare *, int, int))
4840f7ec8155SRichard Henderson {
4841f7ec8155SRichard Henderson     DisasCompare cmp;
4842f7ec8155SRichard Henderson 
48432c4f56c9SRichard Henderson     if (!gen_compare_reg(&cmp, a->cond, gen_load_gpr(dc, a->rs1))) {
48442c4f56c9SRichard Henderson         return false;
48452c4f56c9SRichard Henderson     }
4846f7ec8155SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4847f7ec8155SRichard Henderson         return true;
4848f7ec8155SRichard Henderson     }
4849f7ec8155SRichard Henderson     if (is_128 && gen_trap_float128(dc)) {
4850f7ec8155SRichard Henderson         return true;
4851f7ec8155SRichard Henderson     }
4852f7ec8155SRichard Henderson 
4853f7ec8155SRichard Henderson     gen_op_clear_ieee_excp_and_FTT();
4854f7ec8155SRichard Henderson     func(dc, &cmp, a->rd, a->rs2);
4855f7ec8155SRichard Henderson     return advance_pc(dc);
4856f7ec8155SRichard Henderson }
4857f7ec8155SRichard Henderson 
4858f7ec8155SRichard Henderson TRANS(FMOVRs, 64, do_fmovr, a, false, gen_fmovs)
4859f7ec8155SRichard Henderson TRANS(FMOVRd, 64, do_fmovr, a, false, gen_fmovd)
4860f7ec8155SRichard Henderson TRANS(FMOVRq, 64, do_fmovr, a, true, gen_fmovq)
4861f7ec8155SRichard Henderson 
4862f7ec8155SRichard Henderson static bool do_fmovcc(DisasContext *dc, arg_FMOVscc *a, bool is_128,
4863f7ec8155SRichard Henderson                       void (*func)(DisasContext *, DisasCompare *, int, int))
4864f7ec8155SRichard Henderson {
4865f7ec8155SRichard Henderson     DisasCompare cmp;
4866f7ec8155SRichard Henderson 
4867f7ec8155SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4868f7ec8155SRichard Henderson         return true;
4869f7ec8155SRichard Henderson     }
4870f7ec8155SRichard Henderson     if (is_128 && gen_trap_float128(dc)) {
4871f7ec8155SRichard Henderson         return true;
4872f7ec8155SRichard Henderson     }
4873f7ec8155SRichard Henderson 
4874f7ec8155SRichard Henderson     gen_op_clear_ieee_excp_and_FTT();
4875f7ec8155SRichard Henderson     gen_compare(&cmp, a->cc, a->cond, dc);
4876f7ec8155SRichard Henderson     func(dc, &cmp, a->rd, a->rs2);
4877f7ec8155SRichard Henderson     return advance_pc(dc);
4878f7ec8155SRichard Henderson }
4879f7ec8155SRichard Henderson 
4880f7ec8155SRichard Henderson TRANS(FMOVscc, 64, do_fmovcc, a, false, gen_fmovs)
4881f7ec8155SRichard Henderson TRANS(FMOVdcc, 64, do_fmovcc, a, false, gen_fmovd)
4882f7ec8155SRichard Henderson TRANS(FMOVqcc, 64, do_fmovcc, a, true, gen_fmovq)
4883f7ec8155SRichard Henderson 
4884f7ec8155SRichard Henderson static bool do_fmovfcc(DisasContext *dc, arg_FMOVsfcc *a, bool is_128,
4885f7ec8155SRichard Henderson                        void (*func)(DisasContext *, DisasCompare *, int, int))
4886f7ec8155SRichard Henderson {
4887f7ec8155SRichard Henderson     DisasCompare cmp;
4888f7ec8155SRichard Henderson 
4889f7ec8155SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4890f7ec8155SRichard Henderson         return true;
4891f7ec8155SRichard Henderson     }
4892f7ec8155SRichard Henderson     if (is_128 && gen_trap_float128(dc)) {
4893f7ec8155SRichard Henderson         return true;
4894f7ec8155SRichard Henderson     }
4895f7ec8155SRichard Henderson 
4896f7ec8155SRichard Henderson     gen_op_clear_ieee_excp_and_FTT();
4897f7ec8155SRichard Henderson     gen_fcompare(&cmp, a->cc, a->cond);
4898f7ec8155SRichard Henderson     func(dc, &cmp, a->rd, a->rs2);
4899f7ec8155SRichard Henderson     return advance_pc(dc);
4900f7ec8155SRichard Henderson }
4901f7ec8155SRichard Henderson 
4902f7ec8155SRichard Henderson TRANS(FMOVsfcc, 64, do_fmovfcc, a, false, gen_fmovs)
4903f7ec8155SRichard Henderson TRANS(FMOVdfcc, 64, do_fmovfcc, a, false, gen_fmovd)
4904f7ec8155SRichard Henderson TRANS(FMOVqfcc, 64, do_fmovfcc, a, true, gen_fmovq)
4905f7ec8155SRichard Henderson 
490640f9ad21SRichard Henderson static bool do_fcmps(DisasContext *dc, arg_FCMPs *a, bool e)
490740f9ad21SRichard Henderson {
490840f9ad21SRichard Henderson     TCGv_i32 src1, src2;
490940f9ad21SRichard Henderson 
491040f9ad21SRichard Henderson     if (avail_32(dc) && a->cc != 0) {
491140f9ad21SRichard Henderson         return false;
491240f9ad21SRichard Henderson     }
491340f9ad21SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
491440f9ad21SRichard Henderson         return true;
491540f9ad21SRichard Henderson     }
491640f9ad21SRichard Henderson 
491740f9ad21SRichard Henderson     src1 = gen_load_fpr_F(dc, a->rs1);
491840f9ad21SRichard Henderson     src2 = gen_load_fpr_F(dc, a->rs2);
491940f9ad21SRichard Henderson     if (e) {
4920d8c5b92fSRichard Henderson         gen_helper_fcmpes(cpu_fcc[a->cc], tcg_env, src1, src2);
492140f9ad21SRichard Henderson     } else {
4922d8c5b92fSRichard Henderson         gen_helper_fcmps(cpu_fcc[a->cc], tcg_env, src1, src2);
492340f9ad21SRichard Henderson     }
492440f9ad21SRichard Henderson     return advance_pc(dc);
492540f9ad21SRichard Henderson }
492640f9ad21SRichard Henderson 
492740f9ad21SRichard Henderson TRANS(FCMPs, ALL, do_fcmps, a, false)
492840f9ad21SRichard Henderson TRANS(FCMPEs, ALL, do_fcmps, a, true)
492940f9ad21SRichard Henderson 
493040f9ad21SRichard Henderson static bool do_fcmpd(DisasContext *dc, arg_FCMPd *a, bool e)
493140f9ad21SRichard Henderson {
493240f9ad21SRichard Henderson     TCGv_i64 src1, src2;
493340f9ad21SRichard Henderson 
493440f9ad21SRichard Henderson     if (avail_32(dc) && a->cc != 0) {
493540f9ad21SRichard Henderson         return false;
493640f9ad21SRichard Henderson     }
493740f9ad21SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
493840f9ad21SRichard Henderson         return true;
493940f9ad21SRichard Henderson     }
494040f9ad21SRichard Henderson 
494140f9ad21SRichard Henderson     src1 = gen_load_fpr_D(dc, a->rs1);
494240f9ad21SRichard Henderson     src2 = gen_load_fpr_D(dc, a->rs2);
494340f9ad21SRichard Henderson     if (e) {
4944d8c5b92fSRichard Henderson         gen_helper_fcmped(cpu_fcc[a->cc], tcg_env, src1, src2);
494540f9ad21SRichard Henderson     } else {
4946d8c5b92fSRichard Henderson         gen_helper_fcmpd(cpu_fcc[a->cc], tcg_env, src1, src2);
494740f9ad21SRichard Henderson     }
494840f9ad21SRichard Henderson     return advance_pc(dc);
494940f9ad21SRichard Henderson }
495040f9ad21SRichard Henderson 
495140f9ad21SRichard Henderson TRANS(FCMPd, ALL, do_fcmpd, a, false)
495240f9ad21SRichard Henderson TRANS(FCMPEd, ALL, do_fcmpd, a, true)
495340f9ad21SRichard Henderson 
495440f9ad21SRichard Henderson static bool do_fcmpq(DisasContext *dc, arg_FCMPq *a, bool e)
495540f9ad21SRichard Henderson {
4956f3ceafadSRichard Henderson     TCGv_i128 src1, src2;
4957f3ceafadSRichard Henderson 
495840f9ad21SRichard Henderson     if (avail_32(dc) && a->cc != 0) {
495940f9ad21SRichard Henderson         return false;
496040f9ad21SRichard Henderson     }
496140f9ad21SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
496240f9ad21SRichard Henderson         return true;
496340f9ad21SRichard Henderson     }
496440f9ad21SRichard Henderson     if (gen_trap_float128(dc)) {
496540f9ad21SRichard Henderson         return true;
496640f9ad21SRichard Henderson     }
496740f9ad21SRichard Henderson 
4968f3ceafadSRichard Henderson     src1 = gen_load_fpr_Q(dc, a->rs1);
4969f3ceafadSRichard Henderson     src2 = gen_load_fpr_Q(dc, a->rs2);
497040f9ad21SRichard Henderson     if (e) {
4971d8c5b92fSRichard Henderson         gen_helper_fcmpeq(cpu_fcc[a->cc], tcg_env, src1, src2);
497240f9ad21SRichard Henderson     } else {
4973d8c5b92fSRichard Henderson         gen_helper_fcmpq(cpu_fcc[a->cc], tcg_env, src1, src2);
497440f9ad21SRichard Henderson     }
497540f9ad21SRichard Henderson     return advance_pc(dc);
497640f9ad21SRichard Henderson }
497740f9ad21SRichard Henderson 
497840f9ad21SRichard Henderson TRANS(FCMPq, ALL, do_fcmpq, a, false)
497940f9ad21SRichard Henderson TRANS(FCMPEq, ALL, do_fcmpq, a, true)
498040f9ad21SRichard Henderson 
49816e61bc94SEmilio G. Cota static void sparc_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
4982fcf5ef2aSThomas Huth {
49836e61bc94SEmilio G. Cota     DisasContext *dc = container_of(dcbase, DisasContext, base);
49846e61bc94SEmilio G. Cota     int bound;
4985af00be49SEmilio G. Cota 
4986af00be49SEmilio G. Cota     dc->pc = dc->base.pc_first;
49876e61bc94SEmilio G. Cota     dc->npc = (target_ulong)dc->base.tb->cs_base;
49886e61bc94SEmilio G. Cota     dc->mem_idx = dc->base.tb->flags & TB_FLAG_MMU_MASK;
498977976769SPhilippe Mathieu-Daudé     dc->def = &cpu_env(cs)->def;
49906e61bc94SEmilio G. Cota     dc->fpu_enabled = tb_fpu_enabled(dc->base.tb->flags);
49916e61bc94SEmilio G. Cota     dc->address_mask_32bit = tb_am_enabled(dc->base.tb->flags);
4992c9b459aaSArtyom Tarasenko #ifndef CONFIG_USER_ONLY
49936e61bc94SEmilio G. Cota     dc->supervisor = (dc->base.tb->flags & TB_FLAG_SUPER) != 0;
4994c9b459aaSArtyom Tarasenko #endif
4995fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
4996fcf5ef2aSThomas Huth     dc->fprs_dirty = 0;
49976e61bc94SEmilio G. Cota     dc->asi = (dc->base.tb->flags >> TB_FLAG_ASI_SHIFT) & 0xff;
4998c9b459aaSArtyom Tarasenko #ifndef CONFIG_USER_ONLY
49996e61bc94SEmilio G. Cota     dc->hypervisor = (dc->base.tb->flags & TB_FLAG_HYPER) != 0;
5000c9b459aaSArtyom Tarasenko #endif
5001fcf5ef2aSThomas Huth #endif
50026e61bc94SEmilio G. Cota     /*
50036e61bc94SEmilio G. Cota      * if we reach a page boundary, we stop generation so that the
50046e61bc94SEmilio G. Cota      * PC of a TT_TFAULT exception is always in the right page
50056e61bc94SEmilio G. Cota      */
50066e61bc94SEmilio G. Cota     bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
50076e61bc94SEmilio G. Cota     dc->base.max_insns = MIN(dc->base.max_insns, bound);
5008af00be49SEmilio G. Cota }
5009fcf5ef2aSThomas Huth 
50106e61bc94SEmilio G. Cota static void sparc_tr_tb_start(DisasContextBase *db, CPUState *cs)
50116e61bc94SEmilio G. Cota {
50126e61bc94SEmilio G. Cota }
50136e61bc94SEmilio G. Cota 
50146e61bc94SEmilio G. Cota static void sparc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
50156e61bc94SEmilio G. Cota {
50166e61bc94SEmilio G. Cota     DisasContext *dc = container_of(dcbase, DisasContext, base);
5017633c4283SRichard Henderson     target_ulong npc = dc->npc;
50186e61bc94SEmilio G. Cota 
5019633c4283SRichard Henderson     if (npc & 3) {
5020633c4283SRichard Henderson         switch (npc) {
5021633c4283SRichard Henderson         case JUMP_PC:
5022fcf5ef2aSThomas Huth             assert(dc->jump_pc[1] == dc->pc + 4);
5023633c4283SRichard Henderson             npc = dc->jump_pc[0] | JUMP_PC;
5024633c4283SRichard Henderson             break;
5025633c4283SRichard Henderson         case DYNAMIC_PC:
5026633c4283SRichard Henderson         case DYNAMIC_PC_LOOKUP:
5027633c4283SRichard Henderson             npc = DYNAMIC_PC;
5028633c4283SRichard Henderson             break;
5029633c4283SRichard Henderson         default:
5030633c4283SRichard Henderson             g_assert_not_reached();
5031fcf5ef2aSThomas Huth         }
50326e61bc94SEmilio G. Cota     }
5033633c4283SRichard Henderson     tcg_gen_insn_start(dc->pc, npc);
5034633c4283SRichard Henderson }
5035fcf5ef2aSThomas Huth 
50366e61bc94SEmilio G. Cota static void sparc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
50376e61bc94SEmilio G. Cota {
50386e61bc94SEmilio G. Cota     DisasContext *dc = container_of(dcbase, DisasContext, base);
50396e61bc94SEmilio G. Cota     unsigned int insn;
5040fcf5ef2aSThomas Huth 
504177976769SPhilippe Mathieu-Daudé     insn = translator_ldl(cpu_env(cs), &dc->base, dc->pc);
5042af00be49SEmilio G. Cota     dc->base.pc_next += 4;
5043878cc677SRichard Henderson 
5044878cc677SRichard Henderson     if (!decode(dc, insn)) {
5045ba9c09b4SRichard Henderson         gen_exception(dc, TT_ILL_INSN);
5046878cc677SRichard Henderson     }
5047fcf5ef2aSThomas Huth 
5048af00be49SEmilio G. Cota     if (dc->base.is_jmp == DISAS_NORETURN) {
50496e61bc94SEmilio G. Cota         return;
5050c5e6ccdfSEmilio G. Cota     }
5051af00be49SEmilio G. Cota     if (dc->pc != dc->base.pc_next) {
50526e61bc94SEmilio G. Cota         dc->base.is_jmp = DISAS_TOO_MANY;
5053af00be49SEmilio G. Cota     }
50546e61bc94SEmilio G. Cota }
5055fcf5ef2aSThomas Huth 
50566e61bc94SEmilio G. Cota static void sparc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
50576e61bc94SEmilio G. Cota {
50586e61bc94SEmilio G. Cota     DisasContext *dc = container_of(dcbase, DisasContext, base);
5059186e7890SRichard Henderson     DisasDelayException *e, *e_next;
5060633c4283SRichard Henderson     bool may_lookup;
50616e61bc94SEmilio G. Cota 
506289527e3aSRichard Henderson     finishing_insn(dc);
506389527e3aSRichard Henderson 
506446bb0137SMark Cave-Ayland     switch (dc->base.is_jmp) {
506546bb0137SMark Cave-Ayland     case DISAS_NEXT:
506646bb0137SMark Cave-Ayland     case DISAS_TOO_MANY:
5067633c4283SRichard Henderson         if (((dc->pc | dc->npc) & 3) == 0) {
5068fcf5ef2aSThomas Huth             /* static PC and NPC: we can use direct chaining */
5069fcf5ef2aSThomas Huth             gen_goto_tb(dc, 0, dc->pc, dc->npc);
5070633c4283SRichard Henderson             break;
5071fcf5ef2aSThomas Huth         }
5072633c4283SRichard Henderson 
5073930f1865SRichard Henderson         may_lookup = true;
5074633c4283SRichard Henderson         if (dc->pc & 3) {
5075633c4283SRichard Henderson             switch (dc->pc) {
5076633c4283SRichard Henderson             case DYNAMIC_PC_LOOKUP:
5077633c4283SRichard Henderson                 break;
5078633c4283SRichard Henderson             case DYNAMIC_PC:
5079633c4283SRichard Henderson                 may_lookup = false;
5080633c4283SRichard Henderson                 break;
5081633c4283SRichard Henderson             default:
5082633c4283SRichard Henderson                 g_assert_not_reached();
5083633c4283SRichard Henderson             }
5084633c4283SRichard Henderson         } else {
5085633c4283SRichard Henderson             tcg_gen_movi_tl(cpu_pc, dc->pc);
5086633c4283SRichard Henderson         }
5087633c4283SRichard Henderson 
5088930f1865SRichard Henderson         if (dc->npc & 3) {
5089930f1865SRichard Henderson             switch (dc->npc) {
5090930f1865SRichard Henderson             case JUMP_PC:
5091930f1865SRichard Henderson                 gen_generic_branch(dc);
5092930f1865SRichard Henderson                 break;
5093930f1865SRichard Henderson             case DYNAMIC_PC:
5094930f1865SRichard Henderson                 may_lookup = false;
5095930f1865SRichard Henderson                 break;
5096930f1865SRichard Henderson             case DYNAMIC_PC_LOOKUP:
5097930f1865SRichard Henderson                 break;
5098930f1865SRichard Henderson             default:
5099930f1865SRichard Henderson                 g_assert_not_reached();
5100930f1865SRichard Henderson             }
5101930f1865SRichard Henderson         } else {
5102930f1865SRichard Henderson             tcg_gen_movi_tl(cpu_npc, dc->npc);
5103930f1865SRichard Henderson         }
5104633c4283SRichard Henderson         if (may_lookup) {
5105633c4283SRichard Henderson             tcg_gen_lookup_and_goto_ptr();
5106633c4283SRichard Henderson         } else {
510707ea28b4SRichard Henderson             tcg_gen_exit_tb(NULL, 0);
5108fcf5ef2aSThomas Huth         }
510946bb0137SMark Cave-Ayland         break;
511046bb0137SMark Cave-Ayland 
511146bb0137SMark Cave-Ayland     case DISAS_NORETURN:
511246bb0137SMark Cave-Ayland        break;
511346bb0137SMark Cave-Ayland 
511446bb0137SMark Cave-Ayland     case DISAS_EXIT:
511546bb0137SMark Cave-Ayland         /* Exit TB */
511646bb0137SMark Cave-Ayland         save_state(dc);
511746bb0137SMark Cave-Ayland         tcg_gen_exit_tb(NULL, 0);
511846bb0137SMark Cave-Ayland         break;
511946bb0137SMark Cave-Ayland 
512046bb0137SMark Cave-Ayland     default:
512146bb0137SMark Cave-Ayland         g_assert_not_reached();
5122fcf5ef2aSThomas Huth     }
5123186e7890SRichard Henderson 
5124186e7890SRichard Henderson     for (e = dc->delay_excp_list; e ; e = e_next) {
5125186e7890SRichard Henderson         gen_set_label(e->lab);
5126186e7890SRichard Henderson 
5127186e7890SRichard Henderson         tcg_gen_movi_tl(cpu_pc, e->pc);
5128186e7890SRichard Henderson         if (e->npc % 4 == 0) {
5129186e7890SRichard Henderson             tcg_gen_movi_tl(cpu_npc, e->npc);
5130186e7890SRichard Henderson         }
5131186e7890SRichard Henderson         gen_helper_raise_exception(tcg_env, e->excp);
5132186e7890SRichard Henderson 
5133186e7890SRichard Henderson         e_next = e->next;
5134186e7890SRichard Henderson         g_free(e);
5135186e7890SRichard Henderson     }
5136fcf5ef2aSThomas Huth }
51376e61bc94SEmilio G. Cota 
51386e61bc94SEmilio G. Cota static const TranslatorOps sparc_tr_ops = {
51396e61bc94SEmilio G. Cota     .init_disas_context = sparc_tr_init_disas_context,
51406e61bc94SEmilio G. Cota     .tb_start           = sparc_tr_tb_start,
51416e61bc94SEmilio G. Cota     .insn_start         = sparc_tr_insn_start,
51426e61bc94SEmilio G. Cota     .translate_insn     = sparc_tr_translate_insn,
51436e61bc94SEmilio G. Cota     .tb_stop            = sparc_tr_tb_stop,
51446e61bc94SEmilio G. Cota };
51456e61bc94SEmilio G. Cota 
5146597f9b2dSRichard Henderson void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int *max_insns,
514732f0c394SAnton Johansson                            vaddr pc, void *host_pc)
51486e61bc94SEmilio G. Cota {
51496e61bc94SEmilio G. Cota     DisasContext dc = {};
51506e61bc94SEmilio G. Cota 
5151306c8721SRichard Henderson     translator_loop(cs, tb, max_insns, pc, host_pc, &sparc_tr_ops, &dc.base);
5152fcf5ef2aSThomas Huth }
5153fcf5ef2aSThomas Huth 
515455c3ceefSRichard Henderson void sparc_tcg_init(void)
5155fcf5ef2aSThomas Huth {
5156fcf5ef2aSThomas Huth     static const char gregnames[32][4] = {
5157fcf5ef2aSThomas Huth         "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
5158fcf5ef2aSThomas Huth         "o0", "o1", "o2", "o3", "o4", "o5", "o6", "o7",
5159fcf5ef2aSThomas Huth         "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
5160fcf5ef2aSThomas Huth         "i0", "i1", "i2", "i3", "i4", "i5", "i6", "i7",
5161fcf5ef2aSThomas Huth     };
5162fcf5ef2aSThomas Huth 
5163d8c5b92fSRichard Henderson     static const struct { TCGv_i32 *ptr; int off; const char *name; } r32[] = {
5164d8c5b92fSRichard Henderson #ifdef TARGET_SPARC64
5165d8c5b92fSRichard Henderson         { &cpu_fprs, offsetof(CPUSPARCState, fprs), "fprs" },
5166d8c5b92fSRichard Henderson         { &cpu_fcc[0], offsetof(CPUSPARCState, fcc[0]), "fcc0" },
5167d8c5b92fSRichard Henderson         { &cpu_fcc[1], offsetof(CPUSPARCState, fcc[1]), "fcc1" },
5168d8c5b92fSRichard Henderson         { &cpu_fcc[2], offsetof(CPUSPARCState, fcc[2]), "fcc2" },
5169d8c5b92fSRichard Henderson         { &cpu_fcc[3], offsetof(CPUSPARCState, fcc[3]), "fcc3" },
5170d8c5b92fSRichard Henderson #else
5171d8c5b92fSRichard Henderson         { &cpu_fcc[0], offsetof(CPUSPARCState, fcc[0]), "fcc" },
5172d8c5b92fSRichard Henderson #endif
5173d8c5b92fSRichard Henderson     };
5174d8c5b92fSRichard Henderson 
5175fcf5ef2aSThomas Huth     static const struct { TCGv *ptr; int off; const char *name; } rtl[] = {
5176fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
5177fcf5ef2aSThomas Huth         { &cpu_gsr, offsetof(CPUSPARCState, gsr), "gsr" },
51782a1905c7SRichard Henderson         { &cpu_xcc_Z, offsetof(CPUSPARCState, xcc_Z), "xcc_Z" },
51792a1905c7SRichard Henderson         { &cpu_xcc_C, offsetof(CPUSPARCState, xcc_C), "xcc_C" },
5180fcf5ef2aSThomas Huth #endif
51812a1905c7SRichard Henderson         { &cpu_cc_N, offsetof(CPUSPARCState, cc_N), "cc_N" },
51822a1905c7SRichard Henderson         { &cpu_cc_V, offsetof(CPUSPARCState, cc_V), "cc_V" },
51832a1905c7SRichard Henderson         { &cpu_icc_Z, offsetof(CPUSPARCState, icc_Z), "icc_Z" },
51842a1905c7SRichard Henderson         { &cpu_icc_C, offsetof(CPUSPARCState, icc_C), "icc_C" },
5185fcf5ef2aSThomas Huth         { &cpu_cond, offsetof(CPUSPARCState, cond), "cond" },
5186fcf5ef2aSThomas Huth         { &cpu_pc, offsetof(CPUSPARCState, pc), "pc" },
5187fcf5ef2aSThomas Huth         { &cpu_npc, offsetof(CPUSPARCState, npc), "npc" },
5188fcf5ef2aSThomas Huth         { &cpu_y, offsetof(CPUSPARCState, y), "y" },
5189fcf5ef2aSThomas Huth         { &cpu_tbr, offsetof(CPUSPARCState, tbr), "tbr" },
5190fcf5ef2aSThomas Huth     };
5191fcf5ef2aSThomas Huth 
5192fcf5ef2aSThomas Huth     unsigned int i;
5193fcf5ef2aSThomas Huth 
5194ad75a51eSRichard Henderson     cpu_regwptr = tcg_global_mem_new_ptr(tcg_env,
5195fcf5ef2aSThomas Huth                                          offsetof(CPUSPARCState, regwptr),
5196fcf5ef2aSThomas Huth                                          "regwptr");
5197fcf5ef2aSThomas Huth 
5198d8c5b92fSRichard Henderson     for (i = 0; i < ARRAY_SIZE(r32); ++i) {
5199d8c5b92fSRichard Henderson         *r32[i].ptr = tcg_global_mem_new_i32(tcg_env, r32[i].off, r32[i].name);
5200d8c5b92fSRichard Henderson     }
5201d8c5b92fSRichard Henderson 
5202fcf5ef2aSThomas Huth     for (i = 0; i < ARRAY_SIZE(rtl); ++i) {
5203ad75a51eSRichard Henderson         *rtl[i].ptr = tcg_global_mem_new(tcg_env, rtl[i].off, rtl[i].name);
5204fcf5ef2aSThomas Huth     }
5205fcf5ef2aSThomas Huth 
5206f764718dSRichard Henderson     cpu_regs[0] = NULL;
5207fcf5ef2aSThomas Huth     for (i = 1; i < 8; ++i) {
5208ad75a51eSRichard Henderson         cpu_regs[i] = tcg_global_mem_new(tcg_env,
5209fcf5ef2aSThomas Huth                                          offsetof(CPUSPARCState, gregs[i]),
5210fcf5ef2aSThomas Huth                                          gregnames[i]);
5211fcf5ef2aSThomas Huth     }
5212fcf5ef2aSThomas Huth 
5213fcf5ef2aSThomas Huth     for (i = 8; i < 32; ++i) {
5214fcf5ef2aSThomas Huth         cpu_regs[i] = tcg_global_mem_new(cpu_regwptr,
5215fcf5ef2aSThomas Huth                                          (i - 8) * sizeof(target_ulong),
5216fcf5ef2aSThomas Huth                                          gregnames[i]);
5217fcf5ef2aSThomas Huth     }
5218fcf5ef2aSThomas Huth }
5219fcf5ef2aSThomas Huth 
5220f36aaa53SRichard Henderson void sparc_restore_state_to_opc(CPUState *cs,
5221f36aaa53SRichard Henderson                                 const TranslationBlock *tb,
5222f36aaa53SRichard Henderson                                 const uint64_t *data)
5223fcf5ef2aSThomas Huth {
522477976769SPhilippe Mathieu-Daudé     CPUSPARCState *env = cpu_env(cs);
5225fcf5ef2aSThomas Huth     target_ulong pc = data[0];
5226fcf5ef2aSThomas Huth     target_ulong npc = data[1];
5227fcf5ef2aSThomas Huth 
5228fcf5ef2aSThomas Huth     env->pc = pc;
5229fcf5ef2aSThomas Huth     if (npc == DYNAMIC_PC) {
5230fcf5ef2aSThomas Huth         /* dynamic NPC: already stored */
5231fcf5ef2aSThomas Huth     } else if (npc & JUMP_PC) {
5232fcf5ef2aSThomas Huth         /* jump PC: use 'cond' and the jump targets of the translation */
5233fcf5ef2aSThomas Huth         if (env->cond) {
5234fcf5ef2aSThomas Huth             env->npc = npc & ~3;
5235fcf5ef2aSThomas Huth         } else {
5236fcf5ef2aSThomas Huth             env->npc = pc + 4;
5237fcf5ef2aSThomas Huth         }
5238fcf5ef2aSThomas Huth     } else {
5239fcf5ef2aSThomas Huth         env->npc = npc;
5240fcf5ef2aSThomas Huth     }
5241fcf5ef2aSThomas Huth }
5242