xref: /openbmc/qemu/target/sparc/translate.c (revision d3ef26afde77fbdedd5b30282134ff99d0fe5cc5)
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()
40c92948f2SClément Chigot # define gen_helper_rdasr17(D, E)               qemu_build_not_reached()
4186b82fe0SRichard Henderson # define gen_helper_rett(E)                     qemu_build_not_reached()
420faef01bSRichard Henderson # define gen_helper_power_down(E)               qemu_build_not_reached()
4325524734SRichard Henderson # define gen_helper_wrpsr(E, S)                 qemu_build_not_reached()
44668bb9b7SRichard Henderson #else
450faef01bSRichard Henderson # define gen_helper_clear_softint(E, S)         qemu_build_not_reached()
468f75b8a4SRichard Henderson # define gen_helper_done(E)                     qemu_build_not_reached()
47e8325dc0SRichard Henderson # define gen_helper_flushw(E)                   qemu_build_not_reached()
48a859602cSRichard Henderson # define gen_helper_fmul8x16a(D, S1, S2)        qemu_build_not_reached()
49af25071cSRichard Henderson # define gen_helper_rdccr(D, E)                 qemu_build_not_reached()
505d617bfbSRichard Henderson # define gen_helper_rdcwp(D, E)                 qemu_build_not_reached()
5125524734SRichard Henderson # define gen_helper_restored(E)                 qemu_build_not_reached()
528f75b8a4SRichard Henderson # define gen_helper_retry(E)                    qemu_build_not_reached()
5325524734SRichard Henderson # define gen_helper_saved(E)                    qemu_build_not_reached()
540faef01bSRichard Henderson # define gen_helper_set_softint(E, S)           qemu_build_not_reached()
55af25071cSRichard Henderson # define gen_helper_tick_get_count(D, E, T, C)  qemu_build_not_reached()
569422278eSRichard Henderson # define gen_helper_tick_set_count(P, S)        qemu_build_not_reached()
57bb97f2f5SRichard Henderson # define gen_helper_tick_set_limit(P, S)        qemu_build_not_reached()
580faef01bSRichard Henderson # define gen_helper_wrccr(E, S)                 qemu_build_not_reached()
599422278eSRichard Henderson # define gen_helper_wrcwp(E, S)                 qemu_build_not_reached()
609422278eSRichard Henderson # define gen_helper_wrgl(E, S)                  qemu_build_not_reached()
610faef01bSRichard Henderson # define gen_helper_write_softint(E, S)         qemu_build_not_reached()
629422278eSRichard Henderson # define gen_helper_wrpil(E, S)                 qemu_build_not_reached()
639422278eSRichard Henderson # define gen_helper_wrpstate(E, S)              qemu_build_not_reached()
64e2fa6bd1SRichard Henderson # define gen_helper_fcmpeq16             ({ qemu_build_not_reached(); NULL; })
65e2fa6bd1SRichard Henderson # define gen_helper_fcmpeq32             ({ qemu_build_not_reached(); NULL; })
66e2fa6bd1SRichard Henderson # define gen_helper_fcmpgt16             ({ qemu_build_not_reached(); NULL; })
67e2fa6bd1SRichard Henderson # define gen_helper_fcmpgt32             ({ qemu_build_not_reached(); NULL; })
68e2fa6bd1SRichard Henderson # define gen_helper_fcmple16             ({ qemu_build_not_reached(); NULL; })
69e2fa6bd1SRichard Henderson # define gen_helper_fcmple32             ({ qemu_build_not_reached(); NULL; })
70e2fa6bd1SRichard Henderson # define gen_helper_fcmpne16             ({ qemu_build_not_reached(); NULL; })
71e2fa6bd1SRichard Henderson # define gen_helper_fcmpne32             ({ qemu_build_not_reached(); NULL; })
728aa418b3SRichard Henderson # define gen_helper_fdtox                ({ qemu_build_not_reached(); NULL; })
73e06c9f83SRichard Henderson # define gen_helper_fexpand              ({ qemu_build_not_reached(); NULL; })
74e06c9f83SRichard Henderson # define gen_helper_fmul8sux16           ({ qemu_build_not_reached(); NULL; })
75e06c9f83SRichard Henderson # define gen_helper_fmul8ulx16           ({ qemu_build_not_reached(); NULL; })
76e06c9f83SRichard Henderson # define gen_helper_fmul8x16             ({ qemu_build_not_reached(); NULL; })
77e06c9f83SRichard Henderson # define gen_helper_fpmerge              ({ qemu_build_not_reached(); NULL; })
781617586fSRichard Henderson # define gen_helper_fqtox                ({ qemu_build_not_reached(); NULL; })
79199d43efSRichard Henderson # define gen_helper_fstox                ({ qemu_build_not_reached(); NULL; })
808aa418b3SRichard Henderson # define gen_helper_fxtod                ({ qemu_build_not_reached(); NULL; })
817b8e3e1aSRichard Henderson # define gen_helper_fxtoq                ({ qemu_build_not_reached(); NULL; })
82f4e18df5SRichard Henderson # define gen_helper_fxtos                ({ qemu_build_not_reached(); NULL; })
83afb04344SRichard Henderson # define gen_helper_pdist                ({ qemu_build_not_reached(); NULL; })
84668bb9b7SRichard Henderson # define MAXTL_MASK                             0
85af25071cSRichard Henderson #endif
86af25071cSRichard Henderson 
87633c4283SRichard Henderson /* Dynamic PC, must exit to main loop. */
88633c4283SRichard Henderson #define DYNAMIC_PC         1
89633c4283SRichard Henderson /* Dynamic PC, one of two values according to jump_pc[T2]. */
90633c4283SRichard Henderson #define JUMP_PC            2
91633c4283SRichard Henderson /* Dynamic PC, may lookup next TB. */
92633c4283SRichard Henderson #define DYNAMIC_PC_LOOKUP  3
93fcf5ef2aSThomas Huth 
9446bb0137SMark Cave-Ayland #define DISAS_EXIT  DISAS_TARGET_0
9546bb0137SMark Cave-Ayland 
96fcf5ef2aSThomas Huth /* global register indexes */
97fcf5ef2aSThomas Huth static TCGv_ptr cpu_regwptr;
98c9fa8e58SRichard Henderson static TCGv cpu_pc, cpu_npc;
99fcf5ef2aSThomas Huth static TCGv cpu_regs[32];
100fcf5ef2aSThomas Huth static TCGv cpu_y;
101fcf5ef2aSThomas Huth static TCGv cpu_tbr;
102fcf5ef2aSThomas Huth static TCGv cpu_cond;
1032a1905c7SRichard Henderson static TCGv cpu_cc_N;
1042a1905c7SRichard Henderson static TCGv cpu_cc_V;
1052a1905c7SRichard Henderson static TCGv cpu_icc_Z;
1062a1905c7SRichard Henderson static TCGv cpu_icc_C;
107fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
1082a1905c7SRichard Henderson static TCGv cpu_xcc_Z;
1092a1905c7SRichard Henderson static TCGv cpu_xcc_C;
1102a1905c7SRichard Henderson static TCGv_i32 cpu_fprs;
111fcf5ef2aSThomas Huth static TCGv cpu_gsr;
112fcf5ef2aSThomas Huth #else
113af25071cSRichard Henderson # define cpu_fprs               ({ qemu_build_not_reached(); (TCGv)NULL; })
114af25071cSRichard Henderson # define cpu_gsr                ({ qemu_build_not_reached(); (TCGv)NULL; })
115fcf5ef2aSThomas Huth #endif
1162a1905c7SRichard Henderson 
1172a1905c7SRichard Henderson #ifdef TARGET_SPARC64
1182a1905c7SRichard Henderson #define cpu_cc_Z  cpu_xcc_Z
1192a1905c7SRichard Henderson #define cpu_cc_C  cpu_xcc_C
1202a1905c7SRichard Henderson #else
1212a1905c7SRichard Henderson #define cpu_cc_Z  cpu_icc_Z
1222a1905c7SRichard Henderson #define cpu_cc_C  cpu_icc_C
1232a1905c7SRichard Henderson #define cpu_xcc_Z ({ qemu_build_not_reached(); NULL; })
1242a1905c7SRichard Henderson #define cpu_xcc_C ({ qemu_build_not_reached(); NULL; })
1252a1905c7SRichard Henderson #endif
1262a1905c7SRichard Henderson 
127fcf5ef2aSThomas Huth /* Floating point registers */
128fcf5ef2aSThomas Huth static TCGv_i64 cpu_fpr[TARGET_DPREGS];
129d8c5b92fSRichard Henderson static TCGv_i32 cpu_fcc[TARGET_FCCREGS];
130fcf5ef2aSThomas Huth 
131af25071cSRichard Henderson #define env_field_offsetof(X)     offsetof(CPUSPARCState, X)
132af25071cSRichard Henderson #ifdef TARGET_SPARC64
133cd6269f7SRichard Henderson # define env32_field_offsetof(X)  ({ qemu_build_not_reached(); 0; })
134af25071cSRichard Henderson # define env64_field_offsetof(X)  env_field_offsetof(X)
135af25071cSRichard Henderson #else
136cd6269f7SRichard Henderson # define env32_field_offsetof(X)  env_field_offsetof(X)
137af25071cSRichard Henderson # define env64_field_offsetof(X)  ({ qemu_build_not_reached(); 0; })
138af25071cSRichard Henderson #endif
139af25071cSRichard Henderson 
140533f042fSRichard Henderson typedef struct DisasCompare {
141533f042fSRichard Henderson     TCGCond cond;
142533f042fSRichard Henderson     TCGv c1;
143533f042fSRichard Henderson     int c2;
144533f042fSRichard Henderson } DisasCompare;
145533f042fSRichard Henderson 
146186e7890SRichard Henderson typedef struct DisasDelayException {
147186e7890SRichard Henderson     struct DisasDelayException *next;
148186e7890SRichard Henderson     TCGLabel *lab;
149186e7890SRichard Henderson     TCGv_i32 excp;
150186e7890SRichard Henderson     /* Saved state at parent insn. */
151186e7890SRichard Henderson     target_ulong pc;
152186e7890SRichard Henderson     target_ulong npc;
153186e7890SRichard Henderson } DisasDelayException;
154186e7890SRichard Henderson 
155fcf5ef2aSThomas Huth typedef struct DisasContext {
156af00be49SEmilio G. Cota     DisasContextBase base;
157fcf5ef2aSThomas Huth     target_ulong pc;    /* current Program Counter: integer or DYNAMIC_PC */
158fcf5ef2aSThomas Huth     target_ulong npc;   /* next PC: integer or DYNAMIC_PC or JUMP_PC */
159533f042fSRichard Henderson 
160533f042fSRichard Henderson     /* Used when JUMP_PC value is used. */
161533f042fSRichard Henderson     DisasCompare jump;
162533f042fSRichard Henderson     target_ulong jump_pc[2];
163533f042fSRichard Henderson 
164fcf5ef2aSThomas Huth     int mem_idx;
16589527e3aSRichard Henderson     bool cpu_cond_live;
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     sparc_def_t *def;
176fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
177fcf5ef2aSThomas Huth     int fprs_dirty;
178fcf5ef2aSThomas Huth     int asi;
179fcf5ef2aSThomas Huth #endif
180186e7890SRichard Henderson     DisasDelayException *delay_excp_list;
181fcf5ef2aSThomas Huth } DisasContext;
182fcf5ef2aSThomas Huth 
183fcf5ef2aSThomas Huth // This function uses non-native bit order
184fcf5ef2aSThomas Huth #define GET_FIELD(X, FROM, TO)                                  \
185fcf5ef2aSThomas Huth     ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))
186fcf5ef2aSThomas Huth 
187fcf5ef2aSThomas Huth // This function uses the order in the manuals, i.e. bit 0 is 2^0
188fcf5ef2aSThomas Huth #define GET_FIELD_SP(X, FROM, TO)               \
189fcf5ef2aSThomas Huth     GET_FIELD(X, 31 - (TO), 31 - (FROM))
190fcf5ef2aSThomas Huth 
191fcf5ef2aSThomas Huth #define GET_FIELDs(x,a,b) sign_extend (GET_FIELD(x,a,b), (b) - (a) + 1)
192fcf5ef2aSThomas Huth #define GET_FIELD_SPs(x,a,b) sign_extend (GET_FIELD_SP(x,a,b), ((b) - (a) + 1))
193fcf5ef2aSThomas Huth 
194fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
195fcf5ef2aSThomas Huth #define DFPREG(r) (((r & 1) << 5) | (r & 0x1e))
196fcf5ef2aSThomas Huth #define QFPREG(r) (((r & 1) << 5) | (r & 0x1c))
197fcf5ef2aSThomas Huth #else
198fcf5ef2aSThomas Huth #define DFPREG(r) (r & 0x1e)
199fcf5ef2aSThomas Huth #define QFPREG(r) (r & 0x1c)
200fcf5ef2aSThomas Huth #endif
201fcf5ef2aSThomas Huth 
202fcf5ef2aSThomas Huth #define UA2005_HTRAP_MASK 0xff
203fcf5ef2aSThomas Huth #define V8_TRAP_MASK 0x7f
204fcf5ef2aSThomas Huth 
205fcf5ef2aSThomas Huth #define IS_IMM (insn & (1<<13))
206fcf5ef2aSThomas Huth 
2070c2e96c1SRichard Henderson static void gen_update_fprs_dirty(DisasContext *dc, int rd)
208fcf5ef2aSThomas Huth {
209fcf5ef2aSThomas Huth #if defined(TARGET_SPARC64)
210fcf5ef2aSThomas Huth     int bit = (rd < 32) ? 1 : 2;
211fcf5ef2aSThomas Huth     /* If we know we've already set this bit within the TB,
212fcf5ef2aSThomas Huth        we can avoid setting it again.  */
213fcf5ef2aSThomas Huth     if (!(dc->fprs_dirty & bit)) {
214fcf5ef2aSThomas Huth         dc->fprs_dirty |= bit;
215fcf5ef2aSThomas Huth         tcg_gen_ori_i32(cpu_fprs, cpu_fprs, bit);
216fcf5ef2aSThomas Huth     }
217fcf5ef2aSThomas Huth #endif
218fcf5ef2aSThomas Huth }
219fcf5ef2aSThomas Huth 
220fcf5ef2aSThomas Huth /* floating point registers moves */
221fcf5ef2aSThomas Huth static TCGv_i32 gen_load_fpr_F(DisasContext *dc, unsigned int src)
222fcf5ef2aSThomas Huth {
22336ab4623SRichard Henderson     TCGv_i32 ret = tcg_temp_new_i32();
224dc41aa7dSRichard Henderson     if (src & 1) {
225dc41aa7dSRichard Henderson         tcg_gen_extrl_i64_i32(ret, cpu_fpr[src / 2]);
226dc41aa7dSRichard Henderson     } else {
227dc41aa7dSRichard Henderson         tcg_gen_extrh_i64_i32(ret, cpu_fpr[src / 2]);
228fcf5ef2aSThomas Huth     }
229dc41aa7dSRichard Henderson     return ret;
230fcf5ef2aSThomas Huth }
231fcf5ef2aSThomas Huth 
232fcf5ef2aSThomas Huth static void gen_store_fpr_F(DisasContext *dc, unsigned int dst, TCGv_i32 v)
233fcf5ef2aSThomas Huth {
2348e7bbc75SRichard Henderson     TCGv_i64 t = tcg_temp_new_i64();
2358e7bbc75SRichard Henderson 
2368e7bbc75SRichard Henderson     tcg_gen_extu_i32_i64(t, v);
237fcf5ef2aSThomas Huth     tcg_gen_deposit_i64(cpu_fpr[dst / 2], cpu_fpr[dst / 2], t,
238fcf5ef2aSThomas Huth                         (dst & 1 ? 0 : 32), 32);
239fcf5ef2aSThomas Huth     gen_update_fprs_dirty(dc, dst);
240fcf5ef2aSThomas Huth }
241fcf5ef2aSThomas Huth 
242fcf5ef2aSThomas Huth static TCGv_i64 gen_load_fpr_D(DisasContext *dc, unsigned int src)
243fcf5ef2aSThomas Huth {
244fcf5ef2aSThomas Huth     src = DFPREG(src);
245fcf5ef2aSThomas Huth     return cpu_fpr[src / 2];
246fcf5ef2aSThomas Huth }
247fcf5ef2aSThomas Huth 
248fcf5ef2aSThomas Huth static void gen_store_fpr_D(DisasContext *dc, unsigned int dst, TCGv_i64 v)
249fcf5ef2aSThomas Huth {
250fcf5ef2aSThomas Huth     dst = DFPREG(dst);
251fcf5ef2aSThomas Huth     tcg_gen_mov_i64(cpu_fpr[dst / 2], v);
252fcf5ef2aSThomas Huth     gen_update_fprs_dirty(dc, dst);
253fcf5ef2aSThomas Huth }
254fcf5ef2aSThomas Huth 
255fcf5ef2aSThomas Huth static TCGv_i64 gen_dest_fpr_D(DisasContext *dc, unsigned int dst)
256fcf5ef2aSThomas Huth {
257fcf5ef2aSThomas Huth     return cpu_fpr[DFPREG(dst) / 2];
258fcf5ef2aSThomas Huth }
259fcf5ef2aSThomas Huth 
26033ec4245SRichard Henderson static TCGv_i128 gen_load_fpr_Q(DisasContext *dc, unsigned int src)
26133ec4245SRichard Henderson {
26233ec4245SRichard Henderson     TCGv_i128 ret = tcg_temp_new_i128();
26333ec4245SRichard Henderson 
26433ec4245SRichard Henderson     src = QFPREG(src);
26533ec4245SRichard Henderson     tcg_gen_concat_i64_i128(ret, cpu_fpr[src / 2 + 1], cpu_fpr[src / 2]);
26633ec4245SRichard Henderson     return ret;
26733ec4245SRichard Henderson }
26833ec4245SRichard Henderson 
26933ec4245SRichard Henderson static void gen_store_fpr_Q(DisasContext *dc, unsigned int dst, TCGv_i128 v)
27033ec4245SRichard Henderson {
27133ec4245SRichard Henderson     dst = DFPREG(dst);
27233ec4245SRichard Henderson     tcg_gen_extr_i128_i64(cpu_fpr[dst / 2 + 1], cpu_fpr[dst / 2], v);
27333ec4245SRichard Henderson     gen_update_fprs_dirty(dc, dst);
27433ec4245SRichard Henderson }
27533ec4245SRichard Henderson 
276fcf5ef2aSThomas Huth /* moves */
277fcf5ef2aSThomas Huth #ifdef CONFIG_USER_ONLY
278fcf5ef2aSThomas Huth #define supervisor(dc) 0
279fcf5ef2aSThomas Huth #define hypervisor(dc) 0
280fcf5ef2aSThomas Huth #else
281fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
282c9b459aaSArtyom Tarasenko #define hypervisor(dc) (dc->hypervisor)
283c9b459aaSArtyom Tarasenko #define supervisor(dc) (dc->supervisor | dc->hypervisor)
284fcf5ef2aSThomas Huth #else
285c9b459aaSArtyom Tarasenko #define supervisor(dc) (dc->supervisor)
286668bb9b7SRichard Henderson #define hypervisor(dc) 0
287fcf5ef2aSThomas Huth #endif
288fcf5ef2aSThomas Huth #endif
289fcf5ef2aSThomas Huth 
290b1bc09eaSRichard Henderson #if !defined(TARGET_SPARC64)
291b1bc09eaSRichard Henderson # define AM_CHECK(dc)  false
292b1bc09eaSRichard Henderson #elif defined(TARGET_ABI32)
293b1bc09eaSRichard Henderson # define AM_CHECK(dc)  true
294b1bc09eaSRichard Henderson #elif defined(CONFIG_USER_ONLY)
295b1bc09eaSRichard Henderson # define AM_CHECK(dc)  false
296fcf5ef2aSThomas Huth #else
297b1bc09eaSRichard Henderson # define AM_CHECK(dc)  ((dc)->address_mask_32bit)
298fcf5ef2aSThomas Huth #endif
299fcf5ef2aSThomas Huth 
3000c2e96c1SRichard Henderson static void gen_address_mask(DisasContext *dc, TCGv addr)
301fcf5ef2aSThomas Huth {
302b1bc09eaSRichard Henderson     if (AM_CHECK(dc)) {
303fcf5ef2aSThomas Huth         tcg_gen_andi_tl(addr, addr, 0xffffffffULL);
304b1bc09eaSRichard Henderson     }
305fcf5ef2aSThomas Huth }
306fcf5ef2aSThomas Huth 
30723ada1b1SRichard Henderson static target_ulong address_mask_i(DisasContext *dc, target_ulong addr)
30823ada1b1SRichard Henderson {
30923ada1b1SRichard Henderson     return AM_CHECK(dc) ? (uint32_t)addr : addr;
31023ada1b1SRichard Henderson }
31123ada1b1SRichard Henderson 
3120c2e96c1SRichard Henderson static TCGv gen_load_gpr(DisasContext *dc, int reg)
313fcf5ef2aSThomas Huth {
314fcf5ef2aSThomas Huth     if (reg > 0) {
315fcf5ef2aSThomas Huth         assert(reg < 32);
316fcf5ef2aSThomas Huth         return cpu_regs[reg];
317fcf5ef2aSThomas Huth     } else {
31852123f14SRichard Henderson         TCGv t = tcg_temp_new();
319fcf5ef2aSThomas Huth         tcg_gen_movi_tl(t, 0);
320fcf5ef2aSThomas Huth         return t;
321fcf5ef2aSThomas Huth     }
322fcf5ef2aSThomas Huth }
323fcf5ef2aSThomas Huth 
3240c2e96c1SRichard Henderson static void gen_store_gpr(DisasContext *dc, int reg, TCGv v)
325fcf5ef2aSThomas Huth {
326fcf5ef2aSThomas Huth     if (reg > 0) {
327fcf5ef2aSThomas Huth         assert(reg < 32);
328fcf5ef2aSThomas Huth         tcg_gen_mov_tl(cpu_regs[reg], v);
329fcf5ef2aSThomas Huth     }
330fcf5ef2aSThomas Huth }
331fcf5ef2aSThomas Huth 
3320c2e96c1SRichard Henderson static TCGv gen_dest_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         return tcg_temp_new();
339fcf5ef2aSThomas Huth     }
340fcf5ef2aSThomas Huth }
341fcf5ef2aSThomas Huth 
3425645aa2eSRichard Henderson static bool use_goto_tb(DisasContext *s, target_ulong pc, target_ulong npc)
343fcf5ef2aSThomas Huth {
3445645aa2eSRichard Henderson     return translator_use_goto_tb(&s->base, pc) &&
3455645aa2eSRichard Henderson            translator_use_goto_tb(&s->base, npc);
346fcf5ef2aSThomas Huth }
347fcf5ef2aSThomas Huth 
3485645aa2eSRichard Henderson static void gen_goto_tb(DisasContext *s, int tb_num,
349fcf5ef2aSThomas Huth                         target_ulong pc, target_ulong npc)
350fcf5ef2aSThomas Huth {
351fcf5ef2aSThomas Huth     if (use_goto_tb(s, pc, npc))  {
352fcf5ef2aSThomas Huth         /* jump to same page: we can use a direct jump */
353fcf5ef2aSThomas Huth         tcg_gen_goto_tb(tb_num);
354fcf5ef2aSThomas Huth         tcg_gen_movi_tl(cpu_pc, pc);
355fcf5ef2aSThomas Huth         tcg_gen_movi_tl(cpu_npc, npc);
35607ea28b4SRichard Henderson         tcg_gen_exit_tb(s->base.tb, tb_num);
357fcf5ef2aSThomas Huth     } else {
358f67ccb2fSRichard Henderson         /* jump to another page: we can use an indirect jump */
359fcf5ef2aSThomas Huth         tcg_gen_movi_tl(cpu_pc, pc);
360fcf5ef2aSThomas Huth         tcg_gen_movi_tl(cpu_npc, npc);
361f67ccb2fSRichard Henderson         tcg_gen_lookup_and_goto_ptr();
362fcf5ef2aSThomas Huth     }
363fcf5ef2aSThomas Huth }
364fcf5ef2aSThomas Huth 
365b989ce73SRichard Henderson static TCGv gen_carry32(void)
366fcf5ef2aSThomas Huth {
367b989ce73SRichard Henderson     if (TARGET_LONG_BITS == 64) {
368b989ce73SRichard Henderson         TCGv t = tcg_temp_new();
369b989ce73SRichard Henderson         tcg_gen_extract_tl(t, cpu_icc_C, 32, 1);
370b989ce73SRichard Henderson         return t;
371b989ce73SRichard Henderson     }
372b989ce73SRichard Henderson     return cpu_icc_C;
373fcf5ef2aSThomas Huth }
374fcf5ef2aSThomas Huth 
375b989ce73SRichard Henderson static void gen_op_addcc_int(TCGv dst, TCGv src1, TCGv src2, TCGv cin)
376fcf5ef2aSThomas Huth {
377b989ce73SRichard Henderson     TCGv z = tcg_constant_tl(0);
378fcf5ef2aSThomas Huth 
379b989ce73SRichard Henderson     if (cin) {
380b989ce73SRichard Henderson         tcg_gen_add2_tl(cpu_cc_N, cpu_cc_C, src1, z, cin, z);
381b989ce73SRichard Henderson         tcg_gen_add2_tl(cpu_cc_N, cpu_cc_C, cpu_cc_N, cpu_cc_C, src2, z);
382b989ce73SRichard Henderson     } else {
383b989ce73SRichard Henderson         tcg_gen_add2_tl(cpu_cc_N, cpu_cc_C, src1, z, src2, z);
384b989ce73SRichard Henderson     }
385b989ce73SRichard Henderson     tcg_gen_xor_tl(cpu_cc_Z, src1, src2);
386b989ce73SRichard Henderson     tcg_gen_xor_tl(cpu_cc_V, cpu_cc_N, src2);
387b989ce73SRichard Henderson     tcg_gen_andc_tl(cpu_cc_V, cpu_cc_V, cpu_cc_Z);
388b989ce73SRichard Henderson     if (TARGET_LONG_BITS == 64) {
389b989ce73SRichard Henderson         /*
390b989ce73SRichard Henderson          * Carry-in to bit 32 is result ^ src1 ^ src2.
391b989ce73SRichard Henderson          * We already have the src xor term in Z, from computation of V.
392b989ce73SRichard Henderson          */
393b989ce73SRichard Henderson         tcg_gen_xor_tl(cpu_icc_C, cpu_cc_Z, cpu_cc_N);
394b989ce73SRichard Henderson         tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N);
395b989ce73SRichard Henderson     }
396b989ce73SRichard Henderson     tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N);
397b989ce73SRichard Henderson     tcg_gen_mov_tl(dst, cpu_cc_N);
398b989ce73SRichard Henderson }
399fcf5ef2aSThomas Huth 
400b989ce73SRichard Henderson static void gen_op_addcc(TCGv dst, TCGv src1, TCGv src2)
401b989ce73SRichard Henderson {
402b989ce73SRichard Henderson     gen_op_addcc_int(dst, src1, src2, NULL);
403b989ce73SRichard Henderson }
404fcf5ef2aSThomas Huth 
405b989ce73SRichard Henderson static void gen_op_taddcc(TCGv dst, TCGv src1, TCGv src2)
406b989ce73SRichard Henderson {
407b989ce73SRichard Henderson     TCGv t = tcg_temp_new();
408b989ce73SRichard Henderson 
409b989ce73SRichard Henderson     /* Save the tag bits around modification of dst. */
410b989ce73SRichard Henderson     tcg_gen_or_tl(t, src1, src2);
411b989ce73SRichard Henderson 
412b989ce73SRichard Henderson     gen_op_addcc(dst, src1, src2);
413b989ce73SRichard Henderson 
414b989ce73SRichard Henderson     /* Incorprate tag bits into icc.V */
415b989ce73SRichard Henderson     tcg_gen_andi_tl(t, t, 3);
416b989ce73SRichard Henderson     tcg_gen_neg_tl(t, t);
417b989ce73SRichard Henderson     tcg_gen_ext32u_tl(t, t);
418b989ce73SRichard Henderson     tcg_gen_or_tl(cpu_cc_V, cpu_cc_V, t);
419b989ce73SRichard Henderson }
420b989ce73SRichard Henderson 
421b989ce73SRichard Henderson static void gen_op_addc(TCGv dst, TCGv src1, TCGv src2)
422b989ce73SRichard Henderson {
423b989ce73SRichard Henderson     tcg_gen_add_tl(dst, src1, src2);
424b989ce73SRichard Henderson     tcg_gen_add_tl(dst, dst, gen_carry32());
425b989ce73SRichard Henderson }
426b989ce73SRichard Henderson 
427b989ce73SRichard Henderson static void gen_op_addccc(TCGv dst, TCGv src1, TCGv src2)
428b989ce73SRichard Henderson {
429b989ce73SRichard Henderson     gen_op_addcc_int(dst, src1, src2, gen_carry32());
430fcf5ef2aSThomas Huth }
431fcf5ef2aSThomas Huth 
432f828df74SRichard Henderson static void gen_op_subcc_int(TCGv dst, TCGv src1, TCGv src2, TCGv cin)
433fcf5ef2aSThomas Huth {
434f828df74SRichard Henderson     TCGv z = tcg_constant_tl(0);
435fcf5ef2aSThomas Huth 
436f828df74SRichard Henderson     if (cin) {
437f828df74SRichard Henderson         tcg_gen_sub2_tl(cpu_cc_N, cpu_cc_C, src1, z, cin, z);
438f828df74SRichard Henderson         tcg_gen_sub2_tl(cpu_cc_N, cpu_cc_C, cpu_cc_N, cpu_cc_C, src2, z);
439f828df74SRichard Henderson     } else {
440f828df74SRichard Henderson         tcg_gen_sub2_tl(cpu_cc_N, cpu_cc_C, src1, z, src2, z);
441f828df74SRichard Henderson     }
442f828df74SRichard Henderson     tcg_gen_neg_tl(cpu_cc_C, cpu_cc_C);
443f828df74SRichard Henderson     tcg_gen_xor_tl(cpu_cc_Z, src1, src2);
444f828df74SRichard Henderson     tcg_gen_xor_tl(cpu_cc_V, cpu_cc_N, src1);
445f828df74SRichard Henderson     tcg_gen_and_tl(cpu_cc_V, cpu_cc_V, cpu_cc_Z);
446f828df74SRichard Henderson #ifdef TARGET_SPARC64
447f828df74SRichard Henderson     tcg_gen_xor_tl(cpu_icc_C, cpu_cc_Z, cpu_cc_N);
448f828df74SRichard Henderson     tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N);
449fcf5ef2aSThomas Huth #endif
450f828df74SRichard Henderson     tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N);
451f828df74SRichard Henderson     tcg_gen_mov_tl(dst, cpu_cc_N);
452fcf5ef2aSThomas Huth }
453fcf5ef2aSThomas Huth 
454f828df74SRichard Henderson static void gen_op_subcc(TCGv dst, TCGv src1, TCGv src2)
455fcf5ef2aSThomas Huth {
456f828df74SRichard Henderson     gen_op_subcc_int(dst, src1, src2, NULL);
457fcf5ef2aSThomas Huth }
458fcf5ef2aSThomas Huth 
459f828df74SRichard Henderson static void gen_op_tsubcc(TCGv dst, TCGv src1, TCGv src2)
460fcf5ef2aSThomas Huth {
461f828df74SRichard Henderson     TCGv t = tcg_temp_new();
462fcf5ef2aSThomas Huth 
463f828df74SRichard Henderson     /* Save the tag bits around modification of dst. */
464f828df74SRichard Henderson     tcg_gen_or_tl(t, src1, src2);
465fcf5ef2aSThomas Huth 
466f828df74SRichard Henderson     gen_op_subcc(dst, src1, src2);
467f828df74SRichard Henderson 
468f828df74SRichard Henderson     /* Incorprate tag bits into icc.V */
469f828df74SRichard Henderson     tcg_gen_andi_tl(t, t, 3);
470f828df74SRichard Henderson     tcg_gen_neg_tl(t, t);
471f828df74SRichard Henderson     tcg_gen_ext32u_tl(t, t);
472f828df74SRichard Henderson     tcg_gen_or_tl(cpu_cc_V, cpu_cc_V, t);
473f828df74SRichard Henderson }
474f828df74SRichard Henderson 
475f828df74SRichard Henderson static void gen_op_subc(TCGv dst, TCGv src1, TCGv src2)
476f828df74SRichard Henderson {
477fcf5ef2aSThomas Huth     tcg_gen_sub_tl(dst, src1, src2);
478f828df74SRichard Henderson     tcg_gen_sub_tl(dst, dst, gen_carry32());
479fcf5ef2aSThomas Huth }
480fcf5ef2aSThomas Huth 
481f828df74SRichard Henderson static void gen_op_subccc(TCGv dst, TCGv src1, TCGv src2)
482dfebb950SRichard Henderson {
483f828df74SRichard Henderson     gen_op_subcc_int(dst, src1, src2, gen_carry32());
484dfebb950SRichard Henderson }
485dfebb950SRichard Henderson 
4860c2e96c1SRichard Henderson static void gen_op_mulscc(TCGv dst, TCGv src1, TCGv src2)
487fcf5ef2aSThomas Huth {
488b989ce73SRichard Henderson     TCGv zero = tcg_constant_tl(0);
48950280618SRichard Henderson     TCGv one = tcg_constant_tl(1);
490b989ce73SRichard Henderson     TCGv t_src1 = tcg_temp_new();
491b989ce73SRichard Henderson     TCGv t_src2 = tcg_temp_new();
492b989ce73SRichard Henderson     TCGv t0 = tcg_temp_new();
493fcf5ef2aSThomas Huth 
494b989ce73SRichard Henderson     tcg_gen_ext32u_tl(t_src1, src1);
495b989ce73SRichard Henderson     tcg_gen_ext32u_tl(t_src2, src2);
496fcf5ef2aSThomas Huth 
497b989ce73SRichard Henderson     /*
498b989ce73SRichard Henderson      * if (!(env->y & 1))
499b989ce73SRichard Henderson      *   src2 = 0;
500fcf5ef2aSThomas Huth      */
50150280618SRichard Henderson     tcg_gen_movcond_tl(TCG_COND_TSTEQ, t_src2, cpu_y, one, zero, t_src2);
502fcf5ef2aSThomas Huth 
503b989ce73SRichard Henderson     /*
504b989ce73SRichard Henderson      * b2 = src1 & 1;
505b989ce73SRichard Henderson      * y = (b2 << 31) | (y >> 1);
506b989ce73SRichard Henderson      */
5070b1183e3SPhilippe Mathieu-Daudé     tcg_gen_extract_tl(t0, cpu_y, 1, 31);
508b989ce73SRichard Henderson     tcg_gen_deposit_tl(cpu_y, t0, src1, 31, 1);
509fcf5ef2aSThomas Huth 
510fcf5ef2aSThomas Huth     // b1 = N ^ V;
5112a1905c7SRichard Henderson     tcg_gen_xor_tl(t0, cpu_cc_N, cpu_cc_V);
512fcf5ef2aSThomas Huth 
513b989ce73SRichard Henderson     /*
514b989ce73SRichard Henderson      * src1 = (b1 << 31) | (src1 >> 1)
515b989ce73SRichard Henderson      */
5162a1905c7SRichard Henderson     tcg_gen_andi_tl(t0, t0, 1u << 31);
517b989ce73SRichard Henderson     tcg_gen_shri_tl(t_src1, t_src1, 1);
518b989ce73SRichard Henderson     tcg_gen_or_tl(t_src1, t_src1, t0);
519fcf5ef2aSThomas Huth 
520b989ce73SRichard Henderson     gen_op_addcc(dst, t_src1, t_src2);
521fcf5ef2aSThomas Huth }
522fcf5ef2aSThomas Huth 
5230c2e96c1SRichard Henderson static void gen_op_multiply(TCGv dst, TCGv src1, TCGv src2, int sign_ext)
524fcf5ef2aSThomas Huth {
525fcf5ef2aSThomas Huth #if TARGET_LONG_BITS == 32
526fcf5ef2aSThomas Huth     if (sign_ext) {
527fcf5ef2aSThomas Huth         tcg_gen_muls2_tl(dst, cpu_y, src1, src2);
528fcf5ef2aSThomas Huth     } else {
529fcf5ef2aSThomas Huth         tcg_gen_mulu2_tl(dst, cpu_y, src1, src2);
530fcf5ef2aSThomas Huth     }
531fcf5ef2aSThomas Huth #else
532fcf5ef2aSThomas Huth     TCGv t0 = tcg_temp_new_i64();
533fcf5ef2aSThomas Huth     TCGv t1 = tcg_temp_new_i64();
534fcf5ef2aSThomas Huth 
535fcf5ef2aSThomas Huth     if (sign_ext) {
536fcf5ef2aSThomas Huth         tcg_gen_ext32s_i64(t0, src1);
537fcf5ef2aSThomas Huth         tcg_gen_ext32s_i64(t1, src2);
538fcf5ef2aSThomas Huth     } else {
539fcf5ef2aSThomas Huth         tcg_gen_ext32u_i64(t0, src1);
540fcf5ef2aSThomas Huth         tcg_gen_ext32u_i64(t1, src2);
541fcf5ef2aSThomas Huth     }
542fcf5ef2aSThomas Huth 
543fcf5ef2aSThomas Huth     tcg_gen_mul_i64(dst, t0, t1);
544fcf5ef2aSThomas Huth     tcg_gen_shri_i64(cpu_y, dst, 32);
545fcf5ef2aSThomas Huth #endif
546fcf5ef2aSThomas Huth }
547fcf5ef2aSThomas Huth 
5480c2e96c1SRichard Henderson static void gen_op_umul(TCGv dst, TCGv src1, TCGv src2)
549fcf5ef2aSThomas Huth {
550fcf5ef2aSThomas Huth     /* zero-extend truncated operands before multiplication */
551fcf5ef2aSThomas Huth     gen_op_multiply(dst, src1, src2, 0);
552fcf5ef2aSThomas Huth }
553fcf5ef2aSThomas Huth 
5540c2e96c1SRichard Henderson static void gen_op_smul(TCGv dst, TCGv src1, TCGv src2)
555fcf5ef2aSThomas Huth {
556fcf5ef2aSThomas Huth     /* sign-extend truncated operands before multiplication */
557fcf5ef2aSThomas Huth     gen_op_multiply(dst, src1, src2, 1);
558fcf5ef2aSThomas Huth }
559fcf5ef2aSThomas Huth 
560c2636853SRichard Henderson static void gen_op_sdiv(TCGv dst, TCGv src1, TCGv src2)
561c2636853SRichard Henderson {
56213260103SRichard Henderson #ifdef TARGET_SPARC64
563c2636853SRichard Henderson     gen_helper_sdiv(dst, tcg_env, src1, src2);
56413260103SRichard Henderson     tcg_gen_ext32s_tl(dst, dst);
56513260103SRichard Henderson #else
56613260103SRichard Henderson     TCGv_i64 t64 = tcg_temp_new_i64();
56713260103SRichard Henderson     gen_helper_sdiv(t64, tcg_env, src1, src2);
56813260103SRichard Henderson     tcg_gen_trunc_i64_tl(dst, t64);
56913260103SRichard Henderson #endif
570c2636853SRichard Henderson }
571c2636853SRichard Henderson 
572c2636853SRichard Henderson static void gen_op_udivcc(TCGv dst, TCGv src1, TCGv src2)
573c2636853SRichard Henderson {
57413260103SRichard Henderson     TCGv_i64 t64;
57513260103SRichard Henderson 
57613260103SRichard Henderson #ifdef TARGET_SPARC64
57713260103SRichard Henderson     t64 = cpu_cc_V;
57813260103SRichard Henderson #else
57913260103SRichard Henderson     t64 = tcg_temp_new_i64();
58013260103SRichard Henderson #endif
58113260103SRichard Henderson 
58213260103SRichard Henderson     gen_helper_udiv(t64, tcg_env, src1, src2);
58313260103SRichard Henderson 
58413260103SRichard Henderson #ifdef TARGET_SPARC64
58513260103SRichard Henderson     tcg_gen_ext32u_tl(cpu_cc_N, t64);
58613260103SRichard Henderson     tcg_gen_shri_tl(cpu_cc_V, t64, 32);
58713260103SRichard Henderson     tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N);
58813260103SRichard Henderson     tcg_gen_movi_tl(cpu_icc_C, 0);
58913260103SRichard Henderson #else
59013260103SRichard Henderson     tcg_gen_extr_i64_tl(cpu_cc_N, cpu_cc_V, t64);
59113260103SRichard Henderson #endif
59213260103SRichard Henderson     tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N);
59313260103SRichard Henderson     tcg_gen_movi_tl(cpu_cc_C, 0);
59413260103SRichard Henderson     tcg_gen_mov_tl(dst, cpu_cc_N);
595c2636853SRichard Henderson }
596c2636853SRichard Henderson 
597c2636853SRichard Henderson static void gen_op_sdivcc(TCGv dst, TCGv src1, TCGv src2)
598c2636853SRichard Henderson {
59913260103SRichard Henderson     TCGv_i64 t64;
60013260103SRichard Henderson 
60113260103SRichard Henderson #ifdef TARGET_SPARC64
60213260103SRichard Henderson     t64 = cpu_cc_V;
60313260103SRichard Henderson #else
60413260103SRichard Henderson     t64 = tcg_temp_new_i64();
60513260103SRichard Henderson #endif
60613260103SRichard Henderson 
60713260103SRichard Henderson     gen_helper_sdiv(t64, tcg_env, src1, src2);
60813260103SRichard Henderson 
60913260103SRichard Henderson #ifdef TARGET_SPARC64
61013260103SRichard Henderson     tcg_gen_ext32s_tl(cpu_cc_N, t64);
61113260103SRichard Henderson     tcg_gen_shri_tl(cpu_cc_V, t64, 32);
61213260103SRichard Henderson     tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N);
61313260103SRichard Henderson     tcg_gen_movi_tl(cpu_icc_C, 0);
61413260103SRichard Henderson #else
61513260103SRichard Henderson     tcg_gen_extr_i64_tl(cpu_cc_N, cpu_cc_V, t64);
61613260103SRichard Henderson #endif
61713260103SRichard Henderson     tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N);
61813260103SRichard Henderson     tcg_gen_movi_tl(cpu_cc_C, 0);
61913260103SRichard Henderson     tcg_gen_mov_tl(dst, cpu_cc_N);
620c2636853SRichard Henderson }
621c2636853SRichard Henderson 
622a9aba13dSRichard Henderson static void gen_op_taddcctv(TCGv dst, TCGv src1, TCGv src2)
623a9aba13dSRichard Henderson {
624a9aba13dSRichard Henderson     gen_helper_taddcctv(dst, tcg_env, src1, src2);
625a9aba13dSRichard Henderson }
626a9aba13dSRichard Henderson 
627a9aba13dSRichard Henderson static void gen_op_tsubcctv(TCGv dst, TCGv src1, TCGv src2)
628a9aba13dSRichard Henderson {
629a9aba13dSRichard Henderson     gen_helper_tsubcctv(dst, tcg_env, src1, src2);
630a9aba13dSRichard Henderson }
631a9aba13dSRichard Henderson 
6329c6ec5bcSRichard Henderson static void gen_op_popc(TCGv dst, TCGv src1, TCGv src2)
6339c6ec5bcSRichard Henderson {
6349c6ec5bcSRichard Henderson     tcg_gen_ctpop_tl(dst, src2);
6359c6ec5bcSRichard Henderson }
6369c6ec5bcSRichard Henderson 
63745bfed3bSRichard Henderson #ifndef TARGET_SPARC64
63845bfed3bSRichard Henderson static void gen_helper_array8(TCGv dst, TCGv src1, TCGv src2)
63945bfed3bSRichard Henderson {
64045bfed3bSRichard Henderson     g_assert_not_reached();
64145bfed3bSRichard Henderson }
64245bfed3bSRichard Henderson #endif
64345bfed3bSRichard Henderson 
64445bfed3bSRichard Henderson static void gen_op_array16(TCGv dst, TCGv src1, TCGv src2)
64545bfed3bSRichard Henderson {
64645bfed3bSRichard Henderson     gen_helper_array8(dst, src1, src2);
64745bfed3bSRichard Henderson     tcg_gen_shli_tl(dst, dst, 1);
64845bfed3bSRichard Henderson }
64945bfed3bSRichard Henderson 
65045bfed3bSRichard Henderson static void gen_op_array32(TCGv dst, TCGv src1, TCGv src2)
65145bfed3bSRichard Henderson {
65245bfed3bSRichard Henderson     gen_helper_array8(dst, src1, src2);
65345bfed3bSRichard Henderson     tcg_gen_shli_tl(dst, dst, 2);
65445bfed3bSRichard Henderson }
65545bfed3bSRichard Henderson 
6562f722641SRichard Henderson static void gen_op_fpack16(TCGv_i32 dst, TCGv_i64 src)
6572f722641SRichard Henderson {
6582f722641SRichard Henderson #ifdef TARGET_SPARC64
6592f722641SRichard Henderson     gen_helper_fpack16(dst, cpu_gsr, src);
6602f722641SRichard Henderson #else
6612f722641SRichard Henderson     g_assert_not_reached();
6622f722641SRichard Henderson #endif
6632f722641SRichard Henderson }
6642f722641SRichard Henderson 
6652f722641SRichard Henderson static void gen_op_fpackfix(TCGv_i32 dst, TCGv_i64 src)
6662f722641SRichard Henderson {
6672f722641SRichard Henderson #ifdef TARGET_SPARC64
6682f722641SRichard Henderson     gen_helper_fpackfix(dst, cpu_gsr, src);
6692f722641SRichard Henderson #else
6702f722641SRichard Henderson     g_assert_not_reached();
6712f722641SRichard Henderson #endif
6722f722641SRichard Henderson }
6732f722641SRichard Henderson 
6744b6edc0aSRichard Henderson static void gen_op_fpack32(TCGv_i64 dst, TCGv_i64 src1, TCGv_i64 src2)
6754b6edc0aSRichard Henderson {
6764b6edc0aSRichard Henderson #ifdef TARGET_SPARC64
6774b6edc0aSRichard Henderson     gen_helper_fpack32(dst, cpu_gsr, src1, src2);
6784b6edc0aSRichard Henderson #else
6794b6edc0aSRichard Henderson     g_assert_not_reached();
6804b6edc0aSRichard Henderson #endif
6814b6edc0aSRichard Henderson }
6824b6edc0aSRichard Henderson 
6834b6edc0aSRichard Henderson static void gen_op_faligndata(TCGv_i64 dst, TCGv_i64 s1, TCGv_i64 s2)
6844b6edc0aSRichard Henderson {
6854b6edc0aSRichard Henderson #ifdef TARGET_SPARC64
6864b6edc0aSRichard Henderson     TCGv t1, t2, shift;
6874b6edc0aSRichard Henderson 
6884b6edc0aSRichard Henderson     t1 = tcg_temp_new();
6894b6edc0aSRichard Henderson     t2 = tcg_temp_new();
6904b6edc0aSRichard Henderson     shift = tcg_temp_new();
6914b6edc0aSRichard Henderson 
6924b6edc0aSRichard Henderson     tcg_gen_andi_tl(shift, cpu_gsr, 7);
6934b6edc0aSRichard Henderson     tcg_gen_shli_tl(shift, shift, 3);
6944b6edc0aSRichard Henderson     tcg_gen_shl_tl(t1, s1, shift);
6954b6edc0aSRichard Henderson 
6964b6edc0aSRichard Henderson     /*
6974b6edc0aSRichard Henderson      * A shift of 64 does not produce 0 in TCG.  Divide this into a
6984b6edc0aSRichard Henderson      * shift of (up to 63) followed by a constant shift of 1.
6994b6edc0aSRichard Henderson      */
7004b6edc0aSRichard Henderson     tcg_gen_xori_tl(shift, shift, 63);
7014b6edc0aSRichard Henderson     tcg_gen_shr_tl(t2, s2, shift);
7024b6edc0aSRichard Henderson     tcg_gen_shri_tl(t2, t2, 1);
7034b6edc0aSRichard Henderson 
7044b6edc0aSRichard Henderson     tcg_gen_or_tl(dst, t1, t2);
7054b6edc0aSRichard Henderson #else
7064b6edc0aSRichard Henderson     g_assert_not_reached();
7074b6edc0aSRichard Henderson #endif
7084b6edc0aSRichard Henderson }
7094b6edc0aSRichard Henderson 
7104b6edc0aSRichard Henderson static void gen_op_bshuffle(TCGv_i64 dst, TCGv_i64 src1, TCGv_i64 src2)
7114b6edc0aSRichard Henderson {
7124b6edc0aSRichard Henderson #ifdef TARGET_SPARC64
7134b6edc0aSRichard Henderson     gen_helper_bshuffle(dst, cpu_gsr, src1, src2);
7144b6edc0aSRichard Henderson #else
7154b6edc0aSRichard Henderson     g_assert_not_reached();
7164b6edc0aSRichard Henderson #endif
7174b6edc0aSRichard Henderson }
7184b6edc0aSRichard Henderson 
719a859602cSRichard Henderson static void gen_op_fmul8x16al(TCGv_i64 dst, TCGv_i32 src1, TCGv_i32 src2)
720a859602cSRichard Henderson {
721a859602cSRichard Henderson     tcg_gen_ext16s_i32(src2, src2);
722a859602cSRichard Henderson     gen_helper_fmul8x16a(dst, src1, src2);
723a859602cSRichard Henderson }
724a859602cSRichard Henderson 
725a859602cSRichard Henderson static void gen_op_fmul8x16au(TCGv_i64 dst, TCGv_i32 src1, TCGv_i32 src2)
726a859602cSRichard Henderson {
727a859602cSRichard Henderson     tcg_gen_sari_i32(src2, src2, 16);
728a859602cSRichard Henderson     gen_helper_fmul8x16a(dst, src1, src2);
729a859602cSRichard Henderson }
730a859602cSRichard Henderson 
731be8998e0SRichard Henderson static void gen_op_fmuld8ulx16(TCGv_i64 dst, TCGv_i32 src1, TCGv_i32 src2)
732be8998e0SRichard Henderson {
733be8998e0SRichard Henderson     TCGv_i32 t0 = tcg_temp_new_i32();
734be8998e0SRichard Henderson     TCGv_i32 t1 = tcg_temp_new_i32();
735be8998e0SRichard Henderson     TCGv_i32 t2 = tcg_temp_new_i32();
736be8998e0SRichard Henderson 
737be8998e0SRichard Henderson     tcg_gen_ext8u_i32(t0, src1);
738be8998e0SRichard Henderson     tcg_gen_ext16s_i32(t1, src2);
739be8998e0SRichard Henderson     tcg_gen_mul_i32(t0, t0, t1);
740be8998e0SRichard Henderson 
741be8998e0SRichard Henderson     tcg_gen_extract_i32(t1, src1, 16, 8);
742be8998e0SRichard Henderson     tcg_gen_sextract_i32(t2, src2, 16, 16);
743be8998e0SRichard Henderson     tcg_gen_mul_i32(t1, t1, t2);
744be8998e0SRichard Henderson 
745be8998e0SRichard Henderson     tcg_gen_concat_i32_i64(dst, t0, t1);
746be8998e0SRichard Henderson }
747be8998e0SRichard Henderson 
748be8998e0SRichard Henderson static void gen_op_fmuld8sux16(TCGv_i64 dst, TCGv_i32 src1, TCGv_i32 src2)
749be8998e0SRichard Henderson {
750be8998e0SRichard Henderson     TCGv_i32 t0 = tcg_temp_new_i32();
751be8998e0SRichard Henderson     TCGv_i32 t1 = tcg_temp_new_i32();
752be8998e0SRichard Henderson     TCGv_i32 t2 = tcg_temp_new_i32();
753be8998e0SRichard Henderson 
754be8998e0SRichard Henderson     /*
755be8998e0SRichard Henderson      * The insn description talks about extracting the upper 8 bits
756be8998e0SRichard Henderson      * of the signed 16-bit input rs1, performing the multiply, then
757be8998e0SRichard Henderson      * shifting left by 8 bits.  Instead, zap the lower 8 bits of
758be8998e0SRichard Henderson      * the rs1 input, which avoids the need for two shifts.
759be8998e0SRichard Henderson      */
760be8998e0SRichard Henderson     tcg_gen_ext16s_i32(t0, src1);
761be8998e0SRichard Henderson     tcg_gen_andi_i32(t0, t0, ~0xff);
762be8998e0SRichard Henderson     tcg_gen_ext16s_i32(t1, src2);
763be8998e0SRichard Henderson     tcg_gen_mul_i32(t0, t0, t1);
764be8998e0SRichard Henderson 
765be8998e0SRichard Henderson     tcg_gen_sextract_i32(t1, src1, 16, 16);
766be8998e0SRichard Henderson     tcg_gen_andi_i32(t1, t1, ~0xff);
767be8998e0SRichard Henderson     tcg_gen_sextract_i32(t2, src2, 16, 16);
768be8998e0SRichard Henderson     tcg_gen_mul_i32(t1, t1, t2);
769be8998e0SRichard Henderson 
770be8998e0SRichard Henderson     tcg_gen_concat_i32_i64(dst, t0, t1);
771be8998e0SRichard Henderson }
772be8998e0SRichard Henderson 
77389527e3aSRichard Henderson static void finishing_insn(DisasContext *dc)
77489527e3aSRichard Henderson {
77589527e3aSRichard Henderson     /*
77689527e3aSRichard Henderson      * From here, there is no future path through an unwinding exception.
77789527e3aSRichard Henderson      * If the current insn cannot raise an exception, the computation of
77889527e3aSRichard Henderson      * cpu_cond may be able to be elided.
77989527e3aSRichard Henderson      */
78089527e3aSRichard Henderson     if (dc->cpu_cond_live) {
78189527e3aSRichard Henderson         tcg_gen_discard_tl(cpu_cond);
78289527e3aSRichard Henderson         dc->cpu_cond_live = false;
78389527e3aSRichard Henderson     }
78489527e3aSRichard Henderson }
78589527e3aSRichard Henderson 
7860c2e96c1SRichard Henderson static void gen_generic_branch(DisasContext *dc)
787fcf5ef2aSThomas Huth {
78800ab7e61SRichard Henderson     TCGv npc0 = tcg_constant_tl(dc->jump_pc[0]);
78900ab7e61SRichard Henderson     TCGv npc1 = tcg_constant_tl(dc->jump_pc[1]);
790533f042fSRichard Henderson     TCGv c2 = tcg_constant_tl(dc->jump.c2);
791fcf5ef2aSThomas Huth 
792533f042fSRichard Henderson     tcg_gen_movcond_tl(dc->jump.cond, cpu_npc, dc->jump.c1, c2, npc0, npc1);
793fcf5ef2aSThomas Huth }
794fcf5ef2aSThomas Huth 
795fcf5ef2aSThomas Huth /* call this function before using the condition register as it may
796fcf5ef2aSThomas Huth    have been set for a jump */
7970c2e96c1SRichard Henderson static void flush_cond(DisasContext *dc)
798fcf5ef2aSThomas Huth {
799fcf5ef2aSThomas Huth     if (dc->npc == JUMP_PC) {
800fcf5ef2aSThomas Huth         gen_generic_branch(dc);
80199c82c47SRichard Henderson         dc->npc = DYNAMIC_PC_LOOKUP;
802fcf5ef2aSThomas Huth     }
803fcf5ef2aSThomas Huth }
804fcf5ef2aSThomas Huth 
8050c2e96c1SRichard Henderson static void save_npc(DisasContext *dc)
806fcf5ef2aSThomas Huth {
807633c4283SRichard Henderson     if (dc->npc & 3) {
808633c4283SRichard Henderson         switch (dc->npc) {
809633c4283SRichard Henderson         case JUMP_PC:
810fcf5ef2aSThomas Huth             gen_generic_branch(dc);
81199c82c47SRichard Henderson             dc->npc = DYNAMIC_PC_LOOKUP;
812633c4283SRichard Henderson             break;
813633c4283SRichard Henderson         case DYNAMIC_PC:
814633c4283SRichard Henderson         case DYNAMIC_PC_LOOKUP:
815633c4283SRichard Henderson             break;
816633c4283SRichard Henderson         default:
817633c4283SRichard Henderson             g_assert_not_reached();
818633c4283SRichard Henderson         }
819633c4283SRichard Henderson     } else {
820fcf5ef2aSThomas Huth         tcg_gen_movi_tl(cpu_npc, dc->npc);
821fcf5ef2aSThomas Huth     }
822fcf5ef2aSThomas Huth }
823fcf5ef2aSThomas Huth 
8240c2e96c1SRichard Henderson static void save_state(DisasContext *dc)
825fcf5ef2aSThomas Huth {
826fcf5ef2aSThomas Huth     tcg_gen_movi_tl(cpu_pc, dc->pc);
827fcf5ef2aSThomas Huth     save_npc(dc);
828fcf5ef2aSThomas Huth }
829fcf5ef2aSThomas Huth 
830fcf5ef2aSThomas Huth static void gen_exception(DisasContext *dc, int which)
831fcf5ef2aSThomas Huth {
83289527e3aSRichard Henderson     finishing_insn(dc);
833fcf5ef2aSThomas Huth     save_state(dc);
834ad75a51eSRichard Henderson     gen_helper_raise_exception(tcg_env, tcg_constant_i32(which));
835af00be49SEmilio G. Cota     dc->base.is_jmp = DISAS_NORETURN;
836fcf5ef2aSThomas Huth }
837fcf5ef2aSThomas Huth 
838186e7890SRichard Henderson static TCGLabel *delay_exceptionv(DisasContext *dc, TCGv_i32 excp)
839fcf5ef2aSThomas Huth {
840186e7890SRichard Henderson     DisasDelayException *e = g_new0(DisasDelayException, 1);
841186e7890SRichard Henderson 
842186e7890SRichard Henderson     e->next = dc->delay_excp_list;
843186e7890SRichard Henderson     dc->delay_excp_list = e;
844186e7890SRichard Henderson 
845186e7890SRichard Henderson     e->lab = gen_new_label();
846186e7890SRichard Henderson     e->excp = excp;
847186e7890SRichard Henderson     e->pc = dc->pc;
848186e7890SRichard Henderson     /* Caller must have used flush_cond before branch. */
849186e7890SRichard Henderson     assert(e->npc != JUMP_PC);
850186e7890SRichard Henderson     e->npc = dc->npc;
851186e7890SRichard Henderson 
852186e7890SRichard Henderson     return e->lab;
853186e7890SRichard Henderson }
854186e7890SRichard Henderson 
855186e7890SRichard Henderson static TCGLabel *delay_exception(DisasContext *dc, int excp)
856186e7890SRichard Henderson {
857186e7890SRichard Henderson     return delay_exceptionv(dc, tcg_constant_i32(excp));
858186e7890SRichard Henderson }
859186e7890SRichard Henderson 
860186e7890SRichard Henderson static void gen_check_align(DisasContext *dc, TCGv addr, int mask)
861186e7890SRichard Henderson {
862186e7890SRichard Henderson     TCGv t = tcg_temp_new();
863186e7890SRichard Henderson     TCGLabel *lab;
864186e7890SRichard Henderson 
865186e7890SRichard Henderson     tcg_gen_andi_tl(t, addr, mask);
866186e7890SRichard Henderson 
867186e7890SRichard Henderson     flush_cond(dc);
868186e7890SRichard Henderson     lab = delay_exception(dc, TT_UNALIGNED);
869186e7890SRichard Henderson     tcg_gen_brcondi_tl(TCG_COND_NE, t, 0, lab);
870fcf5ef2aSThomas Huth }
871fcf5ef2aSThomas Huth 
8720c2e96c1SRichard Henderson static void gen_mov_pc_npc(DisasContext *dc)
873fcf5ef2aSThomas Huth {
87489527e3aSRichard Henderson     finishing_insn(dc);
87589527e3aSRichard Henderson 
876633c4283SRichard Henderson     if (dc->npc & 3) {
877633c4283SRichard Henderson         switch (dc->npc) {
878633c4283SRichard Henderson         case JUMP_PC:
879fcf5ef2aSThomas Huth             gen_generic_branch(dc);
880fcf5ef2aSThomas Huth             tcg_gen_mov_tl(cpu_pc, cpu_npc);
88199c82c47SRichard Henderson             dc->pc = DYNAMIC_PC_LOOKUP;
882633c4283SRichard Henderson             break;
883633c4283SRichard Henderson         case DYNAMIC_PC:
884633c4283SRichard Henderson         case DYNAMIC_PC_LOOKUP:
885fcf5ef2aSThomas Huth             tcg_gen_mov_tl(cpu_pc, cpu_npc);
886633c4283SRichard Henderson             dc->pc = dc->npc;
887633c4283SRichard Henderson             break;
888633c4283SRichard Henderson         default:
889633c4283SRichard Henderson             g_assert_not_reached();
890633c4283SRichard Henderson         }
891fcf5ef2aSThomas Huth     } else {
892fcf5ef2aSThomas Huth         dc->pc = dc->npc;
893fcf5ef2aSThomas Huth     }
894fcf5ef2aSThomas Huth }
895fcf5ef2aSThomas Huth 
896fcf5ef2aSThomas Huth static void gen_compare(DisasCompare *cmp, bool xcc, unsigned int cond,
897fcf5ef2aSThomas Huth                         DisasContext *dc)
898fcf5ef2aSThomas Huth {
899b597eedcSRichard Henderson     TCGv t1;
900fcf5ef2aSThomas Huth 
9012a1905c7SRichard Henderson     cmp->c1 = t1 = tcg_temp_new();
902c8507ebfSRichard Henderson     cmp->c2 = 0;
9032a1905c7SRichard Henderson 
9042a1905c7SRichard Henderson     switch (cond & 7) {
9052a1905c7SRichard Henderson     case 0x0: /* never */
9062a1905c7SRichard Henderson         cmp->cond = TCG_COND_NEVER;
907c8507ebfSRichard Henderson         cmp->c1 = tcg_constant_tl(0);
908fcf5ef2aSThomas Huth         break;
9092a1905c7SRichard Henderson 
9102a1905c7SRichard Henderson     case 0x1: /* eq: Z */
9112a1905c7SRichard Henderson         cmp->cond = TCG_COND_EQ;
9122a1905c7SRichard Henderson         if (TARGET_LONG_BITS == 32 || xcc) {
9132a1905c7SRichard Henderson             tcg_gen_mov_tl(t1, cpu_cc_Z);
9142a1905c7SRichard Henderson         } else {
9152a1905c7SRichard Henderson             tcg_gen_ext32u_tl(t1, cpu_icc_Z);
9162a1905c7SRichard Henderson         }
9172a1905c7SRichard Henderson         break;
9182a1905c7SRichard Henderson 
9192a1905c7SRichard Henderson     case 0x2: /* le: Z | (N ^ V) */
9202a1905c7SRichard Henderson         /*
9212a1905c7SRichard Henderson          * Simplify:
9222a1905c7SRichard Henderson          *   cc_Z || (N ^ V) < 0        NE
9232a1905c7SRichard Henderson          *   cc_Z && !((N ^ V) < 0)     EQ
9242a1905c7SRichard Henderson          *   cc_Z & ~((N ^ V) >> TLB)   EQ
9252a1905c7SRichard Henderson          */
9262a1905c7SRichard Henderson         cmp->cond = TCG_COND_EQ;
9272a1905c7SRichard Henderson         tcg_gen_xor_tl(t1, cpu_cc_N, cpu_cc_V);
9282a1905c7SRichard Henderson         tcg_gen_sextract_tl(t1, t1, xcc ? 63 : 31, 1);
9292a1905c7SRichard Henderson         tcg_gen_andc_tl(t1, xcc ? cpu_cc_Z : cpu_icc_Z, t1);
9302a1905c7SRichard Henderson         if (TARGET_LONG_BITS == 64 && !xcc) {
9312a1905c7SRichard Henderson             tcg_gen_ext32u_tl(t1, t1);
9322a1905c7SRichard Henderson         }
9332a1905c7SRichard Henderson         break;
9342a1905c7SRichard Henderson 
9352a1905c7SRichard Henderson     case 0x3: /* lt: N ^ V */
9362a1905c7SRichard Henderson         cmp->cond = TCG_COND_LT;
9372a1905c7SRichard Henderson         tcg_gen_xor_tl(t1, cpu_cc_N, cpu_cc_V);
9382a1905c7SRichard Henderson         if (TARGET_LONG_BITS == 64 && !xcc) {
9392a1905c7SRichard Henderson             tcg_gen_ext32s_tl(t1, t1);
9402a1905c7SRichard Henderson         }
9412a1905c7SRichard Henderson         break;
9422a1905c7SRichard Henderson 
9432a1905c7SRichard Henderson     case 0x4: /* leu: Z | C */
9442a1905c7SRichard Henderson         /*
9452a1905c7SRichard Henderson          * Simplify:
9462a1905c7SRichard Henderson          *   cc_Z == 0 || cc_C != 0     NE
9472a1905c7SRichard Henderson          *   cc_Z != 0 && cc_C == 0     EQ
9482a1905c7SRichard Henderson          *   cc_Z & (cc_C ? 0 : -1)     EQ
9492a1905c7SRichard Henderson          *   cc_Z & (cc_C - 1)          EQ
9502a1905c7SRichard Henderson          */
9512a1905c7SRichard Henderson         cmp->cond = TCG_COND_EQ;
9522a1905c7SRichard Henderson         if (TARGET_LONG_BITS == 32 || xcc) {
9532a1905c7SRichard Henderson             tcg_gen_subi_tl(t1, cpu_cc_C, 1);
9542a1905c7SRichard Henderson             tcg_gen_and_tl(t1, t1, cpu_cc_Z);
9552a1905c7SRichard Henderson         } else {
9562a1905c7SRichard Henderson             tcg_gen_extract_tl(t1, cpu_icc_C, 32, 1);
9572a1905c7SRichard Henderson             tcg_gen_subi_tl(t1, t1, 1);
9582a1905c7SRichard Henderson             tcg_gen_and_tl(t1, t1, cpu_icc_Z);
9592a1905c7SRichard Henderson             tcg_gen_ext32u_tl(t1, t1);
9602a1905c7SRichard Henderson         }
9612a1905c7SRichard Henderson         break;
9622a1905c7SRichard Henderson 
9632a1905c7SRichard Henderson     case 0x5: /* ltu: C */
9642a1905c7SRichard Henderson         cmp->cond = TCG_COND_NE;
9652a1905c7SRichard Henderson         if (TARGET_LONG_BITS == 32 || xcc) {
9662a1905c7SRichard Henderson             tcg_gen_mov_tl(t1, cpu_cc_C);
9672a1905c7SRichard Henderson         } else {
9682a1905c7SRichard Henderson             tcg_gen_extract_tl(t1, cpu_icc_C, 32, 1);
9692a1905c7SRichard Henderson         }
9702a1905c7SRichard Henderson         break;
9712a1905c7SRichard Henderson 
9722a1905c7SRichard Henderson     case 0x6: /* neg: N */
9732a1905c7SRichard Henderson         cmp->cond = TCG_COND_LT;
9742a1905c7SRichard Henderson         if (TARGET_LONG_BITS == 32 || xcc) {
9752a1905c7SRichard Henderson             tcg_gen_mov_tl(t1, cpu_cc_N);
9762a1905c7SRichard Henderson         } else {
9772a1905c7SRichard Henderson             tcg_gen_ext32s_tl(t1, cpu_cc_N);
9782a1905c7SRichard Henderson         }
9792a1905c7SRichard Henderson         break;
9802a1905c7SRichard Henderson 
9812a1905c7SRichard Henderson     case 0x7: /* vs: V */
9822a1905c7SRichard Henderson         cmp->cond = TCG_COND_LT;
9832a1905c7SRichard Henderson         if (TARGET_LONG_BITS == 32 || xcc) {
9842a1905c7SRichard Henderson             tcg_gen_mov_tl(t1, cpu_cc_V);
9852a1905c7SRichard Henderson         } else {
9862a1905c7SRichard Henderson             tcg_gen_ext32s_tl(t1, cpu_cc_V);
9872a1905c7SRichard Henderson         }
9882a1905c7SRichard Henderson         break;
9892a1905c7SRichard Henderson     }
9902a1905c7SRichard Henderson     if (cond & 8) {
9912a1905c7SRichard Henderson         cmp->cond = tcg_invert_cond(cmp->cond);
992fcf5ef2aSThomas Huth     }
993fcf5ef2aSThomas Huth }
994fcf5ef2aSThomas Huth 
995fcf5ef2aSThomas Huth static void gen_fcompare(DisasCompare *cmp, unsigned int cc, unsigned int cond)
996fcf5ef2aSThomas Huth {
997d8c5b92fSRichard Henderson     TCGv_i32 fcc = cpu_fcc[cc];
998d8c5b92fSRichard Henderson     TCGv_i32 c1 = fcc;
999d8c5b92fSRichard Henderson     int c2 = 0;
1000d8c5b92fSRichard Henderson     TCGCond tcond;
1001fcf5ef2aSThomas Huth 
1002d8c5b92fSRichard Henderson     /*
1003d8c5b92fSRichard Henderson      * FCC values:
1004d8c5b92fSRichard Henderson      * 0 =
1005d8c5b92fSRichard Henderson      * 1 <
1006d8c5b92fSRichard Henderson      * 2 >
1007d8c5b92fSRichard Henderson      * 3 unordered
1008d8c5b92fSRichard Henderson      */
1009d8c5b92fSRichard Henderson     switch (cond & 7) {
1010d8c5b92fSRichard Henderson     case 0x0: /* fbn */
1011d8c5b92fSRichard Henderson         tcond = TCG_COND_NEVER;
1012fcf5ef2aSThomas Huth         break;
1013d8c5b92fSRichard Henderson     case 0x1: /* fbne : !0 */
1014d8c5b92fSRichard Henderson         tcond = TCG_COND_NE;
1015fcf5ef2aSThomas Huth         break;
1016d8c5b92fSRichard Henderson     case 0x2: /* fblg : 1 or 2 */
1017d8c5b92fSRichard Henderson         /* fcc in {1,2} - 1 -> fcc in {0,1} */
1018d8c5b92fSRichard Henderson         c1 = tcg_temp_new_i32();
1019d8c5b92fSRichard Henderson         tcg_gen_addi_i32(c1, fcc, -1);
1020d8c5b92fSRichard Henderson         c2 = 1;
1021d8c5b92fSRichard Henderson         tcond = TCG_COND_LEU;
1022fcf5ef2aSThomas Huth         break;
1023d8c5b92fSRichard Henderson     case 0x3: /* fbul : 1 or 3 */
1024d8c5b92fSRichard Henderson         c1 = tcg_temp_new_i32();
1025d8c5b92fSRichard Henderson         tcg_gen_andi_i32(c1, fcc, 1);
1026d8c5b92fSRichard Henderson         tcond = TCG_COND_NE;
1027d8c5b92fSRichard Henderson         break;
1028d8c5b92fSRichard Henderson     case 0x4: /* fbl  : 1 */
1029d8c5b92fSRichard Henderson         c2 = 1;
1030d8c5b92fSRichard Henderson         tcond = TCG_COND_EQ;
1031d8c5b92fSRichard Henderson         break;
1032d8c5b92fSRichard Henderson     case 0x5: /* fbug : 2 or 3 */
1033d8c5b92fSRichard Henderson         c2 = 2;
1034d8c5b92fSRichard Henderson         tcond = TCG_COND_GEU;
1035d8c5b92fSRichard Henderson         break;
1036d8c5b92fSRichard Henderson     case 0x6: /* fbg  : 2 */
1037d8c5b92fSRichard Henderson         c2 = 2;
1038d8c5b92fSRichard Henderson         tcond = TCG_COND_EQ;
1039d8c5b92fSRichard Henderson         break;
1040d8c5b92fSRichard Henderson     case 0x7: /* fbu  : 3 */
1041d8c5b92fSRichard Henderson         c2 = 3;
1042d8c5b92fSRichard Henderson         tcond = TCG_COND_EQ;
1043fcf5ef2aSThomas Huth         break;
1044fcf5ef2aSThomas Huth     }
1045d8c5b92fSRichard Henderson     if (cond & 8) {
1046d8c5b92fSRichard Henderson         tcond = tcg_invert_cond(tcond);
1047fcf5ef2aSThomas Huth     }
1048d8c5b92fSRichard Henderson 
1049d8c5b92fSRichard Henderson     cmp->cond = tcond;
1050d8c5b92fSRichard Henderson     cmp->c2 = c2;
1051d8c5b92fSRichard Henderson     cmp->c1 = tcg_temp_new();
1052d8c5b92fSRichard Henderson     tcg_gen_extu_i32_tl(cmp->c1, c1);
1053fcf5ef2aSThomas Huth }
1054fcf5ef2aSThomas Huth 
10552c4f56c9SRichard Henderson static bool gen_compare_reg(DisasCompare *cmp, int cond, TCGv r_src)
10562c4f56c9SRichard Henderson {
10572c4f56c9SRichard Henderson     static const TCGCond cond_reg[4] = {
1058ab9ffe98SRichard Henderson         TCG_COND_NEVER,  /* reserved */
1059fcf5ef2aSThomas Huth         TCG_COND_EQ,
1060fcf5ef2aSThomas Huth         TCG_COND_LE,
1061fcf5ef2aSThomas Huth         TCG_COND_LT,
1062fcf5ef2aSThomas Huth     };
10632c4f56c9SRichard Henderson     TCGCond tcond;
1064fcf5ef2aSThomas Huth 
10652c4f56c9SRichard Henderson     if ((cond & 3) == 0) {
10662c4f56c9SRichard Henderson         return false;
10672c4f56c9SRichard Henderson     }
10682c4f56c9SRichard Henderson     tcond = cond_reg[cond & 3];
10692c4f56c9SRichard Henderson     if (cond & 4) {
10702c4f56c9SRichard Henderson         tcond = tcg_invert_cond(tcond);
10712c4f56c9SRichard Henderson     }
10722c4f56c9SRichard Henderson 
10732c4f56c9SRichard Henderson     cmp->cond = tcond;
1074816f89b7SRichard Henderson     cmp->c1 = tcg_temp_new();
1075c8507ebfSRichard Henderson     cmp->c2 = 0;
1076816f89b7SRichard Henderson     tcg_gen_mov_tl(cmp->c1, r_src);
10772c4f56c9SRichard Henderson     return true;
1078fcf5ef2aSThomas Huth }
1079fcf5ef2aSThomas Huth 
1080baf3dbf2SRichard Henderson static void gen_op_clear_ieee_excp_and_FTT(void)
1081baf3dbf2SRichard Henderson {
10823590f01eSRichard Henderson     tcg_gen_st_i32(tcg_constant_i32(0), tcg_env,
10833590f01eSRichard Henderson                    offsetof(CPUSPARCState, fsr_cexc_ftt));
1084baf3dbf2SRichard Henderson }
1085baf3dbf2SRichard Henderson 
1086baf3dbf2SRichard Henderson static void gen_op_fmovs(TCGv_i32 dst, TCGv_i32 src)
1087baf3dbf2SRichard Henderson {
1088baf3dbf2SRichard Henderson     gen_op_clear_ieee_excp_and_FTT();
1089baf3dbf2SRichard Henderson     tcg_gen_mov_i32(dst, src);
1090baf3dbf2SRichard Henderson }
1091baf3dbf2SRichard Henderson 
1092baf3dbf2SRichard Henderson static void gen_op_fnegs(TCGv_i32 dst, TCGv_i32 src)
1093baf3dbf2SRichard Henderson {
1094baf3dbf2SRichard Henderson     gen_op_clear_ieee_excp_and_FTT();
1095daf457d4SRichard Henderson     tcg_gen_xori_i32(dst, src, 1u << 31);
1096baf3dbf2SRichard Henderson }
1097baf3dbf2SRichard Henderson 
1098baf3dbf2SRichard Henderson static void gen_op_fabss(TCGv_i32 dst, TCGv_i32 src)
1099baf3dbf2SRichard Henderson {
1100baf3dbf2SRichard Henderson     gen_op_clear_ieee_excp_and_FTT();
1101daf457d4SRichard Henderson     tcg_gen_andi_i32(dst, src, ~(1u << 31));
1102baf3dbf2SRichard Henderson }
1103baf3dbf2SRichard Henderson 
1104c6d83e4fSRichard Henderson static void gen_op_fmovd(TCGv_i64 dst, TCGv_i64 src)
1105c6d83e4fSRichard Henderson {
1106c6d83e4fSRichard Henderson     gen_op_clear_ieee_excp_and_FTT();
1107c6d83e4fSRichard Henderson     tcg_gen_mov_i64(dst, src);
1108c6d83e4fSRichard Henderson }
1109c6d83e4fSRichard Henderson 
1110c6d83e4fSRichard Henderson static void gen_op_fnegd(TCGv_i64 dst, TCGv_i64 src)
1111c6d83e4fSRichard Henderson {
1112c6d83e4fSRichard Henderson     gen_op_clear_ieee_excp_and_FTT();
1113daf457d4SRichard Henderson     tcg_gen_xori_i64(dst, src, 1ull << 63);
1114c6d83e4fSRichard Henderson }
1115c6d83e4fSRichard Henderson 
1116c6d83e4fSRichard Henderson static void gen_op_fabsd(TCGv_i64 dst, TCGv_i64 src)
1117c6d83e4fSRichard Henderson {
1118c6d83e4fSRichard Henderson     gen_op_clear_ieee_excp_and_FTT();
1119daf457d4SRichard Henderson     tcg_gen_andi_i64(dst, src, ~(1ull << 63));
1120daf457d4SRichard Henderson }
1121daf457d4SRichard Henderson 
1122daf457d4SRichard Henderson static void gen_op_fnegq(TCGv_i128 dst, TCGv_i128 src)
1123daf457d4SRichard Henderson {
1124daf457d4SRichard Henderson     TCGv_i64 l = tcg_temp_new_i64();
1125daf457d4SRichard Henderson     TCGv_i64 h = tcg_temp_new_i64();
1126daf457d4SRichard Henderson 
1127daf457d4SRichard Henderson     tcg_gen_extr_i128_i64(l, h, src);
1128daf457d4SRichard Henderson     tcg_gen_xori_i64(h, h, 1ull << 63);
1129daf457d4SRichard Henderson     tcg_gen_concat_i64_i128(dst, l, h);
1130daf457d4SRichard Henderson }
1131daf457d4SRichard Henderson 
1132daf457d4SRichard Henderson static void gen_op_fabsq(TCGv_i128 dst, TCGv_i128 src)
1133daf457d4SRichard Henderson {
1134daf457d4SRichard Henderson     TCGv_i64 l = tcg_temp_new_i64();
1135daf457d4SRichard Henderson     TCGv_i64 h = tcg_temp_new_i64();
1136daf457d4SRichard Henderson 
1137daf457d4SRichard Henderson     tcg_gen_extr_i128_i64(l, h, src);
1138daf457d4SRichard Henderson     tcg_gen_andi_i64(h, h, ~(1ull << 63));
1139daf457d4SRichard Henderson     tcg_gen_concat_i64_i128(dst, l, h);
1140c6d83e4fSRichard Henderson }
1141c6d83e4fSRichard Henderson 
11423590f01eSRichard Henderson static void gen_op_fpexception_im(DisasContext *dc, int ftt)
1143fcf5ef2aSThomas Huth {
11443590f01eSRichard Henderson     /*
11453590f01eSRichard Henderson      * CEXC is only set when succesfully completing an FPop,
11463590f01eSRichard Henderson      * or when raising FSR_FTT_IEEE_EXCP, i.e. check_ieee_exception.
11473590f01eSRichard Henderson      * Thus we can simply store FTT into this field.
11483590f01eSRichard Henderson      */
11493590f01eSRichard Henderson     tcg_gen_st_i32(tcg_constant_i32(ftt), tcg_env,
11503590f01eSRichard Henderson                    offsetof(CPUSPARCState, fsr_cexc_ftt));
1151fcf5ef2aSThomas Huth     gen_exception(dc, TT_FP_EXCP);
1152fcf5ef2aSThomas Huth }
1153fcf5ef2aSThomas Huth 
1154fcf5ef2aSThomas Huth static int gen_trap_ifnofpu(DisasContext *dc)
1155fcf5ef2aSThomas Huth {
1156fcf5ef2aSThomas Huth #if !defined(CONFIG_USER_ONLY)
1157fcf5ef2aSThomas Huth     if (!dc->fpu_enabled) {
1158fcf5ef2aSThomas Huth         gen_exception(dc, TT_NFPU_INSN);
1159fcf5ef2aSThomas Huth         return 1;
1160fcf5ef2aSThomas Huth     }
1161fcf5ef2aSThomas Huth #endif
1162fcf5ef2aSThomas Huth     return 0;
1163fcf5ef2aSThomas Huth }
1164fcf5ef2aSThomas Huth 
1165fcf5ef2aSThomas Huth /* asi moves */
1166fcf5ef2aSThomas Huth typedef enum {
1167fcf5ef2aSThomas Huth     GET_ASI_HELPER,
1168fcf5ef2aSThomas Huth     GET_ASI_EXCP,
1169fcf5ef2aSThomas Huth     GET_ASI_DIRECT,
1170fcf5ef2aSThomas Huth     GET_ASI_DTWINX,
11712786a3f8SRichard Henderson     GET_ASI_CODE,
1172fcf5ef2aSThomas Huth     GET_ASI_BLOCK,
1173fcf5ef2aSThomas Huth     GET_ASI_SHORT,
1174fcf5ef2aSThomas Huth     GET_ASI_BCOPY,
1175fcf5ef2aSThomas Huth     GET_ASI_BFILL,
1176fcf5ef2aSThomas Huth } ASIType;
1177fcf5ef2aSThomas Huth 
1178fcf5ef2aSThomas Huth typedef struct {
1179fcf5ef2aSThomas Huth     ASIType type;
1180fcf5ef2aSThomas Huth     int asi;
1181fcf5ef2aSThomas Huth     int mem_idx;
118214776ab5STony Nguyen     MemOp memop;
1183fcf5ef2aSThomas Huth } DisasASI;
1184fcf5ef2aSThomas Huth 
1185811cc0b0SRichard Henderson /*
1186811cc0b0SRichard Henderson  * Build DisasASI.
1187811cc0b0SRichard Henderson  * For asi == -1, treat as non-asi.
1188811cc0b0SRichard Henderson  * For ask == -2, treat as immediate offset (v8 error, v9 %asi).
1189811cc0b0SRichard Henderson  */
1190811cc0b0SRichard Henderson static DisasASI resolve_asi(DisasContext *dc, int asi, MemOp memop)
1191fcf5ef2aSThomas Huth {
1192fcf5ef2aSThomas Huth     ASIType type = GET_ASI_HELPER;
1193fcf5ef2aSThomas Huth     int mem_idx = dc->mem_idx;
1194fcf5ef2aSThomas Huth 
1195811cc0b0SRichard Henderson     if (asi == -1) {
1196811cc0b0SRichard Henderson         /* Artificial "non-asi" case. */
1197811cc0b0SRichard Henderson         type = GET_ASI_DIRECT;
1198811cc0b0SRichard Henderson         goto done;
1199811cc0b0SRichard Henderson     }
1200811cc0b0SRichard Henderson 
1201fcf5ef2aSThomas Huth #ifndef TARGET_SPARC64
1202fcf5ef2aSThomas Huth     /* Before v9, all asis are immediate and privileged.  */
1203811cc0b0SRichard Henderson     if (asi < 0) {
1204fcf5ef2aSThomas Huth         gen_exception(dc, TT_ILL_INSN);
1205fcf5ef2aSThomas Huth         type = GET_ASI_EXCP;
1206fcf5ef2aSThomas Huth     } else if (supervisor(dc)
1207fcf5ef2aSThomas Huth                /* Note that LEON accepts ASI_USERDATA in user mode, for
1208fcf5ef2aSThomas Huth                   use with CASA.  Also note that previous versions of
1209fcf5ef2aSThomas Huth                   QEMU allowed (and old versions of gcc emitted) ASI_P
1210fcf5ef2aSThomas Huth                   for LEON, which is incorrect.  */
1211fcf5ef2aSThomas Huth                || (asi == ASI_USERDATA
1212fcf5ef2aSThomas Huth                    && (dc->def->features & CPU_FEATURE_CASA))) {
1213fcf5ef2aSThomas Huth         switch (asi) {
1214fcf5ef2aSThomas Huth         case ASI_USERDATA:    /* User data access */
1215fcf5ef2aSThomas Huth             mem_idx = MMU_USER_IDX;
1216fcf5ef2aSThomas Huth             type = GET_ASI_DIRECT;
1217fcf5ef2aSThomas Huth             break;
1218fcf5ef2aSThomas Huth         case ASI_KERNELDATA:  /* Supervisor data access */
1219fcf5ef2aSThomas Huth             mem_idx = MMU_KERNEL_IDX;
1220fcf5ef2aSThomas Huth             type = GET_ASI_DIRECT;
1221fcf5ef2aSThomas Huth             break;
12222786a3f8SRichard Henderson         case ASI_USERTXT:     /* User text access */
12232786a3f8SRichard Henderson             mem_idx = MMU_USER_IDX;
12242786a3f8SRichard Henderson             type = GET_ASI_CODE;
12252786a3f8SRichard Henderson             break;
12262786a3f8SRichard Henderson         case ASI_KERNELTXT:   /* Supervisor text access */
12272786a3f8SRichard Henderson             mem_idx = MMU_KERNEL_IDX;
12282786a3f8SRichard Henderson             type = GET_ASI_CODE;
12292786a3f8SRichard Henderson             break;
1230fcf5ef2aSThomas Huth         case ASI_M_BYPASS:    /* MMU passthrough */
1231fcf5ef2aSThomas Huth         case ASI_LEON_BYPASS: /* LEON MMU passthrough */
1232fcf5ef2aSThomas Huth             mem_idx = MMU_PHYS_IDX;
1233fcf5ef2aSThomas Huth             type = GET_ASI_DIRECT;
1234fcf5ef2aSThomas Huth             break;
1235fcf5ef2aSThomas Huth         case ASI_M_BCOPY: /* Block copy, sta access */
1236fcf5ef2aSThomas Huth             mem_idx = MMU_KERNEL_IDX;
1237fcf5ef2aSThomas Huth             type = GET_ASI_BCOPY;
1238fcf5ef2aSThomas Huth             break;
1239fcf5ef2aSThomas Huth         case ASI_M_BFILL: /* Block fill, stda access */
1240fcf5ef2aSThomas Huth             mem_idx = MMU_KERNEL_IDX;
1241fcf5ef2aSThomas Huth             type = GET_ASI_BFILL;
1242fcf5ef2aSThomas Huth             break;
1243fcf5ef2aSThomas Huth         }
12446e10f37cSKONRAD Frederic 
12456e10f37cSKONRAD Frederic         /* MMU_PHYS_IDX is used when the MMU is disabled to passthrough the
12466e10f37cSKONRAD Frederic          * permissions check in get_physical_address(..).
12476e10f37cSKONRAD Frederic          */
12486e10f37cSKONRAD Frederic         mem_idx = (dc->mem_idx == MMU_PHYS_IDX) ? MMU_PHYS_IDX : mem_idx;
1249fcf5ef2aSThomas Huth     } else {
1250fcf5ef2aSThomas Huth         gen_exception(dc, TT_PRIV_INSN);
1251fcf5ef2aSThomas Huth         type = GET_ASI_EXCP;
1252fcf5ef2aSThomas Huth     }
1253fcf5ef2aSThomas Huth #else
1254811cc0b0SRichard Henderson     if (asi < 0) {
1255fcf5ef2aSThomas Huth         asi = dc->asi;
1256fcf5ef2aSThomas Huth     }
1257fcf5ef2aSThomas Huth     /* With v9, all asis below 0x80 are privileged.  */
1258fcf5ef2aSThomas Huth     /* ??? We ought to check cpu_has_hypervisor, but we didn't copy
1259fcf5ef2aSThomas Huth        down that bit into DisasContext.  For the moment that's ok,
1260fcf5ef2aSThomas Huth        since the direct implementations below doesn't have any ASIs
1261fcf5ef2aSThomas Huth        in the restricted [0x30, 0x7f] range, and the check will be
1262fcf5ef2aSThomas Huth        done properly in the helper.  */
1263fcf5ef2aSThomas Huth     if (!supervisor(dc) && asi < 0x80) {
1264fcf5ef2aSThomas Huth         gen_exception(dc, TT_PRIV_ACT);
1265fcf5ef2aSThomas Huth         type = GET_ASI_EXCP;
1266fcf5ef2aSThomas Huth     } else {
1267fcf5ef2aSThomas Huth         switch (asi) {
1268fcf5ef2aSThomas Huth         case ASI_REAL:      /* Bypass */
1269fcf5ef2aSThomas Huth         case ASI_REAL_IO:   /* Bypass, non-cacheable */
1270fcf5ef2aSThomas Huth         case ASI_REAL_L:    /* Bypass LE */
1271fcf5ef2aSThomas Huth         case ASI_REAL_IO_L: /* Bypass, non-cacheable LE */
1272fcf5ef2aSThomas Huth         case ASI_TWINX_REAL:   /* Real address, twinx */
1273fcf5ef2aSThomas Huth         case ASI_TWINX_REAL_L: /* Real address, twinx, LE */
1274fcf5ef2aSThomas Huth         case ASI_QUAD_LDD_PHYS:
1275fcf5ef2aSThomas Huth         case ASI_QUAD_LDD_PHYS_L:
1276fcf5ef2aSThomas Huth             mem_idx = MMU_PHYS_IDX;
1277fcf5ef2aSThomas Huth             break;
1278fcf5ef2aSThomas Huth         case ASI_N:  /* Nucleus */
1279fcf5ef2aSThomas Huth         case ASI_NL: /* Nucleus LE */
1280fcf5ef2aSThomas Huth         case ASI_TWINX_N:
1281fcf5ef2aSThomas Huth         case ASI_TWINX_NL:
1282fcf5ef2aSThomas Huth         case ASI_NUCLEUS_QUAD_LDD:
1283fcf5ef2aSThomas Huth         case ASI_NUCLEUS_QUAD_LDD_L:
12849a10756dSArtyom Tarasenko             if (hypervisor(dc)) {
128584f8f587SArtyom Tarasenko                 mem_idx = MMU_PHYS_IDX;
12869a10756dSArtyom Tarasenko             } else {
1287fcf5ef2aSThomas Huth                 mem_idx = MMU_NUCLEUS_IDX;
12889a10756dSArtyom Tarasenko             }
1289fcf5ef2aSThomas Huth             break;
1290fcf5ef2aSThomas Huth         case ASI_AIUP:  /* As if user primary */
1291fcf5ef2aSThomas Huth         case ASI_AIUPL: /* As if user primary LE */
1292fcf5ef2aSThomas Huth         case ASI_TWINX_AIUP:
1293fcf5ef2aSThomas Huth         case ASI_TWINX_AIUP_L:
1294fcf5ef2aSThomas Huth         case ASI_BLK_AIUP_4V:
1295fcf5ef2aSThomas Huth         case ASI_BLK_AIUP_L_4V:
1296fcf5ef2aSThomas Huth         case ASI_BLK_AIUP:
1297fcf5ef2aSThomas Huth         case ASI_BLK_AIUPL:
1298fcf5ef2aSThomas Huth             mem_idx = MMU_USER_IDX;
1299fcf5ef2aSThomas Huth             break;
1300fcf5ef2aSThomas Huth         case ASI_AIUS:  /* As if user secondary */
1301fcf5ef2aSThomas Huth         case ASI_AIUSL: /* As if user secondary LE */
1302fcf5ef2aSThomas Huth         case ASI_TWINX_AIUS:
1303fcf5ef2aSThomas Huth         case ASI_TWINX_AIUS_L:
1304fcf5ef2aSThomas Huth         case ASI_BLK_AIUS_4V:
1305fcf5ef2aSThomas Huth         case ASI_BLK_AIUS_L_4V:
1306fcf5ef2aSThomas Huth         case ASI_BLK_AIUS:
1307fcf5ef2aSThomas Huth         case ASI_BLK_AIUSL:
1308fcf5ef2aSThomas Huth             mem_idx = MMU_USER_SECONDARY_IDX;
1309fcf5ef2aSThomas Huth             break;
1310fcf5ef2aSThomas Huth         case ASI_S:  /* Secondary */
1311fcf5ef2aSThomas Huth         case ASI_SL: /* Secondary LE */
1312fcf5ef2aSThomas Huth         case ASI_TWINX_S:
1313fcf5ef2aSThomas Huth         case ASI_TWINX_SL:
1314fcf5ef2aSThomas Huth         case ASI_BLK_COMMIT_S:
1315fcf5ef2aSThomas Huth         case ASI_BLK_S:
1316fcf5ef2aSThomas Huth         case ASI_BLK_SL:
1317fcf5ef2aSThomas Huth         case ASI_FL8_S:
1318fcf5ef2aSThomas Huth         case ASI_FL8_SL:
1319fcf5ef2aSThomas Huth         case ASI_FL16_S:
1320fcf5ef2aSThomas Huth         case ASI_FL16_SL:
1321fcf5ef2aSThomas Huth             if (mem_idx == MMU_USER_IDX) {
1322fcf5ef2aSThomas Huth                 mem_idx = MMU_USER_SECONDARY_IDX;
1323fcf5ef2aSThomas Huth             } else if (mem_idx == MMU_KERNEL_IDX) {
1324fcf5ef2aSThomas Huth                 mem_idx = MMU_KERNEL_SECONDARY_IDX;
1325fcf5ef2aSThomas Huth             }
1326fcf5ef2aSThomas Huth             break;
1327fcf5ef2aSThomas Huth         case ASI_P:  /* Primary */
1328fcf5ef2aSThomas Huth         case ASI_PL: /* Primary LE */
1329fcf5ef2aSThomas Huth         case ASI_TWINX_P:
1330fcf5ef2aSThomas Huth         case ASI_TWINX_PL:
1331fcf5ef2aSThomas Huth         case ASI_BLK_COMMIT_P:
1332fcf5ef2aSThomas Huth         case ASI_BLK_P:
1333fcf5ef2aSThomas Huth         case ASI_BLK_PL:
1334fcf5ef2aSThomas Huth         case ASI_FL8_P:
1335fcf5ef2aSThomas Huth         case ASI_FL8_PL:
1336fcf5ef2aSThomas Huth         case ASI_FL16_P:
1337fcf5ef2aSThomas Huth         case ASI_FL16_PL:
1338fcf5ef2aSThomas Huth             break;
1339fcf5ef2aSThomas Huth         }
1340fcf5ef2aSThomas Huth         switch (asi) {
1341fcf5ef2aSThomas Huth         case ASI_REAL:
1342fcf5ef2aSThomas Huth         case ASI_REAL_IO:
1343fcf5ef2aSThomas Huth         case ASI_REAL_L:
1344fcf5ef2aSThomas Huth         case ASI_REAL_IO_L:
1345fcf5ef2aSThomas Huth         case ASI_N:
1346fcf5ef2aSThomas Huth         case ASI_NL:
1347fcf5ef2aSThomas Huth         case ASI_AIUP:
1348fcf5ef2aSThomas Huth         case ASI_AIUPL:
1349fcf5ef2aSThomas Huth         case ASI_AIUS:
1350fcf5ef2aSThomas Huth         case ASI_AIUSL:
1351fcf5ef2aSThomas Huth         case ASI_S:
1352fcf5ef2aSThomas Huth         case ASI_SL:
1353fcf5ef2aSThomas Huth         case ASI_P:
1354fcf5ef2aSThomas Huth         case ASI_PL:
1355fcf5ef2aSThomas Huth             type = GET_ASI_DIRECT;
1356fcf5ef2aSThomas Huth             break;
1357fcf5ef2aSThomas Huth         case ASI_TWINX_REAL:
1358fcf5ef2aSThomas Huth         case ASI_TWINX_REAL_L:
1359fcf5ef2aSThomas Huth         case ASI_TWINX_N:
1360fcf5ef2aSThomas Huth         case ASI_TWINX_NL:
1361fcf5ef2aSThomas Huth         case ASI_TWINX_AIUP:
1362fcf5ef2aSThomas Huth         case ASI_TWINX_AIUP_L:
1363fcf5ef2aSThomas Huth         case ASI_TWINX_AIUS:
1364fcf5ef2aSThomas Huth         case ASI_TWINX_AIUS_L:
1365fcf5ef2aSThomas Huth         case ASI_TWINX_P:
1366fcf5ef2aSThomas Huth         case ASI_TWINX_PL:
1367fcf5ef2aSThomas Huth         case ASI_TWINX_S:
1368fcf5ef2aSThomas Huth         case ASI_TWINX_SL:
1369fcf5ef2aSThomas Huth         case ASI_QUAD_LDD_PHYS:
1370fcf5ef2aSThomas Huth         case ASI_QUAD_LDD_PHYS_L:
1371fcf5ef2aSThomas Huth         case ASI_NUCLEUS_QUAD_LDD:
1372fcf5ef2aSThomas Huth         case ASI_NUCLEUS_QUAD_LDD_L:
1373fcf5ef2aSThomas Huth             type = GET_ASI_DTWINX;
1374fcf5ef2aSThomas Huth             break;
1375fcf5ef2aSThomas Huth         case ASI_BLK_COMMIT_P:
1376fcf5ef2aSThomas Huth         case ASI_BLK_COMMIT_S:
1377fcf5ef2aSThomas Huth         case ASI_BLK_AIUP_4V:
1378fcf5ef2aSThomas Huth         case ASI_BLK_AIUP_L_4V:
1379fcf5ef2aSThomas Huth         case ASI_BLK_AIUP:
1380fcf5ef2aSThomas Huth         case ASI_BLK_AIUPL:
1381fcf5ef2aSThomas Huth         case ASI_BLK_AIUS_4V:
1382fcf5ef2aSThomas Huth         case ASI_BLK_AIUS_L_4V:
1383fcf5ef2aSThomas Huth         case ASI_BLK_AIUS:
1384fcf5ef2aSThomas Huth         case ASI_BLK_AIUSL:
1385fcf5ef2aSThomas Huth         case ASI_BLK_S:
1386fcf5ef2aSThomas Huth         case ASI_BLK_SL:
1387fcf5ef2aSThomas Huth         case ASI_BLK_P:
1388fcf5ef2aSThomas Huth         case ASI_BLK_PL:
1389fcf5ef2aSThomas Huth             type = GET_ASI_BLOCK;
1390fcf5ef2aSThomas Huth             break;
1391fcf5ef2aSThomas Huth         case ASI_FL8_S:
1392fcf5ef2aSThomas Huth         case ASI_FL8_SL:
1393fcf5ef2aSThomas Huth         case ASI_FL8_P:
1394fcf5ef2aSThomas Huth         case ASI_FL8_PL:
1395fcf5ef2aSThomas Huth             memop = MO_UB;
1396fcf5ef2aSThomas Huth             type = GET_ASI_SHORT;
1397fcf5ef2aSThomas Huth             break;
1398fcf5ef2aSThomas Huth         case ASI_FL16_S:
1399fcf5ef2aSThomas Huth         case ASI_FL16_SL:
1400fcf5ef2aSThomas Huth         case ASI_FL16_P:
1401fcf5ef2aSThomas Huth         case ASI_FL16_PL:
1402fcf5ef2aSThomas Huth             memop = MO_TEUW;
1403fcf5ef2aSThomas Huth             type = GET_ASI_SHORT;
1404fcf5ef2aSThomas Huth             break;
1405fcf5ef2aSThomas Huth         }
1406fcf5ef2aSThomas Huth         /* The little-endian asis all have bit 3 set.  */
1407fcf5ef2aSThomas Huth         if (asi & 8) {
1408fcf5ef2aSThomas Huth             memop ^= MO_BSWAP;
1409fcf5ef2aSThomas Huth         }
1410fcf5ef2aSThomas Huth     }
1411fcf5ef2aSThomas Huth #endif
1412fcf5ef2aSThomas Huth 
1413811cc0b0SRichard Henderson  done:
1414fcf5ef2aSThomas Huth     return (DisasASI){ type, asi, mem_idx, memop };
1415fcf5ef2aSThomas Huth }
1416fcf5ef2aSThomas Huth 
1417a76779eeSRichard Henderson #if defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
1418a76779eeSRichard Henderson static void gen_helper_ld_asi(TCGv_i64 r, TCGv_env e, TCGv a,
1419a76779eeSRichard Henderson                               TCGv_i32 asi, TCGv_i32 mop)
1420a76779eeSRichard Henderson {
1421a76779eeSRichard Henderson     g_assert_not_reached();
1422a76779eeSRichard Henderson }
1423a76779eeSRichard Henderson 
1424a76779eeSRichard Henderson static void gen_helper_st_asi(TCGv_env e, TCGv a, TCGv_i64 r,
1425a76779eeSRichard Henderson                               TCGv_i32 asi, TCGv_i32 mop)
1426a76779eeSRichard Henderson {
1427a76779eeSRichard Henderson     g_assert_not_reached();
1428a76779eeSRichard Henderson }
1429a76779eeSRichard Henderson #endif
1430a76779eeSRichard Henderson 
143142071fc1SRichard Henderson static void gen_ld_asi(DisasContext *dc, DisasASI *da, TCGv dst, TCGv addr)
1432fcf5ef2aSThomas Huth {
1433c03a0fd1SRichard Henderson     switch (da->type) {
1434fcf5ef2aSThomas Huth     case GET_ASI_EXCP:
1435fcf5ef2aSThomas Huth         break;
1436fcf5ef2aSThomas Huth     case GET_ASI_DTWINX: /* Reserved for ldda.  */
1437fcf5ef2aSThomas Huth         gen_exception(dc, TT_ILL_INSN);
1438fcf5ef2aSThomas Huth         break;
1439fcf5ef2aSThomas Huth     case GET_ASI_DIRECT:
1440c03a0fd1SRichard Henderson         tcg_gen_qemu_ld_tl(dst, addr, da->mem_idx, da->memop | MO_ALIGN);
1441fcf5ef2aSThomas Huth         break;
14422786a3f8SRichard Henderson 
14432786a3f8SRichard Henderson     case GET_ASI_CODE:
14442786a3f8SRichard Henderson #if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
14452786a3f8SRichard Henderson         {
14462786a3f8SRichard Henderson             MemOpIdx oi = make_memop_idx(da->memop, da->mem_idx);
14472786a3f8SRichard Henderson             TCGv_i64 t64 = tcg_temp_new_i64();
14482786a3f8SRichard Henderson 
14492786a3f8SRichard Henderson             gen_helper_ld_code(t64, tcg_env, addr, tcg_constant_i32(oi));
14502786a3f8SRichard Henderson             tcg_gen_trunc_i64_tl(dst, t64);
14512786a3f8SRichard Henderson         }
14522786a3f8SRichard Henderson         break;
14532786a3f8SRichard Henderson #else
14542786a3f8SRichard Henderson         g_assert_not_reached();
14552786a3f8SRichard Henderson #endif
14562786a3f8SRichard Henderson 
1457fcf5ef2aSThomas Huth     default:
1458fcf5ef2aSThomas Huth         {
1459c03a0fd1SRichard Henderson             TCGv_i32 r_asi = tcg_constant_i32(da->asi);
1460c03a0fd1SRichard Henderson             TCGv_i32 r_mop = tcg_constant_i32(da->memop | MO_ALIGN);
1461fcf5ef2aSThomas Huth 
1462fcf5ef2aSThomas Huth             save_state(dc);
1463fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
1464ad75a51eSRichard Henderson             gen_helper_ld_asi(dst, tcg_env, addr, r_asi, r_mop);
1465fcf5ef2aSThomas Huth #else
1466fcf5ef2aSThomas Huth             {
1467fcf5ef2aSThomas Huth                 TCGv_i64 t64 = tcg_temp_new_i64();
1468ad75a51eSRichard Henderson                 gen_helper_ld_asi(t64, tcg_env, addr, r_asi, r_mop);
1469fcf5ef2aSThomas Huth                 tcg_gen_trunc_i64_tl(dst, t64);
1470fcf5ef2aSThomas Huth             }
1471fcf5ef2aSThomas Huth #endif
1472fcf5ef2aSThomas Huth         }
1473fcf5ef2aSThomas Huth         break;
1474fcf5ef2aSThomas Huth     }
1475fcf5ef2aSThomas Huth }
1476fcf5ef2aSThomas Huth 
147742071fc1SRichard Henderson static void gen_st_asi(DisasContext *dc, DisasASI *da, TCGv src, TCGv addr)
1478c03a0fd1SRichard Henderson {
1479c03a0fd1SRichard Henderson     switch (da->type) {
1480fcf5ef2aSThomas Huth     case GET_ASI_EXCP:
1481fcf5ef2aSThomas Huth         break;
1482c03a0fd1SRichard Henderson 
1483fcf5ef2aSThomas Huth     case GET_ASI_DTWINX: /* Reserved for stda.  */
1484c03a0fd1SRichard Henderson         if (TARGET_LONG_BITS == 32) {
1485fcf5ef2aSThomas Huth             gen_exception(dc, TT_ILL_INSN);
1486fcf5ef2aSThomas Huth             break;
1487c03a0fd1SRichard Henderson         } else if (!(dc->def->features & CPU_FEATURE_HYPV)) {
14883390537bSArtyom Tarasenko             /* Pre OpenSPARC CPUs don't have these */
14893390537bSArtyom Tarasenko             gen_exception(dc, TT_ILL_INSN);
1490fcf5ef2aSThomas Huth             break;
1491c03a0fd1SRichard Henderson         }
1492c03a0fd1SRichard Henderson         /* In OpenSPARC T1+ CPUs TWINX ASIs in store are ST_BLKINIT_ ASIs */
1493c03a0fd1SRichard Henderson         /* fall through */
1494c03a0fd1SRichard Henderson 
1495c03a0fd1SRichard Henderson     case GET_ASI_DIRECT:
1496c03a0fd1SRichard Henderson         tcg_gen_qemu_st_tl(src, addr, da->mem_idx, da->memop | MO_ALIGN);
1497c03a0fd1SRichard Henderson         break;
1498c03a0fd1SRichard Henderson 
1499fcf5ef2aSThomas Huth     case GET_ASI_BCOPY:
1500c03a0fd1SRichard Henderson         assert(TARGET_LONG_BITS == 32);
150198271007SRichard Henderson         /*
150298271007SRichard Henderson          * Copy 32 bytes from the address in SRC to ADDR.
150398271007SRichard Henderson          *
150498271007SRichard Henderson          * From Ross RT625 hyperSPARC manual, section 4.6:
150598271007SRichard Henderson          * "Block Copy and Block Fill will work only on cache line boundaries."
150698271007SRichard Henderson          *
150798271007SRichard Henderson          * It does not specify if an unaliged address is truncated or trapped.
150898271007SRichard Henderson          * Previous qemu behaviour was to truncate to 4 byte alignment, which
150998271007SRichard Henderson          * is obviously wrong.  The only place I can see this used is in the
151098271007SRichard Henderson          * Linux kernel which begins with page alignment, advancing by 32,
151198271007SRichard Henderson          * so is always aligned.  Assume truncation as the simpler option.
151298271007SRichard Henderson          *
151398271007SRichard Henderson          * Since the loads and stores are paired, allow the copy to happen
151498271007SRichard Henderson          * in the host endianness.  The copy need not be atomic.
151598271007SRichard Henderson          */
1516fcf5ef2aSThomas Huth         {
151798271007SRichard Henderson             MemOp mop = MO_128 | MO_ATOM_IFALIGN_PAIR;
1518fcf5ef2aSThomas Huth             TCGv saddr = tcg_temp_new();
1519fcf5ef2aSThomas Huth             TCGv daddr = tcg_temp_new();
152098271007SRichard Henderson             TCGv_i128 tmp = tcg_temp_new_i128();
1521fcf5ef2aSThomas Huth 
152298271007SRichard Henderson             tcg_gen_andi_tl(saddr, src, -32);
152398271007SRichard Henderson             tcg_gen_andi_tl(daddr, addr, -32);
152498271007SRichard Henderson             tcg_gen_qemu_ld_i128(tmp, saddr, da->mem_idx, mop);
152598271007SRichard Henderson             tcg_gen_qemu_st_i128(tmp, daddr, da->mem_idx, mop);
152698271007SRichard Henderson             tcg_gen_addi_tl(saddr, saddr, 16);
152798271007SRichard Henderson             tcg_gen_addi_tl(daddr, daddr, 16);
152898271007SRichard Henderson             tcg_gen_qemu_ld_i128(tmp, saddr, da->mem_idx, mop);
152998271007SRichard Henderson             tcg_gen_qemu_st_i128(tmp, daddr, da->mem_idx, mop);
1530fcf5ef2aSThomas Huth         }
1531fcf5ef2aSThomas Huth         break;
1532c03a0fd1SRichard Henderson 
1533fcf5ef2aSThomas Huth     default:
1534fcf5ef2aSThomas Huth         {
1535c03a0fd1SRichard Henderson             TCGv_i32 r_asi = tcg_constant_i32(da->asi);
1536c03a0fd1SRichard Henderson             TCGv_i32 r_mop = tcg_constant_i32(da->memop | MO_ALIGN);
1537fcf5ef2aSThomas Huth 
1538fcf5ef2aSThomas Huth             save_state(dc);
1539fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
1540ad75a51eSRichard Henderson             gen_helper_st_asi(tcg_env, addr, src, r_asi, r_mop);
1541fcf5ef2aSThomas Huth #else
1542fcf5ef2aSThomas Huth             {
1543fcf5ef2aSThomas Huth                 TCGv_i64 t64 = tcg_temp_new_i64();
1544fcf5ef2aSThomas Huth                 tcg_gen_extu_tl_i64(t64, src);
1545ad75a51eSRichard Henderson                 gen_helper_st_asi(tcg_env, addr, t64, r_asi, r_mop);
1546fcf5ef2aSThomas Huth             }
1547fcf5ef2aSThomas Huth #endif
1548fcf5ef2aSThomas Huth 
1549fcf5ef2aSThomas Huth             /* A write to a TLB register may alter page maps.  End the TB. */
1550fcf5ef2aSThomas Huth             dc->npc = DYNAMIC_PC;
1551fcf5ef2aSThomas Huth         }
1552fcf5ef2aSThomas Huth         break;
1553fcf5ef2aSThomas Huth     }
1554fcf5ef2aSThomas Huth }
1555fcf5ef2aSThomas Huth 
1556dca544b9SRichard Henderson static void gen_swap_asi(DisasContext *dc, DisasASI *da,
1557c03a0fd1SRichard Henderson                          TCGv dst, TCGv src, TCGv addr)
1558c03a0fd1SRichard Henderson {
1559c03a0fd1SRichard Henderson     switch (da->type) {
1560c03a0fd1SRichard Henderson     case GET_ASI_EXCP:
1561c03a0fd1SRichard Henderson         break;
1562c03a0fd1SRichard Henderson     case GET_ASI_DIRECT:
1563dca544b9SRichard Henderson         tcg_gen_atomic_xchg_tl(dst, addr, src,
1564dca544b9SRichard Henderson                                da->mem_idx, da->memop | MO_ALIGN);
1565c03a0fd1SRichard Henderson         break;
1566c03a0fd1SRichard Henderson     default:
1567c03a0fd1SRichard Henderson         /* ??? Should be DAE_invalid_asi.  */
1568c03a0fd1SRichard Henderson         gen_exception(dc, TT_DATA_ACCESS);
1569c03a0fd1SRichard Henderson         break;
1570c03a0fd1SRichard Henderson     }
1571c03a0fd1SRichard Henderson }
1572c03a0fd1SRichard Henderson 
1573d0a11d25SRichard Henderson static void gen_cas_asi(DisasContext *dc, DisasASI *da,
1574c03a0fd1SRichard Henderson                         TCGv oldv, TCGv newv, TCGv cmpv, TCGv addr)
1575c03a0fd1SRichard Henderson {
1576c03a0fd1SRichard Henderson     switch (da->type) {
1577fcf5ef2aSThomas Huth     case GET_ASI_EXCP:
1578c03a0fd1SRichard Henderson         return;
1579fcf5ef2aSThomas Huth     case GET_ASI_DIRECT:
1580c03a0fd1SRichard Henderson         tcg_gen_atomic_cmpxchg_tl(oldv, addr, cmpv, newv,
1581c03a0fd1SRichard Henderson                                   da->mem_idx, da->memop | MO_ALIGN);
1582fcf5ef2aSThomas Huth         break;
1583fcf5ef2aSThomas Huth     default:
1584fcf5ef2aSThomas Huth         /* ??? Should be DAE_invalid_asi.  */
1585fcf5ef2aSThomas Huth         gen_exception(dc, TT_DATA_ACCESS);
1586fcf5ef2aSThomas Huth         break;
1587fcf5ef2aSThomas Huth     }
1588fcf5ef2aSThomas Huth }
1589fcf5ef2aSThomas Huth 
1590cf07cd1eSRichard Henderson static void gen_ldstub_asi(DisasContext *dc, DisasASI *da, TCGv dst, TCGv addr)
1591c03a0fd1SRichard Henderson {
1592c03a0fd1SRichard Henderson     switch (da->type) {
1593fcf5ef2aSThomas Huth     case GET_ASI_EXCP:
1594fcf5ef2aSThomas Huth         break;
1595fcf5ef2aSThomas Huth     case GET_ASI_DIRECT:
1596cf07cd1eSRichard Henderson         tcg_gen_atomic_xchg_tl(dst, addr, tcg_constant_tl(0xff),
1597cf07cd1eSRichard Henderson                                da->mem_idx, MO_UB);
1598fcf5ef2aSThomas Huth         break;
1599fcf5ef2aSThomas Huth     default:
16003db010c3SRichard Henderson         /* ??? In theory, this should be raise DAE_invalid_asi.
16013db010c3SRichard Henderson            But the SS-20 roms do ldstuba [%l0] #ASI_M_CTL, %o1.  */
1602af00be49SEmilio G. Cota         if (tb_cflags(dc->base.tb) & CF_PARALLEL) {
1603ad75a51eSRichard Henderson             gen_helper_exit_atomic(tcg_env);
16043db010c3SRichard Henderson         } else {
1605c03a0fd1SRichard Henderson             TCGv_i32 r_asi = tcg_constant_i32(da->asi);
160600ab7e61SRichard Henderson             TCGv_i32 r_mop = tcg_constant_i32(MO_UB);
16073db010c3SRichard Henderson             TCGv_i64 s64, t64;
16083db010c3SRichard Henderson 
16093db010c3SRichard Henderson             save_state(dc);
16103db010c3SRichard Henderson             t64 = tcg_temp_new_i64();
1611ad75a51eSRichard Henderson             gen_helper_ld_asi(t64, tcg_env, addr, r_asi, r_mop);
16123db010c3SRichard Henderson 
161300ab7e61SRichard Henderson             s64 = tcg_constant_i64(0xff);
1614ad75a51eSRichard Henderson             gen_helper_st_asi(tcg_env, addr, s64, r_asi, r_mop);
16153db010c3SRichard Henderson 
16163db010c3SRichard Henderson             tcg_gen_trunc_i64_tl(dst, t64);
16173db010c3SRichard Henderson 
16183db010c3SRichard Henderson             /* End the TB.  */
16193db010c3SRichard Henderson             dc->npc = DYNAMIC_PC;
16203db010c3SRichard Henderson         }
1621fcf5ef2aSThomas Huth         break;
1622fcf5ef2aSThomas Huth     }
1623fcf5ef2aSThomas Huth }
1624fcf5ef2aSThomas Huth 
1625287b1152SRichard Henderson static void gen_ldf_asi(DisasContext *dc, DisasASI *da, MemOp orig_size,
16263259b9e2SRichard Henderson                         TCGv addr, int rd)
1627fcf5ef2aSThomas Huth {
16283259b9e2SRichard Henderson     MemOp memop = da->memop;
16293259b9e2SRichard Henderson     MemOp size = memop & MO_SIZE;
1630fcf5ef2aSThomas Huth     TCGv_i32 d32;
1631fcf5ef2aSThomas Huth     TCGv_i64 d64;
1632287b1152SRichard Henderson     TCGv addr_tmp;
1633fcf5ef2aSThomas Huth 
16343259b9e2SRichard Henderson     /* TODO: Use 128-bit load/store below. */
16353259b9e2SRichard Henderson     if (size == MO_128) {
16363259b9e2SRichard Henderson         memop = (memop & ~MO_SIZE) | MO_64;
16373259b9e2SRichard Henderson     }
16383259b9e2SRichard Henderson 
16393259b9e2SRichard Henderson     switch (da->type) {
1640fcf5ef2aSThomas Huth     case GET_ASI_EXCP:
1641fcf5ef2aSThomas Huth         break;
1642fcf5ef2aSThomas Huth 
1643fcf5ef2aSThomas Huth     case GET_ASI_DIRECT:
16443259b9e2SRichard Henderson         memop |= MO_ALIGN_4;
1645fcf5ef2aSThomas Huth         switch (size) {
16463259b9e2SRichard Henderson         case MO_32:
1647388a6465SRichard Henderson             d32 = tcg_temp_new_i32();
16483259b9e2SRichard Henderson             tcg_gen_qemu_ld_i32(d32, addr, da->mem_idx, memop);
1649fcf5ef2aSThomas Huth             gen_store_fpr_F(dc, rd, d32);
1650fcf5ef2aSThomas Huth             break;
16513259b9e2SRichard Henderson 
16523259b9e2SRichard Henderson         case MO_64:
16533259b9e2SRichard Henderson             tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2], addr, da->mem_idx, memop);
1654fcf5ef2aSThomas Huth             break;
16553259b9e2SRichard Henderson 
16563259b9e2SRichard Henderson         case MO_128:
1657fcf5ef2aSThomas Huth             d64 = tcg_temp_new_i64();
16583259b9e2SRichard Henderson             tcg_gen_qemu_ld_i64(d64, addr, da->mem_idx, memop);
1659287b1152SRichard Henderson             addr_tmp = tcg_temp_new();
1660287b1152SRichard Henderson             tcg_gen_addi_tl(addr_tmp, addr, 8);
1661287b1152SRichard Henderson             tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2 + 1], addr_tmp, da->mem_idx, memop);
1662fcf5ef2aSThomas Huth             tcg_gen_mov_i64(cpu_fpr[rd / 2], d64);
1663fcf5ef2aSThomas Huth             break;
1664fcf5ef2aSThomas Huth         default:
1665fcf5ef2aSThomas Huth             g_assert_not_reached();
1666fcf5ef2aSThomas Huth         }
1667fcf5ef2aSThomas Huth         break;
1668fcf5ef2aSThomas Huth 
1669fcf5ef2aSThomas Huth     case GET_ASI_BLOCK:
1670fcf5ef2aSThomas Huth         /* Valid for lddfa on aligned registers only.  */
16713259b9e2SRichard Henderson         if (orig_size == MO_64 && (rd & 7) == 0) {
1672fcf5ef2aSThomas Huth             /* The first operation checks required alignment.  */
1673287b1152SRichard Henderson             addr_tmp = tcg_temp_new();
1674287b1152SRichard Henderson             for (int i = 0; ; ++i) {
16753259b9e2SRichard Henderson                 tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2 + i], addr, da->mem_idx,
16763259b9e2SRichard Henderson                                     memop | (i == 0 ? MO_ALIGN_64 : 0));
1677fcf5ef2aSThomas Huth                 if (i == 7) {
1678fcf5ef2aSThomas Huth                     break;
1679fcf5ef2aSThomas Huth                 }
1680287b1152SRichard Henderson                 tcg_gen_addi_tl(addr_tmp, addr, 8);
1681287b1152SRichard Henderson                 addr = addr_tmp;
1682fcf5ef2aSThomas Huth             }
1683fcf5ef2aSThomas Huth         } else {
1684fcf5ef2aSThomas Huth             gen_exception(dc, TT_ILL_INSN);
1685fcf5ef2aSThomas Huth         }
1686fcf5ef2aSThomas Huth         break;
1687fcf5ef2aSThomas Huth 
1688fcf5ef2aSThomas Huth     case GET_ASI_SHORT:
1689fcf5ef2aSThomas Huth         /* Valid for lddfa only.  */
16903259b9e2SRichard Henderson         if (orig_size == MO_64) {
16913259b9e2SRichard Henderson             tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2], addr, da->mem_idx,
16923259b9e2SRichard Henderson                                 memop | MO_ALIGN);
1693fcf5ef2aSThomas Huth         } else {
1694fcf5ef2aSThomas Huth             gen_exception(dc, TT_ILL_INSN);
1695fcf5ef2aSThomas Huth         }
1696fcf5ef2aSThomas Huth         break;
1697fcf5ef2aSThomas Huth 
1698fcf5ef2aSThomas Huth     default:
1699fcf5ef2aSThomas Huth         {
17003259b9e2SRichard Henderson             TCGv_i32 r_asi = tcg_constant_i32(da->asi);
17013259b9e2SRichard Henderson             TCGv_i32 r_mop = tcg_constant_i32(memop | MO_ALIGN);
1702fcf5ef2aSThomas Huth 
1703fcf5ef2aSThomas Huth             save_state(dc);
1704fcf5ef2aSThomas Huth             /* According to the table in the UA2011 manual, the only
1705fcf5ef2aSThomas Huth                other asis that are valid for ldfa/lddfa/ldqfa are
1706fcf5ef2aSThomas Huth                the NO_FAULT asis.  We still need a helper for these,
1707fcf5ef2aSThomas Huth                but we can just use the integer asi helper for them.  */
1708fcf5ef2aSThomas Huth             switch (size) {
17093259b9e2SRichard Henderson             case MO_32:
1710fcf5ef2aSThomas Huth                 d64 = tcg_temp_new_i64();
1711ad75a51eSRichard Henderson                 gen_helper_ld_asi(d64, tcg_env, addr, r_asi, r_mop);
1712388a6465SRichard Henderson                 d32 = tcg_temp_new_i32();
1713fcf5ef2aSThomas Huth                 tcg_gen_extrl_i64_i32(d32, d64);
1714fcf5ef2aSThomas Huth                 gen_store_fpr_F(dc, rd, d32);
1715fcf5ef2aSThomas Huth                 break;
17163259b9e2SRichard Henderson             case MO_64:
17173259b9e2SRichard Henderson                 gen_helper_ld_asi(cpu_fpr[rd / 2], tcg_env, addr,
17183259b9e2SRichard Henderson                                   r_asi, r_mop);
1719fcf5ef2aSThomas Huth                 break;
17203259b9e2SRichard Henderson             case MO_128:
1721fcf5ef2aSThomas Huth                 d64 = tcg_temp_new_i64();
1722ad75a51eSRichard Henderson                 gen_helper_ld_asi(d64, tcg_env, addr, r_asi, r_mop);
1723287b1152SRichard Henderson                 addr_tmp = tcg_temp_new();
1724287b1152SRichard Henderson                 tcg_gen_addi_tl(addr_tmp, addr, 8);
1725287b1152SRichard Henderson                 gen_helper_ld_asi(cpu_fpr[rd / 2 + 1], tcg_env, addr_tmp,
17263259b9e2SRichard Henderson                                   r_asi, r_mop);
1727fcf5ef2aSThomas Huth                 tcg_gen_mov_i64(cpu_fpr[rd / 2], d64);
1728fcf5ef2aSThomas Huth                 break;
1729fcf5ef2aSThomas Huth             default:
1730fcf5ef2aSThomas Huth                 g_assert_not_reached();
1731fcf5ef2aSThomas Huth             }
1732fcf5ef2aSThomas Huth         }
1733fcf5ef2aSThomas Huth         break;
1734fcf5ef2aSThomas Huth     }
1735fcf5ef2aSThomas Huth }
1736fcf5ef2aSThomas Huth 
1737287b1152SRichard Henderson static void gen_stf_asi(DisasContext *dc, DisasASI *da, MemOp orig_size,
17383259b9e2SRichard Henderson                         TCGv addr, int rd)
17393259b9e2SRichard Henderson {
17403259b9e2SRichard Henderson     MemOp memop = da->memop;
17413259b9e2SRichard Henderson     MemOp size = memop & MO_SIZE;
1742fcf5ef2aSThomas Huth     TCGv_i32 d32;
1743287b1152SRichard Henderson     TCGv addr_tmp;
1744fcf5ef2aSThomas Huth 
17453259b9e2SRichard Henderson     /* TODO: Use 128-bit load/store below. */
17463259b9e2SRichard Henderson     if (size == MO_128) {
17473259b9e2SRichard Henderson         memop = (memop & ~MO_SIZE) | MO_64;
17483259b9e2SRichard Henderson     }
17493259b9e2SRichard Henderson 
17503259b9e2SRichard Henderson     switch (da->type) {
1751fcf5ef2aSThomas Huth     case GET_ASI_EXCP:
1752fcf5ef2aSThomas Huth         break;
1753fcf5ef2aSThomas Huth 
1754fcf5ef2aSThomas Huth     case GET_ASI_DIRECT:
17553259b9e2SRichard Henderson         memop |= MO_ALIGN_4;
1756fcf5ef2aSThomas Huth         switch (size) {
17573259b9e2SRichard Henderson         case MO_32:
1758fcf5ef2aSThomas Huth             d32 = gen_load_fpr_F(dc, rd);
17593259b9e2SRichard Henderson             tcg_gen_qemu_st_i32(d32, addr, da->mem_idx, memop | MO_ALIGN);
1760fcf5ef2aSThomas Huth             break;
17613259b9e2SRichard Henderson         case MO_64:
17623259b9e2SRichard Henderson             tcg_gen_qemu_st_i64(cpu_fpr[rd / 2], addr, da->mem_idx,
17633259b9e2SRichard Henderson                                 memop | MO_ALIGN_4);
1764fcf5ef2aSThomas Huth             break;
17653259b9e2SRichard Henderson         case MO_128:
1766fcf5ef2aSThomas Huth             /* Only 4-byte alignment required.  However, it is legal for the
1767fcf5ef2aSThomas Huth                cpu to signal the alignment fault, and the OS trap handler is
1768fcf5ef2aSThomas Huth                required to fix it up.  Requiring 16-byte alignment here avoids
1769fcf5ef2aSThomas Huth                having to probe the second page before performing the first
1770fcf5ef2aSThomas Huth                write.  */
17713259b9e2SRichard Henderson             tcg_gen_qemu_st_i64(cpu_fpr[rd / 2], addr, da->mem_idx,
17723259b9e2SRichard Henderson                                 memop | MO_ALIGN_16);
1773287b1152SRichard Henderson             addr_tmp = tcg_temp_new();
1774287b1152SRichard Henderson             tcg_gen_addi_tl(addr_tmp, addr, 8);
1775287b1152SRichard Henderson             tcg_gen_qemu_st_i64(cpu_fpr[rd / 2 + 1], addr_tmp, da->mem_idx, memop);
1776fcf5ef2aSThomas Huth             break;
1777fcf5ef2aSThomas Huth         default:
1778fcf5ef2aSThomas Huth             g_assert_not_reached();
1779fcf5ef2aSThomas Huth         }
1780fcf5ef2aSThomas Huth         break;
1781fcf5ef2aSThomas Huth 
1782fcf5ef2aSThomas Huth     case GET_ASI_BLOCK:
1783fcf5ef2aSThomas Huth         /* Valid for stdfa on aligned registers only.  */
17843259b9e2SRichard Henderson         if (orig_size == MO_64 && (rd & 7) == 0) {
1785fcf5ef2aSThomas Huth             /* The first operation checks required alignment.  */
1786287b1152SRichard Henderson             addr_tmp = tcg_temp_new();
1787287b1152SRichard Henderson             for (int i = 0; ; ++i) {
17883259b9e2SRichard Henderson                 tcg_gen_qemu_st_i64(cpu_fpr[rd / 2 + i], addr, da->mem_idx,
17893259b9e2SRichard Henderson                                     memop | (i == 0 ? MO_ALIGN_64 : 0));
1790fcf5ef2aSThomas Huth                 if (i == 7) {
1791fcf5ef2aSThomas Huth                     break;
1792fcf5ef2aSThomas Huth                 }
1793287b1152SRichard Henderson                 tcg_gen_addi_tl(addr_tmp, addr, 8);
1794287b1152SRichard Henderson                 addr = addr_tmp;
1795fcf5ef2aSThomas Huth             }
1796fcf5ef2aSThomas Huth         } else {
1797fcf5ef2aSThomas Huth             gen_exception(dc, TT_ILL_INSN);
1798fcf5ef2aSThomas Huth         }
1799fcf5ef2aSThomas Huth         break;
1800fcf5ef2aSThomas Huth 
1801fcf5ef2aSThomas Huth     case GET_ASI_SHORT:
1802fcf5ef2aSThomas Huth         /* Valid for stdfa only.  */
18033259b9e2SRichard Henderson         if (orig_size == MO_64) {
18043259b9e2SRichard Henderson             tcg_gen_qemu_st_i64(cpu_fpr[rd / 2], addr, da->mem_idx,
18053259b9e2SRichard Henderson                                 memop | MO_ALIGN);
1806fcf5ef2aSThomas Huth         } else {
1807fcf5ef2aSThomas Huth             gen_exception(dc, TT_ILL_INSN);
1808fcf5ef2aSThomas Huth         }
1809fcf5ef2aSThomas Huth         break;
1810fcf5ef2aSThomas Huth 
1811fcf5ef2aSThomas Huth     default:
1812fcf5ef2aSThomas Huth         /* According to the table in the UA2011 manual, the only
1813fcf5ef2aSThomas Huth            other asis that are valid for ldfa/lddfa/ldqfa are
1814fcf5ef2aSThomas Huth            the PST* asis, which aren't currently handled.  */
1815fcf5ef2aSThomas Huth         gen_exception(dc, TT_ILL_INSN);
1816fcf5ef2aSThomas Huth         break;
1817fcf5ef2aSThomas Huth     }
1818fcf5ef2aSThomas Huth }
1819fcf5ef2aSThomas Huth 
182042071fc1SRichard Henderson static void gen_ldda_asi(DisasContext *dc, DisasASI *da, TCGv addr, int rd)
1821fcf5ef2aSThomas Huth {
1822a76779eeSRichard Henderson     TCGv hi = gen_dest_gpr(dc, rd);
1823a76779eeSRichard Henderson     TCGv lo = gen_dest_gpr(dc, rd + 1);
1824fcf5ef2aSThomas Huth 
1825c03a0fd1SRichard Henderson     switch (da->type) {
1826fcf5ef2aSThomas Huth     case GET_ASI_EXCP:
1827fcf5ef2aSThomas Huth         return;
1828fcf5ef2aSThomas Huth 
1829fcf5ef2aSThomas Huth     case GET_ASI_DTWINX:
1830ebbbec92SRichard Henderson #ifdef TARGET_SPARC64
1831ebbbec92SRichard Henderson         {
1832ebbbec92SRichard Henderson             MemOp mop = (da->memop & MO_BSWAP) | MO_128 | MO_ALIGN_16;
1833ebbbec92SRichard Henderson             TCGv_i128 t = tcg_temp_new_i128();
1834ebbbec92SRichard Henderson 
1835ebbbec92SRichard Henderson             tcg_gen_qemu_ld_i128(t, addr, da->mem_idx, mop);
1836ebbbec92SRichard Henderson             /*
1837ebbbec92SRichard Henderson              * Note that LE twinx acts as if each 64-bit register result is
1838ebbbec92SRichard Henderson              * byte swapped.  We perform one 128-bit LE load, so must swap
1839ebbbec92SRichard Henderson              * the order of the writebacks.
1840ebbbec92SRichard Henderson              */
1841ebbbec92SRichard Henderson             if ((mop & MO_BSWAP) == MO_TE) {
1842ebbbec92SRichard Henderson                 tcg_gen_extr_i128_i64(lo, hi, t);
1843ebbbec92SRichard Henderson             } else {
1844ebbbec92SRichard Henderson                 tcg_gen_extr_i128_i64(hi, lo, t);
1845ebbbec92SRichard Henderson             }
1846ebbbec92SRichard Henderson         }
1847fcf5ef2aSThomas Huth         break;
1848ebbbec92SRichard Henderson #else
1849ebbbec92SRichard Henderson         g_assert_not_reached();
1850ebbbec92SRichard Henderson #endif
1851fcf5ef2aSThomas Huth 
1852fcf5ef2aSThomas Huth     case GET_ASI_DIRECT:
1853fcf5ef2aSThomas Huth         {
1854fcf5ef2aSThomas Huth             TCGv_i64 tmp = tcg_temp_new_i64();
1855fcf5ef2aSThomas Huth 
1856c03a0fd1SRichard Henderson             tcg_gen_qemu_ld_i64(tmp, addr, da->mem_idx, da->memop | MO_ALIGN);
1857fcf5ef2aSThomas Huth 
1858fcf5ef2aSThomas Huth             /* Note that LE ldda acts as if each 32-bit register
1859fcf5ef2aSThomas Huth                result is byte swapped.  Having just performed one
1860fcf5ef2aSThomas Huth                64-bit bswap, we need now to swap the writebacks.  */
1861c03a0fd1SRichard Henderson             if ((da->memop & MO_BSWAP) == MO_TE) {
1862a76779eeSRichard Henderson                 tcg_gen_extr_i64_tl(lo, hi, tmp);
1863fcf5ef2aSThomas Huth             } else {
1864a76779eeSRichard Henderson                 tcg_gen_extr_i64_tl(hi, lo, tmp);
1865fcf5ef2aSThomas Huth             }
1866fcf5ef2aSThomas Huth         }
1867fcf5ef2aSThomas Huth         break;
1868fcf5ef2aSThomas Huth 
18692786a3f8SRichard Henderson     case GET_ASI_CODE:
18702786a3f8SRichard Henderson #if !defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
18712786a3f8SRichard Henderson         {
18722786a3f8SRichard Henderson             MemOpIdx oi = make_memop_idx(da->memop, da->mem_idx);
18732786a3f8SRichard Henderson             TCGv_i64 tmp = tcg_temp_new_i64();
18742786a3f8SRichard Henderson 
18752786a3f8SRichard Henderson             gen_helper_ld_code(tmp, tcg_env, addr, tcg_constant_i32(oi));
18762786a3f8SRichard Henderson 
18772786a3f8SRichard Henderson             /* See above.  */
18782786a3f8SRichard Henderson             if ((da->memop & MO_BSWAP) == MO_TE) {
18792786a3f8SRichard Henderson                 tcg_gen_extr_i64_tl(lo, hi, tmp);
18802786a3f8SRichard Henderson             } else {
18812786a3f8SRichard Henderson                 tcg_gen_extr_i64_tl(hi, lo, tmp);
18822786a3f8SRichard Henderson             }
18832786a3f8SRichard Henderson         }
18842786a3f8SRichard Henderson         break;
18852786a3f8SRichard Henderson #else
18862786a3f8SRichard Henderson         g_assert_not_reached();
18872786a3f8SRichard Henderson #endif
18882786a3f8SRichard Henderson 
1889fcf5ef2aSThomas Huth     default:
1890fcf5ef2aSThomas Huth         /* ??? In theory we've handled all of the ASIs that are valid
1891fcf5ef2aSThomas Huth            for ldda, and this should raise DAE_invalid_asi.  However,
1892fcf5ef2aSThomas Huth            real hardware allows others.  This can be seen with e.g.
1893fcf5ef2aSThomas Huth            FreeBSD 10.3 wrt ASI_IC_TAG.  */
1894fcf5ef2aSThomas Huth         {
1895c03a0fd1SRichard Henderson             TCGv_i32 r_asi = tcg_constant_i32(da->asi);
1896c03a0fd1SRichard Henderson             TCGv_i32 r_mop = tcg_constant_i32(da->memop);
1897fcf5ef2aSThomas Huth             TCGv_i64 tmp = tcg_temp_new_i64();
1898fcf5ef2aSThomas Huth 
1899fcf5ef2aSThomas Huth             save_state(dc);
1900ad75a51eSRichard Henderson             gen_helper_ld_asi(tmp, tcg_env, addr, r_asi, r_mop);
1901fcf5ef2aSThomas Huth 
1902fcf5ef2aSThomas Huth             /* See above.  */
1903c03a0fd1SRichard Henderson             if ((da->memop & MO_BSWAP) == MO_TE) {
1904a76779eeSRichard Henderson                 tcg_gen_extr_i64_tl(lo, hi, tmp);
1905fcf5ef2aSThomas Huth             } else {
1906a76779eeSRichard Henderson                 tcg_gen_extr_i64_tl(hi, lo, tmp);
1907fcf5ef2aSThomas Huth             }
1908fcf5ef2aSThomas Huth         }
1909fcf5ef2aSThomas Huth         break;
1910fcf5ef2aSThomas Huth     }
1911fcf5ef2aSThomas Huth 
1912fcf5ef2aSThomas Huth     gen_store_gpr(dc, rd, hi);
1913fcf5ef2aSThomas Huth     gen_store_gpr(dc, rd + 1, lo);
1914fcf5ef2aSThomas Huth }
1915fcf5ef2aSThomas Huth 
191642071fc1SRichard Henderson static void gen_stda_asi(DisasContext *dc, DisasASI *da, TCGv addr, int rd)
1917c03a0fd1SRichard Henderson {
1918c03a0fd1SRichard Henderson     TCGv hi = gen_load_gpr(dc, rd);
1919fcf5ef2aSThomas Huth     TCGv lo = gen_load_gpr(dc, rd + 1);
1920fcf5ef2aSThomas Huth 
1921c03a0fd1SRichard Henderson     switch (da->type) {
1922fcf5ef2aSThomas Huth     case GET_ASI_EXCP:
1923fcf5ef2aSThomas Huth         break;
1924fcf5ef2aSThomas Huth 
1925fcf5ef2aSThomas Huth     case GET_ASI_DTWINX:
1926ebbbec92SRichard Henderson #ifdef TARGET_SPARC64
1927ebbbec92SRichard Henderson         {
1928ebbbec92SRichard Henderson             MemOp mop = (da->memop & MO_BSWAP) | MO_128 | MO_ALIGN_16;
1929ebbbec92SRichard Henderson             TCGv_i128 t = tcg_temp_new_i128();
1930ebbbec92SRichard Henderson 
1931ebbbec92SRichard Henderson             /*
1932ebbbec92SRichard Henderson              * Note that LE twinx acts as if each 64-bit register result is
1933ebbbec92SRichard Henderson              * byte swapped.  We perform one 128-bit LE store, so must swap
1934ebbbec92SRichard Henderson              * the order of the construction.
1935ebbbec92SRichard Henderson              */
1936ebbbec92SRichard Henderson             if ((mop & MO_BSWAP) == MO_TE) {
1937ebbbec92SRichard Henderson                 tcg_gen_concat_i64_i128(t, lo, hi);
1938ebbbec92SRichard Henderson             } else {
1939ebbbec92SRichard Henderson                 tcg_gen_concat_i64_i128(t, hi, lo);
1940ebbbec92SRichard Henderson             }
1941ebbbec92SRichard Henderson             tcg_gen_qemu_st_i128(t, addr, da->mem_idx, mop);
1942ebbbec92SRichard Henderson         }
1943fcf5ef2aSThomas Huth         break;
1944ebbbec92SRichard Henderson #else
1945ebbbec92SRichard Henderson         g_assert_not_reached();
1946ebbbec92SRichard Henderson #endif
1947fcf5ef2aSThomas Huth 
1948fcf5ef2aSThomas Huth     case GET_ASI_DIRECT:
1949fcf5ef2aSThomas Huth         {
1950fcf5ef2aSThomas Huth             TCGv_i64 t64 = tcg_temp_new_i64();
1951fcf5ef2aSThomas Huth 
1952fcf5ef2aSThomas Huth             /* Note that LE stda acts as if each 32-bit register result is
1953fcf5ef2aSThomas Huth                byte swapped.  We will perform one 64-bit LE store, so now
1954fcf5ef2aSThomas Huth                we must swap the order of the construction.  */
1955c03a0fd1SRichard Henderson             if ((da->memop & MO_BSWAP) == MO_TE) {
1956a76779eeSRichard Henderson                 tcg_gen_concat_tl_i64(t64, lo, hi);
1957fcf5ef2aSThomas Huth             } else {
1958a76779eeSRichard Henderson                 tcg_gen_concat_tl_i64(t64, hi, lo);
1959fcf5ef2aSThomas Huth             }
1960c03a0fd1SRichard Henderson             tcg_gen_qemu_st_i64(t64, addr, da->mem_idx, da->memop | MO_ALIGN);
1961fcf5ef2aSThomas Huth         }
1962fcf5ef2aSThomas Huth         break;
1963fcf5ef2aSThomas Huth 
1964a76779eeSRichard Henderson     case GET_ASI_BFILL:
1965a76779eeSRichard Henderson         assert(TARGET_LONG_BITS == 32);
196654c3e953SRichard Henderson         /*
196754c3e953SRichard Henderson          * Store 32 bytes of [rd:rd+1] to ADDR.
196854c3e953SRichard Henderson          * See comments for GET_ASI_COPY above.
196954c3e953SRichard Henderson          */
1970a76779eeSRichard Henderson         {
197154c3e953SRichard Henderson             MemOp mop = MO_TE | MO_128 | MO_ATOM_IFALIGN_PAIR;
197254c3e953SRichard Henderson             TCGv_i64 t8 = tcg_temp_new_i64();
197354c3e953SRichard Henderson             TCGv_i128 t16 = tcg_temp_new_i128();
197454c3e953SRichard Henderson             TCGv daddr = tcg_temp_new();
1975a76779eeSRichard Henderson 
197654c3e953SRichard Henderson             tcg_gen_concat_tl_i64(t8, lo, hi);
197754c3e953SRichard Henderson             tcg_gen_concat_i64_i128(t16, t8, t8);
197854c3e953SRichard Henderson             tcg_gen_andi_tl(daddr, addr, -32);
197954c3e953SRichard Henderson             tcg_gen_qemu_st_i128(t16, daddr, da->mem_idx, mop);
198054c3e953SRichard Henderson             tcg_gen_addi_tl(daddr, daddr, 16);
198154c3e953SRichard Henderson             tcg_gen_qemu_st_i128(t16, daddr, da->mem_idx, mop);
1982a76779eeSRichard Henderson         }
1983a76779eeSRichard Henderson         break;
1984a76779eeSRichard Henderson 
1985fcf5ef2aSThomas Huth     default:
1986fcf5ef2aSThomas Huth         /* ??? In theory we've handled all of the ASIs that are valid
1987fcf5ef2aSThomas Huth            for stda, and this should raise DAE_invalid_asi.  */
1988fcf5ef2aSThomas Huth         {
1989c03a0fd1SRichard Henderson             TCGv_i32 r_asi = tcg_constant_i32(da->asi);
1990c03a0fd1SRichard Henderson             TCGv_i32 r_mop = tcg_constant_i32(da->memop);
1991fcf5ef2aSThomas Huth             TCGv_i64 t64 = tcg_temp_new_i64();
1992fcf5ef2aSThomas Huth 
1993fcf5ef2aSThomas Huth             /* See above.  */
1994c03a0fd1SRichard Henderson             if ((da->memop & MO_BSWAP) == MO_TE) {
1995a76779eeSRichard Henderson                 tcg_gen_concat_tl_i64(t64, lo, hi);
1996fcf5ef2aSThomas Huth             } else {
1997a76779eeSRichard Henderson                 tcg_gen_concat_tl_i64(t64, hi, lo);
1998fcf5ef2aSThomas Huth             }
1999fcf5ef2aSThomas Huth 
2000fcf5ef2aSThomas Huth             save_state(dc);
2001ad75a51eSRichard Henderson             gen_helper_st_asi(tcg_env, addr, t64, r_asi, r_mop);
2002fcf5ef2aSThomas Huth         }
2003fcf5ef2aSThomas Huth         break;
2004fcf5ef2aSThomas Huth     }
2005fcf5ef2aSThomas Huth }
2006fcf5ef2aSThomas Huth 
2007fcf5ef2aSThomas Huth static void gen_fmovs(DisasContext *dc, DisasCompare *cmp, int rd, int rs)
2008fcf5ef2aSThomas Huth {
2009f7ec8155SRichard Henderson #ifdef TARGET_SPARC64
2010fcf5ef2aSThomas Huth     TCGv_i32 c32, zero, dst, s1, s2;
2011dd7dbfccSRichard Henderson     TCGv_i64 c64 = tcg_temp_new_i64();
2012fcf5ef2aSThomas Huth 
2013fcf5ef2aSThomas Huth     /* We have two choices here: extend the 32 bit data and use movcond_i64,
2014fcf5ef2aSThomas Huth        or fold the comparison down to 32 bits and use movcond_i32.  Choose
2015fcf5ef2aSThomas Huth        the later.  */
2016fcf5ef2aSThomas Huth     c32 = tcg_temp_new_i32();
2017c8507ebfSRichard Henderson     tcg_gen_setcondi_i64(cmp->cond, c64, cmp->c1, cmp->c2);
2018fcf5ef2aSThomas Huth     tcg_gen_extrl_i64_i32(c32, c64);
2019fcf5ef2aSThomas Huth 
2020fcf5ef2aSThomas Huth     s1 = gen_load_fpr_F(dc, rs);
2021fcf5ef2aSThomas Huth     s2 = gen_load_fpr_F(dc, rd);
2022388a6465SRichard Henderson     dst = tcg_temp_new_i32();
202300ab7e61SRichard Henderson     zero = tcg_constant_i32(0);
2024fcf5ef2aSThomas Huth 
2025fcf5ef2aSThomas Huth     tcg_gen_movcond_i32(TCG_COND_NE, dst, c32, zero, s1, s2);
2026fcf5ef2aSThomas Huth 
2027fcf5ef2aSThomas Huth     gen_store_fpr_F(dc, rd, dst);
2028f7ec8155SRichard Henderson #else
2029f7ec8155SRichard Henderson     qemu_build_not_reached();
2030f7ec8155SRichard Henderson #endif
2031fcf5ef2aSThomas Huth }
2032fcf5ef2aSThomas Huth 
2033fcf5ef2aSThomas Huth static void gen_fmovd(DisasContext *dc, DisasCompare *cmp, int rd, int rs)
2034fcf5ef2aSThomas Huth {
2035f7ec8155SRichard Henderson #ifdef TARGET_SPARC64
2036fcf5ef2aSThomas Huth     TCGv_i64 dst = gen_dest_fpr_D(dc, rd);
2037c8507ebfSRichard Henderson     tcg_gen_movcond_i64(cmp->cond, dst, cmp->c1, tcg_constant_tl(cmp->c2),
2038fcf5ef2aSThomas Huth                         gen_load_fpr_D(dc, rs),
2039fcf5ef2aSThomas Huth                         gen_load_fpr_D(dc, rd));
2040fcf5ef2aSThomas Huth     gen_store_fpr_D(dc, rd, dst);
2041f7ec8155SRichard Henderson #else
2042f7ec8155SRichard Henderson     qemu_build_not_reached();
2043f7ec8155SRichard Henderson #endif
2044fcf5ef2aSThomas Huth }
2045fcf5ef2aSThomas Huth 
2046fcf5ef2aSThomas Huth static void gen_fmovq(DisasContext *dc, DisasCompare *cmp, int rd, int rs)
2047fcf5ef2aSThomas Huth {
2048f7ec8155SRichard Henderson #ifdef TARGET_SPARC64
2049fcf5ef2aSThomas Huth     int qd = QFPREG(rd);
2050fcf5ef2aSThomas Huth     int qs = QFPREG(rs);
2051c8507ebfSRichard Henderson     TCGv c2 = tcg_constant_tl(cmp->c2);
2052fcf5ef2aSThomas Huth 
2053c8507ebfSRichard Henderson     tcg_gen_movcond_i64(cmp->cond, cpu_fpr[qd / 2], cmp->c1, c2,
2054fcf5ef2aSThomas Huth                         cpu_fpr[qs / 2], cpu_fpr[qd / 2]);
2055c8507ebfSRichard Henderson     tcg_gen_movcond_i64(cmp->cond, cpu_fpr[qd / 2 + 1], cmp->c1, c2,
2056fcf5ef2aSThomas Huth                         cpu_fpr[qs / 2 + 1], cpu_fpr[qd / 2 + 1]);
2057fcf5ef2aSThomas Huth 
2058fcf5ef2aSThomas Huth     gen_update_fprs_dirty(dc, qd);
2059f7ec8155SRichard Henderson #else
2060f7ec8155SRichard Henderson     qemu_build_not_reached();
2061f7ec8155SRichard Henderson #endif
2062fcf5ef2aSThomas Huth }
2063fcf5ef2aSThomas Huth 
2064f7ec8155SRichard Henderson #ifdef TARGET_SPARC64
20655d617bfbSRichard Henderson static void gen_load_trap_state_at_tl(TCGv_ptr r_tsptr)
2066fcf5ef2aSThomas Huth {
2067fcf5ef2aSThomas Huth     TCGv_i32 r_tl = tcg_temp_new_i32();
2068fcf5ef2aSThomas Huth 
2069fcf5ef2aSThomas Huth     /* load env->tl into r_tl */
2070ad75a51eSRichard Henderson     tcg_gen_ld_i32(r_tl, tcg_env, offsetof(CPUSPARCState, tl));
2071fcf5ef2aSThomas Huth 
2072fcf5ef2aSThomas Huth     /* tl = [0 ... MAXTL_MASK] where MAXTL_MASK must be power of 2 */
2073fcf5ef2aSThomas Huth     tcg_gen_andi_i32(r_tl, r_tl, MAXTL_MASK);
2074fcf5ef2aSThomas Huth 
2075fcf5ef2aSThomas Huth     /* calculate offset to current trap state from env->ts, reuse r_tl */
2076fcf5ef2aSThomas Huth     tcg_gen_muli_i32(r_tl, r_tl, sizeof (trap_state));
2077ad75a51eSRichard Henderson     tcg_gen_addi_ptr(r_tsptr, tcg_env, offsetof(CPUSPARCState, ts));
2078fcf5ef2aSThomas Huth 
2079fcf5ef2aSThomas Huth     /* tsptr = env->ts[env->tl & MAXTL_MASK] */
2080fcf5ef2aSThomas Huth     {
2081fcf5ef2aSThomas Huth         TCGv_ptr r_tl_tmp = tcg_temp_new_ptr();
2082fcf5ef2aSThomas Huth         tcg_gen_ext_i32_ptr(r_tl_tmp, r_tl);
2083fcf5ef2aSThomas Huth         tcg_gen_add_ptr(r_tsptr, r_tsptr, r_tl_tmp);
2084fcf5ef2aSThomas Huth     }
2085fcf5ef2aSThomas Huth }
2086fcf5ef2aSThomas Huth #endif
2087fcf5ef2aSThomas Huth 
208806c060d9SRichard Henderson static int extract_dfpreg(DisasContext *dc, int x)
208906c060d9SRichard Henderson {
209006c060d9SRichard Henderson     return DFPREG(x);
209106c060d9SRichard Henderson }
209206c060d9SRichard Henderson 
209306c060d9SRichard Henderson static int extract_qfpreg(DisasContext *dc, int x)
209406c060d9SRichard Henderson {
209506c060d9SRichard Henderson     return QFPREG(x);
209606c060d9SRichard Henderson }
209706c060d9SRichard Henderson 
2098878cc677SRichard Henderson /* Include the auto-generated decoder.  */
2099878cc677SRichard Henderson #include "decode-insns.c.inc"
2100878cc677SRichard Henderson 
2101878cc677SRichard Henderson #define TRANS(NAME, AVAIL, FUNC, ...) \
2102878cc677SRichard Henderson     static bool trans_##NAME(DisasContext *dc, arg_##NAME *a) \
2103878cc677SRichard Henderson     { return avail_##AVAIL(dc) && FUNC(dc, __VA_ARGS__); }
2104878cc677SRichard Henderson 
2105878cc677SRichard Henderson #define avail_ALL(C)      true
2106878cc677SRichard Henderson #ifdef TARGET_SPARC64
2107878cc677SRichard Henderson # define avail_32(C)      false
2108af25071cSRichard Henderson # define avail_ASR17(C)   false
2109d0a11d25SRichard Henderson # define avail_CASA(C)    true
2110c2636853SRichard Henderson # define avail_DIV(C)     true
2111b5372650SRichard Henderson # define avail_MUL(C)     true
21120faef01bSRichard Henderson # define avail_POWERDOWN(C) false
2113878cc677SRichard Henderson # define avail_64(C)      true
21145d617bfbSRichard Henderson # define avail_GL(C)      ((C)->def->features & CPU_FEATURE_GL)
2115af25071cSRichard Henderson # define avail_HYPV(C)    ((C)->def->features & CPU_FEATURE_HYPV)
2116b88ce6f2SRichard Henderson # define avail_VIS1(C)    ((C)->def->features & CPU_FEATURE_VIS1)
2117b88ce6f2SRichard Henderson # define avail_VIS2(C)    ((C)->def->features & CPU_FEATURE_VIS2)
2118878cc677SRichard Henderson #else
2119878cc677SRichard Henderson # define avail_32(C)      true
2120af25071cSRichard Henderson # define avail_ASR17(C)   ((C)->def->features & CPU_FEATURE_ASR17)
2121d0a11d25SRichard Henderson # define avail_CASA(C)    ((C)->def->features & CPU_FEATURE_CASA)
2122c2636853SRichard Henderson # define avail_DIV(C)     ((C)->def->features & CPU_FEATURE_DIV)
2123b5372650SRichard Henderson # define avail_MUL(C)     ((C)->def->features & CPU_FEATURE_MUL)
21240faef01bSRichard Henderson # define avail_POWERDOWN(C) ((C)->def->features & CPU_FEATURE_POWERDOWN)
2125878cc677SRichard Henderson # define avail_64(C)      false
21265d617bfbSRichard Henderson # define avail_GL(C)      false
2127af25071cSRichard Henderson # define avail_HYPV(C)    false
2128b88ce6f2SRichard Henderson # define avail_VIS1(C)    false
2129b88ce6f2SRichard Henderson # define avail_VIS2(C)    false
2130878cc677SRichard Henderson #endif
2131878cc677SRichard Henderson 
2132878cc677SRichard Henderson /* Default case for non jump instructions. */
2133878cc677SRichard Henderson static bool advance_pc(DisasContext *dc)
2134878cc677SRichard Henderson {
21354a8d145dSRichard Henderson     TCGLabel *l1;
21364a8d145dSRichard Henderson 
213789527e3aSRichard Henderson     finishing_insn(dc);
213889527e3aSRichard Henderson 
2139878cc677SRichard Henderson     if (dc->npc & 3) {
2140878cc677SRichard Henderson         switch (dc->npc) {
2141878cc677SRichard Henderson         case DYNAMIC_PC:
2142878cc677SRichard Henderson         case DYNAMIC_PC_LOOKUP:
2143878cc677SRichard Henderson             dc->pc = dc->npc;
2144444d8b30SRichard Henderson             tcg_gen_mov_tl(cpu_pc, cpu_npc);
2145444d8b30SRichard Henderson             tcg_gen_addi_tl(cpu_npc, cpu_npc, 4);
2146878cc677SRichard Henderson             break;
21474a8d145dSRichard Henderson 
2148878cc677SRichard Henderson         case JUMP_PC:
2149878cc677SRichard Henderson             /* we can do a static jump */
21504a8d145dSRichard Henderson             l1 = gen_new_label();
2151533f042fSRichard Henderson             tcg_gen_brcondi_tl(dc->jump.cond, dc->jump.c1, dc->jump.c2, l1);
21524a8d145dSRichard Henderson 
21534a8d145dSRichard Henderson             /* jump not taken */
21544a8d145dSRichard Henderson             gen_goto_tb(dc, 1, dc->jump_pc[1], dc->jump_pc[1] + 4);
21554a8d145dSRichard Henderson 
21564a8d145dSRichard Henderson             /* jump taken */
21574a8d145dSRichard Henderson             gen_set_label(l1);
21584a8d145dSRichard Henderson             gen_goto_tb(dc, 0, dc->jump_pc[0], dc->jump_pc[0] + 4);
21594a8d145dSRichard Henderson 
2160878cc677SRichard Henderson             dc->base.is_jmp = DISAS_NORETURN;
2161878cc677SRichard Henderson             break;
21624a8d145dSRichard Henderson 
2163878cc677SRichard Henderson         default:
2164878cc677SRichard Henderson             g_assert_not_reached();
2165878cc677SRichard Henderson         }
2166878cc677SRichard Henderson     } else {
2167878cc677SRichard Henderson         dc->pc = dc->npc;
2168878cc677SRichard Henderson         dc->npc = dc->npc + 4;
2169878cc677SRichard Henderson     }
2170878cc677SRichard Henderson     return true;
2171878cc677SRichard Henderson }
2172878cc677SRichard Henderson 
21736d2a0768SRichard Henderson /*
21746d2a0768SRichard Henderson  * Major opcodes 00 and 01 -- branches, call, and sethi
21756d2a0768SRichard Henderson  */
21766d2a0768SRichard Henderson 
21779d4e2bc7SRichard Henderson static bool advance_jump_cond(DisasContext *dc, DisasCompare *cmp,
21783951b7a8SRichard Henderson                               bool annul, int disp)
2179276567aaSRichard Henderson {
21803951b7a8SRichard Henderson     target_ulong dest = address_mask_i(dc, dc->pc + disp * 4);
2181c76c8045SRichard Henderson     target_ulong npc;
2182c76c8045SRichard Henderson 
218389527e3aSRichard Henderson     finishing_insn(dc);
218489527e3aSRichard Henderson 
21852d9bb237SRichard Henderson     if (cmp->cond == TCG_COND_ALWAYS) {
21862d9bb237SRichard Henderson         if (annul) {
21872d9bb237SRichard Henderson             dc->pc = dest;
21882d9bb237SRichard Henderson             dc->npc = dest + 4;
21892d9bb237SRichard Henderson         } else {
21902d9bb237SRichard Henderson             gen_mov_pc_npc(dc);
21912d9bb237SRichard Henderson             dc->npc = dest;
21922d9bb237SRichard Henderson         }
21932d9bb237SRichard Henderson         return true;
21942d9bb237SRichard Henderson     }
21952d9bb237SRichard Henderson 
21962d9bb237SRichard Henderson     if (cmp->cond == TCG_COND_NEVER) {
21972d9bb237SRichard Henderson         npc = dc->npc;
21982d9bb237SRichard Henderson         if (npc & 3) {
21992d9bb237SRichard Henderson             gen_mov_pc_npc(dc);
22002d9bb237SRichard Henderson             if (annul) {
22012d9bb237SRichard Henderson                 tcg_gen_addi_tl(cpu_pc, cpu_pc, 4);
22022d9bb237SRichard Henderson             }
22032d9bb237SRichard Henderson             tcg_gen_addi_tl(cpu_npc, cpu_pc, 4);
22042d9bb237SRichard Henderson         } else {
22052d9bb237SRichard Henderson             dc->pc = npc + (annul ? 4 : 0);
22062d9bb237SRichard Henderson             dc->npc = dc->pc + 4;
22072d9bb237SRichard Henderson         }
22082d9bb237SRichard Henderson         return true;
22092d9bb237SRichard Henderson     }
22102d9bb237SRichard Henderson 
2211c76c8045SRichard Henderson     flush_cond(dc);
2212c76c8045SRichard Henderson     npc = dc->npc;
22136b3e4cc6SRichard Henderson 
2214276567aaSRichard Henderson     if (annul) {
22156b3e4cc6SRichard Henderson         TCGLabel *l1 = gen_new_label();
22166b3e4cc6SRichard Henderson 
2217c8507ebfSRichard Henderson         tcg_gen_brcondi_tl(tcg_invert_cond(cmp->cond), cmp->c1, cmp->c2, l1);
22186b3e4cc6SRichard Henderson         gen_goto_tb(dc, 0, npc, dest);
22196b3e4cc6SRichard Henderson         gen_set_label(l1);
22206b3e4cc6SRichard Henderson         gen_goto_tb(dc, 1, npc + 4, npc + 8);
22216b3e4cc6SRichard Henderson 
22226b3e4cc6SRichard Henderson         dc->base.is_jmp = DISAS_NORETURN;
2223276567aaSRichard Henderson     } else {
22246b3e4cc6SRichard Henderson         if (npc & 3) {
22256b3e4cc6SRichard Henderson             switch (npc) {
22266b3e4cc6SRichard Henderson             case DYNAMIC_PC:
22276b3e4cc6SRichard Henderson             case DYNAMIC_PC_LOOKUP:
22286b3e4cc6SRichard Henderson                 tcg_gen_mov_tl(cpu_pc, cpu_npc);
22296b3e4cc6SRichard Henderson                 tcg_gen_addi_tl(cpu_npc, cpu_npc, 4);
22309d4e2bc7SRichard Henderson                 tcg_gen_movcond_tl(cmp->cond, cpu_npc,
2231c8507ebfSRichard Henderson                                    cmp->c1, tcg_constant_tl(cmp->c2),
22326b3e4cc6SRichard Henderson                                    tcg_constant_tl(dest), cpu_npc);
22336b3e4cc6SRichard Henderson                 dc->pc = npc;
22346b3e4cc6SRichard Henderson                 break;
22356b3e4cc6SRichard Henderson             default:
22366b3e4cc6SRichard Henderson                 g_assert_not_reached();
22376b3e4cc6SRichard Henderson             }
22386b3e4cc6SRichard Henderson         } else {
22396b3e4cc6SRichard Henderson             dc->pc = npc;
2240533f042fSRichard Henderson             dc->npc = JUMP_PC;
2241533f042fSRichard Henderson             dc->jump = *cmp;
22426b3e4cc6SRichard Henderson             dc->jump_pc[0] = dest;
22436b3e4cc6SRichard Henderson             dc->jump_pc[1] = npc + 4;
2244dd7dbfccSRichard Henderson 
2245dd7dbfccSRichard Henderson             /* The condition for cpu_cond is always NE -- normalize. */
2246dd7dbfccSRichard Henderson             if (cmp->cond == TCG_COND_NE) {
2247c8507ebfSRichard Henderson                 tcg_gen_xori_tl(cpu_cond, cmp->c1, cmp->c2);
22489d4e2bc7SRichard Henderson             } else {
2249c8507ebfSRichard Henderson                 tcg_gen_setcondi_tl(cmp->cond, cpu_cond, cmp->c1, cmp->c2);
22509d4e2bc7SRichard Henderson             }
225189527e3aSRichard Henderson             dc->cpu_cond_live = true;
22526b3e4cc6SRichard Henderson         }
2253276567aaSRichard Henderson     }
2254276567aaSRichard Henderson     return true;
2255276567aaSRichard Henderson }
2256276567aaSRichard Henderson 
2257af25071cSRichard Henderson static bool raise_priv(DisasContext *dc)
2258af25071cSRichard Henderson {
2259af25071cSRichard Henderson     gen_exception(dc, TT_PRIV_INSN);
2260af25071cSRichard Henderson     return true;
2261af25071cSRichard Henderson }
2262af25071cSRichard Henderson 
226306c060d9SRichard Henderson static bool raise_unimpfpop(DisasContext *dc)
226406c060d9SRichard Henderson {
226506c060d9SRichard Henderson     gen_op_fpexception_im(dc, FSR_FTT_UNIMPFPOP);
226606c060d9SRichard Henderson     return true;
226706c060d9SRichard Henderson }
226806c060d9SRichard Henderson 
226906c060d9SRichard Henderson static bool gen_trap_float128(DisasContext *dc)
227006c060d9SRichard Henderson {
227106c060d9SRichard Henderson     if (dc->def->features & CPU_FEATURE_FLOAT128) {
227206c060d9SRichard Henderson         return false;
227306c060d9SRichard Henderson     }
227406c060d9SRichard Henderson     return raise_unimpfpop(dc);
227506c060d9SRichard Henderson }
227606c060d9SRichard Henderson 
2277276567aaSRichard Henderson static bool do_bpcc(DisasContext *dc, arg_bcc *a)
2278276567aaSRichard Henderson {
22791ea9c62aSRichard Henderson     DisasCompare cmp;
2280276567aaSRichard Henderson 
22811ea9c62aSRichard Henderson     gen_compare(&cmp, a->cc, a->cond, dc);
22823951b7a8SRichard Henderson     return advance_jump_cond(dc, &cmp, a->a, a->i);
2283276567aaSRichard Henderson }
2284276567aaSRichard Henderson 
2285276567aaSRichard Henderson TRANS(Bicc, ALL, do_bpcc, a)
2286276567aaSRichard Henderson TRANS(BPcc,  64, do_bpcc, a)
2287276567aaSRichard Henderson 
228845196ea4SRichard Henderson static bool do_fbpfcc(DisasContext *dc, arg_bcc *a)
228945196ea4SRichard Henderson {
2290d5471936SRichard Henderson     DisasCompare cmp;
229145196ea4SRichard Henderson 
229245196ea4SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
229345196ea4SRichard Henderson         return true;
229445196ea4SRichard Henderson     }
2295d5471936SRichard Henderson     gen_fcompare(&cmp, a->cc, a->cond);
22963951b7a8SRichard Henderson     return advance_jump_cond(dc, &cmp, a->a, a->i);
229745196ea4SRichard Henderson }
229845196ea4SRichard Henderson 
229945196ea4SRichard Henderson TRANS(FBPfcc,  64, do_fbpfcc, a)
230045196ea4SRichard Henderson TRANS(FBfcc,  ALL, do_fbpfcc, a)
230145196ea4SRichard Henderson 
2302ab9ffe98SRichard Henderson static bool trans_BPr(DisasContext *dc, arg_BPr *a)
2303ab9ffe98SRichard Henderson {
2304ab9ffe98SRichard Henderson     DisasCompare cmp;
2305ab9ffe98SRichard Henderson 
2306ab9ffe98SRichard Henderson     if (!avail_64(dc)) {
2307ab9ffe98SRichard Henderson         return false;
2308ab9ffe98SRichard Henderson     }
23092c4f56c9SRichard Henderson     if (!gen_compare_reg(&cmp, a->cond, gen_load_gpr(dc, a->rs1))) {
2310ab9ffe98SRichard Henderson         return false;
2311ab9ffe98SRichard Henderson     }
23123951b7a8SRichard Henderson     return advance_jump_cond(dc, &cmp, a->a, a->i);
2313ab9ffe98SRichard Henderson }
2314ab9ffe98SRichard Henderson 
231523ada1b1SRichard Henderson static bool trans_CALL(DisasContext *dc, arg_CALL *a)
231623ada1b1SRichard Henderson {
231723ada1b1SRichard Henderson     target_long target = address_mask_i(dc, dc->pc + a->i * 4);
231823ada1b1SRichard Henderson 
231923ada1b1SRichard Henderson     gen_store_gpr(dc, 15, tcg_constant_tl(dc->pc));
232023ada1b1SRichard Henderson     gen_mov_pc_npc(dc);
232123ada1b1SRichard Henderson     dc->npc = target;
232223ada1b1SRichard Henderson     return true;
232323ada1b1SRichard Henderson }
232423ada1b1SRichard Henderson 
232545196ea4SRichard Henderson static bool trans_NCP(DisasContext *dc, arg_NCP *a)
232645196ea4SRichard Henderson {
232745196ea4SRichard Henderson     /*
232845196ea4SRichard Henderson      * For sparc32, always generate the no-coprocessor exception.
232945196ea4SRichard Henderson      * For sparc64, always generate illegal instruction.
233045196ea4SRichard Henderson      */
233145196ea4SRichard Henderson #ifdef TARGET_SPARC64
233245196ea4SRichard Henderson     return false;
233345196ea4SRichard Henderson #else
233445196ea4SRichard Henderson     gen_exception(dc, TT_NCP_INSN);
233545196ea4SRichard Henderson     return true;
233645196ea4SRichard Henderson #endif
233745196ea4SRichard Henderson }
233845196ea4SRichard Henderson 
23396d2a0768SRichard Henderson static bool trans_SETHI(DisasContext *dc, arg_SETHI *a)
23406d2a0768SRichard Henderson {
23416d2a0768SRichard Henderson     /* Special-case %g0 because that's the canonical nop.  */
23426d2a0768SRichard Henderson     if (a->rd) {
23436d2a0768SRichard Henderson         gen_store_gpr(dc, a->rd, tcg_constant_tl((uint32_t)a->i << 10));
23446d2a0768SRichard Henderson     }
23456d2a0768SRichard Henderson     return advance_pc(dc);
23466d2a0768SRichard Henderson }
23476d2a0768SRichard Henderson 
23480faef01bSRichard Henderson /*
23490faef01bSRichard Henderson  * Major Opcode 10 -- integer, floating-point, vis, and system insns.
23500faef01bSRichard Henderson  */
23510faef01bSRichard Henderson 
235230376636SRichard Henderson static bool do_tcc(DisasContext *dc, int cond, int cc,
235330376636SRichard Henderson                    int rs1, bool imm, int rs2_or_imm)
235430376636SRichard Henderson {
235530376636SRichard Henderson     int mask = ((dc->def->features & CPU_FEATURE_HYPV) && supervisor(dc)
235630376636SRichard Henderson                 ? UA2005_HTRAP_MASK : V8_TRAP_MASK);
235730376636SRichard Henderson     DisasCompare cmp;
235830376636SRichard Henderson     TCGLabel *lab;
235930376636SRichard Henderson     TCGv_i32 trap;
236030376636SRichard Henderson 
236130376636SRichard Henderson     /* Trap never.  */
236230376636SRichard Henderson     if (cond == 0) {
236330376636SRichard Henderson         return advance_pc(dc);
236430376636SRichard Henderson     }
236530376636SRichard Henderson 
236630376636SRichard Henderson     /*
236730376636SRichard Henderson      * Immediate traps are the most common case.  Since this value is
236830376636SRichard Henderson      * live across the branch, it really pays to evaluate the constant.
236930376636SRichard Henderson      */
237030376636SRichard Henderson     if (rs1 == 0 && (imm || rs2_or_imm == 0)) {
237130376636SRichard Henderson         trap = tcg_constant_i32((rs2_or_imm & mask) + TT_TRAP);
237230376636SRichard Henderson     } else {
237330376636SRichard Henderson         trap = tcg_temp_new_i32();
237430376636SRichard Henderson         tcg_gen_trunc_tl_i32(trap, gen_load_gpr(dc, rs1));
237530376636SRichard Henderson         if (imm) {
237630376636SRichard Henderson             tcg_gen_addi_i32(trap, trap, rs2_or_imm);
237730376636SRichard Henderson         } else {
237830376636SRichard Henderson             TCGv_i32 t2 = tcg_temp_new_i32();
237930376636SRichard Henderson             tcg_gen_trunc_tl_i32(t2, gen_load_gpr(dc, rs2_or_imm));
238030376636SRichard Henderson             tcg_gen_add_i32(trap, trap, t2);
238130376636SRichard Henderson         }
238230376636SRichard Henderson         tcg_gen_andi_i32(trap, trap, mask);
238330376636SRichard Henderson         tcg_gen_addi_i32(trap, trap, TT_TRAP);
238430376636SRichard Henderson     }
238530376636SRichard Henderson 
238689527e3aSRichard Henderson     finishing_insn(dc);
238789527e3aSRichard Henderson 
238830376636SRichard Henderson     /* Trap always.  */
238930376636SRichard Henderson     if (cond == 8) {
239030376636SRichard Henderson         save_state(dc);
239130376636SRichard Henderson         gen_helper_raise_exception(tcg_env, trap);
239230376636SRichard Henderson         dc->base.is_jmp = DISAS_NORETURN;
239330376636SRichard Henderson         return true;
239430376636SRichard Henderson     }
239530376636SRichard Henderson 
239630376636SRichard Henderson     /* Conditional trap.  */
239730376636SRichard Henderson     flush_cond(dc);
239830376636SRichard Henderson     lab = delay_exceptionv(dc, trap);
239930376636SRichard Henderson     gen_compare(&cmp, cc, cond, dc);
2400c8507ebfSRichard Henderson     tcg_gen_brcondi_tl(cmp.cond, cmp.c1, cmp.c2, lab);
240130376636SRichard Henderson 
240230376636SRichard Henderson     return advance_pc(dc);
240330376636SRichard Henderson }
240430376636SRichard Henderson 
240530376636SRichard Henderson static bool trans_Tcc_r(DisasContext *dc, arg_Tcc_r *a)
240630376636SRichard Henderson {
240730376636SRichard Henderson     if (avail_32(dc) && a->cc) {
240830376636SRichard Henderson         return false;
240930376636SRichard Henderson     }
241030376636SRichard Henderson     return do_tcc(dc, a->cond, a->cc, a->rs1, false, a->rs2);
241130376636SRichard Henderson }
241230376636SRichard Henderson 
241330376636SRichard Henderson static bool trans_Tcc_i_v7(DisasContext *dc, arg_Tcc_i_v7 *a)
241430376636SRichard Henderson {
241530376636SRichard Henderson     if (avail_64(dc)) {
241630376636SRichard Henderson         return false;
241730376636SRichard Henderson     }
241830376636SRichard Henderson     return do_tcc(dc, a->cond, 0, a->rs1, true, a->i);
241930376636SRichard Henderson }
242030376636SRichard Henderson 
242130376636SRichard Henderson static bool trans_Tcc_i_v9(DisasContext *dc, arg_Tcc_i_v9 *a)
242230376636SRichard Henderson {
242330376636SRichard Henderson     if (avail_32(dc)) {
242430376636SRichard Henderson         return false;
242530376636SRichard Henderson     }
242630376636SRichard Henderson     return do_tcc(dc, a->cond, a->cc, a->rs1, true, a->i);
242730376636SRichard Henderson }
242830376636SRichard Henderson 
2429af25071cSRichard Henderson static bool trans_STBAR(DisasContext *dc, arg_STBAR *a)
2430af25071cSRichard Henderson {
2431af25071cSRichard Henderson     tcg_gen_mb(TCG_MO_ST_ST | TCG_BAR_SC);
2432af25071cSRichard Henderson     return advance_pc(dc);
2433af25071cSRichard Henderson }
2434af25071cSRichard Henderson 
2435af25071cSRichard Henderson static bool trans_MEMBAR(DisasContext *dc, arg_MEMBAR *a)
2436af25071cSRichard Henderson {
2437af25071cSRichard Henderson     if (avail_32(dc)) {
2438af25071cSRichard Henderson         return false;
2439af25071cSRichard Henderson     }
2440af25071cSRichard Henderson     if (a->mmask) {
2441af25071cSRichard Henderson         /* Note TCG_MO_* was modeled on sparc64, so mmask matches. */
2442af25071cSRichard Henderson         tcg_gen_mb(a->mmask | TCG_BAR_SC);
2443af25071cSRichard Henderson     }
2444af25071cSRichard Henderson     if (a->cmask) {
2445af25071cSRichard Henderson         /* For #Sync, etc, end the TB to recognize interrupts. */
2446af25071cSRichard Henderson         dc->base.is_jmp = DISAS_EXIT;
2447af25071cSRichard Henderson     }
2448af25071cSRichard Henderson     return advance_pc(dc);
2449af25071cSRichard Henderson }
2450af25071cSRichard Henderson 
2451af25071cSRichard Henderson static bool do_rd_special(DisasContext *dc, bool priv, int rd,
2452af25071cSRichard Henderson                           TCGv (*func)(DisasContext *, TCGv))
2453af25071cSRichard Henderson {
2454af25071cSRichard Henderson     if (!priv) {
2455af25071cSRichard Henderson         return raise_priv(dc);
2456af25071cSRichard Henderson     }
2457af25071cSRichard Henderson     gen_store_gpr(dc, rd, func(dc, gen_dest_gpr(dc, rd)));
2458af25071cSRichard Henderson     return advance_pc(dc);
2459af25071cSRichard Henderson }
2460af25071cSRichard Henderson 
2461af25071cSRichard Henderson static TCGv do_rdy(DisasContext *dc, TCGv dst)
2462af25071cSRichard Henderson {
2463af25071cSRichard Henderson     return cpu_y;
2464af25071cSRichard Henderson }
2465af25071cSRichard Henderson 
2466af25071cSRichard Henderson static bool trans_RDY(DisasContext *dc, arg_RDY *a)
2467af25071cSRichard Henderson {
2468af25071cSRichard Henderson     /*
2469af25071cSRichard Henderson      * TODO: Need a feature bit for sparcv8.  In the meantime, treat all
2470af25071cSRichard Henderson      * 32-bit cpus like sparcv7, which ignores the rs1 field.
2471af25071cSRichard Henderson      * This matches after all other ASR, so Leon3 Asr17 is handled first.
2472af25071cSRichard Henderson      */
2473af25071cSRichard Henderson     if (avail_64(dc) && a->rs1 != 0) {
2474af25071cSRichard Henderson         return false;
2475af25071cSRichard Henderson     }
2476af25071cSRichard Henderson     return do_rd_special(dc, true, a->rd, do_rdy);
2477af25071cSRichard Henderson }
2478af25071cSRichard Henderson 
2479af25071cSRichard Henderson static TCGv do_rd_leon3_config(DisasContext *dc, TCGv dst)
2480af25071cSRichard Henderson {
2481c92948f2SClément Chigot     gen_helper_rdasr17(dst, tcg_env);
2482c92948f2SClément Chigot     return dst;
2483af25071cSRichard Henderson }
2484af25071cSRichard Henderson 
2485af25071cSRichard Henderson TRANS(RDASR17, ASR17, do_rd_special, true, a->rd, do_rd_leon3_config)
2486af25071cSRichard Henderson 
2487af25071cSRichard Henderson static TCGv do_rdccr(DisasContext *dc, TCGv dst)
2488af25071cSRichard Henderson {
2489af25071cSRichard Henderson     gen_helper_rdccr(dst, tcg_env);
2490af25071cSRichard Henderson     return dst;
2491af25071cSRichard Henderson }
2492af25071cSRichard Henderson 
2493af25071cSRichard Henderson TRANS(RDCCR, 64, do_rd_special, true, a->rd, do_rdccr)
2494af25071cSRichard Henderson 
2495af25071cSRichard Henderson static TCGv do_rdasi(DisasContext *dc, TCGv dst)
2496af25071cSRichard Henderson {
2497af25071cSRichard Henderson #ifdef TARGET_SPARC64
2498af25071cSRichard Henderson     return tcg_constant_tl(dc->asi);
2499af25071cSRichard Henderson #else
2500af25071cSRichard Henderson     qemu_build_not_reached();
2501af25071cSRichard Henderson #endif
2502af25071cSRichard Henderson }
2503af25071cSRichard Henderson 
2504af25071cSRichard Henderson TRANS(RDASI, 64, do_rd_special, true, a->rd, do_rdasi)
2505af25071cSRichard Henderson 
2506af25071cSRichard Henderson static TCGv do_rdtick(DisasContext *dc, TCGv dst)
2507af25071cSRichard Henderson {
2508af25071cSRichard Henderson     TCGv_ptr r_tickptr = tcg_temp_new_ptr();
2509af25071cSRichard Henderson 
2510af25071cSRichard Henderson     tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(tick));
2511af25071cSRichard Henderson     if (translator_io_start(&dc->base)) {
2512af25071cSRichard Henderson         dc->base.is_jmp = DISAS_EXIT;
2513af25071cSRichard Henderson     }
2514af25071cSRichard Henderson     gen_helper_tick_get_count(dst, tcg_env, r_tickptr,
2515af25071cSRichard Henderson                               tcg_constant_i32(dc->mem_idx));
2516af25071cSRichard Henderson     return dst;
2517af25071cSRichard Henderson }
2518af25071cSRichard Henderson 
2519af25071cSRichard Henderson /* TODO: non-priv access only allowed when enabled. */
2520af25071cSRichard Henderson TRANS(RDTICK, 64, do_rd_special, true, a->rd, do_rdtick)
2521af25071cSRichard Henderson 
2522af25071cSRichard Henderson static TCGv do_rdpc(DisasContext *dc, TCGv dst)
2523af25071cSRichard Henderson {
2524af25071cSRichard Henderson     return tcg_constant_tl(address_mask_i(dc, dc->pc));
2525af25071cSRichard Henderson }
2526af25071cSRichard Henderson 
2527af25071cSRichard Henderson TRANS(RDPC, 64, do_rd_special, true, a->rd, do_rdpc)
2528af25071cSRichard Henderson 
2529af25071cSRichard Henderson static TCGv do_rdfprs(DisasContext *dc, TCGv dst)
2530af25071cSRichard Henderson {
2531af25071cSRichard Henderson     tcg_gen_ext_i32_tl(dst, cpu_fprs);
2532af25071cSRichard Henderson     return dst;
2533af25071cSRichard Henderson }
2534af25071cSRichard Henderson 
2535af25071cSRichard Henderson TRANS(RDFPRS, 64, do_rd_special, true, a->rd, do_rdfprs)
2536af25071cSRichard Henderson 
2537af25071cSRichard Henderson static TCGv do_rdgsr(DisasContext *dc, TCGv dst)
2538af25071cSRichard Henderson {
2539af25071cSRichard Henderson     gen_trap_ifnofpu(dc);
2540af25071cSRichard Henderson     return cpu_gsr;
2541af25071cSRichard Henderson }
2542af25071cSRichard Henderson 
2543af25071cSRichard Henderson TRANS(RDGSR, 64, do_rd_special, true, a->rd, do_rdgsr)
2544af25071cSRichard Henderson 
2545af25071cSRichard Henderson static TCGv do_rdsoftint(DisasContext *dc, TCGv dst)
2546af25071cSRichard Henderson {
2547af25071cSRichard Henderson     tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(softint));
2548af25071cSRichard Henderson     return dst;
2549af25071cSRichard Henderson }
2550af25071cSRichard Henderson 
2551af25071cSRichard Henderson TRANS(RDSOFTINT, 64, do_rd_special, supervisor(dc), a->rd, do_rdsoftint)
2552af25071cSRichard Henderson 
2553af25071cSRichard Henderson static TCGv do_rdtick_cmpr(DisasContext *dc, TCGv dst)
2554af25071cSRichard Henderson {
2555577efa45SRichard Henderson     tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(tick_cmpr));
2556577efa45SRichard Henderson     return dst;
2557af25071cSRichard Henderson }
2558af25071cSRichard Henderson 
2559af25071cSRichard Henderson /* TODO: non-priv access only allowed when enabled. */
2560af25071cSRichard Henderson TRANS(RDTICK_CMPR, 64, do_rd_special, true, a->rd, do_rdtick_cmpr)
2561af25071cSRichard Henderson 
2562af25071cSRichard Henderson static TCGv do_rdstick(DisasContext *dc, TCGv dst)
2563af25071cSRichard Henderson {
2564af25071cSRichard Henderson     TCGv_ptr r_tickptr = tcg_temp_new_ptr();
2565af25071cSRichard Henderson 
2566af25071cSRichard Henderson     tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(stick));
2567af25071cSRichard Henderson     if (translator_io_start(&dc->base)) {
2568af25071cSRichard Henderson         dc->base.is_jmp = DISAS_EXIT;
2569af25071cSRichard Henderson     }
2570af25071cSRichard Henderson     gen_helper_tick_get_count(dst, tcg_env, r_tickptr,
2571af25071cSRichard Henderson                               tcg_constant_i32(dc->mem_idx));
2572af25071cSRichard Henderson     return dst;
2573af25071cSRichard Henderson }
2574af25071cSRichard Henderson 
2575af25071cSRichard Henderson /* TODO: non-priv access only allowed when enabled. */
2576af25071cSRichard Henderson TRANS(RDSTICK, 64, do_rd_special, true, a->rd, do_rdstick)
2577af25071cSRichard Henderson 
2578af25071cSRichard Henderson static TCGv do_rdstick_cmpr(DisasContext *dc, TCGv dst)
2579af25071cSRichard Henderson {
2580577efa45SRichard Henderson     tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(stick_cmpr));
2581577efa45SRichard Henderson     return dst;
2582af25071cSRichard Henderson }
2583af25071cSRichard Henderson 
2584af25071cSRichard Henderson /* TODO: supervisor access only allowed when enabled by hypervisor. */
2585af25071cSRichard Henderson TRANS(RDSTICK_CMPR, 64, do_rd_special, supervisor(dc), a->rd, do_rdstick_cmpr)
2586af25071cSRichard Henderson 
2587af25071cSRichard Henderson /*
2588af25071cSRichard Henderson  * UltraSPARC-T1 Strand status.
2589af25071cSRichard Henderson  * HYPV check maybe not enough, UA2005 & UA2007 describe
2590af25071cSRichard Henderson  * this ASR as impl. dep
2591af25071cSRichard Henderson  */
2592af25071cSRichard Henderson static TCGv do_rdstrand_status(DisasContext *dc, TCGv dst)
2593af25071cSRichard Henderson {
2594af25071cSRichard Henderson     return tcg_constant_tl(1);
2595af25071cSRichard Henderson }
2596af25071cSRichard Henderson 
2597af25071cSRichard Henderson TRANS(RDSTRAND_STATUS, HYPV, do_rd_special, true, a->rd, do_rdstrand_status)
2598af25071cSRichard Henderson 
2599668bb9b7SRichard Henderson static TCGv do_rdpsr(DisasContext *dc, TCGv dst)
2600668bb9b7SRichard Henderson {
2601668bb9b7SRichard Henderson     gen_helper_rdpsr(dst, tcg_env);
2602668bb9b7SRichard Henderson     return dst;
2603668bb9b7SRichard Henderson }
2604668bb9b7SRichard Henderson 
2605668bb9b7SRichard Henderson TRANS(RDPSR, 32, do_rd_special, supervisor(dc), a->rd, do_rdpsr)
2606668bb9b7SRichard Henderson 
2607668bb9b7SRichard Henderson static TCGv do_rdhpstate(DisasContext *dc, TCGv dst)
2608668bb9b7SRichard Henderson {
2609668bb9b7SRichard Henderson     tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hpstate));
2610668bb9b7SRichard Henderson     return dst;
2611668bb9b7SRichard Henderson }
2612668bb9b7SRichard Henderson 
2613668bb9b7SRichard Henderson TRANS(RDHPR_hpstate, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhpstate)
2614668bb9b7SRichard Henderson 
2615668bb9b7SRichard Henderson static TCGv do_rdhtstate(DisasContext *dc, TCGv dst)
2616668bb9b7SRichard Henderson {
2617668bb9b7SRichard Henderson     TCGv_i32 tl = tcg_temp_new_i32();
2618668bb9b7SRichard Henderson     TCGv_ptr tp = tcg_temp_new_ptr();
2619668bb9b7SRichard Henderson 
2620668bb9b7SRichard Henderson     tcg_gen_ld_i32(tl, tcg_env, env64_field_offsetof(tl));
2621668bb9b7SRichard Henderson     tcg_gen_andi_i32(tl, tl, MAXTL_MASK);
2622668bb9b7SRichard Henderson     tcg_gen_shli_i32(tl, tl, 3);
2623668bb9b7SRichard Henderson     tcg_gen_ext_i32_ptr(tp, tl);
2624668bb9b7SRichard Henderson     tcg_gen_add_ptr(tp, tp, tcg_env);
2625668bb9b7SRichard Henderson 
2626668bb9b7SRichard Henderson     tcg_gen_ld_tl(dst, tp, env64_field_offsetof(htstate));
2627668bb9b7SRichard Henderson     return dst;
2628668bb9b7SRichard Henderson }
2629668bb9b7SRichard Henderson 
2630668bb9b7SRichard Henderson TRANS(RDHPR_htstate, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhtstate)
2631668bb9b7SRichard Henderson 
2632668bb9b7SRichard Henderson static TCGv do_rdhintp(DisasContext *dc, TCGv dst)
2633668bb9b7SRichard Henderson {
26342da789deSRichard Henderson     tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hintp));
26352da789deSRichard Henderson     return dst;
2636668bb9b7SRichard Henderson }
2637668bb9b7SRichard Henderson 
2638668bb9b7SRichard Henderson TRANS(RDHPR_hintp, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhintp)
2639668bb9b7SRichard Henderson 
2640668bb9b7SRichard Henderson static TCGv do_rdhtba(DisasContext *dc, TCGv dst)
2641668bb9b7SRichard Henderson {
26422da789deSRichard Henderson     tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(htba));
26432da789deSRichard Henderson     return dst;
2644668bb9b7SRichard Henderson }
2645668bb9b7SRichard Henderson 
2646668bb9b7SRichard Henderson TRANS(RDHPR_htba, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhtba)
2647668bb9b7SRichard Henderson 
2648668bb9b7SRichard Henderson static TCGv do_rdhver(DisasContext *dc, TCGv dst)
2649668bb9b7SRichard Henderson {
26502da789deSRichard Henderson     tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hver));
26512da789deSRichard Henderson     return dst;
2652668bb9b7SRichard Henderson }
2653668bb9b7SRichard Henderson 
2654668bb9b7SRichard Henderson TRANS(RDHPR_hver, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhver)
2655668bb9b7SRichard Henderson 
2656668bb9b7SRichard Henderson static TCGv do_rdhstick_cmpr(DisasContext *dc, TCGv dst)
2657668bb9b7SRichard Henderson {
2658577efa45SRichard Henderson     tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hstick_cmpr));
2659577efa45SRichard Henderson     return dst;
2660668bb9b7SRichard Henderson }
2661668bb9b7SRichard Henderson 
2662668bb9b7SRichard Henderson TRANS(RDHPR_hstick_cmpr, HYPV, do_rd_special, hypervisor(dc), a->rd,
2663668bb9b7SRichard Henderson       do_rdhstick_cmpr)
2664668bb9b7SRichard Henderson 
26655d617bfbSRichard Henderson static TCGv do_rdwim(DisasContext *dc, TCGv dst)
26665d617bfbSRichard Henderson {
2667cd6269f7SRichard Henderson     tcg_gen_ld_tl(dst, tcg_env, env32_field_offsetof(wim));
2668cd6269f7SRichard Henderson     return dst;
26695d617bfbSRichard Henderson }
26705d617bfbSRichard Henderson 
26715d617bfbSRichard Henderson TRANS(RDWIM, 32, do_rd_special, supervisor(dc), a->rd, do_rdwim)
26725d617bfbSRichard Henderson 
26735d617bfbSRichard Henderson static TCGv do_rdtpc(DisasContext *dc, TCGv dst)
26745d617bfbSRichard Henderson {
26755d617bfbSRichard Henderson #ifdef TARGET_SPARC64
26765d617bfbSRichard Henderson     TCGv_ptr r_tsptr = tcg_temp_new_ptr();
26775d617bfbSRichard Henderson 
26785d617bfbSRichard Henderson     gen_load_trap_state_at_tl(r_tsptr);
26795d617bfbSRichard Henderson     tcg_gen_ld_tl(dst, r_tsptr, offsetof(trap_state, tpc));
26805d617bfbSRichard Henderson     return dst;
26815d617bfbSRichard Henderson #else
26825d617bfbSRichard Henderson     qemu_build_not_reached();
26835d617bfbSRichard Henderson #endif
26845d617bfbSRichard Henderson }
26855d617bfbSRichard Henderson 
26865d617bfbSRichard Henderson TRANS(RDPR_tpc, 64, do_rd_special, supervisor(dc), a->rd, do_rdtpc)
26875d617bfbSRichard Henderson 
26885d617bfbSRichard Henderson static TCGv do_rdtnpc(DisasContext *dc, TCGv dst)
26895d617bfbSRichard Henderson {
26905d617bfbSRichard Henderson #ifdef TARGET_SPARC64
26915d617bfbSRichard Henderson     TCGv_ptr r_tsptr = tcg_temp_new_ptr();
26925d617bfbSRichard Henderson 
26935d617bfbSRichard Henderson     gen_load_trap_state_at_tl(r_tsptr);
26945d617bfbSRichard Henderson     tcg_gen_ld_tl(dst, r_tsptr, offsetof(trap_state, tnpc));
26955d617bfbSRichard Henderson     return dst;
26965d617bfbSRichard Henderson #else
26975d617bfbSRichard Henderson     qemu_build_not_reached();
26985d617bfbSRichard Henderson #endif
26995d617bfbSRichard Henderson }
27005d617bfbSRichard Henderson 
27015d617bfbSRichard Henderson TRANS(RDPR_tnpc, 64, do_rd_special, supervisor(dc), a->rd, do_rdtnpc)
27025d617bfbSRichard Henderson 
27035d617bfbSRichard Henderson static TCGv do_rdtstate(DisasContext *dc, TCGv dst)
27045d617bfbSRichard Henderson {
27055d617bfbSRichard Henderson #ifdef TARGET_SPARC64
27065d617bfbSRichard Henderson     TCGv_ptr r_tsptr = tcg_temp_new_ptr();
27075d617bfbSRichard Henderson 
27085d617bfbSRichard Henderson     gen_load_trap_state_at_tl(r_tsptr);
27095d617bfbSRichard Henderson     tcg_gen_ld_tl(dst, r_tsptr, offsetof(trap_state, tstate));
27105d617bfbSRichard Henderson     return dst;
27115d617bfbSRichard Henderson #else
27125d617bfbSRichard Henderson     qemu_build_not_reached();
27135d617bfbSRichard Henderson #endif
27145d617bfbSRichard Henderson }
27155d617bfbSRichard Henderson 
27165d617bfbSRichard Henderson TRANS(RDPR_tstate, 64, do_rd_special, supervisor(dc), a->rd, do_rdtstate)
27175d617bfbSRichard Henderson 
27185d617bfbSRichard Henderson static TCGv do_rdtt(DisasContext *dc, TCGv dst)
27195d617bfbSRichard Henderson {
27205d617bfbSRichard Henderson #ifdef TARGET_SPARC64
27215d617bfbSRichard Henderson     TCGv_ptr r_tsptr = tcg_temp_new_ptr();
27225d617bfbSRichard Henderson 
27235d617bfbSRichard Henderson     gen_load_trap_state_at_tl(r_tsptr);
27245d617bfbSRichard Henderson     tcg_gen_ld32s_tl(dst, r_tsptr, offsetof(trap_state, tt));
27255d617bfbSRichard Henderson     return dst;
27265d617bfbSRichard Henderson #else
27275d617bfbSRichard Henderson     qemu_build_not_reached();
27285d617bfbSRichard Henderson #endif
27295d617bfbSRichard Henderson }
27305d617bfbSRichard Henderson 
27315d617bfbSRichard Henderson TRANS(RDPR_tt, 64, do_rd_special, supervisor(dc), a->rd, do_rdtt)
27325d617bfbSRichard Henderson TRANS(RDPR_tick, 64, do_rd_special, supervisor(dc), a->rd, do_rdtick)
27335d617bfbSRichard Henderson 
27345d617bfbSRichard Henderson static TCGv do_rdtba(DisasContext *dc, TCGv dst)
27355d617bfbSRichard Henderson {
27365d617bfbSRichard Henderson     return cpu_tbr;
27375d617bfbSRichard Henderson }
27385d617bfbSRichard Henderson 
2739e8325dc0SRichard Henderson TRANS(RDTBR, 32, do_rd_special, supervisor(dc), a->rd, do_rdtba)
27405d617bfbSRichard Henderson TRANS(RDPR_tba, 64, do_rd_special, supervisor(dc), a->rd, do_rdtba)
27415d617bfbSRichard Henderson 
27425d617bfbSRichard Henderson static TCGv do_rdpstate(DisasContext *dc, TCGv dst)
27435d617bfbSRichard Henderson {
27445d617bfbSRichard Henderson     tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(pstate));
27455d617bfbSRichard Henderson     return dst;
27465d617bfbSRichard Henderson }
27475d617bfbSRichard Henderson 
27485d617bfbSRichard Henderson TRANS(RDPR_pstate, 64, do_rd_special, supervisor(dc), a->rd, do_rdpstate)
27495d617bfbSRichard Henderson 
27505d617bfbSRichard Henderson static TCGv do_rdtl(DisasContext *dc, TCGv dst)
27515d617bfbSRichard Henderson {
27525d617bfbSRichard Henderson     tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(tl));
27535d617bfbSRichard Henderson     return dst;
27545d617bfbSRichard Henderson }
27555d617bfbSRichard Henderson 
27565d617bfbSRichard Henderson TRANS(RDPR_tl, 64, do_rd_special, supervisor(dc), a->rd, do_rdtl)
27575d617bfbSRichard Henderson 
27585d617bfbSRichard Henderson static TCGv do_rdpil(DisasContext *dc, TCGv dst)
27595d617bfbSRichard Henderson {
27605d617bfbSRichard Henderson     tcg_gen_ld32s_tl(dst, tcg_env, env_field_offsetof(psrpil));
27615d617bfbSRichard Henderson     return dst;
27625d617bfbSRichard Henderson }
27635d617bfbSRichard Henderson 
27645d617bfbSRichard Henderson TRANS(RDPR_pil, 64, do_rd_special, supervisor(dc), a->rd, do_rdpil)
27655d617bfbSRichard Henderson 
27665d617bfbSRichard Henderson static TCGv do_rdcwp(DisasContext *dc, TCGv dst)
27675d617bfbSRichard Henderson {
27685d617bfbSRichard Henderson     gen_helper_rdcwp(dst, tcg_env);
27695d617bfbSRichard Henderson     return dst;
27705d617bfbSRichard Henderson }
27715d617bfbSRichard Henderson 
27725d617bfbSRichard Henderson TRANS(RDPR_cwp, 64, do_rd_special, supervisor(dc), a->rd, do_rdcwp)
27735d617bfbSRichard Henderson 
27745d617bfbSRichard Henderson static TCGv do_rdcansave(DisasContext *dc, TCGv dst)
27755d617bfbSRichard Henderson {
27765d617bfbSRichard Henderson     tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(cansave));
27775d617bfbSRichard Henderson     return dst;
27785d617bfbSRichard Henderson }
27795d617bfbSRichard Henderson 
27805d617bfbSRichard Henderson TRANS(RDPR_cansave, 64, do_rd_special, supervisor(dc), a->rd, do_rdcansave)
27815d617bfbSRichard Henderson 
27825d617bfbSRichard Henderson static TCGv do_rdcanrestore(DisasContext *dc, TCGv dst)
27835d617bfbSRichard Henderson {
27845d617bfbSRichard Henderson     tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(canrestore));
27855d617bfbSRichard Henderson     return dst;
27865d617bfbSRichard Henderson }
27875d617bfbSRichard Henderson 
27885d617bfbSRichard Henderson TRANS(RDPR_canrestore, 64, do_rd_special, supervisor(dc), a->rd,
27895d617bfbSRichard Henderson       do_rdcanrestore)
27905d617bfbSRichard Henderson 
27915d617bfbSRichard Henderson static TCGv do_rdcleanwin(DisasContext *dc, TCGv dst)
27925d617bfbSRichard Henderson {
27935d617bfbSRichard Henderson     tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(cleanwin));
27945d617bfbSRichard Henderson     return dst;
27955d617bfbSRichard Henderson }
27965d617bfbSRichard Henderson 
27975d617bfbSRichard Henderson TRANS(RDPR_cleanwin, 64, do_rd_special, supervisor(dc), a->rd, do_rdcleanwin)
27985d617bfbSRichard Henderson 
27995d617bfbSRichard Henderson static TCGv do_rdotherwin(DisasContext *dc, TCGv dst)
28005d617bfbSRichard Henderson {
28015d617bfbSRichard Henderson     tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(otherwin));
28025d617bfbSRichard Henderson     return dst;
28035d617bfbSRichard Henderson }
28045d617bfbSRichard Henderson 
28055d617bfbSRichard Henderson TRANS(RDPR_otherwin, 64, do_rd_special, supervisor(dc), a->rd, do_rdotherwin)
28065d617bfbSRichard Henderson 
28075d617bfbSRichard Henderson static TCGv do_rdwstate(DisasContext *dc, TCGv dst)
28085d617bfbSRichard Henderson {
28095d617bfbSRichard Henderson     tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(wstate));
28105d617bfbSRichard Henderson     return dst;
28115d617bfbSRichard Henderson }
28125d617bfbSRichard Henderson 
28135d617bfbSRichard Henderson TRANS(RDPR_wstate, 64, do_rd_special, supervisor(dc), a->rd, do_rdwstate)
28145d617bfbSRichard Henderson 
28155d617bfbSRichard Henderson static TCGv do_rdgl(DisasContext *dc, TCGv dst)
28165d617bfbSRichard Henderson {
28175d617bfbSRichard Henderson     tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(gl));
28185d617bfbSRichard Henderson     return dst;
28195d617bfbSRichard Henderson }
28205d617bfbSRichard Henderson 
28215d617bfbSRichard Henderson TRANS(RDPR_gl, GL, do_rd_special, supervisor(dc), a->rd, do_rdgl)
28225d617bfbSRichard Henderson 
28235d617bfbSRichard Henderson /* UA2005 strand status */
28245d617bfbSRichard Henderson static TCGv do_rdssr(DisasContext *dc, TCGv dst)
28255d617bfbSRichard Henderson {
28262da789deSRichard Henderson     tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(ssr));
28272da789deSRichard Henderson     return dst;
28285d617bfbSRichard Henderson }
28295d617bfbSRichard Henderson 
28305d617bfbSRichard Henderson TRANS(RDPR_strand_status, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdssr)
28315d617bfbSRichard Henderson 
28325d617bfbSRichard Henderson static TCGv do_rdver(DisasContext *dc, TCGv dst)
28335d617bfbSRichard Henderson {
28342da789deSRichard Henderson     tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(version));
28352da789deSRichard Henderson     return dst;
28365d617bfbSRichard Henderson }
28375d617bfbSRichard Henderson 
28385d617bfbSRichard Henderson TRANS(RDPR_ver, 64, do_rd_special, supervisor(dc), a->rd, do_rdver)
28395d617bfbSRichard Henderson 
2840e8325dc0SRichard Henderson static bool trans_FLUSHW(DisasContext *dc, arg_FLUSHW *a)
2841e8325dc0SRichard Henderson {
2842e8325dc0SRichard Henderson     if (avail_64(dc)) {
2843e8325dc0SRichard Henderson         gen_helper_flushw(tcg_env);
2844e8325dc0SRichard Henderson         return advance_pc(dc);
2845e8325dc0SRichard Henderson     }
2846e8325dc0SRichard Henderson     return false;
2847e8325dc0SRichard Henderson }
2848e8325dc0SRichard Henderson 
28490faef01bSRichard Henderson static bool do_wr_special(DisasContext *dc, arg_r_r_ri *a, bool priv,
28500faef01bSRichard Henderson                           void (*func)(DisasContext *, TCGv))
28510faef01bSRichard Henderson {
28520faef01bSRichard Henderson     TCGv src;
28530faef01bSRichard Henderson 
28540faef01bSRichard Henderson     /* For simplicity, we under-decoded the rs2 form. */
28550faef01bSRichard Henderson     if (!a->imm && (a->rs2_or_imm & ~0x1f)) {
28560faef01bSRichard Henderson         return false;
28570faef01bSRichard Henderson     }
28580faef01bSRichard Henderson     if (!priv) {
28590faef01bSRichard Henderson         return raise_priv(dc);
28600faef01bSRichard Henderson     }
28610faef01bSRichard Henderson 
28620faef01bSRichard Henderson     if (a->rs1 == 0 && (a->imm || a->rs2_or_imm == 0)) {
28630faef01bSRichard Henderson         src = tcg_constant_tl(a->rs2_or_imm);
28640faef01bSRichard Henderson     } else {
28650faef01bSRichard Henderson         TCGv src1 = gen_load_gpr(dc, a->rs1);
28660faef01bSRichard Henderson         if (a->rs2_or_imm == 0) {
28670faef01bSRichard Henderson             src = src1;
28680faef01bSRichard Henderson         } else {
28690faef01bSRichard Henderson             src = tcg_temp_new();
28700faef01bSRichard Henderson             if (a->imm) {
28710faef01bSRichard Henderson                 tcg_gen_xori_tl(src, src1, a->rs2_or_imm);
28720faef01bSRichard Henderson             } else {
28730faef01bSRichard Henderson                 tcg_gen_xor_tl(src, src1, gen_load_gpr(dc, a->rs2_or_imm));
28740faef01bSRichard Henderson             }
28750faef01bSRichard Henderson         }
28760faef01bSRichard Henderson     }
28770faef01bSRichard Henderson     func(dc, src);
28780faef01bSRichard Henderson     return advance_pc(dc);
28790faef01bSRichard Henderson }
28800faef01bSRichard Henderson 
28810faef01bSRichard Henderson static void do_wry(DisasContext *dc, TCGv src)
28820faef01bSRichard Henderson {
28830faef01bSRichard Henderson     tcg_gen_ext32u_tl(cpu_y, src);
28840faef01bSRichard Henderson }
28850faef01bSRichard Henderson 
28860faef01bSRichard Henderson TRANS(WRY, ALL, do_wr_special, a, true, do_wry)
28870faef01bSRichard Henderson 
28880faef01bSRichard Henderson static void do_wrccr(DisasContext *dc, TCGv src)
28890faef01bSRichard Henderson {
28900faef01bSRichard Henderson     gen_helper_wrccr(tcg_env, src);
28910faef01bSRichard Henderson }
28920faef01bSRichard Henderson 
28930faef01bSRichard Henderson TRANS(WRCCR, 64, do_wr_special, a, true, do_wrccr)
28940faef01bSRichard Henderson 
28950faef01bSRichard Henderson static void do_wrasi(DisasContext *dc, TCGv src)
28960faef01bSRichard Henderson {
28970faef01bSRichard Henderson     TCGv tmp = tcg_temp_new();
28980faef01bSRichard Henderson 
28990faef01bSRichard Henderson     tcg_gen_ext8u_tl(tmp, src);
29000faef01bSRichard Henderson     tcg_gen_st32_tl(tmp, tcg_env, env64_field_offsetof(asi));
29010faef01bSRichard Henderson     /* End TB to notice changed ASI. */
29020faef01bSRichard Henderson     dc->base.is_jmp = DISAS_EXIT;
29030faef01bSRichard Henderson }
29040faef01bSRichard Henderson 
29050faef01bSRichard Henderson TRANS(WRASI, 64, do_wr_special, a, true, do_wrasi)
29060faef01bSRichard Henderson 
29070faef01bSRichard Henderson static void do_wrfprs(DisasContext *dc, TCGv src)
29080faef01bSRichard Henderson {
29090faef01bSRichard Henderson #ifdef TARGET_SPARC64
29100faef01bSRichard Henderson     tcg_gen_trunc_tl_i32(cpu_fprs, src);
29110faef01bSRichard Henderson     dc->fprs_dirty = 0;
29120faef01bSRichard Henderson     dc->base.is_jmp = DISAS_EXIT;
29130faef01bSRichard Henderson #else
29140faef01bSRichard Henderson     qemu_build_not_reached();
29150faef01bSRichard Henderson #endif
29160faef01bSRichard Henderson }
29170faef01bSRichard Henderson 
29180faef01bSRichard Henderson TRANS(WRFPRS, 64, do_wr_special, a, true, do_wrfprs)
29190faef01bSRichard Henderson 
29200faef01bSRichard Henderson static void do_wrgsr(DisasContext *dc, TCGv src)
29210faef01bSRichard Henderson {
29220faef01bSRichard Henderson     gen_trap_ifnofpu(dc);
29230faef01bSRichard Henderson     tcg_gen_mov_tl(cpu_gsr, src);
29240faef01bSRichard Henderson }
29250faef01bSRichard Henderson 
29260faef01bSRichard Henderson TRANS(WRGSR, 64, do_wr_special, a, true, do_wrgsr)
29270faef01bSRichard Henderson 
29280faef01bSRichard Henderson static void do_wrsoftint_set(DisasContext *dc, TCGv src)
29290faef01bSRichard Henderson {
29300faef01bSRichard Henderson     gen_helper_set_softint(tcg_env, src);
29310faef01bSRichard Henderson }
29320faef01bSRichard Henderson 
29330faef01bSRichard Henderson TRANS(WRSOFTINT_SET, 64, do_wr_special, a, supervisor(dc), do_wrsoftint_set)
29340faef01bSRichard Henderson 
29350faef01bSRichard Henderson static void do_wrsoftint_clr(DisasContext *dc, TCGv src)
29360faef01bSRichard Henderson {
29370faef01bSRichard Henderson     gen_helper_clear_softint(tcg_env, src);
29380faef01bSRichard Henderson }
29390faef01bSRichard Henderson 
29400faef01bSRichard Henderson TRANS(WRSOFTINT_CLR, 64, do_wr_special, a, supervisor(dc), do_wrsoftint_clr)
29410faef01bSRichard Henderson 
29420faef01bSRichard Henderson static void do_wrsoftint(DisasContext *dc, TCGv src)
29430faef01bSRichard Henderson {
29440faef01bSRichard Henderson     gen_helper_write_softint(tcg_env, src);
29450faef01bSRichard Henderson }
29460faef01bSRichard Henderson 
29470faef01bSRichard Henderson TRANS(WRSOFTINT, 64, do_wr_special, a, supervisor(dc), do_wrsoftint)
29480faef01bSRichard Henderson 
29490faef01bSRichard Henderson static void do_wrtick_cmpr(DisasContext *dc, TCGv src)
29500faef01bSRichard Henderson {
29510faef01bSRichard Henderson     TCGv_ptr r_tickptr = tcg_temp_new_ptr();
29520faef01bSRichard Henderson 
2953577efa45SRichard Henderson     tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(tick_cmpr));
2954577efa45SRichard Henderson     tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(tick));
29550faef01bSRichard Henderson     translator_io_start(&dc->base);
2956577efa45SRichard Henderson     gen_helper_tick_set_limit(r_tickptr, src);
29570faef01bSRichard Henderson     /* End TB to handle timer interrupt */
29580faef01bSRichard Henderson     dc->base.is_jmp = DISAS_EXIT;
29590faef01bSRichard Henderson }
29600faef01bSRichard Henderson 
29610faef01bSRichard Henderson TRANS(WRTICK_CMPR, 64, do_wr_special, a, supervisor(dc), do_wrtick_cmpr)
29620faef01bSRichard Henderson 
29630faef01bSRichard Henderson static void do_wrstick(DisasContext *dc, TCGv src)
29640faef01bSRichard Henderson {
29650faef01bSRichard Henderson #ifdef TARGET_SPARC64
29660faef01bSRichard Henderson     TCGv_ptr r_tickptr = tcg_temp_new_ptr();
29670faef01bSRichard Henderson 
29680faef01bSRichard Henderson     tcg_gen_ld_ptr(r_tickptr, tcg_env, offsetof(CPUSPARCState, stick));
29690faef01bSRichard Henderson     translator_io_start(&dc->base);
29700faef01bSRichard Henderson     gen_helper_tick_set_count(r_tickptr, src);
29710faef01bSRichard Henderson     /* End TB to handle timer interrupt */
29720faef01bSRichard Henderson     dc->base.is_jmp = DISAS_EXIT;
29730faef01bSRichard Henderson #else
29740faef01bSRichard Henderson     qemu_build_not_reached();
29750faef01bSRichard Henderson #endif
29760faef01bSRichard Henderson }
29770faef01bSRichard Henderson 
29780faef01bSRichard Henderson TRANS(WRSTICK, 64, do_wr_special, a, supervisor(dc), do_wrstick)
29790faef01bSRichard Henderson 
29800faef01bSRichard Henderson static void do_wrstick_cmpr(DisasContext *dc, TCGv src)
29810faef01bSRichard Henderson {
29820faef01bSRichard Henderson     TCGv_ptr r_tickptr = tcg_temp_new_ptr();
29830faef01bSRichard Henderson 
2984577efa45SRichard Henderson     tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(stick_cmpr));
2985577efa45SRichard Henderson     tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(stick));
29860faef01bSRichard Henderson     translator_io_start(&dc->base);
2987577efa45SRichard Henderson     gen_helper_tick_set_limit(r_tickptr, src);
29880faef01bSRichard Henderson     /* End TB to handle timer interrupt */
29890faef01bSRichard Henderson     dc->base.is_jmp = DISAS_EXIT;
29900faef01bSRichard Henderson }
29910faef01bSRichard Henderson 
29920faef01bSRichard Henderson TRANS(WRSTICK_CMPR, 64, do_wr_special, a, supervisor(dc), do_wrstick_cmpr)
29930faef01bSRichard Henderson 
29940faef01bSRichard Henderson static void do_wrpowerdown(DisasContext *dc, TCGv src)
29950faef01bSRichard Henderson {
299689527e3aSRichard Henderson     finishing_insn(dc);
29970faef01bSRichard Henderson     save_state(dc);
29980faef01bSRichard Henderson     gen_helper_power_down(tcg_env);
29990faef01bSRichard Henderson }
30000faef01bSRichard Henderson 
30010faef01bSRichard Henderson TRANS(WRPOWERDOWN, POWERDOWN, do_wr_special, a, supervisor(dc), do_wrpowerdown)
30020faef01bSRichard Henderson 
300325524734SRichard Henderson static void do_wrpsr(DisasContext *dc, TCGv src)
300425524734SRichard Henderson {
300525524734SRichard Henderson     gen_helper_wrpsr(tcg_env, src);
300625524734SRichard Henderson     dc->base.is_jmp = DISAS_EXIT;
300725524734SRichard Henderson }
300825524734SRichard Henderson 
300925524734SRichard Henderson TRANS(WRPSR, 32, do_wr_special, a, supervisor(dc), do_wrpsr)
301025524734SRichard Henderson 
30119422278eSRichard Henderson static void do_wrwim(DisasContext *dc, TCGv src)
30129422278eSRichard Henderson {
30139422278eSRichard Henderson     target_ulong mask = MAKE_64BIT_MASK(0, dc->def->nwindows);
3014cd6269f7SRichard Henderson     TCGv tmp = tcg_temp_new();
3015cd6269f7SRichard Henderson 
3016cd6269f7SRichard Henderson     tcg_gen_andi_tl(tmp, src, mask);
3017cd6269f7SRichard Henderson     tcg_gen_st_tl(tmp, tcg_env, env32_field_offsetof(wim));
30189422278eSRichard Henderson }
30199422278eSRichard Henderson 
30209422278eSRichard Henderson TRANS(WRWIM, 32, do_wr_special, a, supervisor(dc), do_wrwim)
30219422278eSRichard Henderson 
30229422278eSRichard Henderson static void do_wrtpc(DisasContext *dc, TCGv src)
30239422278eSRichard Henderson {
30249422278eSRichard Henderson #ifdef TARGET_SPARC64
30259422278eSRichard Henderson     TCGv_ptr r_tsptr = tcg_temp_new_ptr();
30269422278eSRichard Henderson 
30279422278eSRichard Henderson     gen_load_trap_state_at_tl(r_tsptr);
30289422278eSRichard Henderson     tcg_gen_st_tl(src, r_tsptr, offsetof(trap_state, tpc));
30299422278eSRichard Henderson #else
30309422278eSRichard Henderson     qemu_build_not_reached();
30319422278eSRichard Henderson #endif
30329422278eSRichard Henderson }
30339422278eSRichard Henderson 
30349422278eSRichard Henderson TRANS(WRPR_tpc, 64, do_wr_special, a, supervisor(dc), do_wrtpc)
30359422278eSRichard Henderson 
30369422278eSRichard Henderson static void do_wrtnpc(DisasContext *dc, TCGv src)
30379422278eSRichard Henderson {
30389422278eSRichard Henderson #ifdef TARGET_SPARC64
30399422278eSRichard Henderson     TCGv_ptr r_tsptr = tcg_temp_new_ptr();
30409422278eSRichard Henderson 
30419422278eSRichard Henderson     gen_load_trap_state_at_tl(r_tsptr);
30429422278eSRichard Henderson     tcg_gen_st_tl(src, r_tsptr, offsetof(trap_state, tnpc));
30439422278eSRichard Henderson #else
30449422278eSRichard Henderson     qemu_build_not_reached();
30459422278eSRichard Henderson #endif
30469422278eSRichard Henderson }
30479422278eSRichard Henderson 
30489422278eSRichard Henderson TRANS(WRPR_tnpc, 64, do_wr_special, a, supervisor(dc), do_wrtnpc)
30499422278eSRichard Henderson 
30509422278eSRichard Henderson static void do_wrtstate(DisasContext *dc, TCGv src)
30519422278eSRichard Henderson {
30529422278eSRichard Henderson #ifdef TARGET_SPARC64
30539422278eSRichard Henderson     TCGv_ptr r_tsptr = tcg_temp_new_ptr();
30549422278eSRichard Henderson 
30559422278eSRichard Henderson     gen_load_trap_state_at_tl(r_tsptr);
30569422278eSRichard Henderson     tcg_gen_st_tl(src, r_tsptr, offsetof(trap_state, tstate));
30579422278eSRichard Henderson #else
30589422278eSRichard Henderson     qemu_build_not_reached();
30599422278eSRichard Henderson #endif
30609422278eSRichard Henderson }
30619422278eSRichard Henderson 
30629422278eSRichard Henderson TRANS(WRPR_tstate, 64, do_wr_special, a, supervisor(dc), do_wrtstate)
30639422278eSRichard Henderson 
30649422278eSRichard Henderson static void do_wrtt(DisasContext *dc, TCGv src)
30659422278eSRichard Henderson {
30669422278eSRichard Henderson #ifdef TARGET_SPARC64
30679422278eSRichard Henderson     TCGv_ptr r_tsptr = tcg_temp_new_ptr();
30689422278eSRichard Henderson 
30699422278eSRichard Henderson     gen_load_trap_state_at_tl(r_tsptr);
30709422278eSRichard Henderson     tcg_gen_st32_tl(src, r_tsptr, offsetof(trap_state, tt));
30719422278eSRichard Henderson #else
30729422278eSRichard Henderson     qemu_build_not_reached();
30739422278eSRichard Henderson #endif
30749422278eSRichard Henderson }
30759422278eSRichard Henderson 
30769422278eSRichard Henderson TRANS(WRPR_tt, 64, do_wr_special, a, supervisor(dc), do_wrtt)
30779422278eSRichard Henderson 
30789422278eSRichard Henderson static void do_wrtick(DisasContext *dc, TCGv src)
30799422278eSRichard Henderson {
30809422278eSRichard Henderson     TCGv_ptr r_tickptr = tcg_temp_new_ptr();
30819422278eSRichard Henderson 
30829422278eSRichard Henderson     tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(tick));
30839422278eSRichard Henderson     translator_io_start(&dc->base);
30849422278eSRichard Henderson     gen_helper_tick_set_count(r_tickptr, src);
30859422278eSRichard Henderson     /* End TB to handle timer interrupt */
30869422278eSRichard Henderson     dc->base.is_jmp = DISAS_EXIT;
30879422278eSRichard Henderson }
30889422278eSRichard Henderson 
30899422278eSRichard Henderson TRANS(WRPR_tick, 64, do_wr_special, a, supervisor(dc), do_wrtick)
30909422278eSRichard Henderson 
30919422278eSRichard Henderson static void do_wrtba(DisasContext *dc, TCGv src)
30929422278eSRichard Henderson {
30939422278eSRichard Henderson     tcg_gen_mov_tl(cpu_tbr, src);
30949422278eSRichard Henderson }
30959422278eSRichard Henderson 
30969422278eSRichard Henderson TRANS(WRPR_tba, 64, do_wr_special, a, supervisor(dc), do_wrtba)
30979422278eSRichard Henderson 
30989422278eSRichard Henderson static void do_wrpstate(DisasContext *dc, TCGv src)
30999422278eSRichard Henderson {
31009422278eSRichard Henderson     save_state(dc);
31019422278eSRichard Henderson     if (translator_io_start(&dc->base)) {
31029422278eSRichard Henderson         dc->base.is_jmp = DISAS_EXIT;
31039422278eSRichard Henderson     }
31049422278eSRichard Henderson     gen_helper_wrpstate(tcg_env, src);
31059422278eSRichard Henderson     dc->npc = DYNAMIC_PC;
31069422278eSRichard Henderson }
31079422278eSRichard Henderson 
31089422278eSRichard Henderson TRANS(WRPR_pstate, 64, do_wr_special, a, supervisor(dc), do_wrpstate)
31099422278eSRichard Henderson 
31109422278eSRichard Henderson static void do_wrtl(DisasContext *dc, TCGv src)
31119422278eSRichard Henderson {
31129422278eSRichard Henderson     save_state(dc);
31139422278eSRichard Henderson     tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(tl));
31149422278eSRichard Henderson     dc->npc = DYNAMIC_PC;
31159422278eSRichard Henderson }
31169422278eSRichard Henderson 
31179422278eSRichard Henderson TRANS(WRPR_tl, 64, do_wr_special, a, supervisor(dc), do_wrtl)
31189422278eSRichard Henderson 
31199422278eSRichard Henderson static void do_wrpil(DisasContext *dc, TCGv src)
31209422278eSRichard Henderson {
31219422278eSRichard Henderson     if (translator_io_start(&dc->base)) {
31229422278eSRichard Henderson         dc->base.is_jmp = DISAS_EXIT;
31239422278eSRichard Henderson     }
31249422278eSRichard Henderson     gen_helper_wrpil(tcg_env, src);
31259422278eSRichard Henderson }
31269422278eSRichard Henderson 
31279422278eSRichard Henderson TRANS(WRPR_pil, 64, do_wr_special, a, supervisor(dc), do_wrpil)
31289422278eSRichard Henderson 
31299422278eSRichard Henderson static void do_wrcwp(DisasContext *dc, TCGv src)
31309422278eSRichard Henderson {
31319422278eSRichard Henderson     gen_helper_wrcwp(tcg_env, src);
31329422278eSRichard Henderson }
31339422278eSRichard Henderson 
31349422278eSRichard Henderson TRANS(WRPR_cwp, 64, do_wr_special, a, supervisor(dc), do_wrcwp)
31359422278eSRichard Henderson 
31369422278eSRichard Henderson static void do_wrcansave(DisasContext *dc, TCGv src)
31379422278eSRichard Henderson {
31389422278eSRichard Henderson     tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(cansave));
31399422278eSRichard Henderson }
31409422278eSRichard Henderson 
31419422278eSRichard Henderson TRANS(WRPR_cansave, 64, do_wr_special, a, supervisor(dc), do_wrcansave)
31429422278eSRichard Henderson 
31439422278eSRichard Henderson static void do_wrcanrestore(DisasContext *dc, TCGv src)
31449422278eSRichard Henderson {
31459422278eSRichard Henderson     tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(canrestore));
31469422278eSRichard Henderson }
31479422278eSRichard Henderson 
31489422278eSRichard Henderson TRANS(WRPR_canrestore, 64, do_wr_special, a, supervisor(dc), do_wrcanrestore)
31499422278eSRichard Henderson 
31509422278eSRichard Henderson static void do_wrcleanwin(DisasContext *dc, TCGv src)
31519422278eSRichard Henderson {
31529422278eSRichard Henderson     tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(cleanwin));
31539422278eSRichard Henderson }
31549422278eSRichard Henderson 
31559422278eSRichard Henderson TRANS(WRPR_cleanwin, 64, do_wr_special, a, supervisor(dc), do_wrcleanwin)
31569422278eSRichard Henderson 
31579422278eSRichard Henderson static void do_wrotherwin(DisasContext *dc, TCGv src)
31589422278eSRichard Henderson {
31599422278eSRichard Henderson     tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(otherwin));
31609422278eSRichard Henderson }
31619422278eSRichard Henderson 
31629422278eSRichard Henderson TRANS(WRPR_otherwin, 64, do_wr_special, a, supervisor(dc), do_wrotherwin)
31639422278eSRichard Henderson 
31649422278eSRichard Henderson static void do_wrwstate(DisasContext *dc, TCGv src)
31659422278eSRichard Henderson {
31669422278eSRichard Henderson     tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(wstate));
31679422278eSRichard Henderson }
31689422278eSRichard Henderson 
31699422278eSRichard Henderson TRANS(WRPR_wstate, 64, do_wr_special, a, supervisor(dc), do_wrwstate)
31709422278eSRichard Henderson 
31719422278eSRichard Henderson static void do_wrgl(DisasContext *dc, TCGv src)
31729422278eSRichard Henderson {
31739422278eSRichard Henderson     gen_helper_wrgl(tcg_env, src);
31749422278eSRichard Henderson }
31759422278eSRichard Henderson 
31769422278eSRichard Henderson TRANS(WRPR_gl, GL, do_wr_special, a, supervisor(dc), do_wrgl)
31779422278eSRichard Henderson 
31789422278eSRichard Henderson /* UA2005 strand status */
31799422278eSRichard Henderson static void do_wrssr(DisasContext *dc, TCGv src)
31809422278eSRichard Henderson {
31812da789deSRichard Henderson     tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(ssr));
31829422278eSRichard Henderson }
31839422278eSRichard Henderson 
31849422278eSRichard Henderson TRANS(WRPR_strand_status, HYPV, do_wr_special, a, hypervisor(dc), do_wrssr)
31859422278eSRichard Henderson 
3186bb97f2f5SRichard Henderson TRANS(WRTBR, 32, do_wr_special, a, supervisor(dc), do_wrtba)
3187bb97f2f5SRichard Henderson 
3188bb97f2f5SRichard Henderson static void do_wrhpstate(DisasContext *dc, TCGv src)
3189bb97f2f5SRichard Henderson {
3190bb97f2f5SRichard Henderson     tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(hpstate));
3191bb97f2f5SRichard Henderson     dc->base.is_jmp = DISAS_EXIT;
3192bb97f2f5SRichard Henderson }
3193bb97f2f5SRichard Henderson 
3194bb97f2f5SRichard Henderson TRANS(WRHPR_hpstate, HYPV, do_wr_special, a, hypervisor(dc), do_wrhpstate)
3195bb97f2f5SRichard Henderson 
3196bb97f2f5SRichard Henderson static void do_wrhtstate(DisasContext *dc, TCGv src)
3197bb97f2f5SRichard Henderson {
3198bb97f2f5SRichard Henderson     TCGv_i32 tl = tcg_temp_new_i32();
3199bb97f2f5SRichard Henderson     TCGv_ptr tp = tcg_temp_new_ptr();
3200bb97f2f5SRichard Henderson 
3201bb97f2f5SRichard Henderson     tcg_gen_ld_i32(tl, tcg_env, env64_field_offsetof(tl));
3202bb97f2f5SRichard Henderson     tcg_gen_andi_i32(tl, tl, MAXTL_MASK);
3203bb97f2f5SRichard Henderson     tcg_gen_shli_i32(tl, tl, 3);
3204bb97f2f5SRichard Henderson     tcg_gen_ext_i32_ptr(tp, tl);
3205bb97f2f5SRichard Henderson     tcg_gen_add_ptr(tp, tp, tcg_env);
3206bb97f2f5SRichard Henderson 
3207bb97f2f5SRichard Henderson     tcg_gen_st_tl(src, tp, env64_field_offsetof(htstate));
3208bb97f2f5SRichard Henderson }
3209bb97f2f5SRichard Henderson 
3210bb97f2f5SRichard Henderson TRANS(WRHPR_htstate, HYPV, do_wr_special, a, hypervisor(dc), do_wrhtstate)
3211bb97f2f5SRichard Henderson 
3212bb97f2f5SRichard Henderson static void do_wrhintp(DisasContext *dc, TCGv src)
3213bb97f2f5SRichard Henderson {
32142da789deSRichard Henderson     tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(hintp));
3215bb97f2f5SRichard Henderson }
3216bb97f2f5SRichard Henderson 
3217bb97f2f5SRichard Henderson TRANS(WRHPR_hintp, HYPV, do_wr_special, a, hypervisor(dc), do_wrhintp)
3218bb97f2f5SRichard Henderson 
3219bb97f2f5SRichard Henderson static void do_wrhtba(DisasContext *dc, TCGv src)
3220bb97f2f5SRichard Henderson {
32212da789deSRichard Henderson     tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(htba));
3222bb97f2f5SRichard Henderson }
3223bb97f2f5SRichard Henderson 
3224bb97f2f5SRichard Henderson TRANS(WRHPR_htba, HYPV, do_wr_special, a, hypervisor(dc), do_wrhtba)
3225bb97f2f5SRichard Henderson 
3226bb97f2f5SRichard Henderson static void do_wrhstick_cmpr(DisasContext *dc, TCGv src)
3227bb97f2f5SRichard Henderson {
3228bb97f2f5SRichard Henderson     TCGv_ptr r_tickptr = tcg_temp_new_ptr();
3229bb97f2f5SRichard Henderson 
3230577efa45SRichard Henderson     tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(hstick_cmpr));
3231bb97f2f5SRichard Henderson     tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(hstick));
3232bb97f2f5SRichard Henderson     translator_io_start(&dc->base);
3233577efa45SRichard Henderson     gen_helper_tick_set_limit(r_tickptr, src);
3234bb97f2f5SRichard Henderson     /* End TB to handle timer interrupt */
3235bb97f2f5SRichard Henderson     dc->base.is_jmp = DISAS_EXIT;
3236bb97f2f5SRichard Henderson }
3237bb97f2f5SRichard Henderson 
3238bb97f2f5SRichard Henderson TRANS(WRHPR_hstick_cmpr, HYPV, do_wr_special, a, hypervisor(dc),
3239bb97f2f5SRichard Henderson       do_wrhstick_cmpr)
3240bb97f2f5SRichard Henderson 
324125524734SRichard Henderson static bool do_saved_restored(DisasContext *dc, bool saved)
324225524734SRichard Henderson {
324325524734SRichard Henderson     if (!supervisor(dc)) {
324425524734SRichard Henderson         return raise_priv(dc);
324525524734SRichard Henderson     }
324625524734SRichard Henderson     if (saved) {
324725524734SRichard Henderson         gen_helper_saved(tcg_env);
324825524734SRichard Henderson     } else {
324925524734SRichard Henderson         gen_helper_restored(tcg_env);
325025524734SRichard Henderson     }
325125524734SRichard Henderson     return advance_pc(dc);
325225524734SRichard Henderson }
325325524734SRichard Henderson 
325425524734SRichard Henderson TRANS(SAVED, 64, do_saved_restored, true)
325525524734SRichard Henderson TRANS(RESTORED, 64, do_saved_restored, false)
325625524734SRichard Henderson 
3257d3825800SRichard Henderson static bool trans_NOP(DisasContext *dc, arg_NOP *a)
3258d3825800SRichard Henderson {
3259d3825800SRichard Henderson     return advance_pc(dc);
3260d3825800SRichard Henderson }
3261d3825800SRichard Henderson 
32620faef01bSRichard Henderson /*
32630faef01bSRichard Henderson  * TODO: Need a feature bit for sparcv8.
32640faef01bSRichard Henderson  * In the meantime, treat all 32-bit cpus like sparcv7.
32650faef01bSRichard Henderson  */
32665458fd31SRichard Henderson TRANS(NOP_v7, 32, trans_NOP, a)
32675458fd31SRichard Henderson TRANS(NOP_v9, 64, trans_NOP, a)
32680faef01bSRichard Henderson 
3269b597eedcSRichard Henderson static bool do_arith_int(DisasContext *dc, arg_r_r_ri_cc *a,
3270428881deSRichard Henderson                          void (*func)(TCGv, TCGv, TCGv),
32712a45b736SRichard Henderson                          void (*funci)(TCGv, TCGv, target_long),
32722a45b736SRichard Henderson                          bool logic_cc)
3273428881deSRichard Henderson {
3274428881deSRichard Henderson     TCGv dst, src1;
3275428881deSRichard Henderson 
3276428881deSRichard Henderson     /* For simplicity, we under-decoded the rs2 form. */
3277428881deSRichard Henderson     if (!a->imm && a->rs2_or_imm & ~0x1f) {
3278428881deSRichard Henderson         return false;
3279428881deSRichard Henderson     }
3280428881deSRichard Henderson 
32812a45b736SRichard Henderson     if (logic_cc) {
32822a45b736SRichard Henderson         dst = cpu_cc_N;
3283428881deSRichard Henderson     } else {
3284428881deSRichard Henderson         dst = gen_dest_gpr(dc, a->rd);
3285428881deSRichard Henderson     }
3286428881deSRichard Henderson     src1 = gen_load_gpr(dc, a->rs1);
3287428881deSRichard Henderson 
3288428881deSRichard Henderson     if (a->imm || a->rs2_or_imm == 0) {
3289428881deSRichard Henderson         if (funci) {
3290428881deSRichard Henderson             funci(dst, src1, a->rs2_or_imm);
3291428881deSRichard Henderson         } else {
3292428881deSRichard Henderson             func(dst, src1, tcg_constant_tl(a->rs2_or_imm));
3293428881deSRichard Henderson         }
3294428881deSRichard Henderson     } else {
3295428881deSRichard Henderson         func(dst, src1, cpu_regs[a->rs2_or_imm]);
3296428881deSRichard Henderson     }
32972a45b736SRichard Henderson 
32982a45b736SRichard Henderson     if (logic_cc) {
32992a45b736SRichard Henderson         if (TARGET_LONG_BITS == 64) {
33002a45b736SRichard Henderson             tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N);
33012a45b736SRichard Henderson             tcg_gen_movi_tl(cpu_icc_C, 0);
33022a45b736SRichard Henderson         }
33032a45b736SRichard Henderson         tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N);
33042a45b736SRichard Henderson         tcg_gen_movi_tl(cpu_cc_C, 0);
33052a45b736SRichard Henderson         tcg_gen_movi_tl(cpu_cc_V, 0);
33062a45b736SRichard Henderson     }
33072a45b736SRichard Henderson 
3308428881deSRichard Henderson     gen_store_gpr(dc, a->rd, dst);
3309428881deSRichard Henderson     return advance_pc(dc);
3310428881deSRichard Henderson }
3311428881deSRichard Henderson 
3312b597eedcSRichard Henderson static bool do_arith(DisasContext *dc, arg_r_r_ri_cc *a,
3313428881deSRichard Henderson                      void (*func)(TCGv, TCGv, TCGv),
3314428881deSRichard Henderson                      void (*funci)(TCGv, TCGv, target_long),
3315428881deSRichard Henderson                      void (*func_cc)(TCGv, TCGv, TCGv))
3316428881deSRichard Henderson {
3317428881deSRichard Henderson     if (a->cc) {
3318b597eedcSRichard Henderson         return do_arith_int(dc, a, func_cc, NULL, false);
3319428881deSRichard Henderson     }
3320b597eedcSRichard Henderson     return do_arith_int(dc, a, func, funci, false);
3321428881deSRichard Henderson }
3322428881deSRichard Henderson 
3323428881deSRichard Henderson static bool do_logic(DisasContext *dc, arg_r_r_ri_cc *a,
3324428881deSRichard Henderson                      void (*func)(TCGv, TCGv, TCGv),
3325428881deSRichard Henderson                      void (*funci)(TCGv, TCGv, target_long))
3326428881deSRichard Henderson {
3327b597eedcSRichard Henderson     return do_arith_int(dc, a, func, funci, a->cc);
3328428881deSRichard Henderson }
3329428881deSRichard Henderson 
3330b597eedcSRichard Henderson TRANS(ADD, ALL, do_arith, a, tcg_gen_add_tl, tcg_gen_addi_tl, gen_op_addcc)
3331b597eedcSRichard Henderson TRANS(SUB, ALL, do_arith, a, tcg_gen_sub_tl, tcg_gen_subi_tl, gen_op_subcc)
3332b597eedcSRichard Henderson TRANS(ADDC, ALL, do_arith, a, gen_op_addc, NULL, gen_op_addccc)
3333b597eedcSRichard Henderson TRANS(SUBC, ALL, do_arith, a, gen_op_subc, NULL, gen_op_subccc)
3334428881deSRichard Henderson 
3335b597eedcSRichard Henderson TRANS(TADDcc, ALL, do_arith, a, NULL, NULL, gen_op_taddcc)
3336b597eedcSRichard Henderson TRANS(TSUBcc, ALL, do_arith, a, NULL, NULL, gen_op_tsubcc)
3337b597eedcSRichard Henderson TRANS(TADDccTV, ALL, do_arith, a, NULL, NULL, gen_op_taddcctv)
3338b597eedcSRichard Henderson TRANS(TSUBccTV, ALL, do_arith, a, NULL, NULL, gen_op_tsubcctv)
3339a9aba13dSRichard Henderson 
3340428881deSRichard Henderson TRANS(AND, ALL, do_logic, a, tcg_gen_and_tl, tcg_gen_andi_tl)
3341428881deSRichard Henderson TRANS(XOR, ALL, do_logic, a, tcg_gen_xor_tl, tcg_gen_xori_tl)
3342428881deSRichard Henderson TRANS(ANDN, ALL, do_logic, a, tcg_gen_andc_tl, NULL)
3343428881deSRichard Henderson TRANS(ORN, ALL, do_logic, a, tcg_gen_orc_tl, NULL)
3344428881deSRichard Henderson TRANS(XORN, ALL, do_logic, a, tcg_gen_eqv_tl, NULL)
3345428881deSRichard Henderson 
3346b597eedcSRichard Henderson TRANS(MULX, 64, do_arith, a, tcg_gen_mul_tl, tcg_gen_muli_tl, NULL)
3347b5372650SRichard Henderson TRANS(UMUL, MUL, do_logic, a, gen_op_umul, NULL)
3348b5372650SRichard Henderson TRANS(SMUL, MUL, do_logic, a, gen_op_smul, NULL)
3349b597eedcSRichard Henderson TRANS(MULScc, ALL, do_arith, a, NULL, NULL, gen_op_mulscc)
335022188d7dSRichard Henderson 
33513a6b8de3SRichard Henderson TRANS(UDIVcc, DIV, do_arith, a, NULL, NULL, gen_op_udivcc)
3352b597eedcSRichard Henderson TRANS(SDIV, DIV, do_arith, a, gen_op_sdiv, NULL, gen_op_sdivcc)
33534ee85ea9SRichard Henderson 
33549c6ec5bcSRichard Henderson /* TODO: Should have feature bit -- comes in with UltraSparc T2. */
3355b597eedcSRichard Henderson TRANS(POPC, 64, do_arith, a, gen_op_popc, NULL, NULL)
33569c6ec5bcSRichard Henderson 
3357428881deSRichard Henderson static bool trans_OR(DisasContext *dc, arg_r_r_ri_cc *a)
3358428881deSRichard Henderson {
3359428881deSRichard Henderson     /* OR with %g0 is the canonical alias for MOV. */
3360428881deSRichard Henderson     if (!a->cc && a->rs1 == 0) {
3361428881deSRichard Henderson         if (a->imm || a->rs2_or_imm == 0) {
3362428881deSRichard Henderson             gen_store_gpr(dc, a->rd, tcg_constant_tl(a->rs2_or_imm));
3363428881deSRichard Henderson         } else if (a->rs2_or_imm & ~0x1f) {
3364428881deSRichard Henderson             /* For simplicity, we under-decoded the rs2 form. */
3365428881deSRichard Henderson             return false;
3366428881deSRichard Henderson         } else {
3367428881deSRichard Henderson             gen_store_gpr(dc, a->rd, cpu_regs[a->rs2_or_imm]);
3368428881deSRichard Henderson         }
3369428881deSRichard Henderson         return advance_pc(dc);
3370428881deSRichard Henderson     }
3371428881deSRichard Henderson     return do_logic(dc, a, tcg_gen_or_tl, tcg_gen_ori_tl);
3372428881deSRichard Henderson }
3373428881deSRichard Henderson 
33743a6b8de3SRichard Henderson static bool trans_UDIV(DisasContext *dc, arg_r_r_ri *a)
33753a6b8de3SRichard Henderson {
33763a6b8de3SRichard Henderson     TCGv_i64 t1, t2;
33773a6b8de3SRichard Henderson     TCGv dst;
33783a6b8de3SRichard Henderson 
33793a6b8de3SRichard Henderson     if (!avail_DIV(dc)) {
33803a6b8de3SRichard Henderson         return false;
33813a6b8de3SRichard Henderson     }
33823a6b8de3SRichard Henderson     /* For simplicity, we under-decoded the rs2 form. */
33833a6b8de3SRichard Henderson     if (!a->imm && a->rs2_or_imm & ~0x1f) {
33843a6b8de3SRichard Henderson         return false;
33853a6b8de3SRichard Henderson     }
33863a6b8de3SRichard Henderson 
33873a6b8de3SRichard Henderson     if (unlikely(a->rs2_or_imm == 0)) {
33883a6b8de3SRichard Henderson         gen_exception(dc, TT_DIV_ZERO);
33893a6b8de3SRichard Henderson         return true;
33903a6b8de3SRichard Henderson     }
33913a6b8de3SRichard Henderson 
33923a6b8de3SRichard Henderson     if (a->imm) {
33933a6b8de3SRichard Henderson         t2 = tcg_constant_i64((uint32_t)a->rs2_or_imm);
33943a6b8de3SRichard Henderson     } else {
33953a6b8de3SRichard Henderson         TCGLabel *lab;
33963a6b8de3SRichard Henderson         TCGv_i32 n2;
33973a6b8de3SRichard Henderson 
33983a6b8de3SRichard Henderson         finishing_insn(dc);
33993a6b8de3SRichard Henderson         flush_cond(dc);
34003a6b8de3SRichard Henderson 
34013a6b8de3SRichard Henderson         n2 = tcg_temp_new_i32();
34023a6b8de3SRichard Henderson         tcg_gen_trunc_tl_i32(n2, cpu_regs[a->rs2_or_imm]);
34033a6b8de3SRichard Henderson 
34043a6b8de3SRichard Henderson         lab = delay_exception(dc, TT_DIV_ZERO);
34053a6b8de3SRichard Henderson         tcg_gen_brcondi_i32(TCG_COND_EQ, n2, 0, lab);
34063a6b8de3SRichard Henderson 
34073a6b8de3SRichard Henderson         t2 = tcg_temp_new_i64();
34083a6b8de3SRichard Henderson #ifdef TARGET_SPARC64
34093a6b8de3SRichard Henderson         tcg_gen_ext32u_i64(t2, cpu_regs[a->rs2_or_imm]);
34103a6b8de3SRichard Henderson #else
34113a6b8de3SRichard Henderson         tcg_gen_extu_i32_i64(t2, cpu_regs[a->rs2_or_imm]);
34123a6b8de3SRichard Henderson #endif
34133a6b8de3SRichard Henderson     }
34143a6b8de3SRichard Henderson 
34153a6b8de3SRichard Henderson     t1 = tcg_temp_new_i64();
34163a6b8de3SRichard Henderson     tcg_gen_concat_tl_i64(t1, gen_load_gpr(dc, a->rs1), cpu_y);
34173a6b8de3SRichard Henderson 
34183a6b8de3SRichard Henderson     tcg_gen_divu_i64(t1, t1, t2);
34193a6b8de3SRichard Henderson     tcg_gen_umin_i64(t1, t1, tcg_constant_i64(UINT32_MAX));
34203a6b8de3SRichard Henderson 
34213a6b8de3SRichard Henderson     dst = gen_dest_gpr(dc, a->rd);
34223a6b8de3SRichard Henderson     tcg_gen_trunc_i64_tl(dst, t1);
34233a6b8de3SRichard Henderson     gen_store_gpr(dc, a->rd, dst);
34243a6b8de3SRichard Henderson     return advance_pc(dc);
34253a6b8de3SRichard Henderson }
34263a6b8de3SRichard Henderson 
3427f3141174SRichard Henderson static bool trans_UDIVX(DisasContext *dc, arg_r_r_ri *a)
3428f3141174SRichard Henderson {
3429f3141174SRichard Henderson     TCGv dst, src1, src2;
3430f3141174SRichard Henderson 
3431f3141174SRichard Henderson     if (!avail_64(dc)) {
3432f3141174SRichard Henderson         return false;
3433f3141174SRichard Henderson     }
3434f3141174SRichard Henderson     /* For simplicity, we under-decoded the rs2 form. */
3435f3141174SRichard Henderson     if (!a->imm && a->rs2_or_imm & ~0x1f) {
3436f3141174SRichard Henderson         return false;
3437f3141174SRichard Henderson     }
3438f3141174SRichard Henderson 
3439f3141174SRichard Henderson     if (unlikely(a->rs2_or_imm == 0)) {
3440f3141174SRichard Henderson         gen_exception(dc, TT_DIV_ZERO);
3441f3141174SRichard Henderson         return true;
3442f3141174SRichard Henderson     }
3443f3141174SRichard Henderson 
3444f3141174SRichard Henderson     if (a->imm) {
3445f3141174SRichard Henderson         src2 = tcg_constant_tl(a->rs2_or_imm);
3446f3141174SRichard Henderson     } else {
3447f3141174SRichard Henderson         TCGLabel *lab;
3448f3141174SRichard Henderson 
3449f3141174SRichard Henderson         finishing_insn(dc);
3450f3141174SRichard Henderson         flush_cond(dc);
3451f3141174SRichard Henderson 
3452f3141174SRichard Henderson         lab = delay_exception(dc, TT_DIV_ZERO);
3453f3141174SRichard Henderson         src2 = cpu_regs[a->rs2_or_imm];
3454f3141174SRichard Henderson         tcg_gen_brcondi_tl(TCG_COND_EQ, src2, 0, lab);
3455f3141174SRichard Henderson     }
3456f3141174SRichard Henderson 
3457f3141174SRichard Henderson     dst = gen_dest_gpr(dc, a->rd);
3458f3141174SRichard Henderson     src1 = gen_load_gpr(dc, a->rs1);
3459f3141174SRichard Henderson 
3460f3141174SRichard Henderson     tcg_gen_divu_tl(dst, src1, src2);
3461f3141174SRichard Henderson     gen_store_gpr(dc, a->rd, dst);
3462f3141174SRichard Henderson     return advance_pc(dc);
3463f3141174SRichard Henderson }
3464f3141174SRichard Henderson 
3465f3141174SRichard Henderson static bool trans_SDIVX(DisasContext *dc, arg_r_r_ri *a)
3466f3141174SRichard Henderson {
3467f3141174SRichard Henderson     TCGv dst, src1, src2;
3468f3141174SRichard Henderson 
3469f3141174SRichard Henderson     if (!avail_64(dc)) {
3470f3141174SRichard Henderson         return false;
3471f3141174SRichard Henderson     }
3472f3141174SRichard Henderson     /* For simplicity, we under-decoded the rs2 form. */
3473f3141174SRichard Henderson     if (!a->imm && a->rs2_or_imm & ~0x1f) {
3474f3141174SRichard Henderson         return false;
3475f3141174SRichard Henderson     }
3476f3141174SRichard Henderson 
3477f3141174SRichard Henderson     if (unlikely(a->rs2_or_imm == 0)) {
3478f3141174SRichard Henderson         gen_exception(dc, TT_DIV_ZERO);
3479f3141174SRichard Henderson         return true;
3480f3141174SRichard Henderson     }
3481f3141174SRichard Henderson 
3482f3141174SRichard Henderson     dst = gen_dest_gpr(dc, a->rd);
3483f3141174SRichard Henderson     src1 = gen_load_gpr(dc, a->rs1);
3484f3141174SRichard Henderson 
3485f3141174SRichard Henderson     if (a->imm) {
3486f3141174SRichard Henderson         if (unlikely(a->rs2_or_imm == -1)) {
3487f3141174SRichard Henderson             tcg_gen_neg_tl(dst, src1);
3488f3141174SRichard Henderson             gen_store_gpr(dc, a->rd, dst);
3489f3141174SRichard Henderson             return advance_pc(dc);
3490f3141174SRichard Henderson         }
3491f3141174SRichard Henderson         src2 = tcg_constant_tl(a->rs2_or_imm);
3492f3141174SRichard Henderson     } else {
3493f3141174SRichard Henderson         TCGLabel *lab;
3494f3141174SRichard Henderson         TCGv t1, t2;
3495f3141174SRichard Henderson 
3496f3141174SRichard Henderson         finishing_insn(dc);
3497f3141174SRichard Henderson         flush_cond(dc);
3498f3141174SRichard Henderson 
3499f3141174SRichard Henderson         lab = delay_exception(dc, TT_DIV_ZERO);
3500f3141174SRichard Henderson         src2 = cpu_regs[a->rs2_or_imm];
3501f3141174SRichard Henderson         tcg_gen_brcondi_tl(TCG_COND_EQ, src2, 0, lab);
3502f3141174SRichard Henderson 
3503f3141174SRichard Henderson         /*
3504f3141174SRichard Henderson          * Need to avoid INT64_MIN / -1, which will trap on x86 host.
3505f3141174SRichard Henderson          * Set SRC2 to 1 as a new divisor, to produce the correct result.
3506f3141174SRichard Henderson          */
3507f3141174SRichard Henderson         t1 = tcg_temp_new();
3508f3141174SRichard Henderson         t2 = tcg_temp_new();
3509f3141174SRichard Henderson         tcg_gen_setcondi_tl(TCG_COND_EQ, t1, src1, (target_long)INT64_MIN);
3510f3141174SRichard Henderson         tcg_gen_setcondi_tl(TCG_COND_EQ, t2, src2, -1);
3511f3141174SRichard Henderson         tcg_gen_and_tl(t1, t1, t2);
3512f3141174SRichard Henderson         tcg_gen_movcond_tl(TCG_COND_NE, t1, t1, tcg_constant_tl(0),
3513f3141174SRichard Henderson                            tcg_constant_tl(1), src2);
3514f3141174SRichard Henderson         src2 = t1;
3515f3141174SRichard Henderson     }
3516f3141174SRichard Henderson 
3517f3141174SRichard Henderson     tcg_gen_div_tl(dst, src1, src2);
3518f3141174SRichard Henderson     gen_store_gpr(dc, a->rd, dst);
3519f3141174SRichard Henderson     return advance_pc(dc);
3520f3141174SRichard Henderson }
3521f3141174SRichard Henderson 
3522b88ce6f2SRichard Henderson static bool gen_edge(DisasContext *dc, arg_r_r_r *a,
3523b88ce6f2SRichard Henderson                      int width, bool cc, bool left)
3524b88ce6f2SRichard Henderson {
3525b88ce6f2SRichard Henderson     TCGv dst, s1, s2, lo1, lo2;
3526b88ce6f2SRichard Henderson     uint64_t amask, tabl, tabr;
3527b88ce6f2SRichard Henderson     int shift, imask, omask;
3528b88ce6f2SRichard Henderson 
3529b88ce6f2SRichard Henderson     dst = gen_dest_gpr(dc, a->rd);
3530b88ce6f2SRichard Henderson     s1 = gen_load_gpr(dc, a->rs1);
3531b88ce6f2SRichard Henderson     s2 = gen_load_gpr(dc, a->rs2);
3532b88ce6f2SRichard Henderson 
3533b88ce6f2SRichard Henderson     if (cc) {
3534f828df74SRichard Henderson         gen_op_subcc(cpu_cc_N, s1, s2);
3535b88ce6f2SRichard Henderson     }
3536b88ce6f2SRichard Henderson 
3537b88ce6f2SRichard Henderson     /*
3538b88ce6f2SRichard Henderson      * Theory of operation: there are two tables, left and right (not to
3539b88ce6f2SRichard Henderson      * be confused with the left and right versions of the opcode).  These
3540b88ce6f2SRichard Henderson      * are indexed by the low 3 bits of the inputs.  To make things "easy",
3541b88ce6f2SRichard Henderson      * these tables are loaded into two constants, TABL and TABR below.
3542b88ce6f2SRichard Henderson      * The operation index = (input & imask) << shift calculates the index
3543b88ce6f2SRichard Henderson      * into the constant, while val = (table >> index) & omask calculates
3544b88ce6f2SRichard Henderson      * the value we're looking for.
3545b88ce6f2SRichard Henderson      */
3546b88ce6f2SRichard Henderson     switch (width) {
3547b88ce6f2SRichard Henderson     case 8:
3548b88ce6f2SRichard Henderson         imask = 0x7;
3549b88ce6f2SRichard Henderson         shift = 3;
3550b88ce6f2SRichard Henderson         omask = 0xff;
3551b88ce6f2SRichard Henderson         if (left) {
3552b88ce6f2SRichard Henderson             tabl = 0x80c0e0f0f8fcfeffULL;
3553b88ce6f2SRichard Henderson             tabr = 0xff7f3f1f0f070301ULL;
3554b88ce6f2SRichard Henderson         } else {
3555b88ce6f2SRichard Henderson             tabl = 0x0103070f1f3f7fffULL;
3556b88ce6f2SRichard Henderson             tabr = 0xfffefcf8f0e0c080ULL;
3557b88ce6f2SRichard Henderson         }
3558b88ce6f2SRichard Henderson         break;
3559b88ce6f2SRichard Henderson     case 16:
3560b88ce6f2SRichard Henderson         imask = 0x6;
3561b88ce6f2SRichard Henderson         shift = 1;
3562b88ce6f2SRichard Henderson         omask = 0xf;
3563b88ce6f2SRichard Henderson         if (left) {
3564b88ce6f2SRichard Henderson             tabl = 0x8cef;
3565b88ce6f2SRichard Henderson             tabr = 0xf731;
3566b88ce6f2SRichard Henderson         } else {
3567b88ce6f2SRichard Henderson             tabl = 0x137f;
3568b88ce6f2SRichard Henderson             tabr = 0xfec8;
3569b88ce6f2SRichard Henderson         }
3570b88ce6f2SRichard Henderson         break;
3571b88ce6f2SRichard Henderson     case 32:
3572b88ce6f2SRichard Henderson         imask = 0x4;
3573b88ce6f2SRichard Henderson         shift = 0;
3574b88ce6f2SRichard Henderson         omask = 0x3;
3575b88ce6f2SRichard Henderson         if (left) {
3576b88ce6f2SRichard Henderson             tabl = (2 << 2) | 3;
3577b88ce6f2SRichard Henderson             tabr = (3 << 2) | 1;
3578b88ce6f2SRichard Henderson         } else {
3579b88ce6f2SRichard Henderson             tabl = (1 << 2) | 3;
3580b88ce6f2SRichard Henderson             tabr = (3 << 2) | 2;
3581b88ce6f2SRichard Henderson         }
3582b88ce6f2SRichard Henderson         break;
3583b88ce6f2SRichard Henderson     default:
3584b88ce6f2SRichard Henderson         abort();
3585b88ce6f2SRichard Henderson     }
3586b88ce6f2SRichard Henderson 
3587b88ce6f2SRichard Henderson     lo1 = tcg_temp_new();
3588b88ce6f2SRichard Henderson     lo2 = tcg_temp_new();
3589b88ce6f2SRichard Henderson     tcg_gen_andi_tl(lo1, s1, imask);
3590b88ce6f2SRichard Henderson     tcg_gen_andi_tl(lo2, s2, imask);
3591b88ce6f2SRichard Henderson     tcg_gen_shli_tl(lo1, lo1, shift);
3592b88ce6f2SRichard Henderson     tcg_gen_shli_tl(lo2, lo2, shift);
3593b88ce6f2SRichard Henderson 
3594b88ce6f2SRichard Henderson     tcg_gen_shr_tl(lo1, tcg_constant_tl(tabl), lo1);
3595b88ce6f2SRichard Henderson     tcg_gen_shr_tl(lo2, tcg_constant_tl(tabr), lo2);
3596b88ce6f2SRichard Henderson     tcg_gen_andi_tl(lo1, lo1, omask);
3597b88ce6f2SRichard Henderson     tcg_gen_andi_tl(lo2, lo2, omask);
3598b88ce6f2SRichard Henderson 
3599b88ce6f2SRichard Henderson     amask = address_mask_i(dc, -8);
3600b88ce6f2SRichard Henderson     tcg_gen_andi_tl(s1, s1, amask);
3601b88ce6f2SRichard Henderson     tcg_gen_andi_tl(s2, s2, amask);
3602b88ce6f2SRichard Henderson 
3603b88ce6f2SRichard Henderson     /* Compute dst = (s1 == s2 ? lo1 : lo1 & lo2). */
3604b88ce6f2SRichard Henderson     tcg_gen_and_tl(lo2, lo2, lo1);
3605b88ce6f2SRichard Henderson     tcg_gen_movcond_tl(TCG_COND_EQ, dst, s1, s2, lo1, lo2);
3606b88ce6f2SRichard Henderson 
3607b88ce6f2SRichard Henderson     gen_store_gpr(dc, a->rd, dst);
3608b88ce6f2SRichard Henderson     return advance_pc(dc);
3609b88ce6f2SRichard Henderson }
3610b88ce6f2SRichard Henderson 
3611b88ce6f2SRichard Henderson TRANS(EDGE8cc, VIS1, gen_edge, a, 8, 1, 0)
3612b88ce6f2SRichard Henderson TRANS(EDGE8Lcc, VIS1, gen_edge, a, 8, 1, 1)
3613b88ce6f2SRichard Henderson TRANS(EDGE16cc, VIS1, gen_edge, a, 16, 1, 0)
3614b88ce6f2SRichard Henderson TRANS(EDGE16Lcc, VIS1, gen_edge, a, 16, 1, 1)
3615b88ce6f2SRichard Henderson TRANS(EDGE32cc, VIS1, gen_edge, a, 32, 1, 0)
3616b88ce6f2SRichard Henderson TRANS(EDGE32Lcc, VIS1, gen_edge, a, 32, 1, 1)
3617b88ce6f2SRichard Henderson 
3618b88ce6f2SRichard Henderson TRANS(EDGE8N, VIS2, gen_edge, a, 8, 0, 0)
3619b88ce6f2SRichard Henderson TRANS(EDGE8LN, VIS2, gen_edge, a, 8, 0, 1)
3620b88ce6f2SRichard Henderson TRANS(EDGE16N, VIS2, gen_edge, a, 16, 0, 0)
3621b88ce6f2SRichard Henderson TRANS(EDGE16LN, VIS2, gen_edge, a, 16, 0, 1)
3622b88ce6f2SRichard Henderson TRANS(EDGE32N, VIS2, gen_edge, a, 32, 0, 0)
3623b88ce6f2SRichard Henderson TRANS(EDGE32LN, VIS2, gen_edge, a, 32, 0, 1)
3624b88ce6f2SRichard Henderson 
362545bfed3bSRichard Henderson static bool do_rrr(DisasContext *dc, arg_r_r_r *a,
362645bfed3bSRichard Henderson                    void (*func)(TCGv, TCGv, TCGv))
362745bfed3bSRichard Henderson {
362845bfed3bSRichard Henderson     TCGv dst = gen_dest_gpr(dc, a->rd);
362945bfed3bSRichard Henderson     TCGv src1 = gen_load_gpr(dc, a->rs1);
363045bfed3bSRichard Henderson     TCGv src2 = gen_load_gpr(dc, a->rs2);
363145bfed3bSRichard Henderson 
363245bfed3bSRichard Henderson     func(dst, src1, src2);
363345bfed3bSRichard Henderson     gen_store_gpr(dc, a->rd, dst);
363445bfed3bSRichard Henderson     return advance_pc(dc);
363545bfed3bSRichard Henderson }
363645bfed3bSRichard Henderson 
363745bfed3bSRichard Henderson TRANS(ARRAY8, VIS1, do_rrr, a, gen_helper_array8)
363845bfed3bSRichard Henderson TRANS(ARRAY16, VIS1, do_rrr, a, gen_op_array16)
363945bfed3bSRichard Henderson TRANS(ARRAY32, VIS1, do_rrr, a, gen_op_array32)
364045bfed3bSRichard Henderson 
36419e20ca94SRichard Henderson static void gen_op_alignaddr(TCGv dst, TCGv s1, TCGv s2)
36429e20ca94SRichard Henderson {
36439e20ca94SRichard Henderson #ifdef TARGET_SPARC64
36449e20ca94SRichard Henderson     TCGv tmp = tcg_temp_new();
36459e20ca94SRichard Henderson 
36469e20ca94SRichard Henderson     tcg_gen_add_tl(tmp, s1, s2);
36479e20ca94SRichard Henderson     tcg_gen_andi_tl(dst, tmp, -8);
36489e20ca94SRichard Henderson     tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, tmp, 0, 3);
36499e20ca94SRichard Henderson #else
36509e20ca94SRichard Henderson     g_assert_not_reached();
36519e20ca94SRichard Henderson #endif
36529e20ca94SRichard Henderson }
36539e20ca94SRichard Henderson 
36549e20ca94SRichard Henderson static void gen_op_alignaddrl(TCGv dst, TCGv s1, TCGv s2)
36559e20ca94SRichard Henderson {
36569e20ca94SRichard Henderson #ifdef TARGET_SPARC64
36579e20ca94SRichard Henderson     TCGv tmp = tcg_temp_new();
36589e20ca94SRichard Henderson 
36599e20ca94SRichard Henderson     tcg_gen_add_tl(tmp, s1, s2);
36609e20ca94SRichard Henderson     tcg_gen_andi_tl(dst, tmp, -8);
36619e20ca94SRichard Henderson     tcg_gen_neg_tl(tmp, tmp);
36629e20ca94SRichard Henderson     tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, tmp, 0, 3);
36639e20ca94SRichard Henderson #else
36649e20ca94SRichard Henderson     g_assert_not_reached();
36659e20ca94SRichard Henderson #endif
36669e20ca94SRichard Henderson }
36679e20ca94SRichard Henderson 
36689e20ca94SRichard Henderson TRANS(ALIGNADDR, VIS1, do_rrr, a, gen_op_alignaddr)
36699e20ca94SRichard Henderson TRANS(ALIGNADDRL, VIS1, do_rrr, a, gen_op_alignaddrl)
36709e20ca94SRichard Henderson 
367139ca3490SRichard Henderson static void gen_op_bmask(TCGv dst, TCGv s1, TCGv s2)
367239ca3490SRichard Henderson {
367339ca3490SRichard Henderson #ifdef TARGET_SPARC64
367439ca3490SRichard Henderson     tcg_gen_add_tl(dst, s1, s2);
367539ca3490SRichard Henderson     tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, dst, 32, 32);
367639ca3490SRichard Henderson #else
367739ca3490SRichard Henderson     g_assert_not_reached();
367839ca3490SRichard Henderson #endif
367939ca3490SRichard Henderson }
368039ca3490SRichard Henderson 
368139ca3490SRichard Henderson TRANS(BMASK, VIS2, do_rrr, a, gen_op_bmask)
368239ca3490SRichard Henderson 
36835fc546eeSRichard Henderson static bool do_shift_r(DisasContext *dc, arg_shiftr *a, bool l, bool u)
36845fc546eeSRichard Henderson {
36855fc546eeSRichard Henderson     TCGv dst, src1, src2;
36865fc546eeSRichard Henderson 
36875fc546eeSRichard Henderson     /* Reject 64-bit shifts for sparc32. */
36885fc546eeSRichard Henderson     if (avail_32(dc) && a->x) {
36895fc546eeSRichard Henderson         return false;
36905fc546eeSRichard Henderson     }
36915fc546eeSRichard Henderson 
36925fc546eeSRichard Henderson     src2 = tcg_temp_new();
36935fc546eeSRichard Henderson     tcg_gen_andi_tl(src2, gen_load_gpr(dc, a->rs2), a->x ? 63 : 31);
36945fc546eeSRichard Henderson     src1 = gen_load_gpr(dc, a->rs1);
36955fc546eeSRichard Henderson     dst = gen_dest_gpr(dc, a->rd);
36965fc546eeSRichard Henderson 
36975fc546eeSRichard Henderson     if (l) {
36985fc546eeSRichard Henderson         tcg_gen_shl_tl(dst, src1, src2);
36995fc546eeSRichard Henderson         if (!a->x) {
37005fc546eeSRichard Henderson             tcg_gen_ext32u_tl(dst, dst);
37015fc546eeSRichard Henderson         }
37025fc546eeSRichard Henderson     } else if (u) {
37035fc546eeSRichard Henderson         if (!a->x) {
37045fc546eeSRichard Henderson             tcg_gen_ext32u_tl(dst, src1);
37055fc546eeSRichard Henderson             src1 = dst;
37065fc546eeSRichard Henderson         }
37075fc546eeSRichard Henderson         tcg_gen_shr_tl(dst, src1, src2);
37085fc546eeSRichard Henderson     } else {
37095fc546eeSRichard Henderson         if (!a->x) {
37105fc546eeSRichard Henderson             tcg_gen_ext32s_tl(dst, src1);
37115fc546eeSRichard Henderson             src1 = dst;
37125fc546eeSRichard Henderson         }
37135fc546eeSRichard Henderson         tcg_gen_sar_tl(dst, src1, src2);
37145fc546eeSRichard Henderson     }
37155fc546eeSRichard Henderson     gen_store_gpr(dc, a->rd, dst);
37165fc546eeSRichard Henderson     return advance_pc(dc);
37175fc546eeSRichard Henderson }
37185fc546eeSRichard Henderson 
37195fc546eeSRichard Henderson TRANS(SLL_r, ALL, do_shift_r, a, true, true)
37205fc546eeSRichard Henderson TRANS(SRL_r, ALL, do_shift_r, a, false, true)
37215fc546eeSRichard Henderson TRANS(SRA_r, ALL, do_shift_r, a, false, false)
37225fc546eeSRichard Henderson 
37235fc546eeSRichard Henderson static bool do_shift_i(DisasContext *dc, arg_shifti *a, bool l, bool u)
37245fc546eeSRichard Henderson {
37255fc546eeSRichard Henderson     TCGv dst, src1;
37265fc546eeSRichard Henderson 
37275fc546eeSRichard Henderson     /* Reject 64-bit shifts for sparc32. */
37285fc546eeSRichard Henderson     if (avail_32(dc) && (a->x || a->i >= 32)) {
37295fc546eeSRichard Henderson         return false;
37305fc546eeSRichard Henderson     }
37315fc546eeSRichard Henderson 
37325fc546eeSRichard Henderson     src1 = gen_load_gpr(dc, a->rs1);
37335fc546eeSRichard Henderson     dst = gen_dest_gpr(dc, a->rd);
37345fc546eeSRichard Henderson 
37355fc546eeSRichard Henderson     if (avail_32(dc) || a->x) {
37365fc546eeSRichard Henderson         if (l) {
37375fc546eeSRichard Henderson             tcg_gen_shli_tl(dst, src1, a->i);
37385fc546eeSRichard Henderson         } else if (u) {
37395fc546eeSRichard Henderson             tcg_gen_shri_tl(dst, src1, a->i);
37405fc546eeSRichard Henderson         } else {
37415fc546eeSRichard Henderson             tcg_gen_sari_tl(dst, src1, a->i);
37425fc546eeSRichard Henderson         }
37435fc546eeSRichard Henderson     } else {
37445fc546eeSRichard Henderson         if (l) {
37455fc546eeSRichard Henderson             tcg_gen_deposit_z_tl(dst, src1, a->i, 32 - a->i);
37465fc546eeSRichard Henderson         } else if (u) {
37475fc546eeSRichard Henderson             tcg_gen_extract_tl(dst, src1, a->i, 32 - a->i);
37485fc546eeSRichard Henderson         } else {
37495fc546eeSRichard Henderson             tcg_gen_sextract_tl(dst, src1, a->i, 32 - a->i);
37505fc546eeSRichard Henderson         }
37515fc546eeSRichard Henderson     }
37525fc546eeSRichard Henderson     gen_store_gpr(dc, a->rd, dst);
37535fc546eeSRichard Henderson     return advance_pc(dc);
37545fc546eeSRichard Henderson }
37555fc546eeSRichard Henderson 
37565fc546eeSRichard Henderson TRANS(SLL_i, ALL, do_shift_i, a, true, true)
37575fc546eeSRichard Henderson TRANS(SRL_i, ALL, do_shift_i, a, false, true)
37585fc546eeSRichard Henderson TRANS(SRA_i, ALL, do_shift_i, a, false, false)
37595fc546eeSRichard Henderson 
3760fb4ed7aaSRichard Henderson static TCGv gen_rs2_or_imm(DisasContext *dc, bool imm, int rs2_or_imm)
3761fb4ed7aaSRichard Henderson {
3762fb4ed7aaSRichard Henderson     /* For simplicity, we under-decoded the rs2 form. */
3763fb4ed7aaSRichard Henderson     if (!imm && rs2_or_imm & ~0x1f) {
3764fb4ed7aaSRichard Henderson         return NULL;
3765fb4ed7aaSRichard Henderson     }
3766fb4ed7aaSRichard Henderson     if (imm || rs2_or_imm == 0) {
3767fb4ed7aaSRichard Henderson         return tcg_constant_tl(rs2_or_imm);
3768fb4ed7aaSRichard Henderson     } else {
3769fb4ed7aaSRichard Henderson         return cpu_regs[rs2_or_imm];
3770fb4ed7aaSRichard Henderson     }
3771fb4ed7aaSRichard Henderson }
3772fb4ed7aaSRichard Henderson 
3773fb4ed7aaSRichard Henderson static bool do_mov_cond(DisasContext *dc, DisasCompare *cmp, int rd, TCGv src2)
3774fb4ed7aaSRichard Henderson {
3775fb4ed7aaSRichard Henderson     TCGv dst = gen_load_gpr(dc, rd);
3776c8507ebfSRichard Henderson     TCGv c2 = tcg_constant_tl(cmp->c2);
3777fb4ed7aaSRichard Henderson 
3778c8507ebfSRichard Henderson     tcg_gen_movcond_tl(cmp->cond, dst, cmp->c1, c2, src2, dst);
3779fb4ed7aaSRichard Henderson     gen_store_gpr(dc, rd, dst);
3780fb4ed7aaSRichard Henderson     return advance_pc(dc);
3781fb4ed7aaSRichard Henderson }
3782fb4ed7aaSRichard Henderson 
3783fb4ed7aaSRichard Henderson static bool trans_MOVcc(DisasContext *dc, arg_MOVcc *a)
3784fb4ed7aaSRichard Henderson {
3785fb4ed7aaSRichard Henderson     TCGv src2 = gen_rs2_or_imm(dc, a->imm, a->rs2_or_imm);
3786fb4ed7aaSRichard Henderson     DisasCompare cmp;
3787fb4ed7aaSRichard Henderson 
3788fb4ed7aaSRichard Henderson     if (src2 == NULL) {
3789fb4ed7aaSRichard Henderson         return false;
3790fb4ed7aaSRichard Henderson     }
3791fb4ed7aaSRichard Henderson     gen_compare(&cmp, a->cc, a->cond, dc);
3792fb4ed7aaSRichard Henderson     return do_mov_cond(dc, &cmp, a->rd, src2);
3793fb4ed7aaSRichard Henderson }
3794fb4ed7aaSRichard Henderson 
3795fb4ed7aaSRichard Henderson static bool trans_MOVfcc(DisasContext *dc, arg_MOVfcc *a)
3796fb4ed7aaSRichard Henderson {
3797fb4ed7aaSRichard Henderson     TCGv src2 = gen_rs2_or_imm(dc, a->imm, a->rs2_or_imm);
3798fb4ed7aaSRichard Henderson     DisasCompare cmp;
3799fb4ed7aaSRichard Henderson 
3800fb4ed7aaSRichard Henderson     if (src2 == NULL) {
3801fb4ed7aaSRichard Henderson         return false;
3802fb4ed7aaSRichard Henderson     }
3803fb4ed7aaSRichard Henderson     gen_fcompare(&cmp, a->cc, a->cond);
3804fb4ed7aaSRichard Henderson     return do_mov_cond(dc, &cmp, a->rd, src2);
3805fb4ed7aaSRichard Henderson }
3806fb4ed7aaSRichard Henderson 
3807fb4ed7aaSRichard Henderson static bool trans_MOVR(DisasContext *dc, arg_MOVR *a)
3808fb4ed7aaSRichard Henderson {
3809fb4ed7aaSRichard Henderson     TCGv src2 = gen_rs2_or_imm(dc, a->imm, a->rs2_or_imm);
3810fb4ed7aaSRichard Henderson     DisasCompare cmp;
3811fb4ed7aaSRichard Henderson 
3812fb4ed7aaSRichard Henderson     if (src2 == NULL) {
3813fb4ed7aaSRichard Henderson         return false;
3814fb4ed7aaSRichard Henderson     }
38152c4f56c9SRichard Henderson     if (!gen_compare_reg(&cmp, a->cond, gen_load_gpr(dc, a->rs1))) {
38162c4f56c9SRichard Henderson         return false;
38172c4f56c9SRichard Henderson     }
3818fb4ed7aaSRichard Henderson     return do_mov_cond(dc, &cmp, a->rd, src2);
3819fb4ed7aaSRichard Henderson }
3820fb4ed7aaSRichard Henderson 
382186b82fe0SRichard Henderson static bool do_add_special(DisasContext *dc, arg_r_r_ri *a,
382286b82fe0SRichard Henderson                            bool (*func)(DisasContext *dc, int rd, TCGv src))
382386b82fe0SRichard Henderson {
382486b82fe0SRichard Henderson     TCGv src1, sum;
382586b82fe0SRichard Henderson 
382686b82fe0SRichard Henderson     /* For simplicity, we under-decoded the rs2 form. */
382786b82fe0SRichard Henderson     if (!a->imm && a->rs2_or_imm & ~0x1f) {
382886b82fe0SRichard Henderson         return false;
382986b82fe0SRichard Henderson     }
383086b82fe0SRichard Henderson 
383186b82fe0SRichard Henderson     /*
383286b82fe0SRichard Henderson      * Always load the sum into a new temporary.
383386b82fe0SRichard Henderson      * This is required to capture the value across a window change,
383486b82fe0SRichard Henderson      * e.g. SAVE and RESTORE, and may be optimized away otherwise.
383586b82fe0SRichard Henderson      */
383686b82fe0SRichard Henderson     sum = tcg_temp_new();
383786b82fe0SRichard Henderson     src1 = gen_load_gpr(dc, a->rs1);
383886b82fe0SRichard Henderson     if (a->imm || a->rs2_or_imm == 0) {
383986b82fe0SRichard Henderson         tcg_gen_addi_tl(sum, src1, a->rs2_or_imm);
384086b82fe0SRichard Henderson     } else {
384186b82fe0SRichard Henderson         tcg_gen_add_tl(sum, src1, cpu_regs[a->rs2_or_imm]);
384286b82fe0SRichard Henderson     }
384386b82fe0SRichard Henderson     return func(dc, a->rd, sum);
384486b82fe0SRichard Henderson }
384586b82fe0SRichard Henderson 
384686b82fe0SRichard Henderson static bool do_jmpl(DisasContext *dc, int rd, TCGv src)
384786b82fe0SRichard Henderson {
384886b82fe0SRichard Henderson     /*
384986b82fe0SRichard Henderson      * Preserve pc across advance, so that we can delay
385086b82fe0SRichard Henderson      * the writeback to rd until after src is consumed.
385186b82fe0SRichard Henderson      */
385286b82fe0SRichard Henderson     target_ulong cur_pc = dc->pc;
385386b82fe0SRichard Henderson 
385486b82fe0SRichard Henderson     gen_check_align(dc, src, 3);
385586b82fe0SRichard Henderson 
385686b82fe0SRichard Henderson     gen_mov_pc_npc(dc);
385786b82fe0SRichard Henderson     tcg_gen_mov_tl(cpu_npc, src);
385886b82fe0SRichard Henderson     gen_address_mask(dc, cpu_npc);
385986b82fe0SRichard Henderson     gen_store_gpr(dc, rd, tcg_constant_tl(cur_pc));
386086b82fe0SRichard Henderson 
386186b82fe0SRichard Henderson     dc->npc = DYNAMIC_PC_LOOKUP;
386286b82fe0SRichard Henderson     return true;
386386b82fe0SRichard Henderson }
386486b82fe0SRichard Henderson 
386586b82fe0SRichard Henderson TRANS(JMPL, ALL, do_add_special, a, do_jmpl)
386686b82fe0SRichard Henderson 
386786b82fe0SRichard Henderson static bool do_rett(DisasContext *dc, int rd, TCGv src)
386886b82fe0SRichard Henderson {
386986b82fe0SRichard Henderson     if (!supervisor(dc)) {
387086b82fe0SRichard Henderson         return raise_priv(dc);
387186b82fe0SRichard Henderson     }
387286b82fe0SRichard Henderson 
387386b82fe0SRichard Henderson     gen_check_align(dc, src, 3);
387486b82fe0SRichard Henderson 
387586b82fe0SRichard Henderson     gen_mov_pc_npc(dc);
387686b82fe0SRichard Henderson     tcg_gen_mov_tl(cpu_npc, src);
387786b82fe0SRichard Henderson     gen_helper_rett(tcg_env);
387886b82fe0SRichard Henderson 
387986b82fe0SRichard Henderson     dc->npc = DYNAMIC_PC;
388086b82fe0SRichard Henderson     return true;
388186b82fe0SRichard Henderson }
388286b82fe0SRichard Henderson 
388386b82fe0SRichard Henderson TRANS(RETT, 32, do_add_special, a, do_rett)
388486b82fe0SRichard Henderson 
388586b82fe0SRichard Henderson static bool do_return(DisasContext *dc, int rd, TCGv src)
388686b82fe0SRichard Henderson {
388786b82fe0SRichard Henderson     gen_check_align(dc, src, 3);
38880dfae4f9SRichard Henderson     gen_helper_restore(tcg_env);
388986b82fe0SRichard Henderson 
389086b82fe0SRichard Henderson     gen_mov_pc_npc(dc);
389186b82fe0SRichard Henderson     tcg_gen_mov_tl(cpu_npc, src);
389286b82fe0SRichard Henderson     gen_address_mask(dc, cpu_npc);
389386b82fe0SRichard Henderson 
389486b82fe0SRichard Henderson     dc->npc = DYNAMIC_PC_LOOKUP;
389586b82fe0SRichard Henderson     return true;
389686b82fe0SRichard Henderson }
389786b82fe0SRichard Henderson 
389886b82fe0SRichard Henderson TRANS(RETURN, 64, do_add_special, a, do_return)
389986b82fe0SRichard Henderson 
3900d3825800SRichard Henderson static bool do_save(DisasContext *dc, int rd, TCGv src)
3901d3825800SRichard Henderson {
3902d3825800SRichard Henderson     gen_helper_save(tcg_env);
3903d3825800SRichard Henderson     gen_store_gpr(dc, rd, src);
3904d3825800SRichard Henderson     return advance_pc(dc);
3905d3825800SRichard Henderson }
3906d3825800SRichard Henderson 
3907d3825800SRichard Henderson TRANS(SAVE, ALL, do_add_special, a, do_save)
3908d3825800SRichard Henderson 
3909d3825800SRichard Henderson static bool do_restore(DisasContext *dc, int rd, TCGv src)
3910d3825800SRichard Henderson {
3911d3825800SRichard Henderson     gen_helper_restore(tcg_env);
3912d3825800SRichard Henderson     gen_store_gpr(dc, rd, src);
3913d3825800SRichard Henderson     return advance_pc(dc);
3914d3825800SRichard Henderson }
3915d3825800SRichard Henderson 
3916d3825800SRichard Henderson TRANS(RESTORE, ALL, do_add_special, a, do_restore)
3917d3825800SRichard Henderson 
39188f75b8a4SRichard Henderson static bool do_done_retry(DisasContext *dc, bool done)
39198f75b8a4SRichard Henderson {
39208f75b8a4SRichard Henderson     if (!supervisor(dc)) {
39218f75b8a4SRichard Henderson         return raise_priv(dc);
39228f75b8a4SRichard Henderson     }
39238f75b8a4SRichard Henderson     dc->npc = DYNAMIC_PC;
39248f75b8a4SRichard Henderson     dc->pc = DYNAMIC_PC;
39258f75b8a4SRichard Henderson     translator_io_start(&dc->base);
39268f75b8a4SRichard Henderson     if (done) {
39278f75b8a4SRichard Henderson         gen_helper_done(tcg_env);
39288f75b8a4SRichard Henderson     } else {
39298f75b8a4SRichard Henderson         gen_helper_retry(tcg_env);
39308f75b8a4SRichard Henderson     }
39318f75b8a4SRichard Henderson     return true;
39328f75b8a4SRichard Henderson }
39338f75b8a4SRichard Henderson 
39348f75b8a4SRichard Henderson TRANS(DONE, 64, do_done_retry, true)
39358f75b8a4SRichard Henderson TRANS(RETRY, 64, do_done_retry, false)
39368f75b8a4SRichard Henderson 
39370880d20bSRichard Henderson /*
39380880d20bSRichard Henderson  * Major opcode 11 -- load and store instructions
39390880d20bSRichard Henderson  */
39400880d20bSRichard Henderson 
39410880d20bSRichard Henderson static TCGv gen_ldst_addr(DisasContext *dc, int rs1, bool imm, int rs2_or_imm)
39420880d20bSRichard Henderson {
39430880d20bSRichard Henderson     TCGv addr, tmp = NULL;
39440880d20bSRichard Henderson 
39450880d20bSRichard Henderson     /* For simplicity, we under-decoded the rs2 form. */
39460880d20bSRichard Henderson     if (!imm && rs2_or_imm & ~0x1f) {
39470880d20bSRichard Henderson         return NULL;
39480880d20bSRichard Henderson     }
39490880d20bSRichard Henderson 
39500880d20bSRichard Henderson     addr = gen_load_gpr(dc, rs1);
39510880d20bSRichard Henderson     if (rs2_or_imm) {
39520880d20bSRichard Henderson         tmp = tcg_temp_new();
39530880d20bSRichard Henderson         if (imm) {
39540880d20bSRichard Henderson             tcg_gen_addi_tl(tmp, addr, rs2_or_imm);
39550880d20bSRichard Henderson         } else {
39560880d20bSRichard Henderson             tcg_gen_add_tl(tmp, addr, cpu_regs[rs2_or_imm]);
39570880d20bSRichard Henderson         }
39580880d20bSRichard Henderson         addr = tmp;
39590880d20bSRichard Henderson     }
39600880d20bSRichard Henderson     if (AM_CHECK(dc)) {
39610880d20bSRichard Henderson         if (!tmp) {
39620880d20bSRichard Henderson             tmp = tcg_temp_new();
39630880d20bSRichard Henderson         }
39640880d20bSRichard Henderson         tcg_gen_ext32u_tl(tmp, addr);
39650880d20bSRichard Henderson         addr = tmp;
39660880d20bSRichard Henderson     }
39670880d20bSRichard Henderson     return addr;
39680880d20bSRichard Henderson }
39690880d20bSRichard Henderson 
39700880d20bSRichard Henderson static bool do_ld_gpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp mop)
39710880d20bSRichard Henderson {
39720880d20bSRichard Henderson     TCGv reg, addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
39730880d20bSRichard Henderson     DisasASI da;
39740880d20bSRichard Henderson 
39750880d20bSRichard Henderson     if (addr == NULL) {
39760880d20bSRichard Henderson         return false;
39770880d20bSRichard Henderson     }
39780880d20bSRichard Henderson     da = resolve_asi(dc, a->asi, mop);
39790880d20bSRichard Henderson 
39800880d20bSRichard Henderson     reg = gen_dest_gpr(dc, a->rd);
398142071fc1SRichard Henderson     gen_ld_asi(dc, &da, reg, addr);
39820880d20bSRichard Henderson     gen_store_gpr(dc, a->rd, reg);
39830880d20bSRichard Henderson     return advance_pc(dc);
39840880d20bSRichard Henderson }
39850880d20bSRichard Henderson 
39860880d20bSRichard Henderson TRANS(LDUW, ALL, do_ld_gpr, a, MO_TEUL)
39870880d20bSRichard Henderson TRANS(LDUB, ALL, do_ld_gpr, a, MO_UB)
39880880d20bSRichard Henderson TRANS(LDUH, ALL, do_ld_gpr, a, MO_TEUW)
39890880d20bSRichard Henderson TRANS(LDSB, ALL, do_ld_gpr, a, MO_SB)
39900880d20bSRichard Henderson TRANS(LDSH, ALL, do_ld_gpr, a, MO_TESW)
39910880d20bSRichard Henderson TRANS(LDSW, 64, do_ld_gpr, a, MO_TESL)
39920880d20bSRichard Henderson TRANS(LDX, 64, do_ld_gpr, a, MO_TEUQ)
39930880d20bSRichard Henderson 
39940880d20bSRichard Henderson static bool do_st_gpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp mop)
39950880d20bSRichard Henderson {
39960880d20bSRichard Henderson     TCGv reg, addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
39970880d20bSRichard Henderson     DisasASI da;
39980880d20bSRichard Henderson 
39990880d20bSRichard Henderson     if (addr == NULL) {
40000880d20bSRichard Henderson         return false;
40010880d20bSRichard Henderson     }
40020880d20bSRichard Henderson     da = resolve_asi(dc, a->asi, mop);
40030880d20bSRichard Henderson 
40040880d20bSRichard Henderson     reg = gen_load_gpr(dc, a->rd);
400542071fc1SRichard Henderson     gen_st_asi(dc, &da, reg, addr);
40060880d20bSRichard Henderson     return advance_pc(dc);
40070880d20bSRichard Henderson }
40080880d20bSRichard Henderson 
40090880d20bSRichard Henderson TRANS(STW, ALL, do_st_gpr, a, MO_TEUL)
40100880d20bSRichard Henderson TRANS(STB, ALL, do_st_gpr, a, MO_UB)
40110880d20bSRichard Henderson TRANS(STH, ALL, do_st_gpr, a, MO_TEUW)
40120880d20bSRichard Henderson TRANS(STX, 64, do_st_gpr, a, MO_TEUQ)
40130880d20bSRichard Henderson 
40140880d20bSRichard Henderson static bool trans_LDD(DisasContext *dc, arg_r_r_ri_asi *a)
40150880d20bSRichard Henderson {
40160880d20bSRichard Henderson     TCGv addr;
40170880d20bSRichard Henderson     DisasASI da;
40180880d20bSRichard Henderson 
40190880d20bSRichard Henderson     if (a->rd & 1) {
40200880d20bSRichard Henderson         return false;
40210880d20bSRichard Henderson     }
40220880d20bSRichard Henderson     addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
40230880d20bSRichard Henderson     if (addr == NULL) {
40240880d20bSRichard Henderson         return false;
40250880d20bSRichard Henderson     }
40260880d20bSRichard Henderson     da = resolve_asi(dc, a->asi, MO_TEUQ);
402742071fc1SRichard Henderson     gen_ldda_asi(dc, &da, addr, a->rd);
40280880d20bSRichard Henderson     return advance_pc(dc);
40290880d20bSRichard Henderson }
40300880d20bSRichard Henderson 
40310880d20bSRichard Henderson static bool trans_STD(DisasContext *dc, arg_r_r_ri_asi *a)
40320880d20bSRichard Henderson {
40330880d20bSRichard Henderson     TCGv addr;
40340880d20bSRichard Henderson     DisasASI da;
40350880d20bSRichard Henderson 
40360880d20bSRichard Henderson     if (a->rd & 1) {
40370880d20bSRichard Henderson         return false;
40380880d20bSRichard Henderson     }
40390880d20bSRichard Henderson     addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
40400880d20bSRichard Henderson     if (addr == NULL) {
40410880d20bSRichard Henderson         return false;
40420880d20bSRichard Henderson     }
40430880d20bSRichard Henderson     da = resolve_asi(dc, a->asi, MO_TEUQ);
404442071fc1SRichard Henderson     gen_stda_asi(dc, &da, addr, a->rd);
40450880d20bSRichard Henderson     return advance_pc(dc);
40460880d20bSRichard Henderson }
40470880d20bSRichard Henderson 
4048cf07cd1eSRichard Henderson static bool trans_LDSTUB(DisasContext *dc, arg_r_r_ri_asi *a)
4049cf07cd1eSRichard Henderson {
4050cf07cd1eSRichard Henderson     TCGv addr, reg;
4051cf07cd1eSRichard Henderson     DisasASI da;
4052cf07cd1eSRichard Henderson 
4053cf07cd1eSRichard Henderson     addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
4054cf07cd1eSRichard Henderson     if (addr == NULL) {
4055cf07cd1eSRichard Henderson         return false;
4056cf07cd1eSRichard Henderson     }
4057cf07cd1eSRichard Henderson     da = resolve_asi(dc, a->asi, MO_UB);
4058cf07cd1eSRichard Henderson 
4059cf07cd1eSRichard Henderson     reg = gen_dest_gpr(dc, a->rd);
4060cf07cd1eSRichard Henderson     gen_ldstub_asi(dc, &da, reg, addr);
4061cf07cd1eSRichard Henderson     gen_store_gpr(dc, a->rd, reg);
4062cf07cd1eSRichard Henderson     return advance_pc(dc);
4063cf07cd1eSRichard Henderson }
4064cf07cd1eSRichard Henderson 
4065dca544b9SRichard Henderson static bool trans_SWAP(DisasContext *dc, arg_r_r_ri_asi *a)
4066dca544b9SRichard Henderson {
4067dca544b9SRichard Henderson     TCGv addr, dst, src;
4068dca544b9SRichard Henderson     DisasASI da;
4069dca544b9SRichard Henderson 
4070dca544b9SRichard Henderson     addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
4071dca544b9SRichard Henderson     if (addr == NULL) {
4072dca544b9SRichard Henderson         return false;
4073dca544b9SRichard Henderson     }
4074dca544b9SRichard Henderson     da = resolve_asi(dc, a->asi, MO_TEUL);
4075dca544b9SRichard Henderson 
4076dca544b9SRichard Henderson     dst = gen_dest_gpr(dc, a->rd);
4077dca544b9SRichard Henderson     src = gen_load_gpr(dc, a->rd);
4078dca544b9SRichard Henderson     gen_swap_asi(dc, &da, dst, src, addr);
4079dca544b9SRichard Henderson     gen_store_gpr(dc, a->rd, dst);
4080dca544b9SRichard Henderson     return advance_pc(dc);
4081dca544b9SRichard Henderson }
4082dca544b9SRichard Henderson 
4083d0a11d25SRichard Henderson static bool do_casa(DisasContext *dc, arg_r_r_ri_asi *a, MemOp mop)
4084d0a11d25SRichard Henderson {
4085d0a11d25SRichard Henderson     TCGv addr, o, n, c;
4086d0a11d25SRichard Henderson     DisasASI da;
4087d0a11d25SRichard Henderson 
4088d0a11d25SRichard Henderson     addr = gen_ldst_addr(dc, a->rs1, true, 0);
4089d0a11d25SRichard Henderson     if (addr == NULL) {
4090d0a11d25SRichard Henderson         return false;
4091d0a11d25SRichard Henderson     }
4092d0a11d25SRichard Henderson     da = resolve_asi(dc, a->asi, mop);
4093d0a11d25SRichard Henderson 
4094d0a11d25SRichard Henderson     o = gen_dest_gpr(dc, a->rd);
4095d0a11d25SRichard Henderson     n = gen_load_gpr(dc, a->rd);
4096d0a11d25SRichard Henderson     c = gen_load_gpr(dc, a->rs2_or_imm);
4097d0a11d25SRichard Henderson     gen_cas_asi(dc, &da, o, n, c, addr);
4098d0a11d25SRichard Henderson     gen_store_gpr(dc, a->rd, o);
4099d0a11d25SRichard Henderson     return advance_pc(dc);
4100d0a11d25SRichard Henderson }
4101d0a11d25SRichard Henderson 
4102d0a11d25SRichard Henderson TRANS(CASA, CASA, do_casa, a, MO_TEUL)
4103d0a11d25SRichard Henderson TRANS(CASXA, 64, do_casa, a, MO_TEUQ)
4104d0a11d25SRichard Henderson 
410506c060d9SRichard Henderson static bool do_ld_fpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp sz)
410606c060d9SRichard Henderson {
410706c060d9SRichard Henderson     TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
410806c060d9SRichard Henderson     DisasASI da;
410906c060d9SRichard Henderson 
411006c060d9SRichard Henderson     if (addr == NULL) {
411106c060d9SRichard Henderson         return false;
411206c060d9SRichard Henderson     }
411306c060d9SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
411406c060d9SRichard Henderson         return true;
411506c060d9SRichard Henderson     }
411606c060d9SRichard Henderson     if (sz == MO_128 && gen_trap_float128(dc)) {
411706c060d9SRichard Henderson         return true;
411806c060d9SRichard Henderson     }
411906c060d9SRichard Henderson     da = resolve_asi(dc, a->asi, MO_TE | sz);
4120287b1152SRichard Henderson     gen_ldf_asi(dc, &da, sz, addr, a->rd);
412106c060d9SRichard Henderson     gen_update_fprs_dirty(dc, a->rd);
412206c060d9SRichard Henderson     return advance_pc(dc);
412306c060d9SRichard Henderson }
412406c060d9SRichard Henderson 
412506c060d9SRichard Henderson TRANS(LDF, ALL, do_ld_fpr, a, MO_32)
412606c060d9SRichard Henderson TRANS(LDDF, ALL, do_ld_fpr, a, MO_64)
412706c060d9SRichard Henderson TRANS(LDQF, ALL, do_ld_fpr, a, MO_128)
412806c060d9SRichard Henderson 
4129287b1152SRichard Henderson TRANS(LDFA, 64, do_ld_fpr, a, MO_32)
4130287b1152SRichard Henderson TRANS(LDDFA, 64, do_ld_fpr, a, MO_64)
4131287b1152SRichard Henderson TRANS(LDQFA, 64, do_ld_fpr, a, MO_128)
4132287b1152SRichard Henderson 
413306c060d9SRichard Henderson static bool do_st_fpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp sz)
413406c060d9SRichard Henderson {
413506c060d9SRichard Henderson     TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
413606c060d9SRichard Henderson     DisasASI da;
413706c060d9SRichard Henderson 
413806c060d9SRichard Henderson     if (addr == NULL) {
413906c060d9SRichard Henderson         return false;
414006c060d9SRichard Henderson     }
414106c060d9SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
414206c060d9SRichard Henderson         return true;
414306c060d9SRichard Henderson     }
414406c060d9SRichard Henderson     if (sz == MO_128 && gen_trap_float128(dc)) {
414506c060d9SRichard Henderson         return true;
414606c060d9SRichard Henderson     }
414706c060d9SRichard Henderson     da = resolve_asi(dc, a->asi, MO_TE | sz);
4148287b1152SRichard Henderson     gen_stf_asi(dc, &da, sz, addr, a->rd);
414906c060d9SRichard Henderson     return advance_pc(dc);
415006c060d9SRichard Henderson }
415106c060d9SRichard Henderson 
415206c060d9SRichard Henderson TRANS(STF, ALL, do_st_fpr, a, MO_32)
415306c060d9SRichard Henderson TRANS(STDF, ALL, do_st_fpr, a, MO_64)
415406c060d9SRichard Henderson TRANS(STQF, ALL, do_st_fpr, a, MO_128)
415506c060d9SRichard Henderson 
4156287b1152SRichard Henderson TRANS(STFA, 64, do_st_fpr, a, MO_32)
4157287b1152SRichard Henderson TRANS(STDFA, 64, do_st_fpr, a, MO_64)
4158287b1152SRichard Henderson TRANS(STQFA, 64, do_st_fpr, a, MO_128)
4159287b1152SRichard Henderson 
416006c060d9SRichard Henderson static bool trans_STDFQ(DisasContext *dc, arg_STDFQ *a)
416106c060d9SRichard Henderson {
416206c060d9SRichard Henderson     if (!avail_32(dc)) {
416306c060d9SRichard Henderson         return false;
416406c060d9SRichard Henderson     }
416506c060d9SRichard Henderson     if (!supervisor(dc)) {
416606c060d9SRichard Henderson         return raise_priv(dc);
416706c060d9SRichard Henderson     }
416806c060d9SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
416906c060d9SRichard Henderson         return true;
417006c060d9SRichard Henderson     }
417106c060d9SRichard Henderson     gen_op_fpexception_im(dc, FSR_FTT_SEQ_ERROR);
417206c060d9SRichard Henderson     return true;
417306c060d9SRichard Henderson }
417406c060d9SRichard Henderson 
4175d8c5b92fSRichard Henderson static bool trans_LDFSR(DisasContext *dc, arg_r_r_ri *a)
41763d3c0673SRichard Henderson {
41773590f01eSRichard Henderson     TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
4178d8c5b92fSRichard Henderson     TCGv_i32 tmp;
41793590f01eSRichard Henderson 
41803d3c0673SRichard Henderson     if (addr == NULL) {
41813d3c0673SRichard Henderson         return false;
41823d3c0673SRichard Henderson     }
41833d3c0673SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
41843d3c0673SRichard Henderson         return true;
41853d3c0673SRichard Henderson     }
4186d8c5b92fSRichard Henderson 
4187d8c5b92fSRichard Henderson     tmp = tcg_temp_new_i32();
4188d8c5b92fSRichard Henderson     tcg_gen_qemu_ld_i32(tmp, addr, dc->mem_idx, MO_TEUL | MO_ALIGN);
4189d8c5b92fSRichard Henderson 
4190d8c5b92fSRichard Henderson     tcg_gen_extract_i32(cpu_fcc[0], tmp, FSR_FCC0_SHIFT, 2);
4191d8c5b92fSRichard Henderson     /* LDFSR does not change FCC[1-3]. */
4192d8c5b92fSRichard Henderson 
4193d8c5b92fSRichard Henderson     gen_helper_set_fsr_nofcc_noftt(tcg_env, tmp);
41943d3c0673SRichard Henderson     return advance_pc(dc);
41953d3c0673SRichard Henderson }
41963d3c0673SRichard Henderson 
4197d8c5b92fSRichard Henderson static bool trans_LDXFSR(DisasContext *dc, arg_r_r_ri *a)
4198d8c5b92fSRichard Henderson {
4199d8c5b92fSRichard Henderson #ifdef TARGET_SPARC64
4200d8c5b92fSRichard Henderson     TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
4201d8c5b92fSRichard Henderson     TCGv_i64 t64;
4202d8c5b92fSRichard Henderson     TCGv_i32 lo, hi;
4203d8c5b92fSRichard Henderson 
4204d8c5b92fSRichard Henderson     if (addr == NULL) {
4205d8c5b92fSRichard Henderson         return false;
4206d8c5b92fSRichard Henderson     }
4207d8c5b92fSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4208d8c5b92fSRichard Henderson         return true;
4209d8c5b92fSRichard Henderson     }
4210d8c5b92fSRichard Henderson 
4211d8c5b92fSRichard Henderson     t64 = tcg_temp_new_i64();
4212d8c5b92fSRichard Henderson     tcg_gen_qemu_ld_i64(t64, addr, dc->mem_idx, MO_TEUQ | MO_ALIGN);
4213d8c5b92fSRichard Henderson 
4214d8c5b92fSRichard Henderson     lo = tcg_temp_new_i32();
4215d8c5b92fSRichard Henderson     hi = cpu_fcc[3];
4216d8c5b92fSRichard Henderson     tcg_gen_extr_i64_i32(lo, hi, t64);
4217d8c5b92fSRichard Henderson     tcg_gen_extract_i32(cpu_fcc[0], lo, FSR_FCC0_SHIFT, 2);
4218d8c5b92fSRichard Henderson     tcg_gen_extract_i32(cpu_fcc[1], hi, FSR_FCC1_SHIFT - 32, 2);
4219d8c5b92fSRichard Henderson     tcg_gen_extract_i32(cpu_fcc[2], hi, FSR_FCC2_SHIFT - 32, 2);
4220d8c5b92fSRichard Henderson     tcg_gen_extract_i32(cpu_fcc[3], hi, FSR_FCC3_SHIFT - 32, 2);
4221d8c5b92fSRichard Henderson 
4222d8c5b92fSRichard Henderson     gen_helper_set_fsr_nofcc_noftt(tcg_env, lo);
4223d8c5b92fSRichard Henderson     return advance_pc(dc);
4224d8c5b92fSRichard Henderson #else
4225d8c5b92fSRichard Henderson     return false;
4226d8c5b92fSRichard Henderson #endif
4227d8c5b92fSRichard Henderson }
42283d3c0673SRichard Henderson 
42293d3c0673SRichard Henderson static bool do_stfsr(DisasContext *dc, arg_r_r_ri *a, MemOp mop)
42303d3c0673SRichard Henderson {
42313d3c0673SRichard Henderson     TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
42321ccd6e13SRichard Henderson     TCGv fsr;
42331ccd6e13SRichard Henderson 
42343d3c0673SRichard Henderson     if (addr == NULL) {
42353d3c0673SRichard Henderson         return false;
42363d3c0673SRichard Henderson     }
42373d3c0673SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
42383d3c0673SRichard Henderson         return true;
42393d3c0673SRichard Henderson     }
42401ccd6e13SRichard Henderson 
42411ccd6e13SRichard Henderson     fsr = tcg_temp_new();
42421ccd6e13SRichard Henderson     gen_helper_get_fsr(fsr, tcg_env);
42431ccd6e13SRichard Henderson     tcg_gen_qemu_st_tl(fsr, addr, dc->mem_idx, mop | MO_ALIGN);
42443d3c0673SRichard Henderson     return advance_pc(dc);
42453d3c0673SRichard Henderson }
42463d3c0673SRichard Henderson 
42473d3c0673SRichard Henderson TRANS(STFSR, ALL, do_stfsr, a, MO_TEUL)
42483d3c0673SRichard Henderson TRANS(STXFSR, 64, do_stfsr, a, MO_TEUQ)
42493d3c0673SRichard Henderson 
42503a38260eSRichard Henderson static bool do_fc(DisasContext *dc, int rd, bool c)
42513a38260eSRichard Henderson {
42523a38260eSRichard Henderson     uint64_t mask;
42533a38260eSRichard Henderson 
42543a38260eSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
42553a38260eSRichard Henderson         return true;
42563a38260eSRichard Henderson     }
42573a38260eSRichard Henderson 
42583a38260eSRichard Henderson     if (rd & 1) {
42593a38260eSRichard Henderson         mask = MAKE_64BIT_MASK(0, 32);
42603a38260eSRichard Henderson     } else {
42613a38260eSRichard Henderson         mask = MAKE_64BIT_MASK(32, 32);
42623a38260eSRichard Henderson     }
42633a38260eSRichard Henderson     if (c) {
42643a38260eSRichard Henderson         tcg_gen_ori_i64(cpu_fpr[rd / 2], cpu_fpr[rd / 2], mask);
42653a38260eSRichard Henderson     } else {
42663a38260eSRichard Henderson         tcg_gen_andi_i64(cpu_fpr[rd / 2], cpu_fpr[rd / 2], ~mask);
42673a38260eSRichard Henderson     }
42683a38260eSRichard Henderson     gen_update_fprs_dirty(dc, rd);
42693a38260eSRichard Henderson     return advance_pc(dc);
42703a38260eSRichard Henderson }
42713a38260eSRichard Henderson 
42723a38260eSRichard Henderson TRANS(FZEROs, VIS1, do_fc, a->rd, 0)
42733a38260eSRichard Henderson TRANS(FONEs, VIS1, do_fc, a->rd, 1)
42743a38260eSRichard Henderson 
42753a38260eSRichard Henderson static bool do_dc(DisasContext *dc, int rd, int64_t c)
42763a38260eSRichard Henderson {
42773a38260eSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
42783a38260eSRichard Henderson         return true;
42793a38260eSRichard Henderson     }
42803a38260eSRichard Henderson 
42813a38260eSRichard Henderson     tcg_gen_movi_i64(cpu_fpr[rd / 2], c);
42823a38260eSRichard Henderson     gen_update_fprs_dirty(dc, rd);
42833a38260eSRichard Henderson     return advance_pc(dc);
42843a38260eSRichard Henderson }
42853a38260eSRichard Henderson 
42863a38260eSRichard Henderson TRANS(FZEROd, VIS1, do_dc, a->rd, 0)
42873a38260eSRichard Henderson TRANS(FONEd, VIS1, do_dc, a->rd, -1)
42883a38260eSRichard Henderson 
4289baf3dbf2SRichard Henderson static bool do_ff(DisasContext *dc, arg_r_r *a,
4290baf3dbf2SRichard Henderson                   void (*func)(TCGv_i32, TCGv_i32))
4291baf3dbf2SRichard Henderson {
4292baf3dbf2SRichard Henderson     TCGv_i32 tmp;
4293baf3dbf2SRichard Henderson 
4294baf3dbf2SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4295baf3dbf2SRichard Henderson         return true;
4296baf3dbf2SRichard Henderson     }
4297baf3dbf2SRichard Henderson 
4298baf3dbf2SRichard Henderson     tmp = gen_load_fpr_F(dc, a->rs);
4299baf3dbf2SRichard Henderson     func(tmp, tmp);
4300baf3dbf2SRichard Henderson     gen_store_fpr_F(dc, a->rd, tmp);
4301baf3dbf2SRichard Henderson     return advance_pc(dc);
4302baf3dbf2SRichard Henderson }
4303baf3dbf2SRichard Henderson 
4304baf3dbf2SRichard Henderson TRANS(FMOVs, ALL, do_ff, a, gen_op_fmovs)
4305baf3dbf2SRichard Henderson TRANS(FNEGs, ALL, do_ff, a, gen_op_fnegs)
4306baf3dbf2SRichard Henderson TRANS(FABSs, ALL, do_ff, a, gen_op_fabss)
4307baf3dbf2SRichard Henderson TRANS(FSRCs, VIS1, do_ff, a, tcg_gen_mov_i32)
4308baf3dbf2SRichard Henderson TRANS(FNOTs, VIS1, do_ff, a, tcg_gen_not_i32)
4309baf3dbf2SRichard Henderson 
43102f722641SRichard Henderson static bool do_fd(DisasContext *dc, arg_r_r *a,
43112f722641SRichard Henderson                   void (*func)(TCGv_i32, TCGv_i64))
43122f722641SRichard Henderson {
43132f722641SRichard Henderson     TCGv_i32 dst;
43142f722641SRichard Henderson     TCGv_i64 src;
43152f722641SRichard Henderson 
43162f722641SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
43172f722641SRichard Henderson         return true;
43182f722641SRichard Henderson     }
43192f722641SRichard Henderson 
4320388a6465SRichard Henderson     dst = tcg_temp_new_i32();
43212f722641SRichard Henderson     src = gen_load_fpr_D(dc, a->rs);
43222f722641SRichard Henderson     func(dst, src);
43232f722641SRichard Henderson     gen_store_fpr_F(dc, a->rd, dst);
43242f722641SRichard Henderson     return advance_pc(dc);
43252f722641SRichard Henderson }
43262f722641SRichard Henderson 
43272f722641SRichard Henderson TRANS(FPACK16, VIS1, do_fd, a, gen_op_fpack16)
43282f722641SRichard Henderson TRANS(FPACKFIX, VIS1, do_fd, a, gen_op_fpackfix)
43292f722641SRichard Henderson 
4330119cb94fSRichard Henderson static bool do_env_ff(DisasContext *dc, arg_r_r *a,
4331119cb94fSRichard Henderson                       void (*func)(TCGv_i32, TCGv_env, TCGv_i32))
4332119cb94fSRichard Henderson {
4333119cb94fSRichard Henderson     TCGv_i32 tmp;
4334119cb94fSRichard Henderson 
4335119cb94fSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4336119cb94fSRichard Henderson         return true;
4337119cb94fSRichard Henderson     }
4338119cb94fSRichard Henderson 
4339119cb94fSRichard Henderson     tmp = gen_load_fpr_F(dc, a->rs);
4340119cb94fSRichard Henderson     func(tmp, tcg_env, tmp);
4341119cb94fSRichard Henderson     gen_store_fpr_F(dc, a->rd, tmp);
4342119cb94fSRichard Henderson     return advance_pc(dc);
4343119cb94fSRichard Henderson }
4344119cb94fSRichard Henderson 
4345119cb94fSRichard Henderson TRANS(FSQRTs, ALL, do_env_ff, a, gen_helper_fsqrts)
4346119cb94fSRichard Henderson TRANS(FiTOs, ALL, do_env_ff, a, gen_helper_fitos)
4347119cb94fSRichard Henderson TRANS(FsTOi, ALL, do_env_ff, a, gen_helper_fstoi)
4348119cb94fSRichard Henderson 
43498c94bcd8SRichard Henderson static bool do_env_fd(DisasContext *dc, arg_r_r *a,
43508c94bcd8SRichard Henderson                       void (*func)(TCGv_i32, TCGv_env, TCGv_i64))
43518c94bcd8SRichard Henderson {
43528c94bcd8SRichard Henderson     TCGv_i32 dst;
43538c94bcd8SRichard Henderson     TCGv_i64 src;
43548c94bcd8SRichard Henderson 
43558c94bcd8SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
43568c94bcd8SRichard Henderson         return true;
43578c94bcd8SRichard Henderson     }
43588c94bcd8SRichard Henderson 
4359388a6465SRichard Henderson     dst = tcg_temp_new_i32();
43608c94bcd8SRichard Henderson     src = gen_load_fpr_D(dc, a->rs);
43618c94bcd8SRichard Henderson     func(dst, tcg_env, src);
43628c94bcd8SRichard Henderson     gen_store_fpr_F(dc, a->rd, dst);
43638c94bcd8SRichard Henderson     return advance_pc(dc);
43648c94bcd8SRichard Henderson }
43658c94bcd8SRichard Henderson 
43668c94bcd8SRichard Henderson TRANS(FdTOs, ALL, do_env_fd, a, gen_helper_fdtos)
43678c94bcd8SRichard Henderson TRANS(FdTOi, ALL, do_env_fd, a, gen_helper_fdtoi)
43688c94bcd8SRichard Henderson TRANS(FxTOs, 64, do_env_fd, a, gen_helper_fxtos)
43698c94bcd8SRichard Henderson 
4370c6d83e4fSRichard Henderson static bool do_dd(DisasContext *dc, arg_r_r *a,
4371c6d83e4fSRichard Henderson                   void (*func)(TCGv_i64, TCGv_i64))
4372c6d83e4fSRichard Henderson {
4373c6d83e4fSRichard Henderson     TCGv_i64 dst, src;
4374c6d83e4fSRichard Henderson 
4375c6d83e4fSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4376c6d83e4fSRichard Henderson         return true;
4377c6d83e4fSRichard Henderson     }
4378c6d83e4fSRichard Henderson 
4379c6d83e4fSRichard Henderson     dst = gen_dest_fpr_D(dc, a->rd);
4380c6d83e4fSRichard Henderson     src = gen_load_fpr_D(dc, a->rs);
4381c6d83e4fSRichard Henderson     func(dst, src);
4382c6d83e4fSRichard Henderson     gen_store_fpr_D(dc, a->rd, dst);
4383c6d83e4fSRichard Henderson     return advance_pc(dc);
4384c6d83e4fSRichard Henderson }
4385c6d83e4fSRichard Henderson 
4386c6d83e4fSRichard Henderson TRANS(FMOVd, 64, do_dd, a, gen_op_fmovd)
4387c6d83e4fSRichard Henderson TRANS(FNEGd, 64, do_dd, a, gen_op_fnegd)
4388c6d83e4fSRichard Henderson TRANS(FABSd, 64, do_dd, a, gen_op_fabsd)
4389c6d83e4fSRichard Henderson TRANS(FSRCd, VIS1, do_dd, a, tcg_gen_mov_i64)
4390c6d83e4fSRichard Henderson TRANS(FNOTd, VIS1, do_dd, a, tcg_gen_not_i64)
4391c6d83e4fSRichard Henderson 
43928aa418b3SRichard Henderson static bool do_env_dd(DisasContext *dc, arg_r_r *a,
43938aa418b3SRichard Henderson                       void (*func)(TCGv_i64, TCGv_env, TCGv_i64))
43948aa418b3SRichard Henderson {
43958aa418b3SRichard Henderson     TCGv_i64 dst, src;
43968aa418b3SRichard Henderson 
43978aa418b3SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
43988aa418b3SRichard Henderson         return true;
43998aa418b3SRichard Henderson     }
44008aa418b3SRichard Henderson 
44018aa418b3SRichard Henderson     dst = gen_dest_fpr_D(dc, a->rd);
44028aa418b3SRichard Henderson     src = gen_load_fpr_D(dc, a->rs);
44038aa418b3SRichard Henderson     func(dst, tcg_env, src);
44048aa418b3SRichard Henderson     gen_store_fpr_D(dc, a->rd, dst);
44058aa418b3SRichard Henderson     return advance_pc(dc);
44068aa418b3SRichard Henderson }
44078aa418b3SRichard Henderson 
44088aa418b3SRichard Henderson TRANS(FSQRTd, ALL, do_env_dd, a, gen_helper_fsqrtd)
44098aa418b3SRichard Henderson TRANS(FxTOd, 64, do_env_dd, a, gen_helper_fxtod)
44108aa418b3SRichard Henderson TRANS(FdTOx, 64, do_env_dd, a, gen_helper_fdtox)
44118aa418b3SRichard Henderson 
44127b616f36SRichard Henderson static bool do_df(DisasContext *dc, arg_r_r *a,
44137b616f36SRichard Henderson                   void (*func)(TCGv_i64, TCGv_i32))
44147b616f36SRichard Henderson {
44157b616f36SRichard Henderson     TCGv_i64 dst;
44167b616f36SRichard Henderson     TCGv_i32 src;
44177b616f36SRichard Henderson 
44187b616f36SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
44197b616f36SRichard Henderson         return true;
44207b616f36SRichard Henderson     }
44217b616f36SRichard Henderson 
44227b616f36SRichard Henderson     dst = tcg_temp_new_i64();
44237b616f36SRichard Henderson     src = gen_load_fpr_F(dc, a->rs);
44247b616f36SRichard Henderson     func(dst, src);
44257b616f36SRichard Henderson     gen_store_fpr_D(dc, a->rd, dst);
44267b616f36SRichard Henderson     return advance_pc(dc);
44277b616f36SRichard Henderson }
44287b616f36SRichard Henderson 
44297b616f36SRichard Henderson TRANS(FEXPAND, VIS1, do_df, a, gen_helper_fexpand)
44307b616f36SRichard Henderson 
4431199d43efSRichard Henderson static bool do_env_df(DisasContext *dc, arg_r_r *a,
4432199d43efSRichard Henderson                       void (*func)(TCGv_i64, TCGv_env, TCGv_i32))
4433199d43efSRichard Henderson {
4434199d43efSRichard Henderson     TCGv_i64 dst;
4435199d43efSRichard Henderson     TCGv_i32 src;
4436199d43efSRichard Henderson 
4437199d43efSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4438199d43efSRichard Henderson         return true;
4439199d43efSRichard Henderson     }
4440199d43efSRichard Henderson 
4441199d43efSRichard Henderson     dst = gen_dest_fpr_D(dc, a->rd);
4442199d43efSRichard Henderson     src = gen_load_fpr_F(dc, a->rs);
4443199d43efSRichard Henderson     func(dst, tcg_env, src);
4444199d43efSRichard Henderson     gen_store_fpr_D(dc, a->rd, dst);
4445199d43efSRichard Henderson     return advance_pc(dc);
4446199d43efSRichard Henderson }
4447199d43efSRichard Henderson 
4448199d43efSRichard Henderson TRANS(FiTOd, ALL, do_env_df, a, gen_helper_fitod)
4449199d43efSRichard Henderson TRANS(FsTOd, ALL, do_env_df, a, gen_helper_fstod)
4450199d43efSRichard Henderson TRANS(FsTOx, 64, do_env_df, a, gen_helper_fstox)
4451199d43efSRichard Henderson 
4452daf457d4SRichard Henderson static bool do_qq(DisasContext *dc, arg_r_r *a,
4453daf457d4SRichard Henderson                   void (*func)(TCGv_i128, TCGv_i128))
4454f4e18df5SRichard Henderson {
445533ec4245SRichard Henderson     TCGv_i128 t;
4456f4e18df5SRichard Henderson 
4457f4e18df5SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4458f4e18df5SRichard Henderson         return true;
4459f4e18df5SRichard Henderson     }
4460f4e18df5SRichard Henderson     if (gen_trap_float128(dc)) {
4461f4e18df5SRichard Henderson         return true;
4462f4e18df5SRichard Henderson     }
4463f4e18df5SRichard Henderson 
4464f4e18df5SRichard Henderson     gen_op_clear_ieee_excp_and_FTT();
446533ec4245SRichard Henderson     t = gen_load_fpr_Q(dc, a->rs);
4466daf457d4SRichard Henderson     func(t, t);
446733ec4245SRichard Henderson     gen_store_fpr_Q(dc, a->rd, t);
4468f4e18df5SRichard Henderson     return advance_pc(dc);
4469f4e18df5SRichard Henderson }
4470f4e18df5SRichard Henderson 
4471daf457d4SRichard Henderson TRANS(FMOVq, 64, do_qq, a, tcg_gen_mov_i128)
4472daf457d4SRichard Henderson TRANS(FNEGq, 64, do_qq, a, gen_op_fnegq)
4473daf457d4SRichard Henderson TRANS(FABSq, 64, do_qq, a, gen_op_fabsq)
4474f4e18df5SRichard Henderson 
4475c995216bSRichard Henderson static bool do_env_qq(DisasContext *dc, arg_r_r *a,
4476e41716beSRichard Henderson                       void (*func)(TCGv_i128, TCGv_env, TCGv_i128))
4477c995216bSRichard Henderson {
4478e41716beSRichard Henderson     TCGv_i128 t;
4479e41716beSRichard Henderson 
4480c995216bSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4481c995216bSRichard Henderson         return true;
4482c995216bSRichard Henderson     }
4483c995216bSRichard Henderson     if (gen_trap_float128(dc)) {
4484c995216bSRichard Henderson         return true;
4485c995216bSRichard Henderson     }
4486c995216bSRichard Henderson 
4487e41716beSRichard Henderson     t = gen_load_fpr_Q(dc, a->rs);
4488e41716beSRichard Henderson     func(t, tcg_env, t);
4489e41716beSRichard Henderson     gen_store_fpr_Q(dc, a->rd, t);
4490c995216bSRichard Henderson     return advance_pc(dc);
4491c995216bSRichard Henderson }
4492c995216bSRichard Henderson 
4493c995216bSRichard Henderson TRANS(FSQRTq, ALL, do_env_qq, a, gen_helper_fsqrtq)
4494c995216bSRichard Henderson 
4495bd9c5c42SRichard Henderson static bool do_env_fq(DisasContext *dc, arg_r_r *a,
4496d81e3efeSRichard Henderson                       void (*func)(TCGv_i32, TCGv_env, TCGv_i128))
4497bd9c5c42SRichard Henderson {
4498d81e3efeSRichard Henderson     TCGv_i128 src;
4499bd9c5c42SRichard Henderson     TCGv_i32 dst;
4500bd9c5c42SRichard Henderson 
4501bd9c5c42SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4502bd9c5c42SRichard Henderson         return true;
4503bd9c5c42SRichard Henderson     }
4504bd9c5c42SRichard Henderson     if (gen_trap_float128(dc)) {
4505bd9c5c42SRichard Henderson         return true;
4506bd9c5c42SRichard Henderson     }
4507bd9c5c42SRichard Henderson 
4508d81e3efeSRichard Henderson     src = gen_load_fpr_Q(dc, a->rs);
4509388a6465SRichard Henderson     dst = tcg_temp_new_i32();
4510d81e3efeSRichard Henderson     func(dst, tcg_env, src);
4511bd9c5c42SRichard Henderson     gen_store_fpr_F(dc, a->rd, dst);
4512bd9c5c42SRichard Henderson     return advance_pc(dc);
4513bd9c5c42SRichard Henderson }
4514bd9c5c42SRichard Henderson 
4515bd9c5c42SRichard Henderson TRANS(FqTOs, ALL, do_env_fq, a, gen_helper_fqtos)
4516bd9c5c42SRichard Henderson TRANS(FqTOi, ALL, do_env_fq, a, gen_helper_fqtoi)
4517bd9c5c42SRichard Henderson 
45181617586fSRichard Henderson static bool do_env_dq(DisasContext *dc, arg_r_r *a,
451925a5769eSRichard Henderson                       void (*func)(TCGv_i64, TCGv_env, TCGv_i128))
45201617586fSRichard Henderson {
452125a5769eSRichard Henderson     TCGv_i128 src;
45221617586fSRichard Henderson     TCGv_i64 dst;
45231617586fSRichard Henderson 
45241617586fSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
45251617586fSRichard Henderson         return true;
45261617586fSRichard Henderson     }
45271617586fSRichard Henderson     if (gen_trap_float128(dc)) {
45281617586fSRichard Henderson         return true;
45291617586fSRichard Henderson     }
45301617586fSRichard Henderson 
453125a5769eSRichard Henderson     src = gen_load_fpr_Q(dc, a->rs);
45321617586fSRichard Henderson     dst = gen_dest_fpr_D(dc, a->rd);
453325a5769eSRichard Henderson     func(dst, tcg_env, src);
45341617586fSRichard Henderson     gen_store_fpr_D(dc, a->rd, dst);
45351617586fSRichard Henderson     return advance_pc(dc);
45361617586fSRichard Henderson }
45371617586fSRichard Henderson 
45381617586fSRichard Henderson TRANS(FqTOd, ALL, do_env_dq, a, gen_helper_fqtod)
45391617586fSRichard Henderson TRANS(FqTOx, 64, do_env_dq, a, gen_helper_fqtox)
45401617586fSRichard Henderson 
454113ebcc77SRichard Henderson static bool do_env_qf(DisasContext *dc, arg_r_r *a,
45420b2a61ccSRichard Henderson                       void (*func)(TCGv_i128, TCGv_env, TCGv_i32))
454313ebcc77SRichard Henderson {
454413ebcc77SRichard Henderson     TCGv_i32 src;
45450b2a61ccSRichard Henderson     TCGv_i128 dst;
454613ebcc77SRichard Henderson 
454713ebcc77SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
454813ebcc77SRichard Henderson         return true;
454913ebcc77SRichard Henderson     }
455013ebcc77SRichard Henderson     if (gen_trap_float128(dc)) {
455113ebcc77SRichard Henderson         return true;
455213ebcc77SRichard Henderson     }
455313ebcc77SRichard Henderson 
455413ebcc77SRichard Henderson     src = gen_load_fpr_F(dc, a->rs);
45550b2a61ccSRichard Henderson     dst = tcg_temp_new_i128();
45560b2a61ccSRichard Henderson     func(dst, tcg_env, src);
45570b2a61ccSRichard Henderson     gen_store_fpr_Q(dc, a->rd, dst);
455813ebcc77SRichard Henderson     return advance_pc(dc);
455913ebcc77SRichard Henderson }
456013ebcc77SRichard Henderson 
456113ebcc77SRichard Henderson TRANS(FiTOq, ALL, do_env_qf, a, gen_helper_fitoq)
456213ebcc77SRichard Henderson TRANS(FsTOq, ALL, do_env_qf, a, gen_helper_fstoq)
456313ebcc77SRichard Henderson 
45647b8e3e1aSRichard Henderson static bool do_env_qd(DisasContext *dc, arg_r_r *a,
4565fdc50716SRichard Henderson                       void (*func)(TCGv_i128, TCGv_env, TCGv_i64))
45667b8e3e1aSRichard Henderson {
45677b8e3e1aSRichard Henderson     TCGv_i64 src;
4568fdc50716SRichard Henderson     TCGv_i128 dst;
45697b8e3e1aSRichard Henderson 
45707b8e3e1aSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
45717b8e3e1aSRichard Henderson         return true;
45727b8e3e1aSRichard Henderson     }
45737b8e3e1aSRichard Henderson     if (gen_trap_float128(dc)) {
45747b8e3e1aSRichard Henderson         return true;
45757b8e3e1aSRichard Henderson     }
45767b8e3e1aSRichard Henderson 
45777b8e3e1aSRichard Henderson     src = gen_load_fpr_D(dc, a->rs);
4578fdc50716SRichard Henderson     dst = tcg_temp_new_i128();
4579fdc50716SRichard Henderson     func(dst, tcg_env, src);
4580fdc50716SRichard Henderson     gen_store_fpr_Q(dc, a->rd, dst);
45817b8e3e1aSRichard Henderson     return advance_pc(dc);
45827b8e3e1aSRichard Henderson }
45837b8e3e1aSRichard Henderson 
45847b8e3e1aSRichard Henderson TRANS(FdTOq, ALL, do_env_qd, a, gen_helper_fdtoq)
45857b8e3e1aSRichard Henderson TRANS(FxTOq, 64, do_env_qd, a, gen_helper_fxtoq)
45867b8e3e1aSRichard Henderson 
45877f10b52fSRichard Henderson static bool do_fff(DisasContext *dc, arg_r_r_r *a,
45887f10b52fSRichard Henderson                    void (*func)(TCGv_i32, TCGv_i32, TCGv_i32))
45897f10b52fSRichard Henderson {
45907f10b52fSRichard Henderson     TCGv_i32 src1, src2;
45917f10b52fSRichard Henderson 
45927f10b52fSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
45937f10b52fSRichard Henderson         return true;
45947f10b52fSRichard Henderson     }
45957f10b52fSRichard Henderson 
45967f10b52fSRichard Henderson     src1 = gen_load_fpr_F(dc, a->rs1);
45977f10b52fSRichard Henderson     src2 = gen_load_fpr_F(dc, a->rs2);
45987f10b52fSRichard Henderson     func(src1, src1, src2);
45997f10b52fSRichard Henderson     gen_store_fpr_F(dc, a->rd, src1);
46007f10b52fSRichard Henderson     return advance_pc(dc);
46017f10b52fSRichard Henderson }
46027f10b52fSRichard Henderson 
46037f10b52fSRichard Henderson TRANS(FPADD16s, VIS1, do_fff, a, tcg_gen_vec_add16_i32)
46047f10b52fSRichard Henderson TRANS(FPADD32s, VIS1, do_fff, a, tcg_gen_add_i32)
46057f10b52fSRichard Henderson TRANS(FPSUB16s, VIS1, do_fff, a, tcg_gen_vec_sub16_i32)
46067f10b52fSRichard Henderson TRANS(FPSUB32s, VIS1, do_fff, a, tcg_gen_sub_i32)
46077f10b52fSRichard Henderson TRANS(FNORs, VIS1, do_fff, a, tcg_gen_nor_i32)
46087f10b52fSRichard Henderson TRANS(FANDNOTs, VIS1, do_fff, a, tcg_gen_andc_i32)
46097f10b52fSRichard Henderson TRANS(FXORs, VIS1, do_fff, a, tcg_gen_xor_i32)
46107f10b52fSRichard Henderson TRANS(FNANDs, VIS1, do_fff, a, tcg_gen_nand_i32)
46117f10b52fSRichard Henderson TRANS(FANDs, VIS1, do_fff, a, tcg_gen_and_i32)
46127f10b52fSRichard Henderson TRANS(FXNORs, VIS1, do_fff, a, tcg_gen_eqv_i32)
46137f10b52fSRichard Henderson TRANS(FORNOTs, VIS1, do_fff, a, tcg_gen_orc_i32)
46147f10b52fSRichard Henderson TRANS(FORs, VIS1, do_fff, a, tcg_gen_or_i32)
46157f10b52fSRichard Henderson 
4616c1514961SRichard Henderson static bool do_env_fff(DisasContext *dc, arg_r_r_r *a,
4617c1514961SRichard Henderson                        void (*func)(TCGv_i32, TCGv_env, TCGv_i32, TCGv_i32))
4618c1514961SRichard Henderson {
4619c1514961SRichard Henderson     TCGv_i32 src1, src2;
4620c1514961SRichard Henderson 
4621c1514961SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4622c1514961SRichard Henderson         return true;
4623c1514961SRichard Henderson     }
4624c1514961SRichard Henderson 
4625c1514961SRichard Henderson     src1 = gen_load_fpr_F(dc, a->rs1);
4626c1514961SRichard Henderson     src2 = gen_load_fpr_F(dc, a->rs2);
4627c1514961SRichard Henderson     func(src1, tcg_env, src1, src2);
4628c1514961SRichard Henderson     gen_store_fpr_F(dc, a->rd, src1);
4629c1514961SRichard Henderson     return advance_pc(dc);
4630c1514961SRichard Henderson }
4631c1514961SRichard Henderson 
4632c1514961SRichard Henderson TRANS(FADDs, ALL, do_env_fff, a, gen_helper_fadds)
4633c1514961SRichard Henderson TRANS(FSUBs, ALL, do_env_fff, a, gen_helper_fsubs)
4634c1514961SRichard Henderson TRANS(FMULs, ALL, do_env_fff, a, gen_helper_fmuls)
4635c1514961SRichard Henderson TRANS(FDIVs, ALL, do_env_fff, a, gen_helper_fdivs)
4636c1514961SRichard Henderson 
4637a859602cSRichard Henderson static bool do_dff(DisasContext *dc, arg_r_r_r *a,
4638a859602cSRichard Henderson                    void (*func)(TCGv_i64, TCGv_i32, TCGv_i32))
4639a859602cSRichard Henderson {
4640a859602cSRichard Henderson     TCGv_i64 dst;
4641a859602cSRichard Henderson     TCGv_i32 src1, src2;
4642a859602cSRichard Henderson 
4643a859602cSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4644a859602cSRichard Henderson         return true;
4645a859602cSRichard Henderson     }
4646a859602cSRichard Henderson 
4647a859602cSRichard Henderson     dst = gen_dest_fpr_D(dc, a->rd);
4648a859602cSRichard Henderson     src1 = gen_load_fpr_F(dc, a->rs1);
4649a859602cSRichard Henderson     src2 = gen_load_fpr_F(dc, a->rs2);
4650a859602cSRichard Henderson     func(dst, src1, src2);
4651a859602cSRichard Henderson     gen_store_fpr_D(dc, a->rd, dst);
4652a859602cSRichard Henderson     return advance_pc(dc);
4653a859602cSRichard Henderson }
4654a859602cSRichard Henderson 
4655a859602cSRichard Henderson TRANS(FMUL8x16AU, VIS1, do_dff, a, gen_op_fmul8x16au)
4656a859602cSRichard Henderson TRANS(FMUL8x16AL, VIS1, do_dff, a, gen_op_fmul8x16al)
4657be8998e0SRichard Henderson TRANS(FMULD8SUx16, VIS1, do_dff, a, gen_op_fmuld8sux16)
4658be8998e0SRichard Henderson TRANS(FMULD8ULx16, VIS1, do_dff, a, gen_op_fmuld8ulx16)
4659*d3ef26afSRichard Henderson TRANS(FPMERGE, VIS1, do_dff, a, gen_helper_fpmerge)
4660a859602cSRichard Henderson 
46619157dcccSRichard Henderson static bool do_dfd(DisasContext *dc, arg_r_r_r *a,
46629157dcccSRichard Henderson                    void (*func)(TCGv_i64, TCGv_i32, TCGv_i64))
46639157dcccSRichard Henderson {
46649157dcccSRichard Henderson     TCGv_i64 dst, src2;
46659157dcccSRichard Henderson     TCGv_i32 src1;
46669157dcccSRichard Henderson 
46679157dcccSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
46689157dcccSRichard Henderson         return true;
46699157dcccSRichard Henderson     }
46709157dcccSRichard Henderson 
46719157dcccSRichard Henderson     dst = gen_dest_fpr_D(dc, a->rd);
46729157dcccSRichard Henderson     src1 = gen_load_fpr_F(dc, a->rs1);
46739157dcccSRichard Henderson     src2 = gen_load_fpr_D(dc, a->rs2);
46749157dcccSRichard Henderson     func(dst, src1, src2);
46759157dcccSRichard Henderson     gen_store_fpr_D(dc, a->rd, dst);
46769157dcccSRichard Henderson     return advance_pc(dc);
46779157dcccSRichard Henderson }
46789157dcccSRichard Henderson 
46799157dcccSRichard Henderson TRANS(FMUL8x16, VIS1, do_dfd, a, gen_helper_fmul8x16)
46809157dcccSRichard Henderson 
4681e06c9f83SRichard Henderson static bool do_ddd(DisasContext *dc, arg_r_r_r *a,
4682e06c9f83SRichard Henderson                    void (*func)(TCGv_i64, TCGv_i64, TCGv_i64))
4683e06c9f83SRichard Henderson {
4684e06c9f83SRichard Henderson     TCGv_i64 dst, src1, src2;
4685e06c9f83SRichard Henderson 
4686e06c9f83SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4687e06c9f83SRichard Henderson         return true;
4688e06c9f83SRichard Henderson     }
4689e06c9f83SRichard Henderson 
4690e06c9f83SRichard Henderson     dst = gen_dest_fpr_D(dc, a->rd);
4691e06c9f83SRichard Henderson     src1 = gen_load_fpr_D(dc, a->rs1);
4692e06c9f83SRichard Henderson     src2 = gen_load_fpr_D(dc, a->rs2);
4693e06c9f83SRichard Henderson     func(dst, src1, src2);
4694e06c9f83SRichard Henderson     gen_store_fpr_D(dc, a->rd, dst);
4695e06c9f83SRichard Henderson     return advance_pc(dc);
4696e06c9f83SRichard Henderson }
4697e06c9f83SRichard Henderson 
4698e06c9f83SRichard Henderson TRANS(FMUL8SUx16, VIS1, do_ddd, a, gen_helper_fmul8sux16)
4699e06c9f83SRichard Henderson TRANS(FMUL8ULx16, VIS1, do_ddd, a, gen_helper_fmul8ulx16)
4700e06c9f83SRichard Henderson 
4701e06c9f83SRichard Henderson TRANS(FPADD16, VIS1, do_ddd, a, tcg_gen_vec_add16_i64)
4702e06c9f83SRichard Henderson TRANS(FPADD32, VIS1, do_ddd, a, tcg_gen_vec_add32_i64)
4703e06c9f83SRichard Henderson TRANS(FPSUB16, VIS1, do_ddd, a, tcg_gen_vec_sub16_i64)
4704e06c9f83SRichard Henderson TRANS(FPSUB32, VIS1, do_ddd, a, tcg_gen_vec_sub32_i64)
4705e06c9f83SRichard Henderson TRANS(FNORd, VIS1, do_ddd, a, tcg_gen_nor_i64)
4706e06c9f83SRichard Henderson TRANS(FANDNOTd, VIS1, do_ddd, a, tcg_gen_andc_i64)
4707e06c9f83SRichard Henderson TRANS(FXORd, VIS1, do_ddd, a, tcg_gen_xor_i64)
4708e06c9f83SRichard Henderson TRANS(FNANDd, VIS1, do_ddd, a, tcg_gen_nand_i64)
4709e06c9f83SRichard Henderson TRANS(FANDd, VIS1, do_ddd, a, tcg_gen_and_i64)
4710e06c9f83SRichard Henderson TRANS(FXNORd, VIS1, do_ddd, a, tcg_gen_eqv_i64)
4711e06c9f83SRichard Henderson TRANS(FORNOTd, VIS1, do_ddd, a, tcg_gen_orc_i64)
4712e06c9f83SRichard Henderson TRANS(FORd, VIS1, do_ddd, a, tcg_gen_or_i64)
4713e06c9f83SRichard Henderson 
47144b6edc0aSRichard Henderson TRANS(FPACK32, VIS1, do_ddd, a, gen_op_fpack32)
47154b6edc0aSRichard Henderson TRANS(FALIGNDATAg, VIS1, do_ddd, a, gen_op_faligndata)
47164b6edc0aSRichard Henderson TRANS(BSHUFFLE, VIS2, do_ddd, a, gen_op_bshuffle)
47174b6edc0aSRichard Henderson 
4718e2fa6bd1SRichard Henderson static bool do_rdd(DisasContext *dc, arg_r_r_r *a,
4719e2fa6bd1SRichard Henderson                    void (*func)(TCGv, TCGv_i64, TCGv_i64))
4720e2fa6bd1SRichard Henderson {
4721e2fa6bd1SRichard Henderson     TCGv_i64 src1, src2;
4722e2fa6bd1SRichard Henderson     TCGv dst;
4723e2fa6bd1SRichard Henderson 
4724e2fa6bd1SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4725e2fa6bd1SRichard Henderson         return true;
4726e2fa6bd1SRichard Henderson     }
4727e2fa6bd1SRichard Henderson 
4728e2fa6bd1SRichard Henderson     dst = gen_dest_gpr(dc, a->rd);
4729e2fa6bd1SRichard Henderson     src1 = gen_load_fpr_D(dc, a->rs1);
4730e2fa6bd1SRichard Henderson     src2 = gen_load_fpr_D(dc, a->rs2);
4731e2fa6bd1SRichard Henderson     func(dst, src1, src2);
4732e2fa6bd1SRichard Henderson     gen_store_gpr(dc, a->rd, dst);
4733e2fa6bd1SRichard Henderson     return advance_pc(dc);
4734e2fa6bd1SRichard Henderson }
4735e2fa6bd1SRichard Henderson 
4736e2fa6bd1SRichard Henderson TRANS(FPCMPLE16, VIS1, do_rdd, a, gen_helper_fcmple16)
4737e2fa6bd1SRichard Henderson TRANS(FPCMPNE16, VIS1, do_rdd, a, gen_helper_fcmpne16)
4738e2fa6bd1SRichard Henderson TRANS(FPCMPGT16, VIS1, do_rdd, a, gen_helper_fcmpgt16)
4739e2fa6bd1SRichard Henderson TRANS(FPCMPEQ16, VIS1, do_rdd, a, gen_helper_fcmpeq16)
4740e2fa6bd1SRichard Henderson 
4741e2fa6bd1SRichard Henderson TRANS(FPCMPLE32, VIS1, do_rdd, a, gen_helper_fcmple32)
4742e2fa6bd1SRichard Henderson TRANS(FPCMPNE32, VIS1, do_rdd, a, gen_helper_fcmpne32)
4743e2fa6bd1SRichard Henderson TRANS(FPCMPGT32, VIS1, do_rdd, a, gen_helper_fcmpgt32)
4744e2fa6bd1SRichard Henderson TRANS(FPCMPEQ32, VIS1, do_rdd, a, gen_helper_fcmpeq32)
4745e2fa6bd1SRichard Henderson 
4746f2a59b0aSRichard Henderson static bool do_env_ddd(DisasContext *dc, arg_r_r_r *a,
4747f2a59b0aSRichard Henderson                        void (*func)(TCGv_i64, TCGv_env, TCGv_i64, TCGv_i64))
4748f2a59b0aSRichard Henderson {
4749f2a59b0aSRichard Henderson     TCGv_i64 dst, src1, src2;
4750f2a59b0aSRichard Henderson 
4751f2a59b0aSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4752f2a59b0aSRichard Henderson         return true;
4753f2a59b0aSRichard Henderson     }
4754f2a59b0aSRichard Henderson 
4755f2a59b0aSRichard Henderson     dst = gen_dest_fpr_D(dc, a->rd);
4756f2a59b0aSRichard Henderson     src1 = gen_load_fpr_D(dc, a->rs1);
4757f2a59b0aSRichard Henderson     src2 = gen_load_fpr_D(dc, a->rs2);
4758f2a59b0aSRichard Henderson     func(dst, tcg_env, src1, src2);
4759f2a59b0aSRichard Henderson     gen_store_fpr_D(dc, a->rd, dst);
4760f2a59b0aSRichard Henderson     return advance_pc(dc);
4761f2a59b0aSRichard Henderson }
4762f2a59b0aSRichard Henderson 
4763f2a59b0aSRichard Henderson TRANS(FADDd, ALL, do_env_ddd, a, gen_helper_faddd)
4764f2a59b0aSRichard Henderson TRANS(FSUBd, ALL, do_env_ddd, a, gen_helper_fsubd)
4765f2a59b0aSRichard Henderson TRANS(FMULd, ALL, do_env_ddd, a, gen_helper_fmuld)
4766f2a59b0aSRichard Henderson TRANS(FDIVd, ALL, do_env_ddd, a, gen_helper_fdivd)
4767f2a59b0aSRichard Henderson 
4768ff4c711bSRichard Henderson static bool trans_FsMULd(DisasContext *dc, arg_r_r_r *a)
4769ff4c711bSRichard Henderson {
4770ff4c711bSRichard Henderson     TCGv_i64 dst;
4771ff4c711bSRichard Henderson     TCGv_i32 src1, src2;
4772ff4c711bSRichard Henderson 
4773ff4c711bSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4774ff4c711bSRichard Henderson         return true;
4775ff4c711bSRichard Henderson     }
4776ff4c711bSRichard Henderson     if (!(dc->def->features & CPU_FEATURE_FSMULD)) {
4777ff4c711bSRichard Henderson         return raise_unimpfpop(dc);
4778ff4c711bSRichard Henderson     }
4779ff4c711bSRichard Henderson 
4780ff4c711bSRichard Henderson     dst = gen_dest_fpr_D(dc, a->rd);
4781ff4c711bSRichard Henderson     src1 = gen_load_fpr_F(dc, a->rs1);
4782ff4c711bSRichard Henderson     src2 = gen_load_fpr_F(dc, a->rs2);
4783ff4c711bSRichard Henderson     gen_helper_fsmuld(dst, tcg_env, src1, src2);
4784ff4c711bSRichard Henderson     gen_store_fpr_D(dc, a->rd, dst);
4785ff4c711bSRichard Henderson     return advance_pc(dc);
4786ff4c711bSRichard Henderson }
4787ff4c711bSRichard Henderson 
4788afb04344SRichard Henderson static bool do_dddd(DisasContext *dc, arg_r_r_r *a,
4789afb04344SRichard Henderson                     void (*func)(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_i64))
4790afb04344SRichard Henderson {
4791afb04344SRichard Henderson     TCGv_i64 dst, src0, src1, src2;
4792afb04344SRichard Henderson 
4793afb04344SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4794afb04344SRichard Henderson         return true;
4795afb04344SRichard Henderson     }
4796afb04344SRichard Henderson 
4797afb04344SRichard Henderson     dst  = gen_dest_fpr_D(dc, a->rd);
4798afb04344SRichard Henderson     src0 = gen_load_fpr_D(dc, a->rd);
4799afb04344SRichard Henderson     src1 = gen_load_fpr_D(dc, a->rs1);
4800afb04344SRichard Henderson     src2 = gen_load_fpr_D(dc, a->rs2);
4801afb04344SRichard Henderson     func(dst, src0, src1, src2);
4802afb04344SRichard Henderson     gen_store_fpr_D(dc, a->rd, dst);
4803afb04344SRichard Henderson     return advance_pc(dc);
4804afb04344SRichard Henderson }
4805afb04344SRichard Henderson 
4806afb04344SRichard Henderson TRANS(PDIST, VIS1, do_dddd, a, gen_helper_pdist)
4807afb04344SRichard Henderson 
4808a4056239SRichard Henderson static bool do_env_qqq(DisasContext *dc, arg_r_r_r *a,
480916bedf89SRichard Henderson                        void (*func)(TCGv_i128, TCGv_env, TCGv_i128, TCGv_i128))
4810a4056239SRichard Henderson {
481116bedf89SRichard Henderson     TCGv_i128 src1, src2;
481216bedf89SRichard Henderson 
4813a4056239SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4814a4056239SRichard Henderson         return true;
4815a4056239SRichard Henderson     }
4816a4056239SRichard Henderson     if (gen_trap_float128(dc)) {
4817a4056239SRichard Henderson         return true;
4818a4056239SRichard Henderson     }
4819a4056239SRichard Henderson 
482016bedf89SRichard Henderson     src1 = gen_load_fpr_Q(dc, a->rs1);
482116bedf89SRichard Henderson     src2 = gen_load_fpr_Q(dc, a->rs2);
482216bedf89SRichard Henderson     func(src1, tcg_env, src1, src2);
482316bedf89SRichard Henderson     gen_store_fpr_Q(dc, a->rd, src1);
4824a4056239SRichard Henderson     return advance_pc(dc);
4825a4056239SRichard Henderson }
4826a4056239SRichard Henderson 
4827a4056239SRichard Henderson TRANS(FADDq, ALL, do_env_qqq, a, gen_helper_faddq)
4828a4056239SRichard Henderson TRANS(FSUBq, ALL, do_env_qqq, a, gen_helper_fsubq)
4829a4056239SRichard Henderson TRANS(FMULq, ALL, do_env_qqq, a, gen_helper_fmulq)
4830a4056239SRichard Henderson TRANS(FDIVq, ALL, do_env_qqq, a, gen_helper_fdivq)
4831a4056239SRichard Henderson 
48325e3b17bbSRichard Henderson static bool trans_FdMULq(DisasContext *dc, arg_r_r_r *a)
48335e3b17bbSRichard Henderson {
48345e3b17bbSRichard Henderson     TCGv_i64 src1, src2;
4835ba21dc99SRichard Henderson     TCGv_i128 dst;
48365e3b17bbSRichard Henderson 
48375e3b17bbSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
48385e3b17bbSRichard Henderson         return true;
48395e3b17bbSRichard Henderson     }
48405e3b17bbSRichard Henderson     if (gen_trap_float128(dc)) {
48415e3b17bbSRichard Henderson         return true;
48425e3b17bbSRichard Henderson     }
48435e3b17bbSRichard Henderson 
48445e3b17bbSRichard Henderson     src1 = gen_load_fpr_D(dc, a->rs1);
48455e3b17bbSRichard Henderson     src2 = gen_load_fpr_D(dc, a->rs2);
4846ba21dc99SRichard Henderson     dst = tcg_temp_new_i128();
4847ba21dc99SRichard Henderson     gen_helper_fdmulq(dst, tcg_env, src1, src2);
4848ba21dc99SRichard Henderson     gen_store_fpr_Q(dc, a->rd, dst);
48495e3b17bbSRichard Henderson     return advance_pc(dc);
48505e3b17bbSRichard Henderson }
48515e3b17bbSRichard Henderson 
4852f7ec8155SRichard Henderson static bool do_fmovr(DisasContext *dc, arg_FMOVRs *a, bool is_128,
4853f7ec8155SRichard Henderson                      void (*func)(DisasContext *, DisasCompare *, int, int))
4854f7ec8155SRichard Henderson {
4855f7ec8155SRichard Henderson     DisasCompare cmp;
4856f7ec8155SRichard Henderson 
48572c4f56c9SRichard Henderson     if (!gen_compare_reg(&cmp, a->cond, gen_load_gpr(dc, a->rs1))) {
48582c4f56c9SRichard Henderson         return false;
48592c4f56c9SRichard Henderson     }
4860f7ec8155SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4861f7ec8155SRichard Henderson         return true;
4862f7ec8155SRichard Henderson     }
4863f7ec8155SRichard Henderson     if (is_128 && gen_trap_float128(dc)) {
4864f7ec8155SRichard Henderson         return true;
4865f7ec8155SRichard Henderson     }
4866f7ec8155SRichard Henderson 
4867f7ec8155SRichard Henderson     gen_op_clear_ieee_excp_and_FTT();
4868f7ec8155SRichard Henderson     func(dc, &cmp, a->rd, a->rs2);
4869f7ec8155SRichard Henderson     return advance_pc(dc);
4870f7ec8155SRichard Henderson }
4871f7ec8155SRichard Henderson 
4872f7ec8155SRichard Henderson TRANS(FMOVRs, 64, do_fmovr, a, false, gen_fmovs)
4873f7ec8155SRichard Henderson TRANS(FMOVRd, 64, do_fmovr, a, false, gen_fmovd)
4874f7ec8155SRichard Henderson TRANS(FMOVRq, 64, do_fmovr, a, true, gen_fmovq)
4875f7ec8155SRichard Henderson 
4876f7ec8155SRichard Henderson static bool do_fmovcc(DisasContext *dc, arg_FMOVscc *a, bool is_128,
4877f7ec8155SRichard Henderson                       void (*func)(DisasContext *, DisasCompare *, int, int))
4878f7ec8155SRichard Henderson {
4879f7ec8155SRichard Henderson     DisasCompare cmp;
4880f7ec8155SRichard Henderson 
4881f7ec8155SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4882f7ec8155SRichard Henderson         return true;
4883f7ec8155SRichard Henderson     }
4884f7ec8155SRichard Henderson     if (is_128 && gen_trap_float128(dc)) {
4885f7ec8155SRichard Henderson         return true;
4886f7ec8155SRichard Henderson     }
4887f7ec8155SRichard Henderson 
4888f7ec8155SRichard Henderson     gen_op_clear_ieee_excp_and_FTT();
4889f7ec8155SRichard Henderson     gen_compare(&cmp, a->cc, a->cond, dc);
4890f7ec8155SRichard Henderson     func(dc, &cmp, a->rd, a->rs2);
4891f7ec8155SRichard Henderson     return advance_pc(dc);
4892f7ec8155SRichard Henderson }
4893f7ec8155SRichard Henderson 
4894f7ec8155SRichard Henderson TRANS(FMOVscc, 64, do_fmovcc, a, false, gen_fmovs)
4895f7ec8155SRichard Henderson TRANS(FMOVdcc, 64, do_fmovcc, a, false, gen_fmovd)
4896f7ec8155SRichard Henderson TRANS(FMOVqcc, 64, do_fmovcc, a, true, gen_fmovq)
4897f7ec8155SRichard Henderson 
4898f7ec8155SRichard Henderson static bool do_fmovfcc(DisasContext *dc, arg_FMOVsfcc *a, bool is_128,
4899f7ec8155SRichard Henderson                        void (*func)(DisasContext *, DisasCompare *, int, int))
4900f7ec8155SRichard Henderson {
4901f7ec8155SRichard Henderson     DisasCompare cmp;
4902f7ec8155SRichard Henderson 
4903f7ec8155SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4904f7ec8155SRichard Henderson         return true;
4905f7ec8155SRichard Henderson     }
4906f7ec8155SRichard Henderson     if (is_128 && gen_trap_float128(dc)) {
4907f7ec8155SRichard Henderson         return true;
4908f7ec8155SRichard Henderson     }
4909f7ec8155SRichard Henderson 
4910f7ec8155SRichard Henderson     gen_op_clear_ieee_excp_and_FTT();
4911f7ec8155SRichard Henderson     gen_fcompare(&cmp, a->cc, a->cond);
4912f7ec8155SRichard Henderson     func(dc, &cmp, a->rd, a->rs2);
4913f7ec8155SRichard Henderson     return advance_pc(dc);
4914f7ec8155SRichard Henderson }
4915f7ec8155SRichard Henderson 
4916f7ec8155SRichard Henderson TRANS(FMOVsfcc, 64, do_fmovfcc, a, false, gen_fmovs)
4917f7ec8155SRichard Henderson TRANS(FMOVdfcc, 64, do_fmovfcc, a, false, gen_fmovd)
4918f7ec8155SRichard Henderson TRANS(FMOVqfcc, 64, do_fmovfcc, a, true, gen_fmovq)
4919f7ec8155SRichard Henderson 
492040f9ad21SRichard Henderson static bool do_fcmps(DisasContext *dc, arg_FCMPs *a, bool e)
492140f9ad21SRichard Henderson {
492240f9ad21SRichard Henderson     TCGv_i32 src1, src2;
492340f9ad21SRichard Henderson 
492440f9ad21SRichard Henderson     if (avail_32(dc) && a->cc != 0) {
492540f9ad21SRichard Henderson         return false;
492640f9ad21SRichard Henderson     }
492740f9ad21SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
492840f9ad21SRichard Henderson         return true;
492940f9ad21SRichard Henderson     }
493040f9ad21SRichard Henderson 
493140f9ad21SRichard Henderson     src1 = gen_load_fpr_F(dc, a->rs1);
493240f9ad21SRichard Henderson     src2 = gen_load_fpr_F(dc, a->rs2);
493340f9ad21SRichard Henderson     if (e) {
4934d8c5b92fSRichard Henderson         gen_helper_fcmpes(cpu_fcc[a->cc], tcg_env, src1, src2);
493540f9ad21SRichard Henderson     } else {
4936d8c5b92fSRichard Henderson         gen_helper_fcmps(cpu_fcc[a->cc], tcg_env, src1, src2);
493740f9ad21SRichard Henderson     }
493840f9ad21SRichard Henderson     return advance_pc(dc);
493940f9ad21SRichard Henderson }
494040f9ad21SRichard Henderson 
494140f9ad21SRichard Henderson TRANS(FCMPs, ALL, do_fcmps, a, false)
494240f9ad21SRichard Henderson TRANS(FCMPEs, ALL, do_fcmps, a, true)
494340f9ad21SRichard Henderson 
494440f9ad21SRichard Henderson static bool do_fcmpd(DisasContext *dc, arg_FCMPd *a, bool e)
494540f9ad21SRichard Henderson {
494640f9ad21SRichard Henderson     TCGv_i64 src1, src2;
494740f9ad21SRichard Henderson 
494840f9ad21SRichard Henderson     if (avail_32(dc) && a->cc != 0) {
494940f9ad21SRichard Henderson         return false;
495040f9ad21SRichard Henderson     }
495140f9ad21SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
495240f9ad21SRichard Henderson         return true;
495340f9ad21SRichard Henderson     }
495440f9ad21SRichard Henderson 
495540f9ad21SRichard Henderson     src1 = gen_load_fpr_D(dc, a->rs1);
495640f9ad21SRichard Henderson     src2 = gen_load_fpr_D(dc, a->rs2);
495740f9ad21SRichard Henderson     if (e) {
4958d8c5b92fSRichard Henderson         gen_helper_fcmped(cpu_fcc[a->cc], tcg_env, src1, src2);
495940f9ad21SRichard Henderson     } else {
4960d8c5b92fSRichard Henderson         gen_helper_fcmpd(cpu_fcc[a->cc], tcg_env, src1, src2);
496140f9ad21SRichard Henderson     }
496240f9ad21SRichard Henderson     return advance_pc(dc);
496340f9ad21SRichard Henderson }
496440f9ad21SRichard Henderson 
496540f9ad21SRichard Henderson TRANS(FCMPd, ALL, do_fcmpd, a, false)
496640f9ad21SRichard Henderson TRANS(FCMPEd, ALL, do_fcmpd, a, true)
496740f9ad21SRichard Henderson 
496840f9ad21SRichard Henderson static bool do_fcmpq(DisasContext *dc, arg_FCMPq *a, bool e)
496940f9ad21SRichard Henderson {
4970f3ceafadSRichard Henderson     TCGv_i128 src1, src2;
4971f3ceafadSRichard Henderson 
497240f9ad21SRichard Henderson     if (avail_32(dc) && a->cc != 0) {
497340f9ad21SRichard Henderson         return false;
497440f9ad21SRichard Henderson     }
497540f9ad21SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
497640f9ad21SRichard Henderson         return true;
497740f9ad21SRichard Henderson     }
497840f9ad21SRichard Henderson     if (gen_trap_float128(dc)) {
497940f9ad21SRichard Henderson         return true;
498040f9ad21SRichard Henderson     }
498140f9ad21SRichard Henderson 
4982f3ceafadSRichard Henderson     src1 = gen_load_fpr_Q(dc, a->rs1);
4983f3ceafadSRichard Henderson     src2 = gen_load_fpr_Q(dc, a->rs2);
498440f9ad21SRichard Henderson     if (e) {
4985d8c5b92fSRichard Henderson         gen_helper_fcmpeq(cpu_fcc[a->cc], tcg_env, src1, src2);
498640f9ad21SRichard Henderson     } else {
4987d8c5b92fSRichard Henderson         gen_helper_fcmpq(cpu_fcc[a->cc], tcg_env, src1, src2);
498840f9ad21SRichard Henderson     }
498940f9ad21SRichard Henderson     return advance_pc(dc);
499040f9ad21SRichard Henderson }
499140f9ad21SRichard Henderson 
499240f9ad21SRichard Henderson TRANS(FCMPq, ALL, do_fcmpq, a, false)
499340f9ad21SRichard Henderson TRANS(FCMPEq, ALL, do_fcmpq, a, true)
499440f9ad21SRichard Henderson 
49956e61bc94SEmilio G. Cota static void sparc_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
4996fcf5ef2aSThomas Huth {
49976e61bc94SEmilio G. Cota     DisasContext *dc = container_of(dcbase, DisasContext, base);
49986e61bc94SEmilio G. Cota     int bound;
4999af00be49SEmilio G. Cota 
5000af00be49SEmilio G. Cota     dc->pc = dc->base.pc_first;
50016e61bc94SEmilio G. Cota     dc->npc = (target_ulong)dc->base.tb->cs_base;
50026e61bc94SEmilio G. Cota     dc->mem_idx = dc->base.tb->flags & TB_FLAG_MMU_MASK;
500377976769SPhilippe Mathieu-Daudé     dc->def = &cpu_env(cs)->def;
50046e61bc94SEmilio G. Cota     dc->fpu_enabled = tb_fpu_enabled(dc->base.tb->flags);
50056e61bc94SEmilio G. Cota     dc->address_mask_32bit = tb_am_enabled(dc->base.tb->flags);
5006c9b459aaSArtyom Tarasenko #ifndef CONFIG_USER_ONLY
50076e61bc94SEmilio G. Cota     dc->supervisor = (dc->base.tb->flags & TB_FLAG_SUPER) != 0;
5008c9b459aaSArtyom Tarasenko #endif
5009fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
5010fcf5ef2aSThomas Huth     dc->fprs_dirty = 0;
50116e61bc94SEmilio G. Cota     dc->asi = (dc->base.tb->flags >> TB_FLAG_ASI_SHIFT) & 0xff;
5012c9b459aaSArtyom Tarasenko #ifndef CONFIG_USER_ONLY
50136e61bc94SEmilio G. Cota     dc->hypervisor = (dc->base.tb->flags & TB_FLAG_HYPER) != 0;
5014c9b459aaSArtyom Tarasenko #endif
5015fcf5ef2aSThomas Huth #endif
50166e61bc94SEmilio G. Cota     /*
50176e61bc94SEmilio G. Cota      * if we reach a page boundary, we stop generation so that the
50186e61bc94SEmilio G. Cota      * PC of a TT_TFAULT exception is always in the right page
50196e61bc94SEmilio G. Cota      */
50206e61bc94SEmilio G. Cota     bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
50216e61bc94SEmilio G. Cota     dc->base.max_insns = MIN(dc->base.max_insns, bound);
5022af00be49SEmilio G. Cota }
5023fcf5ef2aSThomas Huth 
50246e61bc94SEmilio G. Cota static void sparc_tr_tb_start(DisasContextBase *db, CPUState *cs)
50256e61bc94SEmilio G. Cota {
50266e61bc94SEmilio G. Cota }
50276e61bc94SEmilio G. Cota 
50286e61bc94SEmilio G. Cota static void sparc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
50296e61bc94SEmilio G. Cota {
50306e61bc94SEmilio G. Cota     DisasContext *dc = container_of(dcbase, DisasContext, base);
5031633c4283SRichard Henderson     target_ulong npc = dc->npc;
50326e61bc94SEmilio G. Cota 
5033633c4283SRichard Henderson     if (npc & 3) {
5034633c4283SRichard Henderson         switch (npc) {
5035633c4283SRichard Henderson         case JUMP_PC:
5036fcf5ef2aSThomas Huth             assert(dc->jump_pc[1] == dc->pc + 4);
5037633c4283SRichard Henderson             npc = dc->jump_pc[0] | JUMP_PC;
5038633c4283SRichard Henderson             break;
5039633c4283SRichard Henderson         case DYNAMIC_PC:
5040633c4283SRichard Henderson         case DYNAMIC_PC_LOOKUP:
5041633c4283SRichard Henderson             npc = DYNAMIC_PC;
5042633c4283SRichard Henderson             break;
5043633c4283SRichard Henderson         default:
5044633c4283SRichard Henderson             g_assert_not_reached();
5045fcf5ef2aSThomas Huth         }
50466e61bc94SEmilio G. Cota     }
5047633c4283SRichard Henderson     tcg_gen_insn_start(dc->pc, npc);
5048633c4283SRichard Henderson }
5049fcf5ef2aSThomas Huth 
50506e61bc94SEmilio G. Cota static void sparc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
50516e61bc94SEmilio G. Cota {
50526e61bc94SEmilio G. Cota     DisasContext *dc = container_of(dcbase, DisasContext, base);
50536e61bc94SEmilio G. Cota     unsigned int insn;
5054fcf5ef2aSThomas Huth 
505577976769SPhilippe Mathieu-Daudé     insn = translator_ldl(cpu_env(cs), &dc->base, dc->pc);
5056af00be49SEmilio G. Cota     dc->base.pc_next += 4;
5057878cc677SRichard Henderson 
5058878cc677SRichard Henderson     if (!decode(dc, insn)) {
5059ba9c09b4SRichard Henderson         gen_exception(dc, TT_ILL_INSN);
5060878cc677SRichard Henderson     }
5061fcf5ef2aSThomas Huth 
5062af00be49SEmilio G. Cota     if (dc->base.is_jmp == DISAS_NORETURN) {
50636e61bc94SEmilio G. Cota         return;
5064c5e6ccdfSEmilio G. Cota     }
5065af00be49SEmilio G. Cota     if (dc->pc != dc->base.pc_next) {
50666e61bc94SEmilio G. Cota         dc->base.is_jmp = DISAS_TOO_MANY;
5067af00be49SEmilio G. Cota     }
50686e61bc94SEmilio G. Cota }
5069fcf5ef2aSThomas Huth 
50706e61bc94SEmilio G. Cota static void sparc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
50716e61bc94SEmilio G. Cota {
50726e61bc94SEmilio G. Cota     DisasContext *dc = container_of(dcbase, DisasContext, base);
5073186e7890SRichard Henderson     DisasDelayException *e, *e_next;
5074633c4283SRichard Henderson     bool may_lookup;
50756e61bc94SEmilio G. Cota 
507689527e3aSRichard Henderson     finishing_insn(dc);
507789527e3aSRichard Henderson 
507846bb0137SMark Cave-Ayland     switch (dc->base.is_jmp) {
507946bb0137SMark Cave-Ayland     case DISAS_NEXT:
508046bb0137SMark Cave-Ayland     case DISAS_TOO_MANY:
5081633c4283SRichard Henderson         if (((dc->pc | dc->npc) & 3) == 0) {
5082fcf5ef2aSThomas Huth             /* static PC and NPC: we can use direct chaining */
5083fcf5ef2aSThomas Huth             gen_goto_tb(dc, 0, dc->pc, dc->npc);
5084633c4283SRichard Henderson             break;
5085fcf5ef2aSThomas Huth         }
5086633c4283SRichard Henderson 
5087930f1865SRichard Henderson         may_lookup = true;
5088633c4283SRichard Henderson         if (dc->pc & 3) {
5089633c4283SRichard Henderson             switch (dc->pc) {
5090633c4283SRichard Henderson             case DYNAMIC_PC_LOOKUP:
5091633c4283SRichard Henderson                 break;
5092633c4283SRichard Henderson             case DYNAMIC_PC:
5093633c4283SRichard Henderson                 may_lookup = false;
5094633c4283SRichard Henderson                 break;
5095633c4283SRichard Henderson             default:
5096633c4283SRichard Henderson                 g_assert_not_reached();
5097633c4283SRichard Henderson             }
5098633c4283SRichard Henderson         } else {
5099633c4283SRichard Henderson             tcg_gen_movi_tl(cpu_pc, dc->pc);
5100633c4283SRichard Henderson         }
5101633c4283SRichard Henderson 
5102930f1865SRichard Henderson         if (dc->npc & 3) {
5103930f1865SRichard Henderson             switch (dc->npc) {
5104930f1865SRichard Henderson             case JUMP_PC:
5105930f1865SRichard Henderson                 gen_generic_branch(dc);
5106930f1865SRichard Henderson                 break;
5107930f1865SRichard Henderson             case DYNAMIC_PC:
5108930f1865SRichard Henderson                 may_lookup = false;
5109930f1865SRichard Henderson                 break;
5110930f1865SRichard Henderson             case DYNAMIC_PC_LOOKUP:
5111930f1865SRichard Henderson                 break;
5112930f1865SRichard Henderson             default:
5113930f1865SRichard Henderson                 g_assert_not_reached();
5114930f1865SRichard Henderson             }
5115930f1865SRichard Henderson         } else {
5116930f1865SRichard Henderson             tcg_gen_movi_tl(cpu_npc, dc->npc);
5117930f1865SRichard Henderson         }
5118633c4283SRichard Henderson         if (may_lookup) {
5119633c4283SRichard Henderson             tcg_gen_lookup_and_goto_ptr();
5120633c4283SRichard Henderson         } else {
512107ea28b4SRichard Henderson             tcg_gen_exit_tb(NULL, 0);
5122fcf5ef2aSThomas Huth         }
512346bb0137SMark Cave-Ayland         break;
512446bb0137SMark Cave-Ayland 
512546bb0137SMark Cave-Ayland     case DISAS_NORETURN:
512646bb0137SMark Cave-Ayland        break;
512746bb0137SMark Cave-Ayland 
512846bb0137SMark Cave-Ayland     case DISAS_EXIT:
512946bb0137SMark Cave-Ayland         /* Exit TB */
513046bb0137SMark Cave-Ayland         save_state(dc);
513146bb0137SMark Cave-Ayland         tcg_gen_exit_tb(NULL, 0);
513246bb0137SMark Cave-Ayland         break;
513346bb0137SMark Cave-Ayland 
513446bb0137SMark Cave-Ayland     default:
513546bb0137SMark Cave-Ayland         g_assert_not_reached();
5136fcf5ef2aSThomas Huth     }
5137186e7890SRichard Henderson 
5138186e7890SRichard Henderson     for (e = dc->delay_excp_list; e ; e = e_next) {
5139186e7890SRichard Henderson         gen_set_label(e->lab);
5140186e7890SRichard Henderson 
5141186e7890SRichard Henderson         tcg_gen_movi_tl(cpu_pc, e->pc);
5142186e7890SRichard Henderson         if (e->npc % 4 == 0) {
5143186e7890SRichard Henderson             tcg_gen_movi_tl(cpu_npc, e->npc);
5144186e7890SRichard Henderson         }
5145186e7890SRichard Henderson         gen_helper_raise_exception(tcg_env, e->excp);
5146186e7890SRichard Henderson 
5147186e7890SRichard Henderson         e_next = e->next;
5148186e7890SRichard Henderson         g_free(e);
5149186e7890SRichard Henderson     }
5150fcf5ef2aSThomas Huth }
51516e61bc94SEmilio G. Cota 
51528eb806a7SRichard Henderson static void sparc_tr_disas_log(const DisasContextBase *dcbase,
51538eb806a7SRichard Henderson                                CPUState *cpu, FILE *logfile)
51546e61bc94SEmilio G. Cota {
51558eb806a7SRichard Henderson     fprintf(logfile, "IN: %s\n", lookup_symbol(dcbase->pc_first));
51568eb806a7SRichard Henderson     target_disas(logfile, cpu, dcbase->pc_first, dcbase->tb->size);
51576e61bc94SEmilio G. Cota }
51586e61bc94SEmilio G. Cota 
51596e61bc94SEmilio G. Cota static const TranslatorOps sparc_tr_ops = {
51606e61bc94SEmilio G. Cota     .init_disas_context = sparc_tr_init_disas_context,
51616e61bc94SEmilio G. Cota     .tb_start           = sparc_tr_tb_start,
51626e61bc94SEmilio G. Cota     .insn_start         = sparc_tr_insn_start,
51636e61bc94SEmilio G. Cota     .translate_insn     = sparc_tr_translate_insn,
51646e61bc94SEmilio G. Cota     .tb_stop            = sparc_tr_tb_stop,
51656e61bc94SEmilio G. Cota     .disas_log          = sparc_tr_disas_log,
51666e61bc94SEmilio G. Cota };
51676e61bc94SEmilio G. Cota 
5168597f9b2dSRichard Henderson void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int *max_insns,
516932f0c394SAnton Johansson                            vaddr pc, void *host_pc)
51706e61bc94SEmilio G. Cota {
51716e61bc94SEmilio G. Cota     DisasContext dc = {};
51726e61bc94SEmilio G. Cota 
5173306c8721SRichard Henderson     translator_loop(cs, tb, max_insns, pc, host_pc, &sparc_tr_ops, &dc.base);
5174fcf5ef2aSThomas Huth }
5175fcf5ef2aSThomas Huth 
517655c3ceefSRichard Henderson void sparc_tcg_init(void)
5177fcf5ef2aSThomas Huth {
5178fcf5ef2aSThomas Huth     static const char gregnames[32][4] = {
5179fcf5ef2aSThomas Huth         "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
5180fcf5ef2aSThomas Huth         "o0", "o1", "o2", "o3", "o4", "o5", "o6", "o7",
5181fcf5ef2aSThomas Huth         "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
5182fcf5ef2aSThomas Huth         "i0", "i1", "i2", "i3", "i4", "i5", "i6", "i7",
5183fcf5ef2aSThomas Huth     };
5184fcf5ef2aSThomas Huth     static const char fregnames[32][4] = {
5185fcf5ef2aSThomas Huth         "f0", "f2", "f4", "f6", "f8", "f10", "f12", "f14",
5186fcf5ef2aSThomas Huth         "f16", "f18", "f20", "f22", "f24", "f26", "f28", "f30",
5187fcf5ef2aSThomas Huth         "f32", "f34", "f36", "f38", "f40", "f42", "f44", "f46",
5188fcf5ef2aSThomas Huth         "f48", "f50", "f52", "f54", "f56", "f58", "f60", "f62",
5189fcf5ef2aSThomas Huth     };
5190fcf5ef2aSThomas Huth 
5191d8c5b92fSRichard Henderson     static const struct { TCGv_i32 *ptr; int off; const char *name; } r32[] = {
5192d8c5b92fSRichard Henderson #ifdef TARGET_SPARC64
5193d8c5b92fSRichard Henderson         { &cpu_fprs, offsetof(CPUSPARCState, fprs), "fprs" },
5194d8c5b92fSRichard Henderson         { &cpu_fcc[0], offsetof(CPUSPARCState, fcc[0]), "fcc0" },
5195d8c5b92fSRichard Henderson         { &cpu_fcc[1], offsetof(CPUSPARCState, fcc[1]), "fcc1" },
5196d8c5b92fSRichard Henderson         { &cpu_fcc[2], offsetof(CPUSPARCState, fcc[2]), "fcc2" },
5197d8c5b92fSRichard Henderson         { &cpu_fcc[3], offsetof(CPUSPARCState, fcc[3]), "fcc3" },
5198d8c5b92fSRichard Henderson #else
5199d8c5b92fSRichard Henderson         { &cpu_fcc[0], offsetof(CPUSPARCState, fcc[0]), "fcc" },
5200d8c5b92fSRichard Henderson #endif
5201d8c5b92fSRichard Henderson     };
5202d8c5b92fSRichard Henderson 
5203fcf5ef2aSThomas Huth     static const struct { TCGv *ptr; int off; const char *name; } rtl[] = {
5204fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
5205fcf5ef2aSThomas Huth         { &cpu_gsr, offsetof(CPUSPARCState, gsr), "gsr" },
52062a1905c7SRichard Henderson         { &cpu_xcc_Z, offsetof(CPUSPARCState, xcc_Z), "xcc_Z" },
52072a1905c7SRichard Henderson         { &cpu_xcc_C, offsetof(CPUSPARCState, xcc_C), "xcc_C" },
5208fcf5ef2aSThomas Huth #endif
52092a1905c7SRichard Henderson         { &cpu_cc_N, offsetof(CPUSPARCState, cc_N), "cc_N" },
52102a1905c7SRichard Henderson         { &cpu_cc_V, offsetof(CPUSPARCState, cc_V), "cc_V" },
52112a1905c7SRichard Henderson         { &cpu_icc_Z, offsetof(CPUSPARCState, icc_Z), "icc_Z" },
52122a1905c7SRichard Henderson         { &cpu_icc_C, offsetof(CPUSPARCState, icc_C), "icc_C" },
5213fcf5ef2aSThomas Huth         { &cpu_cond, offsetof(CPUSPARCState, cond), "cond" },
5214fcf5ef2aSThomas Huth         { &cpu_pc, offsetof(CPUSPARCState, pc), "pc" },
5215fcf5ef2aSThomas Huth         { &cpu_npc, offsetof(CPUSPARCState, npc), "npc" },
5216fcf5ef2aSThomas Huth         { &cpu_y, offsetof(CPUSPARCState, y), "y" },
5217fcf5ef2aSThomas Huth         { &cpu_tbr, offsetof(CPUSPARCState, tbr), "tbr" },
5218fcf5ef2aSThomas Huth     };
5219fcf5ef2aSThomas Huth 
5220fcf5ef2aSThomas Huth     unsigned int i;
5221fcf5ef2aSThomas Huth 
5222ad75a51eSRichard Henderson     cpu_regwptr = tcg_global_mem_new_ptr(tcg_env,
5223fcf5ef2aSThomas Huth                                          offsetof(CPUSPARCState, regwptr),
5224fcf5ef2aSThomas Huth                                          "regwptr");
5225fcf5ef2aSThomas Huth 
5226d8c5b92fSRichard Henderson     for (i = 0; i < ARRAY_SIZE(r32); ++i) {
5227d8c5b92fSRichard Henderson         *r32[i].ptr = tcg_global_mem_new_i32(tcg_env, r32[i].off, r32[i].name);
5228d8c5b92fSRichard Henderson     }
5229d8c5b92fSRichard Henderson 
5230fcf5ef2aSThomas Huth     for (i = 0; i < ARRAY_SIZE(rtl); ++i) {
5231ad75a51eSRichard Henderson         *rtl[i].ptr = tcg_global_mem_new(tcg_env, rtl[i].off, rtl[i].name);
5232fcf5ef2aSThomas Huth     }
5233fcf5ef2aSThomas Huth 
5234f764718dSRichard Henderson     cpu_regs[0] = NULL;
5235fcf5ef2aSThomas Huth     for (i = 1; i < 8; ++i) {
5236ad75a51eSRichard Henderson         cpu_regs[i] = tcg_global_mem_new(tcg_env,
5237fcf5ef2aSThomas Huth                                          offsetof(CPUSPARCState, gregs[i]),
5238fcf5ef2aSThomas Huth                                          gregnames[i]);
5239fcf5ef2aSThomas Huth     }
5240fcf5ef2aSThomas Huth 
5241fcf5ef2aSThomas Huth     for (i = 8; i < 32; ++i) {
5242fcf5ef2aSThomas Huth         cpu_regs[i] = tcg_global_mem_new(cpu_regwptr,
5243fcf5ef2aSThomas Huth                                          (i - 8) * sizeof(target_ulong),
5244fcf5ef2aSThomas Huth                                          gregnames[i]);
5245fcf5ef2aSThomas Huth     }
5246fcf5ef2aSThomas Huth 
5247fcf5ef2aSThomas Huth     for (i = 0; i < TARGET_DPREGS; i++) {
5248ad75a51eSRichard Henderson         cpu_fpr[i] = tcg_global_mem_new_i64(tcg_env,
5249fcf5ef2aSThomas Huth                                             offsetof(CPUSPARCState, fpr[i]),
5250fcf5ef2aSThomas Huth                                             fregnames[i]);
5251fcf5ef2aSThomas Huth     }
5252fcf5ef2aSThomas Huth }
5253fcf5ef2aSThomas Huth 
5254f36aaa53SRichard Henderson void sparc_restore_state_to_opc(CPUState *cs,
5255f36aaa53SRichard Henderson                                 const TranslationBlock *tb,
5256f36aaa53SRichard Henderson                                 const uint64_t *data)
5257fcf5ef2aSThomas Huth {
525877976769SPhilippe Mathieu-Daudé     CPUSPARCState *env = cpu_env(cs);
5259fcf5ef2aSThomas Huth     target_ulong pc = data[0];
5260fcf5ef2aSThomas Huth     target_ulong npc = data[1];
5261fcf5ef2aSThomas Huth 
5262fcf5ef2aSThomas Huth     env->pc = pc;
5263fcf5ef2aSThomas Huth     if (npc == DYNAMIC_PC) {
5264fcf5ef2aSThomas Huth         /* dynamic NPC: already stored */
5265fcf5ef2aSThomas Huth     } else if (npc & JUMP_PC) {
5266fcf5ef2aSThomas Huth         /* jump PC: use 'cond' and the jump targets of the translation */
5267fcf5ef2aSThomas Huth         if (env->cond) {
5268fcf5ef2aSThomas Huth             env->npc = npc & ~3;
5269fcf5ef2aSThomas Huth         } else {
5270fcf5ef2aSThomas Huth             env->npc = pc + 4;
5271fcf5ef2aSThomas Huth         }
5272fcf5ef2aSThomas Huth     } else {
5273fcf5ef2aSThomas Huth         env->npc = npc;
5274fcf5ef2aSThomas Huth     }
5275fcf5ef2aSThomas Huth }
5276