xref: /openbmc/qemu/target/sparc/translate.c (revision c92948f22b0ef62d7b5a6a73e943a110f761273b)
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()
40*c92948f2SClé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()
48af25071cSRichard Henderson # define gen_helper_rdccr(D, E)                 qemu_build_not_reached()
495d617bfbSRichard Henderson # define gen_helper_rdcwp(D, E)                 qemu_build_not_reached()
5025524734SRichard Henderson # define gen_helper_restored(E)                 qemu_build_not_reached()
518f75b8a4SRichard Henderson # define gen_helper_retry(E)                    qemu_build_not_reached()
5225524734SRichard Henderson # define gen_helper_saved(E)                    qemu_build_not_reached()
530faef01bSRichard Henderson # define gen_helper_set_softint(E, S)           qemu_build_not_reached()
54af25071cSRichard Henderson # define gen_helper_tick_get_count(D, E, T, C)  qemu_build_not_reached()
559422278eSRichard Henderson # define gen_helper_tick_set_count(P, S)        qemu_build_not_reached()
56bb97f2f5SRichard Henderson # define gen_helper_tick_set_limit(P, S)        qemu_build_not_reached()
570faef01bSRichard Henderson # define gen_helper_wrccr(E, S)                 qemu_build_not_reached()
589422278eSRichard Henderson # define gen_helper_wrcwp(E, S)                 qemu_build_not_reached()
599422278eSRichard Henderson # define gen_helper_wrgl(E, S)                  qemu_build_not_reached()
600faef01bSRichard Henderson # define gen_helper_write_softint(E, S)         qemu_build_not_reached()
619422278eSRichard Henderson # define gen_helper_wrpil(E, S)                 qemu_build_not_reached()
629422278eSRichard Henderson # define gen_helper_wrpstate(E, S)              qemu_build_not_reached()
63e2fa6bd1SRichard Henderson # define gen_helper_fcmpeq16             ({ qemu_build_not_reached(); NULL; })
64e2fa6bd1SRichard Henderson # define gen_helper_fcmpeq32             ({ qemu_build_not_reached(); NULL; })
65e2fa6bd1SRichard Henderson # define gen_helper_fcmpgt16             ({ qemu_build_not_reached(); NULL; })
66e2fa6bd1SRichard Henderson # define gen_helper_fcmpgt32             ({ qemu_build_not_reached(); NULL; })
67e2fa6bd1SRichard Henderson # define gen_helper_fcmple16             ({ qemu_build_not_reached(); NULL; })
68e2fa6bd1SRichard Henderson # define gen_helper_fcmple32             ({ qemu_build_not_reached(); NULL; })
69e2fa6bd1SRichard Henderson # define gen_helper_fcmpne16             ({ qemu_build_not_reached(); NULL; })
70e2fa6bd1SRichard Henderson # define gen_helper_fcmpne32             ({ qemu_build_not_reached(); NULL; })
718aa418b3SRichard Henderson # define gen_helper_fdtox                ({ qemu_build_not_reached(); NULL; })
72e06c9f83SRichard Henderson # define gen_helper_fexpand              ({ qemu_build_not_reached(); NULL; })
73e06c9f83SRichard Henderson # define gen_helper_fmul8sux16           ({ qemu_build_not_reached(); NULL; })
74e06c9f83SRichard Henderson # define gen_helper_fmul8ulx16           ({ qemu_build_not_reached(); NULL; })
75e06c9f83SRichard Henderson # define gen_helper_fmul8x16al           ({ qemu_build_not_reached(); NULL; })
76e06c9f83SRichard Henderson # define gen_helper_fmul8x16au           ({ qemu_build_not_reached(); NULL; })
77e06c9f83SRichard Henderson # define gen_helper_fmul8x16             ({ qemu_build_not_reached(); NULL; })
78e06c9f83SRichard Henderson # define gen_helper_fmuld8sux16          ({ qemu_build_not_reached(); NULL; })
79e06c9f83SRichard Henderson # define gen_helper_fmuld8ulx16          ({ qemu_build_not_reached(); NULL; })
80e06c9f83SRichard Henderson # define gen_helper_fpmerge              ({ qemu_build_not_reached(); NULL; })
811617586fSRichard Henderson # define gen_helper_fqtox                ({ qemu_build_not_reached(); NULL; })
82199d43efSRichard Henderson # define gen_helper_fstox                ({ qemu_build_not_reached(); NULL; })
838aa418b3SRichard Henderson # define gen_helper_fxtod                ({ qemu_build_not_reached(); NULL; })
847b8e3e1aSRichard Henderson # define gen_helper_fxtoq                ({ qemu_build_not_reached(); NULL; })
85f4e18df5SRichard Henderson # define gen_helper_fxtos                ({ qemu_build_not_reached(); NULL; })
86afb04344SRichard Henderson # define gen_helper_pdist                ({ qemu_build_not_reached(); NULL; })
87668bb9b7SRichard Henderson # define MAXTL_MASK                             0
88af25071cSRichard Henderson #endif
89af25071cSRichard Henderson 
90633c4283SRichard Henderson /* Dynamic PC, must exit to main loop. */
91633c4283SRichard Henderson #define DYNAMIC_PC         1
92633c4283SRichard Henderson /* Dynamic PC, one of two values according to jump_pc[T2]. */
93633c4283SRichard Henderson #define JUMP_PC            2
94633c4283SRichard Henderson /* Dynamic PC, may lookup next TB. */
95633c4283SRichard Henderson #define DYNAMIC_PC_LOOKUP  3
96fcf5ef2aSThomas Huth 
9746bb0137SMark Cave-Ayland #define DISAS_EXIT  DISAS_TARGET_0
9846bb0137SMark Cave-Ayland 
99fcf5ef2aSThomas Huth /* global register indexes */
100fcf5ef2aSThomas Huth static TCGv_ptr cpu_regwptr;
101c9fa8e58SRichard Henderson static TCGv cpu_pc, cpu_npc;
102fcf5ef2aSThomas Huth static TCGv cpu_regs[32];
103fcf5ef2aSThomas Huth static TCGv cpu_y;
104fcf5ef2aSThomas Huth static TCGv cpu_tbr;
105fcf5ef2aSThomas Huth static TCGv cpu_cond;
1062a1905c7SRichard Henderson static TCGv cpu_cc_N;
1072a1905c7SRichard Henderson static TCGv cpu_cc_V;
1082a1905c7SRichard Henderson static TCGv cpu_icc_Z;
1092a1905c7SRichard Henderson static TCGv cpu_icc_C;
110fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
1112a1905c7SRichard Henderson static TCGv cpu_xcc_Z;
1122a1905c7SRichard Henderson static TCGv cpu_xcc_C;
1132a1905c7SRichard Henderson static TCGv_i32 cpu_fprs;
114fcf5ef2aSThomas Huth static TCGv cpu_gsr;
115fcf5ef2aSThomas Huth #else
116af25071cSRichard Henderson # define cpu_fprs               ({ qemu_build_not_reached(); (TCGv)NULL; })
117af25071cSRichard Henderson # define cpu_gsr                ({ qemu_build_not_reached(); (TCGv)NULL; })
118fcf5ef2aSThomas Huth #endif
1192a1905c7SRichard Henderson 
1202a1905c7SRichard Henderson #ifdef TARGET_SPARC64
1212a1905c7SRichard Henderson #define cpu_cc_Z  cpu_xcc_Z
1222a1905c7SRichard Henderson #define cpu_cc_C  cpu_xcc_C
1232a1905c7SRichard Henderson #else
1242a1905c7SRichard Henderson #define cpu_cc_Z  cpu_icc_Z
1252a1905c7SRichard Henderson #define cpu_cc_C  cpu_icc_C
1262a1905c7SRichard Henderson #define cpu_xcc_Z ({ qemu_build_not_reached(); NULL; })
1272a1905c7SRichard Henderson #define cpu_xcc_C ({ qemu_build_not_reached(); NULL; })
1282a1905c7SRichard Henderson #endif
1292a1905c7SRichard Henderson 
130fcf5ef2aSThomas Huth /* Floating point registers */
131fcf5ef2aSThomas Huth static TCGv_i64 cpu_fpr[TARGET_DPREGS];
132d8c5b92fSRichard Henderson static TCGv_i32 cpu_fcc[TARGET_FCCREGS];
133fcf5ef2aSThomas Huth 
134af25071cSRichard Henderson #define env_field_offsetof(X)     offsetof(CPUSPARCState, X)
135af25071cSRichard Henderson #ifdef TARGET_SPARC64
136cd6269f7SRichard Henderson # define env32_field_offsetof(X)  ({ qemu_build_not_reached(); 0; })
137af25071cSRichard Henderson # define env64_field_offsetof(X)  env_field_offsetof(X)
138af25071cSRichard Henderson #else
139cd6269f7SRichard Henderson # define env32_field_offsetof(X)  env_field_offsetof(X)
140af25071cSRichard Henderson # define env64_field_offsetof(X)  ({ qemu_build_not_reached(); 0; })
141af25071cSRichard Henderson #endif
142af25071cSRichard Henderson 
143533f042fSRichard Henderson typedef struct DisasCompare {
144533f042fSRichard Henderson     TCGCond cond;
145533f042fSRichard Henderson     TCGv c1;
146533f042fSRichard Henderson     int c2;
147533f042fSRichard Henderson } DisasCompare;
148533f042fSRichard Henderson 
149186e7890SRichard Henderson typedef struct DisasDelayException {
150186e7890SRichard Henderson     struct DisasDelayException *next;
151186e7890SRichard Henderson     TCGLabel *lab;
152186e7890SRichard Henderson     TCGv_i32 excp;
153186e7890SRichard Henderson     /* Saved state at parent insn. */
154186e7890SRichard Henderson     target_ulong pc;
155186e7890SRichard Henderson     target_ulong npc;
156186e7890SRichard Henderson } DisasDelayException;
157186e7890SRichard Henderson 
158fcf5ef2aSThomas Huth typedef struct DisasContext {
159af00be49SEmilio G. Cota     DisasContextBase base;
160fcf5ef2aSThomas Huth     target_ulong pc;    /* current Program Counter: integer or DYNAMIC_PC */
161fcf5ef2aSThomas Huth     target_ulong npc;   /* next PC: integer or DYNAMIC_PC or JUMP_PC */
162533f042fSRichard Henderson 
163533f042fSRichard Henderson     /* Used when JUMP_PC value is used. */
164533f042fSRichard Henderson     DisasCompare jump;
165533f042fSRichard Henderson     target_ulong jump_pc[2];
166533f042fSRichard Henderson 
167fcf5ef2aSThomas Huth     int mem_idx;
16889527e3aSRichard Henderson     bool cpu_cond_live;
169c9b459aaSArtyom Tarasenko     bool fpu_enabled;
170c9b459aaSArtyom Tarasenko     bool address_mask_32bit;
171c9b459aaSArtyom Tarasenko #ifndef CONFIG_USER_ONLY
172c9b459aaSArtyom Tarasenko     bool supervisor;
173c9b459aaSArtyom Tarasenko #ifdef TARGET_SPARC64
174c9b459aaSArtyom Tarasenko     bool hypervisor;
175c9b459aaSArtyom Tarasenko #endif
176c9b459aaSArtyom Tarasenko #endif
177c9b459aaSArtyom Tarasenko 
178fcf5ef2aSThomas Huth     sparc_def_t *def;
179fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
180fcf5ef2aSThomas Huth     int fprs_dirty;
181fcf5ef2aSThomas Huth     int asi;
182fcf5ef2aSThomas Huth #endif
183186e7890SRichard Henderson     DisasDelayException *delay_excp_list;
184fcf5ef2aSThomas Huth } DisasContext;
185fcf5ef2aSThomas Huth 
186fcf5ef2aSThomas Huth // This function uses non-native bit order
187fcf5ef2aSThomas Huth #define GET_FIELD(X, FROM, TO)                                  \
188fcf5ef2aSThomas Huth     ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))
189fcf5ef2aSThomas Huth 
190fcf5ef2aSThomas Huth // This function uses the order in the manuals, i.e. bit 0 is 2^0
191fcf5ef2aSThomas Huth #define GET_FIELD_SP(X, FROM, TO)               \
192fcf5ef2aSThomas Huth     GET_FIELD(X, 31 - (TO), 31 - (FROM))
193fcf5ef2aSThomas Huth 
194fcf5ef2aSThomas Huth #define GET_FIELDs(x,a,b) sign_extend (GET_FIELD(x,a,b), (b) - (a) + 1)
195fcf5ef2aSThomas Huth #define GET_FIELD_SPs(x,a,b) sign_extend (GET_FIELD_SP(x,a,b), ((b) - (a) + 1))
196fcf5ef2aSThomas Huth 
197fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
198fcf5ef2aSThomas Huth #define DFPREG(r) (((r & 1) << 5) | (r & 0x1e))
199fcf5ef2aSThomas Huth #define QFPREG(r) (((r & 1) << 5) | (r & 0x1c))
200fcf5ef2aSThomas Huth #else
201fcf5ef2aSThomas Huth #define DFPREG(r) (r & 0x1e)
202fcf5ef2aSThomas Huth #define QFPREG(r) (r & 0x1c)
203fcf5ef2aSThomas Huth #endif
204fcf5ef2aSThomas Huth 
205fcf5ef2aSThomas Huth #define UA2005_HTRAP_MASK 0xff
206fcf5ef2aSThomas Huth #define V8_TRAP_MASK 0x7f
207fcf5ef2aSThomas Huth 
208fcf5ef2aSThomas Huth #define IS_IMM (insn & (1<<13))
209fcf5ef2aSThomas Huth 
2100c2e96c1SRichard Henderson static void gen_update_fprs_dirty(DisasContext *dc, int rd)
211fcf5ef2aSThomas Huth {
212fcf5ef2aSThomas Huth #if defined(TARGET_SPARC64)
213fcf5ef2aSThomas Huth     int bit = (rd < 32) ? 1 : 2;
214fcf5ef2aSThomas Huth     /* If we know we've already set this bit within the TB,
215fcf5ef2aSThomas Huth        we can avoid setting it again.  */
216fcf5ef2aSThomas Huth     if (!(dc->fprs_dirty & bit)) {
217fcf5ef2aSThomas Huth         dc->fprs_dirty |= bit;
218fcf5ef2aSThomas Huth         tcg_gen_ori_i32(cpu_fprs, cpu_fprs, bit);
219fcf5ef2aSThomas Huth     }
220fcf5ef2aSThomas Huth #endif
221fcf5ef2aSThomas Huth }
222fcf5ef2aSThomas Huth 
223fcf5ef2aSThomas Huth /* floating point registers moves */
224fcf5ef2aSThomas Huth static TCGv_i32 gen_load_fpr_F(DisasContext *dc, unsigned int src)
225fcf5ef2aSThomas Huth {
22636ab4623SRichard Henderson     TCGv_i32 ret = tcg_temp_new_i32();
227dc41aa7dSRichard Henderson     if (src & 1) {
228dc41aa7dSRichard Henderson         tcg_gen_extrl_i64_i32(ret, cpu_fpr[src / 2]);
229dc41aa7dSRichard Henderson     } else {
230dc41aa7dSRichard Henderson         tcg_gen_extrh_i64_i32(ret, cpu_fpr[src / 2]);
231fcf5ef2aSThomas Huth     }
232dc41aa7dSRichard Henderson     return ret;
233fcf5ef2aSThomas Huth }
234fcf5ef2aSThomas Huth 
235fcf5ef2aSThomas Huth static void gen_store_fpr_F(DisasContext *dc, unsigned int dst, TCGv_i32 v)
236fcf5ef2aSThomas Huth {
2378e7bbc75SRichard Henderson     TCGv_i64 t = tcg_temp_new_i64();
2388e7bbc75SRichard Henderson 
2398e7bbc75SRichard Henderson     tcg_gen_extu_i32_i64(t, v);
240fcf5ef2aSThomas Huth     tcg_gen_deposit_i64(cpu_fpr[dst / 2], cpu_fpr[dst / 2], t,
241fcf5ef2aSThomas Huth                         (dst & 1 ? 0 : 32), 32);
242fcf5ef2aSThomas Huth     gen_update_fprs_dirty(dc, dst);
243fcf5ef2aSThomas Huth }
244fcf5ef2aSThomas Huth 
245fcf5ef2aSThomas Huth static TCGv_i64 gen_load_fpr_D(DisasContext *dc, unsigned int src)
246fcf5ef2aSThomas Huth {
247fcf5ef2aSThomas Huth     src = DFPREG(src);
248fcf5ef2aSThomas Huth     return cpu_fpr[src / 2];
249fcf5ef2aSThomas Huth }
250fcf5ef2aSThomas Huth 
251fcf5ef2aSThomas Huth static void gen_store_fpr_D(DisasContext *dc, unsigned int dst, TCGv_i64 v)
252fcf5ef2aSThomas Huth {
253fcf5ef2aSThomas Huth     dst = DFPREG(dst);
254fcf5ef2aSThomas Huth     tcg_gen_mov_i64(cpu_fpr[dst / 2], v);
255fcf5ef2aSThomas Huth     gen_update_fprs_dirty(dc, dst);
256fcf5ef2aSThomas Huth }
257fcf5ef2aSThomas Huth 
258fcf5ef2aSThomas Huth static TCGv_i64 gen_dest_fpr_D(DisasContext *dc, unsigned int dst)
259fcf5ef2aSThomas Huth {
260fcf5ef2aSThomas Huth     return cpu_fpr[DFPREG(dst) / 2];
261fcf5ef2aSThomas Huth }
262fcf5ef2aSThomas Huth 
26333ec4245SRichard Henderson static TCGv_i128 gen_load_fpr_Q(DisasContext *dc, unsigned int src)
26433ec4245SRichard Henderson {
26533ec4245SRichard Henderson     TCGv_i128 ret = tcg_temp_new_i128();
26633ec4245SRichard Henderson 
26733ec4245SRichard Henderson     src = QFPREG(src);
26833ec4245SRichard Henderson     tcg_gen_concat_i64_i128(ret, cpu_fpr[src / 2 + 1], cpu_fpr[src / 2]);
26933ec4245SRichard Henderson     return ret;
27033ec4245SRichard Henderson }
27133ec4245SRichard Henderson 
27233ec4245SRichard Henderson static void gen_store_fpr_Q(DisasContext *dc, unsigned int dst, TCGv_i128 v)
27333ec4245SRichard Henderson {
27433ec4245SRichard Henderson     dst = DFPREG(dst);
27533ec4245SRichard Henderson     tcg_gen_extr_i128_i64(cpu_fpr[dst / 2 + 1], cpu_fpr[dst / 2], v);
27633ec4245SRichard Henderson     gen_update_fprs_dirty(dc, dst);
27733ec4245SRichard Henderson }
27833ec4245SRichard Henderson 
279fcf5ef2aSThomas Huth /* moves */
280fcf5ef2aSThomas Huth #ifdef CONFIG_USER_ONLY
281fcf5ef2aSThomas Huth #define supervisor(dc) 0
282fcf5ef2aSThomas Huth #define hypervisor(dc) 0
283fcf5ef2aSThomas Huth #else
284fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
285c9b459aaSArtyom Tarasenko #define hypervisor(dc) (dc->hypervisor)
286c9b459aaSArtyom Tarasenko #define supervisor(dc) (dc->supervisor | dc->hypervisor)
287fcf5ef2aSThomas Huth #else
288c9b459aaSArtyom Tarasenko #define supervisor(dc) (dc->supervisor)
289668bb9b7SRichard Henderson #define hypervisor(dc) 0
290fcf5ef2aSThomas Huth #endif
291fcf5ef2aSThomas Huth #endif
292fcf5ef2aSThomas Huth 
293b1bc09eaSRichard Henderson #if !defined(TARGET_SPARC64)
294b1bc09eaSRichard Henderson # define AM_CHECK(dc)  false
295b1bc09eaSRichard Henderson #elif defined(TARGET_ABI32)
296b1bc09eaSRichard Henderson # define AM_CHECK(dc)  true
297b1bc09eaSRichard Henderson #elif defined(CONFIG_USER_ONLY)
298b1bc09eaSRichard Henderson # define AM_CHECK(dc)  false
299fcf5ef2aSThomas Huth #else
300b1bc09eaSRichard Henderson # define AM_CHECK(dc)  ((dc)->address_mask_32bit)
301fcf5ef2aSThomas Huth #endif
302fcf5ef2aSThomas Huth 
3030c2e96c1SRichard Henderson static void gen_address_mask(DisasContext *dc, TCGv addr)
304fcf5ef2aSThomas Huth {
305b1bc09eaSRichard Henderson     if (AM_CHECK(dc)) {
306fcf5ef2aSThomas Huth         tcg_gen_andi_tl(addr, addr, 0xffffffffULL);
307b1bc09eaSRichard Henderson     }
308fcf5ef2aSThomas Huth }
309fcf5ef2aSThomas Huth 
31023ada1b1SRichard Henderson static target_ulong address_mask_i(DisasContext *dc, target_ulong addr)
31123ada1b1SRichard Henderson {
31223ada1b1SRichard Henderson     return AM_CHECK(dc) ? (uint32_t)addr : addr;
31323ada1b1SRichard Henderson }
31423ada1b1SRichard Henderson 
3150c2e96c1SRichard Henderson static TCGv gen_load_gpr(DisasContext *dc, int reg)
316fcf5ef2aSThomas Huth {
317fcf5ef2aSThomas Huth     if (reg > 0) {
318fcf5ef2aSThomas Huth         assert(reg < 32);
319fcf5ef2aSThomas Huth         return cpu_regs[reg];
320fcf5ef2aSThomas Huth     } else {
32152123f14SRichard Henderson         TCGv t = tcg_temp_new();
322fcf5ef2aSThomas Huth         tcg_gen_movi_tl(t, 0);
323fcf5ef2aSThomas Huth         return t;
324fcf5ef2aSThomas Huth     }
325fcf5ef2aSThomas Huth }
326fcf5ef2aSThomas Huth 
3270c2e96c1SRichard Henderson static void gen_store_gpr(DisasContext *dc, int reg, TCGv v)
328fcf5ef2aSThomas Huth {
329fcf5ef2aSThomas Huth     if (reg > 0) {
330fcf5ef2aSThomas Huth         assert(reg < 32);
331fcf5ef2aSThomas Huth         tcg_gen_mov_tl(cpu_regs[reg], v);
332fcf5ef2aSThomas Huth     }
333fcf5ef2aSThomas Huth }
334fcf5ef2aSThomas Huth 
3350c2e96c1SRichard Henderson static TCGv gen_dest_gpr(DisasContext *dc, int reg)
336fcf5ef2aSThomas Huth {
337fcf5ef2aSThomas Huth     if (reg > 0) {
338fcf5ef2aSThomas Huth         assert(reg < 32);
339fcf5ef2aSThomas Huth         return cpu_regs[reg];
340fcf5ef2aSThomas Huth     } else {
34152123f14SRichard Henderson         return tcg_temp_new();
342fcf5ef2aSThomas Huth     }
343fcf5ef2aSThomas Huth }
344fcf5ef2aSThomas Huth 
3455645aa2eSRichard Henderson static bool use_goto_tb(DisasContext *s, target_ulong pc, target_ulong npc)
346fcf5ef2aSThomas Huth {
3475645aa2eSRichard Henderson     return translator_use_goto_tb(&s->base, pc) &&
3485645aa2eSRichard Henderson            translator_use_goto_tb(&s->base, npc);
349fcf5ef2aSThomas Huth }
350fcf5ef2aSThomas Huth 
3515645aa2eSRichard Henderson static void gen_goto_tb(DisasContext *s, int tb_num,
352fcf5ef2aSThomas Huth                         target_ulong pc, target_ulong npc)
353fcf5ef2aSThomas Huth {
354fcf5ef2aSThomas Huth     if (use_goto_tb(s, pc, npc))  {
355fcf5ef2aSThomas Huth         /* jump to same page: we can use a direct jump */
356fcf5ef2aSThomas Huth         tcg_gen_goto_tb(tb_num);
357fcf5ef2aSThomas Huth         tcg_gen_movi_tl(cpu_pc, pc);
358fcf5ef2aSThomas Huth         tcg_gen_movi_tl(cpu_npc, npc);
35907ea28b4SRichard Henderson         tcg_gen_exit_tb(s->base.tb, tb_num);
360fcf5ef2aSThomas Huth     } else {
361f67ccb2fSRichard Henderson         /* jump to another page: we can use an indirect jump */
362fcf5ef2aSThomas Huth         tcg_gen_movi_tl(cpu_pc, pc);
363fcf5ef2aSThomas Huth         tcg_gen_movi_tl(cpu_npc, npc);
364f67ccb2fSRichard Henderson         tcg_gen_lookup_and_goto_ptr();
365fcf5ef2aSThomas Huth     }
366fcf5ef2aSThomas Huth }
367fcf5ef2aSThomas Huth 
368b989ce73SRichard Henderson static TCGv gen_carry32(void)
369fcf5ef2aSThomas Huth {
370b989ce73SRichard Henderson     if (TARGET_LONG_BITS == 64) {
371b989ce73SRichard Henderson         TCGv t = tcg_temp_new();
372b989ce73SRichard Henderson         tcg_gen_extract_tl(t, cpu_icc_C, 32, 1);
373b989ce73SRichard Henderson         return t;
374b989ce73SRichard Henderson     }
375b989ce73SRichard Henderson     return cpu_icc_C;
376fcf5ef2aSThomas Huth }
377fcf5ef2aSThomas Huth 
378b989ce73SRichard Henderson static void gen_op_addcc_int(TCGv dst, TCGv src1, TCGv src2, TCGv cin)
379fcf5ef2aSThomas Huth {
380b989ce73SRichard Henderson     TCGv z = tcg_constant_tl(0);
381fcf5ef2aSThomas Huth 
382b989ce73SRichard Henderson     if (cin) {
383b989ce73SRichard Henderson         tcg_gen_add2_tl(cpu_cc_N, cpu_cc_C, src1, z, cin, z);
384b989ce73SRichard Henderson         tcg_gen_add2_tl(cpu_cc_N, cpu_cc_C, cpu_cc_N, cpu_cc_C, src2, z);
385b989ce73SRichard Henderson     } else {
386b989ce73SRichard Henderson         tcg_gen_add2_tl(cpu_cc_N, cpu_cc_C, src1, z, src2, z);
387b989ce73SRichard Henderson     }
388b989ce73SRichard Henderson     tcg_gen_xor_tl(cpu_cc_Z, src1, src2);
389b989ce73SRichard Henderson     tcg_gen_xor_tl(cpu_cc_V, cpu_cc_N, src2);
390b989ce73SRichard Henderson     tcg_gen_andc_tl(cpu_cc_V, cpu_cc_V, cpu_cc_Z);
391b989ce73SRichard Henderson     if (TARGET_LONG_BITS == 64) {
392b989ce73SRichard Henderson         /*
393b989ce73SRichard Henderson          * Carry-in to bit 32 is result ^ src1 ^ src2.
394b989ce73SRichard Henderson          * We already have the src xor term in Z, from computation of V.
395b989ce73SRichard Henderson          */
396b989ce73SRichard Henderson         tcg_gen_xor_tl(cpu_icc_C, cpu_cc_Z, cpu_cc_N);
397b989ce73SRichard Henderson         tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N);
398b989ce73SRichard Henderson     }
399b989ce73SRichard Henderson     tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N);
400b989ce73SRichard Henderson     tcg_gen_mov_tl(dst, cpu_cc_N);
401b989ce73SRichard Henderson }
402fcf5ef2aSThomas Huth 
403b989ce73SRichard Henderson static void gen_op_addcc(TCGv dst, TCGv src1, TCGv src2)
404b989ce73SRichard Henderson {
405b989ce73SRichard Henderson     gen_op_addcc_int(dst, src1, src2, NULL);
406b989ce73SRichard Henderson }
407fcf5ef2aSThomas Huth 
408b989ce73SRichard Henderson static void gen_op_taddcc(TCGv dst, TCGv src1, TCGv src2)
409b989ce73SRichard Henderson {
410b989ce73SRichard Henderson     TCGv t = tcg_temp_new();
411b989ce73SRichard Henderson 
412b989ce73SRichard Henderson     /* Save the tag bits around modification of dst. */
413b989ce73SRichard Henderson     tcg_gen_or_tl(t, src1, src2);
414b989ce73SRichard Henderson 
415b989ce73SRichard Henderson     gen_op_addcc(dst, src1, src2);
416b989ce73SRichard Henderson 
417b989ce73SRichard Henderson     /* Incorprate tag bits into icc.V */
418b989ce73SRichard Henderson     tcg_gen_andi_tl(t, t, 3);
419b989ce73SRichard Henderson     tcg_gen_neg_tl(t, t);
420b989ce73SRichard Henderson     tcg_gen_ext32u_tl(t, t);
421b989ce73SRichard Henderson     tcg_gen_or_tl(cpu_cc_V, cpu_cc_V, t);
422b989ce73SRichard Henderson }
423b989ce73SRichard Henderson 
424b989ce73SRichard Henderson static void gen_op_addc(TCGv dst, TCGv src1, TCGv src2)
425b989ce73SRichard Henderson {
426b989ce73SRichard Henderson     tcg_gen_add_tl(dst, src1, src2);
427b989ce73SRichard Henderson     tcg_gen_add_tl(dst, dst, gen_carry32());
428b989ce73SRichard Henderson }
429b989ce73SRichard Henderson 
430b989ce73SRichard Henderson static void gen_op_addccc(TCGv dst, TCGv src1, TCGv src2)
431b989ce73SRichard Henderson {
432b989ce73SRichard Henderson     gen_op_addcc_int(dst, src1, src2, gen_carry32());
433fcf5ef2aSThomas Huth }
434fcf5ef2aSThomas Huth 
435f828df74SRichard Henderson static void gen_op_subcc_int(TCGv dst, TCGv src1, TCGv src2, TCGv cin)
436fcf5ef2aSThomas Huth {
437f828df74SRichard Henderson     TCGv z = tcg_constant_tl(0);
438fcf5ef2aSThomas Huth 
439f828df74SRichard Henderson     if (cin) {
440f828df74SRichard Henderson         tcg_gen_sub2_tl(cpu_cc_N, cpu_cc_C, src1, z, cin, z);
441f828df74SRichard Henderson         tcg_gen_sub2_tl(cpu_cc_N, cpu_cc_C, cpu_cc_N, cpu_cc_C, src2, z);
442f828df74SRichard Henderson     } else {
443f828df74SRichard Henderson         tcg_gen_sub2_tl(cpu_cc_N, cpu_cc_C, src1, z, src2, z);
444f828df74SRichard Henderson     }
445f828df74SRichard Henderson     tcg_gen_neg_tl(cpu_cc_C, cpu_cc_C);
446f828df74SRichard Henderson     tcg_gen_xor_tl(cpu_cc_Z, src1, src2);
447f828df74SRichard Henderson     tcg_gen_xor_tl(cpu_cc_V, cpu_cc_N, src1);
448f828df74SRichard Henderson     tcg_gen_and_tl(cpu_cc_V, cpu_cc_V, cpu_cc_Z);
449f828df74SRichard Henderson #ifdef TARGET_SPARC64
450f828df74SRichard Henderson     tcg_gen_xor_tl(cpu_icc_C, cpu_cc_Z, cpu_cc_N);
451f828df74SRichard Henderson     tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N);
452fcf5ef2aSThomas Huth #endif
453f828df74SRichard Henderson     tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N);
454f828df74SRichard Henderson     tcg_gen_mov_tl(dst, cpu_cc_N);
455fcf5ef2aSThomas Huth }
456fcf5ef2aSThomas Huth 
457f828df74SRichard Henderson static void gen_op_subcc(TCGv dst, TCGv src1, TCGv src2)
458fcf5ef2aSThomas Huth {
459f828df74SRichard Henderson     gen_op_subcc_int(dst, src1, src2, NULL);
460fcf5ef2aSThomas Huth }
461fcf5ef2aSThomas Huth 
462f828df74SRichard Henderson static void gen_op_tsubcc(TCGv dst, TCGv src1, TCGv src2)
463fcf5ef2aSThomas Huth {
464f828df74SRichard Henderson     TCGv t = tcg_temp_new();
465fcf5ef2aSThomas Huth 
466f828df74SRichard Henderson     /* Save the tag bits around modification of dst. */
467f828df74SRichard Henderson     tcg_gen_or_tl(t, src1, src2);
468fcf5ef2aSThomas Huth 
469f828df74SRichard Henderson     gen_op_subcc(dst, src1, src2);
470f828df74SRichard Henderson 
471f828df74SRichard Henderson     /* Incorprate tag bits into icc.V */
472f828df74SRichard Henderson     tcg_gen_andi_tl(t, t, 3);
473f828df74SRichard Henderson     tcg_gen_neg_tl(t, t);
474f828df74SRichard Henderson     tcg_gen_ext32u_tl(t, t);
475f828df74SRichard Henderson     tcg_gen_or_tl(cpu_cc_V, cpu_cc_V, t);
476f828df74SRichard Henderson }
477f828df74SRichard Henderson 
478f828df74SRichard Henderson static void gen_op_subc(TCGv dst, TCGv src1, TCGv src2)
479f828df74SRichard Henderson {
480fcf5ef2aSThomas Huth     tcg_gen_sub_tl(dst, src1, src2);
481f828df74SRichard Henderson     tcg_gen_sub_tl(dst, dst, gen_carry32());
482fcf5ef2aSThomas Huth }
483fcf5ef2aSThomas Huth 
484f828df74SRichard Henderson static void gen_op_subccc(TCGv dst, TCGv src1, TCGv src2)
485dfebb950SRichard Henderson {
486f828df74SRichard Henderson     gen_op_subcc_int(dst, src1, src2, gen_carry32());
487dfebb950SRichard Henderson }
488dfebb950SRichard Henderson 
4890c2e96c1SRichard Henderson static void gen_op_mulscc(TCGv dst, TCGv src1, TCGv src2)
490fcf5ef2aSThomas Huth {
491b989ce73SRichard Henderson     TCGv zero = tcg_constant_tl(0);
49250280618SRichard Henderson     TCGv one = tcg_constant_tl(1);
493b989ce73SRichard Henderson     TCGv t_src1 = tcg_temp_new();
494b989ce73SRichard Henderson     TCGv t_src2 = tcg_temp_new();
495b989ce73SRichard Henderson     TCGv t0 = tcg_temp_new();
496fcf5ef2aSThomas Huth 
497b989ce73SRichard Henderson     tcg_gen_ext32u_tl(t_src1, src1);
498b989ce73SRichard Henderson     tcg_gen_ext32u_tl(t_src2, src2);
499fcf5ef2aSThomas Huth 
500b989ce73SRichard Henderson     /*
501b989ce73SRichard Henderson      * if (!(env->y & 1))
502b989ce73SRichard Henderson      *   src2 = 0;
503fcf5ef2aSThomas Huth      */
50450280618SRichard Henderson     tcg_gen_movcond_tl(TCG_COND_TSTEQ, t_src2, cpu_y, one, zero, t_src2);
505fcf5ef2aSThomas Huth 
506b989ce73SRichard Henderson     /*
507b989ce73SRichard Henderson      * b2 = src1 & 1;
508b989ce73SRichard Henderson      * y = (b2 << 31) | (y >> 1);
509b989ce73SRichard Henderson      */
5100b1183e3SPhilippe Mathieu-Daudé     tcg_gen_extract_tl(t0, cpu_y, 1, 31);
511b989ce73SRichard Henderson     tcg_gen_deposit_tl(cpu_y, t0, src1, 31, 1);
512fcf5ef2aSThomas Huth 
513fcf5ef2aSThomas Huth     // b1 = N ^ V;
5142a1905c7SRichard Henderson     tcg_gen_xor_tl(t0, cpu_cc_N, cpu_cc_V);
515fcf5ef2aSThomas Huth 
516b989ce73SRichard Henderson     /*
517b989ce73SRichard Henderson      * src1 = (b1 << 31) | (src1 >> 1)
518b989ce73SRichard Henderson      */
5192a1905c7SRichard Henderson     tcg_gen_andi_tl(t0, t0, 1u << 31);
520b989ce73SRichard Henderson     tcg_gen_shri_tl(t_src1, t_src1, 1);
521b989ce73SRichard Henderson     tcg_gen_or_tl(t_src1, t_src1, t0);
522fcf5ef2aSThomas Huth 
523b989ce73SRichard Henderson     gen_op_addcc(dst, t_src1, t_src2);
524fcf5ef2aSThomas Huth }
525fcf5ef2aSThomas Huth 
5260c2e96c1SRichard Henderson static void gen_op_multiply(TCGv dst, TCGv src1, TCGv src2, int sign_ext)
527fcf5ef2aSThomas Huth {
528fcf5ef2aSThomas Huth #if TARGET_LONG_BITS == 32
529fcf5ef2aSThomas Huth     if (sign_ext) {
530fcf5ef2aSThomas Huth         tcg_gen_muls2_tl(dst, cpu_y, src1, src2);
531fcf5ef2aSThomas Huth     } else {
532fcf5ef2aSThomas Huth         tcg_gen_mulu2_tl(dst, cpu_y, src1, src2);
533fcf5ef2aSThomas Huth     }
534fcf5ef2aSThomas Huth #else
535fcf5ef2aSThomas Huth     TCGv t0 = tcg_temp_new_i64();
536fcf5ef2aSThomas Huth     TCGv t1 = tcg_temp_new_i64();
537fcf5ef2aSThomas Huth 
538fcf5ef2aSThomas Huth     if (sign_ext) {
539fcf5ef2aSThomas Huth         tcg_gen_ext32s_i64(t0, src1);
540fcf5ef2aSThomas Huth         tcg_gen_ext32s_i64(t1, src2);
541fcf5ef2aSThomas Huth     } else {
542fcf5ef2aSThomas Huth         tcg_gen_ext32u_i64(t0, src1);
543fcf5ef2aSThomas Huth         tcg_gen_ext32u_i64(t1, src2);
544fcf5ef2aSThomas Huth     }
545fcf5ef2aSThomas Huth 
546fcf5ef2aSThomas Huth     tcg_gen_mul_i64(dst, t0, t1);
547fcf5ef2aSThomas Huth     tcg_gen_shri_i64(cpu_y, dst, 32);
548fcf5ef2aSThomas Huth #endif
549fcf5ef2aSThomas Huth }
550fcf5ef2aSThomas Huth 
5510c2e96c1SRichard Henderson static void gen_op_umul(TCGv dst, TCGv src1, TCGv src2)
552fcf5ef2aSThomas Huth {
553fcf5ef2aSThomas Huth     /* zero-extend truncated operands before multiplication */
554fcf5ef2aSThomas Huth     gen_op_multiply(dst, src1, src2, 0);
555fcf5ef2aSThomas Huth }
556fcf5ef2aSThomas Huth 
5570c2e96c1SRichard Henderson static void gen_op_smul(TCGv dst, TCGv src1, TCGv src2)
558fcf5ef2aSThomas Huth {
559fcf5ef2aSThomas Huth     /* sign-extend truncated operands before multiplication */
560fcf5ef2aSThomas Huth     gen_op_multiply(dst, src1, src2, 1);
561fcf5ef2aSThomas Huth }
562fcf5ef2aSThomas Huth 
563c2636853SRichard Henderson static void gen_op_sdiv(TCGv dst, TCGv src1, TCGv src2)
564c2636853SRichard Henderson {
56513260103SRichard Henderson #ifdef TARGET_SPARC64
566c2636853SRichard Henderson     gen_helper_sdiv(dst, tcg_env, src1, src2);
56713260103SRichard Henderson     tcg_gen_ext32s_tl(dst, dst);
56813260103SRichard Henderson #else
56913260103SRichard Henderson     TCGv_i64 t64 = tcg_temp_new_i64();
57013260103SRichard Henderson     gen_helper_sdiv(t64, tcg_env, src1, src2);
57113260103SRichard Henderson     tcg_gen_trunc_i64_tl(dst, t64);
57213260103SRichard Henderson #endif
573c2636853SRichard Henderson }
574c2636853SRichard Henderson 
575c2636853SRichard Henderson static void gen_op_udivcc(TCGv dst, TCGv src1, TCGv src2)
576c2636853SRichard Henderson {
57713260103SRichard Henderson     TCGv_i64 t64;
57813260103SRichard Henderson 
57913260103SRichard Henderson #ifdef TARGET_SPARC64
58013260103SRichard Henderson     t64 = cpu_cc_V;
58113260103SRichard Henderson #else
58213260103SRichard Henderson     t64 = tcg_temp_new_i64();
58313260103SRichard Henderson #endif
58413260103SRichard Henderson 
58513260103SRichard Henderson     gen_helper_udiv(t64, tcg_env, src1, src2);
58613260103SRichard Henderson 
58713260103SRichard Henderson #ifdef TARGET_SPARC64
58813260103SRichard Henderson     tcg_gen_ext32u_tl(cpu_cc_N, t64);
58913260103SRichard Henderson     tcg_gen_shri_tl(cpu_cc_V, t64, 32);
59013260103SRichard Henderson     tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N);
59113260103SRichard Henderson     tcg_gen_movi_tl(cpu_icc_C, 0);
59213260103SRichard Henderson #else
59313260103SRichard Henderson     tcg_gen_extr_i64_tl(cpu_cc_N, cpu_cc_V, t64);
59413260103SRichard Henderson #endif
59513260103SRichard Henderson     tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N);
59613260103SRichard Henderson     tcg_gen_movi_tl(cpu_cc_C, 0);
59713260103SRichard Henderson     tcg_gen_mov_tl(dst, cpu_cc_N);
598c2636853SRichard Henderson }
599c2636853SRichard Henderson 
600c2636853SRichard Henderson static void gen_op_sdivcc(TCGv dst, TCGv src1, TCGv src2)
601c2636853SRichard Henderson {
60213260103SRichard Henderson     TCGv_i64 t64;
60313260103SRichard Henderson 
60413260103SRichard Henderson #ifdef TARGET_SPARC64
60513260103SRichard Henderson     t64 = cpu_cc_V;
60613260103SRichard Henderson #else
60713260103SRichard Henderson     t64 = tcg_temp_new_i64();
60813260103SRichard Henderson #endif
60913260103SRichard Henderson 
61013260103SRichard Henderson     gen_helper_sdiv(t64, tcg_env, src1, src2);
61113260103SRichard Henderson 
61213260103SRichard Henderson #ifdef TARGET_SPARC64
61313260103SRichard Henderson     tcg_gen_ext32s_tl(cpu_cc_N, t64);
61413260103SRichard Henderson     tcg_gen_shri_tl(cpu_cc_V, t64, 32);
61513260103SRichard Henderson     tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N);
61613260103SRichard Henderson     tcg_gen_movi_tl(cpu_icc_C, 0);
61713260103SRichard Henderson #else
61813260103SRichard Henderson     tcg_gen_extr_i64_tl(cpu_cc_N, cpu_cc_V, t64);
61913260103SRichard Henderson #endif
62013260103SRichard Henderson     tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N);
62113260103SRichard Henderson     tcg_gen_movi_tl(cpu_cc_C, 0);
62213260103SRichard Henderson     tcg_gen_mov_tl(dst, cpu_cc_N);
623c2636853SRichard Henderson }
624c2636853SRichard Henderson 
625a9aba13dSRichard Henderson static void gen_op_taddcctv(TCGv dst, TCGv src1, TCGv src2)
626a9aba13dSRichard Henderson {
627a9aba13dSRichard Henderson     gen_helper_taddcctv(dst, tcg_env, src1, src2);
628a9aba13dSRichard Henderson }
629a9aba13dSRichard Henderson 
630a9aba13dSRichard Henderson static void gen_op_tsubcctv(TCGv dst, TCGv src1, TCGv src2)
631a9aba13dSRichard Henderson {
632a9aba13dSRichard Henderson     gen_helper_tsubcctv(dst, tcg_env, src1, src2);
633a9aba13dSRichard Henderson }
634a9aba13dSRichard Henderson 
6359c6ec5bcSRichard Henderson static void gen_op_popc(TCGv dst, TCGv src1, TCGv src2)
6369c6ec5bcSRichard Henderson {
6379c6ec5bcSRichard Henderson     tcg_gen_ctpop_tl(dst, src2);
6389c6ec5bcSRichard Henderson }
6399c6ec5bcSRichard Henderson 
64045bfed3bSRichard Henderson #ifndef TARGET_SPARC64
64145bfed3bSRichard Henderson static void gen_helper_array8(TCGv dst, TCGv src1, TCGv src2)
64245bfed3bSRichard Henderson {
64345bfed3bSRichard Henderson     g_assert_not_reached();
64445bfed3bSRichard Henderson }
64545bfed3bSRichard Henderson #endif
64645bfed3bSRichard Henderson 
64745bfed3bSRichard Henderson static void gen_op_array16(TCGv dst, TCGv src1, TCGv src2)
64845bfed3bSRichard Henderson {
64945bfed3bSRichard Henderson     gen_helper_array8(dst, src1, src2);
65045bfed3bSRichard Henderson     tcg_gen_shli_tl(dst, dst, 1);
65145bfed3bSRichard Henderson }
65245bfed3bSRichard Henderson 
65345bfed3bSRichard Henderson static void gen_op_array32(TCGv dst, TCGv src1, TCGv src2)
65445bfed3bSRichard Henderson {
65545bfed3bSRichard Henderson     gen_helper_array8(dst, src1, src2);
65645bfed3bSRichard Henderson     tcg_gen_shli_tl(dst, dst, 2);
65745bfed3bSRichard Henderson }
65845bfed3bSRichard Henderson 
6592f722641SRichard Henderson static void gen_op_fpack16(TCGv_i32 dst, TCGv_i64 src)
6602f722641SRichard Henderson {
6612f722641SRichard Henderson #ifdef TARGET_SPARC64
6622f722641SRichard Henderson     gen_helper_fpack16(dst, cpu_gsr, src);
6632f722641SRichard Henderson #else
6642f722641SRichard Henderson     g_assert_not_reached();
6652f722641SRichard Henderson #endif
6662f722641SRichard Henderson }
6672f722641SRichard Henderson 
6682f722641SRichard Henderson static void gen_op_fpackfix(TCGv_i32 dst, TCGv_i64 src)
6692f722641SRichard Henderson {
6702f722641SRichard Henderson #ifdef TARGET_SPARC64
6712f722641SRichard Henderson     gen_helper_fpackfix(dst, cpu_gsr, src);
6722f722641SRichard Henderson #else
6732f722641SRichard Henderson     g_assert_not_reached();
6742f722641SRichard Henderson #endif
6752f722641SRichard Henderson }
6762f722641SRichard Henderson 
6774b6edc0aSRichard Henderson static void gen_op_fpack32(TCGv_i64 dst, TCGv_i64 src1, TCGv_i64 src2)
6784b6edc0aSRichard Henderson {
6794b6edc0aSRichard Henderson #ifdef TARGET_SPARC64
6804b6edc0aSRichard Henderson     gen_helper_fpack32(dst, cpu_gsr, src1, src2);
6814b6edc0aSRichard Henderson #else
6824b6edc0aSRichard Henderson     g_assert_not_reached();
6834b6edc0aSRichard Henderson #endif
6844b6edc0aSRichard Henderson }
6854b6edc0aSRichard Henderson 
6864b6edc0aSRichard Henderson static void gen_op_faligndata(TCGv_i64 dst, TCGv_i64 s1, TCGv_i64 s2)
6874b6edc0aSRichard Henderson {
6884b6edc0aSRichard Henderson #ifdef TARGET_SPARC64
6894b6edc0aSRichard Henderson     TCGv t1, t2, shift;
6904b6edc0aSRichard Henderson 
6914b6edc0aSRichard Henderson     t1 = tcg_temp_new();
6924b6edc0aSRichard Henderson     t2 = tcg_temp_new();
6934b6edc0aSRichard Henderson     shift = tcg_temp_new();
6944b6edc0aSRichard Henderson 
6954b6edc0aSRichard Henderson     tcg_gen_andi_tl(shift, cpu_gsr, 7);
6964b6edc0aSRichard Henderson     tcg_gen_shli_tl(shift, shift, 3);
6974b6edc0aSRichard Henderson     tcg_gen_shl_tl(t1, s1, shift);
6984b6edc0aSRichard Henderson 
6994b6edc0aSRichard Henderson     /*
7004b6edc0aSRichard Henderson      * A shift of 64 does not produce 0 in TCG.  Divide this into a
7014b6edc0aSRichard Henderson      * shift of (up to 63) followed by a constant shift of 1.
7024b6edc0aSRichard Henderson      */
7034b6edc0aSRichard Henderson     tcg_gen_xori_tl(shift, shift, 63);
7044b6edc0aSRichard Henderson     tcg_gen_shr_tl(t2, s2, shift);
7054b6edc0aSRichard Henderson     tcg_gen_shri_tl(t2, t2, 1);
7064b6edc0aSRichard Henderson 
7074b6edc0aSRichard Henderson     tcg_gen_or_tl(dst, t1, t2);
7084b6edc0aSRichard Henderson #else
7094b6edc0aSRichard Henderson     g_assert_not_reached();
7104b6edc0aSRichard Henderson #endif
7114b6edc0aSRichard Henderson }
7124b6edc0aSRichard Henderson 
7134b6edc0aSRichard Henderson static void gen_op_bshuffle(TCGv_i64 dst, TCGv_i64 src1, TCGv_i64 src2)
7144b6edc0aSRichard Henderson {
7154b6edc0aSRichard Henderson #ifdef TARGET_SPARC64
7164b6edc0aSRichard Henderson     gen_helper_bshuffle(dst, cpu_gsr, src1, src2);
7174b6edc0aSRichard Henderson #else
7184b6edc0aSRichard Henderson     g_assert_not_reached();
7194b6edc0aSRichard Henderson #endif
7204b6edc0aSRichard Henderson }
7214b6edc0aSRichard Henderson 
72289527e3aSRichard Henderson static void finishing_insn(DisasContext *dc)
72389527e3aSRichard Henderson {
72489527e3aSRichard Henderson     /*
72589527e3aSRichard Henderson      * From here, there is no future path through an unwinding exception.
72689527e3aSRichard Henderson      * If the current insn cannot raise an exception, the computation of
72789527e3aSRichard Henderson      * cpu_cond may be able to be elided.
72889527e3aSRichard Henderson      */
72989527e3aSRichard Henderson     if (dc->cpu_cond_live) {
73089527e3aSRichard Henderson         tcg_gen_discard_tl(cpu_cond);
73189527e3aSRichard Henderson         dc->cpu_cond_live = false;
73289527e3aSRichard Henderson     }
73389527e3aSRichard Henderson }
73489527e3aSRichard Henderson 
7350c2e96c1SRichard Henderson static void gen_generic_branch(DisasContext *dc)
736fcf5ef2aSThomas Huth {
73700ab7e61SRichard Henderson     TCGv npc0 = tcg_constant_tl(dc->jump_pc[0]);
73800ab7e61SRichard Henderson     TCGv npc1 = tcg_constant_tl(dc->jump_pc[1]);
739533f042fSRichard Henderson     TCGv c2 = tcg_constant_tl(dc->jump.c2);
740fcf5ef2aSThomas Huth 
741533f042fSRichard Henderson     tcg_gen_movcond_tl(dc->jump.cond, cpu_npc, dc->jump.c1, c2, npc0, npc1);
742fcf5ef2aSThomas Huth }
743fcf5ef2aSThomas Huth 
744fcf5ef2aSThomas Huth /* call this function before using the condition register as it may
745fcf5ef2aSThomas Huth    have been set for a jump */
7460c2e96c1SRichard Henderson static void flush_cond(DisasContext *dc)
747fcf5ef2aSThomas Huth {
748fcf5ef2aSThomas Huth     if (dc->npc == JUMP_PC) {
749fcf5ef2aSThomas Huth         gen_generic_branch(dc);
75099c82c47SRichard Henderson         dc->npc = DYNAMIC_PC_LOOKUP;
751fcf5ef2aSThomas Huth     }
752fcf5ef2aSThomas Huth }
753fcf5ef2aSThomas Huth 
7540c2e96c1SRichard Henderson static void save_npc(DisasContext *dc)
755fcf5ef2aSThomas Huth {
756633c4283SRichard Henderson     if (dc->npc & 3) {
757633c4283SRichard Henderson         switch (dc->npc) {
758633c4283SRichard Henderson         case JUMP_PC:
759fcf5ef2aSThomas Huth             gen_generic_branch(dc);
76099c82c47SRichard Henderson             dc->npc = DYNAMIC_PC_LOOKUP;
761633c4283SRichard Henderson             break;
762633c4283SRichard Henderson         case DYNAMIC_PC:
763633c4283SRichard Henderson         case DYNAMIC_PC_LOOKUP:
764633c4283SRichard Henderson             break;
765633c4283SRichard Henderson         default:
766633c4283SRichard Henderson             g_assert_not_reached();
767633c4283SRichard Henderson         }
768633c4283SRichard Henderson     } else {
769fcf5ef2aSThomas Huth         tcg_gen_movi_tl(cpu_npc, dc->npc);
770fcf5ef2aSThomas Huth     }
771fcf5ef2aSThomas Huth }
772fcf5ef2aSThomas Huth 
7730c2e96c1SRichard Henderson static void save_state(DisasContext *dc)
774fcf5ef2aSThomas Huth {
775fcf5ef2aSThomas Huth     tcg_gen_movi_tl(cpu_pc, dc->pc);
776fcf5ef2aSThomas Huth     save_npc(dc);
777fcf5ef2aSThomas Huth }
778fcf5ef2aSThomas Huth 
779fcf5ef2aSThomas Huth static void gen_exception(DisasContext *dc, int which)
780fcf5ef2aSThomas Huth {
78189527e3aSRichard Henderson     finishing_insn(dc);
782fcf5ef2aSThomas Huth     save_state(dc);
783ad75a51eSRichard Henderson     gen_helper_raise_exception(tcg_env, tcg_constant_i32(which));
784af00be49SEmilio G. Cota     dc->base.is_jmp = DISAS_NORETURN;
785fcf5ef2aSThomas Huth }
786fcf5ef2aSThomas Huth 
787186e7890SRichard Henderson static TCGLabel *delay_exceptionv(DisasContext *dc, TCGv_i32 excp)
788fcf5ef2aSThomas Huth {
789186e7890SRichard Henderson     DisasDelayException *e = g_new0(DisasDelayException, 1);
790186e7890SRichard Henderson 
791186e7890SRichard Henderson     e->next = dc->delay_excp_list;
792186e7890SRichard Henderson     dc->delay_excp_list = e;
793186e7890SRichard Henderson 
794186e7890SRichard Henderson     e->lab = gen_new_label();
795186e7890SRichard Henderson     e->excp = excp;
796186e7890SRichard Henderson     e->pc = dc->pc;
797186e7890SRichard Henderson     /* Caller must have used flush_cond before branch. */
798186e7890SRichard Henderson     assert(e->npc != JUMP_PC);
799186e7890SRichard Henderson     e->npc = dc->npc;
800186e7890SRichard Henderson 
801186e7890SRichard Henderson     return e->lab;
802186e7890SRichard Henderson }
803186e7890SRichard Henderson 
804186e7890SRichard Henderson static TCGLabel *delay_exception(DisasContext *dc, int excp)
805186e7890SRichard Henderson {
806186e7890SRichard Henderson     return delay_exceptionv(dc, tcg_constant_i32(excp));
807186e7890SRichard Henderson }
808186e7890SRichard Henderson 
809186e7890SRichard Henderson static void gen_check_align(DisasContext *dc, TCGv addr, int mask)
810186e7890SRichard Henderson {
811186e7890SRichard Henderson     TCGv t = tcg_temp_new();
812186e7890SRichard Henderson     TCGLabel *lab;
813186e7890SRichard Henderson 
814186e7890SRichard Henderson     tcg_gen_andi_tl(t, addr, mask);
815186e7890SRichard Henderson 
816186e7890SRichard Henderson     flush_cond(dc);
817186e7890SRichard Henderson     lab = delay_exception(dc, TT_UNALIGNED);
818186e7890SRichard Henderson     tcg_gen_brcondi_tl(TCG_COND_NE, t, 0, lab);
819fcf5ef2aSThomas Huth }
820fcf5ef2aSThomas Huth 
8210c2e96c1SRichard Henderson static void gen_mov_pc_npc(DisasContext *dc)
822fcf5ef2aSThomas Huth {
82389527e3aSRichard Henderson     finishing_insn(dc);
82489527e3aSRichard Henderson 
825633c4283SRichard Henderson     if (dc->npc & 3) {
826633c4283SRichard Henderson         switch (dc->npc) {
827633c4283SRichard Henderson         case JUMP_PC:
828fcf5ef2aSThomas Huth             gen_generic_branch(dc);
829fcf5ef2aSThomas Huth             tcg_gen_mov_tl(cpu_pc, cpu_npc);
83099c82c47SRichard Henderson             dc->pc = DYNAMIC_PC_LOOKUP;
831633c4283SRichard Henderson             break;
832633c4283SRichard Henderson         case DYNAMIC_PC:
833633c4283SRichard Henderson         case DYNAMIC_PC_LOOKUP:
834fcf5ef2aSThomas Huth             tcg_gen_mov_tl(cpu_pc, cpu_npc);
835633c4283SRichard Henderson             dc->pc = dc->npc;
836633c4283SRichard Henderson             break;
837633c4283SRichard Henderson         default:
838633c4283SRichard Henderson             g_assert_not_reached();
839633c4283SRichard Henderson         }
840fcf5ef2aSThomas Huth     } else {
841fcf5ef2aSThomas Huth         dc->pc = dc->npc;
842fcf5ef2aSThomas Huth     }
843fcf5ef2aSThomas Huth }
844fcf5ef2aSThomas Huth 
845fcf5ef2aSThomas Huth static void gen_compare(DisasCompare *cmp, bool xcc, unsigned int cond,
846fcf5ef2aSThomas Huth                         DisasContext *dc)
847fcf5ef2aSThomas Huth {
848b597eedcSRichard Henderson     TCGv t1;
849fcf5ef2aSThomas Huth 
8502a1905c7SRichard Henderson     cmp->c1 = t1 = tcg_temp_new();
851c8507ebfSRichard Henderson     cmp->c2 = 0;
8522a1905c7SRichard Henderson 
8532a1905c7SRichard Henderson     switch (cond & 7) {
8542a1905c7SRichard Henderson     case 0x0: /* never */
8552a1905c7SRichard Henderson         cmp->cond = TCG_COND_NEVER;
856c8507ebfSRichard Henderson         cmp->c1 = tcg_constant_tl(0);
857fcf5ef2aSThomas Huth         break;
8582a1905c7SRichard Henderson 
8592a1905c7SRichard Henderson     case 0x1: /* eq: Z */
8602a1905c7SRichard Henderson         cmp->cond = TCG_COND_EQ;
8612a1905c7SRichard Henderson         if (TARGET_LONG_BITS == 32 || xcc) {
8622a1905c7SRichard Henderson             tcg_gen_mov_tl(t1, cpu_cc_Z);
8632a1905c7SRichard Henderson         } else {
8642a1905c7SRichard Henderson             tcg_gen_ext32u_tl(t1, cpu_icc_Z);
8652a1905c7SRichard Henderson         }
8662a1905c7SRichard Henderson         break;
8672a1905c7SRichard Henderson 
8682a1905c7SRichard Henderson     case 0x2: /* le: Z | (N ^ V) */
8692a1905c7SRichard Henderson         /*
8702a1905c7SRichard Henderson          * Simplify:
8712a1905c7SRichard Henderson          *   cc_Z || (N ^ V) < 0        NE
8722a1905c7SRichard Henderson          *   cc_Z && !((N ^ V) < 0)     EQ
8732a1905c7SRichard Henderson          *   cc_Z & ~((N ^ V) >> TLB)   EQ
8742a1905c7SRichard Henderson          */
8752a1905c7SRichard Henderson         cmp->cond = TCG_COND_EQ;
8762a1905c7SRichard Henderson         tcg_gen_xor_tl(t1, cpu_cc_N, cpu_cc_V);
8772a1905c7SRichard Henderson         tcg_gen_sextract_tl(t1, t1, xcc ? 63 : 31, 1);
8782a1905c7SRichard Henderson         tcg_gen_andc_tl(t1, xcc ? cpu_cc_Z : cpu_icc_Z, t1);
8792a1905c7SRichard Henderson         if (TARGET_LONG_BITS == 64 && !xcc) {
8802a1905c7SRichard Henderson             tcg_gen_ext32u_tl(t1, t1);
8812a1905c7SRichard Henderson         }
8822a1905c7SRichard Henderson         break;
8832a1905c7SRichard Henderson 
8842a1905c7SRichard Henderson     case 0x3: /* lt: N ^ V */
8852a1905c7SRichard Henderson         cmp->cond = TCG_COND_LT;
8862a1905c7SRichard Henderson         tcg_gen_xor_tl(t1, cpu_cc_N, cpu_cc_V);
8872a1905c7SRichard Henderson         if (TARGET_LONG_BITS == 64 && !xcc) {
8882a1905c7SRichard Henderson             tcg_gen_ext32s_tl(t1, t1);
8892a1905c7SRichard Henderson         }
8902a1905c7SRichard Henderson         break;
8912a1905c7SRichard Henderson 
8922a1905c7SRichard Henderson     case 0x4: /* leu: Z | C */
8932a1905c7SRichard Henderson         /*
8942a1905c7SRichard Henderson          * Simplify:
8952a1905c7SRichard Henderson          *   cc_Z == 0 || cc_C != 0     NE
8962a1905c7SRichard Henderson          *   cc_Z != 0 && cc_C == 0     EQ
8972a1905c7SRichard Henderson          *   cc_Z & (cc_C ? 0 : -1)     EQ
8982a1905c7SRichard Henderson          *   cc_Z & (cc_C - 1)          EQ
8992a1905c7SRichard Henderson          */
9002a1905c7SRichard Henderson         cmp->cond = TCG_COND_EQ;
9012a1905c7SRichard Henderson         if (TARGET_LONG_BITS == 32 || xcc) {
9022a1905c7SRichard Henderson             tcg_gen_subi_tl(t1, cpu_cc_C, 1);
9032a1905c7SRichard Henderson             tcg_gen_and_tl(t1, t1, cpu_cc_Z);
9042a1905c7SRichard Henderson         } else {
9052a1905c7SRichard Henderson             tcg_gen_extract_tl(t1, cpu_icc_C, 32, 1);
9062a1905c7SRichard Henderson             tcg_gen_subi_tl(t1, t1, 1);
9072a1905c7SRichard Henderson             tcg_gen_and_tl(t1, t1, cpu_icc_Z);
9082a1905c7SRichard Henderson             tcg_gen_ext32u_tl(t1, t1);
9092a1905c7SRichard Henderson         }
9102a1905c7SRichard Henderson         break;
9112a1905c7SRichard Henderson 
9122a1905c7SRichard Henderson     case 0x5: /* ltu: C */
9132a1905c7SRichard Henderson         cmp->cond = TCG_COND_NE;
9142a1905c7SRichard Henderson         if (TARGET_LONG_BITS == 32 || xcc) {
9152a1905c7SRichard Henderson             tcg_gen_mov_tl(t1, cpu_cc_C);
9162a1905c7SRichard Henderson         } else {
9172a1905c7SRichard Henderson             tcg_gen_extract_tl(t1, cpu_icc_C, 32, 1);
9182a1905c7SRichard Henderson         }
9192a1905c7SRichard Henderson         break;
9202a1905c7SRichard Henderson 
9212a1905c7SRichard Henderson     case 0x6: /* neg: N */
9222a1905c7SRichard Henderson         cmp->cond = TCG_COND_LT;
9232a1905c7SRichard Henderson         if (TARGET_LONG_BITS == 32 || xcc) {
9242a1905c7SRichard Henderson             tcg_gen_mov_tl(t1, cpu_cc_N);
9252a1905c7SRichard Henderson         } else {
9262a1905c7SRichard Henderson             tcg_gen_ext32s_tl(t1, cpu_cc_N);
9272a1905c7SRichard Henderson         }
9282a1905c7SRichard Henderson         break;
9292a1905c7SRichard Henderson 
9302a1905c7SRichard Henderson     case 0x7: /* vs: V */
9312a1905c7SRichard Henderson         cmp->cond = TCG_COND_LT;
9322a1905c7SRichard Henderson         if (TARGET_LONG_BITS == 32 || xcc) {
9332a1905c7SRichard Henderson             tcg_gen_mov_tl(t1, cpu_cc_V);
9342a1905c7SRichard Henderson         } else {
9352a1905c7SRichard Henderson             tcg_gen_ext32s_tl(t1, cpu_cc_V);
9362a1905c7SRichard Henderson         }
9372a1905c7SRichard Henderson         break;
9382a1905c7SRichard Henderson     }
9392a1905c7SRichard Henderson     if (cond & 8) {
9402a1905c7SRichard Henderson         cmp->cond = tcg_invert_cond(cmp->cond);
941fcf5ef2aSThomas Huth     }
942fcf5ef2aSThomas Huth }
943fcf5ef2aSThomas Huth 
944fcf5ef2aSThomas Huth static void gen_fcompare(DisasCompare *cmp, unsigned int cc, unsigned int cond)
945fcf5ef2aSThomas Huth {
946d8c5b92fSRichard Henderson     TCGv_i32 fcc = cpu_fcc[cc];
947d8c5b92fSRichard Henderson     TCGv_i32 c1 = fcc;
948d8c5b92fSRichard Henderson     int c2 = 0;
949d8c5b92fSRichard Henderson     TCGCond tcond;
950fcf5ef2aSThomas Huth 
951d8c5b92fSRichard Henderson     /*
952d8c5b92fSRichard Henderson      * FCC values:
953d8c5b92fSRichard Henderson      * 0 =
954d8c5b92fSRichard Henderson      * 1 <
955d8c5b92fSRichard Henderson      * 2 >
956d8c5b92fSRichard Henderson      * 3 unordered
957d8c5b92fSRichard Henderson      */
958d8c5b92fSRichard Henderson     switch (cond & 7) {
959d8c5b92fSRichard Henderson     case 0x0: /* fbn */
960d8c5b92fSRichard Henderson         tcond = TCG_COND_NEVER;
961fcf5ef2aSThomas Huth         break;
962d8c5b92fSRichard Henderson     case 0x1: /* fbne : !0 */
963d8c5b92fSRichard Henderson         tcond = TCG_COND_NE;
964fcf5ef2aSThomas Huth         break;
965d8c5b92fSRichard Henderson     case 0x2: /* fblg : 1 or 2 */
966d8c5b92fSRichard Henderson         /* fcc in {1,2} - 1 -> fcc in {0,1} */
967d8c5b92fSRichard Henderson         c1 = tcg_temp_new_i32();
968d8c5b92fSRichard Henderson         tcg_gen_addi_i32(c1, fcc, -1);
969d8c5b92fSRichard Henderson         c2 = 1;
970d8c5b92fSRichard Henderson         tcond = TCG_COND_LEU;
971fcf5ef2aSThomas Huth         break;
972d8c5b92fSRichard Henderson     case 0x3: /* fbul : 1 or 3 */
973d8c5b92fSRichard Henderson         c1 = tcg_temp_new_i32();
974d8c5b92fSRichard Henderson         tcg_gen_andi_i32(c1, fcc, 1);
975d8c5b92fSRichard Henderson         tcond = TCG_COND_NE;
976d8c5b92fSRichard Henderson         break;
977d8c5b92fSRichard Henderson     case 0x4: /* fbl  : 1 */
978d8c5b92fSRichard Henderson         c2 = 1;
979d8c5b92fSRichard Henderson         tcond = TCG_COND_EQ;
980d8c5b92fSRichard Henderson         break;
981d8c5b92fSRichard Henderson     case 0x5: /* fbug : 2 or 3 */
982d8c5b92fSRichard Henderson         c2 = 2;
983d8c5b92fSRichard Henderson         tcond = TCG_COND_GEU;
984d8c5b92fSRichard Henderson         break;
985d8c5b92fSRichard Henderson     case 0x6: /* fbg  : 2 */
986d8c5b92fSRichard Henderson         c2 = 2;
987d8c5b92fSRichard Henderson         tcond = TCG_COND_EQ;
988d8c5b92fSRichard Henderson         break;
989d8c5b92fSRichard Henderson     case 0x7: /* fbu  : 3 */
990d8c5b92fSRichard Henderson         c2 = 3;
991d8c5b92fSRichard Henderson         tcond = TCG_COND_EQ;
992fcf5ef2aSThomas Huth         break;
993fcf5ef2aSThomas Huth     }
994d8c5b92fSRichard Henderson     if (cond & 8) {
995d8c5b92fSRichard Henderson         tcond = tcg_invert_cond(tcond);
996fcf5ef2aSThomas Huth     }
997d8c5b92fSRichard Henderson 
998d8c5b92fSRichard Henderson     cmp->cond = tcond;
999d8c5b92fSRichard Henderson     cmp->c2 = c2;
1000d8c5b92fSRichard Henderson     cmp->c1 = tcg_temp_new();
1001d8c5b92fSRichard Henderson     tcg_gen_extu_i32_tl(cmp->c1, c1);
1002fcf5ef2aSThomas Huth }
1003fcf5ef2aSThomas Huth 
10042c4f56c9SRichard Henderson static bool gen_compare_reg(DisasCompare *cmp, int cond, TCGv r_src)
10052c4f56c9SRichard Henderson {
10062c4f56c9SRichard Henderson     static const TCGCond cond_reg[4] = {
1007ab9ffe98SRichard Henderson         TCG_COND_NEVER,  /* reserved */
1008fcf5ef2aSThomas Huth         TCG_COND_EQ,
1009fcf5ef2aSThomas Huth         TCG_COND_LE,
1010fcf5ef2aSThomas Huth         TCG_COND_LT,
1011fcf5ef2aSThomas Huth     };
10122c4f56c9SRichard Henderson     TCGCond tcond;
1013fcf5ef2aSThomas Huth 
10142c4f56c9SRichard Henderson     if ((cond & 3) == 0) {
10152c4f56c9SRichard Henderson         return false;
10162c4f56c9SRichard Henderson     }
10172c4f56c9SRichard Henderson     tcond = cond_reg[cond & 3];
10182c4f56c9SRichard Henderson     if (cond & 4) {
10192c4f56c9SRichard Henderson         tcond = tcg_invert_cond(tcond);
10202c4f56c9SRichard Henderson     }
10212c4f56c9SRichard Henderson 
10222c4f56c9SRichard Henderson     cmp->cond = tcond;
1023816f89b7SRichard Henderson     cmp->c1 = tcg_temp_new();
1024c8507ebfSRichard Henderson     cmp->c2 = 0;
1025816f89b7SRichard Henderson     tcg_gen_mov_tl(cmp->c1, r_src);
10262c4f56c9SRichard Henderson     return true;
1027fcf5ef2aSThomas Huth }
1028fcf5ef2aSThomas Huth 
1029baf3dbf2SRichard Henderson static void gen_op_clear_ieee_excp_and_FTT(void)
1030baf3dbf2SRichard Henderson {
10313590f01eSRichard Henderson     tcg_gen_st_i32(tcg_constant_i32(0), tcg_env,
10323590f01eSRichard Henderson                    offsetof(CPUSPARCState, fsr_cexc_ftt));
1033baf3dbf2SRichard Henderson }
1034baf3dbf2SRichard Henderson 
1035baf3dbf2SRichard Henderson static void gen_op_fmovs(TCGv_i32 dst, TCGv_i32 src)
1036baf3dbf2SRichard Henderson {
1037baf3dbf2SRichard Henderson     gen_op_clear_ieee_excp_and_FTT();
1038baf3dbf2SRichard Henderson     tcg_gen_mov_i32(dst, src);
1039baf3dbf2SRichard Henderson }
1040baf3dbf2SRichard Henderson 
1041baf3dbf2SRichard Henderson static void gen_op_fnegs(TCGv_i32 dst, TCGv_i32 src)
1042baf3dbf2SRichard Henderson {
1043baf3dbf2SRichard Henderson     gen_op_clear_ieee_excp_and_FTT();
1044daf457d4SRichard Henderson     tcg_gen_xori_i32(dst, src, 1u << 31);
1045baf3dbf2SRichard Henderson }
1046baf3dbf2SRichard Henderson 
1047baf3dbf2SRichard Henderson static void gen_op_fabss(TCGv_i32 dst, TCGv_i32 src)
1048baf3dbf2SRichard Henderson {
1049baf3dbf2SRichard Henderson     gen_op_clear_ieee_excp_and_FTT();
1050daf457d4SRichard Henderson     tcg_gen_andi_i32(dst, src, ~(1u << 31));
1051baf3dbf2SRichard Henderson }
1052baf3dbf2SRichard Henderson 
1053c6d83e4fSRichard Henderson static void gen_op_fmovd(TCGv_i64 dst, TCGv_i64 src)
1054c6d83e4fSRichard Henderson {
1055c6d83e4fSRichard Henderson     gen_op_clear_ieee_excp_and_FTT();
1056c6d83e4fSRichard Henderson     tcg_gen_mov_i64(dst, src);
1057c6d83e4fSRichard Henderson }
1058c6d83e4fSRichard Henderson 
1059c6d83e4fSRichard Henderson static void gen_op_fnegd(TCGv_i64 dst, TCGv_i64 src)
1060c6d83e4fSRichard Henderson {
1061c6d83e4fSRichard Henderson     gen_op_clear_ieee_excp_and_FTT();
1062daf457d4SRichard Henderson     tcg_gen_xori_i64(dst, src, 1ull << 63);
1063c6d83e4fSRichard Henderson }
1064c6d83e4fSRichard Henderson 
1065c6d83e4fSRichard Henderson static void gen_op_fabsd(TCGv_i64 dst, TCGv_i64 src)
1066c6d83e4fSRichard Henderson {
1067c6d83e4fSRichard Henderson     gen_op_clear_ieee_excp_and_FTT();
1068daf457d4SRichard Henderson     tcg_gen_andi_i64(dst, src, ~(1ull << 63));
1069daf457d4SRichard Henderson }
1070daf457d4SRichard Henderson 
1071daf457d4SRichard Henderson static void gen_op_fnegq(TCGv_i128 dst, TCGv_i128 src)
1072daf457d4SRichard Henderson {
1073daf457d4SRichard Henderson     TCGv_i64 l = tcg_temp_new_i64();
1074daf457d4SRichard Henderson     TCGv_i64 h = tcg_temp_new_i64();
1075daf457d4SRichard Henderson 
1076daf457d4SRichard Henderson     tcg_gen_extr_i128_i64(l, h, src);
1077daf457d4SRichard Henderson     tcg_gen_xori_i64(h, h, 1ull << 63);
1078daf457d4SRichard Henderson     tcg_gen_concat_i64_i128(dst, l, h);
1079daf457d4SRichard Henderson }
1080daf457d4SRichard Henderson 
1081daf457d4SRichard Henderson static void gen_op_fabsq(TCGv_i128 dst, TCGv_i128 src)
1082daf457d4SRichard Henderson {
1083daf457d4SRichard Henderson     TCGv_i64 l = tcg_temp_new_i64();
1084daf457d4SRichard Henderson     TCGv_i64 h = tcg_temp_new_i64();
1085daf457d4SRichard Henderson 
1086daf457d4SRichard Henderson     tcg_gen_extr_i128_i64(l, h, src);
1087daf457d4SRichard Henderson     tcg_gen_andi_i64(h, h, ~(1ull << 63));
1088daf457d4SRichard Henderson     tcg_gen_concat_i64_i128(dst, l, h);
1089c6d83e4fSRichard Henderson }
1090c6d83e4fSRichard Henderson 
10913590f01eSRichard Henderson static void gen_op_fpexception_im(DisasContext *dc, int ftt)
1092fcf5ef2aSThomas Huth {
10933590f01eSRichard Henderson     /*
10943590f01eSRichard Henderson      * CEXC is only set when succesfully completing an FPop,
10953590f01eSRichard Henderson      * or when raising FSR_FTT_IEEE_EXCP, i.e. check_ieee_exception.
10963590f01eSRichard Henderson      * Thus we can simply store FTT into this field.
10973590f01eSRichard Henderson      */
10983590f01eSRichard Henderson     tcg_gen_st_i32(tcg_constant_i32(ftt), tcg_env,
10993590f01eSRichard Henderson                    offsetof(CPUSPARCState, fsr_cexc_ftt));
1100fcf5ef2aSThomas Huth     gen_exception(dc, TT_FP_EXCP);
1101fcf5ef2aSThomas Huth }
1102fcf5ef2aSThomas Huth 
1103fcf5ef2aSThomas Huth static int gen_trap_ifnofpu(DisasContext *dc)
1104fcf5ef2aSThomas Huth {
1105fcf5ef2aSThomas Huth #if !defined(CONFIG_USER_ONLY)
1106fcf5ef2aSThomas Huth     if (!dc->fpu_enabled) {
1107fcf5ef2aSThomas Huth         gen_exception(dc, TT_NFPU_INSN);
1108fcf5ef2aSThomas Huth         return 1;
1109fcf5ef2aSThomas Huth     }
1110fcf5ef2aSThomas Huth #endif
1111fcf5ef2aSThomas Huth     return 0;
1112fcf5ef2aSThomas Huth }
1113fcf5ef2aSThomas Huth 
1114fcf5ef2aSThomas Huth /* asi moves */
1115fcf5ef2aSThomas Huth typedef enum {
1116fcf5ef2aSThomas Huth     GET_ASI_HELPER,
1117fcf5ef2aSThomas Huth     GET_ASI_EXCP,
1118fcf5ef2aSThomas Huth     GET_ASI_DIRECT,
1119fcf5ef2aSThomas Huth     GET_ASI_DTWINX,
1120fcf5ef2aSThomas Huth     GET_ASI_BLOCK,
1121fcf5ef2aSThomas Huth     GET_ASI_SHORT,
1122fcf5ef2aSThomas Huth     GET_ASI_BCOPY,
1123fcf5ef2aSThomas Huth     GET_ASI_BFILL,
1124fcf5ef2aSThomas Huth } ASIType;
1125fcf5ef2aSThomas Huth 
1126fcf5ef2aSThomas Huth typedef struct {
1127fcf5ef2aSThomas Huth     ASIType type;
1128fcf5ef2aSThomas Huth     int asi;
1129fcf5ef2aSThomas Huth     int mem_idx;
113014776ab5STony Nguyen     MemOp memop;
1131fcf5ef2aSThomas Huth } DisasASI;
1132fcf5ef2aSThomas Huth 
1133811cc0b0SRichard Henderson /*
1134811cc0b0SRichard Henderson  * Build DisasASI.
1135811cc0b0SRichard Henderson  * For asi == -1, treat as non-asi.
1136811cc0b0SRichard Henderson  * For ask == -2, treat as immediate offset (v8 error, v9 %asi).
1137811cc0b0SRichard Henderson  */
1138811cc0b0SRichard Henderson static DisasASI resolve_asi(DisasContext *dc, int asi, MemOp memop)
1139fcf5ef2aSThomas Huth {
1140fcf5ef2aSThomas Huth     ASIType type = GET_ASI_HELPER;
1141fcf5ef2aSThomas Huth     int mem_idx = dc->mem_idx;
1142fcf5ef2aSThomas Huth 
1143811cc0b0SRichard Henderson     if (asi == -1) {
1144811cc0b0SRichard Henderson         /* Artificial "non-asi" case. */
1145811cc0b0SRichard Henderson         type = GET_ASI_DIRECT;
1146811cc0b0SRichard Henderson         goto done;
1147811cc0b0SRichard Henderson     }
1148811cc0b0SRichard Henderson 
1149fcf5ef2aSThomas Huth #ifndef TARGET_SPARC64
1150fcf5ef2aSThomas Huth     /* Before v9, all asis are immediate and privileged.  */
1151811cc0b0SRichard Henderson     if (asi < 0) {
1152fcf5ef2aSThomas Huth         gen_exception(dc, TT_ILL_INSN);
1153fcf5ef2aSThomas Huth         type = GET_ASI_EXCP;
1154fcf5ef2aSThomas Huth     } else if (supervisor(dc)
1155fcf5ef2aSThomas Huth                /* Note that LEON accepts ASI_USERDATA in user mode, for
1156fcf5ef2aSThomas Huth                   use with CASA.  Also note that previous versions of
1157fcf5ef2aSThomas Huth                   QEMU allowed (and old versions of gcc emitted) ASI_P
1158fcf5ef2aSThomas Huth                   for LEON, which is incorrect.  */
1159fcf5ef2aSThomas Huth                || (asi == ASI_USERDATA
1160fcf5ef2aSThomas Huth                    && (dc->def->features & CPU_FEATURE_CASA))) {
1161fcf5ef2aSThomas Huth         switch (asi) {
1162fcf5ef2aSThomas Huth         case ASI_USERDATA:   /* User data access */
1163fcf5ef2aSThomas Huth             mem_idx = MMU_USER_IDX;
1164fcf5ef2aSThomas Huth             type = GET_ASI_DIRECT;
1165fcf5ef2aSThomas Huth             break;
1166fcf5ef2aSThomas Huth         case ASI_KERNELDATA: /* Supervisor data access */
1167fcf5ef2aSThomas Huth             mem_idx = MMU_KERNEL_IDX;
1168fcf5ef2aSThomas Huth             type = GET_ASI_DIRECT;
1169fcf5ef2aSThomas Huth             break;
1170fcf5ef2aSThomas Huth         case ASI_M_BYPASS:    /* MMU passthrough */
1171fcf5ef2aSThomas Huth         case ASI_LEON_BYPASS: /* LEON MMU passthrough */
1172fcf5ef2aSThomas Huth             mem_idx = MMU_PHYS_IDX;
1173fcf5ef2aSThomas Huth             type = GET_ASI_DIRECT;
1174fcf5ef2aSThomas Huth             break;
1175fcf5ef2aSThomas Huth         case ASI_M_BCOPY: /* Block copy, sta access */
1176fcf5ef2aSThomas Huth             mem_idx = MMU_KERNEL_IDX;
1177fcf5ef2aSThomas Huth             type = GET_ASI_BCOPY;
1178fcf5ef2aSThomas Huth             break;
1179fcf5ef2aSThomas Huth         case ASI_M_BFILL: /* Block fill, stda access */
1180fcf5ef2aSThomas Huth             mem_idx = MMU_KERNEL_IDX;
1181fcf5ef2aSThomas Huth             type = GET_ASI_BFILL;
1182fcf5ef2aSThomas Huth             break;
1183fcf5ef2aSThomas Huth         }
11846e10f37cSKONRAD Frederic 
11856e10f37cSKONRAD Frederic         /* MMU_PHYS_IDX is used when the MMU is disabled to passthrough the
11866e10f37cSKONRAD Frederic          * permissions check in get_physical_address(..).
11876e10f37cSKONRAD Frederic          */
11886e10f37cSKONRAD Frederic         mem_idx = (dc->mem_idx == MMU_PHYS_IDX) ? MMU_PHYS_IDX : mem_idx;
1189fcf5ef2aSThomas Huth     } else {
1190fcf5ef2aSThomas Huth         gen_exception(dc, TT_PRIV_INSN);
1191fcf5ef2aSThomas Huth         type = GET_ASI_EXCP;
1192fcf5ef2aSThomas Huth     }
1193fcf5ef2aSThomas Huth #else
1194811cc0b0SRichard Henderson     if (asi < 0) {
1195fcf5ef2aSThomas Huth         asi = dc->asi;
1196fcf5ef2aSThomas Huth     }
1197fcf5ef2aSThomas Huth     /* With v9, all asis below 0x80 are privileged.  */
1198fcf5ef2aSThomas Huth     /* ??? We ought to check cpu_has_hypervisor, but we didn't copy
1199fcf5ef2aSThomas Huth        down that bit into DisasContext.  For the moment that's ok,
1200fcf5ef2aSThomas Huth        since the direct implementations below doesn't have any ASIs
1201fcf5ef2aSThomas Huth        in the restricted [0x30, 0x7f] range, and the check will be
1202fcf5ef2aSThomas Huth        done properly in the helper.  */
1203fcf5ef2aSThomas Huth     if (!supervisor(dc) && asi < 0x80) {
1204fcf5ef2aSThomas Huth         gen_exception(dc, TT_PRIV_ACT);
1205fcf5ef2aSThomas Huth         type = GET_ASI_EXCP;
1206fcf5ef2aSThomas Huth     } else {
1207fcf5ef2aSThomas Huth         switch (asi) {
1208fcf5ef2aSThomas Huth         case ASI_REAL:      /* Bypass */
1209fcf5ef2aSThomas Huth         case ASI_REAL_IO:   /* Bypass, non-cacheable */
1210fcf5ef2aSThomas Huth         case ASI_REAL_L:    /* Bypass LE */
1211fcf5ef2aSThomas Huth         case ASI_REAL_IO_L: /* Bypass, non-cacheable LE */
1212fcf5ef2aSThomas Huth         case ASI_TWINX_REAL:   /* Real address, twinx */
1213fcf5ef2aSThomas Huth         case ASI_TWINX_REAL_L: /* Real address, twinx, LE */
1214fcf5ef2aSThomas Huth         case ASI_QUAD_LDD_PHYS:
1215fcf5ef2aSThomas Huth         case ASI_QUAD_LDD_PHYS_L:
1216fcf5ef2aSThomas Huth             mem_idx = MMU_PHYS_IDX;
1217fcf5ef2aSThomas Huth             break;
1218fcf5ef2aSThomas Huth         case ASI_N:  /* Nucleus */
1219fcf5ef2aSThomas Huth         case ASI_NL: /* Nucleus LE */
1220fcf5ef2aSThomas Huth         case ASI_TWINX_N:
1221fcf5ef2aSThomas Huth         case ASI_TWINX_NL:
1222fcf5ef2aSThomas Huth         case ASI_NUCLEUS_QUAD_LDD:
1223fcf5ef2aSThomas Huth         case ASI_NUCLEUS_QUAD_LDD_L:
12249a10756dSArtyom Tarasenko             if (hypervisor(dc)) {
122584f8f587SArtyom Tarasenko                 mem_idx = MMU_PHYS_IDX;
12269a10756dSArtyom Tarasenko             } else {
1227fcf5ef2aSThomas Huth                 mem_idx = MMU_NUCLEUS_IDX;
12289a10756dSArtyom Tarasenko             }
1229fcf5ef2aSThomas Huth             break;
1230fcf5ef2aSThomas Huth         case ASI_AIUP:  /* As if user primary */
1231fcf5ef2aSThomas Huth         case ASI_AIUPL: /* As if user primary LE */
1232fcf5ef2aSThomas Huth         case ASI_TWINX_AIUP:
1233fcf5ef2aSThomas Huth         case ASI_TWINX_AIUP_L:
1234fcf5ef2aSThomas Huth         case ASI_BLK_AIUP_4V:
1235fcf5ef2aSThomas Huth         case ASI_BLK_AIUP_L_4V:
1236fcf5ef2aSThomas Huth         case ASI_BLK_AIUP:
1237fcf5ef2aSThomas Huth         case ASI_BLK_AIUPL:
1238fcf5ef2aSThomas Huth             mem_idx = MMU_USER_IDX;
1239fcf5ef2aSThomas Huth             break;
1240fcf5ef2aSThomas Huth         case ASI_AIUS:  /* As if user secondary */
1241fcf5ef2aSThomas Huth         case ASI_AIUSL: /* As if user secondary LE */
1242fcf5ef2aSThomas Huth         case ASI_TWINX_AIUS:
1243fcf5ef2aSThomas Huth         case ASI_TWINX_AIUS_L:
1244fcf5ef2aSThomas Huth         case ASI_BLK_AIUS_4V:
1245fcf5ef2aSThomas Huth         case ASI_BLK_AIUS_L_4V:
1246fcf5ef2aSThomas Huth         case ASI_BLK_AIUS:
1247fcf5ef2aSThomas Huth         case ASI_BLK_AIUSL:
1248fcf5ef2aSThomas Huth             mem_idx = MMU_USER_SECONDARY_IDX;
1249fcf5ef2aSThomas Huth             break;
1250fcf5ef2aSThomas Huth         case ASI_S:  /* Secondary */
1251fcf5ef2aSThomas Huth         case ASI_SL: /* Secondary LE */
1252fcf5ef2aSThomas Huth         case ASI_TWINX_S:
1253fcf5ef2aSThomas Huth         case ASI_TWINX_SL:
1254fcf5ef2aSThomas Huth         case ASI_BLK_COMMIT_S:
1255fcf5ef2aSThomas Huth         case ASI_BLK_S:
1256fcf5ef2aSThomas Huth         case ASI_BLK_SL:
1257fcf5ef2aSThomas Huth         case ASI_FL8_S:
1258fcf5ef2aSThomas Huth         case ASI_FL8_SL:
1259fcf5ef2aSThomas Huth         case ASI_FL16_S:
1260fcf5ef2aSThomas Huth         case ASI_FL16_SL:
1261fcf5ef2aSThomas Huth             if (mem_idx == MMU_USER_IDX) {
1262fcf5ef2aSThomas Huth                 mem_idx = MMU_USER_SECONDARY_IDX;
1263fcf5ef2aSThomas Huth             } else if (mem_idx == MMU_KERNEL_IDX) {
1264fcf5ef2aSThomas Huth                 mem_idx = MMU_KERNEL_SECONDARY_IDX;
1265fcf5ef2aSThomas Huth             }
1266fcf5ef2aSThomas Huth             break;
1267fcf5ef2aSThomas Huth         case ASI_P:  /* Primary */
1268fcf5ef2aSThomas Huth         case ASI_PL: /* Primary LE */
1269fcf5ef2aSThomas Huth         case ASI_TWINX_P:
1270fcf5ef2aSThomas Huth         case ASI_TWINX_PL:
1271fcf5ef2aSThomas Huth         case ASI_BLK_COMMIT_P:
1272fcf5ef2aSThomas Huth         case ASI_BLK_P:
1273fcf5ef2aSThomas Huth         case ASI_BLK_PL:
1274fcf5ef2aSThomas Huth         case ASI_FL8_P:
1275fcf5ef2aSThomas Huth         case ASI_FL8_PL:
1276fcf5ef2aSThomas Huth         case ASI_FL16_P:
1277fcf5ef2aSThomas Huth         case ASI_FL16_PL:
1278fcf5ef2aSThomas Huth             break;
1279fcf5ef2aSThomas Huth         }
1280fcf5ef2aSThomas Huth         switch (asi) {
1281fcf5ef2aSThomas Huth         case ASI_REAL:
1282fcf5ef2aSThomas Huth         case ASI_REAL_IO:
1283fcf5ef2aSThomas Huth         case ASI_REAL_L:
1284fcf5ef2aSThomas Huth         case ASI_REAL_IO_L:
1285fcf5ef2aSThomas Huth         case ASI_N:
1286fcf5ef2aSThomas Huth         case ASI_NL:
1287fcf5ef2aSThomas Huth         case ASI_AIUP:
1288fcf5ef2aSThomas Huth         case ASI_AIUPL:
1289fcf5ef2aSThomas Huth         case ASI_AIUS:
1290fcf5ef2aSThomas Huth         case ASI_AIUSL:
1291fcf5ef2aSThomas Huth         case ASI_S:
1292fcf5ef2aSThomas Huth         case ASI_SL:
1293fcf5ef2aSThomas Huth         case ASI_P:
1294fcf5ef2aSThomas Huth         case ASI_PL:
1295fcf5ef2aSThomas Huth             type = GET_ASI_DIRECT;
1296fcf5ef2aSThomas Huth             break;
1297fcf5ef2aSThomas Huth         case ASI_TWINX_REAL:
1298fcf5ef2aSThomas Huth         case ASI_TWINX_REAL_L:
1299fcf5ef2aSThomas Huth         case ASI_TWINX_N:
1300fcf5ef2aSThomas Huth         case ASI_TWINX_NL:
1301fcf5ef2aSThomas Huth         case ASI_TWINX_AIUP:
1302fcf5ef2aSThomas Huth         case ASI_TWINX_AIUP_L:
1303fcf5ef2aSThomas Huth         case ASI_TWINX_AIUS:
1304fcf5ef2aSThomas Huth         case ASI_TWINX_AIUS_L:
1305fcf5ef2aSThomas Huth         case ASI_TWINX_P:
1306fcf5ef2aSThomas Huth         case ASI_TWINX_PL:
1307fcf5ef2aSThomas Huth         case ASI_TWINX_S:
1308fcf5ef2aSThomas Huth         case ASI_TWINX_SL:
1309fcf5ef2aSThomas Huth         case ASI_QUAD_LDD_PHYS:
1310fcf5ef2aSThomas Huth         case ASI_QUAD_LDD_PHYS_L:
1311fcf5ef2aSThomas Huth         case ASI_NUCLEUS_QUAD_LDD:
1312fcf5ef2aSThomas Huth         case ASI_NUCLEUS_QUAD_LDD_L:
1313fcf5ef2aSThomas Huth             type = GET_ASI_DTWINX;
1314fcf5ef2aSThomas Huth             break;
1315fcf5ef2aSThomas Huth         case ASI_BLK_COMMIT_P:
1316fcf5ef2aSThomas Huth         case ASI_BLK_COMMIT_S:
1317fcf5ef2aSThomas Huth         case ASI_BLK_AIUP_4V:
1318fcf5ef2aSThomas Huth         case ASI_BLK_AIUP_L_4V:
1319fcf5ef2aSThomas Huth         case ASI_BLK_AIUP:
1320fcf5ef2aSThomas Huth         case ASI_BLK_AIUPL:
1321fcf5ef2aSThomas Huth         case ASI_BLK_AIUS_4V:
1322fcf5ef2aSThomas Huth         case ASI_BLK_AIUS_L_4V:
1323fcf5ef2aSThomas Huth         case ASI_BLK_AIUS:
1324fcf5ef2aSThomas Huth         case ASI_BLK_AIUSL:
1325fcf5ef2aSThomas Huth         case ASI_BLK_S:
1326fcf5ef2aSThomas Huth         case ASI_BLK_SL:
1327fcf5ef2aSThomas Huth         case ASI_BLK_P:
1328fcf5ef2aSThomas Huth         case ASI_BLK_PL:
1329fcf5ef2aSThomas Huth             type = GET_ASI_BLOCK;
1330fcf5ef2aSThomas Huth             break;
1331fcf5ef2aSThomas Huth         case ASI_FL8_S:
1332fcf5ef2aSThomas Huth         case ASI_FL8_SL:
1333fcf5ef2aSThomas Huth         case ASI_FL8_P:
1334fcf5ef2aSThomas Huth         case ASI_FL8_PL:
1335fcf5ef2aSThomas Huth             memop = MO_UB;
1336fcf5ef2aSThomas Huth             type = GET_ASI_SHORT;
1337fcf5ef2aSThomas Huth             break;
1338fcf5ef2aSThomas Huth         case ASI_FL16_S:
1339fcf5ef2aSThomas Huth         case ASI_FL16_SL:
1340fcf5ef2aSThomas Huth         case ASI_FL16_P:
1341fcf5ef2aSThomas Huth         case ASI_FL16_PL:
1342fcf5ef2aSThomas Huth             memop = MO_TEUW;
1343fcf5ef2aSThomas Huth             type = GET_ASI_SHORT;
1344fcf5ef2aSThomas Huth             break;
1345fcf5ef2aSThomas Huth         }
1346fcf5ef2aSThomas Huth         /* The little-endian asis all have bit 3 set.  */
1347fcf5ef2aSThomas Huth         if (asi & 8) {
1348fcf5ef2aSThomas Huth             memop ^= MO_BSWAP;
1349fcf5ef2aSThomas Huth         }
1350fcf5ef2aSThomas Huth     }
1351fcf5ef2aSThomas Huth #endif
1352fcf5ef2aSThomas Huth 
1353811cc0b0SRichard Henderson  done:
1354fcf5ef2aSThomas Huth     return (DisasASI){ type, asi, mem_idx, memop };
1355fcf5ef2aSThomas Huth }
1356fcf5ef2aSThomas Huth 
1357a76779eeSRichard Henderson #if defined(CONFIG_USER_ONLY) && !defined(TARGET_SPARC64)
1358a76779eeSRichard Henderson static void gen_helper_ld_asi(TCGv_i64 r, TCGv_env e, TCGv a,
1359a76779eeSRichard Henderson                               TCGv_i32 asi, TCGv_i32 mop)
1360a76779eeSRichard Henderson {
1361a76779eeSRichard Henderson     g_assert_not_reached();
1362a76779eeSRichard Henderson }
1363a76779eeSRichard Henderson 
1364a76779eeSRichard Henderson static void gen_helper_st_asi(TCGv_env e, TCGv a, TCGv_i64 r,
1365a76779eeSRichard Henderson                               TCGv_i32 asi, TCGv_i32 mop)
1366a76779eeSRichard Henderson {
1367a76779eeSRichard Henderson     g_assert_not_reached();
1368a76779eeSRichard Henderson }
1369a76779eeSRichard Henderson #endif
1370a76779eeSRichard Henderson 
137142071fc1SRichard Henderson static void gen_ld_asi(DisasContext *dc, DisasASI *da, TCGv dst, TCGv addr)
1372fcf5ef2aSThomas Huth {
1373c03a0fd1SRichard Henderson     switch (da->type) {
1374fcf5ef2aSThomas Huth     case GET_ASI_EXCP:
1375fcf5ef2aSThomas Huth         break;
1376fcf5ef2aSThomas Huth     case GET_ASI_DTWINX: /* Reserved for ldda.  */
1377fcf5ef2aSThomas Huth         gen_exception(dc, TT_ILL_INSN);
1378fcf5ef2aSThomas Huth         break;
1379fcf5ef2aSThomas Huth     case GET_ASI_DIRECT:
1380c03a0fd1SRichard Henderson         tcg_gen_qemu_ld_tl(dst, addr, da->mem_idx, da->memop | MO_ALIGN);
1381fcf5ef2aSThomas Huth         break;
1382fcf5ef2aSThomas Huth     default:
1383fcf5ef2aSThomas Huth         {
1384c03a0fd1SRichard Henderson             TCGv_i32 r_asi = tcg_constant_i32(da->asi);
1385c03a0fd1SRichard Henderson             TCGv_i32 r_mop = tcg_constant_i32(da->memop | MO_ALIGN);
1386fcf5ef2aSThomas Huth 
1387fcf5ef2aSThomas Huth             save_state(dc);
1388fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
1389ad75a51eSRichard Henderson             gen_helper_ld_asi(dst, tcg_env, addr, r_asi, r_mop);
1390fcf5ef2aSThomas Huth #else
1391fcf5ef2aSThomas Huth             {
1392fcf5ef2aSThomas Huth                 TCGv_i64 t64 = tcg_temp_new_i64();
1393ad75a51eSRichard Henderson                 gen_helper_ld_asi(t64, tcg_env, addr, r_asi, r_mop);
1394fcf5ef2aSThomas Huth                 tcg_gen_trunc_i64_tl(dst, t64);
1395fcf5ef2aSThomas Huth             }
1396fcf5ef2aSThomas Huth #endif
1397fcf5ef2aSThomas Huth         }
1398fcf5ef2aSThomas Huth         break;
1399fcf5ef2aSThomas Huth     }
1400fcf5ef2aSThomas Huth }
1401fcf5ef2aSThomas Huth 
140242071fc1SRichard Henderson static void gen_st_asi(DisasContext *dc, DisasASI *da, TCGv src, TCGv addr)
1403c03a0fd1SRichard Henderson {
1404c03a0fd1SRichard Henderson     switch (da->type) {
1405fcf5ef2aSThomas Huth     case GET_ASI_EXCP:
1406fcf5ef2aSThomas Huth         break;
1407c03a0fd1SRichard Henderson 
1408fcf5ef2aSThomas Huth     case GET_ASI_DTWINX: /* Reserved for stda.  */
1409c03a0fd1SRichard Henderson         if (TARGET_LONG_BITS == 32) {
1410fcf5ef2aSThomas Huth             gen_exception(dc, TT_ILL_INSN);
1411fcf5ef2aSThomas Huth             break;
1412c03a0fd1SRichard Henderson         } else if (!(dc->def->features & CPU_FEATURE_HYPV)) {
14133390537bSArtyom Tarasenko             /* Pre OpenSPARC CPUs don't have these */
14143390537bSArtyom Tarasenko             gen_exception(dc, TT_ILL_INSN);
1415fcf5ef2aSThomas Huth             break;
1416c03a0fd1SRichard Henderson         }
1417c03a0fd1SRichard Henderson         /* In OpenSPARC T1+ CPUs TWINX ASIs in store are ST_BLKINIT_ ASIs */
1418c03a0fd1SRichard Henderson         /* fall through */
1419c03a0fd1SRichard Henderson 
1420c03a0fd1SRichard Henderson     case GET_ASI_DIRECT:
1421c03a0fd1SRichard Henderson         tcg_gen_qemu_st_tl(src, addr, da->mem_idx, da->memop | MO_ALIGN);
1422c03a0fd1SRichard Henderson         break;
1423c03a0fd1SRichard Henderson 
1424fcf5ef2aSThomas Huth     case GET_ASI_BCOPY:
1425c03a0fd1SRichard Henderson         assert(TARGET_LONG_BITS == 32);
142698271007SRichard Henderson         /*
142798271007SRichard Henderson          * Copy 32 bytes from the address in SRC to ADDR.
142898271007SRichard Henderson          *
142998271007SRichard Henderson          * From Ross RT625 hyperSPARC manual, section 4.6:
143098271007SRichard Henderson          * "Block Copy and Block Fill will work only on cache line boundaries."
143198271007SRichard Henderson          *
143298271007SRichard Henderson          * It does not specify if an unaliged address is truncated or trapped.
143398271007SRichard Henderson          * Previous qemu behaviour was to truncate to 4 byte alignment, which
143498271007SRichard Henderson          * is obviously wrong.  The only place I can see this used is in the
143598271007SRichard Henderson          * Linux kernel which begins with page alignment, advancing by 32,
143698271007SRichard Henderson          * so is always aligned.  Assume truncation as the simpler option.
143798271007SRichard Henderson          *
143898271007SRichard Henderson          * Since the loads and stores are paired, allow the copy to happen
143998271007SRichard Henderson          * in the host endianness.  The copy need not be atomic.
144098271007SRichard Henderson          */
1441fcf5ef2aSThomas Huth         {
144298271007SRichard Henderson             MemOp mop = MO_128 | MO_ATOM_IFALIGN_PAIR;
1443fcf5ef2aSThomas Huth             TCGv saddr = tcg_temp_new();
1444fcf5ef2aSThomas Huth             TCGv daddr = tcg_temp_new();
144598271007SRichard Henderson             TCGv_i128 tmp = tcg_temp_new_i128();
1446fcf5ef2aSThomas Huth 
144798271007SRichard Henderson             tcg_gen_andi_tl(saddr, src, -32);
144898271007SRichard Henderson             tcg_gen_andi_tl(daddr, addr, -32);
144998271007SRichard Henderson             tcg_gen_qemu_ld_i128(tmp, saddr, da->mem_idx, mop);
145098271007SRichard Henderson             tcg_gen_qemu_st_i128(tmp, daddr, da->mem_idx, mop);
145198271007SRichard Henderson             tcg_gen_addi_tl(saddr, saddr, 16);
145298271007SRichard Henderson             tcg_gen_addi_tl(daddr, daddr, 16);
145398271007SRichard Henderson             tcg_gen_qemu_ld_i128(tmp, saddr, da->mem_idx, mop);
145498271007SRichard Henderson             tcg_gen_qemu_st_i128(tmp, daddr, da->mem_idx, mop);
1455fcf5ef2aSThomas Huth         }
1456fcf5ef2aSThomas Huth         break;
1457c03a0fd1SRichard Henderson 
1458fcf5ef2aSThomas Huth     default:
1459fcf5ef2aSThomas Huth         {
1460c03a0fd1SRichard Henderson             TCGv_i32 r_asi = tcg_constant_i32(da->asi);
1461c03a0fd1SRichard Henderson             TCGv_i32 r_mop = tcg_constant_i32(da->memop | MO_ALIGN);
1462fcf5ef2aSThomas Huth 
1463fcf5ef2aSThomas Huth             save_state(dc);
1464fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
1465ad75a51eSRichard Henderson             gen_helper_st_asi(tcg_env, addr, src, r_asi, r_mop);
1466fcf5ef2aSThomas Huth #else
1467fcf5ef2aSThomas Huth             {
1468fcf5ef2aSThomas Huth                 TCGv_i64 t64 = tcg_temp_new_i64();
1469fcf5ef2aSThomas Huth                 tcg_gen_extu_tl_i64(t64, src);
1470ad75a51eSRichard Henderson                 gen_helper_st_asi(tcg_env, addr, t64, r_asi, r_mop);
1471fcf5ef2aSThomas Huth             }
1472fcf5ef2aSThomas Huth #endif
1473fcf5ef2aSThomas Huth 
1474fcf5ef2aSThomas Huth             /* A write to a TLB register may alter page maps.  End the TB. */
1475fcf5ef2aSThomas Huth             dc->npc = DYNAMIC_PC;
1476fcf5ef2aSThomas Huth         }
1477fcf5ef2aSThomas Huth         break;
1478fcf5ef2aSThomas Huth     }
1479fcf5ef2aSThomas Huth }
1480fcf5ef2aSThomas Huth 
1481dca544b9SRichard Henderson static void gen_swap_asi(DisasContext *dc, DisasASI *da,
1482c03a0fd1SRichard Henderson                          TCGv dst, TCGv src, TCGv addr)
1483c03a0fd1SRichard Henderson {
1484c03a0fd1SRichard Henderson     switch (da->type) {
1485c03a0fd1SRichard Henderson     case GET_ASI_EXCP:
1486c03a0fd1SRichard Henderson         break;
1487c03a0fd1SRichard Henderson     case GET_ASI_DIRECT:
1488dca544b9SRichard Henderson         tcg_gen_atomic_xchg_tl(dst, addr, src,
1489dca544b9SRichard Henderson                                da->mem_idx, da->memop | MO_ALIGN);
1490c03a0fd1SRichard Henderson         break;
1491c03a0fd1SRichard Henderson     default:
1492c03a0fd1SRichard Henderson         /* ??? Should be DAE_invalid_asi.  */
1493c03a0fd1SRichard Henderson         gen_exception(dc, TT_DATA_ACCESS);
1494c03a0fd1SRichard Henderson         break;
1495c03a0fd1SRichard Henderson     }
1496c03a0fd1SRichard Henderson }
1497c03a0fd1SRichard Henderson 
1498d0a11d25SRichard Henderson static void gen_cas_asi(DisasContext *dc, DisasASI *da,
1499c03a0fd1SRichard Henderson                         TCGv oldv, TCGv newv, TCGv cmpv, TCGv addr)
1500c03a0fd1SRichard Henderson {
1501c03a0fd1SRichard Henderson     switch (da->type) {
1502fcf5ef2aSThomas Huth     case GET_ASI_EXCP:
1503c03a0fd1SRichard Henderson         return;
1504fcf5ef2aSThomas Huth     case GET_ASI_DIRECT:
1505c03a0fd1SRichard Henderson         tcg_gen_atomic_cmpxchg_tl(oldv, addr, cmpv, newv,
1506c03a0fd1SRichard Henderson                                   da->mem_idx, da->memop | MO_ALIGN);
1507fcf5ef2aSThomas Huth         break;
1508fcf5ef2aSThomas Huth     default:
1509fcf5ef2aSThomas Huth         /* ??? Should be DAE_invalid_asi.  */
1510fcf5ef2aSThomas Huth         gen_exception(dc, TT_DATA_ACCESS);
1511fcf5ef2aSThomas Huth         break;
1512fcf5ef2aSThomas Huth     }
1513fcf5ef2aSThomas Huth }
1514fcf5ef2aSThomas Huth 
1515cf07cd1eSRichard Henderson static void gen_ldstub_asi(DisasContext *dc, DisasASI *da, TCGv dst, TCGv addr)
1516c03a0fd1SRichard Henderson {
1517c03a0fd1SRichard Henderson     switch (da->type) {
1518fcf5ef2aSThomas Huth     case GET_ASI_EXCP:
1519fcf5ef2aSThomas Huth         break;
1520fcf5ef2aSThomas Huth     case GET_ASI_DIRECT:
1521cf07cd1eSRichard Henderson         tcg_gen_atomic_xchg_tl(dst, addr, tcg_constant_tl(0xff),
1522cf07cd1eSRichard Henderson                                da->mem_idx, MO_UB);
1523fcf5ef2aSThomas Huth         break;
1524fcf5ef2aSThomas Huth     default:
15253db010c3SRichard Henderson         /* ??? In theory, this should be raise DAE_invalid_asi.
15263db010c3SRichard Henderson            But the SS-20 roms do ldstuba [%l0] #ASI_M_CTL, %o1.  */
1527af00be49SEmilio G. Cota         if (tb_cflags(dc->base.tb) & CF_PARALLEL) {
1528ad75a51eSRichard Henderson             gen_helper_exit_atomic(tcg_env);
15293db010c3SRichard Henderson         } else {
1530c03a0fd1SRichard Henderson             TCGv_i32 r_asi = tcg_constant_i32(da->asi);
153100ab7e61SRichard Henderson             TCGv_i32 r_mop = tcg_constant_i32(MO_UB);
15323db010c3SRichard Henderson             TCGv_i64 s64, t64;
15333db010c3SRichard Henderson 
15343db010c3SRichard Henderson             save_state(dc);
15353db010c3SRichard Henderson             t64 = tcg_temp_new_i64();
1536ad75a51eSRichard Henderson             gen_helper_ld_asi(t64, tcg_env, addr, r_asi, r_mop);
15373db010c3SRichard Henderson 
153800ab7e61SRichard Henderson             s64 = tcg_constant_i64(0xff);
1539ad75a51eSRichard Henderson             gen_helper_st_asi(tcg_env, addr, s64, r_asi, r_mop);
15403db010c3SRichard Henderson 
15413db010c3SRichard Henderson             tcg_gen_trunc_i64_tl(dst, t64);
15423db010c3SRichard Henderson 
15433db010c3SRichard Henderson             /* End the TB.  */
15443db010c3SRichard Henderson             dc->npc = DYNAMIC_PC;
15453db010c3SRichard Henderson         }
1546fcf5ef2aSThomas Huth         break;
1547fcf5ef2aSThomas Huth     }
1548fcf5ef2aSThomas Huth }
1549fcf5ef2aSThomas Huth 
1550287b1152SRichard Henderson static void gen_ldf_asi(DisasContext *dc, DisasASI *da, MemOp orig_size,
15513259b9e2SRichard Henderson                         TCGv addr, int rd)
1552fcf5ef2aSThomas Huth {
15533259b9e2SRichard Henderson     MemOp memop = da->memop;
15543259b9e2SRichard Henderson     MemOp size = memop & MO_SIZE;
1555fcf5ef2aSThomas Huth     TCGv_i32 d32;
1556fcf5ef2aSThomas Huth     TCGv_i64 d64;
1557287b1152SRichard Henderson     TCGv addr_tmp;
1558fcf5ef2aSThomas Huth 
15593259b9e2SRichard Henderson     /* TODO: Use 128-bit load/store below. */
15603259b9e2SRichard Henderson     if (size == MO_128) {
15613259b9e2SRichard Henderson         memop = (memop & ~MO_SIZE) | MO_64;
15623259b9e2SRichard Henderson     }
15633259b9e2SRichard Henderson 
15643259b9e2SRichard Henderson     switch (da->type) {
1565fcf5ef2aSThomas Huth     case GET_ASI_EXCP:
1566fcf5ef2aSThomas Huth         break;
1567fcf5ef2aSThomas Huth 
1568fcf5ef2aSThomas Huth     case GET_ASI_DIRECT:
15693259b9e2SRichard Henderson         memop |= MO_ALIGN_4;
1570fcf5ef2aSThomas Huth         switch (size) {
15713259b9e2SRichard Henderson         case MO_32:
1572388a6465SRichard Henderson             d32 = tcg_temp_new_i32();
15733259b9e2SRichard Henderson             tcg_gen_qemu_ld_i32(d32, addr, da->mem_idx, memop);
1574fcf5ef2aSThomas Huth             gen_store_fpr_F(dc, rd, d32);
1575fcf5ef2aSThomas Huth             break;
15763259b9e2SRichard Henderson 
15773259b9e2SRichard Henderson         case MO_64:
15783259b9e2SRichard Henderson             tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2], addr, da->mem_idx, memop);
1579fcf5ef2aSThomas Huth             break;
15803259b9e2SRichard Henderson 
15813259b9e2SRichard Henderson         case MO_128:
1582fcf5ef2aSThomas Huth             d64 = tcg_temp_new_i64();
15833259b9e2SRichard Henderson             tcg_gen_qemu_ld_i64(d64, addr, da->mem_idx, memop);
1584287b1152SRichard Henderson             addr_tmp = tcg_temp_new();
1585287b1152SRichard Henderson             tcg_gen_addi_tl(addr_tmp, addr, 8);
1586287b1152SRichard Henderson             tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2 + 1], addr_tmp, da->mem_idx, memop);
1587fcf5ef2aSThomas Huth             tcg_gen_mov_i64(cpu_fpr[rd / 2], d64);
1588fcf5ef2aSThomas Huth             break;
1589fcf5ef2aSThomas Huth         default:
1590fcf5ef2aSThomas Huth             g_assert_not_reached();
1591fcf5ef2aSThomas Huth         }
1592fcf5ef2aSThomas Huth         break;
1593fcf5ef2aSThomas Huth 
1594fcf5ef2aSThomas Huth     case GET_ASI_BLOCK:
1595fcf5ef2aSThomas Huth         /* Valid for lddfa on aligned registers only.  */
15963259b9e2SRichard Henderson         if (orig_size == MO_64 && (rd & 7) == 0) {
1597fcf5ef2aSThomas Huth             /* The first operation checks required alignment.  */
1598287b1152SRichard Henderson             addr_tmp = tcg_temp_new();
1599287b1152SRichard Henderson             for (int i = 0; ; ++i) {
16003259b9e2SRichard Henderson                 tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2 + i], addr, da->mem_idx,
16013259b9e2SRichard Henderson                                     memop | (i == 0 ? MO_ALIGN_64 : 0));
1602fcf5ef2aSThomas Huth                 if (i == 7) {
1603fcf5ef2aSThomas Huth                     break;
1604fcf5ef2aSThomas Huth                 }
1605287b1152SRichard Henderson                 tcg_gen_addi_tl(addr_tmp, addr, 8);
1606287b1152SRichard Henderson                 addr = addr_tmp;
1607fcf5ef2aSThomas Huth             }
1608fcf5ef2aSThomas Huth         } else {
1609fcf5ef2aSThomas Huth             gen_exception(dc, TT_ILL_INSN);
1610fcf5ef2aSThomas Huth         }
1611fcf5ef2aSThomas Huth         break;
1612fcf5ef2aSThomas Huth 
1613fcf5ef2aSThomas Huth     case GET_ASI_SHORT:
1614fcf5ef2aSThomas Huth         /* Valid for lddfa only.  */
16153259b9e2SRichard Henderson         if (orig_size == MO_64) {
16163259b9e2SRichard Henderson             tcg_gen_qemu_ld_i64(cpu_fpr[rd / 2], addr, da->mem_idx,
16173259b9e2SRichard Henderson                                 memop | MO_ALIGN);
1618fcf5ef2aSThomas Huth         } else {
1619fcf5ef2aSThomas Huth             gen_exception(dc, TT_ILL_INSN);
1620fcf5ef2aSThomas Huth         }
1621fcf5ef2aSThomas Huth         break;
1622fcf5ef2aSThomas Huth 
1623fcf5ef2aSThomas Huth     default:
1624fcf5ef2aSThomas Huth         {
16253259b9e2SRichard Henderson             TCGv_i32 r_asi = tcg_constant_i32(da->asi);
16263259b9e2SRichard Henderson             TCGv_i32 r_mop = tcg_constant_i32(memop | MO_ALIGN);
1627fcf5ef2aSThomas Huth 
1628fcf5ef2aSThomas Huth             save_state(dc);
1629fcf5ef2aSThomas Huth             /* According to the table in the UA2011 manual, the only
1630fcf5ef2aSThomas Huth                other asis that are valid for ldfa/lddfa/ldqfa are
1631fcf5ef2aSThomas Huth                the NO_FAULT asis.  We still need a helper for these,
1632fcf5ef2aSThomas Huth                but we can just use the integer asi helper for them.  */
1633fcf5ef2aSThomas Huth             switch (size) {
16343259b9e2SRichard Henderson             case MO_32:
1635fcf5ef2aSThomas Huth                 d64 = tcg_temp_new_i64();
1636ad75a51eSRichard Henderson                 gen_helper_ld_asi(d64, tcg_env, addr, r_asi, r_mop);
1637388a6465SRichard Henderson                 d32 = tcg_temp_new_i32();
1638fcf5ef2aSThomas Huth                 tcg_gen_extrl_i64_i32(d32, d64);
1639fcf5ef2aSThomas Huth                 gen_store_fpr_F(dc, rd, d32);
1640fcf5ef2aSThomas Huth                 break;
16413259b9e2SRichard Henderson             case MO_64:
16423259b9e2SRichard Henderson                 gen_helper_ld_asi(cpu_fpr[rd / 2], tcg_env, addr,
16433259b9e2SRichard Henderson                                   r_asi, r_mop);
1644fcf5ef2aSThomas Huth                 break;
16453259b9e2SRichard Henderson             case MO_128:
1646fcf5ef2aSThomas Huth                 d64 = tcg_temp_new_i64();
1647ad75a51eSRichard Henderson                 gen_helper_ld_asi(d64, tcg_env, addr, r_asi, r_mop);
1648287b1152SRichard Henderson                 addr_tmp = tcg_temp_new();
1649287b1152SRichard Henderson                 tcg_gen_addi_tl(addr_tmp, addr, 8);
1650287b1152SRichard Henderson                 gen_helper_ld_asi(cpu_fpr[rd / 2 + 1], tcg_env, addr_tmp,
16513259b9e2SRichard Henderson                                   r_asi, r_mop);
1652fcf5ef2aSThomas Huth                 tcg_gen_mov_i64(cpu_fpr[rd / 2], d64);
1653fcf5ef2aSThomas Huth                 break;
1654fcf5ef2aSThomas Huth             default:
1655fcf5ef2aSThomas Huth                 g_assert_not_reached();
1656fcf5ef2aSThomas Huth             }
1657fcf5ef2aSThomas Huth         }
1658fcf5ef2aSThomas Huth         break;
1659fcf5ef2aSThomas Huth     }
1660fcf5ef2aSThomas Huth }
1661fcf5ef2aSThomas Huth 
1662287b1152SRichard Henderson static void gen_stf_asi(DisasContext *dc, DisasASI *da, MemOp orig_size,
16633259b9e2SRichard Henderson                         TCGv addr, int rd)
16643259b9e2SRichard Henderson {
16653259b9e2SRichard Henderson     MemOp memop = da->memop;
16663259b9e2SRichard Henderson     MemOp size = memop & MO_SIZE;
1667fcf5ef2aSThomas Huth     TCGv_i32 d32;
1668287b1152SRichard Henderson     TCGv addr_tmp;
1669fcf5ef2aSThomas Huth 
16703259b9e2SRichard Henderson     /* TODO: Use 128-bit load/store below. */
16713259b9e2SRichard Henderson     if (size == MO_128) {
16723259b9e2SRichard Henderson         memop = (memop & ~MO_SIZE) | MO_64;
16733259b9e2SRichard Henderson     }
16743259b9e2SRichard Henderson 
16753259b9e2SRichard Henderson     switch (da->type) {
1676fcf5ef2aSThomas Huth     case GET_ASI_EXCP:
1677fcf5ef2aSThomas Huth         break;
1678fcf5ef2aSThomas Huth 
1679fcf5ef2aSThomas Huth     case GET_ASI_DIRECT:
16803259b9e2SRichard Henderson         memop |= MO_ALIGN_4;
1681fcf5ef2aSThomas Huth         switch (size) {
16823259b9e2SRichard Henderson         case MO_32:
1683fcf5ef2aSThomas Huth             d32 = gen_load_fpr_F(dc, rd);
16843259b9e2SRichard Henderson             tcg_gen_qemu_st_i32(d32, addr, da->mem_idx, memop | MO_ALIGN);
1685fcf5ef2aSThomas Huth             break;
16863259b9e2SRichard Henderson         case MO_64:
16873259b9e2SRichard Henderson             tcg_gen_qemu_st_i64(cpu_fpr[rd / 2], addr, da->mem_idx,
16883259b9e2SRichard Henderson                                 memop | MO_ALIGN_4);
1689fcf5ef2aSThomas Huth             break;
16903259b9e2SRichard Henderson         case MO_128:
1691fcf5ef2aSThomas Huth             /* Only 4-byte alignment required.  However, it is legal for the
1692fcf5ef2aSThomas Huth                cpu to signal the alignment fault, and the OS trap handler is
1693fcf5ef2aSThomas Huth                required to fix it up.  Requiring 16-byte alignment here avoids
1694fcf5ef2aSThomas Huth                having to probe the second page before performing the first
1695fcf5ef2aSThomas Huth                write.  */
16963259b9e2SRichard Henderson             tcg_gen_qemu_st_i64(cpu_fpr[rd / 2], addr, da->mem_idx,
16973259b9e2SRichard Henderson                                 memop | MO_ALIGN_16);
1698287b1152SRichard Henderson             addr_tmp = tcg_temp_new();
1699287b1152SRichard Henderson             tcg_gen_addi_tl(addr_tmp, addr, 8);
1700287b1152SRichard Henderson             tcg_gen_qemu_st_i64(cpu_fpr[rd / 2 + 1], addr_tmp, da->mem_idx, memop);
1701fcf5ef2aSThomas Huth             break;
1702fcf5ef2aSThomas Huth         default:
1703fcf5ef2aSThomas Huth             g_assert_not_reached();
1704fcf5ef2aSThomas Huth         }
1705fcf5ef2aSThomas Huth         break;
1706fcf5ef2aSThomas Huth 
1707fcf5ef2aSThomas Huth     case GET_ASI_BLOCK:
1708fcf5ef2aSThomas Huth         /* Valid for stdfa on aligned registers only.  */
17093259b9e2SRichard Henderson         if (orig_size == MO_64 && (rd & 7) == 0) {
1710fcf5ef2aSThomas Huth             /* The first operation checks required alignment.  */
1711287b1152SRichard Henderson             addr_tmp = tcg_temp_new();
1712287b1152SRichard Henderson             for (int i = 0; ; ++i) {
17133259b9e2SRichard Henderson                 tcg_gen_qemu_st_i64(cpu_fpr[rd / 2 + i], addr, da->mem_idx,
17143259b9e2SRichard Henderson                                     memop | (i == 0 ? MO_ALIGN_64 : 0));
1715fcf5ef2aSThomas Huth                 if (i == 7) {
1716fcf5ef2aSThomas Huth                     break;
1717fcf5ef2aSThomas Huth                 }
1718287b1152SRichard Henderson                 tcg_gen_addi_tl(addr_tmp, addr, 8);
1719287b1152SRichard Henderson                 addr = addr_tmp;
1720fcf5ef2aSThomas Huth             }
1721fcf5ef2aSThomas Huth         } else {
1722fcf5ef2aSThomas Huth             gen_exception(dc, TT_ILL_INSN);
1723fcf5ef2aSThomas Huth         }
1724fcf5ef2aSThomas Huth         break;
1725fcf5ef2aSThomas Huth 
1726fcf5ef2aSThomas Huth     case GET_ASI_SHORT:
1727fcf5ef2aSThomas Huth         /* Valid for stdfa only.  */
17283259b9e2SRichard Henderson         if (orig_size == MO_64) {
17293259b9e2SRichard Henderson             tcg_gen_qemu_st_i64(cpu_fpr[rd / 2], addr, da->mem_idx,
17303259b9e2SRichard Henderson                                 memop | MO_ALIGN);
1731fcf5ef2aSThomas Huth         } else {
1732fcf5ef2aSThomas Huth             gen_exception(dc, TT_ILL_INSN);
1733fcf5ef2aSThomas Huth         }
1734fcf5ef2aSThomas Huth         break;
1735fcf5ef2aSThomas Huth 
1736fcf5ef2aSThomas Huth     default:
1737fcf5ef2aSThomas Huth         /* According to the table in the UA2011 manual, the only
1738fcf5ef2aSThomas Huth            other asis that are valid for ldfa/lddfa/ldqfa are
1739fcf5ef2aSThomas Huth            the PST* asis, which aren't currently handled.  */
1740fcf5ef2aSThomas Huth         gen_exception(dc, TT_ILL_INSN);
1741fcf5ef2aSThomas Huth         break;
1742fcf5ef2aSThomas Huth     }
1743fcf5ef2aSThomas Huth }
1744fcf5ef2aSThomas Huth 
174542071fc1SRichard Henderson static void gen_ldda_asi(DisasContext *dc, DisasASI *da, TCGv addr, int rd)
1746fcf5ef2aSThomas Huth {
1747a76779eeSRichard Henderson     TCGv hi = gen_dest_gpr(dc, rd);
1748a76779eeSRichard Henderson     TCGv lo = gen_dest_gpr(dc, rd + 1);
1749fcf5ef2aSThomas Huth 
1750c03a0fd1SRichard Henderson     switch (da->type) {
1751fcf5ef2aSThomas Huth     case GET_ASI_EXCP:
1752fcf5ef2aSThomas Huth         return;
1753fcf5ef2aSThomas Huth 
1754fcf5ef2aSThomas Huth     case GET_ASI_DTWINX:
1755ebbbec92SRichard Henderson #ifdef TARGET_SPARC64
1756ebbbec92SRichard Henderson         {
1757ebbbec92SRichard Henderson             MemOp mop = (da->memop & MO_BSWAP) | MO_128 | MO_ALIGN_16;
1758ebbbec92SRichard Henderson             TCGv_i128 t = tcg_temp_new_i128();
1759ebbbec92SRichard Henderson 
1760ebbbec92SRichard Henderson             tcg_gen_qemu_ld_i128(t, addr, da->mem_idx, mop);
1761ebbbec92SRichard Henderson             /*
1762ebbbec92SRichard Henderson              * Note that LE twinx acts as if each 64-bit register result is
1763ebbbec92SRichard Henderson              * byte swapped.  We perform one 128-bit LE load, so must swap
1764ebbbec92SRichard Henderson              * the order of the writebacks.
1765ebbbec92SRichard Henderson              */
1766ebbbec92SRichard Henderson             if ((mop & MO_BSWAP) == MO_TE) {
1767ebbbec92SRichard Henderson                 tcg_gen_extr_i128_i64(lo, hi, t);
1768ebbbec92SRichard Henderson             } else {
1769ebbbec92SRichard Henderson                 tcg_gen_extr_i128_i64(hi, lo, t);
1770ebbbec92SRichard Henderson             }
1771ebbbec92SRichard Henderson         }
1772fcf5ef2aSThomas Huth         break;
1773ebbbec92SRichard Henderson #else
1774ebbbec92SRichard Henderson         g_assert_not_reached();
1775ebbbec92SRichard Henderson #endif
1776fcf5ef2aSThomas Huth 
1777fcf5ef2aSThomas Huth     case GET_ASI_DIRECT:
1778fcf5ef2aSThomas Huth         {
1779fcf5ef2aSThomas Huth             TCGv_i64 tmp = tcg_temp_new_i64();
1780fcf5ef2aSThomas Huth 
1781c03a0fd1SRichard Henderson             tcg_gen_qemu_ld_i64(tmp, addr, da->mem_idx, da->memop | MO_ALIGN);
1782fcf5ef2aSThomas Huth 
1783fcf5ef2aSThomas Huth             /* Note that LE ldda acts as if each 32-bit register
1784fcf5ef2aSThomas Huth                result is byte swapped.  Having just performed one
1785fcf5ef2aSThomas Huth                64-bit bswap, we need now to swap the writebacks.  */
1786c03a0fd1SRichard Henderson             if ((da->memop & MO_BSWAP) == MO_TE) {
1787a76779eeSRichard Henderson                 tcg_gen_extr_i64_tl(lo, hi, tmp);
1788fcf5ef2aSThomas Huth             } else {
1789a76779eeSRichard Henderson                 tcg_gen_extr_i64_tl(hi, lo, tmp);
1790fcf5ef2aSThomas Huth             }
1791fcf5ef2aSThomas Huth         }
1792fcf5ef2aSThomas Huth         break;
1793fcf5ef2aSThomas Huth 
1794fcf5ef2aSThomas Huth     default:
1795fcf5ef2aSThomas Huth         /* ??? In theory we've handled all of the ASIs that are valid
1796fcf5ef2aSThomas Huth            for ldda, and this should raise DAE_invalid_asi.  However,
1797fcf5ef2aSThomas Huth            real hardware allows others.  This can be seen with e.g.
1798fcf5ef2aSThomas Huth            FreeBSD 10.3 wrt ASI_IC_TAG.  */
1799fcf5ef2aSThomas Huth         {
1800c03a0fd1SRichard Henderson             TCGv_i32 r_asi = tcg_constant_i32(da->asi);
1801c03a0fd1SRichard Henderson             TCGv_i32 r_mop = tcg_constant_i32(da->memop);
1802fcf5ef2aSThomas Huth             TCGv_i64 tmp = tcg_temp_new_i64();
1803fcf5ef2aSThomas Huth 
1804fcf5ef2aSThomas Huth             save_state(dc);
1805ad75a51eSRichard Henderson             gen_helper_ld_asi(tmp, tcg_env, addr, r_asi, r_mop);
1806fcf5ef2aSThomas Huth 
1807fcf5ef2aSThomas Huth             /* See above.  */
1808c03a0fd1SRichard Henderson             if ((da->memop & MO_BSWAP) == MO_TE) {
1809a76779eeSRichard Henderson                 tcg_gen_extr_i64_tl(lo, hi, tmp);
1810fcf5ef2aSThomas Huth             } else {
1811a76779eeSRichard Henderson                 tcg_gen_extr_i64_tl(hi, lo, tmp);
1812fcf5ef2aSThomas Huth             }
1813fcf5ef2aSThomas Huth         }
1814fcf5ef2aSThomas Huth         break;
1815fcf5ef2aSThomas Huth     }
1816fcf5ef2aSThomas Huth 
1817fcf5ef2aSThomas Huth     gen_store_gpr(dc, rd, hi);
1818fcf5ef2aSThomas Huth     gen_store_gpr(dc, rd + 1, lo);
1819fcf5ef2aSThomas Huth }
1820fcf5ef2aSThomas Huth 
182142071fc1SRichard Henderson static void gen_stda_asi(DisasContext *dc, DisasASI *da, TCGv addr, int rd)
1822c03a0fd1SRichard Henderson {
1823c03a0fd1SRichard Henderson     TCGv hi = gen_load_gpr(dc, rd);
1824fcf5ef2aSThomas Huth     TCGv lo = gen_load_gpr(dc, rd + 1);
1825fcf5ef2aSThomas Huth 
1826c03a0fd1SRichard Henderson     switch (da->type) {
1827fcf5ef2aSThomas Huth     case GET_ASI_EXCP:
1828fcf5ef2aSThomas Huth         break;
1829fcf5ef2aSThomas Huth 
1830fcf5ef2aSThomas Huth     case GET_ASI_DTWINX:
1831ebbbec92SRichard Henderson #ifdef TARGET_SPARC64
1832ebbbec92SRichard Henderson         {
1833ebbbec92SRichard Henderson             MemOp mop = (da->memop & MO_BSWAP) | MO_128 | MO_ALIGN_16;
1834ebbbec92SRichard Henderson             TCGv_i128 t = tcg_temp_new_i128();
1835ebbbec92SRichard Henderson 
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 store, so must swap
1839ebbbec92SRichard Henderson              * the order of the construction.
1840ebbbec92SRichard Henderson              */
1841ebbbec92SRichard Henderson             if ((mop & MO_BSWAP) == MO_TE) {
1842ebbbec92SRichard Henderson                 tcg_gen_concat_i64_i128(t, lo, hi);
1843ebbbec92SRichard Henderson             } else {
1844ebbbec92SRichard Henderson                 tcg_gen_concat_i64_i128(t, hi, lo);
1845ebbbec92SRichard Henderson             }
1846ebbbec92SRichard Henderson             tcg_gen_qemu_st_i128(t, addr, da->mem_idx, mop);
1847ebbbec92SRichard Henderson         }
1848fcf5ef2aSThomas Huth         break;
1849ebbbec92SRichard Henderson #else
1850ebbbec92SRichard Henderson         g_assert_not_reached();
1851ebbbec92SRichard Henderson #endif
1852fcf5ef2aSThomas Huth 
1853fcf5ef2aSThomas Huth     case GET_ASI_DIRECT:
1854fcf5ef2aSThomas Huth         {
1855fcf5ef2aSThomas Huth             TCGv_i64 t64 = tcg_temp_new_i64();
1856fcf5ef2aSThomas Huth 
1857fcf5ef2aSThomas Huth             /* Note that LE stda acts as if each 32-bit register result is
1858fcf5ef2aSThomas Huth                byte swapped.  We will perform one 64-bit LE store, so now
1859fcf5ef2aSThomas Huth                we must swap the order of the construction.  */
1860c03a0fd1SRichard Henderson             if ((da->memop & MO_BSWAP) == MO_TE) {
1861a76779eeSRichard Henderson                 tcg_gen_concat_tl_i64(t64, lo, hi);
1862fcf5ef2aSThomas Huth             } else {
1863a76779eeSRichard Henderson                 tcg_gen_concat_tl_i64(t64, hi, lo);
1864fcf5ef2aSThomas Huth             }
1865c03a0fd1SRichard Henderson             tcg_gen_qemu_st_i64(t64, addr, da->mem_idx, da->memop | MO_ALIGN);
1866fcf5ef2aSThomas Huth         }
1867fcf5ef2aSThomas Huth         break;
1868fcf5ef2aSThomas Huth 
1869a76779eeSRichard Henderson     case GET_ASI_BFILL:
1870a76779eeSRichard Henderson         assert(TARGET_LONG_BITS == 32);
187154c3e953SRichard Henderson         /*
187254c3e953SRichard Henderson          * Store 32 bytes of [rd:rd+1] to ADDR.
187354c3e953SRichard Henderson          * See comments for GET_ASI_COPY above.
187454c3e953SRichard Henderson          */
1875a76779eeSRichard Henderson         {
187654c3e953SRichard Henderson             MemOp mop = MO_TE | MO_128 | MO_ATOM_IFALIGN_PAIR;
187754c3e953SRichard Henderson             TCGv_i64 t8 = tcg_temp_new_i64();
187854c3e953SRichard Henderson             TCGv_i128 t16 = tcg_temp_new_i128();
187954c3e953SRichard Henderson             TCGv daddr = tcg_temp_new();
1880a76779eeSRichard Henderson 
188154c3e953SRichard Henderson             tcg_gen_concat_tl_i64(t8, lo, hi);
188254c3e953SRichard Henderson             tcg_gen_concat_i64_i128(t16, t8, t8);
188354c3e953SRichard Henderson             tcg_gen_andi_tl(daddr, addr, -32);
188454c3e953SRichard Henderson             tcg_gen_qemu_st_i128(t16, daddr, da->mem_idx, mop);
188554c3e953SRichard Henderson             tcg_gen_addi_tl(daddr, daddr, 16);
188654c3e953SRichard Henderson             tcg_gen_qemu_st_i128(t16, daddr, da->mem_idx, mop);
1887a76779eeSRichard Henderson         }
1888a76779eeSRichard Henderson         break;
1889a76779eeSRichard Henderson 
1890fcf5ef2aSThomas Huth     default:
1891fcf5ef2aSThomas Huth         /* ??? In theory we've handled all of the ASIs that are valid
1892fcf5ef2aSThomas Huth            for stda, and this should raise DAE_invalid_asi.  */
1893fcf5ef2aSThomas Huth         {
1894c03a0fd1SRichard Henderson             TCGv_i32 r_asi = tcg_constant_i32(da->asi);
1895c03a0fd1SRichard Henderson             TCGv_i32 r_mop = tcg_constant_i32(da->memop);
1896fcf5ef2aSThomas Huth             TCGv_i64 t64 = tcg_temp_new_i64();
1897fcf5ef2aSThomas Huth 
1898fcf5ef2aSThomas Huth             /* See above.  */
1899c03a0fd1SRichard Henderson             if ((da->memop & MO_BSWAP) == MO_TE) {
1900a76779eeSRichard Henderson                 tcg_gen_concat_tl_i64(t64, lo, hi);
1901fcf5ef2aSThomas Huth             } else {
1902a76779eeSRichard Henderson                 tcg_gen_concat_tl_i64(t64, hi, lo);
1903fcf5ef2aSThomas Huth             }
1904fcf5ef2aSThomas Huth 
1905fcf5ef2aSThomas Huth             save_state(dc);
1906ad75a51eSRichard Henderson             gen_helper_st_asi(tcg_env, addr, t64, r_asi, r_mop);
1907fcf5ef2aSThomas Huth         }
1908fcf5ef2aSThomas Huth         break;
1909fcf5ef2aSThomas Huth     }
1910fcf5ef2aSThomas Huth }
1911fcf5ef2aSThomas Huth 
1912fcf5ef2aSThomas Huth static void gen_fmovs(DisasContext *dc, DisasCompare *cmp, int rd, int rs)
1913fcf5ef2aSThomas Huth {
1914f7ec8155SRichard Henderson #ifdef TARGET_SPARC64
1915fcf5ef2aSThomas Huth     TCGv_i32 c32, zero, dst, s1, s2;
1916dd7dbfccSRichard Henderson     TCGv_i64 c64 = tcg_temp_new_i64();
1917fcf5ef2aSThomas Huth 
1918fcf5ef2aSThomas Huth     /* We have two choices here: extend the 32 bit data and use movcond_i64,
1919fcf5ef2aSThomas Huth        or fold the comparison down to 32 bits and use movcond_i32.  Choose
1920fcf5ef2aSThomas Huth        the later.  */
1921fcf5ef2aSThomas Huth     c32 = tcg_temp_new_i32();
1922c8507ebfSRichard Henderson     tcg_gen_setcondi_i64(cmp->cond, c64, cmp->c1, cmp->c2);
1923fcf5ef2aSThomas Huth     tcg_gen_extrl_i64_i32(c32, c64);
1924fcf5ef2aSThomas Huth 
1925fcf5ef2aSThomas Huth     s1 = gen_load_fpr_F(dc, rs);
1926fcf5ef2aSThomas Huth     s2 = gen_load_fpr_F(dc, rd);
1927388a6465SRichard Henderson     dst = tcg_temp_new_i32();
192800ab7e61SRichard Henderson     zero = tcg_constant_i32(0);
1929fcf5ef2aSThomas Huth 
1930fcf5ef2aSThomas Huth     tcg_gen_movcond_i32(TCG_COND_NE, dst, c32, zero, s1, s2);
1931fcf5ef2aSThomas Huth 
1932fcf5ef2aSThomas Huth     gen_store_fpr_F(dc, rd, dst);
1933f7ec8155SRichard Henderson #else
1934f7ec8155SRichard Henderson     qemu_build_not_reached();
1935f7ec8155SRichard Henderson #endif
1936fcf5ef2aSThomas Huth }
1937fcf5ef2aSThomas Huth 
1938fcf5ef2aSThomas Huth static void gen_fmovd(DisasContext *dc, DisasCompare *cmp, int rd, int rs)
1939fcf5ef2aSThomas Huth {
1940f7ec8155SRichard Henderson #ifdef TARGET_SPARC64
1941fcf5ef2aSThomas Huth     TCGv_i64 dst = gen_dest_fpr_D(dc, rd);
1942c8507ebfSRichard Henderson     tcg_gen_movcond_i64(cmp->cond, dst, cmp->c1, tcg_constant_tl(cmp->c2),
1943fcf5ef2aSThomas Huth                         gen_load_fpr_D(dc, rs),
1944fcf5ef2aSThomas Huth                         gen_load_fpr_D(dc, rd));
1945fcf5ef2aSThomas Huth     gen_store_fpr_D(dc, rd, dst);
1946f7ec8155SRichard Henderson #else
1947f7ec8155SRichard Henderson     qemu_build_not_reached();
1948f7ec8155SRichard Henderson #endif
1949fcf5ef2aSThomas Huth }
1950fcf5ef2aSThomas Huth 
1951fcf5ef2aSThomas Huth static void gen_fmovq(DisasContext *dc, DisasCompare *cmp, int rd, int rs)
1952fcf5ef2aSThomas Huth {
1953f7ec8155SRichard Henderson #ifdef TARGET_SPARC64
1954fcf5ef2aSThomas Huth     int qd = QFPREG(rd);
1955fcf5ef2aSThomas Huth     int qs = QFPREG(rs);
1956c8507ebfSRichard Henderson     TCGv c2 = tcg_constant_tl(cmp->c2);
1957fcf5ef2aSThomas Huth 
1958c8507ebfSRichard Henderson     tcg_gen_movcond_i64(cmp->cond, cpu_fpr[qd / 2], cmp->c1, c2,
1959fcf5ef2aSThomas Huth                         cpu_fpr[qs / 2], cpu_fpr[qd / 2]);
1960c8507ebfSRichard Henderson     tcg_gen_movcond_i64(cmp->cond, cpu_fpr[qd / 2 + 1], cmp->c1, c2,
1961fcf5ef2aSThomas Huth                         cpu_fpr[qs / 2 + 1], cpu_fpr[qd / 2 + 1]);
1962fcf5ef2aSThomas Huth 
1963fcf5ef2aSThomas Huth     gen_update_fprs_dirty(dc, qd);
1964f7ec8155SRichard Henderson #else
1965f7ec8155SRichard Henderson     qemu_build_not_reached();
1966f7ec8155SRichard Henderson #endif
1967fcf5ef2aSThomas Huth }
1968fcf5ef2aSThomas Huth 
1969f7ec8155SRichard Henderson #ifdef TARGET_SPARC64
19705d617bfbSRichard Henderson static void gen_load_trap_state_at_tl(TCGv_ptr r_tsptr)
1971fcf5ef2aSThomas Huth {
1972fcf5ef2aSThomas Huth     TCGv_i32 r_tl = tcg_temp_new_i32();
1973fcf5ef2aSThomas Huth 
1974fcf5ef2aSThomas Huth     /* load env->tl into r_tl */
1975ad75a51eSRichard Henderson     tcg_gen_ld_i32(r_tl, tcg_env, offsetof(CPUSPARCState, tl));
1976fcf5ef2aSThomas Huth 
1977fcf5ef2aSThomas Huth     /* tl = [0 ... MAXTL_MASK] where MAXTL_MASK must be power of 2 */
1978fcf5ef2aSThomas Huth     tcg_gen_andi_i32(r_tl, r_tl, MAXTL_MASK);
1979fcf5ef2aSThomas Huth 
1980fcf5ef2aSThomas Huth     /* calculate offset to current trap state from env->ts, reuse r_tl */
1981fcf5ef2aSThomas Huth     tcg_gen_muli_i32(r_tl, r_tl, sizeof (trap_state));
1982ad75a51eSRichard Henderson     tcg_gen_addi_ptr(r_tsptr, tcg_env, offsetof(CPUSPARCState, ts));
1983fcf5ef2aSThomas Huth 
1984fcf5ef2aSThomas Huth     /* tsptr = env->ts[env->tl & MAXTL_MASK] */
1985fcf5ef2aSThomas Huth     {
1986fcf5ef2aSThomas Huth         TCGv_ptr r_tl_tmp = tcg_temp_new_ptr();
1987fcf5ef2aSThomas Huth         tcg_gen_ext_i32_ptr(r_tl_tmp, r_tl);
1988fcf5ef2aSThomas Huth         tcg_gen_add_ptr(r_tsptr, r_tsptr, r_tl_tmp);
1989fcf5ef2aSThomas Huth     }
1990fcf5ef2aSThomas Huth }
1991fcf5ef2aSThomas Huth #endif
1992fcf5ef2aSThomas Huth 
199306c060d9SRichard Henderson static int extract_dfpreg(DisasContext *dc, int x)
199406c060d9SRichard Henderson {
199506c060d9SRichard Henderson     return DFPREG(x);
199606c060d9SRichard Henderson }
199706c060d9SRichard Henderson 
199806c060d9SRichard Henderson static int extract_qfpreg(DisasContext *dc, int x)
199906c060d9SRichard Henderson {
200006c060d9SRichard Henderson     return QFPREG(x);
200106c060d9SRichard Henderson }
200206c060d9SRichard Henderson 
2003878cc677SRichard Henderson /* Include the auto-generated decoder.  */
2004878cc677SRichard Henderson #include "decode-insns.c.inc"
2005878cc677SRichard Henderson 
2006878cc677SRichard Henderson #define TRANS(NAME, AVAIL, FUNC, ...) \
2007878cc677SRichard Henderson     static bool trans_##NAME(DisasContext *dc, arg_##NAME *a) \
2008878cc677SRichard Henderson     { return avail_##AVAIL(dc) && FUNC(dc, __VA_ARGS__); }
2009878cc677SRichard Henderson 
2010878cc677SRichard Henderson #define avail_ALL(C)      true
2011878cc677SRichard Henderson #ifdef TARGET_SPARC64
2012878cc677SRichard Henderson # define avail_32(C)      false
2013af25071cSRichard Henderson # define avail_ASR17(C)   false
2014d0a11d25SRichard Henderson # define avail_CASA(C)    true
2015c2636853SRichard Henderson # define avail_DIV(C)     true
2016b5372650SRichard Henderson # define avail_MUL(C)     true
20170faef01bSRichard Henderson # define avail_POWERDOWN(C) false
2018878cc677SRichard Henderson # define avail_64(C)      true
20195d617bfbSRichard Henderson # define avail_GL(C)      ((C)->def->features & CPU_FEATURE_GL)
2020af25071cSRichard Henderson # define avail_HYPV(C)    ((C)->def->features & CPU_FEATURE_HYPV)
2021b88ce6f2SRichard Henderson # define avail_VIS1(C)    ((C)->def->features & CPU_FEATURE_VIS1)
2022b88ce6f2SRichard Henderson # define avail_VIS2(C)    ((C)->def->features & CPU_FEATURE_VIS2)
2023878cc677SRichard Henderson #else
2024878cc677SRichard Henderson # define avail_32(C)      true
2025af25071cSRichard Henderson # define avail_ASR17(C)   ((C)->def->features & CPU_FEATURE_ASR17)
2026d0a11d25SRichard Henderson # define avail_CASA(C)    ((C)->def->features & CPU_FEATURE_CASA)
2027c2636853SRichard Henderson # define avail_DIV(C)     ((C)->def->features & CPU_FEATURE_DIV)
2028b5372650SRichard Henderson # define avail_MUL(C)     ((C)->def->features & CPU_FEATURE_MUL)
20290faef01bSRichard Henderson # define avail_POWERDOWN(C) ((C)->def->features & CPU_FEATURE_POWERDOWN)
2030878cc677SRichard Henderson # define avail_64(C)      false
20315d617bfbSRichard Henderson # define avail_GL(C)      false
2032af25071cSRichard Henderson # define avail_HYPV(C)    false
2033b88ce6f2SRichard Henderson # define avail_VIS1(C)    false
2034b88ce6f2SRichard Henderson # define avail_VIS2(C)    false
2035878cc677SRichard Henderson #endif
2036878cc677SRichard Henderson 
2037878cc677SRichard Henderson /* Default case for non jump instructions. */
2038878cc677SRichard Henderson static bool advance_pc(DisasContext *dc)
2039878cc677SRichard Henderson {
20404a8d145dSRichard Henderson     TCGLabel *l1;
20414a8d145dSRichard Henderson 
204289527e3aSRichard Henderson     finishing_insn(dc);
204389527e3aSRichard Henderson 
2044878cc677SRichard Henderson     if (dc->npc & 3) {
2045878cc677SRichard Henderson         switch (dc->npc) {
2046878cc677SRichard Henderson         case DYNAMIC_PC:
2047878cc677SRichard Henderson         case DYNAMIC_PC_LOOKUP:
2048878cc677SRichard Henderson             dc->pc = dc->npc;
2049444d8b30SRichard Henderson             tcg_gen_mov_tl(cpu_pc, cpu_npc);
2050444d8b30SRichard Henderson             tcg_gen_addi_tl(cpu_npc, cpu_npc, 4);
2051878cc677SRichard Henderson             break;
20524a8d145dSRichard Henderson 
2053878cc677SRichard Henderson         case JUMP_PC:
2054878cc677SRichard Henderson             /* we can do a static jump */
20554a8d145dSRichard Henderson             l1 = gen_new_label();
2056533f042fSRichard Henderson             tcg_gen_brcondi_tl(dc->jump.cond, dc->jump.c1, dc->jump.c2, l1);
20574a8d145dSRichard Henderson 
20584a8d145dSRichard Henderson             /* jump not taken */
20594a8d145dSRichard Henderson             gen_goto_tb(dc, 1, dc->jump_pc[1], dc->jump_pc[1] + 4);
20604a8d145dSRichard Henderson 
20614a8d145dSRichard Henderson             /* jump taken */
20624a8d145dSRichard Henderson             gen_set_label(l1);
20634a8d145dSRichard Henderson             gen_goto_tb(dc, 0, dc->jump_pc[0], dc->jump_pc[0] + 4);
20644a8d145dSRichard Henderson 
2065878cc677SRichard Henderson             dc->base.is_jmp = DISAS_NORETURN;
2066878cc677SRichard Henderson             break;
20674a8d145dSRichard Henderson 
2068878cc677SRichard Henderson         default:
2069878cc677SRichard Henderson             g_assert_not_reached();
2070878cc677SRichard Henderson         }
2071878cc677SRichard Henderson     } else {
2072878cc677SRichard Henderson         dc->pc = dc->npc;
2073878cc677SRichard Henderson         dc->npc = dc->npc + 4;
2074878cc677SRichard Henderson     }
2075878cc677SRichard Henderson     return true;
2076878cc677SRichard Henderson }
2077878cc677SRichard Henderson 
20786d2a0768SRichard Henderson /*
20796d2a0768SRichard Henderson  * Major opcodes 00 and 01 -- branches, call, and sethi
20806d2a0768SRichard Henderson  */
20816d2a0768SRichard Henderson 
20829d4e2bc7SRichard Henderson static bool advance_jump_cond(DisasContext *dc, DisasCompare *cmp,
20833951b7a8SRichard Henderson                               bool annul, int disp)
2084276567aaSRichard Henderson {
20853951b7a8SRichard Henderson     target_ulong dest = address_mask_i(dc, dc->pc + disp * 4);
2086c76c8045SRichard Henderson     target_ulong npc;
2087c76c8045SRichard Henderson 
208889527e3aSRichard Henderson     finishing_insn(dc);
208989527e3aSRichard Henderson 
20902d9bb237SRichard Henderson     if (cmp->cond == TCG_COND_ALWAYS) {
20912d9bb237SRichard Henderson         if (annul) {
20922d9bb237SRichard Henderson             dc->pc = dest;
20932d9bb237SRichard Henderson             dc->npc = dest + 4;
20942d9bb237SRichard Henderson         } else {
20952d9bb237SRichard Henderson             gen_mov_pc_npc(dc);
20962d9bb237SRichard Henderson             dc->npc = dest;
20972d9bb237SRichard Henderson         }
20982d9bb237SRichard Henderson         return true;
20992d9bb237SRichard Henderson     }
21002d9bb237SRichard Henderson 
21012d9bb237SRichard Henderson     if (cmp->cond == TCG_COND_NEVER) {
21022d9bb237SRichard Henderson         npc = dc->npc;
21032d9bb237SRichard Henderson         if (npc & 3) {
21042d9bb237SRichard Henderson             gen_mov_pc_npc(dc);
21052d9bb237SRichard Henderson             if (annul) {
21062d9bb237SRichard Henderson                 tcg_gen_addi_tl(cpu_pc, cpu_pc, 4);
21072d9bb237SRichard Henderson             }
21082d9bb237SRichard Henderson             tcg_gen_addi_tl(cpu_npc, cpu_pc, 4);
21092d9bb237SRichard Henderson         } else {
21102d9bb237SRichard Henderson             dc->pc = npc + (annul ? 4 : 0);
21112d9bb237SRichard Henderson             dc->npc = dc->pc + 4;
21122d9bb237SRichard Henderson         }
21132d9bb237SRichard Henderson         return true;
21142d9bb237SRichard Henderson     }
21152d9bb237SRichard Henderson 
2116c76c8045SRichard Henderson     flush_cond(dc);
2117c76c8045SRichard Henderson     npc = dc->npc;
21186b3e4cc6SRichard Henderson 
2119276567aaSRichard Henderson     if (annul) {
21206b3e4cc6SRichard Henderson         TCGLabel *l1 = gen_new_label();
21216b3e4cc6SRichard Henderson 
2122c8507ebfSRichard Henderson         tcg_gen_brcondi_tl(tcg_invert_cond(cmp->cond), cmp->c1, cmp->c2, l1);
21236b3e4cc6SRichard Henderson         gen_goto_tb(dc, 0, npc, dest);
21246b3e4cc6SRichard Henderson         gen_set_label(l1);
21256b3e4cc6SRichard Henderson         gen_goto_tb(dc, 1, npc + 4, npc + 8);
21266b3e4cc6SRichard Henderson 
21276b3e4cc6SRichard Henderson         dc->base.is_jmp = DISAS_NORETURN;
2128276567aaSRichard Henderson     } else {
21296b3e4cc6SRichard Henderson         if (npc & 3) {
21306b3e4cc6SRichard Henderson             switch (npc) {
21316b3e4cc6SRichard Henderson             case DYNAMIC_PC:
21326b3e4cc6SRichard Henderson             case DYNAMIC_PC_LOOKUP:
21336b3e4cc6SRichard Henderson                 tcg_gen_mov_tl(cpu_pc, cpu_npc);
21346b3e4cc6SRichard Henderson                 tcg_gen_addi_tl(cpu_npc, cpu_npc, 4);
21359d4e2bc7SRichard Henderson                 tcg_gen_movcond_tl(cmp->cond, cpu_npc,
2136c8507ebfSRichard Henderson                                    cmp->c1, tcg_constant_tl(cmp->c2),
21376b3e4cc6SRichard Henderson                                    tcg_constant_tl(dest), cpu_npc);
21386b3e4cc6SRichard Henderson                 dc->pc = npc;
21396b3e4cc6SRichard Henderson                 break;
21406b3e4cc6SRichard Henderson             default:
21416b3e4cc6SRichard Henderson                 g_assert_not_reached();
21426b3e4cc6SRichard Henderson             }
21436b3e4cc6SRichard Henderson         } else {
21446b3e4cc6SRichard Henderson             dc->pc = npc;
2145533f042fSRichard Henderson             dc->npc = JUMP_PC;
2146533f042fSRichard Henderson             dc->jump = *cmp;
21476b3e4cc6SRichard Henderson             dc->jump_pc[0] = dest;
21486b3e4cc6SRichard Henderson             dc->jump_pc[1] = npc + 4;
2149dd7dbfccSRichard Henderson 
2150dd7dbfccSRichard Henderson             /* The condition for cpu_cond is always NE -- normalize. */
2151dd7dbfccSRichard Henderson             if (cmp->cond == TCG_COND_NE) {
2152c8507ebfSRichard Henderson                 tcg_gen_xori_tl(cpu_cond, cmp->c1, cmp->c2);
21539d4e2bc7SRichard Henderson             } else {
2154c8507ebfSRichard Henderson                 tcg_gen_setcondi_tl(cmp->cond, cpu_cond, cmp->c1, cmp->c2);
21559d4e2bc7SRichard Henderson             }
215689527e3aSRichard Henderson             dc->cpu_cond_live = true;
21576b3e4cc6SRichard Henderson         }
2158276567aaSRichard Henderson     }
2159276567aaSRichard Henderson     return true;
2160276567aaSRichard Henderson }
2161276567aaSRichard Henderson 
2162af25071cSRichard Henderson static bool raise_priv(DisasContext *dc)
2163af25071cSRichard Henderson {
2164af25071cSRichard Henderson     gen_exception(dc, TT_PRIV_INSN);
2165af25071cSRichard Henderson     return true;
2166af25071cSRichard Henderson }
2167af25071cSRichard Henderson 
216806c060d9SRichard Henderson static bool raise_unimpfpop(DisasContext *dc)
216906c060d9SRichard Henderson {
217006c060d9SRichard Henderson     gen_op_fpexception_im(dc, FSR_FTT_UNIMPFPOP);
217106c060d9SRichard Henderson     return true;
217206c060d9SRichard Henderson }
217306c060d9SRichard Henderson 
217406c060d9SRichard Henderson static bool gen_trap_float128(DisasContext *dc)
217506c060d9SRichard Henderson {
217606c060d9SRichard Henderson     if (dc->def->features & CPU_FEATURE_FLOAT128) {
217706c060d9SRichard Henderson         return false;
217806c060d9SRichard Henderson     }
217906c060d9SRichard Henderson     return raise_unimpfpop(dc);
218006c060d9SRichard Henderson }
218106c060d9SRichard Henderson 
2182276567aaSRichard Henderson static bool do_bpcc(DisasContext *dc, arg_bcc *a)
2183276567aaSRichard Henderson {
21841ea9c62aSRichard Henderson     DisasCompare cmp;
2185276567aaSRichard Henderson 
21861ea9c62aSRichard Henderson     gen_compare(&cmp, a->cc, a->cond, dc);
21873951b7a8SRichard Henderson     return advance_jump_cond(dc, &cmp, a->a, a->i);
2188276567aaSRichard Henderson }
2189276567aaSRichard Henderson 
2190276567aaSRichard Henderson TRANS(Bicc, ALL, do_bpcc, a)
2191276567aaSRichard Henderson TRANS(BPcc,  64, do_bpcc, a)
2192276567aaSRichard Henderson 
219345196ea4SRichard Henderson static bool do_fbpfcc(DisasContext *dc, arg_bcc *a)
219445196ea4SRichard Henderson {
2195d5471936SRichard Henderson     DisasCompare cmp;
219645196ea4SRichard Henderson 
219745196ea4SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
219845196ea4SRichard Henderson         return true;
219945196ea4SRichard Henderson     }
2200d5471936SRichard Henderson     gen_fcompare(&cmp, a->cc, a->cond);
22013951b7a8SRichard Henderson     return advance_jump_cond(dc, &cmp, a->a, a->i);
220245196ea4SRichard Henderson }
220345196ea4SRichard Henderson 
220445196ea4SRichard Henderson TRANS(FBPfcc,  64, do_fbpfcc, a)
220545196ea4SRichard Henderson TRANS(FBfcc,  ALL, do_fbpfcc, a)
220645196ea4SRichard Henderson 
2207ab9ffe98SRichard Henderson static bool trans_BPr(DisasContext *dc, arg_BPr *a)
2208ab9ffe98SRichard Henderson {
2209ab9ffe98SRichard Henderson     DisasCompare cmp;
2210ab9ffe98SRichard Henderson 
2211ab9ffe98SRichard Henderson     if (!avail_64(dc)) {
2212ab9ffe98SRichard Henderson         return false;
2213ab9ffe98SRichard Henderson     }
22142c4f56c9SRichard Henderson     if (!gen_compare_reg(&cmp, a->cond, gen_load_gpr(dc, a->rs1))) {
2215ab9ffe98SRichard Henderson         return false;
2216ab9ffe98SRichard Henderson     }
22173951b7a8SRichard Henderson     return advance_jump_cond(dc, &cmp, a->a, a->i);
2218ab9ffe98SRichard Henderson }
2219ab9ffe98SRichard Henderson 
222023ada1b1SRichard Henderson static bool trans_CALL(DisasContext *dc, arg_CALL *a)
222123ada1b1SRichard Henderson {
222223ada1b1SRichard Henderson     target_long target = address_mask_i(dc, dc->pc + a->i * 4);
222323ada1b1SRichard Henderson 
222423ada1b1SRichard Henderson     gen_store_gpr(dc, 15, tcg_constant_tl(dc->pc));
222523ada1b1SRichard Henderson     gen_mov_pc_npc(dc);
222623ada1b1SRichard Henderson     dc->npc = target;
222723ada1b1SRichard Henderson     return true;
222823ada1b1SRichard Henderson }
222923ada1b1SRichard Henderson 
223045196ea4SRichard Henderson static bool trans_NCP(DisasContext *dc, arg_NCP *a)
223145196ea4SRichard Henderson {
223245196ea4SRichard Henderson     /*
223345196ea4SRichard Henderson      * For sparc32, always generate the no-coprocessor exception.
223445196ea4SRichard Henderson      * For sparc64, always generate illegal instruction.
223545196ea4SRichard Henderson      */
223645196ea4SRichard Henderson #ifdef TARGET_SPARC64
223745196ea4SRichard Henderson     return false;
223845196ea4SRichard Henderson #else
223945196ea4SRichard Henderson     gen_exception(dc, TT_NCP_INSN);
224045196ea4SRichard Henderson     return true;
224145196ea4SRichard Henderson #endif
224245196ea4SRichard Henderson }
224345196ea4SRichard Henderson 
22446d2a0768SRichard Henderson static bool trans_SETHI(DisasContext *dc, arg_SETHI *a)
22456d2a0768SRichard Henderson {
22466d2a0768SRichard Henderson     /* Special-case %g0 because that's the canonical nop.  */
22476d2a0768SRichard Henderson     if (a->rd) {
22486d2a0768SRichard Henderson         gen_store_gpr(dc, a->rd, tcg_constant_tl((uint32_t)a->i << 10));
22496d2a0768SRichard Henderson     }
22506d2a0768SRichard Henderson     return advance_pc(dc);
22516d2a0768SRichard Henderson }
22526d2a0768SRichard Henderson 
22530faef01bSRichard Henderson /*
22540faef01bSRichard Henderson  * Major Opcode 10 -- integer, floating-point, vis, and system insns.
22550faef01bSRichard Henderson  */
22560faef01bSRichard Henderson 
225730376636SRichard Henderson static bool do_tcc(DisasContext *dc, int cond, int cc,
225830376636SRichard Henderson                    int rs1, bool imm, int rs2_or_imm)
225930376636SRichard Henderson {
226030376636SRichard Henderson     int mask = ((dc->def->features & CPU_FEATURE_HYPV) && supervisor(dc)
226130376636SRichard Henderson                 ? UA2005_HTRAP_MASK : V8_TRAP_MASK);
226230376636SRichard Henderson     DisasCompare cmp;
226330376636SRichard Henderson     TCGLabel *lab;
226430376636SRichard Henderson     TCGv_i32 trap;
226530376636SRichard Henderson 
226630376636SRichard Henderson     /* Trap never.  */
226730376636SRichard Henderson     if (cond == 0) {
226830376636SRichard Henderson         return advance_pc(dc);
226930376636SRichard Henderson     }
227030376636SRichard Henderson 
227130376636SRichard Henderson     /*
227230376636SRichard Henderson      * Immediate traps are the most common case.  Since this value is
227330376636SRichard Henderson      * live across the branch, it really pays to evaluate the constant.
227430376636SRichard Henderson      */
227530376636SRichard Henderson     if (rs1 == 0 && (imm || rs2_or_imm == 0)) {
227630376636SRichard Henderson         trap = tcg_constant_i32((rs2_or_imm & mask) + TT_TRAP);
227730376636SRichard Henderson     } else {
227830376636SRichard Henderson         trap = tcg_temp_new_i32();
227930376636SRichard Henderson         tcg_gen_trunc_tl_i32(trap, gen_load_gpr(dc, rs1));
228030376636SRichard Henderson         if (imm) {
228130376636SRichard Henderson             tcg_gen_addi_i32(trap, trap, rs2_or_imm);
228230376636SRichard Henderson         } else {
228330376636SRichard Henderson             TCGv_i32 t2 = tcg_temp_new_i32();
228430376636SRichard Henderson             tcg_gen_trunc_tl_i32(t2, gen_load_gpr(dc, rs2_or_imm));
228530376636SRichard Henderson             tcg_gen_add_i32(trap, trap, t2);
228630376636SRichard Henderson         }
228730376636SRichard Henderson         tcg_gen_andi_i32(trap, trap, mask);
228830376636SRichard Henderson         tcg_gen_addi_i32(trap, trap, TT_TRAP);
228930376636SRichard Henderson     }
229030376636SRichard Henderson 
229189527e3aSRichard Henderson     finishing_insn(dc);
229289527e3aSRichard Henderson 
229330376636SRichard Henderson     /* Trap always.  */
229430376636SRichard Henderson     if (cond == 8) {
229530376636SRichard Henderson         save_state(dc);
229630376636SRichard Henderson         gen_helper_raise_exception(tcg_env, trap);
229730376636SRichard Henderson         dc->base.is_jmp = DISAS_NORETURN;
229830376636SRichard Henderson         return true;
229930376636SRichard Henderson     }
230030376636SRichard Henderson 
230130376636SRichard Henderson     /* Conditional trap.  */
230230376636SRichard Henderson     flush_cond(dc);
230330376636SRichard Henderson     lab = delay_exceptionv(dc, trap);
230430376636SRichard Henderson     gen_compare(&cmp, cc, cond, dc);
2305c8507ebfSRichard Henderson     tcg_gen_brcondi_tl(cmp.cond, cmp.c1, cmp.c2, lab);
230630376636SRichard Henderson 
230730376636SRichard Henderson     return advance_pc(dc);
230830376636SRichard Henderson }
230930376636SRichard Henderson 
231030376636SRichard Henderson static bool trans_Tcc_r(DisasContext *dc, arg_Tcc_r *a)
231130376636SRichard Henderson {
231230376636SRichard Henderson     if (avail_32(dc) && a->cc) {
231330376636SRichard Henderson         return false;
231430376636SRichard Henderson     }
231530376636SRichard Henderson     return do_tcc(dc, a->cond, a->cc, a->rs1, false, a->rs2);
231630376636SRichard Henderson }
231730376636SRichard Henderson 
231830376636SRichard Henderson static bool trans_Tcc_i_v7(DisasContext *dc, arg_Tcc_i_v7 *a)
231930376636SRichard Henderson {
232030376636SRichard Henderson     if (avail_64(dc)) {
232130376636SRichard Henderson         return false;
232230376636SRichard Henderson     }
232330376636SRichard Henderson     return do_tcc(dc, a->cond, 0, a->rs1, true, a->i);
232430376636SRichard Henderson }
232530376636SRichard Henderson 
232630376636SRichard Henderson static bool trans_Tcc_i_v9(DisasContext *dc, arg_Tcc_i_v9 *a)
232730376636SRichard Henderson {
232830376636SRichard Henderson     if (avail_32(dc)) {
232930376636SRichard Henderson         return false;
233030376636SRichard Henderson     }
233130376636SRichard Henderson     return do_tcc(dc, a->cond, a->cc, a->rs1, true, a->i);
233230376636SRichard Henderson }
233330376636SRichard Henderson 
2334af25071cSRichard Henderson static bool trans_STBAR(DisasContext *dc, arg_STBAR *a)
2335af25071cSRichard Henderson {
2336af25071cSRichard Henderson     tcg_gen_mb(TCG_MO_ST_ST | TCG_BAR_SC);
2337af25071cSRichard Henderson     return advance_pc(dc);
2338af25071cSRichard Henderson }
2339af25071cSRichard Henderson 
2340af25071cSRichard Henderson static bool trans_MEMBAR(DisasContext *dc, arg_MEMBAR *a)
2341af25071cSRichard Henderson {
2342af25071cSRichard Henderson     if (avail_32(dc)) {
2343af25071cSRichard Henderson         return false;
2344af25071cSRichard Henderson     }
2345af25071cSRichard Henderson     if (a->mmask) {
2346af25071cSRichard Henderson         /* Note TCG_MO_* was modeled on sparc64, so mmask matches. */
2347af25071cSRichard Henderson         tcg_gen_mb(a->mmask | TCG_BAR_SC);
2348af25071cSRichard Henderson     }
2349af25071cSRichard Henderson     if (a->cmask) {
2350af25071cSRichard Henderson         /* For #Sync, etc, end the TB to recognize interrupts. */
2351af25071cSRichard Henderson         dc->base.is_jmp = DISAS_EXIT;
2352af25071cSRichard Henderson     }
2353af25071cSRichard Henderson     return advance_pc(dc);
2354af25071cSRichard Henderson }
2355af25071cSRichard Henderson 
2356af25071cSRichard Henderson static bool do_rd_special(DisasContext *dc, bool priv, int rd,
2357af25071cSRichard Henderson                           TCGv (*func)(DisasContext *, TCGv))
2358af25071cSRichard Henderson {
2359af25071cSRichard Henderson     if (!priv) {
2360af25071cSRichard Henderson         return raise_priv(dc);
2361af25071cSRichard Henderson     }
2362af25071cSRichard Henderson     gen_store_gpr(dc, rd, func(dc, gen_dest_gpr(dc, rd)));
2363af25071cSRichard Henderson     return advance_pc(dc);
2364af25071cSRichard Henderson }
2365af25071cSRichard Henderson 
2366af25071cSRichard Henderson static TCGv do_rdy(DisasContext *dc, TCGv dst)
2367af25071cSRichard Henderson {
2368af25071cSRichard Henderson     return cpu_y;
2369af25071cSRichard Henderson }
2370af25071cSRichard Henderson 
2371af25071cSRichard Henderson static bool trans_RDY(DisasContext *dc, arg_RDY *a)
2372af25071cSRichard Henderson {
2373af25071cSRichard Henderson     /*
2374af25071cSRichard Henderson      * TODO: Need a feature bit for sparcv8.  In the meantime, treat all
2375af25071cSRichard Henderson      * 32-bit cpus like sparcv7, which ignores the rs1 field.
2376af25071cSRichard Henderson      * This matches after all other ASR, so Leon3 Asr17 is handled first.
2377af25071cSRichard Henderson      */
2378af25071cSRichard Henderson     if (avail_64(dc) && a->rs1 != 0) {
2379af25071cSRichard Henderson         return false;
2380af25071cSRichard Henderson     }
2381af25071cSRichard Henderson     return do_rd_special(dc, true, a->rd, do_rdy);
2382af25071cSRichard Henderson }
2383af25071cSRichard Henderson 
2384af25071cSRichard Henderson static TCGv do_rd_leon3_config(DisasContext *dc, TCGv dst)
2385af25071cSRichard Henderson {
2386*c92948f2SClément Chigot     gen_helper_rdasr17(dst, tcg_env);
2387*c92948f2SClément Chigot     return dst;
2388af25071cSRichard Henderson }
2389af25071cSRichard Henderson 
2390af25071cSRichard Henderson TRANS(RDASR17, ASR17, do_rd_special, true, a->rd, do_rd_leon3_config)
2391af25071cSRichard Henderson 
2392af25071cSRichard Henderson static TCGv do_rdccr(DisasContext *dc, TCGv dst)
2393af25071cSRichard Henderson {
2394af25071cSRichard Henderson     gen_helper_rdccr(dst, tcg_env);
2395af25071cSRichard Henderson     return dst;
2396af25071cSRichard Henderson }
2397af25071cSRichard Henderson 
2398af25071cSRichard Henderson TRANS(RDCCR, 64, do_rd_special, true, a->rd, do_rdccr)
2399af25071cSRichard Henderson 
2400af25071cSRichard Henderson static TCGv do_rdasi(DisasContext *dc, TCGv dst)
2401af25071cSRichard Henderson {
2402af25071cSRichard Henderson #ifdef TARGET_SPARC64
2403af25071cSRichard Henderson     return tcg_constant_tl(dc->asi);
2404af25071cSRichard Henderson #else
2405af25071cSRichard Henderson     qemu_build_not_reached();
2406af25071cSRichard Henderson #endif
2407af25071cSRichard Henderson }
2408af25071cSRichard Henderson 
2409af25071cSRichard Henderson TRANS(RDASI, 64, do_rd_special, true, a->rd, do_rdasi)
2410af25071cSRichard Henderson 
2411af25071cSRichard Henderson static TCGv do_rdtick(DisasContext *dc, TCGv dst)
2412af25071cSRichard Henderson {
2413af25071cSRichard Henderson     TCGv_ptr r_tickptr = tcg_temp_new_ptr();
2414af25071cSRichard Henderson 
2415af25071cSRichard Henderson     tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(tick));
2416af25071cSRichard Henderson     if (translator_io_start(&dc->base)) {
2417af25071cSRichard Henderson         dc->base.is_jmp = DISAS_EXIT;
2418af25071cSRichard Henderson     }
2419af25071cSRichard Henderson     gen_helper_tick_get_count(dst, tcg_env, r_tickptr,
2420af25071cSRichard Henderson                               tcg_constant_i32(dc->mem_idx));
2421af25071cSRichard Henderson     return dst;
2422af25071cSRichard Henderson }
2423af25071cSRichard Henderson 
2424af25071cSRichard Henderson /* TODO: non-priv access only allowed when enabled. */
2425af25071cSRichard Henderson TRANS(RDTICK, 64, do_rd_special, true, a->rd, do_rdtick)
2426af25071cSRichard Henderson 
2427af25071cSRichard Henderson static TCGv do_rdpc(DisasContext *dc, TCGv dst)
2428af25071cSRichard Henderson {
2429af25071cSRichard Henderson     return tcg_constant_tl(address_mask_i(dc, dc->pc));
2430af25071cSRichard Henderson }
2431af25071cSRichard Henderson 
2432af25071cSRichard Henderson TRANS(RDPC, 64, do_rd_special, true, a->rd, do_rdpc)
2433af25071cSRichard Henderson 
2434af25071cSRichard Henderson static TCGv do_rdfprs(DisasContext *dc, TCGv dst)
2435af25071cSRichard Henderson {
2436af25071cSRichard Henderson     tcg_gen_ext_i32_tl(dst, cpu_fprs);
2437af25071cSRichard Henderson     return dst;
2438af25071cSRichard Henderson }
2439af25071cSRichard Henderson 
2440af25071cSRichard Henderson TRANS(RDFPRS, 64, do_rd_special, true, a->rd, do_rdfprs)
2441af25071cSRichard Henderson 
2442af25071cSRichard Henderson static TCGv do_rdgsr(DisasContext *dc, TCGv dst)
2443af25071cSRichard Henderson {
2444af25071cSRichard Henderson     gen_trap_ifnofpu(dc);
2445af25071cSRichard Henderson     return cpu_gsr;
2446af25071cSRichard Henderson }
2447af25071cSRichard Henderson 
2448af25071cSRichard Henderson TRANS(RDGSR, 64, do_rd_special, true, a->rd, do_rdgsr)
2449af25071cSRichard Henderson 
2450af25071cSRichard Henderson static TCGv do_rdsoftint(DisasContext *dc, TCGv dst)
2451af25071cSRichard Henderson {
2452af25071cSRichard Henderson     tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(softint));
2453af25071cSRichard Henderson     return dst;
2454af25071cSRichard Henderson }
2455af25071cSRichard Henderson 
2456af25071cSRichard Henderson TRANS(RDSOFTINT, 64, do_rd_special, supervisor(dc), a->rd, do_rdsoftint)
2457af25071cSRichard Henderson 
2458af25071cSRichard Henderson static TCGv do_rdtick_cmpr(DisasContext *dc, TCGv dst)
2459af25071cSRichard Henderson {
2460577efa45SRichard Henderson     tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(tick_cmpr));
2461577efa45SRichard Henderson     return dst;
2462af25071cSRichard Henderson }
2463af25071cSRichard Henderson 
2464af25071cSRichard Henderson /* TODO: non-priv access only allowed when enabled. */
2465af25071cSRichard Henderson TRANS(RDTICK_CMPR, 64, do_rd_special, true, a->rd, do_rdtick_cmpr)
2466af25071cSRichard Henderson 
2467af25071cSRichard Henderson static TCGv do_rdstick(DisasContext *dc, TCGv dst)
2468af25071cSRichard Henderson {
2469af25071cSRichard Henderson     TCGv_ptr r_tickptr = tcg_temp_new_ptr();
2470af25071cSRichard Henderson 
2471af25071cSRichard Henderson     tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(stick));
2472af25071cSRichard Henderson     if (translator_io_start(&dc->base)) {
2473af25071cSRichard Henderson         dc->base.is_jmp = DISAS_EXIT;
2474af25071cSRichard Henderson     }
2475af25071cSRichard Henderson     gen_helper_tick_get_count(dst, tcg_env, r_tickptr,
2476af25071cSRichard Henderson                               tcg_constant_i32(dc->mem_idx));
2477af25071cSRichard Henderson     return dst;
2478af25071cSRichard Henderson }
2479af25071cSRichard Henderson 
2480af25071cSRichard Henderson /* TODO: non-priv access only allowed when enabled. */
2481af25071cSRichard Henderson TRANS(RDSTICK, 64, do_rd_special, true, a->rd, do_rdstick)
2482af25071cSRichard Henderson 
2483af25071cSRichard Henderson static TCGv do_rdstick_cmpr(DisasContext *dc, TCGv dst)
2484af25071cSRichard Henderson {
2485577efa45SRichard Henderson     tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(stick_cmpr));
2486577efa45SRichard Henderson     return dst;
2487af25071cSRichard Henderson }
2488af25071cSRichard Henderson 
2489af25071cSRichard Henderson /* TODO: supervisor access only allowed when enabled by hypervisor. */
2490af25071cSRichard Henderson TRANS(RDSTICK_CMPR, 64, do_rd_special, supervisor(dc), a->rd, do_rdstick_cmpr)
2491af25071cSRichard Henderson 
2492af25071cSRichard Henderson /*
2493af25071cSRichard Henderson  * UltraSPARC-T1 Strand status.
2494af25071cSRichard Henderson  * HYPV check maybe not enough, UA2005 & UA2007 describe
2495af25071cSRichard Henderson  * this ASR as impl. dep
2496af25071cSRichard Henderson  */
2497af25071cSRichard Henderson static TCGv do_rdstrand_status(DisasContext *dc, TCGv dst)
2498af25071cSRichard Henderson {
2499af25071cSRichard Henderson     return tcg_constant_tl(1);
2500af25071cSRichard Henderson }
2501af25071cSRichard Henderson 
2502af25071cSRichard Henderson TRANS(RDSTRAND_STATUS, HYPV, do_rd_special, true, a->rd, do_rdstrand_status)
2503af25071cSRichard Henderson 
2504668bb9b7SRichard Henderson static TCGv do_rdpsr(DisasContext *dc, TCGv dst)
2505668bb9b7SRichard Henderson {
2506668bb9b7SRichard Henderson     gen_helper_rdpsr(dst, tcg_env);
2507668bb9b7SRichard Henderson     return dst;
2508668bb9b7SRichard Henderson }
2509668bb9b7SRichard Henderson 
2510668bb9b7SRichard Henderson TRANS(RDPSR, 32, do_rd_special, supervisor(dc), a->rd, do_rdpsr)
2511668bb9b7SRichard Henderson 
2512668bb9b7SRichard Henderson static TCGv do_rdhpstate(DisasContext *dc, TCGv dst)
2513668bb9b7SRichard Henderson {
2514668bb9b7SRichard Henderson     tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hpstate));
2515668bb9b7SRichard Henderson     return dst;
2516668bb9b7SRichard Henderson }
2517668bb9b7SRichard Henderson 
2518668bb9b7SRichard Henderson TRANS(RDHPR_hpstate, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhpstate)
2519668bb9b7SRichard Henderson 
2520668bb9b7SRichard Henderson static TCGv do_rdhtstate(DisasContext *dc, TCGv dst)
2521668bb9b7SRichard Henderson {
2522668bb9b7SRichard Henderson     TCGv_i32 tl = tcg_temp_new_i32();
2523668bb9b7SRichard Henderson     TCGv_ptr tp = tcg_temp_new_ptr();
2524668bb9b7SRichard Henderson 
2525668bb9b7SRichard Henderson     tcg_gen_ld_i32(tl, tcg_env, env64_field_offsetof(tl));
2526668bb9b7SRichard Henderson     tcg_gen_andi_i32(tl, tl, MAXTL_MASK);
2527668bb9b7SRichard Henderson     tcg_gen_shli_i32(tl, tl, 3);
2528668bb9b7SRichard Henderson     tcg_gen_ext_i32_ptr(tp, tl);
2529668bb9b7SRichard Henderson     tcg_gen_add_ptr(tp, tp, tcg_env);
2530668bb9b7SRichard Henderson 
2531668bb9b7SRichard Henderson     tcg_gen_ld_tl(dst, tp, env64_field_offsetof(htstate));
2532668bb9b7SRichard Henderson     return dst;
2533668bb9b7SRichard Henderson }
2534668bb9b7SRichard Henderson 
2535668bb9b7SRichard Henderson TRANS(RDHPR_htstate, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhtstate)
2536668bb9b7SRichard Henderson 
2537668bb9b7SRichard Henderson static TCGv do_rdhintp(DisasContext *dc, TCGv dst)
2538668bb9b7SRichard Henderson {
25392da789deSRichard Henderson     tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hintp));
25402da789deSRichard Henderson     return dst;
2541668bb9b7SRichard Henderson }
2542668bb9b7SRichard Henderson 
2543668bb9b7SRichard Henderson TRANS(RDHPR_hintp, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhintp)
2544668bb9b7SRichard Henderson 
2545668bb9b7SRichard Henderson static TCGv do_rdhtba(DisasContext *dc, TCGv dst)
2546668bb9b7SRichard Henderson {
25472da789deSRichard Henderson     tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(htba));
25482da789deSRichard Henderson     return dst;
2549668bb9b7SRichard Henderson }
2550668bb9b7SRichard Henderson 
2551668bb9b7SRichard Henderson TRANS(RDHPR_htba, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhtba)
2552668bb9b7SRichard Henderson 
2553668bb9b7SRichard Henderson static TCGv do_rdhver(DisasContext *dc, TCGv dst)
2554668bb9b7SRichard Henderson {
25552da789deSRichard Henderson     tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hver));
25562da789deSRichard Henderson     return dst;
2557668bb9b7SRichard Henderson }
2558668bb9b7SRichard Henderson 
2559668bb9b7SRichard Henderson TRANS(RDHPR_hver, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdhver)
2560668bb9b7SRichard Henderson 
2561668bb9b7SRichard Henderson static TCGv do_rdhstick_cmpr(DisasContext *dc, TCGv dst)
2562668bb9b7SRichard Henderson {
2563577efa45SRichard Henderson     tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(hstick_cmpr));
2564577efa45SRichard Henderson     return dst;
2565668bb9b7SRichard Henderson }
2566668bb9b7SRichard Henderson 
2567668bb9b7SRichard Henderson TRANS(RDHPR_hstick_cmpr, HYPV, do_rd_special, hypervisor(dc), a->rd,
2568668bb9b7SRichard Henderson       do_rdhstick_cmpr)
2569668bb9b7SRichard Henderson 
25705d617bfbSRichard Henderson static TCGv do_rdwim(DisasContext *dc, TCGv dst)
25715d617bfbSRichard Henderson {
2572cd6269f7SRichard Henderson     tcg_gen_ld_tl(dst, tcg_env, env32_field_offsetof(wim));
2573cd6269f7SRichard Henderson     return dst;
25745d617bfbSRichard Henderson }
25755d617bfbSRichard Henderson 
25765d617bfbSRichard Henderson TRANS(RDWIM, 32, do_rd_special, supervisor(dc), a->rd, do_rdwim)
25775d617bfbSRichard Henderson 
25785d617bfbSRichard Henderson static TCGv do_rdtpc(DisasContext *dc, TCGv dst)
25795d617bfbSRichard Henderson {
25805d617bfbSRichard Henderson #ifdef TARGET_SPARC64
25815d617bfbSRichard Henderson     TCGv_ptr r_tsptr = tcg_temp_new_ptr();
25825d617bfbSRichard Henderson 
25835d617bfbSRichard Henderson     gen_load_trap_state_at_tl(r_tsptr);
25845d617bfbSRichard Henderson     tcg_gen_ld_tl(dst, r_tsptr, offsetof(trap_state, tpc));
25855d617bfbSRichard Henderson     return dst;
25865d617bfbSRichard Henderson #else
25875d617bfbSRichard Henderson     qemu_build_not_reached();
25885d617bfbSRichard Henderson #endif
25895d617bfbSRichard Henderson }
25905d617bfbSRichard Henderson 
25915d617bfbSRichard Henderson TRANS(RDPR_tpc, 64, do_rd_special, supervisor(dc), a->rd, do_rdtpc)
25925d617bfbSRichard Henderson 
25935d617bfbSRichard Henderson static TCGv do_rdtnpc(DisasContext *dc, TCGv dst)
25945d617bfbSRichard Henderson {
25955d617bfbSRichard Henderson #ifdef TARGET_SPARC64
25965d617bfbSRichard Henderson     TCGv_ptr r_tsptr = tcg_temp_new_ptr();
25975d617bfbSRichard Henderson 
25985d617bfbSRichard Henderson     gen_load_trap_state_at_tl(r_tsptr);
25995d617bfbSRichard Henderson     tcg_gen_ld_tl(dst, r_tsptr, offsetof(trap_state, tnpc));
26005d617bfbSRichard Henderson     return dst;
26015d617bfbSRichard Henderson #else
26025d617bfbSRichard Henderson     qemu_build_not_reached();
26035d617bfbSRichard Henderson #endif
26045d617bfbSRichard Henderson }
26055d617bfbSRichard Henderson 
26065d617bfbSRichard Henderson TRANS(RDPR_tnpc, 64, do_rd_special, supervisor(dc), a->rd, do_rdtnpc)
26075d617bfbSRichard Henderson 
26085d617bfbSRichard Henderson static TCGv do_rdtstate(DisasContext *dc, TCGv dst)
26095d617bfbSRichard Henderson {
26105d617bfbSRichard Henderson #ifdef TARGET_SPARC64
26115d617bfbSRichard Henderson     TCGv_ptr r_tsptr = tcg_temp_new_ptr();
26125d617bfbSRichard Henderson 
26135d617bfbSRichard Henderson     gen_load_trap_state_at_tl(r_tsptr);
26145d617bfbSRichard Henderson     tcg_gen_ld_tl(dst, r_tsptr, offsetof(trap_state, tstate));
26155d617bfbSRichard Henderson     return dst;
26165d617bfbSRichard Henderson #else
26175d617bfbSRichard Henderson     qemu_build_not_reached();
26185d617bfbSRichard Henderson #endif
26195d617bfbSRichard Henderson }
26205d617bfbSRichard Henderson 
26215d617bfbSRichard Henderson TRANS(RDPR_tstate, 64, do_rd_special, supervisor(dc), a->rd, do_rdtstate)
26225d617bfbSRichard Henderson 
26235d617bfbSRichard Henderson static TCGv do_rdtt(DisasContext *dc, TCGv dst)
26245d617bfbSRichard Henderson {
26255d617bfbSRichard Henderson #ifdef TARGET_SPARC64
26265d617bfbSRichard Henderson     TCGv_ptr r_tsptr = tcg_temp_new_ptr();
26275d617bfbSRichard Henderson 
26285d617bfbSRichard Henderson     gen_load_trap_state_at_tl(r_tsptr);
26295d617bfbSRichard Henderson     tcg_gen_ld32s_tl(dst, r_tsptr, offsetof(trap_state, tt));
26305d617bfbSRichard Henderson     return dst;
26315d617bfbSRichard Henderson #else
26325d617bfbSRichard Henderson     qemu_build_not_reached();
26335d617bfbSRichard Henderson #endif
26345d617bfbSRichard Henderson }
26355d617bfbSRichard Henderson 
26365d617bfbSRichard Henderson TRANS(RDPR_tt, 64, do_rd_special, supervisor(dc), a->rd, do_rdtt)
26375d617bfbSRichard Henderson TRANS(RDPR_tick, 64, do_rd_special, supervisor(dc), a->rd, do_rdtick)
26385d617bfbSRichard Henderson 
26395d617bfbSRichard Henderson static TCGv do_rdtba(DisasContext *dc, TCGv dst)
26405d617bfbSRichard Henderson {
26415d617bfbSRichard Henderson     return cpu_tbr;
26425d617bfbSRichard Henderson }
26435d617bfbSRichard Henderson 
2644e8325dc0SRichard Henderson TRANS(RDTBR, 32, do_rd_special, supervisor(dc), a->rd, do_rdtba)
26455d617bfbSRichard Henderson TRANS(RDPR_tba, 64, do_rd_special, supervisor(dc), a->rd, do_rdtba)
26465d617bfbSRichard Henderson 
26475d617bfbSRichard Henderson static TCGv do_rdpstate(DisasContext *dc, TCGv dst)
26485d617bfbSRichard Henderson {
26495d617bfbSRichard Henderson     tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(pstate));
26505d617bfbSRichard Henderson     return dst;
26515d617bfbSRichard Henderson }
26525d617bfbSRichard Henderson 
26535d617bfbSRichard Henderson TRANS(RDPR_pstate, 64, do_rd_special, supervisor(dc), a->rd, do_rdpstate)
26545d617bfbSRichard Henderson 
26555d617bfbSRichard Henderson static TCGv do_rdtl(DisasContext *dc, TCGv dst)
26565d617bfbSRichard Henderson {
26575d617bfbSRichard Henderson     tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(tl));
26585d617bfbSRichard Henderson     return dst;
26595d617bfbSRichard Henderson }
26605d617bfbSRichard Henderson 
26615d617bfbSRichard Henderson TRANS(RDPR_tl, 64, do_rd_special, supervisor(dc), a->rd, do_rdtl)
26625d617bfbSRichard Henderson 
26635d617bfbSRichard Henderson static TCGv do_rdpil(DisasContext *dc, TCGv dst)
26645d617bfbSRichard Henderson {
26655d617bfbSRichard Henderson     tcg_gen_ld32s_tl(dst, tcg_env, env_field_offsetof(psrpil));
26665d617bfbSRichard Henderson     return dst;
26675d617bfbSRichard Henderson }
26685d617bfbSRichard Henderson 
26695d617bfbSRichard Henderson TRANS(RDPR_pil, 64, do_rd_special, supervisor(dc), a->rd, do_rdpil)
26705d617bfbSRichard Henderson 
26715d617bfbSRichard Henderson static TCGv do_rdcwp(DisasContext *dc, TCGv dst)
26725d617bfbSRichard Henderson {
26735d617bfbSRichard Henderson     gen_helper_rdcwp(dst, tcg_env);
26745d617bfbSRichard Henderson     return dst;
26755d617bfbSRichard Henderson }
26765d617bfbSRichard Henderson 
26775d617bfbSRichard Henderson TRANS(RDPR_cwp, 64, do_rd_special, supervisor(dc), a->rd, do_rdcwp)
26785d617bfbSRichard Henderson 
26795d617bfbSRichard Henderson static TCGv do_rdcansave(DisasContext *dc, TCGv dst)
26805d617bfbSRichard Henderson {
26815d617bfbSRichard Henderson     tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(cansave));
26825d617bfbSRichard Henderson     return dst;
26835d617bfbSRichard Henderson }
26845d617bfbSRichard Henderson 
26855d617bfbSRichard Henderson TRANS(RDPR_cansave, 64, do_rd_special, supervisor(dc), a->rd, do_rdcansave)
26865d617bfbSRichard Henderson 
26875d617bfbSRichard Henderson static TCGv do_rdcanrestore(DisasContext *dc, TCGv dst)
26885d617bfbSRichard Henderson {
26895d617bfbSRichard Henderson     tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(canrestore));
26905d617bfbSRichard Henderson     return dst;
26915d617bfbSRichard Henderson }
26925d617bfbSRichard Henderson 
26935d617bfbSRichard Henderson TRANS(RDPR_canrestore, 64, do_rd_special, supervisor(dc), a->rd,
26945d617bfbSRichard Henderson       do_rdcanrestore)
26955d617bfbSRichard Henderson 
26965d617bfbSRichard Henderson static TCGv do_rdcleanwin(DisasContext *dc, TCGv dst)
26975d617bfbSRichard Henderson {
26985d617bfbSRichard Henderson     tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(cleanwin));
26995d617bfbSRichard Henderson     return dst;
27005d617bfbSRichard Henderson }
27015d617bfbSRichard Henderson 
27025d617bfbSRichard Henderson TRANS(RDPR_cleanwin, 64, do_rd_special, supervisor(dc), a->rd, do_rdcleanwin)
27035d617bfbSRichard Henderson 
27045d617bfbSRichard Henderson static TCGv do_rdotherwin(DisasContext *dc, TCGv dst)
27055d617bfbSRichard Henderson {
27065d617bfbSRichard Henderson     tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(otherwin));
27075d617bfbSRichard Henderson     return dst;
27085d617bfbSRichard Henderson }
27095d617bfbSRichard Henderson 
27105d617bfbSRichard Henderson TRANS(RDPR_otherwin, 64, do_rd_special, supervisor(dc), a->rd, do_rdotherwin)
27115d617bfbSRichard Henderson 
27125d617bfbSRichard Henderson static TCGv do_rdwstate(DisasContext *dc, TCGv dst)
27135d617bfbSRichard Henderson {
27145d617bfbSRichard Henderson     tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(wstate));
27155d617bfbSRichard Henderson     return dst;
27165d617bfbSRichard Henderson }
27175d617bfbSRichard Henderson 
27185d617bfbSRichard Henderson TRANS(RDPR_wstate, 64, do_rd_special, supervisor(dc), a->rd, do_rdwstate)
27195d617bfbSRichard Henderson 
27205d617bfbSRichard Henderson static TCGv do_rdgl(DisasContext *dc, TCGv dst)
27215d617bfbSRichard Henderson {
27225d617bfbSRichard Henderson     tcg_gen_ld32s_tl(dst, tcg_env, env64_field_offsetof(gl));
27235d617bfbSRichard Henderson     return dst;
27245d617bfbSRichard Henderson }
27255d617bfbSRichard Henderson 
27265d617bfbSRichard Henderson TRANS(RDPR_gl, GL, do_rd_special, supervisor(dc), a->rd, do_rdgl)
27275d617bfbSRichard Henderson 
27285d617bfbSRichard Henderson /* UA2005 strand status */
27295d617bfbSRichard Henderson static TCGv do_rdssr(DisasContext *dc, TCGv dst)
27305d617bfbSRichard Henderson {
27312da789deSRichard Henderson     tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(ssr));
27322da789deSRichard Henderson     return dst;
27335d617bfbSRichard Henderson }
27345d617bfbSRichard Henderson 
27355d617bfbSRichard Henderson TRANS(RDPR_strand_status, HYPV, do_rd_special, hypervisor(dc), a->rd, do_rdssr)
27365d617bfbSRichard Henderson 
27375d617bfbSRichard Henderson static TCGv do_rdver(DisasContext *dc, TCGv dst)
27385d617bfbSRichard Henderson {
27392da789deSRichard Henderson     tcg_gen_ld_tl(dst, tcg_env, env64_field_offsetof(version));
27402da789deSRichard Henderson     return dst;
27415d617bfbSRichard Henderson }
27425d617bfbSRichard Henderson 
27435d617bfbSRichard Henderson TRANS(RDPR_ver, 64, do_rd_special, supervisor(dc), a->rd, do_rdver)
27445d617bfbSRichard Henderson 
2745e8325dc0SRichard Henderson static bool trans_FLUSHW(DisasContext *dc, arg_FLUSHW *a)
2746e8325dc0SRichard Henderson {
2747e8325dc0SRichard Henderson     if (avail_64(dc)) {
2748e8325dc0SRichard Henderson         gen_helper_flushw(tcg_env);
2749e8325dc0SRichard Henderson         return advance_pc(dc);
2750e8325dc0SRichard Henderson     }
2751e8325dc0SRichard Henderson     return false;
2752e8325dc0SRichard Henderson }
2753e8325dc0SRichard Henderson 
27540faef01bSRichard Henderson static bool do_wr_special(DisasContext *dc, arg_r_r_ri *a, bool priv,
27550faef01bSRichard Henderson                           void (*func)(DisasContext *, TCGv))
27560faef01bSRichard Henderson {
27570faef01bSRichard Henderson     TCGv src;
27580faef01bSRichard Henderson 
27590faef01bSRichard Henderson     /* For simplicity, we under-decoded the rs2 form. */
27600faef01bSRichard Henderson     if (!a->imm && (a->rs2_or_imm & ~0x1f)) {
27610faef01bSRichard Henderson         return false;
27620faef01bSRichard Henderson     }
27630faef01bSRichard Henderson     if (!priv) {
27640faef01bSRichard Henderson         return raise_priv(dc);
27650faef01bSRichard Henderson     }
27660faef01bSRichard Henderson 
27670faef01bSRichard Henderson     if (a->rs1 == 0 && (a->imm || a->rs2_or_imm == 0)) {
27680faef01bSRichard Henderson         src = tcg_constant_tl(a->rs2_or_imm);
27690faef01bSRichard Henderson     } else {
27700faef01bSRichard Henderson         TCGv src1 = gen_load_gpr(dc, a->rs1);
27710faef01bSRichard Henderson         if (a->rs2_or_imm == 0) {
27720faef01bSRichard Henderson             src = src1;
27730faef01bSRichard Henderson         } else {
27740faef01bSRichard Henderson             src = tcg_temp_new();
27750faef01bSRichard Henderson             if (a->imm) {
27760faef01bSRichard Henderson                 tcg_gen_xori_tl(src, src1, a->rs2_or_imm);
27770faef01bSRichard Henderson             } else {
27780faef01bSRichard Henderson                 tcg_gen_xor_tl(src, src1, gen_load_gpr(dc, a->rs2_or_imm));
27790faef01bSRichard Henderson             }
27800faef01bSRichard Henderson         }
27810faef01bSRichard Henderson     }
27820faef01bSRichard Henderson     func(dc, src);
27830faef01bSRichard Henderson     return advance_pc(dc);
27840faef01bSRichard Henderson }
27850faef01bSRichard Henderson 
27860faef01bSRichard Henderson static void do_wry(DisasContext *dc, TCGv src)
27870faef01bSRichard Henderson {
27880faef01bSRichard Henderson     tcg_gen_ext32u_tl(cpu_y, src);
27890faef01bSRichard Henderson }
27900faef01bSRichard Henderson 
27910faef01bSRichard Henderson TRANS(WRY, ALL, do_wr_special, a, true, do_wry)
27920faef01bSRichard Henderson 
27930faef01bSRichard Henderson static void do_wrccr(DisasContext *dc, TCGv src)
27940faef01bSRichard Henderson {
27950faef01bSRichard Henderson     gen_helper_wrccr(tcg_env, src);
27960faef01bSRichard Henderson }
27970faef01bSRichard Henderson 
27980faef01bSRichard Henderson TRANS(WRCCR, 64, do_wr_special, a, true, do_wrccr)
27990faef01bSRichard Henderson 
28000faef01bSRichard Henderson static void do_wrasi(DisasContext *dc, TCGv src)
28010faef01bSRichard Henderson {
28020faef01bSRichard Henderson     TCGv tmp = tcg_temp_new();
28030faef01bSRichard Henderson 
28040faef01bSRichard Henderson     tcg_gen_ext8u_tl(tmp, src);
28050faef01bSRichard Henderson     tcg_gen_st32_tl(tmp, tcg_env, env64_field_offsetof(asi));
28060faef01bSRichard Henderson     /* End TB to notice changed ASI. */
28070faef01bSRichard Henderson     dc->base.is_jmp = DISAS_EXIT;
28080faef01bSRichard Henderson }
28090faef01bSRichard Henderson 
28100faef01bSRichard Henderson TRANS(WRASI, 64, do_wr_special, a, true, do_wrasi)
28110faef01bSRichard Henderson 
28120faef01bSRichard Henderson static void do_wrfprs(DisasContext *dc, TCGv src)
28130faef01bSRichard Henderson {
28140faef01bSRichard Henderson #ifdef TARGET_SPARC64
28150faef01bSRichard Henderson     tcg_gen_trunc_tl_i32(cpu_fprs, src);
28160faef01bSRichard Henderson     dc->fprs_dirty = 0;
28170faef01bSRichard Henderson     dc->base.is_jmp = DISAS_EXIT;
28180faef01bSRichard Henderson #else
28190faef01bSRichard Henderson     qemu_build_not_reached();
28200faef01bSRichard Henderson #endif
28210faef01bSRichard Henderson }
28220faef01bSRichard Henderson 
28230faef01bSRichard Henderson TRANS(WRFPRS, 64, do_wr_special, a, true, do_wrfprs)
28240faef01bSRichard Henderson 
28250faef01bSRichard Henderson static void do_wrgsr(DisasContext *dc, TCGv src)
28260faef01bSRichard Henderson {
28270faef01bSRichard Henderson     gen_trap_ifnofpu(dc);
28280faef01bSRichard Henderson     tcg_gen_mov_tl(cpu_gsr, src);
28290faef01bSRichard Henderson }
28300faef01bSRichard Henderson 
28310faef01bSRichard Henderson TRANS(WRGSR, 64, do_wr_special, a, true, do_wrgsr)
28320faef01bSRichard Henderson 
28330faef01bSRichard Henderson static void do_wrsoftint_set(DisasContext *dc, TCGv src)
28340faef01bSRichard Henderson {
28350faef01bSRichard Henderson     gen_helper_set_softint(tcg_env, src);
28360faef01bSRichard Henderson }
28370faef01bSRichard Henderson 
28380faef01bSRichard Henderson TRANS(WRSOFTINT_SET, 64, do_wr_special, a, supervisor(dc), do_wrsoftint_set)
28390faef01bSRichard Henderson 
28400faef01bSRichard Henderson static void do_wrsoftint_clr(DisasContext *dc, TCGv src)
28410faef01bSRichard Henderson {
28420faef01bSRichard Henderson     gen_helper_clear_softint(tcg_env, src);
28430faef01bSRichard Henderson }
28440faef01bSRichard Henderson 
28450faef01bSRichard Henderson TRANS(WRSOFTINT_CLR, 64, do_wr_special, a, supervisor(dc), do_wrsoftint_clr)
28460faef01bSRichard Henderson 
28470faef01bSRichard Henderson static void do_wrsoftint(DisasContext *dc, TCGv src)
28480faef01bSRichard Henderson {
28490faef01bSRichard Henderson     gen_helper_write_softint(tcg_env, src);
28500faef01bSRichard Henderson }
28510faef01bSRichard Henderson 
28520faef01bSRichard Henderson TRANS(WRSOFTINT, 64, do_wr_special, a, supervisor(dc), do_wrsoftint)
28530faef01bSRichard Henderson 
28540faef01bSRichard Henderson static void do_wrtick_cmpr(DisasContext *dc, TCGv src)
28550faef01bSRichard Henderson {
28560faef01bSRichard Henderson     TCGv_ptr r_tickptr = tcg_temp_new_ptr();
28570faef01bSRichard Henderson 
2858577efa45SRichard Henderson     tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(tick_cmpr));
2859577efa45SRichard Henderson     tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(tick));
28600faef01bSRichard Henderson     translator_io_start(&dc->base);
2861577efa45SRichard Henderson     gen_helper_tick_set_limit(r_tickptr, src);
28620faef01bSRichard Henderson     /* End TB to handle timer interrupt */
28630faef01bSRichard Henderson     dc->base.is_jmp = DISAS_EXIT;
28640faef01bSRichard Henderson }
28650faef01bSRichard Henderson 
28660faef01bSRichard Henderson TRANS(WRTICK_CMPR, 64, do_wr_special, a, supervisor(dc), do_wrtick_cmpr)
28670faef01bSRichard Henderson 
28680faef01bSRichard Henderson static void do_wrstick(DisasContext *dc, TCGv src)
28690faef01bSRichard Henderson {
28700faef01bSRichard Henderson #ifdef TARGET_SPARC64
28710faef01bSRichard Henderson     TCGv_ptr r_tickptr = tcg_temp_new_ptr();
28720faef01bSRichard Henderson 
28730faef01bSRichard Henderson     tcg_gen_ld_ptr(r_tickptr, tcg_env, offsetof(CPUSPARCState, stick));
28740faef01bSRichard Henderson     translator_io_start(&dc->base);
28750faef01bSRichard Henderson     gen_helper_tick_set_count(r_tickptr, src);
28760faef01bSRichard Henderson     /* End TB to handle timer interrupt */
28770faef01bSRichard Henderson     dc->base.is_jmp = DISAS_EXIT;
28780faef01bSRichard Henderson #else
28790faef01bSRichard Henderson     qemu_build_not_reached();
28800faef01bSRichard Henderson #endif
28810faef01bSRichard Henderson }
28820faef01bSRichard Henderson 
28830faef01bSRichard Henderson TRANS(WRSTICK, 64, do_wr_special, a, supervisor(dc), do_wrstick)
28840faef01bSRichard Henderson 
28850faef01bSRichard Henderson static void do_wrstick_cmpr(DisasContext *dc, TCGv src)
28860faef01bSRichard Henderson {
28870faef01bSRichard Henderson     TCGv_ptr r_tickptr = tcg_temp_new_ptr();
28880faef01bSRichard Henderson 
2889577efa45SRichard Henderson     tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(stick_cmpr));
2890577efa45SRichard Henderson     tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(stick));
28910faef01bSRichard Henderson     translator_io_start(&dc->base);
2892577efa45SRichard Henderson     gen_helper_tick_set_limit(r_tickptr, src);
28930faef01bSRichard Henderson     /* End TB to handle timer interrupt */
28940faef01bSRichard Henderson     dc->base.is_jmp = DISAS_EXIT;
28950faef01bSRichard Henderson }
28960faef01bSRichard Henderson 
28970faef01bSRichard Henderson TRANS(WRSTICK_CMPR, 64, do_wr_special, a, supervisor(dc), do_wrstick_cmpr)
28980faef01bSRichard Henderson 
28990faef01bSRichard Henderson static void do_wrpowerdown(DisasContext *dc, TCGv src)
29000faef01bSRichard Henderson {
290189527e3aSRichard Henderson     finishing_insn(dc);
29020faef01bSRichard Henderson     save_state(dc);
29030faef01bSRichard Henderson     gen_helper_power_down(tcg_env);
29040faef01bSRichard Henderson }
29050faef01bSRichard Henderson 
29060faef01bSRichard Henderson TRANS(WRPOWERDOWN, POWERDOWN, do_wr_special, a, supervisor(dc), do_wrpowerdown)
29070faef01bSRichard Henderson 
290825524734SRichard Henderson static void do_wrpsr(DisasContext *dc, TCGv src)
290925524734SRichard Henderson {
291025524734SRichard Henderson     gen_helper_wrpsr(tcg_env, src);
291125524734SRichard Henderson     dc->base.is_jmp = DISAS_EXIT;
291225524734SRichard Henderson }
291325524734SRichard Henderson 
291425524734SRichard Henderson TRANS(WRPSR, 32, do_wr_special, a, supervisor(dc), do_wrpsr)
291525524734SRichard Henderson 
29169422278eSRichard Henderson static void do_wrwim(DisasContext *dc, TCGv src)
29179422278eSRichard Henderson {
29189422278eSRichard Henderson     target_ulong mask = MAKE_64BIT_MASK(0, dc->def->nwindows);
2919cd6269f7SRichard Henderson     TCGv tmp = tcg_temp_new();
2920cd6269f7SRichard Henderson 
2921cd6269f7SRichard Henderson     tcg_gen_andi_tl(tmp, src, mask);
2922cd6269f7SRichard Henderson     tcg_gen_st_tl(tmp, tcg_env, env32_field_offsetof(wim));
29239422278eSRichard Henderson }
29249422278eSRichard Henderson 
29259422278eSRichard Henderson TRANS(WRWIM, 32, do_wr_special, a, supervisor(dc), do_wrwim)
29269422278eSRichard Henderson 
29279422278eSRichard Henderson static void do_wrtpc(DisasContext *dc, TCGv src)
29289422278eSRichard Henderson {
29299422278eSRichard Henderson #ifdef TARGET_SPARC64
29309422278eSRichard Henderson     TCGv_ptr r_tsptr = tcg_temp_new_ptr();
29319422278eSRichard Henderson 
29329422278eSRichard Henderson     gen_load_trap_state_at_tl(r_tsptr);
29339422278eSRichard Henderson     tcg_gen_st_tl(src, r_tsptr, offsetof(trap_state, tpc));
29349422278eSRichard Henderson #else
29359422278eSRichard Henderson     qemu_build_not_reached();
29369422278eSRichard Henderson #endif
29379422278eSRichard Henderson }
29389422278eSRichard Henderson 
29399422278eSRichard Henderson TRANS(WRPR_tpc, 64, do_wr_special, a, supervisor(dc), do_wrtpc)
29409422278eSRichard Henderson 
29419422278eSRichard Henderson static void do_wrtnpc(DisasContext *dc, TCGv src)
29429422278eSRichard Henderson {
29439422278eSRichard Henderson #ifdef TARGET_SPARC64
29449422278eSRichard Henderson     TCGv_ptr r_tsptr = tcg_temp_new_ptr();
29459422278eSRichard Henderson 
29469422278eSRichard Henderson     gen_load_trap_state_at_tl(r_tsptr);
29479422278eSRichard Henderson     tcg_gen_st_tl(src, r_tsptr, offsetof(trap_state, tnpc));
29489422278eSRichard Henderson #else
29499422278eSRichard Henderson     qemu_build_not_reached();
29509422278eSRichard Henderson #endif
29519422278eSRichard Henderson }
29529422278eSRichard Henderson 
29539422278eSRichard Henderson TRANS(WRPR_tnpc, 64, do_wr_special, a, supervisor(dc), do_wrtnpc)
29549422278eSRichard Henderson 
29559422278eSRichard Henderson static void do_wrtstate(DisasContext *dc, TCGv src)
29569422278eSRichard Henderson {
29579422278eSRichard Henderson #ifdef TARGET_SPARC64
29589422278eSRichard Henderson     TCGv_ptr r_tsptr = tcg_temp_new_ptr();
29599422278eSRichard Henderson 
29609422278eSRichard Henderson     gen_load_trap_state_at_tl(r_tsptr);
29619422278eSRichard Henderson     tcg_gen_st_tl(src, r_tsptr, offsetof(trap_state, tstate));
29629422278eSRichard Henderson #else
29639422278eSRichard Henderson     qemu_build_not_reached();
29649422278eSRichard Henderson #endif
29659422278eSRichard Henderson }
29669422278eSRichard Henderson 
29679422278eSRichard Henderson TRANS(WRPR_tstate, 64, do_wr_special, a, supervisor(dc), do_wrtstate)
29689422278eSRichard Henderson 
29699422278eSRichard Henderson static void do_wrtt(DisasContext *dc, TCGv src)
29709422278eSRichard Henderson {
29719422278eSRichard Henderson #ifdef TARGET_SPARC64
29729422278eSRichard Henderson     TCGv_ptr r_tsptr = tcg_temp_new_ptr();
29739422278eSRichard Henderson 
29749422278eSRichard Henderson     gen_load_trap_state_at_tl(r_tsptr);
29759422278eSRichard Henderson     tcg_gen_st32_tl(src, r_tsptr, offsetof(trap_state, tt));
29769422278eSRichard Henderson #else
29779422278eSRichard Henderson     qemu_build_not_reached();
29789422278eSRichard Henderson #endif
29799422278eSRichard Henderson }
29809422278eSRichard Henderson 
29819422278eSRichard Henderson TRANS(WRPR_tt, 64, do_wr_special, a, supervisor(dc), do_wrtt)
29829422278eSRichard Henderson 
29839422278eSRichard Henderson static void do_wrtick(DisasContext *dc, TCGv src)
29849422278eSRichard Henderson {
29859422278eSRichard Henderson     TCGv_ptr r_tickptr = tcg_temp_new_ptr();
29869422278eSRichard Henderson 
29879422278eSRichard Henderson     tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(tick));
29889422278eSRichard Henderson     translator_io_start(&dc->base);
29899422278eSRichard Henderson     gen_helper_tick_set_count(r_tickptr, src);
29909422278eSRichard Henderson     /* End TB to handle timer interrupt */
29919422278eSRichard Henderson     dc->base.is_jmp = DISAS_EXIT;
29929422278eSRichard Henderson }
29939422278eSRichard Henderson 
29949422278eSRichard Henderson TRANS(WRPR_tick, 64, do_wr_special, a, supervisor(dc), do_wrtick)
29959422278eSRichard Henderson 
29969422278eSRichard Henderson static void do_wrtba(DisasContext *dc, TCGv src)
29979422278eSRichard Henderson {
29989422278eSRichard Henderson     tcg_gen_mov_tl(cpu_tbr, src);
29999422278eSRichard Henderson }
30009422278eSRichard Henderson 
30019422278eSRichard Henderson TRANS(WRPR_tba, 64, do_wr_special, a, supervisor(dc), do_wrtba)
30029422278eSRichard Henderson 
30039422278eSRichard Henderson static void do_wrpstate(DisasContext *dc, TCGv src)
30049422278eSRichard Henderson {
30059422278eSRichard Henderson     save_state(dc);
30069422278eSRichard Henderson     if (translator_io_start(&dc->base)) {
30079422278eSRichard Henderson         dc->base.is_jmp = DISAS_EXIT;
30089422278eSRichard Henderson     }
30099422278eSRichard Henderson     gen_helper_wrpstate(tcg_env, src);
30109422278eSRichard Henderson     dc->npc = DYNAMIC_PC;
30119422278eSRichard Henderson }
30129422278eSRichard Henderson 
30139422278eSRichard Henderson TRANS(WRPR_pstate, 64, do_wr_special, a, supervisor(dc), do_wrpstate)
30149422278eSRichard Henderson 
30159422278eSRichard Henderson static void do_wrtl(DisasContext *dc, TCGv src)
30169422278eSRichard Henderson {
30179422278eSRichard Henderson     save_state(dc);
30189422278eSRichard Henderson     tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(tl));
30199422278eSRichard Henderson     dc->npc = DYNAMIC_PC;
30209422278eSRichard Henderson }
30219422278eSRichard Henderson 
30229422278eSRichard Henderson TRANS(WRPR_tl, 64, do_wr_special, a, supervisor(dc), do_wrtl)
30239422278eSRichard Henderson 
30249422278eSRichard Henderson static void do_wrpil(DisasContext *dc, TCGv src)
30259422278eSRichard Henderson {
30269422278eSRichard Henderson     if (translator_io_start(&dc->base)) {
30279422278eSRichard Henderson         dc->base.is_jmp = DISAS_EXIT;
30289422278eSRichard Henderson     }
30299422278eSRichard Henderson     gen_helper_wrpil(tcg_env, src);
30309422278eSRichard Henderson }
30319422278eSRichard Henderson 
30329422278eSRichard Henderson TRANS(WRPR_pil, 64, do_wr_special, a, supervisor(dc), do_wrpil)
30339422278eSRichard Henderson 
30349422278eSRichard Henderson static void do_wrcwp(DisasContext *dc, TCGv src)
30359422278eSRichard Henderson {
30369422278eSRichard Henderson     gen_helper_wrcwp(tcg_env, src);
30379422278eSRichard Henderson }
30389422278eSRichard Henderson 
30399422278eSRichard Henderson TRANS(WRPR_cwp, 64, do_wr_special, a, supervisor(dc), do_wrcwp)
30409422278eSRichard Henderson 
30419422278eSRichard Henderson static void do_wrcansave(DisasContext *dc, TCGv src)
30429422278eSRichard Henderson {
30439422278eSRichard Henderson     tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(cansave));
30449422278eSRichard Henderson }
30459422278eSRichard Henderson 
30469422278eSRichard Henderson TRANS(WRPR_cansave, 64, do_wr_special, a, supervisor(dc), do_wrcansave)
30479422278eSRichard Henderson 
30489422278eSRichard Henderson static void do_wrcanrestore(DisasContext *dc, TCGv src)
30499422278eSRichard Henderson {
30509422278eSRichard Henderson     tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(canrestore));
30519422278eSRichard Henderson }
30529422278eSRichard Henderson 
30539422278eSRichard Henderson TRANS(WRPR_canrestore, 64, do_wr_special, a, supervisor(dc), do_wrcanrestore)
30549422278eSRichard Henderson 
30559422278eSRichard Henderson static void do_wrcleanwin(DisasContext *dc, TCGv src)
30569422278eSRichard Henderson {
30579422278eSRichard Henderson     tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(cleanwin));
30589422278eSRichard Henderson }
30599422278eSRichard Henderson 
30609422278eSRichard Henderson TRANS(WRPR_cleanwin, 64, do_wr_special, a, supervisor(dc), do_wrcleanwin)
30619422278eSRichard Henderson 
30629422278eSRichard Henderson static void do_wrotherwin(DisasContext *dc, TCGv src)
30639422278eSRichard Henderson {
30649422278eSRichard Henderson     tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(otherwin));
30659422278eSRichard Henderson }
30669422278eSRichard Henderson 
30679422278eSRichard Henderson TRANS(WRPR_otherwin, 64, do_wr_special, a, supervisor(dc), do_wrotherwin)
30689422278eSRichard Henderson 
30699422278eSRichard Henderson static void do_wrwstate(DisasContext *dc, TCGv src)
30709422278eSRichard Henderson {
30719422278eSRichard Henderson     tcg_gen_st32_tl(src, tcg_env, env64_field_offsetof(wstate));
30729422278eSRichard Henderson }
30739422278eSRichard Henderson 
30749422278eSRichard Henderson TRANS(WRPR_wstate, 64, do_wr_special, a, supervisor(dc), do_wrwstate)
30759422278eSRichard Henderson 
30769422278eSRichard Henderson static void do_wrgl(DisasContext *dc, TCGv src)
30779422278eSRichard Henderson {
30789422278eSRichard Henderson     gen_helper_wrgl(tcg_env, src);
30799422278eSRichard Henderson }
30809422278eSRichard Henderson 
30819422278eSRichard Henderson TRANS(WRPR_gl, GL, do_wr_special, a, supervisor(dc), do_wrgl)
30829422278eSRichard Henderson 
30839422278eSRichard Henderson /* UA2005 strand status */
30849422278eSRichard Henderson static void do_wrssr(DisasContext *dc, TCGv src)
30859422278eSRichard Henderson {
30862da789deSRichard Henderson     tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(ssr));
30879422278eSRichard Henderson }
30889422278eSRichard Henderson 
30899422278eSRichard Henderson TRANS(WRPR_strand_status, HYPV, do_wr_special, a, hypervisor(dc), do_wrssr)
30909422278eSRichard Henderson 
3091bb97f2f5SRichard Henderson TRANS(WRTBR, 32, do_wr_special, a, supervisor(dc), do_wrtba)
3092bb97f2f5SRichard Henderson 
3093bb97f2f5SRichard Henderson static void do_wrhpstate(DisasContext *dc, TCGv src)
3094bb97f2f5SRichard Henderson {
3095bb97f2f5SRichard Henderson     tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(hpstate));
3096bb97f2f5SRichard Henderson     dc->base.is_jmp = DISAS_EXIT;
3097bb97f2f5SRichard Henderson }
3098bb97f2f5SRichard Henderson 
3099bb97f2f5SRichard Henderson TRANS(WRHPR_hpstate, HYPV, do_wr_special, a, hypervisor(dc), do_wrhpstate)
3100bb97f2f5SRichard Henderson 
3101bb97f2f5SRichard Henderson static void do_wrhtstate(DisasContext *dc, TCGv src)
3102bb97f2f5SRichard Henderson {
3103bb97f2f5SRichard Henderson     TCGv_i32 tl = tcg_temp_new_i32();
3104bb97f2f5SRichard Henderson     TCGv_ptr tp = tcg_temp_new_ptr();
3105bb97f2f5SRichard Henderson 
3106bb97f2f5SRichard Henderson     tcg_gen_ld_i32(tl, tcg_env, env64_field_offsetof(tl));
3107bb97f2f5SRichard Henderson     tcg_gen_andi_i32(tl, tl, MAXTL_MASK);
3108bb97f2f5SRichard Henderson     tcg_gen_shli_i32(tl, tl, 3);
3109bb97f2f5SRichard Henderson     tcg_gen_ext_i32_ptr(tp, tl);
3110bb97f2f5SRichard Henderson     tcg_gen_add_ptr(tp, tp, tcg_env);
3111bb97f2f5SRichard Henderson 
3112bb97f2f5SRichard Henderson     tcg_gen_st_tl(src, tp, env64_field_offsetof(htstate));
3113bb97f2f5SRichard Henderson }
3114bb97f2f5SRichard Henderson 
3115bb97f2f5SRichard Henderson TRANS(WRHPR_htstate, HYPV, do_wr_special, a, hypervisor(dc), do_wrhtstate)
3116bb97f2f5SRichard Henderson 
3117bb97f2f5SRichard Henderson static void do_wrhintp(DisasContext *dc, TCGv src)
3118bb97f2f5SRichard Henderson {
31192da789deSRichard Henderson     tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(hintp));
3120bb97f2f5SRichard Henderson }
3121bb97f2f5SRichard Henderson 
3122bb97f2f5SRichard Henderson TRANS(WRHPR_hintp, HYPV, do_wr_special, a, hypervisor(dc), do_wrhintp)
3123bb97f2f5SRichard Henderson 
3124bb97f2f5SRichard Henderson static void do_wrhtba(DisasContext *dc, TCGv src)
3125bb97f2f5SRichard Henderson {
31262da789deSRichard Henderson     tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(htba));
3127bb97f2f5SRichard Henderson }
3128bb97f2f5SRichard Henderson 
3129bb97f2f5SRichard Henderson TRANS(WRHPR_htba, HYPV, do_wr_special, a, hypervisor(dc), do_wrhtba)
3130bb97f2f5SRichard Henderson 
3131bb97f2f5SRichard Henderson static void do_wrhstick_cmpr(DisasContext *dc, TCGv src)
3132bb97f2f5SRichard Henderson {
3133bb97f2f5SRichard Henderson     TCGv_ptr r_tickptr = tcg_temp_new_ptr();
3134bb97f2f5SRichard Henderson 
3135577efa45SRichard Henderson     tcg_gen_st_tl(src, tcg_env, env64_field_offsetof(hstick_cmpr));
3136bb97f2f5SRichard Henderson     tcg_gen_ld_ptr(r_tickptr, tcg_env, env64_field_offsetof(hstick));
3137bb97f2f5SRichard Henderson     translator_io_start(&dc->base);
3138577efa45SRichard Henderson     gen_helper_tick_set_limit(r_tickptr, src);
3139bb97f2f5SRichard Henderson     /* End TB to handle timer interrupt */
3140bb97f2f5SRichard Henderson     dc->base.is_jmp = DISAS_EXIT;
3141bb97f2f5SRichard Henderson }
3142bb97f2f5SRichard Henderson 
3143bb97f2f5SRichard Henderson TRANS(WRHPR_hstick_cmpr, HYPV, do_wr_special, a, hypervisor(dc),
3144bb97f2f5SRichard Henderson       do_wrhstick_cmpr)
3145bb97f2f5SRichard Henderson 
314625524734SRichard Henderson static bool do_saved_restored(DisasContext *dc, bool saved)
314725524734SRichard Henderson {
314825524734SRichard Henderson     if (!supervisor(dc)) {
314925524734SRichard Henderson         return raise_priv(dc);
315025524734SRichard Henderson     }
315125524734SRichard Henderson     if (saved) {
315225524734SRichard Henderson         gen_helper_saved(tcg_env);
315325524734SRichard Henderson     } else {
315425524734SRichard Henderson         gen_helper_restored(tcg_env);
315525524734SRichard Henderson     }
315625524734SRichard Henderson     return advance_pc(dc);
315725524734SRichard Henderson }
315825524734SRichard Henderson 
315925524734SRichard Henderson TRANS(SAVED, 64, do_saved_restored, true)
316025524734SRichard Henderson TRANS(RESTORED, 64, do_saved_restored, false)
316125524734SRichard Henderson 
3162d3825800SRichard Henderson static bool trans_NOP(DisasContext *dc, arg_NOP *a)
3163d3825800SRichard Henderson {
3164d3825800SRichard Henderson     return advance_pc(dc);
3165d3825800SRichard Henderson }
3166d3825800SRichard Henderson 
31670faef01bSRichard Henderson /*
31680faef01bSRichard Henderson  * TODO: Need a feature bit for sparcv8.
31690faef01bSRichard Henderson  * In the meantime, treat all 32-bit cpus like sparcv7.
31700faef01bSRichard Henderson  */
31715458fd31SRichard Henderson TRANS(NOP_v7, 32, trans_NOP, a)
31725458fd31SRichard Henderson TRANS(NOP_v9, 64, trans_NOP, a)
31730faef01bSRichard Henderson 
3174b597eedcSRichard Henderson static bool do_arith_int(DisasContext *dc, arg_r_r_ri_cc *a,
3175428881deSRichard Henderson                          void (*func)(TCGv, TCGv, TCGv),
31762a45b736SRichard Henderson                          void (*funci)(TCGv, TCGv, target_long),
31772a45b736SRichard Henderson                          bool logic_cc)
3178428881deSRichard Henderson {
3179428881deSRichard Henderson     TCGv dst, src1;
3180428881deSRichard Henderson 
3181428881deSRichard Henderson     /* For simplicity, we under-decoded the rs2 form. */
3182428881deSRichard Henderson     if (!a->imm && a->rs2_or_imm & ~0x1f) {
3183428881deSRichard Henderson         return false;
3184428881deSRichard Henderson     }
3185428881deSRichard Henderson 
31862a45b736SRichard Henderson     if (logic_cc) {
31872a45b736SRichard Henderson         dst = cpu_cc_N;
3188428881deSRichard Henderson     } else {
3189428881deSRichard Henderson         dst = gen_dest_gpr(dc, a->rd);
3190428881deSRichard Henderson     }
3191428881deSRichard Henderson     src1 = gen_load_gpr(dc, a->rs1);
3192428881deSRichard Henderson 
3193428881deSRichard Henderson     if (a->imm || a->rs2_or_imm == 0) {
3194428881deSRichard Henderson         if (funci) {
3195428881deSRichard Henderson             funci(dst, src1, a->rs2_or_imm);
3196428881deSRichard Henderson         } else {
3197428881deSRichard Henderson             func(dst, src1, tcg_constant_tl(a->rs2_or_imm));
3198428881deSRichard Henderson         }
3199428881deSRichard Henderson     } else {
3200428881deSRichard Henderson         func(dst, src1, cpu_regs[a->rs2_or_imm]);
3201428881deSRichard Henderson     }
32022a45b736SRichard Henderson 
32032a45b736SRichard Henderson     if (logic_cc) {
32042a45b736SRichard Henderson         if (TARGET_LONG_BITS == 64) {
32052a45b736SRichard Henderson             tcg_gen_mov_tl(cpu_icc_Z, cpu_cc_N);
32062a45b736SRichard Henderson             tcg_gen_movi_tl(cpu_icc_C, 0);
32072a45b736SRichard Henderson         }
32082a45b736SRichard Henderson         tcg_gen_mov_tl(cpu_cc_Z, cpu_cc_N);
32092a45b736SRichard Henderson         tcg_gen_movi_tl(cpu_cc_C, 0);
32102a45b736SRichard Henderson         tcg_gen_movi_tl(cpu_cc_V, 0);
32112a45b736SRichard Henderson     }
32122a45b736SRichard Henderson 
3213428881deSRichard Henderson     gen_store_gpr(dc, a->rd, dst);
3214428881deSRichard Henderson     return advance_pc(dc);
3215428881deSRichard Henderson }
3216428881deSRichard Henderson 
3217b597eedcSRichard Henderson static bool do_arith(DisasContext *dc, arg_r_r_ri_cc *a,
3218428881deSRichard Henderson                      void (*func)(TCGv, TCGv, TCGv),
3219428881deSRichard Henderson                      void (*funci)(TCGv, TCGv, target_long),
3220428881deSRichard Henderson                      void (*func_cc)(TCGv, TCGv, TCGv))
3221428881deSRichard Henderson {
3222428881deSRichard Henderson     if (a->cc) {
3223b597eedcSRichard Henderson         return do_arith_int(dc, a, func_cc, NULL, false);
3224428881deSRichard Henderson     }
3225b597eedcSRichard Henderson     return do_arith_int(dc, a, func, funci, false);
3226428881deSRichard Henderson }
3227428881deSRichard Henderson 
3228428881deSRichard Henderson static bool do_logic(DisasContext *dc, arg_r_r_ri_cc *a,
3229428881deSRichard Henderson                      void (*func)(TCGv, TCGv, TCGv),
3230428881deSRichard Henderson                      void (*funci)(TCGv, TCGv, target_long))
3231428881deSRichard Henderson {
3232b597eedcSRichard Henderson     return do_arith_int(dc, a, func, funci, a->cc);
3233428881deSRichard Henderson }
3234428881deSRichard Henderson 
3235b597eedcSRichard Henderson TRANS(ADD, ALL, do_arith, a, tcg_gen_add_tl, tcg_gen_addi_tl, gen_op_addcc)
3236b597eedcSRichard Henderson TRANS(SUB, ALL, do_arith, a, tcg_gen_sub_tl, tcg_gen_subi_tl, gen_op_subcc)
3237b597eedcSRichard Henderson TRANS(ADDC, ALL, do_arith, a, gen_op_addc, NULL, gen_op_addccc)
3238b597eedcSRichard Henderson TRANS(SUBC, ALL, do_arith, a, gen_op_subc, NULL, gen_op_subccc)
3239428881deSRichard Henderson 
3240b597eedcSRichard Henderson TRANS(TADDcc, ALL, do_arith, a, NULL, NULL, gen_op_taddcc)
3241b597eedcSRichard Henderson TRANS(TSUBcc, ALL, do_arith, a, NULL, NULL, gen_op_tsubcc)
3242b597eedcSRichard Henderson TRANS(TADDccTV, ALL, do_arith, a, NULL, NULL, gen_op_taddcctv)
3243b597eedcSRichard Henderson TRANS(TSUBccTV, ALL, do_arith, a, NULL, NULL, gen_op_tsubcctv)
3244a9aba13dSRichard Henderson 
3245428881deSRichard Henderson TRANS(AND, ALL, do_logic, a, tcg_gen_and_tl, tcg_gen_andi_tl)
3246428881deSRichard Henderson TRANS(XOR, ALL, do_logic, a, tcg_gen_xor_tl, tcg_gen_xori_tl)
3247428881deSRichard Henderson TRANS(ANDN, ALL, do_logic, a, tcg_gen_andc_tl, NULL)
3248428881deSRichard Henderson TRANS(ORN, ALL, do_logic, a, tcg_gen_orc_tl, NULL)
3249428881deSRichard Henderson TRANS(XORN, ALL, do_logic, a, tcg_gen_eqv_tl, NULL)
3250428881deSRichard Henderson 
3251b597eedcSRichard Henderson TRANS(MULX, 64, do_arith, a, tcg_gen_mul_tl, tcg_gen_muli_tl, NULL)
3252b5372650SRichard Henderson TRANS(UMUL, MUL, do_logic, a, gen_op_umul, NULL)
3253b5372650SRichard Henderson TRANS(SMUL, MUL, do_logic, a, gen_op_smul, NULL)
3254b597eedcSRichard Henderson TRANS(MULScc, ALL, do_arith, a, NULL, NULL, gen_op_mulscc)
325522188d7dSRichard Henderson 
32563a6b8de3SRichard Henderson TRANS(UDIVcc, DIV, do_arith, a, NULL, NULL, gen_op_udivcc)
3257b597eedcSRichard Henderson TRANS(SDIV, DIV, do_arith, a, gen_op_sdiv, NULL, gen_op_sdivcc)
32584ee85ea9SRichard Henderson 
32599c6ec5bcSRichard Henderson /* TODO: Should have feature bit -- comes in with UltraSparc T2. */
3260b597eedcSRichard Henderson TRANS(POPC, 64, do_arith, a, gen_op_popc, NULL, NULL)
32619c6ec5bcSRichard Henderson 
3262428881deSRichard Henderson static bool trans_OR(DisasContext *dc, arg_r_r_ri_cc *a)
3263428881deSRichard Henderson {
3264428881deSRichard Henderson     /* OR with %g0 is the canonical alias for MOV. */
3265428881deSRichard Henderson     if (!a->cc && a->rs1 == 0) {
3266428881deSRichard Henderson         if (a->imm || a->rs2_or_imm == 0) {
3267428881deSRichard Henderson             gen_store_gpr(dc, a->rd, tcg_constant_tl(a->rs2_or_imm));
3268428881deSRichard Henderson         } else if (a->rs2_or_imm & ~0x1f) {
3269428881deSRichard Henderson             /* For simplicity, we under-decoded the rs2 form. */
3270428881deSRichard Henderson             return false;
3271428881deSRichard Henderson         } else {
3272428881deSRichard Henderson             gen_store_gpr(dc, a->rd, cpu_regs[a->rs2_or_imm]);
3273428881deSRichard Henderson         }
3274428881deSRichard Henderson         return advance_pc(dc);
3275428881deSRichard Henderson     }
3276428881deSRichard Henderson     return do_logic(dc, a, tcg_gen_or_tl, tcg_gen_ori_tl);
3277428881deSRichard Henderson }
3278428881deSRichard Henderson 
32793a6b8de3SRichard Henderson static bool trans_UDIV(DisasContext *dc, arg_r_r_ri *a)
32803a6b8de3SRichard Henderson {
32813a6b8de3SRichard Henderson     TCGv_i64 t1, t2;
32823a6b8de3SRichard Henderson     TCGv dst;
32833a6b8de3SRichard Henderson 
32843a6b8de3SRichard Henderson     if (!avail_DIV(dc)) {
32853a6b8de3SRichard Henderson         return false;
32863a6b8de3SRichard Henderson     }
32873a6b8de3SRichard Henderson     /* For simplicity, we under-decoded the rs2 form. */
32883a6b8de3SRichard Henderson     if (!a->imm && a->rs2_or_imm & ~0x1f) {
32893a6b8de3SRichard Henderson         return false;
32903a6b8de3SRichard Henderson     }
32913a6b8de3SRichard Henderson 
32923a6b8de3SRichard Henderson     if (unlikely(a->rs2_or_imm == 0)) {
32933a6b8de3SRichard Henderson         gen_exception(dc, TT_DIV_ZERO);
32943a6b8de3SRichard Henderson         return true;
32953a6b8de3SRichard Henderson     }
32963a6b8de3SRichard Henderson 
32973a6b8de3SRichard Henderson     if (a->imm) {
32983a6b8de3SRichard Henderson         t2 = tcg_constant_i64((uint32_t)a->rs2_or_imm);
32993a6b8de3SRichard Henderson     } else {
33003a6b8de3SRichard Henderson         TCGLabel *lab;
33013a6b8de3SRichard Henderson         TCGv_i32 n2;
33023a6b8de3SRichard Henderson 
33033a6b8de3SRichard Henderson         finishing_insn(dc);
33043a6b8de3SRichard Henderson         flush_cond(dc);
33053a6b8de3SRichard Henderson 
33063a6b8de3SRichard Henderson         n2 = tcg_temp_new_i32();
33073a6b8de3SRichard Henderson         tcg_gen_trunc_tl_i32(n2, cpu_regs[a->rs2_or_imm]);
33083a6b8de3SRichard Henderson 
33093a6b8de3SRichard Henderson         lab = delay_exception(dc, TT_DIV_ZERO);
33103a6b8de3SRichard Henderson         tcg_gen_brcondi_i32(TCG_COND_EQ, n2, 0, lab);
33113a6b8de3SRichard Henderson 
33123a6b8de3SRichard Henderson         t2 = tcg_temp_new_i64();
33133a6b8de3SRichard Henderson #ifdef TARGET_SPARC64
33143a6b8de3SRichard Henderson         tcg_gen_ext32u_i64(t2, cpu_regs[a->rs2_or_imm]);
33153a6b8de3SRichard Henderson #else
33163a6b8de3SRichard Henderson         tcg_gen_extu_i32_i64(t2, cpu_regs[a->rs2_or_imm]);
33173a6b8de3SRichard Henderson #endif
33183a6b8de3SRichard Henderson     }
33193a6b8de3SRichard Henderson 
33203a6b8de3SRichard Henderson     t1 = tcg_temp_new_i64();
33213a6b8de3SRichard Henderson     tcg_gen_concat_tl_i64(t1, gen_load_gpr(dc, a->rs1), cpu_y);
33223a6b8de3SRichard Henderson 
33233a6b8de3SRichard Henderson     tcg_gen_divu_i64(t1, t1, t2);
33243a6b8de3SRichard Henderson     tcg_gen_umin_i64(t1, t1, tcg_constant_i64(UINT32_MAX));
33253a6b8de3SRichard Henderson 
33263a6b8de3SRichard Henderson     dst = gen_dest_gpr(dc, a->rd);
33273a6b8de3SRichard Henderson     tcg_gen_trunc_i64_tl(dst, t1);
33283a6b8de3SRichard Henderson     gen_store_gpr(dc, a->rd, dst);
33293a6b8de3SRichard Henderson     return advance_pc(dc);
33303a6b8de3SRichard Henderson }
33313a6b8de3SRichard Henderson 
3332f3141174SRichard Henderson static bool trans_UDIVX(DisasContext *dc, arg_r_r_ri *a)
3333f3141174SRichard Henderson {
3334f3141174SRichard Henderson     TCGv dst, src1, src2;
3335f3141174SRichard Henderson 
3336f3141174SRichard Henderson     if (!avail_64(dc)) {
3337f3141174SRichard Henderson         return false;
3338f3141174SRichard Henderson     }
3339f3141174SRichard Henderson     /* For simplicity, we under-decoded the rs2 form. */
3340f3141174SRichard Henderson     if (!a->imm && a->rs2_or_imm & ~0x1f) {
3341f3141174SRichard Henderson         return false;
3342f3141174SRichard Henderson     }
3343f3141174SRichard Henderson 
3344f3141174SRichard Henderson     if (unlikely(a->rs2_or_imm == 0)) {
3345f3141174SRichard Henderson         gen_exception(dc, TT_DIV_ZERO);
3346f3141174SRichard Henderson         return true;
3347f3141174SRichard Henderson     }
3348f3141174SRichard Henderson 
3349f3141174SRichard Henderson     if (a->imm) {
3350f3141174SRichard Henderson         src2 = tcg_constant_tl(a->rs2_or_imm);
3351f3141174SRichard Henderson     } else {
3352f3141174SRichard Henderson         TCGLabel *lab;
3353f3141174SRichard Henderson 
3354f3141174SRichard Henderson         finishing_insn(dc);
3355f3141174SRichard Henderson         flush_cond(dc);
3356f3141174SRichard Henderson 
3357f3141174SRichard Henderson         lab = delay_exception(dc, TT_DIV_ZERO);
3358f3141174SRichard Henderson         src2 = cpu_regs[a->rs2_or_imm];
3359f3141174SRichard Henderson         tcg_gen_brcondi_tl(TCG_COND_EQ, src2, 0, lab);
3360f3141174SRichard Henderson     }
3361f3141174SRichard Henderson 
3362f3141174SRichard Henderson     dst = gen_dest_gpr(dc, a->rd);
3363f3141174SRichard Henderson     src1 = gen_load_gpr(dc, a->rs1);
3364f3141174SRichard Henderson 
3365f3141174SRichard Henderson     tcg_gen_divu_tl(dst, src1, src2);
3366f3141174SRichard Henderson     gen_store_gpr(dc, a->rd, dst);
3367f3141174SRichard Henderson     return advance_pc(dc);
3368f3141174SRichard Henderson }
3369f3141174SRichard Henderson 
3370f3141174SRichard Henderson static bool trans_SDIVX(DisasContext *dc, arg_r_r_ri *a)
3371f3141174SRichard Henderson {
3372f3141174SRichard Henderson     TCGv dst, src1, src2;
3373f3141174SRichard Henderson 
3374f3141174SRichard Henderson     if (!avail_64(dc)) {
3375f3141174SRichard Henderson         return false;
3376f3141174SRichard Henderson     }
3377f3141174SRichard Henderson     /* For simplicity, we under-decoded the rs2 form. */
3378f3141174SRichard Henderson     if (!a->imm && a->rs2_or_imm & ~0x1f) {
3379f3141174SRichard Henderson         return false;
3380f3141174SRichard Henderson     }
3381f3141174SRichard Henderson 
3382f3141174SRichard Henderson     if (unlikely(a->rs2_or_imm == 0)) {
3383f3141174SRichard Henderson         gen_exception(dc, TT_DIV_ZERO);
3384f3141174SRichard Henderson         return true;
3385f3141174SRichard Henderson     }
3386f3141174SRichard Henderson 
3387f3141174SRichard Henderson     dst = gen_dest_gpr(dc, a->rd);
3388f3141174SRichard Henderson     src1 = gen_load_gpr(dc, a->rs1);
3389f3141174SRichard Henderson 
3390f3141174SRichard Henderson     if (a->imm) {
3391f3141174SRichard Henderson         if (unlikely(a->rs2_or_imm == -1)) {
3392f3141174SRichard Henderson             tcg_gen_neg_tl(dst, src1);
3393f3141174SRichard Henderson             gen_store_gpr(dc, a->rd, dst);
3394f3141174SRichard Henderson             return advance_pc(dc);
3395f3141174SRichard Henderson         }
3396f3141174SRichard Henderson         src2 = tcg_constant_tl(a->rs2_or_imm);
3397f3141174SRichard Henderson     } else {
3398f3141174SRichard Henderson         TCGLabel *lab;
3399f3141174SRichard Henderson         TCGv t1, t2;
3400f3141174SRichard Henderson 
3401f3141174SRichard Henderson         finishing_insn(dc);
3402f3141174SRichard Henderson         flush_cond(dc);
3403f3141174SRichard Henderson 
3404f3141174SRichard Henderson         lab = delay_exception(dc, TT_DIV_ZERO);
3405f3141174SRichard Henderson         src2 = cpu_regs[a->rs2_or_imm];
3406f3141174SRichard Henderson         tcg_gen_brcondi_tl(TCG_COND_EQ, src2, 0, lab);
3407f3141174SRichard Henderson 
3408f3141174SRichard Henderson         /*
3409f3141174SRichard Henderson          * Need to avoid INT64_MIN / -1, which will trap on x86 host.
3410f3141174SRichard Henderson          * Set SRC2 to 1 as a new divisor, to produce the correct result.
3411f3141174SRichard Henderson          */
3412f3141174SRichard Henderson         t1 = tcg_temp_new();
3413f3141174SRichard Henderson         t2 = tcg_temp_new();
3414f3141174SRichard Henderson         tcg_gen_setcondi_tl(TCG_COND_EQ, t1, src1, (target_long)INT64_MIN);
3415f3141174SRichard Henderson         tcg_gen_setcondi_tl(TCG_COND_EQ, t2, src2, -1);
3416f3141174SRichard Henderson         tcg_gen_and_tl(t1, t1, t2);
3417f3141174SRichard Henderson         tcg_gen_movcond_tl(TCG_COND_NE, t1, t1, tcg_constant_tl(0),
3418f3141174SRichard Henderson                            tcg_constant_tl(1), src2);
3419f3141174SRichard Henderson         src2 = t1;
3420f3141174SRichard Henderson     }
3421f3141174SRichard Henderson 
3422f3141174SRichard Henderson     tcg_gen_div_tl(dst, src1, src2);
3423f3141174SRichard Henderson     gen_store_gpr(dc, a->rd, dst);
3424f3141174SRichard Henderson     return advance_pc(dc);
3425f3141174SRichard Henderson }
3426f3141174SRichard Henderson 
3427b88ce6f2SRichard Henderson static bool gen_edge(DisasContext *dc, arg_r_r_r *a,
3428b88ce6f2SRichard Henderson                      int width, bool cc, bool left)
3429b88ce6f2SRichard Henderson {
3430b88ce6f2SRichard Henderson     TCGv dst, s1, s2, lo1, lo2;
3431b88ce6f2SRichard Henderson     uint64_t amask, tabl, tabr;
3432b88ce6f2SRichard Henderson     int shift, imask, omask;
3433b88ce6f2SRichard Henderson 
3434b88ce6f2SRichard Henderson     dst = gen_dest_gpr(dc, a->rd);
3435b88ce6f2SRichard Henderson     s1 = gen_load_gpr(dc, a->rs1);
3436b88ce6f2SRichard Henderson     s2 = gen_load_gpr(dc, a->rs2);
3437b88ce6f2SRichard Henderson 
3438b88ce6f2SRichard Henderson     if (cc) {
3439f828df74SRichard Henderson         gen_op_subcc(cpu_cc_N, s1, s2);
3440b88ce6f2SRichard Henderson     }
3441b88ce6f2SRichard Henderson 
3442b88ce6f2SRichard Henderson     /*
3443b88ce6f2SRichard Henderson      * Theory of operation: there are two tables, left and right (not to
3444b88ce6f2SRichard Henderson      * be confused with the left and right versions of the opcode).  These
3445b88ce6f2SRichard Henderson      * are indexed by the low 3 bits of the inputs.  To make things "easy",
3446b88ce6f2SRichard Henderson      * these tables are loaded into two constants, TABL and TABR below.
3447b88ce6f2SRichard Henderson      * The operation index = (input & imask) << shift calculates the index
3448b88ce6f2SRichard Henderson      * into the constant, while val = (table >> index) & omask calculates
3449b88ce6f2SRichard Henderson      * the value we're looking for.
3450b88ce6f2SRichard Henderson      */
3451b88ce6f2SRichard Henderson     switch (width) {
3452b88ce6f2SRichard Henderson     case 8:
3453b88ce6f2SRichard Henderson         imask = 0x7;
3454b88ce6f2SRichard Henderson         shift = 3;
3455b88ce6f2SRichard Henderson         omask = 0xff;
3456b88ce6f2SRichard Henderson         if (left) {
3457b88ce6f2SRichard Henderson             tabl = 0x80c0e0f0f8fcfeffULL;
3458b88ce6f2SRichard Henderson             tabr = 0xff7f3f1f0f070301ULL;
3459b88ce6f2SRichard Henderson         } else {
3460b88ce6f2SRichard Henderson             tabl = 0x0103070f1f3f7fffULL;
3461b88ce6f2SRichard Henderson             tabr = 0xfffefcf8f0e0c080ULL;
3462b88ce6f2SRichard Henderson         }
3463b88ce6f2SRichard Henderson         break;
3464b88ce6f2SRichard Henderson     case 16:
3465b88ce6f2SRichard Henderson         imask = 0x6;
3466b88ce6f2SRichard Henderson         shift = 1;
3467b88ce6f2SRichard Henderson         omask = 0xf;
3468b88ce6f2SRichard Henderson         if (left) {
3469b88ce6f2SRichard Henderson             tabl = 0x8cef;
3470b88ce6f2SRichard Henderson             tabr = 0xf731;
3471b88ce6f2SRichard Henderson         } else {
3472b88ce6f2SRichard Henderson             tabl = 0x137f;
3473b88ce6f2SRichard Henderson             tabr = 0xfec8;
3474b88ce6f2SRichard Henderson         }
3475b88ce6f2SRichard Henderson         break;
3476b88ce6f2SRichard Henderson     case 32:
3477b88ce6f2SRichard Henderson         imask = 0x4;
3478b88ce6f2SRichard Henderson         shift = 0;
3479b88ce6f2SRichard Henderson         omask = 0x3;
3480b88ce6f2SRichard Henderson         if (left) {
3481b88ce6f2SRichard Henderson             tabl = (2 << 2) | 3;
3482b88ce6f2SRichard Henderson             tabr = (3 << 2) | 1;
3483b88ce6f2SRichard Henderson         } else {
3484b88ce6f2SRichard Henderson             tabl = (1 << 2) | 3;
3485b88ce6f2SRichard Henderson             tabr = (3 << 2) | 2;
3486b88ce6f2SRichard Henderson         }
3487b88ce6f2SRichard Henderson         break;
3488b88ce6f2SRichard Henderson     default:
3489b88ce6f2SRichard Henderson         abort();
3490b88ce6f2SRichard Henderson     }
3491b88ce6f2SRichard Henderson 
3492b88ce6f2SRichard Henderson     lo1 = tcg_temp_new();
3493b88ce6f2SRichard Henderson     lo2 = tcg_temp_new();
3494b88ce6f2SRichard Henderson     tcg_gen_andi_tl(lo1, s1, imask);
3495b88ce6f2SRichard Henderson     tcg_gen_andi_tl(lo2, s2, imask);
3496b88ce6f2SRichard Henderson     tcg_gen_shli_tl(lo1, lo1, shift);
3497b88ce6f2SRichard Henderson     tcg_gen_shli_tl(lo2, lo2, shift);
3498b88ce6f2SRichard Henderson 
3499b88ce6f2SRichard Henderson     tcg_gen_shr_tl(lo1, tcg_constant_tl(tabl), lo1);
3500b88ce6f2SRichard Henderson     tcg_gen_shr_tl(lo2, tcg_constant_tl(tabr), lo2);
3501b88ce6f2SRichard Henderson     tcg_gen_andi_tl(lo1, lo1, omask);
3502b88ce6f2SRichard Henderson     tcg_gen_andi_tl(lo2, lo2, omask);
3503b88ce6f2SRichard Henderson 
3504b88ce6f2SRichard Henderson     amask = address_mask_i(dc, -8);
3505b88ce6f2SRichard Henderson     tcg_gen_andi_tl(s1, s1, amask);
3506b88ce6f2SRichard Henderson     tcg_gen_andi_tl(s2, s2, amask);
3507b88ce6f2SRichard Henderson 
3508b88ce6f2SRichard Henderson     /* Compute dst = (s1 == s2 ? lo1 : lo1 & lo2). */
3509b88ce6f2SRichard Henderson     tcg_gen_and_tl(lo2, lo2, lo1);
3510b88ce6f2SRichard Henderson     tcg_gen_movcond_tl(TCG_COND_EQ, dst, s1, s2, lo1, lo2);
3511b88ce6f2SRichard Henderson 
3512b88ce6f2SRichard Henderson     gen_store_gpr(dc, a->rd, dst);
3513b88ce6f2SRichard Henderson     return advance_pc(dc);
3514b88ce6f2SRichard Henderson }
3515b88ce6f2SRichard Henderson 
3516b88ce6f2SRichard Henderson TRANS(EDGE8cc, VIS1, gen_edge, a, 8, 1, 0)
3517b88ce6f2SRichard Henderson TRANS(EDGE8Lcc, VIS1, gen_edge, a, 8, 1, 1)
3518b88ce6f2SRichard Henderson TRANS(EDGE16cc, VIS1, gen_edge, a, 16, 1, 0)
3519b88ce6f2SRichard Henderson TRANS(EDGE16Lcc, VIS1, gen_edge, a, 16, 1, 1)
3520b88ce6f2SRichard Henderson TRANS(EDGE32cc, VIS1, gen_edge, a, 32, 1, 0)
3521b88ce6f2SRichard Henderson TRANS(EDGE32Lcc, VIS1, gen_edge, a, 32, 1, 1)
3522b88ce6f2SRichard Henderson 
3523b88ce6f2SRichard Henderson TRANS(EDGE8N, VIS2, gen_edge, a, 8, 0, 0)
3524b88ce6f2SRichard Henderson TRANS(EDGE8LN, VIS2, gen_edge, a, 8, 0, 1)
3525b88ce6f2SRichard Henderson TRANS(EDGE16N, VIS2, gen_edge, a, 16, 0, 0)
3526b88ce6f2SRichard Henderson TRANS(EDGE16LN, VIS2, gen_edge, a, 16, 0, 1)
3527b88ce6f2SRichard Henderson TRANS(EDGE32N, VIS2, gen_edge, a, 32, 0, 0)
3528b88ce6f2SRichard Henderson TRANS(EDGE32LN, VIS2, gen_edge, a, 32, 0, 1)
3529b88ce6f2SRichard Henderson 
353045bfed3bSRichard Henderson static bool do_rrr(DisasContext *dc, arg_r_r_r *a,
353145bfed3bSRichard Henderson                    void (*func)(TCGv, TCGv, TCGv))
353245bfed3bSRichard Henderson {
353345bfed3bSRichard Henderson     TCGv dst = gen_dest_gpr(dc, a->rd);
353445bfed3bSRichard Henderson     TCGv src1 = gen_load_gpr(dc, a->rs1);
353545bfed3bSRichard Henderson     TCGv src2 = gen_load_gpr(dc, a->rs2);
353645bfed3bSRichard Henderson 
353745bfed3bSRichard Henderson     func(dst, src1, src2);
353845bfed3bSRichard Henderson     gen_store_gpr(dc, a->rd, dst);
353945bfed3bSRichard Henderson     return advance_pc(dc);
354045bfed3bSRichard Henderson }
354145bfed3bSRichard Henderson 
354245bfed3bSRichard Henderson TRANS(ARRAY8, VIS1, do_rrr, a, gen_helper_array8)
354345bfed3bSRichard Henderson TRANS(ARRAY16, VIS1, do_rrr, a, gen_op_array16)
354445bfed3bSRichard Henderson TRANS(ARRAY32, VIS1, do_rrr, a, gen_op_array32)
354545bfed3bSRichard Henderson 
35469e20ca94SRichard Henderson static void gen_op_alignaddr(TCGv dst, TCGv s1, TCGv s2)
35479e20ca94SRichard Henderson {
35489e20ca94SRichard Henderson #ifdef TARGET_SPARC64
35499e20ca94SRichard Henderson     TCGv tmp = tcg_temp_new();
35509e20ca94SRichard Henderson 
35519e20ca94SRichard Henderson     tcg_gen_add_tl(tmp, s1, s2);
35529e20ca94SRichard Henderson     tcg_gen_andi_tl(dst, tmp, -8);
35539e20ca94SRichard Henderson     tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, tmp, 0, 3);
35549e20ca94SRichard Henderson #else
35559e20ca94SRichard Henderson     g_assert_not_reached();
35569e20ca94SRichard Henderson #endif
35579e20ca94SRichard Henderson }
35589e20ca94SRichard Henderson 
35599e20ca94SRichard Henderson static void gen_op_alignaddrl(TCGv dst, TCGv s1, TCGv s2)
35609e20ca94SRichard Henderson {
35619e20ca94SRichard Henderson #ifdef TARGET_SPARC64
35629e20ca94SRichard Henderson     TCGv tmp = tcg_temp_new();
35639e20ca94SRichard Henderson 
35649e20ca94SRichard Henderson     tcg_gen_add_tl(tmp, s1, s2);
35659e20ca94SRichard Henderson     tcg_gen_andi_tl(dst, tmp, -8);
35669e20ca94SRichard Henderson     tcg_gen_neg_tl(tmp, tmp);
35679e20ca94SRichard Henderson     tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, tmp, 0, 3);
35689e20ca94SRichard Henderson #else
35699e20ca94SRichard Henderson     g_assert_not_reached();
35709e20ca94SRichard Henderson #endif
35719e20ca94SRichard Henderson }
35729e20ca94SRichard Henderson 
35739e20ca94SRichard Henderson TRANS(ALIGNADDR, VIS1, do_rrr, a, gen_op_alignaddr)
35749e20ca94SRichard Henderson TRANS(ALIGNADDRL, VIS1, do_rrr, a, gen_op_alignaddrl)
35759e20ca94SRichard Henderson 
357639ca3490SRichard Henderson static void gen_op_bmask(TCGv dst, TCGv s1, TCGv s2)
357739ca3490SRichard Henderson {
357839ca3490SRichard Henderson #ifdef TARGET_SPARC64
357939ca3490SRichard Henderson     tcg_gen_add_tl(dst, s1, s2);
358039ca3490SRichard Henderson     tcg_gen_deposit_tl(cpu_gsr, cpu_gsr, dst, 32, 32);
358139ca3490SRichard Henderson #else
358239ca3490SRichard Henderson     g_assert_not_reached();
358339ca3490SRichard Henderson #endif
358439ca3490SRichard Henderson }
358539ca3490SRichard Henderson 
358639ca3490SRichard Henderson TRANS(BMASK, VIS2, do_rrr, a, gen_op_bmask)
358739ca3490SRichard Henderson 
35885fc546eeSRichard Henderson static bool do_shift_r(DisasContext *dc, arg_shiftr *a, bool l, bool u)
35895fc546eeSRichard Henderson {
35905fc546eeSRichard Henderson     TCGv dst, src1, src2;
35915fc546eeSRichard Henderson 
35925fc546eeSRichard Henderson     /* Reject 64-bit shifts for sparc32. */
35935fc546eeSRichard Henderson     if (avail_32(dc) && a->x) {
35945fc546eeSRichard Henderson         return false;
35955fc546eeSRichard Henderson     }
35965fc546eeSRichard Henderson 
35975fc546eeSRichard Henderson     src2 = tcg_temp_new();
35985fc546eeSRichard Henderson     tcg_gen_andi_tl(src2, gen_load_gpr(dc, a->rs2), a->x ? 63 : 31);
35995fc546eeSRichard Henderson     src1 = gen_load_gpr(dc, a->rs1);
36005fc546eeSRichard Henderson     dst = gen_dest_gpr(dc, a->rd);
36015fc546eeSRichard Henderson 
36025fc546eeSRichard Henderson     if (l) {
36035fc546eeSRichard Henderson         tcg_gen_shl_tl(dst, src1, src2);
36045fc546eeSRichard Henderson         if (!a->x) {
36055fc546eeSRichard Henderson             tcg_gen_ext32u_tl(dst, dst);
36065fc546eeSRichard Henderson         }
36075fc546eeSRichard Henderson     } else if (u) {
36085fc546eeSRichard Henderson         if (!a->x) {
36095fc546eeSRichard Henderson             tcg_gen_ext32u_tl(dst, src1);
36105fc546eeSRichard Henderson             src1 = dst;
36115fc546eeSRichard Henderson         }
36125fc546eeSRichard Henderson         tcg_gen_shr_tl(dst, src1, src2);
36135fc546eeSRichard Henderson     } else {
36145fc546eeSRichard Henderson         if (!a->x) {
36155fc546eeSRichard Henderson             tcg_gen_ext32s_tl(dst, src1);
36165fc546eeSRichard Henderson             src1 = dst;
36175fc546eeSRichard Henderson         }
36185fc546eeSRichard Henderson         tcg_gen_sar_tl(dst, src1, src2);
36195fc546eeSRichard Henderson     }
36205fc546eeSRichard Henderson     gen_store_gpr(dc, a->rd, dst);
36215fc546eeSRichard Henderson     return advance_pc(dc);
36225fc546eeSRichard Henderson }
36235fc546eeSRichard Henderson 
36245fc546eeSRichard Henderson TRANS(SLL_r, ALL, do_shift_r, a, true, true)
36255fc546eeSRichard Henderson TRANS(SRL_r, ALL, do_shift_r, a, false, true)
36265fc546eeSRichard Henderson TRANS(SRA_r, ALL, do_shift_r, a, false, false)
36275fc546eeSRichard Henderson 
36285fc546eeSRichard Henderson static bool do_shift_i(DisasContext *dc, arg_shifti *a, bool l, bool u)
36295fc546eeSRichard Henderson {
36305fc546eeSRichard Henderson     TCGv dst, src1;
36315fc546eeSRichard Henderson 
36325fc546eeSRichard Henderson     /* Reject 64-bit shifts for sparc32. */
36335fc546eeSRichard Henderson     if (avail_32(dc) && (a->x || a->i >= 32)) {
36345fc546eeSRichard Henderson         return false;
36355fc546eeSRichard Henderson     }
36365fc546eeSRichard Henderson 
36375fc546eeSRichard Henderson     src1 = gen_load_gpr(dc, a->rs1);
36385fc546eeSRichard Henderson     dst = gen_dest_gpr(dc, a->rd);
36395fc546eeSRichard Henderson 
36405fc546eeSRichard Henderson     if (avail_32(dc) || a->x) {
36415fc546eeSRichard Henderson         if (l) {
36425fc546eeSRichard Henderson             tcg_gen_shli_tl(dst, src1, a->i);
36435fc546eeSRichard Henderson         } else if (u) {
36445fc546eeSRichard Henderson             tcg_gen_shri_tl(dst, src1, a->i);
36455fc546eeSRichard Henderson         } else {
36465fc546eeSRichard Henderson             tcg_gen_sari_tl(dst, src1, a->i);
36475fc546eeSRichard Henderson         }
36485fc546eeSRichard Henderson     } else {
36495fc546eeSRichard Henderson         if (l) {
36505fc546eeSRichard Henderson             tcg_gen_deposit_z_tl(dst, src1, a->i, 32 - a->i);
36515fc546eeSRichard Henderson         } else if (u) {
36525fc546eeSRichard Henderson             tcg_gen_extract_tl(dst, src1, a->i, 32 - a->i);
36535fc546eeSRichard Henderson         } else {
36545fc546eeSRichard Henderson             tcg_gen_sextract_tl(dst, src1, a->i, 32 - a->i);
36555fc546eeSRichard Henderson         }
36565fc546eeSRichard Henderson     }
36575fc546eeSRichard Henderson     gen_store_gpr(dc, a->rd, dst);
36585fc546eeSRichard Henderson     return advance_pc(dc);
36595fc546eeSRichard Henderson }
36605fc546eeSRichard Henderson 
36615fc546eeSRichard Henderson TRANS(SLL_i, ALL, do_shift_i, a, true, true)
36625fc546eeSRichard Henderson TRANS(SRL_i, ALL, do_shift_i, a, false, true)
36635fc546eeSRichard Henderson TRANS(SRA_i, ALL, do_shift_i, a, false, false)
36645fc546eeSRichard Henderson 
3665fb4ed7aaSRichard Henderson static TCGv gen_rs2_or_imm(DisasContext *dc, bool imm, int rs2_or_imm)
3666fb4ed7aaSRichard Henderson {
3667fb4ed7aaSRichard Henderson     /* For simplicity, we under-decoded the rs2 form. */
3668fb4ed7aaSRichard Henderson     if (!imm && rs2_or_imm & ~0x1f) {
3669fb4ed7aaSRichard Henderson         return NULL;
3670fb4ed7aaSRichard Henderson     }
3671fb4ed7aaSRichard Henderson     if (imm || rs2_or_imm == 0) {
3672fb4ed7aaSRichard Henderson         return tcg_constant_tl(rs2_or_imm);
3673fb4ed7aaSRichard Henderson     } else {
3674fb4ed7aaSRichard Henderson         return cpu_regs[rs2_or_imm];
3675fb4ed7aaSRichard Henderson     }
3676fb4ed7aaSRichard Henderson }
3677fb4ed7aaSRichard Henderson 
3678fb4ed7aaSRichard Henderson static bool do_mov_cond(DisasContext *dc, DisasCompare *cmp, int rd, TCGv src2)
3679fb4ed7aaSRichard Henderson {
3680fb4ed7aaSRichard Henderson     TCGv dst = gen_load_gpr(dc, rd);
3681c8507ebfSRichard Henderson     TCGv c2 = tcg_constant_tl(cmp->c2);
3682fb4ed7aaSRichard Henderson 
3683c8507ebfSRichard Henderson     tcg_gen_movcond_tl(cmp->cond, dst, cmp->c1, c2, src2, dst);
3684fb4ed7aaSRichard Henderson     gen_store_gpr(dc, rd, dst);
3685fb4ed7aaSRichard Henderson     return advance_pc(dc);
3686fb4ed7aaSRichard Henderson }
3687fb4ed7aaSRichard Henderson 
3688fb4ed7aaSRichard Henderson static bool trans_MOVcc(DisasContext *dc, arg_MOVcc *a)
3689fb4ed7aaSRichard Henderson {
3690fb4ed7aaSRichard Henderson     TCGv src2 = gen_rs2_or_imm(dc, a->imm, a->rs2_or_imm);
3691fb4ed7aaSRichard Henderson     DisasCompare cmp;
3692fb4ed7aaSRichard Henderson 
3693fb4ed7aaSRichard Henderson     if (src2 == NULL) {
3694fb4ed7aaSRichard Henderson         return false;
3695fb4ed7aaSRichard Henderson     }
3696fb4ed7aaSRichard Henderson     gen_compare(&cmp, a->cc, a->cond, dc);
3697fb4ed7aaSRichard Henderson     return do_mov_cond(dc, &cmp, a->rd, src2);
3698fb4ed7aaSRichard Henderson }
3699fb4ed7aaSRichard Henderson 
3700fb4ed7aaSRichard Henderson static bool trans_MOVfcc(DisasContext *dc, arg_MOVfcc *a)
3701fb4ed7aaSRichard Henderson {
3702fb4ed7aaSRichard Henderson     TCGv src2 = gen_rs2_or_imm(dc, a->imm, a->rs2_or_imm);
3703fb4ed7aaSRichard Henderson     DisasCompare cmp;
3704fb4ed7aaSRichard Henderson 
3705fb4ed7aaSRichard Henderson     if (src2 == NULL) {
3706fb4ed7aaSRichard Henderson         return false;
3707fb4ed7aaSRichard Henderson     }
3708fb4ed7aaSRichard Henderson     gen_fcompare(&cmp, a->cc, a->cond);
3709fb4ed7aaSRichard Henderson     return do_mov_cond(dc, &cmp, a->rd, src2);
3710fb4ed7aaSRichard Henderson }
3711fb4ed7aaSRichard Henderson 
3712fb4ed7aaSRichard Henderson static bool trans_MOVR(DisasContext *dc, arg_MOVR *a)
3713fb4ed7aaSRichard Henderson {
3714fb4ed7aaSRichard Henderson     TCGv src2 = gen_rs2_or_imm(dc, a->imm, a->rs2_or_imm);
3715fb4ed7aaSRichard Henderson     DisasCompare cmp;
3716fb4ed7aaSRichard Henderson 
3717fb4ed7aaSRichard Henderson     if (src2 == NULL) {
3718fb4ed7aaSRichard Henderson         return false;
3719fb4ed7aaSRichard Henderson     }
37202c4f56c9SRichard Henderson     if (!gen_compare_reg(&cmp, a->cond, gen_load_gpr(dc, a->rs1))) {
37212c4f56c9SRichard Henderson         return false;
37222c4f56c9SRichard Henderson     }
3723fb4ed7aaSRichard Henderson     return do_mov_cond(dc, &cmp, a->rd, src2);
3724fb4ed7aaSRichard Henderson }
3725fb4ed7aaSRichard Henderson 
372686b82fe0SRichard Henderson static bool do_add_special(DisasContext *dc, arg_r_r_ri *a,
372786b82fe0SRichard Henderson                            bool (*func)(DisasContext *dc, int rd, TCGv src))
372886b82fe0SRichard Henderson {
372986b82fe0SRichard Henderson     TCGv src1, sum;
373086b82fe0SRichard Henderson 
373186b82fe0SRichard Henderson     /* For simplicity, we under-decoded the rs2 form. */
373286b82fe0SRichard Henderson     if (!a->imm && a->rs2_or_imm & ~0x1f) {
373386b82fe0SRichard Henderson         return false;
373486b82fe0SRichard Henderson     }
373586b82fe0SRichard Henderson 
373686b82fe0SRichard Henderson     /*
373786b82fe0SRichard Henderson      * Always load the sum into a new temporary.
373886b82fe0SRichard Henderson      * This is required to capture the value across a window change,
373986b82fe0SRichard Henderson      * e.g. SAVE and RESTORE, and may be optimized away otherwise.
374086b82fe0SRichard Henderson      */
374186b82fe0SRichard Henderson     sum = tcg_temp_new();
374286b82fe0SRichard Henderson     src1 = gen_load_gpr(dc, a->rs1);
374386b82fe0SRichard Henderson     if (a->imm || a->rs2_or_imm == 0) {
374486b82fe0SRichard Henderson         tcg_gen_addi_tl(sum, src1, a->rs2_or_imm);
374586b82fe0SRichard Henderson     } else {
374686b82fe0SRichard Henderson         tcg_gen_add_tl(sum, src1, cpu_regs[a->rs2_or_imm]);
374786b82fe0SRichard Henderson     }
374886b82fe0SRichard Henderson     return func(dc, a->rd, sum);
374986b82fe0SRichard Henderson }
375086b82fe0SRichard Henderson 
375186b82fe0SRichard Henderson static bool do_jmpl(DisasContext *dc, int rd, TCGv src)
375286b82fe0SRichard Henderson {
375386b82fe0SRichard Henderson     /*
375486b82fe0SRichard Henderson      * Preserve pc across advance, so that we can delay
375586b82fe0SRichard Henderson      * the writeback to rd until after src is consumed.
375686b82fe0SRichard Henderson      */
375786b82fe0SRichard Henderson     target_ulong cur_pc = dc->pc;
375886b82fe0SRichard Henderson 
375986b82fe0SRichard Henderson     gen_check_align(dc, src, 3);
376086b82fe0SRichard Henderson 
376186b82fe0SRichard Henderson     gen_mov_pc_npc(dc);
376286b82fe0SRichard Henderson     tcg_gen_mov_tl(cpu_npc, src);
376386b82fe0SRichard Henderson     gen_address_mask(dc, cpu_npc);
376486b82fe0SRichard Henderson     gen_store_gpr(dc, rd, tcg_constant_tl(cur_pc));
376586b82fe0SRichard Henderson 
376686b82fe0SRichard Henderson     dc->npc = DYNAMIC_PC_LOOKUP;
376786b82fe0SRichard Henderson     return true;
376886b82fe0SRichard Henderson }
376986b82fe0SRichard Henderson 
377086b82fe0SRichard Henderson TRANS(JMPL, ALL, do_add_special, a, do_jmpl)
377186b82fe0SRichard Henderson 
377286b82fe0SRichard Henderson static bool do_rett(DisasContext *dc, int rd, TCGv src)
377386b82fe0SRichard Henderson {
377486b82fe0SRichard Henderson     if (!supervisor(dc)) {
377586b82fe0SRichard Henderson         return raise_priv(dc);
377686b82fe0SRichard Henderson     }
377786b82fe0SRichard Henderson 
377886b82fe0SRichard Henderson     gen_check_align(dc, src, 3);
377986b82fe0SRichard Henderson 
378086b82fe0SRichard Henderson     gen_mov_pc_npc(dc);
378186b82fe0SRichard Henderson     tcg_gen_mov_tl(cpu_npc, src);
378286b82fe0SRichard Henderson     gen_helper_rett(tcg_env);
378386b82fe0SRichard Henderson 
378486b82fe0SRichard Henderson     dc->npc = DYNAMIC_PC;
378586b82fe0SRichard Henderson     return true;
378686b82fe0SRichard Henderson }
378786b82fe0SRichard Henderson 
378886b82fe0SRichard Henderson TRANS(RETT, 32, do_add_special, a, do_rett)
378986b82fe0SRichard Henderson 
379086b82fe0SRichard Henderson static bool do_return(DisasContext *dc, int rd, TCGv src)
379186b82fe0SRichard Henderson {
379286b82fe0SRichard Henderson     gen_check_align(dc, src, 3);
37930dfae4f9SRichard Henderson     gen_helper_restore(tcg_env);
379486b82fe0SRichard Henderson 
379586b82fe0SRichard Henderson     gen_mov_pc_npc(dc);
379686b82fe0SRichard Henderson     tcg_gen_mov_tl(cpu_npc, src);
379786b82fe0SRichard Henderson     gen_address_mask(dc, cpu_npc);
379886b82fe0SRichard Henderson 
379986b82fe0SRichard Henderson     dc->npc = DYNAMIC_PC_LOOKUP;
380086b82fe0SRichard Henderson     return true;
380186b82fe0SRichard Henderson }
380286b82fe0SRichard Henderson 
380386b82fe0SRichard Henderson TRANS(RETURN, 64, do_add_special, a, do_return)
380486b82fe0SRichard Henderson 
3805d3825800SRichard Henderson static bool do_save(DisasContext *dc, int rd, TCGv src)
3806d3825800SRichard Henderson {
3807d3825800SRichard Henderson     gen_helper_save(tcg_env);
3808d3825800SRichard Henderson     gen_store_gpr(dc, rd, src);
3809d3825800SRichard Henderson     return advance_pc(dc);
3810d3825800SRichard Henderson }
3811d3825800SRichard Henderson 
3812d3825800SRichard Henderson TRANS(SAVE, ALL, do_add_special, a, do_save)
3813d3825800SRichard Henderson 
3814d3825800SRichard Henderson static bool do_restore(DisasContext *dc, int rd, TCGv src)
3815d3825800SRichard Henderson {
3816d3825800SRichard Henderson     gen_helper_restore(tcg_env);
3817d3825800SRichard Henderson     gen_store_gpr(dc, rd, src);
3818d3825800SRichard Henderson     return advance_pc(dc);
3819d3825800SRichard Henderson }
3820d3825800SRichard Henderson 
3821d3825800SRichard Henderson TRANS(RESTORE, ALL, do_add_special, a, do_restore)
3822d3825800SRichard Henderson 
38238f75b8a4SRichard Henderson static bool do_done_retry(DisasContext *dc, bool done)
38248f75b8a4SRichard Henderson {
38258f75b8a4SRichard Henderson     if (!supervisor(dc)) {
38268f75b8a4SRichard Henderson         return raise_priv(dc);
38278f75b8a4SRichard Henderson     }
38288f75b8a4SRichard Henderson     dc->npc = DYNAMIC_PC;
38298f75b8a4SRichard Henderson     dc->pc = DYNAMIC_PC;
38308f75b8a4SRichard Henderson     translator_io_start(&dc->base);
38318f75b8a4SRichard Henderson     if (done) {
38328f75b8a4SRichard Henderson         gen_helper_done(tcg_env);
38338f75b8a4SRichard Henderson     } else {
38348f75b8a4SRichard Henderson         gen_helper_retry(tcg_env);
38358f75b8a4SRichard Henderson     }
38368f75b8a4SRichard Henderson     return true;
38378f75b8a4SRichard Henderson }
38388f75b8a4SRichard Henderson 
38398f75b8a4SRichard Henderson TRANS(DONE, 64, do_done_retry, true)
38408f75b8a4SRichard Henderson TRANS(RETRY, 64, do_done_retry, false)
38418f75b8a4SRichard Henderson 
38420880d20bSRichard Henderson /*
38430880d20bSRichard Henderson  * Major opcode 11 -- load and store instructions
38440880d20bSRichard Henderson  */
38450880d20bSRichard Henderson 
38460880d20bSRichard Henderson static TCGv gen_ldst_addr(DisasContext *dc, int rs1, bool imm, int rs2_or_imm)
38470880d20bSRichard Henderson {
38480880d20bSRichard Henderson     TCGv addr, tmp = NULL;
38490880d20bSRichard Henderson 
38500880d20bSRichard Henderson     /* For simplicity, we under-decoded the rs2 form. */
38510880d20bSRichard Henderson     if (!imm && rs2_or_imm & ~0x1f) {
38520880d20bSRichard Henderson         return NULL;
38530880d20bSRichard Henderson     }
38540880d20bSRichard Henderson 
38550880d20bSRichard Henderson     addr = gen_load_gpr(dc, rs1);
38560880d20bSRichard Henderson     if (rs2_or_imm) {
38570880d20bSRichard Henderson         tmp = tcg_temp_new();
38580880d20bSRichard Henderson         if (imm) {
38590880d20bSRichard Henderson             tcg_gen_addi_tl(tmp, addr, rs2_or_imm);
38600880d20bSRichard Henderson         } else {
38610880d20bSRichard Henderson             tcg_gen_add_tl(tmp, addr, cpu_regs[rs2_or_imm]);
38620880d20bSRichard Henderson         }
38630880d20bSRichard Henderson         addr = tmp;
38640880d20bSRichard Henderson     }
38650880d20bSRichard Henderson     if (AM_CHECK(dc)) {
38660880d20bSRichard Henderson         if (!tmp) {
38670880d20bSRichard Henderson             tmp = tcg_temp_new();
38680880d20bSRichard Henderson         }
38690880d20bSRichard Henderson         tcg_gen_ext32u_tl(tmp, addr);
38700880d20bSRichard Henderson         addr = tmp;
38710880d20bSRichard Henderson     }
38720880d20bSRichard Henderson     return addr;
38730880d20bSRichard Henderson }
38740880d20bSRichard Henderson 
38750880d20bSRichard Henderson static bool do_ld_gpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp mop)
38760880d20bSRichard Henderson {
38770880d20bSRichard Henderson     TCGv reg, addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
38780880d20bSRichard Henderson     DisasASI da;
38790880d20bSRichard Henderson 
38800880d20bSRichard Henderson     if (addr == NULL) {
38810880d20bSRichard Henderson         return false;
38820880d20bSRichard Henderson     }
38830880d20bSRichard Henderson     da = resolve_asi(dc, a->asi, mop);
38840880d20bSRichard Henderson 
38850880d20bSRichard Henderson     reg = gen_dest_gpr(dc, a->rd);
388642071fc1SRichard Henderson     gen_ld_asi(dc, &da, reg, addr);
38870880d20bSRichard Henderson     gen_store_gpr(dc, a->rd, reg);
38880880d20bSRichard Henderson     return advance_pc(dc);
38890880d20bSRichard Henderson }
38900880d20bSRichard Henderson 
38910880d20bSRichard Henderson TRANS(LDUW, ALL, do_ld_gpr, a, MO_TEUL)
38920880d20bSRichard Henderson TRANS(LDUB, ALL, do_ld_gpr, a, MO_UB)
38930880d20bSRichard Henderson TRANS(LDUH, ALL, do_ld_gpr, a, MO_TEUW)
38940880d20bSRichard Henderson TRANS(LDSB, ALL, do_ld_gpr, a, MO_SB)
38950880d20bSRichard Henderson TRANS(LDSH, ALL, do_ld_gpr, a, MO_TESW)
38960880d20bSRichard Henderson TRANS(LDSW, 64, do_ld_gpr, a, MO_TESL)
38970880d20bSRichard Henderson TRANS(LDX, 64, do_ld_gpr, a, MO_TEUQ)
38980880d20bSRichard Henderson 
38990880d20bSRichard Henderson static bool do_st_gpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp mop)
39000880d20bSRichard Henderson {
39010880d20bSRichard Henderson     TCGv reg, addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
39020880d20bSRichard Henderson     DisasASI da;
39030880d20bSRichard Henderson 
39040880d20bSRichard Henderson     if (addr == NULL) {
39050880d20bSRichard Henderson         return false;
39060880d20bSRichard Henderson     }
39070880d20bSRichard Henderson     da = resolve_asi(dc, a->asi, mop);
39080880d20bSRichard Henderson 
39090880d20bSRichard Henderson     reg = gen_load_gpr(dc, a->rd);
391042071fc1SRichard Henderson     gen_st_asi(dc, &da, reg, addr);
39110880d20bSRichard Henderson     return advance_pc(dc);
39120880d20bSRichard Henderson }
39130880d20bSRichard Henderson 
39140880d20bSRichard Henderson TRANS(STW, ALL, do_st_gpr, a, MO_TEUL)
39150880d20bSRichard Henderson TRANS(STB, ALL, do_st_gpr, a, MO_UB)
39160880d20bSRichard Henderson TRANS(STH, ALL, do_st_gpr, a, MO_TEUW)
39170880d20bSRichard Henderson TRANS(STX, 64, do_st_gpr, a, MO_TEUQ)
39180880d20bSRichard Henderson 
39190880d20bSRichard Henderson static bool trans_LDD(DisasContext *dc, arg_r_r_ri_asi *a)
39200880d20bSRichard Henderson {
39210880d20bSRichard Henderson     TCGv addr;
39220880d20bSRichard Henderson     DisasASI da;
39230880d20bSRichard Henderson 
39240880d20bSRichard Henderson     if (a->rd & 1) {
39250880d20bSRichard Henderson         return false;
39260880d20bSRichard Henderson     }
39270880d20bSRichard Henderson     addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
39280880d20bSRichard Henderson     if (addr == NULL) {
39290880d20bSRichard Henderson         return false;
39300880d20bSRichard Henderson     }
39310880d20bSRichard Henderson     da = resolve_asi(dc, a->asi, MO_TEUQ);
393242071fc1SRichard Henderson     gen_ldda_asi(dc, &da, addr, a->rd);
39330880d20bSRichard Henderson     return advance_pc(dc);
39340880d20bSRichard Henderson }
39350880d20bSRichard Henderson 
39360880d20bSRichard Henderson static bool trans_STD(DisasContext *dc, arg_r_r_ri_asi *a)
39370880d20bSRichard Henderson {
39380880d20bSRichard Henderson     TCGv addr;
39390880d20bSRichard Henderson     DisasASI da;
39400880d20bSRichard Henderson 
39410880d20bSRichard Henderson     if (a->rd & 1) {
39420880d20bSRichard Henderson         return false;
39430880d20bSRichard Henderson     }
39440880d20bSRichard Henderson     addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
39450880d20bSRichard Henderson     if (addr == NULL) {
39460880d20bSRichard Henderson         return false;
39470880d20bSRichard Henderson     }
39480880d20bSRichard Henderson     da = resolve_asi(dc, a->asi, MO_TEUQ);
394942071fc1SRichard Henderson     gen_stda_asi(dc, &da, addr, a->rd);
39500880d20bSRichard Henderson     return advance_pc(dc);
39510880d20bSRichard Henderson }
39520880d20bSRichard Henderson 
3953cf07cd1eSRichard Henderson static bool trans_LDSTUB(DisasContext *dc, arg_r_r_ri_asi *a)
3954cf07cd1eSRichard Henderson {
3955cf07cd1eSRichard Henderson     TCGv addr, reg;
3956cf07cd1eSRichard Henderson     DisasASI da;
3957cf07cd1eSRichard Henderson 
3958cf07cd1eSRichard Henderson     addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
3959cf07cd1eSRichard Henderson     if (addr == NULL) {
3960cf07cd1eSRichard Henderson         return false;
3961cf07cd1eSRichard Henderson     }
3962cf07cd1eSRichard Henderson     da = resolve_asi(dc, a->asi, MO_UB);
3963cf07cd1eSRichard Henderson 
3964cf07cd1eSRichard Henderson     reg = gen_dest_gpr(dc, a->rd);
3965cf07cd1eSRichard Henderson     gen_ldstub_asi(dc, &da, reg, addr);
3966cf07cd1eSRichard Henderson     gen_store_gpr(dc, a->rd, reg);
3967cf07cd1eSRichard Henderson     return advance_pc(dc);
3968cf07cd1eSRichard Henderson }
3969cf07cd1eSRichard Henderson 
3970dca544b9SRichard Henderson static bool trans_SWAP(DisasContext *dc, arg_r_r_ri_asi *a)
3971dca544b9SRichard Henderson {
3972dca544b9SRichard Henderson     TCGv addr, dst, src;
3973dca544b9SRichard Henderson     DisasASI da;
3974dca544b9SRichard Henderson 
3975dca544b9SRichard Henderson     addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
3976dca544b9SRichard Henderson     if (addr == NULL) {
3977dca544b9SRichard Henderson         return false;
3978dca544b9SRichard Henderson     }
3979dca544b9SRichard Henderson     da = resolve_asi(dc, a->asi, MO_TEUL);
3980dca544b9SRichard Henderson 
3981dca544b9SRichard Henderson     dst = gen_dest_gpr(dc, a->rd);
3982dca544b9SRichard Henderson     src = gen_load_gpr(dc, a->rd);
3983dca544b9SRichard Henderson     gen_swap_asi(dc, &da, dst, src, addr);
3984dca544b9SRichard Henderson     gen_store_gpr(dc, a->rd, dst);
3985dca544b9SRichard Henderson     return advance_pc(dc);
3986dca544b9SRichard Henderson }
3987dca544b9SRichard Henderson 
3988d0a11d25SRichard Henderson static bool do_casa(DisasContext *dc, arg_r_r_ri_asi *a, MemOp mop)
3989d0a11d25SRichard Henderson {
3990d0a11d25SRichard Henderson     TCGv addr, o, n, c;
3991d0a11d25SRichard Henderson     DisasASI da;
3992d0a11d25SRichard Henderson 
3993d0a11d25SRichard Henderson     addr = gen_ldst_addr(dc, a->rs1, true, 0);
3994d0a11d25SRichard Henderson     if (addr == NULL) {
3995d0a11d25SRichard Henderson         return false;
3996d0a11d25SRichard Henderson     }
3997d0a11d25SRichard Henderson     da = resolve_asi(dc, a->asi, mop);
3998d0a11d25SRichard Henderson 
3999d0a11d25SRichard Henderson     o = gen_dest_gpr(dc, a->rd);
4000d0a11d25SRichard Henderson     n = gen_load_gpr(dc, a->rd);
4001d0a11d25SRichard Henderson     c = gen_load_gpr(dc, a->rs2_or_imm);
4002d0a11d25SRichard Henderson     gen_cas_asi(dc, &da, o, n, c, addr);
4003d0a11d25SRichard Henderson     gen_store_gpr(dc, a->rd, o);
4004d0a11d25SRichard Henderson     return advance_pc(dc);
4005d0a11d25SRichard Henderson }
4006d0a11d25SRichard Henderson 
4007d0a11d25SRichard Henderson TRANS(CASA, CASA, do_casa, a, MO_TEUL)
4008d0a11d25SRichard Henderson TRANS(CASXA, 64, do_casa, a, MO_TEUQ)
4009d0a11d25SRichard Henderson 
401006c060d9SRichard Henderson static bool do_ld_fpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp sz)
401106c060d9SRichard Henderson {
401206c060d9SRichard Henderson     TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
401306c060d9SRichard Henderson     DisasASI da;
401406c060d9SRichard Henderson 
401506c060d9SRichard Henderson     if (addr == NULL) {
401606c060d9SRichard Henderson         return false;
401706c060d9SRichard Henderson     }
401806c060d9SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
401906c060d9SRichard Henderson         return true;
402006c060d9SRichard Henderson     }
402106c060d9SRichard Henderson     if (sz == MO_128 && gen_trap_float128(dc)) {
402206c060d9SRichard Henderson         return true;
402306c060d9SRichard Henderson     }
402406c060d9SRichard Henderson     da = resolve_asi(dc, a->asi, MO_TE | sz);
4025287b1152SRichard Henderson     gen_ldf_asi(dc, &da, sz, addr, a->rd);
402606c060d9SRichard Henderson     gen_update_fprs_dirty(dc, a->rd);
402706c060d9SRichard Henderson     return advance_pc(dc);
402806c060d9SRichard Henderson }
402906c060d9SRichard Henderson 
403006c060d9SRichard Henderson TRANS(LDF, ALL, do_ld_fpr, a, MO_32)
403106c060d9SRichard Henderson TRANS(LDDF, ALL, do_ld_fpr, a, MO_64)
403206c060d9SRichard Henderson TRANS(LDQF, ALL, do_ld_fpr, a, MO_128)
403306c060d9SRichard Henderson 
4034287b1152SRichard Henderson TRANS(LDFA, 64, do_ld_fpr, a, MO_32)
4035287b1152SRichard Henderson TRANS(LDDFA, 64, do_ld_fpr, a, MO_64)
4036287b1152SRichard Henderson TRANS(LDQFA, 64, do_ld_fpr, a, MO_128)
4037287b1152SRichard Henderson 
403806c060d9SRichard Henderson static bool do_st_fpr(DisasContext *dc, arg_r_r_ri_asi *a, MemOp sz)
403906c060d9SRichard Henderson {
404006c060d9SRichard Henderson     TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
404106c060d9SRichard Henderson     DisasASI da;
404206c060d9SRichard Henderson 
404306c060d9SRichard Henderson     if (addr == NULL) {
404406c060d9SRichard Henderson         return false;
404506c060d9SRichard Henderson     }
404606c060d9SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
404706c060d9SRichard Henderson         return true;
404806c060d9SRichard Henderson     }
404906c060d9SRichard Henderson     if (sz == MO_128 && gen_trap_float128(dc)) {
405006c060d9SRichard Henderson         return true;
405106c060d9SRichard Henderson     }
405206c060d9SRichard Henderson     da = resolve_asi(dc, a->asi, MO_TE | sz);
4053287b1152SRichard Henderson     gen_stf_asi(dc, &da, sz, addr, a->rd);
405406c060d9SRichard Henderson     return advance_pc(dc);
405506c060d9SRichard Henderson }
405606c060d9SRichard Henderson 
405706c060d9SRichard Henderson TRANS(STF, ALL, do_st_fpr, a, MO_32)
405806c060d9SRichard Henderson TRANS(STDF, ALL, do_st_fpr, a, MO_64)
405906c060d9SRichard Henderson TRANS(STQF, ALL, do_st_fpr, a, MO_128)
406006c060d9SRichard Henderson 
4061287b1152SRichard Henderson TRANS(STFA, 64, do_st_fpr, a, MO_32)
4062287b1152SRichard Henderson TRANS(STDFA, 64, do_st_fpr, a, MO_64)
4063287b1152SRichard Henderson TRANS(STQFA, 64, do_st_fpr, a, MO_128)
4064287b1152SRichard Henderson 
406506c060d9SRichard Henderson static bool trans_STDFQ(DisasContext *dc, arg_STDFQ *a)
406606c060d9SRichard Henderson {
406706c060d9SRichard Henderson     if (!avail_32(dc)) {
406806c060d9SRichard Henderson         return false;
406906c060d9SRichard Henderson     }
407006c060d9SRichard Henderson     if (!supervisor(dc)) {
407106c060d9SRichard Henderson         return raise_priv(dc);
407206c060d9SRichard Henderson     }
407306c060d9SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
407406c060d9SRichard Henderson         return true;
407506c060d9SRichard Henderson     }
407606c060d9SRichard Henderson     gen_op_fpexception_im(dc, FSR_FTT_SEQ_ERROR);
407706c060d9SRichard Henderson     return true;
407806c060d9SRichard Henderson }
407906c060d9SRichard Henderson 
4080d8c5b92fSRichard Henderson static bool trans_LDFSR(DisasContext *dc, arg_r_r_ri *a)
40813d3c0673SRichard Henderson {
40823590f01eSRichard Henderson     TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
4083d8c5b92fSRichard Henderson     TCGv_i32 tmp;
40843590f01eSRichard Henderson 
40853d3c0673SRichard Henderson     if (addr == NULL) {
40863d3c0673SRichard Henderson         return false;
40873d3c0673SRichard Henderson     }
40883d3c0673SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
40893d3c0673SRichard Henderson         return true;
40903d3c0673SRichard Henderson     }
4091d8c5b92fSRichard Henderson 
4092d8c5b92fSRichard Henderson     tmp = tcg_temp_new_i32();
4093d8c5b92fSRichard Henderson     tcg_gen_qemu_ld_i32(tmp, addr, dc->mem_idx, MO_TEUL | MO_ALIGN);
4094d8c5b92fSRichard Henderson 
4095d8c5b92fSRichard Henderson     tcg_gen_extract_i32(cpu_fcc[0], tmp, FSR_FCC0_SHIFT, 2);
4096d8c5b92fSRichard Henderson     /* LDFSR does not change FCC[1-3]. */
4097d8c5b92fSRichard Henderson 
4098d8c5b92fSRichard Henderson     gen_helper_set_fsr_nofcc_noftt(tcg_env, tmp);
40993d3c0673SRichard Henderson     return advance_pc(dc);
41003d3c0673SRichard Henderson }
41013d3c0673SRichard Henderson 
4102d8c5b92fSRichard Henderson static bool trans_LDXFSR(DisasContext *dc, arg_r_r_ri *a)
4103d8c5b92fSRichard Henderson {
4104d8c5b92fSRichard Henderson #ifdef TARGET_SPARC64
4105d8c5b92fSRichard Henderson     TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
4106d8c5b92fSRichard Henderson     TCGv_i64 t64;
4107d8c5b92fSRichard Henderson     TCGv_i32 lo, hi;
4108d8c5b92fSRichard Henderson 
4109d8c5b92fSRichard Henderson     if (addr == NULL) {
4110d8c5b92fSRichard Henderson         return false;
4111d8c5b92fSRichard Henderson     }
4112d8c5b92fSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4113d8c5b92fSRichard Henderson         return true;
4114d8c5b92fSRichard Henderson     }
4115d8c5b92fSRichard Henderson 
4116d8c5b92fSRichard Henderson     t64 = tcg_temp_new_i64();
4117d8c5b92fSRichard Henderson     tcg_gen_qemu_ld_i64(t64, addr, dc->mem_idx, MO_TEUQ | MO_ALIGN);
4118d8c5b92fSRichard Henderson 
4119d8c5b92fSRichard Henderson     lo = tcg_temp_new_i32();
4120d8c5b92fSRichard Henderson     hi = cpu_fcc[3];
4121d8c5b92fSRichard Henderson     tcg_gen_extr_i64_i32(lo, hi, t64);
4122d8c5b92fSRichard Henderson     tcg_gen_extract_i32(cpu_fcc[0], lo, FSR_FCC0_SHIFT, 2);
4123d8c5b92fSRichard Henderson     tcg_gen_extract_i32(cpu_fcc[1], hi, FSR_FCC1_SHIFT - 32, 2);
4124d8c5b92fSRichard Henderson     tcg_gen_extract_i32(cpu_fcc[2], hi, FSR_FCC2_SHIFT - 32, 2);
4125d8c5b92fSRichard Henderson     tcg_gen_extract_i32(cpu_fcc[3], hi, FSR_FCC3_SHIFT - 32, 2);
4126d8c5b92fSRichard Henderson 
4127d8c5b92fSRichard Henderson     gen_helper_set_fsr_nofcc_noftt(tcg_env, lo);
4128d8c5b92fSRichard Henderson     return advance_pc(dc);
4129d8c5b92fSRichard Henderson #else
4130d8c5b92fSRichard Henderson     return false;
4131d8c5b92fSRichard Henderson #endif
4132d8c5b92fSRichard Henderson }
41333d3c0673SRichard Henderson 
41343d3c0673SRichard Henderson static bool do_stfsr(DisasContext *dc, arg_r_r_ri *a, MemOp mop)
41353d3c0673SRichard Henderson {
41363d3c0673SRichard Henderson     TCGv addr = gen_ldst_addr(dc, a->rs1, a->imm, a->rs2_or_imm);
41371ccd6e13SRichard Henderson     TCGv fsr;
41381ccd6e13SRichard Henderson 
41393d3c0673SRichard Henderson     if (addr == NULL) {
41403d3c0673SRichard Henderson         return false;
41413d3c0673SRichard Henderson     }
41423d3c0673SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
41433d3c0673SRichard Henderson         return true;
41443d3c0673SRichard Henderson     }
41451ccd6e13SRichard Henderson 
41461ccd6e13SRichard Henderson     fsr = tcg_temp_new();
41471ccd6e13SRichard Henderson     gen_helper_get_fsr(fsr, tcg_env);
41481ccd6e13SRichard Henderson     tcg_gen_qemu_st_tl(fsr, addr, dc->mem_idx, mop | MO_ALIGN);
41493d3c0673SRichard Henderson     return advance_pc(dc);
41503d3c0673SRichard Henderson }
41513d3c0673SRichard Henderson 
41523d3c0673SRichard Henderson TRANS(STFSR, ALL, do_stfsr, a, MO_TEUL)
41533d3c0673SRichard Henderson TRANS(STXFSR, 64, do_stfsr, a, MO_TEUQ)
41543d3c0673SRichard Henderson 
41553a38260eSRichard Henderson static bool do_fc(DisasContext *dc, int rd, bool c)
41563a38260eSRichard Henderson {
41573a38260eSRichard Henderson     uint64_t mask;
41583a38260eSRichard Henderson 
41593a38260eSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
41603a38260eSRichard Henderson         return true;
41613a38260eSRichard Henderson     }
41623a38260eSRichard Henderson 
41633a38260eSRichard Henderson     if (rd & 1) {
41643a38260eSRichard Henderson         mask = MAKE_64BIT_MASK(0, 32);
41653a38260eSRichard Henderson     } else {
41663a38260eSRichard Henderson         mask = MAKE_64BIT_MASK(32, 32);
41673a38260eSRichard Henderson     }
41683a38260eSRichard Henderson     if (c) {
41693a38260eSRichard Henderson         tcg_gen_ori_i64(cpu_fpr[rd / 2], cpu_fpr[rd / 2], mask);
41703a38260eSRichard Henderson     } else {
41713a38260eSRichard Henderson         tcg_gen_andi_i64(cpu_fpr[rd / 2], cpu_fpr[rd / 2], ~mask);
41723a38260eSRichard Henderson     }
41733a38260eSRichard Henderson     gen_update_fprs_dirty(dc, rd);
41743a38260eSRichard Henderson     return advance_pc(dc);
41753a38260eSRichard Henderson }
41763a38260eSRichard Henderson 
41773a38260eSRichard Henderson TRANS(FZEROs, VIS1, do_fc, a->rd, 0)
41783a38260eSRichard Henderson TRANS(FONEs, VIS1, do_fc, a->rd, 1)
41793a38260eSRichard Henderson 
41803a38260eSRichard Henderson static bool do_dc(DisasContext *dc, int rd, int64_t c)
41813a38260eSRichard Henderson {
41823a38260eSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
41833a38260eSRichard Henderson         return true;
41843a38260eSRichard Henderson     }
41853a38260eSRichard Henderson 
41863a38260eSRichard Henderson     tcg_gen_movi_i64(cpu_fpr[rd / 2], c);
41873a38260eSRichard Henderson     gen_update_fprs_dirty(dc, rd);
41883a38260eSRichard Henderson     return advance_pc(dc);
41893a38260eSRichard Henderson }
41903a38260eSRichard Henderson 
41913a38260eSRichard Henderson TRANS(FZEROd, VIS1, do_dc, a->rd, 0)
41923a38260eSRichard Henderson TRANS(FONEd, VIS1, do_dc, a->rd, -1)
41933a38260eSRichard Henderson 
4194baf3dbf2SRichard Henderson static bool do_ff(DisasContext *dc, arg_r_r *a,
4195baf3dbf2SRichard Henderson                   void (*func)(TCGv_i32, TCGv_i32))
4196baf3dbf2SRichard Henderson {
4197baf3dbf2SRichard Henderson     TCGv_i32 tmp;
4198baf3dbf2SRichard Henderson 
4199baf3dbf2SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4200baf3dbf2SRichard Henderson         return true;
4201baf3dbf2SRichard Henderson     }
4202baf3dbf2SRichard Henderson 
4203baf3dbf2SRichard Henderson     tmp = gen_load_fpr_F(dc, a->rs);
4204baf3dbf2SRichard Henderson     func(tmp, tmp);
4205baf3dbf2SRichard Henderson     gen_store_fpr_F(dc, a->rd, tmp);
4206baf3dbf2SRichard Henderson     return advance_pc(dc);
4207baf3dbf2SRichard Henderson }
4208baf3dbf2SRichard Henderson 
4209baf3dbf2SRichard Henderson TRANS(FMOVs, ALL, do_ff, a, gen_op_fmovs)
4210baf3dbf2SRichard Henderson TRANS(FNEGs, ALL, do_ff, a, gen_op_fnegs)
4211baf3dbf2SRichard Henderson TRANS(FABSs, ALL, do_ff, a, gen_op_fabss)
4212baf3dbf2SRichard Henderson TRANS(FSRCs, VIS1, do_ff, a, tcg_gen_mov_i32)
4213baf3dbf2SRichard Henderson TRANS(FNOTs, VIS1, do_ff, a, tcg_gen_not_i32)
4214baf3dbf2SRichard Henderson 
42152f722641SRichard Henderson static bool do_fd(DisasContext *dc, arg_r_r *a,
42162f722641SRichard Henderson                   void (*func)(TCGv_i32, TCGv_i64))
42172f722641SRichard Henderson {
42182f722641SRichard Henderson     TCGv_i32 dst;
42192f722641SRichard Henderson     TCGv_i64 src;
42202f722641SRichard Henderson 
42212f722641SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
42222f722641SRichard Henderson         return true;
42232f722641SRichard Henderson     }
42242f722641SRichard Henderson 
4225388a6465SRichard Henderson     dst = tcg_temp_new_i32();
42262f722641SRichard Henderson     src = gen_load_fpr_D(dc, a->rs);
42272f722641SRichard Henderson     func(dst, src);
42282f722641SRichard Henderson     gen_store_fpr_F(dc, a->rd, dst);
42292f722641SRichard Henderson     return advance_pc(dc);
42302f722641SRichard Henderson }
42312f722641SRichard Henderson 
42322f722641SRichard Henderson TRANS(FPACK16, VIS1, do_fd, a, gen_op_fpack16)
42332f722641SRichard Henderson TRANS(FPACKFIX, VIS1, do_fd, a, gen_op_fpackfix)
42342f722641SRichard Henderson 
4235119cb94fSRichard Henderson static bool do_env_ff(DisasContext *dc, arg_r_r *a,
4236119cb94fSRichard Henderson                       void (*func)(TCGv_i32, TCGv_env, TCGv_i32))
4237119cb94fSRichard Henderson {
4238119cb94fSRichard Henderson     TCGv_i32 tmp;
4239119cb94fSRichard Henderson 
4240119cb94fSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4241119cb94fSRichard Henderson         return true;
4242119cb94fSRichard Henderson     }
4243119cb94fSRichard Henderson 
4244119cb94fSRichard Henderson     tmp = gen_load_fpr_F(dc, a->rs);
4245119cb94fSRichard Henderson     func(tmp, tcg_env, tmp);
4246119cb94fSRichard Henderson     gen_store_fpr_F(dc, a->rd, tmp);
4247119cb94fSRichard Henderson     return advance_pc(dc);
4248119cb94fSRichard Henderson }
4249119cb94fSRichard Henderson 
4250119cb94fSRichard Henderson TRANS(FSQRTs, ALL, do_env_ff, a, gen_helper_fsqrts)
4251119cb94fSRichard Henderson TRANS(FiTOs, ALL, do_env_ff, a, gen_helper_fitos)
4252119cb94fSRichard Henderson TRANS(FsTOi, ALL, do_env_ff, a, gen_helper_fstoi)
4253119cb94fSRichard Henderson 
42548c94bcd8SRichard Henderson static bool do_env_fd(DisasContext *dc, arg_r_r *a,
42558c94bcd8SRichard Henderson                       void (*func)(TCGv_i32, TCGv_env, TCGv_i64))
42568c94bcd8SRichard Henderson {
42578c94bcd8SRichard Henderson     TCGv_i32 dst;
42588c94bcd8SRichard Henderson     TCGv_i64 src;
42598c94bcd8SRichard Henderson 
42608c94bcd8SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
42618c94bcd8SRichard Henderson         return true;
42628c94bcd8SRichard Henderson     }
42638c94bcd8SRichard Henderson 
4264388a6465SRichard Henderson     dst = tcg_temp_new_i32();
42658c94bcd8SRichard Henderson     src = gen_load_fpr_D(dc, a->rs);
42668c94bcd8SRichard Henderson     func(dst, tcg_env, src);
42678c94bcd8SRichard Henderson     gen_store_fpr_F(dc, a->rd, dst);
42688c94bcd8SRichard Henderson     return advance_pc(dc);
42698c94bcd8SRichard Henderson }
42708c94bcd8SRichard Henderson 
42718c94bcd8SRichard Henderson TRANS(FdTOs, ALL, do_env_fd, a, gen_helper_fdtos)
42728c94bcd8SRichard Henderson TRANS(FdTOi, ALL, do_env_fd, a, gen_helper_fdtoi)
42738c94bcd8SRichard Henderson TRANS(FxTOs, 64, do_env_fd, a, gen_helper_fxtos)
42748c94bcd8SRichard Henderson 
4275c6d83e4fSRichard Henderson static bool do_dd(DisasContext *dc, arg_r_r *a,
4276c6d83e4fSRichard Henderson                   void (*func)(TCGv_i64, TCGv_i64))
4277c6d83e4fSRichard Henderson {
4278c6d83e4fSRichard Henderson     TCGv_i64 dst, src;
4279c6d83e4fSRichard Henderson 
4280c6d83e4fSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4281c6d83e4fSRichard Henderson         return true;
4282c6d83e4fSRichard Henderson     }
4283c6d83e4fSRichard Henderson 
4284c6d83e4fSRichard Henderson     dst = gen_dest_fpr_D(dc, a->rd);
4285c6d83e4fSRichard Henderson     src = gen_load_fpr_D(dc, a->rs);
4286c6d83e4fSRichard Henderson     func(dst, src);
4287c6d83e4fSRichard Henderson     gen_store_fpr_D(dc, a->rd, dst);
4288c6d83e4fSRichard Henderson     return advance_pc(dc);
4289c6d83e4fSRichard Henderson }
4290c6d83e4fSRichard Henderson 
4291c6d83e4fSRichard Henderson TRANS(FMOVd, 64, do_dd, a, gen_op_fmovd)
4292c6d83e4fSRichard Henderson TRANS(FNEGd, 64, do_dd, a, gen_op_fnegd)
4293c6d83e4fSRichard Henderson TRANS(FABSd, 64, do_dd, a, gen_op_fabsd)
4294c6d83e4fSRichard Henderson TRANS(FSRCd, VIS1, do_dd, a, tcg_gen_mov_i64)
4295c6d83e4fSRichard Henderson TRANS(FNOTd, VIS1, do_dd, a, tcg_gen_not_i64)
4296c6d83e4fSRichard Henderson 
42978aa418b3SRichard Henderson static bool do_env_dd(DisasContext *dc, arg_r_r *a,
42988aa418b3SRichard Henderson                       void (*func)(TCGv_i64, TCGv_env, TCGv_i64))
42998aa418b3SRichard Henderson {
43008aa418b3SRichard Henderson     TCGv_i64 dst, src;
43018aa418b3SRichard Henderson 
43028aa418b3SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
43038aa418b3SRichard Henderson         return true;
43048aa418b3SRichard Henderson     }
43058aa418b3SRichard Henderson 
43068aa418b3SRichard Henderson     dst = gen_dest_fpr_D(dc, a->rd);
43078aa418b3SRichard Henderson     src = gen_load_fpr_D(dc, a->rs);
43088aa418b3SRichard Henderson     func(dst, tcg_env, src);
43098aa418b3SRichard Henderson     gen_store_fpr_D(dc, a->rd, dst);
43108aa418b3SRichard Henderson     return advance_pc(dc);
43118aa418b3SRichard Henderson }
43128aa418b3SRichard Henderson 
43138aa418b3SRichard Henderson TRANS(FSQRTd, ALL, do_env_dd, a, gen_helper_fsqrtd)
43148aa418b3SRichard Henderson TRANS(FxTOd, 64, do_env_dd, a, gen_helper_fxtod)
43158aa418b3SRichard Henderson TRANS(FdTOx, 64, do_env_dd, a, gen_helper_fdtox)
43168aa418b3SRichard Henderson 
4317199d43efSRichard Henderson static bool do_env_df(DisasContext *dc, arg_r_r *a,
4318199d43efSRichard Henderson                       void (*func)(TCGv_i64, TCGv_env, TCGv_i32))
4319199d43efSRichard Henderson {
4320199d43efSRichard Henderson     TCGv_i64 dst;
4321199d43efSRichard Henderson     TCGv_i32 src;
4322199d43efSRichard Henderson 
4323199d43efSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4324199d43efSRichard Henderson         return true;
4325199d43efSRichard Henderson     }
4326199d43efSRichard Henderson 
4327199d43efSRichard Henderson     dst = gen_dest_fpr_D(dc, a->rd);
4328199d43efSRichard Henderson     src = gen_load_fpr_F(dc, a->rs);
4329199d43efSRichard Henderson     func(dst, tcg_env, src);
4330199d43efSRichard Henderson     gen_store_fpr_D(dc, a->rd, dst);
4331199d43efSRichard Henderson     return advance_pc(dc);
4332199d43efSRichard Henderson }
4333199d43efSRichard Henderson 
4334199d43efSRichard Henderson TRANS(FiTOd, ALL, do_env_df, a, gen_helper_fitod)
4335199d43efSRichard Henderson TRANS(FsTOd, ALL, do_env_df, a, gen_helper_fstod)
4336199d43efSRichard Henderson TRANS(FsTOx, 64, do_env_df, a, gen_helper_fstox)
4337199d43efSRichard Henderson 
4338daf457d4SRichard Henderson static bool do_qq(DisasContext *dc, arg_r_r *a,
4339daf457d4SRichard Henderson                   void (*func)(TCGv_i128, TCGv_i128))
4340f4e18df5SRichard Henderson {
434133ec4245SRichard Henderson     TCGv_i128 t;
4342f4e18df5SRichard Henderson 
4343f4e18df5SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4344f4e18df5SRichard Henderson         return true;
4345f4e18df5SRichard Henderson     }
4346f4e18df5SRichard Henderson     if (gen_trap_float128(dc)) {
4347f4e18df5SRichard Henderson         return true;
4348f4e18df5SRichard Henderson     }
4349f4e18df5SRichard Henderson 
4350f4e18df5SRichard Henderson     gen_op_clear_ieee_excp_and_FTT();
435133ec4245SRichard Henderson     t = gen_load_fpr_Q(dc, a->rs);
4352daf457d4SRichard Henderson     func(t, t);
435333ec4245SRichard Henderson     gen_store_fpr_Q(dc, a->rd, t);
4354f4e18df5SRichard Henderson     return advance_pc(dc);
4355f4e18df5SRichard Henderson }
4356f4e18df5SRichard Henderson 
4357daf457d4SRichard Henderson TRANS(FMOVq, 64, do_qq, a, tcg_gen_mov_i128)
4358daf457d4SRichard Henderson TRANS(FNEGq, 64, do_qq, a, gen_op_fnegq)
4359daf457d4SRichard Henderson TRANS(FABSq, 64, do_qq, a, gen_op_fabsq)
4360f4e18df5SRichard Henderson 
4361c995216bSRichard Henderson static bool do_env_qq(DisasContext *dc, arg_r_r *a,
4362e41716beSRichard Henderson                       void (*func)(TCGv_i128, TCGv_env, TCGv_i128))
4363c995216bSRichard Henderson {
4364e41716beSRichard Henderson     TCGv_i128 t;
4365e41716beSRichard Henderson 
4366c995216bSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4367c995216bSRichard Henderson         return true;
4368c995216bSRichard Henderson     }
4369c995216bSRichard Henderson     if (gen_trap_float128(dc)) {
4370c995216bSRichard Henderson         return true;
4371c995216bSRichard Henderson     }
4372c995216bSRichard Henderson 
4373e41716beSRichard Henderson     t = gen_load_fpr_Q(dc, a->rs);
4374e41716beSRichard Henderson     func(t, tcg_env, t);
4375e41716beSRichard Henderson     gen_store_fpr_Q(dc, a->rd, t);
4376c995216bSRichard Henderson     return advance_pc(dc);
4377c995216bSRichard Henderson }
4378c995216bSRichard Henderson 
4379c995216bSRichard Henderson TRANS(FSQRTq, ALL, do_env_qq, a, gen_helper_fsqrtq)
4380c995216bSRichard Henderson 
4381bd9c5c42SRichard Henderson static bool do_env_fq(DisasContext *dc, arg_r_r *a,
4382d81e3efeSRichard Henderson                       void (*func)(TCGv_i32, TCGv_env, TCGv_i128))
4383bd9c5c42SRichard Henderson {
4384d81e3efeSRichard Henderson     TCGv_i128 src;
4385bd9c5c42SRichard Henderson     TCGv_i32 dst;
4386bd9c5c42SRichard Henderson 
4387bd9c5c42SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4388bd9c5c42SRichard Henderson         return true;
4389bd9c5c42SRichard Henderson     }
4390bd9c5c42SRichard Henderson     if (gen_trap_float128(dc)) {
4391bd9c5c42SRichard Henderson         return true;
4392bd9c5c42SRichard Henderson     }
4393bd9c5c42SRichard Henderson 
4394d81e3efeSRichard Henderson     src = gen_load_fpr_Q(dc, a->rs);
4395388a6465SRichard Henderson     dst = tcg_temp_new_i32();
4396d81e3efeSRichard Henderson     func(dst, tcg_env, src);
4397bd9c5c42SRichard Henderson     gen_store_fpr_F(dc, a->rd, dst);
4398bd9c5c42SRichard Henderson     return advance_pc(dc);
4399bd9c5c42SRichard Henderson }
4400bd9c5c42SRichard Henderson 
4401bd9c5c42SRichard Henderson TRANS(FqTOs, ALL, do_env_fq, a, gen_helper_fqtos)
4402bd9c5c42SRichard Henderson TRANS(FqTOi, ALL, do_env_fq, a, gen_helper_fqtoi)
4403bd9c5c42SRichard Henderson 
44041617586fSRichard Henderson static bool do_env_dq(DisasContext *dc, arg_r_r *a,
440525a5769eSRichard Henderson                       void (*func)(TCGv_i64, TCGv_env, TCGv_i128))
44061617586fSRichard Henderson {
440725a5769eSRichard Henderson     TCGv_i128 src;
44081617586fSRichard Henderson     TCGv_i64 dst;
44091617586fSRichard Henderson 
44101617586fSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
44111617586fSRichard Henderson         return true;
44121617586fSRichard Henderson     }
44131617586fSRichard Henderson     if (gen_trap_float128(dc)) {
44141617586fSRichard Henderson         return true;
44151617586fSRichard Henderson     }
44161617586fSRichard Henderson 
441725a5769eSRichard Henderson     src = gen_load_fpr_Q(dc, a->rs);
44181617586fSRichard Henderson     dst = gen_dest_fpr_D(dc, a->rd);
441925a5769eSRichard Henderson     func(dst, tcg_env, src);
44201617586fSRichard Henderson     gen_store_fpr_D(dc, a->rd, dst);
44211617586fSRichard Henderson     return advance_pc(dc);
44221617586fSRichard Henderson }
44231617586fSRichard Henderson 
44241617586fSRichard Henderson TRANS(FqTOd, ALL, do_env_dq, a, gen_helper_fqtod)
44251617586fSRichard Henderson TRANS(FqTOx, 64, do_env_dq, a, gen_helper_fqtox)
44261617586fSRichard Henderson 
442713ebcc77SRichard Henderson static bool do_env_qf(DisasContext *dc, arg_r_r *a,
44280b2a61ccSRichard Henderson                       void (*func)(TCGv_i128, TCGv_env, TCGv_i32))
442913ebcc77SRichard Henderson {
443013ebcc77SRichard Henderson     TCGv_i32 src;
44310b2a61ccSRichard Henderson     TCGv_i128 dst;
443213ebcc77SRichard Henderson 
443313ebcc77SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
443413ebcc77SRichard Henderson         return true;
443513ebcc77SRichard Henderson     }
443613ebcc77SRichard Henderson     if (gen_trap_float128(dc)) {
443713ebcc77SRichard Henderson         return true;
443813ebcc77SRichard Henderson     }
443913ebcc77SRichard Henderson 
444013ebcc77SRichard Henderson     src = gen_load_fpr_F(dc, a->rs);
44410b2a61ccSRichard Henderson     dst = tcg_temp_new_i128();
44420b2a61ccSRichard Henderson     func(dst, tcg_env, src);
44430b2a61ccSRichard Henderson     gen_store_fpr_Q(dc, a->rd, dst);
444413ebcc77SRichard Henderson     return advance_pc(dc);
444513ebcc77SRichard Henderson }
444613ebcc77SRichard Henderson 
444713ebcc77SRichard Henderson TRANS(FiTOq, ALL, do_env_qf, a, gen_helper_fitoq)
444813ebcc77SRichard Henderson TRANS(FsTOq, ALL, do_env_qf, a, gen_helper_fstoq)
444913ebcc77SRichard Henderson 
44507b8e3e1aSRichard Henderson static bool do_env_qd(DisasContext *dc, arg_r_r *a,
4451fdc50716SRichard Henderson                       void (*func)(TCGv_i128, TCGv_env, TCGv_i64))
44527b8e3e1aSRichard Henderson {
44537b8e3e1aSRichard Henderson     TCGv_i64 src;
4454fdc50716SRichard Henderson     TCGv_i128 dst;
44557b8e3e1aSRichard Henderson 
44567b8e3e1aSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
44577b8e3e1aSRichard Henderson         return true;
44587b8e3e1aSRichard Henderson     }
44597b8e3e1aSRichard Henderson     if (gen_trap_float128(dc)) {
44607b8e3e1aSRichard Henderson         return true;
44617b8e3e1aSRichard Henderson     }
44627b8e3e1aSRichard Henderson 
44637b8e3e1aSRichard Henderson     src = gen_load_fpr_D(dc, a->rs);
4464fdc50716SRichard Henderson     dst = tcg_temp_new_i128();
4465fdc50716SRichard Henderson     func(dst, tcg_env, src);
4466fdc50716SRichard Henderson     gen_store_fpr_Q(dc, a->rd, dst);
44677b8e3e1aSRichard Henderson     return advance_pc(dc);
44687b8e3e1aSRichard Henderson }
44697b8e3e1aSRichard Henderson 
44707b8e3e1aSRichard Henderson TRANS(FdTOq, ALL, do_env_qd, a, gen_helper_fdtoq)
44717b8e3e1aSRichard Henderson TRANS(FxTOq, 64, do_env_qd, a, gen_helper_fxtoq)
44727b8e3e1aSRichard Henderson 
44737f10b52fSRichard Henderson static bool do_fff(DisasContext *dc, arg_r_r_r *a,
44747f10b52fSRichard Henderson                    void (*func)(TCGv_i32, TCGv_i32, TCGv_i32))
44757f10b52fSRichard Henderson {
44767f10b52fSRichard Henderson     TCGv_i32 src1, src2;
44777f10b52fSRichard Henderson 
44787f10b52fSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
44797f10b52fSRichard Henderson         return true;
44807f10b52fSRichard Henderson     }
44817f10b52fSRichard Henderson 
44827f10b52fSRichard Henderson     src1 = gen_load_fpr_F(dc, a->rs1);
44837f10b52fSRichard Henderson     src2 = gen_load_fpr_F(dc, a->rs2);
44847f10b52fSRichard Henderson     func(src1, src1, src2);
44857f10b52fSRichard Henderson     gen_store_fpr_F(dc, a->rd, src1);
44867f10b52fSRichard Henderson     return advance_pc(dc);
44877f10b52fSRichard Henderson }
44887f10b52fSRichard Henderson 
44897f10b52fSRichard Henderson TRANS(FPADD16s, VIS1, do_fff, a, tcg_gen_vec_add16_i32)
44907f10b52fSRichard Henderson TRANS(FPADD32s, VIS1, do_fff, a, tcg_gen_add_i32)
44917f10b52fSRichard Henderson TRANS(FPSUB16s, VIS1, do_fff, a, tcg_gen_vec_sub16_i32)
44927f10b52fSRichard Henderson TRANS(FPSUB32s, VIS1, do_fff, a, tcg_gen_sub_i32)
44937f10b52fSRichard Henderson TRANS(FNORs, VIS1, do_fff, a, tcg_gen_nor_i32)
44947f10b52fSRichard Henderson TRANS(FANDNOTs, VIS1, do_fff, a, tcg_gen_andc_i32)
44957f10b52fSRichard Henderson TRANS(FXORs, VIS1, do_fff, a, tcg_gen_xor_i32)
44967f10b52fSRichard Henderson TRANS(FNANDs, VIS1, do_fff, a, tcg_gen_nand_i32)
44977f10b52fSRichard Henderson TRANS(FANDs, VIS1, do_fff, a, tcg_gen_and_i32)
44987f10b52fSRichard Henderson TRANS(FXNORs, VIS1, do_fff, a, tcg_gen_eqv_i32)
44997f10b52fSRichard Henderson TRANS(FORNOTs, VIS1, do_fff, a, tcg_gen_orc_i32)
45007f10b52fSRichard Henderson TRANS(FORs, VIS1, do_fff, a, tcg_gen_or_i32)
45017f10b52fSRichard Henderson 
4502c1514961SRichard Henderson static bool do_env_fff(DisasContext *dc, arg_r_r_r *a,
4503c1514961SRichard Henderson                        void (*func)(TCGv_i32, TCGv_env, TCGv_i32, TCGv_i32))
4504c1514961SRichard Henderson {
4505c1514961SRichard Henderson     TCGv_i32 src1, src2;
4506c1514961SRichard Henderson 
4507c1514961SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4508c1514961SRichard Henderson         return true;
4509c1514961SRichard Henderson     }
4510c1514961SRichard Henderson 
4511c1514961SRichard Henderson     src1 = gen_load_fpr_F(dc, a->rs1);
4512c1514961SRichard Henderson     src2 = gen_load_fpr_F(dc, a->rs2);
4513c1514961SRichard Henderson     func(src1, tcg_env, src1, src2);
4514c1514961SRichard Henderson     gen_store_fpr_F(dc, a->rd, src1);
4515c1514961SRichard Henderson     return advance_pc(dc);
4516c1514961SRichard Henderson }
4517c1514961SRichard Henderson 
4518c1514961SRichard Henderson TRANS(FADDs, ALL, do_env_fff, a, gen_helper_fadds)
4519c1514961SRichard Henderson TRANS(FSUBs, ALL, do_env_fff, a, gen_helper_fsubs)
4520c1514961SRichard Henderson TRANS(FMULs, ALL, do_env_fff, a, gen_helper_fmuls)
4521c1514961SRichard Henderson TRANS(FDIVs, ALL, do_env_fff, a, gen_helper_fdivs)
4522c1514961SRichard Henderson 
4523e06c9f83SRichard Henderson static bool do_ddd(DisasContext *dc, arg_r_r_r *a,
4524e06c9f83SRichard Henderson                    void (*func)(TCGv_i64, TCGv_i64, TCGv_i64))
4525e06c9f83SRichard Henderson {
4526e06c9f83SRichard Henderson     TCGv_i64 dst, src1, src2;
4527e06c9f83SRichard Henderson 
4528e06c9f83SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4529e06c9f83SRichard Henderson         return true;
4530e06c9f83SRichard Henderson     }
4531e06c9f83SRichard Henderson 
4532e06c9f83SRichard Henderson     dst = gen_dest_fpr_D(dc, a->rd);
4533e06c9f83SRichard Henderson     src1 = gen_load_fpr_D(dc, a->rs1);
4534e06c9f83SRichard Henderson     src2 = gen_load_fpr_D(dc, a->rs2);
4535e06c9f83SRichard Henderson     func(dst, src1, src2);
4536e06c9f83SRichard Henderson     gen_store_fpr_D(dc, a->rd, dst);
4537e06c9f83SRichard Henderson     return advance_pc(dc);
4538e06c9f83SRichard Henderson }
4539e06c9f83SRichard Henderson 
4540e06c9f83SRichard Henderson TRANS(FMUL8x16, VIS1, do_ddd, a, gen_helper_fmul8x16)
4541e06c9f83SRichard Henderson TRANS(FMUL8x16AU, VIS1, do_ddd, a, gen_helper_fmul8x16au)
4542e06c9f83SRichard Henderson TRANS(FMUL8x16AL, VIS1, do_ddd, a, gen_helper_fmul8x16al)
4543e06c9f83SRichard Henderson TRANS(FMUL8SUx16, VIS1, do_ddd, a, gen_helper_fmul8sux16)
4544e06c9f83SRichard Henderson TRANS(FMUL8ULx16, VIS1, do_ddd, a, gen_helper_fmul8ulx16)
4545e06c9f83SRichard Henderson TRANS(FMULD8SUx16, VIS1, do_ddd, a, gen_helper_fmuld8sux16)
4546e06c9f83SRichard Henderson TRANS(FMULD8ULx16, VIS1, do_ddd, a, gen_helper_fmuld8ulx16)
4547e06c9f83SRichard Henderson TRANS(FPMERGE, VIS1, do_ddd, a, gen_helper_fpmerge)
4548e06c9f83SRichard Henderson TRANS(FEXPAND, VIS1, do_ddd, a, gen_helper_fexpand)
4549e06c9f83SRichard Henderson 
4550e06c9f83SRichard Henderson TRANS(FPADD16, VIS1, do_ddd, a, tcg_gen_vec_add16_i64)
4551e06c9f83SRichard Henderson TRANS(FPADD32, VIS1, do_ddd, a, tcg_gen_vec_add32_i64)
4552e06c9f83SRichard Henderson TRANS(FPSUB16, VIS1, do_ddd, a, tcg_gen_vec_sub16_i64)
4553e06c9f83SRichard Henderson TRANS(FPSUB32, VIS1, do_ddd, a, tcg_gen_vec_sub32_i64)
4554e06c9f83SRichard Henderson TRANS(FNORd, VIS1, do_ddd, a, tcg_gen_nor_i64)
4555e06c9f83SRichard Henderson TRANS(FANDNOTd, VIS1, do_ddd, a, tcg_gen_andc_i64)
4556e06c9f83SRichard Henderson TRANS(FXORd, VIS1, do_ddd, a, tcg_gen_xor_i64)
4557e06c9f83SRichard Henderson TRANS(FNANDd, VIS1, do_ddd, a, tcg_gen_nand_i64)
4558e06c9f83SRichard Henderson TRANS(FANDd, VIS1, do_ddd, a, tcg_gen_and_i64)
4559e06c9f83SRichard Henderson TRANS(FXNORd, VIS1, do_ddd, a, tcg_gen_eqv_i64)
4560e06c9f83SRichard Henderson TRANS(FORNOTd, VIS1, do_ddd, a, tcg_gen_orc_i64)
4561e06c9f83SRichard Henderson TRANS(FORd, VIS1, do_ddd, a, tcg_gen_or_i64)
4562e06c9f83SRichard Henderson 
45634b6edc0aSRichard Henderson TRANS(FPACK32, VIS1, do_ddd, a, gen_op_fpack32)
45644b6edc0aSRichard Henderson TRANS(FALIGNDATAg, VIS1, do_ddd, a, gen_op_faligndata)
45654b6edc0aSRichard Henderson TRANS(BSHUFFLE, VIS2, do_ddd, a, gen_op_bshuffle)
45664b6edc0aSRichard Henderson 
4567e2fa6bd1SRichard Henderson static bool do_rdd(DisasContext *dc, arg_r_r_r *a,
4568e2fa6bd1SRichard Henderson                    void (*func)(TCGv, TCGv_i64, TCGv_i64))
4569e2fa6bd1SRichard Henderson {
4570e2fa6bd1SRichard Henderson     TCGv_i64 src1, src2;
4571e2fa6bd1SRichard Henderson     TCGv dst;
4572e2fa6bd1SRichard Henderson 
4573e2fa6bd1SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4574e2fa6bd1SRichard Henderson         return true;
4575e2fa6bd1SRichard Henderson     }
4576e2fa6bd1SRichard Henderson 
4577e2fa6bd1SRichard Henderson     dst = gen_dest_gpr(dc, a->rd);
4578e2fa6bd1SRichard Henderson     src1 = gen_load_fpr_D(dc, a->rs1);
4579e2fa6bd1SRichard Henderson     src2 = gen_load_fpr_D(dc, a->rs2);
4580e2fa6bd1SRichard Henderson     func(dst, src1, src2);
4581e2fa6bd1SRichard Henderson     gen_store_gpr(dc, a->rd, dst);
4582e2fa6bd1SRichard Henderson     return advance_pc(dc);
4583e2fa6bd1SRichard Henderson }
4584e2fa6bd1SRichard Henderson 
4585e2fa6bd1SRichard Henderson TRANS(FPCMPLE16, VIS1, do_rdd, a, gen_helper_fcmple16)
4586e2fa6bd1SRichard Henderson TRANS(FPCMPNE16, VIS1, do_rdd, a, gen_helper_fcmpne16)
4587e2fa6bd1SRichard Henderson TRANS(FPCMPGT16, VIS1, do_rdd, a, gen_helper_fcmpgt16)
4588e2fa6bd1SRichard Henderson TRANS(FPCMPEQ16, VIS1, do_rdd, a, gen_helper_fcmpeq16)
4589e2fa6bd1SRichard Henderson 
4590e2fa6bd1SRichard Henderson TRANS(FPCMPLE32, VIS1, do_rdd, a, gen_helper_fcmple32)
4591e2fa6bd1SRichard Henderson TRANS(FPCMPNE32, VIS1, do_rdd, a, gen_helper_fcmpne32)
4592e2fa6bd1SRichard Henderson TRANS(FPCMPGT32, VIS1, do_rdd, a, gen_helper_fcmpgt32)
4593e2fa6bd1SRichard Henderson TRANS(FPCMPEQ32, VIS1, do_rdd, a, gen_helper_fcmpeq32)
4594e2fa6bd1SRichard Henderson 
4595f2a59b0aSRichard Henderson static bool do_env_ddd(DisasContext *dc, arg_r_r_r *a,
4596f2a59b0aSRichard Henderson                        void (*func)(TCGv_i64, TCGv_env, TCGv_i64, TCGv_i64))
4597f2a59b0aSRichard Henderson {
4598f2a59b0aSRichard Henderson     TCGv_i64 dst, src1, src2;
4599f2a59b0aSRichard Henderson 
4600f2a59b0aSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4601f2a59b0aSRichard Henderson         return true;
4602f2a59b0aSRichard Henderson     }
4603f2a59b0aSRichard Henderson 
4604f2a59b0aSRichard Henderson     dst = gen_dest_fpr_D(dc, a->rd);
4605f2a59b0aSRichard Henderson     src1 = gen_load_fpr_D(dc, a->rs1);
4606f2a59b0aSRichard Henderson     src2 = gen_load_fpr_D(dc, a->rs2);
4607f2a59b0aSRichard Henderson     func(dst, tcg_env, src1, src2);
4608f2a59b0aSRichard Henderson     gen_store_fpr_D(dc, a->rd, dst);
4609f2a59b0aSRichard Henderson     return advance_pc(dc);
4610f2a59b0aSRichard Henderson }
4611f2a59b0aSRichard Henderson 
4612f2a59b0aSRichard Henderson TRANS(FADDd, ALL, do_env_ddd, a, gen_helper_faddd)
4613f2a59b0aSRichard Henderson TRANS(FSUBd, ALL, do_env_ddd, a, gen_helper_fsubd)
4614f2a59b0aSRichard Henderson TRANS(FMULd, ALL, do_env_ddd, a, gen_helper_fmuld)
4615f2a59b0aSRichard Henderson TRANS(FDIVd, ALL, do_env_ddd, a, gen_helper_fdivd)
4616f2a59b0aSRichard Henderson 
4617ff4c711bSRichard Henderson static bool trans_FsMULd(DisasContext *dc, arg_r_r_r *a)
4618ff4c711bSRichard Henderson {
4619ff4c711bSRichard Henderson     TCGv_i64 dst;
4620ff4c711bSRichard Henderson     TCGv_i32 src1, src2;
4621ff4c711bSRichard Henderson 
4622ff4c711bSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4623ff4c711bSRichard Henderson         return true;
4624ff4c711bSRichard Henderson     }
4625ff4c711bSRichard Henderson     if (!(dc->def->features & CPU_FEATURE_FSMULD)) {
4626ff4c711bSRichard Henderson         return raise_unimpfpop(dc);
4627ff4c711bSRichard Henderson     }
4628ff4c711bSRichard Henderson 
4629ff4c711bSRichard Henderson     dst = gen_dest_fpr_D(dc, a->rd);
4630ff4c711bSRichard Henderson     src1 = gen_load_fpr_F(dc, a->rs1);
4631ff4c711bSRichard Henderson     src2 = gen_load_fpr_F(dc, a->rs2);
4632ff4c711bSRichard Henderson     gen_helper_fsmuld(dst, tcg_env, src1, src2);
4633ff4c711bSRichard Henderson     gen_store_fpr_D(dc, a->rd, dst);
4634ff4c711bSRichard Henderson     return advance_pc(dc);
4635ff4c711bSRichard Henderson }
4636ff4c711bSRichard Henderson 
4637afb04344SRichard Henderson static bool do_dddd(DisasContext *dc, arg_r_r_r *a,
4638afb04344SRichard Henderson                     void (*func)(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_i64))
4639afb04344SRichard Henderson {
4640afb04344SRichard Henderson     TCGv_i64 dst, src0, src1, src2;
4641afb04344SRichard Henderson 
4642afb04344SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4643afb04344SRichard Henderson         return true;
4644afb04344SRichard Henderson     }
4645afb04344SRichard Henderson 
4646afb04344SRichard Henderson     dst  = gen_dest_fpr_D(dc, a->rd);
4647afb04344SRichard Henderson     src0 = gen_load_fpr_D(dc, a->rd);
4648afb04344SRichard Henderson     src1 = gen_load_fpr_D(dc, a->rs1);
4649afb04344SRichard Henderson     src2 = gen_load_fpr_D(dc, a->rs2);
4650afb04344SRichard Henderson     func(dst, src0, src1, src2);
4651afb04344SRichard Henderson     gen_store_fpr_D(dc, a->rd, dst);
4652afb04344SRichard Henderson     return advance_pc(dc);
4653afb04344SRichard Henderson }
4654afb04344SRichard Henderson 
4655afb04344SRichard Henderson TRANS(PDIST, VIS1, do_dddd, a, gen_helper_pdist)
4656afb04344SRichard Henderson 
4657a4056239SRichard Henderson static bool do_env_qqq(DisasContext *dc, arg_r_r_r *a,
465816bedf89SRichard Henderson                        void (*func)(TCGv_i128, TCGv_env, TCGv_i128, TCGv_i128))
4659a4056239SRichard Henderson {
466016bedf89SRichard Henderson     TCGv_i128 src1, src2;
466116bedf89SRichard Henderson 
4662a4056239SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4663a4056239SRichard Henderson         return true;
4664a4056239SRichard Henderson     }
4665a4056239SRichard Henderson     if (gen_trap_float128(dc)) {
4666a4056239SRichard Henderson         return true;
4667a4056239SRichard Henderson     }
4668a4056239SRichard Henderson 
466916bedf89SRichard Henderson     src1 = gen_load_fpr_Q(dc, a->rs1);
467016bedf89SRichard Henderson     src2 = gen_load_fpr_Q(dc, a->rs2);
467116bedf89SRichard Henderson     func(src1, tcg_env, src1, src2);
467216bedf89SRichard Henderson     gen_store_fpr_Q(dc, a->rd, src1);
4673a4056239SRichard Henderson     return advance_pc(dc);
4674a4056239SRichard Henderson }
4675a4056239SRichard Henderson 
4676a4056239SRichard Henderson TRANS(FADDq, ALL, do_env_qqq, a, gen_helper_faddq)
4677a4056239SRichard Henderson TRANS(FSUBq, ALL, do_env_qqq, a, gen_helper_fsubq)
4678a4056239SRichard Henderson TRANS(FMULq, ALL, do_env_qqq, a, gen_helper_fmulq)
4679a4056239SRichard Henderson TRANS(FDIVq, ALL, do_env_qqq, a, gen_helper_fdivq)
4680a4056239SRichard Henderson 
46815e3b17bbSRichard Henderson static bool trans_FdMULq(DisasContext *dc, arg_r_r_r *a)
46825e3b17bbSRichard Henderson {
46835e3b17bbSRichard Henderson     TCGv_i64 src1, src2;
4684ba21dc99SRichard Henderson     TCGv_i128 dst;
46855e3b17bbSRichard Henderson 
46865e3b17bbSRichard Henderson     if (gen_trap_ifnofpu(dc)) {
46875e3b17bbSRichard Henderson         return true;
46885e3b17bbSRichard Henderson     }
46895e3b17bbSRichard Henderson     if (gen_trap_float128(dc)) {
46905e3b17bbSRichard Henderson         return true;
46915e3b17bbSRichard Henderson     }
46925e3b17bbSRichard Henderson 
46935e3b17bbSRichard Henderson     src1 = gen_load_fpr_D(dc, a->rs1);
46945e3b17bbSRichard Henderson     src2 = gen_load_fpr_D(dc, a->rs2);
4695ba21dc99SRichard Henderson     dst = tcg_temp_new_i128();
4696ba21dc99SRichard Henderson     gen_helper_fdmulq(dst, tcg_env, src1, src2);
4697ba21dc99SRichard Henderson     gen_store_fpr_Q(dc, a->rd, dst);
46985e3b17bbSRichard Henderson     return advance_pc(dc);
46995e3b17bbSRichard Henderson }
47005e3b17bbSRichard Henderson 
4701f7ec8155SRichard Henderson static bool do_fmovr(DisasContext *dc, arg_FMOVRs *a, bool is_128,
4702f7ec8155SRichard Henderson                      void (*func)(DisasContext *, DisasCompare *, int, int))
4703f7ec8155SRichard Henderson {
4704f7ec8155SRichard Henderson     DisasCompare cmp;
4705f7ec8155SRichard Henderson 
47062c4f56c9SRichard Henderson     if (!gen_compare_reg(&cmp, a->cond, gen_load_gpr(dc, a->rs1))) {
47072c4f56c9SRichard Henderson         return false;
47082c4f56c9SRichard Henderson     }
4709f7ec8155SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4710f7ec8155SRichard Henderson         return true;
4711f7ec8155SRichard Henderson     }
4712f7ec8155SRichard Henderson     if (is_128 && gen_trap_float128(dc)) {
4713f7ec8155SRichard Henderson         return true;
4714f7ec8155SRichard Henderson     }
4715f7ec8155SRichard Henderson 
4716f7ec8155SRichard Henderson     gen_op_clear_ieee_excp_and_FTT();
4717f7ec8155SRichard Henderson     func(dc, &cmp, a->rd, a->rs2);
4718f7ec8155SRichard Henderson     return advance_pc(dc);
4719f7ec8155SRichard Henderson }
4720f7ec8155SRichard Henderson 
4721f7ec8155SRichard Henderson TRANS(FMOVRs, 64, do_fmovr, a, false, gen_fmovs)
4722f7ec8155SRichard Henderson TRANS(FMOVRd, 64, do_fmovr, a, false, gen_fmovd)
4723f7ec8155SRichard Henderson TRANS(FMOVRq, 64, do_fmovr, a, true, gen_fmovq)
4724f7ec8155SRichard Henderson 
4725f7ec8155SRichard Henderson static bool do_fmovcc(DisasContext *dc, arg_FMOVscc *a, bool is_128,
4726f7ec8155SRichard Henderson                       void (*func)(DisasContext *, DisasCompare *, int, int))
4727f7ec8155SRichard Henderson {
4728f7ec8155SRichard Henderson     DisasCompare cmp;
4729f7ec8155SRichard Henderson 
4730f7ec8155SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4731f7ec8155SRichard Henderson         return true;
4732f7ec8155SRichard Henderson     }
4733f7ec8155SRichard Henderson     if (is_128 && gen_trap_float128(dc)) {
4734f7ec8155SRichard Henderson         return true;
4735f7ec8155SRichard Henderson     }
4736f7ec8155SRichard Henderson 
4737f7ec8155SRichard Henderson     gen_op_clear_ieee_excp_and_FTT();
4738f7ec8155SRichard Henderson     gen_compare(&cmp, a->cc, a->cond, dc);
4739f7ec8155SRichard Henderson     func(dc, &cmp, a->rd, a->rs2);
4740f7ec8155SRichard Henderson     return advance_pc(dc);
4741f7ec8155SRichard Henderson }
4742f7ec8155SRichard Henderson 
4743f7ec8155SRichard Henderson TRANS(FMOVscc, 64, do_fmovcc, a, false, gen_fmovs)
4744f7ec8155SRichard Henderson TRANS(FMOVdcc, 64, do_fmovcc, a, false, gen_fmovd)
4745f7ec8155SRichard Henderson TRANS(FMOVqcc, 64, do_fmovcc, a, true, gen_fmovq)
4746f7ec8155SRichard Henderson 
4747f7ec8155SRichard Henderson static bool do_fmovfcc(DisasContext *dc, arg_FMOVsfcc *a, bool is_128,
4748f7ec8155SRichard Henderson                        void (*func)(DisasContext *, DisasCompare *, int, int))
4749f7ec8155SRichard Henderson {
4750f7ec8155SRichard Henderson     DisasCompare cmp;
4751f7ec8155SRichard Henderson 
4752f7ec8155SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
4753f7ec8155SRichard Henderson         return true;
4754f7ec8155SRichard Henderson     }
4755f7ec8155SRichard Henderson     if (is_128 && gen_trap_float128(dc)) {
4756f7ec8155SRichard Henderson         return true;
4757f7ec8155SRichard Henderson     }
4758f7ec8155SRichard Henderson 
4759f7ec8155SRichard Henderson     gen_op_clear_ieee_excp_and_FTT();
4760f7ec8155SRichard Henderson     gen_fcompare(&cmp, a->cc, a->cond);
4761f7ec8155SRichard Henderson     func(dc, &cmp, a->rd, a->rs2);
4762f7ec8155SRichard Henderson     return advance_pc(dc);
4763f7ec8155SRichard Henderson }
4764f7ec8155SRichard Henderson 
4765f7ec8155SRichard Henderson TRANS(FMOVsfcc, 64, do_fmovfcc, a, false, gen_fmovs)
4766f7ec8155SRichard Henderson TRANS(FMOVdfcc, 64, do_fmovfcc, a, false, gen_fmovd)
4767f7ec8155SRichard Henderson TRANS(FMOVqfcc, 64, do_fmovfcc, a, true, gen_fmovq)
4768f7ec8155SRichard Henderson 
476940f9ad21SRichard Henderson static bool do_fcmps(DisasContext *dc, arg_FCMPs *a, bool e)
477040f9ad21SRichard Henderson {
477140f9ad21SRichard Henderson     TCGv_i32 src1, src2;
477240f9ad21SRichard Henderson 
477340f9ad21SRichard Henderson     if (avail_32(dc) && a->cc != 0) {
477440f9ad21SRichard Henderson         return false;
477540f9ad21SRichard Henderson     }
477640f9ad21SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
477740f9ad21SRichard Henderson         return true;
477840f9ad21SRichard Henderson     }
477940f9ad21SRichard Henderson 
478040f9ad21SRichard Henderson     src1 = gen_load_fpr_F(dc, a->rs1);
478140f9ad21SRichard Henderson     src2 = gen_load_fpr_F(dc, a->rs2);
478240f9ad21SRichard Henderson     if (e) {
4783d8c5b92fSRichard Henderson         gen_helper_fcmpes(cpu_fcc[a->cc], tcg_env, src1, src2);
478440f9ad21SRichard Henderson     } else {
4785d8c5b92fSRichard Henderson         gen_helper_fcmps(cpu_fcc[a->cc], tcg_env, src1, src2);
478640f9ad21SRichard Henderson     }
478740f9ad21SRichard Henderson     return advance_pc(dc);
478840f9ad21SRichard Henderson }
478940f9ad21SRichard Henderson 
479040f9ad21SRichard Henderson TRANS(FCMPs, ALL, do_fcmps, a, false)
479140f9ad21SRichard Henderson TRANS(FCMPEs, ALL, do_fcmps, a, true)
479240f9ad21SRichard Henderson 
479340f9ad21SRichard Henderson static bool do_fcmpd(DisasContext *dc, arg_FCMPd *a, bool e)
479440f9ad21SRichard Henderson {
479540f9ad21SRichard Henderson     TCGv_i64 src1, src2;
479640f9ad21SRichard Henderson 
479740f9ad21SRichard Henderson     if (avail_32(dc) && a->cc != 0) {
479840f9ad21SRichard Henderson         return false;
479940f9ad21SRichard Henderson     }
480040f9ad21SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
480140f9ad21SRichard Henderson         return true;
480240f9ad21SRichard Henderson     }
480340f9ad21SRichard Henderson 
480440f9ad21SRichard Henderson     src1 = gen_load_fpr_D(dc, a->rs1);
480540f9ad21SRichard Henderson     src2 = gen_load_fpr_D(dc, a->rs2);
480640f9ad21SRichard Henderson     if (e) {
4807d8c5b92fSRichard Henderson         gen_helper_fcmped(cpu_fcc[a->cc], tcg_env, src1, src2);
480840f9ad21SRichard Henderson     } else {
4809d8c5b92fSRichard Henderson         gen_helper_fcmpd(cpu_fcc[a->cc], tcg_env, src1, src2);
481040f9ad21SRichard Henderson     }
481140f9ad21SRichard Henderson     return advance_pc(dc);
481240f9ad21SRichard Henderson }
481340f9ad21SRichard Henderson 
481440f9ad21SRichard Henderson TRANS(FCMPd, ALL, do_fcmpd, a, false)
481540f9ad21SRichard Henderson TRANS(FCMPEd, ALL, do_fcmpd, a, true)
481640f9ad21SRichard Henderson 
481740f9ad21SRichard Henderson static bool do_fcmpq(DisasContext *dc, arg_FCMPq *a, bool e)
481840f9ad21SRichard Henderson {
4819f3ceafadSRichard Henderson     TCGv_i128 src1, src2;
4820f3ceafadSRichard Henderson 
482140f9ad21SRichard Henderson     if (avail_32(dc) && a->cc != 0) {
482240f9ad21SRichard Henderson         return false;
482340f9ad21SRichard Henderson     }
482440f9ad21SRichard Henderson     if (gen_trap_ifnofpu(dc)) {
482540f9ad21SRichard Henderson         return true;
482640f9ad21SRichard Henderson     }
482740f9ad21SRichard Henderson     if (gen_trap_float128(dc)) {
482840f9ad21SRichard Henderson         return true;
482940f9ad21SRichard Henderson     }
483040f9ad21SRichard Henderson 
4831f3ceafadSRichard Henderson     src1 = gen_load_fpr_Q(dc, a->rs1);
4832f3ceafadSRichard Henderson     src2 = gen_load_fpr_Q(dc, a->rs2);
483340f9ad21SRichard Henderson     if (e) {
4834d8c5b92fSRichard Henderson         gen_helper_fcmpeq(cpu_fcc[a->cc], tcg_env, src1, src2);
483540f9ad21SRichard Henderson     } else {
4836d8c5b92fSRichard Henderson         gen_helper_fcmpq(cpu_fcc[a->cc], tcg_env, src1, src2);
483740f9ad21SRichard Henderson     }
483840f9ad21SRichard Henderson     return advance_pc(dc);
483940f9ad21SRichard Henderson }
484040f9ad21SRichard Henderson 
484140f9ad21SRichard Henderson TRANS(FCMPq, ALL, do_fcmpq, a, false)
484240f9ad21SRichard Henderson TRANS(FCMPEq, ALL, do_fcmpq, a, true)
484340f9ad21SRichard Henderson 
48446e61bc94SEmilio G. Cota static void sparc_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
4845fcf5ef2aSThomas Huth {
48466e61bc94SEmilio G. Cota     DisasContext *dc = container_of(dcbase, DisasContext, base);
4847b77af26eSRichard Henderson     CPUSPARCState *env = cpu_env(cs);
48486e61bc94SEmilio G. Cota     int bound;
4849af00be49SEmilio G. Cota 
4850af00be49SEmilio G. Cota     dc->pc = dc->base.pc_first;
48516e61bc94SEmilio G. Cota     dc->npc = (target_ulong)dc->base.tb->cs_base;
48526e61bc94SEmilio G. Cota     dc->mem_idx = dc->base.tb->flags & TB_FLAG_MMU_MASK;
4853576e1c4cSIgor Mammedov     dc->def = &env->def;
48546e61bc94SEmilio G. Cota     dc->fpu_enabled = tb_fpu_enabled(dc->base.tb->flags);
48556e61bc94SEmilio G. Cota     dc->address_mask_32bit = tb_am_enabled(dc->base.tb->flags);
4856c9b459aaSArtyom Tarasenko #ifndef CONFIG_USER_ONLY
48576e61bc94SEmilio G. Cota     dc->supervisor = (dc->base.tb->flags & TB_FLAG_SUPER) != 0;
4858c9b459aaSArtyom Tarasenko #endif
4859fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
4860fcf5ef2aSThomas Huth     dc->fprs_dirty = 0;
48616e61bc94SEmilio G. Cota     dc->asi = (dc->base.tb->flags >> TB_FLAG_ASI_SHIFT) & 0xff;
4862c9b459aaSArtyom Tarasenko #ifndef CONFIG_USER_ONLY
48636e61bc94SEmilio G. Cota     dc->hypervisor = (dc->base.tb->flags & TB_FLAG_HYPER) != 0;
4864c9b459aaSArtyom Tarasenko #endif
4865fcf5ef2aSThomas Huth #endif
48666e61bc94SEmilio G. Cota     /*
48676e61bc94SEmilio G. Cota      * if we reach a page boundary, we stop generation so that the
48686e61bc94SEmilio G. Cota      * PC of a TT_TFAULT exception is always in the right page
48696e61bc94SEmilio G. Cota      */
48706e61bc94SEmilio G. Cota     bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
48716e61bc94SEmilio G. Cota     dc->base.max_insns = MIN(dc->base.max_insns, bound);
4872af00be49SEmilio G. Cota }
4873fcf5ef2aSThomas Huth 
48746e61bc94SEmilio G. Cota static void sparc_tr_tb_start(DisasContextBase *db, CPUState *cs)
48756e61bc94SEmilio G. Cota {
48766e61bc94SEmilio G. Cota }
48776e61bc94SEmilio G. Cota 
48786e61bc94SEmilio G. Cota static void sparc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
48796e61bc94SEmilio G. Cota {
48806e61bc94SEmilio G. Cota     DisasContext *dc = container_of(dcbase, DisasContext, base);
4881633c4283SRichard Henderson     target_ulong npc = dc->npc;
48826e61bc94SEmilio G. Cota 
4883633c4283SRichard Henderson     if (npc & 3) {
4884633c4283SRichard Henderson         switch (npc) {
4885633c4283SRichard Henderson         case JUMP_PC:
4886fcf5ef2aSThomas Huth             assert(dc->jump_pc[1] == dc->pc + 4);
4887633c4283SRichard Henderson             npc = dc->jump_pc[0] | JUMP_PC;
4888633c4283SRichard Henderson             break;
4889633c4283SRichard Henderson         case DYNAMIC_PC:
4890633c4283SRichard Henderson         case DYNAMIC_PC_LOOKUP:
4891633c4283SRichard Henderson             npc = DYNAMIC_PC;
4892633c4283SRichard Henderson             break;
4893633c4283SRichard Henderson         default:
4894633c4283SRichard Henderson             g_assert_not_reached();
4895fcf5ef2aSThomas Huth         }
48966e61bc94SEmilio G. Cota     }
4897633c4283SRichard Henderson     tcg_gen_insn_start(dc->pc, npc);
4898633c4283SRichard Henderson }
4899fcf5ef2aSThomas Huth 
49006e61bc94SEmilio G. Cota static void sparc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
49016e61bc94SEmilio G. Cota {
49026e61bc94SEmilio G. Cota     DisasContext *dc = container_of(dcbase, DisasContext, base);
4903b77af26eSRichard Henderson     CPUSPARCState *env = cpu_env(cs);
49046e61bc94SEmilio G. Cota     unsigned int insn;
4905fcf5ef2aSThomas Huth 
49064e116893SIlya Leoshkevich     insn = translator_ldl(env, &dc->base, dc->pc);
4907af00be49SEmilio G. Cota     dc->base.pc_next += 4;
4908878cc677SRichard Henderson 
4909878cc677SRichard Henderson     if (!decode(dc, insn)) {
4910ba9c09b4SRichard Henderson         gen_exception(dc, TT_ILL_INSN);
4911878cc677SRichard Henderson     }
4912fcf5ef2aSThomas Huth 
4913af00be49SEmilio G. Cota     if (dc->base.is_jmp == DISAS_NORETURN) {
49146e61bc94SEmilio G. Cota         return;
4915c5e6ccdfSEmilio G. Cota     }
4916af00be49SEmilio G. Cota     if (dc->pc != dc->base.pc_next) {
49176e61bc94SEmilio G. Cota         dc->base.is_jmp = DISAS_TOO_MANY;
4918af00be49SEmilio G. Cota     }
49196e61bc94SEmilio G. Cota }
4920fcf5ef2aSThomas Huth 
49216e61bc94SEmilio G. Cota static void sparc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
49226e61bc94SEmilio G. Cota {
49236e61bc94SEmilio G. Cota     DisasContext *dc = container_of(dcbase, DisasContext, base);
4924186e7890SRichard Henderson     DisasDelayException *e, *e_next;
4925633c4283SRichard Henderson     bool may_lookup;
49266e61bc94SEmilio G. Cota 
492789527e3aSRichard Henderson     finishing_insn(dc);
492889527e3aSRichard Henderson 
492946bb0137SMark Cave-Ayland     switch (dc->base.is_jmp) {
493046bb0137SMark Cave-Ayland     case DISAS_NEXT:
493146bb0137SMark Cave-Ayland     case DISAS_TOO_MANY:
4932633c4283SRichard Henderson         if (((dc->pc | dc->npc) & 3) == 0) {
4933fcf5ef2aSThomas Huth             /* static PC and NPC: we can use direct chaining */
4934fcf5ef2aSThomas Huth             gen_goto_tb(dc, 0, dc->pc, dc->npc);
4935633c4283SRichard Henderson             break;
4936fcf5ef2aSThomas Huth         }
4937633c4283SRichard Henderson 
4938930f1865SRichard Henderson         may_lookup = true;
4939633c4283SRichard Henderson         if (dc->pc & 3) {
4940633c4283SRichard Henderson             switch (dc->pc) {
4941633c4283SRichard Henderson             case DYNAMIC_PC_LOOKUP:
4942633c4283SRichard Henderson                 break;
4943633c4283SRichard Henderson             case DYNAMIC_PC:
4944633c4283SRichard Henderson                 may_lookup = false;
4945633c4283SRichard Henderson                 break;
4946633c4283SRichard Henderson             default:
4947633c4283SRichard Henderson                 g_assert_not_reached();
4948633c4283SRichard Henderson             }
4949633c4283SRichard Henderson         } else {
4950633c4283SRichard Henderson             tcg_gen_movi_tl(cpu_pc, dc->pc);
4951633c4283SRichard Henderson         }
4952633c4283SRichard Henderson 
4953930f1865SRichard Henderson         if (dc->npc & 3) {
4954930f1865SRichard Henderson             switch (dc->npc) {
4955930f1865SRichard Henderson             case JUMP_PC:
4956930f1865SRichard Henderson                 gen_generic_branch(dc);
4957930f1865SRichard Henderson                 break;
4958930f1865SRichard Henderson             case DYNAMIC_PC:
4959930f1865SRichard Henderson                 may_lookup = false;
4960930f1865SRichard Henderson                 break;
4961930f1865SRichard Henderson             case DYNAMIC_PC_LOOKUP:
4962930f1865SRichard Henderson                 break;
4963930f1865SRichard Henderson             default:
4964930f1865SRichard Henderson                 g_assert_not_reached();
4965930f1865SRichard Henderson             }
4966930f1865SRichard Henderson         } else {
4967930f1865SRichard Henderson             tcg_gen_movi_tl(cpu_npc, dc->npc);
4968930f1865SRichard Henderson         }
4969633c4283SRichard Henderson         if (may_lookup) {
4970633c4283SRichard Henderson             tcg_gen_lookup_and_goto_ptr();
4971633c4283SRichard Henderson         } else {
497207ea28b4SRichard Henderson             tcg_gen_exit_tb(NULL, 0);
4973fcf5ef2aSThomas Huth         }
497446bb0137SMark Cave-Ayland         break;
497546bb0137SMark Cave-Ayland 
497646bb0137SMark Cave-Ayland     case DISAS_NORETURN:
497746bb0137SMark Cave-Ayland        break;
497846bb0137SMark Cave-Ayland 
497946bb0137SMark Cave-Ayland     case DISAS_EXIT:
498046bb0137SMark Cave-Ayland         /* Exit TB */
498146bb0137SMark Cave-Ayland         save_state(dc);
498246bb0137SMark Cave-Ayland         tcg_gen_exit_tb(NULL, 0);
498346bb0137SMark Cave-Ayland         break;
498446bb0137SMark Cave-Ayland 
498546bb0137SMark Cave-Ayland     default:
498646bb0137SMark Cave-Ayland         g_assert_not_reached();
4987fcf5ef2aSThomas Huth     }
4988186e7890SRichard Henderson 
4989186e7890SRichard Henderson     for (e = dc->delay_excp_list; e ; e = e_next) {
4990186e7890SRichard Henderson         gen_set_label(e->lab);
4991186e7890SRichard Henderson 
4992186e7890SRichard Henderson         tcg_gen_movi_tl(cpu_pc, e->pc);
4993186e7890SRichard Henderson         if (e->npc % 4 == 0) {
4994186e7890SRichard Henderson             tcg_gen_movi_tl(cpu_npc, e->npc);
4995186e7890SRichard Henderson         }
4996186e7890SRichard Henderson         gen_helper_raise_exception(tcg_env, e->excp);
4997186e7890SRichard Henderson 
4998186e7890SRichard Henderson         e_next = e->next;
4999186e7890SRichard Henderson         g_free(e);
5000186e7890SRichard Henderson     }
5001fcf5ef2aSThomas Huth }
50026e61bc94SEmilio G. Cota 
50038eb806a7SRichard Henderson static void sparc_tr_disas_log(const DisasContextBase *dcbase,
50048eb806a7SRichard Henderson                                CPUState *cpu, FILE *logfile)
50056e61bc94SEmilio G. Cota {
50068eb806a7SRichard Henderson     fprintf(logfile, "IN: %s\n", lookup_symbol(dcbase->pc_first));
50078eb806a7SRichard Henderson     target_disas(logfile, cpu, dcbase->pc_first, dcbase->tb->size);
50086e61bc94SEmilio G. Cota }
50096e61bc94SEmilio G. Cota 
50106e61bc94SEmilio G. Cota static const TranslatorOps sparc_tr_ops = {
50116e61bc94SEmilio G. Cota     .init_disas_context = sparc_tr_init_disas_context,
50126e61bc94SEmilio G. Cota     .tb_start           = sparc_tr_tb_start,
50136e61bc94SEmilio G. Cota     .insn_start         = sparc_tr_insn_start,
50146e61bc94SEmilio G. Cota     .translate_insn     = sparc_tr_translate_insn,
50156e61bc94SEmilio G. Cota     .tb_stop            = sparc_tr_tb_stop,
50166e61bc94SEmilio G. Cota     .disas_log          = sparc_tr_disas_log,
50176e61bc94SEmilio G. Cota };
50186e61bc94SEmilio G. Cota 
5019597f9b2dSRichard Henderson void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int *max_insns,
502032f0c394SAnton Johansson                            vaddr pc, void *host_pc)
50216e61bc94SEmilio G. Cota {
50226e61bc94SEmilio G. Cota     DisasContext dc = {};
50236e61bc94SEmilio G. Cota 
5024306c8721SRichard Henderson     translator_loop(cs, tb, max_insns, pc, host_pc, &sparc_tr_ops, &dc.base);
5025fcf5ef2aSThomas Huth }
5026fcf5ef2aSThomas Huth 
502755c3ceefSRichard Henderson void sparc_tcg_init(void)
5028fcf5ef2aSThomas Huth {
5029fcf5ef2aSThomas Huth     static const char gregnames[32][4] = {
5030fcf5ef2aSThomas Huth         "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
5031fcf5ef2aSThomas Huth         "o0", "o1", "o2", "o3", "o4", "o5", "o6", "o7",
5032fcf5ef2aSThomas Huth         "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
5033fcf5ef2aSThomas Huth         "i0", "i1", "i2", "i3", "i4", "i5", "i6", "i7",
5034fcf5ef2aSThomas Huth     };
5035fcf5ef2aSThomas Huth     static const char fregnames[32][4] = {
5036fcf5ef2aSThomas Huth         "f0", "f2", "f4", "f6", "f8", "f10", "f12", "f14",
5037fcf5ef2aSThomas Huth         "f16", "f18", "f20", "f22", "f24", "f26", "f28", "f30",
5038fcf5ef2aSThomas Huth         "f32", "f34", "f36", "f38", "f40", "f42", "f44", "f46",
5039fcf5ef2aSThomas Huth         "f48", "f50", "f52", "f54", "f56", "f58", "f60", "f62",
5040fcf5ef2aSThomas Huth     };
5041fcf5ef2aSThomas Huth 
5042d8c5b92fSRichard Henderson     static const struct { TCGv_i32 *ptr; int off; const char *name; } r32[] = {
5043d8c5b92fSRichard Henderson #ifdef TARGET_SPARC64
5044d8c5b92fSRichard Henderson         { &cpu_fprs, offsetof(CPUSPARCState, fprs), "fprs" },
5045d8c5b92fSRichard Henderson         { &cpu_fcc[0], offsetof(CPUSPARCState, fcc[0]), "fcc0" },
5046d8c5b92fSRichard Henderson         { &cpu_fcc[1], offsetof(CPUSPARCState, fcc[1]), "fcc1" },
5047d8c5b92fSRichard Henderson         { &cpu_fcc[2], offsetof(CPUSPARCState, fcc[2]), "fcc2" },
5048d8c5b92fSRichard Henderson         { &cpu_fcc[3], offsetof(CPUSPARCState, fcc[3]), "fcc3" },
5049d8c5b92fSRichard Henderson #else
5050d8c5b92fSRichard Henderson         { &cpu_fcc[0], offsetof(CPUSPARCState, fcc[0]), "fcc" },
5051d8c5b92fSRichard Henderson #endif
5052d8c5b92fSRichard Henderson     };
5053d8c5b92fSRichard Henderson 
5054fcf5ef2aSThomas Huth     static const struct { TCGv *ptr; int off; const char *name; } rtl[] = {
5055fcf5ef2aSThomas Huth #ifdef TARGET_SPARC64
5056fcf5ef2aSThomas Huth         { &cpu_gsr, offsetof(CPUSPARCState, gsr), "gsr" },
50572a1905c7SRichard Henderson         { &cpu_xcc_Z, offsetof(CPUSPARCState, xcc_Z), "xcc_Z" },
50582a1905c7SRichard Henderson         { &cpu_xcc_C, offsetof(CPUSPARCState, xcc_C), "xcc_C" },
5059fcf5ef2aSThomas Huth #endif
50602a1905c7SRichard Henderson         { &cpu_cc_N, offsetof(CPUSPARCState, cc_N), "cc_N" },
50612a1905c7SRichard Henderson         { &cpu_cc_V, offsetof(CPUSPARCState, cc_V), "cc_V" },
50622a1905c7SRichard Henderson         { &cpu_icc_Z, offsetof(CPUSPARCState, icc_Z), "icc_Z" },
50632a1905c7SRichard Henderson         { &cpu_icc_C, offsetof(CPUSPARCState, icc_C), "icc_C" },
5064fcf5ef2aSThomas Huth         { &cpu_cond, offsetof(CPUSPARCState, cond), "cond" },
5065fcf5ef2aSThomas Huth         { &cpu_pc, offsetof(CPUSPARCState, pc), "pc" },
5066fcf5ef2aSThomas Huth         { &cpu_npc, offsetof(CPUSPARCState, npc), "npc" },
5067fcf5ef2aSThomas Huth         { &cpu_y, offsetof(CPUSPARCState, y), "y" },
5068fcf5ef2aSThomas Huth         { &cpu_tbr, offsetof(CPUSPARCState, tbr), "tbr" },
5069fcf5ef2aSThomas Huth     };
5070fcf5ef2aSThomas Huth 
5071fcf5ef2aSThomas Huth     unsigned int i;
5072fcf5ef2aSThomas Huth 
5073ad75a51eSRichard Henderson     cpu_regwptr = tcg_global_mem_new_ptr(tcg_env,
5074fcf5ef2aSThomas Huth                                          offsetof(CPUSPARCState, regwptr),
5075fcf5ef2aSThomas Huth                                          "regwptr");
5076fcf5ef2aSThomas Huth 
5077d8c5b92fSRichard Henderson     for (i = 0; i < ARRAY_SIZE(r32); ++i) {
5078d8c5b92fSRichard Henderson         *r32[i].ptr = tcg_global_mem_new_i32(tcg_env, r32[i].off, r32[i].name);
5079d8c5b92fSRichard Henderson     }
5080d8c5b92fSRichard Henderson 
5081fcf5ef2aSThomas Huth     for (i = 0; i < ARRAY_SIZE(rtl); ++i) {
5082ad75a51eSRichard Henderson         *rtl[i].ptr = tcg_global_mem_new(tcg_env, rtl[i].off, rtl[i].name);
5083fcf5ef2aSThomas Huth     }
5084fcf5ef2aSThomas Huth 
5085f764718dSRichard Henderson     cpu_regs[0] = NULL;
5086fcf5ef2aSThomas Huth     for (i = 1; i < 8; ++i) {
5087ad75a51eSRichard Henderson         cpu_regs[i] = tcg_global_mem_new(tcg_env,
5088fcf5ef2aSThomas Huth                                          offsetof(CPUSPARCState, gregs[i]),
5089fcf5ef2aSThomas Huth                                          gregnames[i]);
5090fcf5ef2aSThomas Huth     }
5091fcf5ef2aSThomas Huth 
5092fcf5ef2aSThomas Huth     for (i = 8; i < 32; ++i) {
5093fcf5ef2aSThomas Huth         cpu_regs[i] = tcg_global_mem_new(cpu_regwptr,
5094fcf5ef2aSThomas Huth                                          (i - 8) * sizeof(target_ulong),
5095fcf5ef2aSThomas Huth                                          gregnames[i]);
5096fcf5ef2aSThomas Huth     }
5097fcf5ef2aSThomas Huth 
5098fcf5ef2aSThomas Huth     for (i = 0; i < TARGET_DPREGS; i++) {
5099ad75a51eSRichard Henderson         cpu_fpr[i] = tcg_global_mem_new_i64(tcg_env,
5100fcf5ef2aSThomas Huth                                             offsetof(CPUSPARCState, fpr[i]),
5101fcf5ef2aSThomas Huth                                             fregnames[i]);
5102fcf5ef2aSThomas Huth     }
5103fcf5ef2aSThomas Huth }
5104fcf5ef2aSThomas Huth 
5105f36aaa53SRichard Henderson void sparc_restore_state_to_opc(CPUState *cs,
5106f36aaa53SRichard Henderson                                 const TranslationBlock *tb,
5107f36aaa53SRichard Henderson                                 const uint64_t *data)
5108fcf5ef2aSThomas Huth {
5109f36aaa53SRichard Henderson     SPARCCPU *cpu = SPARC_CPU(cs);
5110f36aaa53SRichard Henderson     CPUSPARCState *env = &cpu->env;
5111fcf5ef2aSThomas Huth     target_ulong pc = data[0];
5112fcf5ef2aSThomas Huth     target_ulong npc = data[1];
5113fcf5ef2aSThomas Huth 
5114fcf5ef2aSThomas Huth     env->pc = pc;
5115fcf5ef2aSThomas Huth     if (npc == DYNAMIC_PC) {
5116fcf5ef2aSThomas Huth         /* dynamic NPC: already stored */
5117fcf5ef2aSThomas Huth     } else if (npc & JUMP_PC) {
5118fcf5ef2aSThomas Huth         /* jump PC: use 'cond' and the jump targets of the translation */
5119fcf5ef2aSThomas Huth         if (env->cond) {
5120fcf5ef2aSThomas Huth             env->npc = npc & ~3;
5121fcf5ef2aSThomas Huth         } else {
5122fcf5ef2aSThomas Huth             env->npc = pc + 4;
5123fcf5ef2aSThomas Huth         }
5124fcf5ef2aSThomas Huth     } else {
5125fcf5ef2aSThomas Huth         env->npc = npc;
5126fcf5ef2aSThomas Huth     }
5127fcf5ef2aSThomas Huth }
5128