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